summaryrefslogtreecommitdiffstats
path: root/dcop
diff options
context:
space:
mode:
Diffstat (limited to 'dcop')
-rw-r--r--dcop/HOWTO552
-rw-r--r--dcop/KDE-ICE/ICE-def.cpp66
-rw-r--r--dcop/KDE-ICE/ICE.h98
-rw-r--r--dcop/KDE-ICE/ICEconn.h247
-rw-r--r--dcop/KDE-ICE/ICElib.h631
-rw-r--r--dcop/KDE-ICE/ICElibint.h626
-rw-r--r--dcop/KDE-ICE/ICEmsg.h319
-rw-r--r--dcop/KDE-ICE/ICEproto.h186
-rw-r--r--dcop/KDE-ICE/ICEutil.h156
-rw-r--r--dcop/KDE-ICE/Makefile.am38
-rw-r--r--dcop/KDE-ICE/Xfuncproto.h83
-rw-r--r--dcop/KDE-ICE/Xtrans.c1343
-rw-r--r--dcop/KDE-ICE/Xtrans.h479
-rw-r--r--dcop/KDE-ICE/Xtransint.h477
-rw-r--r--dcop/KDE-ICE/Xtranssock.c1990
-rw-r--r--dcop/KDE-ICE/Xtransutil.c549
-rw-r--r--dcop/KDE-ICE/accept.c189
-rw-r--r--dcop/KDE-ICE/authutil.c524
-rw-r--r--dcop/KDE-ICE/connect.c547
-rw-r--r--dcop/KDE-ICE/error.c650
-rw-r--r--dcop/KDE-ICE/getauth.c269
-rw-r--r--dcop/KDE-ICE/globals.c56
-rw-r--r--dcop/KDE-ICE/globals.h146
-rw-r--r--dcop/KDE-ICE/iceauth.c273
-rw-r--r--dcop/KDE-ICE/listen.c297
-rw-r--r--dcop/KDE-ICE/listenwk.c155
-rw-r--r--dcop/KDE-ICE/locking.c62
-rw-r--r--dcop/KDE-ICE/misc.c619
-rw-r--r--dcop/KDE-ICE/ping.c59
-rw-r--r--dcop/KDE-ICE/process.c2545
-rw-r--r--dcop/KDE-ICE/protosetup.c287
-rw-r--r--dcop/KDE-ICE/register.c251
-rw-r--r--dcop/KDE-ICE/replywait.c171
-rw-r--r--dcop/KDE-ICE/setauth.c116
-rw-r--r--dcop/KDE-ICE/shutdown.c323
-rw-r--r--dcop/KDE-ICE/transport.c68
-rw-r--r--dcop/KDE-ICE/watch.c199
-rw-r--r--dcop/Mainpage.dox576
-rw-r--r--dcop/Makefile.am69
-rw-r--r--dcop/client/Makefile.am28
-rw-r--r--dcop/client/README.dcop78
-rw-r--r--dcop/client/dcop.cpp924
-rw-r--r--dcop/client/dcopclient.c59
-rw-r--r--dcop/client/dcopfind.cpp282
-rw-r--r--dcop/client/dcopobject.c59
-rw-r--r--dcop/client/dcopquit.cpp2
-rw-r--r--dcop/client/dcopref.c40
-rw-r--r--dcop/client/dcopstart.cpp99
-rw-r--r--dcop/client/marshall.cpp399
-rw-r--r--dcop/configure.in.in9
-rw-r--r--dcop/dcop-path.h.in1
-rw-r--r--dcop/dcop_deadlock_test.cpp96
-rw-r--r--dcop/dcop_deadlock_test.h51
-rw-r--r--dcop/dcopc.c790
-rw-r--r--dcop/dcopc.h134
-rw-r--r--dcop/dcopclient.cpp2283
-rw-r--r--dcop/dcopclient.h840
-rw-r--r--dcop/dcopglobal.h84
-rw-r--r--dcop/dcopidl/Makefile.am27
-rw-r--r--dcop/dcopidl/dcopidl_output.kidl82
-rw-r--r--dcop/dcopidl/dcopidl_test.h109
-rw-r--r--dcop/dcopidl/main.cpp87
-rwxr-xr-xdcop/dcopidl/run_test.sh10
-rw-r--r--dcop/dcopidl/scanner.cc2508
-rw-r--r--dcop/dcopidl/scanner.ll293
-rw-r--r--dcop/dcopidl/yacc.cc2824
-rw-r--r--dcop/dcopidl/yacc.cc.h184
-rw-r--r--dcop/dcopidl/yacc.yy857
-rw-r--r--dcop/dcopidl2cpp/Makefile.am20
-rw-r--r--dcop/dcopidl2cpp/dcopidl_test.h109
-rw-r--r--dcop/dcopidl2cpp/main.cpp128
-rw-r--r--dcop/dcopidl2cpp/main.h40
-rw-r--r--dcop/dcopidl2cpp/skel.cpp445
-rw-r--r--dcop/dcopidl2cpp/stub.cpp216
-rw-r--r--dcop/dcopidl2cpp/stubimpl.cpp277
-rw-r--r--dcop/dcopidl2cpp/type.h22
-rw-r--r--dcop/dcopidlng/Ast.pm51
-rw-r--r--dcop/dcopidlng/Iter.pm532
-rw-r--r--dcop/dcopidlng/Makefile.am8
-rwxr-xr-xdcop/dcopidlng/dcopidlng15
-rw-r--r--dcop/dcopidlng/kalyptus1612
-rw-r--r--dcop/dcopidlng/kalyptusCxxToDcopIDL.pm213
-rw-r--r--dcop/dcopidlng/kdocAstUtil.pm536
-rw-r--r--dcop/dcopidlng/kdocParseDoc.pm419
-rw-r--r--dcop/dcopidlng/kdocUtil.pm189
-rwxr-xr-xdcop/dcopidlng/run_test.sh14
-rw-r--r--dcop/dcopobject.cpp283
-rw-r--r--dcop/dcopobject.h410
-rw-r--r--dcop/dcopref.cpp218
-rw-r--r--dcop/dcopref.h1474
-rw-r--r--dcop/dcopserver.cpp1790
-rw-r--r--dcop/dcopserver.h186
-rw-r--r--dcop/dcopserver_shutdown.c204
-rw-r--r--dcop/dcopserver_shutdown_win.cpp210
-rw-r--r--dcop/dcopserver_win.cpp63
-rw-r--r--dcop/dcopsignals.cpp274
-rw-r--r--dcop/dcopsignals.h158
-rw-r--r--dcop/dcopstub.cpp98
-rw-r--r--dcop/dcopstub.h145
-rw-r--r--dcop/dcoptypes.h91
-rw-r--r--dcop/kdatastream.h56
-rw-r--r--dcop/libDCOP.nmcheck14
-rw-r--r--dcop/libDCOP_weak.nmcheck10
-rw-r--r--dcop/testdcop.cpp298
-rw-r--r--dcop/testdcop.h77
-rw-r--r--dcop/testdcopc.c11
-rw-r--r--dcop/tests/Makefile.am35
-rw-r--r--dcop/tests/README37
-rw-r--r--dcop/tests/driver.cpp65
-rw-r--r--dcop/tests/driver.h21
-rwxr-xr-xdcop/tests/generate.pl221
-rw-r--r--dcop/tests/run-tests.sh44
-rw-r--r--dcop/tests/test.cpp44
-rw-r--r--dcop/tests/testcases105
-rw-r--r--dcop/version.h1
115 files changed, 41019 insertions, 0 deletions
diff --git a/dcop/HOWTO b/dcop/HOWTO
new file mode 100644
index 000000000..8609021c0
--- /dev/null
+++ b/dcop/HOWTO
@@ -0,0 +1,552 @@
+ DCOP: Desktop COmmunications Protocol
+
+ Preston Brown <pbrown@kde.org>
+ October 14, 1999
+
+ Revised and extended by Matthias Ettrich <ettrich@kde.org>
+ Mar 29, 2000
+
+ Extended with DCOP Signals by Waldo Bastian <bastian@kde.org>
+ Feb 19, 2001
+
+
+Motivation and Background:
+--------------------------
+
+The motivation behind building a protocol like DCOP is simple. For
+the past year, we have been attempting to enable interprocess
+communication between KDE applications. KDE already has an extremely
+simple IPC mechanism called KWMcom, which is (was!) used for communicating
+between the panel and the window manager for instance. It is about as
+simple as it gets, passing messages via X Atoms. For this reason it
+is limited in the size and complexity of the data that can be passed
+(X atoms must be small to remain efficient) and it also makes it so
+that X is required. CORBA was thought to be a more effective IPC/RPC
+solution. However, after a year of attempting to make heavy use of
+CORBA in KDE, we have realized that it is a bit slow and memory
+intensive for simple use. It also has no authentication available.
+
+What we really needed was an extremely simple protocol with basic
+authorization, along the lines of MIT-MAGIC-COOKIE, as used by X. It
+would not be able to do NEARLY what CORBA was able to do, but for the
+simple tasks required it would be sufficient. Some examples of such
+tasks might be an application sending a message to the panel saying,
+"I have started, stop displaying the 'application starting' wait
+state," or having a new application that starts query to see if any
+other applications of the same name are running. If they are, simply
+call a function on the remote application to create a new window,
+rather than starting a new process.
+
+Implementation:
+---------------
+
+DCOP is a simple IPC/RPC mechanism built to operate over sockets.
+Either unix domain sockets or tcp/ip sockets are supported. DCOP is
+built on top of the Inter Client Exchange (ICE) protocol, which comes
+standard as a part of X11R6 and later. It also depends on Qt, but
+beyond that it does not require any other libraries. Because of this,
+it is extremely lightweight, enabling it to be linked into all KDE
+applications with low overhead.
+
+Model:
+------
+
+The model is simple. Each application using DCOP is a client. They
+communicate to each other through a DCOP server, which functions like
+a traffic director, dispatching messages/calls to the proper
+destinations. All clients are peers of each other.
+
+Two types of actions are possible with DCOP: "send and forget"
+messages, which do not block, and "calls," which block waiting for
+some data to be returned.
+
+Any data that will be sent is serialized (marshalled, for you CORBA
+types) using the built-in QDataStream operators available in all of
+the Qt classes. This is fast and easy. In fact it's so little work
+that you can easily write the marshalling code by hand. In addition,
+there's a simple IDL-like compiler available (dcopidl and dcopidl2cpp)
+that generates stubs and skeletons for you. Using the dcopidl compiler
+has the additional benefit of type safety.
+
+This HOWTO describes the manual method first and covers the dcopidl
+compiler later.
+
+Establishing the Connection:
+----------------------------
+
+KApplication has gained a method called "KApplication::dcopClient()"
+which returns a pointer to a DCOPClient instance. The first time this
+method is called, the client class will be created. DCOPClients have
+unique identifiers attached to them which are based on what
+KApplication::name() returns. In fact, if there is only a single
+instance of the program running, the appId will be equal to
+KApplication::name().
+
+To actually enable DCOP communication to begin, you must use
+DCOPClient::attach(). This will attempt to attach to the DCOP server.
+If no server is found or there is any other type of error, attach()
+will return false. KApplication will catch a dcop signal and display an
+appropriate error message box in that case.
+
+After connecting with the server via DCOPClient::attach(), you need to
+register this appId with the server so it knows about you. Otherwise,
+you are communicating anonymously. Use the
+DCOPClient::registerAs(const QCString &name) to do so. In the simple
+case:
+
+/*
+ * returns the appId that is actually registered, which _may_ be
+ * different from what you passed
+ */
+appId = client->registerAs(kApp->name());
+
+If you never retrieve the DCOPClient pointer from KApplication, the
+object will not be created and thus there will be no memory overhead.
+
+You may also detach from the server by calling DCOPClient::detach().
+If you wish to attach again you will need to re-register as well. If
+you only wish to change the ID under which you are registered, simply
+call DCOPClient::registerAs() with the new name.
+
+KUniqueApplication automatically registers itself to DCOP. If you
+are using KUniqueApplication you should not attach or register
+yourself, this is already done. The appId is by definition
+equal to kapp->name(). You can retrieve the registered DCOP client
+by calling kapp->dcopClient().
+
+Sending Data to a Remote Application:
+-------------------------------------
+
+To actually communicate, you have one of two choices. You may either
+call the "send" or the "call" method. Both methods require three
+identification parameters: an application identifier, a remote object,
+a remote function. Sending is asynchronous (i.e. it returns immediately)
+and may or may not result in your own application being sent a message at
+some point in the future. Then "send" requires one and "call" requires
+two data parameters.
+
+The remote object must be specified as an object hierarchy. That is,
+if the toplevel object is called "fooObject" and has the child
+"barObject", you would reference this object as "fooObject/barObject".
+Functions must be described by a full function signature. If the
+remote function is called "doIt", and it takes an int, it would be
+described as "doIt(int)". Please note that the return type is not
+specified here, as it is not part of the function signature (or at
+least the C++ understanding of a function signature). You will get
+the return type of a function back as an extra parameter to
+DCOPClient::call(). See the section on call() for more details.
+
+In order to actually get the data to the remote client, it must be
+"serialized" via a QDataStream operating on a QByteArray. This is how
+the data parameter is "built". A few examples will make clear how this
+works.
+
+Say you want to call "doIt" as described above, and not block (or wait
+for a response). You will not receive the return value of the remotely
+called function, but you will not hang while the RPC is processed either.
+The return value of send() indicates whether DCOP communication succeeded
+or not.
+
+QByteArray data;
+QDataStream arg(data, IO_WriteOnly);
+arg << 5;
+if (!client->send("someAppId", "fooObject/barObject", "doIt(int)",
+ data))
+ qDebug("there was some error using DCOP.");
+
+OK, now let's say we wanted to get the data back from the remotely
+called function. You have to execute a call() instead of a send().
+The returned value will then be available in the data parameter "reply".
+The actual return value of call() is still whether or not DCOP
+communication was successful.
+
+QByteArray data, replyData;
+QCString replyType;
+QDataStream arg(data, IO_WriteOnly);
+arg << 5;
+if (!client->call("someAppId", "fooObject/barObject", "doIt(int)",
+ data, replyType, replyData))
+ qDebug("there was some error using DCOP.");
+else {
+ QDataStream reply(replyData, IO_ReadOnly);
+ if (replyType == "QString") {
+ QString result;
+ reply >> result;
+ print("the result is: %s",result.latin1());
+ } else
+ qDebug("doIt returned an unexpected type of reply!");
+}
+
+N.B.: You cannot call() a method belonging to an application which has
+registered with an unique numeric id appended to its textual name (see
+dcopclient.h for more info). In this case, DCOP would not know which
+application it should connect with to call the method. This is not an issue
+with send(), as you can broadcast to all applications that have registered
+with appname-<numeric_id> by using a wildcard (e.g. 'konsole-*'), which
+will send your signal to all applications called 'konsole'.
+
+Receiving Data via DCOP:
+------------------------
+
+Currently the only real way to receive data from DCOP is to multiply
+inherit from the normal class that you are inheriting (usually some
+sort of QWidget subclass or QObject) as well as the DCOPObject class.
+DCOPObject provides one very important method: DCOPObject::process().
+This is a pure virtual method that you must implement in order to
+process DCOP messages that you receive. It takes a function
+signature, QByteArray of parameters, and a reference to a QByteArray
+for the reply data that you must fill in.
+
+Think of DCOPObject::process() as a sort of dispatch agent. In the
+future, there will probably be a precompiler for your sources to write
+this method for you. However, until that point you need to examine
+the incoming function signature and take action accordingly. Here is
+an example implementation.
+
+bool BarObject::process(const QCString &fun, const QByteArray &data,
+ QCString &replyType, QByteArray &replyData)
+{
+ if (fun == "doIt(int)") {
+ QDataStream arg(data, IO_ReadOnly);
+ int i; // parameter
+ arg >> i;
+ QString result = self->doIt (i);
+ QDataStream reply(replyData, IO_WriteOnly);
+ reply << result;
+ replyType = "QString";
+ return true;
+ } else {
+ qDebug("unknown function call to BarObject::process()");
+ return false;
+ }
+}
+
+Receiving Calls and processing them:
+------------------------------------
+
+If your applications is able to process incoming function calls
+right away the above code is all you need. When your application
+needs to do more complex tasks you might want to do the processing
+out of 'process' function call and send the result back later when
+it becomes available.
+
+For this you can ask your DCOPClient for a transactionId. You can
+then return from the 'process' function and when the result is
+available finish the transaction. In the mean time your application
+can receive incoming DCOP function calls from other clients.
+
+Such code could like this:
+
+bool BarObject::process(const QCString &fun, const QByteArray &data,
+ QCString &, QByteArray &)
+{
+ if (fun == "doIt(int)") {
+ QDataStream arg(data, IO_ReadOnly);
+ int i; // parameter
+ arg >> i;
+ QString result = self->doIt(i);
+
+ DCOPClientTransaction *myTransaction;
+ myTransaction = kapp->dcopClient()->beginTransaction();
+
+ // start processing...
+ // Calls slotProcessingDone when finished.
+ startProcessing( myTransaction, i);
+
+ return true;
+ } else {
+ qDebug("unknown function call to BarObject::process()");
+ return false;
+ }
+}
+
+slotProcessingDone(DCOPClientTransaction *myTransaction, const QString &result)
+{
+ QCString replyType = "QString";
+ QByteArray replyData;
+ QDataStream reply(replyData, IO_WriteOnly);
+ reply << result;
+ kapp->dcopClient()->endTransaction( myTransaction, replyType, replyData );
+}
+
+DCOP Signals
+------------
+
+Sometimes a component wants to send notifications via DCOP to other
+components but does not know which components will be interested in these
+notifications. One could use a broadcast in such a case but this is a very
+crude method. For a more sophisticated method DCOP signals have been invented.
+
+DCOP signals are very similair to Qt signals, there are some differences
+though. A DCOP signal can be connected to a DCOP function. Whenever the DCOP
+signal gets emitted, the DCOP functions to which the signal is connected are
+being called. DCOP signals are, just like Qt signals, one way. They do not
+provide a return value.
+
+A DCOP signal originates from a DCOP Object/DCOP Client combination (sender).
+It can be connected to a function of another DCOP Object/DCOP Client
+combination (receiver).
+
+There are two major differences between connections of Qt signals and
+connections of DCOP signals. In DCOP, unlike Qt, a signal connections can
+have an anonymous sender and, unlike Qt, a DCOP signal connection can be
+non-volatile.
+
+With DCOP one can connect a signal without specifying the sending DCOP Object
+or DCOP Client. In that case signals from any DCOP Object and/or DCOP Client
+will be delivered. This allows the specification of certain events without
+tying oneself to a certain object that implementes the events.
+
+Another DCOP feature are so called non-volatile connections. With Qt signal
+connections, the connection gets deleted when either sender or receiver of
+the signal gets deleted. A volatile DCOP signal connection will behave the
+same. However, a non-volatile DCOP signal connection will not get deleted
+when the sending object gets deleted. Once a new object gets created with
+the same name as the original sending object, the connection will be restored.
+There is no difference between the two when the receiving object gets deleted,
+in that case the signal connection will always be deleted.
+
+A receiver can create a non-volatile connection while the sender doesn't (yet)
+exist. An anonymous DCOP connection should always be non-volatile.
+
+The following example shows how KLauncher emits a signal whenever it notices
+that an application that was started via KLauncher terminates.
+
+ QByteArray params;
+ QDataStream stream(params, IO_WriteOnly);
+ stream << pid;
+ kapp->dcopClient()->emitDCOPSignal("clientDied(pid_t)", params);
+
+The task manager of the KDE panel connects to this signal. It uses an
+anonymous connection (it doesn't require that the signal is being emitted
+by KLauncher) that is non-volatile:
+
+ connectDCOPSignal(0, 0, "clientDied(pid_t)", "clientDied(pid_t)", false);
+
+It connects the clientDied(pid_t) signal to its own clientDied(pid_t) DCOP
+function. In this case the signal and the function to call have the same name.
+This isn't needed as long as the arguments of both signal and receiving function
+match. The receiving function may ignore one or more of the trailing arguments
+of the signal. E.g. it is allowed to connect the clientDied(pid_t) signal to
+a clientDied(void) DCOP function.
+
+Using the dcopidl compiler
+---------------------
+
+dcopidl makes setting up a DCOP server easy. Instead of having to implement
+the process() method and unmarshalling (retrieving from QByteArray) parameters
+manually, you can let dcopidl create the necessary code on your behalf.
+
+This also allows you to describe the interface for your class in a
+single, separate header file.
+
+Writing an IDL file is very similar to writing a normal C++ header. An
+exception is the keyword 'ASYNC'. It indicates that a call to this
+function shall be processed asynchronously. For the C++ compiler, it
+expands to 'void'.
+
+Example:
+
+#ifndef MY_INTERFACE_H
+#define MY_INTERFACE_H
+
+#include <dcopobject.h>
+
+class MyInterface : virtual public DCOPObject
+{
+ K_DCOP
+
+ k_dcop:
+
+ virtual ASYNC myAsynchronousMethod(QString someParameter) = 0;
+ virtual QRect mySynchronousMethod() = 0;
+};
+
+#endif
+
+As you can see, you're essentially declaring an abstract base class, which
+virtually inherits from DCOPObject.
+
+If you're using the standard KDE build scripts, then you can simply
+add this file (which you would call MyInterface.h) to your sources
+directory. Then you edit your Makefile.am, adding 'MyInterface.skel'
+to your SOURCES list and MyInterface.h to include_HEADERS.
+
+The build scripts will use dcopidl to parse MyInterface.h, converting
+it to an XML description in MyInterface.kidl. Next, a file called
+MyInterface_skel.cpp will automatically be created, compiled and
+linked with your binary.
+
+The next thing you have to do is to choose which of your classes will
+implement the interface described in MyInterface.h. Alter the inheritance
+of this class such that it virtually inherits from MyInterface. Then
+add declarations to your class interface similar to those on MyInterface.h,
+but virtual, not pure virtual.
+
+Example:
+
+class MyClass: public QObject, virtual public MyInterface
+{
+ Q_OBJECT
+
+ public:
+ MyClass();
+ ~MyClass();
+
+ ASYNC myAsynchronousMethod(QString someParameter);
+ QRect mySynchronousMethod();
+};
+
+Note: (Qt issue) Remember that if you are inheriting from QObject, you must
+place it first in the list of inherited classes.
+
+In the implementation of your class' ctor, you must explicitly initialize
+those classes from which you are inheriting from. This is, of course, good
+practice, but it is essential here as you need to tell DCOPObject the name of
+the interface which your are implementing.
+
+Example:
+
+MyClass::MyClass()
+ : QObject(),
+ DCOPObject("MyInterface")
+{
+ // whatever...
+}
+
+Now you can simply implement the methods you have declared in your interface,
+exactly the same as you would normally.
+
+Example:
+
+void MyClass::myAsynchronousMethod(QString someParameter)
+{
+ qDebug("myAsyncMethod called with param `" + someParameter + "'");
+}
+
+
+It is not necessary (though very clean) to define an interface as an
+abstract class of its own, like we did in the example above. We could
+just as well have defined a k_dcop section directly within MyClass:
+
+class MyClass: public QObject, virtual public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+
+ public:
+ MyClass();
+ ~MyClass();
+
+ k_dcop:
+ ASYNC myAsynchronousMethod(QString someParameter);
+ QRect mySynchronousMethod();
+};
+
+In addition to skeletons, dcopidl2cpp also generate stubs. Those make
+it easy to call a DCOP interface without doing the marshalling
+manually. To use a stub, add MyInterface.stub to the SOURCES list of
+your Makefile.am. The stub class will then be called MyInterface_stub.
+
+Conclusion:
+-----------
+
+Hopefully this document will get you well on your way into the world
+of inter-process communication with KDE! Please direct all comments
+and/or suggestions to Preston Brown <pbrown@kde.org> and Matthias
+Ettrich <ettrich@kde.org>.
+
+
+Inter-user communication
+------------------------
+
+Sometimes it might be interesting to use DCOP between processes
+belonging to different users, e.g. a frontend process running
+with the user's id, and a backend process running as root.
+
+For this you can use kdesu with the --nonewdcop option. kdesu will
+then forward the address of the DCOP server as well as the authentication
+information to the new user.
+
+*WARNING*: This gives the user that you su to, full access to your session!
+If you su to root this will not be a problem, but it may be a problem if
+you su to another user.
+
+By default, KDE applications (e.g. the ones that run as root) that connect
+to the dcopserver of another user will not accept any incoming DCOP calls.
+You can override this with DCOPClient::setAcceptCalls() after you have
+carefully reviewed that your DCOPClient does not provide objects/functions
+that could be abused for privilege escalation.
+
+
+Example: kdesu --nonewdcop -u root -c kcmroot
+
+This will, after kdesu got the root password, execute kcmroot as root,
+talking to the user's dcop server.
+
+
+Performance Tests:
+------------------
+A few back-of-the-napkin tests folks:
+
+Code:
+
+#include <kapplication.h>
+
+int main(int argc, char **argv)
+{
+ KApplication *app;
+
+ app = new KApplication(argc, argv, "testit");
+ return app->exec();
+}
+
+Compiled with:
+
+g++ -O2 -o testit testit.cpp -I$QTDIR/include -L$QTDIR/lib -lkdecore
+
+on Linux yields the following memory use statistics:
+
+VmSize: 8076 kB
+VmLck: 0 kB
+VmRSS: 4532 kB
+VmData: 208 kB
+VmStk: 20 kB
+VmExe: 4 kB
+VmLib: 6588 kB
+
+If I create the KApplication's DCOPClient, and call attach() and
+registerAs(), it changes to this:
+
+VmSize: 8080 kB
+VmLck: 0 kB
+VmRSS: 4624 kB
+VmData: 208 kB
+VmStk: 20 kB
+VmExe: 4 kB
+VmLib: 6588 kB
+
+Basically it appears that using DCOP causes 100k more memory to be
+resident, but no more data or stack. So this will be shared between all
+processes, right? 100k to enable DCOP in all apps doesn't seem bad at
+all. :)
+
+OK now for some timings. Just creating a KApplication and then exiting
+(i.e. removing the call to KApplication::exec) takes this much time:
+
+0.28user 0.02system 0:00.32elapsed 92%CPU (0avgtext+0avgdata 0maxresident)k
+0inputs+0outputs (1084major+62minor)pagefaults 0swaps
+
+I.e. about 1/3 of a second on my PII-233. Now, if we create our DCOP
+object and attach to the server, it takes this long:
+
+0.27user 0.03system 0:00.34elapsed 87%CPU (0avgtext+0avgdata 0maxresident)k
+0inputs+0outputs (1107major+65minor)pagefaults 0swaps
+
+I.e. about 1/3 of a second. Basically DCOPClient creation and attaching
+gets lost in the statistical variation ("noise"). I was getting times
+between .32 and .48 over several runs for both of the example programs, so
+obviously system load is more relevant than the extra two calls to
+DCOPClient::attach and DCOPClient::registerAs, as well as the actual
+DCOPClient constructor time.
+
diff --git a/dcop/KDE-ICE/ICE-def.cpp b/dcop/KDE-ICE/ICE-def.cpp
new file mode 100644
index 000000000..df1d9ea58
--- /dev/null
+++ b/dcop/KDE-ICE/ICE-def.cpp
@@ -0,0 +1,66 @@
+LIBRARY ICE
+VERSION LIBRARY_VERSION
+EXPORTS
+ IceAcceptConnection
+ IceAddConnectionWatch
+ IceAllocScratch
+ IceAppLockConn
+ IceAppUnlockConn
+ IceAuthFileName
+ IceCheckShutdownNegotiation
+ IceCloseConnection
+ IceComposeNetworkIdList
+ IceConnectionNumber
+ IceConnectionStatus
+ IceConnectionString
+ IceFlush
+ IceFreeAuthFileEntry
+ IceFreeListenObjs
+ IceGenerateMagicCookie
+ IceGetAuthFileEntry
+ IceGetConnectionContext
+ IceGetInBufSize
+ IceGetListenConnectionNumber
+ IceGetListenConnectionString
+ IceGetOutBufSize
+ IceInitThreads
+ IceLastReceivedSequenceNumber
+ IceLastSentSequenceNumber
+ IceListenForConnections
+ IceLockAuthFile
+ IceOpenConnection
+ IcePing
+ IceProcessMessages
+ IceProtocolRevision
+ IceProtocolSetup
+ IceProtocolShutdown
+ IceProtocolVersion
+ IceReadAuthFileEntry
+ IceRegisterForProtocolReply
+ IceRegisterForProtocolSetup
+ IceRelease
+ IceRemoveConnectionWatch
+ IceSetErrorHandler
+ IceSetHostBasedAuthProc
+ IceSetIOErrorHandler
+ IceSetPaAuthData
+ IceSetShutdownNegotiation
+ IceSwapping
+ IceUnlockAuthFile
+ IceVendor
+ IceWriteAuthFileEntry
+ _IceTransGetPeerAddr
+ _IceTransGetPeerNetworkId
+ _IceErrorBadMinor
+ _IceErrorBadLength
+ _IceErrorBadState
+ _IceErrorBadValue
+ _IcePaMagicCookie1Proc
+ _IcePoMagicCookie1Proc
+ _IceRead
+ _IceReadSkip
+ _IceWrite
+ IceListenForWellKnownConnections
+ _IceTransGetHostname
+/* $Xorg: ICE-def.cpp,v 1.3 2000/08/21 16:42:31 coskrey Exp $ */
+/* $XFree86: xc/lib/ICE/ICE-def.cpp,v 1.4 2001/01/17 19:41:29 dawes Exp $ */
diff --git a/dcop/KDE-ICE/ICE.h b/dcop/KDE-ICE/ICE.h
new file mode 100644
index 000000000..f7ede88d1
--- /dev/null
+++ b/dcop/KDE-ICE/ICE.h
@@ -0,0 +1,98 @@
+/* $Xorg: ICE.h,v 1.3 2000/08/17 19:44:08 cpqbld Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+
+Author: Ralph Mor, X Consortium
+
+******************************************************************************/
+
+#ifndef _ICE_H_
+#define _ICE_H_
+
+/*
+ * Protocol Version
+ */
+
+#define IceProtoMajor 1
+#define IceProtoMinor 0
+
+
+/*
+ * Byte Order
+ */
+
+#define IceLSBfirst 0
+#define IceMSBfirst 1
+
+
+/*
+ * ICE minor opcodes
+ */
+
+#define ICE_Error 0
+#define ICE_ByteOrder 1
+#define ICE_ConnectionSetup 2
+#define ICE_AuthRequired 3
+#define ICE_AuthReply 4
+#define ICE_AuthNextPhase 5
+#define ICE_ConnectionReply 6
+#define ICE_ProtocolSetup 7
+#define ICE_ProtocolReply 8
+#define ICE_Ping 9
+#define ICE_PingReply 10
+#define ICE_WantToClose 11
+#define ICE_NoClose 12
+
+
+/*
+ * Error severity
+ */
+
+#define IceCanContinue 0
+#define IceFatalToProtocol 1
+#define IceFatalToConnection 2
+
+
+/*
+ * ICE error classes that are common to all protocols
+ */
+
+#define IceBadMinor 0x8000
+#define IceBadState 0x8001
+#define IceBadLength 0x8002
+#define IceBadValue 0x8003
+
+
+/*
+ * ICE error classes that are specific to the ICE protocol
+ */
+
+#define IceBadMajor 0
+#define IceNoAuth 1
+#define IceNoVersion 2
+#define IceSetupFailed 3
+#define IceAuthRejected 4
+#define IceAuthFailed 5
+#define IceProtocolDuplicate 6
+#define IceMajorOpcodeDuplicate 7
+#define IceUnknownProtocol 8
+
+#endif /* _ICE_H_ */
diff --git a/dcop/KDE-ICE/ICEconn.h b/dcop/KDE-ICE/ICEconn.h
new file mode 100644
index 000000000..85dd7ca10
--- /dev/null
+++ b/dcop/KDE-ICE/ICEconn.h
@@ -0,0 +1,247 @@
+/* $Xorg: ICEconn.h,v 1.4 2000/08/17 19:44:10 cpqbld Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#ifndef _ICECONN_H_
+#define _ICECONN_H_
+
+#include "KDE-ICE/ICElib.h"
+
+/*
+ * Data structures for ICE connection object
+ */
+
+typedef struct _IceSavedReplyWait {
+ IceReplyWaitInfo *reply_wait;
+ Bool reply_ready;
+ struct _IceSavedReplyWait *next;
+} _IceSavedReplyWait;
+
+typedef struct _IcePingWait {
+ IcePingReplyProc ping_reply_proc;
+ IcePointer client_data;
+ struct _IcePingWait *next;
+} _IcePingWait;
+
+typedef struct {
+ char *vendor;
+ char *release;
+ int version_count;
+ IcePoVersionRec *version_recs;
+ int auth_count;
+ char **auth_names;
+ IcePoAuthProc *auth_procs;
+ IceIOErrorProc io_error_proc;
+} _IcePoProtocol;
+
+typedef struct {
+ char *vendor;
+ char *release;
+ int version_count;
+ IcePaVersionRec *version_recs;
+ IceProtocolSetupProc protocol_setup_proc;
+ IceProtocolActivateProc protocol_activate_proc;
+ int auth_count;
+ char **auth_names;
+ IcePaAuthProc *auth_procs;
+ IceHostBasedAuthProc host_based_auth_proc;
+ IceIOErrorProc io_error_proc;
+} _IcePaProtocol;
+
+typedef struct {
+ char *protocol_name;
+ _IcePoProtocol *orig_client;
+ _IcePaProtocol *accept_client;
+} _IceProtocol;
+
+typedef struct {
+ Bool in_use;
+ int my_opcode;
+ _IceProtocol *protocol;
+ IcePointer client_data;
+ Bool accept_flag;
+ union {
+ IcePaProcessMsgProc accept_client;
+ IcePoProcessMsgProc orig_client;
+ } process_msg_proc;
+} _IceProcessMsgInfo;
+
+typedef struct {
+ int his_version_index;
+ int my_version_index;
+ char *his_vendor;
+ char *his_release;
+ char my_auth_index;
+ IcePointer my_auth_state;
+ Bool must_authenticate;
+} _IceConnectToMeInfo;
+
+typedef struct {
+ int his_opcode;
+ int my_opcode;
+ int his_version_index;
+ int my_version_index;
+ char *his_vendor;
+ char *his_release;
+ char my_auth_index;
+ IcePointer my_auth_state;
+ Bool must_authenticate;
+} _IceProtoSetupToMeInfo;
+
+typedef struct {
+ Bool auth_active;
+ char my_auth_index;
+ IcePointer my_auth_state;
+} _IceConnectToYouInfo;
+
+typedef struct {
+ int my_opcode;
+ int my_auth_count;
+ int *my_auth_indices;
+ Bool auth_active;
+ char my_auth_index;
+ IcePointer my_auth_state;
+} _IceProtoSetupToYouInfo;
+
+
+struct _IceConn {
+
+ unsigned int io_ok : 1; /* did an IO error occur? */
+ unsigned int swap : 1; /* do we need to swap on reads? */
+ unsigned int waiting_for_byteorder : 1; /* waiting for a ByteOrder msg? */
+ unsigned int skip_want_to_close : 1; /* avoid shutdown negotiation? */
+ unsigned int want_to_close : 1; /* did we send a WantToClose? */
+ unsigned int free_asap : 1; /* free as soon as possible */
+ unsigned int unused1 : 2; /* future use */
+ unsigned int unused2 : 8; /* future use */
+
+ IceConnectStatus connection_status; /* pending, accepted, rejected */
+
+ unsigned char my_ice_version_index; /* which version are we using? */
+
+ struct _XtransConnInfo *trans_conn; /* transport connection object */
+ unsigned long send_sequence; /* Sequence # of last msg sent */
+ unsigned long receive_sequence; /* Sequence # of last msg received */
+
+ char *connection_string; /* network connection string */
+ char *vendor; /* other client's vendor */
+ char *release; /* other client's release */
+
+ char *inbuf; /* Input buffer starting address */
+ char *inbufptr; /* Input buffer index pointer */
+ char *inbufmax; /* Input buffer maximum+1 address */
+
+ char *outbuf; /* Output buffer starting address */
+ char *outbufptr; /* Output buffer index pointer */
+ char *outbufmax; /* Output buffer maximum+1 address */
+
+ char *scratch; /* scratch buffer */
+ unsigned long scratch_size; /* scratch size */
+
+ int dispatch_level; /* IceProcessMessages dispatch level */
+
+ IcePointer context; /* context associated with caller
+ of IceOpenConnection */
+
+ /*
+ * Before we read a message, the major opcode of the message must be
+ * mapped to our corresponding major opcode (the two clients can use
+ * different opcodes for the same protocol). In order to save space,
+ * we keep track of the mininum and maximum major opcodes used by the
+ * other client. To get the information on how to process this message,
+ * we do the following...
+ *
+ * processMsgInfo = iceConn->process_msg_info[
+ * message->majorOpcode - iceConn->his_min_opcode]
+ *
+ * Note that the number of elements in the iceConn->process_msg_info
+ * array is always (iceConn->his_max_opcode - iceConn->his_min_opcode + 1).
+ * We check process_msg_info->in_use to see if the opcode is being used.
+ */
+
+ _IceProcessMsgInfo *process_msg_info;
+ char his_min_opcode; /* [1..255] */
+ char his_max_opcode; /* [1..255] */
+
+
+ /*
+ * Number of times this iceConn was returned in IceOpenConnection
+ * or IceAcceptConnection.
+ */
+
+ unsigned char open_ref_count;
+
+
+ /*
+ * Number of active protocols.
+ */
+
+ unsigned char proto_ref_count;
+
+
+ /*
+ * If this ICE connection was created with IceAcceptConnection,
+ * the listen_obj field is set to the listen object. Otherwise,
+ * the listen_obj field is NULL.
+ */
+
+ IceListenObj listen_obj;
+
+
+
+
+ /*
+ * We need to keep track of all the replies we're waiting for.
+ * Check the comments in process.c for how this works.
+ */
+
+ _IceSavedReplyWait *saved_reply_waits;
+
+
+ /*
+ * We keep track of all Pings sent from the client. When the Ping reply
+ * arrives, we remove it from the list.
+ */
+
+ _IcePingWait *ping_waits;
+
+
+ /*
+ * Some state for a client doing a Connection/Protocol Setup
+ */
+
+ _IceConnectToYouInfo *connect_to_you;
+ _IceProtoSetupToYouInfo *protosetup_to_you;
+
+
+ /*
+ * Some state for a client receiving a Connection/Protocol Setup
+ */
+
+ _IceConnectToMeInfo *connect_to_me;
+ _IceProtoSetupToMeInfo *protosetup_to_me;
+
+};
+
+#endif /* _ICECONN_H_ */
diff --git a/dcop/KDE-ICE/ICElib.h b/dcop/KDE-ICE/ICElib.h
new file mode 100644
index 000000000..69c2c2228
--- /dev/null
+++ b/dcop/KDE-ICE/ICElib.h
@@ -0,0 +1,631 @@
+/* $XConsortium: ICElib.h /main/41 1996/11/29 13:30:19 swick $ */
+/* $XFree86: xc/lib/ICE/ICElib.h,v 3.1 1996/12/23 05:58:57 dawes Exp $ */
+/******************************************************************************
+
+
+Copyright (c) 1993 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#ifndef _ICELIB_H_
+#define _ICELIB_H_
+
+#include <KDE-ICE/ICE.h>
+#include <KDE-ICE/Xfuncproto.h>
+#ifndef SIZEOF
+#define _SIZEOF(x) sz_##x
+#define SIZEOF(x) _SIZEOF(x)
+#endif
+
+#define Bool int
+#define Status int
+#define True 1
+#define False 0
+
+#if NeedFunctionPrototypes
+typedef void *IcePointer;
+#else
+typedef char *IcePointer;
+#endif
+
+typedef enum {
+ IcePoAuthHaveReply,
+ IcePoAuthRejected,
+ IcePoAuthFailed,
+ IcePoAuthDoneCleanup
+} IcePoAuthStatus;
+
+typedef enum {
+ IcePaAuthContinue,
+ IcePaAuthAccepted,
+ IcePaAuthRejected,
+ IcePaAuthFailed
+} IcePaAuthStatus;
+
+typedef enum {
+ IceConnectPending,
+ IceConnectAccepted,
+ IceConnectRejected,
+ IceConnectIOError
+} IceConnectStatus;
+
+typedef enum {
+ IceProtocolSetupSuccess,
+ IceProtocolSetupFailure,
+ IceProtocolSetupIOError,
+ IceProtocolAlreadyActive
+} IceProtocolSetupStatus;
+
+typedef enum {
+ IceAcceptSuccess,
+ IceAcceptFailure,
+ IceAcceptBadMalloc
+} IceAcceptStatus;
+
+typedef enum {
+ IceClosedNow,
+ IceClosedASAP,
+ IceConnectionInUse,
+ IceStartedShutdownNegotiation
+} IceCloseStatus;
+
+typedef enum {
+ IceProcessMessagesSuccess,
+ IceProcessMessagesIOError,
+ IceProcessMessagesConnectionClosed
+} IceProcessMessagesStatus;
+
+typedef struct {
+ unsigned long sequence_of_request;
+ int major_opcode_of_request;
+ int minor_opcode_of_request;
+ IcePointer reply;
+} IceReplyWaitInfo;
+
+typedef struct _IceConn *IceConn;
+typedef struct _IceListenObj *IceListenObj;
+
+typedef void (*IceWatchProc) (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ IcePointer /* clientData */,
+ Bool /* opening */,
+ IcePointer * /* watchData */
+#endif
+);
+
+typedef void (*IcePoProcessMsgProc) (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ IcePointer /* clientData */,
+ int /* opcode */,
+ unsigned long /* length */,
+ Bool /* swap */,
+ IceReplyWaitInfo * /* replyWait */,
+ Bool * /* replyReadyRet */
+#endif
+);
+
+typedef void (*IcePaProcessMsgProc) (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ IcePointer /* clientData */,
+ int /* opcode */,
+ unsigned long /* length */,
+ Bool /* swap */
+#endif
+);
+
+typedef struct {
+ int major_version;
+ int minor_version;
+ IcePoProcessMsgProc process_msg_proc;
+} IcePoVersionRec;
+
+typedef struct {
+ int major_version;
+ int minor_version;
+ IcePaProcessMsgProc process_msg_proc;
+} IcePaVersionRec;
+
+typedef IcePoAuthStatus (*IcePoAuthProc) (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ IcePointer * /* authStatePtr */,
+ Bool /* cleanUp */,
+ Bool /* swap */,
+ int /* authDataLen */,
+ IcePointer /* authData */,
+ int * /* replyDataLenRet */,
+ IcePointer * /* replyDataRet */,
+ char ** /* errorStringRet */
+#endif
+);
+
+typedef IcePaAuthStatus (*IcePaAuthProc) (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ IcePointer * /* authStatePtr */,
+ Bool /* swap */,
+ int /* authDataLen */,
+ IcePointer /* authData */,
+ int * /* replyDataLenRet */,
+ IcePointer * /* replyDataRet */,
+ char ** /* errorStringRet */
+#endif
+);
+
+typedef Bool (*IceHostBasedAuthProc) (
+#if NeedFunctionPrototypes
+ char * /* hostName */
+#endif
+);
+
+typedef Status (*IceProtocolSetupProc) (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* majorVersion */,
+ int /* minorVersion */,
+ char * /* vendor */,
+ char * /* release */,
+ IcePointer * /* clientDataRet */,
+ char ** /* failureReasonRet */
+#endif
+);
+
+typedef void (*IceProtocolActivateProc) (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ IcePointer /* clientData */
+#endif
+);
+
+typedef void (*IceWriteHandler) (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ unsigned long /* nbytes */,
+ char * /* ptr */
+#endif
+);
+
+typedef void (*IceIOErrorProc) (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+typedef void (*IcePingReplyProc) (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ IcePointer /* clientData */
+#endif
+);
+
+typedef void (*IceErrorHandler) (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ Bool /* swap */,
+ int /* offendingMinorOpcode */,
+ unsigned long /* offendingSequence */,
+ int /* errorClass */,
+ int /* severity */,
+ IcePointer /* values */
+#endif
+);
+
+typedef void (*IceIOErrorHandler) (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+
+/*
+ * Function prototypes
+ */
+
+_XFUNCPROTOBEGIN
+
+#define IceRegisterForProtocolSetup KDE_IceRegisterForProtocolSetup
+
+extern int IceRegisterForProtocolSetup (
+#if NeedFunctionPrototypes
+ char * /* protocolName */,
+ char * /* vendor */,
+ char * /* release */,
+ int /* versionCount */,
+ IcePoVersionRec * /* versionRecs */,
+ int /* authCount */,
+ char ** /* authNames */,
+ IcePoAuthProc * /* authProcs */,
+ IceIOErrorProc /* IOErrorProc */
+#endif
+);
+
+#define IceRegisterForProtocolReply KDE_IceRegisterForProtocolReply
+
+extern int IceRegisterForProtocolReply (
+#if NeedFunctionPrototypes
+ char * /* protocolName */,
+ char * /* vendor */,
+ char * /* release */,
+ int /* versionCount */,
+ IcePaVersionRec * /* versionRecs */,
+ int /* authCount */,
+ char ** /* authNames */,
+ IcePaAuthProc * /* authProcs */,
+ IceHostBasedAuthProc /* hostBasedAuthProc */,
+ IceProtocolSetupProc /* protocolSetupProc */,
+ IceProtocolActivateProc /* protocolActivateProc */,
+ IceIOErrorProc /* IOErrorProc */
+#endif
+);
+
+#define IceOpenConnection KDE_IceOpenConnection
+
+extern IceConn IceOpenConnection (
+#if NeedFunctionPrototypes
+ char * /* networkIdsList */,
+ IcePointer /* context */,
+ Bool /* mustAuthenticate */,
+ int /* majorOpcodeCheck */,
+ int /* errorLength */,
+ char * /* errorStringRet */
+#endif
+);
+
+#define IceGetConnectionContext KDE_IceGetConnectionContext
+
+extern IcePointer IceGetConnectionContext (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define IceListenForConnections KDE_IceListenForConnections
+
+extern Status IceListenForConnections (
+#if NeedFunctionPrototypes
+ int * /* countRet */,
+ IceListenObj ** /* listenObjsRet */,
+ int /* errorLength */,
+ char * /* errorStringRet */
+#endif
+);
+
+#define IceListenForWellKnownConnections KDE_IceListenForWellKnownConnections
+
+extern Status IceListenForWellKnownConnections (
+#if NeedFunctionPrototypes
+ char * /* port */,
+ int * /* countRet */,
+ IceListenObj ** /* listenObjsRet */,
+ int /* errorLength */,
+ char * /* errorStringRet */
+#endif
+);
+
+#define IceGetListenConnectionNumber KDE_IceGetListenConnectionNumber
+
+extern int IceGetListenConnectionNumber (
+#if NeedFunctionPrototypes
+ IceListenObj /* listenObj */
+#endif
+);
+
+#define IceGetListenConnectionString KDE_IceGetListenConnectionString
+
+extern char *IceGetListenConnectionString (
+#if NeedFunctionPrototypes
+ IceListenObj /* listenObj */
+#endif
+);
+
+#define IceComposeNetworkIdList KDE_IceComposeNetworkIdList
+
+extern char *IceComposeNetworkIdList (
+#if NeedFunctionPrototypes
+ int /* count */,
+ IceListenObj * /* listenObjs */
+#endif
+);
+
+#define IceFreeListenObjs KDE_IceFreeListenObjs
+
+extern void IceFreeListenObjs (
+#if NeedFunctionPrototypes
+ int /* count */,
+ IceListenObj * /* listenObjs */
+#endif
+);
+
+#define IceSetHostBasedAuthProc KDE_IceSetHostBasedAuthProc
+
+extern void IceSetHostBasedAuthProc (
+#if NeedFunctionPrototypes
+ IceListenObj /* listenObj */,
+ IceHostBasedAuthProc /* hostBasedAuthProc */
+#endif
+);
+
+#define IceAcceptConnection KDE_IceAcceptConnection
+
+extern IceConn IceAcceptConnection (
+#if NeedFunctionPrototypes
+ IceListenObj /* listenObj */,
+ IceAcceptStatus * /* statusRet */
+#endif
+);
+
+#define IceSetShutdownNegotiation KDE_IceSetShutdownNegotiation
+
+extern void IceSetShutdownNegotiation (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ Bool /* negotiate */
+#endif
+);
+
+#define IceCheckShutdownNegotiation KDE_IceCheckShutdownNegotiation
+
+extern Bool IceCheckShutdownNegotiation (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define IceCloseConnection KDE_IceCloseConnection
+
+extern IceCloseStatus IceCloseConnection (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define IceAddConnectionWatch KDE_IceAddConnectionWatch
+
+extern Status IceAddConnectionWatch (
+#if NeedFunctionPrototypes
+ IceWatchProc /* watchProc */,
+ IcePointer /* clientData */
+#endif
+);
+
+#define IceRemoveConnectionWatch KDE_IceRemoveConnectionWatch
+
+extern void IceRemoveConnectionWatch (
+#if NeedFunctionPrototypes
+ IceWatchProc /* watchProc */,
+ IcePointer /* clientData */
+#endif
+);
+
+#define IceProtocolSetup KDE_IceProtocolSetup
+
+extern IceProtocolSetupStatus IceProtocolSetup (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* myOpcode */,
+ IcePointer /* clientData */,
+ Bool /* mustAuthenticate */,
+ int * /* majorVersionRet */,
+ int * /* minorVersionRet */,
+ char ** /* vendorRet */,
+ char ** /* releaseRet */,
+ int /* errorLength */,
+ char * /* errorStringRet */
+#endif
+);
+
+#define IceProtocolShutdown KDE_IceProtocolShutdown
+
+extern Status IceProtocolShutdown (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* majorOpcode */
+#endif
+);
+
+#define IceProcessMessages KDE_IceProcessMessages
+
+extern IceProcessMessagesStatus IceProcessMessages (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ IceReplyWaitInfo * /* replyWait */,
+ Bool * /* replyReadyRet */
+#endif
+);
+
+#define IcePing KDE_IcePing
+
+extern Status IcePing (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ IcePingReplyProc /* pingReplyProc */,
+ IcePointer /* clientData */
+#endif
+);
+
+#define IceAllocScratch KDE_IceAllocScratch
+
+extern char *IceAllocScratch (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ unsigned long /* size */
+#endif
+);
+
+#define IceFlush KDE_IceFlush
+
+extern void IceFlush (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define IceGetOutBufSize KDE_IceGetOutBufSize
+
+extern int IceGetOutBufSize (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define IceGetInBufSize KDE_IceGetInBufSize
+
+extern int IceGetInBufSize (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define IceConnectionStatus KDE_IceConnectionStatus
+
+extern IceConnectStatus IceConnectionStatus (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define IceVendor KDE_IceVendor
+
+extern char *IceVendor (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define IceRelease KDE_IceRelease
+
+extern char *IceRelease (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define IceProtocolVersion KDE_IceProtocolVersion
+
+extern int IceProtocolVersion (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define IceProtocolRevision KDE_IceProtocolRevision
+
+extern int IceProtocolRevision (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define IceConnectionNumber KDE_IceConnectionNumber
+
+extern int IceConnectionNumber (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define IceConnectionString KDE_IceConnectionString
+
+extern char *IceConnectionString (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define IceLastSentSequenceNumber KDE_IceLastSentSequenceNumber
+
+extern unsigned long IceLastSentSequenceNumber (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define IceLastReceivedSequenceNumber KDE_IceLastReceivedSequenceNumber
+
+extern unsigned long IceLastReceivedSequenceNumber (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define IceSwapping KDE_IceSwapping
+
+extern Bool IceSwapping (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define IceSetErrorHandler KDE_IceSetErrorHandler
+
+extern IceErrorHandler IceSetErrorHandler (
+#if NeedFunctionPrototypes
+ IceErrorHandler /* handler */
+#endif
+);
+
+#define IceSetIOErrorHandler KDE_IceSetIOErrorHandler
+
+extern IceIOErrorHandler IceSetIOErrorHandler (
+#if NeedFunctionPrototypes
+ IceIOErrorHandler /* handler */
+#endif
+);
+
+
+/*
+ * Multithread Routines
+ */
+
+#define IceInitThreads KDE_IceInitThreads
+
+extern Status IceInitThreads (
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+#define IceAppLockConn KDE_IceAppLockConn
+
+extern void IceAppLockConn (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define IceAppUnlockConn KDE_IceAppUnlockConn
+
+extern void IceAppUnlockConn (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+_XFUNCPROTOEND
+
+#endif /* _ICELIB_H_ */
diff --git a/dcop/KDE-ICE/ICElibint.h b/dcop/KDE-ICE/ICElibint.h
new file mode 100644
index 000000000..f36ab7acc
--- /dev/null
+++ b/dcop/KDE-ICE/ICElibint.h
@@ -0,0 +1,626 @@
+/* $Xorg: ICElibint.h,v 1.3 2000/08/17 19:44:10 cpqbld Exp $ */
+/******************************************************************************
+
+
+Copyright (c) 1993, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+/* $XFree86: xc/lib/ICE/ICElibint.h,v 1.4 2001/01/17 19:41:29 dawes Exp $ */
+#ifndef _ICELIBINT_H_
+#define _ICELIBINT_H_
+
+#include "config.h"
+#if defined Q_WS_X11 && ! defined K_WS_QTONLY
+#include <X11/Xos.h>
+#include <X11/Xfuncs.h>
+#include <X11/Xmd.h> //schroder
+#else
+#define _SIZEOF(x) sz_##x
+#define SIZEOF(x) _SIZEOF(x)
+#endif
+#include <KDE-ICE/ICEproto.h>
+#include <KDE-ICE/ICEconn.h>
+#include <KDE-ICE/ICEmsg.h>
+
+#ifndef X_NOT_STDC_ENV
+#include <stdlib.h>
+#else
+char *malloc();
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+/*
+ * Vendor & Release
+ */
+
+#define IceVendorString "MIT"
+#define IceReleaseString "1.0"
+
+
+/*
+ * Pad to a 64 bit boundary
+ */
+
+#define PAD64(_bytes) ((8 - ((unsigned int) (_bytes) % 8)) % 8)
+
+#define PADDED_BYTES64(_bytes) (_bytes + PAD64 (_bytes))
+
+
+/*
+ * Pad to 32 bit boundary
+ */
+
+#define PAD32(_bytes) ((4 - ((unsigned int) (_bytes) % 4)) % 4)
+
+#define PADDED_BYTES32(_bytes) (_bytes + PAD32 (_bytes))
+
+
+/*
+ * Number of 8 byte units in _bytes.
+ */
+
+#define WORD64COUNT(_bytes) (((unsigned int) ((_bytes) + 7)) >> 3)
+
+
+/*
+ * Number of 4 byte units in _bytes.
+ */
+
+#define WORD32COUNT(_bytes) (((unsigned int) ((_bytes) + 3)) >> 2)
+
+
+/*
+ * Given a string, compute the number of bytes for the STRING representation
+ */
+
+#define STRING_BYTES(_string) \
+ (2 + strlen (_string) + PAD32 (2 + strlen (_string)))
+
+
+/*
+ * Size of ICE input/output buffers
+ */
+
+#define ICE_INBUFSIZE 1024
+
+#define ICE_OUTBUFSIZE 1024
+
+
+/*
+ * Maxium number of ICE authentication methods allowed, and maxiumum
+ * number of authentication data entries allowed to be set in the
+ * IceSetPaAuthData function.
+ *
+ * We should use linked lists, but this is easier and should suffice.
+ */
+
+#define MAX_ICE_AUTH_NAMES 32
+#define ICE_MAX_AUTH_DATA_ENTRIES 100
+
+
+/*
+ * ICE listen object
+ */
+
+struct _IceListenObj {
+ struct _XtransConnInfo *trans_conn; /* transport connection object */
+ char *network_id;
+ IceHostBasedAuthProc host_based_auth_proc;
+};
+
+
+/*
+ * Some internal data structures for processing ICE messages.
+ */
+
+typedef void (*_IceProcessCoreMsgProc) (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* opcode */,
+ unsigned long /* length */,
+ Bool /* swap */,
+ IceReplyWaitInfo * /* replyWait */,
+ Bool * /* replyReadyRet */,
+ Bool * /* connectionClosedRet */
+#endif
+);
+
+typedef struct {
+ int major_version;
+ int minor_version;
+ _IceProcessCoreMsgProc process_core_msg_proc;
+} _IceVersion;
+
+
+/*
+ * STORE FOO
+ */
+
+#define STORE_CARD8(_pBuf, _val) \
+{ \
+ *((CARD8 *) _pBuf) = _val; \
+ _pBuf += 1; \
+}
+
+#ifndef WORD64
+
+#define STORE_CARD16(_pBuf, _val) \
+{ \
+ *((CARD16 *) _pBuf) = _val; \
+ _pBuf += 2; \
+}
+
+#define STORE_CARD32(_pBuf, _val) \
+{ \
+ *((CARD32 *) _pBuf) = _val; \
+ _pBuf += 4; \
+}
+
+#else /* WORD64 */
+
+#define STORE_CARD16(_pBuf, _val) \
+{ \
+ struct { \
+ int value :16; \
+ int pad :16; \
+ } _d; \
+ _d.value = _val; \
+ memcpy (_pBuf, &_d, 2); \
+ _pBuf += 2; \
+}
+
+#define STORE_CARD32(_pBuf, _val) \
+{ \
+ struct { \
+ int value :32; \
+ } _d; \
+ _d.value = _val; \
+ memcpy (_pBuf, &_d, 4); \
+ _pBuf += 4; \
+}
+
+#endif /* WORD64 */
+
+#define STORE_STRING(_pBuf, _string) \
+{ \
+ CARD16 _len = strlen (_string); \
+ STORE_CARD16 (_pBuf, _len); \
+ memcpy (_pBuf, _string, _len); \
+ _pBuf += _len; \
+ if (PAD32 (2 + _len)) \
+ _pBuf += PAD32 (2 + _len); \
+}
+
+
+/*
+ * EXTRACT FOO
+ */
+
+#define EXTRACT_CARD8(_pBuf, _val) \
+{ \
+ _val = *((CARD8 *) _pBuf); \
+ _pBuf += 1; \
+}
+
+#ifndef WORD64
+
+#define EXTRACT_CARD16(_pBuf, _swap, _val) \
+{ \
+ _val = *((CARD16 *) _pBuf); \
+ _pBuf += 2; \
+ if (_swap) \
+ _val = lswaps (_val); \
+}
+
+#define EXTRACT_CARD32(_pBuf, _swap, _val) \
+{ \
+ _val = *((CARD32 *) _pBuf); \
+ _pBuf += 4; \
+ if (_swap) \
+ _val = lswapl (_val); \
+}
+
+#else /* WORD64 */
+
+#define EXTRACT_CARD16(_pBuf, _swap, _val) \
+{ \
+ _val = *(_pBuf + 0) & 0xff; /* 0xff incase _pBuf is signed */ \
+ _val <<= 8; \
+ _val |= *(_pBuf + 1) & 0xff;\
+ _pBuf += 2; \
+ if (_swap) \
+ _val = lswaps (_val); \
+}
+
+#define EXTRACT_CARD32(_pBuf, _swap, _val) \
+{ \
+ _val = *(_pBuf + 0) & 0xff; /* 0xff incase _pBuf is signed */ \
+ _val <<= 8; \
+ _val |= *(_pBuf + 1) & 0xff;\
+ _val <<= 8; \
+ _val |= *(_pBuf + 2) & 0xff;\
+ _val <<= 8; \
+ _val |= *(_pBuf + 3) & 0xff;\
+ _pBuf += 4; \
+ if (_swap) \
+ _val = lswapl (_val); \
+}
+
+#endif /* WORD64 */
+
+#define EXTRACT_STRING(_pBuf, _swap, _string) \
+{ \
+ CARD16 _len; \
+ EXTRACT_CARD16 (_pBuf, _swap, _len); \
+ _string = (char *) malloc (_len + 1); \
+ memcpy (_string, _pBuf, _len); \
+ _pBuf += _len; \
+ _string[_len] = '\0'; \
+ if (PAD32 (2 + _len)) \
+ _pBuf += PAD32 (2 + _len); \
+}
+
+#define EXTRACT_LISTOF_STRING(_pBuf, _swap, _count, _strings) \
+{ \
+ int _i; \
+ for (_i = 0; _i < _count; _i++) \
+ EXTRACT_STRING (_pBuf, _swap, _strings[_i]); \
+}
+
+
+#define SKIP_STRING(_pBuf, _swap, _end, _bail) \
+{ \
+ CARD16 _len; \
+ EXTRACT_CARD16 (_pBuf, _swap, _len); \
+ _pBuf += _len + PAD32(2+_len); \
+ if (_pBuf > _end) { \
+ _bail; \
+ } \
+}
+
+#define SKIP_LISTOF_STRING(_pBuf, _swap, _count, _end, _bail) \
+{ \
+ int _i; \
+ for (_i = 0; _i < _count; _i++) \
+ SKIP_STRING (_pBuf, _swap, _end, _bail); \
+}
+
+
+
+/*
+ * Byte swapping
+ */
+
+/* byte swap a long literal */
+#define lswapl(_val) ((((_val) & 0xff) << 24) |\
+ (((_val) & 0xff00) << 8) |\
+ (((_val) & 0xff0000) >> 8) |\
+ (((_val) >> 24) & 0xff))
+
+/* byte swap a short literal */
+#define lswaps(_val) ((((_val) & 0xff) << 8) | (((_val) >> 8) & 0xff))
+
+
+
+/*
+ * ICE replies (not processed via callbacks because we block)
+ */
+
+#define ICE_CONNECTION_REPLY 1
+#define ICE_CONNECTION_ERROR 2
+#define ICE_PROTOCOL_REPLY 3
+#define ICE_PROTOCOL_ERROR 4
+
+typedef struct {
+ int type;
+ int version_index;
+ char *vendor;
+ char *release;
+} _IceConnectionReply;
+
+typedef struct {
+ int type;
+ char *error_message;
+} _IceConnectionError;
+
+typedef struct {
+ int type;
+ int major_opcode;
+ int version_index;
+ char *vendor;
+ char *release;
+} _IceProtocolReply;
+
+typedef struct {
+ int type;
+ char *error_message;
+} _IceProtocolError;
+
+
+typedef union {
+ int type;
+ _IceConnectionReply connection_reply;
+ _IceConnectionError connection_error;
+ _IceProtocolReply protocol_reply;
+ _IceProtocolError protocol_error;
+} _IceReply;
+
+
+/*
+ * Watch for ICE connection create/destroy.
+ */
+
+typedef struct _IceWatchedConnection {
+ IceConn iceConn;
+ IcePointer watch_data;
+ struct _IceWatchedConnection *next;
+} _IceWatchedConnection;
+
+typedef struct _IceWatchProc {
+ IceWatchProc watch_proc;
+ IcePointer client_data;
+ _IceWatchedConnection *watched_connections;
+ struct _IceWatchProc *next;
+} _IceWatchProc;
+
+
+/*
+ * Locking
+ */
+
+#define IceLockConn(_iceConn)
+#define IceUnlockConn(_iceConn)
+
+
+/*
+ * Extern declarations
+ */
+
+extern IceConn _IceConnectionObjs[];
+extern char *_IceConnectionStrings[];
+extern int _IceConnectionCount;
+
+extern int _IceAuthCount;
+extern const char *_IceAuthNames[];
+extern IcePoAuthProc _IcePoAuthProcs[];
+extern IcePaAuthProc _IcePaAuthProcs[];
+
+extern int _IceVersionCount;
+
+#define _IceErrorBadMajor _kde_IceErrorBadMajor
+
+
+extern void _IceErrorBadMajor (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* offendingMajor */,
+ int /* offendingMinor */,
+ int /* severity */
+#endif
+);
+
+#define _IceErrorNoAuthentication _kde_IceErrorNoAuthentication
+
+extern void _IceErrorNoAuthentication (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* offendingMinor */
+#endif
+);
+
+#define _IceErrorNoVersion _kde_IceErrorNoVersion
+
+extern void _IceErrorNoVersion (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* offendingMinor */
+#endif
+);
+
+#define _IceErrorSetupFailed _kde_IceErrorSetupFailed
+
+extern void _IceErrorSetupFailed (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* offendingMinor */,
+ const char * /* reason */
+#endif
+);
+
+#define _IceErrorAuthenticationRejected _kde_IceErrorAuthenticationRejected
+
+extern void _IceErrorAuthenticationRejected (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* offendingMinor */,
+ const char * /* reason */
+#endif
+);
+
+#define _IceErrorAuthenticationFailed _kde_IceErrorAuthenticationFailed
+
+extern void _IceErrorAuthenticationFailed (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* offendingMinor */,
+ const char * /* reason */
+#endif
+);
+
+#define _IceErrorProtocolDuplicate _kde_IceErrorProtocolDuplicate
+
+extern void _IceErrorProtocolDuplicate (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ const char * /* protocolName */
+#endif
+);
+
+#define _IceErrorMajorOpcodeDuplicate _kde_IceErrorMajorOpcodeDuplicate
+
+extern void _IceErrorMajorOpcodeDuplicate (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* majorOpcode */
+#endif
+);
+
+#define _IceErrorUnknownProtocol _kde_IceErrorUnknownProtocol
+
+extern void _IceErrorUnknownProtocol (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ const char * /* protocolName */
+#endif
+);
+
+#define _IceAddOpcodeMapping _kde_IceAddOpcodeMapping
+
+extern void _IceAddOpcodeMapping (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* hisOpcode */,
+ int /* myOpcode */
+#endif
+);
+
+#define _IceGetPeerName _kde_IceGetPeerName
+
+extern char *_IceGetPeerName (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define _IceFreeConnection _kde_IceFreeConnection
+
+extern void _IceFreeConnection (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define _IceAddReplyWait _kde_IceAddReplyWait
+
+extern void _IceAddReplyWait (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ IceReplyWaitInfo * /* replyWait */
+#endif
+);
+
+#define _IceSearchReplyWaits _kde_IceSearchReplyWaits
+
+extern IceReplyWaitInfo *_IceSearchReplyWaits (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* majorOpcode */
+#endif
+);
+
+#define _IceSetReplyReady _kde_IceSetReplyReady
+
+extern void _IceSetReplyReady (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ IceReplyWaitInfo * /* replyWait */
+#endif
+);
+
+#define _IceCheckReplyReady _kde_IceCheckReplyReady
+
+extern Bool _IceCheckReplyReady (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ IceReplyWaitInfo * /* replyWait */
+#endif
+);
+
+#define _IceConnectionOpened _kde_IceConnectionOpened
+
+extern void _IceConnectionOpened (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define _IceConnectionClosed _kde_IceConnectionClosed
+
+extern void _IceConnectionClosed (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define _IceGetPoAuthData _kde_IceGetPoAuthData
+
+extern void _IceGetPoAuthData (
+#if NeedFunctionPrototypes
+ const char * /* protocol_name */,
+ const char * /* address */,
+ const char * /* auth_name */,
+ unsigned short * /* auth_data_length_ret */,
+ char ** /* auth_data_ret */
+#endif
+);
+
+#define _IceGetPaAuthData _kde_IceGetPaAuthData
+
+extern void _IceGetPaAuthData (
+#if NeedFunctionPrototypes
+ const char * /* protocol_name */,
+ const char * /* address */,
+ const char * /* auth_name */,
+ unsigned short * /* auth_data_length_ret */,
+ char ** /* auth_data_ret */
+#endif
+);
+
+#define _IceGetPoValidAuthIndices _kde_IceGetPoValidAuthIndices
+
+extern void _IceGetPoValidAuthIndices (
+#if NeedFunctionPrototypes
+ const char * /* protocol_name */,
+ const char * /* address */,
+ int /* num_auth_names */,
+ const char ** /* auth_names */,
+ int * /* num_indices_ret */,
+ int * /* indices_ret */
+#endif
+);
+
+#define _IceGetPaValidAuthIndices _kde_IceGetPaValidAuthIndices
+
+extern void _IceGetPaValidAuthIndices (
+#if NeedFunctionPrototypes
+ const char * /* protocol_name */,
+ const char * /* address */,
+ int /* num_auth_names */,
+ const char ** /* auth_names */,
+ int * /* num_indices_ret */,
+ int * /* indices_ret */
+#endif
+);
+
+#endif /* _ICELIBINT_H_ */
diff --git a/dcop/KDE-ICE/ICEmsg.h b/dcop/KDE-ICE/ICEmsg.h
new file mode 100644
index 000000000..cf4d98975
--- /dev/null
+++ b/dcop/KDE-ICE/ICEmsg.h
@@ -0,0 +1,319 @@
+/* $XConsortium: ICEmsg.h,v 1.5 94/04/17 20:15:26 mor Exp $ */
+/******************************************************************************
+
+
+Copyright (c) 1993 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#ifndef _ICEMSG_H_
+#define _ICEMSG_H_
+
+#include <KDE-ICE/ICEconn.h>
+
+/*
+ * Function prototypes for internal ICElib functions
+ */
+
+#define _IceRead _kde_IceRead
+
+extern Status _IceRead (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ unsigned long /* nbytes */,
+ char * /* ptr */
+#endif
+);
+
+#define _IceReadSkip _kde_IceReadSkip
+
+extern void _IceReadSkip (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ unsigned long /* nbytes */
+#endif
+);
+
+#define _IceWrite _kde_IceWrite
+
+extern void _IceWrite (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ unsigned long /* nbytes */,
+ char * /* ptr */
+#endif
+);
+
+#define _IceWriteHandler _kde_IceWriteHandler
+extern IceWriteHandler _IceWriteHandler;
+
+#define _IceErrorBadMinor _kde_IceErrorBadMinor
+
+extern void _IceErrorBadMinor (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* majorOpcode */,
+ int /* offendingMinor */,
+ int /* severity */
+#endif
+);
+
+#define _IceErrorBadState _kde_IceErrorBadState
+
+extern void _IceErrorBadState (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* majorOpcode */,
+ int /* offendingMinor */,
+ int /* severity */
+#endif
+);
+
+#define _IceErrorBadLength _kde_IceErrorBadLength
+
+extern void _IceErrorBadLength (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* majorOpcode */,
+ int /* offendingMinor */,
+ int /* severity */
+#endif
+);
+
+#define _IceErrorBadValue _kde_IceErrorBadValue
+
+extern void _IceErrorBadValue (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* majorOpcode */,
+ int /* offendingMinor */,
+ int /* offset */,
+ int /* length */,
+ IcePointer /* value */
+#endif
+);
+
+
+/*
+ * Macro to check if IO operations are valid on an ICE connection.
+ */
+
+#define IceValidIO(_iceConn) _iceConn->io_ok
+
+
+/*
+ * Macros for writing messages.
+ */
+
+#define IceGetHeader(_iceConn, _major, _minor, _headerSize, _msgType, _pMsg) \
+ if ((_iceConn->outbufptr + _headerSize) > _iceConn->outbufmax) \
+ IceFlush (_iceConn); \
+ _pMsg = (_msgType *) _iceConn->outbufptr; \
+ _pMsg->majorOpcode = _major; \
+ _pMsg->minorOpcode = _minor; \
+ _pMsg->length = (_headerSize - SIZEOF (iceMsg)) >> 3; \
+ _iceConn->outbufptr += _headerSize; \
+ _iceConn->send_sequence++
+
+#define IceGetHeaderExtra(_iceConn, _major, _minor, _headerSize, _extra, _msgType, _pMsg, _pData) \
+ if ((_iceConn->outbufptr + \
+ _headerSize + ((_extra) << 3)) > _iceConn->outbufmax) \
+ IceFlush (_iceConn); \
+ _pMsg = (_msgType *) _iceConn->outbufptr; \
+ if ((_iceConn->outbufptr + \
+ _headerSize + ((_extra) << 3)) <= _iceConn->outbufmax) \
+ _pData = (char *) _pMsg + _headerSize; \
+ else \
+ _pData = NULL; \
+ _pMsg->majorOpcode = _major; \
+ _pMsg->minorOpcode = _minor; \
+ _pMsg->length = ((_headerSize - SIZEOF (iceMsg)) >> 3) + (_extra); \
+ _iceConn->outbufptr += (_headerSize + ((_extra) << 3)); \
+ _iceConn->send_sequence++
+
+#define IceSimpleMessage(_iceConn, _major, _minor) \
+{ \
+ iceMsg *_pMsg; \
+ IceGetHeader (_iceConn, _major, _minor, SIZEOF (iceMsg), iceMsg, _pMsg); \
+}
+
+#define IceErrorHeader(_iceConn, _offendingMajorOpcode, _offendingMinorOpcode, _offendingSequenceNum, _severity, _errorClass, _dataLength) \
+{ \
+ iceErrorMsg *_pMsg; \
+\
+ IceGetHeader (_iceConn, _offendingMajorOpcode, ICE_Error, \
+ SIZEOF (iceErrorMsg), iceErrorMsg, _pMsg); \
+ _pMsg->length += (_dataLength); \
+ _pMsg->offendingMinorOpcode = _offendingMinorOpcode; \
+ _pMsg->severity = _severity; \
+ _pMsg->offendingSequenceNum = _offendingSequenceNum; \
+ _pMsg->errorClass = _errorClass; \
+}
+
+
+/*
+ * Write data into the ICE output buffer.
+ */
+
+#define IceWriteData(_iceConn, _bytes, _data) \
+{ \
+ if ((_iceConn->outbufptr + (_bytes)) > _iceConn->outbufmax) \
+ { \
+ IceFlush (_iceConn); \
+ (*_IceWriteHandler) (_iceConn, (unsigned long) (_bytes), _data); \
+ } \
+ else \
+ { \
+ memcpy (_iceConn->outbufptr, _data, _bytes); \
+ _iceConn->outbufptr += (_bytes); \
+ } \
+}
+
+#ifndef WORD64
+
+#define IceWriteData16(_iceConn, _bytes, _data) \
+ IceWriteData (_iceConn, _bytes, (char *) _data)
+
+#define IceWriteData32(_iceConn, _bytes, _data) \
+ IceWriteData (_iceConn, _bytes, (char *) _data)
+
+#else /* WORD64 */
+
+/* IceWriteData16 and IceWriteData32 defined in misc.c for WORD64 */
+
+#endif /* WORD64 */
+
+
+/*
+ * The IceSendData macro bypasses copying the data to the
+ * ICE connection buffer and sends the data directly. If necessary,
+ * the ICE connection buffer is first flushed.
+ */
+
+#define IceSendData(_iceConn, _bytes, _data) \
+{ \
+ if (_iceConn->outbufptr > _iceConn->outbuf) \
+ IceFlush (_iceConn); \
+ (*_IceWriteHandler) (_iceConn, (unsigned long) (_bytes), _data); \
+}
+
+
+/*
+ * Write pad bytes. Used to force 32 or 64 bit alignment.
+ * A maxium of 7 pad bytes can be specified.
+ */
+
+#define IceWritePad(_iceConn, _bytes) \
+{ \
+ if ((_iceConn->outbufptr + (_bytes)) > _iceConn->outbufmax) \
+ { \
+ char _dummy[7]; \
+ IceFlush (_iceConn); \
+ (*_IceWriteHandler) (_iceConn, (unsigned long) (_bytes), _dummy); \
+ } \
+ else \
+ { \
+ _iceConn->outbufptr += (_bytes); \
+ } \
+}
+
+
+/*
+ * Macros for reading messages.
+ */
+
+#define IceReadCompleteMessage(_iceConn, _headerSize, _msgType, _pMsg, _pData)\
+{ \
+ unsigned long _bytes; \
+ IceReadMessageHeader (_iceConn, _headerSize, _msgType, _pMsg); \
+ _bytes = (_pMsg->length << 3) - (_headerSize - SIZEOF (iceMsg)); \
+ if ((unsigned long)(_iceConn->inbufmax - _iceConn->inbufptr) >= _bytes) \
+ { \
+ _IceRead (_iceConn, _bytes, _iceConn->inbufptr); \
+ _pData = _iceConn->inbufptr; \
+ _iceConn->inbufptr += _bytes; \
+ } \
+ else \
+ { \
+ _pData = (char *) malloc ((unsigned) _bytes); \
+ if (_pData) \
+ _IceRead (_iceConn, _bytes, _pData); \
+ else \
+ _IceReadSkip (_iceConn, _bytes); \
+ } \
+}
+
+#define IceDisposeCompleteMessage(_iceConn, _pData) \
+ if ((char *) _pData < _iceConn->inbuf || \
+ (char *) _pData >= _iceConn->inbufmax) \
+ free ((char *) _pData);
+
+
+#define IceReadSimpleMessage(_iceConn, _msgType, _pMsg) \
+ _pMsg = (_msgType *) (_iceConn->inbuf);
+
+#define IceReadMessageHeader(_iceConn, _headerSize, _msgType, _pMsg) \
+{ \
+ _IceRead (_iceConn, \
+ (unsigned long) (_headerSize - SIZEOF (iceMsg)), \
+ _iceConn->inbufptr); \
+ _pMsg = (_msgType *) (_iceConn->inbuf); \
+ _iceConn->inbufptr += (_headerSize - SIZEOF (iceMsg)); \
+}
+
+#define IceReadData(_iceConn, _bytes, _pData) \
+ _IceRead (_iceConn, (unsigned long) (_bytes), (char *) _pData); \
+
+#ifndef WORD64
+
+#define IceReadData16(_iceConn, _swap, _bytes, _pData) \
+{ \
+ _IceRead (_iceConn, (unsigned long) (_bytes), (char *) _pData); \
+}
+
+#define IceReadData32(_iceConn, _swap, _bytes, _pData) \
+{ \
+ _IceRead (_iceConn, (unsigned long) (_bytes), (char *) _pData); \
+}
+
+#else /* WORD64 */
+
+/* IceReadData16 and IceReadData32 defined in misc.c for WORD64 */
+
+#endif /* WORD64 */
+
+
+/*
+ * Read pad bytes (for 32 or 64 bit alignment).
+ * A maxium of 7 pad bytes can be specified.
+ */
+
+#define IceReadPad(_iceConn, _bytes) \
+{ \
+ char _dummy[7]; \
+ _IceRead (_iceConn, (unsigned long) (_bytes), _dummy); \
+}
+
+#endif /* _ICEMSG_H_ */
diff --git a/dcop/KDE-ICE/ICEproto.h b/dcop/KDE-ICE/ICEproto.h
new file mode 100644
index 000000000..ff848df04
--- /dev/null
+++ b/dcop/KDE-ICE/ICEproto.h
@@ -0,0 +1,186 @@
+/* $Xorg: ICEproto.h,v 1.4 2000/08/17 19:44:11 cpqbld Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#ifndef _ICEPROTO_H_
+#define _ICEPROTO_H_
+
+#include "config.h"
+#if defined Q_WS_X11 && ! defined K_WS_QTONLY
+#include <X11/Xmd.h>
+#else
+#if defined(__alpha__) || defined(__ia64__) || defined(__s390x__)
+typedef unsigned int CARD32;
+#else
+typedef unsigned long CARD32;
+#endif
+typedef unsigned short CARD16;
+typedef unsigned char CARD8;
+#define B32 :32
+#define B16 :16
+#include <unistd.h>
+#endif
+
+typedef struct {
+ CARD8 majorOpcode;
+ CARD8 minorOpcode;
+ CARD8 data[2];
+ CARD32 length B32;
+} iceMsg;
+
+typedef struct {
+ CARD8 majorOpcode;
+ CARD8 minorOpcode;
+ CARD16 errorClass B16;
+ CARD32 length B32;
+ CARD8 offendingMinorOpcode;
+ CARD8 severity;
+ CARD16 unused B16;
+ CARD32 offendingSequenceNum B32;
+ /* n varying values */
+ /* p p = pad (n, 8) */
+} iceErrorMsg;
+
+typedef struct {
+ CARD8 majorOpcode;
+ CARD8 minorOpcode;
+ CARD8 byteOrder;
+ CARD8 unused;
+ CARD32 length B32;
+} iceByteOrderMsg;
+
+typedef struct {
+ CARD8 majorOpcode;
+ CARD8 minorOpcode;
+ CARD8 versionCount;
+ CARD8 authCount;
+ CARD32 length B32;
+ CARD8 mustAuthenticate;
+ CARD8 unused[7];
+ /* i STRING vendor */
+ /* j STRING release */
+ /* k LIST of STRING authentication-protocol-names */
+ /* m LIST of VERSION version-list */
+ /* p p = pad (i+j+k+m, 8) */
+} iceConnectionSetupMsg;
+
+typedef struct {
+ CARD8 majorOpcode;
+ CARD8 minorOpcode;
+ CARD8 authIndex;
+ CARD8 unused1;
+ CARD32 length B32;
+ CARD16 authDataLength B16;
+ CARD8 unused2[6];
+ /* n varying data */
+ /* p p = pad (n, 8) */
+} iceAuthRequiredMsg;
+
+typedef struct {
+ CARD8 majorOpcode;
+ CARD8 minorOpcode;
+ CARD8 unused1[2];
+ CARD32 length B32;
+ CARD16 authDataLength B16;
+ CARD8 unused2[6];
+ /* n varying data */
+ /* p p = pad (n, 8) */
+} iceAuthReplyMsg;
+
+typedef struct {
+ CARD8 majorOpcode;
+ CARD8 minorOpcode;
+ CARD8 unused1[2];
+ CARD32 length B32;
+ CARD16 authDataLength B16;
+ CARD8 unused2[6];
+ /* n varying data */
+ /* p p = pad (n, 8) */
+} iceAuthNextPhaseMsg;
+
+typedef struct {
+ CARD8 majorOpcode;
+ CARD8 minorOpcode;
+ CARD8 versionIndex;
+ CARD8 unused;
+ CARD32 length B32;
+ /* i STRING vendor */
+ /* j STRING release */
+ /* p p = pad (i+j, 8) */
+} iceConnectionReplyMsg;
+
+typedef struct {
+ CARD8 majorOpcode;
+ CARD8 minorOpcode;
+ CARD8 protocolOpcode;
+ CARD8 mustAuthenticate;
+ CARD32 length B32;
+ CARD8 versionCount;
+ CARD8 authCount;
+ CARD8 unused[6];
+ /* i STRING protocol-name */
+ /* j STRING vendor */
+ /* k STRING release */
+ /* m LIST of STRING authentication-protocol-names */
+ /* n LIST of VERSION version-list */
+ /* p p = pad (i+j+k+m+n, 8) */
+} iceProtocolSetupMsg;
+
+typedef struct {
+ CARD8 majorOpcode;
+ CARD8 minorOpcode;
+ CARD8 versionIndex;
+ CARD8 protocolOpcode;
+ CARD32 length B32;
+ /* i STRING vendor */
+ /* j STRING release */
+ /* p p = pad (i+j, 8) */
+} iceProtocolReplyMsg;
+
+typedef iceMsg icePingMsg;
+typedef iceMsg icePingReplyMsg;
+typedef iceMsg iceWantToCloseMsg;
+typedef iceMsg iceNoCloseMsg;
+
+
+/*
+ * SIZEOF values. These better be multiples of 8.
+ */
+
+#define sz_iceMsg 8
+#define sz_iceErrorMsg 16
+#define sz_iceByteOrderMsg 8
+#define sz_iceConnectionSetupMsg 16
+#define sz_iceAuthRequiredMsg 16
+#define sz_iceAuthReplyMsg 16
+#define sz_iceAuthNextPhaseMsg 16
+#define sz_iceConnectionReplyMsg 8
+#define sz_iceProtocolSetupMsg 16
+#define sz_iceProtocolReplyMsg 8
+#define sz_icePingMsg 8
+#define sz_icePingReplyMsg 8
+#define sz_iceWantToCloseMsg 8
+#define sz_iceNoCloseMsg 8
+
+#endif /* _ICEPROTO_H_ */
diff --git a/dcop/KDE-ICE/ICEutil.h b/dcop/KDE-ICE/ICEutil.h
new file mode 100644
index 000000000..dd32fe620
--- /dev/null
+++ b/dcop/KDE-ICE/ICEutil.h
@@ -0,0 +1,156 @@
+/* $XConsortium: ICEutil.h,v 1.5 94/04/17 20:15:27 mor Exp $ */
+/******************************************************************************
+
+
+Copyright (c) 1993 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#ifndef _ICEUTIL_H_
+#define _ICEUTIL_H_
+
+#include <stdio.h>
+
+/*
+ * Data structure for entry in ICE authority file
+ */
+
+typedef struct {
+ char *protocol_name;
+ unsigned short protocol_data_length;
+ char *protocol_data;
+ char *network_id;
+ char *auth_name;
+ unsigned short auth_data_length;
+ char *auth_data;
+} IceAuthFileEntry;
+
+
+/*
+ * Authentication data maintained in memory.
+ */
+
+typedef struct {
+ char *protocol_name;
+ char *network_id;
+ char *auth_name;
+ unsigned short auth_data_length;
+ char *auth_data;
+} IceAuthDataEntry;
+
+
+/*
+ * Return values from IceLockAuthFile
+ */
+
+#define IceAuthLockSuccess 0 /* lock succeeded */
+#define IceAuthLockError 1 /* lock unexpectely failed, check errno */
+#define IceAuthLockTimeout 2 /* lock failed, timeouts expired */
+
+
+/*
+ * Function Prototypes
+ */
+
+#define IceAuthFileName KDE_IceAuthFileName
+
+extern char *IceAuthFileName (
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+#define IceLockAuthFile KDE_IceLockAuthFile
+
+extern int IceLockAuthFile (
+#if NeedFunctionPrototypes
+ char * /* file_name */,
+ int /* retries */,
+ int /* timeout */,
+ long /* dead */
+#endif
+);
+
+#define IceUnlockAuthFile KDE_IceUnlockAuthFile
+
+extern void IceUnlockAuthFile (
+#if NeedFunctionPrototypes
+ char * /* file_name */
+#endif
+);
+
+#define IceReadAuthFileEntry KDE_IceReadAuthFileEntry
+
+extern IceAuthFileEntry *IceReadAuthFileEntry (
+#if NeedFunctionPrototypes
+ FILE * /* auth_file */
+#endif
+);
+
+#define IceFreeAuthFileEntry KDE_IceFreeAuthFileEntry
+
+extern void IceFreeAuthFileEntry (
+#if NeedFunctionPrototypes
+ IceAuthFileEntry * /* auth */
+#endif
+);
+
+#define IceWriteAuthFileEntry KDE_IceWriteAuthFileEntry
+
+extern Status KDE_IceWriteAuthFileEntry (
+#if NeedFunctionPrototypes
+ FILE * /* auth_file */,
+ IceAuthFileEntry * /* auth */
+#endif
+);
+
+#define IceGetAuthFileEntry KDE_IceGetAuthFileEntry
+
+extern IceAuthFileEntry *IceGetAuthFileEntry (
+#if NeedFunctionPrototypes
+ const char * /* protocol_name */,
+ const char * /* network_id */,
+ const char * /* auth_name */
+#endif
+);
+
+#define IceGenerateMagicCookie KDE_IceGenerateMagicCookie
+
+extern char *IceGenerateMagicCookie (
+#if NeedFunctionPrototypes
+ int /* len */
+#endif
+);
+
+#define IceSetPaAuthData KDE_IceSetPaAuthData
+
+extern void IceSetPaAuthData (
+#if NeedFunctionPrototypes
+ int /* numEntries */,
+ IceAuthDataEntry * /* entries */
+#endif
+);
+
+#endif /* _ICEUTIL_H_ */
diff --git a/dcop/KDE-ICE/Makefile.am b/dcop/KDE-ICE/Makefile.am
new file mode 100644
index 000000000..b75fc0a13
--- /dev/null
+++ b/dcop/KDE-ICE/Makefile.am
@@ -0,0 +1,38 @@
+
+AM_CFLAGS = -DICE_t -DTRANS_SERVER -DTRANS_CLIENT -DUNIXCONN -DANSICPP
+INCLUDES = $(all_includes)
+
+noinst_LTLIBRARIES = libkICE.la
+
+noinst_HEADERS = ICE.h \
+ ICEconn.h \
+ ICElib.h \
+ ICElibint.h \
+ ICEmsg.h \
+ ICEproto.h \
+ ICEutil.h \
+ Xtrans.h \
+ Xtransint.h \
+ Xfuncproto.h \
+ globals.h
+
+libkICE_la_SOURCES = accept.c \
+ authutil.c \
+ connect.c \
+ error.c \
+ getauth.c \
+ iceauth.c \
+ listen.c \
+ listenwk.c \
+ locking.c \
+ misc.c \
+ ping.c \
+ process.c \
+ protosetup.c \
+ register.c \
+ replywait.c \
+ setauth.c \
+ shutdown.c \
+ watch.c \
+ transport.c \
+ globals.c
diff --git a/dcop/KDE-ICE/Xfuncproto.h b/dcop/KDE-ICE/Xfuncproto.h
new file mode 100644
index 000000000..e434e7257
--- /dev/null
+++ b/dcop/KDE-ICE/Xfuncproto.h
@@ -0,0 +1,83 @@
+/* $Xorg: Xfuncproto.h,v 1.3 2000/08/18 04:05:44 coskrey Exp $ */
+/*
+ *
+Copyright 1989, 1991, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+ *
+ */
+
+/* Definitions to make function prototypes manageable */
+
+#ifndef _XFUNCPROTO_H_
+#define _XFUNCPROTO_H_
+
+#ifndef NeedFunctionPrototypes
+#if defined(FUNCPROTO) || defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus)
+#define NeedFunctionPrototypes 1
+#else
+#define NeedFunctionPrototypes 0
+#endif
+#endif /* NeedFunctionPrototypes */
+
+#ifndef NeedVarargsPrototypes
+#if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus) || (FUNCPROTO&2)
+#define NeedVarargsPrototypes 1
+#else
+#define NeedVarargsPrototypes 0
+#endif
+#endif /* NeedVarargsPrototypes */
+
+#if NeedFunctionPrototypes
+
+#ifndef NeedNestedPrototypes
+#if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus) || (FUNCPROTO&8)
+#define NeedNestedPrototypes 1
+#else
+#define NeedNestedPrototypes 0
+#endif
+#endif /* NeedNestedPrototypes */
+
+#ifndef _Xconst
+#if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus) || (FUNCPROTO&4)
+#define _Xconst const
+#else
+#define _Xconst
+#endif
+#endif /* _Xconst */
+
+#ifndef NeedWidePrototypes
+#ifdef NARROWPROTO
+#define NeedWidePrototypes 0
+#else
+#define NeedWidePrototypes 1 /* default to make interropt. easier */
+#endif
+#endif /* NeedWidePrototypes */
+
+#endif /* NeedFunctionPrototypes */
+
+#ifndef _XFUNCPROTOBEGIN
+#ifdef __cplusplus /* for C++ V2.0 */
+#define _XFUNCPROTOBEGIN extern "C" { /* do not leave open across includes */
+#define _XFUNCPROTOEND }
+#else
+#define _XFUNCPROTOBEGIN
+#define _XFUNCPROTOEND
+#endif
+#endif /* _XFUNCPROTOBEGIN */
+
+#endif /* _XFUNCPROTO_H_ */
diff --git a/dcop/KDE-ICE/Xtrans.c b/dcop/KDE-ICE/Xtrans.c
new file mode 100644
index 000000000..371752919
--- /dev/null
+++ b/dcop/KDE-ICE/Xtrans.c
@@ -0,0 +1,1343 @@
+/* $TOG: Xtrans.c /main/34 1998/02/06 15:55:15 kaleb $ */
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+
+*/
+/* $XFree86: xc/lib/xtrans/Xtrans.c,v 3.22 1999/12/27 00:39:28 robin Exp $ */
+
+/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
+ *
+ * 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 NCR not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCR makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NCR 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.
+ */
+
+#include <ctype.h>
+#ifdef _AIX
+extern char *strpbrk(const char *, const char *);
+extern char *strchr(const char *, int);
+#endif
+
+/*
+ * The transport table contains a definition for every transport (protocol)
+ * family. All operations that can be made on the transport go through this
+ * table.
+ *
+ * Each transport is assigned a unique transport id.
+ *
+ * New transports can be added by adding an entry in this table.
+ * For compatibility, the transport ids should never be renumbered.
+ * Always add to the end of the list.
+ */
+
+#define TRANS_TLI_INET_INDEX 1
+#define TRANS_TLI_TCP_INDEX 2
+#define TRANS_TLI_TLI_INDEX 3
+#define TRANS_SOCKET_UNIX_INDEX 4
+#define TRANS_SOCKET_LOCAL_INDEX 5
+#define TRANS_SOCKET_INET_INDEX 6
+#define TRANS_SOCKET_TCP_INDEX 7
+#define TRANS_DNET_INDEX 8
+#define TRANS_LOCAL_LOCAL_INDEX 9
+#define TRANS_LOCAL_PTS_INDEX 10
+#define TRANS_LOCAL_NAMED_INDEX 11
+#define TRANS_LOCAL_ISC_INDEX 12
+#define TRANS_LOCAL_SCO_INDEX 13
+#define TRANS_AMOEBA_INDEX 14
+#define TRANS_MNX_INET_INDEX 15
+#define TRANS_MNX_TCP_INDEX 16
+
+
+static
+Xtransport_table Xtransports[] = {
+#if defined(STREAMSCONN)
+ { &TRANS(TLITCPFuncs), TRANS_TLI_TCP_INDEX },
+ { &TRANS(TLIINETFuncs), TRANS_TLI_INET_INDEX },
+ { &TRANS(TLITLIFuncs), TRANS_TLI_TLI_INDEX },
+#endif /* STREAMSCONN */
+#if defined(TCPCONN)
+ { &TRANS(SocketTCPFuncs), TRANS_SOCKET_TCP_INDEX },
+ { &TRANS(SocketINETFuncs), TRANS_SOCKET_INET_INDEX },
+#endif /* TCPCONN */
+#if defined(DNETCONN)
+ { &TRANS(DNETFuncs), TRANS_DNET_INDEX },
+#endif /* DNETCONN */
+#if defined(UNIXCONN)
+#if !defined(LOCALCONN)
+ { &TRANS(SocketLocalFuncs), TRANS_SOCKET_LOCAL_INDEX },
+#endif /* !LOCALCONN */
+ { &TRANS(SocketUNIXFuncs), TRANS_SOCKET_UNIX_INDEX },
+#endif /* UNIXCONN */
+#if defined(OS2PIPECONN)
+ { &TRANS(OS2LocalFuncs), TRANS_LOCAL_LOCAL_INDEX },
+#endif /* OS2PIPECONN */
+#if defined(LOCALCONN)
+ { &TRANS(LocalFuncs), TRANS_LOCAL_LOCAL_INDEX },
+#ifndef sun
+ { &TRANS(PTSFuncs), TRANS_LOCAL_PTS_INDEX },
+#endif /* sun */
+#ifdef SVR4
+ { &TRANS(NAMEDFuncs), TRANS_LOCAL_NAMED_INDEX },
+#endif
+#ifndef sun
+ { &TRANS(ISCFuncs), TRANS_LOCAL_ISC_INDEX },
+ { &TRANS(SCOFuncs), TRANS_LOCAL_SCO_INDEX },
+#endif /* sun */
+#endif /* LOCALCONN */
+#if defined(AMRPCCONN) || defined(AMTCPCONN)
+ { &TRANS(AmConnFuncs), TRANS_AMOEBA_INDEX },
+#endif /* AMRPCCONN || AMTCPCONN */
+#if defined(MNX_TCPCONN)
+ { &TRANS(MnxINETFuncs), TRANS_MNX_INET_INDEX },
+ { &TRANS(MnxTCPFuncs), TRANS_MNX_TCP_INDEX },
+#endif /* MNX_TCPCONN */
+};
+
+#define NUMTRANS (sizeof(Xtransports)/sizeof(Xtransport_table))
+
+
+#ifdef _WIN32
+#define ioctl ioctlsocket
+#endif
+
+
+/*
+ * These are a few utility function used by the public interface functions.
+ */
+
+void
+TRANS(FreeConnInfo) (XtransConnInfo ciptr)
+
+{
+ PRMSG (3,"FreeConnInfo(%x)\n", ciptr, 0, 0);
+
+ if (ciptr->addr)
+ xfree (ciptr->addr);
+
+ if (ciptr->peeraddr)
+ xfree (ciptr->peeraddr);
+
+ if (ciptr->port)
+ xfree (ciptr->port);
+
+ xfree ((char *) ciptr);
+}
+
+
+#define PROTOBUFSIZE 20
+
+static Xtransport *
+TRANS(SelectTransport) (char *protocol)
+
+{
+ char protobuf[PROTOBUFSIZE];
+ int i;
+
+ PRMSG (3,"SelectTransport(%s)\n", protocol, 0, 0);
+
+ /*
+ * Force Protocol to be lowercase as a way of doing
+ * a case insensitive match.
+ */
+
+ strncpy (protobuf, protocol, PROTOBUFSIZE - 1);
+ protobuf[PROTOBUFSIZE-1] = '\0';
+
+ for (i = 0; i < PROTOBUFSIZE && protobuf[i] != '\0'; i++)
+ if (isupper (protobuf[i]))
+ protobuf[i] = tolower (protobuf[i]);
+
+ /* Look at all of the configured protocols */
+
+ for (i = 0; i < (int) NUMTRANS; i++)
+ {
+ if (!strcmp (protobuf, Xtransports[i].transport->TransName))
+ return Xtransports[i].transport;
+ }
+
+ return NULL;
+}
+
+#ifndef TEST_t
+static
+#endif /* TEST_t */
+int
+TRANS(ParseAddress) (char *address, char **protocol, char **host, char **port)
+
+{
+ /*
+ * For the font library, the address is a string formatted
+ * as "protocol/host:port[/catalog]". Note that the catalog
+ * is optional. At this time, the catalog info is ignored, but
+ * we have to parse it anyways.
+ *
+ * Other than fontlib, the address is a string formatted
+ * as "protocol/host:port".
+ *
+ * If the protocol part is missing, then assume INET.
+ * If the protocol part and host part are missing, then assume local.
+ */
+
+ char *mybuf, *tmpptr;
+ char *_protocol, *_host, *_port;
+ char hostnamebuf[256];
+
+ PRMSG (3,"ParseAddress(%s)\n", address, 0, 0);
+
+ /* Copy the string so it can be changed */
+
+ tmpptr = mybuf = (char *) xalloc (strlen (address) + 1);
+ strcpy (mybuf, address);
+
+ /* Parse the string to get each component */
+
+ /* Get the protocol part */
+
+ _protocol = mybuf;
+
+
+ if ( ((mybuf = strchr (mybuf,'/')) == NULL) &&
+ ((mybuf = strrchr (tmpptr,':')) == NULL) )
+ {
+ /* address is in a bad format */
+ *protocol = NULL;
+ *host = NULL;
+ *port = NULL;
+ xfree (tmpptr);
+ return 0;
+ }
+
+ if (*mybuf == ':')
+ {
+ /*
+ * If there is a hostname, then assume tcp, otherwise
+ * it must be local.
+ */
+ if (mybuf == tmpptr)
+ {
+ /* There is neither a protocol or host specified */
+ _protocol = (char*)"local";
+ }
+ else
+ {
+ /* Ther is a hostname specified */
+ _protocol = (char*)"inet";
+ mybuf = tmpptr; /* reset to the begining of the host ptr */
+ }
+ }
+ else
+ {
+ /* *mybuf == '/' */
+
+ *mybuf ++= '\0'; /* put a null at the end of the protocol */
+
+ if (strlen(_protocol) == 0)
+ {
+ /*
+ * If there is a hostname, then assume inet, otherwise
+ * it must be local.
+ */
+ if (*mybuf != ':')
+ _protocol = (char*)"inet";
+ else
+ _protocol = (char*)"local";
+ }
+ }
+
+ /* Get the host part */
+
+ _host = mybuf;
+
+ if ((mybuf = strrchr (mybuf,':')) == NULL)
+ {
+ *protocol = NULL;
+ *host = NULL;
+ *port = NULL;
+ xfree (tmpptr);
+ return 0;
+ }
+
+ *mybuf ++= '\0';
+
+ if (strlen(_host) == 0)
+ {
+ TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
+ _host = hostnamebuf;
+ }
+
+ /* Get the port */
+
+ _port = mybuf;
+
+#if defined(FONT_t) || defined(FS_t)
+ /*
+ * Is there an optional catalog list?
+ */
+
+ if ((mybuf = strchr (mybuf,'/')) != NULL)
+ *mybuf ++= '\0';
+
+ /*
+ * The rest, if any, is the (currently unused) catalog list.
+ *
+ * _catalogue = mybuf;
+ */
+#endif
+
+ /*
+ * Now that we have all of the components, allocate new
+ * string space for them.
+ */
+
+ if ((*protocol = (char *) xalloc(strlen (_protocol) + 1)) == NULL)
+ {
+ /* Malloc failed */
+ *port = NULL;
+ *host = NULL;
+ *protocol = NULL;
+ xfree (tmpptr);
+ return 0;
+ }
+ else
+ strcpy (*protocol, _protocol);
+
+ if ((*host = (char *) xalloc (strlen (_host) + 1)) == NULL)
+ {
+ /* Malloc failed */
+ *port = NULL;
+ *host = NULL;
+ xfree (*protocol);
+ *protocol = NULL;
+ xfree (tmpptr);
+ return 0;
+ }
+ else
+ strcpy (*host, _host);
+
+ if ((*port = (char *) xalloc (strlen (_port) + 1)) == NULL)
+ {
+ /* Malloc failed */
+ *port = NULL;
+ xfree (*host);
+ *host = NULL;
+ xfree (*protocol);
+ *protocol = NULL;
+ xfree (tmpptr);
+ return 0;
+ }
+ else
+ strcpy (*port, _port);
+
+ xfree (tmpptr);
+
+ return 1;
+}
+
+
+/*
+ * TRANS(Open) does all of the real work opening a connection. The only
+ * funny part about this is the type parameter which is used to decide which
+ * type of open to perform.
+ */
+
+static XtransConnInfo
+TRANS(Open) (int type, char *address)
+
+{
+ char *protocol = NULL, *host = NULL, *port = NULL;
+ XtransConnInfo ciptr = NULL;
+ Xtransport *thistrans;
+
+ PRMSG (2,"Open(%d,%s)\n", type, address, 0);
+
+#if defined(_WIN32) && (defined(TCPCONN) || defined(DNETCONN))
+ if (TRANS(WSAStartup)())
+ {
+ PRMSG (1,"Open: WSAStartup failed\n", 0, 0, 0);
+ return NULL;
+ }
+#endif
+
+ /* Parse the Address */
+
+ if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
+ {
+ PRMSG (1,"Open: Unable to Parse address %s\n", address, 0, 0);
+ return NULL;
+ }
+
+ /* Determine the transport type */
+
+ if ((thistrans = TRANS(SelectTransport) (protocol)) == NULL)
+ {
+ PRMSG (1,"Open: Unable to find transport for %s\n",
+ protocol, 0, 0);
+
+ xfree (protocol);
+ xfree (host);
+ xfree (port);
+ return NULL;
+ }
+
+ /* Open the transport */
+
+ switch (type)
+ {
+ case XTRANS_OPEN_COTS_CLIENT:
+#ifdef TRANS_CLIENT
+ ciptr = thistrans->OpenCOTSClient(thistrans, protocol, host, port);
+#endif /* TRANS_CLIENT */
+ break;
+ case XTRANS_OPEN_COTS_SERVER:
+#ifdef TRANS_SERVER
+ ciptr = thistrans->OpenCOTSServer(thistrans, protocol, host, port);
+#endif /* TRANS_SERVER */
+ break;
+ case XTRANS_OPEN_CLTS_CLIENT:
+#ifdef TRANS_CLIENT
+ ciptr = thistrans->OpenCLTSClient(thistrans, protocol, host, port);
+#endif /* TRANS_CLIENT */
+ break;
+ case XTRANS_OPEN_CLTS_SERVER:
+#ifdef TRANS_SERVER
+ ciptr = thistrans->OpenCLTSServer(thistrans, protocol, host, port);
+#endif /* TRANS_SERVER */
+ break;
+ default:
+ PRMSG (1,"Open: Unknown Open type %d\n", type, 0, 0);
+ }
+
+ if (ciptr == NULL)
+ {
+ if (!(thistrans->flags & TRANS_DISABLED))
+ {
+ PRMSG (1,"Open: transport open failed for %s/%s:%s\n",
+ protocol, host, port);
+ }
+ xfree (protocol);
+ xfree (host);
+ xfree (port);
+ return NULL;
+ }
+
+ ciptr->transptr = thistrans;
+ ciptr->port = port; /* We need this for TRANS(Reopen) */
+
+ xfree (protocol);
+ xfree (host);
+
+ return ciptr;
+}
+
+
+#ifdef TRANS_REOPEN
+
+/*
+ * We might want to create an XtransConnInfo object based on a previously
+ * opened connection. For example, the font server may clone itself and
+ * pass file descriptors to the parent.
+ */
+
+static XtransConnInfo
+TRANS(Reopen) (int type, int trans_id, int fd, char *port)
+
+{
+ XtransConnInfo ciptr = NULL;
+ Xtransport *thistrans = NULL;
+ char *save_port;
+ int i;
+
+ PRMSG (2,"Reopen(%d,%d,%s)\n", trans_id, fd, port);
+
+ /* Determine the transport type */
+
+ for (i = 0; i < NUMTRANS; i++)
+ if (Xtransports[i].transport_id == trans_id)
+ {
+ thistrans = Xtransports[i].transport;
+ break;
+ }
+
+ if (thistrans == NULL)
+ {
+ PRMSG (1,"Reopen: Unable to find transport id %d\n",
+ trans_id, 0, 0);
+
+ return NULL;
+ }
+
+ if ((save_port = (char *) xalloc (strlen (port) + 1)) == NULL)
+ {
+ PRMSG (1,"Reopen: Unable to malloc port string\n", 0, 0, 0);
+
+ return NULL;
+ }
+
+ strcpy (save_port, port);
+
+ /* Get a new XtransConnInfo object */
+
+ switch (type)
+ {
+ case XTRANS_OPEN_COTS_SERVER:
+ ciptr = thistrans->ReopenCOTSServer(thistrans, fd, port);
+ break;
+ case XTRANS_OPEN_CLTS_SERVER:
+ ciptr = thistrans->ReopenCLTSServer(thistrans, fd, port);
+ break;
+ default:
+ PRMSG (1,"Reopen: Bad Open type %d\n", type, 0, 0);
+ }
+
+ if (ciptr == NULL)
+ {
+ PRMSG (1,"Reopen: transport open failed\n", 0, 0, 0);
+ return NULL;
+ }
+
+ ciptr->transptr = thistrans;
+ ciptr->port = save_port;
+
+ return ciptr;
+}
+
+#endif /* TRANS_REOPEN */
+
+
+
+/*
+ * These are the public interfaces to this Transport interface.
+ * These are the only functions that should have knowledge of the transport
+ * table.
+ */
+
+#ifdef TRANS_CLIENT
+
+XtransConnInfo
+TRANS(OpenCOTSClient) (char *address)
+
+{
+ PRMSG (2,"OpenCOTSClient(%s)\n", address, 0, 0);
+ return TRANS(Open) (XTRANS_OPEN_COTS_CLIENT, address);
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+XtransConnInfo
+TRANS(OpenCOTSServer) (char *address)
+
+{
+ PRMSG (2,"OpenCOTSServer(%s)\n", address, 0, 0);
+ return TRANS(Open) (XTRANS_OPEN_COTS_SERVER, address);
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_CLIENT
+
+XtransConnInfo
+TRANS(OpenCLTSClient) (char *address)
+
+{
+ PRMSG (2,"OpenCLTSClient(%s)\n", address, 0, 0);
+ return TRANS(Open) (XTRANS_OPEN_CLTS_CLIENT, address);
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+XtransConnInfo
+TRANS(OpenCLTSServer) (char *address)
+
+{
+ PRMSG (2,"OpenCLTSServer(%s)\n", address, 0, 0);
+ return TRANS(Open) (XTRANS_OPEN_CLTS_SERVER, address);
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_REOPEN
+
+XtransConnInfo
+TRANS(ReopenCOTSServer) (int trans_id, int fd, char *port)
+
+{
+ PRMSG (2,"ReopenCOTSServer(%d, %d, %s)\n", trans_id, fd, port);
+ return TRANS(Reopen) (XTRANS_OPEN_COTS_SERVER, trans_id, fd, port);
+}
+
+XtransConnInfo
+TRANS(ReopenCLTSServer) (int trans_id, int fd, char *port)
+
+{
+ PRMSG (2,"ReopenCLTSServer(%d, %d, %s)\n", trans_id, fd, port);
+ return TRANS(Reopen) (XTRANS_OPEN_CLTS_SERVER, trans_id, fd, port);
+}
+
+
+int
+TRANS(GetReopenInfo) (XtransConnInfo ciptr,
+ int *trans_id, int *fd, char **port)
+
+{
+ int i;
+
+ for (i = 0; i < NUMTRANS; i++)
+ if (Xtransports[i].transport == ciptr->transptr)
+ {
+ *trans_id = Xtransports[i].transport_id;
+ *fd = ciptr->fd;
+
+ if ((*port = (char *) xalloc (strlen (ciptr->port) + 1)) == NULL)
+ return 0;
+ else
+ {
+ strcpy (*port, ciptr->port);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+#endif /* TRANS_REOPEN */
+
+
+int
+TRANS(SetOption) (XtransConnInfo ciptr, int option, int arg)
+
+{
+ int fd = ciptr->fd;
+ int ret = 0;
+
+ PRMSG (2,"SetOption(%d,%d,%d)\n", fd, option, arg);
+
+ /*
+ * For now, all transport type use the same stuff for setting options.
+ * As long as this is true, we can put the common code here. Once a more
+ * complicated transport such as shared memory or an OSI implementation
+ * that uses the session and application libraries is implemented, this
+ * code may have to move to a transport dependent function.
+ *
+ * ret = ciptr->transptr->SetOption (ciptr, option, arg);
+ */
+
+#ifdef MINIX
+ return ciptr->transptr->SetOption(ciptr, option, arg);
+#else /* !MINIX */
+
+ switch (option)
+ {
+ case TRANS_NONBLOCKING:
+ switch (arg)
+ {
+ case 0:
+ /* Set to blocking mode */
+ break;
+ case 1: /* Set to non-blocking mode */
+
+#if defined(O_NONBLOCK) && (!defined(ultrix) && !defined(hpux) && !defined(AIXV3) && !defined(uniosu) && !defined(__EMX__) && !defined(SCO)) && !defined(__QNX__)
+ ret = fcntl (fd, F_GETFL, 0);
+ if (ret != -1)
+ ret = fcntl (fd, F_SETFL, ret | O_NONBLOCK);
+#else
+#ifdef FIOSNBIO
+ {
+ int arg;
+ arg = 1;
+ ret = ioctl (fd, FIOSNBIO, &arg);
+ }
+#else
+#if (defined(AIXV3) || defined(uniosu) || defined(_WIN32) || defined(__EMX__) || defined(__QNX__)) && defined(FIONBIO)
+ {
+ int arg;
+ arg = 1;
+/* IBM TCP/IP understands this option too well: it causes TRANS(Read) to fail
+ * eventually with EWOULDBLOCK */
+#ifndef __EMX__
+ ret = ioctl (fd, FIONBIO, &arg);
+#else
+/* ret = ioctl(fd, FIONBIO, &arg, sizeof(int));*/
+#endif
+ }
+#else
+ ret = fcntl (fd, F_GETFL, 0);
+#ifdef FNDELAY
+ ret = fcntl (fd, F_SETFL, ret | FNDELAY);
+#else
+ ret = fcntl (fd, F_SETFL, ret | O_NDELAY);
+#endif
+#endif /* AIXV3 || uniosu */
+#endif /* FIOSNBIO */
+#endif /* O_NONBLOCK */
+ break;
+ default:
+ /* Unknown option */
+ break;
+ }
+ break;
+ case TRANS_CLOSEONEXEC:
+#ifdef F_SETFD
+#ifdef FD_CLOEXEC
+ ret = fcntl (fd, F_SETFD, FD_CLOEXEC);
+#else
+ ret = fcntl (fd, F_SETFD, 1);
+#endif /* FD_CLOEXEC */
+#endif /* F_SETFD */
+ break;
+ }
+
+ return ret;
+#endif /* MINIX */
+}
+
+#ifdef TRANS_SERVER
+
+int
+TRANS(CreateListener) (XtransConnInfo ciptr, char *port)
+
+{
+ return ciptr->transptr->CreateListener (ciptr, port);
+}
+
+int
+TRANS(NoListen) (char * protocol)
+
+{
+ Xtransport *trans;
+
+ if ((trans = TRANS(SelectTransport)(protocol)) == NULL)
+ {
+ PRMSG (1,"TRANS(TransNoListen): unable to find transport: %s\n",
+ protocol, 0, 0);
+
+ return -1;
+ }
+
+ trans->flags |= TRANS_NOLISTEN;
+ return 0;
+}
+
+int
+TRANS(ResetListener) (XtransConnInfo ciptr)
+
+{
+ if (ciptr->transptr->ResetListener)
+ return ciptr->transptr->ResetListener (ciptr);
+ else
+ return TRANS_RESET_NOOP;
+}
+
+
+XtransConnInfo
+TRANS(Accept) (XtransConnInfo ciptr, int *status)
+
+{
+ XtransConnInfo newciptr;
+
+ PRMSG (2,"Accept(%d)\n", ciptr->fd, 0, 0);
+
+ newciptr = ciptr->transptr->Accept (ciptr, status);
+
+ if (newciptr)
+ newciptr->transptr = ciptr->transptr;
+
+ return newciptr;
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_CLIENT
+
+int
+TRANS(Connect) (XtransConnInfo ciptr, char *address)
+
+{
+ char *protocol;
+ char *host;
+ char *port;
+ int ret;
+
+ PRMSG (2,"Connect(%d,%s)\n", ciptr->fd, address, 0);
+
+ if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
+ {
+ PRMSG (1,"Connect: Unable to Parse address %s\n",
+ address, 0, 0);
+ return -1;
+ }
+
+ if (!port || !*port)
+ {
+ PRMSG (1,"Connect: Missing port specification in %s\n",
+ address, 0, 0);
+ if (protocol) xfree (protocol);
+ if (host) xfree (host);
+ return -1;
+ }
+
+ ret = ciptr->transptr->Connect (ciptr, host, port);
+
+ if (protocol) xfree (protocol);
+ if (host) xfree (host);
+ if (port) xfree (port);
+
+ return ret;
+}
+
+#endif /* TRANS_CLIENT */
+
+
+int
+TRANS(BytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
+
+{
+ return ciptr->transptr->BytesReadable (ciptr, pend);
+}
+
+int
+TRANS(Read) (XtransConnInfo ciptr, char *buf, int size)
+
+{
+ return ciptr->transptr->Read (ciptr, buf, size);
+}
+
+int
+TRANS(Write) (XtransConnInfo ciptr, char *buf, int size)
+
+{
+ return ciptr->transptr->Write (ciptr, buf, size);
+}
+
+int
+TRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size)
+
+{
+ return ciptr->transptr->Readv (ciptr, buf, size);
+}
+
+int
+TRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size)
+
+{
+ return ciptr->transptr->Writev (ciptr, buf, size);
+}
+
+int
+TRANS(Disconnect) (XtransConnInfo ciptr)
+
+{
+ return ciptr->transptr->Disconnect (ciptr);
+}
+
+int
+TRANS(Close) (XtransConnInfo ciptr)
+
+{
+ int ret;
+
+ PRMSG (2,"Close(%d)\n", ciptr->fd, 0, 0);
+
+ ret = ciptr->transptr->Close (ciptr);
+
+ TRANS(FreeConnInfo) (ciptr);
+
+ return ret;
+}
+
+int
+TRANS(CloseForCloning) (XtransConnInfo ciptr)
+
+{
+ int ret;
+
+ PRMSG (2,"CloseForCloning(%d)\n", ciptr->fd, 0, 0);
+
+ ret = ciptr->transptr->CloseForCloning (ciptr);
+
+ TRANS(FreeConnInfo) (ciptr);
+
+ return ret;
+}
+
+int
+TRANS(IsLocal) (XtransConnInfo ciptr)
+
+{
+ return (ciptr->family == AF_UNIX);
+}
+
+
+int
+TRANS(GetMyAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp,
+ Xtransaddr **addrp)
+
+{
+ PRMSG (2,"GetMyAddr(%d)\n", ciptr->fd, 0, 0);
+
+ *familyp = ciptr->family;
+ *addrlenp = ciptr->addrlen;
+
+ if ((*addrp = (Xtransaddr *) xalloc (ciptr->addrlen)) == NULL)
+ {
+ PRMSG (1,"GetMyAddr: malloc failed\n", 0, 0, 0);
+ return -1;
+ }
+ memcpy(*addrp, ciptr->addr, ciptr->addrlen);
+
+ return 0;
+}
+
+int
+TRANS(GetPeerAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp,
+ Xtransaddr **addrp)
+
+{
+ PRMSG (2,"GetPeerAddr(%d)\n", ciptr->fd, 0, 0);
+
+ *familyp = ciptr->family;
+ *addrlenp = ciptr->peeraddrlen;
+
+ if ((*addrp = (Xtransaddr *) xalloc (ciptr->peeraddrlen)) == NULL)
+ {
+ PRMSG (1,"GetPeerAddr: malloc failed\n", 0, 0, 0);
+ return -1;
+ }
+ memcpy(*addrp, ciptr->peeraddr, ciptr->peeraddrlen);
+
+ return 0;
+}
+
+
+int
+TRANS(GetConnectionNumber) (XtransConnInfo ciptr)
+
+{
+ return ciptr->fd;
+}
+
+
+/*
+ * These functions are really utility functions, but they require knowledge
+ * of the internal data structures, so they have to be part of the Transport
+ * Independant API.
+ */
+
+#ifdef TRANS_SERVER
+
+static int
+complete_network_count (void)
+
+{
+ int count = 0;
+ int found_local = 0;
+ int i;
+
+ /*
+ * For a complete network, we only need one LOCALCONN transport to work
+ */
+
+ for (i = 0; i < (int) NUMTRANS; i++)
+ {
+ if (Xtransports[i].transport->flags & TRANS_ALIAS
+ || Xtransports[i].transport->flags & TRANS_NOLISTEN)
+ continue;
+
+ if (Xtransports[i].transport->flags & TRANS_LOCAL)
+ found_local = 1;
+ else
+ count++;
+ }
+
+ return (count + found_local);
+}
+
+
+
+int
+TRANS(MakeAllCOTSServerListeners) (char *port, int *partial, int *count_ret,
+ XtransConnInfo **ciptrs_ret)
+
+{
+ char buffer[256]; /* ??? What size ?? */
+ XtransConnInfo ciptr, temp_ciptrs[NUMTRANS];
+ int status, i, j;
+
+ PRMSG (2,"MakeAllCOTSServerListeners(%s,%x)\n",
+ port ? port : "NULL", ciptrs_ret, 0);
+
+ *count_ret = 0;
+
+ for (i = 0; i < (int) NUMTRANS; i++)
+ {
+ Xtransport *trans = Xtransports[i].transport;
+
+ if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN)
+ continue;
+
+ snprintf(buffer, sizeof(buffer), "%s/:%s", trans->TransName, port ? port : "");
+
+ PRMSG (5,"MakeAllCOTSServerListeners: opening %s\n",
+ buffer, 0, 0);
+
+ if ((ciptr = TRANS(OpenCOTSServer(buffer))) == NULL)
+ {
+ if (trans->flags & TRANS_DISABLED)
+ continue;
+
+ PRMSG (1,
+ "MakeAllCOTSServerListeners: failed to open listener for %s\n",
+ trans->TransName, 0, 0);
+ continue;
+ }
+
+ if ((status = TRANS(CreateListener (ciptr, port))) < 0)
+ {
+ if (status == TRANS_ADDR_IN_USE)
+ {
+ /*
+ * We failed to bind to the specified address because the
+ * address is in use. It must be that a server is already
+ * running at this address, and this function should fail.
+ */
+
+ PRMSG (1,
+ "MakeAllCOTSServerListeners: server already running\n",
+ 0, 0, 0);
+
+ for (j = 0; j < *count_ret; j++)
+ TRANS(Close) (temp_ciptrs[j]);
+
+ *count_ret = 0;
+ *ciptrs_ret = NULL;
+ *partial = 0;
+ return -1;
+ }
+ else
+ {
+ PRMSG (1,
+ "MakeAllCOTSServerListeners: failed to create listener for %s\n",
+ trans->TransName, 0, 0);
+
+ continue;
+ }
+ }
+
+ PRMSG (5,
+ "MakeAllCOTSServerListeners: opened listener for %s, %d\n",
+ trans->TransName, ciptr->fd, 0);
+
+ temp_ciptrs[*count_ret] = ciptr;
+ (*count_ret)++;
+ }
+
+ *partial = (*count_ret < complete_network_count());
+
+ PRMSG (5,
+ "MakeAllCLTSServerListeners: partial=%d, actual=%d, complete=%d \n",
+ *partial, *count_ret, complete_network_count());
+
+ if (*count_ret > 0)
+ {
+ if ((*ciptrs_ret = (XtransConnInfo *) xalloc (
+ *count_ret * sizeof (XtransConnInfo))) == NULL)
+ {
+ return -1;
+ }
+
+ for (i = 0; i < *count_ret; i++)
+ {
+ (*ciptrs_ret)[i] = temp_ciptrs[i];
+ }
+ }
+ else
+ *ciptrs_ret = NULL;
+
+ return 0;
+}
+
+int
+TRANS(MakeAllCLTSServerListeners) (char *port, int *partial, int *count_ret,
+ XtransConnInfo **ciptrs_ret)
+
+{
+ char buffer[256]; /* ??? What size ?? */
+ XtransConnInfo ciptr, temp_ciptrs[NUMTRANS];
+ int status, i, j;
+
+ PRMSG (2,"MakeAllCLTSServerListeners(%s,%x)\n",
+ port ? port : "NULL", ciptrs_ret, 0);
+
+ *count_ret = 0;
+
+ for (i = 0; i < (int) NUMTRANS; i++)
+ {
+ Xtransport *trans = Xtransports[i].transport;
+
+ if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN)
+ continue;
+
+ snprintf(buffer, sizeof(buffer), "%s/:%s", trans->TransName, port ? port : "");
+
+ PRMSG (5,"MakeAllCLTSServerListeners: opening %s\n",
+ buffer, 0, 0);
+
+ if ((ciptr = TRANS(OpenCLTSServer (buffer))) == NULL)
+ {
+ PRMSG (1,
+ "MakeAllCLTSServerListeners: failed to open listener for %s\n",
+ trans->TransName, 0, 0);
+ continue;
+ }
+
+ if ((status = TRANS(CreateListener (ciptr, port))) < 0)
+ {
+ if (status == TRANS_ADDR_IN_USE)
+ {
+ /*
+ * We failed to bind to the specified address because the
+ * address is in use. It must be that a server is already
+ * running at this address, and this function should fail.
+ */
+
+ PRMSG (1,
+ "MakeAllCLTSServerListeners: server already running\n",
+ 0, 0, 0);
+
+ for (j = 0; j < *count_ret; j++)
+ TRANS(Close) (temp_ciptrs[j]);
+
+ *count_ret = 0;
+ *ciptrs_ret = NULL;
+ *partial = 0;
+ return -1;
+ }
+ else
+ {
+ PRMSG (1,
+ "MakeAllCLTSServerListeners: failed to create listener for %s\n",
+ trans->TransName, 0, 0);
+
+ continue;
+ }
+ }
+
+ PRMSG (5,
+ "MakeAllCLTSServerListeners: opened listener for %s, %d\n",
+ trans->TransName, ciptr->fd, 0);
+ temp_ciptrs[*count_ret] = ciptr;
+ (*count_ret)++;
+ }
+
+ *partial = (*count_ret < complete_network_count());
+
+ PRMSG (5,
+ "MakeAllCLTSServerListeners: partial=%d, actual=%d, complete=%d \n",
+ *partial, *count_ret, complete_network_count());
+
+ if (*count_ret > 0)
+ {
+ if ((*ciptrs_ret = (XtransConnInfo *) xalloc (
+ *count_ret * sizeof (XtransConnInfo))) == NULL)
+ {
+ return -1;
+ }
+
+ for (i = 0; i < *count_ret; i++)
+ {
+ (*ciptrs_ret)[i] = temp_ciptrs[i];
+ }
+ }
+ else
+ *ciptrs_ret = NULL;
+
+ return 0;
+}
+
+#endif /* TRANS_SERVER */
+
+
+
+/*
+ * These routines are not part of the X Transport Interface, but they
+ * may be used by it.
+ */
+
+#ifdef CRAY
+
+/*
+ * Cray UniCOS does not have readv and writev so we emulate
+ */
+
+static int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
+
+{
+ struct msghdr hdr;
+
+ hdr.msg_iov = iov;
+ hdr.msg_iovlen = iovcnt;
+ hdr.msg_accrights = 0;
+ hdr.msg_accrightslen = 0;
+ hdr.msg_name = 0;
+ hdr.msg_namelen = 0;
+
+ return (recvmsg (ciptr->fd, &hdr, 0));
+}
+
+static int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
+
+{
+ struct msghdr hdr;
+
+ hdr.msg_iov = iov;
+ hdr.msg_iovlen = iovcnt;
+ hdr.msg_accrights = 0;
+ hdr.msg_accrightslen = 0;
+ hdr.msg_name = 0;
+ hdr.msg_namelen = 0;
+
+ return (sendmsg (ciptr->fd, &hdr, 0));
+}
+
+#endif /* CRAY */
+
+#if (defined(SYSV) && defined(i386) && !defined(SCO325)) || defined(_WIN32) || defined(__sxg__) || defined(__EMX__)
+
+/*
+ * emulate readv
+ */
+
+static int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
+
+{
+ int i, len, total;
+ char *base;
+
+ ESET(0);
+ for (i = 0, total = 0; i < iovcnt; i++, iov++) {
+ len = iov->iov_len;
+ base = iov->iov_base;
+ while (len > 0) {
+ register int nbytes;
+ nbytes = TRANS(Read) (ciptr, base, len);
+ if (nbytes < 0 && total == 0) return -1;
+ if (nbytes <= 0) return total;
+ ESET(0);
+ len -= nbytes;
+ total += nbytes;
+ base += nbytes;
+ }
+ }
+ return total;
+}
+
+#endif /* SYSV && i386 || _WIN32 || __sxg__ */
+
+#if (defined(SYSV) && defined(i386) && !defined(SCO325)) || defined(_WIN32) || defined(__sxg__) || defined(__EMX__)
+
+/*
+ * emulate writev
+ */
+
+static int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
+
+{
+ int i, len, total;
+ char *base;
+
+ ESET(0);
+ for (i = 0, total = 0; i < iovcnt; i++, iov++) {
+ len = iov->iov_len;
+ base = iov->iov_base;
+ while (len > 0) {
+ register int nbytes;
+ nbytes = TRANS(Write) (ciptr, base, len);
+ if (nbytes < 0 && total == 0) return -1;
+ if (nbytes <= 0) return total;
+ ESET(0);
+ len -= nbytes;
+ total += nbytes;
+ base += nbytes;
+ }
+ }
+ return total;
+}
+
+#endif /* SYSV && i386 || _WIN32 || __sxg__ */
+
+
+#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(USG) || defined(SVR4) || defined(SCO)
+#ifndef NEED_UTSNAME
+#define NEED_UTSNAME
+#endif
+#include <sys/utsname.h>
+#endif
+
+/*
+ * TRANS(GetHostname) - similar to gethostname but allows special processing.
+ */
+
+int TRANS(GetHostname) (char *buf, int maxlen)
+
+{
+ int len;
+
+#ifdef NEED_UTSNAME
+ struct utsname name;
+
+ uname (&name);
+ len = strlen (name.nodename);
+ if (len >= maxlen) len = maxlen - 1;
+ strncpy (buf, name.nodename, len);
+ buf[len] = '\0';
+#else
+ buf[0] = '\0';
+ (void) gethostname (buf, maxlen);
+ buf [maxlen - 1] = '\0';
+ len = strlen(buf);
+#endif /* NEED_UTSNAME */
+ return len;
+}
diff --git a/dcop/KDE-ICE/Xtrans.h b/dcop/KDE-ICE/Xtrans.h
new file mode 100644
index 000000000..95c817fa1
--- /dev/null
+++ b/dcop/KDE-ICE/Xtrans.h
@@ -0,0 +1,479 @@
+/* $TOG: Xtrans.h /main/31 1998/02/06 15:55:22 kaleb $ */
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+
+*/
+/* $XFree86: xc/lib/xtrans/Xtrans.h,v 3.14 1999/12/13 02:52:54 robin Exp $ */
+
+/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
+ *
+ * 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 NCR not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCR makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NCR 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 _XTRANS_H_
+#define _XTRANS_H_
+
+#include "config.h"
+#if defined Q_WS_X11 && ! defined K_WS_QTONLY
+#include <X11/Xfuncproto.h>
+#include <X11/Xos.h>
+#else
+#include <KDE-ICE/Xfuncproto.h>
+#include <fcntl.h>
+#endif
+
+/*
+ * Set the functions names according to where this code is being compiled.
+ */
+
+#ifdef X11_t
+#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP)
+#define TRANS(func) _X11Trans##func
+#else
+#define TRANS(func) _X11Trans/**/func
+#endif
+#ifdef XTRANSDEBUG
+static char* __xtransname = "_X11Trans";
+#endif
+#endif /* X11_t */
+
+#ifdef XSERV_t
+#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP)
+#define TRANS(func) _XSERVTrans##func
+#else
+#define TRANS(func) _XSERVTrans/**/func
+#endif
+#ifdef XTRANSDEBUG
+static char* __xtransname = "_XSERVTrans";
+#endif
+#define X11_t
+#endif /* X11_t */
+
+#ifdef XIM_t
+#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP)
+#define TRANS(func) _XimXTrans##func
+#else
+#define TRANS(func) _XimXTrans/**/func
+#endif
+#ifdef XTRANSDEBUG
+static char* __xtransname = "_XimTrans";
+#endif
+#endif /* XIM_t */
+
+#ifdef FS_t
+#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP)
+#define TRANS(func) _FSTrans##func
+#else
+#define TRANS(func) _FSTrans/**/func
+#endif
+#ifdef XTRANSDEBUG
+static char* __xtransname = "_FSTrans";
+#endif
+#endif /* FS_t */
+
+#ifdef FONT_t
+#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP)
+#define TRANS(func) _FontTrans##func
+#else
+#define TRANS(func) _FontTrans/**/func
+#endif
+#ifdef XTRANSDEBUG
+static char* __xtransname = "_FontTrans";
+#endif
+#endif /* FONT_t */
+
+#ifdef ICE_t
+#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP)
+#define TRANS(func) _kde_IceTrans##func
+#else
+#define TRANS(func) _kde_IceTrans/**/func
+#endif
+#ifdef XTRANSDEBUG
+static char* __xtransname = (char *)"_kde_IceTrans";
+#endif
+#endif /* ICE_t */
+
+#ifdef TEST_t
+#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP)
+#define TRANS(func) _TESTTrans##func
+#else
+#define TRANS(func) _TESTTrans/**/func
+#endif
+#ifdef XTRANSDEBUG
+static char* __xtransname = "_TESTTrans";
+#endif
+#endif /* TEST_t */
+
+#ifdef LBXPROXY_t
+#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP)
+#define TRANS(func) _LBXPROXYTrans##func
+#else
+#define TRANS(func) _LBXPROXYTrans/**/func
+#endif
+#define X11_t /* The server defines this - so should the LBX proxy */
+#ifdef XTRANSDEBUG
+static char* __xtransname = "_LBXPROXYTrans";
+#endif
+#endif /* LBXPROXY_t */
+
+#if !defined(TRANS)
+#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP)
+#define TRANS(func) _XTrans##func
+#else
+#define TRANS(func) _XTrans/**/func
+#endif
+#ifdef XTRANSDEBUG
+static char* __xtransname = "_XTrans";
+#endif
+#endif /* !TRANS */
+
+
+/*
+ * Create a single address structure that can be used wherever
+ * an address structure is needed. struct sockaddr is not big enough
+ * to hold a sockadd_un, so we create this definition to have a single
+ * structure that is big enough for all the structures we might need.
+ *
+ * This structure needs to be independent of the socket/TLI interface used.
+ */
+
+#define XTRANS_MAX_ADDR_LEN 128 /* large enough to hold sun_path */
+
+typedef struct {
+ unsigned char addr[XTRANS_MAX_ADDR_LEN];
+} Xtransaddr;
+
+
+#ifdef LONG64
+typedef int BytesReadable_t;
+#else
+typedef long BytesReadable_t;
+#endif
+
+
+#if defined(_WIN32) || (defined(USG) && !defined(CRAY) && !defined(umips) && !defined(MOTOROLA) && !defined(uniosu) && !defined(__sxg__)) || defined(MINIX)
+
+/*
+ * TRANS(Readv) and TRANS(Writev) use struct iovec, normally found
+ * in Berkeley systems in <sys/uio.h>. See the readv(2) and writev(2)
+ * manual pages for details.
+ */
+
+struct iovec {
+ caddr_t iov_base;
+ int iov_len;
+};
+
+#else
+#ifndef Lynx
+#include <sys/uio.h>
+#else
+#include <uio.h>
+#endif
+#endif
+
+typedef struct _XtransConnInfo *XtransConnInfo;
+
+
+/*
+ * Transport Option definitions
+ */
+
+#define TRANS_NONBLOCKING 1
+#define TRANS_CLOSEONEXEC 2
+
+
+/*
+ * Return values of Connect (0 is success)
+ */
+
+#define TRANS_CONNECT_FAILED -1
+#define TRANS_TRY_CONNECT_AGAIN -2
+#define TRANS_IN_PROGRESS -3
+
+
+/*
+ * Return values of CreateListener (0 is success)
+ */
+
+#define TRANS_CREATE_LISTENER_FAILED -1
+#define TRANS_ADDR_IN_USE -2
+
+
+/*
+ * Return values of Accept (0 is success)
+ */
+
+#define TRANS_ACCEPT_BAD_MALLOC -1
+#define TRANS_ACCEPT_FAILED -2
+#define TRANS_ACCEPT_MISC_ERROR -3
+
+
+/*
+ * ResetListener return values
+ */
+
+#define TRANS_RESET_NOOP 1
+#define TRANS_RESET_NEW_FD 2
+#define TRANS_RESET_FAILURE 3
+
+
+/*
+ * Function prototypes for the exposed interface
+ */
+
+void TRANS(FreeConnInfo) (
+ XtransConnInfo /* ciptr */
+);
+
+#ifdef TRANS_CLIENT
+
+XtransConnInfo TRANS(OpenCOTSClient)(
+ char * /* address */
+);
+
+#endif /* TRANS_CLIENT */
+
+#ifdef TRANS_SERVER
+
+XtransConnInfo TRANS(OpenCOTSServer)(
+ char * /* address */
+);
+
+#endif /* TRANS_SERVER */
+
+#ifdef TRANS_CLIENT
+
+XtransConnInfo TRANS(OpenCLTSClient)(
+ char * /* address */
+);
+
+#endif /* TRANS_CLIENT */
+
+#ifdef TRANS_SERVER
+
+XtransConnInfo TRANS(OpenCLTSServer)(
+ char * /* address */
+);
+
+#endif /* TRANS_SERVER */
+
+#ifdef TRANS_REOPEN
+
+XtransConnInfo TRANS(ReopenCOTSServer)(
+ int, /* trans_id */
+ int, /* fd */
+ char * /* port */
+);
+
+XtransConnInfo TRANS(ReopenCLTSServer)(
+ int, /* trans_id */
+ int, /* fd */
+ char * /* port */
+);
+
+int TRANS(GetReopenInfo)(
+ XtransConnInfo, /* ciptr */
+ int *, /* trans_id */
+ int *, /* fd */
+ char ** /* port */
+);
+
+#endif /* TRANS_REOPEN */
+
+
+int TRANS(SetOption)(
+ XtransConnInfo, /* ciptr */
+ int, /* option */
+ int /* arg */
+);
+
+#ifdef TRANS_SERVER
+
+int TRANS(CreateListener)(
+ XtransConnInfo, /* ciptr */
+ char * /* port */
+);
+
+int TRANS(NoListen) (
+ char* /* protocol*/
+);
+
+int TRANS(ResetListener)(
+ XtransConnInfo /* ciptr */
+);
+
+XtransConnInfo TRANS(Accept)(
+ XtransConnInfo, /* ciptr */
+ int * /* status */
+);
+
+#endif /* TRANS_SERVER */
+
+#ifdef TRANS_CLIENT
+
+int TRANS(Connect)(
+ XtransConnInfo, /* ciptr */
+ char * /* address */
+);
+
+#endif /* TRANS_CLIENT */
+
+int TRANS(BytesReadable)(
+ XtransConnInfo, /* ciptr */
+ BytesReadable_t * /* pend */
+);
+
+int TRANS(Read)(
+ XtransConnInfo, /* ciptr */
+ char *, /* buf */
+ int /* size */
+);
+
+int TRANS(Write)(
+ XtransConnInfo, /* ciptr */
+ char *, /* buf */
+ int /* size */
+);
+
+int TRANS(Readv)(
+ XtransConnInfo, /* ciptr */
+ struct iovec *, /* buf */
+ int /* size */
+);
+
+int TRANS(Writev)(
+ XtransConnInfo, /* ciptr */
+ struct iovec *, /* buf */
+ int /* size */
+);
+
+int TRANS(Disconnect)(
+ XtransConnInfo /* ciptr */
+);
+
+int TRANS(Close)(
+ XtransConnInfo /* ciptr */
+);
+
+int TRANS(CloseForCloning)(
+ XtransConnInfo /* ciptr */
+);
+
+int TRANS(IsLocal)(
+ XtransConnInfo /* ciptr */
+);
+
+int TRANS(GetMyAddr)(
+ XtransConnInfo, /* ciptr */
+ int *, /* familyp */
+ int *, /* addrlenp */
+ Xtransaddr ** /* addrp */
+);
+
+int TRANS(GetPeerAddr)(
+ XtransConnInfo, /* ciptr */
+ int *, /* familyp */
+ int *, /* addrlenp */
+ Xtransaddr ** /* addrp */
+);
+
+int TRANS(GetConnectionNumber)(
+ XtransConnInfo /* ciptr */
+);
+
+#ifdef TRANS_SERVER
+
+int TRANS(MakeAllCOTSServerListeners)(
+ char *, /* port */
+ int *, /* partial */
+ int *, /* count_ret */
+ XtransConnInfo ** /* ciptrs_ret */
+);
+
+int TRANS(MakeAllCLTSServerListeners)(
+ char *, /* port */
+ int *, /* partial */
+ int *, /* count_ret */
+ XtransConnInfo ** /* ciptrs_ret */
+);
+
+#endif /* TRANS_SERVER */
+
+
+/*
+ * Function Prototypes for Utility Functions.
+ */
+
+#ifdef X11_t
+
+int TRANS(ConvertAddress)(
+ int *, /* familyp */
+ int *, /* addrlenp */
+ Xtransaddr ** /* addrp */
+);
+
+#endif /* X11_t */
+
+#if defined(ICE_t)
+
+char *
+TRANS(GetMyNetworkId)(
+ XtransConnInfo /* ciptr */
+);
+
+char *
+TRANS(GetPeerNetworkId)(
+ XtransConnInfo /* ciptr */
+);
+
+#endif /* ICE_t */
+
+int
+TRANS(GetHostname) (
+ char * /* buf */,
+ int /* maxlen */
+);
+
+#if defined(_WIN32) && (defined(TCPCONN) || defined(DNETCONN))
+int TRANS(WSAStartup)();
+#endif
+
+#endif /* _XTRANS_H_ */
diff --git a/dcop/KDE-ICE/Xtransint.h b/dcop/KDE-ICE/Xtransint.h
new file mode 100644
index 000000000..3678e48bf
--- /dev/null
+++ b/dcop/KDE-ICE/Xtransint.h
@@ -0,0 +1,477 @@
+/* $TOG: Xtransint.h /main/27 1998/02/06 15:54:39 kaleb $ */
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+
+*/
+/* $XFree86: xc/lib/xtrans/Xtransint.h,v 3.27 1999/12/27 00:39:28 robin Exp $ */
+
+/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
+ *
+ * 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 NCR not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCR makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NCR 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 _XTRANSINT_H_
+#define _XTRANSINT_H_
+
+/*
+ * XTRANSDEBUG will enable the PRMSG() macros used in the X Transport
+ * Interface code. Each use of the PRMSG macro has a level associated with
+ * it. XTRANSDEBUG is defined to be a level. If the invocation level is =<
+ * the value of XTRANSDEBUG, then the message will be printed out to stderr.
+ * Recommended levels are:
+ *
+ * XTRANSDEBUG=1 Error messages
+ * XTRANSDEBUG=2 API Function Tracing
+ * XTRANSDEBUG=3 All Function Tracing
+ * XTRANSDEBUG=4 printing of intermediate values
+ * XTRANSDEBUG=5 really detailed stuff
+#define XTRANSDEBUG 2
+ *
+ * Defining XTRANSDEBUGTIMESTAMP will cause printing timestamps with each
+ * message.
+ */
+
+#ifndef __EMX__
+# define XTRANSDEBUG 1
+#else
+#define XTRANSDEBUG 1
+#endif
+
+#ifdef _WIN32
+#define _WILLWINSOCK_
+#endif
+
+#include "Xtrans.h"
+
+#ifdef XTRANSDEBUG
+#include <stdio.h>
+#endif /* XTRANSDEBUG */
+
+#include <errno.h>
+#ifdef X_NOT_STDC_ENV
+extern int errno; /* Internal system error number. */
+#endif
+
+#ifndef _WIN32
+#ifndef MINIX
+#ifndef Lynx
+#include <sys/socket.h>
+#else
+#include <socket.h>
+#endif
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#ifdef __EMX__
+#include <sys/ioctl.h>
+#endif
+
+/*
+ * Moved the setting of NEED_UTSNAME to this header file from Xtrans.c,
+ * to avoid a race condition. JKJ (6/5/97)
+ */
+
+#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(USG) || defined(SVR4) || defined(SCO)
+#ifndef NEED_UTSNAME
+#define NEED_UTSNAME
+#endif
+#include <sys/utsname.h>
+#endif
+
+/*
+ * makedepend screws up on #undef OPEN_MAX, so we define a new symbol
+ */
+
+#ifndef TRANS_OPEN_MAX
+
+#ifndef X_NOT_POSIX
+#ifdef _POSIX_SOURCE
+#include <limits.h>
+#else
+#define _POSIX_SOURCE
+#include <limits.h>
+#undef _POSIX_SOURCE
+#endif
+#endif
+#ifndef OPEN_MAX
+#ifdef __GNU__
+#define OPEN_MAX (sysconf(_SC_OPEN_MAX))
+#endif
+#ifdef SVR4
+#define OPEN_MAX 256
+#else
+#include <sys/param.h>
+#ifndef OPEN_MAX
+#if defined(__OSF1__) || defined(__osf__)
+#define OPEN_MAX 256
+#else
+#ifdef NOFILE
+#define OPEN_MAX NOFILE
+#else
+#if !defined(__EMX__) && !defined(__QNX__)
+#define OPEN_MAX NOFILES_MAX
+#else
+#define OPEN_MAX 256
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#ifdef __GNU__
+#define TRANS_OPEN_MAX OPEN_MAX
+#else /* !__GNU__ */
+#if OPEN_MAX > 256
+#define TRANS_OPEN_MAX 256
+#else
+#define TRANS_OPEN_MAX OPEN_MAX
+#endif
+#endif /*__GNU__*/
+
+#endif /* TRANS_OPEN_MAX */
+
+#ifdef __EMX__
+#define ESET(val)
+#else
+#define ESET(val) errno = val
+#endif
+#define EGET() errno
+
+#else /* _WIN32 */
+
+#include <limits.h> /* for USHRT_MAX */
+
+#define ESET(val) WSASetLastError(val)
+#define EGET() WSAGetLastError()
+
+#endif /* _WIN32 */
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifdef X11_t
+#define X_TCP_PORT 6000
+#endif
+
+struct _XtransConnInfo {
+ struct _Xtransport *transptr;
+ int index;
+ char *priv;
+ int flags;
+ int fd;
+ char *port;
+ int family;
+ char *addr;
+ int addrlen;
+ char *peeraddr;
+ int peeraddrlen;
+};
+
+#define XTRANS_OPEN_COTS_CLIENT 1
+#define XTRANS_OPEN_COTS_SERVER 2
+#define XTRANS_OPEN_CLTS_CLIENT 3
+#define XTRANS_OPEN_CLTS_SERVER 4
+
+
+typedef struct _Xtransport {
+ char *TransName;
+ int flags;
+
+#ifdef TRANS_CLIENT
+
+ XtransConnInfo (*OpenCOTSClient)(
+ struct _Xtransport *, /* transport */
+ char *, /* protocol */
+ char *, /* host */
+ char * /* port */
+ );
+
+#endif /* TRANS_CLIENT */
+
+#ifdef TRANS_SERVER
+
+ XtransConnInfo (*OpenCOTSServer)(
+ struct _Xtransport *, /* transport */
+ char *, /* protocol */
+ char *, /* host */
+ char * /* port */
+ );
+
+#endif /* TRANS_SERVER */
+
+#ifdef TRANS_CLIENT
+
+ XtransConnInfo (*OpenCLTSClient)(
+ struct _Xtransport *, /* transport */
+ char *, /* protocol */
+ char *, /* host */
+ char * /* port */
+ );
+
+#endif /* TRANS_CLIENT */
+
+#ifdef TRANS_SERVER
+
+ XtransConnInfo (*OpenCLTSServer)(
+ struct _Xtransport *, /* transport */
+ char *, /* protocol */
+ char *, /* host */
+ char * /* port */
+ );
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_REOPEN
+
+ XtransConnInfo (*ReopenCOTSServer)(
+ struct _Xtransport *, /* transport */
+ int, /* fd */
+ char * /* port */
+ );
+
+ XtransConnInfo (*ReopenCLTSServer)(
+ struct _Xtransport *, /* transport */
+ int, /* fd */
+ char * /* port */
+ );
+
+#endif /* TRANS_REOPEN */
+
+
+ int (*SetOption)(
+ XtransConnInfo, /* connection */
+ int, /* option */
+ int /* arg */
+ );
+
+#ifdef TRANS_SERVER
+
+ int (*CreateListener)(
+ XtransConnInfo, /* connection */
+ char * /* port */
+ );
+
+ int (*ResetListener)(
+ XtransConnInfo /* connection */
+ );
+
+ XtransConnInfo (*Accept)(
+ XtransConnInfo, /* connection */
+ int * /* status */
+ );
+
+#endif /* TRANS_SERVER */
+
+#ifdef TRANS_CLIENT
+
+ int (*Connect)(
+ XtransConnInfo, /* connection */
+ char *, /* host */
+ char * /* port */
+ );
+
+#endif /* TRANS_CLIENT */
+
+ int (*BytesReadable)(
+ XtransConnInfo, /* connection */
+ BytesReadable_t * /* pend */
+ );
+
+ int (*Read)(
+ XtransConnInfo, /* connection */
+ char *, /* buf */
+ int /* size */
+ );
+
+ int (*Write)(
+ XtransConnInfo, /* connection */
+ char *, /* buf */
+ int /* size */
+ );
+
+ int (*Readv)(
+ XtransConnInfo, /* connection */
+ struct iovec *, /* buf */
+ int /* size */
+ );
+
+ int (*Writev)(
+ XtransConnInfo, /* connection */
+ struct iovec *, /* buf */
+ int /* size */
+ );
+
+ int (*Disconnect)(
+ XtransConnInfo /* connection */
+ );
+
+ int (*Close)(
+ XtransConnInfo /* connection */
+ );
+
+ int (*CloseForCloning)(
+ XtransConnInfo /* connection */
+ );
+
+} Xtransport;
+
+
+typedef struct _Xtransport_table {
+ Xtransport *transport;
+ int transport_id;
+} Xtransport_table;
+
+
+/*
+ * Flags for the flags member of Xtransport.
+ */
+
+#define TRANS_ALIAS (1<<0) /* record is an alias, don't create server */
+#define TRANS_LOCAL (1<<1) /* local transport */
+#define TRANS_DISABLED (1<<2) /* Don't open this one */
+#define TRANS_NOLISTEN (1<<3) /* Don't listen on this one */
+
+
+/*
+ * readv() and writev() don't exist or don't work correctly on some
+ * systems, so they may be emulated.
+ */
+
+#if defined(CRAY) || (defined(SYSV) && defined(i386) && !defined(SCO325)) || defined(_WIN32) || defined(__sxg__) || defined(__EMX__)
+
+#define READV(ciptr, iov, iovcnt) TRANS(ReadV)(ciptr, iov, iovcnt)
+
+static int TRANS(ReadV)(
+ XtransConnInfo, /* ciptr */
+ struct iovec *, /* iov */
+ int /* iovcnt */
+);
+
+#else
+
+#define READV(ciptr, iov, iovcnt) readv(ciptr->fd, iov, iovcnt)
+
+#endif /* CRAY || (SYSV && i386) || _WIN32 || __sxg__ || */
+
+
+#if defined(CRAY) || (defined(SYSV) && defined(i386) && !defined(SCO325)) || defined(_WIN32) || defined(__sxg__) || defined(__EMX__)
+
+#define WRITEV(ciptr, iov, iovcnt) TRANS(WriteV)(ciptr, iov, iovcnt)
+
+static int TRANS(WriteV)(
+ XtransConnInfo, /* ciptr */
+ struct iovec *, /* iov */
+ int /* iovcnt */
+);
+
+#else
+
+#define WRITEV(ciptr, iov, iovcnt) writev(ciptr->fd, iov, iovcnt)
+
+#endif /* CRAY || _WIN32 || __sxg__ */
+
+
+static int is_numeric (
+ char * /* str */
+);
+
+#ifdef TRANS_SERVER
+static int trans_mkdir (
+ char *, /* path */
+ int /* mode */
+);
+#endif
+
+/*
+ * Some XTRANSDEBUG stuff
+ */
+
+#if defined(XTRANSDEBUG)
+/* add hack to the format string to avoid warnings about extra arguments
+ * to fprintf.
+ */
+#ifdef XTRANSDEBUGTIMESTAMP
+#if defined(XSERV_t) && defined(TRANS_SERVER)
+/* Use ErrorF() for the X server */
+#define PRMSG(lvl,x,a,b,c) if (lvl <= XTRANSDEBUG){ \
+ int hack= 0, saveerrno=errno; \
+ struct timeval tp;\
+ gettimeofday(&tp,0); \
+ ErrorF(__xtransname); \
+ ErrorF(x+hack,a,b,c); \
+ ErrorF("timestamp (ms): %d\n",tp.tv_sec*1000+tp.tv_usec/1000); \
+ errno=saveerrno; \
+ } else ((void)0)
+#else
+#define PRMSG(lvl,x,a,b,c) if (lvl <= XTRANSDEBUG){ \
+ int hack= 0, saveerrno=errno; \
+ struct timeval tp;\
+ gettimeofday(&tp,0); \
+ fprintf(stderr, __xtransname); fflush(stderr); \
+ fprintf(stderr, x+hack,a,b,c); fflush(stderr); \
+ fprintf(stderr, "timestamp (ms): %d\n",tp.tv_sec*1000+tp.tv_usec/1000); \
+ fflush(stderr); \
+ errno=saveerrno; \
+ } else ((void)0)
+#endif /* XSERV_t && TRANS_SERVER */
+#else /* XTRANSDEBUGTIMESTAMP */
+#if defined(XSERV_t) && defined(TRANS_SERVER)
+/* Use ErrorF() for the X server */
+#define PRMSG(lvl,x,a,b,c) if (lvl <= XTRANSDEBUG){ \
+ int hack= 0, saveerrno=errno; \
+ ErrorF(__xtransname); \
+ ErrorF(x+hack,a,b,c); \
+ errno=saveerrno; \
+ } else ((void)0)
+#else
+#define PRMSG(lvl,x,a,b,c) if (lvl <= XTRANSDEBUG){ \
+ int hack= 0, saveerrno=errno; \
+ fprintf(stderr, (const char*)(x+hack),a,b,c); fflush(stderr); \
+ errno=saveerrno; \
+ } else ((void)0)
+#endif /* XSERV_t && TRANS_SERVER */
+#endif /* XTRANSDEBUGTIMESTAMP */
+#else
+#define PRMSG(lvl,x,a,b,c) ((void)0)
+#endif /* XTRANSDEBUG */
+
+#endif /* _XTRANSINT_H_ */
diff --git a/dcop/KDE-ICE/Xtranssock.c b/dcop/KDE-ICE/Xtranssock.c
new file mode 100644
index 000000000..100d218b1
--- /dev/null
+++ b/dcop/KDE-ICE/Xtranssock.c
@@ -0,0 +1,1990 @@
+/* $TOG: Xtranssock.c /main/61 1998/02/06 15:54:53 kaleb $ */
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+
+*/
+/* $XFree86: xc/lib/xtrans/Xtranssock.c,v 3.45 1999/12/27 00:39:29 robin Exp $ */
+
+/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
+ *
+ * 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 NCR not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCR makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NCR 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.
+ */
+
+#include <ctype.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#ifndef _WIN32
+
+#if defined(TCPCONN) || defined(UNIXCONN)
+#include <netinet/in.h>
+#else
+#ifdef ESIX
+#include <lan/in.h>
+#endif
+#endif
+#if defined(TCPCONN) || defined(UNIXCONN)
+#include <netdb.h>
+#endif
+
+#ifdef UNIXCONN
+#ifndef X_NO_SYS_UN
+#ifndef Lynx
+#include <sys/un.h>
+#else
+#include <un.h>
+#endif
+#endif
+#include <sys/stat.h>
+#endif
+
+#if defined(hpux) || defined(__EMX__)
+#define NO_TCP_H
+#endif /* hpux */
+#ifdef MOTOROLA
+#ifdef SYSV
+#define NO_TCP_H
+#endif /* SYSV */
+#endif /* MOTOROLA */
+#ifndef NO_TCP_H
+#ifdef __osf__
+#include <sys/param.h>
+#endif /* osf */
+#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
+#include <machine/endian.h>
+#endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ */
+#include <netinet/tcp.h>
+#endif /* !NO_TCP_H */
+#include <sys/ioctl.h>
+#if (defined(SVR4) || defined(__SVR4)) && !defined(SCO325) && !defined(DGUX)
+#include <sys/filio.h>
+#endif
+#if (defined(i386) && defined(SYSV)) || defined(_SEQUENT_)
+#if !defined(_SEQUENT_) && !defined(ESIX) && !defined(sco)
+#include <net/errno.h>
+#endif /* _SEQUENT_ || ESIX || SCO */
+#if !defined(ISC) || !defined(I_NREAD) || defined(SCO325)
+#include <sys/stropts.h>
+#endif
+#endif /* i386 && SYSV || _SEQUENT_ */
+
+#else /* !_WIN32 */
+
+#ifdef _WIN32
+#if !defined(WIN32_LEAN_AND_MEAN)
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <winsock2.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+#else
+#include <X11/Xwinsock.h>
+#include <X11/Xw32defs.h>
+#endif
+#undef close
+#define close closesocket
+#define ECONNREFUSED WSAECONNREFUSED
+#define EADDRINUSE WSAEADDRINUSE
+#define EPROTOTYPE WSAEPROTOTYPE
+#define EINPROGRESS WSAEINPROGRESS
+#undef EWOULDBLOCK
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#undef EINTR
+#define EINTR WSAEINTR
+#include <netdb.h>
+#endif /* _WIN32 */
+
+#if defined(SO_DONTLINGER) && defined(SO_LINGER)
+#undef SO_DONTLINGER
+#endif
+
+#if defined(__EMX__)
+#if defined(NOT_EMX09A)
+static int IBMsockInit = 0;
+#define SocketInitOnce()\
+ if (!IBMsockInit) {\
+ sock_init();\
+ IBMsockInit = 1;\
+ }
+#undef EINTR
+#define EINTR SOCEINTR
+#undef EINVAL
+#define EINVAL SOCEINVAL
+#undef errno
+#define errno sock_errno()
+#undef close
+#define close soclose
+#undef ioctl
+#define ioctl sockioctl
+#else
+#define SocketInitOnce() /**/
+#endif
+/* this is still not there */
+#define SOCKET int
+#else
+/* others don't need this */
+#define SocketInitOnce() /**/
+#endif
+
+#define MIN_BACKLOG 128
+#ifdef SOMAXCONN
+#if SOMAXCONN > MIN_BACKLOG
+#define BACKLOG SOMAXCONN
+#endif
+#endif
+#ifndef BACKLOG
+#define BACKLOG MIN_BACKLOG
+#endif
+/*
+ * This is the Socket implementation of the X Transport service layer
+ *
+ * This file contains the implementation for both the UNIX and INET domains,
+ * and can be built for either one, or both.
+ *
+ */
+
+typedef struct _Sockettrans2dev {
+ char *transname;
+ int family;
+ int devcotsname;
+ int devcltsname;
+ int protocol;
+} Sockettrans2dev;
+
+static Sockettrans2dev Sockettrans2devtab[] = {
+#ifdef TCPCONN
+ {(char *)"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
+ {(char *)"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
+#endif /* TCPCONN */
+#ifdef UNIXCONN
+ {(char *)"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
+#if !defined(LOCALCONN)
+ {(char *)"local",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
+#endif /* !LOCALCONN */
+#endif /* UNIXCONN */
+};
+
+#define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev))
+
+
+#ifdef UNIXCONN
+
+#ifdef hpux
+
+#if defined(X11_t)
+#define UNIX_PATH "/usr/spool/sockets/X11/"
+#define UNIX_DIR "/usr/spool/sockets/X11"
+#define OLD_UNIX_PATH "/tmp/.X11-unix/X"
+#endif /* X11_t */
+#if defined(XIM_t)
+#define UNIX_PATH "/usr/spool/sockets/XIM/"
+#define UNIX_DIR "/usr/spool/sockets/XIM"
+#define OLD_UNIX_PATH "/tmp/.XIM-unix/XIM"
+#endif /* XIM_t */
+#if defined(FS_t) || defined(FONT_t)
+#define UNIX_PATH "/usr/spool/sockets/fontserv/"
+#define UNIX_DIR "/usr/spool/sockets/fontserv"
+#endif /* FS_t || FONT_t */
+#if defined(ICE_t)
+#define UNIX_PATH "/usr/spool/sockets/ICE/"
+#define UNIX_DIR "/usr/spool/sockets/ICE"
+#endif /* ICE_t */
+#if defined(TEST_t)
+#define UNIX_PATH "/usr/spool/sockets/xtrans_test/"
+#define UNIX_DIR "/usr/spool/sockets/xtrans_test"
+#endif
+#if defined(LBXPROXY_t)
+#define UNIX_PATH "/usr/spool/sockets/X11/"
+#define UNIX_DIR "/usr/spool/sockets/X11"
+#endif
+
+#else /* !hpux */
+
+#if defined(X11_t)
+#define UNIX_PATH "/tmp/.X11-unix/X"
+#define UNIX_DIR "/tmp/.X11-unix"
+#endif /* X11_t */
+#if defined(XIM_t)
+#define UNIX_PATH "/tmp/.XIM-unix/XIM"
+#define UNIX_DIR "/tmp/.XIM-unix"
+#endif /* XIM_t */
+#if defined(FS_t) || defined(FONT_t)
+#define UNIX_PATH "/tmp/.font-unix/fs"
+#define UNIX_DIR "/tmp/.font-unix"
+#endif /* FS_t || FONT_t */
+#if defined(ICE_t)
+#define UNIX_PATH "/tmp/.ICE-unix/"
+#define UNIX_DIR "/tmp/.ICE-unix"
+#endif /* ICE_t */
+#if defined(TEST_t)
+#define UNIX_PATH "/tmp/.Test-unix/test"
+#define UNIX_DIR "/tmp/.Test-unix"
+#endif
+#if defined(LBXPROXY_t)
+#define UNIX_PATH "/tmp/.X11-unix/X"
+#define UNIX_DIR "/tmp/.X11-unix"
+#endif
+
+#endif /* hpux */
+
+#endif /* UNIXCONN */
+
+#define PORTBUFSIZE 32
+
+/*
+ * These are some utility function used by the real interface function below.
+ */
+
+static int
+TRANS(SocketSelectFamily) (char *family)
+
+{
+ int i;
+
+ PRMSG (3,(const char*)"SocketSelectFamily(%s)\n", family, 0, 0);
+
+ for (i = 0; i < (int) NUMSOCKETFAMILIES;i++)
+ {
+ if (!strcmp (family, Sockettrans2devtab[i].transname))
+ return i;
+ }
+
+ return -1;
+}
+
+
+/*
+ * This function gets the local address of the socket and stores it in the
+ * XtransConnInfo structure for the connection.
+ */
+#ifdef TCPCONN
+static int
+TRANS(SocketINETGetAddr) (XtransConnInfo ciptr)
+
+{
+ struct sockaddr_in sockname;
+#if defined(SVR4) || defined(SCO325)
+ size_t namelen = sizeof sockname;
+#else
+ int namelen = sizeof sockname;
+#endif
+
+ PRMSG (3,"SocketINETGetAddr(%x)\n", ciptr, 0, 0);
+
+ if (getsockname (ciptr->fd,(struct sockaddr *) &sockname, &namelen) < 0)
+ {
+ PRMSG (1,"SocketINETGetAddr: getsockname() failed: %d\n",
+ EGET(),0, 0);
+ return -1;
+ }
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketINETGetAddr: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ return -1;
+ }
+
+ ciptr->family = sockname.sin_family;
+ ciptr->addrlen = namelen;
+ memcpy (ciptr->addr, &sockname, ciptr->addrlen);
+
+ return 0;
+}
+
+
+/*
+ * This function gets the remote address of the socket and stores it in the
+ * XtransConnInfo structure for the connection.
+ */
+
+static int
+TRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr)
+
+{
+ struct sockaddr_in sockname;
+#if defined(SVR4) || defined(SCO325)
+ size_t namelen = sizeof sockname;
+#else
+ int namelen = sizeof sockname;
+#endif
+
+ PRMSG (3,"SocketINETGetPeerAddr(%x)\n", ciptr, 0, 0);
+
+ if (getpeername (ciptr->fd, (struct sockaddr *) &sockname, &namelen) < 0)
+ {
+ PRMSG (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n",
+ EGET(), 0, 0);
+ return -1;
+ }
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketINETGetPeerAddr: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ return -1;
+ }
+
+ ciptr->peeraddrlen = namelen;
+ memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
+
+ return 0;
+}
+#endif /* TCPCONN */
+
+static XtransConnInfo
+TRANS(SocketOpen) (int i, int type)
+
+{
+ XtransConnInfo ciptr;
+
+ PRMSG (3,"SocketOpen(%d,%d)\n", i, type, 0);
+
+ if ((ciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "SocketOpen: malloc failed\n", 0, 0, 0);
+ return NULL;
+ }
+
+ if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type,
+ Sockettrans2devtab[i].protocol)) < 0
+ ) {
+ PRMSG (1, "SocketOpen: socket() failed for %s\n",
+ Sockettrans2devtab[i].transname, 0, 0);
+
+ xfree ((char *) ciptr);
+ return NULL;
+ }
+
+#ifdef TCP_NODELAY
+ if (Sockettrans2devtab[i].family == AF_INET)
+ {
+ /*
+ * turn off TCP coalescence for INET sockets
+ */
+
+ int tmp = 1;
+ setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY,
+ (char *) &tmp, sizeof (int));
+ }
+#endif
+
+ return ciptr;
+}
+
+
+#ifdef TRANS_REOPEN
+
+static XtransConnInfo
+TRANS(SocketReopen) (int i, int type, int fd, char *port)
+
+{
+ XtransConnInfo ciptr;
+
+ PRMSG (3,"SocketReopen(%d,%d,%s)\n", type, fd, port);
+
+ if ((ciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "SocketReopen: malloc failed\n", 0, 0, 0);
+ return NULL;
+ }
+
+ ciptr->fd = fd;
+
+ return ciptr;
+}
+
+#endif /* TRANS_REOPEN */
+
+
+/*
+ * These functions are the interface supplied in the Xtransport structure
+ */
+
+#ifdef TRANS_CLIENT
+
+static XtransConnInfo
+TRANS(SocketOpenCOTSClient) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i;
+
+ PRMSG (2, "SocketOpenCOTSClient(%s,%s,%s)\n",
+ protocol, host, port);
+
+ SocketInitOnce();
+
+ if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
+ {
+ PRMSG (1,
+ "SocketOpenCOTSClient: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ if ((ciptr = TRANS(SocketOpen) (
+ i, Sockettrans2devtab[i].devcotsname)) == NULL)
+ {
+ PRMSG (1,"SocketOpenCOTSClient: Unable to open socket for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+static XtransConnInfo
+TRANS(SocketOpenCOTSServer) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i;
+
+ PRMSG (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port);
+
+ SocketInitOnce();
+
+ if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
+ {
+ PRMSG (1,
+ "SocketOpenCOTSServer: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ if ((ciptr = TRANS(SocketOpen) (
+ i, Sockettrans2devtab[i].devcotsname)) == NULL)
+ {
+ PRMSG (1,"SocketOpenCOTSServer: Unable to open socket for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ /*
+ * Using this prevents the bind() check for an existing server listening
+ * on the same port, but it is required for other reasons.
+ */
+#ifdef SO_REUSEADDR
+
+ /*
+ * SO_REUSEADDR only applied to AF_INET
+ */
+
+ if (Sockettrans2devtab[i].family == AF_INET)
+ {
+ int one = 1;
+ setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR,
+ (char *) &one, sizeof (int));
+ }
+#endif
+
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_CLIENT
+
+static XtransConnInfo
+TRANS(SocketOpenCLTSClient) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i;
+
+ PRMSG (2,"SocketOpenCLTSClient(%s,%s,%s)\n", protocol, host, port);
+
+ SocketInitOnce();
+
+ if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
+ {
+ PRMSG (1,
+ "SocketOpenCLTSClient: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ if ((ciptr = TRANS(SocketOpen) (
+ i, Sockettrans2devtab[i].devcotsname)) == NULL)
+ {
+ PRMSG (1,"SocketOpenCLTSClient: Unable to open socket for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+static XtransConnInfo
+TRANS(SocketOpenCLTSServer) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i;
+
+ PRMSG (2,"SocketOpenCLTSServer(%s,%s,%s)\n", protocol, host, port);
+
+ SocketInitOnce();
+
+ if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
+ {
+ PRMSG (1,
+ "SocketOpenCLTSServer: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ if ((ciptr = TRANS(SocketOpen) (
+ i, Sockettrans2devtab[i].devcotsname)) == NULL)
+ {
+ PRMSG (1,"SocketOpenCLTSServer: Unable to open socket for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_REOPEN
+
+static XtransConnInfo
+TRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i;
+
+ PRMSG (2,
+ "SocketReopenCOTSServer(%d, %s)\n", fd, port, 0);
+
+ SocketInitOnce();
+
+ if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
+ {
+ PRMSG (1,
+ "SocketReopenCOTSServer: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ if ((ciptr = TRANS(SocketReopen) (
+ i, Sockettrans2devtab[i].devcotsname, fd, port)) == NULL)
+ {
+ PRMSG (1,
+ "SocketReopenCOTSServer: Unable to reopen socket for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+static XtransConnInfo
+TRANS(SocketReopenCLTSServer) (Xtransport *thistrans, int fd, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i;
+
+ PRMSG (2,
+ "SocketReopenCLTSServer(%d, %s)\n", fd, port, 0);
+
+ SocketInitOnce();
+
+ if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
+ {
+ PRMSG (1,
+ "SocketReopenCLTSServer: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ if ((ciptr = TRANS(SocketReopen) (
+ i, Sockettrans2devtab[i].devcotsname, fd, port)) == NULL)
+ {
+ PRMSG (1,
+ "SocketReopenCLTSServer: Unable to reopen socket for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_REOPEN */
+
+
+static int
+TRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg)
+
+{
+ PRMSG (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg);
+
+ return -1;
+}
+
+#ifdef UNIXCONN
+static int
+set_sun_path(const char *port, const char *upath, char *path)
+{
+ struct sockaddr_un s;
+ unsigned int maxlen = sizeof(s.sun_path) - 1;
+
+ if (!port || !*port || !path)
+ return -1;
+
+ if (*port == '/') { /* a full pathname */
+ if (strlen(port) > maxlen)
+ return -1;
+ sprintf(path, "%s", port);
+ } else {
+ if (strlen(port) + strlen(upath) > maxlen)
+ return -1;
+ sprintf(path, "%s%s", upath, port);
+ }
+ return 0;
+}
+#endif
+
+#ifdef TRANS_SERVER
+
+static int
+TRANS(SocketCreateListener) (XtransConnInfo ciptr,
+ struct sockaddr *sockname, int socknamelen)
+
+{
+ int namelen = socknamelen;
+ int fd = ciptr->fd;
+ int retry;
+
+ PRMSG (3, "SocketCreateListener(%x,%d)\n", ciptr, fd, 0);
+
+ if (Sockettrans2devtab[ciptr->index].family == AF_INET)
+ retry = 20;
+ else
+ retry = 0;
+
+ while (bind (fd, (struct sockaddr *) sockname, namelen) < 0)
+ {
+ if (errno == EADDRINUSE)
+ return TRANS_ADDR_IN_USE;
+
+ if (retry-- == 0) {
+ PRMSG (1, "SocketCreateListener: failed to bind listener\n",
+ 0, 0, 0);
+ close (fd);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+#ifdef SO_REUSEADDR
+ sleep (1);
+#else
+ sleep (10);
+#endif /* SO_REUSEDADDR */
+ }
+
+ if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
+#ifdef SO_DONTLINGER
+ setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0);
+#else
+#ifdef SO_LINGER
+ {
+ static int linger[2] = { 0, 0 };
+ setsockopt (fd, SOL_SOCKET, SO_LINGER,
+ (char *) linger, sizeof (linger));
+ }
+#endif
+#endif
+}
+
+ if (listen (fd, BACKLOG) < 0)
+ {
+ PRMSG (1, "SocketCreateListener: listen() failed\n", 0, 0, 0);
+ close (fd);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+
+ /* Set a flag to indicate that this connection is a listener */
+
+ ciptr->flags = 1;
+
+ return 0;
+}
+
+#ifdef TCPCONN
+static int
+TRANS(SocketINETCreateListener) (XtransConnInfo ciptr, char *port)
+
+{
+ struct sockaddr_in sockname;
+ int namelen = sizeof(sockname);
+ int status;
+ long tmpport;
+ struct servent *servp;
+
+#ifdef X11_t
+ char portbuf[PORTBUFSIZE];
+#endif
+
+ PRMSG (2, "SocketINETCreateListener(%s)\n", port, 0, 0);
+
+#ifdef X11_t
+ /*
+ * X has a well known port, that is transport dependent. It is easier
+ * to handle it here, than try and come up with a transport independent
+ * representation that can be passed in and resolved the usual way.
+ *
+ * The port that is passed here is really a string containing the idisplay
+ * from ConnectDisplay().
+ */
+
+ if (is_numeric (port))
+ {
+ /* fixup the server port address */
+ tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
+ sprintf (portbuf,"%lu", tmpport);
+ port = portbuf;
+ }
+#endif
+
+ if (port && *port)
+ {
+ /* Check to see if the port string is just a number (handles X11) */
+
+ if (!is_numeric (port))
+ {
+ if ((servp = getservbyname (port,"tcp")) == NULL)
+ {
+ PRMSG (1,
+ "SocketINETCreateListener: Unable to get service for %s\n",
+ port, 0, 0);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+ /* we trust getservbyname to return a valid number */
+ sockname.sin_port = htons (servp->s_port);
+ }
+ else
+ {
+ tmpport = strtol (port, (char**)NULL, 10);
+ /*
+ * check that somehow the port address isn't negative or in
+ * the range of reserved port addresses. This can happen and
+ * be very bad if the server is suid-root and the user does
+ * something (dumb) like `X :60049`.
+ */
+ if (tmpport < 1024 || tmpport > USHRT_MAX)
+ return TRANS_CREATE_LISTENER_FAILED;
+
+ sockname.sin_port = htons (((unsigned short) tmpport));
+ }
+ }
+ else
+ sockname.sin_port = htons (0);
+
+#ifdef BSD44SOCKETS
+ sockname.sin_len = sizeof (sockname);
+#endif
+ sockname.sin_family = AF_INET;
+ sockname.sin_addr.s_addr = htonl (INADDR_ANY);
+
+ if ((status = TRANS(SocketCreateListener) (ciptr,
+ (struct sockaddr *) &sockname, namelen)) < 0)
+ {
+ PRMSG (1,
+ "SocketINETCreateListener: ...SocketCreateListener() failed\n",
+ 0, 0, 0);
+ return status;
+ }
+
+ if (TRANS(SocketINETGetAddr) (ciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETCreateListener: ...SocketINETGetAddr() failed\n",
+ 0, 0, 0);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+
+ return 0;
+}
+
+#endif /* SOCKCONN */
+
+
+#ifdef UNIXCONN
+
+static int
+TRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, char *port)
+
+{
+ struct sockaddr_un sockname;
+ int namelen;
+ int oldUmask;
+ int status;
+ unsigned int mode;
+
+ PRMSG (2, "SocketUNIXCreateListener(%s)\n",
+ port ? port : "NULL", 0, 0);
+
+ /* Make sure the directory is created */
+
+ oldUmask = umask (0);
+
+#ifdef UNIX_DIR
+#ifdef HAS_STICKY_DIR_BIT
+ mode = 01777;
+#else
+ mode = 0777;
+#endif
+ if (trans_mkdir((char*)UNIX_DIR, mode) == -1) {
+ PRMSG (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n",
+ UNIX_DIR, errno, 0);
+ (void) umask (oldUmask);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+#endif
+
+ sockname.sun_family = AF_UNIX;
+
+ if (port && *port) {
+ if (set_sun_path(port, UNIX_PATH, sockname.sun_path) != 0) {
+ PRMSG (1, "SocketUNIXCreateListener: path too long\n", 0, 0, 0);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+ } else {
+ sprintf (sockname.sun_path, "%s%d", UNIX_PATH, getpid());
+ }
+
+ namelen = sizeof( sockname ) - sizeof( sockname.sun_path ) + strlen( sockname.sun_path ) + 1;
+#if defined(BSD44SOCKETS)
+ sockname.sun_len = namelen;
+#endif
+
+ unlink (sockname.sun_path);
+ (void) umask (oldUmask);
+
+ if ((status = TRANS(SocketCreateListener) (ciptr,
+ (struct sockaddr *) &sockname, namelen)) < 0)
+ {
+ PRMSG (1,
+ "SocketUNIXCreateListener: ...SocketCreateListener() failed\n",
+ 0, 0, 0);
+ return status;
+ }
+
+ /*
+ * Now that the listener is esablished, create the addr info for
+ * this connection. getpeername() doesn't work for UNIX Domain Sockets
+ * on some systems (hpux at least), so we will just do it manually, instead
+ * of calling something like TRANS(SocketUNIXGetAddr).
+ */
+
+ namelen = sizeof (sockname); /* this will always make it the same size */
+
+ if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketUNIXCreateListener: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+
+ ciptr->family = sockname.sun_family;
+ ciptr->addrlen = namelen;
+ memcpy (ciptr->addr, &sockname, ciptr->addrlen);
+
+ return 0;
+}
+
+
+static int
+TRANS(SocketUNIXResetListener) (XtransConnInfo ciptr)
+
+{
+ /*
+ * See if the unix domain socket has disappeared. If it has, recreate it.
+ */
+
+ struct sockaddr_un *unsock = (struct sockaddr_un *) ciptr->addr;
+ struct stat statb;
+ int status = TRANS_RESET_NOOP;
+ unsigned int mode;
+
+ PRMSG (3, "SocketUNIXResetListener(%x,%d)\n", ciptr, ciptr->fd, 0);
+
+ if (stat (unsock->sun_path, &statb) == -1 ||
+ ((statb.st_mode & S_IFMT) !=
+#if (defined (sun) && defined(SVR4)) || defined(NCR) || defined(SCO) || defined(sco) || !defined(S_IFSOCK)
+ S_IFIFO))
+#else
+ S_IFSOCK))
+#endif
+ {
+ int oldUmask = umask (0);
+
+#ifdef UNIX_DIR
+#ifdef HAS_STICKY_DIR_BIT
+ mode = 01777;
+#else
+ mode = 0777;
+#endif
+ if (trans_mkdir((char*)UNIX_DIR, mode) == -1) {
+ PRMSG (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n",
+ UNIX_DIR, errno, 0);
+ (void) umask (oldUmask);
+ return TRANS_RESET_FAILURE;
+ }
+#endif
+
+ close (ciptr->fd);
+ unlink (unsock->sun_path);
+
+ if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
+ {
+ TRANS(FreeConnInfo) (ciptr);
+ (void) umask (oldUmask);
+ return TRANS_RESET_FAILURE;
+ }
+
+ if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0)
+ {
+ close (ciptr->fd);
+ TRANS(FreeConnInfo) (ciptr);
+ return TRANS_RESET_FAILURE;
+ }
+
+ if (listen (ciptr->fd, BACKLOG) < 0)
+ {
+ close (ciptr->fd);
+ TRANS(FreeConnInfo) (ciptr);
+ (void) umask (oldUmask);
+ return TRANS_RESET_FAILURE;
+ }
+
+ umask (oldUmask);
+
+ status = TRANS_RESET_NEW_FD;
+ }
+
+ return status;
+}
+
+#endif /* UNIXCONN */
+
+
+#ifdef TCPCONN
+
+static XtransConnInfo
+TRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status)
+
+{
+ XtransConnInfo newciptr;
+ struct sockaddr_in sockname;
+#if defined(SVR4) || defined(SCO325)
+ size_t namelen = sizeof sockname;
+#else
+ int namelen = sizeof(sockname);
+#endif
+
+ PRMSG (2, "SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
+
+ if ((newciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "SocketINETAccept: malloc failed\n", 0, 0, 0);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+ if ((newciptr->fd = accept (ciptr->fd,
+ (struct sockaddr *) &sockname, &namelen)) < 0)
+ {
+ PRMSG (1, "SocketINETAccept: accept() failed\n", 0, 0, 0);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_FAILED;
+ return NULL;
+ }
+
+#ifdef TCP_NODELAY
+ {
+ /*
+ * turn off TCP coalescence for INET sockets
+ */
+
+ int tmp = 1;
+ setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY,
+ (char *) &tmp, sizeof (int));
+ }
+#endif
+
+ /*
+ * Get this address again because the transport may give a more
+ * specific address now that a connection is established.
+ */
+
+ if (TRANS(SocketINETGetAddr) (newciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETAccept: ...SocketINETGetAddr() failed:\n",
+ 0, 0, 0);
+ close (newciptr->fd);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return NULL;
+ }
+
+ if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n",
+ 0, 0, 0);
+ close (newciptr->fd);
+ if (newciptr->addr) xfree (newciptr->addr);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return NULL;
+ }
+
+ *status = 0;
+
+ return newciptr;
+}
+
+#endif /* TCPCONN */
+
+
+#ifdef UNIXCONN
+static XtransConnInfo
+TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status)
+
+{
+ XtransConnInfo newciptr;
+ struct sockaddr_un sockname;
+#if defined(SVR4) || defined(SCO325)
+ size_t namelen = sizeof sockname;
+#else
+ int namelen = sizeof sockname;
+#endif
+
+ PRMSG (2, "SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
+
+ if ((newciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "SocketUNIXAccept: malloc() failed\n", 0, 0, 0);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+ if ((newciptr->fd = accept (ciptr->fd,
+ (struct sockaddr *) &sockname, &namelen)) < 0)
+ {
+ PRMSG (1, "SocketUNIXAccept: accept() failed\n", 0, 0, 0);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_FAILED;
+ return NULL;
+ }
+
+ /*
+ * Get the socket name and the peer name from the listener socket,
+ * since this is unix domain.
+ */
+
+ if ((newciptr->addr = (char *) xalloc (ciptr->addrlen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketUNIXAccept: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ close (newciptr->fd);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+
+ newciptr->addrlen = ciptr->addrlen;
+ memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen);
+
+ if ((newciptr->peeraddr = (char *) xalloc (ciptr->addrlen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketUNIXAccept: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ close (newciptr->fd);
+ if (newciptr->addr) xfree (newciptr->addr);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+ newciptr->peeraddrlen = ciptr->addrlen;
+ memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen);
+
+ newciptr->family = AF_UNIX;
+
+ *status = 0;
+
+ return newciptr;
+}
+
+#endif /* UNIXCONN */
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_CLIENT
+
+#ifdef TCPCONN
+static int
+TRANS(SocketINETConnect) (XtransConnInfo ciptr, char *host, char *port)
+
+{
+ struct sockaddr_in sockname;
+#if defined(SVR4) || defined(SCO325)
+ size_t namelen = sizeof sockname;
+#else
+ int namelen = sizeof sockname;
+#endif
+ struct hostent *hostp;
+ struct servent *servp;
+
+#ifdef X11_t
+ char portbuf[PORTBUFSIZE];
+#endif
+
+ long tmpport;
+ unsigned long tmpaddr;
+ char hostnamebuf[256]; /* tmp space */
+
+ PRMSG (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port);
+
+ if (!host)
+ {
+ hostnamebuf[0] = '\0';
+ (void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
+ host = hostnamebuf;
+ }
+
+#ifdef X11_t
+ /*
+ * X has a well known port, that is transport dependent. It is easier
+ * to handle it here, than try and come up with a transport independent
+ * representation that can be passed in and resolved the usual way.
+ *
+ * The port that is passed here is really a string containing the idisplay
+ * from ConnectDisplay().
+ */
+
+ if (is_numeric (port))
+ {
+ tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
+ sprintf (portbuf, "%lu", tmpport);
+ port = portbuf;
+ }
+#endif
+
+ /*
+ * Build the socket name.
+ */
+
+#ifdef BSD44SOCKETS
+ sockname.sin_len = sizeof (struct sockaddr_in);
+#endif
+ sockname.sin_family = AF_INET;
+
+ /*
+ * fill in sin_addr
+ */
+
+ /* check for ww.xx.yy.zz host string */
+
+ if (isascii (host[0]) && isdigit (host[0])) {
+ tmpaddr = inet_addr (host); /* returns network byte order */
+ } else {
+ tmpaddr = -1;
+ }
+
+ PRMSG (4,"SocketINETConnect: inet_addr(%s) = %x\n",
+ host, tmpaddr, 0);
+
+ if (tmpaddr == -1)
+ {
+#ifdef _WIN32
+ if ((hostp = gethostbyname(host)) == NULL)
+#else
+ if ((hostp = gethostbyname(host,hparams)) == NULL)
+#endif
+ {
+ PRMSG (1,"SocketINETConnect: Can't get address for %s\n",
+ host, 0, 0);
+ ESET(EINVAL);
+ return TRANS_CONNECT_FAILED;
+ }
+ if (hostp->h_addrtype != AF_INET) /* is IP host? */
+ {
+ PRMSG (1,"SocketINETConnect: not INET host%s\n",
+ host, 0, 0);
+ ESET(EPROTOTYPE);
+ return TRANS_CONNECT_FAILED;
+ }
+
+#if defined(CRAY) && defined(OLDTCP)
+ /* Only Cray UNICOS3 and UNICOS4 will define this */
+ {
+ long t;
+ memcpy ((char *)&t, (char *) hostp->h_addr, sizeof (t));
+ sockname.sin_addr = t;
+ }
+#else
+ memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr,
+ sizeof (sockname.sin_addr));
+#endif /* CRAY and OLDTCP */
+
+ }
+else
+ {
+#if defined(CRAY) && defined(OLDTCP)
+ /* Only Cray UNICOS3 and UNICOS4 will define this */
+ sockname.sin_addr = tmpaddr;
+#else
+ sockname.sin_addr.s_addr = tmpaddr;
+#endif /* CRAY and OLDTCP */
+ }
+
+ /*
+ * fill in sin_port
+ */
+
+ /* Check for number in the port string */
+
+ if (!is_numeric (port))
+ {
+ if ((servp = getservbyname (port,"tcp")) == NULL)
+ {
+ PRMSG (1,"SocketINETConnect: can't get service for %s\n",
+ port, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+ sockname.sin_port = htons (servp->s_port);
+ }
+ else
+ {
+ tmpport = strtol (port, (char**)NULL, 10);
+ if (tmpport < 1024 || tmpport > USHRT_MAX)
+ return TRANS_CONNECT_FAILED;
+ sockname.sin_port = htons (((unsigned short) tmpport));
+ }
+
+ PRMSG (4,"SocketINETConnect: sockname.sin_port = %d\n",
+ ntohs(sockname.sin_port), 0, 0);
+
+ /*
+ * Do the connect()
+ */
+
+ if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
+ {
+#ifdef _WIN32
+ int olderrno = WSAGetLastError();
+#else
+ int olderrno = errno;
+#endif
+
+ /*
+ * If the error was ECONNREFUSED, the server may be overloaded
+ * and we should try again.
+ *
+ * If the error was EWOULDBLOCK or EINPROGRESS then the socket
+ * was non-blocking and we should poll using select
+ *
+ * If the error was EINTR, the connect was interrupted and we
+ * should try again.
+ */
+
+ if (olderrno == ECONNREFUSED || olderrno == EINTR)
+ return TRANS_TRY_CONNECT_AGAIN;
+ else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
+ return TRANS_IN_PROGRESS;
+ else
+ {
+ PRMSG (2,"SocketINETConnect: Can't connect: errno = %d\n",
+ olderrno,0, 0);
+
+ return TRANS_CONNECT_FAILED;
+ }
+ }
+
+
+ /*
+ * Sync up the address fields of ciptr.
+ */
+
+ if (TRANS(SocketINETGetAddr) (ciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETConnect: ...SocketINETGetAddr() failed:\n",
+ 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+ if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n",
+ 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+ return 0;
+}
+
+#endif /* TCPCONN */
+
+
+
+#ifdef UNIXCONN
+
+/*
+ * Make sure 'host' is really local.
+ */
+
+static int
+UnixHostReallyLocal (char *host)
+
+{
+ char hostnamebuf[256];
+
+ TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
+
+ if (strcmp (hostnamebuf, host) == 0)
+ {
+ return (1);
+ }
+ else
+ {
+ /*
+ * A host may have more than one network address. If any of the
+ * network addresses of 'host' (specified to the connect call)
+ * match any of the network addresses of 'hostname' (determined
+ * by TRANS(GetHostname)), then the two hostnames are equivalent,
+ * and we know that 'host' is really a local host.
+ */
+ char specified_local_addr_list[10][4];
+ int scount, equiv, i, j;
+ struct hostent *hostp;
+
+ if ((hostp = gethostbyname (host)) == NULL)
+ return (0);
+
+ scount = 0;
+ while (hostp->h_addr_list[scount] && scount <= 8)
+ {
+ /*
+ * The 2nd call to gethostname() overrides the data
+ * from the 1st call, so we must save the address list.
+ */
+
+ specified_local_addr_list[scount][0] =
+ hostp->h_addr_list[scount][0];
+ specified_local_addr_list[scount][1] =
+ hostp->h_addr_list[scount][1];
+ specified_local_addr_list[scount][2] =
+ hostp->h_addr_list[scount][2];
+ specified_local_addr_list[scount][3] =
+ hostp->h_addr_list[scount][3];
+ scount++;
+ }
+ if ((hostp = gethostbyname (hostnamebuf)) == NULL)
+ return (0);
+
+ equiv = 0;
+ i = 0;
+
+ while (i < scount && !equiv)
+ {
+ j = 0;
+
+ while (hostp->h_addr_list[j])
+ {
+ if ((specified_local_addr_list[i][0] ==
+ hostp->h_addr_list[j][0]) &&
+ (specified_local_addr_list[i][1] ==
+ hostp->h_addr_list[j][1]) &&
+ (specified_local_addr_list[i][2] ==
+ hostp->h_addr_list[j][2]) &&
+ (specified_local_addr_list[i][3] ==
+ hostp->h_addr_list[j][3]))
+ {
+ /* They're equal, so we're done */
+
+ equiv = 1;
+ break;
+ }
+
+ j++;
+ }
+
+ i++;
+ }
+
+ return (equiv);
+ }
+}
+
+static int
+TRANS(SocketUNIXConnect) (XtransConnInfo ciptr, char *host, char *port)
+
+{
+ struct sockaddr_un sockname;
+ int namelen;
+
+#if defined(hpux) && defined(X11_t)
+ struct sockaddr_un old_sockname;
+ int old_namelen;
+#endif
+
+
+ PRMSG (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port);
+
+ /*
+ * Make sure 'host' is really local. If not, we return failure.
+ * The reason we make this check is because a process may advertise
+ * a "local" network ID for which it can accept connections, but if
+ * a process on a remote machine tries to connect to this network ID,
+ * we know for sure it will fail.
+ */
+
+ if (strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host))
+ {
+ PRMSG (1,
+ "SocketUNIXConnect: Cannot connect to non-local host %s\n",
+ host, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+
+ /*
+ * Check the port.
+ */
+
+ if (!port || !*port)
+ {
+ PRMSG (1,"SocketUNIXConnect: Missing port specification\n",
+ 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+ /*
+ * Build the socket name.
+ */
+
+ sockname.sun_family = AF_UNIX;
+
+ if (set_sun_path(port, UNIX_PATH, sockname.sun_path) != 0) {
+ PRMSG (1, "SocketUNIXConnect: path too long\n", 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+ namelen = sizeof( sockname ) - sizeof( sockname.sun_path ) + strlen( sockname.sun_path ) + 1;
+#if defined(BSD44SOCKETS)
+ sockname.sun_len = namelen;
+#endif
+
+#if defined(hpux) && defined(X11_t)
+ /*
+ * This is gross, but it was in Xlib
+ */
+ old_sockname.sun_family = AF_UNIX;
+ if (set_sun_path(port, OLD_UNIX_PATH, old_sockname.sun_path) != 0) {
+ PRMSG (1, "SocketUNIXConnect: path too long\n", 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+ old_namelen = strlen (old_sockname.sun_path) +
+ sizeof (old_sockname.sun_family);
+#endif
+
+
+ /*
+ * Do the connect()
+ */
+
+ if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
+ {
+ int olderrno = errno;
+ int connected = 0;
+
+#if defined(hpux) && defined(X11_t)
+ if (olderrno == ENOENT)
+ {
+ if (connect (ciptr->fd,
+ (struct sockaddr *) &old_sockname, old_namelen) >= 0)
+ {
+ connected = 1;
+ }
+ else
+ olderrno = errno;
+ }
+#endif
+ if (!connected)
+ {
+ errno = olderrno;
+
+ /*
+ * If the error was ENOENT, the server may be starting up
+ * and we should try again.
+ *
+ * If the error was EWOULDBLOCK or EINPROGRESS then the socket
+ * was non-blocking and we should poll using select
+ *
+ * If the error was EINTR, the connect was interrupted and we
+ * should try again.
+ */
+
+ if (olderrno == ENOENT || olderrno == EINTR)
+ return TRANS_TRY_CONNECT_AGAIN;
+ else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
+ return TRANS_IN_PROGRESS;
+ else
+ {
+ PRMSG (2,"SocketUNIXConnect: Can't connect: errno = %d\n",
+ EGET(),0, 0);
+
+ return TRANS_CONNECT_FAILED;
+ }
+ }
+ }
+
+ /*
+ * Get the socket name and the peer name from the connect socket,
+ * since this is unix domain.
+ */
+
+ if ((ciptr->addr = (char *) xalloc(namelen)) == NULL ||
+ (ciptr->peeraddr = (char *) xalloc(namelen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketUNIXCreateListener: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+ ciptr->family = AF_UNIX;
+ ciptr->addrlen = namelen;
+ ciptr->peeraddrlen = namelen;
+ memcpy (ciptr->addr, &sockname, ciptr->addrlen);
+ memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
+
+ return 0;
+}
+
+#endif /* UNIXCONN */
+
+#endif /* TRANS_CLIENT */
+
+
+static int
+TRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
+
+{
+ PRMSG (2,"SocketBytesReadable(%x,%d,%x)\n",
+ ciptr, ciptr->fd, pend);
+#if defined(QNX4)
+ *pend = 0L; /* FIONREAD only returns a short. Zero out upper bits */
+#endif
+#ifdef _WIN32
+ return ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend);
+#else
+#if (defined(i386) && defined(SYSV)) || defined(_SEQUENT_)
+ return ioctl (ciptr->fd, I_NREAD, (char *) pend);
+#else
+#if defined(__EMX__)
+ return ioctl (ciptr->fd, FIONREAD, (char*) pend, sizeof(int));
+#else
+ return ioctl (ciptr->fd, FIONREAD, (char *) pend);
+#endif /* __EMX__ */
+#endif /* i386 && SYSV && !SCO || _SEQUENT_ */
+#endif /* _WIN32 */
+}
+
+
+static int
+TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size)
+
+{
+ PRMSG (2,"SocketRead(%d,%x,%d)\n", ciptr->fd, buf, size);
+
+#if defined(_WIN32) || defined(__EMX__)
+ return recv ((SOCKET)ciptr->fd, buf, size, 0);
+#else
+ return read (ciptr->fd, buf, size);
+#endif /* _WIN32 */
+}
+
+
+static int
+TRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size)
+
+{
+ PRMSG (2,"SocketWrite(%d,%x,%d)\n", ciptr->fd, buf, size);
+
+#if defined(_WIN32) || defined(__EMX__)
+ return send ((SOCKET)ciptr->fd, buf, size, 0);
+#else
+ return write (ciptr->fd, buf, size);
+#endif /* _WIN32 */
+}
+
+
+static int
+TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size)
+
+{
+ PRMSG (2,"SocketReadv(%d,%x,%d)\n", ciptr->fd, buf, size);
+
+ return READV (ciptr, buf, size);
+}
+
+
+static int
+TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
+
+{
+ PRMSG (2,"SocketWritev(%d,%x,%d)\n", ciptr->fd, buf, size);
+
+ return WRITEV (ciptr, buf, size);
+}
+
+
+static int
+TRANS(SocketDisconnect) (XtransConnInfo ciptr)
+
+{
+ PRMSG (2,"SocketDisconnect(%x,%d)\n", ciptr, ciptr->fd, 0);
+
+ return shutdown (ciptr->fd, 2); /* disallow further sends and receives */
+}
+
+
+#ifdef TCPCONN
+static int
+TRANS(SocketINETClose) (XtransConnInfo ciptr)
+
+{
+ PRMSG (2,"SocketINETClose(%x,%d)\n", ciptr, ciptr->fd, 0);
+
+ return close (ciptr->fd);
+}
+
+#endif /* TCPCONN */
+
+
+#ifdef UNIXCONN
+static int
+TRANS(SocketUNIXClose) (XtransConnInfo ciptr)
+
+{
+ /*
+ * If this is the server side, then once the socket is closed,
+ * it must be unlinked to completely close it
+ */
+
+ struct sockaddr_un *sockname = (struct sockaddr_un *) ciptr->addr;
+ char path[200]; /* > sizeof sun_path +1 */
+ int ret;
+
+ PRMSG (2,"SocketUNIXClose(%x,%d)\n", ciptr, ciptr->fd, 0);
+
+ ret = close(ciptr->fd);
+
+ if (ciptr->flags
+ && sockname
+ && sockname->sun_family == AF_UNIX
+ && sockname->sun_path[0])
+ {
+ strncpy (path, sockname->sun_path,
+ ciptr->addrlen - sizeof (sockname->sun_family));
+ unlink (path);
+ }
+
+ return ret;
+}
+
+static int
+TRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr)
+
+{
+ /*
+ * Don't unlink path.
+ */
+
+ int ret;
+
+ PRMSG (2,"SocketUNIXCloseForCloning(%x,%d)\n",
+ ciptr, ciptr->fd, 0);
+
+ ret = close(ciptr->fd);
+
+ return ret;
+}
+
+#endif /* UNIXCONN */
+
+
+#ifdef TCPCONN
+Xtransport TRANS(SocketTCPFuncs) = {
+ /* Socket Interface */
+ "tcp",
+ 0,
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SocketReopenCOTSServer),
+ TRANS(SocketReopenCLTSServer),
+#endif
+ TRANS(SocketSetOption),
+#ifdef TRANS_SERVER
+ TRANS(SocketINETCreateListener),
+ NULL, /* ResetListener */
+ TRANS(SocketINETAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketINETConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(SocketBytesReadable),
+ TRANS(SocketRead),
+ TRANS(SocketWrite),
+ TRANS(SocketReadv),
+ TRANS(SocketWritev),
+ TRANS(SocketDisconnect),
+ TRANS(SocketINETClose),
+ TRANS(SocketINETClose),
+ };
+
+Xtransport TRANS(SocketINETFuncs) = {
+ /* Socket Interface */
+ "inet",
+ TRANS_ALIAS,
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SocketReopenCOTSServer),
+ TRANS(SocketReopenCLTSServer),
+#endif
+ TRANS(SocketSetOption),
+#ifdef TRANS_SERVER
+ TRANS(SocketINETCreateListener),
+ NULL, /* ResetListener */
+ TRANS(SocketINETAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketINETConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(SocketBytesReadable),
+ TRANS(SocketRead),
+ TRANS(SocketWrite),
+ TRANS(SocketReadv),
+ TRANS(SocketWritev),
+ TRANS(SocketDisconnect),
+ TRANS(SocketINETClose),
+ TRANS(SocketINETClose),
+ };
+
+#endif /* TCPCONN */
+
+#ifdef UNIXCONN
+#if !defined(LOCALCONN)
+Xtransport TRANS(SocketLocalFuncs) = {
+ /* Socket Interface */
+ (char*)"local",
+ 0,
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SocketReopenCOTSServer),
+ TRANS(SocketReopenCLTSServer),
+#endif
+ TRANS(SocketSetOption),
+#ifdef TRANS_SERVER
+ TRANS(SocketUNIXCreateListener),
+ TRANS(SocketUNIXResetListener),
+ TRANS(SocketUNIXAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketUNIXConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(SocketBytesReadable),
+ TRANS(SocketRead),
+ TRANS(SocketWrite),
+ TRANS(SocketReadv),
+ TRANS(SocketWritev),
+ TRANS(SocketDisconnect),
+ TRANS(SocketUNIXClose),
+ TRANS(SocketUNIXCloseForCloning),
+ };
+#endif /* !LOCALCONN */
+
+Xtransport TRANS(SocketUNIXFuncs) = {
+ /* Socket Interface */
+ (char*)"unix",
+#if !defined(LOCALCONN)
+ TRANS_ALIAS,
+#else
+ 0,
+#endif
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SocketReopenCOTSServer),
+ TRANS(SocketReopenCLTSServer),
+#endif
+ TRANS(SocketSetOption),
+#ifdef TRANS_SERVER
+ TRANS(SocketUNIXCreateListener),
+ TRANS(SocketUNIXResetListener),
+ TRANS(SocketUNIXAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketUNIXConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(SocketBytesReadable),
+ TRANS(SocketRead),
+ TRANS(SocketWrite),
+ TRANS(SocketReadv),
+ TRANS(SocketWritev),
+ TRANS(SocketDisconnect),
+ TRANS(SocketUNIXClose),
+ TRANS(SocketUNIXCloseForCloning),
+ };
+
+#endif /* UNIXCONN */
diff --git a/dcop/KDE-ICE/Xtransutil.c b/dcop/KDE-ICE/Xtransutil.c
new file mode 100644
index 000000000..bad9aae53
--- /dev/null
+++ b/dcop/KDE-ICE/Xtransutil.c
@@ -0,0 +1,549 @@
+/* $TOG: Xtransutil.c /main/33 1998/02/06 15:55:10 kaleb $ */
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+
+*/
+/* $XFree86: xc/lib/xtrans/Xtransutil.c,v 3.14 1999/06/20 08:41:24 dawes Exp $ */
+
+/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
+ *
+ * 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 NCR not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCR makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCRS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NCR 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.
+ */
+
+/*
+ * These are some utility functions created for convenience or to provide
+ * an interface that is similar to an existing interface. These are built
+ * only using the Transport Independant API, and have no knowledge of
+ * the internal implementation.
+ */
+
+#ifdef X11_t
+
+/*
+ * These values come from X.h and Xauth.h, and MUST match them. Some
+ * of these values are also defined by the ChangeHost protocol message.
+ */
+
+#define FamilyInternet 0 /* IPv4 */
+#define FamilyDECnet 1
+#define FamilyChaos 2
+#define FamilyInternet6 6
+#define FamilyAmoeba 33
+#define FamilyLocalHost 252
+#define FamilyKrb5Principal 253
+#define FamilyNetname 254
+#define FamilyLocal 256
+#define FamilyWild 65535
+
+/*
+ * TRANS(ConvertAddress) converts a sockaddr based address to an
+ * X authorization based address. Some of this is defined as part of
+ * the ChangeHost protocol. The rest is just doen in a consistent manner.
+ */
+
+int
+TRANS(ConvertAddress)(int *familyp, int *addrlenp, Xtransaddr **addrp)
+
+{
+
+ PRMSG(2,"ConvertAddress(%d,%d,%x)\n",*familyp,*addrlenp,*addrp);
+
+ switch( *familyp )
+ {
+#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
+ case AF_INET:
+ {
+ /*
+ * Check for the BSD hack localhost address 127.0.0.1.
+ * In this case, we are really FamilyLocal.
+ */
+
+ struct sockaddr_in saddr;
+#ifdef CRAY
+#ifdef OLDTCP
+ int len = sizeof(saddr.sin_addr);
+#else
+ int len = SIZEOF_in_addr;
+#endif /* OLDTCP */
+ char *cp = (char *) &saddr.sin_addr;
+#else /* else not CRAY */
+ int len = sizeof(saddr.sin_addr.s_addr);
+ char *cp = (char *) &saddr.sin_addr.s_addr;
+#endif /* CRAY */
+
+ memcpy (&saddr, *addrp, sizeof (struct sockaddr_in));
+
+ if ((len == 4) && (cp[0] == 127) && (cp[1] == 0) &&
+ (cp[2] == 0) && (cp[3] == 1))
+ {
+ *familyp=FamilyLocal;
+ }
+ else
+ {
+ *familyp=FamilyInternet;
+ *addrlenp=len;
+ memcpy(*addrp,&saddr.sin_addr,len);
+ }
+ break;
+ }
+#endif /* defined(TCPCONN) || defined(STREAMSCONN) || MNX_TCPCONN */
+
+#if defined(DNETCONN)
+ case AF_DECnet:
+ {
+ struct sockaddr_dn saddr;
+
+ memcpy (&saddr, *addrp, sizeof (struct sockaddr_dn));
+
+ *familyp=FamilyDECnet;
+ *addrlenp=sizeof(struct dn_naddr);
+ memcpy(*addrp,&saddr.sdn_add,*addrlenp);
+
+ break;
+ }
+#endif /* defined(DNETCONN) */
+
+#if defined(UNIXCONN) || defined(LOCALCONN) || defined(OS2PIPECONN)
+ case AF_UNIX:
+ {
+ *familyp=FamilyLocal;
+ break;
+ }
+#endif /* defined(UNIXCONN) || defined(LOCALCONN) || defined(OS2PIPECONN)*/
+
+#if defined(AMRPCCONN)
+ case AF_AMOEBA:
+ {
+ *familyp=FamilyAmoeba;
+ break;
+ }
+#endif
+#if defined(AMTCPCONN) && !(defined(TCPCONN) || defined(STREAMSCONN))
+ case AF_INET:
+ {
+ *familyp=FamilyInternet;
+ break;
+ }
+#endif
+
+ default:
+ PRMSG(1,"ConvertAddress: Unknown family type %d\n",
+ *familyp, 0,0 );
+ return -1;
+ }
+
+
+ if (*familyp == FamilyLocal)
+ {
+ /*
+ * In the case of a local connection, we need to get the
+ * host name for authentication.
+ */
+
+ char hostnamebuf[256];
+ int len = TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
+
+ if (len > 0) {
+ if (*addrp && *addrlenp < (len + 1))
+ {
+ xfree ((char *) *addrp);
+ *addrp = NULL;
+ }
+ if (!*addrp)
+ *addrp = (Xtransaddr *) xalloc (len + 1);
+ if (*addrp) {
+ strcpy ((char *) *addrp, hostnamebuf);
+ *addrlenp = len;
+ } else {
+ *addrlenp = 0;
+ }
+ }
+ else
+ {
+ if (*addrp)
+ xfree ((char *) *addrp);
+ *addrp = NULL;
+ *addrlenp = 0;
+ }
+ }
+
+ return 0;
+}
+
+#endif /* X11_t */
+
+#ifdef ICE_t
+
+#include <signal.h>
+
+char *
+TRANS(GetMyNetworkId) (XtransConnInfo ciptr)
+
+{
+ int family = ciptr->family;
+ char *addr = ciptr->addr;
+ char hostnamebuf[256];
+ char *networkId = NULL;
+ char *transName = ciptr->transptr->TransName;
+
+ if (gethostname (hostnamebuf, sizeof (hostnamebuf)) < 0)
+ {
+ return (NULL);
+ }
+ hostnamebuf[sizeof(hostnamebuf)-1] = '\0';
+
+ switch (family)
+ {
+#if defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) || defined(OS2PIPECONN)
+ case AF_UNIX:
+ {
+ struct sockaddr_un *saddr = (struct sockaddr_un *) addr;
+ networkId = (char *) xalloc (3 + strlen (transName) +
+ strlen (hostnamebuf) + strlen (saddr->sun_path));
+ sprintf (networkId, "%s/%s:%s", transName,
+ hostnamebuf, saddr->sun_path);
+ break;
+ }
+#endif /* defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) || defined(OS2PIPECONN)
+*/
+
+#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
+ case AF_INET:
+ {
+ struct sockaddr_in *saddr = (struct sockaddr_in *) addr;
+ char portnumbuf[10];
+
+ sprintf (portnumbuf, "%d", ntohs (saddr->sin_port));
+ networkId = (char *) xalloc (3 + strlen (transName) +
+ strlen (hostnamebuf) + strlen (portnumbuf));
+ sprintf (networkId, "%s/%s:%s", transName, hostnamebuf, portnumbuf);
+ break;
+ }
+#endif /* defined(TCPCONN) || defined(STREAMSCONN) || MNX_TCPCONN */
+
+#if defined(DNETCONN)
+ case AF_DECnet:
+ {
+ struct sockaddr_dn *saddr = (struct sockaddr_dn *) addr;
+
+ networkId = (char *) xalloc (
+ 13 + strlen (hostnamebuf) + saddr->sdn_objnamel);
+ sprintf (networkId, "dnet/%s::%s",
+ hostnamebuf, saddr->sdn_objname);
+ break;
+ }
+#endif /* defined(DNETCONN) */
+
+ default:
+ break;
+ }
+
+ return (networkId);
+}
+
+#include <setjmp.h>
+static jmp_buf env;
+
+#ifdef SIGALRM
+static volatile int nameserver_timedout = 0;
+
+static
+#ifdef SIGNALRETURNSINT
+int
+#else
+void
+#endif
+nameserver_lost(int sig)
+{
+ (void)sig;/*unused*/
+ nameserver_timedout = 1;
+ longjmp (env, -1);
+ /* NOTREACHED */
+#ifdef SIGNALRETURNSINT
+ return -1; /* for picky compilers */
+#endif
+}
+#endif /* SIGALARM */
+
+
+char *
+TRANS(GetPeerNetworkId) (XtransConnInfo ciptr)
+
+{
+ int family = ciptr->family;
+ char *hostname;
+ char addrbuf[256];
+ char *addr = NULL;
+
+ switch (family)
+ {
+ case AF_UNSPEC:
+#if defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) || defined(OS2PIPECONN)
+ case AF_UNIX:
+ {
+ if (gethostname (addrbuf, sizeof (addrbuf)) == 0) {
+ addrbuf[sizeof(addrbuf)-1] = '\0';
+ addr = addrbuf;
+ }
+ break;
+ }
+#endif /* defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) || defined(OS2PIPECONN)
+*/
+
+#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
+ case AF_INET:
+ {
+ char *peer_addr = ciptr->peeraddr;
+ struct sockaddr_in *saddr = (struct sockaddr_in *) peer_addr;
+ struct hostent * hostp = NULL;
+
+#if defined(SIGALRM) && !defined(_WIN32)
+ /*
+ * gethostbyaddr can take a LONG time if the host does not exist.
+ * Assume that if it does not respond in NAMESERVER_TIMEOUT seconds
+ * that something is wrong and do not make the user wait.
+ * gethostbyaddr will continue after a signal, so we have to
+ * jump out of it.
+ */
+
+ nameserver_timedout = 0;
+ signal (SIGALRM, nameserver_lost);
+ alarm (4);
+ if (setjmp(env) == 0) {
+#endif
+ hostp = gethostbyaddr ((char *) &saddr->sin_addr,
+ sizeof (saddr->sin_addr), AF_INET);
+#if defined(SIGALRM) && !defined(_WIN32)
+ }
+ alarm (0);
+#endif
+ if (hostp != NULL)
+ addr = hostp->h_name;
+ else
+ addr = inet_ntoa (saddr->sin_addr);
+ break;
+ }
+
+#endif /* defined(TCPCONN) || defined(STREAMSCONN) || MNX_TCPCONN */
+
+#if defined(DNETCONN)
+ case AF_DECnet:
+ {
+ char *peer_addr = ciptr->peeraddr;
+ struct sockaddr_dn *saddr = (struct sockaddr_dn *) peer_addr;
+ struct nodeent *np;
+
+ if (np = getnodebyaddr(saddr->sdn_add.a_addr,
+ saddr->sdn_add.a_len, AF_DECnet)) {
+ snprintf(addrbuf, sizeof(addrbuf), "%s:", np->n_name);
+ } else {
+ snprintf(addrbuf, sizeof(addrbuf), "%s:", dnet_htoa(&saddr->sdn_add));
+ }
+ addr = addrbuf;
+ break;
+ }
+#endif /* defined(DNETCONN) */
+
+#if defined(AMRPCCONN)
+ case AF_AMOEBA:
+ {
+ addr = "Amoeba"; /* not really used */
+ break;
+ }
+#endif
+#if defined(AMTCPCONN) && !(defined(TCPCONN) || defined(STREAMSCONN))
+ case AF_INET:
+ {
+ if (gethostname (addrbuf, sizeof (addrbuf)) == 0) {
+ addrbuf[sizeof(addrbuf)-1] = '\0';
+ addr = addrbuf;
+ } else {
+ addr = "";
+ }
+ break;
+ }
+#endif
+
+ default:
+ return (NULL);
+ }
+
+
+ hostname = (char *) xalloc (
+ strlen (ciptr->transptr->TransName) + strlen (addr) + 2);
+ strcpy (hostname, ciptr->transptr->TransName);
+ strcat (hostname, "/");
+ if (addr)
+ strcat (hostname, addr);
+
+ return (hostname);
+}
+
+#endif /* ICE_t */
+
+
+#if defined(_WIN32) && (defined(TCPCONN) || defined(DNETCONN))
+int
+TRANS(WSAStartup) (void)
+{
+ static WSADATA wsadata;
+
+ PRMSG (2,"WSAStartup()\n", 0, 0, 0);
+
+ if (!wsadata.wVersion && WSAStartup(MAKEWORD(1,1), &wsadata))
+ return 1;
+ return 0;
+}
+#endif
+
+
+static int
+is_numeric (char *str)
+
+{
+ int i;
+
+ for (i = 0; i < (int) strlen (str); i++)
+ if (!isdigit (str[i]))
+ return (0);
+
+ return (1);
+}
+
+#ifdef TRANS_SERVER
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#if !defined(S_IFLNK) && !defined(S_ISLNK)
+#define lstat(a,b) stat(a,b)
+#endif
+
+static int
+trans_mkdir(char *path, int mode)
+{
+ struct stat buf;
+
+ if (mkdir(path, mode) == 0) {
+ chmod(path, mode);
+ return 0;
+ }
+ /* If mkdir failed with EEXIST, test if it is a directory with
+ the right modes, else fail */
+ if (errno == EEXIST) {
+ if (lstat(path, &buf) != 0) {
+ PRMSG(1, "mkdir: (l)stat failed for %s (%d)\n",
+ path, errno, 0);
+ return -1;
+ }
+ if (S_ISDIR(buf.st_mode)) {
+ int updateOwner = 0;
+ int updateMode = 0;
+ int updatedOwner = 0;
+ int updatedMode = 0;
+ /* Check if the directory's ownership is OK. */
+ if (buf.st_uid != 0)
+ updateOwner = 1;
+ /*
+ * Check if the directory's mode is OK. An exact match isn't
+ * required, just a mode that isn't more permissive than the
+ * one requested.
+ */
+ if ((~mode) & 0077 & buf.st_mode)
+ updateMode = 1;
+ if ((mode & 01000) &&
+ (buf.st_mode & 0002) && !(buf.st_mode & 01000))
+ updateMode = 1;
+#ifdef HAS_FCHOWN
+ /*
+ * If fchown(2) and fchmod(2) are available, try to correct the
+ * directory's owner and mode. Otherwise it isn't safe to attempt
+ * to do this.
+ */
+ if (updateMode || updateOwner) {
+ int fd = -1;
+ struct stat fbuf;
+ if ((fd = open(path, O_RDONLY)) != -1) {
+ if (fstat(fd, &fbuf) == -1) {
+ PRMSG(1, "mkdir: fstat failed for %s (%d)\n",
+ path, errno, 0);
+ close(fd);
+ return -1;
+ }
+ /*
+ * Verify that we've opened the same directory as was
+ * checked above.
+ */
+ if (!S_ISDIR(fbuf.st_mode) ||
+ buf.st_dev != fbuf.st_dev ||
+ buf.st_ino != fbuf.st_ino) {
+ PRMSG(1, "mkdir: inode for %s changed\n",
+ path, 0, 0);
+ close(fd);
+ return -1;
+ }
+ if (updateOwner && fchown(fd, 0, 0) == 0)
+ updatedOwner = 1;
+ if (updateMode && fchmod(fd, mode) == 0)
+ updatedMode = 1;
+ close(fd);
+ }
+ }
+#endif
+#ifndef __CYGWIN__
+ if (updateOwner && !updatedOwner) {
+ PRMSG(1, "mkdir: Owner of %s should be set to root\n",
+ path, 0, 0);
+/* sleep(5); */
+ }
+ if (updateMode && !updatedMode) {
+ PRMSG(1, "mkdir: Mode of %s should be set to %04o\n",
+ path, mode, 0);
+/* sleep(5); */
+ }
+#endif
+ return 0;
+ }
+ }
+ /* In all other cases, fail */
+ return -1;
+}
+
+#endif /* TRANS_SERVER */
diff --git a/dcop/KDE-ICE/accept.c b/dcop/KDE-ICE/accept.c
new file mode 100644
index 000000000..59d63d191
--- /dev/null
+++ b/dcop/KDE-ICE/accept.c
@@ -0,0 +1,189 @@
+/* $XConsortium: accept.c,v 1.24 94/12/20 17:50:13 mor Exp $ */
+/******************************************************************************
+
+
+Copyright (c) 1993 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <string.h>
+
+#include "KDE-ICE/ICElib.h"
+#include "KDE-ICE/ICElibint.h"
+#include "KDE-ICE/Xtrans.h"
+#include "KDE-ICE/globals.h"
+
+IceConn
+IceAcceptConnection (listenObj, statusRet)
+
+IceListenObj listenObj;
+IceAcceptStatus *statusRet;
+
+{
+ IceConn iceConn;
+ XtransConnInfo newconn;
+ iceByteOrderMsg *pMsg;
+ int endian, status;
+
+ /*
+ * Accept the connection.
+ */
+
+ if ((newconn = (XtransConnInfo)_kde_IceTransAccept (listenObj->trans_conn, &status)) == 0)
+ {
+ if (status == TRANS_ACCEPT_BAD_MALLOC)
+ *statusRet = IceAcceptBadMalloc;
+ else
+ *statusRet = IceAcceptFailure;
+ return (NULL);
+ }
+
+
+ /*
+ * Set close-on-exec so that programs that fork() don't get confused.
+ */
+
+ _kde_IceTransSetOption (newconn, TRANS_CLOSEONEXEC, 1);
+
+
+ /*
+ * Create an ICE object for this connection.
+ */
+
+ if ((iceConn = (IceConn) malloc (sizeof (struct _IceConn))) == NULL)
+ {
+ _kde_IceTransClose (newconn);
+ *statusRet = IceAcceptBadMalloc;
+ return (NULL);
+ }
+
+ iceConn->listen_obj = listenObj;
+
+ iceConn->waiting_for_byteorder = True;
+ iceConn->connection_status = IceConnectPending;
+ iceConn->io_ok = True;
+ iceConn->dispatch_level = 0;
+ iceConn->context = NULL;
+ iceConn->my_ice_version_index = 0;
+
+ iceConn->trans_conn = newconn;
+ iceConn->send_sequence = 0;
+ iceConn->receive_sequence = 0;
+
+ iceConn->connection_string = (char *) malloc (
+ strlen (listenObj->network_id) + 1);
+
+ if (iceConn->connection_string == NULL)
+ {
+ _kde_IceTransClose (newconn);
+ free ((char *) iceConn);
+ *statusRet = IceAcceptBadMalloc;
+ return (NULL);
+ }
+ else
+ strcpy (iceConn->connection_string, listenObj->network_id);
+
+ iceConn->vendor = NULL;
+ iceConn->release = NULL;
+
+ if ((iceConn->inbuf = iceConn->inbufptr =
+ (char *) malloc (ICE_INBUFSIZE)) != NULL)
+ {
+ iceConn->inbufmax = iceConn->inbuf + ICE_INBUFSIZE;
+ }
+ else
+ {
+ _kde_IceTransClose (newconn);
+ free ((char *) iceConn);
+ *statusRet = IceAcceptBadMalloc;
+ return (NULL);
+ }
+
+ if ((iceConn->outbuf = iceConn->outbufptr =
+ (char *) malloc (ICE_OUTBUFSIZE)) != NULL)
+ {
+ memset(iceConn->outbuf, 0, ICE_OUTBUFSIZE);
+ iceConn->outbufmax = iceConn->outbuf + ICE_OUTBUFSIZE;
+ }
+ else
+ {
+ _kde_IceTransClose (newconn);
+ free (iceConn->inbuf);
+ free ((char *) iceConn);
+ *statusRet = IceAcceptBadMalloc;
+ return (NULL);
+ }
+
+ iceConn->scratch = NULL;
+ iceConn->scratch_size = 0;
+
+ iceConn->open_ref_count = 1;
+ iceConn->proto_ref_count = 0;
+
+ iceConn->skip_want_to_close = False;
+ iceConn->want_to_close = False;
+ iceConn->free_asap = False;
+
+ iceConn->saved_reply_waits = NULL;
+ iceConn->ping_waits = NULL;
+
+ iceConn->process_msg_info = NULL;
+
+ iceConn->connect_to_you = NULL;
+ iceConn->protosetup_to_you = NULL;
+
+ iceConn->connect_to_me = NULL;
+ iceConn->protosetup_to_me = NULL;
+
+
+ /*
+ * Send our byte order.
+ */
+
+ IceGetHeader (iceConn, 0, ICE_ByteOrder,
+ SIZEOF (iceByteOrderMsg), iceByteOrderMsg, pMsg);
+
+ endian = 1;
+ if (*(char *) &endian)
+ pMsg->byteOrder = IceLSBfirst;
+ else
+ pMsg->byteOrder = IceMSBfirst;
+
+ IceFlush (iceConn);
+
+
+ if (_IceWatchProcs)
+ {
+ /*
+ * Notify the watch procedures that an iceConn was opened.
+ */
+
+ _IceConnectionOpened (iceConn);
+ }
+
+ *statusRet = IceAcceptSuccess;
+
+ return (iceConn);
+}
diff --git a/dcop/KDE-ICE/authutil.c b/dcop/KDE-ICE/authutil.c
new file mode 100644
index 000000000..41a2eefaa
--- /dev/null
+++ b/dcop/KDE-ICE/authutil.c
@@ -0,0 +1,524 @@
+/* $XConsortium: authutil.c /main/16 1996/09/28 16:33:00 rws $ */
+/* $XFree86: xc/lib/ICE/authutil.c,v 3.2 1997/01/05 11:51:53 dawes Exp $ */
+/******************************************************************************
+
+
+Copyright (c) 1993 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <KDE-ICE/ICElib.h>
+#include "KDE-ICE/ICElibint.h"
+#include <KDE-ICE/ICEutil.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <string.h>
+
+#if defined(X_NOT_STDC_ENV) && !defined(__EMX__)
+extern int errno;
+extern long time ();
+extern char *getenv();
+#define Time_t long
+#else
+#include <time.h>
+#define Time_t time_t
+#ifdef __EMX__
+extern char* getenv(const char*);
+#define link rename
+#endif
+#endif
+#ifndef X_NOT_POSIX
+#include <unistd.h>
+#else
+#ifndef _WIN32
+extern unsigned sleep ();
+#else
+#define link rename
+#endif
+#endif
+
+static Status read_short (FILE *file, unsigned short *shortp);
+static Status read_string (FILE *file, char **stringp);
+static Status read_counted_string (FILE *file, unsigned short *countp, char **stringp);
+static Status write_short (FILE *file, unsigned short s);
+static Status write_string (FILE *file, char *string);
+static Status write_counted_string (FILE *file, unsigned short count, char *string);
+
+
+
+/*
+ * The following routines are for manipulating the .ICEauthority file
+ * These are utility functions - they are not part of the standard
+ * ICE library specification.
+ */
+
+char *
+IceAuthFileName ()
+
+{
+#ifdef _WIN32
+ static char slashDotICEauthority[] = "\\.ICEauthority";
+#else
+ static char slashDotICEauthority[] = "/.ICEauthority";
+#endif
+ char *name;
+ static char *buf;
+ static int bsize;
+ int size;
+#if defined(_WIN32) || defined(__EMX__)
+ char dir[128];
+#endif
+
+ name = getenv ("ICEAUTHORITY");
+ if ( name )
+ return (name);
+
+ name = getenv ("HOME");
+
+ if (!name)
+ {
+#ifdef _WIN32
+ if(name = getenv ("HOMEDRIVE"))
+ {
+ strcpy (dir, name);
+ if(name = getenv ("HOMEPATH"))
+ strcat (dir, name);
+ }
+ else
+ {
+ if(name = getenv ("USERPROFILE"))
+ strcpy (dir, name);
+ }
+ name = dir;
+ if (!name)
+#endif
+#ifdef __EMX__
+ strcpy (dir,"c:");
+ name = dir;
+ if (!name)
+#endif
+ return (NULL);
+ }
+
+ size = strlen (name) + strlen (&slashDotICEauthority[1]) + 2;
+
+ if (size > bsize)
+ {
+ if (buf)
+ free (buf);
+ buf = malloc ((unsigned) size);
+ if (!buf)
+ return (NULL);
+ bsize = size;
+ }
+
+ strcpy (buf, name);
+ strcat (buf, slashDotICEauthority + (name[1] == '\0' ? 1 : 0));
+
+ return (buf);
+}
+
+
+
+int
+IceLockAuthFile (file_name, retries, timeout, dead)
+
+char *file_name;
+int retries;
+int timeout;
+long dead;
+
+{
+ char creat_name[1025], link_name[1025];
+ struct stat statb;
+ Time_t now;
+ int creat_fd = -1;
+
+ if ((int) strlen (file_name) > 1022)
+ return (IceAuthLockError);
+
+ strcpy (creat_name, file_name);
+ strcat (creat_name, "-c");
+ strcpy (link_name, file_name);
+ strcat (link_name, "-l");
+
+ if (stat (creat_name, &statb) != -1)
+ {
+ now = time ((Time_t *) 0);
+
+ /*
+ * NFS may cause ctime to be before now, special
+ * case a 0 deadtime to force lock removal
+ */
+
+ if (dead == 0 || now - statb.st_ctime > dead)
+ {
+ unlink (creat_name);
+ unlink (link_name);
+ }
+ }
+
+ while (retries > 0)
+ {
+ if (creat_fd == -1)
+ {
+ creat_fd = creat (creat_name, 0666);
+
+ if (creat_fd == -1)
+ {
+ if (errno != EACCES)
+ return (IceAuthLockError);
+ }
+ else
+ close (creat_fd);
+ }
+
+ if (creat_fd != -1)
+ {
+ if (link (creat_name, link_name) != -1)
+ return (IceAuthLockSuccess);
+
+ if (errno == ENOENT)
+ {
+ creat_fd = -1; /* force re-creat next time around */
+ continue;
+ }
+
+ if (errno != EEXIST)
+ return (IceAuthLockError);
+ }
+
+ sleep ((unsigned) timeout);
+ --retries;
+ }
+
+ return (IceAuthLockTimeout);
+}
+
+
+
+void
+IceUnlockAuthFile (file_name)
+
+char *file_name;
+
+{
+#ifndef _WIN32
+ char creat_name[1025];
+#endif
+ char link_name[1025];
+
+ if ((int) strlen (file_name) > 1022)
+ return;
+
+#ifndef _WIN32
+ strcpy (creat_name, file_name);
+ strcat (creat_name, "-c");
+#endif
+ strcpy (link_name, file_name);
+ strcat (link_name, "-l");
+
+#ifndef _WIN32
+ unlink (creat_name);
+#endif
+ unlink (link_name);
+}
+
+
+
+IceAuthFileEntry *
+IceReadAuthFileEntry (auth_file)
+
+FILE *auth_file;
+
+{
+ IceAuthFileEntry local;
+ IceAuthFileEntry *ret;
+
+ local.protocol_name = NULL;
+ local.protocol_data = NULL;
+ local.network_id = NULL;
+ local.auth_name = NULL;
+ local.auth_data = NULL;
+
+ if (!read_string (auth_file, &local.protocol_name))
+ return (NULL);
+
+ if (!read_counted_string (auth_file,
+ &local.protocol_data_length, &local.protocol_data))
+ goto bad;
+
+ if (!read_string (auth_file, &local.network_id))
+ goto bad;
+
+ if (!read_string (auth_file, &local.auth_name))
+ goto bad;
+
+ if (!read_counted_string (auth_file,
+ &local.auth_data_length, &local.auth_data))
+ goto bad;
+
+ if (!(ret = (IceAuthFileEntry *) malloc (sizeof (IceAuthFileEntry))))
+ goto bad;
+
+ *ret = local;
+
+ return (ret);
+
+ bad:
+
+ if (local.protocol_name) free (local.protocol_name);
+ if (local.protocol_data) free (local.protocol_data);
+ if (local.network_id) free (local.network_id);
+ if (local.auth_name) free (local.auth_name);
+ if (local.auth_data) free (local.auth_data);
+
+ return (NULL);
+}
+
+
+
+void
+IceFreeAuthFileEntry (auth)
+
+IceAuthFileEntry *auth;
+
+{
+ if (auth)
+ {
+ if (auth->protocol_name) free (auth->protocol_name);
+ if (auth->protocol_data) free (auth->protocol_data);
+ if (auth->network_id) free (auth->network_id);
+ if (auth->auth_name) free (auth->auth_name);
+ if (auth->auth_data) free (auth->auth_data);
+ free ((char *) auth);
+ }
+}
+
+
+
+Status
+IceWriteAuthFileEntry (auth_file, auth)
+
+FILE *auth_file;
+IceAuthFileEntry *auth;
+
+{
+ if (!write_string (auth_file, auth->protocol_name))
+ return (0);
+
+ if (!write_counted_string (auth_file,
+ auth->protocol_data_length, auth->protocol_data))
+ return (0);
+
+ if (!write_string (auth_file, auth->network_id))
+ return (0);
+
+ if (!write_string (auth_file, auth->auth_name))
+ return (0);
+
+ if (!write_counted_string (auth_file,
+ auth->auth_data_length, auth->auth_data))
+ return (0);
+
+ return (1);
+}
+
+
+
+IceAuthFileEntry *
+IceGetAuthFileEntry (protocol_name, network_id, auth_name)
+
+const char *protocol_name;
+const char *network_id;
+const char *auth_name;
+
+{
+ FILE *auth_file;
+ char *filename;
+ IceAuthFileEntry *entry;
+
+ if (!(filename = IceAuthFileName ()))
+ return (NULL);
+
+ if (access (filename, R_OK) != 0) /* checks REAL id */
+ return (NULL);
+
+ if (!(auth_file = fopen (filename, "rb")))
+ return (NULL);
+
+ for (;;)
+ {
+ if (!(entry = IceReadAuthFileEntry (auth_file)))
+ break;
+
+ if (strcmp (protocol_name, entry->protocol_name) == 0 &&
+ strcmp (network_id, entry->network_id) == 0 &&
+ strcmp (auth_name, entry->auth_name) == 0)
+ {
+ break;
+ }
+
+ IceFreeAuthFileEntry (entry);
+ }
+
+ fclose (auth_file);
+
+ return (entry);
+}
+
+
+
+/*
+ * local routines
+ */
+
+static Status
+read_short (FILE *file, unsigned short *shortp)
+{
+ unsigned char file_short[2];
+
+ if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
+ return (0);
+
+ *shortp = file_short[0] * 256 + file_short[1];
+ return (1);
+}
+
+
+static Status
+read_string (FILE *file, char **stringp)
+{
+ unsigned short len;
+ char *data;
+
+ if (!read_short (file, &len))
+ return (0);
+
+ if (len == 0)
+ {
+ data = malloc ( 1 );
+ *data = 0;
+ }
+ else
+ {
+ data = malloc ((unsigned) len + 1);
+
+ if (!data)
+ return (0);
+
+ if (fread (data, (int) sizeof (char), (int) len, file) != len)
+ {
+ free (data);
+ return (0);
+ }
+
+ data[len] = '\0';
+ }
+
+ *stringp = data;
+
+ return (1);
+}
+
+
+static Status
+read_counted_string (FILE *file, unsigned short *countp, char **stringp)
+{
+ unsigned short len;
+ char *data;
+
+ if (!read_short (file, &len))
+ return (0);
+
+ if (len == 0)
+ {
+ data = 0;
+ }
+ else
+ {
+ data = malloc ((unsigned) len);
+
+ if (!data)
+ return (0);
+
+ if (fread (data, (int) sizeof (char), (int) len, file) != len)
+ {
+ free (data);
+ return (0);
+ }
+ }
+
+ *stringp = data;
+ *countp = len;
+
+ return (1);
+}
+
+
+static Status
+write_short (FILE *file, unsigned short s)
+{
+ unsigned char file_short[2];
+
+ file_short[0] = (s & (unsigned) 0xff00) >> 8;
+ file_short[1] = s & 0xff;
+
+ if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
+ return (0);
+
+ return (1);
+}
+
+
+static Status
+write_string (FILE *file, char *string)
+{
+ unsigned short count = strlen (string);
+
+ if (!write_short (file, count))
+ return (0);
+
+ if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
+ return (0);
+
+ return (1);
+}
+
+
+static Status
+write_counted_string (FILE *file, unsigned short count, char *string)
+{
+ if (!write_short (file, count))
+ return (0);
+
+ if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
+ return (0);
+
+ return (1);
+}
diff --git a/dcop/KDE-ICE/connect.c b/dcop/KDE-ICE/connect.c
new file mode 100644
index 000000000..99c947b38
--- /dev/null
+++ b/dcop/KDE-ICE/connect.c
@@ -0,0 +1,547 @@
+/* $XConsortium: connect.c /main/32 1996/12/10 15:58:34 swick $ */
+/******************************************************************************
+
+
+Copyright (c) 1993 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+/* $XFree86: xc/lib/ICE/connect.c,v 3.2.2.2 1998/05/19 14:21:32 dawes Exp $ */
+
+#include "KDE-ICE/ICElib.h"
+#include "KDE-ICE/ICElibint.h"
+#include "KDE-ICE/Xtrans.h"
+#include "globals.h"
+#include <string.h>
+
+static XtransConnInfo ConnectToPeer(char *networkIdsList, char **actualConnectionRet);
+
+#ifndef X_NOT_STDC_ENV
+#define Strstr strstr
+#else
+static char *Strstr(s1, s2)
+ char *s1, *s2;
+{
+ int n1, n2;
+
+ n1 = strlen(s1);
+ n2 = strlen(s2);
+ for ( ; n1 >= n2; s1++, n1--) {
+ if (!strncmp(s1, s2, n2))
+ return s1;
+ }
+ return NULL;
+}
+#endif
+
+IceConn
+IceOpenConnection (networkIdsList, context, mustAuthenticate, majorOpcodeCheck,
+ errorLength, errorStringRet)
+
+char *networkIdsList;
+IcePointer context;
+Bool mustAuthenticate;
+int majorOpcodeCheck;
+int errorLength;
+char *errorStringRet;
+
+{
+ IceConn iceConn;
+ int extra, i, j;
+ int endian;
+ Bool gotReply, ioErrorOccured;
+ unsigned long setup_sequence;
+ iceByteOrderMsg *pByteOrderMsg;
+ iceConnectionSetupMsg *pSetupMsg;
+ char *pData;
+ IceReplyWaitInfo replyWait;
+ _IceReply reply;
+ int authUsableCount;
+ int authUsableFlags[MAX_ICE_AUTH_NAMES];
+ int authIndices[MAX_ICE_AUTH_NAMES];
+
+ if (errorStringRet && errorLength > 0)
+ *errorStringRet = '\0';
+
+ if (networkIdsList == NULL || *networkIdsList == '\0')
+ {
+ strncpy (errorStringRet,
+ "networkIdsList argument is NULL", errorLength);
+ return (NULL);
+ }
+
+ /*
+ * Check to see if we can use a previously created ICE connection.
+ *
+ * If iceConn->want_to_close is True, or iceConn->free_asap is True,
+ * we can not use the iceConn.
+ *
+ * If 'context' is non-NULL, we will only use a previously opened ICE
+ * connection if the specified 'context' is equal to the context
+ * associated with the ICE connection, or if the context associated
+ * with the ICE connection is NULL.
+ *
+ * If 'majorOpcodeCheck' is non-zero, it will contain a protocol major
+ * opcode that we should make sure is not already active on the ICE
+ * connection. Some clients will want two seperate connections for the
+ * same protocol to the same destination client.
+ */
+
+ for (i = 0; i < _IceConnectionCount; i++)
+ {
+ char *strptr;
+ if ((strptr = (char *) Strstr (
+ networkIdsList, _IceConnectionStrings[i])) != NULL)
+ {
+ char ch = *(strptr + strlen (_IceConnectionStrings[i]));
+ if (ch == ',' || ch == '\0')
+ {
+ /*
+ * OK, we found a connection. Make sure we can reuse it.
+ */
+
+ IceConn newIceConn = _IceConnectionObjs[i];
+
+ if (newIceConn->want_to_close || newIceConn->free_asap ||
+ (context && newIceConn->context &&
+ newIceConn->context != context))
+ {
+ /* force a new connection to be created */
+ break;
+ }
+
+ if (majorOpcodeCheck)
+ {
+ for (j = newIceConn->his_min_opcode;
+ j <= newIceConn->his_max_opcode; j++)
+ {
+ if (newIceConn->process_msg_info[
+ j - newIceConn->his_min_opcode].in_use &&
+ newIceConn->process_msg_info[
+ j - newIceConn->his_min_opcode].my_opcode ==
+ majorOpcodeCheck)
+ break;
+ }
+
+ if (j <= newIceConn->his_max_opcode ||
+ (newIceConn->protosetup_to_you &&
+ newIceConn->protosetup_to_you->my_opcode ==
+ majorOpcodeCheck))
+ {
+ /* force a new connection to be created */
+ break;
+ }
+ }
+
+ newIceConn->open_ref_count++;
+ if (context && !newIceConn->context)
+ newIceConn->context = context;
+ return (newIceConn);
+ }
+ }
+ }
+
+ if ((iceConn = (IceConn) malloc (sizeof (struct _IceConn))) == NULL)
+ {
+ strncpy (errorStringRet, "Can't malloc", errorLength);
+ return (NULL);
+ }
+
+
+ /*
+ * Open a network connection with the peer client.
+ */
+
+ if ((iceConn->trans_conn = ConnectToPeer (networkIdsList,
+ &iceConn->connection_string)) == NULL)
+ {
+ free ((char *) iceConn);
+ strncpy (errorStringRet, "Could not open network socket", errorLength);
+ return (NULL);
+ }
+
+ /*
+ * Set close-on-exec so that programs that fork() don't get confused.
+ */
+
+ _kde_IceTransSetOption (iceConn->trans_conn, TRANS_CLOSEONEXEC, 1);
+
+ iceConn->listen_obj = NULL;
+
+ iceConn->connection_status = IceConnectPending;
+ iceConn->io_ok = True;
+ iceConn->dispatch_level = 0;
+ iceConn->context = context;
+ iceConn->my_ice_version_index = 0;
+ iceConn->send_sequence = 0;
+ iceConn->receive_sequence = 0;
+
+ iceConn->vendor = NULL;
+ iceConn->release = NULL;
+ iceConn->outbuf = NULL;
+
+ iceConn->scratch = NULL;
+ iceConn->scratch_size = 0;
+
+ iceConn->process_msg_info = NULL;
+
+ iceConn->connect_to_you = NULL;
+ iceConn->protosetup_to_you = NULL;
+
+ iceConn->connect_to_me = NULL;
+ iceConn->protosetup_to_me = NULL;
+
+ if ((iceConn->inbuf = iceConn->inbufptr =
+ (char *) malloc (ICE_INBUFSIZE)) == NULL)
+ {
+ _IceFreeConnection (iceConn);
+ strncpy (errorStringRet, "Can't malloc", errorLength);
+ return (NULL);
+ }
+ memset (iceConn->inbuf, 0, ICE_INBUFSIZE);
+
+ iceConn->inbufmax = iceConn->inbuf + ICE_INBUFSIZE;
+
+ if ((iceConn->outbuf = iceConn->outbufptr =
+ (char *) malloc (ICE_OUTBUFSIZE)) == NULL)
+ {
+ _IceFreeConnection (iceConn);
+ strncpy (errorStringRet, "Can't malloc", errorLength);
+ return (NULL);
+ }
+ memset (iceConn->outbuf, 0, ICE_OUTBUFSIZE);
+
+ iceConn->outbufmax = iceConn->outbuf + ICE_OUTBUFSIZE;
+
+ iceConn->open_ref_count = 1;
+ iceConn->proto_ref_count = 0;
+
+ iceConn->skip_want_to_close = False;
+ iceConn->want_to_close = False;
+ iceConn->free_asap = False;
+
+ iceConn->saved_reply_waits = NULL;
+ iceConn->ping_waits = NULL;
+
+ iceConn->connect_to_you = (_IceConnectToYouInfo *) malloc (
+ sizeof (_IceConnectToYouInfo));
+ iceConn->connect_to_you->auth_active = 0;
+
+ /*
+ * Send our byte order.
+ */
+
+ IceGetHeader (iceConn, 0, ICE_ByteOrder,
+ SIZEOF (iceByteOrderMsg), iceByteOrderMsg, pByteOrderMsg);
+
+ endian = 1;
+ if (*(char *) &endian)
+ pByteOrderMsg->byteOrder = IceLSBfirst;
+ else
+ pByteOrderMsg->byteOrder = IceMSBfirst;
+
+ IceFlush (iceConn);
+
+
+ /*
+ * Now read the ByteOrder message from the other client.
+ * iceConn->swap should be set to the appropriate boolean
+ * value after the call to IceProcessMessages.
+ */
+
+ iceConn->waiting_for_byteorder = True;
+
+ ioErrorOccured = False;
+ while (iceConn->waiting_for_byteorder == True && !ioErrorOccured)
+ {
+ ioErrorOccured = (IceProcessMessages (
+ iceConn, NULL, NULL) == IceProcessMessagesIOError);
+ }
+
+ if (ioErrorOccured)
+ {
+ _IceFreeConnection (iceConn);
+ strncpy (errorStringRet, "IO error occurred opening connection",
+ errorLength);
+ return (NULL);
+ }
+
+ if (iceConn->connection_status == IceConnectRejected)
+ {
+ /*
+ * We failed to get the required ByteOrder message.
+ */
+
+ _IceFreeConnection (iceConn);
+ strncpy (errorStringRet,
+ "Internal error - did not receive the expected ByteOrder message",
+ errorLength);
+ return (NULL);
+ }
+
+
+ /*
+ * Determine which authentication methods are available for
+ * the Connection Setup authentication.
+ */
+
+ _IceGetPoValidAuthIndices (
+ "ICE", iceConn->connection_string,
+ _IceAuthCount, _IceAuthNames, &authUsableCount, authIndices);
+
+ for (i = 0; i < _IceAuthCount; i++)
+ {
+ authUsableFlags[i] = 0;
+ for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++)
+ authUsableFlags[i] = (authIndices[j] == i);
+ }
+
+
+ /*
+ * Now send a Connection Setup message.
+ */
+
+ extra = STRING_BYTES (IceVendorString) + STRING_BYTES (IceReleaseString);
+
+ for (i = 0; i < _IceAuthCount; i++)
+ if (authUsableFlags[i])
+ {
+ extra += STRING_BYTES (_IceAuthNames[i]);
+ }
+
+ extra += (_IceVersionCount * 4);
+
+ IceGetHeaderExtra (iceConn, 0, ICE_ConnectionSetup,
+ SIZEOF (iceConnectionSetupMsg), WORD64COUNT (extra),
+ iceConnectionSetupMsg, pSetupMsg, pData);
+
+ setup_sequence = iceConn->send_sequence;
+
+ pSetupMsg->versionCount = _IceVersionCount;
+ pSetupMsg->authCount = authUsableCount;
+ pSetupMsg->mustAuthenticate = mustAuthenticate;
+
+ STORE_STRING (pData, IceVendorString);
+ STORE_STRING (pData, IceReleaseString);
+
+ for (i = 0; i < _IceAuthCount; i++)
+ if (authUsableFlags[i])
+ {
+ STORE_STRING (pData, _IceAuthNames[i]);
+ }
+
+ for (i = 0; i < _IceVersionCount; i++)
+ {
+ STORE_CARD16 (pData, _IceVersions[i].major_version);
+ STORE_CARD16 (pData, _IceVersions[i].minor_version);
+ }
+
+ IceFlush (iceConn);
+
+
+ /*
+ * Process messages until we get a Connection Reply or an Error Message.
+ * Authentication will take place behind the scenes.
+ */
+
+ replyWait.sequence_of_request = setup_sequence;
+ replyWait.major_opcode_of_request = 0;
+ replyWait.minor_opcode_of_request = ICE_ConnectionSetup;
+ replyWait.reply = (IcePointer) &reply;
+
+ gotReply = False;
+ ioErrorOccured = False;
+
+ while (!gotReply && !ioErrorOccured)
+ {
+ ioErrorOccured = (IceProcessMessages (
+ iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError);
+
+ if (ioErrorOccured)
+ {
+ strncpy (errorStringRet, "IO error occurred opening connection",
+ errorLength);
+ _IceFreeConnection (iceConn);
+ iceConn = NULL;
+ }
+ else if (gotReply)
+ {
+ if (reply.type == ICE_CONNECTION_REPLY)
+ {
+ if (reply.connection_reply.version_index >= _IceVersionCount)
+ {
+ strncpy (errorStringRet,
+ "Got a bad version index in the Connection Reply",
+ errorLength);
+
+ free (reply.connection_reply.vendor);
+ free (reply.connection_reply.release);
+ _IceFreeConnection (iceConn);
+ iceConn = NULL;
+ }
+ else
+ {
+ iceConn->my_ice_version_index =
+ reply.connection_reply.version_index;
+ iceConn->vendor = reply.connection_reply.vendor;
+ iceConn->release = reply.connection_reply.release;
+
+ _IceConnectionObjs[_IceConnectionCount] = iceConn;
+ _IceConnectionStrings[_IceConnectionCount] =
+ iceConn->connection_string;
+ _IceConnectionCount++;
+
+ free ((char *) iceConn->connect_to_you);
+ iceConn->connect_to_you = NULL;
+
+ iceConn->connection_status = IceConnectAccepted;
+ }
+ }
+ else /* reply.type == ICE_CONNECTION_ERROR */
+ {
+ /* Connection failed */
+
+ strncpy (errorStringRet, reply.connection_error.error_message,
+ errorLength);
+
+ free (reply.connection_error.error_message);
+
+ _IceFreeConnection (iceConn);
+ iceConn = NULL;
+ }
+ }
+ }
+
+ if (iceConn && _IceWatchProcs)
+ {
+#ifdef MINIX
+ _kde_IceTransSetOption(iceConn->trans_conn, TRANS_NONBLOCKING, 1);
+#endif
+ /*
+ * Notify the watch procedures that an iceConn was opened.
+ */
+
+ _IceConnectionOpened (iceConn);
+ }
+
+ return (iceConn);
+}
+
+
+
+IcePointer
+IceGetConnectionContext (iceConn)
+
+IceConn iceConn;
+
+{
+ return (iceConn->context);
+}
+
+
+
+/* ------------------------------------------------------------------------- *
+ * local routines *
+ * ------------------------------------------------------------------------- */
+
+#define ICE_CONNECTION_RETRIES 5
+
+
+static XtransConnInfo
+ConnectToPeer (char *networkIdsList, char **actualConnectionRet)
+{
+ char address[256];
+ char *ptr, *endptr, *delim;
+ int madeConnection = 0;
+ int len, retry;
+ int connect_stat;
+ XtransConnInfo trans_conn = NULL;
+
+ *actualConnectionRet = NULL;
+
+ ptr = networkIdsList;
+ endptr = networkIdsList + strlen (networkIdsList);
+
+ while (ptr < endptr && !madeConnection)
+ {
+ if ((delim = (char *) strchr (ptr, ',')) == NULL)
+ delim = endptr;
+
+ len = delim - ptr;
+ if (len > (int) sizeof(address) - 1)
+ len = sizeof(address) - 1;
+ strncpy (address, ptr, len);
+ address[len] = '\0';
+
+ ptr = delim + 1;
+
+ for (retry = ICE_CONNECTION_RETRIES; retry >= 0; retry--)
+ {
+ if ((trans_conn = (XtransConnInfo)_kde_IceTransOpenCOTSClient (address)) == NULL)
+ {
+ break;
+ }
+
+ if ((connect_stat = _kde_IceTransConnect (trans_conn, address)) < 0)
+ {
+ _kde_IceTransClose (trans_conn);
+
+ if (connect_stat == TRANS_TRY_CONNECT_AGAIN)
+ {
+ sleep(1);
+ continue;
+ }
+ else
+ break;
+ }
+ else
+ {
+ madeConnection = 1;
+ break;
+ }
+ }
+ }
+
+
+ if (madeConnection)
+ {
+ /*
+ * We need to return the actual network connection string
+ */
+
+ *actualConnectionRet = (char *) malloc (strlen (address) + 1);
+ strcpy (*actualConnectionRet, address);
+
+
+ /*
+ * Return the file descriptor
+ */
+
+ return (trans_conn);
+ }
+ else
+ {
+ return (NULL);
+ }
+}
diff --git a/dcop/KDE-ICE/error.c b/dcop/KDE-ICE/error.c
new file mode 100644
index 000000000..c187d7cd7
--- /dev/null
+++ b/dcop/KDE-ICE/error.c
@@ -0,0 +1,650 @@
+/* $XConsortium: error.c /main/16 1995/09/15 13:54:01 mor $ */
+/******************************************************************************
+
+
+Copyright (c) 1993 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include "KDE-ICE/ICElib.h"
+#include "KDE-ICE/ICElibint.h"
+#include "KDE-ICE/globals.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef X_NOT_STDC_ENV
+extern int errno;
+#endif
+
+
+void
+_IceErrorBadMinor (iceConn, majorOpcode, offendingMinor, severity)
+
+IceConn iceConn;
+int majorOpcode;
+int offendingMinor;
+int severity;
+
+{
+ IceErrorHeader (iceConn,
+ majorOpcode, offendingMinor,
+ iceConn->receive_sequence,
+ severity,
+ IceBadMinor,
+ 0);
+
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorBadState (iceConn, majorOpcode, offendingMinor, severity)
+
+IceConn iceConn;
+int majorOpcode;
+int offendingMinor;
+int severity;
+
+{
+ IceErrorHeader (iceConn,
+ majorOpcode, offendingMinor,
+ iceConn->receive_sequence,
+ severity,
+ IceBadState,
+ 0);
+
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorBadLength (iceConn, majorOpcode, offendingMinor, severity)
+
+IceConn iceConn;
+int majorOpcode;
+int offendingMinor;
+int severity;
+
+{
+ IceErrorHeader (iceConn,
+ majorOpcode, offendingMinor,
+ iceConn->receive_sequence,
+ severity,
+ IceBadLength,
+ 0);
+
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorBadValue (iceConn, majorOpcode, offendingMinor, offset, length, value)
+
+IceConn iceConn;
+int majorOpcode;
+int offendingMinor;
+int offset;
+int length; /* in bytes */
+IcePointer value;
+
+{
+ IceErrorHeader (iceConn,
+ majorOpcode, offendingMinor,
+ iceConn->receive_sequence,
+ IceCanContinue,
+ IceBadValue,
+ WORD64COUNT (8 + length));
+
+ IceWriteData32 (iceConn, 4, &offset);
+ IceWriteData32 (iceConn, 4, &length);
+ IceWriteData (iceConn, length, (char *) value);
+
+ if (PAD64 (length))
+ IceWritePad (iceConn, PAD64 (length));
+
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorNoAuthentication (iceConn, offendingMinor)
+
+IceConn iceConn;
+int offendingMinor;
+
+{
+ int severity = (offendingMinor == ICE_ConnectionSetup) ?
+ IceFatalToConnection : IceFatalToProtocol;
+
+ IceErrorHeader (iceConn,
+ 0, offendingMinor,
+ iceConn->receive_sequence,
+ severity,
+ IceNoAuth,
+ 0);
+
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorNoVersion (iceConn, offendingMinor)
+
+IceConn iceConn;
+int offendingMinor;
+
+{
+ int severity = (offendingMinor == ICE_ConnectionSetup) ?
+ IceFatalToConnection : IceFatalToProtocol;
+
+ IceErrorHeader (iceConn,
+ 0, offendingMinor,
+ iceConn->receive_sequence,
+ severity,
+ IceNoVersion,
+ 0);
+
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorSetupFailed (iceConn, offendingMinor, reason)
+
+IceConn iceConn;
+int offendingMinor;
+const char *reason;
+
+{
+ char *pBuf, *pStart;
+ int bytes;
+ int severity = (offendingMinor == ICE_ConnectionSetup) ?
+ IceFatalToConnection : IceFatalToProtocol;
+
+ if (!reason)
+ reason = "";
+ bytes = STRING_BYTES (reason);
+
+ IceErrorHeader (iceConn,
+ 0, offendingMinor,
+ iceConn->receive_sequence,
+ severity,
+ IceSetupFailed,
+ WORD64COUNT (bytes));
+
+ pBuf = pStart = IceAllocScratch (iceConn, PADDED_BYTES64 (bytes));
+ STORE_STRING (pBuf, reason);
+
+ IceWriteData (iceConn, PADDED_BYTES64 (bytes), pStart);
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorAuthenticationRejected (iceConn, offendingMinor, reason)
+
+IceConn iceConn;
+int offendingMinor;
+const char *reason;
+
+{
+ char *pBuf, *pStart;
+ int bytes;
+
+ if (!reason)
+ reason = "";
+ bytes = STRING_BYTES (reason);
+
+ IceErrorHeader (iceConn,
+ 0, offendingMinor,
+ iceConn->receive_sequence,
+ IceFatalToProtocol,
+ IceAuthRejected,
+ WORD64COUNT (bytes));
+
+ pBuf = pStart = IceAllocScratch (iceConn, PADDED_BYTES64 (bytes));
+ STORE_STRING (pBuf, reason);
+
+ IceWriteData (iceConn, PADDED_BYTES64 (bytes), pStart);
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorAuthenticationFailed (iceConn, offendingMinor, reason)
+
+IceConn iceConn;
+int offendingMinor;
+const char *reason;
+
+{
+ char *pBuf, *pStart;
+ int bytes;
+
+ if (!reason)
+ reason = "";
+ bytes = STRING_BYTES (reason);
+
+ IceErrorHeader (iceConn,
+ 0, offendingMinor,
+ iceConn->receive_sequence,
+ IceFatalToProtocol,
+ IceAuthFailed,
+ WORD64COUNT (bytes));
+
+ pBuf = pStart = IceAllocScratch (iceConn, PADDED_BYTES64 (bytes));
+ STORE_STRING (pBuf, reason);
+
+ IceWriteData (iceConn, PADDED_BYTES64 (bytes), pStart);
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorProtocolDuplicate (iceConn, protocolName)
+
+IceConn iceConn;
+const char *protocolName;
+
+{
+ char *pBuf, *pStart;
+ int bytes;
+
+ if (!protocolName)
+ protocolName = "";
+ bytes = STRING_BYTES (protocolName);
+
+ IceErrorHeader (iceConn,
+ 0, ICE_ProtocolSetup,
+ iceConn->receive_sequence,
+ IceFatalToProtocol,
+ IceProtocolDuplicate,
+ WORD64COUNT (bytes));
+
+ pBuf = pStart = IceAllocScratch (iceConn, PADDED_BYTES64 (bytes));
+ STORE_STRING (pBuf, protocolName);
+
+ IceWriteData (iceConn, PADDED_BYTES64 (bytes), pStart);
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorMajorOpcodeDuplicate (iceConn, majorOpcode)
+
+IceConn iceConn;
+int majorOpcode;
+
+{
+ char mOp[8];
+ mOp[0] = (char) majorOpcode;
+ mOp[1] = mOp[2] = mOp[3] = mOp[4] = mOp[5] = mOp[6] = mOp[7] = 0;
+
+ IceErrorHeader (iceConn,
+ 0, ICE_ProtocolSetup,
+ iceConn->receive_sequence,
+ IceFatalToProtocol,
+ IceMajorOpcodeDuplicate,
+ 1 /* length */);
+
+ IceWriteData (iceConn, 8, mOp);
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorUnknownProtocol (iceConn, protocolName)
+
+IceConn iceConn;
+const char *protocolName;
+
+{
+ char *pBuf, *pStart;
+ int bytes;
+
+ if (!protocolName)
+ protocolName = "";
+ bytes = STRING_BYTES (protocolName);
+
+ IceErrorHeader (iceConn,
+ 0, ICE_ProtocolSetup,
+ iceConn->receive_sequence,
+ IceFatalToProtocol,
+ IceUnknownProtocol,
+ WORD64COUNT (bytes));
+
+ pBuf = pStart = IceAllocScratch (iceConn, PADDED_BYTES64 (bytes));
+ STORE_STRING (pBuf, protocolName);
+
+ IceWriteData (iceConn, PADDED_BYTES64 (bytes), pStart);
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorBadMajor (iceConn, offendingMajor, offendingMinor, severity)
+
+IceConn iceConn;
+int offendingMajor;
+int offendingMinor;
+int severity;
+
+{
+ char maj[8];
+ maj[0] = (char) offendingMajor;
+ maj[1] = maj[2] = maj[3] = maj[4] = maj[5] = maj[6] = maj[7] = 0;
+
+ IceErrorHeader (iceConn,
+ 0, offendingMinor,
+ iceConn->receive_sequence,
+ severity,
+ IceBadMajor,
+ 1 /* length */);
+
+ IceWriteData (iceConn, 8, maj);
+ IceFlush (iceConn);
+}
+
+
+
+/*
+ * Default error handler.
+ */
+
+void
+_IceDefaultErrorHandler (iceConn, swap,
+ offendingMinorOpcode, offendingSequence, errorClass, severity, values)
+
+IceConn iceConn;
+Bool swap;
+int offendingMinorOpcode;
+unsigned long offendingSequence;
+int errorClass;
+int severity;
+IcePointer values;
+
+{
+ char *str;
+ char *pData = (char *) values;
+ (void)iceConn;/*unused*/
+
+ switch (offendingMinorOpcode)
+ {
+ case ICE_ConnectionSetup:
+ str = (char *)"ConnectionSetup";
+ break;
+ case ICE_AuthRequired:
+ str = (char *)"AuthRequired";
+ break;
+ case ICE_AuthReply:
+ str = (char *)"AuthReply";
+ break;
+ case ICE_AuthNextPhase:
+ str = (char *)"AuthNextPhase";
+ break;
+ case ICE_ConnectionReply:
+ str = (char *)"ConnectionReply";
+ break;
+ case ICE_ProtocolSetup:
+ str = (char *)"ProtocolSetup";
+ break;
+ case ICE_ProtocolReply:
+ str = (char *)"ProtocolReply";
+ break;
+ case ICE_Ping:
+ str = (char *)"Ping";
+ break;
+ case ICE_PingReply:
+ str = (char *)"PingReply";
+ break;
+ case ICE_WantToClose:
+ str = (char *)"WantToClose";
+ break;
+ case ICE_NoClose:
+ str = (char *)"NoClose";
+ break;
+ default:
+ str = (char *)"";
+ }
+
+ fprintf (stderr, "\n");
+
+ fprintf (stderr, "ICE error: Offending minor opcode = %d (%s)\n",
+ offendingMinorOpcode, str);
+
+ fprintf (stderr, " Offending sequence number = %ld\n",
+ offendingSequence);
+
+ switch (errorClass)
+ {
+ case IceBadMinor:
+ str = (char *)"BadMinor";
+ break;
+ case IceBadState:
+ str = (char *)"BadState";
+ break;
+ case IceBadLength:
+ str = (char *)"BadLength";
+ break;
+ case IceBadValue:
+ str = (char *)"BadValue";
+ break;
+ case IceBadMajor:
+ str = (char *)"BadMajor";
+ break;
+ case IceNoAuth:
+ str = (char *)"NoAuthentication";
+ break;
+ case IceNoVersion:
+ str = (char *)"NoVersion";
+ break;
+ case IceSetupFailed:
+ str = (char *)"SetupFailed";
+ break;
+ case IceAuthRejected:
+ str = (char *)"AuthenticationRejected";
+ break;
+ case IceAuthFailed:
+ str = (char *)"AuthenticationFailed";
+ break;
+ case IceProtocolDuplicate:
+ str = (char *)"ProtocolDuplicate";
+ break;
+ case IceMajorOpcodeDuplicate:
+ str = (char *)"MajorOpcodeDuplicate";
+ break;
+ case IceUnknownProtocol:
+ str = (char *)"UnknownProtocol";
+ break;
+ default:
+ str = (char *)"???";
+ }
+
+ fprintf (stderr, " Error class = %s\n", str);
+
+ if (severity == IceCanContinue)
+ str = (char *)"CanContinue";
+ else if (severity == IceFatalToProtocol)
+ str = (char *)"FatalToProtocol";
+ else if (severity == IceFatalToConnection)
+ str = (char *)"FatalToConnection";
+ else
+ str = (char *)"???";
+
+ fprintf (stderr, " Severity = %s\n", str);
+
+ switch (errorClass)
+ {
+ case IceBadValue:
+ {
+ int offset, length, val;
+
+ EXTRACT_CARD32 (pData, swap, offset);
+ EXTRACT_CARD32 (pData, swap, length);
+
+ fprintf (stderr,
+ " BadValue Offset = %d\n", offset);
+ fprintf (stderr,
+ " BadValue Length = %d\n", length);
+
+ if (length <= 4)
+ {
+ if (length == 1)
+ val = (int) *pData;
+ else if (length == 2)
+ {
+ EXTRACT_CARD16 (pData, swap, val);
+ }
+ else
+ {
+ EXTRACT_CARD32 (pData, swap, val);
+ }
+
+ fprintf (stderr,
+ " BadValue = %d\n", val);
+ }
+ break;
+ }
+
+ case IceBadMajor:
+
+ fprintf (stderr, "Major opcode : %d\n", (int) *pData);
+ break;
+
+ case IceSetupFailed:
+
+ EXTRACT_STRING (pData, swap, str);
+ fprintf (stderr, "Reason : %s\n", str);
+ break;
+
+ case IceAuthRejected:
+
+ EXTRACT_STRING (pData, swap, str);
+ fprintf (stderr, "Reason : %s\n", str);
+ break;
+
+ case IceAuthFailed:
+
+ EXTRACT_STRING (pData, swap, str);
+ fprintf (stderr, "Reason : %s\n", str);
+ break;
+
+ case IceProtocolDuplicate:
+
+ EXTRACT_STRING (pData, swap, str);
+ fprintf (stderr, "Protocol name : %s\n", str);
+ break;
+
+ case IceMajorOpcodeDuplicate:
+
+ fprintf (stderr, "Major opcode : %d\n", (int) *pData);
+ break;
+
+ case IceUnknownProtocol:
+
+ EXTRACT_STRING (pData, swap, str);
+ fprintf (stderr, "Protocol name : %s\n", str);
+ break;
+
+ default:
+ break;
+ }
+
+ fprintf (stderr, "\n");
+
+ if (severity != IceCanContinue)
+ exit (1);
+}
+
+
+
+/*
+ * This procedure sets the ICE error handler to be the specified
+ * routine. If NULL is passed in the default error handler is restored.
+ * The function's return value is the previous error handler.
+ */
+
+IceErrorHandler
+IceSetErrorHandler (handler)
+
+IceErrorHandler handler;
+
+{
+ IceErrorHandler oldHandler = _IceErrorHandler;
+
+ if (handler != NULL)
+ _IceErrorHandler = handler;
+ else
+ _IceErrorHandler = _IceDefaultErrorHandler;
+
+ return (oldHandler);
+}
+
+
+
+/*
+ * Default IO error handler.
+ */
+
+void
+_IceDefaultIOErrorHandler (iceConn)
+
+IceConn iceConn;
+
+{
+ (void)iceConn;/*unused*/
+ fprintf (stderr,
+ "ICE default IO error handler doing an exit(), pid = %d, errno = %d\n",
+ getpid(), errno);
+
+ exit (1);
+}
+
+
+
+/*
+ * This procedure sets the ICE fatal I/O error handler to be the
+ * specified routine. If NULL is passed in the default error
+ * handler is restored. The function's return value is the
+ * previous error handler.
+ */
+
+IceIOErrorHandler
+IceSetIOErrorHandler (handler)
+
+IceIOErrorHandler handler;
+
+{
+ IceIOErrorHandler oldHandler = _IceIOErrorHandler;
+
+ if (handler != NULL)
+ _IceIOErrorHandler = handler;
+ else
+ _IceIOErrorHandler = _IceDefaultIOErrorHandler;
+
+ return (oldHandler);
+}
diff --git a/dcop/KDE-ICE/getauth.c b/dcop/KDE-ICE/getauth.c
new file mode 100644
index 000000000..8699d6563
--- /dev/null
+++ b/dcop/KDE-ICE/getauth.c
@@ -0,0 +1,269 @@
+/* $XConsortium: getauth.c,v 1.8 94/04/17 20:15:33 mor Exp $ */
+/******************************************************************************
+
+
+Copyright (c) 1993 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include "KDE-ICE/ICElib.h"
+#include "KDE-ICE/ICElibint.h"
+#include "KDE-ICE/ICEutil.h"
+#include "KDE-ICE/globals.h"
+#include <string.h>
+#ifdef _AIX
+#include <sys/access.h>
+#endif
+
+static Bool auth_valid (const char *auth_name, int num_auth_names, const char **auth_names, int *index_ret);
+
+extern IceAuthDataEntry _IcePaAuthDataEntries[];
+
+
+/*
+ * The functions in this file are not a standard part of ICElib.
+ *
+ * The sample implementation uses an .ICEauthority to manipulate
+ * authentication data.
+ *
+ * For the client that initiates a Protocol Setup, we look in the
+ * .ICEauthority file to get the data.
+ *
+ * For the client accepting the Protocol Setup, we get the data
+ * from an in-memory database of authentication data (set by the
+ * application calling IceSetPaAuthData). We have to get the data
+ * from memory because getting it directly from the .ICEauthority
+ * file is not secure - someone can just modify the contents of the
+ * .ICEauthority file behind our back.
+ */
+
+void
+_IceGetPoAuthData (protocolName, networkId, authName,
+ authDataLenRet, authDataRet)
+
+const char *protocolName;
+const char *networkId;
+const char *authName;
+unsigned short *authDataLenRet;
+char **authDataRet;
+
+{
+ IceAuthFileEntry *entry;
+
+ entry = IceGetAuthFileEntry (protocolName, networkId, authName);
+
+ if (entry)
+ {
+ *authDataLenRet = entry->auth_data_length;
+
+ if ((*authDataRet = (char *) malloc (entry->auth_data_length)) != NULL)
+ memcpy (*authDataRet, entry->auth_data, entry->auth_data_length);
+ }
+ else
+ {
+ *authDataLenRet = 0;
+ *authDataRet = NULL;
+ }
+
+ IceFreeAuthFileEntry (entry);
+}
+
+
+
+void
+_IceGetPaAuthData (protocolName, networkId, authName,
+ authDataLenRet, authDataRet)
+
+const char *protocolName;
+const char *networkId;
+const char *authName;
+unsigned short *authDataLenRet;
+char **authDataRet;
+
+{
+ IceAuthDataEntry *entry = NULL;
+ int found = 0;
+ int i;
+
+ for (i = 0; i < _IcePaAuthDataEntryCount && !found; i++)
+ {
+ entry = &_IcePaAuthDataEntries[i];
+
+ found =
+ strcmp (protocolName, entry->protocol_name) == 0 &&
+ strcmp (networkId, entry->network_id) == 0 &&
+ strcmp (authName, entry->auth_name) == 0;
+ }
+
+ if (found)
+ {
+ *authDataLenRet = entry->auth_data_length;
+
+ if ((*authDataRet = (char *) malloc (entry->auth_data_length)) != NULL)
+ memcpy (*authDataRet, entry->auth_data, entry->auth_data_length);
+ }
+ else
+ {
+ *authDataLenRet = 0;
+ *authDataRet = NULL;
+ }
+}
+
+
+
+void
+_IceGetPoValidAuthIndices (protocol_name, network_id,
+ num_auth_names, auth_names, num_indices_ret, indices_ret)
+
+const char *protocol_name;
+const char *network_id;
+int num_auth_names;
+const char **auth_names;
+int *num_indices_ret;
+int *indices_ret; /* in/out arg */
+
+{
+ FILE *auth_file;
+ char *filename;
+ IceAuthFileEntry *entry;
+ int index_ret, i;
+
+ *num_indices_ret = 0;
+
+ if (!(filename = IceAuthFileName ()))
+ return;
+
+ if (access (filename, R_OK) != 0) /* checks REAL id */
+ return;
+
+ if (!(auth_file = fopen (filename, "rb")))
+ return;
+
+ for (;;)
+ {
+ if (!(entry = IceReadAuthFileEntry (auth_file)))
+ break;
+
+ if (strcmp (protocol_name, entry->protocol_name) == 0 &&
+ strcmp (network_id, entry->network_id) == 0 &&
+ auth_valid (entry->auth_name, num_auth_names,
+ auth_names, &index_ret))
+ {
+ /*
+ * Make sure we didn't store this index already.
+ */
+
+ for (i = 0; i < *num_indices_ret; i++)
+ if (index_ret == indices_ret[i])
+ break;
+
+ if (i >= *num_indices_ret)
+ {
+ indices_ret[*num_indices_ret] = index_ret;
+ *num_indices_ret += 1;
+ }
+ }
+
+ IceFreeAuthFileEntry (entry);
+ }
+
+ fclose (auth_file);
+}
+
+
+
+void
+_IceGetPaValidAuthIndices (protocol_name, network_id,
+ num_auth_names, auth_names, num_indices_ret, indices_ret)
+
+const char *protocol_name;
+const char *network_id;
+int num_auth_names;
+const char **auth_names;
+int *num_indices_ret;
+int *indices_ret; /* in/out arg */
+
+{
+ int index_ret;
+ int i, j;
+ IceAuthDataEntry *entry;
+
+ *num_indices_ret = 0;
+
+ for (i = 0; i < _IcePaAuthDataEntryCount; i++)
+ {
+ entry = &_IcePaAuthDataEntries[i];
+
+ if (strcmp (protocol_name, entry->protocol_name) == 0 &&
+ strcmp (network_id, entry->network_id) == 0 &&
+ auth_valid (entry->auth_name, num_auth_names,
+ auth_names, &index_ret))
+ {
+ /*
+ * Make sure we didn't store this index already.
+ */
+
+ for (j = 0; j < *num_indices_ret; j++)
+ if (index_ret == indices_ret[j])
+ break;
+
+ if (j >= *num_indices_ret)
+ {
+ indices_ret[*num_indices_ret] = index_ret;
+ *num_indices_ret += 1;
+ }
+ }
+ }
+}
+
+
+
+/*
+ * local routines
+ */
+
+static Bool
+auth_valid (const char *auth_name, int num_auth_names, const char **auth_names, int *index_ret)
+{
+ /*
+ * Check if auth_name is in auth_names. Return index.
+ */
+
+ int i;
+
+ for (i = 0; i < num_auth_names; i++)
+ if (strcmp (auth_name, auth_names[i]) == 0)
+ {
+ break;
+ }
+
+ if (i < num_auth_names)
+ {
+ *index_ret = i;
+ return (1);
+ }
+ else
+ return (0);
+}
diff --git a/dcop/KDE-ICE/globals.c b/dcop/KDE-ICE/globals.c
new file mode 100644
index 000000000..84114918b
--- /dev/null
+++ b/dcop/KDE-ICE/globals.c
@@ -0,0 +1,56 @@
+/* $XConsortium: globals.h,v 1.14 94/04/17 20:15:33 mor Exp $ */
+/******************************************************************************
+
+
+Copyright (c) 1993 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+/* $XFree86: xc/lib/ICE/globals.h,v 1.1.1.1.12.2 1998/10/19 20:57:04 hohndel Exp $ */
+
+#include "KDE-ICE/ICElib.h"
+#include "KDE-ICE/ICElibint.h"
+#include "KDE-ICE/globals.h"
+
+IceConn _IceConnectionObjs[256];
+char *_IceConnectionStrings[256];
+int _IceConnectionCount = 0;
+
+_IceProtocol _IceProtocols[255];
+int _IceLastMajorOpcode = 0;
+
+int _IceAuthCount = 1;
+const char *_IceAuthNames[] = {"MIT-MAGIC-COOKIE-1"};
+IcePoAuthProc _IcePoAuthProcs[] = {_IcePoMagicCookie1Proc};
+IcePaAuthProc _IcePaAuthProcs[] = {_IcePaMagicCookie1Proc};
+
+int _IceVersionCount = 1;
+_IceVersion _IceVersions[] = {
+ {IceProtoMajor, IceProtoMinor, _IceProcessCoreMessage}};
+
+_IceWatchProc *_IceWatchProcs = NULL;
+
+IceErrorHandler _IceErrorHandler = _IceDefaultErrorHandler;
+IceIOErrorHandler _IceIOErrorHandler = _IceDefaultIOErrorHandler;
+IceWriteHandler _IceWriteHandler = _IceWrite;
diff --git a/dcop/KDE-ICE/globals.h b/dcop/KDE-ICE/globals.h
new file mode 100644
index 000000000..814e8980c
--- /dev/null
+++ b/dcop/KDE-ICE/globals.h
@@ -0,0 +1,146 @@
+/* $XConsortium: globals.h,v 1.14 94/04/17 20:15:33 mor Exp $ */
+/******************************************************************************
+
+
+Copyright (c) 1993 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+/* $XFree86: xc/lib/ICE/globals.h,v 1.1.1.1.12.2 1998/10/19 20:57:04 hohndel Exp $ */
+
+#include "KDE-ICE/ICElib.h"
+#include "KDE-ICE/ICElibint.h"
+#include "KDE-ICE/ICEutil.h"
+
+#define _IceDefaultErrorHandler _kde_IceDefaultErrorHandler
+
+extern void _IceDefaultErrorHandler (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ Bool /* swap */,
+ int /* offendingMinorOpcode */,
+ unsigned long /* offendingSequence */,
+ int /* errorClass */,
+ int /* severity */,
+ IcePointer /* values */
+#endif
+);
+
+#define _IceDefaultIOErrorHandler _kde_IceDefaultIOErrorHandler
+
+extern void _IceDefaultIOErrorHandler (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+#define _IcePoMagicCookie1Proc _kde_IcePoMagicCookie1Proc
+
+extern IcePoAuthStatus _IcePoMagicCookie1Proc (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ IcePointer * /* authStatePtr */,
+ Bool /* cleanUp */,
+ Bool /* swap */,
+ int /* authDataLen */,
+ IcePointer /* authData */,
+ int * /* replyDataLenRet */,
+ IcePointer * /* replyDataRet */,
+ char ** /* errorStringRet */
+#endif
+);
+
+#define _IcePaMagicCookie1Proc _kde_IcePaMagicCookie1Proc
+
+extern IcePaAuthStatus _IcePaMagicCookie1Proc (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ IcePointer * /* authStatePtr */,
+ Bool /* swap */,
+ int /* authDataLen */,
+ IcePointer /* authData */,
+ int * /* replyDataLenRet */,
+ IcePointer * /* replyDataRet */,
+ char ** /* errorStringRet */
+#endif
+);
+
+#define _IceProcessCoreMessage _kde_IceProcessCoreMessage
+
+extern void _IceProcessCoreMessage (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* opcode */,
+ unsigned long /* length */,
+ Bool /* swap */,
+ IceReplyWaitInfo * /* replyWait */,
+ Bool * /* replyReadyRet */,
+ Bool * /* connectionClosedRet */
+#endif
+);
+
+#define _IceConnectionObjs _kde_IceConnectionObjs
+#define _IceConnectionStrings _kde_IceConnectionStrings
+#define _IceConnectionCount _kde_IceConnectionCount
+
+extern IceConn _IceConnectionObjs[256];
+extern char *_IceConnectionStrings[256];
+extern int _IceConnectionCount;
+
+#define _IceProtocols _kde_IceProtocols
+#define _IceLastMajorOpcode _kde_IceLastMajorOpcode
+
+extern _IceProtocol _IceProtocols[255];
+extern int _IceLastMajorOpcode;
+
+#define _IceAuthCount _kde_IceAuthCount
+#define _IceAuthNames _kde_IceAuthNames
+#define _IcePoAuthProcs _kde_IcePoAuthProcs
+#define _IcePaAuthProcs _kde_IcePaAuthProcs
+
+extern int _IceAuthCount;
+extern const char *_IceAuthNames[];
+extern IcePoAuthProc _IcePoAuthProcs[];
+extern IcePaAuthProc _IcePaAuthProcs[];
+
+#define _IceVersionCount _kde_IceVersionCount
+#define _IceVersions _kde_IceVersions
+#define _IceWatchProcs _kde_IceWatchProcs
+
+extern int _IceVersionCount;
+extern _IceVersion _IceVersions[];
+
+extern _IceWatchProc *_IceWatchProcs;
+
+#define _IceErrorHandler _kde_IceErrorHandler
+#define _IceIOErrorHandler _kde_IceIOErrorHandler
+
+extern IceErrorHandler _IceErrorHandler;
+extern IceIOErrorHandler _IceIOErrorHandler;
+
+#define _IcePaAuthDataEntryCount _kde_IcePaAuthDataEntryCount
+#define _IcePaAuthDataEntries _kde_IcePaAuthDataEntries
+
+extern int _IcePaAuthDataEntryCount;
+extern IceAuthDataEntry _IcePaAuthDataEntries[];
diff --git a/dcop/KDE-ICE/iceauth.c b/dcop/KDE-ICE/iceauth.c
new file mode 100644
index 000000000..72297ceb5
--- /dev/null
+++ b/dcop/KDE-ICE/iceauth.c
@@ -0,0 +1,273 @@
+/* $XConsortium: iceauth.c,v 1.21 94/12/20 16:49:58 mor Exp $ */
+/* $XFree86: xc/lib/ICE/iceauth.c,v 3.1 1995/01/27 04:44:52 dawes Exp $ */
+/******************************************************************************
+
+
+Copyright (c) 1993 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include "KDE-ICE/ICElib.h"
+#include "KDE-ICE/ICElibint.h"
+#include "KDE-ICE/ICEutil.h"
+#include "KDE-ICE/globals.h"
+
+#include <sys/time.h>
+#include <string.h>
+
+#if defined(X_NOT_STDC_ENV) && !defined(__EMX__)
+#define Time_t long
+extern Time_t time ();
+#else
+#include <time.h>
+#define Time_t time_t
+#endif
+
+static int binaryEqual (register const char *a, register const char *b, register unsigned len);
+
+static int was_called_state;
+
+/*
+ * MIT-MAGIC-COOKIE-1 is a sample authentication method implemented by
+ * the SI. It is not part of standard ICElib.
+ */
+
+
+char *
+IceGenerateMagicCookie (len)
+
+int len;
+
+{
+ char *auth;
+ long ldata[2];
+ int seed;
+ int value;
+ int i;
+
+ if ((auth = (char *) malloc (len + 1)) == NULL)
+ return (NULL);
+
+ {
+ struct timeval now;
+ gettimeofday(&now, 0);
+ ldata[0] = now.tv_sec;
+ ldata[1] = now.tv_usec;
+ }
+ seed = (ldata[0]) + (ldata[1] << 16);
+ srand (seed);
+ for (i = 0; i < len; i++)
+ {
+ value = rand ();
+ auth[i] = value & 0xff;
+ }
+ auth[len] = '\0';
+
+ return (auth);
+}
+
+
+IcePoAuthStatus
+_IcePoMagicCookie1Proc (iceConn, authStatePtr, cleanUp, swap,
+ authDataLen, authData, replyDataLenRet, replyDataRet, errorStringRet)
+
+IceConn iceConn;
+IcePointer *authStatePtr;
+Bool cleanUp;
+Bool swap;
+int authDataLen;
+IcePointer authData;
+int *replyDataLenRet;
+IcePointer *replyDataRet;
+char **errorStringRet;
+
+{
+ (void)swap;/*unused*/
+ (void)authDataLen;/*unused*/
+ (void)authData;/*unused*/
+ if (cleanUp)
+ {
+ /*
+ * We didn't allocate any state. We're done.
+ */
+
+ return (IcePoAuthDoneCleanup);
+ }
+
+ *errorStringRet = NULL;
+
+ if (*authStatePtr == NULL)
+ {
+ /*
+ * This is the first time we're being called. Search the
+ * authentication data for the first occurrence of
+ * MIT-MAGIC-COOKIE-1 that matches iceConn->connection_string.
+ */
+
+ unsigned short length;
+ char *data;
+
+ _IceGetPoAuthData ("ICE", iceConn->connection_string,
+ "MIT-MAGIC-COOKIE-1", &length, &data);
+
+ if (!data)
+ {
+ const char *tempstr =
+ "Could not find correct MIT-MAGIC-COOKIE-1 authentication";
+
+ *errorStringRet = (char *) malloc (strlen (tempstr) + 1);
+ if (*errorStringRet)
+ strcpy (*errorStringRet, tempstr);
+
+ return (IcePoAuthFailed);
+ }
+ else
+ {
+ *authStatePtr = (IcePointer) &was_called_state;
+
+ *replyDataLenRet = length;
+ *replyDataRet = data;
+
+ return (IcePoAuthHaveReply);
+ }
+ }
+ else
+ {
+ /*
+ * We should never get here for MIT-MAGIC-COOKIE-1 since it is
+ * a single pass authentication method.
+ */
+
+ const char *tempstr = "MIT-MAGIC-COOKIE-1 authentication internal error";
+
+ *errorStringRet = (char *) malloc (strlen (tempstr) + 1);
+ if (*errorStringRet)
+ strcpy (*errorStringRet, tempstr);
+
+ return (IcePoAuthFailed);
+ }
+}
+
+
+
+IcePaAuthStatus
+_IcePaMagicCookie1Proc (iceConn, authStatePtr, swap,
+ authDataLen, authData, replyDataLenRet, replyDataRet, errorStringRet)
+
+IceConn iceConn;
+IcePointer *authStatePtr;
+Bool swap;
+int authDataLen;
+IcePointer authData;
+int *replyDataLenRet;
+IcePointer *replyDataRet;
+char **errorStringRet;
+
+{
+ (void)swap;/*unused*/
+ *errorStringRet = NULL;
+ *replyDataLenRet = 0;
+ *replyDataRet = NULL;
+
+ if (*authStatePtr == NULL)
+ {
+ /*
+ * This is the first time we're being called. We don't have
+ * any data to pass to the other client.
+ */
+
+ *authStatePtr = (IcePointer) &was_called_state;
+
+ return (IcePaAuthContinue);
+ }
+ else
+ {
+ /*
+ * Search the authentication data for the first occurrence of
+ * MIT-MAGIC-COOKIE-1 that matches iceConn->connection_string.
+ */
+
+ unsigned short length;
+ char *data;
+
+ _IceGetPaAuthData ("ICE", iceConn->connection_string,
+ "MIT-MAGIC-COOKIE-1", &length, &data);
+
+ if (data)
+ {
+ IcePaAuthStatus status;
+
+ if (authDataLen == length &&
+ binaryEqual ((char *) authData, data, authDataLen))
+ {
+ status = IcePaAuthAccepted;
+ }
+ else
+ {
+ const char *tempstr = "MIT-MAGIC-COOKIE-1 authentication rejected";
+
+ *errorStringRet = (char *) malloc (strlen (tempstr) + 1);
+ if (*errorStringRet)
+ strcpy (*errorStringRet, tempstr);
+
+ status = IcePaAuthRejected;
+ }
+
+ free (data);
+ return (status);
+ }
+ else
+ {
+ /*
+ * We should never get here because in the ConnectionReply
+ * we should have passed all the valid methods. So we should
+ * always find a valid entry.
+ */
+
+ const char *tempstr =
+ "MIT-MAGIC-COOKIE-1 authentication internal error";
+
+ *errorStringRet = (char *) malloc (strlen (tempstr) + 1);
+ if (*errorStringRet)
+ strcpy (*errorStringRet, tempstr);
+
+ return (IcePaAuthFailed);
+ }
+ }
+}
+
+
+
+/*
+ * local routines
+ */
+
+static int binaryEqual (register const char *a, register const char *b, register unsigned len)
+{
+ while (len--)
+ if (*a++ != *b++)
+ return 0;
+ return 1;
+}
diff --git a/dcop/KDE-ICE/listen.c b/dcop/KDE-ICE/listen.c
new file mode 100644
index 000000000..03b715c27
--- /dev/null
+++ b/dcop/KDE-ICE/listen.c
@@ -0,0 +1,297 @@
+/* $XConsortium: listen.c,v 1.15 94/05/02 11:22:36 mor Exp $ */
+/******************************************************************************
+
+
+Copyright (c) 1993 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <KDE-ICE/ICElib.h>
+#include "KDE-ICE/ICElibint.h"
+#include "KDE-ICE/Xtrans.h"
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+
+
+Status
+IceListenForConnections (countRet, listenObjsRet, errorLength, errorStringRet)
+
+int *countRet;
+IceListenObj **listenObjsRet;
+int errorLength;
+char *errorStringRet;
+
+{
+ struct _IceListenObj *listenObjs;
+ char *networkId;
+ int transCount, partial, i, j;
+ int result = -1;
+ int count = 0;
+ Status status = 1;
+ XtransConnInfo *transConns = NULL;
+
+ while ((result < 0) && (count < 5))
+ {
+ char port[128];
+#ifdef _WIN32
+ int nTCPPort = ((getpid() + time(NULL) + count) % 32768) + 1024;
+ sprintf(port, "%d", nTCPPort);
+#else
+ sprintf(port, "dcop%d-%ld", getpid(), time(NULL)+count);
+#endif
+ result = _kde_IceTransMakeAllCOTSServerListeners (port, &partial,
+ &transCount, &transConns);
+ count++;
+ }
+
+ if ((result < 0) || (transCount < 1))
+ {
+ *listenObjsRet = NULL;
+ *countRet = 0;
+
+ strncpy (errorStringRet,
+ "Cannot establish any listening sockets", errorLength);
+
+ return (0);
+ }
+
+ if ((listenObjs = (struct _IceListenObj *) malloc (
+ transCount * sizeof (struct _IceListenObj))) == NULL)
+ {
+ for (i = 0; i < transCount; i++)
+ _kde_IceTransClose (transConns[i]);
+ free ((char *) transConns);
+ return (0);
+ }
+
+ *countRet = 0;
+
+ for (i = 0; i < transCount; i++)
+ {
+ networkId = (char*)_kde_IceTransGetMyNetworkId (transConns[i]);
+
+ if (networkId)
+ {
+ listenObjs[*countRet].trans_conn = transConns[i];
+ listenObjs[*countRet].network_id = networkId;
+
+ (*countRet)++;
+ }
+ }
+
+ if (*countRet == 0)
+ {
+ *listenObjsRet = NULL;
+
+ strncpy (errorStringRet,
+ "Cannot establish any listening sockets", errorLength);
+
+ status = 0;
+ }
+ else
+ {
+ *listenObjsRet = (IceListenObj *) malloc (
+ *countRet * sizeof (IceListenObj));
+
+ if (*listenObjsRet == NULL)
+ {
+ strncpy (errorStringRet, "Malloc failed", errorLength);
+
+ status = 0;
+ }
+ else
+ {
+ for (i = 0; i < *countRet; i++)
+ {
+ (*listenObjsRet)[i] = (IceListenObj) malloc (
+ sizeof (struct _IceListenObj));
+
+ if ((*listenObjsRet)[i] == NULL)
+ {
+ strncpy (errorStringRet, "Malloc failed", errorLength);
+
+ for (j = 0; j < i; j++)
+ free ((char *) (*listenObjsRet)[j]);
+
+ free ((char *) *listenObjsRet);
+
+ status = 0;
+ }
+ else
+ {
+ *((*listenObjsRet)[i]) = listenObjs[i];
+ }
+ }
+ }
+ }
+
+ if (status == 1)
+ {
+ if (errorStringRet && errorLength > 0)
+ *errorStringRet = '\0';
+
+ for (i = 0; i < *countRet; i++)
+ {
+ (*listenObjsRet)[i]->host_based_auth_proc = NULL;
+ }
+ }
+ else
+ {
+ for (i = 0; i < transCount; i++)
+ _kde_IceTransClose (transConns[i]);
+ }
+
+ free ((char *) listenObjs);
+ free ((char *) transConns);
+
+ return (status);
+}
+
+
+
+int
+IceGetListenConnectionNumber (listenObj)
+
+IceListenObj listenObj;
+
+{
+ return (_kde_IceTransGetConnectionNumber (listenObj->trans_conn));
+}
+
+
+
+char *
+IceGetListenConnectionString (listenObj)
+
+IceListenObj listenObj;
+
+{
+ char *networkId;
+
+ networkId = (char *) malloc (strlen (listenObj->network_id) + 1);
+
+ if (networkId)
+ strcpy (networkId, listenObj->network_id);
+
+ return (networkId);
+}
+
+
+
+char *
+IceComposeNetworkIdList (count, listenObjs)
+
+int count;
+IceListenObj *listenObjs;
+
+{
+ char *list;
+ int len = 0;
+ int i;
+
+ if (count < 1 || listenObjs == NULL)
+ return (NULL);
+
+ for (i = 0; i < count; i++)
+ len += (strlen (listenObjs[i]->network_id) + 1);
+
+ list = (char *) malloc (len);
+
+ if (list == NULL)
+ return (NULL);
+ else
+ {
+ int doneCount = 0;
+
+ list[0] = '\0';
+
+ for (i = 0; i < count; i++)
+ {
+ if (_kde_IceTransIsLocal (listenObjs[i]->trans_conn))
+ {
+ strcat (list, listenObjs[i]->network_id);
+ doneCount++;
+ if (doneCount < count)
+ strcat (list, ",");
+ }
+ }
+
+ if (doneCount < count)
+ {
+ for (i = 0; i < count; i++)
+ {
+ if (!_kde_IceTransIsLocal (listenObjs[i]->trans_conn))
+ {
+ strcat (list, listenObjs[i]->network_id);
+ doneCount++;
+ if (doneCount < count)
+ strcat (list, ",");
+ }
+ }
+ }
+
+ return (list);
+ }
+}
+
+
+
+void
+IceFreeListenObjs (count, listenObjs)
+
+int count;
+IceListenObj *listenObjs;
+
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ {
+ free (listenObjs[i]->network_id);
+ _kde_IceTransClose (listenObjs[i]->trans_conn);
+ free ((char *) listenObjs[i]);
+ }
+
+ free ((char *) listenObjs);
+}
+
+
+
+/*
+ * Allow host based authentication for the ICE Connection Setup.
+ * Do not confuse with the host based authentication callbacks that
+ * can be set up in IceRegisterForProtocolReply.
+ */
+
+void
+IceSetHostBasedAuthProc (listenObj, hostBasedAuthProc)
+
+IceListenObj listenObj;
+IceHostBasedAuthProc hostBasedAuthProc;
+
+{
+ listenObj->host_based_auth_proc = hostBasedAuthProc;
+}
diff --git a/dcop/KDE-ICE/listenwk.c b/dcop/KDE-ICE/listenwk.c
new file mode 100644
index 000000000..80ff1dbae
--- /dev/null
+++ b/dcop/KDE-ICE/listenwk.c
@@ -0,0 +1,155 @@
+/* $Xorg: listenwk.c,v 1.4 2000/08/17 19:44:15 cpqbld Exp $ */
+
+/*
+
+Copyright 1996, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+
+*/
+/* $XFree86: xc/lib/ICE/listenwk.c,v 1.3 2001/01/17 19:41:29 dawes Exp $ */
+
+
+/* Author: Ralph Mor, X Consortium */
+
+#include "KDE-ICE/ICElib.h"
+#include "KDE-ICE/ICElibint.h"
+#include <KDE-ICE/Xtrans.h>
+#include <stdio.h>
+#include <string.h>
+
+
+Status
+IceListenForWellKnownConnections (port, countRet, listenObjsRet, errorLength, errorStringRet)
+
+char *port;
+int *countRet;
+IceListenObj **listenObjsRet;
+int errorLength;
+char *errorStringRet;
+
+{
+ struct _IceListenObj *listenObjs;
+ char *networkId;
+ int transCount, partial, i, j;
+ Status status = 1;
+ XtransConnInfo *transConns = NULL;
+
+
+ if ((_kde_IceTransMakeAllCOTSServerListeners (port, &partial,
+ &transCount, &transConns) < 0) || (transCount < 1))
+ {
+ *listenObjsRet = NULL;
+ *countRet = 0;
+
+ strncpy (errorStringRet,
+ "Cannot establish any listening sockets", errorLength);
+
+ return (0);
+ }
+
+ if ((listenObjs = (struct _IceListenObj *) malloc (
+ transCount * sizeof (struct _IceListenObj))) == NULL)
+ {
+ for (i = 0; i < transCount; i++)
+ _kde_IceTransClose (transConns[i]);
+ free ((char *) transConns);
+ return (0);
+ }
+
+ *countRet = 0;
+
+ for (i = 0; i < transCount; i++)
+ {
+ networkId = (char *)_kde_IceTransGetMyNetworkId (transConns[i]);
+
+ if (networkId)
+ {
+ listenObjs[*countRet].trans_conn = transConns[i];
+ listenObjs[*countRet].network_id = networkId;
+
+ (*countRet)++;
+ }
+ }
+
+ if (*countRet == 0)
+ {
+ *listenObjsRet = NULL;
+
+ strncpy (errorStringRet,
+ "Cannot establish any listening sockets", errorLength);
+
+ status = 0;
+ }
+ else
+ {
+ *listenObjsRet = (IceListenObj *) malloc (
+ *countRet * sizeof (IceListenObj));
+
+ if (*listenObjsRet == NULL)
+ {
+ strncpy (errorStringRet, "Malloc failed", errorLength);
+
+ status = 0;
+ }
+ else
+ {
+ for (i = 0; i < *countRet; i++)
+ {
+ (*listenObjsRet)[i] = (IceListenObj) malloc (
+ sizeof (struct _IceListenObj));
+
+ if ((*listenObjsRet)[i] == NULL)
+ {
+ strncpy (errorStringRet, "Malloc failed", errorLength);
+
+ for (j = 0; j < i; j++)
+ free ((char *) (*listenObjsRet)[j]);
+
+ free ((char *) *listenObjsRet);
+
+ status = 0;
+ }
+ else
+ {
+ *((*listenObjsRet)[i]) = listenObjs[i];
+ }
+ }
+ }
+ }
+
+ if (status == 1)
+ {
+ if (errorStringRet && errorLength > 0)
+ *errorStringRet = '\0';
+
+ for (i = 0; i < *countRet; i++)
+ {
+ (*listenObjsRet)[i]->host_based_auth_proc = NULL;
+ }
+ }
+ else
+ {
+ for (i = 0; i < transCount; i++)
+ _kde_IceTransClose (transConns[i]);
+ }
+
+ free ((char *) listenObjs);
+ free ((char *) transConns);
+
+ return (status);
+}
diff --git a/dcop/KDE-ICE/locking.c b/dcop/KDE-ICE/locking.c
new file mode 100644
index 000000000..0acce8368
--- /dev/null
+++ b/dcop/KDE-ICE/locking.c
@@ -0,0 +1,62 @@
+/* $Xorg: locking.c,v 1.3 2000/08/17 19:44:15 cpqbld Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <KDE-ICE/ICElib.h>
+#include "KDE-ICE/ICElibint.h"
+
+
+/*
+ * NOT IMPLEMENTED YET
+ */
+
+
+Status
+IceInitThreads ()
+
+{
+ return (0);
+}
+
+
+void
+IceAppLockConn (iceConn)
+
+IceConn iceConn;
+
+{
+ (void)iceConn;/*unused in the macro*/
+ IceLockConn (iceConn);
+}
+
+
+void
+IceAppUnlockConn (iceConn)
+
+IceConn iceConn;
+
+{
+ (void)iceConn;/*unused in the macro*/
+ IceUnlockConn (iceConn);
+}
diff --git a/dcop/KDE-ICE/misc.c b/dcop/KDE-ICE/misc.c
new file mode 100644
index 000000000..0dbbf24b7
--- /dev/null
+++ b/dcop/KDE-ICE/misc.c
@@ -0,0 +1,619 @@
+/* $XConsortium: misc.c /main/29 1996/11/13 14:43:55 lehors $ */
+/******************************************************************************
+
+
+Copyright (c) 1993 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include "KDE-ICE/ICElib.h"
+#include "KDE-ICE/ICElibint.h"
+#include "KDE-ICE/Xtrans.h"
+#include "KDE-ICE/globals.h"
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+
+/*
+ * scratch buffer
+ */
+
+char *
+IceAllocScratch (iceConn, size)
+
+IceConn iceConn;
+unsigned long size;
+
+{
+ if (!iceConn->scratch || size > iceConn->scratch_size)
+ {
+ if (iceConn->scratch)
+ free (iceConn->scratch);
+
+ iceConn->scratch = (char *) malloc ((unsigned) size);
+ iceConn->scratch_size = size;
+ }
+
+ return (iceConn->scratch);
+}
+
+
+
+/*
+ * Output/Input buffer functions
+ */
+
+void IceFlush (IceConn iceConn)
+{
+ (*_IceWriteHandler) (iceConn,
+ (unsigned long) (iceConn->outbufptr - iceConn->outbuf),
+ iceConn->outbuf);
+
+ iceConn->outbufptr = iceConn->outbuf;
+}
+
+
+int
+IceGetOutBufSize (iceConn)
+
+IceConn iceConn;
+
+{
+ return (iceConn->outbufmax - iceConn->outbuf);
+}
+
+
+int
+IceGetInBufSize (iceConn)
+
+IceConn iceConn;
+
+{
+ return (iceConn->inbufmax - iceConn->inbuf);
+}
+
+
+
+/*
+ * informational functions
+ */
+
+IceConnectStatus
+IceConnectionStatus (iceConn)
+
+IceConn iceConn;
+
+{
+ return (iceConn->connection_status);
+}
+
+
+char *
+IceVendor (iceConn)
+
+IceConn iceConn;
+
+{
+ char *string = (char *) malloc (strlen (iceConn->vendor) + 1);
+
+ if (string)
+ strcpy (string, iceConn->vendor);
+
+ return (string);
+}
+
+
+char *
+IceRelease (iceConn)
+
+IceConn iceConn;
+
+{
+ char *string = (char *) malloc (strlen (iceConn->release) + 1);
+
+ if (string)
+ strcpy (string, iceConn->release);
+
+ return (string);
+}
+
+
+int
+IceProtocolVersion (iceConn)
+
+IceConn iceConn;
+
+{
+ return (_IceVersions[iceConn->my_ice_version_index].major_version);
+}
+
+
+int
+IceProtocolRevision (iceConn)
+
+IceConn iceConn;
+
+{
+ return (_IceVersions[iceConn->my_ice_version_index].minor_version);
+}
+
+
+int
+IceConnectionNumber (iceConn)
+
+IceConn iceConn;
+
+{
+ return (_kde_IceTransGetConnectionNumber (iceConn->trans_conn));
+}
+
+
+char *
+IceConnectionString (iceConn)
+
+IceConn iceConn;
+
+{
+ if (iceConn->connection_string)
+ {
+ char *string = (char *) malloc (
+ strlen (iceConn->connection_string) + 1);
+
+ if (string)
+ strcpy (string, iceConn->connection_string);
+
+ return (string);
+ }
+ else
+ return (NULL);
+}
+
+
+unsigned long
+IceLastSentSequenceNumber (iceConn)
+
+IceConn iceConn;
+
+{
+ return (iceConn->send_sequence);
+}
+
+
+unsigned long
+IceLastReceivedSequenceNumber (iceConn)
+
+IceConn iceConn;
+
+{
+ return (iceConn->receive_sequence);
+}
+
+
+Bool
+IceSwapping (iceConn)
+
+IceConn iceConn;
+
+{
+ return (iceConn->swap);
+}
+
+
+
+/*
+ * Read "n" bytes from a connection.
+ *
+ * Return Status 0 if we detected an EXPECTED closed connection.
+ *
+ */
+
+Status
+_IceRead (iceConn, nbytes, ptr)
+
+register IceConn iceConn;
+unsigned long nbytes;
+register char *ptr;
+
+{
+ register unsigned long nleft;
+
+ nleft = nbytes;
+ while (nleft > 0)
+ {
+ int nread;
+
+ if (iceConn->io_ok)
+ nread = _kde_IceTransRead (iceConn->trans_conn, ptr, (int) nleft);
+ else
+ return (1);
+
+ if (nread <= 0)
+ {
+#ifdef _WIN32
+ errno = WSAGetLastError();
+#endif
+ if( nread < 0 && errno == EINTR )
+ continue;
+ if (iceConn->want_to_close)
+ {
+ /*
+ * We sent a WantToClose message and now we detected that
+ * the other side closed the connection.
+ */
+
+ _IceConnectionClosed (iceConn); /* invoke watch procs */
+ _IceFreeConnection (iceConn);
+
+ return (0);
+ }
+ else
+ {
+ /*
+ * Fatal IO error. First notify each protocol's IceIOErrorProc
+ * callback, then invoke the application IO error handler.
+ */
+
+ iceConn->io_ok = False;
+
+ if (iceConn->connection_status == IceConnectPending)
+ {
+ /*
+ * Don't invoke IO error handler if we are in the
+ * middle of a connection setup.
+ */
+
+ return (1);
+ }
+
+ if (iceConn->process_msg_info)
+ {
+ int i;
+
+ for (i = iceConn->his_min_opcode;
+ i <= iceConn->his_max_opcode; i++)
+ {
+ _IceProcessMsgInfo *process;
+
+ process = &iceConn->process_msg_info[
+ i - iceConn->his_min_opcode];
+
+ if (process->in_use)
+ {
+ IceIOErrorProc IOErrProc = process->accept_flag ?
+ process->protocol->accept_client->io_error_proc :
+ process->protocol->orig_client->io_error_proc;
+
+ if (IOErrProc)
+ (*IOErrProc) (iceConn);
+ }
+ }
+ }
+
+ (*_IceIOErrorHandler) (iceConn);
+ return (1);
+ }
+ }
+
+ nleft -= nread;
+ ptr += nread;
+ }
+
+ return (1);
+}
+
+
+
+/*
+ * If we read a message header with a bad major or minor opcode,
+ * we need to advance to the end of the message. This way, the next
+ * message can be processed correctly.
+ */
+
+void
+_IceReadSkip (iceConn, nbytes)
+
+register IceConn iceConn;
+register unsigned long nbytes;
+
+{
+ char temp[512];
+
+ while (nbytes > 0)
+ {
+ unsigned long rbytes = nbytes > 512 ? 512 : nbytes;
+
+ _IceRead (iceConn, rbytes, temp);
+ nbytes -= rbytes;
+ }
+}
+
+
+
+/*
+ * Write "n" bytes to a connection.
+ */
+
+void
+_IceWrite (iceConn, nbytes, ptr)
+
+register IceConn iceConn;
+unsigned long nbytes;
+register char *ptr;
+
+{
+ register unsigned long nleft;
+
+ nleft = nbytes;
+ while (nleft > 0)
+ {
+ int nwritten;
+
+ if (iceConn->io_ok)
+ nwritten = _kde_IceTransWrite (iceConn->trans_conn, ptr, (int) nleft);
+ else
+ return;
+
+
+ if (nwritten <= 0)
+ {
+#ifdef _WIN32
+ errno = WSAGetLastError();
+#endif
+ if( nwritten < 0 && errno == EINTR )
+ continue;
+ /*
+ * Fatal IO error. First notify each protocol's IceIOErrorProc
+ * callback, then invoke the application IO error handler.
+ */
+
+ iceConn->io_ok = False;
+
+ if (iceConn->connection_status == IceConnectPending)
+ {
+ /*
+ * Don't invoke IO error handler if we are in the
+ * middle of a connection setup.
+ */
+
+ return;
+ }
+
+ if (iceConn->process_msg_info)
+ {
+ int i;
+
+ for (i = iceConn->his_min_opcode;
+ i <= iceConn->his_max_opcode; i++)
+ {
+ _IceProcessMsgInfo *process;
+
+ process = &iceConn->process_msg_info[
+ i - iceConn->his_min_opcode];
+
+ if (process->in_use)
+ {
+ IceIOErrorProc IOErrProc = process->accept_flag ?
+ process->protocol->accept_client->io_error_proc :
+ process->protocol->orig_client->io_error_proc;
+
+ if (IOErrProc)
+ (*IOErrProc) (iceConn);
+ }
+ }
+ }
+
+ (*_IceIOErrorHandler) (iceConn);
+ return;
+ }
+
+ nleft -= nwritten;
+ ptr += nwritten;
+ }
+}
+
+#ifdef WORD64
+
+IceWriteData16 (iceConn, nbytes, data)
+
+IceConn iceConn;
+unsigned long nbytes;
+short *data;
+
+{
+ int numShorts = nbytes / 2;
+ int index = 0;
+
+ while (index < numShorts)
+ {
+ int spaceLeft, count, i;
+ int shortsLeft = numShorts - index;
+
+ spaceLeft = iceConn->outbufmax - iceConn->outbufptr - 1;
+
+ if (spaceLeft < 2)
+ {
+ IceFlush (iceConn);
+ spaceLeft = iceConn->outbufmax - iceConn->outbufptr - 1;
+ }
+
+ count = (shortsLeft < spaceLeft / 2) ? shortsLeft : spaceLeft / 2;
+
+ for (i = 0; i < count; i++)
+ STORE_CARD16 (iceConn->outbufptr, data[index++]);
+ }
+}
+
+
+IceWriteData32 (iceConn, nbytes, data)
+
+IceConn iceConn;
+unsigned long nbytes;
+int *data;
+
+{
+ int numLongs = nbytes / 4;
+ int index = 0;
+
+ while (index < numLongs)
+ {
+ int spaceLeft, count, i;
+ int longsLeft = numLongs - index;
+
+ spaceLeft = iceConn->outbufmax - iceConn->outbufptr - 1;
+
+ if (spaceLeft < 4)
+ {
+ IceFlush (iceConn);
+ spaceLeft = iceConn->outbufmax - iceConn->outbufptr - 1;
+ }
+
+ count = (longsLeft < spaceLeft / 4) ? longsLeft : spaceLeft / 4;
+
+ for (i = 0; i < count; i++)
+ STORE_CARD32 (iceConn->outbufptr, data[index++]);
+ }
+}
+
+
+IceReadData16 (iceConn, swap, nbytes, data)
+
+IceConn iceConn;
+Bool swap;
+unsigned long nbytes;
+short *data;
+
+{
+ /* NOT IMPLEMENTED YET */
+}
+
+
+IceReadData32 (iceConn, swap, nbytes, data)
+
+IceConn iceConn;
+Bool swap;
+unsigned long nbytes;
+int *data;
+
+{
+ /* NOT IMPLEMENTED YET */
+}
+
+#endif /* WORD64 */
+
+
+
+void
+_IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode)
+
+IceConn iceConn;
+int hisOpcode;
+int myOpcode;
+
+{
+ if (hisOpcode <= 0 || hisOpcode > 255)
+ {
+ return;
+ }
+ else if (iceConn->process_msg_info == NULL)
+ {
+ iceConn->process_msg_info = (_IceProcessMsgInfo *) malloc (
+ sizeof (_IceProcessMsgInfo));
+ iceConn->his_min_opcode = iceConn->his_max_opcode = hisOpcode;
+ }
+ else if (hisOpcode < iceConn->his_min_opcode)
+ {
+ _IceProcessMsgInfo *oldVec = iceConn->process_msg_info;
+ int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1;
+ int newsize = iceConn->his_max_opcode - hisOpcode + 1;
+ int i;
+
+ iceConn->process_msg_info = (_IceProcessMsgInfo *) malloc (
+ newsize * sizeof (_IceProcessMsgInfo));
+
+ memcpy (&iceConn->process_msg_info[
+ iceConn->his_min_opcode - hisOpcode], oldVec,
+ oldsize * sizeof (_IceProcessMsgInfo));
+
+ free ((char *) oldVec);
+
+ for (i = hisOpcode + 1; i < iceConn->his_min_opcode; i++)
+ {
+ iceConn->process_msg_info[i -
+ iceConn->his_min_opcode].in_use = False;
+
+ iceConn->process_msg_info[i -
+ iceConn->his_min_opcode].protocol = NULL;
+ }
+
+ iceConn->his_min_opcode = hisOpcode;
+ }
+ else if (hisOpcode > iceConn->his_max_opcode)
+ {
+ _IceProcessMsgInfo *oldVec = iceConn->process_msg_info;
+ int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1;
+ int newsize = hisOpcode - iceConn->his_min_opcode + 1;
+ int i;
+
+ iceConn->process_msg_info = (_IceProcessMsgInfo *) malloc (
+ newsize * sizeof (_IceProcessMsgInfo));
+
+ memcpy (iceConn->process_msg_info, oldVec,
+ oldsize * sizeof (_IceProcessMsgInfo));
+
+ free ((char *) oldVec);
+
+ for (i = iceConn->his_max_opcode + 1; i < hisOpcode; i++)
+ {
+ iceConn->process_msg_info[i -
+ iceConn->his_min_opcode].in_use = False;
+
+ iceConn->process_msg_info[i -
+ iceConn->his_min_opcode].protocol = NULL;
+ }
+
+ iceConn->his_max_opcode = hisOpcode;
+ }
+
+ iceConn->process_msg_info[hisOpcode -
+ iceConn->his_min_opcode].in_use = True;
+
+ iceConn->process_msg_info[hisOpcode -
+ iceConn->his_min_opcode].my_opcode = myOpcode;
+
+ iceConn->process_msg_info[hisOpcode -
+ iceConn->his_min_opcode].protocol = &_IceProtocols[myOpcode - 1];
+}
+
+
+
+char *
+_IceGetPeerName (iceConn)
+
+IceConn iceConn;
+
+{
+ return ((char*)_kde_IceTransGetPeerNetworkId (iceConn->trans_conn));
+}
diff --git a/dcop/KDE-ICE/ping.c b/dcop/KDE-ICE/ping.c
new file mode 100644
index 000000000..5c0c601d6
--- /dev/null
+++ b/dcop/KDE-ICE/ping.c
@@ -0,0 +1,59 @@
+/* $Xorg: ping.c,v 1.3 2000/08/17 19:44:15 cpqbld Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <KDE-ICE/ICElib.h>
+#include "KDE-ICE/ICElibint.h"
+
+Status
+IcePing (iceConn, pingReplyProc, clientData)
+
+IceConn iceConn;
+IcePingReplyProc pingReplyProc;
+IcePointer clientData;
+
+{
+ _IcePingWait *newping = (_IcePingWait *) malloc (sizeof (_IcePingWait));
+ _IcePingWait *ptr = iceConn->ping_waits;
+
+ if (newping == NULL)
+ return (0);
+
+ newping->ping_reply_proc = pingReplyProc;
+ newping->client_data = clientData;
+ newping->next = NULL;
+
+ while (ptr && ptr->next)
+ ptr = ptr->next;
+
+ if (ptr == NULL)
+ iceConn->ping_waits = newping;
+ else
+ ptr->next = newping;
+
+ IceSimpleMessage (iceConn, 0, ICE_Ping);
+ IceFlush (iceConn);
+
+ return (1);
+}
diff --git a/dcop/KDE-ICE/process.c b/dcop/KDE-ICE/process.c
new file mode 100644
index 000000000..5769946ec
--- /dev/null
+++ b/dcop/KDE-ICE/process.c
@@ -0,0 +1,2545 @@
+/* $Xorg: process.c,v 1.3 2000/08/17 19:44:16 cpqbld Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+/* $XFree86: xc/lib/ICE/process.c,v 3.5 2001/01/17 19:41:29 dawes Exp $ */
+
+#include "KDE-ICE/ICElib.h"
+#include "KDE-ICE/ICElibint.h"
+#include "KDE-ICE/globals.h"
+
+#include <string.h>
+#include <stdio.h> /* sprintf */
+
+#ifdef MINIX
+#include <KDE-ICE/Xtrans.h>
+#endif
+
+/*
+ * Check for bad length
+ */
+
+#define CHECK_SIZE_MATCH(_iceConn, _opcode, _expected_len, _actual_len, _severity) \
+ if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) != _expected_len) \
+ { \
+ _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \
+ return (0); \
+ }
+
+#define CHECK_AT_LEAST_SIZE(_iceConn, _opcode, _expected_len, _actual_len, _severity) \
+ if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) > (long)_expected_len) \
+ { \
+ _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \
+ return (0); \
+ }
+
+#define CHECK_COMPLETE_SIZE(_iceConn, _opcode, _expected_len, _actual_len, _pStart, _severity) \
+ if (((PADDED_BYTES64((_actual_len)) - SIZEOF (iceMsg)) >> 3) \
+ != _expected_len) \
+ { \
+ _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \
+ IceDisposeCompleteMessage (iceConn, _pStart); \
+ return (0); \
+ }
+
+#define BAIL_STRING(_iceConn, _opcode, _pStart) {\
+ _IceErrorBadLength (_iceConn, 0, _opcode, IceFatalToConnection);\
+ IceDisposeCompleteMessage (_iceConn, _pStart);\
+ return (0);\
+}
+
+/*
+ * IceProcessMessages:
+ *
+ * If replyWait == NULL, the client is not waiting for a reply.
+ *
+ * If replyWait != NULL, the client is waiting for a reply...
+ *
+ * - replyWait->sequence_of_request is the sequence number of the
+ * message for which the client is waiting a reply. This is needed
+ * to determine if an error matches a replyWait.
+ *
+ * - replyWait->major_opcode_of_request is the major opcode of the
+ * message for which we are waiting a reply.
+ *
+ * - replyWait->minor_opcode_of_request is the minor opcode of the
+ * message for which we are waiting a reply.
+ *
+ * - replyWait->reply is a pointer to the reply message which will be
+ * filled in when the reply is ready (the protocol library should
+ * cast this IcePointer to the appropriate reply type). In most cases,
+ * the reply will have some fixed-size part, and the sender function
+ * will have provided a pointer to a structure (e.g.) to hold this
+ * fixed-size data. If there is variable-length data, it would be
+ * expected that the reply function will have to allocate additional
+ * memory and store pointer(s) to that memory in the fixed-size
+ * structure. If the entire data is variable length (e.g., a single
+ * variable-length string), then the sender function would probably
+ * just pass a pointer to fixed-size space to hold a pointer, and the
+ * reply function would allocate the storage and store the pointer.
+ * It is the responsibility of the client receiving the reply to
+ * free up any memory allocated on it's behalf.
+ *
+ * We might be waiting for several different replies (a function can wait
+ * for a reply, and while calling IceProcessMessages, a callback can be
+ * invoked which will wait for another reply). We take advantage of the
+ * fact that for a given protocol, we are guaranteed that messages are
+ * processed in the order we sent them. So, every time we have a new
+ * replyWait, we add it to the END of the 'saved_reply_waits' list. When
+ * we read a message and want to see if it matches a replyWait, we use the
+ * FIRST replyWait in the list with the major opcode of the message. If the
+ * reply is ready, we remove that replyWait from the list.
+ *
+ * If the reply/error is ready for the replyWait passed in to
+ * IceProcessMessages, *replyReadyRet is set to True.
+ *
+ * The return value of IceProcessMessages is one of the following:
+ *
+ * IceProcessMessagesSuccess - the message was processed successfully.
+ * IceProcessMessagesIOError - an IO error occurred. The caller should
+ * invoked IceCloseConnection.
+ * IceProcessMessagesConnectionClosed - the connection was closed as a
+ * result of shutdown negotiation.
+ */
+
+IceProcessMessagesStatus
+IceProcessMessages (iceConn, replyWait, replyReadyRet)
+
+IceConn iceConn;
+IceReplyWaitInfo *replyWait;
+Bool *replyReadyRet;
+
+{
+ iceMsg *header;
+ Bool replyReady = False;
+ IceReplyWaitInfo *useThisReplyWait = NULL;
+ IceProcessMessagesStatus retStatus = IceProcessMessagesSuccess;
+
+ if (replyWait)
+ *replyReadyRet = False;
+
+ /*
+ * Each time IceProcessMessages is entered, we increment the dispatch
+ * level. Each time we leave it, we decrement the dispatch level.
+ */
+
+ iceConn->dispatch_level++;
+
+
+ /*
+ * Read the ICE message header.
+ */
+
+ if (!_IceRead (iceConn, (unsigned long) SIZEOF (iceMsg), iceConn->inbuf))
+ {
+ /*
+ * If we previously sent a WantToClose and now we detected
+ * that the connection was closed, _IceRead returns status 0.
+ * Since the connection was closed, we just want to return here.
+ */
+
+ return (IceProcessMessagesConnectionClosed);
+ }
+
+ if (!iceConn->io_ok)
+ {
+ /*
+ * An unexpected IO error occurred. The caller of IceProcessMessages
+ * should call IceCloseConnection which will cause the watch procedures
+ * to be invoked and the ICE connection to be freed.
+ */
+
+ iceConn->dispatch_level--;
+ iceConn->connection_status = IceConnectIOError;
+ return (IceProcessMessagesIOError);
+ }
+
+ header = (iceMsg *) iceConn->inbuf;
+ iceConn->inbufptr = iceConn->inbuf + SIZEOF (iceMsg);
+
+ iceConn->receive_sequence++;
+
+ if (iceConn->waiting_for_byteorder)
+ {
+ if (header->majorOpcode == 0 &&
+ header->minorOpcode == ICE_ByteOrder)
+ {
+ char byteOrder = ((iceByteOrderMsg *) header)->byteOrder;
+ int endian = 1;
+
+ CHECK_SIZE_MATCH (iceConn, ICE_ByteOrder,
+ header->length, SIZEOF (iceByteOrderMsg),
+ IceFatalToConnection);
+
+ if (byteOrder != IceMSBfirst && byteOrder != IceLSBfirst)
+ {
+ _IceErrorBadValue (iceConn, 0,
+ ICE_ByteOrder, 2, 1, &byteOrder);
+
+ iceConn->connection_status = IceConnectRejected;
+ }
+ else
+ {
+ iceConn->swap =
+ (((*(char *) &endian) && byteOrder == IceMSBfirst) ||
+ (!(*(char *) &endian) && byteOrder == IceLSBfirst));
+
+ iceConn->waiting_for_byteorder = 0;
+ }
+ }
+ else
+ {
+ if (header->majorOpcode != 0)
+ {
+ _IceErrorBadMajor (iceConn, header->majorOpcode,
+ header->minorOpcode, IceFatalToConnection);
+ }
+ else
+ {
+ _IceErrorBadState (iceConn, 0,
+ header->minorOpcode, IceFatalToConnection);
+ }
+
+ iceConn->connection_status = IceConnectRejected;
+ }
+
+ iceConn->dispatch_level--;
+ if (!iceConn->io_ok)
+ {
+ iceConn->connection_status = IceConnectIOError;
+ retStatus = IceProcessMessagesIOError;
+ }
+
+ return (retStatus);
+ }
+
+ if (iceConn->swap)
+ {
+ /* swap the length field */
+
+ header->length = lswapl (header->length);
+ }
+
+ if (replyWait)
+ {
+ /*
+ * Add to the list of replyWaits (only if it doesn't exist
+ * in the list already.
+ */
+
+ _IceAddReplyWait (iceConn, replyWait);
+
+
+ /*
+ * Note that there are two different replyWaits. The first is
+ * the one passed into IceProcessMessages, and is the replyWait
+ * for the message the client is blocking on. The second is
+ * the replyWait for the message currently being processed
+ * by IceProcessMessages. We call it "useThisReplyWait".
+ */
+
+ useThisReplyWait = _IceSearchReplyWaits (iceConn, header->majorOpcode);
+ }
+
+ if (header->majorOpcode == 0)
+ {
+ /*
+ * ICE protocol
+ */
+
+ Bool connectionClosed;
+
+ _IceProcessCoreMsgProc processIce =
+ _IceVersions[iceConn->my_ice_version_index].process_core_msg_proc;
+
+ (*processIce) (iceConn, header->minorOpcode,
+ header->length, iceConn->swap,
+ useThisReplyWait, &replyReady, &connectionClosed);
+
+ if (connectionClosed)
+ {
+ /*
+ * As a result of shutdown negotiation, the connection was closed.
+ */
+
+ return (IceProcessMessagesConnectionClosed);
+ }
+ }
+ else
+ {
+ /*
+ * Sub protocol
+ */
+
+ if ((int) header->majorOpcode < iceConn->his_min_opcode ||
+ (int) header->majorOpcode > iceConn->his_max_opcode ||
+ !(iceConn->process_msg_info[header->majorOpcode -
+ iceConn->his_min_opcode].in_use))
+ {
+ /*
+ * The protocol of the message we just read is not supported.
+ */
+
+ _IceErrorBadMajor (iceConn, header->majorOpcode,
+ header->minorOpcode, IceCanContinue);
+
+ _IceReadSkip (iceConn, header->length << 3);
+ }
+ else
+ {
+ _IceProcessMsgInfo *processMsgInfo = &iceConn->process_msg_info[
+ header->majorOpcode - iceConn->his_min_opcode];
+
+ if (processMsgInfo->accept_flag)
+ {
+ IcePaProcessMsgProc processProc =
+ processMsgInfo->process_msg_proc.accept_client;
+
+ (*processProc) (iceConn, processMsgInfo->client_data,
+ header->minorOpcode, header->length, iceConn->swap);
+ }
+ else
+ {
+ IcePoProcessMsgProc processProc =
+ processMsgInfo->process_msg_proc.orig_client;
+
+ (*processProc) (iceConn,
+ processMsgInfo->client_data, header->minorOpcode,
+ header->length, iceConn->swap,
+ useThisReplyWait, &replyReady);
+ }
+ }
+ }
+
+ if (replyReady)
+ {
+ _IceSetReplyReady (iceConn, useThisReplyWait);
+ }
+
+
+ /*
+ * Now we check if the reply is ready for the replyWait passed
+ * into IceProcessMessages. The replyWait is removed from the
+ * replyWait list if it is ready.
+ */
+
+ if (replyWait)
+ *replyReadyRet = _IceCheckReplyReady (iceConn, replyWait);
+
+
+ /*
+ * Decrement the dispatch level. If we reach level 0, and the
+ * free_asap bit is set, free the connection now. Also check for
+ * possible bad IO status.
+ */
+
+ iceConn->dispatch_level--;
+
+ if (iceConn->dispatch_level == 0 && iceConn->free_asap)
+ {
+ _IceFreeConnection (iceConn);
+ retStatus = IceProcessMessagesConnectionClosed;
+ }
+ else if (!iceConn->io_ok)
+ {
+ iceConn->connection_status = IceConnectIOError;
+ retStatus = IceProcessMessagesIOError;
+ }
+
+ return (retStatus);
+}
+
+
+
+static void
+AuthRequired (iceConn, authIndex, authDataLen, authData)
+
+IceConn iceConn;
+int authIndex;
+int authDataLen;
+IcePointer authData;
+
+{
+ iceAuthRequiredMsg *pMsg;
+
+ IceGetHeader (iceConn, 0, ICE_AuthRequired,
+ SIZEOF (iceAuthRequiredMsg), iceAuthRequiredMsg, pMsg);
+
+ pMsg->authIndex = authIndex;
+ pMsg->authDataLength = authDataLen;
+ pMsg->length += WORD64COUNT (authDataLen);
+
+ IceWriteData (iceConn, authDataLen, (char *) authData);
+
+ if (PAD64 (authDataLen))
+ IceWritePad (iceConn, PAD64 (authDataLen));
+
+ IceFlush (iceConn);
+}
+
+
+
+static void
+AuthReply (iceConn, authDataLen, authData)
+
+IceConn iceConn;
+int authDataLen;
+IcePointer authData;
+
+{
+ iceAuthReplyMsg *pMsg;
+
+ IceGetHeader (iceConn, 0, ICE_AuthReply,
+ SIZEOF (iceAuthReplyMsg), iceAuthReplyMsg, pMsg);
+
+ pMsg->authDataLength = authDataLen;
+ pMsg->length += WORD64COUNT (authDataLen);
+
+ IceWriteData (iceConn, authDataLen, (char *) authData);
+
+ if (PAD64 (authDataLen))
+ IceWritePad (iceConn, PAD64 (authDataLen));
+
+ IceFlush (iceConn);
+}
+
+
+
+static void
+AuthNextPhase (iceConn, authDataLen, authData)
+
+IceConn iceConn;
+int authDataLen;
+IcePointer authData;
+
+{
+ iceAuthNextPhaseMsg *pMsg;
+
+ IceGetHeader (iceConn, 0, ICE_AuthNextPhase,
+ SIZEOF (iceAuthNextPhaseMsg), iceAuthNextPhaseMsg, pMsg);
+
+ pMsg->authDataLength = authDataLen;
+ pMsg->length += WORD64COUNT (authDataLen);
+
+ IceWriteData (iceConn, authDataLen, (char *) authData);
+
+ if (PAD64 (authDataLen))
+ IceWritePad (iceConn, PAD64 (authDataLen));
+
+ IceFlush (iceConn);
+}
+
+
+
+static void
+AcceptConnection (iceConn, versionIndex)
+
+IceConn iceConn;
+int versionIndex;
+
+{
+ iceConnectionReplyMsg *pMsg;
+ char *pData;
+ int extra;
+
+ extra = STRING_BYTES (IceVendorString) + STRING_BYTES (IceReleaseString);
+
+ IceGetHeaderExtra (iceConn, 0, ICE_ConnectionReply,
+ SIZEOF (iceConnectionReplyMsg), WORD64COUNT (extra),
+ iceConnectionReplyMsg, pMsg, pData);
+
+ pMsg->versionIndex = versionIndex;
+
+ STORE_STRING (pData, IceVendorString);
+ STORE_STRING (pData, IceReleaseString);
+
+ IceFlush (iceConn);
+
+ iceConn->connection_status = IceConnectAccepted;
+}
+
+
+
+static void
+AcceptProtocol (iceConn, hisOpcode, myOpcode, versionIndex, vendor, release)
+
+IceConn iceConn;
+int hisOpcode;
+int myOpcode;
+int versionIndex;
+char *vendor;
+char *release;
+
+{
+ iceProtocolReplyMsg *pMsg;
+ char *pData;
+ int extra;
+
+ extra = STRING_BYTES (vendor) + STRING_BYTES (release);
+
+ IceGetHeaderExtra (iceConn, 0, ICE_ProtocolReply,
+ SIZEOF (iceProtocolReplyMsg), WORD64COUNT (extra),
+ iceProtocolReplyMsg, pMsg, pData);
+
+ pMsg->protocolOpcode = myOpcode;
+ pMsg->versionIndex = versionIndex;
+
+ STORE_STRING (pData, vendor);
+ STORE_STRING (pData, release);
+
+ IceFlush (iceConn);
+
+
+ /*
+ * We may be using a different major opcode for this protocol
+ * than the other client. Whenever we get a message, we must
+ * map to our own major opcode.
+ */
+
+ _IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode);
+}
+
+
+
+static void
+PingReply (iceConn)
+
+IceConn iceConn;
+
+{
+ IceSimpleMessage (iceConn, 0, ICE_PingReply);
+ IceFlush (iceConn);
+}
+
+
+
+static Bool
+ProcessError (iceConn, length, swap, replyWait)
+
+IceConn iceConn;
+unsigned long length;
+Bool swap;
+IceReplyWaitInfo *replyWait;
+
+{
+ int invokeHandler = 0;
+ Bool errorReturned = False;
+ iceErrorMsg *message;
+ char *pData, *pStart;
+ char severity;
+
+ CHECK_AT_LEAST_SIZE (iceConn, ICE_Error,
+ length, SIZEOF (iceErrorMsg),
+ (iceConn->connect_to_you || iceConn->connect_to_me) ?
+ IceFatalToConnection : IceFatalToProtocol);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg),
+ iceErrorMsg, message, pStart);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ severity = message->severity;
+
+ if (severity != IceCanContinue && severity != IceFatalToProtocol &&
+ severity != IceFatalToConnection)
+ {
+ _IceErrorBadValue (iceConn, 0,
+ ICE_Error, 9, 1, &severity);
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ pData = pStart;
+
+ if (swap)
+ {
+ message->errorClass = lswaps (message->errorClass);
+ message->offendingSequenceNum = lswapl (message->offendingSequenceNum);
+ }
+
+ if (!replyWait ||
+ message->offendingSequenceNum != replyWait->sequence_of_request)
+ {
+ invokeHandler = 1;
+ }
+ else
+ {
+ if (iceConn->connect_to_you &&
+ ((!iceConn->connect_to_you->auth_active &&
+ message->offendingMinorOpcode == ICE_ConnectionSetup) ||
+ (iceConn->connect_to_you->auth_active &&
+ message->offendingMinorOpcode == ICE_AuthReply)))
+ {
+ _IceConnectionError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->connection_error);
+ char *errorStr = NULL;
+ char *tempstr;
+ char *prefix, *temp;
+
+ invokeHandler = 0;
+ errorReturned = True;
+
+ switch (message->errorClass)
+ {
+ case IceNoVersion:
+
+ tempstr =
+ (char *)"None of the ICE versions specified are supported";
+ errorStr = (char *) malloc (strlen (tempstr) + 1);
+ strcpy (errorStr, tempstr);
+ break;
+
+ case IceNoAuth:
+
+ tempstr =
+ (char *)"None of the authentication protocols specified are supported";
+ errorStr = (char *) malloc (strlen (tempstr) + 1);
+ strcpy (errorStr, tempstr);
+ break;
+
+ case IceSetupFailed:
+
+ prefix = (char *)"Connection Setup Failed, reason : ";
+
+ EXTRACT_STRING (pData, swap, temp);
+ errorStr = (char *) malloc (
+ strlen (prefix) + strlen (temp) + 1);
+ sprintf (errorStr, "%s%s", prefix, temp);
+ free (temp);
+ break;
+
+ case IceAuthRejected:
+
+ prefix = (char *)"Authentication Rejected, reason : ";
+ EXTRACT_STRING (pData, swap, temp);
+ errorStr = (char *) malloc (
+ strlen (prefix) + strlen (temp) + 1);
+ sprintf (errorStr, "%s%s", prefix, temp);
+ free (temp);
+ break;
+
+ case IceAuthFailed:
+
+ prefix = (char *)"Authentication Failed, reason : ";
+ EXTRACT_STRING (pData, swap, temp);
+ errorStr = (char *) malloc (
+ strlen (prefix) + strlen (temp) + 1);
+ sprintf (errorStr, "%s%s", prefix, temp);
+ free (temp);
+ break;
+
+ default:
+ invokeHandler = 1;
+ }
+
+ errorReply->type = ICE_CONNECTION_ERROR;
+ errorReply->error_message = errorStr;
+ }
+ else if (iceConn->protosetup_to_you &&
+ ((!iceConn->protosetup_to_you->auth_active &&
+ message->offendingMinorOpcode == ICE_ProtocolSetup) ||
+ (iceConn->protosetup_to_you->auth_active &&
+ message->offendingMinorOpcode == ICE_AuthReply)))
+ {
+ _IceProtocolError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->protocol_error);
+ char *errorStr = (char *)"";
+ char *prefix, *temp;
+
+ invokeHandler = 0;
+ errorReturned = True;
+
+ switch (message->errorClass)
+ {
+ case IceNoVersion:
+
+ temp =
+ (char *)"None of the protocol versions specified are supported";
+ errorStr = (char *) malloc (strlen (temp) + 1);
+ strcpy (errorStr, temp);
+ break;
+
+ case IceNoAuth:
+
+ temp =
+ (char *)"None of the authentication protocols specified are supported";
+ errorStr = (char *) malloc (strlen (temp) + 1);
+ strcpy (errorStr, temp);
+ break;
+
+ case IceSetupFailed:
+
+ prefix = (char *)"Protocol Setup Failed, reason : ";
+
+ EXTRACT_STRING (pData, swap, temp);
+ errorStr = (char *) malloc (
+ strlen (prefix) + strlen (temp) + 1);
+ sprintf (errorStr, "%s%s", prefix, temp);
+ free (temp);
+ break;
+
+ case IceAuthRejected:
+
+ prefix = (char *)"Authentication Rejected, reason : ";
+ EXTRACT_STRING (pData, swap, temp);
+ errorStr = (char *) malloc (
+ strlen (prefix) + strlen (temp) + 1);
+ sprintf (errorStr, "%s%s", prefix, temp);
+ free (temp);
+ break;
+
+ case IceAuthFailed:
+
+ prefix = (char *)"Authentication Failed, reason : ";
+ EXTRACT_STRING (pData, swap, temp);
+ errorStr = (char *) malloc (
+ strlen (prefix) + strlen (temp) + 1);
+ sprintf (errorStr, "%s%s", prefix, temp);
+ free (temp);
+ break;
+
+ case IceProtocolDuplicate:
+
+ prefix = (char *)"Protocol was already registered : ";
+ EXTRACT_STRING (pData, swap, temp);
+ errorStr = (char *) malloc (
+ strlen (prefix) + strlen (temp) + 1);
+ sprintf (errorStr, "%s%s", prefix, temp);
+ free (temp);
+ break;
+
+ case IceMajorOpcodeDuplicate:
+
+ prefix = (char *)"The major opcode was already used : ";
+ errorStr = (char *) malloc (strlen (prefix) + 16);
+ sprintf (errorStr, "%s%d", prefix, (int) *pData);
+ break;
+
+ case IceUnknownProtocol:
+
+ prefix = (char *)"Unknown Protocol : ";
+ EXTRACT_STRING (pData, swap, temp);
+ errorStr = (char *) malloc (
+ strlen (prefix) + strlen (temp) + 1);
+ sprintf (errorStr, "%s%s", prefix, temp);
+ free (temp);
+ break;
+
+ default:
+ invokeHandler = 1;
+ }
+
+ errorReply->type = ICE_PROTOCOL_ERROR;
+ errorReply->error_message = errorStr;
+ }
+
+ if (errorReturned == True)
+ {
+ /*
+ * If we tried to authenticate, tell the authentication
+ * procedure to clean up.
+ */
+
+ IcePoAuthProc authProc;
+
+ if (iceConn->connect_to_you &&
+ iceConn->connect_to_you->auth_active)
+ {
+ authProc = _IcePoAuthProcs[(int)
+ (iceConn->connect_to_you->my_auth_index)];
+
+ (*authProc) (iceConn, &iceConn->connect_to_you->my_auth_state,
+ True /* clean up */, False /* swap */,
+ 0, NULL, NULL, NULL, NULL);
+ }
+ else if (iceConn->protosetup_to_you &&
+ iceConn->protosetup_to_you->auth_active)
+ {
+ _IcePoProtocol *protocol = _IceProtocols[
+ iceConn->protosetup_to_you->my_opcode - 1].orig_client;
+
+ authProc = protocol->auth_procs[(int)(iceConn->
+ protosetup_to_you->my_auth_index)];
+
+ (*authProc) (iceConn,
+ &iceConn->protosetup_to_you->my_auth_state,
+ True /* clean up */, False /* swap */,
+ 0, NULL, NULL, NULL, NULL);
+ }
+ }
+ }
+
+ if (invokeHandler)
+ {
+ (*_IceErrorHandler) (iceConn, swap, message->offendingMinorOpcode,
+ message->offendingSequenceNum, message->errorClass,
+ message->severity, (IcePointer) pData);
+ }
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+
+ return (errorReturned);
+}
+
+
+
+static int
+ProcessConnectionSetup (iceConn, length, swap)
+
+IceConn iceConn;
+unsigned long length;
+Bool swap;
+
+{
+ iceConnectionSetupMsg *message;
+ int myVersionCount, hisVersionCount;
+ int myVersionIndex, hisVersionIndex;
+ int hisMajorVersion, hisMinorVersion;
+ int myAuthCount, hisAuthCount;
+ int found, i, j;
+ const char *myAuthName;
+ char **hisAuthNames = NULL;
+ char *pData, *pStart, *pEnd;
+ char *vendor = NULL;
+ char *release = NULL;
+ int myAuthIndex = 0;
+ int hisAuthIndex = 0;
+ int accept_setup_now = 0;
+ char mustAuthenticate;
+ int authUsableCount;
+ int authUsableFlags[MAX_ICE_AUTH_NAMES];
+ int authIndices[MAX_ICE_AUTH_NAMES];
+
+ CHECK_AT_LEAST_SIZE (iceConn, ICE_ConnectionSetup,
+ length, SIZEOF (iceConnectionSetupMsg), IceFatalToConnection);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (iceConnectionSetupMsg),
+ iceConnectionSetupMsg, message, pStart);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ pData = pStart;
+ pEnd = pStart + (length << 3);
+
+ SKIP_STRING (pData, swap, pEnd,
+ BAIL_STRING(iceConn, ICE_ConnectionSetup,
+ pStart)); /* vendor */
+ SKIP_STRING (pData, swap, pEnd,
+ BAIL_STRING(iceConn, ICE_ConnectionSetup,
+ pStart)); /* release */
+ SKIP_LISTOF_STRING (pData, swap, (int) message->authCount, pEnd,
+ BAIL_STRING(iceConn, ICE_ConnectionSetup,
+ pStart)); /* auth names */
+
+ pData += (message->versionCount * 4); /* versions */
+
+ CHECK_COMPLETE_SIZE (iceConn, ICE_ConnectionSetup,
+ length, pData - pStart + SIZEOF (iceConnectionSetupMsg),
+ pStart, IceFatalToConnection);
+
+ mustAuthenticate = message->mustAuthenticate;
+ if (mustAuthenticate != 0 && mustAuthenticate != 1)
+ {
+ _IceErrorBadValue (iceConn, 0,
+ ICE_ConnectionSetup, 8, 1, &mustAuthenticate);
+ iceConn->connection_status = IceConnectRejected;
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ pData = pStart;
+
+ EXTRACT_STRING (pData, swap, vendor);
+ EXTRACT_STRING (pData, swap, release);
+
+ if ((hisAuthCount = message->authCount) > 0)
+ {
+ hisAuthNames = (char **) malloc (hisAuthCount * sizeof (char *));
+ EXTRACT_LISTOF_STRING (pData, swap, hisAuthCount, hisAuthNames);
+ }
+
+ hisVersionCount = message->versionCount;
+ myVersionCount = _IceVersionCount;
+
+ hisVersionIndex = myVersionIndex = found = 0;
+
+ for (i = 0; i < hisVersionCount && !found; i++)
+ {
+ EXTRACT_CARD16 (pData, swap, hisMajorVersion);
+ EXTRACT_CARD16 (pData, swap, hisMinorVersion);
+
+ for (j = 0; j < myVersionCount && !found; j++)
+ {
+ if (_IceVersions[j].major_version == hisMajorVersion &&
+ _IceVersions[j].minor_version == hisMinorVersion)
+ {
+ hisVersionIndex = i;
+ myVersionIndex = j;
+ found = 1;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ _IceErrorNoVersion (iceConn, ICE_ConnectionSetup);
+ iceConn->connection_status = IceConnectRejected;
+
+ free (vendor);
+ free (release);
+
+ if (hisAuthCount > 0)
+ {
+ for (i = 0; i < hisAuthCount; i++)
+ free (hisAuthNames[i]);
+
+ free ((char *) hisAuthNames);
+ }
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ _IceGetPaValidAuthIndices ("ICE", iceConn->connection_string,
+ _IceAuthCount, _IceAuthNames, &authUsableCount, authIndices);
+
+ for (i = 0; i < _IceAuthCount; i++)
+ {
+ authUsableFlags[i] = 0;
+ for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++)
+ authUsableFlags[i] = (authIndices[j] == i);
+ }
+
+ myAuthCount = _IceAuthCount;
+
+ for (i = found = 0; i < myAuthCount && !found; i++)
+ {
+ if (authUsableFlags[i])
+ {
+ myAuthName = _IceAuthNames[i];
+
+ for (j = 0; j < hisAuthCount && !found; j++)
+ if (strcmp (myAuthName, hisAuthNames[j]) == 0)
+ {
+ myAuthIndex = i;
+ hisAuthIndex = j;
+ found = 1;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ /*
+ * None of the authentication methods specified by the
+ * other client is supported. If the other client requires
+ * authentication, we must reject the connection now.
+ * Otherwise, we can invoke the host-based authentication callback
+ * to see if we can accept this connection.
+ */
+
+ if (mustAuthenticate || !iceConn->listen_obj->host_based_auth_proc)
+ {
+ _IceErrorNoAuthentication (iceConn, ICE_ConnectionSetup);
+ iceConn->connection_status = IceConnectRejected;
+ }
+ else
+ {
+ char *hostname = _IceGetPeerName (iceConn);
+
+ if ((*iceConn->listen_obj->host_based_auth_proc) (hostname))
+ {
+ accept_setup_now = 1;
+ }
+ else
+ {
+ _IceErrorAuthenticationRejected (iceConn,
+ ICE_ConnectionSetup, "None of the authentication protocols specified are supported and host-based authentication failed");
+
+ iceConn->connection_status = IceConnectRejected;
+ }
+
+ if (hostname)
+ free (hostname);
+ }
+
+ if (iceConn->connection_status == IceConnectRejected)
+ {
+ free (vendor);
+ free (release);
+ }
+ }
+ else
+ {
+ IcePaAuthStatus status;
+ int authDataLen;
+ IcePointer authData = NULL;
+ IcePointer authState;
+ char *errorString = NULL;
+ IcePaAuthProc authProc = _IcePaAuthProcs[myAuthIndex];
+
+ authState = NULL;
+
+ status = (*authProc) (iceConn, &authState,
+ swap, 0, NULL, &authDataLen, &authData, &errorString);
+
+ if (status == IcePaAuthContinue)
+ {
+ _IceConnectToMeInfo *setupInfo;
+
+ AuthRequired (iceConn, hisAuthIndex, authDataLen, authData);
+
+ iceConn->connect_to_me = setupInfo = (_IceConnectToMeInfo *)
+ malloc (sizeof (_IceConnectToMeInfo));
+
+ setupInfo->my_version_index = myVersionIndex;
+ setupInfo->his_version_index = hisVersionIndex;
+ setupInfo->his_vendor = vendor;
+ setupInfo->his_release = release;
+ setupInfo->my_auth_index = myAuthIndex;
+ setupInfo->my_auth_state = authState;
+ setupInfo->must_authenticate = mustAuthenticate;
+ }
+ else if (status == IcePaAuthAccepted)
+ {
+ accept_setup_now = 1;
+ }
+
+ if (authData && authDataLen > 0)
+ free ((char *) authData);
+
+ if (errorString)
+ free (errorString);
+ }
+
+ if (accept_setup_now)
+ {
+ AcceptConnection (iceConn, hisVersionIndex);
+
+ iceConn->vendor = vendor;
+ iceConn->release = release;
+ iceConn->my_ice_version_index = myVersionIndex;
+ }
+
+ if (hisAuthCount > 0)
+ {
+ for (i = 0; i < hisAuthCount; i++)
+ free (hisAuthNames[i]);
+
+ free ((char *) hisAuthNames);
+ }
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+}
+
+
+
+static Bool
+ProcessAuthRequired (iceConn, length, swap, replyWait)
+
+IceConn iceConn;
+unsigned long length;
+Bool swap;
+IceReplyWaitInfo *replyWait;
+
+{
+ iceAuthRequiredMsg *message;
+ int authDataLen;
+ IcePointer authData;
+ int replyDataLen;
+ IcePointer replyData = NULL;
+ char *errorString = NULL;
+ IcePoAuthProc authProc;
+ IcePoAuthStatus status;
+ IcePointer authState;
+ int realAuthIndex = 0;
+
+ CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthRequired,
+ length, SIZEOF (iceAuthRequiredMsg),
+ iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (iceAuthRequiredMsg),
+ iceAuthRequiredMsg, message, authData);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, authData);
+ return (0);
+ }
+
+ if (swap)
+ {
+ message->authDataLength = lswaps (message->authDataLength);
+ }
+
+ CHECK_COMPLETE_SIZE (iceConn, ICE_AuthRequired, length,
+ message->authDataLength + SIZEOF (iceAuthRequiredMsg), authData,
+ iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
+
+ if (iceConn->connect_to_you)
+ {
+ if ((int) message->authIndex >= _IceAuthCount)
+ {
+ _IceConnectionError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->connection_error);
+
+ char *tempstr = (char *)"Received bad authIndex in the AuthRequired message";
+ char errIndex = (int) message->authIndex;
+
+ errorString = (char *) malloc (strlen (tempstr) + 1);
+ strcpy (errorString, tempstr);
+
+ errorReply->type = ICE_CONNECTION_ERROR;
+ errorReply->error_message = errorString;
+
+ _IceErrorBadValue (iceConn, 0,
+ ICE_AuthRequired, 2, 1, &errIndex);
+
+ IceDisposeCompleteMessage (iceConn, authData);
+ return (1);
+ }
+ else
+ {
+ authProc = _IcePoAuthProcs[message->authIndex];
+
+ iceConn->connect_to_you->auth_active = 1;
+ }
+ }
+ else if (iceConn->protosetup_to_you)
+ {
+ if ((int) message->authIndex >=
+ iceConn->protosetup_to_you->my_auth_count)
+ {
+ _IceProtocolError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->protocol_error);
+
+ char *tempstr = (char *)"Received bad authIndex in the AuthRequired message";
+ char errIndex = (int) message->authIndex;
+
+ errorString = (char *) malloc (strlen (tempstr) + 1);
+ strcpy (errorString, tempstr);
+
+ errorReply->type = ICE_PROTOCOL_ERROR;
+ errorReply->error_message = errorString;
+
+ _IceErrorBadValue (iceConn, 0,
+ ICE_AuthRequired, 2, 1, &errIndex);
+
+ IceDisposeCompleteMessage (iceConn, authData);
+ return (1);
+ }
+ else
+ {
+ _IcePoProtocol *myProtocol = _IceProtocols[
+ iceConn->protosetup_to_you->my_opcode - 1].orig_client;
+
+ realAuthIndex = iceConn->protosetup_to_you->
+ my_auth_indices[message->authIndex];
+
+ authProc = myProtocol->auth_procs[realAuthIndex];
+
+ iceConn->protosetup_to_you->auth_active = 1;
+ }
+ }
+ else
+ {
+ /*
+ * Unexpected message
+ */
+
+ _IceErrorBadState (iceConn, 0, ICE_AuthRequired, IceCanContinue);
+
+ IceDisposeCompleteMessage (iceConn, authData);
+ return (0);
+ }
+
+ authState = NULL;
+ authDataLen = message->authDataLength;
+
+ status = (*authProc) (iceConn, &authState, False /* don't clean up */,
+ swap, authDataLen, authData, &replyDataLen, &replyData, &errorString);
+
+ if (status == IcePoAuthHaveReply)
+ {
+ AuthReply (iceConn, replyDataLen, replyData);
+
+ replyWait->sequence_of_request = iceConn->send_sequence;
+ replyWait->minor_opcode_of_request = ICE_AuthReply;
+
+ if (iceConn->connect_to_you)
+ {
+ iceConn->connect_to_you->my_auth_state = authState;
+ iceConn->connect_to_you->my_auth_index = message->authIndex;
+ }
+ else if (iceConn->protosetup_to_you)
+ {
+ iceConn->protosetup_to_you->my_auth_state = authState;
+ iceConn->protosetup_to_you->my_auth_index = realAuthIndex;
+ }
+ }
+ else if (status == IcePoAuthRejected || status == IcePoAuthFailed)
+ {
+ char *prefix, *returnErrorString;
+
+ if (status == IcePoAuthRejected)
+ {
+ _IceErrorAuthenticationRejected (iceConn,
+ ICE_AuthRequired, errorString);
+
+ prefix = (char *)"Authentication Rejected, reason : ";
+ }
+ else
+ {
+ _IceErrorAuthenticationFailed (iceConn,
+ ICE_AuthRequired, errorString);
+
+ prefix = (char *)"Authentication Failed, reason : ";
+ }
+
+ returnErrorString = (char *) malloc (strlen (prefix) +
+ strlen (errorString) + 1);
+ sprintf (returnErrorString, "%s%s", prefix, errorString);
+ free (errorString);
+
+ if (iceConn->connect_to_you)
+ {
+ _IceConnectionError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->connection_error);
+
+ errorReply->type = ICE_CONNECTION_ERROR;
+ errorReply->error_message = returnErrorString;
+ }
+ else
+ {
+ _IceProtocolError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->protocol_error);
+
+ errorReply->type = ICE_PROTOCOL_ERROR;
+ errorReply->error_message = returnErrorString;
+ }
+ }
+
+ if (replyData && replyDataLen > 0)
+ free ((char *) replyData);
+
+ IceDisposeCompleteMessage (iceConn, authData);
+
+ return (status != IcePoAuthHaveReply);
+}
+
+
+
+static int
+ProcessAuthReply (iceConn, length, swap)
+
+IceConn iceConn;
+unsigned long length;
+Bool swap;
+
+{
+ iceAuthReplyMsg *message;
+ int replyDataLen;
+ IcePointer replyData;
+ int authDataLen;
+ IcePointer authData = NULL;
+ char *errorString = NULL;
+
+ CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthReply,
+ length, SIZEOF (iceAuthReplyMsg),
+ iceConn->connect_to_me ? IceFatalToConnection : IceFatalToProtocol);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (iceAuthReplyMsg),
+ iceAuthReplyMsg, message, replyData);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, replyData);
+ return (0);
+ }
+
+ if (swap)
+ {
+ message->authDataLength = lswaps (message->authDataLength);
+ }
+
+ CHECK_COMPLETE_SIZE (iceConn, ICE_AuthReply, length,
+ message->authDataLength + SIZEOF (iceAuthReplyMsg), replyData,
+ iceConn->connect_to_me ? IceFatalToConnection : IceFatalToProtocol);
+
+ replyDataLen = message->authDataLength;
+
+ if (iceConn->connect_to_me)
+ {
+ IcePaAuthProc authProc = _IcePaAuthProcs[(int)
+ (iceConn->connect_to_me->my_auth_index)];
+ IcePaAuthStatus status =
+ (*authProc) (iceConn, &iceConn->connect_to_me->my_auth_state, swap,
+ replyDataLen, replyData, &authDataLen, &authData, &errorString);
+
+ if (status == IcePaAuthContinue)
+ {
+ AuthNextPhase (iceConn, authDataLen, authData);
+ }
+ else if (status == IcePaAuthRejected || status == IcePaAuthFailed)
+ {
+ /*
+ * Before we reject, invoke host-based authentication callback
+ * and give it a chance to accept the connection (only if the
+ * other client doesn't require authentication).
+ */
+
+ if (!iceConn->connect_to_me->must_authenticate &&
+ iceConn->listen_obj->host_based_auth_proc)
+ {
+ char *hostname = _IceGetPeerName (iceConn);
+
+ if ((*iceConn->listen_obj->host_based_auth_proc) (hostname))
+ {
+ status = IcePaAuthAccepted;
+ }
+
+ if (hostname)
+ free (hostname);
+ }
+
+ if (status != IcePaAuthAccepted)
+ {
+ free (iceConn->connect_to_me->his_vendor);
+ free (iceConn->connect_to_me->his_release);
+ free ((char *) iceConn->connect_to_me);
+ iceConn->connect_to_me = NULL;
+
+ iceConn->connection_status = IceConnectRejected;
+
+ if (status == IcePaAuthRejected)
+ {
+ _IceErrorAuthenticationRejected (iceConn,
+ ICE_AuthReply, errorString);
+ }
+ else
+ {
+ _IceErrorAuthenticationFailed (iceConn,
+ ICE_AuthReply, errorString);
+ }
+ }
+ }
+
+ if (status == IcePaAuthAccepted)
+ {
+ AcceptConnection (iceConn,
+ iceConn->connect_to_me->his_version_index);
+
+ iceConn->vendor = iceConn->connect_to_me->his_vendor;
+ iceConn->release = iceConn->connect_to_me->his_release;
+ iceConn->my_ice_version_index =
+ iceConn->connect_to_me->my_version_index;
+
+ free ((char *) iceConn->connect_to_me);
+ iceConn->connect_to_me = NULL;
+ }
+ }
+ else if (iceConn->protosetup_to_me)
+ {
+ _IcePaProtocol *myProtocol = _IceProtocols[iceConn->protosetup_to_me->
+ my_opcode - 1].accept_client;
+ IcePaAuthProc authProc = myProtocol->auth_procs[(int)
+ (iceConn->protosetup_to_me->my_auth_index)];
+ IcePaAuthStatus status =
+ (*authProc) (iceConn, &iceConn->protosetup_to_me->my_auth_state,
+ swap, replyDataLen, replyData,
+ &authDataLen, &authData, &errorString);
+ int free_setup_info = 1;
+
+ if (status == IcePaAuthContinue)
+ {
+ AuthNextPhase (iceConn, authDataLen, authData);
+ free_setup_info = 0;
+ }
+ else if (status == IcePaAuthRejected || status == IcePaAuthFailed)
+ {
+ /*
+ * Before we reject, invoke host-based authentication callback
+ * and give it a chance to accept the Protocol Setup (only if the
+ * other client doesn't require authentication).
+ */
+
+ if (!iceConn->protosetup_to_me->must_authenticate &&
+ myProtocol->host_based_auth_proc)
+ {
+ char *hostname = _IceGetPeerName (iceConn);
+
+ if ((*myProtocol->host_based_auth_proc) (hostname))
+ {
+ status = IcePaAuthAccepted;
+ }
+
+ if (hostname)
+ free (hostname);
+ }
+
+ if (status == IcePaAuthRejected)
+ {
+ _IceErrorAuthenticationRejected (iceConn,
+ ICE_AuthReply, errorString);
+ }
+ else
+ {
+ _IceErrorAuthenticationFailed (iceConn,
+ ICE_AuthReply, errorString);
+ }
+ }
+
+ if (status == IcePaAuthAccepted)
+ {
+ IcePaProcessMsgProc processMsgProc;
+ IceProtocolSetupProc protocolSetupProc;
+ IceProtocolActivateProc protocolActivateProc;
+ _IceProcessMsgInfo *process_msg_info;
+ IcePointer clientData = NULL;
+ char *failureReason = NULL;
+ Status con_status = 1;
+
+ protocolSetupProc = myProtocol->protocol_setup_proc;
+ protocolActivateProc = myProtocol->protocol_activate_proc;
+
+ if (protocolSetupProc)
+ {
+ /*
+ * Notify the client of the Protocol Setup.
+ */
+
+ con_status = (*protocolSetupProc) (iceConn,
+ myProtocol->version_recs[iceConn->protosetup_to_me->
+ my_version_index].major_version,
+ myProtocol->version_recs[iceConn->protosetup_to_me->
+ my_version_index].minor_version,
+ iceConn->protosetup_to_me->his_vendor,
+ iceConn->protosetup_to_me->his_release,
+ &clientData, &failureReason);
+
+ /*
+ * Set vendor and release pointers to NULL, so it won't
+ * get freed below. The ProtocolSetupProc should
+ * free it.
+ */
+
+ iceConn->protosetup_to_me->his_vendor = NULL;
+ iceConn->protosetup_to_me->his_release = NULL;
+ }
+
+ if (con_status != 0)
+ {
+ /*
+ * Send the Protocol Reply
+ */
+
+ AcceptProtocol (iceConn,
+ iceConn->protosetup_to_me->his_opcode,
+ iceConn->protosetup_to_me->my_opcode,
+ iceConn->protosetup_to_me->his_version_index,
+ myProtocol->vendor, myProtocol->release);
+
+
+ /*
+ * Set info for this protocol.
+ */
+
+ processMsgProc = myProtocol->version_recs[
+ iceConn->protosetup_to_me->
+ my_version_index].process_msg_proc;
+
+ process_msg_info = &iceConn->process_msg_info[
+ iceConn->protosetup_to_me->
+ his_opcode -iceConn->his_min_opcode];
+
+ process_msg_info->client_data = clientData;
+ process_msg_info->accept_flag = 1;
+ process_msg_info->process_msg_proc.
+ accept_client = processMsgProc;
+
+
+ /*
+ * Increase the reference count for the number
+ * of active protocols.
+ */
+
+ iceConn->proto_ref_count++;
+
+
+ /*
+ * Notify the client that the protocol is active. The reason
+ * we have this 2nd callback invoked is because the client
+ * may wish to immediately generate a message for this
+ * protocol, but it must wait until we send the Protocol Reply.
+ */
+
+ if (protocolActivateProc)
+ {
+ (*protocolActivateProc) (iceConn,
+ process_msg_info->client_data);
+ }
+ }
+ else
+ {
+ /*
+ * An error was encountered.
+ */
+
+ _IceErrorSetupFailed (iceConn, ICE_ProtocolSetup,
+ failureReason);
+
+ if (failureReason)
+ free (failureReason);
+ }
+ }
+
+
+ if (free_setup_info)
+ {
+ if (iceConn->protosetup_to_me->his_vendor)
+ free (iceConn->protosetup_to_me->his_vendor);
+ if (iceConn->protosetup_to_me->his_release)
+ free (iceConn->protosetup_to_me->his_release);
+ free ((char *) iceConn->protosetup_to_me);
+ iceConn->protosetup_to_me = NULL;
+ }
+ }
+ else
+ {
+ /*
+ * Unexpected message
+ */
+
+ _IceErrorBadState (iceConn, 0, ICE_AuthReply, IceCanContinue);
+ }
+
+ if (authData && authDataLen > 0)
+ free ((char *) authData);
+
+ if (errorString)
+ free (errorString);
+
+ IceDisposeCompleteMessage (iceConn, replyData);
+ return (0);
+}
+
+
+
+static Bool
+ProcessAuthNextPhase (iceConn, length, swap, replyWait)
+
+IceConn iceConn;
+unsigned long length;
+Bool swap;
+IceReplyWaitInfo *replyWait;
+
+{
+ iceAuthNextPhaseMsg *message;
+ int authDataLen;
+ IcePointer authData;
+ int replyDataLen;
+ IcePointer replyData = NULL;
+ char *errorString = NULL;
+ IcePoAuthProc authProc;
+ IcePoAuthStatus status;
+ IcePointer *authState;
+
+ CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthNextPhase,
+ length, SIZEOF (iceAuthNextPhaseMsg),
+ iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (iceAuthNextPhaseMsg),
+ iceAuthNextPhaseMsg, message, authData);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, authData);
+ return (0);
+ }
+
+ if (swap)
+ {
+ message->authDataLength = lswaps (message->authDataLength);
+ }
+
+ CHECK_COMPLETE_SIZE (iceConn, ICE_AuthNextPhase, length,
+ message->authDataLength + SIZEOF (iceAuthNextPhaseMsg), authData,
+ iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
+
+ if (iceConn->connect_to_you)
+ {
+ authProc = _IcePoAuthProcs[(int)
+ (iceConn->connect_to_you->my_auth_index)];
+
+ authState = &iceConn->connect_to_you->my_auth_state;
+ }
+ else if (iceConn->protosetup_to_you)
+ {
+ _IcePoProtocol *myProtocol =
+ _IceProtocols[iceConn->protosetup_to_you->my_opcode - 1].orig_client;
+
+ authProc = myProtocol->auth_procs[(int)
+ (iceConn->protosetup_to_you->my_auth_index)];
+
+ authState = &iceConn->protosetup_to_you->my_auth_state;
+ }
+ else
+ {
+ /*
+ * Unexpected message
+ */
+
+ _IceErrorBadState (iceConn, 0, ICE_AuthNextPhase, IceCanContinue);
+
+ IceDisposeCompleteMessage (iceConn, authData);
+ return (0);
+ }
+
+ authDataLen = message->authDataLength;
+
+ status = (*authProc) (iceConn, authState, False /* don't clean up */,
+ swap, authDataLen, authData, &replyDataLen, &replyData, &errorString);
+
+ if (status == IcePoAuthHaveReply)
+ {
+ AuthReply (iceConn, replyDataLen, replyData);
+
+ replyWait->sequence_of_request = iceConn->send_sequence;
+ }
+ else if (status == IcePoAuthRejected || status == IcePoAuthFailed)
+ {
+ char *prefix = NULL;
+ char *returnErrorString;
+
+ if (status == IcePoAuthRejected)
+ {
+ _IceErrorAuthenticationRejected (iceConn,
+ ICE_AuthNextPhase, errorString);
+
+ prefix = (char *)"Authentication Rejected, reason : ";
+ }
+ else if (status == IcePoAuthFailed)
+ {
+ _IceErrorAuthenticationFailed (iceConn,
+ ICE_AuthNextPhase, errorString);
+
+ prefix = (char *)"Authentication Failed, reason : ";
+ }
+
+ returnErrorString = (char *) malloc (strlen (prefix) +
+ strlen (errorString) + 1);
+ sprintf (returnErrorString, "%s%s", prefix, errorString);
+ free (errorString);
+
+ if (iceConn->connect_to_you)
+ {
+ _IceConnectionError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->connection_error);
+
+ errorReply->type = ICE_CONNECTION_ERROR;
+ errorReply->error_message = returnErrorString;
+ }
+ else
+ {
+ _IceProtocolError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->protocol_error);
+
+ errorReply->type = ICE_PROTOCOL_ERROR;
+ errorReply->error_message = returnErrorString;
+ }
+ }
+
+ if (replyData && replyDataLen > 0)
+ free ((char *) replyData);
+
+ IceDisposeCompleteMessage (iceConn, authData);
+
+ return (status != IcePoAuthHaveReply);
+}
+
+
+
+static Bool
+ProcessConnectionReply (iceConn, length, swap, replyWait)
+
+IceConn iceConn;
+unsigned long length;
+Bool swap;
+IceReplyWaitInfo *replyWait;
+
+{
+ iceConnectionReplyMsg *message;
+ char *pData, *pStart, *pEnd;
+ Bool replyReady;
+
+ CHECK_AT_LEAST_SIZE (iceConn, ICE_ConnectionReply,
+ length, SIZEOF (iceConnectionReplyMsg), IceFatalToConnection);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (iceConnectionReplyMsg),
+ iceConnectionReplyMsg, message, pStart);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ pData = pStart;
+ pEnd = pStart + (length << 3);
+
+ SKIP_STRING (pData, swap, pEnd,
+ BAIL_STRING (iceConn, ICE_ConnectionReply,
+ pStart)); /* vendor */
+ SKIP_STRING (pData, swap, pEnd,
+ BAIL_STRING (iceConn, ICE_ConnectionReply,
+ pStart)); /* release */
+
+ CHECK_COMPLETE_SIZE (iceConn, ICE_ConnectionReply,
+ length, pData - pStart + SIZEOF (iceConnectionReplyMsg),
+ pStart, IceFatalToConnection);
+
+ pData = pStart;
+
+ if (iceConn->connect_to_you)
+ {
+ if (iceConn->connect_to_you->auth_active)
+ {
+ /*
+ * Tell the authentication procedure to clean up.
+ */
+
+ IcePoAuthProc authProc = _IcePoAuthProcs[(int)
+ (iceConn->connect_to_you->my_auth_index)];
+
+ (*authProc) (iceConn, &iceConn->connect_to_you->my_auth_state,
+ True /* clean up */, False /* swap */,
+ 0, NULL, NULL, NULL, NULL);
+ }
+
+ if ((int) message->versionIndex >= _IceVersionCount)
+ {
+ _IceConnectionError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->connection_error);
+ char errIndex = message->versionIndex;
+
+ _IceErrorBadValue (iceConn, 0,
+ ICE_ConnectionReply, 2, 1, &errIndex);
+
+ errorReply->type = ICE_CONNECTION_ERROR;
+ errorReply->error_message =
+ (char *)"Received bad version index in Connection Reply";
+ }
+ else
+ {
+ _IceReply *reply = (_IceReply *) (replyWait->reply);
+
+ reply->type = ICE_CONNECTION_REPLY;
+ reply->connection_reply.version_index = message->versionIndex;
+
+ EXTRACT_STRING (pData, swap, reply->connection_reply.vendor);
+ EXTRACT_STRING (pData, swap, reply->connection_reply.release);
+ }
+
+ replyReady = True;
+ }
+ else
+ {
+ /*
+ * Unexpected message
+ */
+
+ _IceErrorBadState (iceConn, 0, ICE_ConnectionReply, IceCanContinue);
+
+ replyReady = False;
+ }
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+
+ return (replyReady);
+}
+
+
+
+static int
+ProcessProtocolSetup (iceConn, length, swap)
+
+IceConn iceConn;
+unsigned long length;
+Bool swap;
+
+{
+ iceProtocolSetupMsg *message;
+ _IcePaProtocol *myProtocol;
+ int myVersionCount, hisVersionCount;
+ int myVersionIndex, hisVersionIndex;
+ int hisMajorVersion, hisMinorVersion;
+ int myAuthCount, hisAuthCount;
+ int myOpcode, hisOpcode;
+ int found, i, j;
+ char *myAuthName;
+ char **hisAuthNames = NULL;
+ char *protocolName;
+ char *pData, *pStart, *pEnd;
+ char *vendor = NULL;
+ char *release = NULL;
+ int accept_setup_now = 0;
+ int myAuthIndex = 0;
+ int hisAuthIndex = 0;
+ char mustAuthenticate;
+ int authUsableCount;
+ int authUsableFlags[MAX_ICE_AUTH_NAMES];
+ int authIndices[MAX_ICE_AUTH_NAMES];
+
+ CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolSetup,
+ length, SIZEOF (iceProtocolSetupMsg), IceFatalToProtocol);
+
+ if (iceConn->want_to_close)
+ {
+ /*
+ * If we sent a WantToClose message, but just got a ProtocolSetup,
+ * we must cancel our WantToClose. It is the responsiblity of the
+ * other client to send a WantToClose later on.
+ */
+
+ iceConn->want_to_close = 0;
+ }
+
+ IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolSetupMsg),
+ iceProtocolSetupMsg, message, pStart);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ pData = pStart;
+ pEnd = pStart + (length << 3);
+
+ SKIP_STRING (pData, swap, pEnd,
+ BAIL_STRING(iceConn, ICE_ProtocolSetup,
+ pStart)); /* proto name */
+ SKIP_STRING (pData, swap, pEnd,
+ BAIL_STRING(iceConn, ICE_ProtocolSetup,
+ pStart)); /* vendor */
+ SKIP_STRING (pData, swap, pEnd,
+ BAIL_STRING(iceConn, ICE_ProtocolSetup,
+ pStart)); /* release */
+ SKIP_LISTOF_STRING (pData, swap, (int) message->authCount, pEnd,
+ BAIL_STRING(iceConn, ICE_ProtocolSetup,
+ pStart)); /* auth names */
+ pData += (message->versionCount * 4); /* versions */
+
+ CHECK_COMPLETE_SIZE (iceConn, ICE_ProtocolSetup,
+ length, pData - pStart + SIZEOF (iceProtocolSetupMsg),
+ pStart, IceFatalToProtocol);
+
+ mustAuthenticate = message->mustAuthenticate;
+
+ if (mustAuthenticate != 0 && mustAuthenticate != 1)
+ {
+ _IceErrorBadValue (iceConn, 0,
+ ICE_ProtocolSetup, 4, 1, &mustAuthenticate);
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ pData = pStart;
+
+ if (iceConn->process_msg_info &&
+ (int) message->protocolOpcode >= iceConn->his_min_opcode &&
+ (int) message->protocolOpcode <= iceConn->his_max_opcode &&
+ iceConn->process_msg_info[
+ message->protocolOpcode - iceConn->his_min_opcode].in_use)
+ {
+ _IceErrorMajorOpcodeDuplicate (iceConn, message->protocolOpcode);
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ EXTRACT_STRING (pData, swap, protocolName);
+
+ if (iceConn->process_msg_info)
+ {
+ for (i = 0;
+ i <= (iceConn->his_max_opcode - iceConn->his_min_opcode); i++)
+ {
+ if (iceConn->process_msg_info[i].in_use && strcmp (protocolName,
+ iceConn->process_msg_info[i].protocol->protocol_name) == 0)
+ {
+ _IceErrorProtocolDuplicate (iceConn, protocolName);
+ free (protocolName);
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+ }
+ }
+
+ for (i = 0; i < _IceLastMajorOpcode; i++)
+ if (strcmp (protocolName, _IceProtocols[i].protocol_name) == 0)
+ break;
+
+ if (i < _IceLastMajorOpcode &&
+ (myProtocol = _IceProtocols[i].accept_client) != NULL)
+ {
+ hisOpcode = message->protocolOpcode;
+ myOpcode = i + 1;
+ free (protocolName);
+ }
+ else
+ {
+ _IceErrorUnknownProtocol (iceConn, protocolName);
+ free (protocolName);
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ EXTRACT_STRING (pData, swap, vendor);
+ EXTRACT_STRING (pData, swap, release);
+
+ if ((hisAuthCount = message->authCount) > 0)
+ {
+ hisAuthNames = (char **) malloc (hisAuthCount * sizeof (char *));
+ EXTRACT_LISTOF_STRING (pData, swap, hisAuthCount, hisAuthNames);
+ }
+
+ hisVersionCount = message->versionCount;
+ myVersionCount = myProtocol->version_count;
+
+ hisVersionIndex = myVersionIndex = found = 0;
+
+ for (i = 0; i < hisVersionCount && !found; i++)
+ {
+ EXTRACT_CARD16 (pData, swap, hisMajorVersion);
+ EXTRACT_CARD16 (pData, swap, hisMinorVersion);
+
+ for (j = 0; j < myVersionCount && !found; j++)
+ {
+ if (myProtocol->version_recs[j].major_version == hisMajorVersion &&
+ myProtocol->version_recs[j].minor_version == hisMinorVersion)
+ {
+ hisVersionIndex = i;
+ myVersionIndex = j;
+ found = 1;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ _IceErrorNoVersion (iceConn, ICE_ProtocolSetup);
+
+ free (vendor);
+ free (release);
+
+ if (hisAuthCount > 0)
+ {
+ for (i = 0; i < hisAuthCount; i++)
+ free (hisAuthNames[i]);
+
+ free ((char *) hisAuthNames);
+ }
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ myAuthCount = myProtocol->auth_count;
+
+ _IceGetPaValidAuthIndices (
+ _IceProtocols[myOpcode - 1].protocol_name,
+ iceConn->connection_string, myAuthCount, (const char **)myProtocol->auth_names,
+ &authUsableCount, authIndices);
+
+ for (i = 0; i < myAuthCount; i++)
+ {
+ authUsableFlags[i] = 0;
+ for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++)
+ authUsableFlags[i] = (authIndices[j] == i);
+ }
+
+ for (i = found = 0; i < myAuthCount && !found; i++)
+ {
+ if (authUsableFlags[i])
+ {
+ myAuthName = myProtocol->auth_names[i];
+
+ for (j = 0; j < hisAuthCount && !found; j++)
+ if (strcmp (myAuthName, hisAuthNames[j]) == 0)
+ {
+ myAuthIndex = i;
+ hisAuthIndex = j;
+ found = 1;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ /*
+ * None of the authentication methods specified by the
+ * other client is supported. If the other client requires
+ * authentication, we must reject the Protocol Setup now.
+ * Otherwise, we can invoke the host-based authentication callback
+ * to see if we can accept this Protocol Setup.
+ */
+
+ if (mustAuthenticate || !myProtocol->host_based_auth_proc)
+ {
+ _IceErrorNoAuthentication (iceConn, ICE_ProtocolSetup);
+ }
+ else
+ {
+ char *hostname = _IceGetPeerName (iceConn);
+
+ if ((*myProtocol->host_based_auth_proc) (hostname))
+ {
+ accept_setup_now = 1;
+ }
+ else
+ {
+ _IceErrorAuthenticationRejected (iceConn,
+ ICE_ProtocolSetup, "None of the authentication protocols specified are supported and host-based authentication failed");
+ }
+
+ if (hostname)
+ free (hostname);
+ }
+ }
+ else
+ {
+ IcePaAuthStatus status;
+ int authDataLen;
+ IcePointer authData = NULL;
+ IcePointer authState;
+ char *errorString = NULL;
+ IcePaAuthProc authProc =
+ myProtocol->auth_procs[myAuthIndex];
+
+ authState = NULL;
+
+ status = (*authProc) (iceConn, &authState, swap, 0, NULL,
+ &authDataLen, &authData, &errorString);
+
+ if (status == IcePaAuthContinue)
+ {
+ _IceProtoSetupToMeInfo *setupInfo;
+
+ AuthRequired (iceConn, hisAuthIndex, authDataLen, authData);
+
+ iceConn->protosetup_to_me = setupInfo =
+ (_IceProtoSetupToMeInfo *) malloc (
+ sizeof (_IceProtoSetupToMeInfo));
+
+ setupInfo->his_opcode = hisOpcode;
+ setupInfo->my_opcode = myOpcode;
+ setupInfo->my_version_index = myVersionIndex;
+ setupInfo->his_version_index = hisVersionIndex;
+ setupInfo->his_vendor = vendor;
+ setupInfo->his_release = release;
+ vendor = release = NULL; /* so we don't free it */
+ setupInfo->my_auth_index = myAuthIndex;
+ setupInfo->my_auth_state = authState;
+ setupInfo->must_authenticate = mustAuthenticate;
+ }
+ else if (status == IcePaAuthAccepted)
+ {
+ accept_setup_now = 1;
+ }
+
+ if (authData && authDataLen > 0)
+ free ((char *) authData);
+
+ if (errorString)
+ free (errorString);
+ }
+
+ if (accept_setup_now)
+ {
+ IcePaProcessMsgProc processMsgProc;
+ IceProtocolSetupProc protocolSetupProc;
+ IceProtocolActivateProc protocolActivateProc;
+ _IceProcessMsgInfo *process_msg_info;
+ IcePointer clientData = NULL;
+ char *failureReason = NULL;
+ Status status = 1;
+
+ protocolSetupProc = myProtocol->protocol_setup_proc;
+ protocolActivateProc = myProtocol->protocol_activate_proc;
+
+ if (protocolSetupProc)
+ {
+ /*
+ * Notify the client of the Protocol Setup.
+ */
+
+ status = (*protocolSetupProc) (iceConn,
+ myProtocol->version_recs[myVersionIndex].major_version,
+ myProtocol->version_recs[myVersionIndex].minor_version,
+ vendor, release, &clientData, &failureReason);
+
+ vendor = release = NULL; /* so we don't free it */
+ }
+
+ if (status != 0)
+ {
+ /*
+ * Send the Protocol Reply
+ */
+
+ AcceptProtocol (iceConn, hisOpcode, myOpcode, hisVersionIndex,
+ myProtocol->vendor, myProtocol->release);
+
+
+ /*
+ * Set info for this protocol.
+ */
+
+ processMsgProc = myProtocol->version_recs[
+ myVersionIndex].process_msg_proc;
+
+ process_msg_info = &iceConn->process_msg_info[hisOpcode -
+ iceConn->his_min_opcode];
+
+ process_msg_info->client_data = clientData;
+ process_msg_info->accept_flag = 1;
+ process_msg_info->process_msg_proc.accept_client = processMsgProc;
+
+
+ /*
+ * Increase the reference count for the number of active protocols.
+ */
+
+ iceConn->proto_ref_count++;
+
+
+ /*
+ * Notify the client that the protocol is active. The reason
+ * we have this 2nd callback invoked is because the client
+ * may wish to immediately generate a message for this
+ * protocol, but it must wait until we send the Protocol Reply.
+ */
+
+ if (protocolActivateProc)
+ {
+ (*protocolActivateProc) (iceConn,
+ process_msg_info->client_data);
+ }
+ }
+ else
+ {
+ /*
+ * An error was encountered.
+ */
+
+ _IceErrorSetupFailed (iceConn, ICE_ProtocolSetup, failureReason);
+
+ if (failureReason)
+ free (failureReason);
+ }
+ }
+
+ if (vendor)
+ free (vendor);
+
+ if (release)
+ free (release);
+
+ if (hisAuthCount > 0)
+ {
+ for (i = 0; i < hisAuthCount; i++)
+ free (hisAuthNames[i]);
+
+ free ((char *) hisAuthNames);
+ }
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+}
+
+
+
+static Bool
+ProcessProtocolReply (iceConn, length, swap, replyWait)
+
+IceConn iceConn;
+unsigned long length;
+Bool swap;
+IceReplyWaitInfo *replyWait;
+
+{
+ iceProtocolReplyMsg *message;
+ char *pData, *pStart, *pEnd;
+ Bool replyReady;
+
+ CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolReply,
+ length, SIZEOF (iceProtocolReplyMsg), IceFatalToProtocol);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolReplyMsg),
+ iceProtocolReplyMsg, message, pStart);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ pData = pStart;
+ pEnd = pStart + (length << 3);
+
+ SKIP_STRING (pData, swap, pEnd,
+ BAIL_STRING(iceConn, ICE_ProtocolReply,
+ pStart)); /* vendor */
+ SKIP_STRING (pData, swap, pEnd,
+ BAIL_STRING(iceConn, ICE_ProtocolReply,
+ pStart)); /* release */
+
+ CHECK_COMPLETE_SIZE (iceConn, ICE_ProtocolReply,
+ length, pData - pStart + SIZEOF (iceProtocolReplyMsg),
+ pStart, IceFatalToProtocol);
+
+ pData = pStart;
+
+ if (iceConn->protosetup_to_you)
+ {
+ if (iceConn->protosetup_to_you->auth_active)
+ {
+ /*
+ * Tell the authentication procedure to clean up.
+ */
+
+ _IcePoProtocol *myProtocol = _IceProtocols[
+ iceConn->protosetup_to_you->my_opcode - 1].orig_client;
+
+ IcePoAuthProc authProc = myProtocol->auth_procs[(int)
+ (iceConn->protosetup_to_you->my_auth_index)];
+
+#ifdef SVR4
+
+/*
+ * authProc is never NULL, but the cc compiler on UNIX System V/386
+ * Release 4.2 Version 1 screws up an optimization. Unless there is
+ * some sort of reference to authProc before the function call, the
+ * function call will seg fault.
+ */
+ if (authProc)
+#endif
+ (*authProc) (iceConn,
+ &iceConn->protosetup_to_you->my_auth_state,
+ True /* clean up */, False /* swap */,
+ 0, NULL, NULL, NULL, NULL);
+ }
+
+ if ((int) message->versionIndex >= _IceVersionCount)
+ {
+ _IceProtocolError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->protocol_error);
+ char errIndex = message->versionIndex;
+
+ _IceErrorBadValue (iceConn, 0,
+ ICE_ProtocolReply, 2, 1, &errIndex);
+
+ errorReply->type = ICE_PROTOCOL_ERROR;
+ errorReply->error_message =
+ (char *)"Received bad version index in Protocol Reply";
+ }
+ else
+ {
+ _IceProtocolReply *reply =
+ &(((_IceReply *) (replyWait->reply))->protocol_reply);
+
+ reply->type = ICE_PROTOCOL_REPLY;
+ reply->major_opcode = message->protocolOpcode;
+ reply->version_index = message->versionIndex;
+
+ EXTRACT_STRING (pData, swap, reply->vendor);
+ EXTRACT_STRING (pData, swap, reply->release);
+ }
+
+ replyReady = True;
+ }
+ else
+ {
+ _IceErrorBadState (iceConn, 0, ICE_ProtocolReply, IceCanContinue);
+
+ replyReady = False;
+ }
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+
+ return (replyReady);
+}
+
+
+
+static int
+ProcessPing (iceConn, length)
+
+IceConn iceConn;
+unsigned long length;
+
+{
+ CHECK_SIZE_MATCH (iceConn, ICE_Ping,
+ length, SIZEOF (icePingMsg), IceFatalToConnection);
+
+ PingReply (iceConn);
+
+ return (0);
+}
+
+
+
+static int
+ProcessPingReply (iceConn, length)
+
+IceConn iceConn;
+unsigned long length;
+
+{
+ CHECK_SIZE_MATCH (iceConn, ICE_PingReply,
+ length, SIZEOF (icePingReplyMsg), IceFatalToConnection);
+
+ if (iceConn->ping_waits)
+ {
+ _IcePingWait *next = iceConn->ping_waits->next;
+
+ (*iceConn->ping_waits->ping_reply_proc) (iceConn,
+ iceConn->ping_waits->client_data);
+
+ free ((char *) iceConn->ping_waits);
+ iceConn->ping_waits = next;
+ }
+ else
+ {
+ _IceErrorBadState (iceConn, 0, ICE_PingReply, IceCanContinue);
+ }
+
+ return (0);
+}
+
+
+
+static int
+ProcessWantToClose (iceConn, length, connectionClosedRet)
+
+IceConn iceConn;
+unsigned long length;
+Bool *connectionClosedRet;
+
+{
+ *connectionClosedRet = False;
+
+ CHECK_SIZE_MATCH (iceConn, ICE_WantToClose,
+ length, SIZEOF (iceWantToCloseMsg), IceFatalToConnection);
+
+ if (iceConn->want_to_close || iceConn->open_ref_count == 0)
+ {
+ /*
+ * We just received a WantToClose. Either we also sent a
+ * WantToClose, so we close the connection, or the iceConn
+ * is not being used, so we close the connection. This
+ * second case is possible if we sent a WantToClose because
+ * the iceConn->open_ref_count reached zero, but then we
+ * received a NoClose.
+ */
+
+ _IceConnectionClosed (iceConn); /* invoke watch procs */
+ _IceFreeConnection (iceConn);
+ *connectionClosedRet = True;
+ }
+ else if (iceConn->proto_ref_count > 0)
+ {
+ /*
+ * We haven't shut down all of our protocols yet. We send a NoClose,
+ * and it's up to us to generate a WantToClose later on.
+ */
+
+ IceSimpleMessage (iceConn, 0, ICE_NoClose);
+ IceFlush (iceConn);
+ }
+ else
+ {
+ /*
+ * The reference count on this iceConn is zero. This means that
+ * there are no active protocols, but the client didn't explicitly
+ * close the connection yet. If we didn't just send a Protocol Setup,
+ * we send a NoClose, and it's up to us to generate a WantToClose
+ * later on.
+ */
+
+ if (!iceConn->protosetup_to_you)
+ {
+ IceSimpleMessage (iceConn, 0, ICE_NoClose);
+ IceFlush (iceConn);
+ }
+ }
+
+ return (0);
+}
+
+
+
+static int
+ProcessNoClose (iceConn, length)
+
+IceConn iceConn;
+unsigned long length;
+
+{
+ CHECK_SIZE_MATCH (iceConn, ICE_NoClose,
+ length, SIZEOF (iceNoCloseMsg), IceFatalToConnection);
+
+ if (iceConn->want_to_close)
+ {
+ /*
+ * The other side can't close now. We cancel our WantToClose,
+ * and we can expect a WantToClose from the other side.
+ */
+
+ iceConn->want_to_close = 0;
+ }
+ else
+ {
+ _IceErrorBadState (iceConn, 0, ICE_NoClose, IceCanContinue);
+ }
+
+ return (0);
+}
+
+
+
+void
+_IceProcessCoreMessage (iceConn, opcode, length, swap,
+ replyWait, replyReadyRet, connectionClosedRet)
+
+IceConn iceConn;
+int opcode;
+unsigned long length;
+Bool swap;
+IceReplyWaitInfo *replyWait;
+Bool *replyReadyRet;
+Bool *connectionClosedRet;
+
+{
+ Bool replyReady = False;
+
+ *connectionClosedRet = False;
+
+ switch (opcode)
+ {
+ case ICE_Error:
+
+ replyReady = ProcessError (iceConn, length, swap, replyWait);
+ break;
+
+ case ICE_ConnectionSetup:
+
+ ProcessConnectionSetup (iceConn, length, swap);
+ break;
+
+ case ICE_AuthRequired:
+
+ replyReady = ProcessAuthRequired (iceConn, length, swap, replyWait);
+ break;
+
+ case ICE_AuthReply:
+
+ ProcessAuthReply (iceConn, length, swap);
+ break;
+
+ case ICE_AuthNextPhase:
+
+ replyReady = ProcessAuthNextPhase (iceConn, length, swap, replyWait);
+ break;
+
+ case ICE_ConnectionReply:
+
+ replyReady = ProcessConnectionReply (iceConn, length, swap, replyWait);
+ break;
+
+ case ICE_ProtocolSetup:
+
+ ProcessProtocolSetup (iceConn, length, swap);
+ break;
+
+ case ICE_ProtocolReply:
+
+ replyReady = ProcessProtocolReply (iceConn, length, swap, replyWait);
+ break;
+
+ case ICE_Ping:
+
+ ProcessPing (iceConn, length);
+ break;
+
+ case ICE_PingReply:
+
+ ProcessPingReply (iceConn, length);
+ break;
+
+ case ICE_WantToClose:
+
+ ProcessWantToClose (iceConn, length, connectionClosedRet);
+ break;
+
+ case ICE_NoClose:
+
+ ProcessNoClose (iceConn, length);
+ break;
+
+ default:
+
+ _IceErrorBadMinor (iceConn, 0, opcode, IceCanContinue);
+ _IceReadSkip (iceConn, length << 3);
+ break;
+ }
+
+ if (replyWait)
+ *replyReadyRet = replyReady;
+}
+
+
+#ifdef MINIX
+int
+MNX_IceMessagesAvailable(iceConn)
+
+IceConn iceConn;
+{
+ BytesReadable_t bytes;
+
+ _kde_IceTransSetOption(iceConn->trans_conn, TRANS_NONBLOCKING, 1);
+ if (_kde_IceTransBytesReadable(iceConn->trans_conn, &bytes) < 0)
+ bytes= -1;
+ _kde_IceTransSetOption(iceConn->trans_conn, TRANS_NONBLOCKING, 0);
+ return (bytes != 0);
+}
+#endif
diff --git a/dcop/KDE-ICE/protosetup.c b/dcop/KDE-ICE/protosetup.c
new file mode 100644
index 000000000..f675ccd89
--- /dev/null
+++ b/dcop/KDE-ICE/protosetup.c
@@ -0,0 +1,287 @@
+/* $Xorg: protosetup.c,v 1.3 2000/08/17 19:44:17 cpqbld Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include "KDE-ICE/ICElib.h"
+#include "KDE-ICE/ICElibint.h"
+#include "KDE-ICE/globals.h"
+#include <string.h>
+
+
+IceProtocolSetupStatus
+IceProtocolSetup (iceConn, myOpcode, clientData, mustAuthenticate,
+ majorVersionRet, minorVersionRet, vendorRet, releaseRet,
+ errorLength, errorStringRet)
+
+IceConn iceConn;
+int myOpcode;
+IcePointer clientData;
+Bool mustAuthenticate;
+int *majorVersionRet;
+int *minorVersionRet;
+char **vendorRet;
+char **releaseRet;
+int errorLength;
+char *errorStringRet;
+
+{
+ iceProtocolSetupMsg *pMsg;
+ char *pData;
+ _IceProtocol *myProtocol;
+ int extra;
+ Bool gotReply, ioErrorOccured;
+ int accepted, i;
+ int hisOpcode;
+ unsigned long setup_sequence;
+ IceReplyWaitInfo replyWait;
+ _IceReply reply;
+ IcePoVersionRec *versionRec = NULL;
+ int authCount;
+ int *authIndices;
+
+ if (errorStringRet && errorLength > 0)
+ *errorStringRet = '\0';
+
+ *majorVersionRet = 0;
+ *minorVersionRet = 0;
+ *vendorRet = NULL;
+ *releaseRet = NULL;
+
+ if (myOpcode < 1 || myOpcode > _IceLastMajorOpcode)
+ {
+ strncpy (errorStringRet, "myOpcode out of range", errorLength);
+ return (IceProtocolSetupFailure);
+ }
+
+ myProtocol = &_IceProtocols[myOpcode - 1];
+
+ if (myProtocol->orig_client == NULL)
+ {
+ strncpy (errorStringRet,
+ "IceRegisterForProtocolSetup was not called", errorLength);
+ return (IceProtocolSetupFailure);
+ }
+
+
+ /*
+ * Make sure this protocol hasn't been activated already.
+ */
+
+ if (iceConn->process_msg_info)
+ {
+ for (i = iceConn->his_min_opcode; i <= iceConn->his_max_opcode; i++)
+ {
+ if (iceConn->process_msg_info[
+ i - iceConn->his_min_opcode].in_use &&
+ iceConn->process_msg_info[
+ i - iceConn->his_min_opcode ].my_opcode == myOpcode)
+ break;
+ }
+
+ if (i <= iceConn->his_max_opcode)
+ {
+ return (IceProtocolAlreadyActive);
+ }
+ }
+
+ /*
+ * Generate the message.
+ */
+
+ if (myProtocol->orig_client->auth_count > 0)
+ {
+ authIndices = (int *) malloc (
+ myProtocol->orig_client->auth_count * sizeof (int));
+
+ _IceGetPoValidAuthIndices (myProtocol->protocol_name,
+ iceConn->connection_string,
+ myProtocol->orig_client->auth_count,
+ (const char**)myProtocol->orig_client->auth_names,
+ &authCount, authIndices);
+
+ }
+ else
+ {
+ authCount = 0;
+ authIndices = NULL;
+ }
+
+ extra = STRING_BYTES (myProtocol->protocol_name) +
+ STRING_BYTES (myProtocol->orig_client->vendor) +
+ STRING_BYTES (myProtocol->orig_client->release);
+
+ for (i = 0; i < authCount; i++)
+ {
+ extra += STRING_BYTES (myProtocol->orig_client->auth_names[
+ authIndices[i]]);
+ }
+
+ extra += (myProtocol->orig_client->version_count * 4);
+
+ IceGetHeaderExtra (iceConn, 0, ICE_ProtocolSetup,
+ SIZEOF (iceProtocolSetupMsg), WORD64COUNT (extra),
+ iceProtocolSetupMsg, pMsg, pData);
+
+ setup_sequence = iceConn->send_sequence;
+
+ pMsg->protocolOpcode = myOpcode;
+ pMsg->versionCount = myProtocol->orig_client->version_count;
+ pMsg->authCount = authCount;
+ pMsg->mustAuthenticate = mustAuthenticate;
+
+ STORE_STRING (pData, myProtocol->protocol_name);
+ STORE_STRING (pData, myProtocol->orig_client->vendor);
+ STORE_STRING (pData, myProtocol->orig_client->release);
+
+ for (i = 0; i < authCount; i++)
+ {
+ STORE_STRING (pData, myProtocol->orig_client->auth_names[
+ authIndices[i]]);
+ }
+
+ for (i = 0; i < myProtocol->orig_client->version_count; i++)
+ {
+ STORE_CARD16 (pData,
+ myProtocol->orig_client->version_recs[i].major_version);
+ STORE_CARD16 (pData,
+ myProtocol->orig_client->version_recs[i].minor_version);
+ }
+
+ IceFlush (iceConn);
+
+
+ /*
+ * Process messages until we get a Protocol Reply.
+ */
+
+ replyWait.sequence_of_request = setup_sequence;
+ replyWait.major_opcode_of_request = 0;
+ replyWait.minor_opcode_of_request = ICE_ProtocolSetup;
+ replyWait.reply = (IcePointer) &reply;
+
+ iceConn->protosetup_to_you = (_IceProtoSetupToYouInfo *) malloc (
+ sizeof (_IceProtoSetupToYouInfo));
+ iceConn->protosetup_to_you->my_opcode = myOpcode;
+ iceConn->protosetup_to_you->my_auth_count = authCount;
+ iceConn->protosetup_to_you->auth_active = 0;
+ iceConn->protosetup_to_you->my_auth_indices = authIndices;
+
+ gotReply = False;
+ ioErrorOccured = False;
+ accepted = 0;
+
+ while (!gotReply && !ioErrorOccured)
+ {
+ ioErrorOccured = (IceProcessMessages (
+ iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError);
+
+ if (ioErrorOccured)
+ {
+ strncpy (errorStringRet,
+ "IO error occurred doing Protocol Setup on connection",
+ errorLength);
+ return (IceProtocolSetupIOError);
+ }
+ else if (gotReply)
+ {
+ if (reply.type == ICE_PROTOCOL_REPLY)
+ {
+ if (reply.protocol_reply.version_index >=
+ myProtocol->orig_client->version_count)
+ {
+ strncpy (errorStringRet,
+ "Got a bad version index in the Protocol Reply",
+ errorLength);
+
+ free (reply.protocol_reply.vendor);
+ free (reply.protocol_reply.release);
+ }
+ else
+ {
+ versionRec = &(myProtocol->orig_client->version_recs[
+ reply.protocol_reply.version_index]);
+
+ accepted = 1;
+ }
+ }
+ else /* reply.type == ICE_PROTOCOL_ERROR */
+ {
+ /* Protocol Setup failed */
+
+ strncpy (errorStringRet, reply.protocol_error.error_message,
+ errorLength);
+
+ free (reply.protocol_error.error_message);
+ }
+
+ if (iceConn->protosetup_to_you->my_auth_indices)
+ free ((char *) iceConn->protosetup_to_you->my_auth_indices);
+ free ((char *) iceConn->protosetup_to_you);
+ iceConn->protosetup_to_you = NULL;
+ }
+ }
+
+ if (accepted)
+ {
+ _IceProcessMsgInfo *process_msg_info;
+
+ *majorVersionRet = versionRec->major_version;
+ *minorVersionRet = versionRec->minor_version;
+ *vendorRet = reply.protocol_reply.vendor;
+ *releaseRet = reply.protocol_reply.release;
+
+
+ /*
+ * Increase the reference count for the number of active protocols.
+ */
+
+ iceConn->proto_ref_count++;
+
+
+ /*
+ * We may be using a different major opcode for this protocol
+ * than the other client. Whenever we get a message, we must
+ * map to our own major opcode.
+ */
+
+ hisOpcode = reply.protocol_reply.major_opcode;
+
+ _IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode);
+
+ process_msg_info = &iceConn->process_msg_info[hisOpcode -
+ iceConn->his_min_opcode];
+
+ process_msg_info->client_data = clientData;
+ process_msg_info->accept_flag = 0;
+
+ process_msg_info->process_msg_proc.orig_client =
+ versionRec->process_msg_proc;
+
+ return (IceProtocolSetupSuccess);
+ }
+ else
+ {
+ return (IceProtocolSetupFailure);
+ }
+}
diff --git a/dcop/KDE-ICE/register.c b/dcop/KDE-ICE/register.c
new file mode 100644
index 000000000..77c686ba0
--- /dev/null
+++ b/dcop/KDE-ICE/register.c
@@ -0,0 +1,251 @@
+/* $Xorg: register.c,v 1.3 2000/08/17 19:44:18 cpqbld Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include "KDE-ICE/ICElib.h"
+#include "KDE-ICE/ICElibint.h"
+#include "KDE-ICE/globals.h"
+#include <string.h>
+
+int
+IceRegisterForProtocolSetup (protocolName, vendor, release,
+ versionCount, versionRecs, authCount, authNames, authProcs, IOErrorProc)
+
+char *protocolName;
+char *vendor;
+char *release;
+int versionCount;
+IcePoVersionRec *versionRecs;
+int authCount;
+char **authNames;
+IcePoAuthProc *authProcs;
+IceIOErrorProc IOErrorProc;
+
+{
+ _IcePoProtocol *p;
+ int opcodeRet, i;
+
+ for (i = 1; i <= _IceLastMajorOpcode; i++)
+ if (strcmp (protocolName, _IceProtocols[i - 1].protocol_name) == 0)
+ {
+ if (_IceProtocols[i - 1].orig_client != NULL)
+ {
+ /*
+ * We've already registered this protocol.
+ */
+
+ return (i);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (i <= _IceLastMajorOpcode)
+ {
+ p = _IceProtocols[i - 1].orig_client =
+ (_IcePoProtocol *) malloc (sizeof (_IcePoProtocol));
+ opcodeRet = i;
+ }
+ else if (_IceLastMajorOpcode == 255 ||
+ versionCount < 1 ||
+ strlen (protocolName) == 0)
+ {
+ return (-1);
+ }
+ else
+ {
+ char *name;
+
+ _IceProtocols[_IceLastMajorOpcode].protocol_name = name =
+ (char *) malloc (strlen (protocolName) + 1);
+ strcpy (name, protocolName);
+
+ p = _IceProtocols[_IceLastMajorOpcode].orig_client =
+ (_IcePoProtocol *) malloc (sizeof (_IcePoProtocol));
+
+ _IceProtocols[_IceLastMajorOpcode].accept_client = NULL;
+
+ opcodeRet = ++_IceLastMajorOpcode;
+ }
+
+ p->vendor = (char *) malloc (strlen (vendor) + 1);
+ strcpy (p->vendor, vendor);
+
+ p->release = (char *) malloc (strlen (release) + 1);
+ strcpy (p->release, release);
+
+ p->version_count = versionCount;
+
+ p->version_recs = (IcePoVersionRec *) malloc (
+ versionCount * sizeof (IcePoVersionRec));
+ memcpy (p->version_recs, versionRecs,
+ versionCount * sizeof (IcePoVersionRec));
+
+ if ((p->auth_count = authCount) > 0)
+ {
+ p->auth_names = (char **) malloc (
+ authCount * sizeof (char *));
+
+ p->auth_procs = (IcePoAuthProc *) malloc (
+ authCount * sizeof (IcePoAuthProc));
+
+ for (i = 0; i < authCount; i++)
+ {
+ p->auth_names[i] =
+ (char *) malloc (strlen (authNames[i]) + 1);
+ strcpy (p->auth_names[i], authNames[i]);
+
+ p->auth_procs[i] = authProcs[i];
+ }
+ }
+ else
+ {
+ p->auth_names = NULL;
+ p->auth_procs = NULL;
+ }
+
+ p->io_error_proc = IOErrorProc;
+
+ return (opcodeRet);
+}
+
+
+
+int
+IceRegisterForProtocolReply (protocolName, vendor, release,
+ versionCount, versionRecs, authCount, authNames, authProcs,
+ hostBasedAuthProc, protocolSetupProc, protocolActivateProc,
+ IOErrorProc)
+
+char *protocolName;
+char *vendor;
+char *release;
+int versionCount;
+IcePaVersionRec *versionRecs;
+int authCount;
+char **authNames;
+IcePaAuthProc *authProcs;
+IceHostBasedAuthProc hostBasedAuthProc;
+IceProtocolSetupProc protocolSetupProc;
+IceProtocolActivateProc protocolActivateProc;
+IceIOErrorProc IOErrorProc;
+
+{
+ _IcePaProtocol *p;
+ int opcodeRet, i;
+
+ for (i = 1; i <= _IceLastMajorOpcode; i++)
+ if (strcmp (protocolName, _IceProtocols[i - 1].protocol_name) == 0)
+ {
+ if (_IceProtocols[i - 1].accept_client != NULL)
+ {
+ /*
+ * We've already registered this protocol.
+ */
+
+ return (i);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+
+ if (i <= _IceLastMajorOpcode)
+ {
+ p = _IceProtocols[i - 1].accept_client =
+ (_IcePaProtocol *) malloc (sizeof (_IcePaProtocol));
+ opcodeRet = i;
+ }
+ else if (_IceLastMajorOpcode == 255 ||
+ versionCount < 1 ||
+ strlen (protocolName) == 0)
+ {
+ return (-1);
+ }
+ else
+ {
+ char *name;
+
+ _IceProtocols[_IceLastMajorOpcode].protocol_name = name =
+ (char *) malloc (strlen (protocolName) + 1);
+ strcpy (name, protocolName);
+
+ _IceProtocols[_IceLastMajorOpcode].orig_client = NULL;
+
+ p = _IceProtocols[_IceLastMajorOpcode].accept_client =
+ (_IcePaProtocol *) malloc (sizeof (_IcePaProtocol));
+
+ opcodeRet = ++_IceLastMajorOpcode;
+ }
+
+ p->vendor = (char *) malloc (strlen (vendor) + 1);
+ strcpy (p->vendor, vendor);
+
+ p->release = (char *) malloc (strlen (release) + 1);
+ strcpy (p->release, release);
+
+ p->version_count = versionCount;
+
+ p->version_recs = (IcePaVersionRec *) malloc (
+ versionCount * sizeof (IcePaVersionRec));
+ memcpy (p->version_recs, versionRecs,
+ versionCount * sizeof (IcePaVersionRec));
+
+ p->protocol_setup_proc = protocolSetupProc;
+ p->protocol_activate_proc = protocolActivateProc;
+
+ if ((p->auth_count = authCount) > 0)
+ {
+ p->auth_names = (char **) malloc (
+ authCount * sizeof (char *));
+
+ p->auth_procs = (IcePaAuthProc *) malloc (
+ authCount * sizeof (IcePaAuthProc));
+
+ for (i = 0; i < authCount; i++)
+ {
+ p->auth_names[i] =
+ (char *) malloc (strlen (authNames[i]) + 1);
+ strcpy (p->auth_names[i], authNames[i]);
+
+ p->auth_procs[i] = authProcs[i];
+ }
+ }
+ else
+ {
+ p->auth_names = NULL;
+ p->auth_procs = NULL;
+ }
+
+ p->host_based_auth_proc = hostBasedAuthProc;
+
+ p->io_error_proc = IOErrorProc;
+
+ return (opcodeRet);
+}
+
diff --git a/dcop/KDE-ICE/replywait.c b/dcop/KDE-ICE/replywait.c
new file mode 100644
index 000000000..a54ce144d
--- /dev/null
+++ b/dcop/KDE-ICE/replywait.c
@@ -0,0 +1,171 @@
+/* $XConsortium: replywait.c,v 1.4 94/04/17 20:15:39 mor Exp $ */
+/******************************************************************************
+
+
+Copyright (c) 1993 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <KDE-ICE/ICElib.h>
+#include "KDE-ICE/ICElibint.h"
+
+
+void
+_IceAddReplyWait (iceConn, replyWait)
+
+IceConn iceConn;
+IceReplyWaitInfo *replyWait;
+
+{
+ /*
+ * Add this replyWait to the end of the list (only if the
+ * replyWait is not already in the list).
+ */
+
+ _IceSavedReplyWait *savedReplyWait;
+ _IceSavedReplyWait *prev, *last;
+
+ prev = NULL;
+ last = iceConn->saved_reply_waits;
+
+ while (last)
+ {
+ if (last->reply_wait == replyWait)
+ return;
+
+ prev = last;
+ last = last->next;
+ }
+
+ savedReplyWait = (_IceSavedReplyWait *) malloc (
+ sizeof (_IceSavedReplyWait));
+
+ savedReplyWait->reply_wait = replyWait;
+ savedReplyWait->reply_ready = False;
+ savedReplyWait->next = NULL;
+
+ if (prev == NULL)
+ iceConn->saved_reply_waits = savedReplyWait;
+ else
+ prev->next = savedReplyWait;
+}
+
+
+
+IceReplyWaitInfo *
+_IceSearchReplyWaits (iceConn, majorOpcode)
+
+IceConn iceConn;
+int majorOpcode;
+
+{
+ /*
+ * Return the first replyWait in the list with the given majorOpcode
+ */
+ _IceSavedReplyWait *savedReplyWait = iceConn->saved_reply_waits;
+
+
+ /* first translate the opcode from the other end to our major */
+ if (majorOpcode != 0) /* major 0 (ICE) is always the same*/
+ {
+ if ((majorOpcode < iceConn->his_min_opcode) || (majorOpcode > iceConn->his_max_opcode))
+ return NULL;
+ majorOpcode = iceConn->process_msg_info[majorOpcode - iceConn->his_min_opcode].my_opcode;
+ }
+
+
+ while (savedReplyWait)
+ {
+ if (!savedReplyWait->reply_ready &&
+ (savedReplyWait->reply_wait->major_opcode_of_request == majorOpcode))
+ return savedReplyWait->reply_wait;
+
+ savedReplyWait = savedReplyWait->next;
+ }
+
+ return NULL;
+}
+
+
+
+void
+_IceSetReplyReady (iceConn, replyWait)
+
+IceConn iceConn;
+IceReplyWaitInfo *replyWait;
+
+{
+ /*
+ * The replyWait specified has a reply ready.
+ */
+
+ _IceSavedReplyWait *savedReplyWait = iceConn->saved_reply_waits;
+
+ while (savedReplyWait && savedReplyWait->reply_wait != replyWait)
+ savedReplyWait = savedReplyWait->next;
+
+ if (savedReplyWait)
+ savedReplyWait->reply_ready = True;
+}
+
+
+
+Bool
+_IceCheckReplyReady (iceConn, replyWait)
+
+IceConn iceConn;
+IceReplyWaitInfo *replyWait;
+
+{
+ _IceSavedReplyWait *savedReplyWait = iceConn->saved_reply_waits;
+ _IceSavedReplyWait *prev = NULL;
+ Bool found = False;
+ Bool ready;
+
+ while (savedReplyWait && !found)
+ {
+ if (savedReplyWait->reply_wait == replyWait)
+ found = True;
+ else
+ {
+ prev = savedReplyWait;
+ savedReplyWait = savedReplyWait->next;
+ }
+ }
+
+ ready = found && savedReplyWait->reply_ready;
+
+ if (ready)
+ {
+ if (prev == NULL)
+ iceConn->saved_reply_waits = savedReplyWait->next;
+ else
+ prev->next = savedReplyWait->next;
+
+ free ((char *) savedReplyWait);
+ }
+
+ return (ready);
+}
diff --git a/dcop/KDE-ICE/setauth.c b/dcop/KDE-ICE/setauth.c
new file mode 100644
index 000000000..5c16f656f
--- /dev/null
+++ b/dcop/KDE-ICE/setauth.c
@@ -0,0 +1,116 @@
+/* $Xorg: setauth.c,v 1.3 2000/08/17 19:44:18 cpqbld Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+/* $XFree86: xc/lib/ICE/setauth.c,v 1.3 2001/01/17 19:41:29 dawes Exp $ */
+
+#include "KDE-ICE/ICElib.h"
+#include "KDE-ICE/ICElibint.h"
+#include "KDE-ICE/ICEutil.h"
+#include "KDE-ICE/globals.h"
+#include <string.h>
+
+
+/*
+ * IceSetPaAuthData is not a standard part of ICElib, it is specific
+ * to the sample implementation.
+ *
+ * For the client that initiates a Protocol Setup, we look in the
+ * .ICEauthority file to get authentication data.
+ *
+ * For the client accepting the Protocol Setup, we get the data
+ * from an in-memory database of authentication data (set by the
+ * application calling IceSetPaAuthData). We have to get the data
+ * from memory because getting it directly from the .ICEauthority
+ * file is not secure - someone can just modify the contents of the
+ * .ICEauthority file behind our back.
+ */
+
+int _IcePaAuthDataEntryCount = 0;
+#ifndef __EMX__
+IceAuthDataEntry _IcePaAuthDataEntries[ICE_MAX_AUTH_DATA_ENTRIES];
+#else
+IceAuthDataEntry _IcePaAuthDataEntries[ICE_MAX_AUTH_DATA_ENTRIES] = {0};
+#endif
+
+
+void
+IceSetPaAuthData (numEntries, entries)
+
+int numEntries;
+IceAuthDataEntry *entries;
+
+{
+ /*
+ * _IcePaAuthDataEntries should really be a linked list.
+ * On my list of TO DO stuff.
+ */
+
+ int i, j;
+
+ for (i = 0; i < numEntries; i++)
+ {
+ for (j = 0; j < _IcePaAuthDataEntryCount; j++)
+ if (strcmp (entries[i].protocol_name,
+ _IcePaAuthDataEntries[j].protocol_name) == 0 &&
+ strcmp (entries[i].network_id,
+ _IcePaAuthDataEntries[j].network_id) == 0 &&
+ strcmp (entries[i].auth_name,
+ _IcePaAuthDataEntries[j].auth_name) == 0)
+ break;
+
+ if (j < _IcePaAuthDataEntryCount)
+ {
+ free (_IcePaAuthDataEntries[j].protocol_name);
+ free (_IcePaAuthDataEntries[j].network_id);
+ free (_IcePaAuthDataEntries[j].auth_name);
+ free (_IcePaAuthDataEntries[j].auth_data);
+ }
+ else
+ {
+ _IcePaAuthDataEntryCount++;
+ }
+
+ _IcePaAuthDataEntries[j].protocol_name = (char *) malloc (
+ strlen (entries[i].protocol_name) + 1);
+ strcpy (_IcePaAuthDataEntries[j].protocol_name,
+ entries[i].protocol_name);
+
+ _IcePaAuthDataEntries[j].network_id = (char *) malloc (
+ strlen (entries[i].network_id) + 1);
+ strcpy (_IcePaAuthDataEntries[j].network_id,
+ entries[i].network_id);
+
+ _IcePaAuthDataEntries[j].auth_name = (char *) malloc (
+ strlen (entries[i].auth_name) + 1);
+ strcpy (_IcePaAuthDataEntries[j].auth_name,
+ entries[i].auth_name);
+
+ _IcePaAuthDataEntries[j].auth_data_length =
+ entries[i].auth_data_length;
+ _IcePaAuthDataEntries[j].auth_data = (char *) malloc (
+ entries[i].auth_data_length);
+ memcpy (_IcePaAuthDataEntries[j].auth_data,
+ entries[i].auth_data, entries[i].auth_data_length);
+ }
+}
diff --git a/dcop/KDE-ICE/shutdown.c b/dcop/KDE-ICE/shutdown.c
new file mode 100644
index 000000000..740126fa4
--- /dev/null
+++ b/dcop/KDE-ICE/shutdown.c
@@ -0,0 +1,323 @@
+/* $Xorg: shutdown.c,v 1.3 2000/08/17 19:44:18 cpqbld Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include "KDE-ICE/ICElib.h"
+#include "KDE-ICE/ICElibint.h"
+#include "KDE-ICE/Xtrans.h"
+#include "KDE-ICE/globals.h"
+
+
+Status
+IceProtocolShutdown (iceConn, majorOpcode)
+
+IceConn iceConn;
+int majorOpcode;
+
+{
+ if (iceConn->proto_ref_count == 0 || iceConn->process_msg_info == NULL ||
+ majorOpcode < 1 || majorOpcode > _IceLastMajorOpcode)
+ {
+ return (0);
+ }
+ else
+ {
+ /*
+ * Make sure this majorOpcode is really being used.
+ */
+
+ int i;
+
+ for (i = iceConn->his_min_opcode; i <= iceConn->his_max_opcode; i++)
+ {
+ if (iceConn->process_msg_info[
+ i - iceConn->his_min_opcode].in_use &&
+ iceConn->process_msg_info[
+ i - iceConn->his_min_opcode].my_opcode == majorOpcode)
+ break;
+ }
+
+ if (i > iceConn->his_max_opcode)
+ {
+ return (0);
+ }
+ else
+ {
+ /*
+ * OK, we can shut down the protocol.
+ */
+
+ iceConn->process_msg_info[
+ i - iceConn->his_min_opcode].in_use = False;
+ iceConn->proto_ref_count--;
+
+ return (1);
+ }
+ }
+}
+
+
+
+void
+IceSetShutdownNegotiation (iceConn, negotiate)
+
+IceConn iceConn;
+Bool negotiate;
+
+{
+ iceConn->skip_want_to_close = negotiate ? False : True;
+}
+
+
+
+Bool
+IceCheckShutdownNegotiation (iceConn)
+
+IceConn iceConn;
+
+{
+ return (iceConn->skip_want_to_close ? False : True);
+}
+
+
+
+IceCloseStatus
+IceCloseConnection (iceConn)
+
+IceConn iceConn;
+
+{
+ int refCountReachedZero;
+ IceCloseStatus status;
+
+ /*
+ * If this connection object was never valid, we can close
+ * it right now. This happens if IceAcceptConnection was
+ * called, but after calling IceProcessMessages several times
+ * the connection was rejected (because of authentication or
+ * some other reason).
+ */
+
+ if (iceConn->listen_obj &&
+ iceConn->connection_status != IceConnectAccepted)
+ {
+ _IceConnectionClosed (iceConn); /* invoke watch procs */
+ _IceFreeConnection (iceConn);
+ return (IceClosedNow);
+ }
+
+
+ /*---------------------------------------------------------------
+
+ ACTIONS:
+
+ A = Invoke Watch Procedures
+ B = Set free-asap bit
+ C = Free connection
+ D = Initialize shutdown negotiation
+ N = do nothing
+
+
+ ACTION TABLE:
+
+ IO free- dispatch protocol shutdown
+ error asap bit level refcount negotiation ACTION
+ occurred set reached 0 reached 0
+
+ 0 0 0 0 0 N
+ 0 0 0 0 1 N
+ 0 0 0 1 0 AB
+ 0 0 0 1 1 N
+ 0 0 1 0 0 N
+ 0 0 1 0 1 N
+ 0 0 1 1 0 AC
+ 0 0 1 1 1 D
+ 0 1 0 0 0 N
+ 0 1 0 0 1 N
+ 0 1 0 1 0 N
+ 0 1 0 1 1 N
+ 0 1 1 0 0 C
+ 0 1 1 0 1 D
+ 0 1 1 1 0 C
+ 0 1 1 1 1 D
+ 1 0 0 0 0 AB
+ 1 0 0 0 1 AB
+ 1 0 0 1 0 AB
+ 1 0 0 1 1 AB
+ 1 0 1 0 0 AC
+ 1 0 1 0 1 AC
+ 1 0 1 1 0 AC
+ 1 0 1 1 1 AC
+ 1 1 0 0 0 N
+ 1 1 0 0 1 N
+ 1 1 0 1 0 N
+ 1 1 0 1 1 N
+ 1 1 1 0 0 C
+ 1 1 1 0 1 C
+ 1 1 1 1 0 C
+ 1 1 1 1 1 C
+
+ ---------------------------------------------------------------*/
+
+ if (iceConn->open_ref_count > 0)
+ iceConn->open_ref_count--;
+
+ refCountReachedZero = iceConn->open_ref_count == 0 &&
+ iceConn->proto_ref_count == 0;
+
+ status = IceConnectionInUse;
+
+ if (!iceConn->free_asap && (!iceConn->io_ok ||
+ (iceConn->io_ok && refCountReachedZero &&
+ iceConn->skip_want_to_close)))
+ {
+ /*
+ * Invoke the watch procedures now.
+ */
+
+ _IceConnectionClosed (iceConn);
+ status = IceClosedNow; /* may be overwritten by IceClosedASAP */
+ }
+
+ if (!iceConn->free_asap && iceConn->dispatch_level != 0 &&
+ (!iceConn->io_ok ||
+ (iceConn->io_ok && refCountReachedZero &&
+ iceConn->skip_want_to_close)))
+ {
+ /*
+ * Set flag so we free the connection as soon as possible.
+ */
+
+ iceConn->free_asap = True;
+ status = IceClosedASAP;
+ }
+
+ if (iceConn->io_ok && iceConn->dispatch_level == 0 &&
+ !iceConn->skip_want_to_close && refCountReachedZero)
+ {
+ /*
+ * Initiate shutdown negotiation.
+ */
+
+ IceSimpleMessage (iceConn, 0, ICE_WantToClose);
+ IceFlush (iceConn);
+
+ iceConn->want_to_close = 1;
+
+ status = IceStartedShutdownNegotiation;
+ }
+ else if (iceConn->dispatch_level == 0 &&
+ (!iceConn->io_ok || (iceConn->io_ok && iceConn->skip_want_to_close &&
+ (iceConn->free_asap || (!iceConn->free_asap && refCountReachedZero)))))
+ {
+ /*
+ * Free the connection.
+ */
+
+ _IceFreeConnection (iceConn);
+
+ status = IceClosedNow;
+ }
+
+ return (status);
+}
+
+
+
+void
+_IceFreeConnection (iceConn)
+
+IceConn iceConn;
+
+{
+ if (iceConn->listen_obj == NULL)
+ {
+ /*
+ * This iceConn was created with IceOpenConnection.
+ * We keep track of all open IceConn's, so we need
+ * to remove it from the list.
+ */
+
+ int i;
+
+ for (i = 0; i < _IceConnectionCount; i++)
+ if (_IceConnectionObjs[i] == iceConn)
+ break;
+
+ if (i < _IceConnectionCount)
+ {
+ if (i < _IceConnectionCount - 1)
+ {
+ _IceConnectionObjs[i] =
+ _IceConnectionObjs[_IceConnectionCount - 1];
+ _IceConnectionStrings[i] =
+ _IceConnectionStrings[_IceConnectionCount - 1];
+ }
+
+ _IceConnectionCount--;
+ }
+ }
+
+ if (iceConn->trans_conn)
+ _kde_IceTransClose (iceConn->trans_conn);
+
+ if (iceConn->connection_string)
+ free (iceConn->connection_string);
+
+ if (iceConn->vendor)
+ free (iceConn->vendor);
+
+ if (iceConn->release)
+ free (iceConn->release);
+
+ if (iceConn->inbuf)
+ free (iceConn->inbuf);
+
+ if (iceConn->outbuf)
+ free (iceConn->outbuf);
+
+ if (iceConn->scratch)
+ free (iceConn->scratch);
+
+ if (iceConn->process_msg_info)
+ free ((char *) iceConn->process_msg_info);
+
+ if (iceConn->connect_to_you)
+ free ((char *) iceConn->connect_to_you);
+
+ if (iceConn->protosetup_to_you)
+ free ((char *) iceConn->protosetup_to_you);
+
+ if (iceConn->connect_to_me)
+ free ((char *) iceConn->connect_to_me);
+
+ if (iceConn->protosetup_to_me)
+ free ((char *) iceConn->protosetup_to_me);
+
+ free ((char *) iceConn);
+}
+
+
+
+
diff --git a/dcop/KDE-ICE/transport.c b/dcop/KDE-ICE/transport.c
new file mode 100644
index 000000000..8c862ddfb
--- /dev/null
+++ b/dcop/KDE-ICE/transport.c
@@ -0,0 +1,68 @@
+/* $TOG: transport.c /main/7 1998/02/06 15:54:19 kaleb $ */
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+
+*/
+/* $XFree86: xc/lib/xtrans/transport.c,v 3.4 1998/10/03 09:07:37 dawes Exp $ */
+
+/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
+ *
+ * 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 NCR not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCR makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NCR 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 X_NOT_STDC_ENV
+#include <stdlib.h>
+#endif
+
+#define xalloc(_size) malloc(_size)
+#define xcalloc(_num,_size) calloc(_num,_size)
+#define xrealloc(_ptr,_size) realloc(_ptr,_size)
+#define xfree(_ptr) free(_ptr)
+
+#include "Xtransint.h"
+
+#ifdef LOCALCONN
+#include "Xtranslcl.c"
+#endif
+#if defined(TCPCONN) || defined(UNIXCONN)
+#include "Xtranssock.c"
+#endif
+#include "Xtrans.c"
+#include "Xtransutil.c"
diff --git a/dcop/KDE-ICE/watch.c b/dcop/KDE-ICE/watch.c
new file mode 100644
index 000000000..79a2b8910
--- /dev/null
+++ b/dcop/KDE-ICE/watch.c
@@ -0,0 +1,199 @@
+/* $Xorg: watch.c,v 1.3 2000/08/17 19:44:19 cpqbld Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+All Rights Reserved.
+
+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.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include "KDE-ICE/ICElib.h"
+#include "KDE-ICE/ICElibint.h"
+#include "KDE-ICE/globals.h"
+
+Status
+IceAddConnectionWatch (watchProc, clientData)
+
+IceWatchProc watchProc;
+IcePointer clientData;
+
+{
+ /*
+ * watchProc will be called each time an ICE connection is
+ * created/destroyed by ICElib.
+ */
+
+ _IceWatchProc *ptr = _IceWatchProcs;
+ _IceWatchProc *newWatchProc;
+ int i;
+
+ if ((newWatchProc = (_IceWatchProc *) malloc (
+ sizeof (_IceWatchProc))) == NULL)
+ {
+ return (0);
+ }
+
+ newWatchProc->watch_proc = watchProc;
+ newWatchProc->client_data = clientData;
+ newWatchProc->watched_connections = NULL;
+ newWatchProc->next = NULL;
+
+ while (ptr && ptr->next)
+ ptr = ptr->next;
+
+ if (ptr == NULL)
+ _IceWatchProcs = newWatchProc;
+ else
+ ptr->next = newWatchProc;
+
+
+ /*
+ * Invoke the watch proc with any previously opened ICE connections.
+ */
+
+ for (i = 0; i < _IceConnectionCount; i++)
+ {
+ _IceWatchedConnection *newWatchedConn = (_IceWatchedConnection *)
+ malloc (sizeof (_IceWatchedConnection));
+
+ newWatchedConn->iceConn = _IceConnectionObjs[i];
+ newWatchedConn->next = NULL;
+
+ newWatchProc->watched_connections = newWatchedConn;
+
+ (*newWatchProc->watch_proc) (_IceConnectionObjs[i],
+ newWatchProc->client_data, True, &newWatchedConn->watch_data);
+ }
+
+ return (1);
+}
+
+
+
+void
+IceRemoveConnectionWatch (watchProc, clientData)
+
+IceWatchProc watchProc;
+IcePointer clientData;
+
+{
+ _IceWatchProc *currWatchProc = _IceWatchProcs;
+ _IceWatchProc *prevWatchProc = NULL;
+
+ while (currWatchProc && (currWatchProc->watch_proc != watchProc ||
+ currWatchProc->client_data != clientData))
+ {
+ prevWatchProc = currWatchProc;
+ currWatchProc = currWatchProc->next;
+ }
+
+ if (currWatchProc)
+ {
+ _IceWatchProc *nextWatchProc = currWatchProc->next;
+ _IceWatchedConnection *watchedConn;
+
+ watchedConn = currWatchProc->watched_connections;
+ while (watchedConn)
+ {
+ _IceWatchedConnection *nextWatchedConn = watchedConn->next;
+ free ((char *) watchedConn);
+ watchedConn = nextWatchedConn;
+ }
+
+ if (prevWatchProc == NULL)
+ _IceWatchProcs = nextWatchProc;
+ else
+ prevWatchProc->next = nextWatchProc;
+
+ free ((char *) currWatchProc);
+ }
+}
+
+
+
+void
+_IceConnectionOpened (iceConn)
+
+IceConn iceConn;
+
+{
+ _IceWatchProc *watchProc = _IceWatchProcs;
+
+ while (watchProc)
+ {
+ _IceWatchedConnection *newWatchedConn = (_IceWatchedConnection *)
+ malloc (sizeof (_IceWatchedConnection));
+ _IceWatchedConnection *watchedConn;
+
+ watchedConn = watchProc->watched_connections;
+ while (watchedConn && watchedConn->next)
+ watchedConn = watchedConn->next;
+
+ newWatchedConn->iceConn = iceConn;
+ newWatchedConn->next = NULL;
+
+ if (watchedConn == NULL)
+ watchProc->watched_connections = newWatchedConn;
+ else
+ watchedConn->next = newWatchedConn;
+
+ (*watchProc->watch_proc) (iceConn,
+ watchProc->client_data, True, &newWatchedConn->watch_data);
+
+ watchProc = watchProc->next;
+ }
+}
+
+
+
+void
+_IceConnectionClosed (iceConn)
+
+IceConn iceConn;
+
+{
+ _IceWatchProc *watchProc = _IceWatchProcs;
+
+ while (watchProc)
+ {
+ _IceWatchedConnection *watchedConn = watchProc->watched_connections;
+ _IceWatchedConnection *prev = NULL;
+
+ while (watchedConn && watchedConn->iceConn != iceConn)
+ {
+ prev = watchedConn;
+ watchedConn = watchedConn->next;
+ }
+
+ if (watchedConn)
+ {
+ (*watchProc->watch_proc) (iceConn,
+ watchProc->client_data, False, &watchedConn->watch_data);
+
+ if (prev == NULL)
+ watchProc->watched_connections = watchedConn->next;
+ else
+ prev->next = watchedConn->next;
+
+ free ((char *) watchedConn);
+ }
+
+ watchProc = watchProc->next;
+ }
+}
diff --git a/dcop/Mainpage.dox b/dcop/Mainpage.dox
new file mode 100644
index 000000000..af4f14ec3
--- /dev/null
+++ b/dcop/Mainpage.dox
@@ -0,0 +1,576 @@
+/*
+ A dummy source file for documenting the library.
+ Copied from HOWTO with small syntactic changes.
+*/
+
+/**
+ \mainpage The DCOP Desktop COmmunication Protocol library
+
+DCOP is a simple IPC/RPC mechanism built to operate over sockets.
+Either unix domain sockets or TCP/IP sockets are supported. DCOP is
+built on top of the Inter Client Exchange (ICE) protocol, which comes
+standard as a part of X11R6 and later. It also depends on Qt, but
+beyond that it does not require any other libraries. Because of this,
+it is extremely lightweight, enabling it to be linked into all KDE
+applications with low overhead.
+
+\section model Model:
+
+The model is simple. Each application using DCOP is a client. They
+communicate to each other through a DCOP server, which functions like
+a traffic director, dispatching messages/calls to the proper
+destinations. All clients are peers of each other.
+
+Two types of actions are possible with DCOP: "send and forget"
+messages, which do not block, and "calls," which block waiting for
+some data to be returned.
+
+Any data that will be sent is serialized (also referred to as marshalling
+in CORBA speak) using the built-in QDataStream operators available in all
+of the Qt classes. This is fast and easy. In fact it's so little work
+that you can easily write the marshalling code by hand. In addition,
+there's a simple IDL-like compiler available (dcopidl and dcopidl2cpp)
+that generates stubs and skeletons for you. Using the dcopidl compiler
+has the additional benefit of type safety.
+
+The manual method is covered first, followed by the automatic IDL method.
+
+
+\section establish Establishing the Connection:
+
+KApplication has gained a method called \p KApplication::dcopClient()
+which returns a pointer to a DCOPClient instance. The first time this
+method is called, the client class will be created. DCOPClients have
+unique identifiers attached to them which are based on what
+KApplication::name() returns. In fact, if there is only a single
+instance of the program running, the appId will be equal to
+KApplication::name().
+
+To actually enable DCOP communication to begin, you must use
+\p DCOPClient::attach(). This will attempt to attach to the DCOP server.
+If no server is found or there is any other type of error,
+DCOPClient::attach() will return false. KApplication will catch a dcop
+signal and display an appropriate error message box in that case.
+
+After connecting with the server via DCOPClient::attach(), you need to
+register this appId with the server so it knows about you. Otherwise,
+you are communicating anonymously. Use the
+DCOPClient::registerAs(const QCString &name) to do so. In the simple
+case:
+
+\code
+appId = client->registerAs(kapp->name());
+\endcode
+
+If you never retrieve the DCOPClient pointer from KApplication, the
+object will not be created and thus there will be no memory overhead.
+
+You may also detach from the server by calling DCOPClient::detach().
+If you wish to attach again you will need to re-register as well. If
+you only wish to change the ID under which you are registered, simply
+call DCOPClient::registerAs() with the new name.
+
+KUniqueApplication automatically registers itself to DCOP. If you
+are using KUniqueApplication you should not attach or register
+yourself, this is already done. The appId is by definition
+equal to \p kapp->name(). You can retrieve the registered DCOP client
+by calling \p kapp->dcopClient().
+
+
+\section sending_data Sending Data to a Remote Application:
+
+To actually communicate, you have one of two choices. You may either
+call the "send" or the "call" method. Both methods require three
+identification parameters: an application identifier, a remote object,
+a remote function. Sending is asynchronous (i.e. it returns immediately)
+and may or may not result in your own application being sent a message at
+some point in the future. Then "send" requires one and "call" requires
+two data parameters.
+
+The remote object must be specified as an object hierarchy. That is,
+if the toplevel object is called \p fooObject and has the child
+\p barObject, you would reference this object as \p fooObject/barObject.
+Functions must be described by a full function signature. If the
+remote function is called \p doIt, and it takes an int, it would be
+described as \p doIt(int). Please note that the return type is not
+specified here, as it is not part of the function signature (or at
+least the C++ understanding of a function signature). You will get
+the return type of a function back as an extra parameter to
+DCOPClient::call(). See the section on call() for more details.
+
+In order to actually get the data to the remote client, it must be
+"serialized" via a QDataStream operating on a QByteArray. This is how
+the data parameter is "built". A few examples will make clear how this
+works.
+
+Say you want to call \p doIt as described above, and not block (or wait
+for a response). You will not receive the return value of the remotely
+called function, but you will not hang while the RPC is processed either.
+The return value of DCOPClient::send() indicates whether DCOP communication
+succeeded or not.
+
+\code
+QByteArray data;
+QDataStream arg(data, IO_WriteOnly);
+arg << 5;
+if (!client->send("someAppId", "fooObject/barObject", "doIt(int)",
+ data))
+ qDebug("there was some error using DCOP.");
+\endcode
+
+OK, now let's say we wanted to get the data back from the remotely
+called function. You have to execute a DCOPClient::call() instead of a
+DCOPClient::send(). The returned value will then be available in the
+data parameter "reply". The actual return value of call() is still
+whether or not DCOP communication was successful.
+
+\code
+QByteArray data, replyData;
+QCString replyType;
+QDataStream arg(data, IO_WriteOnly);
+arg << 5;
+if (!client->call("someAppId", "fooObject/barObject", "doIt(int)",
+ data, replyType, replyData))
+ qDebug("there was some error using DCOP.");
+else {
+ QDataStream reply(replyData, IO_ReadOnly);
+ if (replyType == "QString") {
+ QString result;
+ reply >> result;
+ print("the result is: %s",result.latin1());
+ } else
+ qDebug("doIt returned an unexpected type of reply!");
+}
+\endcode
+
+
+\section receiving_data Receiving Data via DCOP:
+
+Currently the only real way to receive data from DCOP is to multiply
+inherit from the normal class that you are inheriting (usually some
+sort of QWidget subclass or QObject) as well as the DCOPObject class.
+DCOPObject provides one very important method: DCOPObject::process().
+This is a pure virtual method that you must implement in order to
+process DCOP messages that you receive. It takes a function
+signature, QByteArray of parameters, and a reference to a QByteArray
+for the reply data that you must fill in.
+
+Think of DCOPObject::process() as a sort of dispatch agent. In the
+future, there will probably be a precompiler for your sources to write
+this method for you. However, until that point you need to examine
+the incoming function signature and take action accordingly. Here is
+an example implementation.
+
+\code
+bool BarObject::process(const QCString &fun, const QByteArray &data,
+ QCString &replyType, QByteArray &replyData)
+{
+ if (fun == "doIt(int)") {
+ QDataStream arg(data, IO_ReadOnly);
+ int i; // parameter
+ arg >> i;
+ QString result = self->doIt (i);
+ QDataStream reply(replyData, IO_WriteOnly);
+ reply << result;
+ replyType = "QString";
+ return true;
+ } else {
+ qDebug("unknown function call to BarObject::process()");
+ return false;
+ }
+}
+\endcode
+
+
+\section receiving_calls Receiving Calls and processing them:
+
+If your applications is able to process incoming function calls
+right away the above code is all you need. When your application
+needs to do more complex tasks you might want to do the processing
+out of 'process' function call and send the result back later when
+it becomes available.
+
+For this you can ask your DCOPClient for a transactionId. You can
+then return from the 'process' function and when the result is
+available finish the transaction. In the mean time your application
+can receive incoming DCOP function calls from other clients.
+
+Such code could like this:
+
+\code
+bool BarObject::process(const QCString &fun, const QByteArray &data,
+ QCString &, QByteArray &)
+{
+ if (fun == "doIt(int)") {
+ QDataStream arg(data, IO_ReadOnly);
+ int i; // parameter
+ arg >> i;
+ QString result = self->doIt(i);
+
+ DCOPClientTransaction *myTransaction;
+ myTransaction = kapp->dcopClient()->beginTransaction();
+
+ // start processing...
+ // Calls slotProcessingDone when finished.
+ startProcessing( myTransaction, i);
+
+ return true;
+ } else {
+ qDebug("unknown function call to BarObject::process()");
+ return false;
+ }
+}
+
+slotProcessingDone(DCOPClientTransaction *myTransaction, const QString &result)
+{
+ QCString replyType = "QString";
+ QByteArray replyData;
+ QDataStream reply(replyData, IO_WriteOnly);
+ reply << result;
+ kapp->dcopClient()->endTransaction( myTransaction, replyType, replyData );
+}
+\endcode
+
+
+\section dcopidl Using the dcopidl compiler:
+
+dcopidl makes setting up a DCOP server easy. Instead of having to implement
+the process() method and unmarshalling (retrieving from QByteArray) parameters
+manually, you can let dcopidl create the necessary code on your behalf.
+
+This also allows you to describe the interface for your class in a
+single, separate header file.
+
+Writing an IDL file is very similar to writing a normal C++ header. An
+exception is the keyword 'ASYNC'. It indicates that a call to this
+function shall be processed asynchronously. For the C++ compiler, it
+expands to 'void'.
+
+Example:
+
+\code
+#ifndef MY_INTERFACE_H
+#define MY_INTERFACE_H
+
+#include <dcopobject.h>
+
+class MyInterface : virtual public DCOPObject
+{
+ K_DCOP
+
+ k_dcop:
+
+ virtual ASYNC myAsynchronousMethod(QString someParameter) = 0;
+ virtual QRect mySynchronousMethod() = 0;
+};
+
+#endif
+\endcode
+
+As you can see, you're essentially declaring an abstract base class, which
+virtually inherits from DCOPObject.
+
+If you're using the standard KDE build scripts, then you can simply
+add this file (which you would call MyInterface.h) to your sources
+directory. Then you edit your Makefile.am, adding 'MyInterface.skel'
+to your SOURCES list and MyInterface.h to include_HEADERS.
+
+The build scripts will use dcopidl to parse MyInterface.h, converting
+it to an XML description in MyInterface.kidl. Next, a file called
+MyInterface_skel.cpp will automatically be created, compiled and
+linked with your binary.
+
+The next thing you have to do is to choose which of your classes will
+implement the interface described in MyInterface.h. Alter the inheritance
+of this class such that it virtually inherits from MyInterface. Then
+add declarations to your class interface similar to those on MyInterface.h,
+but virtual, not pure virtual.
+
+Example:
+
+\code
+class MyClass: public QObject, virtual public MyInterface
+{
+ Q_OBJECT
+
+ public:
+ MyClass();
+ ~MyClass();
+
+ ASYNC myAsynchronousMethod(QString someParameter);
+ QRect mySynchronousMethod();
+};
+\endcode
+\note (Qt issue) Remember that if you are inheriting from QObject, you must
+place it first in the list of inherited classes.
+
+In the implementation of your class' ctor, you must explicitly initialize
+those classes from which you are inheriting from. This is, of course, good
+practice, but it is essential here as you need to tell DCOPObject the name of
+the interface which your are implementing.
+
+Example:
+
+\code
+MyClass::MyClass()
+ : QObject(),
+ DCOPObject("MyInterface")
+{
+ // whatever...
+}
+\endcode
+
+
+Now you can simply implement the methods you have declared in your interface,
+exactly the same as you would normally.
+
+Example:
+
+\code
+void MyClass::myAsynchronousMethod(QString someParameter)
+{
+ qDebug("myAsyncMethod called with param `" + someParameter + "'");
+}
+\endcode
+
+It is not necessary (though very clean) to define an interface as an
+abstract class of its own, like we did in the example above. We could
+just as well have defined a k_dcop section directly within MyClass:
+
+\code
+class MyClass: public QObject, virtual public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+
+ public:
+ MyClass();
+ ~MyClass();
+
+ k_dcop:
+ ASYNC myAsynchronousMethod(QString someParameter);
+ QRect mySynchronousMethod();
+};
+\endcode
+
+In addition to skeletons, dcopidl2cpp also generate stubs. Those make
+it easy to call a DCOP interface without doing the marshalling
+manually. To use a stub, add MyInterface.stub to the SOURCES list of
+your Makefile.am. The stub class will then be called MyInterface_stub.
+
+
+\section iuc Inter-user communication:
+
+Sometimes it might be interesting to use DCOP between processes
+belonging to different users, e.g. a frontend process running
+with the user's id, and a backend process running as root.
+
+To do this, two steps have to be taken:
+
+a) both processes need to talk to the same DCOP server
+b) the authentication must be ensured
+
+For the first step, you simply pass the server address (as
+found in .DCOPserver) to the second process. For the authentication,
+you can use the ICEAUTHORITY environment variable to tell the
+second process where to find the authentication information.
+(Note that this implies that the second process is able to
+read the authentication file, so it will probably only work
+if the second process runs as root. If it should run as another
+user, a similar approach to what kdesu does with xauth must
+be taken. In fact, it would be a very good idea to add DCOP
+support to kdesu!)
+
+For example
+
+ICEAUTHORITY=~user/.ICEauthority kdesu root -c kcmroot -dcopserver `cat ~user/.DCOPserver`
+
+will, after kdesu got the root password, execute kcmroot as root, talking
+to the user's dcop server.
+
+
+NOTE: DCOP communication is not encrypted, so please do not
+pass important information around this way.
+
+\section protocol DCOP Protocol description:
+
+A DCOPSend message does not expect any reply.
+\code
+data: << fromId << toId << objId << fun << dataSize + data[dataSize]
+\endcode
+
+A DCOPCall message can get a DCOPReply, a DCOPReplyFailed
+or a DCOPReplyWait message in response.
+\code
+data: << fromId << toId << objId << fun << dataSize + data[dataSize]
+\endcode
+
+DCOPReply is the successful reply to a DCOPCall message
+\code
+data: << fromId << toId << replyType << replyDataSize + replyData[replyDataSize]
+\endcode
+
+DCOPReplyFailed indicates failure of a DCOPCall message
+\code
+data: << fromId << toId
+\endcode
+
+DCOPReplyWait indicates that a DCOPCall message is successfully
+being processed but that response will come later.
+\code
+data: << fromId << toId << transactionId
+\endcode
+
+DCOPReplyDelayed is the successful reply to a DCOPCall message
+after a DCOPReplyWait message.
+\code
+data: << fromId << toId << transactionId << replyType << replyData
+\endcode
+
+DCOPFind is a message much like a "call" message. It can however
+be send to multiple objects within a client. If a function in a
+object that is being called returns a boolean with the value "true",
+a DCOPReply will be send back containing the DCOPRef of the object
+who returned "true".
+
+All c-strings (fromId, toId, objId, fun and replyType), are marshalled with
+their respective length as 32 bit unsigned integer first:
+\code
+data: length + string[length]
+\endcode
+\note This happens automatically when using QCString on a QDataStream.
+
+\section Deadlock protection and reentrancy
+
+When a DCOP call is made, the dcop client will be monitoring the
+dcop connection for the reply on the call. When an incoming call is
+received in this period, it will normally not be processed but queued
+until the outgoing call has been fully handled.
+
+However, the above scenario would cause deadlock if the incoming call
+was directly or indirectly a result of the outgoing call and the reply
+on the outgoing call is waiting for the result of the incoming call.
+(E.g. a circular call such as client A calling client B, with client B
+calling client A)
+
+To prevent deadlock in this case, DCOP has a call tracing mechanism that
+detects circular calls. When it detects an incoming circular call that
+would otherwise be queued and as a result cause deadlock, it will handle
+the incoming call immediately instead of queueing it. This means that the
+incoming call may be processed at a point in the code where an outgoing
+DCOP call is made. An application should be aware of this kind of
+reentrancy. A special case of this is when a DCOP client makes a call
+to itself, such calls are always handled directly.
+
+Call tracing works by appending a key to each outgoing call. When a client
+receives an incoming call while waiting for a response on an outgoing call,
+it will check if the key of the incoming call is equal to the key used for
+the last outgoing call. If the keys are equal a circular call has been
+detected.
+
+The key used by clients is 0 if they have not yet received any key. In this
+case the server will send them back a unique key that they should use in
+further calls. If a client makes an outgoing call in response to an incoming
+call it will use the key of the incoming call for the outgoing call instead
+of the key that was received from the server.
+
+A key value of 1 has a special meaning and is used for non-call messages
+such as DCOPSend, DCOPReplyFailed and DCOP signals.
+
+A key value of 2 has a special meaning and is used for priority calls.
+When a dcop clien is in priority call mode, it will only handle incoming
+calls that have a key value of 2.
+
+NOTE: If client A and client B would call each other simultaneously there
+is still a risk of deadlock because both calls would have unique keys and
+both clients would decide to queue the incoming call until they receive
+a response on their outgoing call.
+
+\section dcop_signals DCOP Signals:
+
+Sometimes a component wants to send notifications via DCOP to other
+components but does not know which components will be interested in these
+notifications. One could use a broadcast in such a case but this is a very
+crude method. For a more sophisticated method DCOP signals have been invented.
+
+DCOP signals are very similair to Qt signals, there are some differences
+though. A DCOP signal can be connected to a DCOP function. Whenever the DCOP
+signal gets emitted, the DCOP functions to which the signal is connected are
+being called. DCOP signals are, just like Qt signals, one way. They do not
+provide a return value. For declaration of dcop signals, the keyword
+\p k_dcop_signals is provided. A declaration looks like this:
+
+\code
+class Example : virtual public DCOPClient
+{
+ K_DCOP
+
+ k_dcop:
+ // some ordinary dcop methods here
+ ...
+ k_dcop_signals:
+ // our dcop signal
+ void clientDied(pid_t pid);
+ ...
+}
+\endcode
+
+A DCOP signal originates from a DCOP Object/DCOP Client combination (sender).
+It can be connected to a function of another DCOP Object/DCOP Client
+combination (receiver).
+
+\note There are two major differences between connections of Qt signals and
+connections of DCOP signals. In DCOP, unlike Qt, a signal connections can
+have an anonymous sender and, unlike Qt, a DCOP signal connection can be
+non-volatile.
+
+With DCOP one can connect a signal without specifying the sending DCOP Object
+or DCOP Client. In that case signals from any DCOP Object and/or DCOP Client
+will be delivered. This allows the specification of certain events without
+tying oneself to a certain object that implementes the events.
+
+Another DCOP feature are so called non-volatile connections. With Qt signal
+connections, the connection gets deleted when either sender or receiver of
+the signal gets deleted. A volatile DCOP signal connection will behave the
+same. However, a non-volatile DCOP signal connection will not get deleted
+when the sending object gets deleted. Once a new object gets created with
+the same name as the original sending object, the connection will be restored.
+There is no difference between the two when the receiving object gets deleted,
+in that case the signal connection will always be deleted.
+
+A receiver can create a non-volatile connection while the sender doesn't (yet)
+exist. An anonymous DCOP connection should always be non-volatile.
+
+The following example shows how KLauncher emits a signal whenever it notices
+that an application that was started via KLauncher terminates:
+
+\code
+QByteArray params;
+QDataStream stream(params, IO_WriteOnly);
+stream << pid;
+kapp->dcopClient()->emitDCOPSignal("clientDied(pid_t)", params);
+\endcode
+
+The task manager of the KDE panel connects to this signal. It uses an
+anonymous connection (it doesn't require that the signal is being emitted
+by KLauncher) that is non-volatile:
+
+\code
+connectDCOPSignal(0, 0, "clientDied(pid_t)", "clientDied(pid_t)", false);
+\endcode
+
+It connects the clientDied(pid_t) signal to its own clientDied(pid_t) DCOP
+function. In this case the signal and the function to call have the same name.
+This isn't needed as long as the arguments of both signal and receiving function
+match. The receiving function may ignore one or more of the trailing arguments
+of the signal. E.g. it is allowed to connect the clientDied(pid_t) signal to
+a clientDied(void) DCOP function.
+
+
+\section conclusion Conclusion:
+
+Hopefully this document will get you well on your way into the world of
+inter-process communication with KDE! Please direct all comments and/or
+suggestions to the KDE Core Developers List \<kde-core-devel@kde.org\>.
+
+*/
diff --git a/dcop/Makefile.am b/dcop/Makefile.am
new file mode 100644
index 000000000..8dfa033ad
--- /dev/null
+++ b/dcop/Makefile.am
@@ -0,0 +1,69 @@
+# This Makefile.am was taken from the kdelibs distribution and
+# modified for DCOP. Preston Brown (Oct 10, 1999)
+#
+# Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+# Copyright (c) 1999 Matthias Ettrich <ettrich@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
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+SUBDIRS = KDE-ICE . dcopidl dcopidlng dcopidl2cpp client tests
+KDE_OPTIONS = qtonly
+
+INCLUDES = $(all_includes)
+
+bin_PROGRAMS = dcopserver_shutdown
+check_PROGRAMS = testdcop testdcopc dcop_deadlock_test
+
+lib_LTLIBRARIES = libDCOP.la
+libDCOP_la_LIBADD = KDE-ICE/libkICE.la $(LIB_QT)
+libDCOP_la_LDFLAGS = $(KDE_RPATH) -version-info 6:0:2 -no-undefined $(all_libraries)
+libDCOP_la_NMCHECK = $(srcdir)/libDCOP.nmcheck
+libDCOP_la_NMCHECKWEAK = $(srcdir)/libDCOP_weak.nmcheck $(top_srcdir)/kdecore/libqt-mt_weak.nmcheck
+
+include_HEADERS = dcopclient.h dcopobject.h dcopstub.h dcopref.h dcoptypes.h kdatastream.h
+noinst_HEADERS = version.h dcopglobal.h dcopserver.h testdcop.h dcopsignals.h dcop-path.h
+
+METASOURCES = AUTO
+
+# dcopstub needs to go first for --enable-final to work
+libDCOP_la_SOURCES = dcopstub.cpp dcopref.cpp dcopobject.cpp dcopclient.cpp
+
+kdeinit_LTLIBRARIES = dcopserver.la
+dcopserver_la_LDFLAGS = -module -avoid-version $(all_libraries)
+dcopserver_la_SOURCES = dcopserver.cpp dcopsignals.cpp
+dcopserver_la_LIBADD = libDCOP.la
+
+dcopserver_shutdown_SOURCES = dcopserver_shutdown.c
+
+testdcop_LDFLAGS = $(KDE_RPATH) $(all_libraries)
+testdcop_SOURCES = testdcop.cpp
+testdcop_LDADD = libDCOP.la
+
+dcop_deadlock_test_LDFLAGS = $(KDE_RPATH) $(all_libraries)
+dcop_deadlock_test_SOURCES = dcop_deadlock_test.cpp
+dcop_deadlock_test_LDADD = ../kdecore/libkdecore.la
+
+testdcopc_LDFLAGS = $(KDE_RPATH) $(all_libraries)
+testdcopc_SOURCES = testdcopc.c dcopc.c
+testdcopc_LDADD = KDE-ICE/libkICE.la $(LIBSM)
+
+EXTRA_DIST = HOWTO ICE Mainpage.dox
+
+DOXYGEN_REFERENCES = kdecore
+DOXYGEN_EXCLUDE = KDE-ICE
+include ../admin/Doxyfile.am
diff --git a/dcop/client/Makefile.am b/dcop/client/Makefile.am
new file mode 100644
index 000000000..bae7ddd26
--- /dev/null
+++ b/dcop/client/Makefile.am
@@ -0,0 +1,28 @@
+
+INCLUDES = $(all_includes)
+AM_LDFLAGS = $(all_libraries)
+DCOP_LIB = ../libDCOP.la
+
+####### Files
+
+bin_PROGRAMS = dcop dcopfind dcopclient dcopobject dcopref dcopstart dcopquit
+
+dcop_SOURCES = dcop.cpp
+dcop_LDADD = $(LIB_QT) $(DCOP_LIB)
+dcop_LDFLAGS = $(KDE_RPATH)
+
+dcopstart_SOURCES = dcopstart.cpp
+dcopstart_LDADD = $(LIB_QT) $(DCOP_LIB)
+dcopstart_LDFLAGS = $(KDE_RPATH)
+
+dcopquit_SOURCES = dcopquit.cpp
+dcopquit_LDADD = $(LIB_QT) $(DCOP_LIB)
+dcopquit_LDFLAGS = $(KDE_RPATH)
+
+dcopfind_SOURCES = dcopfind.cpp
+dcopfind_LDADD = $(LIB_QT) $(DCOP_LIB)
+dcopfind_LDFLAGS = $(KDE_RPATH)
+
+dcopclient_SOURCES = dcopclient.c
+dcopobject_SOURCES = dcopobject.c
+dcopref_SOURCES = dcopref.c
diff --git a/dcop/client/README.dcop b/dcop/client/README.dcop
new file mode 100644
index 000000000..e352cb439
--- /dev/null
+++ b/dcop/client/README.dcop
@@ -0,0 +1,78 @@
+Overview of dcop command line utilities
+
+dcop [<app-id> [<object-id> [<function> [args]]]]
+
+Make a dcop call to the specified function.
+If no function is specified, a list of available functions is listed.
+If no object is specified, a list of available objects is listed.
+If no app-id is specified, a list of available application-ids is listed.
+
+****
+* As of KDE 3.0: You will NO LONGER be able to use "dcop konqueror" to
+* communicate with e.g. "konqueror-4783". You will have to use "dcop
+* konqueror-4783" for that (or the DCOPRef notation, see below)
+****
+
+dcopstart <app>
+
+Starts <app> and returns the <app-id> on stdout that can be used for the
+other commands. E.g. "dcopstart kedit" might return "kedit-29322". An
+exit-code of '0' means success. An exit-code of '1' means error, the error
+msg is printed to stderr and no data is printed to stdout.
+
+
+dcopfind [-l] [-a] <app-id> [<object-id> [<select_func> [args]]]
+
+Finds an existing DCOP application/object. The select_func can be used to
+select a specific single instance out of many based on some criteria.
+<app-id> and <object-id> may end with a '*' as wildcard.
+
+The function returns a <app-object-id> to stdout in the form
+
+ "DCOPRef(<app-id>, <object-id>)"
+
+if an object is found and returns an exit-code of '0'.
+If no object is found, nothing is written to stdout and the exit-code is '1'.
+
+With the -a option it prints out "<app-id>" instead of a DCOPRef.
+
+With the -l option it calls "dcopstart <app-id>" if no object is found,
+stripping off any wildcard from the <app-id>. If the dcopstart command is
+successful the find command is repeated, if the dcopstart command fails, an
+error message is printed to stderr and the command exits with exit-code '2'.
+
+The default selection criteria is "any". Applications can declare their own
+select_func as they see fit, e.g. konqueror could declare
+"isDoingProtocol(QString protocol)" and then the following command would
+select a konqueror mainwindow that is currently handling the help-protocol:
+
+ "dcopfind 'konqueror*' 'konqueror-mainwindow*' 'isDoingProtocol(QString
+protocol)' help"
+
+
+dcop <dcopref> <function> args
+
+In addtion to the current syntax of
+
+ dcop <appid> <object> <function> args
+
+you will now also be able to use <dcopref> to make calls with <dcopref> being
+"DCOPRef(<appid>, <objectid>)" as returned by dcopfind.
+
+Additional utilities:
+
+ "dcopref <appid> <object>"
+
+Creates a DCOPRef from appid and object.
+
+
+ "dcopclient <dcopref>"
+
+Extracts the appid from dcopref.
+
+
+ "dcopobject <dcopref>"
+
+Extracts the object from dcopref.
+
+
diff --git a/dcop/client/dcop.cpp b/dcop/client/dcop.cpp
new file mode 100644
index 000000000..e8fd7683a
--- /dev/null
+++ b/dcop/client/dcop.cpp
@@ -0,0 +1,924 @@
+/*****************************************************************
+Copyright (c) 2000 Matthias Ettrich <ettrich@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 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.
+
+******************************************************************/
+
+// putenv() is not available on all platforms, so make sure the emulation
+// wrapper is available in those cases by loading config.h!
+#include <config.h>
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <qbuffer.h>
+#include <qcolor.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qimage.h>
+#include <qmap.h>
+#include <qstringlist.h>
+#include <qtextstream.h>
+#include <qvariant.h>
+
+#include "../dcopclient.h"
+#include "../dcopref.h"
+#include "../kdatastream.h"
+
+#include "marshall.cpp"
+
+#if defined Q_WS_X11
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#endif
+
+typedef QMap<QString, QString> UserList;
+
+static DCOPClient* dcop = 0;
+
+static QTextStream cin_ ( stdin, IO_ReadOnly );
+static QTextStream cout_( stdout, IO_WriteOnly );
+static QTextStream cerr_( stderr, IO_WriteOnly );
+
+/**
+ * Session to send call to
+ * DefaultSession - current session. Current KDE session when called without
+ * --user or --all-users option. Otherwise this value ignores
+ * all users with more than one active session.
+ * AllSessions - Send to all sessions found. requires --user or --all-users.
+ * QuerySessions - Don't call DCOP, return a list of available sessions.
+ * CustomSession - Use the specified session
+ */
+enum Session { DefaultSession = 0, AllSessions, QuerySessions, CustomSession };
+
+bool startsWith(const QCString &id, const char *str, int n)
+{
+ return !n || (strncmp(id.data(), str, n) == 0);
+}
+
+bool endsWith(QCString &id, char c)
+{
+ if (id.length() && (id[id.length()-1] == c))
+ {
+ id.truncate(id.length()-1);
+ return true;
+ }
+ return false;
+}
+
+void queryApplications(const QCString &filter)
+{
+ int filterLen = filter.length();
+ QCStringList apps = dcop->registeredApplications();
+ for ( QCStringList::Iterator it = apps.begin(); it != apps.end(); ++it )
+ {
+ QCString &clientId = *it;
+ if ( (clientId != dcop->appId()) &&
+ !startsWith(clientId, "anonymous",9) &&
+ startsWith(clientId, filter, filterLen)
+ )
+ printf( "%s\n", clientId.data() );
+ }
+
+ if ( !dcop->isAttached() )
+ {
+ qWarning( "server not accessible" );
+ exit(1);
+ }
+}
+
+void queryObjects( const QCString &app, const QCString &filter )
+{
+ int filterLen = filter.length();
+ bool ok = false;
+ bool isDefault = false;
+ QCStringList objs = dcop->remoteObjects( app, &ok );
+ for ( QCStringList::Iterator it = objs.begin(); it != objs.end(); ++it )
+ {
+ QCString &objId = *it;
+
+ if (objId == "default")
+ {
+ isDefault = true;
+ continue;
+ }
+
+ if (startsWith(objId, filter, filterLen))
+ {
+ if (isDefault)
+ printf( "%s (default)\n", objId.data() );
+ else
+ printf( "%s\n", objId.data() );
+ }
+ isDefault = false;
+ }
+ if ( !ok )
+ {
+ if (!dcop->isApplicationRegistered(app))
+ qWarning( "No such application: '%s'", app.data());
+ else
+ qWarning( "Application '%s' not accessible", app.data() );
+ exit(1);
+ }
+}
+
+void queryFunctions( const char* app, const char* obj )
+{
+ bool ok = false;
+ QCStringList funcs = dcop->remoteFunctions( app, obj, &ok );
+ for ( QCStringList::Iterator it = funcs.begin(); it != funcs.end(); ++it ) {
+ printf( "%s\n", (*it).data() );
+ }
+ if ( !ok )
+ {
+ qWarning( "object '%s' in application '%s' not accessible", obj, app );
+ exit( 1 );
+ }
+}
+
+int callFunction( const char* app, const char* obj, const char* func, const QCStringList args )
+{
+ QString f = func; // Qt is better with unicode strings, so use one.
+ int left = f.find( '(' );
+ int right = f.find( ')' );
+
+ if ( right < left )
+ {
+ qWarning( "parentheses do not match" );
+ return( 1 );
+ }
+
+ if ( left < 0 ) {
+ // try to get the interface from the server
+ bool ok = false;
+ QCStringList funcs = dcop->remoteFunctions( app, obj, &ok );
+ QCString realfunc;
+ if ( !ok && args.isEmpty() )
+ goto doit;
+ if ( !ok )
+ {
+ qWarning( "object not accessible" );
+ return( 1 );
+ }
+ for ( QCStringList::Iterator it = funcs.begin(); it != funcs.end(); ++it ) {
+ int l = (*it).find( '(' );
+ int s;
+ if (l > 0)
+ s = (*it).findRev( ' ', l);
+ else
+ s = (*it).find( ' ' );
+
+ if ( s < 0 )
+ s = 0;
+ else
+ s++;
+
+ if ( l > 0 && (*it).mid( s, l - s ) == func ) {
+ realfunc = (*it).mid( s );
+ const QString arguments = (*it).mid(l+1,(*it).find( ')' )-l-1);
+ uint a = arguments.contains(',');
+ if ( (a==0 && !arguments.isEmpty()) || a>0)
+ a++;
+ if ( a == args.count() )
+ break;
+ }
+ }
+ if ( realfunc.isEmpty() )
+ {
+ qWarning("no such function");
+ return( 1 );
+ }
+ f = realfunc;
+ left = f.find( '(' );
+ right = f.find( ')' );
+ }
+
+ doit:
+ if ( left < 0 )
+ f += "()";
+
+ // This may seem expensive but is done only once per invocation
+ // of dcop, so it should be OK.
+ //
+ //
+ QStringList intTypes;
+ intTypes << "int" << "unsigned" << "long" << "bool" ;
+
+ QStringList types;
+ if ( left >0 && left + 1 < right - 1) {
+ types = QStringList::split( ',', f.mid( left + 1, right - left - 1) );
+ for ( QStringList::Iterator it = types.begin(); it != types.end(); ++it ) {
+ QString lt = (*it).simplifyWhiteSpace();
+
+ int s = lt.find(' ');
+
+ // If there are spaces in the name, there may be two
+ // reasons: the parameter name is still there, ie.
+ // "QString URL" or it's a complicated int type, ie.
+ // "unsigned long long int bool".
+ //
+ //
+ if ( s > 0 )
+ {
+ QStringList partl = QStringList::split(' ' , lt);
+
+ // The zero'th part is -- at the very least -- a
+ // type part. Any trailing parts *might* be extra
+ // int-type keywords, or at most one may be the
+ // parameter name.
+ //
+ //
+ s=1;
+
+ while (s < static_cast<int>(partl.count()) && intTypes.contains(partl[s]))
+ {
+ s++;
+ }
+
+ if ( s < static_cast<int>(partl.count())-1)
+ {
+ qWarning("The argument `%s' seems syntactically wrong.",
+ lt.latin1());
+ }
+ if ( s == static_cast<int>(partl.count())-1)
+ {
+ partl.remove(partl.at(s));
+ }
+
+ lt = partl.join(" ");
+ lt = lt.simplifyWhiteSpace();
+ }
+
+ (*it) = lt;
+ }
+ QString fc = f.left( left );
+ fc += '(';
+ bool first = true;
+ for ( QStringList::Iterator it = types.begin(); it != types.end(); ++it ) {
+ if ( !first )
+ fc +=",";
+ first = false;
+ fc += *it;
+ }
+ fc += ')';
+ f = fc;
+ }
+
+ QByteArray data, replyData;
+ QCString replyType;
+ QDataStream arg(data, IO_WriteOnly);
+
+ uint i = 0;
+ for( QStringList::Iterator it = types.begin(); it != types.end(); ++it )
+ marshall( arg, args, i, *it );
+
+ if ( i != args.count() )
+ {
+ qWarning( "arguments do not match" );
+ return( 1 );
+ }
+
+ if ( !dcop->call( app, obj, f.latin1(), data, replyType, replyData) ) {
+ qWarning( "call failed");
+ return( 1 );
+ } else {
+ QDataStream reply(replyData, IO_ReadOnly);
+
+ if ( replyType != "void" && replyType != "ASYNC" )
+ {
+ QCString replyString = demarshal( reply, replyType );
+ if ( !replyString.isEmpty() )
+ printf( "%s\n", replyString.data() );
+ else
+ printf("\n");
+ }
+ }
+ return 0;
+}
+
+/**
+ * Show command-line help and exit
+ */
+void showHelp( int exitCode = 0 )
+{
+#ifdef DCOPQUIT
+ cout_ << "Usage: dcopquit [options] [application]" << endl
+#else
+ cout_ << "Usage: dcop [options] [application [object [function [arg1] [arg2] ... ] ] ]" << endl
+#endif
+ << "" << endl
+ << "Console DCOP client" << endl
+ << "" << endl
+ << "Generic options:" << endl
+ << " --help Show help about options" << endl
+ << "" << endl
+ << "Options:" << endl
+ << " --pipe Call DCOP for each line read from stdin. The string '%1'" << endl
+ << " will be used in the argument list as a placeholder for" << endl
+ << " the substituted line." << endl
+ << " For example," << endl
+ << " dcop --pipe konqueror html-widget1 evalJS %1" << endl
+ << " is equivalent to calling" << endl
+ << " while read line ; do" << endl
+ << " dcop konqueror html-widget1 evalJS \"$line\"" << endl
+ << " done" << endl
+ << " in bash, but because no new dcop instance has to be started" << endl
+ << " for each line this is generally much faster, especially for" << endl
+ << " the slower GNU dynamic linkers." << endl
+ << " The '%1' placeholder cannot be used to replace e.g. the" << endl
+ << " program, object or method name." << endl
+ << " --user <user> Connect to the given user's DCOP server. This option will" << endl
+ << " ignore the values of the environment vars $DCOPSERVER and" << endl
+ << " $ICEAUTHORITY, even if they are set." << endl
+ << " If the user has more than one open session, you must also" << endl
+ << " use one of the --list-sessions, --session or --all-sessions" << endl
+ << " command-line options." << endl
+ << " --all-users Send the same DCOP call to all users with a running DCOP" << endl
+ << " server. Only failed calls to existing DCOP servers will" << endl
+ << " generate an error message. If no DCOP server is available" << endl
+ << " at all, no error will be generated." << endl
+ << " --session <ses> Send to the given KDE session. This option can only be" << endl
+ << " used in combination with the --user option." << endl
+ << " --all-sessions Send to all sessions found. Only works with the --user" << endl
+ << " and --all-users options." << endl
+ << " --list-sessions List all active KDE session for a user or all users." << endl
+ << " --no-user-time Don't update the user activity timestamp in the called" << endl
+ << " application (for usage in scripts running" << endl
+ << " in the background)." << endl
+ << endl;
+
+ exit( exitCode );
+}
+
+/**
+ * Return a list of all users and their home directories.
+ * Returns an empty list if /etc/passwd cannot be read for some reason.
+ */
+static UserList userList()
+{
+ UserList result;
+
+ while( passwd* pstruct = getpwent() )
+ {
+ result[ QString::fromLocal8Bit(pstruct->pw_name) ] = QFile::decodeName(pstruct->pw_dir);
+ }
+
+ return result;
+}
+
+/**
+ * Return a list of available DCOP sessions for the specified user
+ * An empty list means no sessions are available, or an error occurred.
+ */
+QStringList dcopSessionList( const QString &user, const QString &home )
+{
+ if( home.isEmpty() )
+ {
+ cerr_ << "WARNING: Cannot determine home directory for user "
+ << user << "!" << endl
+ << "Please check permissions or set the $DCOPSERVER variable manually before" << endl
+ << "calling dcop." << endl;
+ return QStringList();
+ }
+
+ QStringList result;
+ QFileInfo dirInfo( home );
+ if( !dirInfo.exists() || !dirInfo.isReadable() )
+ return result;
+
+ QDir d( home );
+ d.setFilter( QDir::Files | QDir::Hidden | QDir::NoSymLinks );
+ d.setNameFilter( ".DCOPserver*" );
+
+ const QFileInfoList *list = d.entryInfoList();
+ if( !list )
+ return result;
+
+ QFileInfoListIterator it( *list );
+ QFileInfo *fi;
+
+ while ( ( fi = it.current() ) != 0 )
+ {
+ if( fi->isReadable() )
+ result.append( fi->fileName() );
+ ++it;
+ }
+ return result;
+}
+
+void sendUserTime( const char* app )
+{
+#if defined Q_WS_X11
+ static unsigned long time = 0;
+ if( time == 0 )
+ {
+ Display* dpy = XOpenDisplay( NULL );
+ if( dpy != NULL )
+ {
+ Window w = XCreateSimpleWindow( dpy, DefaultRootWindow( dpy ), 0, 0, 1, 1, 0, 0, 0 );
+ XSelectInput( dpy, w, PropertyChangeMask );
+ unsigned char data[ 1 ];
+ XChangeProperty( dpy, w, XA_ATOM, XA_ATOM, 8, PropModeAppend, data, 1 );
+ XEvent ev;
+ XWindowEvent( dpy, w, PropertyChangeMask, &ev );
+ time = ev.xproperty.time;
+ XDestroyWindow( dpy, w );
+ }
+ }
+ DCOPRef( app, "MainApplication-Interface" ).call( "updateUserTimestamp", time );
+#else
+// ...
+#endif
+}
+
+/**
+ * Do the actual DCOP call
+ */
+int runDCOP( QCStringList args, UserList users, Session session,
+ const QString sessionName, bool readStdin, bool updateUserTime )
+{
+ bool DCOPrefmode=false;
+ QCString app;
+ QCString objid;
+ QCString function;
+ QCStringList params;
+ DCOPClient *client = 0L;
+ int retval = 0;
+ if ( !args.isEmpty() && args[ 0 ].find( "DCOPRef(" ) == 0 )
+ {
+ int delimPos = args[ 0 ].findRev( ',' );
+ if( delimPos == -1 )
+ {
+ cerr_ << "Error: '" << args[ 0 ]
+ << "' is not a valid DCOP reference." << endl;
+ exit( -1 );
+ }
+ app = args[ 0 ].mid( 8, delimPos-8 );
+ delimPos++;
+ objid = args[ 0 ].mid( delimPos, args[ 0 ].length()-delimPos-1 );
+ if( args.count() > 1 )
+ function = args[ 1 ];
+ if( args.count() > 2 )
+ {
+ params = args;
+ params.remove( params.begin() );
+ params.remove( params.begin() );
+ }
+ DCOPrefmode=true;
+ }
+ else
+ {
+ if( !args.isEmpty() )
+ app = args[ 0 ];
+ if( args.count() > 1 )
+ objid = args[ 1 ];
+ if( args.count() > 2 )
+ function = args[ 2 ];
+ if( args.count() > 3)
+ {
+ params = args;
+ params.remove( params.begin() );
+ params.remove( params.begin() );
+ params.remove( params.begin() );
+ }
+ }
+
+ bool firstRun = true;
+ UserList::Iterator it;
+ QStringList sessions;
+ bool presetDCOPServer = false;
+// char *dcopStr = 0L;
+ QString dcopServer;
+
+ for( it = users.begin(); it != users.end() || firstRun; ++it )
+ {
+ firstRun = false;
+
+ //cout_ << "Iterating '" << it.key() << "'" << endl;
+
+ if( session == QuerySessions )
+ {
+ QStringList sessions = dcopSessionList( it.key(), it.data() );
+ if( sessions.isEmpty() )
+ {
+ if( users.count() <= 1 )
+ {
+ cout_ << "No active sessions";
+ if( !( *it ).isEmpty() )
+ cout_ << " for user " << *it;
+ cout_ << endl;
+ }
+ }
+ else
+ {
+ cout_ << "Active sessions ";
+ if( !( *it ).isEmpty() )
+ cout_ << "for user " << *it << " ";
+ cout_ << ":" << endl;
+
+ QStringList::Iterator sIt = sessions.begin();
+ for( ; sIt != sessions.end(); ++sIt )
+ cout_ << " " << *sIt << endl;
+
+ cout_ << endl;
+ }
+ continue;
+ }
+
+ if( getenv( "DCOPSERVER" ) )
+ {
+ sessions.append( getenv( "DCOPSERVER" ) );
+ presetDCOPServer = true;
+ }
+
+ if( users.count() > 1 || ( users.count() == 1 &&
+ ( getenv( "DCOPSERVER" ) == 0 /*&& getenv( "DISPLAY" ) == 0*/ ) ) )
+ {
+ sessions = dcopSessionList( it.key(), it.data() );
+ if( sessions.isEmpty() )
+ {
+ if( users.count() > 1 )
+ continue;
+ else
+ {
+ cerr_ << "ERROR: No active KDE sessions!" << endl
+ << "If you are sure there is one, please set the $DCOPSERVER variable manually" << endl
+ << "before calling dcop." << endl;
+ exit( -1 );
+ }
+ }
+ else if( !sessionName.isEmpty() )
+ {
+ if( sessions.contains( sessionName ) )
+ {
+ sessions.clear();
+ sessions.append( sessionName );
+ }
+ else
+ {
+ cerr_ << "ERROR: The specified session doesn't exist!" << endl;
+ exit( -1 );
+ }
+ }
+ else if( sessions.count() > 1 && session != AllSessions )
+ {
+ cerr_ << "ERROR: Multiple available KDE sessions!" << endl
+ << "Please specify the correct session to use with --session or use the" << endl
+ << "--all-sessions option to broadcast to all sessions." << endl;
+ exit( -1 );
+ }
+ }
+
+ if( users.count() > 1 || ( users.count() == 1 &&
+ ( getenv( "ICEAUTHORITY" ) == 0 || getenv( "DISPLAY" ) == 0 ) ) )
+ {
+ // Check for ICE authority file and if the file can be read by us
+ QString home = it.data();
+ QString iceFile = it.data() + "/.ICEauthority";
+ QFileInfo fi( iceFile );
+ if( iceFile.isEmpty() )
+ {
+ cerr_ << "WARNING: Cannot determine home directory for user "
+ << it.key() << "!" << endl
+ << "Please check permissions or set the $ICEAUTHORITY variable manually before" << endl
+ << "calling dcop." << endl;
+ }
+ else if( fi.exists() )
+ {
+ if( fi.isReadable() )
+ {
+ char *envStr = strdup( ( "ICEAUTHORITY=" + iceFile ).ascii() );
+ putenv( envStr );
+ //cerr_ << "ice: " << envStr << endl;
+ }
+ else
+ {
+ cerr_ << "WARNING: ICE authority file " << iceFile
+ << "is not readable by you!" << endl
+ << "Please check permissions or set the $ICEAUTHORITY variable manually before" << endl
+ << "calling dcop." << endl;
+ }
+ }
+ else
+ {
+ if( users.count() > 1 )
+ continue;
+ else
+ {
+ cerr_ << "WARNING: Cannot find ICE authority file "
+ << iceFile << "!" << endl
+ << "Please check permissions or set the $ICEAUTHORITY"
+ << " variable manually before" << endl
+ << "calling dcop." << endl;
+ }
+ }
+ }
+
+ // Main loop
+ // If users is an empty list we're calling for the currently logged
+ // in user. In this case we don't have a session, but still want
+ // to iterate the loop once.
+ QStringList::Iterator sIt = sessions.begin();
+ for( ; sIt != sessions.end() || users.isEmpty(); ++sIt )
+ {
+ if( !presetDCOPServer && !users.isEmpty() )
+ {
+ QString dcopFile = it.data() + "/" + *sIt;
+ QFile f( dcopFile );
+ if( !f.open( IO_ReadOnly ) )
+ {
+ cerr_ << "Can't open " << dcopFile << " for reading!" << endl;
+ exit( -1 );
+ }
+
+ QStringList l( QStringList::split( '\n', f.readAll() ) );
+ dcopServer = l.first();
+
+ if( dcopServer.isEmpty() )
+ {
+ cerr_ << "WARNING: Unable to determine DCOP server for session "
+ << *sIt << "!" << endl
+ << "Please check permissions or set the $DCOPSERVER variable manually before" << endl
+ << "calling dcop." << endl;
+ exit( -1 );
+ }
+ }
+
+ delete client;
+ client = new DCOPClient;
+ if( !dcopServer.isEmpty() )
+ client->setServerAddress( dcopServer.ascii() );
+ bool success = client->attach();
+ if( !success )
+ {
+ cerr_ << "ERROR: Couldn't attach to DCOP server!" << endl;
+ retval = QMAX( retval, 1 );
+ if( users.isEmpty() )
+ break;
+ else
+ continue;
+ }
+ dcop = client;
+
+ int argscount = args.count();
+ if ( DCOPrefmode )
+ argscount++;
+ switch ( argscount )
+ {
+ case 0:
+ queryApplications("");
+ break;
+ case 1:
+ if (endsWith(app, '*'))
+ queryApplications(app);
+ else
+ queryObjects( app, "" );
+ break;
+ case 2:
+ if (endsWith(objid, '*'))
+ queryObjects(app, objid);
+ else
+ queryFunctions( app, objid );
+ break;
+ case 3:
+ default:
+ if( updateUserTime )
+ sendUserTime( app );
+ if( readStdin )
+ {
+ QCStringList::Iterator replaceArg = params.end();
+
+ QCStringList::Iterator it = params.begin();
+ for( ; it != params.end(); ++it )
+ if( *it == "%1" )
+ replaceArg = it;
+
+ // Read from stdin until EOF and call function for each
+ // read line
+ while ( !cin_.atEnd() )
+ {
+ QString buf = cin_.readLine();
+
+ if( replaceArg != params.end() )
+ *replaceArg = buf.local8Bit();
+
+ if( !buf.isNull() )
+ {
+ int res = callFunction( app, objid, function, params );
+ retval = QMAX( retval, res );
+ }
+ }
+ }
+ else
+ {
+ // Just call function
+// cout_ << "call " << app << ", " << objid << ", " << function << ", (params)" << endl;
+ int res = callFunction( app, objid, function, params );
+ retval = QMAX( retval, res );
+ }
+ break;
+ }
+ // Another sIt++ would make the loop infinite...
+ if( users.isEmpty() )
+ break;
+ }
+
+ // Another it++ would make the loop infinite...
+ if( it == users.end() )
+ break;
+ }
+
+ return retval;
+}
+
+#ifdef Q_OS_WIN
+# define main kdemain
+#endif
+
+int main( int argc, char** argv )
+{
+ bool readStdin = false;
+ int numOptions = 0;
+ QString user;
+ Session session = DefaultSession;
+ QString sessionName;
+ bool updateUserTime = true;
+
+ cin_.setEncoding( QTextStream::Locale );
+
+ // Scan for command-line options first
+ for( int pos = 1 ; pos <= argc - 1 ; pos++ )
+ {
+ if( strcmp( argv[ pos ], "--help" ) == 0 )
+ showHelp( 0 );
+ else if( strcmp( argv[ pos ], "--pipe" ) == 0 )
+ {
+ readStdin = true;
+ numOptions++;
+ }
+ else if( strcmp( argv[ pos ], "--user" ) == 0 )
+ {
+ if( pos <= argc - 2 )
+ {
+ user = QString::fromLocal8Bit( argv[ pos + 1] );
+ numOptions +=2;
+ pos++;
+ }
+ else
+ {
+ cerr_ << "Missing username for '--user' option!" << endl << endl;
+ showHelp( -1 );
+ }
+ }
+ else if( strcmp( argv[ pos ], "--session" ) == 0 )
+ {
+ if( session == AllSessions )
+ {
+ cerr_ << "ERROR: --session cannot be mixed with --all-sessions!" << endl << endl;
+ showHelp( -1 );
+ }
+ else if( pos <= argc - 2 )
+ {
+ sessionName = QString::fromLocal8Bit( argv[ pos + 1] );
+ numOptions +=2;
+ pos++;
+ }
+ else
+ {
+ cerr_ << "Missing session name for '--session' option!" << endl << endl;
+ showHelp( -1 );
+ }
+ }
+ else if( strcmp( argv[ pos ], "--all-users" ) == 0 )
+ {
+ user = "*";
+ numOptions ++;
+ }
+ else if( strcmp( argv[ pos ], "--list-sessions" ) == 0 )
+ {
+ session = QuerySessions;
+ numOptions ++;
+ }
+ else if( strcmp( argv[ pos ], "--all-sessions" ) == 0 )
+ {
+ if( !sessionName.isEmpty() )
+ {
+ cerr_ << "ERROR: --session cannot be mixed with --all-sessions!" << endl << endl;
+ showHelp( -1 );
+ }
+ session = AllSessions;
+ numOptions ++;
+ }
+ else if( strcmp( argv[ pos ], "--no-user-time" ) == 0 )
+ {
+ updateUserTime = false;
+ numOptions ++;
+ }
+ else if( argv[ pos ][ 0 ] == '-' )
+ {
+ cerr_ << "Unknown command-line option '" << argv[ pos ]
+ << "'." << endl << endl;
+ showHelp( -1 );
+ }
+ else
+ break; // End of options
+ }
+
+ argc -= numOptions;
+
+ QCStringList args;
+
+#ifdef DCOPQUIT
+ if (argc > 1)
+ {
+ QCString prog = argv[ numOptions + 1 ];
+
+ if (!prog.isEmpty())
+ {
+ args.append( prog );
+
+ // Pass as-is if it ends with a wildcard
+ if (prog[prog.length()-1] != '*')
+ {
+ // Strip a trailing -<PID> part.
+ int i = prog.findRev('-');
+ if ((i >= 0) && prog.mid(i+1).toLong())
+ {
+ prog = prog.left(i);
+ }
+ args.append( "qt/"+prog );
+ args.append( "quit()" );
+ }
+ }
+ }
+#else
+ for( int i = numOptions; i < argc + numOptions - 1; i++ )
+ args.append( argv[ i + 1 ] );
+#endif
+
+ if( readStdin && args.count() < 3 )
+ {
+ cerr_ << "--pipe option only supported for function calls!" << endl << endl;
+ showHelp( -1 );
+ }
+
+ if( user == "*" && args.count() < 3 && session != QuerySessions )
+ {
+ cerr_ << "ERROR: The --all-users option is only supported for function calls!" << endl << endl;
+ showHelp( -1 );
+ }
+
+ if( session == QuerySessions && !args.isEmpty() )
+ {
+ cerr_ << "ERROR: The --list-sessions option cannot be used for actual DCOP calls!" << endl << endl;
+ showHelp( -1 );
+ }
+
+ if( session == QuerySessions && user.isEmpty() )
+ {
+ cerr_ << "ERROR: The --list-sessions option can only be used with the --user or" << endl
+ << "--all-users options!" << endl << endl;
+ showHelp( -1 );
+ }
+
+ if( session != DefaultSession && session != QuerySessions &&
+ args.count() < 3 )
+ {
+ cerr_ << "ERROR: The --session and --all-sessions options are only supported for function" << endl
+ << "calls!" << endl << endl;
+ showHelp( -1 );
+ }
+
+ UserList users;
+ if( user == "*" )
+ users = userList();
+ else if( !user.isEmpty() )
+ users[ user ] = userList()[ user ];
+
+ int retval = runDCOP( args, users, session, sessionName, readStdin, updateUserTime );
+
+ return retval;
+}
+
+// vim: set ts=8 sts=4 sw=4 noet:
+
diff --git a/dcop/client/dcopclient.c b/dcop/client/dcopclient.c
new file mode 100644
index 000000000..0ca67d465
--- /dev/null
+++ b/dcop/client/dcopclient.c
@@ -0,0 +1,59 @@
+/* vi: set ts=2 sw=2 tw=78:
+
+ Extracts the dcopclient form a DCOPRef
+
+ Copyright 2001 Waldo Bastian <bastian@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 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.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+ const char *dcopref;
+ char *delim;
+ if ((argc != 2) || (argv[1][0] == '-'))
+ {
+ fprintf(stderr, "Usage: dcopclient <dcopref>\n");
+ return 1;
+ }
+ dcopref = argv[1];
+ if (strncmp(dcopref, "DCOPRef(", 8) != 0)
+ goto bad_ref;
+
+ if (dcopref[strlen(dcopref)-1] != ')')
+ goto bad_ref;
+
+ delim = strchr(dcopref, ',');
+ if (!delim)
+ goto bad_ref;
+
+ dcopref += 8;
+ *delim = 0;
+ puts(dcopref);
+ return 0;
+
+bad_ref:
+ fprintf(stderr, "Error: '%s' is not a valid DCOP reference.\n", dcopref);
+ return 1;
+}
diff --git a/dcop/client/dcopfind.cpp b/dcop/client/dcopfind.cpp
new file mode 100644
index 000000000..4f69f848f
--- /dev/null
+++ b/dcop/client/dcopfind.cpp
@@ -0,0 +1,282 @@
+/*****************************************************************
+Copyright (c) 2000 Matthias Ettrich <ettrich@kde.org>
+Copyright (c) 2001 Waldo Bastian <bastian@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 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.
+
+******************************************************************/
+
+#include <qbuffer.h>
+#include <qvariant.h>
+#include <qcolor.h>
+#include <qimage.h>
+#include "../kdatastream.h"
+#include "../dcopclient.h"
+#include "../dcopref.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "marshall.cpp"
+
+static DCOPClient* dcop = 0;
+static bool bAppIdOnly = 0;
+static bool bLaunchApp = 0;
+
+bool findObject( const char* app, const char* obj, const char* func, QCStringList args )
+{
+ QString f = func; // Qt is better with unicode strings, so use one.
+ int left = f.find( '(' );
+ int right = f.find( ')' );
+
+ if ( right < left )
+ {
+ qWarning( "parentheses do not match" );
+ exit(1);
+ }
+
+ if ( !f.isEmpty() && (left < 0) )
+ f += "()";
+
+ // This may seem expensive but is done only once per invocation
+ // of dcop, so it should be OK.
+ //
+ //
+ QStringList intTypes;
+ intTypes << "int" << "unsigned" << "long" << "bool" ;
+
+ QStringList types;
+ if ( left >0 && left + 1 < right - 1) {
+ types = QStringList::split( ',', f.mid( left + 1, right - left - 1) );
+ for ( QStringList::Iterator it = types.begin(); it != types.end(); ++it ) {
+ QString lt = (*it).simplifyWhiteSpace();
+
+ int s = lt.find(' ');
+
+ // If there are spaces in the name, there may be two
+ // reasons: the parameter name is still there, ie.
+ // "QString URL" or it's a complicated int type, ie.
+ // "unsigned long long int bool".
+ //
+ //
+ if ( s > 0 )
+ {
+ QStringList partl = QStringList::split(' ' , lt);
+
+ // The zero'th part is -- at the very least -- a
+ // type part. Any trailing parts *might* be extra
+ // int-type keywords, or at most one may be the
+ // parameter name.
+ //
+ //
+ s=1;
+
+ while (s < (int)partl.count() && intTypes.contains(partl[s]))
+ {
+ s++;
+ }
+
+ if (s<(int)partl.count()-1)
+ {
+ qWarning("The argument `%s' seems syntactically wrong.",
+ lt.latin1());
+ }
+ if (s==(int)partl.count()-1)
+ {
+ partl.remove(partl.at(s));
+ }
+
+ lt = partl.join(" ");
+ lt = lt.simplifyWhiteSpace();
+ }
+
+ (*it) = lt;
+ }
+ QString fc = f.left( left );
+ fc += '(';
+ bool first = true;
+ for ( QStringList::Iterator it = types.begin(); it != types.end(); ++it ) {
+ if ( !first )
+ fc +=",";
+ first = false;
+ fc += *it;
+ }
+ fc += ')';
+ f = fc;
+ }
+
+ if ( types.count() != args.count() ) {
+ qWarning( "arguments do not match" );
+ exit(1);
+ }
+
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+
+ uint i = 0;
+ for ( QStringList::Iterator it = types.begin(); it != types.end(); ++it ) {
+ marshall(arg, args, i, *it);
+ }
+ if ( (uint) i != args.count() ) {
+ qWarning( "arguments do not match" );
+ exit(1);
+ }
+
+ QCString foundApp;
+ QCString foundObj;
+ if ( dcop->findObject( app, obj, f.latin1(), data, foundApp, foundObj) )
+ {
+ if (bAppIdOnly)
+ puts(foundApp.data());
+ else
+ printf("DCOPRef(%s,%s)\n", qStringToC(foundApp), qStringToC(foundObj));
+ return true;
+ }
+ return false;
+}
+
+bool launchApp(QString app)
+{
+ int l = app.length();
+ if (l && (app[l-1] == '*'))
+ l--;
+ if (l && (app[l-1] == '-'))
+ l--;
+ if (!l) return false;
+ app.truncate(l);
+
+ QStringList URLs;
+ QByteArray data, replyData;
+ QCString replyType;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << app << URLs;
+
+ if ( !dcop->call( "klauncher", "klauncher", "start_service_by_desktop_name(QString,QStringList)",
+ data, replyType, replyData) ) {
+ qWarning( "call to klauncher failed.");
+ return false;
+ }
+ QDataStream reply(replyData, IO_ReadOnly);
+
+ if ( replyType != "serviceResult" )
+ {
+ qWarning( "unexpected result '%s' from klauncher.", replyType.data());
+ return false;
+ }
+ int result;
+ QCString dcopName;
+ QString error;
+ reply >> result >> dcopName >> error;
+ if (result != 0)
+ {
+ qWarning("Error starting '%s': %s", app.local8Bit().data(), error.local8Bit().data());
+ return false;
+ }
+ return true;
+}
+
+void usage()
+{
+ fprintf( stderr, "Usage: dcopfind [-l] [-a] application [object [function [arg1] [arg2] [arg3] ... ] ] ] \n" );
+ exit(0);
+}
+
+#ifdef Q_OS_WIN
+# define main kdemain
+#endif
+
+int main( int argc, char** argv )
+{
+ int argi = 1;
+
+ while ((argi < argc) && (argv[argi][0] == '-'))
+ {
+ switch ( argv[argi][1] ) {
+ case 'l':
+ bLaunchApp = true;
+ break;
+ case 'a':
+ bAppIdOnly = true;
+ break;
+ default:
+ usage();
+ }
+ argi++;
+ }
+
+ if (argc <= argi)
+ usage();
+
+ DCOPClient client;
+ client.attach();
+ dcop = &client;
+
+ QCString app;
+ QCString objid;
+ QCString function;
+ char **args = 0;
+ if ((argc > argi) && (strncmp(argv[argi], "DCOPRef(", 8)) == 0)
+ {
+ char *delim = strchr(argv[argi], ',');
+ if (!delim)
+ {
+ fprintf(stderr, "Error: '%s' is not a valid DCOP reference.\n", argv[argi]);
+ return 1;
+ }
+ *delim = 0;
+ app = argv[argi++] + 8;
+ delim++;
+ delim[strlen(delim)-1] = 0;
+ objid = delim;
+ }
+ else
+ {
+ if (argc > argi)
+ app = argv[argi++];
+ if (argc > argi)
+ objid = argv[argi++];
+ }
+ if (argc > argi)
+ function = argv[argi++];
+
+ if (argc > argi)
+ {
+ args = &argv[argi];
+ argc = argc-argi;
+ }
+ else
+ {
+ argc = 0;
+ }
+
+ QCStringList params;
+ for( int i = 0; i < argc; i++ )
+ params.append( args[ i ] );
+ bool ok = findObject( app, objid, function, params );
+ if (ok)
+ return 0;
+ if (bLaunchApp)
+ {
+ ok = launchApp(app);
+ if (!ok)
+ return 2;
+ ok = findObject( app, objid, function, params );
+ }
+
+ return 1;
+}
diff --git a/dcop/client/dcopobject.c b/dcop/client/dcopobject.c
new file mode 100644
index 000000000..a0ec31469
--- /dev/null
+++ b/dcop/client/dcopobject.c
@@ -0,0 +1,59 @@
+/* vi: set ts=2 sw=2 tw=78:
+
+ Extracts the dcopobject form a DCOPRef
+
+ Copyright 2001 Waldo Bastian <bastian@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 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.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+ char *dcopref;
+ char *delim;
+ if ((argc != 2) || (argv[1][0] == '-'))
+ {
+ fprintf(stderr, "Usage: dcopobject <dcopref>\n");
+ return 1;
+ }
+ dcopref = argv[1];
+ if (strncmp(dcopref, "DCOPRef(", 8) != 0)
+ goto bad_ref;
+
+ if (dcopref[strlen(dcopref)-1] != ')')
+ goto bad_ref;
+
+ delim = strchr(dcopref, ',');
+ if (!delim)
+ goto bad_ref;
+
+ dcopref = delim+1;
+ dcopref[strlen(dcopref)-1] = 0;
+ puts(dcopref);
+ return 0;
+
+bad_ref:
+ fprintf(stderr, "Error: '%s' is not a valid DCOP reference.\n", dcopref);
+ return 1;
+}
diff --git a/dcop/client/dcopquit.cpp b/dcop/client/dcopquit.cpp
new file mode 100644
index 000000000..8fdeedf02
--- /dev/null
+++ b/dcop/client/dcopquit.cpp
@@ -0,0 +1,2 @@
+#define DCOPQUIT 1
+#include "dcop.cpp"
diff --git a/dcop/client/dcopref.c b/dcop/client/dcopref.c
new file mode 100644
index 000000000..f096db27a
--- /dev/null
+++ b/dcop/client/dcopref.c
@@ -0,0 +1,40 @@
+/* vi: set ts=2 sw=2 tw=78:
+
+ Creates a DCOPRef from a dcopclient and a dcopobject.
+
+ Copyright 2001 Waldo Bastian <bastian@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 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.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+ if ((argc != 3) || (argv[1][0] == '-'))
+ {
+ fprintf(stderr, "Usage: dcopref <dcopclient> <dcopobject>\n");
+ return 1;
+ }
+ printf("DCOPRef(%s,%s)\n", argv[1], argv[2]);
+ return 0;
+}
diff --git a/dcop/client/dcopstart.cpp b/dcop/client/dcopstart.cpp
new file mode 100644
index 000000000..2b870964f
--- /dev/null
+++ b/dcop/client/dcopstart.cpp
@@ -0,0 +1,99 @@
+/*****************************************************************
+Copyright (c) 2001 Waldo Bastian <bastian@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 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.
+
+******************************************************************/
+
+#include "../kdatastream.h"
+#include "../dcopclient.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include <qstringlist.h>
+
+static DCOPClient* dcop = 0;
+
+void startApp(const char *_app, int argc, const char **args)
+{
+ const char *function = 0;
+ QString app = QString::fromLatin1(_app);
+ if (app.endsWith(".desktop"))
+ function = "start_service_by_desktop_path(QString,QStringList)";
+ else
+ function = "start_service_by_desktop_name(QString,QStringList)";
+ QStringList URLs;
+ for(int i = 0; i < argc; i++)
+ {
+ URLs.append(QString::fromLocal8Bit(args[i]));
+ }
+
+ QByteArray data, replyData;
+ QCString replyType;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << app << URLs;
+
+ if ( !dcop->call( "klauncher", "klauncher", function, data, replyType, replyData) ) {
+ qWarning( "call failed");
+ exit(1);
+ } else {
+ QDataStream reply(replyData, IO_ReadOnly);
+
+ if ( replyType != "serviceResult" )
+ {
+ qWarning( "unexpected result '%s'", replyType.data());
+ exit(1);
+ }
+ int result;
+ QCString dcopName;
+ QString error;
+ reply >> result >> dcopName >> error;
+ if (result != 0)
+ {
+ qWarning("Error: %s", error.local8Bit().data());
+ exit(1);
+ }
+ if (!dcopName.isEmpty())
+ puts(dcopName.data());
+ }
+}
+
+#ifdef Q_OS_WIN
+# define main kdemain
+#endif
+
+int main( int argc, char** argv )
+{
+ if (( argc < 2) || (argv[1][0] == '-' )) {
+ fprintf( stderr, "Usage: dcopstart <application> [url1] [url2] ...\n" );
+ exit(0);
+ }
+
+ DCOPClient client;
+ client.attach();
+ dcop = &client;
+
+ QCString app;
+ QCString objid;
+ QCString function;
+ /*char **args = 0;*/
+ startApp( argv[1], argc - 2, (const char**)&argv[2] );
+
+ return 0;
+}
diff --git a/dcop/client/marshall.cpp b/dcop/client/marshall.cpp
new file mode 100644
index 000000000..d7d5c260a
--- /dev/null
+++ b/dcop/client/marshall.cpp
@@ -0,0 +1,399 @@
+/*****************************************************************
+Copyright (c) 2000 Matthias Ettrich <ettrich@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 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.
+
+******************************************************************/
+
+#define KDE_QT_ONLY
+#include "../../kdecore/kurl.cpp"
+
+bool mkBool( const QString& s )
+{
+ if ( s.lower() == "true" )
+ return true;
+ if ( s.lower() == "yes" )
+ return true;
+ if ( s.lower() == "on" )
+ return true;
+ if ( s.toInt() != 0 )
+ return true;
+
+ return false;
+}
+
+QPoint mkPoint( const QString &str )
+{
+ const char *s = str.latin1();
+ char *end;
+ while(*s && !isdigit(*s) && *s != '-') s++;
+ int x = strtol(s, &end, 10);
+ s = (const char *)end;
+ while(*s && !isdigit(*s) && *s != '-') s++;
+ int y = strtol(s, &end, 10);
+ return QPoint( x, y );
+}
+
+QSize mkSize( const QString &str )
+{
+ const char *s = str.latin1();
+ char *end;
+ while(*s && !isdigit(*s) && *s != '-') s++;
+ int w = strtol(s, &end, 10);
+ s = (const char *)end;
+ while(*s && !isdigit(*s) && *s != '-') s++;
+ int h = strtol(s, &end, 10);
+ return QSize( w, h );
+}
+
+QRect mkRect( const QString &str )
+{
+ const char *s = str.latin1();
+ char *end;
+ while(*s && !isdigit(*s) && *s != '-') s++;
+ int p1 = strtol(s, &end, 10);
+ s = (const char *)end;
+ bool legacy = (*s == 'x');
+ while(*s && !isdigit(*s) && *s != '-') s++;
+ int p2 = strtol(s, &end, 10);
+ s = (const char *)end;
+ while(*s && !isdigit(*s) && *s != '-') s++;
+ int p3 = strtol(s, &end, 10);
+ s = (const char *)end;
+ while(*s && !isdigit(*s) && *s != '-') s++;
+ int p4 = strtol(s, &end, 10);
+ if (legacy)
+ {
+ return QRect( p3, p4, p1, p2 );
+ }
+ return QRect( p1, p2, p3, p4 );
+}
+
+QColor mkColor( const QString& s )
+{
+ QColor c;
+ c.setNamedColor(s);
+ return c;
+}
+
+const char *qStringToC(const QCString &s)
+{
+ if (s.isEmpty())
+ return "";
+ return s.data();
+}
+
+QCString demarshal( QDataStream &stream, const QString &type )
+{
+ QCString result;
+
+ if ( type == "int" || type == "Q_INT32" )
+ {
+ int i;
+ stream >> i;
+ result.setNum( i );
+ } else if ( type == "uint" || type == "Q_UINT32" || type == "unsigned int" )
+ {
+ uint i;
+ stream >> i;
+ result.setNum( i );
+ } else if ( type == "long" || type == "long int" )
+ {
+ long l;
+ stream >> l;
+ result.setNum( l );
+ } else if ( type == "unsigned long" || type == "unsigned long int" )
+ {
+ unsigned long l;
+ stream >> l;
+ result.setNum( l );
+ } else if ( type == "float" )
+ {
+ float f;
+ stream >> f;
+ result.setNum( f, 'f' );
+ } else if ( type == "double" )
+ {
+ double d;
+ stream >> d;
+ result.setNum( d, 'f' );
+ } else if ( type == "Q_INT64" ) {
+ Q_INT64 i;
+ stream >> i;
+ result.sprintf( "%lld", i );
+ } else if ( type == "Q_UINT64" ) {
+ Q_UINT64 i;
+ stream >> i;
+ result.sprintf( "%llu", i );
+ } else if ( type == "bool" )
+ {
+ bool b;
+ stream >> b;
+ result = b ? "true" : "false";
+ } else if ( type == "QString" )
+ {
+ QString s;
+ stream >> s;
+ result = s.local8Bit();
+ } else if ( type == "QCString" )
+ {
+ stream >> result;
+ } else if ( type == "QCStringList" )
+ {
+ return demarshal( stream, "QValueList<QCString>" );
+ } else if ( type == "QStringList" )
+ {
+ return demarshal( stream, "QValueList<QString>" );
+ } else if ( type == "QColor" )
+ {
+ QColor c;
+ stream >> c;
+ result = c.name().local8Bit();
+ } else if ( type == "QSize" )
+ {
+ QSize s;
+ stream >> s;
+ result.sprintf( "%dx%d", s.width(), s.height() );
+ } else if ( type == "QPixmap" || type == "QImage" )
+ {
+ QImage i;
+ stream >> i;
+ QByteArray ba;
+ QBuffer buf( ba );
+ buf.open( IO_WriteOnly );
+ i.save( &buf, "XPM" );
+ result = ba;
+ } else if ( type == "QPoint" )
+ {
+ QPoint p;
+ stream >> p;
+ result.sprintf( "+%d+%d", p.x(), p.y() );
+ } else if ( type == "QRect" )
+ {
+ QRect r;
+ stream >> r;
+ result.sprintf( "%dx%d+%d+%d", r.width(), r.height(), r.x(), r.y() );
+ } else if ( type == "QVariant" )
+ {
+ Q_INT32 type;
+ stream >> type;
+ return demarshal( stream, QVariant::typeToName( (QVariant::Type)type ) );
+ } else if ( type == "DCOPRef" )
+ {
+ DCOPRef r;
+ stream >> r;
+ result.sprintf( "DCOPRef(%s,%s)", qStringToC(r.app()), qStringToC(r.object()) );
+ } else if ( type == "KURL" )
+ {
+ KURL r;
+ stream >> r;
+ result = r.url().local8Bit();
+ } else if ( type.left( 11 ) == "QValueList<" )
+ {
+ if ( (uint)type.find( '>', 11 ) != type.length() - 1 )
+ return result;
+
+ QString nestedType = type.mid( 11, type.length() - 12 );
+
+ if ( nestedType.isEmpty() )
+ return result;
+
+ Q_UINT32 count;
+ stream >> count;
+
+ Q_UINT32 i = 0;
+ for (; i < count; ++i )
+ {
+ QCString arg = demarshal( stream, nestedType );
+ result += arg;
+
+ if ( i < count - 1 )
+ result += '\n';
+ }
+ } else if ( type.left( 5 ) == "QMap<" )
+ {
+ int commaPos = type.find( ',', 5 );
+
+ if ( commaPos == -1 )
+ return result;
+
+ if ( (uint)type.find( '>', commaPos ) != type.length() - 1 )
+ return result;
+
+ QString keyType = type.mid( 5, commaPos - 5 );
+ QString valueType = type.mid( commaPos + 1, type.length() - commaPos - 2 );
+
+ Q_UINT32 count;
+ stream >> count;
+
+ Q_UINT32 i = 0;
+ for (; i < count; ++i )
+ {
+ QCString key = demarshal( stream, keyType );
+
+ if ( key.isEmpty() )
+ continue;
+
+ QCString value = demarshal( stream, valueType );
+
+ if ( value.isEmpty() )
+ continue;
+
+ result += key + "->" + value;
+
+ if ( i < count - 1 )
+ result += '\n';
+ }
+ }
+ else
+ {
+ result.sprintf( "<%s>", type.latin1());
+ }
+
+ return result;
+
+}
+
+void marshall( QDataStream &arg, QCStringList args, uint &i, QString type )
+{
+ if( i >= args.count() )
+ {
+ qWarning("Not enough arguments (expected %d, got %d).", i, args.count());
+ exit(1);
+ }
+ QString s = QString::fromLocal8Bit( args[ i ] );
+
+ if (type == "QStringList")
+ type = "QValueList<QString>";
+ if (type == "QCStringList")
+ type = "QValueList<QCString>";
+
+ if ( type == "int" )
+ arg << s.toInt();
+ else if ( type == "uint" )
+ arg << s.toUInt();
+ else if ( type == "unsigned" )
+ arg << s.toUInt();
+ else if ( type == "unsigned int" )
+ arg << s.toUInt();
+ else if ( type == "Q_INT32" )
+ arg << s.toInt();
+ else if ( type == "Q_INT64" ) {
+ QVariant qv = QVariant( s );
+ arg << qv.toLongLong();
+ }
+ else if ( type == "Q_UINT32" )
+ arg << s.toUInt();
+ else if ( type == "Q_UINT64" ) {
+ QVariant qv = QVariant( s );
+ arg << qv.toULongLong();
+ }
+ else if ( type == "long" )
+ arg << s.toLong();
+ else if ( type == "long int" )
+ arg << s.toLong();
+ else if ( type == "unsigned long" )
+ arg << s.toULong();
+ else if ( type == "unsigned long int" )
+ arg << s.toULong();
+ else if ( type == "float" )
+ arg << s.toFloat();
+ else if ( type == "double" )
+ arg << s.toDouble();
+ else if ( type == "bool" )
+ arg << mkBool( s );
+ else if ( type == "QString" )
+ arg << s;
+ else if ( type == "QCString" )
+ arg << QCString( args[ i ] );
+ else if ( type == "QColor" )
+ arg << mkColor( s );
+ else if ( type == "QPoint" )
+ arg << mkPoint( s );
+ else if ( type == "QSize" )
+ arg << mkSize( s );
+ else if ( type == "QRect" )
+ arg << mkRect( s );
+ else if ( type == "KURL" )
+ arg << KURL( s );
+ else if ( type == "QVariant" ) {
+ if ( s == "true" || s == "false" )
+ arg << QVariant( mkBool( s ), 42 );
+ else if ( s.left( 4 ) == "int(" )
+ arg << QVariant( s.mid(4, s.length()-5).toInt() );
+ else if ( s.left( 7 ) == "QPoint(" )
+ arg << QVariant( mkPoint( s.mid(7, s.length()-8) ) );
+ else if ( s.left( 6 ) == "QSize(" )
+ arg << QVariant( mkSize( s.mid(6, s.length()-7) ) );
+ else if ( s.left( 6 ) == "QRect(" )
+ arg << QVariant( mkRect( s.mid(6, s.length()-7) ) );
+ else if ( s.left( 7 ) == "QColor(" )
+ arg << QVariant( mkColor( s.mid(7, s.length()-8) ) );
+ else
+ arg << QVariant( s );
+ } else if ( type.startsWith("QValueList<") ||
+ type == "KURL::List" ) {
+ if ( type == "KURL::List" )
+ type = "KURL";
+ else
+ type = type.mid(11, type.length() - 12);
+ QStringList list;
+ QString delim = s;
+ if (delim == "[")
+ delim = "]";
+ if (delim == "(")
+ delim = ")";
+ i++;
+ QByteArray dummy_data;
+ QDataStream dummy_arg(dummy_data, IO_WriteOnly);
+
+ uint j = i;
+ uint count = 0;
+ // Parse list to get the count
+ while (true) {
+ if( j > args.count() )
+ {
+ qWarning("List end-delimiter '%s' not found.", delim.latin1());
+ exit(1);
+ }
+ if( QString::fromLocal8Bit( args[ j ] ) == delim )
+ break;
+ marshall( dummy_arg, args, j, type );
+ count++;
+ }
+ arg << (Q_UINT32) count;
+ // Parse the list for real
+ while (true) {
+ if( i > args.count() )
+ {
+ qWarning("List end-delimiter '%s' not found.", delim.latin1());
+ exit(1);
+ }
+ if( QString::fromLocal8Bit( args[ i ] ) == delim )
+ break;
+ marshall( arg, args, i, type );
+ }
+ } else {
+ qWarning( "cannot handle datatype '%s'", type.latin1() );
+ exit(1);
+ }
+ i++;
+}
+
+// vim: set noet ts=8 sts=4 sw=4:
+
diff --git a/dcop/configure.in.in b/dcop/configure.in.in
new file mode 100644
index 000000000..60b3e5737
--- /dev/null
+++ b/dcop/configure.in.in
@@ -0,0 +1,9 @@
+dcop_prefix=${prefix}
+if test "${exec_prefix}" != NONE; then
+ dcop_prefix=${exec_prefix}
+fi
+
+AC_DEFINE_UNQUOTED(DCOP_PATH, ["${dcop_prefix}/bin"], [Define where your dcop binary is])
+AM_CONFIG_HEADER([dcop/dcop-path.h])
+
+AC_PATH_PROGS(MD5SUM, [md5sum gmd5sum], [md5sum])
diff --git a/dcop/dcop-path.h.in b/dcop/dcop-path.h.in
new file mode 100644
index 000000000..1c2522227
--- /dev/null
+++ b/dcop/dcop-path.h.in
@@ -0,0 +1 @@
+#undef DCOP_PATH
diff --git a/dcop/dcop_deadlock_test.cpp b/dcop/dcop_deadlock_test.cpp
new file mode 100644
index 000000000..d26bc25fb
--- /dev/null
+++ b/dcop/dcop_deadlock_test.cpp
@@ -0,0 +1,96 @@
+/*****************************************************************
+
+Copyright (c) 2004 Waldo Bastian <bastian@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 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.
+
+******************************************************************
+*/
+
+#include <dcop_deadlock_test.h>
+#include <dcopref.h>
+#include <qtimer.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+MyDCOPObject::MyDCOPObject(const QCString &name, const QCString &remoteName)
+: QObject(0, name), DCOPObject(name), m_remoteName(remoteName)
+{
+ connect(&m_timer, SIGNAL(timeout()), this, SLOT(slotTimeout()));
+}
+
+bool MyDCOPObject::process(const QCString &fun, const QByteArray &data,
+QCString& replyType, QByteArray &replyData)
+{
+ if (fun == "function(QCString)") {
+ QDataStream args( data, IO_ReadOnly );
+ args >> m_remoteName;
+
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+qWarning("%s: function('%s') %d:%06d", name(), m_remoteName.data(), tv.tv_sec % 100, tv.tv_usec);
+
+ replyType = "QString";
+ QDataStream reply( replyData, IO_WriteOnly );
+ reply << QString("Hey");
+ m_timer.start(1000, true);
+ return true;
+ }
+ return DCOPObject::process(fun, data, replyType, replyData);
+}
+
+void MyDCOPObject::slotTimeout()
+{
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+qWarning("%s: slotTimeout() %d:%06d", name(), tv.tv_sec % 100, tv.tv_usec);
+
+ m_timer.start(1000, true);
+ QString result;
+ DCOPRef(m_remoteName, m_remoteName).call("function", QCString(name())).get(result);
+ gettimeofday(&tv, 0);
+qWarning("%s: Got result '%s' %d:%06d", name(), result.latin1(), tv.tv_sec % 100, tv.tv_usec);
+}
+
+int main(int argc, char **argv)
+{
+ QCString myName = KApplication::dcopClient()->registerAs("testdcop", false);
+ KApplication app(argc, argv, "testdcop");
+
+ qWarning("%d:I am '%s'", getpid(), app.dcopClient()->appId().data());
+
+ if (myName == "testdcop")
+ {
+ system("./dcop_deadlock_test testdcop&");
+ }
+
+ QCString remoteApp;
+ if (argc == 2)
+ {
+ remoteApp = argv[1];
+ }
+ MyDCOPObject myObject(app.dcopClient()->appId(), remoteApp);
+
+ if (!remoteApp.isEmpty())
+ myObject.slotTimeout();
+ app.exec();
+}
+
+#include "dcop_deadlock_test.moc"
diff --git a/dcop/dcop_deadlock_test.h b/dcop/dcop_deadlock_test.h
new file mode 100644
index 000000000..f4f437fb2
--- /dev/null
+++ b/dcop/dcop_deadlock_test.h
@@ -0,0 +1,51 @@
+/*****************************************************************
+
+Copyright (c) 2004 Waldo Bastian <bastian@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 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.
+
+******************************************************************
+*/
+
+#ifndef _TESTDCOP_H_
+#define _TESTDCOP_H_
+
+#include <kapplication.h>
+#include <dcopclient.h>
+#include <dcopobject.h>
+
+#include <qobject.h>
+#include <qtimer.h>
+
+#include <stdio.h>
+
+class MyDCOPObject : public QObject, public DCOPObject
+{
+ Q_OBJECT
+public:
+ MyDCOPObject(const QCString &name, const QCString &remoteName);
+ bool process(const QCString &fun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData);
+public slots:
+ void slotTimeout();
+
+private:
+ QCString m_remoteName;
+ QTimer m_timer;
+};
+#endif
diff --git a/dcop/dcopc.c b/dcop/dcopc.c
new file mode 100644
index 000000000..c62caf2ba
--- /dev/null
+++ b/dcop/dcopc.c
@@ -0,0 +1,790 @@
+/* vi: set ts=2 sw=2 tw=78:
+ *
+ * C interface to DCOP
+ *
+ * (C) 2000 Rik Hemsley <rik@kde.org>
+ * (C) 2000 Simon Hausmann <hausmann@kde.org>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* sometimes __STDC__ is defined, but to 0. The hateful X headers
+ ask for '#if __STDC__', so they become confused. */
+#if defined(__STDC__)
+#if !__STDC__
+#undef __STDC__
+#define __STDC__ 1
+#endif
+#endif
+
+/* We really don't want to require X11 headers... */
+
+#include "config.h"
+#include <qglobal.h>
+#if defined Q_WS_X11 && ! defined K_WS_QTONLY
+#include <X11/Xlib.h>
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/Xmd.h>
+
+#include <X11/ICE/ICE.h>
+#include <X11/ICE/ICElib.h>
+#include <X11/ICE/ICEutil.h>
+#include <X11/ICE/ICEconn.h>
+#include <X11/ICE/ICEmsg.h>
+#include <X11/ICE/ICEproto.h>
+#endif
+
+#include "dcopglobal.h"
+#include "dcopc.h"
+
+
+#define BUFFER_SIZE 1024
+
+enum {
+ DCOP_REPLY_PENDING,
+ DCOP_REPLY_OK,
+ DCOP_REPLY_FAILED
+};
+
+struct dcop_reply_struct
+{
+ unsigned long status;
+ char ** replyType;
+ char ** replyData;
+ int * replyDataLength;
+ int replyId;
+};
+
+ void
+dcop_process_message(
+ IceConn iceConn,
+ IcePointer clientObject,
+ int opcode,
+ unsigned long length,
+ Bool swap,
+ IceReplyWaitInfo * replyWait,
+ Bool * replyWaitRet
+);
+
+Bool dcop_attach_internal(Bool register_as_anonymous);
+Bool dcop_ice_register(void);
+Bool dcop_connect(void);
+Bool dcop_protocol_setup(void);
+
+char * dcop_write_int (char * buf, int i);
+char * dcop_read_int (char * buf, int * i);
+char * dcop_write_string (char * buf, const char * text);
+char * dcop_read_string (char * buf, char ** output);
+
+static char * dcop_requested_name = 0;
+static char * dcop_app_name = 0;
+static int dcop_major_opcode = 0;
+static IceConn dcop_ice_conn = 0L;
+static CARD32 dcop_key = 0;
+static int dcop_reply_id = 0;
+
+static IcePoVersionRec DCOPVersions[] = {
+ { DCOPVersionMajor, DCOPVersionMinor, dcop_process_message }
+};
+
+/***************************************************************************/
+
+ char *
+dcop_write_int(char * buf, int i)
+{
+ char * p = (char *)(&i);
+
+ buf[3] = *p++;
+ buf[2] = *p++;
+ buf[1] = *p++;
+ buf[0] = *p;
+
+ return buf + 4;
+}
+
+/***************************************************************************/
+
+ char *
+dcop_read_int(char * buf, int * i)
+{
+ char *p = (char *)i;
+
+ *p++ = buf[3];
+ *p++ = buf[2];
+ *p++ = buf[1];
+ *p = buf[0];
+
+ return buf + 4;
+}
+
+/***************************************************************************/
+
+ char *
+dcop_write_string(char * buf, const char * text)
+{
+ char * pos = buf;
+ int l = strlen( text ) + 1; /* we need the \0! (Simon) */
+ pos = dcop_write_int(buf, l);
+ memcpy(pos, text, l);
+ return pos + l;
+}
+
+/***************************************************************************/
+
+ char *
+dcop_read_string(char * buf, char ** output)
+{
+ int length;
+ char * pos = dcop_read_int(buf, &length);
+ fprintf(stderr, "dcop_read_string: length == %d\n", length);
+
+ *output = (char *)malloc(length);
+ memcpy(*output, pos, length);
+ return pos + length;
+}
+
+/***************************************************************************/
+
+ Bool
+dcop_register_callback(const char * object_id, dcop_callback_t callback)
+{
+ /* STUB */
+
+ /* Avoid unused param warnings */
+ object_id = object_id;
+ callback = callback;
+ return False;
+
+ /*
+ * TODO:
+ * Map the given object id to the given callback internally, so that when we
+ * receive a message, we know where to send it. Or... should we just allow
+ * one callback only, and pass that all calls ? Depends whether I can be
+ * bothered to figure out how to do a 'map' in C.
+ */
+}
+
+/***************************************************************************/
+
+ void
+dcop_process_message(
+ IceConn iceConn,
+ IcePointer clientObject,
+ int opcode,
+ unsigned long length,
+ Bool swap,
+ IceReplyWaitInfo * replyWait,
+ Bool * replyWaitRet
+)
+{
+ struct DCOPMsg * pMsg = 0L;
+ Status status = False;
+
+ char * buf = 0L;
+ char * senderId = 0L;
+ char * app = 0L;
+ char * objId = 0L;
+ char * fun = 0L;
+ char * pos = 0L;
+ char * replyType = 0L;
+
+ int dataLength = 0;
+
+ unsigned long replyVal = 0L;
+
+ /* Avoid unused param warnings */
+ clientObject = clientObject;
+ swap = swap;
+
+ if (0 == replyWait) {
+ fprintf(stderr, "dcop_process_message(): replyWait is 0\n");
+ }
+
+ if (iceConn != dcop_ice_conn) {
+ fprintf(stderr, "dcop_process_message(): ICE connection does not match\n");
+ return;
+ }
+
+ IceReadMessageHeader(
+ dcop_ice_conn,
+ sizeof(struct DCOPMsg),
+ struct DCOPMsg,
+ pMsg
+ );
+
+
+ switch (opcode) {
+
+ case DCOPReply:
+ fprintf(stderr, "dcop_process_message(): DCOPReply received\n");
+
+ fprintf(stderr, "dcop_process_message(): length == %ld\n", length);
+ buf = (char *)malloc(length);
+ status = IceReadData(dcop_ice_conn, length, buf);
+ if (False == status) {
+ fprintf(stderr, "dcop_process_message(): IceReadData failed\n");
+ }
+
+ fprintf(stderr, "dcop_process_message(): Reading data\n");
+ pos = buf;
+ pos = dcop_read_string(pos, &replyType);
+ fprintf(stderr, "dcop_process_message(): replyType : `%s'\n", replyType);
+
+ /* TODO: Run user-provided callback. */
+
+ free(replyType);
+
+ replyVal = DCOP_REPLY_OK;
+ break;
+
+ case DCOPReplyFailed:
+ fprintf(stderr, "dcop_process_message(): DCOPReplyFailed received\n");
+ break;
+
+ case DCOPReplyWait:
+ fprintf(stderr, "dcop_process_message(): DCOPReplyWait received\n");
+ break;
+
+ case DCOPReplyDelayed:
+ fprintf(stderr, "dcop_process_message(): DCOPReplyDelayed received\n");
+ break;
+
+ case DCOPFind:
+ fprintf(stderr, "dcop_process_message(): DCOPFind received\n");
+ break;
+
+ case DCOPSend:
+
+ fprintf(stderr, "dcop_process_message(): DCOPSend received\n");
+
+ buf = (char *)malloc(length);
+ IceReadData(dcop_ice_conn, length, buf);
+
+ pos = buf;
+ pos = dcop_read_string(pos, &senderId);
+ pos = dcop_read_string(pos, &app);
+ pos = dcop_read_string(pos, &objId);
+ pos = dcop_read_string(pos, &fun);
+ pos = dcop_read_int(pos, &dataLength);
+
+ /* TODO: Run user-provided callback. */
+
+ free(senderId);
+ free(app);
+ free(objId);
+ free(fun);
+ free(buf);
+
+ replyVal = DCOP_REPLY_OK;
+ break;
+
+ case DCOPCall:
+ fprintf(stderr, "dcop_process_message(): DCOPCall not yet implemented\n");
+ break;
+
+ default:
+ fprintf(stderr, "dcop_process_message(): Invalid opcode %d\n", opcode);
+ break;
+ }
+
+ if (0 != replyWait)
+ ((struct dcop_reply_struct *)replyWait->reply)->status = replyVal;
+
+ fprintf(stderr, "dcop_process_message(): Setting replyWaitRet = True\n");
+ *replyWaitRet = True;
+ fprintf(stderr, "dcop_process_message(): Returning\n");
+}
+
+/***************************************************************************/
+
+ Bool
+dcop_send_signal(
+ const char * receiving_app,
+ const char * object,
+ const char * function,
+ char * data,
+ int dataLength
+)
+{
+ char * pos = 0L;
+ char * header = 0L;
+ unsigned int headerLength = 0;
+
+ struct DCOPMsg * pMsgPtr = 0;
+
+ static const char* sAnonymous = "anonymous";
+
+ if (0 == dcop_ice_conn) {
+ fprintf(stderr, "Try running dcop_attach(), moron\n");
+ return False;
+ }
+
+ /*
+ * First let ICE initialize the ICE Message Header and give us a pointer to
+ * it (ICE manages that buffer internally)
+ */
+ IceGetHeader(
+ dcop_ice_conn,
+ dcop_major_opcode,
+ DCOPSend,
+ sizeof(struct DCOPMsg),
+ struct DCOPMsg,
+ pMsgPtr
+ );
+
+ /*
+ * Marshall the arguments for the DCOP message header (callerApp, destApp,
+ * destObj, destFunc. The last argument is actually part of the data part of
+ * the call, but we add it to the header. It's the size of the marshalled
+ * argument data. In Qt it would look like QDataStream str( ... ) str <<
+ * callerApp << destApp << destObj << destFun <<
+ * argumentQByteArrayDataStuff; (where as str is the complete data stream
+ * sent do the dcopserver, excluding the ICE header) As the QByteArray is
+ * marshalled as [size][data] and as we (below) send the data in two chunks,
+ * first the dcop msg header and the the data, we just put the [size] field
+ * as last field into the dcop msg header ;-)
+ */
+
+ headerLength = strlen(sAnonymous) + 1 +
+ strlen(receiving_app) + 1 +
+ strlen(object) + 1 +
+ strlen(function) + 1 +
+ 4*5; /* 4 string lengths + 1 int */
+
+ header = (char *)malloc(headerLength);
+
+ pos = header;
+
+ pos = dcop_write_string(pos, sAnonymous);
+ pos = dcop_write_string(pos, receiving_app);
+ pos = dcop_write_string(pos, object);
+ pos = dcop_write_string(pos, function);
+ pos = dcop_write_int(pos, dataLength);
+
+ headerLength = pos - header;
+
+ pMsgPtr->key = dcop_key;
+ /*
+ * The length field tells the dcopserver how much bytes the dcop message
+ * takes up. We add that size to the already by IceGetHeader initialized
+ * length value, as it seems that under some circumstances (depending on the
+ * DCOPMsg structure size) the length field is aligned/padded.
+ */
+ pMsgPtr->length += headerLength + dataLength;
+
+ /* First let's send the dcop message header.
+ * IceSendData automatically takes care of first sending the Ice Message
+ * Header (outbufptr > outbuf -> flush the connection buffer)
+ */
+ IceSendData(dcop_ice_conn, headerLength, header);
+
+ /* Now the function argument data */
+ IceSendData(dcop_ice_conn, dataLength, data);
+
+ /* Send it all ;-) */
+ IceFlush(dcop_ice_conn);
+
+ free(header);
+
+ if (IceConnectionStatus(dcop_ice_conn) != IceConnectAccepted)
+ return False;
+
+ return True;
+}
+
+/***************************************************************************/
+
+ Bool
+dcop_call(
+ const char * appId,
+ const char * remApp,
+ const char * remObjId,
+ const char * remFun,
+ const char * data,
+ int dataLength,
+ char ** replyType,
+ char ** replyData,
+ int * replyDataLength
+)
+{
+ IceReplyWaitInfo waitInfo;
+ IceProcessMessagesStatus status;
+ struct dcop_reply_struct replyStruct;
+
+ char * pos = 0L;
+ char * outputData = 0L;
+ int outputDataLength = 0;
+ int temp = 0;
+ Bool success = False;
+ Bool readyRet = False;
+
+ struct DCOPMsg * pMsg;
+
+
+ fprintf(stderr, "dcop_call() ...\n");
+
+ if (0 == dcop_ice_conn) {
+ fprintf(stderr, "Try running dcop_register(), moron\n");
+ return False;
+ }
+
+
+ temp += strlen(appId);
+ temp += strlen(remApp);
+ temp += strlen(remObjId);
+ temp += strlen(remFun);
+ temp += dataLength;
+ temp += 1024; /* Extra space for marshalling overhead */
+
+ outputData = (char *)malloc(temp);
+
+ temp = 0;
+
+ pos = outputData;
+ pos = dcop_write_string(pos, appId);
+ pos = dcop_write_string(pos, remApp);
+ pos = dcop_write_string(pos, remObjId);
+ pos = dcop_write_string(pos, remFun);
+ pos = dcop_write_int(pos, dataLength);
+
+ outputDataLength = pos - outputData;
+
+ IceGetHeader(
+ dcop_ice_conn,
+ dcop_major_opcode,
+ DCOPCall,
+ sizeof(struct DCOPMsg),
+ struct DCOPMsg,
+ pMsg
+ );
+
+ pMsg->length += outputDataLength + dataLength;
+
+ IceSendData(dcop_ice_conn, outputDataLength, outputData);
+ IceSendData(dcop_ice_conn, dataLength, (char *)data);
+
+ IceFlush(dcop_ice_conn);
+
+ free(outputData);
+ outputData = NULL;
+
+ if (IceConnectionStatus(dcop_ice_conn) != IceConnectAccepted) {
+ fprintf(stderr, "dcop_call(): Connection not accepted\n");
+ return False;
+ }
+
+ waitInfo.sequence_of_request = IceLastSentSequenceNumber(dcop_ice_conn);
+ waitInfo.major_opcode_of_request = dcop_major_opcode;
+ waitInfo.minor_opcode_of_request = DCOPCall;
+
+ replyStruct.status = DCOP_REPLY_PENDING;
+ replyStruct.replyId = dcop_reply_id++;
+ replyStruct.replyType = replyType;
+ replyStruct.replyData = replyData;
+ replyStruct.replyDataLength = replyDataLength;
+
+ waitInfo.reply = (IcePointer)(&replyStruct);
+
+ readyRet = False;
+
+ do {
+ fprintf(stderr, "dcop_call(): Doing IceProcessMessages\n");
+ status = IceProcessMessages(dcop_ice_conn, &waitInfo, &readyRet);
+
+ if (status == IceProcessMessagesIOError) {
+ fprintf(stderr, "dcop_call(): IceProcessMessagesIOError\n");
+ IceCloseConnection(dcop_ice_conn);
+ return False;
+ }
+
+ fprintf(stderr, "dcop_call(): readyRet == %s\n", readyRet ? "True" : "False");
+ } while (!readyRet);
+
+ fprintf(stderr, "dcop_call(): Finished\n");
+ return (replyStruct.status == DCOP_REPLY_OK) ? True : False;
+}
+
+/***************************************************************************/
+
+ Bool
+dcop_attach()
+{
+ fprintf(stderr, "dcop_attach()\n");
+ return dcop_attach_internal(True);
+}
+
+ Bool
+dcop_attach_internal(Bool register_as_anonymous)
+{
+ fprintf(stderr,
+ "dcop_attach_internal(%s)\n", register_as_anonymous ? "True" : "False");
+
+ if (False == dcop_ice_register()) return False;
+ if (False == dcop_connect()) return False;
+ if (False == dcop_protocol_setup()) return False;
+
+ if (register_as_anonymous)
+ return (0L != dcop_register("anonymous", True)) ? True : False;
+
+ return True;
+}
+
+/***************************************************************************/
+
+ char *
+dcop_register(const char * app_name, Bool add_pid)
+{
+ char * replyType = 0L;
+ char * replyData = 0L;
+ int replyLen = 0;
+ char * data = 0L;
+ char * pos = 0L;
+ int dataLength = 0;
+ Bool callStatus = False;
+
+ fprintf(stderr, "dcop_register(`%s')\n", app_name);
+
+ if (0 == dcop_app_name) {
+
+ if (0 == dcop_ice_conn)
+ if (False == dcop_attach_internal(False))
+ return 0L;
+
+ } else {
+
+ fprintf(stderr, "dcop_init(): Reregistering as `%s'\n", app_name);
+
+ callStatus = dcop_detach();
+
+ if (False == callStatus) {
+ fprintf(stderr, "dcop_init(): Could not detach before reregistering\n");
+ return 0L;
+ }
+ }
+
+ if (False == add_pid)
+ dcop_requested_name = strdup(app_name);
+
+ else {
+
+ /* Leave room for "-pid" */
+ int len = strlen(app_name) + 64;
+ dcop_requested_name = (char *)malloc(len);
+
+ snprintf(dcop_requested_name, len, "%s-%ld", app_name, (long)getpid());
+ }
+
+ data = (char *)malloc(strlen(dcop_requested_name) + 42);
+
+ pos = data;
+ pos = dcop_write_string(pos, dcop_requested_name);
+ dataLength = pos - data;
+
+ callStatus =
+ dcop_call(
+ dcop_requested_name,
+ "DCOPServer",
+ "", /* Object irrelevant */
+ "registerAs(QCString)",
+ data,
+ dataLength,
+ &replyType,
+ &replyData,
+ &replyLen
+ );
+
+ free(dcop_requested_name);
+ free(data);
+
+ if (False == callStatus) {
+ fprintf(stderr, "dcop_register(): dcop_call() failed\n");
+ return 0L;
+ }
+
+ fprintf(stderr, "dcop_register(): Reply length is %d\n", replyLen);
+
+ if (replyLen == 0)
+ return 0L;
+
+ dcop_read_string(replyData, &dcop_app_name);
+
+ return dcop_app_name;
+}
+
+/***************************************************************************/
+
+ Bool
+dcop_ice_register()
+{
+ dcop_major_opcode =
+ IceRegisterForProtocolSetup(
+ (char *)("DCOP"),
+ (char *)DCOPVendorString,
+ (char *)DCOPReleaseString,
+ 1, /* What's this ? */
+ DCOPVersions,
+ DCOPAuthCount,
+ (char **)DCOPAuthNames,
+ DCOPClientAuthProcs,
+ 0L /* What's this ? */
+ );
+
+ return (dcop_major_opcode >= 0) ? True : False;
+}
+
+
+/***************************************************************************/
+
+ Bool
+dcop_connect()
+{
+ size_t bytesRead = 0;
+ IcePointer context = 0;
+ FILE * f = 0L;
+ char * newline = 0L;
+ char * homeDir = 0L;
+ char * display = 0L;
+ char * dcopServer = 0L;
+ char errBuf[BUFFER_SIZE];
+ char fileName[BUFFER_SIZE];
+ char hostName[BUFFER_SIZE];
+ char displayName[BUFFER_SIZE];
+ char * i;
+
+ homeDir = getenv("HOME");
+
+ if (NULL == homeDir)
+ return False;
+
+ display = getenv("DISPLAY");
+
+ if (NULL == display)
+ display = "NODISPLAY";
+
+ strncpy(displayName, display, sizeof(displayName));
+ displayName[sizeof(displayName) - 1] = 0;
+
+ if((i = strrchr(displayName, '.')) > strrchr(displayName, ':') && i)
+ *i = '\0';
+
+ while((i = strchr(displayName, ':')) != NULL)
+ *i = '_';
+
+ dcopServer = getenv("DCOPSERVER");
+
+ if (NULL == dcopServer) {
+
+ if (-1 == chdir(homeDir)) {
+ fprintf(stderr, "Cannot cd ~\n");
+ return False;
+ }
+
+ hostName[0] = '\0';
+ if (gethostname(hostName, sizeof(hostName)))
+ strcpy(hostName, "localhost");
+ else
+ hostName[sizeof(hostName)-1] = '\0';
+
+ snprintf(fileName, sizeof(fileName), ".DCOPserver_%s_%s", hostName, displayName);
+ f = fopen(fileName, "r");
+
+ if (NULL == f) {
+ fprintf(stderr, "Cannot open ~/%s\n", fileName);
+ return False;
+ }
+
+ dcopServer = (char *)malloc(BUFFER_SIZE);
+
+ bytesRead = fread((void *)dcopServer, sizeof(char), BUFFER_SIZE, f);
+ dcopServer[BUFFER_SIZE - 1] = 0;
+
+ if (0 == bytesRead)
+ return False;
+
+ newline = strchr(dcopServer, '\n');
+
+ if (NULL == newline) {
+ fprintf(stderr, "dcop server file format invalid\n");
+ return False;
+ }
+
+ *newline = '\0';
+ }
+
+ dcop_ice_conn =
+ IceOpenConnection(
+ dcopServer,
+ context,
+ False,
+ dcop_major_opcode,
+ sizeof(errBuf),
+ errBuf
+ );
+
+ if (NULL != dcopServer)
+ free(dcopServer);
+
+ if (0 == dcop_ice_conn) {
+ fprintf(stderr, "dcop_ice_conn is 0 :(\n");
+ return False;
+ }
+
+ IceSetShutdownNegotiation(dcop_ice_conn, False);
+
+ return True;
+}
+
+/***************************************************************************/
+
+ Bool
+dcop_protocol_setup()
+{
+ char * vendor = 0L;
+ char * release = 0L;
+ IcePointer clientData = 0;
+ int majorVersion = 0;
+ int minorVersion = 0;
+ int status = 0;
+ char errBuf[BUFFER_SIZE];
+
+ status =
+ IceProtocolSetup(
+ dcop_ice_conn,
+ dcop_major_opcode,
+ clientData,
+ True,
+ &(majorVersion),
+ &(minorVersion),
+ &(vendor),
+ &(release),
+ BUFFER_SIZE,
+ errBuf
+ );
+
+ return (
+ (status == IceProtocolSetupSuccess) &&
+ (IceConnectionStatus(dcop_ice_conn) == IceConnectAccepted)
+ );
+}
+
+/***************************************************************************/
+
+ Bool
+dcop_detach()
+{
+ int status;
+ IceProtocolShutdown(dcop_ice_conn, dcop_major_opcode);
+ status = IceCloseConnection(dcop_ice_conn);
+
+ if (status == IceClosedNow)
+ dcop_ice_conn = 0L;
+ else
+ fprintf(stderr, "dcop_detach(): Could not detach\n");
+
+ return status == IceClosedNow;
+}
+
diff --git a/dcop/dcopc.h b/dcop/dcopc.h
new file mode 100644
index 000000000..89aec973c
--- /dev/null
+++ b/dcop/dcopc.h
@@ -0,0 +1,134 @@
+/*
+ * C interface to DCOP
+ *
+ * (C) 2000 Rik Hemsley <rik@kde.org>
+ * (C) 2000 Simon Hausmann <hausmann@kde.org>
+ */
+
+#ifndef __dcopc_h__
+#define __dcopc_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef Bool
+#define Bool int
+#define True 1
+#define False 0
+#endif
+
+typedef void (*dcop_callback_t)(
+ const char * object_id,
+ const char * function,
+ const char * data,
+ unsigned int data_length
+);
+
+/**
+ * \addtogroup dcopc C interface to DCOP
+ * @{
+ * dcop_attach, dcop_register, dcop_detach, dcop_register_callback,
+ * dcop_send_signal, and dcop_call make up the C interface to DCOP.
+ */
+
+/**
+ * \relates DCOPClient
+ * Attach to the DCOP server.
+ * This registers you as anonymous-pid - you may then register with a 'real'
+ * name with dcop_register().
+ */
+Bool dcop_attach(void);
+
+/**
+ * \relates DCOPClient
+ * Register as app 'app_name'.
+ * If add_pid is true, you will be registered as app_name-pid.
+ *
+ * It might not be possible to give you the exact name you requested.
+ * In this case, the retval will be different to what you expect, so you
+ * should not rely on getting 'app_name'.
+ *
+ * If it was not possible to register, retval is 0.
+ * @param app_name the name of the application.
+ * @param add_pid the process id of the application
+ * @return the registered name, or 0 when the registration failed
+ */
+char * dcop_register(const char * app_name, Bool add_pid);
+
+/**
+ * \relates DCOPClient
+ * Detach from the DCOP server.
+ * @return true if successful, false otherwise
+ */
+Bool dcop_detach(void);
+
+/**
+ * \relates DCOPClient
+ * Register the callback function for an object id.
+ * This function should have signature dcop_callback_t. The name of the
+ * actual function that should be called is passed in the struct.
+ * @param object_id the object id to register
+ * @param callback the callback for the object id
+ * @return true if successful, false otherwise
+ */
+Bool dcop_register_callback(const char * object_id, dcop_callback_t callback);
+
+/**
+ * \relates DCOPClient
+ * Send a signal to a DCOP object.
+ *
+ * @param receiving_app Name the target application is registered under.
+ * Note that you may use wildcards here. For example,
+ * you could send to all 'konsole' objects that are
+ * registered using the '-pid' extension with
+ * "konsole-*".
+ *
+ * @param object Name of the remote object.
+ * @param function Name of the function to call.
+ * @param data Marshalled arguments to pass to function.
+ * @param data_length Number of octets in data.
+ * @return true if successful, false otherwise
+ */
+Bool dcop_send_signal(
+ const char * receiving_app,
+ const char * object,
+ const char * function,
+ char * data,
+ int data_length
+);
+
+/**
+ * \relates DCOPClient
+ * Call a function of a DCOP object.
+ *
+ * @param app_name Name this application is registered under.
+ * @param remote_app_name Name the target application is registered under.
+ * @param remote_object_id Name of the remote object.
+ * @param remote_function Name of the function to call.
+ * @param data Marshalled arguments to pass to function.
+ * @param data_length Number of octets in data.
+ * @param reply_type Will be set to type of retval, represented as a string.
+ * @param reply_data Will be set to retval (marshalled).
+ * @param reply_data_length Will be set to number of octets in retval.
+ * @return true if successful, false otherwise
+ */
+Bool dcop_call(
+ const char * app_name,
+ const char * remote_app_name,
+ const char * remote_object_id,
+ const char * remote_function,
+ const char * data,
+ int data_length,
+ char ** reply_type,
+ char ** reply_data,
+ int * reply_data_length
+);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __dcopc_h__ */
diff --git a/dcop/dcopclient.cpp b/dcop/dcopclient.cpp
new file mode 100644
index 000000000..2b39ecb55
--- /dev/null
+++ b/dcop/dcopclient.cpp
@@ -0,0 +1,2283 @@
+/*****************************************************************
+
+Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+Copyright (c) 1999 Matthias Ettrich <ettrich@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 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.
+
+******************************************************************/
+
+// qt <-> dcop integration
+#include <qobjectlist.h>
+#include <qmetaobject.h>
+#include <qvariant.h>
+#include <qtimer.h>
+#include <qintdict.h>
+#include <qeventloop.h>
+// end of qt <-> dcop integration
+
+#include "config.h"
+
+#include <config.h>
+#include <dcopref.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <ctype.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#ifndef QT_CLEAN_NAMESPACE
+#define QT_CLEAN_NAMESPACE
+#endif
+#include <qguardedptr.h>
+#include <qtextstream.h>
+#include <qfile.h>
+#include <qdir.h>
+#include <qapplication.h>
+#include <qsocketnotifier.h>
+#include <qregexp.h>
+
+#include <private/qucomextra_p.h>
+
+#include <dcopglobal.h>
+#include <dcopclient.h>
+#include <dcopobject.h>
+
+#if defined Q_WS_X11 && ! defined K_WS_QTONLY
+#include <X11/Xmd.h>
+#endif
+extern "C" {
+#include <KDE-ICE/ICElib.h>
+#include <KDE-ICE/ICEutil.h>
+#include <KDE-ICE/ICEmsg.h>
+#include <KDE-ICE/ICEproto.h>
+}
+
+// #define DCOPCLIENT_DEBUG 1
+
+extern QMap<QCString, DCOPObject *> * kde_dcopObjMap; // defined in dcopobject.cpp
+
+/*********************************************
+ * Keep track of local clients
+ *********************************************/
+typedef QAsciiDict<DCOPClient> client_map_t;
+static client_map_t *DCOPClient_CliMap = 0;
+
+static
+client_map_t *cliMap()
+{
+ if (!DCOPClient_CliMap)
+ DCOPClient_CliMap = new client_map_t;
+ return DCOPClient_CliMap;
+}
+
+DCOPClient *DCOPClient::findLocalClient( const QCString &_appId )
+{
+ return cliMap()->find(_appId.data());
+}
+
+static
+void registerLocalClient( const QCString &_appId, DCOPClient *client )
+{
+ cliMap()->replace(_appId.data(), client);
+}
+
+static
+void unregisterLocalClient( const QCString &_appId )
+{
+ client_map_t *map = cliMap();
+ map->remove(_appId.data());
+}
+/////////////////////////////////////////////////////////
+
+template class QPtrList<DCOPObjectProxy>;
+template class QPtrList<DCOPClientTransaction>;
+template class QPtrList<_IceConn>;
+
+struct DCOPClientMessage
+{
+ int opcode;
+ CARD32 key;
+ QByteArray data;
+};
+
+class DCOPClient::ReplyStruct
+{
+public:
+ enum ReplyStatus { Pending, Ok, Failed };
+ ReplyStruct() {
+ status = Pending;
+ replyType = 0;
+ replyData = 0;
+ replyId = -1;
+ transactionId = -1;
+ replyObject = 0;
+ }
+ ReplyStatus status;
+ QCString* replyType;
+ QByteArray* replyData;
+ int replyId;
+ Q_INT32 transactionId;
+ QCString calledApp;
+ QGuardedPtr<QObject> replyObject;
+ QCString replySlot;
+};
+
+class DCOPClientPrivate
+{
+public:
+ DCOPClient *parent;
+ QCString appId;
+ IceConn iceConn;
+ int majorOpcode; // major opcode negotiated w/server and used to tag all comms.
+
+ int majorVersion, minorVersion; // protocol versions negotiated w/server
+
+ static const char* serverAddr; // location of server in ICE-friendly format.
+ QSocketNotifier *notifier;
+ bool non_blocking_call_lock;
+ bool registered;
+ bool foreign_server;
+ bool accept_calls;
+ bool accept_calls_override; // If true, user has specified policy.
+ bool qt_bridge_enabled;
+
+ QCString senderId;
+ QCString objId;
+ QCString function;
+
+ QCString defaultObject;
+ QPtrList<DCOPClientTransaction> *transactionList;
+ bool transaction;
+ Q_INT32 transactionId;
+ int opcode;
+
+ // Special key values:
+ // 0 : Not specified
+ // 1 : DCOPSend
+ // 2 : Priority
+ // >= 42: Normal
+ CARD32 key;
+ CARD32 currentKey;
+ CARD32 currentKeySaved;
+
+ QTimer postMessageTimer;
+ QPtrList<DCOPClientMessage> messages;
+
+ QPtrList<DCOPClient::ReplyStruct> pendingReplies;
+ QPtrList<DCOPClient::ReplyStruct> asyncReplyQueue;
+
+ struct LocalTransactionResult
+ {
+ QCString replyType;
+ QByteArray replyData;
+ };
+
+ QIntDict<LocalTransactionResult> localTransActionList;
+
+ QTimer eventLoopTimer;
+};
+
+class DCOPClientTransaction
+{
+public:
+ Q_INT32 id;
+ CARD32 key;
+ QCString senderId;
+};
+
+QCString DCOPClient::iceauthPath()
+{
+#ifdef Q_OS_WIN32
+ char szPath[512];
+ char * pszFilePart;
+ int ret;
+ ret = SearchPathA(NULL,"iceauth.exe",NULL,sizeof(szPath)/sizeof(szPath[0]),szPath,&pszFilePart);
+ if(ret != 0)
+ return QCString(szPath);
+#else
+ QCString path = ::getenv("PATH");
+ if (path.isEmpty())
+ path = "/bin:/usr/bin";
+ path += ":/usr/bin/X11:/usr/X11/bin:/usr/X11R6/bin";
+ QCString fPath = strtok(path.data(), ":\b");
+ while (!fPath.isNull())
+ {
+ fPath += "/iceauth";
+ if (access(fPath.data(), X_OK) == 0)
+ {
+ return fPath;
+ }
+
+ fPath = strtok(NULL, ":\b");
+ }
+#endif
+ return 0;
+}
+
+static QCString dcopServerFile(const QCString &hostname, bool old)
+{
+ QCString fName = ::getenv("DCOPAUTHORITY");
+ if (!old && !fName.isEmpty())
+ return fName;
+
+ fName = QFile::encodeName( QDir::homeDirPath() );
+// fName = ::getenv("HOME");
+ if (fName.isEmpty())
+ {
+ fprintf(stderr, "Aborting. $HOME is not set.\n");
+ exit(1);
+ }
+#ifdef Q_WS_X11
+ QCString disp = getenv("DISPLAY");
+#elif defined(Q_WS_QWS)
+ QCString disp = getenv("QWS_DISPLAY");
+#else
+ QCString disp;
+#endif
+ if (disp.isEmpty())
+ disp = "NODISPLAY";
+
+ int i;
+ if((i = disp.findRev('.')) > disp.findRev(KPATH_SEPARATOR) && i >= 0)
+ disp.truncate(i);
+
+ if (!old)
+ {
+ while( (i = disp.find(KPATH_SEPARATOR)) >= 0)
+ disp[i] = '_';
+ }
+
+ fName += "/.DCOPserver_";
+ if (hostname.isEmpty())
+ {
+ char hostName[256];
+ hostName[0] = '\0';
+ if (gethostname(hostName, sizeof(hostName)))
+ {
+ fName += "localhost";
+ }
+ else
+ {
+ hostName[sizeof(hostName)-1] = '\0';
+ fName += hostName;
+ }
+ }
+ else
+ {
+ fName += hostname;
+ }
+ fName += "_"+disp;
+ return fName;
+}
+
+
+// static
+QCString DCOPClient::dcopServerFile(const QCString &hostname)
+{
+ return ::dcopServerFile(hostname, false);
+}
+
+
+// static
+QCString DCOPClient::dcopServerFileOld(const QCString &hostname)
+{
+ return ::dcopServerFile(hostname, true);
+}
+
+
+const char* DCOPClientPrivate::serverAddr = 0;
+
+static void DCOPProcessInternal( DCOPClientPrivate *d, int opcode, CARD32 key, const QByteArray& dataReceived, bool canPost );
+
+void DCOPClient::handleAsyncReply(ReplyStruct *replyStruct)
+{
+ if (replyStruct->replyObject)
+ {
+ QObject::connect(this, SIGNAL(callBack(int, const QCString&, const QByteArray &)),
+ replyStruct->replyObject, replyStruct->replySlot);
+ emit callBack(replyStruct->replyId, *(replyStruct->replyType), *(replyStruct->replyData));
+ QObject::disconnect(this, SIGNAL(callBack(int, const QCString&, const QByteArray &)),
+ replyStruct->replyObject, replyStruct->replySlot);
+ }
+ delete replyStruct;
+}
+
+/**
+ * Callback for ICE.
+ */
+static void DCOPProcessMessage(IceConn iceConn, IcePointer clientObject,
+ int opcode, unsigned long length, Bool /*swap*/,
+ IceReplyWaitInfo *replyWait,
+ Bool *replyWaitRet)
+{
+ DCOPMsg *pMsg = 0;
+ DCOPClientPrivate *d = static_cast<DCOPClientPrivate *>(clientObject);
+ DCOPClient::ReplyStruct *replyStruct = replyWait ? static_cast<DCOPClient::ReplyStruct*>(replyWait->reply) : 0;
+
+ IceReadMessageHeader(iceConn, sizeof(DCOPMsg), DCOPMsg, pMsg);
+ CARD32 key = pMsg->key;
+ if ( d->key == 0 )
+ d->key = key; // received a key from the server
+
+ QByteArray dataReceived( length );
+ IceReadData(iceConn, length, dataReceived.data() );
+
+ d->opcode = opcode;
+ switch (opcode ) {
+
+ case DCOPReplyFailed:
+ if ( replyStruct ) {
+ replyStruct->status = DCOPClient::ReplyStruct::Failed;
+ replyStruct->transactionId = 0;
+ *replyWaitRet = True;
+ return;
+ } else {
+ qWarning("Very strange! got a DCOPReplyFailed opcode, but we were not waiting for a reply!");
+ return;
+ }
+ case DCOPReply:
+ if ( replyStruct ) {
+ QByteArray* b = replyStruct->replyData;
+ QCString* t = replyStruct->replyType;
+ replyStruct->status = DCOPClient::ReplyStruct::Ok;
+ replyStruct->transactionId = 0;
+
+ QCString calledApp, app;
+ QDataStream ds( dataReceived, IO_ReadOnly );
+ ds >> calledApp >> app >> *t >> *b;
+
+ *replyWaitRet = True;
+ return;
+ } else {
+ qWarning("Very strange! got a DCOPReply opcode, but we were not waiting for a reply!");
+ return;
+ }
+ case DCOPReplyWait:
+ if ( replyStruct ) {
+ QCString calledApp, app;
+ Q_INT32 id;
+ QDataStream ds( dataReceived, IO_ReadOnly );
+ ds >> calledApp >> app >> id;
+ replyStruct->transactionId = id;
+ replyStruct->calledApp = calledApp;
+ d->pendingReplies.append(replyStruct);
+ *replyWaitRet = True;
+ return;
+ } else {
+ qWarning("Very strange! got a DCOPReplyWait opcode, but we were not waiting for a reply!");
+ return;
+ }
+ case DCOPReplyDelayed:
+ {
+ QDataStream ds( dataReceived, IO_ReadOnly );
+ QCString calledApp, app;
+ Q_INT32 id;
+
+ ds >> calledApp >> app >> id;
+ if (replyStruct && (id == replyStruct->transactionId) && (calledApp == replyStruct->calledApp))
+ {
+ *replyWaitRet = True;
+ }
+
+ for(DCOPClient::ReplyStruct *rs = d->pendingReplies.first(); rs;
+ rs = d->pendingReplies.next())
+ {
+ if ((rs->transactionId == id) && (rs->calledApp == calledApp))
+ {
+ d->pendingReplies.remove();
+ QByteArray* b = rs->replyData;
+ QCString* t = rs->replyType;
+ ds >> *t >> *b;
+
+ rs->status = DCOPClient::ReplyStruct::Ok;
+ rs->transactionId = 0;
+ if (!rs->replySlot.isEmpty())
+ {
+ d->parent->handleAsyncReply(rs);
+ }
+ return;
+ }
+ }
+ }
+ qWarning("Very strange! got a DCOPReplyDelayed opcode, but we were not waiting for a reply!");
+ return;
+ case DCOPCall:
+ case DCOPFind:
+ case DCOPSend:
+ DCOPProcessInternal( d, opcode, key, dataReceived, true );
+ }
+}
+
+void DCOPClient::processPostedMessagesInternal()
+{
+ if ( d->messages.isEmpty() )
+ return;
+ QPtrListIterator<DCOPClientMessage> it (d->messages );
+ DCOPClientMessage* msg ;
+ while ( ( msg = it.current() ) ) {
+ ++it;
+ if ( d->currentKey && msg->key != d->currentKey )
+ continue;
+ d->messages.removeRef( msg );
+ d->opcode = msg->opcode;
+ DCOPProcessInternal( d, msg->opcode, msg->key, msg->data, false );
+ delete msg;
+ }
+ if ( !d->messages.isEmpty() )
+ d->postMessageTimer.start( 100, true );
+}
+
+/**
+ Processes DCOPCall, DCOPFind and DCOPSend
+ */
+void DCOPProcessInternal( DCOPClientPrivate *d, int opcode, CARD32 key, const QByteArray& dataReceived, bool canPost )
+{
+ if (!d->accept_calls && (opcode == DCOPSend))
+ return;
+
+ IceConn iceConn = d->iceConn;
+ DCOPMsg *pMsg = 0;
+ DCOPClient *c = d->parent;
+ QDataStream ds( dataReceived, IO_ReadOnly );
+
+ QCString fromApp;
+ ds >> fromApp;
+ if (fromApp.isEmpty())
+ return; // Reserved for local calls
+
+ if (!d->accept_calls)
+ {
+ QByteArray reply;
+ QDataStream replyStream( reply, IO_WriteOnly );
+ // Call rejected.
+ replyStream << d->appId << fromApp;
+ IceGetHeader( iceConn, d->majorOpcode, DCOPReplyFailed,
+ sizeof(DCOPMsg), DCOPMsg, pMsg );
+ int datalen = reply.size();
+ pMsg->key = key;
+ pMsg->length += datalen;
+ IceSendData( iceConn, datalen, const_cast<char *>(reply.data()));
+ return;
+ }
+
+ QCString app, objId, fun;
+ QByteArray data;
+ ds >> app >> objId >> fun >> data;
+ d->senderId = fromApp;
+ d->objId = objId;
+ d->function = fun;
+
+// qWarning("DCOP: %s got call: %s:%s:%s key = %d currentKey = %d", d->appId.data(), app.data(), objId.data(), fun.data(), key, d->currentKey);
+
+ if ( canPost && d->currentKey && key != d->currentKey ) {
+ DCOPClientMessage* msg = new DCOPClientMessage;
+ msg->opcode = opcode;
+ msg->key = key;
+ msg->data = dataReceived;
+ d->messages.append( msg );
+ d->postMessageTimer.start( 0, true );
+ return;
+ }
+
+ d->objId = objId;
+ d->function = fun;
+
+ QCString replyType;
+ QByteArray replyData;
+ bool b;
+ CARD32 oldCurrentKey = d->currentKey;
+ if ( opcode != DCOPSend ) // DCOPSend doesn't change the current key
+ d->currentKey = key;
+
+ if ( opcode == DCOPFind )
+ b = c->find(app, objId, fun, data, replyType, replyData );
+ else
+ b = c->receive( app, objId, fun, data, replyType, replyData );
+ // set notifier back to previous state
+
+ if ( opcode == DCOPSend )
+ return;
+
+ if ((d->currentKey == key) || (oldCurrentKey != 2))
+ d->currentKey = oldCurrentKey;
+
+ QByteArray reply;
+ QDataStream replyStream( reply, IO_WriteOnly );
+
+ Q_INT32 id = c->transactionId();
+ if (id) {
+ // Call delayed. Send back the transaction ID.
+ replyStream << d->appId << fromApp << id;
+
+ IceGetHeader( iceConn, d->majorOpcode, DCOPReplyWait,
+ sizeof(DCOPMsg), DCOPMsg, pMsg );
+ pMsg->key = key;
+ pMsg->length += reply.size();
+ IceSendData( iceConn, reply.size(), const_cast<char *>(reply.data()));
+ return;
+ }
+
+ if ( !b ) {
+ // Call failed. No data send back.
+
+ replyStream << d->appId << fromApp;
+ IceGetHeader( iceConn, d->majorOpcode, DCOPReplyFailed,
+ sizeof(DCOPMsg), DCOPMsg, pMsg );
+ int datalen = reply.size();
+ pMsg->key = key;
+ pMsg->length += datalen;
+ IceSendData( iceConn, datalen, const_cast<char *>(reply.data()));
+ return;
+ }
+
+ // Call successful. Send back replyType and replyData.
+ replyStream << d->appId << fromApp << replyType << replyData.size();
+
+
+ // we are calling, so we need to set up reply data
+ IceGetHeader( iceConn, d->majorOpcode, DCOPReply,
+ sizeof(DCOPMsg), DCOPMsg, pMsg );
+ int datalen = reply.size() + replyData.size();
+ pMsg->key = key;
+ pMsg->length += datalen;
+ // use IceSendData not IceWriteData to avoid a copy. Output buffer
+ // shouldn't need to be flushed.
+ IceSendData( iceConn, reply.size(), const_cast<char *>(reply.data()));
+ IceSendData( iceConn, replyData.size(), const_cast<char *>(replyData.data()));
+}
+
+
+
+static IcePoVersionRec DCOPClientVersions[] = {
+ { DCOPVersionMajor, DCOPVersionMinor, DCOPProcessMessage }
+};
+
+
+static DCOPClient* dcop_main_client = 0;
+
+DCOPClient* DCOPClient::mainClient()
+{
+ return dcop_main_client;
+}
+
+void DCOPClient::setMainClient( DCOPClient* client )
+{
+ dcop_main_client = client;
+}
+
+
+DCOPClient::DCOPClient()
+{
+ d = new DCOPClientPrivate;
+ d->parent = this;
+ d->iceConn = 0L;
+ d->key = 0;
+ d->currentKey = 0;
+ d->majorOpcode = 0;
+ d->appId = 0;
+ d->notifier = 0L;
+ d->non_blocking_call_lock = false;
+ d->registered = false;
+ d->foreign_server = true;
+ d->accept_calls = true;
+ d->accept_calls_override = false;
+ d->qt_bridge_enabled = true;
+ d->transactionList = 0L;
+ d->transactionId = 0;
+ QObject::connect( &d->postMessageTimer, SIGNAL( timeout() ), this, SLOT( processPostedMessagesInternal() ) );
+ QObject::connect( &d->eventLoopTimer, SIGNAL( timeout() ), this, SLOT( eventLoopTimeout() ) );
+
+ if ( !mainClient() )
+ setMainClient( this );
+}
+
+DCOPClient::~DCOPClient()
+{
+#ifdef DCOPCLIENT_DEBUG
+ qWarning("d->messages.count() = %d", d->messages.count());
+ QPtrListIterator<DCOPClientMessage> it (d->messages );
+ DCOPClientMessage* msg ;
+ while ( ( msg = it.current() ) ) {
+ ++it;
+ d->messages.removeRef( msg );
+ qWarning("DROPPING UNHANDLED DCOP MESSAGE:");
+ qWarning(" opcode = %d key = %d", msg->opcode, msg->key);
+ QDataStream ds( msg->data, IO_ReadOnly );
+
+ QCString fromApp, app, objId, fun;
+ ds >> fromApp >> app >> objId >> fun;
+ qWarning(" from = %s", fromApp.data());
+ qWarning(" to = %s / %s / %s", app.data(), objId.data(), fun.data());
+ delete msg;
+ }
+#endif
+ if (d->iceConn)
+ if (IceConnectionStatus(d->iceConn) == IceConnectAccepted)
+ detach();
+
+ if (d->registered)
+ unregisterLocalClient( d->appId );
+
+ delete d->notifier;
+ delete d->transactionList;
+ d->messages.setAutoDelete(true);
+ delete d;
+
+ if ( mainClient() == this )
+ setMainClient( 0 );
+}
+
+void DCOPClient::setServerAddress(const QCString &addr)
+{
+ QCString env = "DCOPSERVER=" + addr;
+ putenv(strdup(env.data()));
+ delete [] DCOPClientPrivate::serverAddr;
+ DCOPClientPrivate::serverAddr = qstrdup( addr.data() );
+}
+
+bool DCOPClient::attach()
+{
+ if (!attachInternal( true ))
+ if (!attachInternal( true ))
+ return false; // Try two times!
+ return true;
+}
+
+void DCOPClient::bindToApp()
+{
+ // check if we have a qApp instantiated. If we do,
+ // we can create a QSocketNotifier and use it for receiving data.
+ if (qApp) {
+ if ( d->notifier )
+ delete d->notifier;
+ d->notifier = new QSocketNotifier(socket(),
+ QSocketNotifier::Read, 0, 0);
+ QObject::connect(d->notifier, SIGNAL(activated(int)),
+ SLOT(processSocketData(int)));
+ }
+}
+
+void DCOPClient::suspend()
+{
+#ifdef Q_WS_WIN //TODO: remove (win32 ports sometimes do not create notifiers)
+ if (!d->notifier)
+ return;
+#endif
+ assert(d->notifier); // Suspending makes no sense if we didn't had a qApp yet
+ d->notifier->setEnabled(false);
+}
+
+void DCOPClient::resume()
+{
+#ifdef Q_WS_WIN //TODO: remove
+ if (!d->notifier)
+ return;
+#endif
+ assert(d->notifier); // Should never happen
+ d->notifier->setEnabled(true);
+}
+
+bool DCOPClient::isSuspended() const
+{
+#if defined(Q_WS_WIN) || defined(Q_WS_MAC) //TODO: REMOVE
+ if (!d->notifier)
+ return false;
+#endif
+ return !d->notifier->isEnabled();
+}
+
+#ifdef SO_PEERCRED
+// Check whether the remote end is owned by the same user.
+static bool peerIsUs(int sockfd)
+{
+ struct ucred cred;
+ socklen_t siz = sizeof(cred);
+ if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cred, &siz) != 0)
+ return false;
+ return (cred.uid == getuid());
+}
+#else
+// Check whether the socket is owned by the same user.
+static bool isServerSocketOwnedByUser(const char*server)
+{
+#ifdef Q_OS_WIN
+ if (strncmp(server, "tcp/", 4) != 0)
+ return false; // Not a local socket -> foreign.
+ else
+ return true;
+#else
+ if (strncmp(server, "local/", 6) != 0)
+ return false; // Not a local socket -> foreign.
+ const char *path = strchr(server, KPATH_SEPARATOR);
+ if (!path)
+ return false;
+ path++;
+
+ struct stat stat_buf;
+ if (stat(path, &stat_buf) != 0)
+ return false;
+
+ return (stat_buf.st_uid == getuid());
+#endif
+}
+#endif
+
+
+bool DCOPClient::attachInternal( bool registerAsAnonymous )
+{
+ char errBuf[1024];
+
+ if ( isAttached() )
+ detach();
+
+ if ((d->majorOpcode = IceRegisterForProtocolSetup(const_cast<char *>("DCOP"),
+ const_cast<char *>(DCOPVendorString),
+ const_cast<char *>(DCOPReleaseString),
+ 1, DCOPClientVersions,
+ DCOPAuthCount,
+ const_cast<char **>(DCOPAuthNames),
+ DCOPClientAuthProcs, 0L)) < 0) {
+ emit attachFailed(QString::fromLatin1( "Communications could not be established." ));
+ return false;
+ }
+
+ bool bClearServerAddr = false;
+ // first, check if serverAddr was ever set.
+ if (!d->serverAddr) {
+ // here, we obtain the list of possible DCOP connections,
+ // and attach to them.
+ QCString dcopSrv;
+ dcopSrv = ::getenv("DCOPSERVER");
+ if (dcopSrv.isEmpty()) {
+ QCString fName = dcopServerFile();
+ QFile f(QFile::decodeName(fName));
+ if (!f.open(IO_ReadOnly)) {
+ emit attachFailed(QString::fromLatin1( "Could not read network connection list.\n" )+QFile::decodeName(fName));
+ return false;
+ }
+ int size = QMIN( 1024, f.size() ); // protection against a huge file
+ QCString contents( size+1 );
+ if ( f.readBlock( contents.data(), size ) != size )
+ {
+ qDebug("Error reading from %s, didn't read the expected %d bytes", fName.data(), size);
+ // Should we abort ?
+ }
+ contents[size] = '\0';
+ int pos = contents.find('\n');
+ if ( pos == -1 ) // Shouldn't happen
+ {
+ qDebug("Only one line in dcopserver file !: %s", contents.data());
+ dcopSrv = contents;
+ }
+ else
+ {
+ if(contents[pos - 1] == '\r') // check for windows end of line
+ pos--;
+ dcopSrv = contents.left( pos );
+//#ifndef NDEBUG
+// qDebug("dcopserver address: %s", dcopSrv.data());
+//#endif
+ }
+ }
+ d->serverAddr = qstrdup( const_cast<char *>(dcopSrv.data()) );
+ bClearServerAddr = true;
+ }
+
+ if ((d->iceConn = IceOpenConnection(const_cast<char*>(d->serverAddr),
+ static_cast<IcePointer>(this), False, d->majorOpcode,
+ sizeof(errBuf), errBuf)) == 0L) {
+ qDebug("DCOPClient::attachInternal. Attach failed %s", errBuf);
+ d->iceConn = 0;
+ if (bClearServerAddr) {
+ delete [] d->serverAddr;
+ d->serverAddr = 0;
+ }
+ emit attachFailed(QString::fromLatin1( errBuf ));
+ return false;
+ }
+ fcntl(socket(), F_SETFL, FD_CLOEXEC);
+
+ IceSetShutdownNegotiation(d->iceConn, False);
+
+ int setupstat;
+ char* vendor = 0;
+ char* release = 0;
+ setupstat = IceProtocolSetup(d->iceConn, d->majorOpcode,
+ static_cast<IcePointer>(d),
+ False, /* must authenticate */
+ &(d->majorVersion), &(d->minorVersion),
+ &(vendor), &(release), 1024, errBuf);
+ if (vendor) free(vendor);
+ if (release) free(release);
+
+ if (setupstat == IceProtocolSetupFailure ||
+ setupstat == IceProtocolSetupIOError) {
+ IceCloseConnection(d->iceConn);
+ d->iceConn = 0;
+ if (bClearServerAddr) {
+ delete [] d->serverAddr;
+ d->serverAddr = 0;
+ }
+ emit attachFailed(QString::fromLatin1( errBuf ));
+ return false;
+ } else if (setupstat == IceProtocolAlreadyActive) {
+ if (bClearServerAddr) {
+ delete [] d->serverAddr;
+ d->serverAddr = 0;
+ }
+ /* should not happen because 3rd arg to IceOpenConnection was 0. */
+ emit attachFailed(QString::fromLatin1( "internal error in IceOpenConnection" ));
+ return false;
+ }
+
+
+ if (IceConnectionStatus(d->iceConn) != IceConnectAccepted) {
+ if (bClearServerAddr) {
+ delete [] d->serverAddr;
+ d->serverAddr = 0;
+ }
+ emit attachFailed(QString::fromLatin1( "DCOP server did not accept the connection." ));
+ return false;
+ }
+
+#ifdef SO_PEERCRED
+ d->foreign_server = !peerIsUs(socket());
+#else
+ d->foreign_server = !isServerSocketOwnedByUser(d->serverAddr);
+#endif
+ if (!d->accept_calls_override)
+ d->accept_calls = !d->foreign_server;
+
+ bindToApp();
+
+ if ( registerAsAnonymous )
+ registerAs( "anonymous", true );
+
+ return true;
+}
+
+
+bool DCOPClient::detach()
+{
+ int status;
+
+ if (d->iceConn) {
+ IceProtocolShutdown(d->iceConn, d->majorOpcode);
+ status = IceCloseConnection(d->iceConn);
+ if (status != IceClosedNow)
+ return false;
+ else
+ d->iceConn = 0L;
+ }
+
+ if (d->registered)
+ unregisterLocalClient(d->appId);
+
+ delete d->notifier;
+ d->notifier = 0L;
+ d->registered = false;
+ d->foreign_server = true;
+ return true;
+}
+
+bool DCOPClient::isAttached() const
+{
+ if (!d->iceConn)
+ return false;
+
+ return (IceConnectionStatus(d->iceConn) == IceConnectAccepted);
+}
+
+bool DCOPClient::isAttachedToForeignServer() const
+{
+ return isAttached() && d->foreign_server;
+}
+
+bool DCOPClient::acceptCalls() const
+{
+ return isAttached() && d->accept_calls;
+}
+
+void DCOPClient::setAcceptCalls(bool b)
+{
+ d->accept_calls = b;
+ d->accept_calls_override = true;
+}
+
+bool DCOPClient::qtBridgeEnabled()
+{
+ return d->qt_bridge_enabled;
+}
+
+void DCOPClient::setQtBridgeEnabled(bool b)
+{
+ d->qt_bridge_enabled = b;
+}
+
+QCString DCOPClient::registerAs( const QCString &appId, bool addPID )
+{
+ QCString result;
+
+ QCString _appId = appId;
+
+ if (addPID) {
+ QCString pid;
+ pid.sprintf("-%d", getpid());
+ _appId = _appId + pid;
+ }
+
+ if( d->appId == _appId )
+ return d->appId;
+
+#if 0 // no need to detach, dcopserver can handle renaming
+ // Detach before reregistering.
+ if ( isRegistered() ) {
+ detach();
+ }
+#endif
+
+ if ( !isAttached() ) {
+ if (!attachInternal( false ))
+ if (!attachInternal( false ))
+ return result; // Try two times
+ }
+
+ // register the application identifier with the server
+ QCString replyType;
+ QByteArray data, replyData;
+ QDataStream arg( data, IO_WriteOnly );
+ arg << _appId;
+ if ( call( "DCOPServer", "", "registerAs(QCString)", data, replyType, replyData ) ) {
+ QDataStream reply( replyData, IO_ReadOnly );
+ reply >> result;
+ }
+
+ d->appId = result;
+ d->registered = !result.isNull();
+
+ if (d->registered)
+ registerLocalClient( d->appId, this );
+
+ return result;
+}
+
+bool DCOPClient::isRegistered() const
+{
+ return d->registered;
+}
+
+
+QCString DCOPClient::appId() const
+{
+ return d->appId;
+}
+
+
+int DCOPClient::socket() const
+{
+ if (d->iceConn)
+ return IceConnectionNumber(d->iceConn);
+ return 0;
+}
+
+static inline bool isIdentChar( char x )
+{ // Avoid bug in isalnum
+ return x == '_' || (x >= '0' && x <= '9') ||
+ (x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z');
+}
+
+QCString DCOPClient::normalizeFunctionSignature( const QCString& fun ) {
+ if ( fun.isEmpty() ) // nothing to do
+ return fun.copy();
+ QCString result( fun.size() );
+ char *from = fun.data();
+ char *to = result.data();
+ char *first = to;
+ char last = 0;
+ while ( true ) {
+ while ( *from && isspace(*from) )
+ from++;
+ if ( last && isIdentChar( last ) && isIdentChar( *from ) )
+ *to++ = 0x20;
+ while ( *from && !isspace(*from) ) {
+ last = *from++;
+ *to++ = last;
+ }
+ if ( !*from )
+ break;
+ }
+ if ( to > first && *(to-1) == 0x20 )
+ to--;
+ *to = '\0';
+ result.resize( (int)((long)to - (long)result.data()) + 1 );
+ return result;
+}
+
+
+QCString DCOPClient::senderId() const
+{
+ return d->senderId;
+}
+
+
+bool DCOPClient::send(const QCString &remApp, const QCString &remObjId,
+ const QCString &remFun, const QByteArray &data)
+{
+ if (remApp.isEmpty())
+ return false;
+ DCOPClient *localClient = findLocalClient( remApp );
+
+ if ( localClient ) {
+ bool saveTransaction = d->transaction;
+ Q_INT32 saveTransactionId = d->transactionId;
+ QCString saveSenderId = d->senderId;
+
+ d->senderId = 0; // Local call
+ QCString replyType;
+ QByteArray replyData;
+ (void) localClient->receive( remApp, remObjId, remFun, data, replyType, replyData );
+
+ d->transaction = saveTransaction;
+ d->transactionId = saveTransactionId;
+ d->senderId = saveSenderId;
+ // send() returns true if the data could be send to the DCOPServer,
+ // regardles of receiving the data on the other application.
+ // So we assume the data is successfully send to the (virtual) server
+ // and return true in any case.
+ return true;
+ }
+
+ if ( !isAttached() )
+ return false;
+
+
+ DCOPMsg *pMsg;
+
+ QByteArray ba;
+ QDataStream ds(ba, IO_WriteOnly);
+ ds << d->appId << remApp << remObjId << normalizeFunctionSignature(remFun) << data.size();
+
+ IceGetHeader(d->iceConn, d->majorOpcode, DCOPSend,
+ sizeof(DCOPMsg), DCOPMsg, pMsg);
+
+ pMsg->key = 1; // DCOPSend always uses the magic key 1
+ int datalen = ba.size() + data.size();
+ pMsg->length += datalen;
+
+ IceSendData( d->iceConn, ba.size(), const_cast<char *>(ba.data()) );
+ IceSendData( d->iceConn, data.size(), const_cast<char *>(data.data()) );
+
+ //IceFlush(d->iceConn);
+
+ if (IceConnectionStatus(d->iceConn) == IceConnectAccepted)
+ return true;
+ return false;
+}
+
+bool DCOPClient::send(const QCString &remApp, const QCString &remObjId,
+ const QCString &remFun, const QString &data)
+{
+ QByteArray ba;
+ QDataStream ds(ba, IO_WriteOnly);
+ ds << data;
+ return send(remApp, remObjId, remFun, ba);
+}
+
+bool DCOPClient::findObject(const QCString &remApp, const QCString &remObj,
+ const QCString &remFun, const QByteArray &data,
+ QCString &foundApp, QCString &foundObj,
+ bool useEventLoop)
+{
+ return findObject( remApp, remObj, remFun, data, foundApp, foundObj, useEventLoop, -1 );
+}
+
+bool DCOPClient::findObject(const QCString &remApp, const QCString &remObj,
+ const QCString &remFun, const QByteArray &data,
+ QCString &foundApp, QCString &foundObj,
+ bool useEventLoop, int timeout)
+{
+ QCStringList appList;
+ QCString app = remApp;
+ if (app.isEmpty())
+ app = "*";
+
+ foundApp = 0;
+ foundObj = 0;
+
+ if (app[app.length()-1] == '*')
+ {
+ // Find all apps that match 'app'.
+ // NOTE: It would be more efficient to do the filtering in
+ // the dcopserver itself.
+ int len = app.length()-1;
+ QCStringList apps=registeredApplications();
+ for( QCStringList::ConstIterator it = apps.begin();
+ it != apps.end();
+ ++it)
+ {
+ if ( strncmp( (*it).data(), app.data(), len) == 0)
+ appList.append(*it);
+ }
+ }
+ else
+ {
+ appList.append(app);
+ }
+
+ // We do all the local clients in phase1 and the rest in phase2
+ for(int phase=1; phase <= 2; phase++)
+ {
+ for( QCStringList::ConstIterator it = appList.begin();
+ it != appList.end();
+ ++it)
+ {
+ QCString remApp = *it;
+ QCString replyType;
+ QByteArray replyData;
+ bool result = false;
+ DCOPClient *localClient = findLocalClient( remApp );
+
+ if ( (phase == 1) && localClient ) {
+ // In phase 1 we do all local clients
+ bool saveTransaction = d->transaction;
+ Q_INT32 saveTransactionId = d->transactionId;
+ QCString saveSenderId = d->senderId;
+
+ d->senderId = 0; // Local call
+ result = localClient->find( remApp, remObj, remFun, data, replyType, replyData );
+
+ Q_INT32 id = localClient->transactionId();
+ if (id) {
+ // Call delayed. We have to wait till it has been processed.
+ do {
+ QApplication::eventLoop()->processEvents( QEventLoop::WaitForMore);
+ } while( !localClient->isLocalTransactionFinished(id, replyType, replyData));
+ result = true;
+ }
+ d->transaction = saveTransaction;
+ d->transactionId = saveTransactionId;
+ d->senderId = saveSenderId;
+ }
+ else if ((phase == 2) && !localClient)
+ {
+ // In phase 2 we do the other clients
+ result = callInternal(remApp, remObj, remFun, data,
+ replyType, replyData, useEventLoop, timeout, DCOPFind);
+ }
+
+ if (result)
+ {
+ if (replyType == "DCOPRef")
+ {
+ DCOPRef ref;
+ QDataStream reply( replyData, IO_ReadOnly );
+ reply >> ref;
+
+ if (ref.app() == remApp) // Consistency check
+ {
+ // replyType contains objId.
+ foundApp = ref.app();
+ foundObj = ref.object();
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool DCOPClient::process(const QCString &, const QByteArray &,
+ QCString&, QByteArray &)
+{
+ return false;
+}
+
+bool DCOPClient::isApplicationRegistered( const QCString& remApp)
+{
+ QCString replyType;
+ QByteArray data, replyData;
+ QDataStream arg( data, IO_WriteOnly );
+ arg << remApp;
+ int result = false;
+ if ( call( "DCOPServer", "", "isApplicationRegistered(QCString)", data, replyType, replyData ) ) {
+ QDataStream reply( replyData, IO_ReadOnly );
+ reply >> result;
+ }
+ return result;
+}
+
+QCStringList DCOPClient::registeredApplications()
+{
+ QCString replyType;
+ QByteArray data, replyData;
+ QCStringList result;
+ if ( call( "DCOPServer", "", "registeredApplications()", data, replyType, replyData ) ) {
+ QDataStream reply( replyData, IO_ReadOnly );
+ reply >> result;
+ }
+ return result;
+}
+
+QCStringList DCOPClient::remoteObjects( const QCString& remApp, bool *ok )
+{
+ QCString replyType;
+ QByteArray data, replyData;
+ QCStringList result;
+ if ( ok )
+ *ok = false;
+ if ( call( remApp, "DCOPClient", "objects()", data, replyType, replyData ) ) {
+ QDataStream reply( replyData, IO_ReadOnly );
+ reply >> result;
+ if ( ok )
+ *ok = true;
+ }
+ return result;
+}
+
+QCStringList DCOPClient::remoteInterfaces( const QCString& remApp, const QCString& remObj, bool *ok )
+{
+ QCString replyType;
+ QByteArray data, replyData;
+ QCStringList result;
+ if ( ok )
+ *ok = false;
+ if ( call( remApp, remObj, "interfaces()", data, replyType, replyData ) && replyType == "QCStringList") {
+ QDataStream reply( replyData, IO_ReadOnly );
+ reply >> result;
+ if ( ok )
+ *ok = true;
+ }
+ return result;
+}
+
+QCStringList DCOPClient::remoteFunctions( const QCString& remApp, const QCString& remObj, bool *ok )
+{
+ QCString replyType;
+ QByteArray data, replyData;
+ QCStringList result;
+ if ( ok )
+ *ok = false;
+ if ( call( remApp, remObj, "functions()", data, replyType, replyData ) && replyType == "QCStringList") {
+ QDataStream reply( replyData, IO_ReadOnly );
+ reply >> result;
+ if ( ok )
+ *ok = true;
+ }
+ return result;
+}
+
+void DCOPClient::setNotifications(bool enabled)
+{
+ QByteArray data;
+ QDataStream ds(data, IO_WriteOnly);
+ ds << static_cast<Q_INT8>(enabled);
+
+ QCString replyType;
+ QByteArray reply;
+ if (!call("DCOPServer", "", "setNotifications( bool )", data, replyType, reply))
+ qWarning("I couldn't enable notifications at the dcopserver!");
+}
+
+void DCOPClient::setDaemonMode( bool daemonMode )
+{
+ QByteArray data;
+ QDataStream ds(data, IO_WriteOnly);
+ ds << static_cast<Q_INT8>( daemonMode );
+
+ QCString replyType;
+ QByteArray reply;
+ if (!call("DCOPServer", "", "setDaemonMode(bool)", data, replyType, reply))
+ qWarning("I couldn't enable daemon mode at the dcopserver!");
+}
+
+
+
+/*
+ DCOP <-> Qt bridge
+
+ ********************************************************************************
+ */
+static void fillQtObjects( QCStringList& l, QObject* o, QCString path )
+{
+ if ( !path.isEmpty() )
+ path += '/';
+
+ int unnamed = 0;
+ const QObjectList *list = o ? o->children() : QObject::objectTrees();
+ if ( list ) {
+ QObjectListIt it( *list );
+ QObject *obj;
+ while ( (obj=it.current()) ) {
+ ++it;
+ QCString n = obj->name();
+ if ( n == "unnamed" || n.isEmpty() )
+ {
+ n.sprintf("%p", (void *) obj);
+ n = QString("unnamed%1(%2, %3)").arg(++unnamed).arg(obj->className()).arg(n).latin1();
+ }
+ QCString fn = path + n;
+ l.append( fn );
+ if ( obj->children() )
+ fillQtObjects( l, obj, fn );
+ }
+ }
+}
+
+namespace
+{
+struct O
+{
+ O(): o(0) {}
+ O ( const QCString& str, QObject* obj ):s(str), o(obj){}
+ QCString s;
+ QObject* o;
+};
+} // namespace
+
+static void fillQtObjectsEx( QValueList<O>& l, QObject* o, QCString path )
+{
+ if ( !path.isEmpty() )
+ path += '/';
+
+ int unnamed = 0;
+ const QObjectList *list = o ? o->children() : QObject::objectTrees();
+ if ( list ) {
+ QObjectListIt it( *list );
+ QObject *obj;
+ while ( (obj=it.current()) ) {
+ ++it;
+ QCString n = obj->name();
+ if ( n == "unnamed" || n.isEmpty() )
+ {
+ n.sprintf("%p", (void *) obj);
+ n = QString("unnamed%1(%2, %3)").arg(++unnamed).arg(obj->className()).arg(n).latin1();
+ }
+ QCString fn = path + n;
+ l.append( O( fn, obj ) );
+ if ( obj->children() )
+ fillQtObjectsEx( l, obj, fn );
+ }
+ }
+}
+
+
+static QObject* findQtObject( QCString id )
+{
+ QRegExp expr( id );
+ QValueList<O> l;
+ fillQtObjectsEx( l, 0, "qt" );
+ // Prefer an exact match, but fall-back on the first that contains the substring
+ QObject* firstContains = 0L;
+ for ( QValueList<O>::ConstIterator it = l.begin(); it != l.end(); ++it ) {
+ if ( (*it).s == id ) // exact match
+ return (*it).o;
+ if ( !firstContains && (*it).s.contains( expr ) ) {
+ firstContains = (*it).o;
+ }
+ }
+ return firstContains;
+}
+
+static QCStringList findQtObjects( QCString id )
+{
+ QRegExp expr( id );
+ QValueList<O> l;
+ fillQtObjectsEx( l, 0, "qt" );
+ QCStringList result;
+ for ( QValueList<O>::ConstIterator it = l.begin(); it != l.end(); ++it ) {
+ if ( (*it).s.contains( expr ) )
+ result << (*it).s;
+ }
+ return result;
+}
+
+static bool receiveQtObject( const QCString &objId, const QCString &fun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData)
+{
+ if ( objId == "qt" ) {
+ if ( fun == "interfaces()" ) {
+ replyType = "QCStringList";
+ QDataStream reply( replyData, IO_WriteOnly );
+ QCStringList l;
+ l << "DCOPObject";
+ l << "Qt";
+ reply << l;
+ return true;
+ } else if ( fun == "functions()" ) {
+ replyType = "QCStringList";
+ QDataStream reply( replyData, IO_WriteOnly );
+ QCStringList l;
+ l << "QCStringList functions()";
+ l << "QCStringList interfaces()";
+ l << "QCStringList objects()";
+ l << "QCStringList find(QCString)";
+ reply << l;
+ return true;
+ } else if ( fun == "objects()" ) {
+ replyType = "QCStringList";
+ QDataStream reply( replyData, IO_WriteOnly );
+ QCStringList l;
+ fillQtObjects( l, 0, "qt" );
+ reply << l;
+ return true;
+ } else if ( fun == "find(QCString)" ) {
+ QDataStream ds( data, IO_ReadOnly );
+ QCString id;
+ ds >> id ;
+ replyType = "QCStringList";
+ QDataStream reply( replyData, IO_WriteOnly );
+ reply << findQtObjects( id ) ;
+ return true;
+ }
+ } else if ( objId.left(3) == "qt/" ) {
+ QObject* o = findQtObject( objId );
+ if ( !o )
+ return false;
+ if ( fun == "functions()" ) {
+ replyType = "QCStringList";
+ QDataStream reply( replyData, IO_WriteOnly );
+ QCStringList l;
+ l << "QCStringList functions()";
+ l << "QCStringList interfaces()";
+ l << "QCStringList properties()";
+ l << "bool setProperty(QCString,QVariant)";
+ l << "QVariant property(QCString)";
+ QStrList lst = o->metaObject()->slotNames( true );
+ int i = 0;
+ for ( QPtrListIterator<char> it( lst ); it.current(); ++it ) {
+ if ( o->metaObject()->slot( i++, true )->access != QMetaData::Public )
+ continue;
+ QCString slot = it.current();
+ if ( slot.contains( "()" ) ) {
+ slot.prepend("void ");
+ l << slot;
+ }
+ }
+ reply << l;
+ return true;
+ } else if ( fun == "interfaces()" ) {
+ replyType = "QCStringList";
+ QDataStream reply( replyData, IO_WriteOnly );
+ QCStringList l;
+ QMetaObject *meta = o->metaObject();
+ while ( meta ) {
+ l.prepend( meta->className() );
+ meta = meta->superClass();
+ }
+ reply << l;
+ return true;
+ } else if ( fun == "properties()" ) {
+ replyType = "QCStringList";
+ QDataStream reply( replyData, IO_WriteOnly );
+ QCStringList l;
+ QStrList lst = o->metaObject()->propertyNames( true );
+ for ( QPtrListIterator<char> it( lst ); it.current(); ++it ) {
+ QMetaObject *mo = o->metaObject();
+ const QMetaProperty* p = mo->property( mo->findProperty( it.current(), true ), true );
+ if ( !p )
+ continue;
+ QCString prop = p->type();
+ prop += ' ';
+ prop += p->name();
+ if ( !p->writable() )
+ prop += " readonly";
+ l << prop;
+ }
+ reply << l;
+ return true;
+ } else if ( fun == "property(QCString)" ) {
+ replyType = "QVariant";
+ QDataStream ds( data, IO_ReadOnly );
+ QCString name;
+ ds >> name ;
+ QVariant result = o->property( name );
+ QDataStream reply( replyData, IO_WriteOnly );
+ reply << result;
+ return true;
+ } else if ( fun == "setProperty(QCString,QVariant)" ) {
+ QDataStream ds( data, IO_ReadOnly );
+ QCString name;
+ QVariant value;
+ ds >> name >> value;
+ replyType = "bool";
+ QDataStream reply( replyData, IO_WriteOnly );
+ reply << (Q_INT8) o->setProperty( name, value );
+ return true;
+ } else {
+ int slot = o->metaObject()->findSlot( fun, true );
+ if ( slot != -1 ) {
+ replyType = "void";
+ QUObject uo[ 1 ];
+ o->qt_invoke( slot, uo );
+ return true;
+ }
+ }
+
+
+ }
+ return false;
+}
+
+
+/*
+ ********************************************************************************
+ End of DCOP <-> Qt bridge
+ */
+
+
+bool DCOPClient::receive(const QCString &/*app*/, const QCString &objId,
+ const QCString &fun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData)
+{
+ d->transaction = false; // Assume no transaction.
+ if ( objId == "DCOPClient" ) {
+ if ( fun == "objects()" ) {
+ replyType = "QCStringList";
+ QDataStream reply( replyData, IO_WriteOnly );
+ QCStringList l;
+ if (d->qt_bridge_enabled)
+ {
+ l << "qt"; // the Qt bridge object
+ }
+ if ( kde_dcopObjMap ) {
+ QMap<QCString, DCOPObject *>::ConstIterator it( kde_dcopObjMap->begin());
+ for (; it != kde_dcopObjMap->end(); ++it) {
+ if ( !it.key().isEmpty() ) {
+ if ( it.key() == d->defaultObject )
+ l << "default";
+ l << it.key();
+ }
+ }
+ }
+ reply << l;
+ return true;
+ }
+ }
+
+ if ( objId.isEmpty() || objId == "DCOPClient" ) {
+ if ( fun == "applicationRegistered(QCString)" ) {
+ QDataStream ds( data, IO_ReadOnly );
+ QCString r;
+ ds >> r;
+ emit applicationRegistered( r );
+ return true;
+ } else if ( fun == "applicationRemoved(QCString)" ) {
+ QDataStream ds( data, IO_ReadOnly );
+ QCString r;
+ ds >> r;
+ emit applicationRemoved( r );
+ return true;
+ }
+
+ if ( process( fun, data, replyType, replyData ) )
+ return true;
+ // fall through and send to defaultObject if available
+
+ } else if (d->qt_bridge_enabled &&
+ (objId == "qt" || objId.left(3) == "qt/") ) { // dcop <-> qt bridge
+ return receiveQtObject( objId, fun, data, replyType, replyData );
+ }
+
+ if ( objId.isEmpty() || objId == "default" ) {
+ if ( !d->defaultObject.isEmpty() && DCOPObject::hasObject( d->defaultObject ) ) {
+ DCOPObject *objPtr = DCOPObject::find( d->defaultObject );
+ objPtr->setCallingDcopClient(this);
+ if (objPtr->process(fun, data, replyType, replyData))
+ return true;
+ }
+
+ // fall through and send to object proxies
+ }
+
+ if (!objId.isEmpty() && objId[objId.length()-1] == '*') {
+ // handle a multicast to several objects.
+ // doesn't handle proxies currently. should it?
+ QPtrList<DCOPObject> matchList =
+ DCOPObject::match(objId.left(objId.length()-1));
+ for (DCOPObject *objPtr = matchList.first();
+ objPtr != 0L; objPtr = matchList.next()) {
+ objPtr->setCallingDcopClient(this);
+ if (!objPtr->process(fun, data, replyType, replyData))
+ return false;
+ }
+ return true;
+ } else if (!DCOPObject::hasObject(objId)) {
+ if ( DCOPObjectProxy::proxies ) {
+ for ( QPtrListIterator<DCOPObjectProxy> it( *DCOPObjectProxy::proxies ); it.current(); ++it ) {
+ // TODO: it.current()->setCallingDcopClient(this);
+ if ( it.current()->process( objId, fun, data, replyType, replyData ) )
+ return true;
+ }
+ }
+ return false;
+
+ } else {
+ DCOPObject *objPtr = DCOPObject::find(objId);
+ objPtr->setCallingDcopClient(this);
+ if (!objPtr->process(fun, data, replyType, replyData)) {
+ // obj doesn't understand function or some other error.
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Check if the function result is a bool with the value "true"
+// If so set the function result to DCOPRef pointing to (app,objId) and
+// return true. Return false otherwise.
+static bool findResultOk(QCString &replyType, QByteArray &replyData)
+{
+ Q_INT8 success; // Tsk.. why is there no operator>>(bool)?
+ if (replyType != "bool") return false;
+
+ QDataStream reply( replyData, IO_ReadOnly );
+ reply >> success;
+
+ if (!success) return false;
+ return true;
+}
+
+// set the function result to DCOPRef pointing to (app,objId) and
+// return true.
+static bool findSuccess(const QCString &app, const QCString objId, QCString &replyType, QByteArray &replyData)
+{
+ DCOPRef ref(app, objId);
+ replyType = "DCOPRef";
+
+ replyData = QByteArray();
+ QDataStream final_reply( replyData, IO_WriteOnly );
+ final_reply << ref;
+ return true;
+}
+
+
+bool DCOPClient::find(const QCString &app, const QCString &objId,
+ const QCString &fun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData)
+{
+ d->transaction = false; // Transactions are not allowed.
+ if ( !app.isEmpty() && app != d->appId && app[app.length()-1] != '*') {
+ qWarning("WEIRD! we somehow received a DCOP message w/a different appId");
+ return false;
+ }
+
+ if (objId.isEmpty() || objId[objId.length()-1] != '*')
+ {
+ if (fun.isEmpty())
+ {
+ if (objId.isEmpty() || DCOPObject::hasObject(objId))
+ return findSuccess(app, objId, replyType, replyData);
+ return false;
+ }
+ // Message to application or single object...
+ if (receive(app, objId, fun, data, replyType, replyData))
+ {
+ if (findResultOk(replyType, replyData))
+ return findSuccess(app, objId, replyType, replyData);
+ }
+ }
+ else {
+ // handle a multicast to several objects.
+ // doesn't handle proxies currently. should it?
+ QPtrList<DCOPObject> matchList =
+ DCOPObject::match(objId.left(objId.length()-1));
+ for (DCOPObject *objPtr = matchList.first();
+ objPtr != 0L; objPtr = matchList.next())
+ {
+ replyType = 0;
+ replyData = QByteArray();
+ if (fun.isEmpty())
+ return findSuccess(app, objPtr->objId(), replyType, replyData);
+ objPtr->setCallingDcopClient(this);
+ if (objPtr->process(fun, data, replyType, replyData))
+ if (findResultOk(replyType, replyData))
+ return findSuccess(app, objPtr->objId(), replyType, replyData);
+ }
+ }
+ return false;
+}
+
+
+bool DCOPClient::call(const QCString &remApp, const QCString &remObjId,
+ const QCString &remFun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData,
+ bool useEventLoop)
+{
+ return call( remApp, remObjId, remFun, data, replyType, replyData, useEventLoop, -1 );
+}
+
+bool DCOPClient::call(const QCString &remApp, const QCString &remObjId,
+ const QCString &remFun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData,
+ bool useEventLoop, int timeout)
+{
+ if (remApp.isEmpty())
+ return false;
+ DCOPClient *localClient = findLocalClient( remApp );
+
+ if ( localClient ) {
+ bool saveTransaction = d->transaction;
+ Q_INT32 saveTransactionId = d->transactionId;
+ QCString saveSenderId = d->senderId;
+
+ d->senderId = 0; // Local call
+ bool b = localClient->receive( remApp, remObjId, remFun, data, replyType, replyData );
+
+ Q_INT32 id = localClient->transactionId();
+ if (id) {
+ // Call delayed. We have to wait till it has been processed.
+ do {
+ QApplication::eventLoop()->processEvents( QEventLoop::WaitForMore);
+ } while( !localClient->isLocalTransactionFinished(id, replyType, replyData));
+ b = true;
+ }
+ d->transaction = saveTransaction;
+ d->transactionId = saveTransactionId;
+ d->senderId = saveSenderId;
+ return b;
+ }
+
+ return callInternal(remApp, remObjId, remFun, data,
+ replyType, replyData, useEventLoop, timeout, DCOPCall);
+}
+
+void DCOPClient::asyncReplyReady()
+{
+ while( d->asyncReplyQueue.count() )
+ {
+ ReplyStruct *replyStruct = d->asyncReplyQueue.take(0);
+ handleAsyncReply(replyStruct);
+ }
+}
+
+int DCOPClient::callAsync(const QCString &remApp, const QCString &remObjId,
+ const QCString &remFun, const QByteArray &data,
+ QObject *callBackObj, const char *callBackSlot)
+{
+ QCString replyType;
+ QByteArray replyData;
+
+ ReplyStruct *replyStruct = new ReplyStruct;
+ replyStruct->replyType = new QCString;
+ replyStruct->replyData = new QByteArray;
+ replyStruct->replyObject = callBackObj;
+ replyStruct->replySlot = callBackSlot;
+ replyStruct->replyId = ++d->transactionId;
+ if (d->transactionId < 0) // Ensure that ids > 0
+ d->transactionId = 0;
+
+ bool b = callInternal(remApp, remObjId, remFun, data,
+ replyStruct, false, -1, DCOPCall);
+ if (!b)
+ {
+ delete replyStruct->replyType;
+ delete replyStruct->replyData;
+ delete replyStruct;
+ return 0;
+ }
+
+ if (replyStruct->transactionId == 0)
+ {
+ // Call is finished already
+ QTimer::singleShot(0, this, SLOT(asyncReplyReady()));
+ d->asyncReplyQueue.append(replyStruct);
+ }
+
+ return replyStruct->replyId;
+}
+
+bool DCOPClient::callInternal(const QCString &remApp, const QCString &remObjId,
+ const QCString &remFun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData,
+ bool useEventLoop, int timeout, int minor_opcode)
+{
+ ReplyStruct replyStruct;
+ replyStruct.replyType = &replyType;
+ replyStruct.replyData = &replyData;
+ return callInternal(remApp, remObjId, remFun, data, &replyStruct, useEventLoop, timeout, minor_opcode);
+}
+
+bool DCOPClient::callInternal(const QCString &remApp, const QCString &remObjId,
+ const QCString &remFun, const QByteArray &data,
+ ReplyStruct *replyStruct,
+ bool useEventLoop, int timeout, int minor_opcode)
+{
+ if ( !isAttached() )
+ return false;
+
+ DCOPMsg *pMsg;
+
+ CARD32 oldCurrentKey = d->currentKey;
+ if ( !d->currentKey )
+ d->currentKey = d->key; // no key yet, initiate new call
+
+ QByteArray ba;
+ QDataStream ds(ba, IO_WriteOnly);
+ ds << d->appId << remApp << remObjId << normalizeFunctionSignature(remFun) << data.size();
+
+ IceGetHeader(d->iceConn, d->majorOpcode, minor_opcode,
+ sizeof(DCOPMsg), DCOPMsg, pMsg);
+
+ pMsg->key = d->currentKey;
+ int datalen = ba.size() + data.size();
+ pMsg->length += datalen;
+
+// qWarning("DCOP: %s made call %s:%s:%s key = %d", d->appId.data(), remApp.data(), remObjId.data(), remFun.data(), pMsg->key);
+
+ IceSendData(d->iceConn, ba.size(), const_cast<char *>(ba.data()));
+ IceSendData(d->iceConn, data.size(), const_cast<char *>(data.data()));
+
+ if (IceConnectionStatus(d->iceConn) != IceConnectAccepted)
+ return false;
+
+ IceFlush (d->iceConn);
+
+ IceReplyWaitInfo waitInfo;
+ waitInfo.sequence_of_request = IceLastSentSequenceNumber(d->iceConn);
+ waitInfo.major_opcode_of_request = d->majorOpcode;
+ waitInfo.minor_opcode_of_request = minor_opcode;
+
+ replyStruct->transactionId = -1;
+ waitInfo.reply = static_cast<IcePointer>(replyStruct);
+
+ Bool readyRet = False;
+ IceProcessMessagesStatus s;
+
+ timeval time_start;
+ int time_left = -1;
+ if( timeout >= 0 )
+ {
+ gettimeofday( &time_start, NULL );
+ time_left = timeout;
+ }
+ for(;;) {
+ bool checkMessages = true;
+ if ( useEventLoop
+ ? d->notifier != NULL // useEventLoop needs a socket notifier and a qApp
+ : timeout >= 0 ) { // !useEventLoop doesn't block only for timeout >= 0
+ const int guiTimeout = 100;
+ checkMessages = false;
+
+ int msecs = useEventLoop
+ ? guiTimeout // timeout for the GUI refresh
+ : time_left; // time remaining for the whole call
+ fd_set fds;
+ struct timeval tv;
+ FD_ZERO( &fds );
+ FD_SET( socket(), &fds );
+ tv.tv_sec = msecs / 1000;
+ tv.tv_usec = (msecs % 1000) * 1000;
+ if ( select( socket() + 1, &fds, 0, 0, &tv ) <= 0 ) {
+ if( useEventLoop && (timeout < 0 || time_left > guiTimeout)) {
+ // nothing was available, we got a timeout. Reactivate
+ // the GUI in blocked state.
+ bool old_lock = d->non_blocking_call_lock;
+ if ( !old_lock ) {
+ d->non_blocking_call_lock = true;
+ emit blockUserInput( true );
+ }
+ if( timeout >= 0 )
+ d->eventLoopTimer.start(time_left - guiTimeout, true);
+ qApp->enter_loop();
+ d->eventLoopTimer.stop();
+ if ( !old_lock ) {
+ d->non_blocking_call_lock = false;
+ emit blockUserInput( false );
+ }
+ }
+ }
+ else
+ {
+ checkMessages = true;
+ }
+ }
+ if (!d->iceConn)
+ return false;
+
+ if( replyStruct->transactionId != -1 )
+ {
+ if (replyStruct->transactionId == 0)
+ break; // Call complete
+ if (!replyStruct->replySlot.isEmpty())
+ break; // Async call
+ }
+
+ if( checkMessages ) { // something is available
+ s = IceProcessMessages(d->iceConn, &waitInfo,
+ &readyRet);
+ if (s == IceProcessMessagesIOError) {
+ detach();
+ d->currentKey = oldCurrentKey;
+ return false;
+ }
+ }
+
+ if( replyStruct->transactionId != -1 )
+ {
+ if (replyStruct->transactionId == 0)
+ break; // Call complete
+ if (!replyStruct->replySlot.isEmpty())
+ break; // Async call
+ }
+
+ if( timeout < 0 )
+ continue;
+ timeval time_now;
+ gettimeofday( &time_now, NULL );
+ time_left = timeout -
+ ((time_now.tv_sec - time_start.tv_sec) * 1000) -
+ ((time_now.tv_usec - time_start.tv_usec) / 1000);
+ if( time_left <= 0)
+ {
+ if (useEventLoop)
+ {
+ // Before we fail, check one more time if something is available
+ time_left = 0;
+ useEventLoop = false;
+ continue;
+ }
+ *(replyStruct->replyType) = QCString();
+ *(replyStruct->replyData) = QByteArray();
+ replyStruct->status = ReplyStruct::Failed;
+ break;
+ }
+ }
+
+ // Wake up parent call, maybe it's reply is available already.
+ if ( d->non_blocking_call_lock ) {
+ qApp->exit_loop();
+ }
+
+ d->currentKey = oldCurrentKey;
+ return replyStruct->status != ReplyStruct::Failed;
+}
+
+void DCOPClient::eventLoopTimeout()
+{
+ qApp->exit_loop();
+}
+
+void DCOPClient::processSocketData(int fd)
+{
+ // Make sure there is data to read!
+ fd_set fds;
+ timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+ int result = select(fd+1, &fds, 0, 0, &timeout);
+ if (result == 0)
+ return;
+
+ if ( d->non_blocking_call_lock ) {
+ if( qApp )
+ qApp->exit_loop();
+ return;
+ }
+
+ if (!d->iceConn) {
+ if( d->notifier )
+ d->notifier->deleteLater();
+ d->notifier = 0;
+ qWarning("received an error processing data from the DCOP server!");
+ return;
+ }
+
+ IceProcessMessagesStatus s = IceProcessMessages(d->iceConn, 0, 0);
+
+ if (s == IceProcessMessagesIOError) {
+ detach();
+ qWarning("received an error processing data from the DCOP server!");
+ return;
+ }
+}
+
+void DCOPClient::setDefaultObject( const QCString& objId )
+{
+ d->defaultObject = objId;
+}
+
+
+QCString DCOPClient::defaultObject() const
+{
+ return d->defaultObject;
+}
+
+bool
+DCOPClient::isLocalTransactionFinished(Q_INT32 id, QCString &replyType, QByteArray &replyData)
+{
+ DCOPClientPrivate::LocalTransactionResult *result = d->localTransActionList.take(id);
+ if (!result)
+ return false;
+
+ replyType = result->replyType;
+ replyData = result->replyData;
+ delete result;
+
+ return true;
+}
+
+DCOPClientTransaction *
+DCOPClient::beginTransaction()
+{
+ if (d->opcode == DCOPSend)
+ return 0;
+ if (!d->transactionList)
+ d->transactionList = new QPtrList<DCOPClientTransaction>;
+
+ d->transaction = true;
+ DCOPClientTransaction *trans = new DCOPClientTransaction();
+ trans->senderId = d->senderId;
+ trans->id = ++d->transactionId;
+ if (d->transactionId < 0) // Ensure that ids > 0
+ d->transactionId = 0;
+ trans->key = d->currentKey;
+
+ d->transactionList->append( trans );
+
+ return trans;
+}
+
+Q_INT32
+DCOPClient::transactionId() const
+{
+ if (d->transaction)
+ return d->transactionId;
+ else
+ return 0;
+}
+
+void
+DCOPClient::endTransaction( DCOPClientTransaction *trans, QCString& replyType,
+ QByteArray &replyData)
+{
+ if ( !trans )
+ return;
+
+ if ( !isAttached() )
+ return;
+
+ if ( !d->transactionList) {
+ qWarning("Transaction unknown: No pending transactions!");
+ return; // No pending transactions!
+ }
+
+ if ( !d->transactionList->removeRef( trans ) ) {
+ qWarning("Transaction unknown: Not on list of pending transactions!");
+ return; // Transaction
+ }
+
+ if (trans->senderId.isEmpty())
+ {
+ // Local transaction
+ DCOPClientPrivate::LocalTransactionResult *result = new DCOPClientPrivate::LocalTransactionResult();
+ result->replyType = replyType;
+ result->replyData = replyData;
+
+ d->localTransActionList.insert(trans->id, result);
+
+ delete trans;
+
+ return;
+ }
+
+ DCOPMsg *pMsg;
+
+ QByteArray ba;
+ QDataStream ds(ba, IO_WriteOnly);
+ ds << d->appId << trans->senderId << trans->id << replyType << replyData;
+
+ IceGetHeader(d->iceConn, d->majorOpcode, DCOPReplyDelayed,
+ sizeof(DCOPMsg), DCOPMsg, pMsg);
+ pMsg->key = trans->key;
+ pMsg->length += ba.size();
+
+ IceSendData( d->iceConn, ba.size(), const_cast<char *>(ba.data()) );
+
+ delete trans;
+}
+
+void
+DCOPClient::emitDCOPSignal( const QCString &object, const QCString &signal, const QByteArray &data)
+{
+ // We hack the sending object name into the signal name
+ send("DCOPServer", "emit", object+"#"+normalizeFunctionSignature(signal), data);
+}
+
+void
+DCOPClient::emitDCOPSignal( const QCString &signal, const QByteArray &data)
+{
+ emitDCOPSignal(0, signal, data);
+}
+
+bool
+DCOPClient::connectDCOPSignal( const QCString &sender, const QCString &senderObj,
+ const QCString &signal,
+ const QCString &receiverObj, const QCString &slot, bool Volatile)
+{
+ QCString replyType;
+ QByteArray data, replyData;
+ Q_INT8 iVolatile = Volatile ? 1 : 0;
+
+ QDataStream args(data, IO_WriteOnly );
+ args << sender << senderObj << normalizeFunctionSignature(signal) << receiverObj << normalizeFunctionSignature(slot) << iVolatile;
+
+ if (!call("DCOPServer", 0,
+ "connectSignal(QCString,QCString,QCString,QCString,QCString,bool)",
+ data, replyType, replyData))
+ {
+ return false;
+ }
+
+ if (replyType != "bool")
+ return false;
+
+ QDataStream reply(replyData, IO_ReadOnly );
+ Q_INT8 result;
+ reply >> result;
+ return (result != 0);
+}
+
+bool
+DCOPClient::connectDCOPSignal( const QCString &sender, const QCString &signal,
+ const QCString &receiverObj, const QCString &slot, bool Volatile)
+{
+ return connectDCOPSignal( sender, 0, signal, receiverObj, slot, Volatile);
+}
+
+bool
+DCOPClient::disconnectDCOPSignal( const QCString &sender, const QCString &senderObj,
+ const QCString &signal,
+ const QCString &receiverObj, const QCString &slot)
+{
+ QCString replyType;
+ QByteArray data, replyData;
+
+ QDataStream args(data, IO_WriteOnly );
+ args << sender << senderObj << normalizeFunctionSignature(signal) << receiverObj << normalizeFunctionSignature(slot);
+
+ if (!call("DCOPServer", 0,
+ "disconnectSignal(QCString,QCString,QCString,QCString,QCString)",
+ data, replyType, replyData))
+ {
+ return false;
+ }
+
+ if (replyType != "bool")
+ return false;
+
+ QDataStream reply(replyData, IO_ReadOnly );
+ Q_INT8 result;
+ reply >> result;
+ return (result != 0);
+}
+
+bool
+DCOPClient::disconnectDCOPSignal( const QCString &sender, const QCString &signal,
+ const QCString &receiverObj, const QCString &slot)
+{
+ return disconnectDCOPSignal( sender, 0, signal, receiverObj, slot);
+}
+
+void
+DCOPClient::setPriorityCall(bool b)
+{
+ if (b)
+ {
+ if (d->currentKey == 2)
+ return;
+ d->currentKeySaved = d->currentKey;
+ d->currentKey = 2;
+ }
+ else
+ {
+ if (d->currentKey != 2)
+ return;
+ d->currentKey = d->currentKeySaved;
+ if ( !d->messages.isEmpty() )
+ d->postMessageTimer.start( 0, true ); // Process queued messages
+ }
+}
+
+
+
+void
+DCOPClient::emergencyClose()
+{
+ QPtrList<DCOPClient> list;
+ client_map_t *map = DCOPClient_CliMap;
+ if (!map) return;
+ QAsciiDictIterator<DCOPClient> it(*map);
+ while(it.current()) {
+ list.removeRef(it.current());
+ list.append(it.current());
+ ++it;
+ }
+ for(DCOPClient *cl = list.first(); cl; cl = list.next())
+ {
+ if (cl->d->iceConn) {
+ IceProtocolShutdown(cl->d->iceConn, cl->d->majorOpcode);
+ IceCloseConnection(cl->d->iceConn);
+ cl->d->iceConn = 0L;
+ }
+ }
+}
+
+const char *
+DCOPClient::postMortemSender()
+{
+ if (!dcop_main_client)
+ return "";
+ if (dcop_main_client->d->senderId.isEmpty())
+ return "";
+ return dcop_main_client->d->senderId.data();
+}
+
+const char *
+DCOPClient::postMortemObject()
+{
+ if (!dcop_main_client)
+ return "";
+ return dcop_main_client->d->objId.data();
+}
+const char *
+DCOPClient::postMortemFunction()
+{
+ if (!dcop_main_client)
+ return "";
+ return dcop_main_client->d->function.data();
+}
+
+void DCOPClient::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include <dcopclient.moc>
+
diff --git a/dcop/dcopclient.h b/dcop/dcopclient.h
new file mode 100644
index 000000000..2024aeaeb
--- /dev/null
+++ b/dcop/dcopclient.h
@@ -0,0 +1,840 @@
+/*
+Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+Copyright (c) 1999, 2000 Matthias Ettrich <ettrich@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 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.
+*/
+
+#ifndef _DCOPCLIENT_H
+#define _DCOPCLIENT_H
+
+#include <qobject.h>
+#include <qcstring.h>
+#include <qvaluelist.h>
+#include <qstring.h>
+#include <kdatastream.h> // needed for proper bool marshalling
+#include <kdelibs_export.h>
+
+class DCOPObjectProxy;
+class DCOPClientPrivate;
+class DCOPClientTransaction;
+
+typedef QValueList<QCString> QCStringList;
+
+/**
+ * Inter-process communication and remote procedure calls
+ * for KDE applications.
+ *
+ * This class provides IPC and RPC for KDE applications. Usually you
+ * will not have to instantiate one yourself because KApplication
+ * contains a method to return a pointer to a DCOPClient object which
+ * can be used for your whole application.
+ *
+ * Before being able to send or receive any DCOP messages, you will have
+ * to attach your client object to the DCOP server, and then register
+ * your application with a specific name. See attach()
+ * and registerAs() for
+ * more information.
+ *
+ * Data to be sent should be serialized into a QDataStream which was
+ * initialized with the QByteArray that you actually intend to send
+ * the data in. An example of how you might do this:
+ *
+ * \code
+ * QByteArray data;
+ * QDataStream arg(data, IO_WriteOnly);
+ * arg << QString("This is text I am serializing");
+ * client->send("someApp", "someObject", "someFunction(QString)", data);
+ * \endcode
+ *
+ * @see KApplication::dcopClient()
+ * @author Preston Brown <pbrown@kde.org>, Matthias Ettrich <ettrich@kde.org>
+ */
+class DCOP_EXPORT DCOPClient : public QObject
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructs a new DCOP client, but does not attach to any server. */
+ DCOPClient();
+
+ /**
+ * Cleans up any open connections and dynamic data.
+ */
+ virtual ~DCOPClient();
+
+ /**
+ * Sets the address of a server to use upon attaching.
+ *
+ * If no server address is ever specified, attach will try its best to
+ * find the server anyway.
+ * @param addr the new address of the server
+ */
+ static void setServerAddress(const QCString &addr);
+
+ /**
+ * Attaches to the DCOP server.
+ *
+ * If the connection was already attached,
+ * the connection will be re-established with the current server address.
+ *
+ * Naturally, only attached application can use DCOP services.
+ *
+ * If a QApplication object exists then client registers itself as
+ * QApplication::name() + "-" + \<pid\>.
+ * If no QApplication object exists the client registers itself as
+ * "anonymous".
+ *
+ * If you want to register differently, you should use registerAs()
+ * instead.
+ *
+ * @return true if attaching was successful.
+ */
+ bool attach();
+
+ /**
+ * @internal
+ * Internal function for KUniqueApplication to register the DCOPClient
+ * with the application in case the application didn't exist at the
+ * time the DCOPClient was created.
+ */
+ void bindToApp();
+
+ /**
+ * Detaches from the DCOP server.
+ * @return true if successful, false otherwise
+ */
+ bool detach();
+
+ /**
+ * Returns whether or not the client is attached to the server.
+ * @return true if attached, false if not
+ */
+ bool isAttached() const;
+
+ /**
+ * Returns whether the client is attached to a server owned by
+ * another user.
+ * @return true if attached to a foreign server, false if not
+ */
+ bool isAttachedToForeignServer() const;
+
+ /**
+ * Returns whether the client handles incoming calls.
+ * @return true if the client accepts calls
+ */
+ bool acceptCalls() const;
+
+ /**
+ * Specify whether the client should accept incoming calls.
+ * By default clients accept incoming calls, but not when connected
+ * to a foreign server.
+ * @param b true to accept calls, false to reject them
+ */
+ void setAcceptCalls(bool b);
+
+ /**
+ * Returns whether the DCOP - Qt bridge is enabled.
+ * By default the DCOP - Qt bridge is enabled.
+ * @return true if Qt objects are accessible over DCOP
+ * @since 3.0.2
+ */
+ bool qtBridgeEnabled(); // ### KDE 4.0: make const
+
+ /**
+ * Specify whether Qt objects of the application should be accessible
+ * via DCOP.
+ * By default the DCOP - Qt bridge is enabled.
+ * @param b true to make Qt objects accessible over DCOP
+ * @since 3.0.2
+ */
+ void setQtBridgeEnabled(bool b);
+
+ /**
+ * Registers at the DCOP server.
+ *
+ * If the application was already registered,
+ * the registration will be re-done with the new appId.
+ *
+ * @p appId is a @p unique application/program id that the server
+ * will use to associate requests with. If there is already an application
+ * registered with the same name, the server will add a number to the
+ * id to unify it. If @p addPID is true, the PID of the current process
+ * will be added to id.
+ *
+ * Registration is necessary if you want to allow other clients to talk
+ * to you. They can do so using your @p appId as first parameter
+ * for send() or call(). If you just want to talk to
+ * other clients, you
+ * do not need to register at the server. In that case attach() is
+ * enough.
+ * It will implicitly register you as "anonymous".
+ *
+ * @param appId the id of the application
+ * @param addPID true to add the process id
+ * @return The actual @p appId used for the registration or a null string
+ * if the registration wasn't successful.
+ */
+ QCString registerAs( const QCString &appId, bool addPID = true );
+
+ /**
+ * Returns whether or not the client is registered at the server.
+ * @return true if registered at the server
+ */
+ bool isRegistered() const;
+
+ /**
+ * Returns the current app id or a null string if the application
+ * hasn't yet been registered.
+ * @return the application id, or QString::null if not registered
+ */
+ QCString appId() const;
+
+ /**
+ * Returns the socket fd that is used for communication with the server.
+ * @return The socket over which DCOP is communicating with the server.
+ */
+ int socket() const;
+
+ /**
+ * Temporarily suspends processing of DCOP events.
+ * This can be useful if you need to show e.g. a dialog before
+ * your application is ready to accept DCOP requests. Normally the
+ * dialog would start an event loop and in this event loop DCOP
+ * requests will be handled.
+ *
+ * Be aware that not responding to DCOP requests may cause other
+ * programs that want to communicate with your application, to hang.
+ * @see resume()
+ * @see isSuspended()
+ */
+ void suspend();
+
+ /**
+ * Resumes the processing of DCOP events.
+ * @see suspend().
+ * @see isSuspended()
+ */
+ void resume();
+
+ /**
+ * Returns whether DCOP events are being processed.
+ * @see suspend()
+ * @see resume().
+ * @since 3.1
+ */
+ bool isSuspended() const;
+
+ /**
+ * Sends a data block to the server.
+ *
+ * @param remApp The remote application id.
+ * @param remObj The name of the remote object.
+ * @param remFun The remote function in the specified object to call.
+ * @param data The data to provide to the remote function.
+ *
+ * @return Whether or not the server was able to accept the send.
+ */
+ bool send(const QCString &remApp, const QCString &remObj,
+ const QCString &remFun, const QByteArray &data);
+
+ /**
+ * This function acts exactly the same as the above, but the data
+ * parameter can be specified as a QString for convenience.
+ *
+ * @param remApp The remote application id.
+ * @param remObj The name of the remote object.
+ * @param remFun The remote function in the specified object to call.
+ * @param data The data to provide to the remote function.
+ *
+ * @return Whether or not the server was able to accept the send.
+ */
+ bool send(const QCString &remApp, const QCString &remObj,
+ const QCString &remFun, const QString &data);
+
+ /**
+ * Performs a synchronous send and receive.
+ *
+ * The parameters are the same as for send, with the exception of
+ * another QByteArray being provided for results to be
+ * (optionally) returned in.
+ *
+ * A call blocks the application until the process receives the
+ * answer.
+ *
+ * If @p useEventLoop is true, a local event loop will be started after
+ * 1/10th of a second in order to keep the user interface updated
+ * (by processing paint events and such) until an answer is received.
+ *
+ * @param remApp the remote application's id
+ * @param remObj the remote object id
+ * @param remFun the remote function id
+ * @param data the data to send
+ * @param replyType the type of the reply will be written here
+ * @param replyData the data of the reply will be written here
+ * @param useEventLoop if true the event loop will be started when
+ * the call blocks too long
+ * @param timeout timeout for the call in miliseconds, or -1 for no timeout
+ * @return true if successful, false otherwise
+ *
+ * @since 3.2
+ *
+ * @see send()
+ */
+ bool call(const QCString &remApp, const QCString &remObj,
+ const QCString &remFun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData,
+ bool useEventLoop/*=false*/, int timeout/*=-1*/);
+ /**
+ * @deprecated
+ */
+ // KDE4 merge with above
+ bool call(const QCString &remApp, const QCString &remObj,
+ const QCString &remFun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData,
+ bool useEventLoop=false);
+
+ /**
+ * Performs a asynchronous send with receive callback.
+ *
+ * The first four parameters are the same as for send.
+ *
+ * @p callBackObj and @p callBackSlot specify a call back
+ * slot that is called when an answer is received.
+ *
+ * The slot should have the following signature:
+ * callBackSlot(int callId, const QCString& replyType,
+ * const QByteArray &replyData);
+ *
+ *
+ * @param remApp the remote application's id
+ * @param remObj the remote object id
+ * @param remFun the remote function id
+ * @param data the data to send
+ * @param callBackObj object to call back
+ * @param callBackSlot slot to call back
+ * @return 0 on failure, on success a callId > 0 is
+ * returned that will be passed as first argument of
+ * the result call back
+ *
+ * @see send()
+ * @see callback()
+ *
+ * @since 3.2
+ */
+ int callAsync(const QCString &remApp, const QCString &remObj,
+ const QCString &remFun, const QByteArray &data,
+ QObject *callBackObj, const char *callBackSlot);
+
+ /**
+ * Searches for an object which matches a criteria.
+ *
+ * findObject calls @p remFun in the applications and objects identified
+ * by @p remApp and @p remObj until @p remFun returns true. The name of
+ * the application and object that returned true are returned in
+ * @p foundApp and @p foundObj respectively.
+ *
+ * If @p remFun is empty a default function is called in the object
+ * which always returns @p true.
+ *
+ * A findObject blocks the application until the process receives the
+ * answer.
+ *
+ * If @p useEventLoop is true, a local event loop will be started after
+ * 1/10th of a second in order to keep the user interface updated
+ * (by processing paint events and such) until an answer is received.
+ *
+ * @param remApp The remote application id.
+ * @param remObj The name of the remote object.
+ * @param remFun The remote function in the specified object to call.
+ * This function should return a bool and is used as
+ * criteria.
+ * @param data The data to provide to the remote function.
+ * @param foundApp The remote application id that matched the criteria.
+ * @param foundObj The remote object that matched the criteria.
+ * @param useEventLoop if true the event loop will be started when
+ * the call blocks too long
+ * @param timeout timeout for the call in miliseconds, or -1 for no timeout
+ * @return true is returned when an object was found for which @p remFun
+ * returned true. If no such object is the function returns false.
+ *
+ * @since 3.2
+ *
+ * @see send()
+ */
+ bool findObject(const QCString &remApp, const QCString &remObj,
+ const QCString &remFun, const QByteArray &data,
+ QCString &foundApp, QCString &foundObj,
+ bool useEventLoop/*=false*/, int timeout/*=-1*/);
+
+ /**
+ * @deprecated
+ */
+ // KDE4 merge with above
+ bool findObject(const QCString &remApp, const QCString &remObj,
+ const QCString &remFun, const QByteArray &data,
+ QCString &foundApp, QCString &foundObj,
+ bool useEventLoop=false);
+
+
+ /**
+ * Emits @p signal as DCOP signal from object @p object with @p data as
+ * arguments.
+ */
+ void emitDCOPSignal( const QCString &object, const QCString &signal,
+ const QByteArray &data);
+
+ /* For backwards compatibility */
+ void emitDCOPSignal( const QCString &signal, const QByteArray &data);
+
+ /**
+ * Connects to a DCOP signal.
+ * @param sender the name of the client that emits the signal. When empty
+ * the signal will be passed from any client.
+ * @param senderObj the name of the sending object that emits the signal.
+ * @param signal the name of the signal. The arguments should match with slot.
+ * @param receiverObj The name of the object to call
+ * @param slot The name of the slot to call. Its arguments should match with signal.
+ * @param Volatile If true, the connection will not be reestablished when
+ * @p sender unregisters and reregisters with DCOP. In this case the @p sender
+ * must be registered when the connection is made.
+ * If false, the connection will be reestablished when @p sender reregisters.
+ * In this case the connection can be made even if @p sender is not registered
+ * at that time.
+ *
+ * @return false if a connection could not be established.
+ * This will be the case when
+ * @li @p Volatile is true and @p sender does not exist.
+ * @li @p signal and @p slot do not have matching arguments.
+ */
+ bool connectDCOPSignal( const QCString &sender, const QCString &senderObj,
+ const QCString &signal,
+ const QCString &receiverObj, const QCString &slot,
+ bool Volatile);
+
+ /**
+ * @deprecated
+ * For backwards compatibility
+ */
+ bool connectDCOPSignal( const QCString &sender, const QCString &signal,
+ const QCString &receiverObj, const QCString &slot,
+ bool Volatile) KDE_DEPRECATED;
+
+ /**
+ * Disconnects a DCOP signal.
+ *
+ * A special case is when both @p sender & @p signal are empty. In this
+ * case all connections related to @p receiverObj in the current client
+ * are disconnected. (Both connections from as well as to this object!)
+ *
+ * @param sender the name of the client that emits the signal.
+ * @param senderObj the name of the object that emits the signal.
+ * If empty all objects will be disconnected.
+ * @param signal the name of the signal. The arguments should match with slot.
+ * @param receiverObj The name of the object the signal is connected to.
+ * If empty all objects will be disconnected.
+ * @param slot The name of the slot the signal is connected to.
+ * If empty all slots will be disconnected.
+ * @return false if no connection(s) where removed.
+ */
+ bool disconnectDCOPSignal( const QCString &sender, const QCString &senderObj,
+ const QCString &signal,
+ const QCString &receiverObj, const QCString &slot);
+
+ /**
+ * @deprecated
+ * For backwards compatibility
+ */
+ bool disconnectDCOPSignal( const QCString &sender, const QCString &signal,
+ const QCString &receiverObj, const QCString &slot) KDE_DEPRECATED;
+
+ /**
+ * Reimplement this function to handle app-wide function calls unassociated w/an object.
+ *
+ * Note that @p fun is normalized. See normalizeFunctionSignature().
+ *
+ * If you do not want to reimplement this function for whatever reason,
+ * you can also use a default object or a DCOPObjectProxy.
+ *
+ * @param fun the normalized function signature
+ * @param data the received data
+ * @param replyType write the reply type in this string
+ * @param replyData write the reply data in this array
+ * @return true if successful, false otherwise
+ * @see setDefaultObject()
+ */
+ virtual bool process(const QCString &fun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData);
+
+ /**
+ * Delays the reply of the current function call
+ * until endTransaction() is called.
+ *
+ * This allows a server to queue requests.
+ *
+ * Note: Should be called from inside process() only!
+ * @see endTransaction()
+ */
+ DCOPClientTransaction *beginTransaction( );
+
+ /**
+ * Sends the delayed reply of a function call.
+ * @param t the transaction as received from beginTransaction()
+ * @param replyType write the reply type in this string
+ * @param replyData write the reply data in this array
+ * @see beginTransaction()
+ */
+ void endTransaction( DCOPClientTransaction *t, QCString& replyType, QByteArray &replyData);
+
+ /**
+ * Test whether the current function call is delayed.
+ *
+ * Note: Should be called from inside process() only!
+ * @return The ID of the current transaction or
+ * 0 if no transaction is going on.
+ * @see process()
+ * @see beginTransaction()
+ */
+ Q_INT32 transactionId() const;
+
+ /**
+ * Checks whether @p remApp is registered with the DCOP server.
+ * @param remApp the id of the remote application
+ * @return true if the remote application is registered, otherwise @p false.
+ */
+ bool isApplicationRegistered( const QCString& remApp);
+
+ /**
+ * Retrieves the list of all currently registered applications
+ * from dcopserver.
+ * @return a list of all regietered applications
+ */
+ QCStringList registeredApplications();
+
+ /**
+ * Retrieves the list of objects of the remote application @p remApp.
+ * @param remApp he id of the application
+ * @param ok if not null, the function sets @p ok to true if successful
+ * and false if an error occurred
+ * @return the list of object ids
+ */
+ QCStringList remoteObjects( const QCString& remApp, bool *ok = 0 );
+
+ /**
+ * Retrieves the list of interfaces of the remote object @p remObj
+ * of application @p remApp.
+ * @param remApp the id of the application
+ * @param remObj the id of the object
+ * @param ok if not null, the function sets @p ok to true if successful
+ * and false if an error occurred
+ * @return the list of interfaces
+ */
+ QCStringList remoteInterfaces( const QCString& remApp, const QCString& remObj , bool *ok = 0 );
+
+ /**
+ * Retrieves the list of functions of the remote object @p remObj
+ * of application @p remApp
+ * @param remApp the id of the application
+ * @param remObj the id of the object
+ * @param ok if not null, the function sets @p ok to true if successful
+ * and false if an error occurred
+ * @return the list of function ids
+ */
+ QCStringList remoteFunctions( const QCString& remApp, const QCString& remObj , bool *ok = 0 );
+
+ /**
+ * @internal
+ * Receives a DCOPSend or DCOPCall message from the server.
+ *
+ * @param app The application the message was intended for. Should be
+ * equal to our appId that we passed when the DCOPClient was
+ * created.
+ * @param obj The name of the object to pass the data on to.
+ * @param fun The name of the function in the object to call.
+ * @param data The arguments for the function.
+ * @param replyType write the reply type in this string
+ * @param replyData write the reply data in this array
+ * @return true if successful, false otherwise
+ */
+ bool receive(const QCString &app, const QCString &obj,
+ const QCString &fun, const QByteArray& data,
+ QCString& replyType, QByteArray &replyData);
+
+ /**
+ * @internal
+ * Receives a @p DCOPFind message from the server.
+ *
+ * @param app The application the message was intended for. Should be
+ * equal to our appId that we passed when the DCOPClient was
+ * created.
+ * @param obj The name of the object to pass the data on to.
+ * @param fun The name of the function in the object to call.
+ * @param data The arguments for the function.
+ * @param replyType write the reply type in this string
+ * @param replyData write the reply data in this array
+ */
+ bool find(const QCString &app, const QCString &obj,
+ const QCString &fun, const QByteArray& data,
+ QCString& replyType, QByteArray &replyData);
+
+ /**
+ * Normalizes the function signature @p fun.
+ *
+ * A normalized signature doesn't contain any unnecessary whitespace
+ * anymore. The remaining whitespace consists of single blanks only (0x20).
+ *
+ * Example for a normalized signature:
+ * \code
+ * "someFunction(QString,int)"
+ * \endcode
+ *
+ * When using send() or call(), normalization is done
+ * automatically for you.
+ *
+ * @param fun the function signature to normalize
+ * @return the normalized function
+ */
+ static QCString normalizeFunctionSignature( const QCString& fun );
+
+
+ /**
+ * Returns the appId of the last application that talked to us.
+ * @return the application id of the last application that send a message
+ * to this client
+ */
+ QCString senderId() const;
+
+
+ /**
+ * Installs object @p objId as application-wide default object.
+ *
+ * All app-wide messages that have not been processed by the dcopclient
+ * will be send further to @p objId.
+ * @param objId the id of the new default object
+ */
+ void setDefaultObject( const QCString& objId );
+
+ /**
+ * Returns the current default object or an empty string if no object is
+ * installed as default object.
+ *
+ * A default object receives application-wide messages that have not
+ * been processed by the DCOPClient itself.
+ * @return the id of the new default object
+ */
+ QCString defaultObject() const;
+
+ /**
+ * Enables / disables the applicationRegistered() /
+ * applicationRemoved() signals.
+ * Note that a counter is maintained about how often this method
+ * was called. If this method is called twice with @p enabled set to
+ * true, notifications will be enabled until it was called with
+ * @p enabled set to false as often.
+ *
+ * They are disabled by default.
+ * @param enabled true to enable notifications, false to disable
+ */
+ void setNotifications( bool enabled );
+
+ /**
+ * Tells the dcopserver to treat the client as daemon client, not
+ * as regular client.
+ * If the number of regular clients drops down to zero, the
+ * dcopserver will emit a KDE termination signal after 10
+ * seconds.
+ * @param daemonMode true to enable daemon mode, false to disable
+ */
+ void setDaemonMode( bool daemonMode );
+
+ /**
+ * @internal
+ *
+ * Switch to priority call mode.
+ */
+ void setPriorityCall(bool);
+
+ /**
+ * Returns the application's main dcop client. The main client can
+ * be used by objects that do not have any specific access to a dcop
+ * client. In KDE applications, the main client usually is the same
+ * as KApplication::dcopClient().
+ * @return the application's main dcop client
+ */
+ static DCOPClient* mainClient();
+
+ /**
+ * Sets the application's main dcop client. The main client can
+ * be used by objects that do not have any specific access to a dcop
+ * client. In KDE applications, the main client usually is the same
+ * as KApplication::dcopClient().
+ * @param mainClient the new main dcop client
+ */
+ static void setMainClient( DCOPClient* mainClient);
+
+ /**
+ * Look for the given client only in this process. This can be used
+ * to check whether a given client (by name) is running in the same
+ * process or in another one.
+ */
+ static DCOPClient* findLocalClient( const QCString &_appId );
+
+ /**
+ * @internal Do not use.
+ */
+ static void emergencyClose();
+
+ /**
+ * @internal Do not use.
+ *
+ * Provides information about the last DCOP call for debugging purposes.
+ */
+ static const char *postMortemSender();
+ /** @internal */
+ static const char *postMortemObject();
+ /** @internal */
+ static const char *postMortemFunction();
+
+ /**
+ * File with information how to reach the dcopserver.
+ * @param hostname Hostname to use, if empty current hostname of
+ * the system is used.
+ * @return Filename that contains information how to contact the
+ * DCOPserver.
+ */
+ static QCString dcopServerFile(const QCString &hostname=0);
+
+ /**
+ * @deprecated
+ * For backwards compatibility with KDE 2.x
+ * // KDE4 remove
+ */
+ static QCString dcopServerFileOld(const QCString &hostname=0) KDE_DEPRECATED;
+
+ /**
+ * Return the path of iceauth or an empty string if not found.
+ */
+ static QCString iceauthPath();
+
+signals:
+ /**
+ * Indicates that the application @p appId has been registered with
+ * the server we are attached to.
+ *
+ * You need to call setNotifications() first, to tell the DCOP server
+ * that you want to get these events.
+ * @param appId the id of the new application
+ */
+ void applicationRegistered( const QCString& appId );
+ /**
+ * Indicates that the formerly registered application @p appId has
+ * been removed.
+ *
+ * You need to call setNotifications() first, to tell the
+ * DCOP server that you want to get these events.
+ * @param appId the id of the removed application
+ */
+ void applicationRemoved( const QCString& appId );
+
+ /**
+ * Indicates that the process of establishing DCOP communications failed
+ * in some manner.
+ *
+ * Usually attached to a dialog box or some other visual
+ * aid.
+ * @param msg the message tha contains further information
+ */
+ void attachFailed(const QString &msg);
+
+ /**
+ * Indicates that user input shall be blocked or released,
+ * depending on the argument.
+ *
+ * The signal is emitted whenever the client has to wait too long
+ * (i.e. more than 1/10 of a second) for an answer to a
+ * synchronous call. In that case, it will enter a local event
+ * loop to keep the GUI updated until finally an answer arrives.
+ *
+ * In KDE, the KApplication object connects to this signal to be
+ * able to block any user input (i.e. mouse and key events) while
+ * we are waiting for an answer. If we did not do this, the
+ * application might end up in an illegal state, as a keyboard
+ * shortcut or a mouse action might cause another dcop call to be
+ * issued.
+ * @param block true to block user input, false otherwise
+ */
+ void blockUserInput( bool block );
+
+ /**
+ * @internal
+ *
+ * Signal used for callbacks of async calls.
+ * This signal is automatically connected to the call back
+ * slot specified in the async call.
+ * @see callAsync()
+ * @since 3.2
+ */
+ void callBack(int, const QCString&, const QByteArray &);
+
+public slots:
+ /**
+ * Process data from the socket.
+ * @param socknum the fd of the socket
+ */
+ void processSocketData(int socknum);
+
+protected slots:
+
+private slots:
+ void processPostedMessagesInternal();
+ void asyncReplyReady();
+ void eventLoopTimeout();
+
+public:
+ class ReplyStruct;
+
+ /**
+ * @internal
+ **/
+ void handleAsyncReply(ReplyStruct *replyStruct);
+
+private:
+
+ bool isLocalTransactionFinished(Q_INT32 id, QCString &replyType, QByteArray &replyData);
+
+ bool attachInternal( bool registerAsAnonymous = true );
+
+ bool callInternal(const QCString &remApp, const QCString &remObj,
+ const QCString &remFun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData,
+ bool useEventLoop, int timeout, int minor_opcode);
+
+
+ bool callInternal(const QCString &remApp, const QCString &remObjId,
+ const QCString &remFun, const QByteArray &data,
+ ReplyStruct *replyStruct,
+ bool useEventLoop, int timeout, int minor_opcode);
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ DCOPClientPrivate *d;
+};
+
+#endif
diff --git a/dcop/dcopglobal.h b/dcop/dcopglobal.h
new file mode 100644
index 000000000..8e018226d
--- /dev/null
+++ b/dcop/dcopglobal.h
@@ -0,0 +1,84 @@
+/*
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+ Copyright (c) 1999 Matthias Ettrich <ettrich@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 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.
+*/
+
+#ifndef DCOPGLOBAL_H
+#define DCOPGLOBAL_H "$Id$"
+
+
+#define DCOPVendorString "KDE"
+#define DCOPReleaseString "2.0"
+#define DCOPVersionMajor 2
+#define DCOPVersionMinor 0
+
+#define DCOPSend 1
+#define DCOPCall 2
+#define DCOPReply 3
+#define DCOPReplyFailed 4
+#define DCOPReplyWait 5
+#define DCOPReplyDelayed 6
+#define DCOPFind 7
+
+#define INT32 QINT32
+#ifdef Q_WS_X11
+#include <X11/Xlib.h>
+#include <X11/Xmd.h>
+#endif
+#include <KDE-ICE/ICElib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <KDE-ICE/ICEutil.h>
+#include <KDE-ICE/ICEmsg.h>
+#include <KDE-ICE/ICEproto.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern IcePoAuthStatus _kde_IcePoMagicCookie1Proc (IceConn, void **, int, int, int, void *, int *, void **, char **);
+extern IcePaAuthStatus _kde_IcePaMagicCookie1Proc (IceConn, void **, int, int, void *, int *, void **, char **);
+#ifdef __cplusplus
+}
+#endif
+/* these 4 below are static, otherwise build with --disable-shared will fail */
+static IcePoAuthProc DCOPClientAuthProcs[] = {_kde_IcePoMagicCookie1Proc};
+static IcePaAuthProc DCOPServerAuthProcs[] = {_kde_IcePaMagicCookie1Proc};
+static int DCOPAuthCount = 1;
+static const char *DCOPAuthNames[] = {"MIT-MAGIC-COOKIE-1"};
+
+/**
+ * @internal
+ */
+struct DCOPMsg {
+ CARD8 majorOpcode;
+ CARD8 minorOpcode;
+ CARD8 data[2];
+ CARD32 length B32;
+ CARD32 key;
+};
+
+#endif
diff --git a/dcop/dcopidl/Makefile.am b/dcop/dcopidl/Makefile.am
new file mode 100644
index 000000000..2b07f5e0a
--- /dev/null
+++ b/dcop/dcopidl/Makefile.am
@@ -0,0 +1,27 @@
+
+INCLUDES = $(all_includes)
+AM_LDFLAGS = $(all_libraries)
+AM_CPPFLAGS = -DYYDEBUG
+
+####### Files
+
+bin_PROGRAMS = dcopidl
+
+dcopidl_SOURCES = main.cpp yacc.cc scanner.cc
+noinst_HEADERS = yacc.cc.h
+
+dcopidl_LDADD = $(LIB_QT)
+dcopidl_LDFLAGS = $(KDE_RPATH) $(AM_LDFLAGS)
+
+####### Build rules
+
+parser:
+ cd $(srcdir) && flex -B -8 -oscanner.cc scanner.ll ;\
+ bison -t -d -v -o yacc.cc yacc.yy && mv yacc.hh yacc.cc.h
+
+check-local:
+ $(srcdir)/run_test.sh $(srcdir)
+
+EXTRA_DIST = dcopidl_test.h scanner.ll yacc.yy
+
+MAINTAINERCLEANFILES = yacc.cc.output
diff --git a/dcop/dcopidl/dcopidl_output.kidl b/dcop/dcopidl/dcopidl_output.kidl
new file mode 100644
index 000000000..83df49a81
--- /dev/null
+++ b/dcop/dcopidl/dcopidl_output.kidl
@@ -0,0 +1,82 @@
+<!DOCTYPE DCOP-IDL><DCOP-IDL>
+<SOURCE>./dcopidl_test.h</SOURCE>
+<INCLUDE>dcopobject.h</INCLUDE>
+<INCLUDE>dcopref.h</INCLUDE>
+<INCLUDE>qstring.h</INCLUDE>
+<CLASS>
+ <NAME>Test</NAME>
+ <LINK_SCOPE>KDEUI_EXPORT</LINK_SCOPE>
+ <SUPER>MyNamespace::MyParentClass</SUPER>
+ <SUPER>DCOPObject</SUPER>
+ <SUPER>QValueList&lt;<TYPE>QString</TYPE>&gt;</SUPER>
+ <FUNC>
+ <TYPE>QString</TYPE>
+ <NAME>url</NAME>
+ </FUNC>
+ <FUNC qual="const">
+ <TYPE>QString</TYPE>
+ <NAME>constTest</NAME>
+ </FUNC>
+ <FUNC>
+ <TYPE>DCOPRef</TYPE>
+ <NAME>firstView</NAME>
+ </FUNC>
+ <FUNC>
+ <TYPE>DCOPRef</TYPE>
+ <NAME>nextView</NAME>
+ </FUNC>
+ <FUNC>
+ <TYPE>int</TYPE>
+ <NAME>getNumObjects</NAME>
+ </FUNC>
+ <FUNC>
+ <TYPE>DCOPRef</TYPE>
+ <NAME>getObject</NAME>
+ <ARG><TYPE>int</TYPE><NAME>num</NAME></ARG>
+ </FUNC>
+ <FUNC>
+ <TYPE>int</TYPE>
+ <NAME>getNumPages</NAME>
+ </FUNC>
+ <FUNC>
+ <TYPE>DCOPRef</TYPE>
+ <NAME>getPage</NAME>
+ <ARG><TYPE>int</TYPE><NAME>num</NAME></ARG>
+ </FUNC>
+ <FUNC>
+ <TYPE>int</TYPE>
+ <NAME>getPageOfObj</NAME>
+ <ARG><TYPE>int</TYPE><NAME>obj</NAME></ARG>
+ </FUNC>
+ <FUNC>
+ <TYPE>void</TYPE>
+ <NAME>setCell</NAME>
+ <ARG><TYPE qleft="const" qright="&amp;">int</TYPE><NAME>point</NAME></ARG>
+ </FUNC>
+ <FUNC>
+ <TYPE>QValueList&lt;DCOPRef&gt;</TYPE>
+ <NAME>getWindows</NAME>
+ </FUNC>
+ <FUNC>
+ <TYPE>QStringList</TYPE>
+ <NAME>remotes</NAME>
+ </FUNC>
+ <SIGNAL>
+ <TYPE>void</TYPE>
+ <NAME>blah_signal</NAME>
+ </SIGNAL>
+</CLASS>
+<CLASS>
+ <NAME>Test2</NAME>
+ <SUPER>DCOPObject</SUPER>
+ <SIGNAL>
+ <TYPE>void</TYPE>
+ <NAME>fooSignal</NAME>
+ <ARG><TYPE>int</TYPE><NAME>arg</NAME></ARG>
+ </SIGNAL>
+</CLASS>
+<CLASS>
+ <NAME>TheNameSpace::Test3</NAME>
+ <SUPER>DCOPObject</SUPER>
+</CLASS>
+</DCOP-IDL>
diff --git a/dcop/dcopidl/dcopidl_test.h b/dcop/dcopidl/dcopidl_test.h
new file mode 100644
index 000000000..a902be4fd
--- /dev/null
+++ b/dcop/dcopidl/dcopidl_test.h
@@ -0,0 +1,109 @@
+/* This is a comment */
+
+#ifndef TEST_H
+#define TEST_H
+
+// some comment
+#include <dcopobject.h>
+#include <dcopref.h>
+
+/* We never use it, but it's a test after all :)
+ */
+class Test2;
+
+// this has to work too
+#include <qstring.h>
+
+typedef QMap<KIO::Job *, KIODownload> KIODownloadMap;
+class Test3;
+
+// Those namespaces are opened and closed, so they should be just ignored
+namespace Kpgp {
+ class Config;
+}
+namespace KMail {
+ class IdentityDialog;
+}
+
+/**
+ * This is a stupid comment that might help
+ * geiseri at some point in the near future.
+ * blah di blah
+ **/
+class KDEUI_EXPORT Test : public MyNamespace::MyParentClass, virtual public DCOPObject,
+ public QValueList<QString>
+{
+ K_DCOP
+
+public:
+ struct Bar {
+ int i;
+ };
+ class SomeForwardFooPrivate;
+ Test();
+ Test() : DCOPObject("name") {}
+ ~Test();
+ int getPageOfObj( int obj );
+ void setCell( KSpreadTable *table,
+ const QPoint& point );
+
+ SomeForwardFooPrivate *d;
+ static const int AUDIO_CD = 1;
+ static const int AUDIO_CD = 1 << 6;
+ static const int m_number0[ 20 ];
+ enum { Enum1, Enum2 };
+ enum NamedEnum { Enum3, Enum4 };
+k_dcop:
+ virtual QString url();
+ virtual QString constTest() const;
+ virtual DCOPRef firstView();
+ virtual DCOPRef nextView();
+ virtual int getNumObjects();
+ virtual DCOPRef getObject( int num );
+ virtual int getNumPages();
+ virtual DCOPRef getPage( int num );
+ /**
+ * a function comment
+ * @see blah di blah also
+ **/
+ int getPageOfObj( int obj );
+ void setCell( const int& point = 3 );
+ QValueList<DCOPRef> getWindows();
+ const QStringList remotes(); // returns const type, but shouldn't use const var for it in stub
+
+k_dcop_signals:
+ void blah_signal();
+
+private:
+ Test3 *doc();
+
+ struct KIODownload;
+ typedef QMap<KIO::Job *, KIODownload> KIODownloadMap;
+};
+
+class Test2 : public DCOPObject
+{
+ K_DCOP
+public:
+k_dcop_signals:
+ void fooSignal(int arg);
+};
+
+namespace TheNameSpace {
+
+ class Test3;
+
+ class Test3 : public DCOPObject
+ {
+ K_DCOP
+ public:
+ void yadda();
+ };
+
+};
+
+#endif // end of line comment
+
+/* Test for line numbers */
+
+
diff --git a/dcop/dcopidl/main.cpp b/dcop/dcopidl/main.cpp
new file mode 100644
index 000000000..03e0a6465
--- /dev/null
+++ b/dcop/dcopidl/main.cpp
@@ -0,0 +1,87 @@
+/*****************************************************************
+Copyright (c) 1999 Torben Weis <weis@kde.org>
+Copyright (c) 2000 Matthias Ettrich <ettrich@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 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.
+
+******************************************************************/
+#include <qstring.h>
+#include <qfile.h>
+#include <qcstring.h>
+#include <stdlib.h>
+
+void dcopidlParse( const char *_code );
+
+int idl_line_no;
+
+#if YYDEBUG
+extern int yydebug;
+#endif
+
+int main( int argc, char** argv )
+{
+ if (argc != 2)
+ {
+ fprintf(stderr, "Usage : dcopidl input_file\n");
+ return -1;
+ }
+ QFile file( argv[1] );
+ if ( !file.open( IO_ReadOnly ) )
+ {
+ fprintf(stderr, "Can't open input file\n");
+ return -1;
+ }
+
+ QByteArray arr = file.readAll();
+ uint len = arr.size();
+ uint j = 1;
+ for (uint i = 1; i<len; i++, j++) {
+ if (arr[ i-1 ] == '\r' && ((i+1)==len || arr[ i ] != '\n')) {
+ // change single \r's (Mac OS line endings) to \n
+ arr[ j-1 ] = '\n';
+ if ((i+1)==len) //special case: cut last character
+ j--;
+ }
+ else if (arr[ i-1 ] == '\r' && arr[ i ] == '\n') {
+ // change \r\n's (win32 line endings) to \n
+ arr[ j-1 ] = '\n';
+ i++; //skip \n
+ }
+ else if (i!=j) {
+ arr[ j-1 ] = arr[ i-1 ];
+ }
+ }
+ len = j;
+ arr.resize( len + 1 );
+ arr[ len ] = 0;
+
+#if YYDEBUG
+ char *debug = getenv("DEBUG");
+ if (debug)
+ yydebug = 1;
+#endif
+ idl_line_no = 1;
+
+ printf("<!DOCTYPE DCOP-IDL><DCOP-IDL>\n");
+ printf("<SOURCE>%s</SOURCE>\n", argv[1] );
+ dcopidlParse( arr.data() );
+ printf("</DCOP-IDL>\n");
+
+ file.close();
+ return 0;
+}
diff --git a/dcop/dcopidl/run_test.sh b/dcop/dcopidl/run_test.sh
new file mode 100755
index 000000000..6bcfaed82
--- /dev/null
+++ b/dcop/dcopidl/run_test.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+# Regression testing: generate .kidl out of dcopidl_test.h and compare with expected baseline
+# Usage: $srcdir/run_test.sh $srcdir
+
+srcdir="$1"
+builddir=`pwd`
+cd $srcdir
+"$builddir/dcopidl" ./dcopidl_test.h > $builddir/dcopidl_new_output.kidl || exit 1
+diff -u $srcdir/dcopidl_output.kidl $builddir/dcopidl_new_output.kidl
diff --git a/dcop/dcopidl/scanner.cc b/dcop/dcopidl/scanner.cc
new file mode 100644
index 000000000..4926e0421
--- /dev/null
+++ b/dcop/dcopidl/scanner.cc
@@ -0,0 +1,2508 @@
+#line 2 "scanner.cc"
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ * $Header$
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator). This
+ * avoids problems with code like:
+ *
+ * if ( condition_holds )
+ * yyless( 5 );
+ * else
+ * do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ *yy_cp = yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+ };
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+
+#define YY_USES_REJECT
+
+#define yywrap() 1
+#define YY_SKIP_YYWRAP
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yytext_ptr = yy_bp; \
+ yyleng = (int) (yy_cp - yy_bp); \
+ yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 83
+#define YY_END_OF_BUFFER 84
+static yyconst short int yy_acclist[655] =
+ { 0,
+ 6, 6, 84, 6, 82, 83, 1, 6, 82, 83,
+ 2, 83, 6, 82, 83, 6, 82, 83, 6, 82,
+ 83, 6, 23, 82, 83, 6, 82, 83, 6, 14,
+ 82, 83, 6, 15, 82, 83, 7, 21, 82, 83,
+ 6, 17, 82, 83, 6, 20, 82, 83, 6, 18,
+ 82, 83, 6, 28, 82, 83, 6, 82, 83, 6,
+ 68, 78, 82, 83, 6, 77, 82, 83, 6, 16,
+ 82, 83, 6, 22, 82, 83, 6, 24, 82, 83,
+ 6, 27, 82, 83, 6, 25, 82, 83, 6, 71,
+ 82, 83, 6, 71, 82, 83, 6, 71, 82, 83,
+
+ 6, 71, 82, 83, 6, 71, 82, 83, 6, 30,
+ 82, 83, 6, 31, 82, 83, 6, 71, 82, 83,
+ 6, 71, 82, 83, 6, 71, 82, 83, 6, 71,
+ 82, 83, 6, 71, 82, 83, 6, 71, 82, 83,
+ 6, 71, 82, 83, 6, 71, 82, 83, 6, 71,
+ 82, 83, 6, 71, 82, 83, 6, 71, 82, 83,
+ 6, 71, 82, 83, 6, 71, 82, 83, 6, 71,
+ 82, 83, 6, 71, 82, 83, 6, 12, 82, 83,
+ 5, 13, 82, 83, 6, 19, 82, 83, 6, 6,
+ 34, 6, 6, 81, 6, 6, 11, 6, 9, 6,
+
+ 6, 6, 4, 6, 32, 6, 6, 75, 3, 6,
+ 8, 6, 6, 78, 6, 6, 6, 68, 6, 79,
+ 6, 77, 6, 77, 6, 26, 6, 33, 6, 71,
+ 6, 71, 6, 71, 6, 71, 6, 71, 6, 71,
+ 6, 71, 6, 71, 6, 71, 6, 71, 6, 71,
+ 6, 71, 6, 71, 6, 71, 6, 71, 6, 71,
+ 6, 71, 6, 71, 6, 71, 6, 71, 6, 71,
+ 6, 71, 6, 71, 6, 71, 6, 71, 6, 71,
+ 6, 71, 6, 71, 6, 71, 6, 71, 81, 6,
+ 6, 6, 9, 9, 6, 6, 80, 80, 6, 80,
+
+ 6, 6, 6, 29, 6, 6, 8, 8, 6, 74,
+ 6, 6, 73, 6, 79, 6, 71, 6, 71, 6,
+ 71, 6, 71, 6, 71, 6, 71, 6, 71, 6,
+ 71, 6, 71, 6, 71, 6, 71, 6, 71, 6,
+ 58, 71, 6, 71, 6, 71, 6, 71, 6, 71,
+ 6, 71, 6, 71, 6, 71, 6, 71, 6, 71,
+ 6, 71, 6, 71, 6, 71, 6, 71, 6, 71,
+ 6, 71, 6, 71, 6, 71, 6, 71, 6, 71,
+ 6, 6, 6, 6, 6, 6, 6, 76, 6, 6,
+ 71, 6, 71, 6, 71, 6, 61, 71, 6, 59,
+
+ 71, 6, 71, 6, 71, 6, 36, 71, 6, 71,
+ 6, 71, 6, 71, 6, 71, 6, 71, 6, 50,
+ 71, 6, 71, 6, 71, 6, 71, 6, 71, 6,
+ 71, 6, 71, 6, 71, 6, 71, 6, 71, 6,
+ 71, 6, 71, 6, 71, 6, 57, 71, 6, 71,
+ 6, 71, 6, 71, 6, 71, 6, 6, 6, 6,
+ 6, 6, 72, 6, 62, 71, 6, 71, 6, 71,
+ 6, 39, 71, 6, 35, 71, 6, 71, 6, 60,
+ 71, 6, 71, 6, 71, 6, 71, 6, 71, 6,
+ 71, 6, 71, 6, 71, 6, 71, 6, 71, 6,
+
+ 71, 6, 49, 71, 6, 71, 6, 71, 6, 56,
+ 71, 6, 71, 6, 71, 6, 71, 6, 71, 6,
+ 38, 71, 6, 71, 6, 6, 66, 71, 6, 71,
+ 6, 71, 6, 51, 71, 6, 44, 71, 6, 63,
+ 71, 6, 71, 6, 71, 6, 71, 6, 71, 6,
+ 71, 6, 43, 71, 6, 55, 71, 6, 71, 6,
+ 47, 71, 6, 45, 71, 6, 40, 71, 6, 71,
+ 6, 71, 6, 71, 6, 6, 71, 6, 6, 71,
+ 6, 46, 71, 6, 71, 6, 71, 6, 53, 71,
+ 6, 71, 6, 54, 71, 6, 65, 71, 6, 71,
+
+ 6, 42, 71, 6, 6, 67, 71, 6, 69, 6,
+ 69, 6, 71, 6, 71, 6, 41, 71, 6, 71,
+ 6, 48, 71, 6, 6, 6, 6, 71, 6, 37,
+ 71, 6, 52, 71, 6, 11, 6, 6, 70, 6,
+ 71, 10, 11, 6, 6, 71, 10, 6, 71, 6,
+ 71, 6, 64, 71
+ } ;
+
+static yyconst short int yy_accept[312] =
+ { 0,
+ 1, 2, 3, 4, 7, 11, 13, 16, 19, 22,
+ 26, 29, 33, 37, 41, 45, 49, 53, 57, 60,
+ 65, 69, 73, 77, 81, 85, 89, 93, 97, 101,
+ 105, 109, 113, 117, 121, 125, 129, 133, 137, 141,
+ 145, 149, 153, 157, 161, 165, 169, 173, 177, 181,
+ 185, 189, 190, 192, 193, 195, 195, 196, 197, 198,
+ 200, 200, 201, 202, 202, 203, 204, 206, 207, 209,
+ 210, 212, 213, 215, 216, 217, 219, 221, 223, 225,
+ 227, 229, 231, 233, 235, 237, 239, 241, 243, 245,
+ 247, 249, 251, 253, 255, 257, 259, 261, 263, 265,
+
+ 267, 269, 271, 273, 275, 277, 279, 281, 283, 285,
+ 287, 289, 290, 290, 291, 292, 294, 295, 296, 298,
+ 299, 301, 302, 303, 305, 306, 308, 309, 311, 312,
+ 314, 316, 318, 320, 322, 324, 326, 328, 330, 332,
+ 334, 336, 338, 340, 343, 345, 347, 349, 351, 353,
+ 355, 357, 359, 361, 363, 365, 367, 369, 371, 373,
+ 375, 377, 379, 381, 381, 381, 382, 383, 384, 385,
+ 386, 387, 389, 390, 392, 394, 396, 399, 402, 404,
+ 406, 409, 411, 413, 415, 417, 419, 422, 424, 426,
+ 428, 430, 432, 434, 436, 438, 440, 442, 444, 446,
+
+ 449, 451, 453, 455, 457, 457, 457, 458, 459, 460,
+ 461, 462, 464, 467, 469, 471, 474, 477, 479, 482,
+ 484, 486, 488, 490, 492, 494, 496, 498, 500, 502,
+ 505, 507, 509, 512, 514, 516, 518, 520, 523, 525,
+ 525, 525, 526, 529, 531, 533, 536, 539, 542, 544,
+ 546, 548, 550, 552, 555, 558, 560, 563, 566, 569,
+ 571, 573, 575, 576, 578, 579, 581, 584, 586, 588,
+ 591, 593, 596, 599, 601, 604, 605, 608, 610, 611,
+ 612, 614, 616, 619, 621, 624, 625, 626, 627, 629,
+ 632, 635, 636, 637, 638, 638, 640, 642, 642, 642,
+
+ 644, 645, 645, 647, 648, 648, 648, 650, 652, 655,
+ 655
+ } ;
+
+static yyconst int yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 4, 5, 6, 7, 1, 1, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 19,
+ 19, 19, 19, 19, 19, 20, 20, 21, 22, 23,
+ 24, 25, 26, 1, 27, 28, 29, 30, 31, 32,
+ 33, 33, 33, 34, 35, 36, 33, 33, 37, 38,
+ 39, 40, 41, 42, 43, 33, 33, 44, 33, 33,
+ 45, 46, 47, 1, 48, 1, 49, 50, 51, 52,
+
+ 53, 54, 55, 56, 57, 33, 58, 59, 60, 61,
+ 62, 63, 33, 64, 65, 66, 67, 68, 33, 69,
+ 70, 33, 71, 1, 72, 73, 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,
+ 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, 1
+ } ;
+
+static yyconst int yy_meta[74] =
+ { 0,
+ 1, 2, 3, 4, 1, 5, 1, 1, 5, 1,
+ 1, 6, 1, 1, 1, 1, 1, 7, 7, 8,
+ 1, 1, 1, 1, 1, 5, 8, 8, 8, 8,
+ 8, 8, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 9, 1, 5, 1, 4, 7, 7,
+ 8, 8, 8, 7, 4, 4, 4, 4, 4, 4,
+ 9, 4, 4, 9, 4, 9, 4, 9, 9, 4,
+ 1, 10, 1
+ } ;
+
+static yyconst short int yy_base[329] =
+ { 0,
+ 0, 0, 904, 0, 0, 1106, 879, 72, 74, 0,
+ 73, 0, 0, 885, 0, 0, 876, 71, 64, 79,
+ 85, 879, 0, 69, 874, 82, 148, 221, 61, 69,
+ 73, 0, 0, 81, 53, 75, 67, 85, 98, 84,
+ 93, 103, 114, 148, 120, 140, 141, 155, 0, 1106,
+ 0, 0, 0, 178, 0, 193, 289, 124, 1106, 180,
+ 887, 188, 880, 879, 353, 1106, 0, 858, 238, 1106,
+ 117, 189, 243, 257, 198, 0, 405, 266, 0, 0,
+ 0, 846, 99, 158, 160, 171, 206, 238, 193, 213,
+ 224, 244, 226, 245, 237, 251, 243, 254, 188, 266,
+
+ 272, 252, 274, 279, 278, 297, 289, 286, 298, 273,
+ 290, 1106, 308, 372, 442, 317, 869, 329, 0, 1106,
+ 860, 351, 479, 0, 368, 332, 0, 374, 346, 390,
+ 0, 304, 176, 320, 369, 348, 341, 346, 355, 386,
+ 399, 389, 294, 840, 401, 340, 349, 393, 402, 411,
+ 414, 404, 416, 403, 420, 418, 421, 422, 423, 424,
+ 448, 441, 438, 494, 0, 532, 603, 511, 506, 667,
+ 498, 501, 528, 451, 499, 508, 839, 838, 474, 461,
+ 837, 426, 510, 495, 518, 522, 836, 525, 526, 527,
+ 528, 532, 530, 531, 533, 537, 535, 539, 538, 835,
+
+ 540, 542, 546, 541, 592, 716, 600, 601, 569, 852,
+ 598, 606, 832, 544, 612, 831, 830, 553, 829, 567,
+ 610, 566, 561, 601, 600, 613, 617, 618, 621, 827,
+ 615, 631, 824, 633, 623, 624, 632, 820, 643, 655,
+ 656, 678, 813, 638, 676, 807, 805, 661, 651, 664,
+ 644, 673, 683, 797, 763, 687, 762, 756, 732, 678,
+ 680, 681, 725, 685, 797, 688, 715, 704, 696, 697,
+ 698, 547, 534, 702, 476, 769, 459, 870, 456, 0,
+ 684, 711, 413, 730, 358, 825, 774, 336, 729, 310,
+ 107, 827, 733, 773, 790, 0, 734, 810, 760, 1106,
+
+ 788, 771, 752, 1106, 784, 785, 767, 790, 56, 1106,
+ 943, 952, 962, 972, 982, 991, 1001, 1011, 1021, 1027,
+ 1036, 1046, 1050, 1058, 1066, 1075, 1085, 1095
+ } ;
+
+static yyconst short int yy_def[329] =
+ { 0,
+ 310, 1, 310, 311, 311, 310, 311, 312, 313, 311,
+ 314, 311, 311, 310, 311, 311, 311, 311, 311, 311,
+ 311, 311, 311, 311, 311, 311, 315, 315, 28, 28,
+ 28, 311, 311, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 311, 310,
+ 311, 311, 311, 312, 311, 316, 311, 313, 310, 317,
+ 318, 313, 311, 310, 311, 310, 311, 311, 311, 310,
+ 319, 311, 311, 311, 311, 311, 311, 311, 311, 311,
+ 311, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 310, 320, 312, 311, 317, 321, 313, 311, 310,
+ 311, 311, 311, 311, 311, 319, 322, 311, 311, 311,
+ 77, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 316, 323, 312, 312, 313, 311, 311,
+ 311, 311, 311, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+
+ 28, 28, 28, 28, 316, 316, 312, 312, 313, 311,
+ 311, 311, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 316,
+ 316, 313, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 313, 28, 324, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 313, 28, 324, 311, 325,
+ 28, 28, 28, 28, 28, 313, 326, 311, 28, 28,
+ 28, 326, 327, 313, 328, 311, 28, 327, 310, 310,
+
+ 313, 318, 28, 310, 310, 318, 28, 28, 28, 0,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310
+ } ;
+
+static yyconst short int yy_nxt[1180] =
+ { 0,
+ 4, 5, 6, 5, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 21,
+ 22, 23, 24, 25, 26, 4, 27, 27, 27, 27,
+ 27, 28, 27, 27, 29, 27, 27, 27, 30, 27,
+ 27, 31, 27, 27, 32, 4, 33, 27, 27, 27,
+ 34, 27, 35, 36, 27, 27, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 27, 27,
+ 49, 50, 51, 52, 52, 70, 59, 55, 60, 82,
+ 71, 52, 82, 56, 64, 61, 68, 82, 69, 69,
+ 69, 81, 53, 82, 72, 82, 73, 73, 74, 82,
+
+ 72, 82, 78, 78, 78, 53, 81, 82, 84, 75,
+ 82, 82, 86, 90, 76, 75, 85, 57, 65, 82,
+ 79, 91, 77, 92, 82, 82, 59, 94, 127, 82,
+ 62, 75, 95, 82, 132, 61, 87, 75, 93, 88,
+ 82, 98, 89, 56, 64, 61, 82, 77, 52, 52,
+ 97, 52, 52, 52, 52, 52, 52, 52, 52, 96,
+ 52, 52, 52, 52, 52, 99, 82, 82, 52, 52,
+ 52, 52, 52, 52, 82, 103, 104, 100, 105, 52,
+ 101, 82, 59, 55, 82, 106, 82, 133, 127, 56,
+ 59, 117, 52, 52, 52, 61, 134, 82, 112, 61,
+
+ 102, 109, 82, 107, 175, 110, 128, 128, 128, 108,
+ 129, 111, 129, 135, 82, 130, 130, 130, 52, 82,
+ 52, 52, 52, 57, 52, 52, 52, 52, 52, 52,
+ 52, 52, 82, 52, 52, 52, 52, 52, 113, 82,
+ 149, 52, 52, 52, 52, 52, 52, 83, 118, 56,
+ 82, 117, 82, 138, 136, 69, 69, 69, 72, 61,
+ 73, 73, 74, 82, 82, 52, 52, 52, 125, 82,
+ 82, 82, 72, 75, 74, 74, 74, 82, 82, 139,
+ 82, 72, 142, 78, 78, 78, 137, 75, 145, 140,
+ 125, 52, 82, 52, 54, 75, 75, 54, 82, 82,
+
+ 82, 79, 141, 143, 82, 82, 114, 114, 147, 75,
+ 144, 146, 82, 148, 54, 82, 82, 153, 75, 59,
+ 82, 152, 150, 82, 82, 164, 164, 151, 117, 162,
+ 82, 59, 115, 155, 54, 154, 82, 54, 54, 156,
+ 61, 296, 54, 127, 174, 157, 82, 176, 160, 54,
+ 185, 165, 54, 163, 54, 159, 54, 115, 63, 119,
+ 158, 121, 161, 130, 130, 130, 82, 82, 169, 169,
+ 122, 122, 82, 52, 82, 82, 165, 55, 63, 168,
+ 171, 82, 171, 56, 82, 172, 172, 172, 117, 166,
+ 166, 128, 128, 128, 187, 82, 123, 188, 63, 177,
+
+ 61, 63, 63, 127, 173, 179, 63, 130, 130, 130,
+ 180, 178, 82, 63, 181, 82, 63, 57, 63, 82,
+ 63, 123, 131, 131, 131, 82, 173, 82, 82, 82,
+ 82, 131, 131, 131, 131, 131, 131, 82, 182, 82,
+ 82, 184, 82, 56, 82, 189, 82, 82, 82, 82,
+ 82, 186, 82, 131, 131, 131, 131, 131, 131, 167,
+ 167, 167, 193, 183, 82, 190, 195, 82, 167, 167,
+ 167, 167, 167, 167, 82, 200, 201, 82, 191, 192,
+ 196, 213, 194, 197, 288, 82, 198, 82, 199, 218,
+ 167, 167, 167, 167, 167, 167, 170, 170, 170, 112,
+
+ 82, 203, 82, 204, 202, 170, 170, 170, 170, 170,
+ 170, 205, 205, 59, 119, 172, 172, 172, 172, 172,
+ 172, 82, 61, 63, 63, 82, 217, 170, 170, 170,
+ 170, 170, 170, 52, 82, 214, 82, 55, 216, 113,
+ 211, 215, 211, 56, 82, 212, 212, 212, 82, 207,
+ 207, 82, 82, 82, 82, 220, 82, 82, 82, 82,
+ 82, 82, 219, 82, 82, 82, 82, 82, 82, 209,
+ 82, 59, 82, 82, 223, 225, 226, 57, 221, 82,
+ 61, 243, 61, 222, 227, 231, 228, 82, 235, 232,
+ 224, 236, 82, 82, 229, 234, 237, 112, 230, 233,
+
+ 238, 52, 52, 56, 52, 55, 55, 239, 55, 240,
+ 240, 56, 56, 245, 56, 212, 212, 212, 246, 249,
+ 208, 208, 208, 212, 212, 212, 82, 82, 248, 208,
+ 208, 208, 208, 208, 208, 242, 82, 113, 82, 82,
+ 61, 82, 244, 82, 82, 57, 57, 82, 57, 82,
+ 82, 208, 208, 208, 208, 208, 208, 82, 82, 82,
+ 112, 112, 247, 250, 82, 251, 264, 253, 254, 82,
+ 82, 56, 56, 256, 56, 119, 260, 82, 252, 265,
+ 59, 255, 257, 258, 210, 210, 210, 82, 259, 61,
+ 82, 262, 261, 210, 210, 210, 210, 210, 210, 82,
+
+ 113, 113, 82, 267, 82, 269, 82, 82, 266, 82,
+ 82, 82, 268, 82, 82, 210, 210, 210, 210, 210,
+ 210, 112, 82, 82, 82, 270, 277, 59, 82, 263,
+ 82, 273, 274, 241, 241, 241, 61, 82, 299, 275,
+ 289, 82, 241, 241, 241, 241, 241, 241, 271, 61,
+ 284, 272, 281, 285, 282, 82, 82, 299, 82, 283,
+ 82, 113, 304, 290, 241, 241, 241, 241, 241, 241,
+ 286, 59, 286, 300, 287, 300, 293, 276, 82, 294,
+ 61, 291, 82, 297, 61, 295, 304, 300, 82, 82,
+ 300, 287, 293, 82, 303, 302, 61, 52, 294, 61,
+
+ 307, 52, 279, 52, 52, 52, 52, 52, 280, 52,
+ 52, 52, 52, 52, 302, 299, 82, 52, 52, 52,
+ 52, 52, 52, 82, 305, 308, 286, 59, 286, 293,
+ 287, 82, 294, 82, 299, 306, 61, 301, 295, 82,
+ 61, 52, 52, 52, 61, 295, 82, 287, 305, 306,
+ 82, 294, 301, 82, 309, 82, 82, 82, 82, 61,
+ 119, 82, 82, 82, 82, 82, 82, 52, 119, 52,
+ 52, 59, 82, 124, 52, 52, 52, 52, 52, 52,
+ 52, 280, 52, 52, 52, 52, 52, 120, 119, 59,
+ 52, 52, 52, 52, 52, 52, 61, 53, 295, 80,
+
+ 67, 66, 53, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 52, 52, 52, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 52, 310, 52, 52, 52, 310, 52, 52, 310, 52,
+ 52, 52, 54, 54, 310, 54, 54, 54, 54, 54,
+ 54, 54, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 63, 63, 310, 63, 63, 63, 63, 63,
+ 63, 63, 82, 82, 310, 82, 82, 310, 82, 82,
+ 82, 56, 310, 310, 56, 56, 56, 56, 56, 56,
+
+ 56, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+ 116, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+ 61, 126, 126, 310, 126, 126, 126, 126, 126, 126,
+ 126, 56, 310, 56, 310, 56, 117, 117, 117, 117,
+ 117, 117, 117, 117, 117, 117, 127, 127, 310, 127,
+ 127, 127, 127, 127, 127, 127, 206, 206, 278, 278,
+ 310, 278, 278, 278, 278, 278, 278, 280, 310, 280,
+ 310, 280, 280, 280, 280, 292, 292, 292, 292, 292,
+ 292, 292, 292, 292, 292, 298, 298, 298, 298, 298,
+ 298, 298, 298, 298, 298, 295, 295, 295, 295, 295,
+
+ 295, 295, 295, 295, 295, 3, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310
+ } ;
+
+static yyconst short int yy_chk[1180] =
+ { 0,
+ 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, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 8, 11, 19, 9, 8, 9, 35,
+ 19, 11, 309, 8, 11, 9, 18, 29, 18, 18,
+ 18, 24, 24, 37, 20, 30, 20, 20, 20, 31,
+
+ 21, 36, 21, 21, 21, 26, 26, 34, 29, 20,
+ 40, 38, 31, 35, 20, 21, 30, 8, 11, 41,
+ 21, 35, 20, 36, 39, 83, 58, 37, 71, 42,
+ 9, 20, 38, 291, 83, 58, 34, 21, 36, 34,
+ 43, 41, 34, 8, 11, 9, 45, 20, 27, 27,
+ 40, 27, 27, 27, 27, 27, 27, 27, 27, 39,
+ 27, 27, 27, 27, 27, 42, 46, 47, 27, 27,
+ 27, 27, 27, 27, 44, 45, 45, 43, 45, 54,
+ 43, 48, 60, 54, 84, 45, 85, 84, 71, 54,
+ 62, 60, 27, 27, 27, 58, 85, 86, 56, 62,
+
+ 44, 47, 133, 46, 133, 47, 72, 72, 72, 46,
+ 75, 48, 75, 86, 99, 75, 75, 75, 27, 89,
+ 27, 28, 28, 54, 28, 28, 28, 28, 28, 28,
+ 28, 28, 87, 28, 28, 28, 28, 28, 56, 90,
+ 99, 28, 28, 28, 28, 28, 28, 28, 62, 54,
+ 91, 60, 93, 89, 87, 69, 69, 69, 73, 62,
+ 73, 73, 73, 95, 88, 28, 28, 28, 69, 97,
+ 92, 94, 74, 73, 74, 74, 74, 96, 102, 90,
+ 98, 78, 93, 78, 78, 78, 88, 74, 95, 91,
+ 69, 28, 100, 28, 57, 73, 78, 57, 101, 110,
+
+ 103, 78, 92, 94, 105, 104, 57, 57, 97, 74,
+ 94, 96, 108, 98, 57, 107, 111, 102, 78, 116,
+ 143, 101, 100, 106, 109, 113, 113, 100, 116, 110,
+ 132, 118, 57, 104, 57, 103, 290, 57, 57, 105,
+ 118, 288, 57, 126, 132, 106, 134, 134, 108, 57,
+ 143, 113, 57, 111, 57, 107, 57, 57, 65, 122,
+ 106, 65, 109, 129, 129, 129, 146, 137, 122, 122,
+ 65, 65, 138, 114, 136, 147, 113, 114, 65, 118,
+ 125, 139, 125, 114, 285, 125, 125, 125, 116, 114,
+ 114, 128, 128, 128, 146, 135, 65, 147, 65, 135,
+
+ 118, 65, 65, 126, 128, 137, 65, 130, 130, 130,
+ 138, 136, 140, 65, 139, 142, 65, 114, 65, 148,
+ 65, 65, 77, 77, 77, 141, 128, 145, 149, 154,
+ 152, 77, 77, 77, 77, 77, 77, 150, 140, 283,
+ 151, 142, 153, 114, 156, 148, 155, 157, 158, 159,
+ 160, 145, 182, 77, 77, 77, 77, 77, 77, 115,
+ 115, 115, 152, 141, 163, 149, 154, 162, 115, 115,
+ 115, 115, 115, 115, 161, 159, 160, 174, 150, 151,
+ 155, 174, 153, 156, 279, 277, 157, 180, 158, 182,
+ 115, 115, 115, 115, 115, 115, 123, 123, 123, 164,
+
+ 179, 162, 275, 163, 161, 123, 123, 123, 123, 123,
+ 123, 164, 164, 168, 169, 171, 171, 171, 172, 172,
+ 172, 184, 168, 169, 169, 175, 180, 123, 123, 123,
+ 123, 123, 123, 166, 176, 175, 183, 166, 179, 164,
+ 173, 176, 173, 166, 185, 173, 173, 173, 186, 166,
+ 166, 188, 189, 190, 191, 184, 193, 194, 192, 195,
+ 273, 197, 183, 196, 199, 198, 201, 204, 202, 168,
+ 214, 209, 203, 272, 188, 190, 191, 166, 185, 218,
+ 209, 214, 168, 186, 192, 196, 193, 223, 199, 196,
+ 189, 201, 222, 220, 194, 198, 202, 205, 195, 197,
+
+ 203, 207, 208, 166, 167, 207, 208, 204, 167, 205,
+ 205, 207, 208, 218, 167, 211, 211, 211, 220, 223,
+ 167, 167, 167, 212, 212, 212, 225, 224, 222, 167,
+ 167, 167, 167, 167, 167, 209, 221, 205, 215, 226,
+ 209, 231, 215, 227, 228, 207, 208, 229, 167, 235,
+ 236, 167, 167, 167, 167, 167, 167, 232, 237, 234,
+ 240, 241, 221, 224, 244, 225, 244, 227, 228, 239,
+ 251, 207, 208, 231, 167, 170, 236, 249, 226, 245,
+ 242, 229, 232, 234, 170, 170, 170, 248, 235, 242,
+ 250, 239, 237, 170, 170, 170, 170, 170, 170, 252,
+
+ 240, 241, 245, 249, 260, 251, 261, 262, 248, 253,
+ 281, 264, 250, 256, 266, 170, 170, 170, 170, 170,
+ 170, 206, 269, 270, 271, 252, 264, 263, 274, 242,
+ 268, 260, 261, 206, 206, 206, 263, 282, 293, 262,
+ 281, 267, 206, 206, 206, 206, 206, 206, 253, 242,
+ 271, 256, 266, 274, 268, 289, 284, 293, 259, 269,
+ 297, 206, 299, 282, 206, 206, 206, 206, 206, 206,
+ 276, 276, 276, 302, 276, 294, 287, 263, 303, 287,
+ 276, 284, 258, 289, 294, 287, 305, 306, 257, 255,
+ 301, 276, 295, 307, 297, 295, 263, 265, 287, 301,
+
+ 303, 265, 265, 265, 265, 265, 265, 265, 265, 265,
+ 265, 265, 265, 265, 295, 298, 308, 265, 265, 265,
+ 265, 265, 265, 254, 299, 307, 286, 286, 286, 292,
+ 286, 247, 292, 246, 298, 302, 286, 294, 292, 243,
+ 276, 265, 265, 265, 294, 287, 238, 286, 305, 306,
+ 233, 292, 301, 230, 308, 219, 217, 216, 213, 301,
+ 210, 200, 187, 181, 178, 177, 144, 265, 121, 265,
+ 278, 117, 82, 68, 278, 278, 278, 278, 278, 278,
+ 278, 278, 278, 278, 278, 278, 278, 64, 63, 61,
+ 278, 278, 278, 278, 278, 278, 286, 25, 292, 22,
+
+ 17, 14, 7, 3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 278, 278, 278, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 278, 0, 278, 311, 311, 0, 311, 311, 0, 311,
+ 311, 311, 312, 312, 0, 312, 312, 312, 312, 312,
+ 312, 312, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 314, 314, 0, 314, 314, 314, 314, 314,
+ 314, 314, 315, 315, 0, 315, 315, 0, 315, 315,
+ 315, 316, 0, 0, 316, 316, 316, 316, 316, 316,
+
+ 316, 317, 317, 317, 317, 317, 317, 317, 317, 317,
+ 317, 318, 318, 318, 318, 318, 318, 318, 318, 318,
+ 318, 319, 319, 0, 319, 319, 319, 319, 319, 319,
+ 319, 320, 0, 320, 0, 320, 321, 321, 321, 321,
+ 321, 321, 321, 321, 321, 321, 322, 322, 0, 322,
+ 322, 322, 322, 322, 322, 322, 323, 323, 324, 324,
+ 0, 324, 324, 324, 324, 324, 324, 325, 0, 325,
+ 0, 325, 325, 325, 325, 326, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 327, 327, 327, 327, 327,
+ 327, 327, 327, 327, 327, 328, 328, 328, 328, 328,
+
+ 328, 328, 328, 328, 328, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 310
+ } ;
+
+static yy_state_type yy_state_buf[YY_BUF_SIZE + 2], *yy_state_ptr;
+static char *yy_full_match;
+static int yy_lp;
+#define REJECT \
+{ \
+*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ \
+yy_cp = yy_full_match; /* restore poss. backed-over text */ \
+++yy_lp; \
+goto find_rule; \
+}
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "scanner.ll"
+#define INITIAL 0
+#line 2 "scanner.ll"
+/*****************************************************************
+Copyright (c) 1999 Torben Weis <weis@kde.org>
+Copyright (c) 2000 Matthias Ettrich <ettrich@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 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.
+
+******************************************************************/
+
+#define YY_NO_UNPUT
+#include <stdlib.h>
+#include <ctype.h>
+
+class QString;
+
+#ifndef KDE_USE_FINAL
+#include "yacc.cc.h"
+#endif
+
+extern int idl_line_no;
+int comment_mode;
+int function_mode = 0;
+
+#include <qstring.h>
+#include <qregexp.h>
+
+static long ascii_to_longlong( long base, const char *s )
+{
+ long ll = 0;
+ while( *s != '\0' ) {
+ char c = *s++;
+ if( c >= 'a' )
+ c -= 'a' - 'A';
+ c -= '0';
+ if( c > 9 )
+ c -= 'A' - '0' - 10;
+ ll = ll * base + c;
+ }
+ return ll;
+}
+
+static double ascii_to_longdouble (const char *s)
+{
+ double d;
+#ifdef HAVE_SCANF_LF
+ sscanf (s, "%Lf", &d);
+#else
+ /*
+ * this is only an approximation and will probably break fixed<>
+ * parameter calculation on systems where
+ * sizeof(double) < sizeof(long double). but fortunately all
+ * systems where scanf("%Lf") is known to be broken (Linux/Alpha
+ * and HPUX) have sizeof(double) == sizeof(long double).
+ */
+ d = strtod (s, NULL);
+#endif
+ return d;
+}
+
+static char translate_char( const char *s )
+{
+ char c = *s++;
+
+ if( c != '\\' )
+ return c;
+ c = *s++;
+ switch( c ) {
+ case 'n':
+ return '\n';
+ case 't':
+ return '\t';
+ case 'v':
+ return '\v';
+ case 'b':
+ return '\b';
+ case 'r':
+ return '\r';
+ case 'f':
+ return '\f';
+ case 'a':
+ return '\a';
+ case '\\':
+ return '\\';
+ case '?':
+ return '\?';
+ case '\'':
+ return '\'';
+ case '"':
+ return '"';
+ case 'x':
+ case 'X':
+ return (char) ascii_to_longlong( 16, s );
+ default:
+ // Gotta be an octal
+ return (char) ascii_to_longlong( 8, s );
+ }
+}
+
+
+#define YY_NEVER_INTERACTIVE 1
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+#line 933 "scanner.cc"
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines. This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( yy_current_buffer->yy_is_interactive ) \
+ { \
+ int c = '*', n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
+ && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" );
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+YY_DECL
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+#line 148 "scanner.ll"
+
+
+#line 1087 "scanner.cc"
+
+ if ( yy_init )
+ {
+ yy_init = 0;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! yy_start )
+ yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! yy_current_buffer )
+ yy_current_buffer =
+ yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_load_buffer_state();
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yy_start;
+ yy_state_ptr = yy_state_buf;
+ *yy_state_ptr++ = yy_current_state;
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 311 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ *yy_state_ptr++ = yy_current_state;
+ ++yy_cp;
+ }
+ while ( yy_current_state != 310 );
+
+yy_find_action:
+ yy_current_state = *--yy_state_ptr;
+ yy_lp = yy_accept[yy_current_state];
+find_rule: /* we branch to this label when backing up */
+ for ( ; ; ) /* until we find what rule we matched */
+ {
+ if ( yy_lp && yy_lp < yy_accept[yy_current_state + 1] )
+ {
+ yy_act = yy_acclist[yy_lp];
+ {
+ yy_full_match = yy_cp;
+ break;
+ }
+ }
+ --yy_cp;
+ yy_current_state = *--yy_state_ptr;
+ yy_lp = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+
+do_action: /* This label is used only to access EOF actions. */
+
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+case 1:
+YY_RULE_SETUP
+#line 150 "scanner.ll"
+;
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 151 "scanner.ll"
+{ idl_line_no++; }
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 153 "scanner.ll"
+{ comment_mode = 1; }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 154 "scanner.ll"
+{ if (!comment_mode) { REJECT; } else { comment_mode = 0; } }
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 155 "scanner.ll"
+{
+ if (! comment_mode) {
+ if (!function_mode) { REJECT; } else {
+ function_mode = 0;
+ return T_RIGHT_CURLY_BRACKET;
+ }
+ }
+ }
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 163 "scanner.ll"
+{ if (!comment_mode && !function_mode) { REJECT; } }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 164 "scanner.ll"
+{ if (!comment_mode) { REJECT; } }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 166 "scanner.ll"
+;
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 167 "scanner.ll"
+{
+ exit( 1 );
+ }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 170 "scanner.ll"
+{
+ QString s( yytext );
+ int i = s.find(QRegExp("[\"<]"))+1;
+ int j = s.find(QRegExp("[\">]"), i);
+ yylval._str = new QString( s.mid( i, j - i ) );
+ idl_line_no++;
+ return T_INCLUDE;
+ }
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 178 "scanner.ll"
+{
+ idl_line_no++;
+ }
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 181 "scanner.ll"
+return T_LEFT_CURLY_BRACKET;
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 182 "scanner.ll"
+return T_RIGHT_CURLY_BRACKET;
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 183 "scanner.ll"
+return T_LEFT_PARANTHESIS;
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 184 "scanner.ll"
+return T_RIGHT_PARANTHESIS;
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 185 "scanner.ll"
+return T_COLON;
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 186 "scanner.ll"
+return T_PLUS;
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 187 "scanner.ll"
+return T_MINUS;
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 188 "scanner.ll"
+return T_TILDE;
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 189 "scanner.ll"
+return T_COMMA;
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 190 "scanner.ll"
+return T_ASTERISK;
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 191 "scanner.ll"
+return T_SEMICOLON;
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 192 "scanner.ll"
+return T_AMPERSAND;
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 193 "scanner.ll"
+return T_LESS;
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 194 "scanner.ll"
+return T_GREATER;
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 195 "scanner.ll"
+return T_SCOPE;
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 196 "scanner.ll"
+return T_EQUAL;
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 197 "scanner.ll"
+return T_ACCESS;
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 198 "scanner.ll"
+return T_TRIPLE_DOT;
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 199 "scanner.ll"
+return T_ARRAY_OPEN;
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 200 "scanner.ll"
+return T_ARRAY_CLOSE;
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 201 "scanner.ll"
+return T_ACCESS;
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 202 "scanner.ll"
+return T_SHIFT;
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 203 "scanner.ll"
+return T_MISCOPERATOR;
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 206 "scanner.ll"
+return T_CONST;
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 207 "scanner.ll"
+return T_ENUM;
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 208 "scanner.ll"
+return T_NAMESPACE;
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 209 "scanner.ll"
+return T_USING;
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 210 "scanner.ll"
+return T_CLASS;
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 211 "scanner.ll"
+return T_STRUCT;
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 212 "scanner.ll"
+return T_FUNOPERATOR;
+ YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 213 "scanner.ll"
+return T_VIRTUAL;
+ YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 214 "scanner.ll"
+return T_PUBLIC;
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 215 "scanner.ll"
+return T_INLINE;
+ YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 216 "scanner.ll"
+return T_STATIC;
+ YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 217 "scanner.ll"
+return T_MUTABLE;
+ YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 218 "scanner.ll"
+return T_SIGNED;
+ YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 219 "scanner.ll"
+return T_UNSIGNED;
+ YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 220 "scanner.ll"
+return T_SHORT;
+ YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 221 "scanner.ll"
+return T_LONG;
+ YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 222 "scanner.ll"
+return T_FRIEND;
+ YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 223 "scanner.ll"
+return T_PROTECTED;
+ YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 224 "scanner.ll"
+return T_PRIVATE;
+ YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 225 "scanner.ll"
+return T_SIGNAL;
+ YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 226 "scanner.ll"
+return T_RETURN;
+ YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 227 "scanner.ll"
+return T_SLOT;
+ YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 228 "scanner.ll"
+return T_TRUE;
+ YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 229 "scanner.ll"
+return T_INT;
+ YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 230 "scanner.ll"
+return T_CHAR;
+ YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 231 "scanner.ll"
+return T_FALSE;
+ YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 232 "scanner.ll"
+return T_TRUE;
+ YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 233 "scanner.ll"
+return T_FALSE;
+ YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 234 "scanner.ll"
+return T_DCOP_AREA;
+ YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 235 "scanner.ll"
+return T_DCOP_SIGNAL_AREA;
+ YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 236 "scanner.ll"
+return T_TYPEDEF;
+ YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 237 "scanner.ll"
+return T_DCOP;
+ YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 238 "scanner.ll"
+;
+ YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 239 "scanner.ll"
+return T_NULL;
+ YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 240 "scanner.ll"
+return T_EXTERN;
+ YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 241 "scanner.ll"
+return T_EXTERN_C;
+ YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 243 "scanner.ll"
+{
+ yylval._str = new QString( yytext );
+ return T_IDENTIFIER;
+ }
+ YY_BREAK
+case 72:
+#line 249 "scanner.ll"
+case 73:
+#line 250 "scanner.ll"
+case 74:
+#line 251 "scanner.ll"
+case 75:
+#line 252 "scanner.ll"
+case 76:
+YY_RULE_SETUP
+#line 252 "scanner.ll"
+{
+ yylval._float = ascii_to_longdouble( yytext );
+ return T_DOUBLE_LITERAL;
+ }
+ YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 256 "scanner.ll"
+{
+ yylval._int = ascii_to_longlong( 10, yytext );
+ return T_INTEGER_LITERAL;
+ }
+ YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 260 "scanner.ll"
+{
+ yylval._int = ascii_to_longlong( 8, yytext );
+ return T_INTEGER_LITERAL;
+ }
+ YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 264 "scanner.ll"
+{
+ yylval._int = ascii_to_longlong( 16, yytext + 2 );
+ return T_INTEGER_LITERAL;
+ }
+ YY_BREAK
+case 80:
+YY_RULE_SETUP
+#line 268 "scanner.ll"
+{
+ QCString s( yytext );
+ s = s.mid( 1, s.length() - 2 );
+ yylval._char = translate_char( s );
+ return T_CHARACTER_LITERAL;
+ }
+ YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 274 "scanner.ll"
+{
+ QString s( yytext );
+ yylval._str = new QString( s.mid( 1, s.length() - 2 ) );
+ return T_STRING_LITERAL;
+ }
+ YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 279 "scanner.ll"
+{
+ if (function_mode)
+ return yylex(); // call once again
+
+ qFatal("could not parse %c(%d) at line %d" , yytext[0], yytext[0], idl_line_no);
+ return T_UNKNOWN;
+ }
+ YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 287 "scanner.ll"
+ECHO;
+ YY_BREAK
+#line 1622 "scanner.cc"
+ case YY_STATE_EOF(INITIAL):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between yy_current_buffer and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yy_current_buffer->yy_input_file = yyin;
+ yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yy_c_buf_p;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yy_did_buffer_switch_on_eof = 0;
+
+ if ( yywrap() )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p =
+ yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yy_c_buf_p =
+ &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+ } /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+ {
+ register char *dest = yy_current_buffer->yy_ch_buf;
+ register char *source = yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( yy_current_buffer->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read =
+ yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+ YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = yy_current_buffer;
+
+ int yy_c_buf_p_offset =
+ (int) (yy_c_buf_p - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yy_flex_realloc( (void *) b->yy_ch_buf,
+ b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = yy_current_buffer->yy_buf_size -
+ number_to_move - 1;
+#endif
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+ yy_n_chars, num_to_read );
+
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ if ( yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart( yyin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ yy_current_buffer->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ yy_n_chars += number_to_move;
+ yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+ return ret_val;
+ }
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = yy_start;
+ yy_state_ptr = yy_state_buf;
+ *yy_state_ptr++ = yy_current_state;
+
+ for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 311 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ *yy_state_ptr++ = yy_current_state;
+ }
+
+ return yy_current_state;
+ }
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+ {
+ register int yy_is_jam;
+
+ register YY_CHAR yy_c = 1;
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 311 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 310);
+ if ( ! yy_is_jam )
+ *yy_state_ptr++ = yy_current_state;
+
+ return yy_is_jam ? 0 : yy_current_state;
+ }
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+ {
+ register char *yy_cp = yy_c_buf_p;
+
+ /* undo effects of setting up yytext */
+ *yy_cp = yy_hold_char;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = yy_n_chars + 2;
+ register char *dest = &yy_current_buffer->yy_ch_buf[
+ yy_current_buffer->yy_buf_size + 2];
+ register char *source =
+ &yy_current_buffer->yy_ch_buf[number_to_move];
+
+ while ( source > yy_current_buffer->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ yy_current_buffer->yy_n_chars =
+ yy_n_chars = yy_current_buffer->yy_buf_size;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+
+ yytext_ptr = yy_bp;
+ yy_hold_char = *yy_cp;
+ yy_c_buf_p = yy_cp;
+ }
+#endif /* ifndef YY_NO_UNPUT */
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+ {
+ int c;
+
+ *yy_c_buf_p = yy_hold_char;
+
+ if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ /* This was really a NUL. */
+ *yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ int offset = yy_c_buf_p - yytext_ptr;
+ ++yy_c_buf_p;
+
+ switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart( yyin );
+
+ /* fall through */
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap() )
+ return EOF;
+
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p = yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */
+ *yy_c_buf_p = '\0'; /* preserve yytext */
+ yy_hold_char = *++yy_c_buf_p;
+
+
+ return c;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+ {
+ if ( ! yy_current_buffer )
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_init_buffer( yy_current_buffer, input_file );
+ yy_load_buffer_state();
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+ {
+ if ( yy_current_buffer == new_buffer )
+ return;
+
+ if ( yy_current_buffer )
+ {
+ /* Flush out information for old buffer. */
+ *yy_c_buf_p = yy_hold_char;
+ yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ yy_current_buffer = new_buffer;
+ yy_load_buffer_state();
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yy_did_buffer_switch_on_eof = 1;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+ {
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+ yyin = yy_current_buffer->yy_input_file;
+ yy_hold_char = *yy_c_buf_p;
+ }
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer( b, file );
+
+ return b;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+ {
+ if ( ! b )
+ return;
+
+ if ( b == yy_current_buffer )
+ yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yy_flex_free( (void *) b->yy_ch_buf );
+
+ yy_flex_free( (void *) b );
+ }
+
+
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO(( int ));
+#endif
+#endif
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+ {
+ yy_flush_buffer( b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+ b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+ b->yy_is_interactive = 0;
+#else
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+ {
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == yy_current_buffer )
+ yy_load_buffer_state();
+ }
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer( b );
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+#else
+YY_BUFFER_STATE yy_scan_string( yy_str )
+yyconst char *yy_str;
+#endif
+ {
+ int len;
+ for ( len = 0; yy_str[len]; ++len )
+ ;
+
+ return yy_scan_bytes( yy_str, len );
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+ {
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = len + 2;
+ buf = (char *) yy_flex_alloc( n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < len; ++i )
+ buf[i] = bytes[i];
+
+ buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer( buf, n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+ {
+ if ( yy_start_stack_ptr >= yy_start_stack_depth )
+ {
+ yy_size_t new_size;
+
+ yy_start_stack_depth += YY_START_STACK_INCR;
+ new_size = yy_start_stack_depth * sizeof( int );
+
+ if ( ! yy_start_stack )
+ yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+ else
+ yy_start_stack = (int *) yy_flex_realloc(
+ (void *) yy_start_stack, new_size );
+
+ if ( ! yy_start_stack )
+ YY_FATAL_ERROR(
+ "out of memory expanding start-condition stack" );
+ }
+
+ yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+ BEGIN(new_state);
+ }
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+ {
+ if ( --yy_start_stack_ptr < 0 )
+ YY_FATAL_ERROR( "start-condition stack underflow" );
+
+ BEGIN(yy_start_stack[yy_start_stack_ptr]);
+ }
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+ {
+ return yy_start_stack[yy_start_stack_ptr - 1];
+ }
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+ {
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+ }
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ yytext[yyleng] = yy_hold_char; \
+ yy_c_buf_p = yytext + n; \
+ yy_hold_char = *yy_c_buf_p; \
+ *yy_c_buf_p = '\0'; \
+ yyleng = n; \
+ } \
+ while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+ {
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+ }
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int yy_flex_strlen( yyconst char *s )
+#else
+static int yy_flex_strlen( s )
+yyconst char *s;
+#endif
+ {
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+ }
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+ {
+ return (void *) malloc( size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+ {
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+ {
+ free( ptr );
+ }
+
+#if YY_MAIN
+int main()
+ {
+ yylex();
+ return 0;
+ }
+#endif
+#line 287 "scanner.ll"
+
+
+void dcopidlInitFlex( const char *_code )
+{
+ comment_mode = 0;
+ yy_switch_to_buffer( yy_scan_string( _code ) );
+}
diff --git a/dcop/dcopidl/scanner.ll b/dcop/dcopidl/scanner.ll
new file mode 100644
index 000000000..767594ac6
--- /dev/null
+++ b/dcop/dcopidl/scanner.ll
@@ -0,0 +1,293 @@
+%{
+/*****************************************************************
+Copyright (c) 1999 Torben Weis <weis@kde.org>
+Copyright (c) 2000 Matthias Ettrich <ettrich@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 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.
+
+******************************************************************/
+
+#define YY_NO_UNPUT
+#include <stdlib.h>
+#include <ctype.h>
+
+class QString;
+
+#ifndef KDE_USE_FINAL
+#include "yacc.cc.h"
+#endif
+
+extern int idl_line_no;
+int comment_mode;
+int function_mode = 0;
+
+#include <qstring.h>
+#include <qregexp.h>
+
+static long ascii_to_longlong( long base, const char *s )
+{
+ long ll = 0;
+ while( *s != '\0' ) {
+ char c = *s++;
+ if( c >= 'a' )
+ c -= 'a' - 'A';
+ c -= '0';
+ if( c > 9 )
+ c -= 'A' - '0' - 10;
+ ll = ll * base + c;
+ }
+ return ll;
+}
+
+static double ascii_to_longdouble (const char *s)
+{
+ double d;
+#ifdef HAVE_SCANF_LF
+ sscanf (s, "%Lf", &d);
+#else
+ /*
+ * this is only an approximation and will probably break fixed<>
+ * parameter calculation on systems where
+ * sizeof(double) < sizeof(long double). but fortunately all
+ * systems where scanf("%Lf") is known to be broken (Linux/Alpha
+ * and HPUX) have sizeof(double) == sizeof(long double).
+ */
+ d = strtod (s, NULL);
+#endif
+ return d;
+}
+
+static char translate_char( const char *s )
+{
+ char c = *s++;
+
+ if( c != '\\' )
+ return c;
+ c = *s++;
+ switch( c ) {
+ case 'n':
+ return '\n';
+ case 't':
+ return '\t';
+ case 'v':
+ return '\v';
+ case 'b':
+ return '\b';
+ case 'r':
+ return '\r';
+ case 'f':
+ return '\f';
+ case 'a':
+ return '\a';
+ case '\\':
+ return '\\';
+ case '?':
+ return '\?';
+ case '\'':
+ return '\'';
+ case '"':
+ return '"';
+ case 'x':
+ case 'X':
+ return (char) ascii_to_longlong( 16, s );
+ default:
+ // Gotta be an octal
+ return (char) ascii_to_longlong( 8, s );
+ }
+}
+
+
+%}
+
+%option noyywrap
+%option never-interactive
+/*--------------------------------------------------------------------------*/
+
+Digits [0-9]+
+Oct_Digit [0-7]
+Hex_Digit [a-fA-F0-9]
+Int_Literal [1-9][0-9]*L?
+Oct_Literal 0{Oct_Digit}*
+Hex_Literal (0x|0X){Hex_Digit}*
+Esc_Sequence1 "\\"[ntvbrfa\\\?\'\"]
+Esc_Sequence2 "\\"{Oct_Digit}{1,3}
+Esc_Sequence3 "\\"(x|X){Hex_Digit}{1,2}
+Esc_Sequence ({Esc_Sequence1}|{Esc_Sequence2}|{Esc_Sequence3})
+Char ([^\n\t\"\'\\]|{Esc_Sequence})
+Char_Literal "'"({Char}|\"|\\)"'"
+String_Literal \"({Char}|"'")*\"
+Float_Literal1 {Digits}"."{Digits}(e|E)("+"|"-")?{Digits}
+Float_Literal2 {Digits}(e|E)("+"|"-")?{Digits}
+Float_Literal3 {Digits}"."{Digits}
+Float_Literal4 "."{Digits}
+Float_Literal5 "."{Digits}(e|E)("+"|"-")?{Digits}
+
+/*--------------------------------------------------------------------------*/
+
+Kidl_Identifier [_a-zA-Z][a-zA-Z0-9_]*
+
+/*--------------------------------------------------------------------------*/
+
+
+
+%%
+
+[ \t] ;
+[\n] { idl_line_no++; }
+
+"/\*" { comment_mode = 1; }
+"\*/" { if (!comment_mode) { REJECT; } else { comment_mode = 0; } }
+"}" {
+ if (! comment_mode) {
+ if (!function_mode) { REJECT; } else {
+ function_mode = 0;
+ return T_RIGHT_CURLY_BRACKET;
+ }
+ }
+ }
+[^\n}*]* { if (!comment_mode && !function_mode) { REJECT; } }
+"*" { if (!comment_mode) { REJECT; } }
+
+"//"[^\n]* ;
+"#!"[^\n]* {
+ exit( 1 );
+ }
+"#include"[ \t]*[<\"][^>"]*[>\"]\s*\n {
+ QString s( yytext );
+ int i = s.find(QRegExp("[\"<]"))+1;
+ int j = s.find(QRegExp("[\">]"), i);
+ yylval._str = new QString( s.mid( i, j - i ) );
+ idl_line_no++;
+ return T_INCLUDE;
+ }
+"#"[^\n]*\n {
+ idl_line_no++;
+ }
+"{" return T_LEFT_CURLY_BRACKET;
+"}" return T_RIGHT_CURLY_BRACKET;
+"(" return T_LEFT_PARANTHESIS;
+")" return T_RIGHT_PARANTHESIS;
+":" return T_COLON;
+"+" return T_PLUS;
+"-" return T_MINUS;
+"~" return T_TILDE;
+"," return T_COMMA;
+"*" return T_ASTERISK;
+";" return T_SEMICOLON;
+"&" return T_AMPERSAND;
+"<" return T_LESS;
+">" return T_GREATER;
+"::" return T_SCOPE;
+"=" return T_EQUAL;
+"." return T_ACCESS;
+"..." return T_TRIPLE_DOT;
+"[" return T_ARRAY_OPEN;
+"]" return T_ARRAY_CLOSE;
+"->" return T_ACCESS;
+(">>"|"<<") return T_SHIFT;
+(">="|"<="|"!="|"==") return T_MISCOPERATOR;
+
+
+const return T_CONST;
+enum return T_ENUM;
+namespace return T_NAMESPACE;
+using return T_USING;
+class return T_CLASS;
+struct return T_STRUCT;
+operator return T_FUNOPERATOR;
+virtual return T_VIRTUAL;
+public return T_PUBLIC;
+inline return T_INLINE;
+static return T_STATIC;
+mutable return T_MUTABLE;
+signed return T_SIGNED;
+unsigned return T_UNSIGNED;
+short return T_SHORT;
+long return T_LONG;
+friend return T_FRIEND;
+protected return T_PROTECTED;
+private return T_PRIVATE;
+signals return T_SIGNAL;
+return return T_RETURN;
+slots return T_SLOT;
+true return T_TRUE;
+int return T_INT;
+char return T_CHAR;
+false return T_FALSE;
+TRUE return T_TRUE;
+FALSE return T_FALSE;
+"k_dcop" return T_DCOP_AREA;
+"k_dcop_signals" return T_DCOP_SIGNAL_AREA;
+typedef return T_TYPEDEF;
+K_DCOP return T_DCOP;
+Q_OBJECT ;
+("0"|"0L") return T_NULL;
+"extern "[A-Za-z0-9_ \t*]+ return T_EXTERN;
+"extern \"C\"" return T_EXTERN_C;
+
+{Kidl_Identifier} {
+ yylval._str = new QString( yytext );
+ return T_IDENTIFIER;
+ }
+
+{Float_Literal1} |
+{Float_Literal2} |
+{Float_Literal3} |
+{Float_Literal4} |
+{Float_Literal5} {
+ yylval._float = ascii_to_longdouble( yytext );
+ return T_DOUBLE_LITERAL;
+ }
+{Int_Literal} {
+ yylval._int = ascii_to_longlong( 10, yytext );
+ return T_INTEGER_LITERAL;
+ }
+{Oct_Literal} {
+ yylval._int = ascii_to_longlong( 8, yytext );
+ return T_INTEGER_LITERAL;
+ }
+{Hex_Literal} {
+ yylval._int = ascii_to_longlong( 16, yytext + 2 );
+ return T_INTEGER_LITERAL;
+ }
+{Char_Literal} {
+ QCString s( yytext );
+ s = s.mid( 1, s.length() - 2 );
+ yylval._char = translate_char( s );
+ return T_CHARACTER_LITERAL;
+ }
+{String_Literal} {
+ QString s( yytext );
+ yylval._str = new QString( s.mid( 1, s.length() - 2 ) );
+ return T_STRING_LITERAL;
+ }
+. {
+ if (function_mode)
+ return yylex(); // call once again
+
+ qFatal("could not parse %c(%d) at line %d" , yytext[0], yytext[0], idl_line_no);
+ return T_UNKNOWN;
+ }
+
+%%
+
+void dcopidlInitFlex( const char *_code )
+{
+ comment_mode = 0;
+ yy_switch_to_buffer( yy_scan_string( _code ) );
+}
diff --git a/dcop/dcopidl/yacc.cc b/dcop/dcopidl/yacc.cc
new file mode 100644
index 000000000..4147a3472
--- /dev/null
+++ b/dcop/dcopidl/yacc.cc
@@ -0,0 +1,2824 @@
+/* A Bison parser, made by GNU Bison 1.875d. */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* Written by Richard Stallman by simplifying the original so called
+ ``semantic'' parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ T_UNIMPORTANT = 258,
+ T_CHARACTER_LITERAL = 259,
+ T_DOUBLE_LITERAL = 260,
+ T_IDENTIFIER = 261,
+ T_INTEGER_LITERAL = 262,
+ T_STRING_LITERAL = 263,
+ T_INCLUDE = 264,
+ T_CLASS = 265,
+ T_STRUCT = 266,
+ T_LEFT_CURLY_BRACKET = 267,
+ T_LEFT_PARANTHESIS = 268,
+ T_RIGHT_CURLY_BRACKET = 269,
+ T_RIGHT_PARANTHESIS = 270,
+ T_COLON = 271,
+ T_SEMICOLON = 272,
+ T_PUBLIC = 273,
+ T_PROTECTED = 274,
+ T_TRIPE_DOT = 275,
+ T_PRIVATE = 276,
+ T_VIRTUAL = 277,
+ T_CONST = 278,
+ T_INLINE = 279,
+ T_FRIEND = 280,
+ T_RETURN = 281,
+ T_SIGNAL = 282,
+ T_SLOT = 283,
+ T_TYPEDEF = 284,
+ T_PLUS = 285,
+ T_MINUS = 286,
+ T_COMMA = 287,
+ T_ASTERISK = 288,
+ T_TILDE = 289,
+ T_LESS = 290,
+ T_GREATER = 291,
+ T_AMPERSAND = 292,
+ T_EXTERN = 293,
+ T_EXTERN_C = 294,
+ T_ACCESS = 295,
+ T_ENUM = 296,
+ T_NAMESPACE = 297,
+ T_USING = 298,
+ T_UNKNOWN = 299,
+ T_TRIPLE_DOT = 300,
+ T_TRUE = 301,
+ T_FALSE = 302,
+ T_STATIC = 303,
+ T_MUTABLE = 304,
+ T_EQUAL = 305,
+ T_SCOPE = 306,
+ T_NULL = 307,
+ T_INT = 308,
+ T_ARRAY_OPEN = 309,
+ T_ARRAY_CLOSE = 310,
+ T_CHAR = 311,
+ T_DCOP = 312,
+ T_DCOP_AREA = 313,
+ T_DCOP_SIGNAL_AREA = 314,
+ T_SIGNED = 315,
+ T_UNSIGNED = 316,
+ T_LONG = 317,
+ T_SHORT = 318,
+ T_FUNOPERATOR = 319,
+ T_MISCOPERATOR = 320,
+ T_SHIFT = 321
+ };
+#endif
+#define T_UNIMPORTANT 258
+#define T_CHARACTER_LITERAL 259
+#define T_DOUBLE_LITERAL 260
+#define T_IDENTIFIER 261
+#define T_INTEGER_LITERAL 262
+#define T_STRING_LITERAL 263
+#define T_INCLUDE 264
+#define T_CLASS 265
+#define T_STRUCT 266
+#define T_LEFT_CURLY_BRACKET 267
+#define T_LEFT_PARANTHESIS 268
+#define T_RIGHT_CURLY_BRACKET 269
+#define T_RIGHT_PARANTHESIS 270
+#define T_COLON 271
+#define T_SEMICOLON 272
+#define T_PUBLIC 273
+#define T_PROTECTED 274
+#define T_TRIPE_DOT 275
+#define T_PRIVATE 276
+#define T_VIRTUAL 277
+#define T_CONST 278
+#define T_INLINE 279
+#define T_FRIEND 280
+#define T_RETURN 281
+#define T_SIGNAL 282
+#define T_SLOT 283
+#define T_TYPEDEF 284
+#define T_PLUS 285
+#define T_MINUS 286
+#define T_COMMA 287
+#define T_ASTERISK 288
+#define T_TILDE 289
+#define T_LESS 290
+#define T_GREATER 291
+#define T_AMPERSAND 292
+#define T_EXTERN 293
+#define T_EXTERN_C 294
+#define T_ACCESS 295
+#define T_ENUM 296
+#define T_NAMESPACE 297
+#define T_USING 298
+#define T_UNKNOWN 299
+#define T_TRIPLE_DOT 300
+#define T_TRUE 301
+#define T_FALSE 302
+#define T_STATIC 303
+#define T_MUTABLE 304
+#define T_EQUAL 305
+#define T_SCOPE 306
+#define T_NULL 307
+#define T_INT 308
+#define T_ARRAY_OPEN 309
+#define T_ARRAY_CLOSE 310
+#define T_CHAR 311
+#define T_DCOP 312
+#define T_DCOP_AREA 313
+#define T_DCOP_SIGNAL_AREA 314
+#define T_SIGNED 315
+#define T_UNSIGNED 316
+#define T_LONG 317
+#define T_SHORT 318
+#define T_FUNOPERATOR 319
+#define T_MISCOPERATOR 320
+#define T_SHIFT 321
+
+
+
+
+/* Copy the first part of user declarations. */
+#line 1 "yacc.yy"
+
+/*****************************************************************
+Copyright (c) 1999 Torben Weis <weis@kde.org>
+Copyright (c) 2000 Matthias Ettrich <ettrich@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 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.
+
+******************************************************************/
+
+#include <config.h>
+
+// Workaround for a bison issue:
+// bison.simple concludes from _GNU_SOURCE that stpcpy is available,
+// while GNU string.h only exposes it if __USE_GNU is set.
+#ifdef _GNU_SOURCE
+#define __USE_GNU 1
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include <qstring.h>
+
+#define AMP_ENTITY "&amp;"
+#define YYERROR_VERBOSE
+
+extern int yylex();
+
+// extern QString idl_lexFile;
+extern int idl_line_no;
+extern int function_mode;
+
+static int dcop_area = 0;
+static int dcop_signal_area = 0;
+
+static QString in_namespace( "" );
+
+void dcopidlInitFlex( const char *_code );
+
+void yyerror( const char *s )
+{
+ qDebug( "In line %i : %s", idl_line_no, s );
+ exit(1);
+ // theParser->parse_error( idl_lexFile, s, idl_line_no );
+}
+
+
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+#line 67 "yacc.yy"
+typedef union YYSTYPE {
+ long _int;
+ QString *_str;
+ unsigned short _char;
+ double _float;
+} YYSTYPE;
+/* Line 191 of yacc.c. */
+#line 279 "yacc.cc"
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 214 of yacc.c. */
+#line 291 "yacc.cc"
+
+#if ! defined (yyoverflow) || YYERROR_VERBOSE
+
+# ifndef YYFREE
+# define YYFREE free
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# endif
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# define YYSTACK_ALLOC alloca
+# endif
+# else
+# if defined (alloca) || defined (_ALLOCA_H)
+# define YYSTACK_ALLOC alloca
+# else
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+# if defined (__STDC__) || defined (__cplusplus)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# endif
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# endif
+#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
+
+
+#if (! defined (yyoverflow) \
+ && (! defined (__cplusplus) \
+ || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ short int yyss;
+ YYSTYPE yyvs;
+ };
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined (__GNUC__) && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ register YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (0)
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack, Stack, yysize); \
+ Stack = &yyptr->Stack; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (0)
+
+#endif
+
+#if defined (__STDC__) || defined (__cplusplus)
+ typedef signed char yysigned_char;
+#else
+ typedef short int yysigned_char;
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 5
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 559
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 67
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 53
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 185
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 374
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 321
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const unsigned char yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const unsigned short int yyprhs[] =
+{
+ 0, 0, 3, 7, 8, 11, 16, 17, 19, 20,
+ 27, 35, 39, 43, 49, 50, 58, 63, 69, 72,
+ 77, 85, 94, 97, 99, 101, 103, 106, 107, 109,
+ 111, 113, 115, 117, 119, 121, 122, 126, 129, 132,
+ 135, 137, 141, 143, 148, 152, 154, 157, 161, 164,
+ 166, 167, 169, 171, 174, 178, 181, 184, 187, 190,
+ 193, 196, 202, 207, 212, 217, 224, 229, 236, 243,
+ 251, 258, 265, 271, 275, 277, 281, 283, 285, 287,
+ 290, 292, 294, 296, 300, 304, 312, 322, 323, 325,
+ 327, 330, 332, 335, 338, 342, 345, 349, 352, 356,
+ 359, 363, 365, 367, 370, 372, 375, 377, 380, 383,
+ 386, 388, 389, 391, 395, 397, 399, 402, 405, 410,
+ 417, 421, 423, 426, 428, 432, 436, 439, 442, 446,
+ 449, 451, 454, 458, 460, 464, 467, 469, 470, 473,
+ 479, 481, 483, 485, 487, 492, 493, 495, 497, 499,
+ 501, 503, 505, 512, 520, 522, 526, 527, 532, 534,
+ 538, 541, 547, 551, 557, 565, 572, 576, 578, 580,
+ 584, 589, 592, 593, 595, 598, 599, 601, 605, 608,
+ 611, 615, 621, 627, 633, 640
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yysigned_char yyrhs[] =
+{
+ 68, 0, -1, 69, 71, 68, -1, -1, 69, 9,
+ -1, 39, 12, 68, 14, -1, -1, 57, -1, -1,
+ 10, 80, 84, 70, 86, 17, -1, 10, 6, 80,
+ 84, 70, 86, 17, -1, 10, 80, 17, -1, 11,
+ 80, 17, -1, 11, 80, 84, 86, 17, -1, -1,
+ 42, 6, 12, 72, 68, 14, 85, -1, 43, 42,
+ 6, 17, -1, 43, 6, 51, 6, 17, -1, 38,
+ 17, -1, 29, 100, 80, 17, -1, 29, 11, 12,
+ 73, 14, 80, 17, -1, 29, 11, 80, 12, 73,
+ 14, 80, 17, -1, 24, 111, -1, 111, -1, 119,
+ -1, 87, -1, 119, 73, -1, -1, 46, -1, 47,
+ -1, 21, -1, 19, -1, 18, -1, 27, -1, 28,
+ -1, -1, 75, 76, 16, -1, 76, 16, -1, 58,
+ 16, -1, 59, 16, -1, 6, -1, 6, 51, 80,
+ -1, 80, -1, 80, 35, 101, 36, -1, 105, 18,
+ 81, -1, 81, -1, 82, 12, -1, 82, 32, 83,
+ -1, 16, 83, -1, 12, -1, -1, 17, -1, 14,
+ -1, 92, 86, -1, 24, 111, 86, -1, 111, 86,
+ -1, 79, 86, -1, 87, 86, -1, 78, 86, -1,
+ 77, 86, -1, 119, 86, -1, 25, 10, 80, 17,
+ 86, -1, 25, 80, 17, 86, -1, 25, 107, 17,
+ 86, -1, 10, 80, 17, 86, -1, 10, 80, 84,
+ 86, 17, 86, -1, 11, 80, 17, 86, -1, 11,
+ 80, 84, 86, 17, 86, -1, 43, 6, 51, 6,
+ 17, 86, -1, 41, 6, 12, 88, 14, 6, 17,
+ -1, 41, 6, 12, 88, 14, 17, -1, 41, 12,
+ 88, 14, 6, 17, -1, 41, 12, 88, 14, 17,
+ -1, 89, 32, 88, -1, 89, -1, 6, 50, 91,
+ -1, 6, -1, 4, -1, 7, -1, 31, 7, -1,
+ 52, -1, 80, -1, 90, -1, 90, 30, 90, -1,
+ 90, 66, 90, -1, 29, 80, 35, 101, 36, 80,
+ 17, -1, 29, 80, 35, 101, 36, 51, 6, 80,
+ 17, -1, -1, 23, -1, 60, -1, 60, 53, -1,
+ 61, -1, 61, 53, -1, 60, 63, -1, 60, 63,
+ 53, -1, 60, 62, -1, 60, 62, 53, -1, 61,
+ 63, -1, 61, 63, 53, -1, 61, 62, -1, 61,
+ 62, 53, -1, 53, -1, 62, -1, 62, 53, -1,
+ 63, -1, 63, 53, -1, 56, -1, 60, 56, -1,
+ 61, 56, -1, 33, 95, -1, 33, -1, -1, 102,
+ -1, 96, 32, 102, -1, 94, -1, 80, -1, 11,
+ 80, -1, 10, 80, -1, 80, 35, 98, 36, -1,
+ 80, 35, 98, 36, 51, 80, -1, 99, 32, 98,
+ -1, 99, -1, 97, 95, -1, 97, -1, 23, 97,
+ 95, -1, 23, 97, 37, -1, 23, 97, -1, 97,
+ 23, -1, 97, 23, 37, -1, 97, 37, -1, 97,
+ -1, 97, 95, -1, 100, 32, 101, -1, 100, -1,
+ 100, 80, 103, -1, 100, 103, -1, 45, -1, -1,
+ 50, 104, -1, 50, 13, 100, 15, 104, -1, 8,
+ -1, 91, -1, 5, -1, 74, -1, 80, 13, 96,
+ 15, -1, -1, 22, -1, 65, -1, 66, -1, 36,
+ -1, 35, -1, 50, -1, 100, 80, 13, 96, 15,
+ 93, -1, 100, 64, 106, 13, 96, 15, 93, -1,
+ 104, -1, 104, 32, 108, -1, -1, 6, 13, 108,
+ 15, -1, 109, -1, 109, 32, 110, -1, 107, 113,
+ -1, 22, 107, 50, 52, 113, -1, 22, 107, 113,
+ -1, 80, 13, 96, 15, 113, -1, 80, 13, 96,
+ 15, 16, 110, 113, -1, 105, 34, 80, 13, 15,
+ 113, -1, 48, 107, 113, -1, 12, -1, 17, -1,
+ 112, 114, 14, -1, 112, 114, 14, 17, -1, 115,
+ 114, -1, -1, 17, -1, 32, 118, -1, -1, 6,
+ -1, 6, 50, 104, -1, 95, 6, -1, 117, 116,
+ -1, 100, 118, 17, -1, 100, 80, 16, 7, 17,
+ -1, 48, 100, 6, 103, 17, -1, 49, 100, 6,
+ 103, 17, -1, 100, 6, 54, 91, 55, 17, -1,
+ 48, 100, 6, 54, 91, 55, 17, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const unsigned short int yyrline[] =
+{
+ 0, 164, 164, 167, 171, 175, 179, 184, 185, 189,
+ 198, 207, 210, 213, 217, 216, 228, 231, 234, 237,
+ 240, 243, 246, 249, 252, 255, 261, 262, 265, 265,
+ 267, 267, 267, 269, 269, 269, 272, 277, 285, 293,
+ 305, 308, 316, 322, 331, 335, 342, 346, 354, 358,
+ 366, 368, 372, 376, 380, 384, 388, 392, 396, 400,
+ 404, 408, 412, 416, 420, 424, 428, 432, 436, 443,
+ 444, 445, 446, 450, 451, 455, 456, 460, 461, 462,
+ 463, 464, 468, 469, 470, 474, 484, 493, 496, 503,
+ 504, 505, 506, 507, 508, 509, 510, 511, 512, 513,
+ 514, 515, 516, 517, 518, 519, 520, 521, 522, 526,
+ 527, 532, 535, 536, 544, 545, 546, 547, 548, 554,
+ 565, 569, 577, 582, 591, 596, 603, 608, 613, 620,
+ 625, 630, 638, 642, 649, 658, 666, 676, 678, 681,
+ 688, 691, 694, 697, 700, 706, 707, 711, 711, 711,
+ 711, 711, 715, 737, 748, 749, 750, 755, 760, 761,
+ 765, 769, 773, 777, 783, 789, 795, 808, 815, 816,
+ 817, 821, 822, 826, 830, 831, 834, 835, 836, 839,
+ 843, 844, 845, 846, 847, 848
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE
+/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "T_UNIMPORTANT", "T_CHARACTER_LITERAL",
+ "T_DOUBLE_LITERAL", "T_IDENTIFIER", "T_INTEGER_LITERAL",
+ "T_STRING_LITERAL", "T_INCLUDE", "T_CLASS", "T_STRUCT",
+ "T_LEFT_CURLY_BRACKET", "T_LEFT_PARANTHESIS", "T_RIGHT_CURLY_BRACKET",
+ "T_RIGHT_PARANTHESIS", "T_COLON", "T_SEMICOLON", "T_PUBLIC",
+ "T_PROTECTED", "T_TRIPE_DOT", "T_PRIVATE", "T_VIRTUAL", "T_CONST",
+ "T_INLINE", "T_FRIEND", "T_RETURN", "T_SIGNAL", "T_SLOT", "T_TYPEDEF",
+ "T_PLUS", "T_MINUS", "T_COMMA", "T_ASTERISK", "T_TILDE", "T_LESS",
+ "T_GREATER", "T_AMPERSAND", "T_EXTERN", "T_EXTERN_C", "T_ACCESS",
+ "T_ENUM", "T_NAMESPACE", "T_USING", "T_UNKNOWN", "T_TRIPLE_DOT",
+ "T_TRUE", "T_FALSE", "T_STATIC", "T_MUTABLE", "T_EQUAL", "T_SCOPE",
+ "T_NULL", "T_INT", "T_ARRAY_OPEN", "T_ARRAY_CLOSE", "T_CHAR", "T_DCOP",
+ "T_DCOP_AREA", "T_DCOP_SIGNAL_AREA", "T_SIGNED", "T_UNSIGNED", "T_LONG",
+ "T_SHORT", "T_FUNOPERATOR", "T_MISCOPERATOR", "T_SHIFT", "$accept",
+ "main", "includes", "dcoptag", "declaration", "@1", "member_list",
+ "bool_value", "nodcop_area", "sigslot", "nodcop_area_begin",
+ "dcop_area_begin", "dcop_signal_area_begin", "Identifier",
+ "super_class_name", "super_class", "super_classes", "class_header",
+ "opt_semicolon", "body", "enum", "enum_list", "enum_item", "number",
+ "int_expression", "typedef", "const_qualifier", "int_type", "asterisks",
+ "params", "type_name", "templ_type_list", "templ_type", "type",
+ "type_list", "param", "default", "value", "virtual_qualifier",
+ "operator", "function_header", "values", "init_item", "init_list",
+ "function", "function_begin", "function_body", "function_lines",
+ "function_line", "Identifier_list_rest", "Identifier_list_entry",
+ "Identifier_list", "member", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const unsigned short int yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, 318, 319, 320, 321
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const unsigned char yyr1[] =
+{
+ 0, 67, 68, 68, 69, 69, 69, 70, 70, 71,
+ 71, 71, 71, 71, 72, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 73, 73, 74, 74,
+ 75, 75, 75, 76, 76, 76, 77, 77, 78, 79,
+ 80, 80, 81, 81, 82, 82, 83, 83, 84, 84,
+ 85, 85, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 87,
+ 87, 87, 87, 88, 88, 89, 89, 90, 90, 90,
+ 90, 90, 91, 91, 91, 92, 92, 93, 93, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 95,
+ 95, 96, 96, 96, 97, 97, 97, 97, 97, 97,
+ 98, 98, 99, 99, 100, 100, 100, 100, 100, 100,
+ 100, 100, 101, 101, 102, 102, 102, 103, 103, 103,
+ 104, 104, 104, 104, 104, 105, 105, 106, 106, 106,
+ 106, 106, 107, 107, 108, 108, 108, 109, 110, 110,
+ 111, 111, 111, 111, 111, 111, 111, 112, 113, 113,
+ 113, 114, 114, 115, 116, 116, 117, 117, 117, 118,
+ 119, 119, 119, 119, 119, 119
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const unsigned char yyr2[] =
+{
+ 0, 2, 3, 0, 2, 4, 0, 1, 0, 6,
+ 7, 3, 3, 5, 0, 7, 4, 5, 2, 4,
+ 7, 8, 2, 1, 1, 1, 2, 0, 1, 1,
+ 1, 1, 1, 1, 1, 0, 3, 2, 2, 2,
+ 1, 3, 1, 4, 3, 1, 2, 3, 2, 1,
+ 0, 1, 1, 2, 3, 2, 2, 2, 2, 2,
+ 2, 5, 4, 4, 4, 6, 4, 6, 6, 7,
+ 6, 6, 5, 3, 1, 3, 1, 1, 1, 2,
+ 1, 1, 1, 3, 3, 7, 9, 0, 1, 1,
+ 2, 1, 2, 2, 3, 2, 3, 2, 3, 2,
+ 3, 1, 1, 2, 1, 2, 1, 2, 2, 2,
+ 1, 0, 1, 3, 1, 1, 2, 2, 4, 6,
+ 3, 1, 2, 1, 3, 3, 2, 2, 3, 2,
+ 1, 2, 3, 1, 3, 2, 1, 0, 2, 5,
+ 1, 1, 1, 1, 4, 0, 1, 1, 1, 1,
+ 1, 1, 6, 7, 1, 3, 0, 4, 1, 3,
+ 2, 5, 3, 5, 7, 6, 3, 1, 1, 3,
+ 4, 2, 0, 1, 2, 0, 1, 3, 2, 2,
+ 3, 5, 5, 5, 6, 7
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const unsigned char yydefact[] =
+{
+ 6, 0, 0, 145, 6, 1, 40, 4, 0, 0,
+ 146, 0, 145, 0, 0, 0, 0, 0, 0, 0,
+ 101, 106, 89, 91, 102, 104, 6, 115, 25, 114,
+ 130, 0, 0, 0, 23, 24, 0, 0, 40, 117,
+ 116, 0, 0, 115, 0, 0, 126, 0, 22, 0,
+ 0, 18, 0, 0, 0, 0, 0, 0, 0, 0,
+ 90, 107, 95, 93, 92, 108, 99, 97, 103, 105,
+ 2, 111, 0, 127, 110, 129, 131, 40, 0, 0,
+ 0, 175, 0, 0, 167, 168, 172, 160, 5, 41,
+ 0, 49, 145, 11, 8, 12, 35, 117, 116, 0,
+ 0, 162, 125, 124, 27, 116, 0, 0, 76, 0,
+ 74, 14, 0, 0, 40, 166, 137, 96, 94, 100,
+ 98, 136, 0, 137, 112, 123, 0, 121, 128, 109,
+ 0, 0, 150, 149, 151, 147, 148, 0, 111, 0,
+ 178, 0, 179, 180, 0, 173, 0, 172, 8, 146,
+ 42, 45, 0, 48, 0, 7, 35, 0, 0, 52,
+ 32, 31, 30, 145, 0, 33, 34, 0, 0, 0,
+ 0, 35, 0, 35, 35, 35, 0, 35, 35, 35,
+ 35, 0, 0, 0, 0, 27, 27, 19, 0, 0,
+ 0, 0, 6, 0, 16, 0, 0, 0, 0, 0,
+ 0, 137, 135, 122, 118, 0, 77, 142, 78, 140,
+ 0, 28, 29, 80, 143, 81, 82, 141, 177, 81,
+ 0, 111, 0, 0, 176, 174, 0, 169, 171, 35,
+ 0, 46, 145, 0, 0, 117, 116, 35, 0, 115,
+ 0, 0, 0, 38, 39, 0, 37, 59, 58, 56,
+ 13, 57, 53, 55, 60, 161, 0, 0, 0, 26,
+ 0, 0, 75, 0, 72, 73, 0, 17, 0, 138,
+ 0, 182, 183, 0, 163, 113, 134, 0, 120, 79,
+ 111, 0, 0, 0, 0, 87, 181, 0, 170, 0,
+ 133, 0, 47, 44, 9, 35, 35, 35, 35, 54,
+ 117, 35, 35, 0, 0, 36, 137, 0, 0, 0,
+ 70, 71, 50, 0, 0, 0, 158, 0, 119, 0,
+ 83, 84, 184, 87, 88, 152, 165, 10, 0, 43,
+ 64, 0, 66, 0, 35, 62, 63, 0, 0, 20,
+ 0, 69, 51, 15, 0, 185, 156, 0, 164, 144,
+ 153, 132, 35, 35, 61, 0, 35, 21, 139, 154,
+ 0, 159, 65, 67, 0, 0, 68, 156, 157, 0,
+ 85, 155, 0, 86
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const short int yydefgoto[] =
+{
+ -1, 2, 3, 156, 26, 192, 183, 214, 171, 172,
+ 173, 174, 175, 27, 151, 152, 153, 94, 343, 176,
+ 177, 109, 110, 216, 217, 178, 325, 29, 80, 122,
+ 30, 126, 127, 31, 291, 124, 197, 359, 32, 137,
+ 33, 360, 316, 317, 179, 86, 87, 146, 147, 142,
+ 81, 82, 180
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -191
+static const short int yypact[] =
+{
+ 28, 78, 99, 342, 80, -191, 67, -191, 115, 159,
+ 205, 81, 386, 463, 153, 44, 190, 32, 205, 205,
+ -191, -191, 181, 287, 154, 161, 47, 66, -191, -191,
+ 138, 19, 185, 143, -191, -191, 207, 159, 21, 183,
+ 219, 159, 159, 194, 16, 31, 152, 205, -191, 91,
+ 159, -191, 228, 236, 233, 202, 264, 18, 143, 272,
+ -191, -191, 231, 232, -191, -191, 246, 248, -191, -191,
+ -191, 445, 81, 249, 256, -191, -191, 85, 182, 42,
+ 296, 273, 290, 159, -191, -191, 291, -191, -191, -191,
+ 196, -191, 146, -191, 262, -191, 269, -191, -191, 300,
+ 252, -191, -191, -191, 404, 311, 307, 236, 276, 319,
+ 302, -191, 329, 320, 60, -191, 289, -191, -191, -191,
+ -191, -191, 114, 39, -191, 256, 305, 310, -191, -191,
+ 507, 101, -191, -191, -191, -191, -191, 332, 445, 339,
+ -191, 62, -191, -191, 341, -191, 343, 291, 262, -191,
+ 321, -191, 34, -191, 337, -191, 269, 159, 159, -191,
+ -191, -191, -191, 386, 474, -191, -191, 159, 352, 344,
+ 346, 211, 347, 269, 269, 269, 350, 269, 269, 269,
+ 269, 143, 205, 354, 87, 404, 404, -191, 356, 101,
+ 156, 236, 80, 359, -191, 120, 101, 360, 364, 247,
+ 445, 289, -191, -191, 331, 81, -191, -191, -191, -191,
+ 379, -191, -191, -191, -191, 374, 40, -191, -191, -191,
+ 333, 445, 116, 372, 349, -191, 378, 377, -191, 269,
+ 205, -191, 146, 159, 383, 265, 299, 269, 159, 27,
+ 384, 371, 361, -191, -191, 391, -191, -191, -191, -191,
+ -191, -191, -191, -191, -191, -191, 407, 159, 400, -191,
+ 403, 176, -191, 401, -191, -191, 405, -191, 205, -191,
+ 365, -191, -191, 415, -191, -191, -191, 159, -191, -191,
+ 445, 101, 101, 406, 132, 399, -191, 143, -191, 408,
+ 392, 390, -191, -191, -191, 269, 269, 269, 269, -191,
+ 411, 269, 269, 205, 425, -191, 144, 418, 159, 419,
+ -191, -191, 420, 417, 421, 427, 409, 143, -191, 148,
+ -191, -191, -191, 399, -191, -191, -191, -191, 205, -191,
+ -191, 426, -191, 428, 269, -191, -191, 414, 437, -191,
+ 441, -191, -191, -191, 507, -191, 507, 415, -191, -191,
+ -191, -191, 269, 269, -191, 25, 269, -191, -191, 412,
+ 444, -191, -191, -191, 455, 446, -191, 507, -191, 159,
+ -191, -191, 453, -191
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const short int yypgoto[] =
+{
+ -191, 9, -191, 314, -191, -191, -2, -191, -191, 301,
+ -191, -191, -191, -8, 238, -191, 243, -33, -191, 77,
+ 473, -91, -191, -72, -111, -191, 155, -191, -9, -123,
+ 1, 274, -191, 41, -190, 277, -97, -124, -78, -191,
+ 22, 121, -191, 134, 6, -191, -41, 335, -191, -191,
+ -191, 348, 5
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -177
+static const short int yytable[] =
+{
+ 39, 40, 43, 43, 101, 43, 218, 96, 35, 34,
+ 43, 43, 46, 36, 154, 222, 188, 115, 48, 198,
+ 220, 76, 6, 79, 114, 77, 202, 6, -3, 89,
+ 90, 6, 45, 97, 98, 70, 99, 103, 55, 43,
+ 58, 105, 106, 84, 301, 6, 231, -3, 85, 99,
+ 52, 44, 74, 44, 50, 138, 53, 148, 139, 57,
+ 59, -3, 72, 43, 43, 129, 232, 1, 224, 58,
+ 281, 269, 37, 125, 56, 144, 364, -137, 262, 71,
+ 78, 100, 78, 78, 150, 270, 1, 6, 44, 195,
+ 4, 41, 42, 77, -3, 74, 43, 6, 284, 5,
+ 265, 72, -176, 104, 276, 206, 282, 6, 208, 185,
+ 195, 37, 123, 337, 196, 201, 203, -176, 37, 1,
+ 74, 38, 215, 219, 206, 207, 6, 208, 209, 199,
+ 43, 285, 210, 268, 20, 130, 37, 21, 351, 131,
+ 255, 22, 23, 24, 25, 184, 200, 323, 200, 235,
+ 236, 210, 6, 213, 154, 84, 239, 319, 274, 241,
+ 85, 73, 263, 349, 200, 6, 211, 212, 149, 237,
+ 51, 74, 213, 264, 43, 75, 258, 43, 43, 123,
+ 200, 219, 309, 259, 260, 74, 240, 215, 219, 102,
+ 185, 185, 43, 310, 195, 91, 54, 43, 196, 92,
+ 93, 266, 296, 298, 44, 44, 125, 68, 91, 320,
+ 321, 6, 92, 43, 69, 41, 42, 132, 133, 83,
+ 358, 88, 43, 256, 150, 150, 184, 184, 11, 72,
+ 300, 91, 134, 234, 60, 92, 95, 61, 165, 166,
+ 107, 123, 108, 62, 63, 111, 326, 135, 136, 307,
+ 247, 248, 249, 112, 251, 252, 253, 254, 20, 84,
+ 43, 21, 123, 273, 85, 22, 23, 24, 25, 318,
+ 113, 290, 43, 219, 219, 6, 348, 91, 116, 157,
+ 158, 92, 295, 159, 117, 118, 128, 160, 161, 74,
+ 162, 10, 11, 163, 164, 43, 165, 166, 167, 119,
+ 340, 120, 140, -145, 181, 141, 289, 143, 145, 313,
+ 15, 91, 168, 138, 299, 92, 297, 18, 19, 155,
+ 43, 123, 20, 186, 187, 21, 189, 169, 170, 22,
+ 23, 24, 25, 190, 191, 193, 215, 194, 215, 195,
+ 64, 204, 205, 65, 290, 221, 223, 365, 6, 66,
+ 67, 7, 8, 9, 226, 233, 230, 227, 242, 215,
+ 243, 372, 244, 246, 10, 11, 12, 250, 257, 290,
+ 261, 13, 330, 331, 332, 333, 267, 271, 335, 336,
+ 14, 272, 277, 15, 16, 17, 279, 280, 283, 286,
+ 18, 19, 6, 287, 288, 20, 41, 42, 21, 130,
+ 294, 302, 22, 23, 24, 25, 303, 305, 10, 11,
+ 6, 354, 304, 306, 41, 42, 139, 308, 311, 312,
+ 314, 315, 324, 322, 328, 327, 329, 11, 334, 362,
+ 363, 338, 344, 366, 47, 339, 341, 342, 345, 20,
+ 346, 347, 21, 352, 367, 353, 22, 23, 24, 25,
+ 355, 6, 182, 19, 356, 41, 42, 20, 357, 368,
+ 21, 369, 229, 370, 22, 23, 24, 25, 11, 6,
+ 373, 293, 245, 41, 49, 292, 28, 275, 350, 278,
+ 6, 361, 228, 0, 238, 42, 11, 0, 371, 225,
+ 121, 0, 0, 0, 0, 0, 0, 11, 20, 0,
+ 0, 21, 0, 0, 0, 22, 23, 24, 25, 0,
+ 0, 206, 207, 6, 208, 209, 20, 0, 0, 21,
+ 0, 0, 0, 22, 23, 24, 25, 20, 0, 0,
+ 21, 0, 0, 0, 22, 23, 24, 25, 210, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 211, 212, 0, 0, 0, 0, 213
+};
+
+static const short int yycheck[] =
+{
+ 8, 9, 10, 11, 45, 13, 130, 40, 3, 3,
+ 18, 19, 11, 4, 92, 138, 107, 58, 12, 116,
+ 131, 30, 6, 31, 6, 6, 123, 6, 0, 37,
+ 38, 6, 10, 41, 42, 26, 44, 46, 6, 47,
+ 18, 49, 50, 12, 17, 6, 12, 0, 17, 57,
+ 6, 10, 33, 12, 13, 13, 12, 90, 16, 18,
+ 19, 14, 35, 71, 72, 74, 32, 39, 6, 47,
+ 30, 195, 51, 72, 42, 83, 51, 17, 189, 13,
+ 64, 50, 64, 64, 92, 196, 39, 6, 47, 50,
+ 12, 10, 11, 6, 14, 33, 104, 6, 221, 0,
+ 191, 35, 17, 12, 201, 4, 66, 6, 7, 104,
+ 50, 51, 71, 303, 54, 123, 125, 32, 51, 39,
+ 33, 6, 130, 131, 4, 5, 6, 7, 8, 15,
+ 138, 15, 31, 13, 53, 50, 51, 56, 328, 54,
+ 181, 60, 61, 62, 63, 104, 32, 15, 32, 157,
+ 158, 31, 6, 52, 232, 12, 164, 280, 199, 167,
+ 17, 23, 6, 15, 32, 6, 46, 47, 22, 163,
+ 17, 33, 52, 17, 182, 37, 184, 185, 186, 138,
+ 32, 189, 6, 185, 186, 33, 164, 195, 196, 37,
+ 185, 186, 200, 17, 50, 12, 6, 205, 54, 16,
+ 17, 192, 235, 236, 163, 164, 205, 53, 12, 281,
+ 282, 6, 16, 221, 53, 10, 11, 35, 36, 34,
+ 344, 14, 230, 182, 232, 233, 185, 186, 23, 35,
+ 238, 12, 50, 156, 53, 16, 17, 56, 27, 28,
+ 12, 200, 6, 62, 63, 12, 287, 65, 66, 257,
+ 173, 174, 175, 51, 177, 178, 179, 180, 53, 12,
+ 268, 56, 221, 16, 17, 60, 61, 62, 63, 277,
+ 6, 230, 280, 281, 282, 6, 317, 12, 6, 10,
+ 11, 16, 17, 14, 53, 53, 37, 18, 19, 33,
+ 21, 22, 23, 24, 25, 303, 27, 28, 29, 53,
+ 308, 53, 6, 34, 52, 32, 229, 17, 17, 268,
+ 41, 12, 43, 13, 237, 16, 17, 48, 49, 57,
+ 328, 280, 53, 12, 17, 56, 50, 58, 59, 60,
+ 61, 62, 63, 14, 32, 6, 344, 17, 346, 50,
+ 53, 36, 32, 56, 303, 13, 7, 355, 6, 62,
+ 63, 9, 10, 11, 13, 18, 35, 14, 6, 367,
+ 16, 369, 16, 16, 22, 23, 24, 17, 14, 328,
+ 14, 29, 295, 296, 297, 298, 17, 17, 301, 302,
+ 38, 17, 51, 41, 42, 43, 7, 13, 55, 17,
+ 48, 49, 6, 15, 17, 53, 10, 11, 56, 50,
+ 17, 17, 60, 61, 62, 63, 35, 16, 22, 23,
+ 6, 334, 51, 6, 10, 11, 16, 14, 17, 14,
+ 55, 6, 23, 17, 32, 17, 36, 23, 17, 352,
+ 353, 6, 15, 356, 48, 17, 17, 17, 17, 53,
+ 13, 32, 56, 17, 32, 17, 60, 61, 62, 63,
+ 36, 6, 48, 49, 17, 10, 11, 53, 17, 15,
+ 56, 6, 148, 17, 60, 61, 62, 63, 23, 6,
+ 17, 233, 171, 10, 11, 232, 3, 200, 323, 205,
+ 6, 347, 147, -1, 10, 11, 23, -1, 367, 141,
+ 45, -1, -1, -1, -1, -1, -1, 23, 53, -1,
+ -1, 56, -1, -1, -1, 60, 61, 62, 63, -1,
+ -1, 4, 5, 6, 7, 8, 53, -1, -1, 56,
+ -1, -1, -1, 60, 61, 62, 63, 53, -1, -1,
+ 56, -1, -1, -1, 60, 61, 62, 63, 31, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 46, 47, -1, -1, -1, -1, 52
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const unsigned char yystos[] =
+{
+ 0, 39, 68, 69, 12, 0, 6, 9, 10, 11,
+ 22, 23, 24, 29, 38, 41, 42, 43, 48, 49,
+ 53, 56, 60, 61, 62, 63, 71, 80, 87, 94,
+ 97, 100, 105, 107, 111, 119, 68, 51, 6, 80,
+ 80, 10, 11, 80, 100, 107, 97, 48, 111, 11,
+ 100, 17, 6, 12, 6, 6, 42, 100, 107, 100,
+ 53, 56, 62, 63, 53, 56, 62, 63, 53, 53,
+ 68, 13, 35, 23, 33, 37, 95, 6, 64, 80,
+ 95, 117, 118, 34, 12, 17, 112, 113, 14, 80,
+ 80, 12, 16, 17, 84, 17, 84, 80, 80, 80,
+ 50, 113, 37, 95, 12, 80, 80, 12, 6, 88,
+ 89, 12, 51, 6, 6, 113, 6, 53, 53, 53,
+ 53, 45, 96, 100, 102, 97, 98, 99, 37, 95,
+ 50, 54, 35, 36, 50, 65, 66, 106, 13, 16,
+ 6, 32, 116, 17, 80, 17, 114, 115, 84, 22,
+ 80, 81, 82, 83, 105, 57, 70, 10, 11, 14,
+ 18, 19, 21, 24, 25, 27, 28, 29, 43, 58,
+ 59, 75, 76, 77, 78, 79, 86, 87, 92, 111,
+ 119, 52, 48, 73, 100, 119, 12, 17, 88, 50,
+ 14, 32, 72, 6, 17, 50, 54, 103, 103, 15,
+ 32, 80, 103, 95, 36, 32, 4, 5, 7, 8,
+ 31, 46, 47, 52, 74, 80, 90, 91, 104, 80,
+ 91, 13, 96, 7, 6, 118, 13, 14, 114, 70,
+ 35, 12, 32, 18, 86, 80, 80, 111, 10, 80,
+ 107, 80, 6, 16, 16, 76, 16, 86, 86, 86,
+ 17, 86, 86, 86, 86, 113, 100, 14, 80, 73,
+ 73, 14, 91, 6, 17, 88, 68, 17, 13, 104,
+ 91, 17, 17, 16, 113, 102, 103, 51, 98, 7,
+ 13, 30, 66, 55, 96, 15, 17, 15, 17, 86,
+ 100, 101, 83, 81, 17, 17, 84, 17, 84, 86,
+ 80, 17, 17, 35, 51, 16, 6, 80, 14, 6,
+ 17, 17, 14, 100, 55, 6, 109, 110, 80, 96,
+ 90, 90, 17, 15, 23, 93, 113, 17, 32, 36,
+ 86, 86, 86, 86, 17, 86, 86, 101, 6, 17,
+ 80, 17, 17, 85, 15, 17, 13, 32, 113, 15,
+ 93, 101, 17, 17, 86, 36, 17, 17, 104, 104,
+ 108, 110, 86, 86, 51, 80, 86, 32, 15, 6,
+ 17, 108, 80, 17
+};
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror ("syntax error: cannot back up");\
+ YYERROR; \
+ } \
+while (0)
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+ are run). */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ ((Current).first_line = (Rhs)[1].first_line, \
+ (Current).first_column = (Rhs)[1].first_column, \
+ (Current).last_line = (Rhs)[N].last_line, \
+ (Current).last_column = (Rhs)[N].last_column)
+#endif
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (0)
+
+# define YYDSYMPRINT(Args) \
+do { \
+ if (yydebug) \
+ yysymprint Args; \
+} while (0)
+
+# define YYDSYMPRINTF(Title, Token, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yysymprint (stderr, \
+ Token, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (0)
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_stack_print (short int *bottom, short int *top)
+#else
+static void
+yy_stack_print (bottom, top)
+ short int *bottom;
+ short int *top;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (/* Nothing. */; bottom <= top; ++bottom)
+ YYFPRINTF (stderr, " %d", *bottom);
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_reduce_print (int yyrule)
+#else
+static void
+yy_reduce_print (yyrule)
+ int yyrule;
+#endif
+{
+ int yyi;
+ unsigned int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
+ yyrule - 1, yylno);
+ /* Print the symbols being reduced, and their result. */
+ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
+ YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
+ YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (Rule); \
+} while (0)
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YYDSYMPRINT(Args)
+# define YYDSYMPRINTF(Title, Token, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0
+# undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined (__GLIBC__) && defined (_STRING_H)
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+static YYSIZE_T
+# if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+# else
+yystrlen (yystr)
+ const char *yystr;
+# endif
+{
+ register const char *yys = yystr;
+
+ while (*yys++ != '\0')
+ continue;
+
+ return yys - yystr - 1;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+static char *
+# if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+# else
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+# endif
+{
+ register char *yyd = yydest;
+ register const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+#endif /* !YYERROR_VERBOSE */
+
+
+
+#if YYDEBUG
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yysymprint (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ /* Pacify ``unused variable'' warnings. */
+ (void) yyvaluep;
+
+ if (yytype < YYNTOKENS)
+ {
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+# ifdef YYPRINT
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+ }
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+ YYFPRINTF (yyoutput, ")");
+}
+
+#endif /* ! YYDEBUG */
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yydestruct (int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yytype, yyvaluep)
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ /* Pacify ``unused variable'' warnings. */
+ (void) yyvaluep;
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes. */
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM);
+# else
+int yyparse ();
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* The lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM)
+# else
+int yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+
+ register int yystate;
+ register int yyn;
+ int yyresult;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken = 0;
+
+ /* Three stacks and their tools:
+ `yyss': related to states,
+ `yyvs': related to semantic values,
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ short int yyssa[YYINITDEPTH];
+ short int *yyss = yyssa;
+ register short int *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ register YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK (yyvsp--, yyssp--)
+
+ YYSIZE_T yystacksize = YYINITDEPTH;
+
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+
+ /* When reducing, the number of symbols on the RHS of the reduced
+ rule. */
+ int yylen;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks.
+ */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ short int *yyss1 = yyss;
+
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow ("parser stack overflow",
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyoverflowlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyoverflowlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ short int *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyoverflowlab;
+ YYSTACK_RELOCATE (yyss);
+ YYSTACK_RELOCATE (yyvs);
+
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+/* Do appropriate processing given the current state. */
+/* Read a lookahead token if we need one and don't already have one. */
+/* yyresume: */
+
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+ YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2:
+#line 165 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 4:
+#line 172 "yacc.yy"
+ {
+ printf("<INCLUDE>%s</INCLUDE>\n", yyvsp[0]._str->latin1() );
+ ;}
+ break;
+
+ case 5:
+#line 176 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 6:
+#line 179 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 7:
+#line 184 "yacc.yy"
+ { yyval._int = 1; ;}
+ break;
+
+ case 8:
+#line 185 "yacc.yy"
+ { yyval._int = 0; ;}
+ break;
+
+ case 9:
+#line 190 "yacc.yy"
+ {
+ if (yyvsp[-2]._int)
+ printf("<CLASS>\n <NAME>%s</NAME>\n%s%s</CLASS>\n", ( in_namespace + *yyvsp[-4]._str ).latin1(), yyvsp[-3]._str->latin1(), yyvsp[-1]._str->latin1() );
+ // default C++ visibility specifier is 'private'
+ dcop_area = 0;
+ dcop_signal_area = 0;
+
+ ;}
+ break;
+
+ case 10:
+#line 199 "yacc.yy"
+ {
+ if (yyvsp[-2]._int)
+ printf("<CLASS>\n <NAME>%s</NAME>\n <LINK_SCOPE>%s</LINK_SCOPE>\n%s%s</CLASS>\n", ( in_namespace + *yyvsp[-4]._str ).latin1(),yyvsp[-5]._str->latin1(), yyvsp[-3]._str->latin1(), yyvsp[-1]._str->latin1() );
+ // default C++ visibility specifier is 'private'
+ dcop_area = 0;
+ dcop_signal_area = 0;
+
+ ;}
+ break;
+
+ case 11:
+#line 208 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 12:
+#line 211 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 13:
+#line 214 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 14:
+#line 217 "yacc.yy"
+ {
+ in_namespace += *yyvsp[-1]._str; in_namespace += "::";
+ ;}
+ break;
+
+ case 15:
+#line 221 "yacc.yy"
+ {
+ int pos = in_namespace.findRev( "::", -3 );
+ if( pos >= 0 )
+ in_namespace = in_namespace.left( pos + 2 );
+ else
+ in_namespace = "";
+ ;}
+ break;
+
+ case 16:
+#line 229 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 17:
+#line 232 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 18:
+#line 235 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 19:
+#line 238 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 20:
+#line 241 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 21:
+#line 244 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 22:
+#line 247 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 23:
+#line 250 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 24:
+#line 253 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 25:
+#line 256 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 36:
+#line 273 "yacc.yy"
+ {
+ dcop_area = 0;
+ dcop_signal_area = 0;
+ ;}
+ break;
+
+ case 37:
+#line 278 "yacc.yy"
+ {
+ dcop_area = 0;
+ dcop_signal_area = 0;
+ ;}
+ break;
+
+ case 38:
+#line 286 "yacc.yy"
+ {
+ dcop_area = 1;
+ dcop_signal_area = 0;
+ ;}
+ break;
+
+ case 39:
+#line 294 "yacc.yy"
+ {
+ /*
+ A dcop signals area needs all dcop area capabilities,
+ e.g. parsing of function parameters.
+ */
+ dcop_area = 1;
+ dcop_signal_area = 1;
+ ;}
+ break;
+
+ case 40:
+#line 305 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 41:
+#line 308 "yacc.yy"
+ {
+ QString* tmp = new QString( "%1::%2" );
+ *tmp = tmp->arg(*(yyvsp[-2]._str)).arg(*(yyvsp[0]._str));
+ yyval._str = tmp;
+ ;}
+ break;
+
+ case 42:
+#line 317 "yacc.yy"
+ {
+ QString* tmp = new QString( " <SUPER>%1</SUPER>\n" );
+ *tmp = tmp->arg( *(yyvsp[0]._str) );
+ yyval._str = tmp;
+ ;}
+ break;
+
+ case 43:
+#line 323 "yacc.yy"
+ {
+ QString* tmp = new QString( " <SUPER>%1</SUPER>\n" );
+ *tmp = tmp->arg( *(yyvsp[-3]._str) + "&lt;" + *(yyvsp[-1]._str) + "&gt;" );
+ yyval._str = tmp;
+ ;}
+ break;
+
+ case 44:
+#line 332 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 45:
+#line 336 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 46:
+#line 343 "yacc.yy"
+ {
+ yyval._str = yyvsp[-1]._str;
+ ;}
+ break;
+
+ case 47:
+#line 347 "yacc.yy"
+ {
+ /* $$ = $1; */
+ yyval._str = new QString( *(yyvsp[-2]._str) + *(yyvsp[0]._str) );
+ ;}
+ break;
+
+ case 48:
+#line 355 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 49:
+#line 359 "yacc.yy"
+ {
+ yyval._str = new QString( "" );
+ ;}
+ break;
+
+ case 50:
+#line 366 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 52:
+#line 373 "yacc.yy"
+ {
+ yyval._str = new QString( "" );
+ ;}
+ break;
+
+ case 53:
+#line 377 "yacc.yy"
+ {
+ yyval._str = new QString( *(yyvsp[-1]._str) + *(yyvsp[0]._str) );
+ ;}
+ break;
+
+ case 54:
+#line 381 "yacc.yy"
+ {
+ yyval._str = new QString( *(yyvsp[-1]._str) + *(yyvsp[0]._str) );
+ ;}
+ break;
+
+ case 55:
+#line 385 "yacc.yy"
+ {
+ yyval._str = new QString( *(yyvsp[-1]._str) + *(yyvsp[0]._str) );
+ ;}
+ break;
+
+ case 56:
+#line 389 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 57:
+#line 393 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 58:
+#line 397 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 59:
+#line 401 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 60:
+#line 405 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 61:
+#line 409 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 62:
+#line 413 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 63:
+#line 417 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 64:
+#line 421 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 65:
+#line 425 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 66:
+#line 429 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 67:
+#line 433 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 68:
+#line 437 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 75:
+#line 455 "yacc.yy"
+ {;}
+ break;
+
+ case 76:
+#line 456 "yacc.yy"
+ {;}
+ break;
+
+ case 77:
+#line 460 "yacc.yy"
+ {;}
+ break;
+
+ case 78:
+#line 461 "yacc.yy"
+ {;}
+ break;
+
+ case 79:
+#line 462 "yacc.yy"
+ {;}
+ break;
+
+ case 80:
+#line 463 "yacc.yy"
+ {;}
+ break;
+
+ case 81:
+#line 464 "yacc.yy"
+ {;}
+ break;
+
+ case 82:
+#line 468 "yacc.yy"
+ {;}
+ break;
+
+ case 83:
+#line 469 "yacc.yy"
+ {;}
+ break;
+
+ case 84:
+#line 470 "yacc.yy"
+ {;}
+ break;
+
+ case 85:
+#line 475 "yacc.yy"
+ {
+ if (dcop_area) {
+ QString* tmp = new QString("<TYPEDEF name=\"%1\" template=\"%2\"><PARAM %3</TYPEDEF>\n");
+ *tmp = tmp->arg( *(yyvsp[-1]._str) ).arg( *(yyvsp[-5]._str) ).arg( *(yyvsp[-3]._str) );
+ yyval._str = tmp;
+ } else {
+ yyval._str = new QString("");
+ }
+ ;}
+ break;
+
+ case 86:
+#line 485 "yacc.yy"
+ {
+ if (dcop_area)
+ yyerror("scoped template typedefs are not supported in dcop areas!");
+ ;}
+ break;
+
+ case 87:
+#line 493 "yacc.yy"
+ {
+ yyval._int = 0;
+ ;}
+ break;
+
+ case 88:
+#line 497 "yacc.yy"
+ {
+ yyval._int = 1;
+ ;}
+ break;
+
+ case 89:
+#line 503 "yacc.yy"
+ { yyval._str = new QString("signed int"); ;}
+ break;
+
+ case 90:
+#line 504 "yacc.yy"
+ { yyval._str = new QString("signed int"); ;}
+ break;
+
+ case 91:
+#line 505 "yacc.yy"
+ { yyval._str = new QString("unsigned int"); ;}
+ break;
+
+ case 92:
+#line 506 "yacc.yy"
+ { yyval._str = new QString("unsigned int"); ;}
+ break;
+
+ case 93:
+#line 507 "yacc.yy"
+ { yyval._str = new QString("signed short int"); ;}
+ break;
+
+ case 94:
+#line 508 "yacc.yy"
+ { yyval._str = new QString("signed short int"); ;}
+ break;
+
+ case 95:
+#line 509 "yacc.yy"
+ { yyval._str = new QString("signed long int"); ;}
+ break;
+
+ case 96:
+#line 510 "yacc.yy"
+ { yyval._str = new QString("signed long int"); ;}
+ break;
+
+ case 97:
+#line 511 "yacc.yy"
+ { yyval._str = new QString("unsigned short int"); ;}
+ break;
+
+ case 98:
+#line 512 "yacc.yy"
+ { yyval._str = new QString("unsigned short int"); ;}
+ break;
+
+ case 99:
+#line 513 "yacc.yy"
+ { yyval._str = new QString("unsigned long int"); ;}
+ break;
+
+ case 100:
+#line 514 "yacc.yy"
+ { yyval._str = new QString("unsigned long int"); ;}
+ break;
+
+ case 101:
+#line 515 "yacc.yy"
+ { yyval._str = new QString("int"); ;}
+ break;
+
+ case 102:
+#line 516 "yacc.yy"
+ { yyval._str = new QString("long int"); ;}
+ break;
+
+ case 103:
+#line 517 "yacc.yy"
+ { yyval._str = new QString("long int"); ;}
+ break;
+
+ case 104:
+#line 518 "yacc.yy"
+ { yyval._str = new QString("short int"); ;}
+ break;
+
+ case 105:
+#line 519 "yacc.yy"
+ { yyval._str = new QString("short int"); ;}
+ break;
+
+ case 106:
+#line 520 "yacc.yy"
+ { yyval._str = new QString("char"); ;}
+ break;
+
+ case 107:
+#line 521 "yacc.yy"
+ { yyval._str = new QString("signed char"); ;}
+ break;
+
+ case 108:
+#line 522 "yacc.yy"
+ { yyval._str = new QString("unsigned char"); ;}
+ break;
+
+ case 111:
+#line 532 "yacc.yy"
+ {
+ yyval._str = new QString( "" );
+ ;}
+ break;
+
+ case 113:
+#line 537 "yacc.yy"
+ {
+ yyval._str = new QString( *(yyvsp[-2]._str) + *(yyvsp[0]._str) );
+ ;}
+ break;
+
+ case 115:
+#line 545 "yacc.yy"
+ { yyval._str = yyvsp[0]._str; ;}
+ break;
+
+ case 116:
+#line 546 "yacc.yy"
+ { yyval._str = yyvsp[0]._str; ;}
+ break;
+
+ case 117:
+#line 547 "yacc.yy"
+ { yyval._str = yyvsp[0]._str; ;}
+ break;
+
+ case 118:
+#line 548 "yacc.yy"
+ {
+ QString *tmp = new QString("%1&lt;%2&gt;");
+ *tmp = tmp->arg(*(yyvsp[-3]._str));
+ *tmp = tmp->arg(*(yyvsp[-1]._str));
+ yyval._str = tmp;
+ ;}
+ break;
+
+ case 119:
+#line 554 "yacc.yy"
+ {
+ QString *tmp = new QString("%1&lt;%2&gt;::%3");
+ *tmp = tmp->arg(*(yyvsp[-5]._str));
+ *tmp = tmp->arg(*(yyvsp[-3]._str));
+ *tmp = tmp->arg(*(yyvsp[0]._str));
+ yyval._str = tmp;
+ ;}
+ break;
+
+ case 120:
+#line 566 "yacc.yy"
+ {
+ yyval._str = new QString(*(yyvsp[-2]._str) + "," + *(yyvsp[0]._str));
+ ;}
+ break;
+
+ case 121:
+#line 570 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 122:
+#line 578 "yacc.yy"
+ {
+ if (dcop_area)
+ yyerror("in dcop areas are no pointers allowed");
+ ;}
+ break;
+
+ case 123:
+#line 583 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 124:
+#line 592 "yacc.yy"
+ {
+ if (dcop_area)
+ yyerror("in dcop areas are no pointers allowed");
+ ;}
+ break;
+
+ case 125:
+#line 596 "yacc.yy"
+ {
+ if (dcop_area) {
+ QString* tmp = new QString("<TYPE qleft=\"const\" qright=\"" AMP_ENTITY "\">%1</TYPE>");
+ *tmp = tmp->arg( *(yyvsp[-1]._str) );
+ yyval._str = tmp;
+ }
+ ;}
+ break;
+
+ case 126:
+#line 603 "yacc.yy"
+ {
+ QString* tmp = new QString("<TYPE>%1</TYPE>");
+ *tmp = tmp->arg( *(yyvsp[0]._str) );
+ yyval._str = tmp;
+ ;}
+ break;
+
+ case 127:
+#line 608 "yacc.yy"
+ {
+ QString* tmp = new QString("<TYPE>%1</TYPE>");
+ *tmp = tmp->arg( *(yyvsp[-1]._str) );
+ yyval._str = tmp;
+ ;}
+ break;
+
+ case 128:
+#line 613 "yacc.yy"
+ {
+ if (dcop_area) {
+ QString* tmp = new QString("<TYPE qleft=\"const\" qright=\"" AMP_ENTITY "\">%1</TYPE>");
+ *tmp = tmp->arg( *(yyvsp[-2]._str) );
+ yyval._str = tmp;
+ }
+ ;}
+ break;
+
+ case 129:
+#line 620 "yacc.yy"
+ {
+ if (dcop_area)
+ yyerror("in dcop areas are only const references allowed!");
+ ;}
+ break;
+
+ case 130:
+#line 625 "yacc.yy"
+ {
+ QString* tmp = new QString("<TYPE>%1</TYPE>");
+ *tmp = tmp->arg( *(yyvsp[0]._str) );
+ yyval._str = tmp;
+ ;}
+ break;
+
+ case 131:
+#line 631 "yacc.yy"
+ {
+ if (dcop_area)
+ yyerror("in dcop areas are no pointers allowed");
+ ;}
+ break;
+
+ case 132:
+#line 639 "yacc.yy"
+ {
+ yyval._str = new QString(*(yyvsp[-2]._str) + "," + *(yyvsp[0]._str));
+ ;}
+ break;
+
+ case 133:
+#line 643 "yacc.yy"
+ {
+ yyval._str = yyvsp[0]._str;
+ ;}
+ break;
+
+ case 134:
+#line 650 "yacc.yy"
+ {
+ if (dcop_area) {
+ QString* tmp = new QString("\n <ARG>%1<NAME>%2</NAME></ARG>");
+ *tmp = tmp->arg( *(yyvsp[-2]._str) );
+ *tmp = tmp->arg( *(yyvsp[-1]._str) );
+ yyval._str = tmp;
+ } else yyval._str = new QString();
+ ;}
+ break;
+
+ case 135:
+#line 659 "yacc.yy"
+ {
+ if (dcop_area) {
+ QString* tmp = new QString("\n <ARG>%1</ARG>");
+ *tmp = tmp->arg( *(yyvsp[-1]._str) );
+ yyval._str = tmp;
+ } else yyval._str = new QString();
+ ;}
+ break;
+
+ case 136:
+#line 667 "yacc.yy"
+ {
+ if (dcop_area)
+ yyerror("variable arguments not supported in dcop area.");
+ yyval._str = new QString("");
+ ;}
+ break;
+
+ case 137:
+#line 676 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 138:
+#line 679 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 139:
+#line 682 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 140:
+#line 689 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 141:
+#line 692 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 142:
+#line 695 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 143:
+#line 698 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 144:
+#line 701 "yacc.yy"
+ {
+ ;}
+ break;
+
+ case 145:
+#line 706 "yacc.yy"
+ { yyval._int = 0; ;}
+ break;
+
+ case 146:
+#line 707 "yacc.yy"
+ { yyval._int = 1; ;}
+ break;
+
+ case 152:
+#line 716 "yacc.yy"
+ {
+ if (dcop_area || dcop_signal_area) {
+ QString* tmp = 0;
+ tmp = new QString(
+ " <%4>\n"
+ " %2\n"
+ " <NAME>%1</NAME>"
+ "%3\n"
+ " </%5>\n");
+ *tmp = tmp->arg( *(yyvsp[-4]._str) );
+ *tmp = tmp->arg( *(yyvsp[-5]._str) );
+ *tmp = tmp->arg( *(yyvsp[-2]._str) );
+
+ QString tagname = (dcop_signal_area) ? "SIGNAL" : "FUNC";
+ QString attr = (yyvsp[0]._int) ? " qual=\"const\"" : "";
+ *tmp = tmp->arg( QString("%1%2").arg(tagname).arg(attr) );
+ *tmp = tmp->arg( QString("%1").arg(tagname) );
+ yyval._str = tmp;
+ } else
+ yyval._str = new QString("");
+ ;}
+ break;
+
+ case 153:
+#line 738 "yacc.yy"
+ {
+ if (dcop_area)
+ yyerror("operators aren't allowed in dcop areas!");
+ yyval._str = new QString("");
+ ;}
+ break;
+
+ case 154:
+#line 748 "yacc.yy"
+ {;}
+ break;
+
+ case 155:
+#line 749 "yacc.yy"
+ {;}
+ break;
+
+ case 156:
+#line 750 "yacc.yy"
+ {;}
+ break;
+
+ case 157:
+#line 755 "yacc.yy"
+ {;}
+ break;
+
+ case 158:
+#line 760 "yacc.yy"
+ {;}
+ break;
+
+ case 159:
+#line 761 "yacc.yy"
+ {;}
+ break;
+
+ case 160:
+#line 766 "yacc.yy"
+ {
+ yyval._str = yyvsp[-1]._str;
+ ;}
+ break;
+
+ case 161:
+#line 770 "yacc.yy"
+ {
+ yyval._str = yyvsp[-3]._str;
+ ;}
+ break;
+
+ case 162:
+#line 774 "yacc.yy"
+ {
+ yyval._str = yyvsp[-1]._str;
+ ;}
+ break;
+
+ case 163:
+#line 778 "yacc.yy"
+ {
+ /* The constructor */
+ assert(!dcop_area);
+ yyval._str = new QString("");
+ ;}
+ break;
+
+ case 164:
+#line 784 "yacc.yy"
+ {
+ /* The constructor */
+ assert(!dcop_area);
+ yyval._str = new QString("");
+ ;}
+ break;
+
+ case 165:
+#line 790 "yacc.yy"
+ {
+ /* The destructor */
+ assert(!dcop_area);
+ yyval._str = new QString("");
+ ;}
+ break;
+
+ case 166:
+#line 796 "yacc.yy"
+ {
+ if (dcop_area) {
+ if (dcop_signal_area)
+ yyerror("DCOP signals cannot be static");
+ else
+ yyerror("DCOP functions cannot be static");
+ } else {
+ yyval._str = new QString();
+ }
+ ;}
+ break;
+
+ case 167:
+#line 809 "yacc.yy"
+ {
+ function_mode = 1;
+ ;}
+ break;
+
+ case 171:
+#line 821 "yacc.yy"
+ {;}
+ break;
+
+ case 172:
+#line 822 "yacc.yy"
+ {;}
+ break;
+
+ case 176:
+#line 834 "yacc.yy"
+ {;}
+ break;
+
+ case 177:
+#line 835 "yacc.yy"
+ {;}
+ break;
+
+ case 178:
+#line 836 "yacc.yy"
+ {;}
+ break;
+
+ case 179:
+#line 839 "yacc.yy"
+ {;}
+ break;
+
+ case 180:
+#line 843 "yacc.yy"
+ {;}
+ break;
+
+ case 181:
+#line 844 "yacc.yy"
+ {;}
+ break;
+
+ case 182:
+#line 845 "yacc.yy"
+ {;}
+ break;
+
+ case 183:
+#line 846 "yacc.yy"
+ {;}
+ break;
+
+ case 184:
+#line 847 "yacc.yy"
+ {;}
+ break;
+
+ case 185:
+#line 848 "yacc.yy"
+ {;}
+ break;
+
+
+ }
+
+/* Line 1010 of yacc.c. */
+#line 2591 "yacc.cc"
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+
+
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+ if (YYPACT_NINF < yyn && yyn < YYLAST)
+ {
+ YYSIZE_T yysize = 0;
+ int yytype = YYTRANSLATE (yychar);
+ const char* yyprefix;
+ char *yymsg;
+ int yyx;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 0;
+
+ yyprefix = ", expecting ";
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
+ yycount += 1;
+ if (yycount == 5)
+ {
+ yysize = 0;
+ break;
+ }
+ }
+ yysize += (sizeof ("syntax error, unexpected ")
+ + yystrlen (yytname[yytype]));
+ yymsg = (char *) YYSTACK_ALLOC (yysize);
+ if (yymsg != 0)
+ {
+ char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
+ yyp = yystpcpy (yyp, yytname[yytype]);
+
+ if (yycount < 5)
+ {
+ yyprefix = ", expecting ";
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ yyp = yystpcpy (yyp, yyprefix);
+ yyp = yystpcpy (yyp, yytname[yyx]);
+ yyprefix = " or ";
+ }
+ }
+ yyerror (yymsg);
+ YYSTACK_FREE (yymsg);
+ }
+ else
+ yyerror ("syntax error; also virtual memory exhausted");
+ }
+ else
+#endif /* YYERROR_VERBOSE */
+ yyerror ("syntax error");
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* If at end of input, pop the error token,
+ then the rest of the stack, then return failure. */
+ if (yychar == YYEOF)
+ for (;;)
+ {
+ YYPOPSTACK;
+ if (yyssp == yyss)
+ YYABORT;
+ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+ yydestruct (yystos[*yyssp], yyvsp);
+ }
+ }
+ else
+ {
+ YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
+ yydestruct (yytoken, &yylval);
+ yychar = YYEMPTY;
+
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+#ifdef __GNUC__
+ /* Pacify GCC when the user code never invokes YYERROR and the label
+ yyerrorlab therefore never appears in user code. */
+ if (0)
+ goto yyerrorlab;
+#endif
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+ yydestruct (yystos[yystate], yyvsp);
+ YYPOPSTACK;
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ YYDPRINTF ((stderr, "Shifting error token, "));
+
+ *++yyvsp = yylval;
+
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#ifndef yyoverflow
+/*----------------------------------------------.
+| yyoverflowlab -- parser overflow comes here. |
+`----------------------------------------------*/
+yyoverflowlab:
+ yyerror ("parser stack overflow");
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+ return yyresult;
+}
+
+
+#line 851 "yacc.yy"
+
+
+void dcopidlParse( const char *_code )
+{
+ dcopidlInitFlex( _code );
+ yyparse();
+}
+
+
diff --git a/dcop/dcopidl/yacc.cc.h b/dcop/dcopidl/yacc.cc.h
new file mode 100644
index 000000000..b056f2922
--- /dev/null
+++ b/dcop/dcopidl/yacc.cc.h
@@ -0,0 +1,184 @@
+/* A Bison parser, made by GNU Bison 1.875d. */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ T_UNIMPORTANT = 258,
+ T_CHARACTER_LITERAL = 259,
+ T_DOUBLE_LITERAL = 260,
+ T_IDENTIFIER = 261,
+ T_INTEGER_LITERAL = 262,
+ T_STRING_LITERAL = 263,
+ T_INCLUDE = 264,
+ T_CLASS = 265,
+ T_STRUCT = 266,
+ T_LEFT_CURLY_BRACKET = 267,
+ T_LEFT_PARANTHESIS = 268,
+ T_RIGHT_CURLY_BRACKET = 269,
+ T_RIGHT_PARANTHESIS = 270,
+ T_COLON = 271,
+ T_SEMICOLON = 272,
+ T_PUBLIC = 273,
+ T_PROTECTED = 274,
+ T_TRIPE_DOT = 275,
+ T_PRIVATE = 276,
+ T_VIRTUAL = 277,
+ T_CONST = 278,
+ T_INLINE = 279,
+ T_FRIEND = 280,
+ T_RETURN = 281,
+ T_SIGNAL = 282,
+ T_SLOT = 283,
+ T_TYPEDEF = 284,
+ T_PLUS = 285,
+ T_MINUS = 286,
+ T_COMMA = 287,
+ T_ASTERISK = 288,
+ T_TILDE = 289,
+ T_LESS = 290,
+ T_GREATER = 291,
+ T_AMPERSAND = 292,
+ T_EXTERN = 293,
+ T_EXTERN_C = 294,
+ T_ACCESS = 295,
+ T_ENUM = 296,
+ T_NAMESPACE = 297,
+ T_USING = 298,
+ T_UNKNOWN = 299,
+ T_TRIPLE_DOT = 300,
+ T_TRUE = 301,
+ T_FALSE = 302,
+ T_STATIC = 303,
+ T_MUTABLE = 304,
+ T_EQUAL = 305,
+ T_SCOPE = 306,
+ T_NULL = 307,
+ T_INT = 308,
+ T_ARRAY_OPEN = 309,
+ T_ARRAY_CLOSE = 310,
+ T_CHAR = 311,
+ T_DCOP = 312,
+ T_DCOP_AREA = 313,
+ T_DCOP_SIGNAL_AREA = 314,
+ T_SIGNED = 315,
+ T_UNSIGNED = 316,
+ T_LONG = 317,
+ T_SHORT = 318,
+ T_FUNOPERATOR = 319,
+ T_MISCOPERATOR = 320,
+ T_SHIFT = 321
+ };
+#endif
+#define T_UNIMPORTANT 258
+#define T_CHARACTER_LITERAL 259
+#define T_DOUBLE_LITERAL 260
+#define T_IDENTIFIER 261
+#define T_INTEGER_LITERAL 262
+#define T_STRING_LITERAL 263
+#define T_INCLUDE 264
+#define T_CLASS 265
+#define T_STRUCT 266
+#define T_LEFT_CURLY_BRACKET 267
+#define T_LEFT_PARANTHESIS 268
+#define T_RIGHT_CURLY_BRACKET 269
+#define T_RIGHT_PARANTHESIS 270
+#define T_COLON 271
+#define T_SEMICOLON 272
+#define T_PUBLIC 273
+#define T_PROTECTED 274
+#define T_TRIPE_DOT 275
+#define T_PRIVATE 276
+#define T_VIRTUAL 277
+#define T_CONST 278
+#define T_INLINE 279
+#define T_FRIEND 280
+#define T_RETURN 281
+#define T_SIGNAL 282
+#define T_SLOT 283
+#define T_TYPEDEF 284
+#define T_PLUS 285
+#define T_MINUS 286
+#define T_COMMA 287
+#define T_ASTERISK 288
+#define T_TILDE 289
+#define T_LESS 290
+#define T_GREATER 291
+#define T_AMPERSAND 292
+#define T_EXTERN 293
+#define T_EXTERN_C 294
+#define T_ACCESS 295
+#define T_ENUM 296
+#define T_NAMESPACE 297
+#define T_USING 298
+#define T_UNKNOWN 299
+#define T_TRIPLE_DOT 300
+#define T_TRUE 301
+#define T_FALSE 302
+#define T_STATIC 303
+#define T_MUTABLE 304
+#define T_EQUAL 305
+#define T_SCOPE 306
+#define T_NULL 307
+#define T_INT 308
+#define T_ARRAY_OPEN 309
+#define T_ARRAY_CLOSE 310
+#define T_CHAR 311
+#define T_DCOP 312
+#define T_DCOP_AREA 313
+#define T_DCOP_SIGNAL_AREA 314
+#define T_SIGNED 315
+#define T_UNSIGNED 316
+#define T_LONG 317
+#define T_SHORT 318
+#define T_FUNOPERATOR 319
+#define T_MISCOPERATOR 320
+#define T_SHIFT 321
+
+
+
+
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+#line 67 "yacc.yy"
+typedef union YYSTYPE {
+ long _int;
+ QString *_str;
+ unsigned short _char;
+ double _float;
+} YYSTYPE;
+/* Line 1285 of yacc.c. */
+#line 176 "yacc.hh"
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+extern YYSTYPE yylval;
+
+
+
diff --git a/dcop/dcopidl/yacc.yy b/dcop/dcopidl/yacc.yy
new file mode 100644
index 000000000..ca22c65e1
--- /dev/null
+++ b/dcop/dcopidl/yacc.yy
@@ -0,0 +1,857 @@
+%{
+/*****************************************************************
+Copyright (c) 1999 Torben Weis <weis@kde.org>
+Copyright (c) 2000 Matthias Ettrich <ettrich@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 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.
+
+******************************************************************/
+
+#include <config.h>
+
+// Workaround for a bison issue:
+// bison.simple concludes from _GNU_SOURCE that stpcpy is available,
+// while GNU string.h only exposes it if __USE_GNU is set.
+#ifdef _GNU_SOURCE
+#define __USE_GNU 1
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include <qstring.h>
+
+#define AMP_ENTITY "&amp;"
+#define YYERROR_VERBOSE
+
+extern int yylex();
+
+// extern QString idl_lexFile;
+extern int idl_line_no;
+extern int function_mode;
+
+static int dcop_area = 0;
+static int dcop_signal_area = 0;
+
+static QString in_namespace( "" );
+
+void dcopidlInitFlex( const char *_code );
+
+void yyerror( const char *s )
+{
+ qDebug( "In line %i : %s", idl_line_no, s );
+ exit(1);
+ // theParser->parse_error( idl_lexFile, s, idl_line_no );
+}
+
+%}
+
+
+%union
+{
+ long _int;
+ QString *_str;
+ unsigned short _char;
+ double _float;
+}
+
+%nonassoc T_UNIMPORTANT
+%token <_char> T_CHARACTER_LITERAL
+%token <_float> T_DOUBLE_LITERAL
+%right <_str> T_IDENTIFIER
+%token <_int> T_INTEGER_LITERAL
+%token <_str> T_STRING_LITERAL
+%token <_str> T_INCLUDE
+%token T_CLASS
+%token T_STRUCT
+%token T_LEFT_CURLY_BRACKET
+%token T_LEFT_PARANTHESIS
+%token T_RIGHT_CURLY_BRACKET
+%token T_RIGHT_PARANTHESIS
+%token T_COLON
+%token T_SEMICOLON
+%token T_PUBLIC
+%token T_PROTECTED
+%token T_TRIPE_DOT
+%token T_PRIVATE
+%token T_VIRTUAL
+%token T_CONST
+%token T_INLINE
+%token T_FRIEND
+%token T_RETURN
+%token T_SIGNAL
+%token T_SLOT
+%token T_TYPEDEF
+%token T_PLUS
+%token T_MINUS
+%token T_COMMA
+%right T_ASTERISK
+%token T_TILDE
+%token T_LESS
+%token T_GREATER
+%token T_AMPERSAND
+%token T_EXTERN
+%token T_EXTERN_C
+%token T_ACCESS
+%token T_ENUM
+%token T_NAMESPACE
+%token T_USING
+%token T_UNKNOWN
+%token T_TRIPLE_DOT
+%token T_TRUE
+%token T_FALSE
+%token T_STATIC
+%token T_MUTABLE
+%token T_EQUAL
+%token T_SCOPE
+%token T_NULL
+%token T_INT
+%token T_ARRAY_OPEN
+%token T_ARRAY_CLOSE
+%token T_CHAR
+%token T_DCOP
+%token T_DCOP_AREA
+%token T_DCOP_SIGNAL_AREA
+%token T_SIGNED
+%token T_UNSIGNED
+%token T_LONG
+%token T_SHORT
+%token T_FUNOPERATOR
+%token T_MISCOPERATOR
+%token T_SHIFT
+
+%type <_str> body
+%type <_str> class_header
+%type <_str> super_classes
+%type <_str> super_class
+%type <_str> super_class_name
+%type <_str> typedef
+%type <_str> function
+%type <_str> function_header
+%type <_str> param
+%type <_str> type
+%type <_str> type_name
+%type <_str> templ_type
+%type <_str> templ_type_list
+%type <_str> type_list
+%type <_str> params
+%type <_str> int_type
+%type <_int> const_qualifier
+%type <_int> virtual_qualifier
+%type <_str> Identifier
+%type <_int> dcoptag
+
+%%
+
+/*1*/
+main
+ : includes declaration main
+ {
+ }
+ | /* empty */
+ ;
+
+includes
+ : includes T_INCLUDE
+ {
+ printf("<INCLUDE>%s</INCLUDE>\n", $2->latin1() );
+ }
+ | T_EXTERN_C T_LEFT_CURLY_BRACKET main T_RIGHT_CURLY_BRACKET
+ {
+ }
+ | /* empty */
+ {
+ }
+ ;
+
+dcoptag
+ : T_DCOP { $$ = 1; }
+ | /* empty */ { $$ = 0; }
+ ;
+
+declaration
+ : T_CLASS Identifier class_header dcoptag body T_SEMICOLON
+ {
+ if ($4)
+ printf("<CLASS>\n <NAME>%s</NAME>\n%s%s</CLASS>\n", ( in_namespace + *$2 ).latin1(), $3->latin1(), $5->latin1() );
+ // default C++ visibility specifier is 'private'
+ dcop_area = 0;
+ dcop_signal_area = 0;
+
+ }
+ | T_CLASS T_IDENTIFIER Identifier class_header dcoptag body T_SEMICOLON
+ {
+ if ($5)
+ printf("<CLASS>\n <NAME>%s</NAME>\n <LINK_SCOPE>%s</LINK_SCOPE>\n%s%s</CLASS>\n", ( in_namespace + *$3 ).latin1(),$2->latin1(), $4->latin1(), $6->latin1() );
+ // default C++ visibility specifier is 'private'
+ dcop_area = 0;
+ dcop_signal_area = 0;
+
+ }
+ | T_CLASS Identifier T_SEMICOLON
+ {
+ }
+ | T_STRUCT Identifier T_SEMICOLON
+ {
+ }
+ | T_STRUCT Identifier class_header body T_SEMICOLON
+ {
+ }
+ | T_NAMESPACE T_IDENTIFIER T_LEFT_CURLY_BRACKET
+ {
+ in_namespace += *$2; in_namespace += "::";
+ }
+ main T_RIGHT_CURLY_BRACKET opt_semicolon
+ {
+ int pos = in_namespace.findRev( "::", -3 );
+ if( pos >= 0 )
+ in_namespace = in_namespace.left( pos + 2 );
+ else
+ in_namespace = "";
+ }
+ | T_USING T_NAMESPACE T_IDENTIFIER T_SEMICOLON
+ {
+ }
+ | T_USING T_IDENTIFIER T_SCOPE T_IDENTIFIER T_SEMICOLON
+ {
+ }
+ | T_EXTERN T_SEMICOLON
+ {
+ }
+ | T_TYPEDEF type Identifier T_SEMICOLON
+ {
+ }
+ | T_TYPEDEF T_STRUCT T_LEFT_CURLY_BRACKET member_list T_RIGHT_CURLY_BRACKET Identifier T_SEMICOLON
+ {
+ }
+ | T_TYPEDEF T_STRUCT Identifier T_LEFT_CURLY_BRACKET member_list T_RIGHT_CURLY_BRACKET Identifier T_SEMICOLON
+ {
+ }
+ | T_INLINE function
+ {
+ }
+ | function
+ {
+ }
+ | member
+ {
+ }
+ | enum
+ {
+ }
+ ;
+
+member_list
+ : member member_list
+ | /* empty */
+ ;
+
+bool_value: T_TRUE | T_FALSE;
+
+nodcop_area: T_PRIVATE | T_PROTECTED | T_PUBLIC ;
+
+sigslot: T_SIGNAL | T_SLOT | ;
+
+nodcop_area_begin
+ : nodcop_area sigslot T_COLON
+ {
+ dcop_area = 0;
+ dcop_signal_area = 0;
+ }
+ | sigslot T_COLON
+ {
+ dcop_area = 0;
+ dcop_signal_area = 0;
+ }
+ ;
+
+dcop_area_begin
+ : T_DCOP_AREA T_COLON
+ {
+ dcop_area = 1;
+ dcop_signal_area = 0;
+ }
+ ;
+
+dcop_signal_area_begin
+ : T_DCOP_SIGNAL_AREA T_COLON
+ {
+ /*
+ A dcop signals area needs all dcop area capabilities,
+ e.g. parsing of function parameters.
+ */
+ dcop_area = 1;
+ dcop_signal_area = 1;
+ }
+ ;
+
+Identifier
+ : T_IDENTIFIER %prec T_UNIMPORTANT {
+ $$ = $1;
+ }
+ | T_IDENTIFIER T_SCOPE Identifier {
+ QString* tmp = new QString( "%1::%2" );
+ *tmp = tmp->arg(*($1)).arg(*($3));
+ $$ = tmp;
+ }
+ ;
+
+super_class_name
+ : Identifier
+ {
+ QString* tmp = new QString( " <SUPER>%1</SUPER>\n" );
+ *tmp = tmp->arg( *($1) );
+ $$ = tmp;
+ }
+ | Identifier T_LESS type_list T_GREATER
+ {
+ QString* tmp = new QString( " <SUPER>%1</SUPER>\n" );
+ *tmp = tmp->arg( *($1) + "&lt;" + *($3) + "&gt;" );
+ $$ = tmp;
+ }
+ ;
+
+super_class
+ : virtual_qualifier T_PUBLIC super_class_name
+ {
+ $$ = $3;
+ }
+ | super_class_name
+ {
+ $$ = $1;
+ }
+ ;
+
+super_classes
+ : super_class T_LEFT_CURLY_BRACKET
+ {
+ $$ = $1;
+ }
+ | super_class T_COMMA super_classes
+ {
+ /* $$ = $1; */
+ $$ = new QString( *($1) + *($3) );
+ }
+ ;
+
+class_header
+ : T_COLON super_classes
+ {
+ $$ = $2;
+ }
+ | T_LEFT_CURLY_BRACKET
+ {
+ $$ = new QString( "" );
+ }
+ ;
+
+opt_semicolon
+ : /* empty */
+ {
+ }
+ | T_SEMICOLON
+ ;
+
+body
+ : T_RIGHT_CURLY_BRACKET
+ {
+ $$ = new QString( "" );
+ }
+ | typedef body
+ {
+ $$ = new QString( *($1) + *($2) );
+ }
+ | T_INLINE function body
+ {
+ $$ = new QString( *($2) + *($3) );
+ }
+ | function body
+ {
+ $$ = new QString( *($1) + *($2) );
+ }
+ | dcop_signal_area_begin body
+ {
+ $$ = $2;
+ }
+ | enum body
+ {
+ $$ = $2;
+ }
+ | dcop_area_begin body
+ {
+ $$ = $2;
+ }
+ | nodcop_area_begin body
+ {
+ $$ = $2;
+ }
+ | member body
+ {
+ $$ = $2;
+ }
+ | T_FRIEND T_CLASS Identifier T_SEMICOLON body
+ {
+ $$ = $5;
+ }
+ | T_FRIEND Identifier T_SEMICOLON body
+ {
+ $$ = $4;
+ }
+ | T_FRIEND function_header T_SEMICOLON body
+ {
+ $$ = $4;
+ }
+ | T_CLASS Identifier T_SEMICOLON body
+ {
+ $$ = $4;
+ }
+ | T_CLASS Identifier class_header body T_SEMICOLON body
+ {
+ $$ = $6;
+ }
+ | T_STRUCT Identifier T_SEMICOLON body
+ {
+ $$ = $4;
+ }
+ | T_STRUCT Identifier class_header body T_SEMICOLON body
+ {
+ $$ = $6;
+ }
+ | T_USING T_IDENTIFIER T_SCOPE T_IDENTIFIER T_SEMICOLON body
+ {
+ $$ = $6;
+ }
+ ;
+
+enum
+ : T_ENUM T_IDENTIFIER T_LEFT_CURLY_BRACKET enum_list T_RIGHT_CURLY_BRACKET T_IDENTIFIER T_SEMICOLON
+ | T_ENUM T_IDENTIFIER T_LEFT_CURLY_BRACKET enum_list T_RIGHT_CURLY_BRACKET T_SEMICOLON
+ | T_ENUM T_LEFT_CURLY_BRACKET enum_list T_RIGHT_CURLY_BRACKET T_IDENTIFIER T_SEMICOLON
+ | T_ENUM T_LEFT_CURLY_BRACKET enum_list T_RIGHT_CURLY_BRACKET T_SEMICOLON
+ ;
+
+enum_list
+ : enum_item T_COMMA enum_list
+ | enum_item
+ ;
+
+enum_item
+ : T_IDENTIFIER T_EQUAL int_expression {}
+ | T_IDENTIFIER {}
+ ;
+
+number
+ : T_CHARACTER_LITERAL {}
+ | T_INTEGER_LITERAL {}
+ | T_MINUS T_INTEGER_LITERAL {}
+ | T_NULL {}
+ | Identifier {}
+ ;
+
+int_expression
+ : number {}
+ | number T_PLUS number {}
+ | number T_SHIFT number {}
+ ;
+
+typedef
+ : T_TYPEDEF Identifier T_LESS type_list T_GREATER Identifier T_SEMICOLON
+ {
+ if (dcop_area) {
+ QString* tmp = new QString("<TYPEDEF name=\"%1\" template=\"%2\"><PARAM %3</TYPEDEF>\n");
+ *tmp = tmp->arg( *($6) ).arg( *($2) ).arg( *($4) );
+ $$ = tmp;
+ } else {
+ $$ = new QString("");
+ }
+ }
+ | T_TYPEDEF Identifier T_LESS type_list T_GREATER T_SCOPE T_IDENTIFIER Identifier T_SEMICOLON
+ {
+ if (dcop_area)
+ yyerror("scoped template typedefs are not supported in dcop areas!");
+ }
+ ;
+
+const_qualifier
+ : /* empty */
+ {
+ $$ = 0;
+ }
+ | T_CONST
+ {
+ $$ = 1;
+ }
+ ;
+
+int_type
+ : T_SIGNED { $$ = new QString("signed int"); }
+ | T_SIGNED T_INT { $$ = new QString("signed int"); }
+ | T_UNSIGNED { $$ = new QString("unsigned int"); }
+ | T_UNSIGNED T_INT { $$ = new QString("unsigned int"); }
+ | T_SIGNED T_SHORT { $$ = new QString("signed short int"); }
+ | T_SIGNED T_SHORT T_INT { $$ = new QString("signed short int"); }
+ | T_SIGNED T_LONG { $$ = new QString("signed long int"); }
+ | T_SIGNED T_LONG T_INT { $$ = new QString("signed long int"); }
+ | T_UNSIGNED T_SHORT { $$ = new QString("unsigned short int"); }
+ | T_UNSIGNED T_SHORT T_INT { $$ = new QString("unsigned short int"); }
+ | T_UNSIGNED T_LONG { $$ = new QString("unsigned long int"); }
+ | T_UNSIGNED T_LONG T_INT { $$ = new QString("unsigned long int"); }
+ | T_INT { $$ = new QString("int"); }
+ | T_LONG { $$ = new QString("long int"); }
+ | T_LONG T_INT { $$ = new QString("long int"); }
+ | T_SHORT { $$ = new QString("short int"); }
+ | T_SHORT T_INT { $$ = new QString("short int"); }
+ | T_CHAR { $$ = new QString("char"); }
+ | T_SIGNED T_CHAR { $$ = new QString("signed char"); }
+ | T_UNSIGNED T_CHAR { $$ = new QString("unsigned char"); }
+ ;
+
+asterisks
+ : T_ASTERISK asterisks
+ | T_ASTERISK
+ ;
+
+params
+ : /* empty */
+ {
+ $$ = new QString( "" );
+ }
+ | param
+ | params T_COMMA param
+ {
+ $$ = new QString( *($1) + *($3) );
+ }
+ ;
+
+/* Lowlevel definition of a type - doesn't include const, * nor & */
+type_name
+ : int_type
+ | Identifier { $$ = $1; }
+ | T_STRUCT Identifier { $$ = $2; }
+ | T_CLASS Identifier { $$ = $2; }
+ | Identifier T_LESS templ_type_list T_GREATER {
+ QString *tmp = new QString("%1&lt;%2&gt;");
+ *tmp = tmp->arg(*($1));
+ *tmp = tmp->arg(*($3));
+ $$ = tmp;
+ }
+ | Identifier T_LESS templ_type_list T_GREATER T_SCOPE Identifier{
+ QString *tmp = new QString("%1&lt;%2&gt;::%3");
+ *tmp = tmp->arg(*($1));
+ *tmp = tmp->arg(*($3));
+ *tmp = tmp->arg(*($6));
+ $$ = tmp;
+ }
+ ;
+
+/* List of types inside a template def like QMap< blah, blah > */
+templ_type_list
+ : templ_type T_COMMA templ_type_list
+ {
+ $$ = new QString(*($1) + "," + *($3));
+ }
+ | templ_type
+ {
+ $$ = $1;
+ }
+ ;
+
+/* One type inside a template. No '&' or const here. */
+templ_type
+ : type_name asterisks
+ {
+ if (dcop_area)
+ yyerror("in dcop areas are no pointers allowed");
+ }
+ | type_name
+ {
+ $$ = $1;
+ }
+ ;
+
+/* The hi-level, complete definition of a type, which also generates
+ the <TYPE> tag for it */
+type
+ : T_CONST type_name asterisks
+ {
+ if (dcop_area)
+ yyerror("in dcop areas are no pointers allowed");
+ }
+ | T_CONST type_name T_AMPERSAND {
+ if (dcop_area) {
+ QString* tmp = new QString("<TYPE qleft=\"const\" qright=\"" AMP_ENTITY "\">%1</TYPE>");
+ *tmp = tmp->arg( *($2) );
+ $$ = tmp;
+ }
+ }
+ | T_CONST type_name %prec T_UNIMPORTANT {
+ QString* tmp = new QString("<TYPE>%1</TYPE>");
+ *tmp = tmp->arg( *($2) );
+ $$ = tmp;
+ }
+ | type_name T_CONST %prec T_UNIMPORTANT {
+ QString* tmp = new QString("<TYPE>%1</TYPE>");
+ *tmp = tmp->arg( *($1) );
+ $$ = tmp;
+ }
+ | type_name T_CONST T_AMPERSAND {
+ if (dcop_area) {
+ QString* tmp = new QString("<TYPE qleft=\"const\" qright=\"" AMP_ENTITY "\">%1</TYPE>");
+ *tmp = tmp->arg( *($1) );
+ $$ = tmp;
+ }
+ }
+ | type_name T_AMPERSAND {
+ if (dcop_area)
+ yyerror("in dcop areas are only const references allowed!");
+ }
+
+ | type_name %prec T_UNIMPORTANT {
+ QString* tmp = new QString("<TYPE>%1</TYPE>");
+ *tmp = tmp->arg( *($1) );
+ $$ = tmp;
+ }
+ | type_name asterisks
+ {
+ if (dcop_area)
+ yyerror("in dcop areas are no pointers allowed");
+ }
+ ;
+
+type_list
+ : type T_COMMA type_list
+ {
+ $$ = new QString(*($1) + "," + *($3));
+ }
+ | type
+ {
+ $$ = $1;
+ }
+ ;
+
+param
+ : type Identifier default
+ {
+ if (dcop_area) {
+ QString* tmp = new QString("\n <ARG>%1<NAME>%2</NAME></ARG>");
+ *tmp = tmp->arg( *($1) );
+ *tmp = tmp->arg( *($2) );
+ $$ = tmp;
+ } else $$ = new QString();
+ }
+ | type default
+ {
+ if (dcop_area) {
+ QString* tmp = new QString("\n <ARG>%1</ARG>");
+ *tmp = tmp->arg( *($1) );
+ $$ = tmp;
+ } else $$ = new QString();
+ }
+ | T_TRIPLE_DOT
+ {
+ if (dcop_area)
+ yyerror("variable arguments not supported in dcop area.");
+ $$ = new QString("");
+ }
+ ;
+
+default
+ : /* empty */
+ {
+ }
+ | T_EQUAL value
+ {
+ }
+ | T_EQUAL T_LEFT_PARANTHESIS type T_RIGHT_PARANTHESIS value /* cast */
+ {
+ }
+ ;
+
+/* Literal or calculated value, used for an initialization */
+value
+ : T_STRING_LITERAL
+ {
+ }
+ | int_expression
+ {
+ }
+ | T_DOUBLE_LITERAL
+ {
+ }
+ | bool_value
+ {
+ }
+ | Identifier T_LEFT_PARANTHESIS params T_RIGHT_PARANTHESIS
+ {
+ }
+ ;
+
+virtual_qualifier
+ : /* empty */ { $$ = 0; }
+ | T_VIRTUAL { $$ = 1; }
+ ;
+
+operator
+ : T_MISCOPERATOR | T_SHIFT | T_GREATER | T_LESS | T_EQUAL
+ ;
+
+function_header
+ : type Identifier T_LEFT_PARANTHESIS params T_RIGHT_PARANTHESIS const_qualifier
+ {
+ if (dcop_area || dcop_signal_area) {
+ QString* tmp = 0;
+ tmp = new QString(
+ " <%4>\n"
+ " %2\n"
+ " <NAME>%1</NAME>"
+ "%3\n"
+ " </%5>\n");
+ *tmp = tmp->arg( *($2) );
+ *tmp = tmp->arg( *($1) );
+ *tmp = tmp->arg( *($4) );
+
+ QString tagname = (dcop_signal_area) ? "SIGNAL" : "FUNC";
+ QString attr = ($6) ? " qual=\"const\"" : "";
+ *tmp = tmp->arg( QString("%1%2").arg(tagname).arg(attr) );
+ *tmp = tmp->arg( QString("%1").arg(tagname) );
+ $$ = tmp;
+ } else
+ $$ = new QString("");
+ }
+ | type T_FUNOPERATOR operator T_LEFT_PARANTHESIS params T_RIGHT_PARANTHESIS const_qualifier
+ {
+ if (dcop_area)
+ yyerror("operators aren't allowed in dcop areas!");
+ $$ = new QString("");
+ }
+ ;
+
+/* In an inline constructor:
+ List of values used as initialization for member var, or as params to parent constructor */
+values
+ : value {}
+ | value T_COMMA values {}
+ | /* empty */ {}
+ ;
+
+/* One initialization done by an inline constructor */
+init_item
+ : T_IDENTIFIER T_LEFT_PARANTHESIS values T_RIGHT_PARANTHESIS {}
+ ;
+
+/* List of initializations done by an inline constructor */
+init_list
+ : init_item {}
+ | init_item T_COMMA init_list {}
+ ;
+
+function
+ : function_header function_body
+ {
+ $$ = $1;
+ }
+ | T_VIRTUAL function_header T_EQUAL T_NULL function_body
+ {
+ $$ = $2;
+ }
+ | T_VIRTUAL function_header function_body
+ {
+ $$ = $2;
+ }
+ | Identifier T_LEFT_PARANTHESIS params T_RIGHT_PARANTHESIS function_body
+ {
+ /* The constructor */
+ assert(!dcop_area);
+ $$ = new QString("");
+ }
+ | Identifier T_LEFT_PARANTHESIS params T_RIGHT_PARANTHESIS T_COLON init_list function_body
+ {
+ /* The constructor */
+ assert(!dcop_area);
+ $$ = new QString("");
+ }
+ | virtual_qualifier T_TILDE Identifier T_LEFT_PARANTHESIS T_RIGHT_PARANTHESIS function_body
+ {
+ /* The destructor */
+ assert(!dcop_area);
+ $$ = new QString("");
+ }
+ | T_STATIC function_header function_body
+ {
+ if (dcop_area) {
+ if (dcop_signal_area)
+ yyerror("DCOP signals cannot be static");
+ else
+ yyerror("DCOP functions cannot be static");
+ } else {
+ $$ = new QString();
+ }
+ }
+ ;
+
+function_begin : T_LEFT_CURLY_BRACKET
+ {
+ function_mode = 1;
+ }
+ ;
+
+function_body
+ : T_SEMICOLON
+ | function_begin function_lines T_RIGHT_CURLY_BRACKET
+ | function_begin function_lines T_RIGHT_CURLY_BRACKET T_SEMICOLON
+ ;
+
+function_lines
+ : function_line function_lines {}
+ | /* empty */ {}
+ ;
+
+function_line
+ : T_SEMICOLON /* dummy */
+ ;
+
+Identifier_list_rest
+ : T_COMMA Identifier_list
+ | /* empty */
+ ;
+
+Identifier_list_entry : T_IDENTIFIER {}
+ | T_IDENTIFIER T_EQUAL value {}
+ | asterisks T_IDENTIFIER {}
+ ;
+
+Identifier_list : Identifier_list_entry Identifier_list_rest {}
+ ;
+
+member
+ : type Identifier_list T_SEMICOLON {}
+ | type Identifier T_COLON T_INTEGER_LITERAL T_SEMICOLON {}
+ | T_STATIC type T_IDENTIFIER default T_SEMICOLON {}
+ | T_MUTABLE type T_IDENTIFIER default T_SEMICOLON {}
+ | type T_IDENTIFIER T_ARRAY_OPEN int_expression T_ARRAY_CLOSE T_SEMICOLON {}
+ | T_STATIC type T_IDENTIFIER T_ARRAY_OPEN int_expression T_ARRAY_CLOSE T_SEMICOLON {}
+ ;
+
+%%
+
+void dcopidlParse( const char *_code )
+{
+ dcopidlInitFlex( _code );
+ yyparse();
+}
diff --git a/dcop/dcopidl2cpp/Makefile.am b/dcop/dcopidl2cpp/Makefile.am
new file mode 100644
index 000000000..9b9a6b599
--- /dev/null
+++ b/dcop/dcopidl2cpp/Makefile.am
@@ -0,0 +1,20 @@
+
+INCLUDES = $(all_includes)
+AM_LDFLAGS = $(all_libraries)
+
+####### Files
+
+bin_PROGRAMS = dcopidl2cpp
+
+dcopidl2cpp_SOURCES = main.cpp skel.cpp stub.cpp stubimpl.cpp
+noinst_HEADERS = main.h
+
+dcopidl2cpp_LDADD = $(LIB_QT)
+dcopidl2cpp_LDFLAGS = $(KDE_RPATH) $(AM_LDFLAGS)
+
+dcopidl_output.kidl: ../dcopidl/dcopidl $(srcdir)/dcopidl_test.h
+ ../dcopidl/dcopidl $(srcdir)/dcopidl_test.h > dcopidl_output.kidl
+
+check-local: dcopidl_output.kidl
+ ./dcopidl2cpp dcopidl_output.kidl
+ $(MD5SUM) dcopidl_output_*
diff --git a/dcop/dcopidl2cpp/dcopidl_test.h b/dcop/dcopidl2cpp/dcopidl_test.h
new file mode 100644
index 000000000..a6c625abe
--- /dev/null
+++ b/dcop/dcopidl2cpp/dcopidl_test.h
@@ -0,0 +1,109 @@
+#include <klistview.h>
+#include "main.h"
+
+#ifndef TEST_H
+#define TEST_H
+
+// still todo:
+// stub:
+// - includes to super relationship, a bit much to test, needs multiple files?
+
+class KDEUI_EXPORT DefaultTest : public QObject, virtual public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+public:
+ DefaultTest();
+ void nonDcopFunction( QString filename, QString url, QString text, QString address, QString icon );
+k_dcop:
+ void noArgsTest();
+ void argsTest( QString filename, QString url );
+ void unNamedArgsTest( QString, QString );
+
+ void constTest( QString, QString ) const;
+ QStringList writeTypeTest( const QString &, QPtrList<int> );
+
+ void voidReturnType( QString filename, QString url, QString text, QString address, QString icon );
+ QString nonVoidReturnType( QString filename, QString text, QString address );
+ int intReturnType( QString filename, QString text, QString address );
+ bool boolReturnType( QString filename, QString text, QString address );
+
+ ASYNC asyncTest( QString filename, QString text, QString address );
+};
+
+namespace TestNamespace {
+ class NamespaceTest
+ {
+ K_DCOP
+ public:
+ NamespaceTest();
+ k_dcop:
+ void function1( QString filename, QString url, QString text, QString address, QString icon );
+ };
+}
+
+class NoSuper
+{
+ K_DCOP
+public:
+ NoSuper();
+k_dcop:
+ void function1( QString filename, QString url, QString text, QString address, QString icon );
+};
+
+class NonDCOPObject : public MyDCOPObjectBase
+{
+ K_DCOP
+public:
+ NonDCOPObject();
+k_dcop:
+ void function1( QString filename, QString url, QString text, QString address, QString icon );
+};
+
+class NoFunctions : public DCOPObject
+{
+ K_DCOP
+public:
+ NonDCOPObject();
+ void nonDcopFunction( QString filename, QString url, QString text, QString address, QString icon );
+};
+
+class NonHashingTest : public QObject, virtual public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+public:
+ NonHashingTest();
+k_dcop:
+ void function1( QString );
+};
+
+class HashingTest : public QObject, virtual public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+public:
+ HashingTest();
+k_dcop:
+ void function1( QString );
+ void function2( QString, QString );
+ void function3( QString, QString, QString );
+ void function4( QString, QString, QString, QString );
+ void function5( QString, QString, QString, QString, QString );
+ void function6( QString, QString, QString, QString, QString, QString );
+ void function7( QString, QString, QString, QString, QString, QString, QString );
+ void function8( QString, QString, QString, QString, QString, QString, QString, QString );
+};
+
+class SignalTest : virtual public DCOPObject
+{
+ K_DCOP
+public:
+ SignalTest(QCString objId = "KBookmarkNotifier") : DCOPObject(objId) {}
+k_dcop_signals:
+ void signal1( QString filename, QString url, QString text, QString address, QString icon );
+ void signal2( QString filename, QString text, QString address );
+ void signal3( QString filename, QString url );
+};
+
+#endif // end
diff --git a/dcop/dcopidl2cpp/main.cpp b/dcop/dcopidl2cpp/main.cpp
new file mode 100644
index 000000000..32d128c30
--- /dev/null
+++ b/dcop/dcopidl2cpp/main.cpp
@@ -0,0 +1,128 @@
+/*****************************************************************
+Copyright (c) 1999 Torben Weis <weis@kde.org>
+Copyright (c) 2000 Matthias Ettrich <ettrich@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 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.
+
+******************************************************************/
+#include <qdom.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qstring.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "main.h"
+
+
+
+void usage()
+{
+ fprintf( stderr, "Usage: dcopidl2cpp [ --no-skel | --no-stub ] [--c++-suffix <suffix>] file\n" );
+}
+
+int main( int argc, char** argv )
+{
+
+ if ( *qVersion() == '1' ) {
+ fprintf( stderr, "dcopidl2cpp appears to be linked to Qt 1 instead of Qt >= 2 ! Aborting.\n" );
+ exit(1);
+ }
+ if ( argc < 2 ) {
+ usage();
+ return 1;
+ }
+ int argpos = 1;
+ bool generate_skel = true;
+ bool generate_stub = true;
+
+ QString suffix = "cpp";
+
+ while (argc > 2) {
+
+ if ( strcmp( argv[argpos], "--no-skel" ) == 0 )
+ {
+ generate_skel = false;
+ for (int i = argpos; i < argc - 1; i++) argv[i] = argv[i+1];
+ argc--;
+ }
+ else if ( strcmp( argv[argpos], "--no-stub" ) == 0 )
+ {
+ generate_stub = false;
+ for (int i = argpos; i < argc - 1; i++) argv[i] = argv[i+1];
+ argc--;
+ }
+ else if ( strcmp( argv[argpos], "--no-signals" ) == 0 )
+ {
+ // Obsolete: Signal stubs are now always generated.
+ // Leave this command line argument intact, so old Makefiles won't break.
+ for (int i = argpos; i < argc - 1; i++) argv[i] = argv[i+1];
+ argc--;
+ }
+ else if ( strcmp( argv[argpos], "--c++-suffix" ) == 0)
+ {
+ if (argc - 1 < argpos) {
+ usage();
+ exit(1);
+ }
+ suffix = argv[argpos+1];
+ for (int i = argpos; i < argc - 2; i++) argv[i] = argv[i+2];
+ argc -= 2;
+ } else {
+ usage();
+ exit(1);
+ }
+ }
+
+ QFile in( QFile::decodeName(argv[argpos]) );
+ if ( !in.open( IO_ReadOnly ) )
+ qFatal("Could not read %s", argv[argpos] );
+
+ QDomDocument doc;
+ doc.setContent( &in );
+
+ QDomElement de = doc.documentElement();
+ Q_ASSERT( de.tagName() == "DCOP-IDL" );
+
+ QString base( argv[argpos] );
+ QString idl = base;
+
+ int pos = base.findRev( '.' );
+ if ( pos != -1 )
+ base = base.left( pos );
+
+ pos = idl.findRev('/');
+ if ( pos != -1 )
+ idl = idl.mid( pos+1 );
+
+ if ( generate_skel )
+ generateSkel( idl, base + "_skel." + suffix, de );
+
+ if ( generate_stub ) {
+ QString header = base;
+ generateStub( idl, header + "_stub.h", de );
+ pos = header.findRev('/');
+ if ( pos != -1 )
+ header = header.mid( pos+1 );
+ generateStubImpl( idl, header + "_stub.h", base+".h", base + "_stub." + suffix, de);
+ }
+
+ return 0;
+}
diff --git a/dcop/dcopidl2cpp/main.h b/dcop/dcopidl2cpp/main.h
new file mode 100644
index 000000000..a0ecdb250
--- /dev/null
+++ b/dcop/dcopidl2cpp/main.h
@@ -0,0 +1,40 @@
+/*****************************************************************
+Copyright (c) 1999 Torben Weis <weis@kde.org>
+Copyright (c) 2000 Matthias Ettrich <ettrich@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
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+#include <qdom.h>
+#include <qstring.h>
+
+/**
+ * Writes the skeleton
+ */
+void generateSkel( const QString& idl, const QString& filename, QDomElement de );
+
+/**
+ * Writes the stubs header
+ */
+void generateStub( const QString& idl, const QString& filename, QDomElement de);
+
+/**
+ * Writes the stub implementation
+ */
+void generateStubImpl( const QString& idl, const QString& header, const QString& headerBase, const QString& filename, QDomElement de);
+
diff --git a/dcop/dcopidl2cpp/skel.cpp b/dcop/dcopidl2cpp/skel.cpp
new file mode 100644
index 000000000..fe79aec92
--- /dev/null
+++ b/dcop/dcopidl2cpp/skel.cpp
@@ -0,0 +1,445 @@
+/*****************************************************************
+Copyright (c) 1999 Torben Weis <weis@kde.org>
+Copyright (c) 2000 Matthias Ettrich <ettrich@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
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+#include <qdom.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "main.h"
+#include "type.h"
+
+static int const primes[] =
+{
+ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
+ 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
+ 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
+ 127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
+ 179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
+ 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
+ 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
+ 353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
+ 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
+ 467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
+ 547, 557, 563, 569, 571, 577, 587, 593, 599, 601,0
+};
+
+
+struct Function
+{
+ Function(){}
+ Function( const QString& t, const QString& n, const QString&fn, bool h )
+ : type( t ), name( n ), fullName( fn ), hidden( h ) {}
+ QString type;
+ QString name;
+ QString fullName;
+ bool hidden;
+};
+
+
+/*
+ * Writes the skeleton
+ */
+void generateSkel( const QString& idl, const QString& filename, QDomElement de )
+{
+ QFile skel( filename );
+ if ( !skel.open( IO_WriteOnly ) )
+ qFatal("Could not write to %s", filename.local8Bit().data() );
+
+ QTextStream str( &skel );
+
+ str << "/****************************************************************************" << endl;
+ str << "**" << endl;
+ str << "** DCOP Skeleton generated by dcopidl2cpp from " << idl << endl;
+ str << "**" << endl;
+ str << "** WARNING! All changes made in this file will be lost!" << endl;
+ str << "**" << endl;
+ str << "*****************************************************************************/" << endl;
+ str << endl;
+
+ QDomElement e = de.firstChild().toElement();
+ if ( e.tagName() == "SOURCE" ) {
+ str << "#include \"" << e.firstChild().toText().data() << "\"" << endl << endl;
+ }
+
+ for( ; !e.isNull(); e = e.nextSibling().toElement() ) {
+ if ( e.tagName() != "CLASS" )
+ continue;
+ QDomElement n = e.firstChild().toElement();
+ Q_ASSERT( n.tagName() == "NAME" );
+ QString className = n.firstChild().toText().data();
+ // find dcop parent ( rightmost super class )
+ QString DCOPParent;
+ QDomElement s = n.nextSibling().toElement();
+ for( ; !s.isNull(); s = s.nextSibling().toElement() ) {
+ if ( s.tagName() == "SUPER" )
+ DCOPParent = s.firstChild().toText().data();
+ }
+
+ // get function table
+ QValueList<Function> functions;
+ s = n.nextSibling().toElement();
+ for( ; !s.isNull(); s = s.nextSibling().toElement() ) {
+ if ( s.tagName() != "FUNC" )
+ continue;
+ QDomElement r = s.firstChild().toElement();
+ Q_ASSERT( r.tagName() == "TYPE" );
+ QString funcType = r.firstChild().toText().data();
+ r = r.nextSibling().toElement();
+ Q_ASSERT ( r.tagName() == "NAME" );
+ QString funcName = r.firstChild().toText().data();
+ QStringList argtypes;
+ QStringList argnames;
+ r = r.nextSibling().toElement();
+ for( ; !r.isNull(); r = r.nextSibling().toElement() ) {
+ Q_ASSERT( r.tagName() == "ARG" );
+ QDomElement a = r.firstChild().toElement();
+ Q_ASSERT( a.tagName() == "TYPE" );
+ argtypes.append( a.firstChild().toText().data() );
+ a = a.nextSibling().toElement();
+ if ( !a.isNull() ) {
+ Q_ASSERT( a.tagName() == "NAME" );
+ argnames.append( a.firstChild().toText().data() );
+ } else {
+ argnames.append( QString::null );
+ }
+ }
+ funcName += '(';
+ QString fullFuncName = funcName;
+ bool first = true;
+ QStringList::Iterator ittype = argtypes.begin();
+ QStringList::Iterator itname = argnames.begin();
+ while ( ittype != argtypes.end() && itname != argnames.end() ) {
+ if ( !first ) {
+ funcName += ',';
+ fullFuncName += ',';
+ }
+ first = false;
+ funcName += *ittype;
+ fullFuncName += *ittype;
+ if ( ! (*itname).isEmpty() ) {
+ fullFuncName += ' ';
+ fullFuncName += *itname;
+ }
+ ++ittype;
+ ++itname;
+ }
+ funcName += ')';
+ fullFuncName += ')';
+ bool hidden = (s.attribute("hidden") == "yes");
+ functions.append( Function( funcType, funcName, fullFuncName, hidden ) );
+ }
+
+ // create static tables
+
+ int fhash = functions.count() + 1;
+ for ( int i = 0; primes[i]; i++ ) {
+ if ( primes[i] > static_cast<int>(functions.count()) ) {
+ fhash = primes[i];
+ break;
+ }
+ }
+
+ str << "#include <kdatastream.h>" << endl;
+
+ bool useHashing = functions.count() > 7;
+ if ( useHashing ) {
+ str << "#include <qasciidict.h>" << endl;
+ }
+
+ QString classNameFull = className; // class name with possible namespaces prepended
+ // namespaces will be removed from className now
+ int namespace_count = 0;
+ QString namespace_tmp = className;
+ str << endl;
+ for(;;) {
+ int pos = namespace_tmp.find( "::" );
+ if( pos < 0 ) {
+ className = namespace_tmp;
+ break;
+ }
+ str << "namespace " << namespace_tmp.left( pos ) << " {" << endl;
+ ++namespace_count;
+ namespace_tmp = namespace_tmp.mid( pos + 2 );
+ }
+
+ str << endl;
+
+ if ( useHashing ) {
+ str << "static const int " << className << "_fhash = " << fhash << ";" << endl;
+ }
+ str << "static const char* const " << className << "_ftable[" << functions.count() + 1 << "][3] = {" << endl;
+ for( QValueList<Function>::Iterator it = functions.begin(); it != functions.end(); ++it ){
+ str << " { \"" << (*it).type << "\", \"" << (*it).name << "\", \"" << (*it).fullName << "\" }," << endl;
+ }
+ str << " { 0, 0, 0 }" << endl;
+ str << "};" << endl;
+
+ if (functions.count() > 0) {
+ str << "static const int " << className << "_ftable_hiddens[" << functions.count() << "] = {" << endl;
+ for( QValueList<Function>::Iterator it = functions.begin(); it != functions.end(); ++it ){
+ str << " " << !!(*it).hidden << "," << endl;
+ }
+ str << "};" << endl;
+ }
+
+ str << endl;
+
+
+ // Write dispatcher
+ str << "bool " << className;
+ str << "::process(const QCString &fun, const QByteArray &data, QCString& replyType, QByteArray &replyData)" << endl;
+ str << "{" << endl;
+ if ( useHashing ) {
+ str << " static QAsciiDict<int>* fdict = 0;" << endl;
+
+ str << " if ( !fdict ) {" << endl;
+ str << "\tfdict = new QAsciiDict<int>( " << className << "_fhash, true, false );" << endl;
+ str << "\tfor ( int i = 0; " << className << "_ftable[i][1]; i++ )" << endl;
+ str << "\t fdict->insert( " << className << "_ftable[i][1], new int( i ) );" << endl;
+ str << " }" << endl;
+
+ str << " int* fp = fdict->find( fun );" << endl;
+ str << " switch ( fp?*fp:-1) {" << endl;
+ }
+ s = n.nextSibling().toElement();
+ int fcount = 0; // counter of written functions
+ bool firstFunc = true;
+ for( ; !s.isNull(); s = s.nextSibling().toElement() ) {
+ if ( s.tagName() != "FUNC" )
+ continue;
+ QDomElement r = s.firstChild().toElement();
+ Q_ASSERT( r.tagName() == "TYPE" );
+ QString funcType = r.firstChild().toText().data();
+ if ( funcType == "ASYNC" )
+ funcType = "void";
+ r = r.nextSibling().toElement();
+ Q_ASSERT ( r.tagName() == "NAME" );
+ QString funcName = r.firstChild().toText().data();
+ QStringList args;
+ QStringList argtypes;
+ r = r.nextSibling().toElement();
+ for( ; !r.isNull(); r = r.nextSibling().toElement() ) {
+ Q_ASSERT( r.tagName() == "ARG" );
+ QDomElement a = r.firstChild().toElement();
+ Q_ASSERT( a.tagName() == "TYPE" );
+ argtypes.append( a.firstChild().toText().data() );
+ args.append( QString("arg" ) + QString::number( args.count() ) );
+ }
+ QString plainFuncName = funcName;
+ funcName += '(';
+ bool first = true;
+ for( QStringList::Iterator argtypes_count = argtypes.begin(); argtypes_count != argtypes.end(); ++argtypes_count ){
+ if ( !first )
+ funcName += ',';
+ first = false;
+ funcName += *argtypes_count;
+ }
+ funcName += ')';
+
+ if ( useHashing ) {
+ str << " case " << fcount << ": { // " << funcType << " " << funcName << endl;
+ } else {
+ if ( firstFunc )
+ str << " if ( fun == " << className << "_ftable[" << fcount << "][1] ) { // " << funcType << " " << funcName << endl;
+ else
+ str << " else if ( fun == " << className << "_ftable[" << fcount << "][1] ) { // " << funcType << " " << funcName << endl;
+ firstFunc = false;
+ }
+ if ( !args.isEmpty() ) {
+ QStringList::Iterator ittypes = argtypes.begin();
+ QStringList::Iterator args_count;
+ for( args_count = args.begin(); args_count != args.end(); ++args_count ){
+ str << '\t'<< *ittypes << " " << *args_count << ";" << endl;
+ ++ittypes;
+ }
+ str << "\tQDataStream arg( data, IO_ReadOnly );" << endl;
+ for( args_count = args.begin(); args_count != args.end(); ++args_count ){
+ str << "\tif (arg.atEnd()) return false;" << endl; // Basic error checking
+ str << "\targ >> " << *args_count << ";" << endl;
+ }
+ }
+
+ str << "\treplyType = " << className << "_ftable[" << fcount++ << "][0]; " << endl;
+ if ( funcType == "void" ) {
+ str << '\t' << plainFuncName << '(';
+ } else {
+ str << "\tQDataStream _replyStream( replyData, IO_WriteOnly );" << endl;
+ str << "\t_replyStream << " << plainFuncName << '(';
+ }
+
+ first = true;
+ for ( QStringList::Iterator args_count = args.begin(); args_count != args.end(); ++args_count ){
+ if ( !first )
+ str << ", ";
+ first = false;
+ str << *args_count;
+ }
+ str << " );" << endl;
+ if (useHashing ) {
+ str << " } break;" << endl;
+ } else {
+ str << " }";
+ }
+ }
+
+ // only open an 'else' clause if there were one or more functions
+ if ( fcount > 0 ) {
+ if ( useHashing ) {
+ str << " default: " << endl;
+ } else {
+ str << " else {" << endl;
+ }
+ }
+
+ // if no DCOP function was called, delegate the request to the parent
+ if (!DCOPParent.isEmpty()) {
+ str << "\treturn " << DCOPParent << "::process( fun, data, replyType, replyData );" << endl;
+ } else {
+ str << "\treturn false;" << endl;
+ }
+
+ // only close the 'else' clause and add the default 'return true'
+ // (signifying a DCOP method was found and called) if there were
+ // one or more functions.
+ if ( fcount > 0 ) {
+ str << " }" << endl;
+ str << " return true;" << endl;
+ }
+
+ // close the 'process' function
+ str << "}" << endl << endl;
+
+ str << "QCStringList " << className;
+ str << "::interfaces()" << endl;
+ str << "{" << endl;
+ if (!DCOPParent.isEmpty()) {
+ str << " QCStringList ifaces = " << DCOPParent << "::interfaces();" << endl;
+ } else {
+ str << " QCStringList ifaces;" << endl;
+ }
+ str << " ifaces += \"" << classNameFull << "\";" << endl;
+ str << " return ifaces;" << endl;
+ str << "}" << endl << endl;
+
+
+ str << "QCStringList " << className;
+ str << "::functions()" << endl;
+ str << "{" << endl;
+ if (!DCOPParent.isEmpty()) {
+ str << " QCStringList funcs = " << DCOPParent << "::functions();" << endl;
+ } else {
+ str << " QCStringList funcs;" << endl;
+ }
+ str << " for ( int i = 0; " << className << "_ftable[i][2]; i++ ) {" << endl;
+ if (functions.count() > 0) {
+ str << "\tif (" << className << "_ftable_hiddens[i])" << endl;
+ str << "\t continue;" << endl;
+ }
+ str << "\tQCString func = " << className << "_ftable[i][0];" << endl;
+ str << "\tfunc += ' ';" << endl;
+ str << "\tfunc += " << className << "_ftable[i][2];" << endl;
+ str << "\tfuncs << func;" << endl;
+ str << " }" << endl;
+ str << " return funcs;" << endl;
+ str << "}" << endl << endl;
+
+ // Add signal stubs
+ for(s = e.firstChild().toElement(); !s.isNull(); s = s.nextSibling().toElement() ) {
+ if (s.tagName() != "SIGNAL")
+ continue;
+ QDomElement r = s.firstChild().toElement();
+ QString result = writeType( str, r );
+
+ r = r.nextSibling().toElement();
+ Q_ASSERT ( r.tagName() == "NAME" );
+ QString funcName = r.firstChild().toText().data();
+ str << className << "::" << funcName << "(";
+
+ QStringList args;
+ QStringList argtypes;
+ bool first = true;
+ r = r.nextSibling().toElement();
+ for( ; !r.isNull(); r = r.nextSibling().toElement() ) {
+ if ( !first )
+ str << ", ";
+ else
+ str << " ";
+ first = false;
+ Q_ASSERT( r.tagName() == "ARG" );
+ QDomElement a = r.firstChild().toElement();
+ QString type = writeType( str, a );
+ argtypes.append( type );
+ args.append( QString("arg" ) + QString::number( args.count() ) ) ;
+ str << args.last();
+ }
+ if ( !first )
+ str << " ";
+ str << ")";
+
+ if ( s.hasAttribute("qual") )
+ str << " " << s.attribute("qual");
+ str << endl;
+
+ str << "{" << endl ;
+
+ funcName += "(";
+ first = true;
+ for( QStringList::Iterator it = argtypes.begin(); it != argtypes.end(); ++it ){
+ if ( !first )
+ funcName += ",";
+ first = false;
+ funcName += *it;
+ }
+ funcName += ")";
+
+ if ( result != "void" )
+ qFatal("Error in DCOP signal %s::%s: DCOP signals can not return values.", className.latin1(), funcName.latin1());
+
+ str << " QByteArray data;" << endl;
+ if ( !args.isEmpty() ) {
+ str << " QDataStream arg( data, IO_WriteOnly );" << endl;
+ for( QStringList::Iterator args_count = args.begin(); args_count != args.end(); ++args_count ){
+ str << " arg << " << *args_count << ";" << endl;
+ }
+ }
+
+ str << " emitDCOPSignal( \"" << funcName << "\", data );" << endl;
+
+ str << "}" << endl << endl;
+
+ }
+
+ for(; namespace_count > 0; --namespace_count )
+ str << "} // namespace" << endl;
+ str << endl;
+ }
+
+ skel.close();
+}
+
+// :set expandtab!<RETURN>:set ts=8<RETURN>:set sts=4<RETURN>:set sw=4<RETURN>
diff --git a/dcop/dcopidl2cpp/stub.cpp b/dcop/dcopidl2cpp/stub.cpp
new file mode 100644
index 000000000..4060ae88f
--- /dev/null
+++ b/dcop/dcopidl2cpp/stub.cpp
@@ -0,0 +1,216 @@
+/*****************************************************************
+Copyright (c) 1999 Torben Weis <weis@kde.org>
+Copyright (c) 2000 Matthias Ettrich <ettrich@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
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+#include <qdom.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "main.h"
+#include "type.h"
+
+/*
+ * Writes the stubs header
+ */
+void generateStub( const QString& idl, const QString& filename, QDomElement de)
+{
+ QFile stub( filename );
+ if ( !stub.open( IO_WriteOnly ) )
+ qFatal("Could not write to %s", filename.local8Bit().data() );
+
+ QTextStream str( &stub );
+
+ str << "/****************************************************************************" << endl;
+ str << "**" << endl;
+ str << "** DCOP Stub Definition created by dcopidl2cpp from " << idl << endl;
+ str << "**" << endl;
+ str << "** WARNING! All changes made in this file will be lost!" << endl;
+ str << "**" << endl;
+ str << "*****************************************************************************/" << endl;
+ str << endl;
+
+ QString ifdefstring = idl.upper();
+ int pos = idl.findRev( '.' );
+ if ( pos != -1 )
+ ifdefstring = ifdefstring.left( pos );
+
+ QString ifdefsuffix = "_STUB__";
+ str << "#ifndef __" << ifdefstring << ifdefsuffix << endl;
+ str << "#define __" << ifdefstring << ifdefsuffix << endl << endl;
+
+ str << "#include <dcopstub.h>" << endl;
+
+ QStringList includeslist, all_includes;
+ QDomElement e = de.firstChild().toElement();
+ for( ; !e.isNull(); e = e.nextSibling().toElement() ) {
+ if ( e.tagName() == "INCLUDE" ) {
+ // dcopidl lists the includes in reversed order because of the used yacc/bison gramatic
+ // so let's reverse it back, as the order may be important
+ includeslist.prepend( e.firstChild().toText().data());
+ continue;
+ }
+ if( !includeslist.empty()) {
+ for( QStringList::ConstIterator it = includeslist.begin();
+ it != includeslist.end();
+ ++it ) {
+ str << "#include <" << ( *it ) << ">" << endl;
+ all_includes.append( *it );
+ }
+ includeslist.clear();
+ }
+ if ( e.tagName() != "CLASS" )
+ continue;
+
+ str << endl;
+
+ QDomElement n = e.firstChild().toElement();
+ Q_ASSERT( n.tagName() == "NAME" );
+ QString className = n.firstChild().toText().data() + ( "_stub" );
+
+ //add link scope, if available
+ n = n.nextSibling().toElement();
+ QString linkScope;
+ if (n.tagName()=="LINK_SCOPE") {
+ linkScope = n.firstChild().toText().data() + " ";
+ n = n.nextSibling().toElement();
+ }
+
+ // find dcop parent ( rightmost super class )
+ QString DCOPParent;
+ for( ; !n.isNull(); n = n.nextSibling().toElement() ) {
+ if ( n.tagName() == "SUPER" )
+ DCOPParent = n.firstChild().toText().data();
+ }
+
+ if( DCOPParent != "DCOPObject" ) { // we need to include the .h file for the base stub
+ if( all_includes.contains( DCOPParent + ".h" ))
+ str << "#include <" << DCOPParent << "_stub.h>" << endl;
+ else if( all_includes.contains( DCOPParent.lower() + ".h" ))
+ str << "#include <" << DCOPParent.lower() << "_stub.h>" << endl;
+ else {// damn ... let's assume it's the last include
+ QString stub_h = all_includes.last();
+ unsigned int pos = stub_h.find( ".h" );
+ if( pos > 0 ) {
+ stub_h = stub_h.remove( pos, 100000 );
+ str << "#include <" << stub_h << "_stub.h>" << endl;
+ }
+ else
+ str << "#include <" << stub_h << ">" << endl;
+ }
+ }
+
+ QString classNameFull = className; // class name with possible namespaces prepended
+ // namespaces will be removed from className now
+ int namespace_count = 0;
+ QString namespace_tmp = className;
+ for(;;) {
+ int pos = namespace_tmp.find( "::" );
+ if( pos < 0 ) {
+ className = namespace_tmp;
+ break;
+ }
+ str << "namespace " << namespace_tmp.left( pos ) << " {" << endl;
+ ++namespace_count;
+ namespace_tmp = namespace_tmp.mid( pos + 2 );
+ }
+
+ str << endl;
+
+ // Stub class definition
+ str << "class " << linkScope << className;
+
+ // Parent : inherited interface stub or dcopstub
+ if ( !DCOPParent.isEmpty() && DCOPParent != "DCOPObject" ) {
+ str << " : ";
+ str << "virtual public " << DCOPParent << "_stub";
+ } else {
+ str << " : virtual public DCOPStub";
+ }
+
+ str << endl;
+ str << "{" << endl;
+ str << "public:" << endl;
+
+ // Constructors
+ str << " " << className << "( const QCString& app, const QCString& id );" << endl;
+ str << " " << className << "( DCOPClient* client, const QCString& app, const QCString& id );" << endl;
+ str << " explicit " << className << "( const DCOPRef& ref );" << endl;
+
+ n = e.firstChild().toElement();
+ for( ; !n.isNull(); n = n.nextSibling().toElement() ) {
+ if (n.tagName() != "FUNC")
+ continue;
+ QDomElement r = n.firstChild().toElement();
+ str << " virtual "; // KDE4 - I really don't think these need to be virtual
+ writeType( str, r );
+
+ r = r.nextSibling().toElement();
+ Q_ASSERT ( r.tagName() == "NAME" );
+ str << r.firstChild().toText().data() << "(";
+
+ bool first = true;
+ r = r.nextSibling().toElement();
+ for( ; !r.isNull(); r = r.nextSibling().toElement() ) {
+ if ( !first )
+ str << ", ";
+ else
+ str << " ";
+ first = false;
+ Q_ASSERT( r.tagName() == "ARG" );
+ QDomElement a = r.firstChild().toElement();
+ writeType( str, a );
+ a = a.nextSibling().toElement();
+ if ( a.tagName() == "NAME" )
+ str << a.firstChild().toText().data();
+ }
+ if ( !first )
+ str << " ";
+ str << ")";
+
+ //const methods stubs can't compile, they need to call setStatus().
+ //if ( n.hasAttribute("qual") )
+ // str << " " << n.attribute("qual");
+ str << ";" << endl;
+ }
+
+ // needed for inherited stubs
+ str << "protected:" << endl;
+ str << " " << className << "() : DCOPStub( never_use ) {}" << endl;
+
+ str << "};" << endl;
+ str << endl;
+
+ for(; namespace_count > 0; --namespace_count )
+ str << "} // namespace" << endl;
+ str << endl;
+ }
+
+ str << "#endif" << endl;
+ stub.close();
+}
+
+// :set expandtab!<RETURN>:set ts=8<RETURN>:set sts=4<RETURN>:set sw=4<RETURN>
diff --git a/dcop/dcopidl2cpp/stubimpl.cpp b/dcop/dcopidl2cpp/stubimpl.cpp
new file mode 100644
index 000000000..22c11527b
--- /dev/null
+++ b/dcop/dcopidl2cpp/stubimpl.cpp
@@ -0,0 +1,277 @@
+/*****************************************************************
+Copyright (c) 1999 Torben Weis <weis@kde.org>
+Copyright (c) 2000 Matthias Ettrich <ettrich@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
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+#include <qdom.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "main.h"
+#include "type.h"
+
+static bool isIntType( const QString& t )
+{
+ return ((t == "int")
+ || (t == "signed int")
+ || (t == "unsigned int")
+ || (t == "uint")
+ || (t == "unsigned")
+ || (t == "signed short int")
+ || (t == "signed short")
+ || (t == "short int")
+ || (t == "short")
+ || (t == "unsigned short int")
+ || (t == "unsigned short")
+ || (t == "ushort")
+ || (t == "long int")
+ || (t == "signed long int")
+ || (t == "long")
+ || (t == "signed long")
+ || (t == "unsigned long int")
+ || (t == "unsigned long")
+ || (t == "ulong")
+ || (t == "char")
+ || (t == "signed char")
+ || (t == "unsigned char"));
+}
+
+/*
+ * Writes the stub implementation
+ */
+void generateStubImpl( const QString& idl, const QString& header, const QString& /*headerBase*/, const QString& filename, QDomElement de )
+{
+ QFile impl( filename );
+ if ( !impl.open( IO_WriteOnly ) )
+ qFatal("Could not write to %s", filename.latin1() );
+
+ QTextStream str( &impl );
+
+ str << "/****************************************************************************" << endl;
+ str << "**" << endl;
+ str << "** DCOP Stub Implementation created by dcopidl2cpp from " << idl << endl;
+ str << "**" << endl;
+ str << "** WARNING! All changes made in this file will be lost!" << endl;
+ str << "**" << endl;
+ str << "*****************************************************************************/" << endl;
+ str << endl;
+
+ str << "#include \"" << header << "\"" << endl;
+ str << "#include <dcopclient.h>" << endl << endl;
+ str << "#include <kdatastream.h>" << endl;
+
+ QDomElement e = de.firstChild().toElement();
+ for( ; !e.isNull(); e = e.nextSibling().toElement() ) {
+ if ( e.tagName() != "CLASS" )
+ continue;
+ QDomElement n = e.firstChild().toElement();
+ Q_ASSERT( n.tagName() == "NAME" );
+ QString classNameBase = n.firstChild().toText().data();
+ QString className_stub = classNameBase + "_stub";
+
+ QString classNameFull = className_stub; // class name with possible namespaces prepended
+ // namespaces will be removed from className now
+ int namespace_count = 0;
+ QString namespace_tmp = className_stub;
+ str << endl;
+ for(;;) {
+ int pos = namespace_tmp.find( "::" );
+ if( pos < 0 ) {
+ className_stub = namespace_tmp;
+ break;
+ }
+ str << "namespace " << namespace_tmp.left( pos ) << " {" << endl;
+ ++namespace_count;
+ namespace_tmp = namespace_tmp.mid( pos + 2 );
+ }
+
+ str << endl;
+
+ // Write constructors
+ str << className_stub << "::" << className_stub << "( const QCString& app, const QCString& obj )" << endl;
+ str << " : ";
+
+ // Always explicitly call DCOPStub constructor, because it's virtual base class.
+ // Calling other ones doesn't matter, as they don't do anything important.
+ str << "DCOPStub( app, obj )" << endl;
+
+ str << "{" << endl;
+ str << "}" << endl << endl;
+
+ str << className_stub << "::" << className_stub << "( DCOPClient* client, const QCString& app, const QCString& obj )" << endl;
+ str << " : ";
+
+ str << "DCOPStub( client, app, obj )" << endl;
+
+ str << "{" << endl;
+ str << "}" << endl << endl;
+
+ str << className_stub << "::" << className_stub << "( const DCOPRef& ref )" << endl;
+ str << " : ";
+
+ str << "DCOPStub( ref )" << endl;
+
+ str << "{" << endl;
+ str << "}" << endl << endl;
+
+ // Write marshalling code
+ QDomElement s = e.firstChild().toElement();
+ for( ; !s.isNull(); s = s.nextSibling().toElement() ) {
+ if (s.tagName() != "FUNC")
+ continue;
+ QDomElement r = s.firstChild().toElement();
+ Q_ASSERT( r.tagName() == "TYPE" );
+ QString result = r.firstChild().toText().data();
+ bool async = result == "ASYNC";
+ if ( async) {
+ result = "void";
+ str << result << " ";
+ } else
+ result = writeType( str, r );
+
+ r = r.nextSibling().toElement();
+ Q_ASSERT ( r.tagName() == "NAME" );
+ QString funcName = r.firstChild().toText().data();
+ str << className_stub << "::" << funcName << "(";
+
+ QStringList args;
+ QStringList argtypes;
+ bool first = true;
+ r = r.nextSibling().toElement();
+ for( ; !r.isNull(); r = r.nextSibling().toElement() ) {
+ if ( !first )
+ str << ", ";
+ else
+ str << " ";
+ first = false;
+ Q_ASSERT( r.tagName() == "ARG" );
+ QDomElement a = r.firstChild().toElement();
+ QString type = writeType( str, a );
+ argtypes.append( type );
+ args.append( QString("arg" ) + QString::number( args.count() ) ) ;
+ str << args.last();
+ }
+ if ( !first )
+ str << " ";
+ str << ")";
+
+ //const methods in a stub can't compile, they need to call setStatus()
+ //if ( s.hasAttribute("qual") )
+ // str << " " << s.attribute("qual");
+ str << endl;
+
+ str << "{" << endl ;
+
+
+ funcName += "(";
+ first = true;
+ for( QStringList::Iterator it = argtypes.begin(); it != argtypes.end(); ++it ){
+ if ( !first )
+ funcName += ",";
+ first = false;
+ funcName += *it;
+ }
+ funcName += ")";
+
+ if ( async ) {
+
+ str << " if ( !dcopClient() ) {"<< endl;
+ str << "\tsetStatus( CallFailed );" << endl;
+ str << "\treturn;" << endl;
+ str << " }" << endl;
+
+ str << " QByteArray data;" << endl;
+ if ( !args.isEmpty() ) {
+ str << " QDataStream arg( data, IO_WriteOnly );" << endl;
+ for( QStringList::Iterator args_count = args.begin(); args_count != args.end(); ++args_count ){
+ str << " arg << " << *args_count << ";" << endl;
+ }
+ }
+
+ str << " dcopClient()->send( app(), obj(), \"" << funcName << "\", data );" << endl;
+ str << " setStatus( CallSucceeded );" << endl;
+
+ } else {
+
+ if ( result != "void" ) {
+ str << " " << result << " result";
+ if (isIntType( result ))
+ str << " = 0";
+ else if (result == "float" || result == "double")
+ str << " = 0.0";
+ else if ( result == "bool" )
+ str << " = false";
+
+ str << ";" << endl;
+ }
+
+ str << " if ( !dcopClient() ) {"<< endl;
+ str << "\tsetStatus( CallFailed );" << endl;
+ if ( result != "void" )
+ str << "\treturn result;" << endl;
+ else
+ str << "\treturn;" << endl;
+ str << " }" << endl;
+
+ str << " QByteArray data, replyData;" << endl;
+ str << " QCString replyType;" << endl;
+
+ if ( !args.isEmpty() ) {
+ str << " QDataStream arg( data, IO_WriteOnly );" << endl;
+ for( QStringList::Iterator args_count = args.begin(); args_count != args.end(); ++args_count ){
+ str << " arg << " << *args_count << ";" << endl;
+ }
+ }
+ str << " if ( dcopClient()->call( app(), obj(), \"" << funcName << "\",";
+ str << " data, replyType, replyData ) ) {" << endl;
+ if ( result != "void" ) {
+ str << "\tif ( replyType == \"" << result << "\" ) {" << endl;
+ str << "\t QDataStream _reply_stream( replyData, IO_ReadOnly );" << endl;
+ str << "\t _reply_stream >> result;" << endl;
+ str << "\t setStatus( CallSucceeded );" << endl;
+ str << "\t} else {" << endl;
+ str << "\t callFailed();" << endl;
+ str << "\t}" << endl;
+ } else {
+ str << "\tsetStatus( CallSucceeded );" << endl;
+ }
+ str << " } else { " << endl;
+ str << "\tcallFailed();" << endl;
+ str << " }" << endl;
+ if ( result != "void" )
+ str << " return result;" << endl;
+ }
+ str << "}" << endl << endl;
+ }
+
+ for(; namespace_count > 0; --namespace_count )
+ str << "} // namespace" << endl;
+ str << endl;
+ }
+ impl.close();
+}
+
+// :set expandtab!<RETURN>:set ts=8<RETURN>:set sts=4<RETURN>:set sw=4<RETURN>
diff --git a/dcop/dcopidl2cpp/type.h b/dcop/dcopidl2cpp/type.h
new file mode 100644
index 000000000..baaacacfb
--- /dev/null
+++ b/dcop/dcopidl2cpp/type.h
@@ -0,0 +1,22 @@
+#ifndef TYPE_H
+#define TYPE_H
+
+#include <qtextstream.h>
+#include <qdom.h>
+
+static QString writeType( QTextStream& str, const QDomElement& r )
+{
+ Q_ASSERT( r.tagName() == "TYPE" );
+ if ( r.hasAttribute( "qleft" ) )
+ str << r.attribute("qleft") << " ";
+ QString t = r.firstChild().toText().data();
+ t = t.replace( ">>", "> >" );
+ str << t;
+ if ( r.hasAttribute( "qright" ) )
+ str << r.attribute("qright") << " ";
+ else
+ str << " ";
+ return t;
+}
+
+#endif
diff --git a/dcop/dcopidlng/Ast.pm b/dcop/dcopidlng/Ast.pm
new file mode 100644
index 000000000..65af89e63
--- /dev/null
+++ b/dcop/dcopidlng/Ast.pm
@@ -0,0 +1,51 @@
+package Ast;
+use strict;
+
+use vars qw/ $this $pack @endCodes /;
+
+#-----------------------------------------------------------------------------
+# This package is used to create a simple Abstract Syntax tree. Each node
+# in the AST is an associative array and supports two kinds of properties -
+# scalars and lists of scalars.
+# See SchemParser.pm for an example of usage.
+# ... Sriram
+#-----------------------------------------------------------------------------
+
+# Constructor
+# e.g AST::New ("personnel")
+# Stores the argument in a property called astNodeName whose sole purpose
+# is to support Print()
+
+sub New {
+ my ($this) = {"astNodeName" => $_[0]};
+ bless ($this);
+ return $this;
+}
+
+# Add a property to this object
+# $astNode->AddProp("className", "Employee");
+
+sub AddProp {
+ my ($this) = $_[0];
+ $this->{$_[1]} = $_[2];
+}
+
+# Equivalent to AddProp, except the property name is associated
+# with a list of values
+# $classAstNode->AddProp("attrList", $attrAstNode);
+
+sub AddPropList {
+ my ($this) = $_[0];
+ if (! exists $this->{$_[1]}) {
+ $this->{$_[1]} = [];
+ }
+ push (@{$this->{$_[1]}}, $_[2]);
+}
+
+# Returns a list of all the property names of this object
+sub GetProps {
+ my ($this) = $_[0];
+ return keys %{$this};
+}
+
+1;
diff --git a/dcop/dcopidlng/Iter.pm b/dcop/dcopidlng/Iter.pm
new file mode 100644
index 000000000..7279a6faf
--- /dev/null
+++ b/dcop/dcopidlng/Iter.pm
@@ -0,0 +1,532 @@
+package Iter;
+
+=head1 Iterator Module
+
+A set of iterator functions for traversing the various trees and indexes.
+Each iterator expects closures that operate on the elements in the iterated
+data structure.
+
+
+=head2 Generic
+
+ Params: $node, &$loopsub, &$skipsub, &$applysub, &$recursesub
+
+Iterate over $node\'s children. For each iteration:
+
+If loopsub( $node, $kid ) returns false, the loop is terminated.
+If skipsub( $node, $kid ) returns true, the element is skipped.
+
+Applysub( $node, $kid ) is called
+If recursesub( $node, $kid ) returns true, the function recurses into
+the current node.
+
+=cut
+
+sub Generic
+{
+ my ( $root, $loopcond, $skipcond, $applysub, $recursecond ) = @_;
+
+ return sub {
+ foreach my $node ( @{$root->{Kids}} ) {
+
+ if ( defined $loopcond ) {
+ return 0 unless $loopcond->( $root, $node );
+ }
+
+ if ( defined $skipcond ) {
+ next if $skipcond->( $root, $node );
+ }
+
+ my $ret = $applysub->( $root, $node );
+ return $ret if defined $ret && $ret;
+
+ if ( defined $recursecond
+ && $recursecond->( $root, $node ) ) {
+ $ret = Generic( $node, $loopcond, $skipcond,
+ $applysub, $recursecond)->();
+ if ( $ret ) {
+ return $ret;
+ }
+ }
+ }
+
+ return 0;
+ };
+}
+
+sub Class
+{
+ my ( $root, $applysub, $recurse ) = @_;
+
+ return Generic( $root, undef,
+ sub {
+ return !( $node->{NodeType} eq "class"
+ || $node->{NodeType} eq "struct" );
+ },
+ $applysub, $recurse );
+}
+
+=head2 Tree
+
+ Params: $root, $recurse?, $commonsub, $compoundsub, $membersub,
+ $skipsub
+
+Traverse the ast tree starting at $root, skipping if skipsub returns true.
+
+Applying $commonsub( $node, $kid),
+then $compoundsub( $node, $kid ) or $membersub( $node, $kid ) depending on
+the Compound flag of the node.
+
+=cut
+
+sub Tree
+{
+ my ( $rootnode, $recurse, $commonsub, $compoundsub, $membersub,
+ $skipsub ) = @_;
+
+ my $recsub = $recurse ? sub { return 1 if $_[1]->{Compound}; }
+ : undef;
+
+ Generic( $rootnode, undef, $skipsub,
+ sub { # apply
+ my ( $root, $node ) = @_;
+ my $ret;
+
+ if ( defined $commonsub ) {
+ $ret = $commonsub->( $root, $node );
+ return $ret if defined $ret;
+ }
+
+ if ( $node->{Compound} && defined $compoundsub ) {
+ $ret = $compoundsub->( $root, $node );
+ return $ret if defined $ret;
+ }
+
+ if( !$node->{Compound} && defined $membersub ) {
+ $ret = $membersub->( $root, $node );
+ return $ret if defined $ret;
+ }
+ return;
+ },
+ $recsub # skip
+ )->();
+}
+
+=head2 LocalCompounds
+
+Apply $compoundsub( $node ) to all locally defined compound nodes
+(ie nodes that are not external to the library being processed).
+
+=cut
+
+sub LocalCompounds
+{
+ my ( $rootnode, $compoundsub ) = @_;
+
+ return unless defined $rootnode && defined $rootnode->{Kids};
+
+ foreach my $kid ( sort { $a->{astNodeName} cmp $b->{astNodeName} }
+ @{$rootnode->{Kids}} ) {
+ next if !defined $kid->{Compound};
+
+ $compoundsub->( $kid ) unless defined $kid->{ExtSource};
+ LocalCompounds( $kid, $compoundsub );
+ }
+}
+
+=head2 Hierarchy
+
+ Params: $node, $levelDownSub, $printSub, $levelUpSub
+
+This allows easy hierarchy traversal and printing.
+
+Traverses the inheritance hierarchy starting at $node, calling printsub
+for each node. When recursing downward into the tree, $levelDownSub($node) is
+called, the recursion takes place, and $levelUpSub is called when the
+recursion call is completed.
+
+=cut
+
+sub Hierarchy
+{
+ my ( $node, $ldownsub, $printsub, $lupsub, $nokidssub ) = @_;
+
+ return if defined $node->{ExtSource}
+ && (!defined $node->{InBy}
+ || !kdocAstUtil::hasLocalInheritor( $node ));
+
+ $printsub->( $node );
+
+ if ( defined $node->{InBy} ) {
+ $ldownsub->( $node );
+
+ foreach my $kid (
+ sort {$a->{astNodeName} cmp $b->{astNodeName}}
+ @{ $node->{InBy} } ) {
+ Hierarchy( $kid, $ldownsub, $printsub, $lupsub );
+ }
+
+ $lupsub->( $node );
+ }
+ elsif ( defined $nokidssub ) {
+ $nokidssub->( $node );
+ }
+
+ return;
+}
+
+=head2
+
+ Call $printsub for each *direct* ancestor of $node.
+ Only multiple inheritance can lead to $printsub being called more than once.
+
+=cut
+sub Ancestors
+{
+ my ( $node, $rootnode, $noancessub, $startsub, $printsub,
+ $endsub ) = @_;
+ my @anlist = ();
+
+ return if $node eq $rootnode;
+
+ if ( !exists $node->{InList} ) {
+ $noancessub->( $node ) unless !defined $noancessub;
+ return;
+ }
+
+ foreach my $innode ( @{ $node->{InList} } ) {
+ my $nref = $innode->{Node}; # real ancestor
+ next if defined $nref && $nref == $rootnode;
+
+ push @anlist, $innode;
+ }
+
+ if ( $#anlist < 0 ) {
+ $noancessub->( $node ) unless !defined $noancessub;
+ return;
+ }
+
+ $startsub->( $node ) unless !defined $startsub;
+
+ foreach my $innode ( sort { $a->{astNodeName} cmp $b->{astNodeName} }
+ @anlist ) {
+
+ # print
+ $printsub->( $innode->{Node}, $innode->{astNodeName},
+ $innode->{Type}, $innode->{TmplType} )
+ unless !defined $printsub;
+ }
+
+ $endsub->( $node ) unless !defined $endsub;
+
+ return;
+
+}
+
+sub Descendants
+{
+ my ( $node, $nodescsub, $startsub, $printsub, $endsub ) = @_;
+
+ if ( !exists $node->{InBy} ) {
+ $nodescsub->( $node ) unless !defined $nodescsub;
+ return;
+ }
+
+
+ my @desclist = ();
+ DescendantList( \@desclist, $node );
+
+ if ( $#desclist < 0 ) {
+ $nodescsub->( $node ) unless !defined $nodescsub;
+ return;
+ }
+
+ $startsub->( $node ) unless !defined $startsub;
+
+ foreach my $innode ( sort { $a->{astNodeName} cmp $b->{astNodeName} }
+ @desclist ) {
+
+ $printsub->( $innode)
+ unless !defined $printsub;
+ }
+
+ $endsub->( $node ) unless !defined $endsub;
+
+ return;
+
+}
+
+sub DescendantList
+{
+ my ( $list, $node ) = @_;
+
+ return unless exists $node->{InBy};
+
+ foreach my $kid ( @{ $node->{InBy} } ) {
+ push @$list, $kid;
+ DescendantList( $list, $kid );
+ }
+}
+
+=head2 DocTree
+
+=cut
+
+sub DocTree
+{
+ my ( $rootnode, $allowforward, $recurse,
+ $commonsub, $compoundsub, $membersub ) = @_;
+
+ Generic( $rootnode, undef,
+ sub { # skip
+ my( $node, $kid ) = @_;
+
+ unless (!(defined $kid->{ExtSource})
+ && ($allowforward || $kid->{NodeType} ne "Forward")
+ && ($main::doPrivate || !($kid->{Access} =~ /private/))
+ && exists $kid->{DocNode} ) {
+
+ return 1;
+ }
+
+ return;
+ },
+ sub { # apply
+ my ( $root, $node ) = @_;
+
+ my $ret;
+
+ if ( defined $commonsub ) {
+ $ret = $commonsub->( $root, $node );
+ return $ret if defined $ret;
+ }
+
+ if ( $node->{Compound} && defined $compoundsub ) {
+ $ret = $compoundsub->( $root, $node );
+ return $ret if defined $ret;
+ }
+ elsif( defined $membersub ) {
+ $ret = $membersub->( $root, $node );
+ return $ret if defined $ret;
+ }
+
+ return;
+ },
+ sub { return 1 if $recurse; return; } # recurse
+ )->();
+
+}
+
+sub MembersByType
+{
+ my ( $node, $startgrpsub, $methodsub, $endgrpsub, $nokidssub ) = @_;
+
+# public
+ # types
+ # data
+ # methods
+ # signals
+ # slots
+ # static
+# protected
+# private (if enabled)
+
+ if ( !defined $node->{Kids} ) {
+ $nokidssub->( $node ) if defined $nokidssub;
+ return;
+ }
+
+ foreach my $acc ( qw/public protected private/ ) {
+ next if $acc eq "private" && !$main::doPrivate;
+ $access = $acc;
+
+ my @types = ();
+ my @data = ();
+ my @signals = ();
+ my @k_dcops = ();
+ my @k_dcop_signals = ();
+ my @k_dcop_hiddens = ();
+ my @slots =();
+ my @methods = ();
+ my @static = ();
+ my @modules = ();
+ my @interfaces = ();
+
+ # Build lists
+ foreach my $kid ( @{$node->{Kids}} ) {
+ next unless ( $kid->{Access} =~ /$access/
+ && !$kid->{ExtSource})
+ || ( $access eq "public"
+ && ( $kid->{Access} eq "signals"
+ || $kid->{Access} =~ "k_dcop" # note the =~
+ || $kid->{Access} eq "K_DCOP"));
+
+ my $type = $kid->{NodeType};
+
+ if ( $type eq "method" ) {
+ if ( $kid->{Flags} =~ "s" ) {
+ push @static, $kid;
+ }
+ elsif ( $kid->{Flags} =~ "l" ) {
+ push @slots, $kid;
+ }
+ elsif ( $kid->{Flags} =~ "n" ) {
+ push @signals, $kid;
+ }
+ elsif ( $kid->{Flags} =~ "d" ) {
+ push @k_dcops, $kid;
+ }
+ elsif ( $kid->{Flags} =~ "z" ) {
+ push @k_dcop_signals, $kid;
+ }
+ elsif ( $kid->{Flags} =~ "y" ) {
+ push @k_dcop_hiddens, $kid;
+ }
+ else {
+ push @methods, $kid; }
+ }
+ elsif ( $kid->{Compound} ) {
+ if ( $type eq "module" ) {
+ push @modules, $kid;
+ }
+ elsif ( $type eq "interface" ) {
+ push @interfaces, $kid;
+ }
+ else {
+ push @types, $kid;
+ }
+ }
+ elsif ( $type eq "typedef" || $type eq "enum" ) {
+ push @types, $kid;
+ }
+ else {
+ push @data, $kid;
+ }
+ }
+
+ # apply
+ $uc_access = ucfirst( $access );
+
+ doGroup( "$uc_access Types", $node, \@types, $startgrpsub,
+ $methodsub, $endgrpsub);
+ doGroup( "Modules", $node, \@modules, $startgrpsub,
+ $methodsub, $endgrpsub);
+ doGroup( "Interfaces", $node, \@interfaces, $startgrpsub,
+ $methodsub, $endgrpsub);
+ doGroup( "$uc_access Methods", $node, \@methods, $startgrpsub,
+ $methodsub, $endgrpsub);
+ doGroup( "$uc_access Slots", $node, \@slots, $startgrpsub,
+ $methodsub, $endgrpsub);
+ doGroup( "Signals", $node, \@signals, $startgrpsub,
+ $methodsub, $endgrpsub);
+ doGroup( "k_dcop", $node, \@k_dcops, $startgrpsub,
+ $methodsub, $endgrpsub);
+ doGroup( "k_dcop_signals", $node, \@k_dcop_signals, $startgrpsub,
+ $methodsub, $endgrpsub);
+ doGroup( "k_dcop_hiddens", $node, \@k_dcop_hiddens, $startgrpsub,
+ $methodsub, $endgrpsub);
+ doGroup( "$uc_access Static Methods", $node, \@static,
+ $startgrpsub, $methodsub, $endgrpsub);
+ doGroup( "$uc_access Members", $node, \@data, $startgrpsub,
+ $methodsub, $endgrpsub);
+ }
+}
+
+sub doGroup
+{
+ my ( $name, $node, $list, $startgrpsub, $methodsub, $endgrpsub ) = @_;
+
+ my ( $hasMembers ) = 0;
+ foreach my $kid ( @$list ) {
+ if ( !exists $kid->{DocNode}->{Reimplemented} ) {
+ $hasMembers = 1;
+ break;
+ }
+ }
+ return if !$hasMembers;
+
+ if ( defined $methodsub ) {
+ foreach my $kid ( @$list ) {
+ if ( !exists $kid->{DocNode}->{Reimplemented} ) {
+ $methodsub->( $node, $kid );
+ }
+ }
+ }
+
+ $endgrpsub->( $name ) if defined $endgrpsub;
+}
+
+sub ByGroupLogical
+{
+ my ( $root, $startgrpsub, $itemsub, $endgrpsub ) = @_;
+
+ return 0 unless defined $root->{Groups};
+
+ foreach my $groupname ( sort keys %{$root->{Groups}} ) {
+ next if $groupname eq "astNodeName"||$groupname eq "NodeType";
+
+ my $group = $root->{Groups}->{ $group };
+ next unless $group->{Kids};
+
+ $startgrpsub->( $group->{astNodeName}, $group->{Desc} );
+
+ foreach my $kid (sort {$a->{astNodeName} cmp $b->{astNodeName}}
+ @group->{Kids} ) {
+ $itemsub->( $root, $kid );
+ }
+ $endgrpsub->( $group->{Desc} );
+ }
+
+ return 1;
+}
+
+sub SeeAlso
+{
+ my ( $node, $nonesub, $startsub, $printsub, $endsub ) = @_;
+
+ if( !defined $node ) {
+ $nonesub->();
+ return;
+ }
+
+ my $doc = $node;
+
+ if ( $node->{NodeType} ne "DocNode" ) {
+ $doc = $node->{DocNode};
+ if ( !defined $doc ) {
+ $nonesub->() if defined $nonesub;
+ return;
+ }
+ }
+
+ if ( !defined $doc->{See} ) {
+ $nonesub->() if defined $nonesub;
+ return;
+ }
+
+ my $see = $doc->{See};
+ my $ref = $doc->{SeeRef};
+
+ if ( $#$see < 1 ) {
+ $nonesub->() if defined $nonesub;
+ return;
+ }
+
+ $startsub->( $node ) if defined $startsub;
+
+ for my $i ( 0..$#$see ) {
+ my $seelabel = $see->[ $i ];
+ my $seenode = undef;
+ if ( defined $ref ) {
+ $seenode = $ref->[ $i ];
+ }
+
+ $printsub->( $seelabel, $seenode ) if defined $printsub;
+ }
+
+ $endsub->( $node ) if defined $endsub;
+
+ return;
+}
+
+1;
diff --git a/dcop/dcopidlng/Makefile.am b/dcop/dcopidlng/Makefile.am
new file mode 100644
index 000000000..69aefdac2
--- /dev/null
+++ b/dcop/dcopidlng/Makefile.am
@@ -0,0 +1,8 @@
+bin_SCRIPTS = dcopidlng
+
+dcopidlnglib_DATA = Ast.pm Iter.pm kalyptusCxxToDcopIDL.pm kdocAstUtil.pm kdocParseDoc.pm kdocUtil.pm
+dcopidlnglib_SCRIPTS = kalyptus
+dcopidlnglibdir = $(kde_datadir)/dcopidlng
+
+check-local:
+ $(srcdir)/run_test.sh $(srcdir)
diff --git a/dcop/dcopidlng/dcopidlng b/dcop/dcopidlng/dcopidlng
new file mode 100755
index 000000000..073614242
--- /dev/null
+++ b/dcop/dcopidlng/dcopidlng
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+trap "rm -f dcopidlng.stderr.$$" 0 1 2 15
+
+if test -z "$KDECONFIG"; then
+ KDECONFIG=kde-config
+fi
+LIBDIR="`$KDECONFIG --install data --expandvars`/dcopidlng"
+perl -I"$LIBDIR" "$LIBDIR/kalyptus" --allow_k_dcop_accessors -f dcopidl $1 2> dcopidlng.stderr.$$
+RET=$?
+if [ $RET -ne 0 ]
+then
+ cat dcopidlng.stderr.$$ >&2
+fi
+exit $RET
diff --git a/dcop/dcopidlng/kalyptus b/dcop/dcopidlng/kalyptus
new file mode 100644
index 000000000..9a3709fc0
--- /dev/null
+++ b/dcop/dcopidlng/kalyptus
@@ -0,0 +1,1612 @@
+#!/usr/bin/perl -I/Users/duke/src/kde/kdebindings/kalyptus
+# -*- indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
+
+# KDOC -- C++ and CORBA IDL interface documentation tool.
+# Sirtaj Singh Kang <taj@kde.org>, Jan 1999.
+# $Id$
+
+# All files in this project are distributed under the GNU General
+# Public License. This is Free Software.
+
+require 5.000;
+
+use Carp;
+use Getopt::Long;
+use File::Basename;
+use strict;
+
+use Ast;
+
+use kdocUtil;
+use kdocAstUtil;
+use kdocParseDoc;
+
+use vars qw/ %rootNodes $declNodeType @includes_list %options @formats_wanted $allow_k_dcop_accessors
+ $skipInternal %defines $defines $match_qt_defines
+ $libname $outputdir $parse_global_space $striphpath $doPrivate $readstdin
+ $Version $quiet $debug $debuggen $parseonly $currentfile $cSourceNode $exe
+ %formats %flagnames @allowed_k_dcop_accesors $allowed_k_dcop_accesors_re $rootNode
+ @classStack $cNode $globalSpaceClassName
+ $lastLine $docNode @includes $cpp $defcppcmd $cppcmd $docincluded
+ $inExtern $inNamespace %stats %definitions @inputqueue @codeqobject /;
+
+## globals
+
+%rootNodes = (); # root nodes for each file type
+$declNodeType = undef; # last declaration type
+
+@includes_list = (); # list of files included from the parsed .h
+
+# All options
+
+%options = (); # hash of options (set getopt below)
+@formats_wanted = ();
+
+$libname = "";
+$outputdir = ".";
+
+$striphpath = 0;
+
+$doPrivate = 0;
+$Version = "0.9";
+
+$quiet = 0;
+$debug = 0;
+$debuggen = 0;
+$parseonly = 0;
+$globalSpaceClassName = "QGlobalSpace";
+
+$currentfile = "";
+
+$cpp = 0;
+$defcppcmd = "g++ -Wp,-C -E";
+$cppcmd = "";
+
+$exe = basename $0;
+
+@inputqueue = ();
+@codeqobject = split "\n", <<CODE;
+public:
+ virtual QMetaObject *metaObject() const;
+ virtual const char *className() const;
+ virtual void* qt_cast( const char* );
+ virtual bool qt_invoke( int, QUObject* );
+ virtual bool qt_emit( int, QUObject* );
+ virtual bool qt_property( int, int, QVariant* );
+ static QMetaObject* staticMetaObject();
+ QObject* qObject();
+ static QString tr( const char *, const char * = 0 );
+ static QString trUtf8( const char *, const char * = 0 );
+private:
+CODE
+
+# Supported formats
+%formats = ( "dcopidl" => "kalyptusCxxToDcopIDL" );
+
+# these are for expansion of method flags
+%flagnames = ( v => 'virtual', 's' => 'static', p => 'pure',
+ c => 'const', l => 'slot', i => 'inline', n => 'signal',
+ d => 'k_dcop', z => 'k_dcop_signals', y => 'k_dcop_hidden' );
+
+@allowed_k_dcop_accesors = qw(k_dcop k_dcop_hidden k_dcop_signals);
+$allowed_k_dcop_accesors_re = join("|", @allowed_k_dcop_accesors);
+
+%definitions = {
+ _STYLE_CDE => '',
+ _STYLE_MOTIF => '',
+ _STYLE_MOTIF_PLUS => '',
+ PLUS => '',
+ _STYLE_PLATINUM => '',
+ _STYLE_SGI => '',
+ _STYLE_WINDOWS => '',
+ QT_STATIC_CONST => 'static const',
+ Q_EXPORT => '',
+ Q_REFCOUNT => '',
+ QM_EXPORT_CANVAS => '',
+ QM_EXPORT_DNS => '',
+ QM_EXPORT_ICONVIEW => '',
+ QM_EXPORT_NETWORK => '',
+ QM_EXPORT_SQL => '',
+ QM_EXPORT_WORKSPACE => '',
+ QT_NO_REMOTE => 'QT_NO_REMOTE',
+ QT_ACCESSIBILITY_SUPPORT => 'QT_ACCESSIBILITY_SUPPORT',
+ Q_WS_X11 => 'Q_WS_X11',
+ Q_DISABLE_COPY => 'Q_DISABLE_COPY',
+ Q_WS_QWS => 'undef',
+ Q_WS_MAC => 'undef',
+ Q_OBJECT => <<'CODE',
+public:
+ virtual QMetaObject *metaObject() const;
+ virtual const char *className() const;
+ virtual bool qt_invoke( int, QUObject* );
+ virtual bool qt_emit( int, QUObject* );
+ static QString tr( const char *, const char * = 0 );
+ static QString trUtf8( const char *, const char * = 0 );
+private:
+CODE
+};
+
+=head1 KDOC -- Source documentation tool
+
+ Sirtaj Singh Kang <taj@kde.org>, Dec 1998.
+
+=cut
+
+# read options
+
+Getopt::Long::config qw( no_ignore_case permute bundling auto_abbrev );
+
+GetOptions( \%options,
+ "format|f=s", \@formats_wanted,
+ "url|u=s",
+ "skip-internal", \$skipInternal,
+ "skip-deprecated|e",
+ "document-all|a",
+ "compress|z",
+ # HTML options
+ "html-cols=i",
+ "html-logo=s",
+
+ "strip-h-path", \$striphpath,
+ "outputdir|d=s", \$outputdir,
+ "stdin|i", \$readstdin,
+ "name|n=s", \$libname,
+ "version|v|V", \&show_version,
+ "private|p", \$doPrivate,
+ "globspace", \$parse_global_space,
+ "allow_k_dcop_accessors", \$allow_k_dcop_accessors,
+
+ "cpp|P", \$cpp,
+ "docincluded", \$docincluded,
+ "cppcmd|C=s", \$cppcmd,
+ "includedir|I=s", \@includes,
+ "define=s", \%defines, # define a single preprocessing symbol
+ "defines=s", \$defines, # file containing preprocessing symbols, one per line
+
+ "quiet|q", \$quiet,
+ "debug|D", \$debug, # debug the parsing
+ "debuggen", \$debuggen, # debug the file generation
+ "parse-only", \$parseonly )
+ || exit 1;
+
+$| = 1 if $debug or $debuggen;
+
+# preprocessor settings
+
+if ( $cppcmd eq "" ) {
+ $cppcmd = $defcppcmd;
+}
+else {
+ $cpp = 1;
+}
+
+if ( $#includes >= 0 && !$cpp ) {
+ die "$exe: --includedir requires --cpp\n";
+}
+
+# Check output formats. HTML is the default
+if( $#formats_wanted < 0 ) {
+ push @formats_wanted, "java";
+}
+
+foreach my $format ( @formats_wanted ) {
+ die "$exe: unsupported format '$format'.\n"
+ if !defined $formats{$format};
+}
+
+if( $defines )
+{
+ open( DEFS, $defines ) or die "Couldn't open $defines: $!\n";
+ my @defs = <DEFS>;
+ chomp @defs;
+ close DEFS;
+ foreach (@defs)
+ {
+ $defines{ $_ } = 1 unless exists $defines{ $_ };
+ }
+}
+
+# Check the %defines hash for QT_* symbols and compile the corresponding RE
+# Otherwise, compile the default ones. Used for filtering in readCxxLine.
+if ( my @qt_defines = map { ($_=~m/^QT_(.*)/)[0] } keys %defines)
+{
+ my $regexp = "m/^#\\s*ifn?def\\s+QT_(?:" . join('|', map { "\$qt_defines[$_]" } 0..$#qt_defines).")/o";
+ $match_qt_defines = eval "sub { my \$s=shift;
+ \$s=~/^#\\s*if(n)?def/ || return 0;
+ if(!\$1) { return \$s=~$regexp ? 0:1 }
+ else { return \$s=~$regexp ? 1:0 }
+ }";
+ die if $@;
+}
+else
+{
+ $match_qt_defines = eval q£
+ sub
+ {
+ my $s = shift;
+ $s =~ m/^\#\s*ifndef\s+QT_NO_(?:REMOTE| # not in the default compile options
+ NIS| # ...
+ XINERAMA|
+ IMAGEIO_(?:MNG|JPEG)|
+ STYLE_(?:MAC|INTERLACE|COMPACT)
+ )/x;
+ }
+ £;
+ die if $@;
+}
+# Check if there any files to process.
+# We do it here to prevent the libraries being loaded up first.
+
+checkFileArgs();
+
+######
+###### main program
+######
+ parseFiles();
+
+ if ( $parseonly ) {
+ print "\n\tParse Tree\n\t------------\n\n";
+ kdocAstUtil::dumpAst( $rootNode );
+ }
+ else {
+ writeDocumentation();
+ }
+
+ kdocAstUtil::printDebugStats() if $debug;
+
+ exit 0;
+######
+
+sub checkFileArgs
+{
+ return unless $#ARGV < 0;
+
+ die "$exe: no input files.\n" unless $readstdin;
+
+ # read filenames from standard input
+ while (<STDIN>) {
+ chop;
+ $_ =~ s,\\,/,g; # back to fwd slash (for Windows)
+ foreach my $file ( split( /\s+/, $_ ) ) {
+ push @ARGV, $file;
+ }
+ }
+}
+
+sub parseFiles
+{
+ foreach $currentfile ( @ARGV ) {
+ my $lang = "CXX";
+
+ if ( $currentfile =~ /\.idl\s*$/ ) {
+ # IDL file
+ $lang = "IDL";
+ }
+
+ # assume cxx file
+ if( $cpp ) {
+ # pass through preprocessor
+ my $cmd = $cppcmd;
+ foreach my $dir ( @includes ) {
+ $cmd .= " -I $dir ";
+ }
+
+ $cmd .= " -DQOBJECTDEFS_H $currentfile";
+
+ open( INPUT, "$cmd |" )
+ || croak "Can't preprocess $currentfile";
+ }
+ else {
+ open( INPUT, "$currentfile" )
+ || croak "Can't read from $currentfile";
+ }
+
+ print STDERR "$exe: processing $currentfile\n" unless $quiet;
+
+ # reset vars
+ $rootNode = getRoot( $lang );
+
+
+ # add to file lookup table
+ my $showname = $striphpath ? basename( $currentfile )
+ : $currentfile;
+ $cSourceNode = Ast::New( $showname );
+ $cSourceNode->AddProp( "NodeType", "source" );
+ $cSourceNode->AddProp( "Path", $currentfile );
+ $rootNode->AddPropList( "Sources", $cSourceNode );
+
+ # reset state
+ @classStack = ();
+ $cNode = $rootNode;
+ $inExtern = 0;
+ $inNamespace = 0;
+
+ # parse
+ my $k = undef;
+ while ( defined ($k = readDecl()) ) {
+ print "\nDecl: <$k>[$declNodeType]\n" if $debug;
+ if( identifyDecl( $k ) && $k =~ /{/ ) {
+ readCxxCodeBlock();
+ }
+ }
+ close INPUT;
+ }
+}
+
+
+sub writeDocumentation
+{
+ foreach my $node ( values %rootNodes ) {
+ # postprocess
+ kdocAstUtil::makeInherit( $node, $node );
+
+ # write
+ no strict "refs";
+ foreach my $format ( @formats_wanted ) {
+ my $pack = $formats{ $format };
+ require $pack.".pm";
+
+ print STDERR "Generating bindings for $format ",
+ "language...\n" if $debug;
+
+ my $f = "$pack\::writeDoc";
+ &$f( $libname, $node, $outputdir, \%options );
+ }
+ }
+}
+
+###### Parser routines
+
+=head2 readSourceLine
+
+ Returns a raw line read from the current input file.
+ This is used by routines outside main, since I don t know
+ how to share fds.
+
+=cut
+
+sub readSourceLine
+{
+ return <INPUT>;
+}
+
+=head2 readCxxLine
+
+ Reads a C++ source line, skipping comments, blank lines,
+ preprocessor tokens and the Q_OBJECT macro
+
+=cut
+
+sub readCxxLine
+{
+ my( $p );
+ my( $l );
+
+ while( 1 ) {
+ $p = shift @inputqueue || <INPUT>;
+ return undef if !defined ($p);
+
+ $p =~ s#//.*$##g; # C++ comment
+ $p =~ s#/\*(?!\*).*?\*/##g; # C comment
+
+ # join all multiline comments
+ if( $p =~ m#/\*(?!\*)#s ) {
+ # unterminated comment
+LOOP:
+ while( defined ($l = <INPUT>) ) {
+ $l =~ s#//.*$##g; # C++ comment
+ $p .= $l;
+ $p =~ s#/\*(?!\*).*?\*/##sg; # C comment
+ last LOOP unless $p =~ m#(/\*(?!\*))|(\*/)#sg;
+ }
+ }
+
+ if ( $p =~ /^\s*Q_OBJECT/ ) {
+ push @inputqueue, @codeqobject;
+ next;
+ }
+ # Hack, waiting for real handling of preprocessor defines
+ $p =~ s/QT_STATIC_CONST/static const/;
+ $p =~ s/KSVG_GET/KJS::Value get();/;
+ $p =~ s/KSVG_BASECLASS_GET/KJS::Value get();/;
+ $p =~ s/KSVG_BRIDGE/KJS::ObjectImp *bridge();/;
+ $p =~ s/KSVG_FORWARDGET/KJS::Value getforward();/;
+ $p =~ s/KSVG_PUT/bool put();/;
+ $p =~ s/KSVG_FORWARDPUT/bool putforward();/;
+ $p =~ s/KSVG_BASECLASS/virtual KJS::Value cache();/;
+ if ( $p =~ m/KSVG_DEFINE_PROTOTYPE\((\w+)\)/ ) {
+ push @inputqueue, split('\n',"namespace KSVG {\nclass $1 {\n};\n};");
+ }
+
+ next if ( $p =~ /^\s*$/s ); # blank lines
+# || $p =~ /^\s*Q_OBJECT/ # QObject macro
+# );
+#
+
+ next if ( $p =~ /^\s*Q_ENUMS/ # ignore Q_ENUMS
+ || $p =~ /^\s*Q_PROPERTY/ # and Q_PROPERTY
+ || $p =~ /^\s*Q_OVERRIDE/ # and Q_OVERRIDE
+ || $p =~ /^\s*Q_SETS/
+ || $p =~ /^\s*Q_DUMMY_COMPARISON_OPERATOR/
+ || $p =~ /^\s*K_SYCOCATYPE/ # and K_SYCOCA stuff
+ || $p =~ /^\s*K_SYCOCAFACTORY/ #
+ || $p =~ /^\s*KSVG_/ # and KSVG stuff ;)
+ || $p =~ /^\s*KDOM_/
+ );
+
+ push @includes_list, $1 if $p =~ /^#include\s+<?(.*?)>?\s*$/;
+
+ # remove all preprocessor macros
+ if( $p =~ /^\s*#\s*(\w+)/ ) {
+ # Handling of preprocessed sources: skip anything included from
+ # other files, unless --docincluded was passed.
+ if (!$docincluded && $p =~ /^\s*#\s*[0-9]+\s*\".*$/
+ && not($p =~ /\"$currentfile\"/)) {
+ # include file markers
+ while( <INPUT> ) {
+ last if(/\"$currentfile\"/);
+ print "Overread $_" if $debug;
+ };
+ print "Cont: $_" if $debug;
+ }
+ else {
+ # Skip platform-specific stuff, or #if 0 stuff
+ # or #else of something we parsed (e.g. for QKeySequence)
+ if ( $p =~ m/^#\s*ifdef\s*Q_WS_/ or
+ $p =~ m/^#\s*if\s+defined\(Q_WS_/ or
+ $p =~ m/^#\s*if\s+defined\(Q_OS_/ or
+ $p =~ m/^#\s*if\s+defined\(Q_CC_/ or
+ $p =~ m/^#\s*if\s+defined\(QT_THREAD_SUPPORT/ or
+ $p =~ m/^#\s*else/ or
+ $p =~ m/^#\s*if\s+defined\(Q_FULL_TEMPLATE_INSTANTIATION/ or
+ $p =~ m/^#\s*ifdef\s+CONTAINER_CUSTOM_WIDGETS/ or
+ &$match_qt_defines( $p ) or
+ $p =~ m/^#\s*if\s+0\s+/ ) {
+ my $if_depth = 1;
+ while ( defined $p && $if_depth > 0 ) {
+ $p = <INPUT>;
+ last if !defined $p;
+ $if_depth++ if $p =~ m/^#\s*if/;
+ $if_depth-- if $p =~ m/^#\s*endif/;
+ # Exit at #else in the #ifdef QT_NO_ACCEL/#else/#endif case
+ last if $if_depth == 1 && $p =~ m/^#\s*else\s/;
+ #ignore elif for now
+ print "Skipping ifdef'ed line: $p" if $debug;
+ }
+ }
+
+ # multiline macros
+ while ( defined $p && $p =~ m#\\\s*$# ) {
+ $p = <INPUT>;
+ }
+ }
+ next;
+ }
+
+ $lastLine = $p;
+ return $p;
+ }
+}
+
+=head2 readCxxCodeBlock
+
+ Reads a C++ code block (recursive curlies), returning the last line
+ or undef on error.
+
+ Parameters: none
+
+=cut
+
+sub readCxxCodeBlock
+{
+# Code: begins in a {, ends in }\s*;?
+# In between: cxx source, including {}
+ my ( $count ) = 0;
+ my $l = undef;
+
+ if ( defined $lastLine ) {
+ print "lastLine: '$lastLine'" if $debug;
+
+ my $open = kdocUtil::countReg( $lastLine, "{" );
+ my $close = kdocUtil::countReg( $lastLine, "}" );
+ $count = $open - $close;
+
+ return $lastLine if ( $open || $close) && $count == 0;
+ }
+
+ # find opening brace
+ if ( $count == 0 ) {
+ while( $count == 0 ) {
+ $l = readCxxLine();
+ return undef if !defined $l;
+ $l =~ s/\\.//g;
+ $l =~ s/'.?'//g;
+ $l =~ s/".*?"//g;
+
+ $count += kdocUtil::countReg( $l, "{" );
+ print "c ", $count, " at '$l'" if $debug;
+ }
+ $count -= kdocUtil::countReg( $l, "}" );
+ }
+
+ # find associated closing brace
+ while ( $count > 0 ) {
+ $l = readCxxLine();
+ croak "Confused by unmatched braces" if !defined $l;
+ $l =~ s/\\.//g;
+ $l =~ s/'.?'//g;
+ $l =~ s/".*?"//g;
+
+ my $add = kdocUtil::countReg( $l, "{" );
+ my $sub = kdocUtil::countReg( $l, "}" );
+ $count += $add - $sub;
+
+ print "o ", $add, " c ", $sub, " at '$l'" if $debug;
+ }
+
+ undef $lastLine;
+ return $l;
+}
+
+=head2 readDecl
+
+ Returns a declaration and sets the $declNodeType variable.
+
+ A decl starts with a type or keyword and ends with [{};]
+ The entire decl is returned in a single line, sans newlines.
+
+ declNodeType values: undef for error, "a" for access specifier,
+ "c" for doc comment, "d" for other decls.
+
+ readCxxLine is used to read the declaration.
+
+=cut
+
+sub readDecl
+{
+ undef $declNodeType;
+ my $l = readCxxLine();
+ my ( $decl ) = "";
+
+ my $allowed_accesors = "private|public|protected|signals";
+ $allowed_accesors .= "|$allowed_k_dcop_accesors_re" if $allow_k_dcop_accessors;
+
+ if( !defined $l ) {
+ return undef;
+ }
+ elsif ( $l =~ /^\s*($allowed_accesors)
+ (\s+\w+)?\s*:/x) { # access specifier
+ $declNodeType = "a";
+ return $l;
+ }
+ elsif ( $l =~ /K_DCOP/ ) {
+ $declNodeType = "k";
+ return $l;
+ }
+ elsif ( $l =~ m#^\s*/\*\*# ) { # doc comment
+ $declNodeType = "c";
+ return $l;
+ }
+
+ do {
+ $decl .= $l;
+
+ if ( $l =~ /[{};]/ ) {
+ $decl =~ s/\n/ /gs;
+ $declNodeType = "d";
+ return $decl;
+ }
+ return undef if !defined ($l = readCxxLine());
+
+ } while ( 1 );
+}
+
+#### AST Generator Routines
+
+=head2 getRoot
+
+ Return a root node for the given type of input file.
+
+=cut
+
+sub getRoot
+{
+ my $type = shift;
+ carp "getRoot called without type" unless defined $type;
+
+ if ( !exists $rootNodes{ $type } ) {
+ my $node = Ast::New( "Global" ); # parent of all nodes
+ $node->AddProp( "NodeType", "root" );
+ $node->AddProp( "RootType", $type );
+ $node->AddProp( "Compound", 1 );
+ $node->AddProp( "KidAccess", "public" );
+
+ $rootNodes{ $type } = $node;
+ }
+ print "getRoot: call for $type\n" if $debug;
+
+ return $rootNodes{ $type };
+}
+
+=head2 identifyDecl
+
+ Parameters: decl
+
+ Identifies a declaration returned by readDecl. If a code block
+ needs to be skipped, this subroutine returns a 1, or 0 otherwise.
+
+=cut
+
+sub identifyDecl
+{
+ my( $decl ) = @_;
+
+ my $newNode = undef;
+ my $skipBlock = 0;
+
+ # Doc comment
+ if ( $declNodeType eq "c" ) {
+ $docNode = kdocParseDoc::newDocComment( $decl );
+
+ # if it's the main doc, it is attached to the root node
+ if ( defined $docNode->{LibDoc} ) {
+ kdocParseDoc::attachDoc( $rootNode, $docNode,
+ $rootNode );
+ undef $docNode;
+ }
+
+ }
+ elsif ( $declNodeType eq "a" ) {
+ newAccess( $decl );
+ }
+ elsif ( $declNodeType eq "k" ) {
+ $cNode->AddProp( "DcopExported", 1 );
+ }
+
+ # Typedef struct/class
+ elsif ( $decl =~ /^\s*typedef
+ \s+(struct|union|class|enum)
+ \s*([_\w\:]*)
+ \s*([;{])
+ /xs ) {
+ my ($type, $name, $endtag, $rest ) = ($1, $2, $3, $' );
+ $name = "--" if $name eq "";
+
+ warn "typedef '$type' n:'$name'\n" if $debug;
+
+ if ( $rest =~ /}\s*([\w_]+(?:::[\w_])*)\s*;/ ) {
+ # TODO: Doesn't parse members yet!
+ $endtag = ";";
+ $name = $1;
+ }
+
+ $newNode = newTypedefComp( $type, $name, $endtag );
+ }
+
+ # Typedef
+ elsif ( $decl =~ /^\s*typedef\s+
+ (?:typename\s+)? # `typename' keyword
+ (.*?\s*[\*&]?) # type
+ \s+([-\w_\:]+) # name
+ \s*((?:\[[-\w_\:<>\s]*\])*) # array
+ \s*[{;]\s*$/xs ) {
+
+ print "Typedef: <$1 $3> <$2>\n" if $debug;
+ $newNode = newTypedef( $1." ".$3, $2 );
+ }
+
+ # Enum
+ elsif ( $decl =~ /^\s*enum\s+([-\w_:]*)?\s*\{(.*)/s ) {
+
+ print "Enum: <$1>\n" if $debug;
+ my $enumname = defined $2 ? $1 : "";
+
+ $newNode = newEnum( $enumname );
+ }
+
+ # Class/Struct
+ elsif ( $decl =~ /^\s*((?:template\s*<.*>)?) # 1 template
+ \s*(class|struct|union|namespace) # 2 struct type
+ \s*([A-Z_]*EXPORT[A-Z_]*)? # 3 export
+ (?:\s*Q_PACKED)?
+ (?:\s*Q_REFCOUNT)?
+ \s+([\w_]+ # 4 name
+ (?:<[\w_ :,]+?>)? # maybe explicit template
+ # (eat chars between <> non-hungry)
+ (?:::[\w_]+)* # maybe nested
+ )
+ ([^\(]*?) # 5 inheritance
+ ([;{])/xs ) { # 6 rest
+
+ print "Class: => [$1]\n\t[$2]\n\t[$3]\n\t[$4]\n\t[$5]\n\t[$6]\n" if $debug;
+ my ( $tmpl, $ntype, $export, $name, $rest, $endtag ) =
+ ( $1, $2, $3, $4, $5, $6 );
+
+ if ($ntype eq 'namespace') {
+ if ($decl =~ /}/) {
+ return 0;
+ }
+ # Set a flag to indicate we're in a multi-line namespace declaration
+ $inNamespace = 1;
+ }
+
+
+ my @inherits = ();
+
+ $tmpl =~ s/<(.*)>/$1/ if $tmpl ne "";
+
+ if( $rest =~ /^\s*:\s*/ ) {
+ # inheritance
+ $rest = $';
+ @inherits = parseInheritance( $rest );
+ }
+
+ $newNode = newClass( $tmpl, $ntype, $export,
+ $name, $endtag, @inherits );
+ }
+ # IDL compound node
+ elsif( $decl =~ /^\s*(module|interface|exception) # struct type
+ \s+([-\w_]+) # name
+ (.*?) # inheritance?
+ ([;{])/xs ) {
+
+ my ( $type, $name, $rest, $fwd, $complete )
+ = ( $1, $2, $3, $4 eq ";" ? 1 : 0,
+ 0 );
+ my @in = ();
+ print "IDL: [$type] [$name] [$rest] [$fwd]\n" if $debug;
+
+ if( $rest =~ /^\s*:\s*/ ) {
+ $rest = $';
+ $rest =~ s/\s+//g;
+ @in = split ",", $rest;
+ }
+ if( $decl =~ /}\s*;/ ) {
+ $complete = 1;
+ }
+
+ $newNode = newIDLstruct( $type, $name, $fwd, $complete, @in );
+ }
+ # Method
+ elsif ( $decl =~ /^\s*(?:(?:class|struct)\s*)?([^=]+?(?:operator\s*(?:\(\)|.?=)\s*)?) # ret+nm
+ \( (.*?) \) # parameters
+ \s*((?:const)?)\s*
+ (?:throw\s*\(.*?\))?
+ \s*((?:=\s*0(?:L?))?)\s* # Pureness. is "0L" allowed?
+ \s*[;{]+/xs ) { # rest
+
+ my $tpn = $1; # type + name
+ my $params = $2;
+ # Remove constructor initializer, that's not in the params
+ if ( $params =~ /\s*\)\s*:\s*/ ) {
+ # Hack: first .* made non-greedy for QSizePolicy using a?(b):c in ctor init
+ $params =~ s/(.*?)\s*\)\s*:\s*.*$/$1/;
+ }
+
+ my $const = $3 eq "" ? 0 : 1;
+ my $pure = $4 eq "" ? 0 : 1;
+ $tpn =~ s/\s+/ /g;
+ $params =~ s/\s+/ /g;
+
+ print "Method: R+N:[$tpn]\n\tP:[$params]\n\t[$const]\n" if $debug;
+
+ if ( $tpn =~ /((?:\w+\s*::\s*)?operator.*?)\s*$/ # operator
+ || $tpn =~ /((?:\w*\s*::\s*~?)?[-\w:]+)\s*$/ ) { # normal
+ my $name = $1;
+ $tpn = $`;
+ $newNode = newMethod( $tpn, $name,
+ $params, $const, $pure );
+ }
+
+ $skipBlock = 1; # FIXME check end token before doing this!
+ }
+ # Using: import namespace
+ elsif ( $decl =~ /^\s*using\s+namespace\s+(\w+)/ ) {
+ newNamespace( $1 );
+
+ }
+
+ # extern block
+ elsif ( $decl =~ /^\s*extern\s*"(.*)"\s*{/ ) {
+ $inExtern = 1 unless $decl =~ /}/;
+ }
+
+ # Single variable
+ elsif ( $decl =~ /^
+ \s*( (?:[\w_:]+(?:\s+[\w_:]+)*? )# type
+ \s*(?:<.+>)? # template
+ \s*(?:[\&\*])? # ptr or ref
+ (?:\s*(?:const|volatile))* )
+ \s*([\w_:]+) # name
+ \s*( (?:\[[^\[\]]*\] (?:\s*\[[^\[\]]*\])*)? ) # array
+ \s*((?:=.*)?) # value
+ \s*([;{])\s*$/xs ) {
+ my $type = $1;
+ my $name = $2;
+ my $arr = $3;
+ my $val = $4;
+ my $end = $5;
+
+ $type =~ s/\s+/ /g;
+
+ if ( $type !~ /^friend\s+class\s*/ ) {
+ print "Var: [$name] type: [$type$arr] val: [$val]\n"
+ if $debug;
+
+ $newNode = newVar( $type.$arr, $name, $val );
+ }
+
+ $skipBlock = 1 if $end eq '{';
+ }
+
+ # Multi variables
+ elsif ( $decl =~ m/^
+ \s*( (?:[\w_:]+(?:\s+[\w_:]+)*? ) # type
+ \s*(?:<.+>)?) # template
+
+ \s*( (?:\s*(?: [\&\*][\&\*\s]*)? # ptr or ref
+ [\w_:]+) # name
+ \s*(?:\[[^\[\]]*\] (?:\s*\[[^\[\]]*\])*)? # array
+ \s*(?:, # extra vars
+ \s*(?: [\&\*][\&\*\s]*)? # ptr or ref
+ \s*(?:[\w_:]+) # name
+ \s*(?:\[[^\[\]]*\] (?:\s*\[[^\[\]]*\])*)? # array
+ )*
+ \s*(?:=.*)?) # value
+ \s*[;]/xs ) {
+
+ my $type = $1;
+ my $names = $2;
+ my $end = $3;
+ my $doc = $docNode;
+
+ print "Multivar: type: [$type] names: [$names] \n" if $debug;
+
+ foreach my $vardecl ( split( /\s*,\s*/, $names ) ) {
+ next unless $vardecl =~ m/
+ \s*((?: [\&\*][\&\*\s]*)?) # ptr or ref
+ \s*([\w_:]+) # name
+ \s*( (?:\[[^\[\]]*\] (?:\s*\[[^\[\]]*\])*)? ) # array
+ \s*((?:=.*)?) # value
+ /xs;
+ my ($ptr, $name, $arr, $val) = ($1, $2, $3, $4);
+
+ print "Split: type: [$type$ptr$arr] ",
+ " name: [$name] val: [$val] \n" if $debug;
+
+ my $node = newVar( $type.$ptr.$arr, $name, $val );
+
+ $docNode = $doc; # reuse docNode for each
+ postInitNode( $node ) unless !defined $node;
+ }
+
+ $skipBlock = 1 if $end eq '{';
+ }
+ # end of an "extern" block
+ elsif ( $decl =~ /^\s*}\s*$/ && $inExtern ) {
+ $inExtern = 0;
+ }
+ # end of an in-block declaration
+ elsif ( $decl =~ /^\s*}\s*(.*?)\s*;\s*$/ || ($decl =~ /^\s*}\s*$/ && $inNamespace) ) {
+
+ if ( $cNode->{astNodeName} eq "--" ) {
+ # structure typedefs should have no name preassigned.
+ # If they do, then the name in
+ # "typedef struct <name> { ..." is kept instead.
+ # TODO: Buglet. You should fix YOUR code dammit. ;)
+
+
+ $cNode->{astNodeName} = $1;
+ my $siblings = $cNode->{Parent}->{KidHash};
+ undef $siblings->{"--"};
+ $siblings->{ $1 } = $cNode;
+ }
+
+ # C++ namespaces end with a '}', and not '};' like classes
+ if ($decl =~ /^\s*}\s*$/ ) {
+ $inNamespace = 0;
+ }
+
+ if ( $#classStack < 0 ) {
+ confess "close decl found, but no class in stack!" ;
+ $cNode = $rootNode;
+ }
+ else {
+ $cNode = pop @classStack;
+ print "end decl: popped $cNode->{astNodeName}\n"
+ if $debug;
+ }
+ }
+ # unidentified block start
+ elsif ( $decl =~ /{/ ) {
+ print "Unidentified block start: $decl\n" if $debug;
+ $skipBlock = 1;
+ }
+ # explicit template instantiation, or friend template
+ elsif ( $decl =~ /(template|friend)\s+class\s+(?:Q[A-Z_]*EXPORT[A-Z_]*\s*)?\w+\s*<.*>\s*;/x ) {
+ # Nothing to be done with those.
+ }
+ else {
+
+ ## decl is unidentified.
+ warn "Unidentified decl: $decl\n";
+ }
+
+ # once we get here, the last doc node is already used.
+ # postInitNode should NOT be called for forward decls
+ postInitNode( $newNode ) unless !defined $newNode;
+
+ return $skipBlock;
+}
+
+sub postInitNode
+{
+ my $newNode = shift;
+
+ carp "Cannot postinit undef node." if !defined $newNode;
+
+ # The reasoning here:
+ # Forward decls never get a source node.
+ # Once a source node is defined, don't assign another one.
+
+ if ( $newNode->{NodeType} ne "Forward" && !defined $newNode->{Source}) {
+ $newNode->AddProp( "Source", $cSourceNode );
+ } elsif ( $newNode->{NodeType} eq "Forward" ) {
+ if ($debug) {
+ print "postInit: skipping fwd: $newNode->{astNodeName}\n";
+ }
+ undef $docNode;
+ return;
+ }
+
+ if( defined $docNode ) {
+ kdocParseDoc::attachDoc( $newNode, $docNode, $rootNode );
+ undef $docNode;
+ }
+}
+
+
+##### Node generators
+
+=head2 newEnum
+
+ Reads the parameters of an enumeration.
+
+ Returns the parameters, or undef on error.
+
+=cut
+
+sub newEnum
+{
+ my ( $enum ) = @_;
+ my $k = undef;
+ my $params = "";
+
+ $k = $lastLine if defined $lastLine;
+
+ if( defined $lastLine && $lastLine =~ /{/ ) {
+ $params = $';
+ if ( $lastLine =~ /}(.*?);/ ) {
+ return initEnum( $enum, $1, $params );
+ }
+ }
+
+ while ( defined ( $k = readCxxLine() ) ) {
+ $params .= $k;
+
+ if ( $k =~ /}(.*?);/ ) {
+ return initEnum( $enum, $1, $params );
+ }
+ }
+
+ return undef;
+}
+
+=head2 initEnum
+
+ Parameters: name, (ref) params
+
+ Returns an initialized enum node.
+
+=cut
+
+sub initEnum
+{
+ my( $name, $end, $params ) = @_;
+
+ ($name = $end) if $name eq "" && $end ne "";
+
+ $params =~ s#\s+# #sg; # no newlines
+ $params =~ s#\s*/\*([^\*]/|\*[^/]|[^\*/])*\*/##g; # strip out comments
+ $params = $1 if $params =~ /^\s*{?(.*)}/;
+ print "$name params: [$params]\n" if $debug;
+
+
+ my ( $node ) = Ast::New( $name );
+ $node->AddProp( "NodeType", "enum" );
+ $node->AddProp( "Params", $params );
+ makeParamList( $node, $params, 1 ); # Adds the ParamList property containing the list of param nodes
+ kdocAstUtil::attachChild( $cNode, $node );
+
+ return $node;
+}
+
+=head2 newIDLstruct
+
+ Parameters: type, name, forward, complete, inherits...
+
+ Handles an IDL structure definition (ie module, interface,
+ exception).
+
+=cut
+
+sub newIDLstruct
+{
+ my ( $type, $name, $fwd, $complete ) = @_;
+
+ my $node = exists $cNode->{KidHash} ?
+ $cNode->{KidHash}->{ $name } : undef;
+
+ if( !defined $node ) {
+ $node = Ast::New( $name );
+ $node->AddProp( "NodeType", $fwd ? "Forward" : $type );
+ $node->AddProp( "KidAccess", "public" );
+ $node->AddProp( "Compound", 1 ) unless $fwd;
+ kdocAstUtil::attachChild( $cNode, $node );
+ }
+ elsif ( $fwd ) {
+ # If we have a node already, we ignore forwards.
+ return undef;
+ }
+ elsif ( $node->{NodeType} eq "Forward" ) {
+ # we are defining a previously forward node.
+ $node->AddProp( "NodeType", $type );
+ $node->AddProp( "Compound", 1 );
+ $node->AddProp( "Source", $cSourceNode );
+ }
+
+ # register ancestors.
+ foreach my $ances ( splice ( @_, 4 ) ) {
+ my $n = kdocAstUtil::newInherit( $node, $ances );
+ }
+
+ if( !( $fwd || $complete) ) {
+ print "newIDL: pushing $cNode->{astNodeName},",
+ " new is $node->{astNodeName}\n"
+ if $debug;
+ push @classStack, $cNode;
+ $cNode = $node;
+ }
+
+ return $node;
+}
+
+=head2 newClass
+
+ Parameters: tmplArgs, cNodeType, export, name, endTag, @inheritlist
+
+ Handles a class declaration (also fwd decls).
+
+=cut
+
+sub newClass
+{
+ my( $tmplArgs, $cNodeType, $export, $name, $endTag ) = @_;
+
+ my $access = "private";
+ $access = "public" if $cNodeType ne "class";
+
+ # try to find an exisiting node, or create a new one
+ # We need to make the fully-qualified-name otherwise findRef will look
+ # for that classname in the global namespace
+ # testcase: class Foo; namespace Bar { class Foo { ... } }
+ my @parents;
+ push @parents, kdocAstUtil::heritage($cNode) if (defined $cNode->{Parent});
+ push @parents, $name;
+ my $fullyQualifiedName = join "::", @parents;
+ print "looking for $fullyQualifiedName\n" if($debug);
+ my $oldnode = kdocAstUtil::findRef( $cNode, $fullyQualifiedName );
+ my $node = defined $oldnode ? $oldnode : Ast::New( $name );
+
+ if ( $endTag ne "{" ) {
+ # forward
+ if ( !defined $oldnode ) {
+ # new forward node
+ $node->AddProp( "NodeType", "Forward" );
+ $node->AddProp( "KidAccess", $access );
+ print "newClass: Attaching $node->{astNodeName} to $cNode->{astNodeName}\n" if $debug;
+ kdocAstUtil::attachChild( $cNode, $node );
+ }
+ return $node;
+ }
+
+ # this is a class declaration
+
+ print "ClassName: $name\n" if $debug;
+
+ $node->AddProp( "NodeType", $cNodeType );
+ $node->AddProp( "Compound", 1 );
+ $node->AddProp( "Source", $cSourceNode );
+
+ if ($cNodeType eq 'namespace') {
+ $node->AddPropList( "Sources", $cSourceNode );
+ }
+
+ $node->AddProp( "KidAccess", $access );
+ $node->AddProp( "Export", $export ) unless $export eq "";
+ $node->AddProp( "Tmpl", $tmplArgs ) unless $tmplArgs eq "";
+
+ if ( !defined $oldnode ) {
+ print "newClass: Attaching $node->{astNodeName} to $cNode->{astNodeName}\n" if $debug;
+ kdocAstUtil::attachChild( $cNode, $node );
+ } else {
+ print "newClass: Already found $node->{astNodeName} in $cNode->{astNodeName}\n" if $debug;
+ }
+
+ # inheritance
+
+ foreach my $ances ( splice (@_, 5) ) {
+ my $type = "";
+ my $name = $ances;
+ my $intmpl = undef;
+
+WORD:
+ foreach my $word ( split ( /([\w:]+(:?\s*<.*>)?)/, $ances ) ) {
+ next WORD unless $word =~ /^[\w:]/;
+ if ( $word =~ /(private|public|protected|virtual)/ ) {
+ $type .= "$1 ";
+ }
+ else {
+
+ if ( $word =~ /<(.*)>/ ) {
+ # FIXME: Handle multiple tmpl args
+ $name = $`;
+ $intmpl = $1;
+ }
+ else {
+ $name = $word;
+ }
+
+ last WORD;
+ }
+ }
+
+ # set inheritance access specifier if none specified
+ if ( $type eq "" ) {
+ $type = $cNodeType eq "class" ? "private ":"public ";
+ }
+ chop $type;
+
+ # attach inheritance information
+ my $n = kdocAstUtil::newInherit( $node, $name );
+ $n->AddProp( "Type", $type );
+
+ $n->AddProp( "TmplType", $intmpl ) if defined $intmpl;
+
+ print "In: $name type: $type, tmpl: $intmpl\n" if $debug;
+ }
+
+ # new current node
+ print "newClass: Pushing $cNode->{astNodeName}, new current node is $node->{astNodeName}\n" if $debug;
+ push ( @classStack, $cNode );
+ $cNode = $node;
+
+ return $node;
+}
+
+
+=head3 parseInheritance
+
+ Param: inheritance decl string
+ Returns: list of superclasses (template decls included)
+
+ This will fail if < and > appear in strings in the decl.
+
+=cut
+
+sub parseInheritance
+{
+ my $instring = shift;
+ my @inherits = ();
+
+ my $accum = "";
+ foreach $instring ( split (/\s*,\s*/, $instring) ) {
+ $accum .= $instring.", ";
+ next unless (kdocUtil::countReg( $accum, "<" )
+ - kdocUtil::countReg( $accum, ">" ) ) == 0;
+
+ # matching no. of < and >, so assume the parent is
+ # complete
+ $accum =~ s/,\s*$//;
+ print "Inherits: '$accum'\n" if $debug;
+ push @inherits, $accum;
+ $accum = "";
+ }
+
+ return @inherits;
+}
+
+
+=head2 newNamespace
+
+ Param: namespace name.
+ Returns nothing.
+
+ Imports a namespace into the current node, for ref searches etc.
+ Triggered by "using namespace ..."
+
+=cut
+
+sub newNamespace
+{
+ $cNode->AddPropList( "ImpNames", shift );
+}
+
+
+
+=head2 newTypedef
+
+ Parameters: realtype, name
+
+ Handles a type definition.
+
+=cut
+
+sub newTypedef
+{
+ my ( $realtype, $name ) = @_;
+
+ my ( $node ) = Ast::New( $name );
+
+ $node->AddProp( "NodeType", "typedef" );
+ $node->AddProp( "Type", $realtype );
+
+ kdocAstUtil::attachChild( $cNode, $node );
+
+ return $node;
+}
+
+=head2 newTypedefComp
+
+ Params: realtype, name endtoken
+
+ Creates a new compound type definition.
+
+=cut
+
+sub newTypedefComp
+{
+ my ( $realtype, $name, $endtag ) = @_;
+
+ my ( $node ) = Ast::New( $name );
+
+ $node->AddProp( "NodeType", "typedef" );
+ $node->AddProp( "Type", $realtype );
+
+ kdocAstUtil::attachChild( $cNode, $node );
+
+ if ( $endtag eq '{' ) {
+ print "newTypedefComp: Pushing $cNode->{astNodeName}\n"
+ if $debug;
+ push ( @classStack, $cNode );
+ $cNode = $node;
+ }
+
+ return $node;
+}
+
+
+=head2 newMethod
+
+ Parameters: retType, name, params, const, pure?
+
+ Handles a new method declaration or definition.
+
+=cut
+BEGIN {
+
+my $theSourceNode = $cSourceNode;
+
+sub newMethod
+{
+ my ( $retType, $name, $params, $const, $pure ) = @_;
+ my $parent = $cNode;
+ my $class;
+
+ print "Cracked: [$retType] [$name]\n\t[$params]\n\t[$const]\n"
+ if $debug;
+
+ if ( $retType =~ /([\w\s_<>,]+)\s*::\s*$/ ) {
+ # check if stuff before :: got into rettype by mistake.
+ $retType = $`;
+ ($name = $1."::".$name);
+ $name =~ s/\s+/ /g;
+ print "New name = \"$name\" and type = '$retType'\n" if $debug;
+ }
+
+ # A 'friend method' declaration isn't a real method declaration
+ return undef if ( $retType =~ /^friend\s+/ || $retType =~ /^friend\s+class\s+/ );
+
+ my $isGlobalSpace = 0;
+
+ if( $name =~ /^\s*(.*?)\s*::\s*(.*?)\s*$/ ) {
+ # Fully qualified method name.
+ $name = $2;
+ $class = $1;
+
+ if( $class =~ /^\s*$/ ) {
+ $parent = $rootNode;
+ }
+ elsif ( $class eq $cNode->{astNodeName} ) {
+ $parent = $cNode;
+ }
+ else {
+ # ALWAYS IGNORE...
+ return undef;
+
+ my $node = kdocAstUtil::findRef( $cNode, $class );
+
+ if ( !defined $node ) {
+ # if we couldn't find the name, try again with
+ # all template parameters stripped off:
+ my $strippedClass = $class;
+ $strippedClass =~ s/<[^<>]*>//g;
+
+ $node = kdocAstUtil::findRef( $cNode, $strippedClass );
+
+ # if still not found: give up
+ if ( !defined $node ) {
+ warn "$exe: Unidentified class: $class ".
+ "in $currentfile\:$.\n";
+ return undef;
+ }
+ }
+
+ $parent = $node;
+ }
+ }
+ # TODO fix for $retType =~ /template<.*?>/
+ elsif( $parse_global_space && $parent->{NodeType} eq "root" && $name !~ /\s*qt_/ && $retType !~ /template\s*<.*?>/ ) {
+ $class = $globalSpaceClassName; # FIXME - sanitize the naming system?
+ $isGlobalSpace = 1;
+
+ my $opsNode = kdocAstUtil::findRef( $cNode, $class );
+ if (!$opsNode) {
+ # manually create a "GlobalSpace" class
+ $opsNode = Ast::New( $class );
+ $opsNode->AddProp( "NodeType", "class" );
+ $opsNode->AddProp( "Compound", 1 );
+ $opsNode->AddProp( "Source", $cSourceNode ); # dummy
+ $opsNode->AddProp( "KidAccess", "public" );
+ kdocAstUtil::attachChild( $cNode, $opsNode );
+ }
+ # Add a special 'Source' property for methods in global space
+ $cNode->AddProp( "Source", $theSourceNode );
+ unless( $theSourceNode == $cSourceNode ) {
+ $theSourceNode = $cSourceNode;
+ $opsNode->AddPropList( "Sources", $theSourceNode ); # sources are scattered across Qt
+ }
+ $parent = $opsNode;
+ }
+
+ # flags
+
+ my $flags = "";
+
+ if( $retType =~ /static/ || $isGlobalSpace ) {
+ $flags .= "s";
+ $retType =~ s/static//g;
+ }
+
+ if( $const && !$isGlobalSpace ) {
+ $flags .= "c";
+ }
+
+ if( $pure ) {
+ $flags .= "p";
+ }
+
+ if( $retType =~ /virtual/ ) {
+ $flags .= "v";
+ $retType =~ s/virtual//g;
+ }
+
+ print "\n" if $flags ne "" && $debug;
+
+ if ( !defined $parent->{KidAccess} ) {
+ warn "'", $parent->{astNodeName}, "' has no KidAccess ",
+ exists $parent->{Forward} ? "(forward)\n" :"\n";
+ }
+
+ # NB, these are =~, so make sure they are listed in correct order
+ if ( $parent->{KidAccess} =~ /slot/ ) {
+ $flags .= "l";
+ }
+ elsif ( $parent->{KidAccess} =~ /k_dcop_signals/ ) {
+ $flags .= "z";
+ }
+ elsif ( $parent->{KidAccess} =~ /k_dcop_hidden/ ) {
+ $flags .= "y";
+ }
+ elsif ( $parent->{KidAccess} =~ /k_dcop/ ) {
+ $flags .= "d";
+ }
+ elsif ( $parent->{KidAccess} =~ /signal/ ) {
+ $flags .= "n";
+ }
+
+ $retType =~ s/QM?_EXPORT[_A-Z]*\s*//;
+ $retType =~ s/inline\s+//;
+ $retType =~ s/extern\s+//;
+ $retType =~ s/^\s*//g;
+ $retType =~ s/\s*$//g;
+ $retType =~ s/^class\s/ /; # Remove redundant class forward decln's
+ $retType =~ s/<class\s/</;
+
+ # node
+
+ my $node = Ast::New( $name );
+ $node->AddProp( "NodeType", "method" );
+ $node->AddProp( "Flags", $flags );
+ $node->AddProp( "ReturnType", $retType );
+ $node->AddProp( "Params", $params ); # The raw string with the whole param list
+ makeParamList( $node, $params, 0 ); # Adds the ParamList property containing the list of param nodes
+
+ $parent->AddProp( "Pure", 1 ) if $pure;
+
+ kdocAstUtil::attachChild( $parent, $node );
+ return $node;
+}
+
+}
+
+=head2 makeParamList
+
+ Parameters:
+ * method (or enum) node
+ * string containing the whole param list
+ * 1 for enums
+
+ Adds a property "ParamList" to the method node.
+ This property contains a list of nodes, one for each parameter.
+
+ Each parameter node has the following properties:
+ * ArgType the type of the argument, e.g. const QString&
+ * ArgName the name of the argument - optionnal
+ * DefaultValue the default value of the argument - optionnal
+
+ For enum values, ArgType is unset, ArgName is the name, DefaultValue its value.
+
+ Author: David Faure <faure@kde.org>
+=cut
+
+sub makeParamList($$$)
+{
+ my ( $methodNode, $params, $isEnum ) = @_;
+ $params =~ s/\s+/ /g; # normalize multiple spaces/tabs into a single one
+ $params =~ s/\s*([\*\&])\s*/$1 /g; # normalize spaces before and after *, &
+ $params =~ s/\s*(,)([^'\s])\s*/$1 $2/g; # And after ',', but not if inside single quotes
+ $params =~ s/^\s*void\s*$//; # foo(void) ==> foo()
+ $params =~ s/^\s*$//;
+ # Make sure the property always exists, makes iteration over it easier
+ $methodNode->AddProp( "ParamList", [] );
+
+ my @args = kdocUtil::splitUnnested( ',', $params);
+
+ my $argId = 0;
+ foreach my $arg ( @args ) {
+ my $argType;
+ my $argName;
+ my $defaultparam;
+ $arg =~ s/\s*([^\s].*[^\s])\s*/$1/; # stripWhiteSpace
+ $arg =~ s/(\w+)\[\]/\* $1/; # Turn [] array into *
+ $arg =~ s/^class //; # Remove any redundant 'class' forward decln's
+
+ # The RE below reads as: = ( string constant or char or cast to numeric literal
+ # or some word/number, with optional bitwise shifts, OR'ed or +'ed flags, and/or function call ).
+ if ( $arg =~ s/\s*=\s*(("[^\"]*")|\([^)]*\)\s*[\+-]?\s*[0-9]+|(\'.\')|(([-\w:~]*)\s*([<>\|\+-]*\s*[\w._]*\s*)*(\([^(]*\))?))// ) {
+ $defaultparam = $1;
+ }
+
+ if (defined $defaultparam && $isEnum) {
+ # Remove any casts in enum values, for example this in kfileitem.h:
+ # 'enum { Unknown = (mode_t) - 1 };'
+ $defaultparam =~ s/\([^\)]+\)(.*[0-9].*)/$1/;
+ }
+
+ # Separate arg type from arg name, if the latter is specified
+ if ( $arg =~ /(.*)\s+([\w_]+)\s*$/ || $arg =~ /(.*)\(\s*\*\s([\w_]+)\)\s*\((.*)\)\s*$/ ) {
+ if ( defined $3 ) { # function pointer
+ $argType = $1."(*)($3)";
+ $argName = $2;
+ } else {
+ $argType = $1;
+ $argName = $2;
+ }
+ } else { # unnamed arg - or enum value
+ $argType = $arg if (!$isEnum);
+ $argName = $arg if ($isEnum);
+ }
+ $argId++;
+
+ my $node = Ast::New( $argId ); # let's make the arg index the node "name"
+ $node->AddProp( "NodeType", "param" );
+ $node->AddProp( "ArgType", $argType );
+ $node->AddProp( "ArgName", $argName ) if (defined $argName);
+ $node->AddProp( "DefaultValue", $defaultparam ) if (defined $defaultparam);
+ $methodNode->AddPropList( "ParamList", $node );
+ #print STDERR "ArgType: $argType ArgName: $argName\n" if ($debug);
+ }
+}
+
+=head2 newAccess
+
+ Parameters: access
+
+ Sets the default "Access" specifier for the current class node. If
+ the access is a "slot" type, "_slots" is appended to the access
+ string.
+
+=cut
+
+sub newAccess
+{
+ my ( $access ) = @_;
+
+ return undef unless ($access =~ /^\s*(\w+)\s*(slots|$allowed_k_dcop_accesors_re)?/);
+
+ print "Access: [$1] [$2]\n" if $debug;
+
+ $access = $1;
+
+ if ( defined $2 && $2 ne "" ) {
+ $access .= "_" . $2;
+ }
+
+ $cNode->AddProp( "KidAccess", $access );
+
+ return $cNode;
+}
+
+
+=head2 newVar
+
+ Parameters: type, name, value
+
+ New variable. Value is ignored if undef
+
+=cut
+
+sub newVar
+{
+ my ( $type, $name, $val ) = @_;
+
+ my $node = Ast::New( $name );
+ $node->AddProp( "NodeType", "var" );
+
+ my $static = 0;
+ if ( $type =~ /static/ ) {
+ # $type =~ s/static//;
+ $static = 1;
+ }
+
+ $node->AddProp( "Type", $type );
+ $node->AddProp( "Flags", 's' ) if $static;
+ $node->AddProp( "Value", $val ) if defined $val;
+ kdocAstUtil::attachChild( $cNode, $node );
+
+ return $node;
+}
+
+
+
+=head2 show_version
+
+ Display short version information and quit.
+
+=cut
+
+sub show_version
+{
+ die "$exe: $Version (c) Sirtaj S. Kang <taj\@kde.org>\n";
+}
diff --git a/dcop/dcopidlng/kalyptusCxxToDcopIDL.pm b/dcop/dcopidlng/kalyptusCxxToDcopIDL.pm
new file mode 100644
index 000000000..8a2988f06
--- /dev/null
+++ b/dcop/dcopidlng/kalyptusCxxToDcopIDL.pm
@@ -0,0 +1,213 @@
+#***************************************************************************
+# kalyptusCxxToDcopIDL.pm - Generates idl from dcop headers
+# -------------------
+# begin : Fri Jan 25 12:00:00 2000
+# copyright : (C) 2003 Alexander Kellett
+# email : lypanov@kde.org
+# author : Alexander Kellett
+#***************************************************************************/
+
+#/***************************************************************************
+# * *
+# * 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. *
+# * *
+#***************************************************************************/
+
+package kalyptusCxxToDcopIDL;
+
+use File::Path;
+use File::Basename;
+use Carp;
+use Ast;
+use kdocAstUtil;
+use kdocUtil;
+use Iter;
+
+use strict;
+no strict "subs";
+
+use vars qw/$libname $rootnode $outputdir $opt $debug/;
+
+BEGIN
+{
+}
+
+sub writeDoc
+{
+ ( $libname, $rootnode, $outputdir, $opt ) = @_;
+
+ $debug = $main::debuggen;
+
+ print STDERR "Preparsing...\n";
+
+ # Preparse everything, to prepare some additional data in the classes and methods
+ Iter::LocalCompounds( $rootnode, sub { preParseClass( shift ); } );
+
+ kdocAstUtil::dumpAst($rootnode) if ($debug);
+
+ print STDERR "Writing dcopidl...\n";
+
+ print STDOUT "<!DOCTYPE DCOP-IDL><DCOP-IDL>\n";
+
+ print STDOUT "<SOURCE>".@{$rootnode->{Sources}}[0]->{astNodeName}."</SOURCE>\n";
+
+ print STDOUT map { "<INCLUDE>$_</INCLUDE>\n" } @main::includes_list;
+
+ Iter::LocalCompounds( $rootnode, sub {
+ my ($node) = @_;
+
+ my ($methodCode) = generateAllMethods( $node );
+ my $className = join "::", kdocAstUtil::heritage($node);
+
+ if ($node->{DcopExported}) {
+ print STDOUT "<CLASS>\n";
+ print STDOUT " <NAME>$className</NAME>\n";
+ print STDOUT " <LINK_SCOPE>$node->{Export}</LINK_SCOPE>\n" if ($node->{Export});
+ print STDOUT join("\n", map { " <SUPER>$_</SUPER>"; } grep { $_ ne "Global"; }
+ map {
+ my $name = $_->{astNodeName};
+ $name =~ s/</&lt;/;
+ $name =~ s/>/&gt;/;
+ my $tmpl = $_->{TmplType};
+ $tmpl =~ s/</&lt;/;
+ $tmpl =~ s/>/&gt;/;
+ $tmpl ? "$name&lt;<TYPE>$tmpl</TYPE>&gt;" : $name;
+ } @{$node->{InList}}) . "\n";
+ print STDOUT $methodCode;
+
+ print STDOUT "</CLASS>\n";
+ }
+ });
+
+ print STDOUT "</DCOP-IDL>\n";
+
+ print STDERR "Done.\n";
+}
+
+=head2 preParseClass
+ Called for each class
+=cut
+sub preParseClass
+{
+ my( $classNode ) = @_;
+ my $className = join( "::", kdocAstUtil::heritage($classNode) );
+
+ if( $#{$classNode->{Kids}} < 0 ||
+ $classNode->{Access} eq "private" ||
+ $classNode->{Access} eq "protected" || # e.g. QPixmap::QPixmapData
+ exists $classNode->{Tmpl} ||
+ $classNode->{NodeType} eq 'union' # Skip unions for now, e.g. QPDevCmdParam
+ ) {
+ print STDERR "Skipping $className\n" if ($debug);
+ print STDERR "Skipping union $className\n" if ( $classNode->{NodeType} eq 'union');
+ delete $classNode->{Compound}; # Cheat, to get it excluded from Iter::LocalCompounds
+ return;
+ }
+}
+
+
+sub generateMethod($$)
+{
+ my( $classNode, $m ) = @_; # input
+ my $methodCode = ''; # output
+
+ my $name = $m->{astNodeName}; # method name
+ my @heritage = kdocAstUtil::heritage($classNode);
+ my $className = join( "::", @heritage );
+
+ # Check some method flags: constructor, destructor etc.
+ my $flags = $m->{Flags};
+
+ if ( !defined $flags ) {
+ warn "Method ".$name. " has no flags\n";
+ }
+
+ my $returnType = $m->{ReturnType};
+ $returnType = undef if ($returnType eq 'void');
+
+ # Don't use $className here, it's never the fully qualified (A::B) name for a ctor.
+ my $isConstructor = ($name eq $classNode->{astNodeName} );
+ my $isDestructor = ($returnType eq '~');
+
+ if ($debug) {
+ print STDERR " Method $name";
+ print STDERR ", is DTOR" if $isDestructor;
+ print STDERR ", returns $returnType" if $returnType;
+ #print STDERR " ($m->{Access})";
+ print STDERR "\n";
+ }
+
+ # Don't generate anything for destructors
+ return if $isDestructor;
+
+ my $args = "";
+
+ foreach my $arg ( @{$m->{ParamList}} ) {
+
+ print STDERR " Param ".$arg->{astNodeName}." type: ".$arg->{ArgType}." name:".$arg->{ArgName}." default: ".$arg->{DefaultValue}."\n" if ($debug);
+
+ my $argType = $arg->{ArgType};
+
+ my $x_isConst = ($argType =~ s/const//);
+ my $x_isRef = ($argType =~ s/&//);
+
+ my $typeAttrs = "";
+ $typeAttrs .= " qleft=\"const\"" if $x_isConst;
+ $typeAttrs .= " qright=\"&amp;\"" if $x_isRef;
+
+ $argType =~ s/^\s*(.*?)\s*$/$1/;
+ $argType =~ s/</&lt;/g;
+ $argType =~ s/>/&gt;/g;
+ $argType =~ s/\s//g;
+
+ $args .= " <ARG><TYPE$typeAttrs>$argType</TYPE><NAME>$arg->{ArgName}</NAME></ARG>\n";
+ }
+
+ my $qual = "";
+ $qual .= " qual=\"const\"" if $flags =~ "c";
+
+ $returnType = "void" unless $returnType;
+ $returnType =~ s/</&lt;/g;
+ $returnType =~ s/>/&gt;/g;
+ $returnType =~ s/^\s*const\s*//;
+
+ my $methodCode = "";
+
+ my $tagType = ($flags !~ /z/) ? "FUNC" : "SIGNAL";
+ my $tagAttr = "";
+ $tagAttr .= " hidden=\"yes\"" if $flags =~ /y/;
+
+ if (!$isConstructor) {
+ $methodCode .= " <$tagType$tagAttr$qual>\n";
+ $methodCode .= " <TYPE>$returnType</TYPE>\n";
+ $methodCode .= " <NAME>$name</NAME>\n";
+ $methodCode .= "$args";
+ $methodCode .= " </$tagType>\n";
+ }
+
+ return ( $methodCode );
+}
+
+sub generateAllMethods
+{
+ my ($classNode) = @_;
+ my $methodCode = '';
+
+ # Then all methods
+ Iter::MembersByType ( $classNode, undef,
+ sub { my ($classNode, $methodNode ) = @_;
+
+ if ( $methodNode->{NodeType} eq 'method' ) {
+ next unless $methodNode->{Flags} =~ /(d|z|y)/;
+ my ($meth) = generateMethod( $classNode, $methodNode );
+ $methodCode .= $meth;
+ }
+ }, undef );
+
+ return ( $methodCode );
+}
+
+1;
diff --git a/dcop/dcopidlng/kdocAstUtil.pm b/dcop/dcopidlng/kdocAstUtil.pm
new file mode 100644
index 000000000..ec67ace5f
--- /dev/null
+++ b/dcop/dcopidlng/kdocAstUtil.pm
@@ -0,0 +1,536 @@
+=head1 kdocAstUtil
+
+ Utilities for syntax trees.
+
+=cut
+
+
+package kdocAstUtil;
+
+use Ast;
+use Carp;
+use File::Basename;
+use kdocUtil;
+use Iter;
+use strict;
+
+use vars qw/ $depth $refcalls $refiters @noreflist %noref /;
+
+sub BEGIN {
+# statistics for findRef
+
+ $depth = 0;
+ $refcalls = 0;
+ $refiters = 0;
+
+# findRef will ignore these words
+
+ @noreflist = qw( const int char long double template
+ unsigned signed float void bool true false uint
+ uint32 uint64 extern static inline virtual operator );
+
+ foreach my $r ( @noreflist ) {
+ $noref{ $r } = 1;
+ }
+}
+
+
+=head2 findRef
+
+ Parameters: root, ident, report-on-fail
+ Returns: node, or undef
+
+ Given a root node and a fully qualified identifier (:: separated),
+ this function will try to find a child of the root node that matches
+ the identifier.
+
+=cut
+
+sub findRef
+{
+ my( $root, $name, $r ) = @_;
+
+ confess "findRef: no name" if !defined $name || $name eq "";
+
+ $name =~ s/\s+//g;
+ return undef if exists $noref{ $name };
+
+ $name =~ s/^#//g;
+
+ my ($iter, @tree) = split /(?:\:\:|#)/, $name;
+ my $kid;
+
+ $refcalls++;
+
+ # Upward search for the first token
+ return undef if !defined $iter;
+
+ while ( !defined findIn( $root, $iter ) ) {
+ return undef if !defined $root->{Parent};
+ $root = $root->{Parent};
+ }
+ $root = $root->{KidHash}->{$iter};
+ carp if !defined $root;
+
+ # first token found, resolve the rest of the tree downwards
+ foreach $iter ( @tree ) {
+ confess "iter in $name is undefined\n" if !defined $iter;
+ next if $iter =~ /^\s*$/;
+
+ unless ( defined findIn( $root, $iter ) ) {
+ confess "findRef: failed on '$name' at '$iter'\n"
+ if defined $r;
+ return undef;
+ }
+
+ $root = $root->{KidHash}->{ $iter };
+ carp if !defined $root;
+ }
+
+ return $root;
+}
+
+=head2 findIn
+
+ node, name: search for a child
+
+=cut
+
+sub findIn
+{
+ return undef unless defined $_[0]->{KidHash};
+
+ my $ret = $_[0]->{KidHash}->{ $_[1] };
+
+ return $ret;
+}
+
+
+#
+# Inheritance utilities
+#
+
+=head2 makeInherit
+
+ Parameter: $rootnode, $parentnode
+
+ Make an inheritance graph from the parse tree that begins
+ at rootnode. parentnode is the node that is the parent of
+ all base class nodes.
+
+=cut
+
+sub makeInherit
+{
+ my( $rnode, $parent ) = @_;
+
+ foreach my $node ( @{ $rnode->{Kids} } ) {
+ next if !defined $node->{Compound};
+
+ # set parent to root if no inheritance
+
+ if ( !exists $node->{InList} ) {
+ newInherit( $node, "Global", $parent );
+ $parent->AddPropList( 'InBy', $node );
+
+ makeInherit( $node, $parent );
+ next;
+ }
+
+ # link each ancestor
+ my $acount = 0;
+ANITER:
+ foreach my $in ( @{ $node->{InList} } ) {
+ unless ( defined $in ) {
+ Carp::cluck "warning: $node->{astNodeName} "
+ ." has undef in InList.";
+ next ANITER;
+ }
+
+ my $ref = kdocAstUtil::findRef( $rnode,
+ $in->{astNodeName} );
+
+ if( !defined $ref ) {
+ # ancestor undefined
+ warn "warning: ", $node->{astNodeName},
+ " inherits unknown class '",
+ $in->{astNodeName},"'\n";
+
+ $parent->AddPropList( 'InBy', $node );
+ }
+ else {
+ # found ancestor
+ $in->AddProp( "Node", $ref );
+ $ref->AddPropList( 'InBy', $node );
+ $acount++;
+ }
+ }
+
+ if ( $acount == 0 ) {
+ # inherits no known class: just parent it to global
+ newInherit( $node, "Global", $parent );
+ $parent->AddPropList( 'InBy', $node );
+ }
+ makeInherit( $node, $parent );
+ }
+}
+
+=head2 newInherit
+
+ p: $node, $name, $lnode?
+
+ Add a new ancestor to $node with raw name = $name and
+ node = lnode.
+=cut
+
+sub newInherit
+{
+ my ( $node, $name, $link ) = @_;
+
+ my $n = Ast::New( $name );
+ $n->AddProp( "Node", $link ) unless !defined $link;
+
+ $node->AddPropList( "InList", $n );
+ return $n;
+}
+
+=head2 inheritName
+
+ pr: $inheritance node.
+
+ Returns the name of the inherited node. This checks for existence
+ of a linked node and will use the "raw" name if it is not found.
+
+=cut
+
+sub inheritName
+{
+ my ( $innode ) = @_;
+
+ return defined $innode->{Node} ?
+ $innode->{Node}->{astNodeName}
+ : $innode->{astNodeName};
+}
+
+=head2 inheritedBy
+
+ Parameters: out listref, node
+
+ Recursively searches for nodes that inherit from this one, returning
+ a list of inheriting nodes in the list ref.
+
+=cut
+
+sub inheritedBy
+{
+ my ( $list, $node ) = @_;
+
+ return unless exists $node->{InBy};
+
+ foreach my $kid ( @{ $node->{InBy} } ) {
+ push @$list, $kid;
+ inheritedBy( $list, $kid );
+ }
+}
+
+=head2 hasLocalInheritor
+
+ Parameter: node
+ Returns: 0 on fail
+
+ Checks if the node has an inheritor that is defined within the
+ current library. This is useful for drawing the class hierarchy,
+ since you don't want to display classes that have no relationship
+ with classes within this library.
+
+ NOTE: perhaps we should cache the value to reduce recursion on
+ subsequent calls.
+
+=cut
+
+sub hasLocalInheritor
+{
+ my $node = shift;
+
+ return 0 if !exists $node->{InBy};
+
+ my $in;
+ foreach $in ( @{$node->{InBy}} ) {
+ return 1 if !exists $in->{ExtSource}
+ || hasLocalInheritor( $in );
+ }
+
+ return 0;
+}
+
+
+
+=head2 allMembers
+
+ Parameters: hashref outlist, node, $type
+
+ Fills the outlist hashref with all the methods of outlist,
+ recursively traversing the inheritance tree.
+
+ If type is not specified, it is assumed to be "method"
+
+=cut
+
+sub allMembers
+{
+ my ( $outlist, $n, $type ) = @_;
+ my $in;
+ $type = "method" if !defined $type;
+
+ if ( exists $n->{InList} ) {
+
+ foreach $in ( @{$n->{InList}} ) {
+ next if !defined $in->{Node};
+ my $i = $in->{Node};
+
+ allMembers( $outlist, $i )
+ unless $i == $main::rootNode;
+ }
+ }
+
+ return unless exists $n->{Kids};
+
+ foreach $in ( @{$n->{Kids}} ) {
+ next if $in->{NodeType} ne $type;
+
+ $outlist->{ $in->{astNodeName} } = $in;
+ }
+}
+
+=head2 findOverride
+
+ Parameters: root, node, name
+
+ Looks for nodes of the same name as the parameter, in its parent
+ and the parent's ancestors. It returns a node if it finds one.
+
+=cut
+
+sub findOverride
+{
+ my ( $root, $node, $name ) = @_;
+ return undef if !exists $node->{InList};
+
+ foreach my $in ( @{$node->{InList}} ) {
+ my $n = $in->{Node};
+ next unless defined $n && $n != $root && exists $n->{KidHash};
+
+ my $ref = $n->{KidHash}->{ $name };
+
+ return $n if defined $ref && $ref->{NodeType} eq "method";
+
+ if ( exists $n->{InList} ) {
+ $ref = findOverride( $root, $n, $name );
+ return $ref if defined $ref;
+ }
+ }
+
+ return undef;
+}
+
+=head2 attachChild
+
+ Parameters: parent, child
+
+ Attaches child to the parent, setting Access, Kids
+ and KidHash of respective nodes.
+
+=cut
+
+sub attachChild
+{
+ my ( $parent, $child ) = @_;
+ confess "Attempt to attach ".$child->{astNodeName}." to an ".
+ "undefined parent\n" if !defined $parent;
+
+ $child->AddProp( "Access", $parent->{KidAccess} );
+ $child->AddProp( "Parent", $parent );
+
+ $parent->AddPropList( "Kids", $child );
+
+ if( !exists $parent->{KidHash} ) {
+ my $kh = Ast::New( "LookupTable" );
+ $parent->AddProp( "KidHash", $kh );
+ }
+
+ $parent->{KidHash}->AddProp( $child->{astNodeName},
+ $child );
+}
+
+=head2 makeClassList
+
+ Parameters: node, outlist ref
+
+ fills outlist with a sorted list of all direct, non-external
+ compound children of node.
+
+=cut
+
+sub makeClassList
+{
+ my ( $rootnode, $list ) = @_;
+
+ @$list = ();
+
+ Iter::LocalCompounds( $rootnode,
+ sub {
+ my $node = shift;
+
+ my $her = join ( "::", heritage( $node ) );
+ $node->AddProp( "FullName", $her );
+
+ if ( !exists $node->{DocNode}->{Internal} ||
+ !$main::skipInternal ) {
+ push @$list, $node;
+ }
+ } );
+
+ @$list = sort { $a->{FullName} cmp $b->{FullName} } @$list;
+}
+
+#
+# Debugging utilities
+#
+
+=head2 dumpAst
+
+ Parameters: node, deep
+ Returns: none
+
+ Does a recursive dump of the node and its children.
+ If deep is set, it is used as the recursion property, otherwise
+ "Kids" is used.
+
+=cut
+
+sub dumpAst
+{
+ my ( $node, $deep ) = @_;
+
+ $deep = "Kids" if !defined $deep;
+
+ print "\t" x $depth, $node->{astNodeName},
+ " (", $node->{NodeType}, ")\n";
+
+ my $kid;
+
+ foreach $kid ( $node->GetProps() ) {
+ print "\t" x $depth, " -\t", $kid, " -> ", $node->{$kid},"\n"
+ unless $kid =~ /^(astNodeName|NodeType|$deep)$/;
+ }
+ if ( exists $node->{InList} ) {
+ print "\t" x $depth, " -\tAncestors -> ";
+ foreach my $innode ( @{$node->{InList}} ) {
+ print $innode->{astNodeName} . ",";
+ }
+ print "\n";
+ }
+
+ print "\t" x $depth, " -\n" if (defined $node->{ $deep } && scalar(@{$node->{ $deep }}) != 0);
+
+ $depth++;
+ foreach $kid ( @{$node->{ $deep }} ) {
+ dumpAst( $kid );
+ }
+
+ print "\t" x $depth, "Documentation nodes:\n" if defined
+ @{ $node->{Doc}->{ "Text" }};
+
+ foreach $kid ( @{ $node->{Doc}->{ "Text" }} ) {
+ dumpAst( $kid );
+ }
+
+ $depth--;
+}
+
+=head2 testRef
+
+ Parameters: rootnode
+
+ Interactive testing of referencing system. Calling this
+ will use the readline library to allow interactive entering of
+ identifiers. If a matching node is found, its node name will be
+ printed.
+
+=cut
+
+sub testRef {
+ require Term::ReadLine;
+
+ my $rootNode = $_[ 0 ];
+
+ my $term = new Term::ReadLine 'Testing findRef';
+
+ my $OUT = $term->OUT || *STDOUT{IO};
+ my $prompt = "Identifier: ";
+
+ while( defined ($_ = $term->readline($prompt)) ) {
+
+ my $node = kdocAstUtil::findRef( $rootNode, $_ );
+
+ if( defined $node ) {
+ print $OUT "Reference: '", $node->{astNodeName},
+ "', Type: '", $node->{NodeType},"'\n";
+ }
+ else {
+ print $OUT "No reference found.\n";
+ }
+
+ $term->addhistory( $_ ) if /\S/;
+ }
+}
+
+sub printDebugStats
+{
+ print "findRef: ", $refcalls, " calls, ",
+ $refiters, " iterations.\n";
+}
+
+sub External
+{
+ return defined $_[0]->{ExtSource};
+}
+
+sub Compound
+{
+ return defined $_[0]->{Compound};
+}
+
+sub localComp
+{
+ my ( $node ) = $_[0];
+ return defined $node->{Compound}
+ && !defined $node->{ExtSource}
+ && $node->{NodeType} ne "Forward";
+}
+
+sub hasDoc
+{
+ return defined $_[0]->{DocNode};
+}
+
+### Warning: this returns the list of parents, e.g. the 3 words in KParts::ReadOnlyPart::SomeEnum
+### It has nothing do to with inheritance.
+sub heritage
+{
+ my $node = shift;
+ my @heritage;
+
+ while( 1 ) {
+ push @heritage, $node->{astNodeName};
+
+ last unless defined $node->{Parent};
+ $node = $node->{Parent};
+ last unless defined $node->{Parent};
+ }
+
+ return reverse @heritage;
+}
+
+
+1;
diff --git a/dcop/dcopidlng/kdocParseDoc.pm b/dcop/dcopidlng/kdocParseDoc.pm
new file mode 100644
index 000000000..e5f19d50c
--- /dev/null
+++ b/dcop/dcopidlng/kdocParseDoc.pm
@@ -0,0 +1,419 @@
+package kdocParseDoc;
+
+use Ast;
+use strict;
+
+use vars qw/ $buffer $docNode %extraprops $currentProp $propType /;
+
+=head1 kdocParseDoc
+
+ Routines for parsing of javadoc comments.
+
+=head2 newDocComment
+
+ Parameters: begin (starting line of declaration)
+
+ Reads a doc comment to the end and creates a new doc node.
+
+ Read a line
+ check if it changes the current context
+ yes
+ flush old context
+ check if it is a non-text tag
+ (ie internal/deprecated etc)
+ yes
+ reset context to text
+ set associated property
+ no
+ set the new context
+ assign text to new buffer
+ no add to text buffer
+ continue
+ at end
+ flush anything pending.
+
+=cut
+
+sub newDocComment
+{
+ my( $text ) = @_;
+ return undef unless $text =~ m#/\*\*+#;
+
+ setType( "DocText", 2 );
+ $text =~ m#/\*#; # need to do the match again, otherwise /***/ doesn't parse
+ ### TODO update this method from kdoc
+ $buffer = $'; # everything after the first \*
+ $docNode = undef;
+ %extraprops = (); # used for textprops when flushing.
+ my $finished = 0;
+ my $inbounded = 0;
+
+ if ( $buffer =~ m#\*/# ) {
+ $buffer = $`;
+ $finished = 1;
+ }
+
+PARSELOOP:
+ while ( defined $text && !$finished ) {
+ # read text and remove leading junk
+ $text = main::readSourceLine();
+ next if !defined $text;
+ $text =~ s#^\s*\*(?!\/)##;
+
+# if ( $text =~ /^\s*<\/pre>/i ) {
+# flushProp();
+# $inbounded = 0;
+# }
+ if( $inbounded ) {
+ if ( $text =~ m#\*/# ) {
+ $finished = 1;
+ $text = $`;
+ }
+ $buffer .= $text;
+ next PARSELOOP;
+ }
+# elsif ( $text =~ /^\s*<pre>/i ) {
+# textProp( "Pre" );
+# $inbounded = 1;
+# }
+ elsif ( $text =~ /^\s*$/ ) {
+ textProp( "ParaBreak", "\n" );
+ }
+ elsif ( $text =~ /^\s*\@internal\s*/ ) {
+ codeProp( "Internal", 1 );
+ }
+ elsif ( $text =~ /^\s*\@deprecated\s*/ ) {
+ codeProp( "Deprecated", 1 );
+ }
+ elsif ( $text =~ /^\s*\@reimplemented\s*/ ) {
+ codeProp( "Reimplemented", 1 );
+ }
+ elsif ( $text =~ /^\s*\@group\s*/ ) {
+ # logical group tag in which this node belongs
+ # multiples allowed
+
+ my $groups = $';
+ $groups =~ s/^\s*(.*?)\s*$/$1/;
+
+ if ( $groups ne "" ) {
+ foreach my $g ( split( /[^_\w]+/, $groups) ) {
+
+ codeProp( "InGroup", $g );
+ }
+ }
+ }
+ elsif ( $text =~ /^\s*\@defgroup\s+(\w+)\s*/ ) {
+ # parse group tag and description
+ my $grptag = $1;
+ my $grpdesc = $' eq "" ? $grptag : $';
+
+ # create group node
+ my $grpnode = Ast::New( $grptag );
+ $grpnode->AddProp( "Desc", $grpdesc );
+ $grpnode->AddProp( "NodeType", "GroupDef" );
+
+ # attach
+ codeProp( "Groups", $grpnode );
+ }
+ elsif ( $text =~ /^\s*\@see\s*/ ) {
+ docListProp( "See" );
+ }
+ elsif( $text =~ /^\s*\@short\s*/ ) {
+ docProp( "ClassShort" );
+ }
+ elsif( $text =~ /^\s*\@author\s*/ ) {
+ docProp( "Author" );
+
+ }
+ elsif( $text =~ /^\s*\@version\s*/ ) {
+ docProp( "Version" );
+ }
+ elsif( $text =~ /^\s*\@id\s*/ ) {
+
+ docProp( "Id" );
+ }
+ elsif( $text =~ /^\s*\@since\s*/ ) {
+ docProp( "Since" );
+ }
+ elsif( $text =~ /^\s*\@returns?\s*/ ) {
+ docProp( "Returns" );
+ }
+ elsif( $text =~ /^\s*\@(?:throws|exception|raises)\s*/ ) {
+ docListProp( "Throws" );
+ }
+ elsif( $text =~ /^\s*\@image\s+([^\s]+)\s*/ ) {
+ textProp( "Image" );
+ $extraprops{ "Path" } = $1;
+ }
+ elsif( $text =~ /^\s*\@param\s+(\w+)\s*/ ) {
+ textProp( "Param" );
+ $extraprops{ "Name" } = $1;
+ }
+ elsif( $text =~ /^\s*\@sect\s+/ ) {
+
+ textProp( "DocSection" );
+ }
+ elsif( $text =~ /^\s*\@li\s+/ ) {
+
+ textProp( "ListItem" );
+ }
+ elsif ( $text =~ /^\s*\@libdoc\s+/ ) {
+ # Defines the text for the entire library
+ docProp( "LibDoc" );
+ }
+ else {
+ if ( $text =~ m#\*/# ) {
+ $finished = 1;
+ $text = $`;
+ }
+ $buffer .= $text;
+ }
+ }
+
+ flushProp();
+
+
+ return undef if !defined $docNode;
+
+# postprocess docnode
+
+ # add a . to the end of the short if required.
+ my $short = $docNode->{ClassShort};
+
+ if ( defined $short ) {
+ if ( !($short =~ /\.\s*$/) ) {
+ $docNode->{ClassShort} =~ s/\s*$/./;
+ }
+ }
+ else {
+ # use first line of normal text as short name.
+ if ( defined $docNode->{Text} ) {
+ my $node;
+ foreach $node ( @{$docNode->{Text}} ) {
+ next if $node->{NodeType} ne "DocText";
+ $short = $node->{astNodeName};
+ $short = $`."." if $short =~ /\./;
+ $docNode->{ClassShort} = $short;
+ goto shortdone;
+ }
+ }
+ }
+shortdone:
+
+# Join and break all word list props so that they are one string per list
+# node, ie remove all commas and spaces.
+
+ recombineOnWords( $docNode, "See" );
+ recombineOnWords( $docNode, "Throws" );
+
+ return $docNode;
+}
+
+=head3 setType
+
+ Parameters: propname, proptype ( 0 = single, 1 = list, 2 = text )
+
+ Set the name and type of the pending property.
+
+=cut
+
+sub setType
+{
+ ( $currentProp, $propType ) = @_;
+}
+
+=head3 flushProp
+
+ Flush any pending item and reset the buffer. type is set to DocText.
+
+=cut
+
+sub flushProp
+{
+ return if $buffer eq "";
+ initDocNode() unless defined $docNode;
+
+ if( $propType == 1 ) {
+ # list prop
+ $docNode->AddPropList( $currentProp, $buffer );
+ }
+ elsif ( $propType == 2 ) {
+ # text prop
+ my $textnode = Ast::New( $buffer );
+ $textnode->AddProp( 'NodeType', $currentProp );
+ $docNode->AddPropList( 'Text', $textnode );
+
+ foreach my $prop ( keys %extraprops ) {
+ $textnode->AddProp( $prop,
+ $extraprops{ $prop } );
+ }
+
+ %extraprops = ();
+ }
+ else {
+ # one-off prop
+ $docNode->AddProp( $currentProp, $buffer );
+ }
+
+ # reset buffer
+ $buffer = "";
+ setType( "DocText", 2 );
+}
+
+=head3 codeProp
+
+ Flush the last node, add a new property and reset type to DocText.
+
+=cut
+
+sub codeProp
+{
+ my( $prop, $val ) = @_;
+
+ flushProp();
+
+ initDocNode() unless defined $docNode;
+ $docNode->AddPropList( $prop, $val );
+
+ setType( "DocText", 2 );
+
+}
+
+=head3 docListProp
+
+ The next item is a list property of docNode.
+
+=cut
+
+sub docListProp
+{
+ my( $prop ) = @_;
+
+ flushProp();
+
+ $buffer = $';
+ setType( $prop, 1 );
+}
+
+=head3 docProp
+
+ The next item is a simple property of docNode.
+
+=cut
+
+sub docProp
+{
+ my( $prop ) = @_;
+
+ flushProp();
+
+ $buffer = $';
+ setType( $prop, 0 );
+}
+
+=head3 textProp
+
+ Parameters: prop, val
+
+ Set next item to be a 'Text' list node. if val is assigned, the
+ new node is assigned that text and flushed immediately. If this
+ is the case, the next item is given the 'DocText' text property.
+
+=cut
+
+sub textProp
+{
+ my( $prop, $val ) = @_;
+
+ flushProp();
+
+ if ( defined $val ) {
+ $buffer = $val;
+ setType( $prop, 2 );
+ flushProp();
+ $prop = "DocText";
+ }
+
+ setType( $prop, 2 );
+ $buffer = $';
+}
+
+
+=head3 initDocNode
+
+ Creates docNode if it is not defined.
+
+=cut
+
+sub initDocNode
+{
+ $docNode = Ast::New( "Doc" );
+ $docNode->AddProp( "NodeType", "DocNode" );
+}
+
+sub recombineOnWords
+{
+ my ( $docNode, $prop ) = @_;
+
+ if ( exists $docNode->{$prop} ) {
+ my @oldsee = @{$docNode->{$prop}};
+ @{$docNode->{$prop}} = split (/[\s,]+/, join( " ", @oldsee ));
+ }
+}
+
+###############
+
+=head2 attachDoc
+
+Connects a docnode to a code node, setting any other properties
+if required, such as groups, internal/deprecated flags etc.
+
+=cut
+
+sub attachDoc
+{
+ my ( $node, $doc, $rootnode ) = @_;
+
+ $node->AddProp( "DocNode", $doc );
+ $node->AddProp( "Internal", 1 ) if defined $doc->{Internal};
+ $node->AddProp( "Deprecated", 1 ) if defined $doc->{Deprecated};
+
+ # attach group definitions if they exist
+ if ( defined $doc->{Groups} ) {
+ my $groupdef = $rootnode->{Groups};
+ if( !defined $groupdef ) {
+ $groupdef = Ast::New( "Groups" );
+ $rootnode->AddProp( "Groups", $groupdef );
+ }
+
+ foreach my $grp ( @{$doc->{Groups}} ) {
+ if ( defined $groupdef->{ $grp->{astNodeName} } ) {
+ $groupdef->{ $grp->{ astNodeName}
+ }->AddProp( "Desc", $grp->{Desc} );
+ }
+ else {
+ $groupdef->AddProp( $grp->{astNodeName}, $grp );
+ }
+ }
+ }
+
+ # attach node to group index(es)
+ # create groups if not found, they may be parsed later.
+
+ if ( defined $doc->{InGroup} ) {
+ my $groupdef = $rootnode->{Groups};
+
+ foreach my $grp ( @{$doc->{InGroup}} ) {
+ if ( !exists $groupdef->{$grp} ) {
+ my $newgrp = Ast::New( $grp );
+ $newgrp->AddProp( "Desc", $grp );
+ $newgrp->AddProp( "NodeType", "GroupDef" );
+ $groupdef->AddProp( $grp, $newgrp );
+ }
+
+ $groupdef->{$grp}->AddPropList( "Kids", $node );
+ }
+ }
+}
+
+1;
diff --git a/dcop/dcopidlng/kdocUtil.pm b/dcop/dcopidlng/kdocUtil.pm
new file mode 100644
index 000000000..629147ac3
--- /dev/null
+++ b/dcop/dcopidlng/kdocUtil.pm
@@ -0,0 +1,189 @@
+
+package kdocUtil;
+
+use strict;
+
+
+=head1 kdocUtil
+
+ General utilities.
+
+=head2 countReg
+
+ Parameters: string, regexp
+
+ Returns the number of times of regexp occurs in string.
+
+=cut
+
+sub countReg
+{
+ my( $str, $regexp ) = @_;
+ my( $count ) = 0;
+
+ while( $str =~ /$regexp/s ) {
+ $count++;
+
+ $str =~ s/$regexp//s;
+ }
+
+ return $count;
+}
+
+=head2 findCommonPrefix
+
+ Parameters: string, string
+
+ Returns the prefix common to both strings. An empty string
+ is returned if the strings have no common prefix.
+
+=cut
+
+sub findCommonPrefix
+{
+ my @s1 = split( "/", $_[0] );
+ my @s2 = split( "/", $_[1] );
+ my $accum = "";
+ my $len = ($#s2 > $#s1 ) ? $#s1 : $#s2;
+
+ for my $i ( 0..$len ) {
+# print "Compare: $i '$s1[$i]', '$s2[$i]'\n";
+ last if $s1[ $i ] ne $s2[ $i ];
+ $accum .= $s1[ $i ]."/";
+ }
+
+ return $accum;
+}
+
+=head2 makeRelativePath
+
+ Parameters: localpath, destpath
+
+ Returns a relative path to the destination from the local path,
+ after removal of any common prefix.
+
+=cut
+
+sub makeRelativePath
+{
+ my ( $from, $to ) = @_;
+
+ # remove prefix
+ $from .= '/' unless $from =~ m#/$#;
+ $to .= '/' unless $to =~ m#/$#;
+
+ my $pfx = findCommonPrefix( $from, $to );
+
+ if ( $pfx ne "" ) {
+ $from =~ s/^$pfx//g;
+ $to =~ s/^$pfx//g;
+ }
+# print "Prefix is '$pfx'\n";
+
+ $from =~ s#/+#/#g;
+ $to =~ s#/+#/#g;
+ $pfx = countReg( $from, '\/' );
+
+ my $rel = "../" x $pfx;
+ $rel .= $to;
+
+ return $rel;
+}
+
+sub hostName
+{
+ my $host = "";
+ my @hostenvs = qw( HOST HOSTNAME COMPUTERNAME );
+
+ # Host name
+ foreach my $evar ( @hostenvs ) {
+ next unless defined $ENV{ $evar };
+
+ $host = $ENV{ $evar };
+ last;
+ }
+
+ if( $host eq "" ) {
+ $host = `uname -n`;
+ chop $host;
+ }
+
+ return $host;
+}
+
+sub userName
+{
+ my $who = "";
+ my @userenvs = qw( USERNAME USER LOGNAME );
+
+ # User name
+ foreach my $evar ( @userenvs ) {
+ next unless defined $ENV{ $evar };
+
+ $who = $ENV{ $evar };
+ last;
+ }
+
+ if( $who eq "" ) {
+ if ( $who = `whoami` ) {
+ chop $who;
+ }
+ elsif ( $who - `who am i` ) {
+ $who = ( split (/ /, $who ) )[0];
+ }
+ }
+
+ return $who;
+}
+
+=head2 splitUnnested
+ Helper to split a list using a delimiter, but looking for
+ nesting with (), {}, [] and <>.
+ Example: splitting int a, QPair<c,b> d, e=","
+ on ',' will give 3 items in the list.
+
+ Parameter: delimiter, string
+ Returns: array, after splitting the string
+
+ Thanks to Ashley Winters
+=cut
+sub splitUnnested($$) {
+ my $delim = shift;
+ my $string = shift;
+ my(%open) = (
+ '[' => ']',
+ '(' => ')',
+ '<' => '>',
+ '{' => '}',
+ );
+ my(%close) = reverse %open;
+ my @ret;
+ my $depth = 0;
+ my $start = 0;
+ my $indoublequotes = 0;
+ while($string =~ /($delim|<<|>>|[][}{)(><\"])/g) {
+ my $c = $1;
+ if(!$depth and !$indoublequotes and $c eq $delim) {
+ my $len = pos($string) - $start - 1;
+ push @ret, substr($string, $start, $len);
+ $start = pos($string);
+ } elsif($open{$c}) {
+ $depth++;
+ } elsif($close{$c}) {
+ $depth--;
+ } elsif($c eq '"') {
+ if ($indoublequotes) {
+ $indoublequotes = 0;
+ } else {
+ $indoublequotes = 1;
+ }
+ }
+ }
+
+ my $subs = substr($string, $start);
+ push @ret, $subs if ($subs);
+ return @ret;
+}
+
+1;
+
diff --git a/dcop/dcopidlng/run_test.sh b/dcop/dcopidlng/run_test.sh
new file mode 100755
index 000000000..bfa3aa8b3
--- /dev/null
+++ b/dcop/dcopidlng/run_test.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# Regression testing: generate .kidl out of dcopidl_test.h and compare with expected baseline
+# Usage: $srcdir/run_test.sh $srcdir
+
+srcdir="$1"
+builddir=`pwd`
+# Make a symlink in dcopidlng's builddir, to have "./dcopidl_test.h" in the kidl
+test -f dcopidl_test.h || ln -s $srcdir/../dcopidl/dcopidl_test.h .
+# Note that dcopidlng might not be installed yet, so we can't use the dcopidlng script
+# (which looks into kde's datadir)
+dcopidlng="perl -I$srcdir $srcdir/kalyptus --allow_k_dcop_accessors -f dcopidl"
+$dcopidlng ./dcopidl_test.h > $builddir/dcopidl_new_output.kidl || exit 1
+diff -u $srcdir/../dcopidl/dcopidl_output.kidl $builddir/dcopidl_new_output.kidl
diff --git a/dcop/dcopobject.cpp b/dcop/dcopobject.cpp
new file mode 100644
index 000000000..98a147e9f
--- /dev/null
+++ b/dcop/dcopobject.cpp
@@ -0,0 +1,283 @@
+/*****************************************************************
+
+Copyright (c) 1999,2000 Preston Brown <pbrown@kde.org>
+Copyright (c) 1999 Matthias Ettrich <ettrich@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 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.
+
+******************************************************************/
+
+#include <dcopobject.h>
+#include <dcopclient.h>
+
+QMap<QCString, DCOPObject *> *kde_dcopObjMap = 0;
+
+static inline QMap<QCString, DCOPObject *> *objMap()
+{
+ if (!kde_dcopObjMap)
+ kde_dcopObjMap = new QMap<QCString, DCOPObject *>;
+ return kde_dcopObjMap;
+}
+
+class DCOPObject::DCOPObjectPrivate
+{
+public:
+ DCOPObjectPrivate()
+ { m_signalConnections = 0; m_dcopClient = 0; }
+
+ unsigned int m_signalConnections;
+ DCOPClient *m_dcopClient;
+};
+
+DCOPObject::DCOPObject()
+{
+ d = new DCOPObjectPrivate;
+ ident.sprintf("%p", (void *)this );
+ objMap()->insert(ident, this );
+}
+
+DCOPObject::DCOPObject(QObject *obj)
+{
+ d = new DCOPObjectPrivate;
+ QObject *currentObj = obj;
+ while (currentObj != 0L) {
+ ident.prepend( currentObj->name() );
+ ident.prepend("/");
+ currentObj = currentObj->parent();
+ }
+ if ( ident[0] == '/' )
+ ident = ident.mid(1);
+
+ objMap()->insert(ident, this);
+}
+
+DCOPObject::DCOPObject(const QCString &_objId)
+ : ident(_objId)
+{
+ d = new DCOPObjectPrivate;
+ if ( ident.isEmpty() )
+ ident.sprintf("%p", (void *)this );
+ objMap()->insert(ident, this);
+}
+
+DCOPObject::~DCOPObject()
+{
+ DCOPClient *client = DCOPClient::mainClient();
+ if ( d->m_signalConnections > 0 && client )
+ client->disconnectDCOPSignal( 0, 0, 0, objId(), 0 );
+
+ objMap()->remove(ident);
+ delete d;
+}
+
+DCOPClient *DCOPObject::callingDcopClient()
+{
+ return d->m_dcopClient;
+}
+
+void DCOPObject::setCallingDcopClient(DCOPClient *client)
+{
+ d->m_dcopClient = client;
+}
+
+bool DCOPObject::setObjId(const QCString &objId)
+{
+ if (objMap()->find(objId)!=objMap()->end()) return false;
+
+ DCOPClient *client = DCOPClient::mainClient();
+ if ( d->m_signalConnections > 0 && client )
+ client->disconnectDCOPSignal( 0, 0, 0, ident, 0 );
+
+ objMap()->remove(ident);
+ ident=objId;
+ objMap()->insert(ident,this);
+ return true;
+}
+
+QCString DCOPObject::objId() const
+{
+ return ident;
+}
+
+bool DCOPObject::hasObject(const QCString &_objId)
+{
+ if (objMap()->contains(_objId))
+ return true;
+ else
+ return false;
+}
+
+DCOPObject *DCOPObject::find(const QCString &_objId)
+{
+ QMap<QCString, DCOPObject *>::ConstIterator it;
+ it = objMap()->find(_objId);
+ if (it != objMap()->end())
+ return *it;
+ else
+ return 0L;
+}
+
+QPtrList<DCOPObject> DCOPObject::match(const QCString &partialId)
+{
+ QPtrList<DCOPObject> mlist;
+ QMap<QCString, DCOPObject *>::ConstIterator it(objMap()->begin());
+ for (; it != objMap()->end(); ++it)
+ if (it.key().left(partialId.length()) == partialId) // found it?
+ mlist.append(it.data());
+ return mlist;
+}
+
+
+QCString DCOPObject::objectName( QObject* obj )
+{
+ if ( obj == 0 )
+ return QCString();
+
+ QCString identity;
+
+ QObject *currentObj = obj;
+ while (currentObj != 0 )
+ {
+ identity.prepend( currentObj->name() );
+ identity.prepend("/");
+ currentObj = currentObj->parent();
+ }
+ if ( identity[0] == '/' )
+ identity = identity.mid(1);
+
+ return identity;
+}
+
+bool DCOPObject::process(const QCString &fun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData)
+{
+ if ( fun == "interfaces()" ) {
+ replyType = "QCStringList";
+ QDataStream reply( replyData, IO_WriteOnly );
+ reply << interfaces();
+ return true;
+ } else if ( fun == "functions()" ) {
+ replyType = "QCStringList";
+ QDataStream reply( replyData, IO_WriteOnly );
+ reply << functions();
+ return true;
+ }
+ return processDynamic( fun, data, replyType, replyData );
+}
+
+bool DCOPObject::processDynamic( const QCString&, const QByteArray&, QCString&, QByteArray& )
+{
+ return false;
+}
+QCStringList DCOPObject::interfacesDynamic()
+{
+ QCStringList result;
+ return result;
+}
+
+QCStringList DCOPObject::functionsDynamic()
+{
+ QCStringList result;
+ return result;
+}
+QCStringList DCOPObject::interfaces()
+{
+ QCStringList result = interfacesDynamic();
+ result << "DCOPObject";
+ return result;
+}
+
+QCStringList DCOPObject::functions()
+{
+ QCStringList result = functionsDynamic();
+ result.prepend("QCStringList functions()");
+ result.prepend("QCStringList interfaces()");
+ return result;
+}
+
+void DCOPObject::emitDCOPSignal( const QCString &signal, const QByteArray &data)
+{
+ DCOPClient *client = DCOPClient::mainClient();
+ if ( client )
+ client->emitDCOPSignal( objId(), signal, data );
+}
+
+bool DCOPObject::connectDCOPSignal( const QCString &sender, const QCString &senderObj,
+ const QCString &signal,
+ const QCString &slot,
+ bool Volatile)
+{
+ DCOPClient *client = DCOPClient::mainClient();
+
+ if ( !client )
+ return false;
+
+ d->m_signalConnections++;
+ return client->connectDCOPSignal( sender, senderObj, signal, objId(), slot, Volatile );
+}
+
+bool DCOPObject::disconnectDCOPSignal( const QCString &sender, const QCString &senderObj,
+ const QCString &signal,
+ const QCString &slot)
+{
+ DCOPClient *client = DCOPClient::mainClient();
+
+ if ( !client )
+ return false;
+
+ d->m_signalConnections--;
+ return client->disconnectDCOPSignal( sender, senderObj, signal, objId(), slot );
+}
+
+
+QPtrList<DCOPObjectProxy>* DCOPObjectProxy::proxies = 0;
+
+DCOPObjectProxy::DCOPObjectProxy()
+{
+ if ( !proxies )
+ proxies = new QPtrList<DCOPObjectProxy>;
+ proxies->append( this );
+}
+
+DCOPObjectProxy::DCOPObjectProxy( DCOPClient*)
+{
+ if ( !proxies )
+ proxies = new QPtrList<DCOPObjectProxy>;
+ proxies->append( this );
+}
+
+DCOPObjectProxy:: ~DCOPObjectProxy()
+{
+ if ( proxies )
+ proxies->removeRef( this );
+}
+
+bool DCOPObjectProxy::process( const QCString& /*obj*/,
+ const QCString& /*fun*/,
+ const QByteArray& /*data*/,
+ QCString& /*replyType*/,
+ QByteArray &/*replyData*/ )
+{
+ return false;
+}
+
+void DCOPObject::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void DCOPObjectProxy::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
diff --git a/dcop/dcopobject.h b/dcop/dcopobject.h
new file mode 100644
index 000000000..691ad4e67
--- /dev/null
+++ b/dcop/dcopobject.h
@@ -0,0 +1,410 @@
+/*
+Copyright (c) 1999,2000 Preston Brown <pbrown@kde.org>
+Copyright (c) 1999, 2000 Matthias Ettrich <ettrich@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 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.
+*/
+
+#ifndef _DCOPOBJECT_H
+#define _DCOPOBJECT_H
+
+#include <qobject.h>
+#include <qmap.h>
+#include <qstring.h>
+#include <qptrlist.h>
+#include <qvaluelist.h>
+#include <kdatastream.h> // needed for proper bool marshalling
+#include "kdelibs_export.h"
+
+class DCOPClient;
+typedef QValueList<QCString> QCStringList;
+
+// Makros for DCOP interfaces
+
+#define K_DCOP \
+public: \
+ virtual bool process(const QCString &fun, const QByteArray &data, QCString& replyType, QByteArray &replyData); \
+ QCStringList functions(); \
+ QCStringList interfaces(); \
+private:
+
+#define k_dcop_signals public
+#define k_dcop_hidden public
+#define k_dcop public
+#define ASYNC void
+
+/**
+ * Provides an interface for receiving DCOP messages.
+ *
+ * This class provides an interface for receiving DCOP messages. To use it,
+ * simply multiply-inherit from DCOPObject and from some other class, and
+ * then implement the DCOPObject::process() method. Because this method is
+ * pure virtual, you must implement the method.
+ *
+ * Note that it is usually more convenient to mark a section in the class with
+ * "k_dcop:", add your DCOP methods there and let the IDL compiler do the rest.
+ * Read the tutorials for more information.
+ *
+ * @see DCOPClient
+ * @see DCOPObjectProxy
+ * @author Preston Brown <pbrown@kde.org>, Matthias Ettrich <ettrich@kde.org>
+ */
+class DCOP_EXPORT DCOPObject
+{
+public:
+ /**
+ * Creates a DCOPObject and calculates the object id
+ * using its physical memory address.
+ */
+ DCOPObject();
+ /**
+ * Creates a DCOPObject and calculates the object id
+ * using QObject::name().
+ * @param obj the object to extract the name from
+ */
+ DCOPObject(QObject *obj);
+ /**
+ * Creates a DCOPObject with object Id @p objId.
+ * @param objId the object id of the DCOP object
+ */
+ DCOPObject(const QCString &objId);
+ /**
+ * Destroys the DCOPObject and removes it from the map
+ * of known objects.
+ */
+ virtual ~DCOPObject();
+
+ /**
+ * Returns the object id of the DCOPObject.
+ * @return the object's id
+ */
+ QCString objId() const;
+
+ /**
+ * Renames a dcop object, if no other with the same name exists
+ * Use with care, all dcop signals are disconnected
+ *
+ * @param objId the new object id
+ **/
+ bool setObjId(const QCString &objId);
+
+ /**
+ * Dispatches a message.
+ *
+ * Usually you want to use an IDL
+ * compiler to automatically generate an implementation for
+ * this function.
+ *
+ * If this function returns false, then processDynamic()
+ * is called.
+ *
+ * Note to implementators: remember to call the baseclasses
+ * implementation. It handles the functions "functions()" and
+ * "interfaces()" which return the lists of supported functions
+ * and interfaces, respectively.
+ *
+ * @param fun is the normalized function signature.
+ * Such a signature usually looks like
+ * foobar(QString,int). The return type,
+ * qualifiers like "const" etc. are not part of
+ * the signature.
+ * @param data the received data
+ * @param replyType write the reply type in this string
+ * @param replyData write the reply data in this array
+ * @return true if successful, false otherwise. The default implementation
+ * returns false for all @p fun except "functions()" and
+ * "interfaces()".
+ *
+ * @see DCOPClient::normalizeFunctionSignature()
+ * @see functions()
+ * @see DCOPClient::process()
+ */
+ virtual bool process(const QCString &fun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData);
+
+
+ /**
+ * This function is of interest when you used an IDL compiler
+ * to generate the implementation for process() but
+ * you still want to dispatch some functions dynamically.
+ * Dynamically means that methods may appear and vanish
+ * during runtime.
+ *
+ * @param fun is the normalized function signature.
+ * Such a signature usually looks like
+ * foobar(QString,int). The return type,
+ * qualifiers like "const" etc. are not part of
+ * the signature.
+ * @param data the received data
+ * @param replyType write the reply type in this string
+ * @param replyData write the reply data in this array
+ * @return true if successful, false otherwise. The default implementation
+ * returns always false.
+ * @see process()
+ * @see DCOPClient::normalizeFunctionSignature()
+ * @see functions(),
+ * @see DCOPClient::process()
+ */
+ virtual bool processDynamic(const QCString &fun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData);
+
+ /**
+ * This function is of interest when you used an IDL compiler
+ * to generate the implementation for functions() but
+ * you still want to list some functions dynamically.
+ * Dynamically means that the methods may appear and vanish
+ * during runtime.
+ *
+ * @return A list of the additional functions, default is an empty list.
+ *
+ * @see functions(),
+ */
+ virtual QCStringList functionsDynamic();
+
+ /**
+ * This function is of interest when you used an IDL compiler
+ * to generate the implementation for interfaces() but
+ * you still want to list some interfaces dynamically.
+ * Dynamically means that they may appear and vanish
+ * during runtime.
+ *
+ * @return A list of the additional interfaces, default is an empty list.
+ *
+ * @see interfaces(),
+ */
+ virtual QCStringList interfacesDynamic();
+
+ /**
+ * Returns the names of the interfaces, specific ones last. The
+ * functions gets reimplemented by the IDL compiler. If you don't
+ * use the IDL compiler, consider implementing this function
+ * manually if you want your object to be easily explorable.
+ *
+ * @return a list of interfaces
+ * @see functions()
+ */
+ virtual QCStringList interfaces();
+
+ /**
+ * Returns the list of functions understood by the object. It gets
+ * reimplemented by the IDL compiler. If you don't use the IDL
+ * compiler, consider implementing this function manually if you
+ * want your object to be easily scriptable.
+ *
+ * Rationale: functions() allows an interpreter to do client-side
+ * type-casting properly.
+ *
+ * Note to implementators: remember to call the baseclasses
+ * implementation.
+ *
+ * @return a list of functions
+ * @see interfaces()
+ * @see process()
+ * @see processDynamic()
+ * @see DCOPClient::normalizeFunctionSignature()
+ */
+ virtual QCStringList functions();
+
+ /**
+ * Emit @p signal as DCOP signal from this object with @p data as
+ * arguments
+ * @param signal the signal to emit
+ * @param data the data to send
+ */
+ void emitDCOPSignal( const QCString &signal, const QByteArray &data);
+
+ /**
+ * Connects to a DCOP signal.
+ * @param sender the name of the client that emits the signal. When empty
+ * the signal will be passed from any client.
+ * @param senderObj the name of the sending object that emits the signal.
+ * @param signal the name of the signal. The arguments should match with slot.
+ * @param slot The name of the slot to call. Its arguments should match with signal.
+ * @param Volatile If true, the connection will not be reestablished when
+ * @p sender unregisters and reregisters with DCOP. In this case the @p sender
+ * must be registered when the connection is made.
+ * If false, the connection will be reestablished when @p sender reregisters.
+ * In this case the connection can be made even if @p sender is not registered
+ * at that time.
+ *
+ * @return false if a connection could not be established.
+ * This will be the case when
+ * @li @p Volatile is true and @p sender does not exist.
+ * @li @p signal and @p slot do not have matching arguments.
+ */
+ bool connectDCOPSignal( const QCString &sender, const QCString &senderObj,
+ const QCString &signal,
+ const QCString &slot,
+ bool Volatile);
+
+ /**
+ * Disconnects a DCOP signal.
+ *
+ * A special case is when both @p sender & @p signal are empty. In this
+ * case all connections related to this object in the current client
+ * are disconnected. (Both connections from as well as to this object!)
+ *
+ * @param sender the name of the client that emits the signal.
+ * @param senderObj the name of the object that emits the signal.
+ * If empty all objects will be disconnected.
+ * @param signal the name of the signal. The arguments should match with slot.
+ * If empty all objects will be disconnected.
+ * @param slot The name of the slot the signal is connected to.
+ * If empty all slots will be disconnected.
+ *
+ * @return false if no connection(s) where removed.
+ */
+ bool disconnectDCOPSignal( const QCString &sender, const QCString &senderObj,
+ const QCString &signal,
+ const QCString &slot);
+
+ /**
+ * Returns the DCOPClient responsible for making the call.
+ * Only call this function while you are handling a DCOP call.
+ * @return the DCOPClient responsible for making the call.
+ * This information is only guaranteed to be correct when
+ * entering your DCOP function.
+ * @since 3.1
+ */
+ DCOPClient *callingDcopClient();
+
+ /**
+ * @internal Sets DCOPClient returned by callingDcopClient()
+ * @since 3.1
+ */
+ void setCallingDcopClient(DCOPClient *);
+
+ /**
+ * Checks whether an object with the given id is known in this process.
+ * @return true if an object with the questionable @p objId is
+ * known in this process. This query does not ask proxies.
+ *
+ * DCOPObjectProxy
+ */
+ static bool hasObject(const QCString &objId);
+
+ /**
+ * Try to find a dcop object with the given id.
+ * This function does not query the DCOPObjectProxy.
+ * @param objId the object id to search
+ * @return the DCOPObject for the id @p objId.
+ */
+ static DCOPObject *find(const QCString &objId);
+
+
+ /**
+ * Tries to find an object using a partial object id.
+ * This function is used for multicasting a DCOP message to
+ * several objects inside a single process.
+ *
+ * @param partialId the partial object id to search for
+ * @return a list of DCOPObjects beginning with the string
+ * contained in @p partialId.
+ */
+ static QPtrList<DCOPObject> match(const QCString &partialId);
+
+ /**
+ * Creates an object id for the QObject @p obj. This is done
+ * using the QObject::name() function.
+ * @param obj the object whose name will be used
+ * @return the created object id
+ */
+ static QCString objectName( QObject* obj );
+
+private:
+ /**
+ * The object id of this DCOPObject.
+ */
+ QCString ident;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class DCOPObjectPrivate;
+ DCOPObjectPrivate *d;
+};
+
+class DCOPObjectProxyPrivate;
+/**
+ * You must use a proxy if you want to dispatch method calls for
+ * object IDs which don't have (yet) a corresponding DCOPObject.
+ * This is somewhat like virtual object references in CORBA.
+ *
+ * @see DCOPObject
+ * @see DCOPClient
+ * @author Matthias Ettrich <ettrich@kde.org>
+ */
+class DCOP_EXPORT DCOPObjectProxy
+{
+public:
+ /**
+ * Creates a new proxy.
+ */
+ DCOPObjectProxy();
+
+ /**
+ * Obsolete, do not use. DCOP clients know about object proxies
+ * automatically.
+ *
+ * @deprecated
+ */
+ DCOPObjectProxy( DCOPClient*);
+
+ /**
+ * Destroy the proxy.
+ */
+ virtual ~DCOPObjectProxy();
+
+ /**
+ * Reimplement this method to dispatch method calls.
+ *
+ * This method is called of all proxies if the DCOPClient
+ * knows no object with the id @p obj. If the first proxy returns
+ * @p true, the DCOPClient will no longer call other proxies.
+ *
+ * The object id @p obj may be empty for app-wide function calls no
+ * associated with any object.
+ * @param obj the id of the object
+ * @param fun is the normalized function signature.
+ * Such a signature usually looks like
+ * foobar(QString,int). The return type,
+ * qualifiers like "const" etc. are not part of
+ * the signature.
+ * @param data the received data
+ * @param replyType write the reply type in this string
+ * @param replyData write the reply data in this array
+ * @return true if successful, false otherwise. The default implementation
+ * returns always false.
+ */
+ virtual bool process( const QCString& obj, const QCString& fun,
+ const QByteArray& data,
+ QCString& replyType, QByteArray &replyData );
+private:
+ void* unused;
+ void* unused_too;
+ friend class DCOPClient;
+ static QPtrList<DCOPObjectProxy>* proxies;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ DCOPObjectProxyPrivate* d;
+};
+
+
+
+#endif
diff --git a/dcop/dcopref.cpp b/dcop/dcopref.cpp
new file mode 100644
index 000000000..9e94821fc
--- /dev/null
+++ b/dcop/dcopref.cpp
@@ -0,0 +1,218 @@
+/*****************************************************************
+
+Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+Copyright (c) 1999 Matthias Ettrich <ettrich@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 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.
+
+******************************************************************/
+
+#include "dcopref.h"
+#include "dcopclient.h"
+#include "dcopobject.h"
+
+#include <qdatastream.h>
+
+#define STR( s ) ( s.data() ? s.data() : "" )
+
+bool DCOPReply::typeCheck( const char* t )
+{
+ return typeCheck( t, true );
+}
+
+bool DCOPReply::typeCheck( const char* t, bool warn )
+{
+ if ( type == t )
+ return true;
+ if( warn
+ || strcmp( t, "<unknown>" )) // type not listed in dcoptypes.h
+ qWarning( "WARNING: DCOPReply<%s>: cast to '%s' error",
+ STR( type ), t );
+ return false;
+}
+
+// this has to stay BC too even if private, because it's called from inlines
+DCOPReply DCOPRef::callInternal( const QCString& fun, const QCString& args, const QByteArray& data )
+{
+ return callInternal( fun, args, data, NoEventLoop, -1 );
+}
+
+DCOPReply DCOPRef::callInternal( const QCString& fun, const QCString& args, const QByteArray& data,
+ EventLoopFlag useEventLoop, int timeout )
+{
+ DCOPReply reply;
+ if ( isNull() ) {
+ qWarning( "DCOPRef: call '%s' on null reference error",
+ STR( fun ) );
+ return reply;
+ }
+ QCString sig = fun;
+ if ( fun.find('(') == -1 ) {
+ sig += args;
+ if( args.find( "<unknown" ) != -1 )
+ qWarning("DCOPRef: unknown type error "
+ "<\"%s\",\"%s\">::call(\"%s\",%s",
+ STR(m_app), STR(m_obj), STR(fun), args.data()+1 );
+ }
+ DCOPClient* dc = dcopClient();
+ if ( !dc || !dc->isAttached() ) {
+ qWarning( "DCOPRef::call(): no DCOP client or client not attached error" );
+ return reply;
+ }
+ dc->call( m_app, m_obj, sig, data, reply.type, reply.data, useEventLoop == UseEventLoop, timeout );
+ return reply;
+}
+
+bool DCOPRef::sendInternal( const QCString& fun, const QCString& args, const QByteArray& data )
+{
+ if ( isNull() ) {
+ qWarning( "DCOPRef: send '%s' on null reference error",
+ STR( fun ) );
+ return false;
+ }
+ Q_UNUSED( data );
+ QCString sig = fun;
+ if ( fun.find('(') == -1 ) {
+ sig += args;
+ if( args.find( "<unknown" ) != -1 )
+ qWarning("DCOPRef: unknown type error "
+ "<\"%s\",\"%s\">::send(\"%s\",%s",
+ STR(m_app), STR(m_obj), STR(fun), args.data()+1 );
+ }
+ DCOPClient* dc = dcopClient();
+ if ( !dc || !dc->isAttached() ) {
+ qWarning( "DCOPRef::send(): no DCOP client or client not attached error" );
+ return false;
+ }
+ return dc->send( m_app, m_obj, sig, data );
+}
+
+DCOPRef::DCOPRef()
+ :d(0)
+{
+}
+
+DCOPRef::DCOPRef( const DCOPRef& ref )
+ :d( ref.d )
+{
+ m_app = ref.app();
+ m_obj = ref.obj();
+ m_type = ref.type();
+}
+
+DCOPRef::DCOPRef( DCOPObject *o )
+ : m_app( DCOPClient::mainClient() ? DCOPClient::mainClient()->appId() : QCString() ),
+ m_obj( o->objId() ), m_type( o->interfaces().last() ), d(0)
+
+{
+}
+
+DCOPRef::DCOPRef( const QCString& _app, const QCString& obj )
+ : m_app( _app ), m_obj( obj ), d(0)
+{
+}
+
+DCOPRef::DCOPRef( const QCString& _app, const QCString& _obj, const QCString& _type )
+ : m_app( _app ), m_obj( _obj ), m_type( _type ), d(0)
+{
+}
+
+bool DCOPRef::isNull() const
+{
+ return ( m_app.isNull() || m_obj.isNull() );
+}
+
+QCString DCOPRef::app() const
+{
+ return m_app;
+}
+
+QCString DCOPRef::obj() const
+{
+ return m_obj;
+}
+
+QCString DCOPRef::object() const
+{
+ return m_obj;
+}
+
+
+QCString DCOPRef::type() const
+{
+ return m_type;
+}
+
+void DCOPRef::setDCOPClient( DCOPClient* dc )
+{
+ d = (DCOPRefPrivate*) dc;
+}
+
+DCOPClient* DCOPRef::dcopClient() const
+{
+ return d ? (DCOPClient*)d : DCOPClient::mainClient();
+}
+
+DCOPRef& DCOPRef::operator=( const DCOPRef& ref )
+{
+ d = ref.d;
+ m_app = ref.app();
+ m_obj = ref.obj();
+ m_type = ref.type();
+ return *this;
+}
+
+void DCOPRef::setRef( const QCString& _app, const QCString& _obj )
+{
+ m_app = _app;
+ m_obj = _obj;
+ m_type = 0;
+}
+
+void DCOPRef::setRef( const QCString& _app, const QCString& _obj, const QCString& _type )
+{
+ m_app = _app;
+ m_obj = _obj;
+ m_type = _type;
+}
+
+void DCOPRef::clear()
+{
+ m_app = 0;
+ m_obj = 0;
+ m_type = 0;
+}
+
+QDataStream& operator<<( QDataStream& str, const DCOPRef& ref )
+{
+ str << ref.app();
+ str << ref.obj();
+ str << ref.type();
+
+ return str;
+}
+
+QDataStream& operator>>( QDataStream& str, DCOPRef& ref )
+{
+ QCString a, o, t;
+ str >> a >> o >> t;
+
+ ref.setRef( a, o, t );
+
+ return str;
+}
diff --git a/dcop/dcopref.h b/dcop/dcopref.h
new file mode 100644
index 000000000..3b65fb9dc
--- /dev/null
+++ b/dcop/dcopref.h
@@ -0,0 +1,1474 @@
+/*
+Copyright (c) 2002 Matthias Ettrich <ettrich@kde.org>
+Copyright (c) 1999 Preston Brown <pbrown@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 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.
+*/
+
+#ifndef _DCOPREF_H
+#define _DCOPREF_H
+
+#include <qcstring.h>
+#include <dcoptypes.h>
+#include <kdatastream.h> // needed for proper bool marshalling
+#include "kdelibs_export.h"
+
+class QDataStream;
+class DCOPObject;
+class DCOPClient;
+
+/**
+ * Represents the return value of a DCOPRef:call() or
+ * DCOPRef:send() invocation.
+ *
+ * @see DCOPRef
+ * @see DCOPRef::call()
+ * @see DCOPArg
+ * @since 3.1
+ */
+class DCOP_EXPORT DCOPReply
+{
+public:
+ /**
+ * Casts the value to the type @p T. Requires that the
+ * type @p T suppports QDataStream deserialisation
+ * and has a function dcopTypeName(T). This is true for most
+ * basic types.
+ */
+ template<class T>
+ operator T() {
+ T t;
+ dcopTypeInit(t);
+ if ( typeCheck( dcopTypeName(t), true ) ) {
+ QDataStream reply( data, IO_ReadOnly );
+ reply >> t;
+ }
+ return t;
+ }
+ /**
+ * Retrieves the value from the type @p T. Requires that the
+ * type @p T suppports QDataStream deserialisation.
+ * @param t the type will be written here, if successful
+ * @param tname the signature type name
+ * @return true if successful, false otherwise
+ */
+ template <class T> bool get( T& t, const char* tname ) {
+ if ( typeCheck( tname, false ) ) {
+ QDataStream reply( data, IO_ReadOnly );
+ reply >> t;
+ return true;
+ }
+ return false;
+ }
+ /**
+ * Retrieves the value from the type @p T. Requires that the
+ * type @p T suppports QDataStream deserialisation
+ * and has a function dcopTypeName(T). This is true for most
+ * basic types.
+ * @param t the type will be written here, if successful
+ * @return true if successful, false otherwise
+ */
+ template <class T> bool get( T& t ) {
+ if ( typeCheck( dcopTypeName(t), false ) ) {
+ QDataStream reply( data, IO_ReadOnly );
+ reply >> t;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Checks whether the type is valid.
+ * @return true if valid, false otherwise
+ */
+ inline bool isValid() const { return !type.isNull(); }
+
+ /// The serialized data.
+ QByteArray data;
+ /// The name of the type, or 0 if unknown.
+ QCString type;
+private:
+ bool typeCheck( const char* t );
+ bool typeCheck( const char* t, bool warn );
+};
+
+/**
+ * A generic DCOP argument.
+ * This class allows you to use user-defined argument types for
+ * DCOPRef::call() or DCOPRef::send().
+ *
+ * @see DCOPRef::call()
+ * @see DCOPRef
+ * @see DCOPReply
+ * @since 3.1
+ */
+class DCOP_EXPORT DCOPArg {
+public:
+ /**
+ * Creates a DCOPArg for DCOPRef::call().
+ * @param t the data that will be written to a QDataStream. It must
+ * overload writing to a QDataStream using the "<<"
+ * operator
+ * @param tname_arg the name of the data that will appear in the
+ * function's signature
+ */
+ template <class T> DCOPArg( const T& t, const char* tname_arg )
+ : tname(tname_arg)
+ {
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t;
+ }
+ /**
+ * Creates a DCOPArg for DCOPRef::call().
+ * @param t the data that will be written to a QDataStream. It must
+ * overload writing to a QDataStream using the "<<"
+ * operator. The name of the type will be determined by
+ * calling the function dcopTypeName(T) that must be provided
+ * by you.
+ */
+ template <class T> DCOPArg( const T& t )
+ : tname( dcopTypeName(t) )
+ {
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t;
+ }
+
+ /// The serialized data.
+ QByteArray data;
+ /// The signature type name of the data.
+ const char* tname;
+};
+
+inline const char* dcopTypeName( const DCOPArg &arg ) { return arg.tname; }
+inline QDataStream & operator << (QDataStream & str, const DCOPArg& arg )
+ { str.writeRawBytes( arg.data.data(), arg.data.size() ); return str; }
+
+
+
+/**
+ * A DCOPRef(erence) encapsulates a remote DCOP object as a triple
+ * <app,obj,type> where type is optional. It allows for calling and
+ * passing DCOP objects.
+ *
+ * A DCOP reference makes it possible to return references to other DCOP
+ * objects in a DCOP interface, for example in the method
+ * giveMeAnotherObject() in an interface like this:
+ *
+ * \code
+ * class Example : public DCOPObject
+ * {
+ * K_DCOP
+ * ...
+ * k_dcop:
+ * DCOPRef giveMeAnotherObject();
+ * int doSomething( QString, float, bool );
+ * ASYNC pingMe( QCString message );
+ * UserType userFunction( UserType );
+ * };
+ * \endcode
+ *
+ * In addition, the reference can operate as a comfortable generic
+ * stub to call remote DCOP objects in cases where no DCOPStub is
+ * available. The advantage of using DCOPRef instead of the low-level
+ * functions DCOPClient::call() and DCOPClient::send() are the nicer
+ * syntax and the implicit runtime error checking.
+ *
+ * Say you want to call the method "doSomething" from the above
+ * interface on an object called "example" that lives in application
+ * "foo". Using DCOPRef, you would write
+ *
+ * \code
+ * DCOPRef example( "foo", "example" );
+ * int result = example.call( "doSomething", QString("Hello World"), (float)2.5, true );
+ * \endcode
+ *
+ * If it is important for you to know whether the call succeeded or
+ * not, you can use the slightly more elaborate pattern:
+ *
+ * \code
+ * DCOPRef example( "foo", "example" );
+ * DCOPReply reply = example.call( "doSomething", QString("Hello World"), (float)2.5, true );
+ * if ( reply.isValid() ) {
+ * int result = reply;
+ * // ...
+ * }
+ * \endcode
+ *
+ * Note that you must pass a QString for the first argument. If you use a
+ * regular char pointer, it will be converted to a QCString.
+ *
+ * For curiosity, here is how you would achieve the exactly same
+ * functionality by using DCOPClient::call() directly:
+ *
+ * \code
+ * QByteArray data, replyData;
+ * QCString replyType;
+ * QDataStream arg( data, IO_WriteOnly );
+ * arg << QString("hello world" ), (float) 2.5 << true;
+ * if ( DCOPClient::mainClient()->call( app, obj,
+ * "doSomething(QString,float,bool)",
+ * data, replyType, replyData ) ) {
+ * if ( replyType == "int" ) {
+ * int result;
+ * QDataStream reply( replyData, IO_ReadOnly );
+ * reply >> result;
+ * // ...
+ * }
+ * }
+ * \endcode
+ *
+ * As you might see from the code snippet, the DCOPRef has to "guess"
+ * the names of the datatypes of the arguments to construct a dcop
+ * call. This is done through global inline overloads of the
+ * dcopTypeName function, for example
+ *
+ * \code
+ * inline const char* dcopTypeName( const QString& ) { return "QString"; }
+ * \endcode
+ *
+ * If you use custom data types that do support QDataStream but have
+ * no corresponding dcopTypeName overload, you can either provide such
+ * an overload or use a DCOPArg wrapper that allows you to specify the type.
+ *
+ * \code
+ * UserType userType;
+ * DCOPReply reply = example.call( "userFunction", DCOPArg( userType, "UserType" ) );
+ * \endcode
+ *
+ * Similar, when you retrieve such a data type, you can use an
+ * explicit call to DCOPReply::get():
+ *
+ * \code
+ * UserType userType;
+ * reply.get( userType, "UserType" );
+ * \endcode
+ *
+ * The function send() works very similar to call(), only that it
+ * returns a simple bool on whether the signal could be sent or not:
+ *
+ * \code
+ * if ( example.send( "pingMe", "message" ) == false )
+ * qWarning("could not ping example" );
+ * \endcode
+ *
+ * A DCOP reference operates on DCOPClient::mainClient(), unless you
+ * explicitly specify another client with setDCOPClient().
+ *
+ * @see DCOPArg
+ * @see DCOPReply
+ * @see DCOPObject
+ * @author Matthias Ettrich <ettrich@kde.org>, Torben Weis <weis@kde.org>
+ */
+
+class DCOP_EXPORT DCOPRef
+{
+public:
+ /**
+ * Creates a null reference.
+ * @see isNull()
+ */
+ DCOPRef();
+
+ /**
+ * Copy constructor.
+ */
+ DCOPRef( const DCOPRef& ref );
+ /**
+ * Creates a reference for application @p app and object @p obj
+ *
+ * @param app The name of an application as registered
+ * by the dcopserver.
+ * @param obj The name of the dcop object.
+ */
+ DCOPRef( const QCString& app, const QCString& obj = "" );
+
+ /**
+ * Creates a reference to an existing dcop object
+ *
+ * @param object The dcop object to create the ref to.
+ */
+ DCOPRef( DCOPObject *object );
+
+ /**
+ * Creates a reference for application @p app and object @p obj
+ * with a specified type @p type.
+ *
+ * @param app The name of an application as registered
+ * by the dcopserver.
+ * @param obj The name of the dcop object
+ * @param type The object's type
+ */
+ DCOPRef( const QCString& app, const QCString& obj, const QCString& type );
+
+ /**
+ * Tests whether this is a null reference.
+ * @return true if this object is a null reference
+ * @see clear()
+ */
+ bool isNull() const;
+
+ /**
+ * Name of the application in which the object resides.
+ * @return the application's id. Can be null or empty if not set.
+ */
+ QCString app() const;
+
+ /**
+ * Object ID of the referenced object.
+ * @return the id of the referenced object. Can be null or empty if not set.
+ * @since 3.1
+ */
+ QCString obj() const;
+
+ /**
+ * @obsolete
+ */
+ QCString object() const;
+
+ /**
+ * Type of the referenced object. May be null (i.e. unknown).
+ * @return the type of the referenced object, or null if unknown
+ */
+ QCString type() const;
+
+
+ /**
+ * Assignment operator. Copies the references data.
+ */
+ DCOPRef& operator=( const DCOPRef& );
+
+ /**
+ * Changes the referenced object. Resets the type to unknown (null).
+ * The type is not needed for call() and send().
+ * @param app the application id.
+ * @param obj the object id
+ */
+ void setRef( const QCString& app, const QCString& obj = "" );
+
+ /**
+ * Changes the referenced object.
+ * @param app the application id.
+ * @param obj the object id
+ * @param type the object's type
+ */
+ void setRef( const QCString& app, const QCString& obj, const QCString& type );
+
+
+ /**
+ * Makes this a null reference.
+ * @see isNull()
+ */
+ void clear();
+
+
+ /**
+ * Returns the dcop client the reference operates on. If no client
+ * has been set, this is the DCOPClient::mainClient().
+ * @return the DCOPClient of this object
+ * @since 3.1
+ */
+ DCOPClient* dcopClient() const;
+
+ /**
+ * Sets a specific dcop client for this reference. Otherwise
+ * DCOPClient::mainClient() is used.
+ * @param client the new DCOPClient of this object
+ * @since 3.1
+ */
+ void setDCOPClient( DCOPClient *client );
+
+ /**
+ * Flag for allowing entering the event loop if the call blocks too long.
+ * @p NoEventLoop disables entering the event loop.
+ * @p UseEventLoop allows entering the event loop while waiting for long
+ * blocking DCOP call, thus making the GUI repaint if needed, and possibly
+ * allowing also other code in the application to be executed.
+ * @see DCOPClient::call()
+ */
+ enum EventLoopFlag { NoEventLoop, UseEventLoop };
+ /**
+ * Calls the function @p fun on the object referenced by this reference.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @return the DCOPReply object. Is invalid ( DCOPReply::isValid())
+ * when an error occurred.
+ * @see send()
+ * @see DCOPArg
+ * @since 3.1
+ */
+ DCOPReply call( const QCString& fun ) {
+ QByteArray data;
+ return callInternal( fun, "()", data );
+ }
+
+ /**
+ * Like call(), with additional arguments allowing entering the event loop
+ * and specifying timeout.
+ * @param useEventLoop if UseEventLoop, the event loop will be started when
+ * the call blocks too long
+ * @param timeout timeout for the call in miliseconds, or -1 for no timeout
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @since 3.2
+ */
+ DCOPReply callExt( const QCString& fun, EventLoopFlag useEventLoop=NoEventLoop,
+ int timeout=-1 ) {
+ QByteArray data;
+ return callInternal( fun, "()", data, useEventLoop, timeout );
+ }
+
+ /**
+ * Calls the function @p fun on the object referenced by this reference.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @return the DCOPReply object. Is invalid ( DCOPReply::isValid())
+ * when an error occurred.
+ * @see send()
+ * @see DCOPArg
+ * @since 3.1
+ */
+ template <class T1>
+ DCOPReply call( const QCString& fun, const T1& t1 ) {
+ QCString args;
+ args.sprintf( "(%s)",
+ dcopTypeName(t1) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1;
+ return callInternal( fun, args, data );
+ }
+
+ /**
+ * Like call(), with additional arguments allowing entering the event loop
+ * and specifying timeout.
+ * @param useEventLoop if UseEventLoop, the event loop will be started when
+ * the call blocks too long
+ * @param timeout timeout for the call in miliseconds, or -1 for no timeout
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @since 3.2
+ */
+ template <class T1>
+ DCOPReply callExt( const QCString& fun,
+ EventLoopFlag useEventLoop, int timeout,
+ const T1& t1) {
+ QCString args;
+ args.sprintf( "(%s)",
+ dcopTypeName(t1) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1;
+ return callInternal( fun, args, data, useEventLoop, timeout );
+ }
+
+ /**
+ * Calls the function @p fun on the object referenced by this reference.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @return the DCOPReply object. Is invalid ( DCOPReply::isValid())
+ * when an error occurred.
+ * @see send()
+ * @see DCOPArg
+ * @since 3.1
+ */
+ template <class T1, class T2>
+ DCOPReply call( const QCString& fun,
+ const T1& t1,
+ const T2& t2 ) {
+ QCString args;
+ args.sprintf( "(%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2;
+ return callInternal( fun, args, data );
+ }
+
+ /**
+ * Like call(), with additional arguments allowing entering the event loop
+ * and specifying timeout.
+ * @param useEventLoop if UseEventLoop, the event loop will be started when
+ * the call blocks too long
+ * @param timeout timeout for the call in miliseconds, or -1 for no timeout
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @since 3.2
+ */
+ template <class T1, class T2>
+ DCOPReply callExt( const QCString& fun,
+ EventLoopFlag useEventLoop, int timeout,
+ const T1& t1,
+ const T2& t2) {
+ QCString args;
+ args.sprintf( "(%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2;
+ return callInternal( fun, args, data, useEventLoop, timeout );
+ }
+
+ /**
+ * Calls the function @p fun on the object referenced by this reference.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t3 the third argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @return the DCOPReply object. Is invalid ( DCOPReply::isValid())
+ * when an error occurred.
+ * @see send()
+ * @see DCOPArg
+ * @since 3.1
+ */
+ template <class T1, class T2, class T3>
+ DCOPReply call( const QCString& fun,
+ const T1& t1,
+ const T2& t2,
+ const T3& t3 ) {
+ QCString args;
+ args.sprintf( "(%s,%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2),
+ dcopTypeName(t3) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2 << t3;
+ return callInternal( fun, args, data );
+ }
+
+ /**
+ * Like call(), with additional arguments allowing entering the event loop
+ * and specifying timeout.
+ * @param useEventLoop if UseEventLoop, the event loop will be started when
+ * the call blocks too long
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t3 the third argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param timeout timeout for the call in miliseconds, or -1 for no timeout
+ * @since 3.2
+ */
+ template <class T1, class T2, class T3>
+ DCOPReply callExt( const QCString& fun,
+ EventLoopFlag useEventLoop, int timeout,
+ const T1& t1,
+ const T2& t2,
+ const T3& t3) {
+ QCString args;
+ args.sprintf( "(%s,%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2),
+ dcopTypeName(t3) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2 << t3;
+ return callInternal( fun, args, data, useEventLoop, timeout );
+ }
+
+ /**
+ * Calls the function @p fun on the object referenced by this reference.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t3 the third argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t4 the fourth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @return the DCOPReply object. Is invalid ( DCOPReply::isValid())
+ * when an error occurred.
+ * @see send()
+ * @see DCOPArg
+ * @since 3.1
+ */
+ template <class T1,class T2,class T3,class T4>
+ DCOPReply call( const QCString& fun,
+ const T1& t1,
+ const T2& t2,
+ const T3& t3,
+ const T4& t4 ) {
+ QCString args;
+ args.sprintf( "(%s,%s,%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2),
+ dcopTypeName(t3),
+ dcopTypeName(t4) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2 << t3 << t4;
+ return callInternal( fun, args, data );
+ }
+
+ /**
+ * Like call(), with additional arguments allowing entering the event loop
+ * and specifying timeout.
+ * @param useEventLoop if UseEventLoop, the event loop will be started when
+ * the call blocks too long
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param timeout timeout for the call in miliseconds, or -1 for no timeout
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t3 the third argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t4 the fourth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @since 3.2
+ */
+ template <class T1,class T2,class T3,class T4>
+ DCOPReply callExt( const QCString& fun,
+ EventLoopFlag useEventLoop, int timeout,
+ const T1& t1,
+ const T2& t2,
+ const T3& t3,
+ const T4& t4) {
+ QCString args;
+ args.sprintf( "(%s,%s,%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2),
+ dcopTypeName(t3),
+ dcopTypeName(t4) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2 << t3 << t4;
+ return callInternal( fun, args, data, useEventLoop, timeout );
+ }
+
+ /**
+ * Calls the function @p fun on the object referenced by this reference.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t3 the third argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t4 the fourth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t5 the fifth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @return the DCOPReply object. Is invalid ( DCOPReply::isValid())
+ * when an error occurred.
+ * @see send()
+ * @see DCOPArg
+ * @since 3.1
+ */
+ template <class T1,class T2,class T3,class T4,class T5>
+ DCOPReply call( const QCString& fun,
+ const T1& t1,
+ const T2& t2,
+ const T3& t3,
+ const T4& t4,
+ const T5& t5 ) {
+ QCString args;
+ args.sprintf( "(%s,%s,%s,%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2),
+ dcopTypeName(t3),
+ dcopTypeName(t4),
+ dcopTypeName(t5) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2 << t3 << t4 << t5;
+ return callInternal( fun, args, data );
+ }
+
+ /**
+ * Like call(), with additional arguments allowing entering the event loop
+ * and specifying timeout.
+ * @param useEventLoop if UseEventLoop, the event loop will be started when
+ * the call blocks too long
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param timeout timeout for the call in miliseconds, or -1 for no timeout
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t3 the third argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t4 the fourth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t5 the fifth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @since 3.2
+ */
+ template <class T1,class T2,class T3,class T4,class T5>
+ DCOPReply callExt( const QCString& fun,
+ EventLoopFlag useEventLoop, int timeout,
+ const T1& t1,
+ const T2& t2,
+ const T3& t3,
+ const T4& t4,
+ const T5& t5 ) {
+ QCString args;
+ args.sprintf( "(%s,%s,%s,%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2),
+ dcopTypeName(t3),
+ dcopTypeName(t4),
+ dcopTypeName(t5) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2 << t3 << t4 << t5;
+ return callInternal( fun, args, data, useEventLoop, timeout );
+ }
+
+ /**
+ * Calls the function @p fun on the object referenced by this reference.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t3 the third argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t4 the fourth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t5 the fifth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t6 the sixth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @return the DCOPReply object. Is invalid ( DCOPReply::isValid())
+ * when an error occurred.
+ * @see send()
+ * @see DCOPArg
+ * @since 3.1
+ */
+ template <class T1,class T2,class T3,class T4,class T5,class T6>
+ DCOPReply call( const QCString& fun,
+ const T1& t1,
+ const T2& t2,
+ const T3& t3,
+ const T4& t4,
+ const T5& t5,
+ const T6& t6 ) {
+ QCString args;
+ args.sprintf( "(%s,%s,%s,%s,%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2),
+ dcopTypeName(t3),
+ dcopTypeName(t4),
+ dcopTypeName(t5),
+ dcopTypeName(t6) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2 << t3 << t4 << t5 << t6;
+ return callInternal( fun, args, data );
+ }
+
+ /**
+ * Like call(), with additional arguments allowing entering the event loop
+ * and specifying timeout.
+ * @param useEventLoop if UseEventLoop, the event loop will be started when
+ * the call blocks too long
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param timeout timeout for the call in miliseconds, or -1 for no timeout
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t3 the third argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t4 the fourth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t5 the fifth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t6 the sixth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @since 3.2
+ */
+ template <class T1,class T2,class T3,class T4,class T5,class T6>
+ DCOPReply callExt( const QCString& fun,
+ EventLoopFlag useEventLoop, int timeout,
+ const T1& t1,
+ const T2& t2,
+ const T3& t3,
+ const T4& t4,
+ const T5& t5,
+ const T6& t6) {
+ QCString args;
+ args.sprintf( "(%s,%s,%s,%s,%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2),
+ dcopTypeName(t3),
+ dcopTypeName(t4),
+ dcopTypeName(t5),
+ dcopTypeName(t6) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2 << t3 << t4 << t5 << t6;
+ return callInternal( fun, args, data, useEventLoop, timeout );
+ }
+ /**
+ * Calls the function @p fun on the object referenced by this reference.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t3 the third argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t4 the fourth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t5 the fifth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t6 the sixth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t7 the seventh argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @return the DCOPReply object. Is invalid ( DCOPReply::isValid())
+ * when an error occurred.
+ * @see send()
+ * @see DCOPArg
+ * @since 3.1
+ */
+ template <class T1,class T2,class T3,class T4,class T5,class T6,class T7>
+ DCOPReply call( const QCString& fun,
+ const T1& t1,
+ const T2& t2,
+ const T3& t3,
+ const T4& t4,
+ const T5& t5,
+ const T6& t6,
+ const T7& t7 ) {
+ QCString args;
+ args.sprintf( "(%s,%s,%s,%s,%s,%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2),
+ dcopTypeName(t3),
+ dcopTypeName(t4),
+ dcopTypeName(t5),
+ dcopTypeName(t6),
+ dcopTypeName(t7) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2 << t3 << t4 << t5 << t6 << t7;
+ return callInternal( fun, args, data );
+ }
+
+ /**
+ * Like call(), with additional arguments allowing entering the event loop
+ * and specifying timeout.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param useEventLoop if UseEventLoop, the event loop will be started when
+ * the call blocks too long
+ * @param timeout timeout for the call in miliseconds, or -1 for no timeout
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t3 the third argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t4 the fourth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t5 the fifth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t6 the sixth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t7 the seventh argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @since 3.2
+ */
+ template <class T1,class T2,class T3,class T4,class T5,class T6,class T7>
+ DCOPReply callExt( const QCString& fun,
+ EventLoopFlag useEventLoop, int timeout,
+ const T1& t1,
+ const T2& t2,
+ const T3& t3,
+ const T4& t4,
+ const T5& t5,
+ const T6& t6,
+ const T7& t7) {
+ QCString args;
+ args.sprintf( "(%s,%s,%s,%s,%s,%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2),
+ dcopTypeName(t3),
+ dcopTypeName(t4),
+ dcopTypeName(t5),
+ dcopTypeName(t6),
+ dcopTypeName(t7) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2 << t3 << t4 << t5 << t6 << t7;
+ return callInternal( fun, args, data, useEventLoop, timeout );
+ }
+
+ /**
+ * Calls the function @p fun on the object referenced by this reference.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t3 the third argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t4 the fourth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t5 the fifth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t6 the sixth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t7 the seventh argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t8 the eigth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @return the DCOPReply object. Is invalid ( DCOPReply::isValid())
+ * when an error occurred.
+ * @see send()
+ * @see DCOPArg
+ * @since 3.1
+ */
+ template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8>
+ DCOPReply call( const QCString& fun,
+ const T1& t1,
+ const T2& t2,
+ const T3& t3,
+ const T4& t4,
+ const T5& t5,
+ const T6& t6,
+ const T7& t7,
+ const T8& t8 ) {
+ QCString args;
+ args.sprintf( "(%s,%s,%s,%s,%s,%s,%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2),
+ dcopTypeName(t3),
+ dcopTypeName(t4),
+ dcopTypeName(t5),
+ dcopTypeName(t6),
+ dcopTypeName(t7),
+ dcopTypeName(t8) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2 << t3 << t4 << t5 << t6 << t7 << t8;
+ return callInternal( fun, args, data );
+ }
+
+ /**
+ * Like call(), with additional arguments allowing entering the event loop
+ * and specifying timeout.
+ * @param useEventLoop if UseEventLoop, the event loop will be started when
+ * the call blocks too long
+ * @param timeout timeout for the call in miliseconds, or -1 for no timeout
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t3 the third argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t4 the fourth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t5 the fifth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t6 the sixth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t7 the seventh argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t8 the eigth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @since 3.2
+ */
+ template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8>
+ DCOPReply callExt( const QCString& fun,
+ EventLoopFlag useEventLoop, int timeout,
+ const T1& t1,
+ const T2& t2,
+ const T3& t3,
+ const T4& t4,
+ const T5& t5,
+ const T6& t6,
+ const T7& t7,
+ const T8& t8) {
+ QCString args;
+ args.sprintf( "(%s,%s,%s,%s,%s,%s,%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2),
+ dcopTypeName(t3),
+ dcopTypeName(t4),
+ dcopTypeName(t5),
+ dcopTypeName(t6),
+ dcopTypeName(t7),
+ dcopTypeName(t8) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2 << t3 << t4 << t5 << t6 << t7 << t8;
+ return callInternal( fun, args, data, useEventLoop, timeout );
+ }
+
+ /**
+ * Calls the function @p fun on the object referenced by this reference.
+ * Unlike call() this method does not expect a return value.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @return the DCOPReply object. Is invalid ( DCOPReply::isValid())
+ * when an error occurred.
+ * @see call()
+ * @since 3.1
+ */
+ bool send( const QCString& fun ) {
+ QByteArray data;
+ return sendInternal( fun, "()", data );
+ }
+
+ /**
+ * Calls the function @p fun on the object referenced by this reference.
+ * Unlike call() this method does not expect a return value.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @return the DCOPReply object. Is invalid ( DCOPReply::isValid())
+ * when an error occurred.
+ * @see call()
+ * @see DCOPArg
+ * @since 3.1
+ */
+ template <class T1>
+ bool send( const QCString& fun, const T1& t1 ) {
+ QCString args;
+ args.sprintf( "(%s)",
+ dcopTypeName(t1) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1;
+ return sendInternal( fun, args, data );
+ }
+ /**
+ * Calls the function @p fun on the object referenced by this reference.
+ * Unlike call() this method does not expect a return value.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @return the DCOPReply object. Is invalid ( DCOPReply::isValid())
+ * when an error occurred.
+ * @see call()
+ * @see DCOPArg
+ * @since 3.1
+ */
+ template <class T1, class T2>
+ bool send( const QCString& fun,
+ const T1& t1,
+ const T2& t2 ) {
+ QCString args;
+ args.sprintf( "(%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2;
+ return sendInternal( fun, args, data );
+ }
+ /**
+ * Calls the function @p fun on the object referenced by this reference.
+ * Unlike call() this method does not expect a return value.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t3 the third argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @return the DCOPReply object. Is invalid ( DCOPReply::isValid())
+ * when an error occurred.
+ * @see call()
+ * @see DCOPArg
+ * @since 3.1
+ */
+ template <class T1, class T2, class T3>
+ bool send( const QCString& fun,
+ const T1& t1,
+ const T2& t2,
+ const T3& t3 ) {
+ QCString args;
+ args.sprintf( "(%s,%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2),
+ dcopTypeName(t3) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2 << t3;
+ return sendInternal( fun, args, data );
+ }
+ /**
+ * Calls the function @p fun on the object referenced by this reference.
+ * Unlike call() this method does not expect a return value.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t3 the third argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t4 the fourth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @return the DCOPReply object. Is invalid ( DCOPReply::isValid())
+ * when an error occurred.
+ * @see call()
+ * @see DCOPArg
+ * @since 3.1
+ */
+ template <class T1,class T2,class T3,class T4>
+ bool send( const QCString& fun,
+ const T1& t1,
+ const T2& t2,
+ const T3& t3,
+ const T4& t4 ) {
+ QCString args;
+ args.sprintf( "(%s,%s,%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2),
+ dcopTypeName(t3),
+ dcopTypeName(t4) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2 << t3 << t4;
+ return sendInternal( fun, args, data );
+ }
+ /**
+ * Calls the function @p fun on the object referenced by this reference.
+ * Unlike call() this method does not expect a return value.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t3 the third argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t4 the fourth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t5 the fifth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @return the DCOPReply object. Is invalid ( DCOPReply::isValid())
+ * when an error occurred.
+ * @see call()
+ * @see DCOPArg
+ * @since 3.1
+ */
+ template <class T1,class T2,class T3,class T4,class T5>
+ bool send( const QCString& fun,
+ const T1& t1,
+ const T2& t2,
+ const T3& t3,
+ const T4& t4,
+ const T5& t5 ) {
+ QCString args;
+ args.sprintf( "(%s,%s,%s,%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2),
+ dcopTypeName(t3),
+ dcopTypeName(t4),
+ dcopTypeName(t5) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2 << t3 << t4 << t5;
+ return sendInternal( fun, args, data );
+ }
+ /**
+ * Calls the function @p fun on the object referenced by this reference.
+ * Unlike call() this method does not expect a return value.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t3 the third argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t4 the fourth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t5 the fifth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t6 the sixth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @return the DCOPReply object. Is invalid ( DCOPReply::isValid())
+ * when an error occurred.
+ * @see call()
+ * @see DCOPArg
+ * @since 3.1
+ */
+ template <class T1,class T2,class T3,class T4,class T5,class T6>
+ bool send( const QCString& fun,
+ const T1& t1,
+ const T2& t2,
+ const T3& t3,
+ const T4& t4,
+ const T5& t5,
+ const T6& t6 ) {
+ QCString args;
+ args.sprintf( "(%s,%s,%s,%s,%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2),
+ dcopTypeName(t3),
+ dcopTypeName(t4),
+ dcopTypeName(t5),
+ dcopTypeName(t6) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2 << t3 << t4 << t5 << t6;
+ return sendInternal( fun, args, data );
+ }
+ /**
+ * Calls the function @p fun on the object referenced by this reference.
+ * Unlike call() this method does not expect a return value.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t3 the third argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t4 the fourth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t5 the fifth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t6 the sixth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t7 the seventh argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @return the DCOPReply object. Is invalid ( DCOPReply::isValid())
+ * when an error occurred.
+ * @see call()
+ * @see DCOPArg
+ * @since 3.1
+ */
+ template <class T1,class T2,class T3,class T4,class T5,class T6,class T7>
+ bool send( const QCString& fun,
+ const T1& t1,
+ const T2& t2,
+ const T3& t3,
+ const T4& t4,
+ const T5& t5,
+ const T6& t6,
+ const T7& t7 ) {
+ QCString args;
+ args.sprintf( "(%s,%s,%s,%s,%s,%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2),
+ dcopTypeName(t3),
+ dcopTypeName(t4),
+ dcopTypeName(t5),
+ dcopTypeName(t6),
+ dcopTypeName(t7) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2 << t3 << t4 << t5 << t6 << t7;
+ return sendInternal( fun, args, data );
+ }
+ /**
+ * Calls the function @p fun on the object referenced by this reference.
+ * Unlike call() this method does not expect a return value.
+ * @param fun the name of the DCOP function. This can be either the
+ * full function signature (e.g. "setName(QString)") or
+ * only the function's name (e.g. "setName"). In the
+ * latter case the exact signature will be guessed from
+ * the arguments
+ * @param t1 the first argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t2 the second argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t3 the third argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t4 the fourth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t5 the fifth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t6 the sixth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t7 the seventh argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @param t8 the eigth argument of the function. This can be a
+ * supported base type or a DCOPArg object.
+ * @return the DCOPReply object. Is invalid ( DCOPReply::isValid())
+ * when an error occurred.
+ * @see call()
+ * @see DCOPArg
+ * @since 3.1
+ */
+ template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8>
+ bool send( const QCString& fun,
+ const T1& t1,
+ const T2& t2,
+ const T3& t3,
+ const T4& t4,
+ const T5& t5,
+ const T6& t6,
+ const T7& t7,
+ const T8& t8 ) {
+ QCString args;
+ args.sprintf( "(%s,%s,%s,%s,%s,%s,%s,%s)",
+ dcopTypeName(t1),
+ dcopTypeName(t2),
+ dcopTypeName(t3),
+ dcopTypeName(t4),
+ dcopTypeName(t5),
+ dcopTypeName(t6),
+ dcopTypeName(t7),
+ dcopTypeName(t8) );
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << t1 << t2 << t3 << t4 << t5 << t6 << t7 << t8;
+ return sendInternal( fun, args, data );
+ }
+
+
+
+private:
+ DCOPReply callInternal( const QCString& fun, const QCString& args, const QByteArray& data,
+ EventLoopFlag useEventLoop, int timeout );
+ DCOPReply callInternal( const QCString& fun, const QCString& args, const QByteArray& data );
+ bool sendInternal( const QCString& fun, const QCString& args, const QByteArray& data );
+
+ QCString m_app;
+ QCString m_obj;
+ QCString m_type;
+
+ class DCOPRefPrivate;
+ DCOPRefPrivate *d;
+};
+
+/**
+ * Writes the reference (NOT the object itself) to the stream.
+ */
+DCOP_EXPORT QDataStream& operator<<( QDataStream&, const DCOPRef& ref );
+/**
+ * Reads a reference from the stream.
+ */
+DCOP_EXPORT QDataStream& operator>>( QDataStream&, DCOPRef& ref );
+
+#endif
diff --git a/dcop/dcopserver.cpp b/dcop/dcopserver.cpp
new file mode 100644
index 000000000..f64e13303
--- /dev/null
+++ b/dcop/dcopserver.cpp
@@ -0,0 +1,1790 @@
+/*****************************************************************
+
+#include "dcopserver.h"
+
+Copyright (c) 1999,2000 Preston Brown <pbrown@kde.org>
+Copyright (c) 1999,2000 Matthias Ettrich <ettrich@kde.org>
+Copyright (c) 1999,2001 Waldo Bastian <bastian@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 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.
+
+******************************************************************/
+
+#include <config.h>
+
+#include <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <sys/resource.h>
+#include <sys/socket.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#define QT_CLEAN_NAMESPACE 1
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qdatastream.h>
+#include <qptrstack.h>
+#include <qtimer.h>
+
+#include "dcopserver.h"
+
+#include <dcopsignals.h>
+#include <dcopclient.h>
+#include <dcopglobal.h>
+#include "dcop-path.h"
+
+#ifdef DCOP_LOG
+#undef Unsorted
+#include <qdir.h>
+#include <string.h>
+#endif
+
+// #define DCOP_DEBUG
+
+DCOPServer* the_server;
+
+template class QDict<DCOPConnection>;
+template class QPtrDict<DCOPConnection>;
+template class QPtrList<DCOPListener>;
+
+#define _DCOPIceSendBegin(x) \
+ int fd = IceConnectionNumber( x ); \
+ long fd_fl = fcntl(fd, F_GETFL, 0); \
+ fcntl(fd, F_SETFL, fd_fl | O_NDELAY);
+#define _DCOPIceSendEnd() \
+ fcntl(fd, F_SETFL, fd_fl);
+
+static QCString findDcopserverShutdown()
+{
+#ifdef Q_OS_WIN32
+ char szPath[512];
+ char *pszFilePart;
+ int ret;
+ ret = SearchPathA(NULL,"dcopserver_shutdown","exe",sizeof(szPath)/sizeof(szPath[0]),szPath,&pszFilePart);
+ if(ret != 0)
+ return QCString(szPath);
+#else
+ QCString path = getenv("PATH");
+ char *dir = strtok(path.data(), ":");
+ while (dir)
+ {
+ QCString file = dir;
+ file += "/dcopserver_shutdown";
+ if (access(file.data(), X_OK) == 0)
+ return file;
+ dir = strtok(NULL, ":");
+ }
+ QCString file = DCOP_PATH;
+ file += "/dcopserver_shutdown";
+ if (access(file.data(), X_OK) == 0)
+ return file;
+#endif
+ return QCString("dcopserver_shutdown");
+}
+
+static Bool HostBasedAuthProc ( char* /*hostname*/)
+{
+ return false; // no host based authentication
+}
+
+extern "C" {
+extern IceWriteHandler _kde_IceWriteHandler;
+extern IceIOErrorHandler _kde_IceIOErrorHandler;
+void DCOPIceWriteChar(register IceConn iceConn, unsigned long nbytes, char *ptr);
+}
+
+static QCString readQCString(QDataStream &ds)
+{
+ QCString result;
+ Q_UINT32 len;
+ ds >> len;
+ QIODevice *device = ds.device();
+ int bytesLeft = device->size()-device->at();
+ if ((bytesLeft < 0 ) || (len > (uint) bytesLeft))
+ {
+ qWarning("Corrupt data!\n");
+ return result;
+ }
+ result.QByteArray::resize( (uint)len );
+ if (len > 0)
+ ds.readRawBytes( result.data(), (uint)len);
+ return result;
+}
+
+static QByteArray readQByteArray(QDataStream &ds)
+{
+ QByteArray result;
+ Q_UINT32 len;
+ ds >> len;
+ QIODevice *device = ds.device();
+ int bytesLeft = device->size()-device->at();
+ if ((bytesLeft < 0 ) || (len > (uint) bytesLeft))
+ {
+ qWarning("Corrupt data!\n");
+ return result;
+ }
+ result.resize( (uint)len );
+ if (len > 0)
+ ds.readRawBytes( result.data(), (uint)len);
+ return result;
+}
+
+
+extern "C" {
+extern int _kde_IceTransWrite (void * ciptr, char *buf, int size);
+}
+
+static unsigned long writeIceData(IceConn iceConn, unsigned long nbytes, char *ptr)
+{
+ int fd = IceConnectionNumber(iceConn);
+ unsigned long nleft = nbytes;
+ while (nleft > 0)
+ {
+ int nwritten;
+
+ if (iceConn->io_ok)
+ {
+ nwritten = send(fd, ptr, (int) nleft, 0);
+ }
+ else
+ return 0;
+
+ if (nwritten <= 0)
+ {
+ if (errno == EINTR)
+ continue;
+
+ if (errno == EAGAIN)
+ return nleft;
+
+ /*
+ * Fatal IO error. First notify each protocol's IceIOErrorProc
+ * callback, then invoke the application IO error handler.
+ */
+
+ iceConn->io_ok = False;
+
+ if (iceConn->connection_status == IceConnectPending)
+ {
+ /*
+ * Don't invoke IO error handler if we are in the
+ * middle of a connection setup.
+ */
+
+ return 0;
+ }
+
+ if (iceConn->process_msg_info)
+ {
+ int i;
+
+ for (i = iceConn->his_min_opcode;
+ i <= iceConn->his_max_opcode; i++)
+ {
+ _IceProcessMsgInfo *process;
+
+ process = &iceConn->process_msg_info[
+ i - iceConn->his_min_opcode];
+
+ if (process->in_use)
+ {
+ IceIOErrorProc IOErrProc = process->accept_flag ?
+ process->protocol->accept_client->io_error_proc :
+ process->protocol->orig_client->io_error_proc;
+
+ if (IOErrProc)
+ (*IOErrProc) (iceConn);
+ }
+ }
+ }
+
+ (*_kde_IceIOErrorHandler) (iceConn);
+ return 0;
+ }
+
+ nleft -= nwritten;
+ ptr += nwritten;
+ }
+ return 0;
+}
+
+void DCOPIceWriteChar(register IceConn iceConn, unsigned long nbytes, char *ptr)
+{
+ DCOPConnection* conn = the_server->findConn( iceConn );
+#ifdef DCOP_DEBUG
+qWarning("DCOPServer: DCOPIceWriteChar() Writing %d bytes to %d [%s]", nbytes, fd, conn ? conn->appId.data() : "<unknown>");
+#endif
+
+ if (conn)
+ {
+ if (conn->outputBlocked)
+ {
+ QByteArray _data(nbytes);
+ memcpy(_data.data(), ptr, nbytes);
+#ifdef DCOP_DEBUG
+qWarning("DCOPServer: _IceWrite() outputBlocked. Queuing %d bytes.", _data.size());
+#endif
+ conn->outputBuffer.append(_data);
+ return;
+ }
+ // assert(conn->outputBuffer.isEmpty());
+ }
+
+ unsigned long nleft = writeIceData(iceConn, nbytes, ptr);
+ if ((nleft > 0) && conn)
+ {
+ QByteArray _data(nleft);
+ memcpy(_data.data(), ptr, nleft);
+ conn->waitForOutputReady(_data, 0);
+ return;
+ }
+}
+
+static void DCOPIceWrite(IceConn iceConn, const QByteArray &_data)
+{
+ DCOPConnection* conn = the_server->findConn( iceConn );
+#ifdef DCOP_DEBUG
+qWarning("DCOPServer: DCOPIceWrite() Writing %d bytes to %d [%s]", _data.size(), fd, conn ? conn->appId.data() : "<unknown>");
+#endif
+ if (conn)
+ {
+ if (conn->outputBlocked)
+ {
+#ifdef DCOP_DEBUG
+qWarning("DCOPServer: DCOPIceWrite() outputBlocked. Queuing %d bytes.", _data.size());
+#endif
+ conn->outputBuffer.append(_data);
+ return;
+ }
+ // assert(conn->outputBuffer.isEmpty());
+ }
+
+ unsigned long nleft = writeIceData(iceConn, _data.size(), _data.data());
+ if ((nleft > 0) && conn)
+ {
+ conn->waitForOutputReady(_data, _data.size() - nleft);
+ return;
+ }
+}
+
+void DCOPConnection::waitForOutputReady(const QByteArray &_data, int start)
+{
+#ifdef DCOP_DEBUG
+qWarning("DCOPServer: waitForOutputReady fd = %d datasize = %d start = %d", socket(), _data.size(), start);
+#endif
+ outputBlocked = true;
+ outputBuffer.append(_data);
+ outputBufferStart = start;
+ if (!outputBufferNotifier)
+ {
+ outputBufferNotifier = new QSocketNotifier(socket(), Write);
+ connect(outputBufferNotifier, SIGNAL(activated(int)),
+ the_server, SLOT(slotOutputReady(int)));
+ }
+ outputBufferNotifier->setEnabled(true);
+ return;
+}
+
+void DCOPServer::slotOutputReady(int socket)
+{
+#ifdef DCOP_DEBUG
+qWarning("DCOPServer: slotOutputReady fd = %d", socket);
+#endif
+ // Find out connection.
+ DCOPConnection *conn = fd_clients.find(socket);
+ //assert(conn);
+ //assert(conn->outputBlocked);
+ //assert(conn->socket() == socket);
+ // Forward
+ conn->slotOutputReady();
+}
+
+
+void DCOPConnection::slotOutputReady()
+{
+ //assert(outputBlocked);
+ //assert(!outputBuffer.isEmpty());
+
+ QByteArray data = outputBuffer.first();
+
+ int fd = socket();
+
+ long fd_fl = fcntl(fd, F_GETFL, 0);
+ fcntl(fd, F_SETFL, fd_fl | O_NDELAY);
+ /*
+ Use special write handling on windows platform. The write function from
+ the runtime library (on MSVC) does not allow to write on sockets.
+ */
+ int nwritten;
+ nwritten = ::send(fd,data.data()+outputBufferStart,data.size()-outputBufferStart,0);
+
+ int e = errno;
+ fcntl(fd, F_SETFL, fd_fl);
+
+#ifdef DCOP_DEBUG
+qWarning("DCOPServer: slotOutputReady() %d bytes written", nwritten);
+#endif
+
+ if (nwritten < 0)
+ {
+ if ((e == EINTR) || (e == EAGAIN))
+ return;
+ (*_kde_IceIOErrorHandler) (iceConn);
+ return;
+ }
+ outputBufferStart += nwritten;
+
+ if (outputBufferStart == data.size())
+ {
+ outputBufferStart = 0;
+ outputBuffer.remove(outputBuffer.begin());
+ if (outputBuffer.isEmpty())
+ {
+#ifdef DCOP_DEBUG
+qWarning("DCOPServer: slotOutputRead() all data transmitted.");
+#endif
+ outputBlocked = false;
+ outputBufferNotifier->setEnabled(false);
+ }
+#ifdef DCOP_DEBUG
+else
+{
+qWarning("DCOPServer: slotOutputRead() more data to send.");
+}
+#endif
+ }
+}
+
+static void DCOPIceSendData(register IceConn _iceConn,
+ const QByteArray &_data)
+{
+ if (_iceConn->outbufptr > _iceConn->outbuf)
+ {
+#ifdef DCOP_DEBUG
+qWarning("DCOPServer: Flushing data, fd = %d", IceConnectionNumber(_iceConn));
+#endif
+ IceFlush( _iceConn );
+ }
+ DCOPIceWrite(_iceConn, _data);
+}
+
+class DCOPListener : public QSocketNotifier
+{
+public:
+ DCOPListener( IceListenObj obj )
+ : QSocketNotifier( IceGetListenConnectionNumber( obj ),
+ QSocketNotifier::Read, 0, 0)
+{
+ listenObj = obj;
+}
+
+ IceListenObj listenObj;
+};
+
+DCOPConnection::DCOPConnection( IceConn conn )
+ : QSocketNotifier( IceConnectionNumber( conn ),
+ QSocketNotifier::Read, 0, 0 )
+{
+ iceConn = conn;
+ notifyRegister = 0;
+ _signalConnectionList = 0;
+ daemon = false;
+ outputBlocked = false;
+ outputBufferNotifier = 0;
+ outputBufferStart = 0;
+}
+
+DCOPConnection::~DCOPConnection()
+{
+ delete _signalConnectionList;
+ delete outputBufferNotifier;
+}
+
+DCOPSignalConnectionList *
+DCOPConnection::signalConnectionList()
+{
+ if (!_signalConnectionList)
+ _signalConnectionList = new DCOPSignalConnectionList;
+ return _signalConnectionList;
+}
+
+static IceAuthDataEntry *authDataEntries;
+static char *addAuthFile;
+
+static IceListenObj *listenObjs;
+static int numTransports;
+static int ready[2];
+
+
+/* for printing hex digits */
+static void fprintfhex (FILE *fp, unsigned int len, char *cp)
+{
+ static char hexchars[] = "0123456789abcdef";
+
+ for (; len > 0; len--, cp++) {
+ unsigned char s = *cp;
+ putc(hexchars[s >> 4], fp);
+ putc(hexchars[s & 0x0f], fp);
+ }
+}
+
+/*
+ * We use temporary files which contain commands to add entries to
+ * the .ICEauthority file.
+ */
+static void
+write_iceauth (FILE *addfp, IceAuthDataEntry *entry)
+{
+ fprintf (addfp,
+ "add %s \"\" %s %s ",
+ entry->protocol_name,
+ entry->network_id,
+ entry->auth_name);
+ fprintfhex (addfp, entry->auth_data_length, entry->auth_data);
+ fprintf (addfp, "\n");
+}
+
+#ifndef HAVE_MKSTEMPS
+#include <string.h>
+#include <strings.h>
+
+/* this is based on code taken from the GNU libc, distributed under the LGPL license */
+
+/* Generate a unique temporary file name from TEMPLATE.
+
+ TEMPLATE has the form:
+
+ <path>/ccXXXXXX<suffix>
+
+ SUFFIX_LEN tells us how long <suffix> is (it can be zero length).
+
+ The last six characters of TEMPLATE before <suffix> must be "XXXXXX";
+ they are replaced with a string that makes the filename unique.
+
+ Returns a file descriptor open on the file for reading and writing. */
+
+int mkstemps (char* _template, int suffix_len)
+{
+ static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ char *XXXXXX;
+ int len;
+ int count;
+ int value;
+
+ len = strlen (_template);
+
+ if ((int) len < 6 + suffix_len || strncmp (&_template[len - 6 - suffix_len], "XXXXXX", 6))
+ return -1;
+
+ XXXXXX = &_template[len - 6 - suffix_len];
+
+ value = rand();
+ for (count = 0; count < 256; ++count)
+ {
+ int v = value;
+ int fd;
+
+ /* Fill in the random bits. */
+ XXXXXX[0] = letters[v % 62];
+ v /= 62;
+ XXXXXX[1] = letters[v % 62];
+ v /= 62;
+ XXXXXX[2] = letters[v % 62];
+ v /= 62;
+ XXXXXX[3] = letters[v % 62];
+ v /= 62;
+ XXXXXX[4] = letters[v % 62];
+ v /= 62;
+ XXXXXX[5] = letters[v % 62];
+
+ fd = open (_template, O_RDWR|O_CREAT|O_EXCL, 0600);
+ if (fd >= 0)
+ /* The file does not exist. */
+ return fd;
+
+ /* This is a random value. It is only necessary that the next
+ TMP_MAX values generated by adding 7777 to VALUE are different
+ with (module 2^32). */
+ value += 7777;
+ }
+ /* We return the null string if we can't find a unique file name. */
+ _template[0] = '\0';
+ return -1;
+}
+
+#endif
+
+static char *unique_filename (const char *path, const char *prefix, int *pFd)
+{
+ char tempFile[PATH_MAX];
+ char *ptr;
+
+#ifdef Q_OS_WIN
+ snprintf (tempFile, PATH_MAX, "%s\\%sXXXXXX", path, prefix);
+#else
+ snprintf (tempFile, PATH_MAX, "%s/%sXXXXXX", path, prefix);
+#endif
+ ptr = static_cast<char *>(malloc(strlen(tempFile) + 1));
+ if (ptr != NULL)
+ {
+ int fd = mkstemps(tempFile, 0);
+ if(fd >= 0)
+ {
+ *pFd = fd;
+ strcpy(ptr, tempFile);
+ }
+ else
+ {
+ free(ptr);
+ ptr = NULL;
+ }
+ }
+ return ptr;
+}
+
+#define MAGIC_COOKIE_LEN 16
+
+Status
+SetAuthentication (int count, IceListenObj *_listenObjs,
+ IceAuthDataEntry **_authDataEntries)
+{
+ FILE *addfp = NULL;
+ const char *path;
+ int original_umask;
+ int i;
+ QCString command;
+ int fd;
+
+ original_umask = umask (0077); /* disallow non-owner access */
+
+#ifdef Q_OS_WIN
+ char temppath[512];
+ DWORD dw = GetTempPathA(sizeof(temppath),temppath);
+ if(dw != 0)
+ {
+ temppath[dw - 1] = 0;
+ path = temppath;
+ }
+ else
+ path = ".";
+#else
+ path = getenv ("DCOP_SAVE_DIR");
+ if (!path)
+ path = "/tmp";
+#endif
+ if ((addAuthFile = unique_filename (path, "dcop", &fd)) == NULL)
+ goto bad;
+
+ if (!(addfp = fdopen(fd, "wb")))
+ goto bad;
+
+ if ((*_authDataEntries = static_cast<IceAuthDataEntry *>(malloc (count * 2 * sizeof (IceAuthDataEntry)))) == NULL)
+ goto bad;
+
+ for (i = 0; i < numTransports * 2; i += 2) {
+ (*_authDataEntries)[i].network_id =
+ IceGetListenConnectionString (_listenObjs[i/2]);
+ (*_authDataEntries)[i].protocol_name = const_cast<char *>("ICE");
+ (*_authDataEntries)[i].auth_name = const_cast<char *>("MIT-MAGIC-COOKIE-1");
+
+ (*_authDataEntries)[i].auth_data =
+ IceGenerateMagicCookie (MAGIC_COOKIE_LEN);
+ (*_authDataEntries)[i].auth_data_length = MAGIC_COOKIE_LEN;
+
+ (*_authDataEntries)[i+1].network_id =
+ IceGetListenConnectionString (_listenObjs[i/2]);
+ (*_authDataEntries)[i+1].protocol_name = const_cast<char *>("DCOP");
+ (*_authDataEntries)[i+1].auth_name = const_cast<char *>("MIT-MAGIC-COOKIE-1");
+
+ (*_authDataEntries)[i+1].auth_data =
+ IceGenerateMagicCookie (MAGIC_COOKIE_LEN);
+ (*_authDataEntries)[i+1].auth_data_length = MAGIC_COOKIE_LEN;
+
+ write_iceauth (addfp, &(*_authDataEntries)[i]);
+ write_iceauth (addfp, &(*_authDataEntries)[i+1]);
+
+ IceSetPaAuthData (2, &(*_authDataEntries)[i]);
+
+ IceSetHostBasedAuthProc (_listenObjs[i/2], HostBasedAuthProc);
+ }
+
+ fclose (addfp);
+
+ umask (original_umask);
+
+ command = DCOPClient::iceauthPath();
+
+ if (command.isEmpty())
+ {
+ fprintf( stderr, "dcopserver: 'iceauth' not found in path, aborting.\n" );
+ exit(1);
+ }
+
+ command += " source ";
+ command += addAuthFile;
+ system (command);
+
+ unlink(addAuthFile);
+
+ return (1);
+
+ bad:
+
+ if (addfp)
+ fclose (addfp);
+
+ if (addAuthFile) {
+ unlink(addAuthFile);
+ free(addAuthFile);
+ }
+
+ umask (original_umask);
+
+ return (0);
+}
+
+/*
+ * Free up authentication data.
+ */
+void
+FreeAuthenticationData(int count, IceAuthDataEntry *_authDataEntries)
+{
+ /* Each transport has entries for ICE and XSMP */
+ int i;
+
+ for (i = 0; i < count * 2; i++) {
+ free (_authDataEntries[i].network_id);
+ free (_authDataEntries[i].auth_data);
+ }
+
+ free(_authDataEntries);
+ free(addAuthFile);
+}
+
+void DCOPWatchProc ( IceConn iceConn, IcePointer client_data, Bool opening, IcePointer* watch_data)
+{
+ DCOPServer* ds = static_cast<DCOPServer*>(client_data);
+
+ if (opening) {
+ *watch_data = static_cast<IcePointer>(ds->watchConnection( iceConn ));
+ }
+ else {
+ ds->removeConnection( static_cast<void*>(*watch_data) );
+ }
+}
+
+void DCOPProcessMessage( IceConn iceConn, IcePointer /*clientData*/,
+ int opcode, unsigned long length, Bool swap)
+{
+ the_server->processMessage( iceConn, opcode, length, swap );
+}
+
+void DCOPServer::processMessage( IceConn iceConn, int opcode,
+ unsigned long length, Bool /*swap*/)
+{
+ DCOPConnection* conn = clients.find( iceConn );
+ if ( !conn ) {
+ qWarning("DCOPServer::processMessage message from unknown connection. [opcode = %d]", opcode);
+ return;
+ }
+ switch( opcode ) {
+ case DCOPSend:
+ case DCOPReplyDelayed:
+ {
+ DCOPMsg *pMsg = 0;
+ IceReadMessageHeader(iceConn, sizeof(DCOPMsg), DCOPMsg, pMsg);
+ CARD32 key = pMsg->key;
+ QByteArray ba( length );
+ IceReadData(iceConn, length, ba.data() );
+ QDataStream ds( ba, IO_ReadOnly );
+ QCString fromApp = readQCString(ds);
+ QCString toApp = readQCString(ds);
+
+ DCOPConnection* target = findApp( toApp );
+ int datalen = ba.size();
+ if ( opcode == DCOPReplyDelayed ) {
+ if ( !target )
+ qWarning("DCOPServer::DCOPReplyDelayed for unknown connection.");
+ else if ( !conn )
+ qWarning("DCOPServer::DCOPReplyDelayed from unknown connection.");
+ else if (!conn->waitingForDelayedReply.removeRef( target->iceConn ))
+ qWarning("DCOPServer::DCOPReplyDelayed from/to does not match. (#2)");
+ else if (!target->waitingOnReply.removeRef(iceConn))
+ qWarning("DCOPServer::DCOPReplyDelayed for client who wasn't waiting on one!");
+ }
+ if ( target ) {
+#ifdef DCOP_DEBUG
+if (opcode == DCOPSend)
+{
+ QCString obj = readQCString(ds);
+ QCString fun = readQCString(ds);
+ qWarning("Sending %d bytes from %s to %s. DCOPSend %s", length, fromApp.data(), toApp.data(), fun.data());
+}
+#endif
+ IceGetHeader( target->iceConn, majorOpcode, opcode,
+ sizeof(DCOPMsg), DCOPMsg, pMsg );
+ pMsg->key = key;
+ pMsg->length += datalen;
+ _DCOPIceSendBegin( target->iceConn );
+ DCOPIceSendData(target->iceConn, ba);
+ _DCOPIceSendEnd();
+ } else if ( toApp == "DCOPServer" ) {
+ QCString obj = readQCString(ds);
+ QCString fun = readQCString(ds);
+ QByteArray data = readQByteArray(ds);
+
+ QCString replyType;
+ QByteArray replyData;
+ if ( !receive( toApp, obj, fun, data, replyType, replyData, iceConn ) ) {
+ qWarning("%s failure: object '%s' has no function '%s'", toApp.data(), obj.data(), fun.data() );
+ }
+ } else if ( toApp[toApp.length()-1] == '*') {
+#ifdef DCOP_DEBUG
+if (opcode == DCOPSend)
+{
+ QCString obj = readQCString(ds);
+ QCString fun = readQCString(ds);
+ qWarning("Sending %d bytes from %s to %s. DCOPSend %s", length, fromApp.data(), toApp.data(), fun.data());
+}
+#endif
+ // handle a multicast.
+ QAsciiDictIterator<DCOPConnection> aIt(appIds);
+ int l = toApp.length()-1;
+ for ( ; aIt.current(); ++aIt) {
+ DCOPConnection *client = aIt.current();
+ if (!l || (strncmp(client->appId.data(), toApp.data(), l) == 0))
+ {
+ IceGetHeader(client->iceConn, majorOpcode, DCOPSend,
+ sizeof(DCOPMsg), DCOPMsg, pMsg);
+ pMsg->key = key;
+ pMsg->length += datalen;
+ _DCOPIceSendBegin( client->iceConn );
+ DCOPIceSendData(client->iceConn, ba);
+ _DCOPIceSendEnd();
+ }
+ }
+ }
+ }
+ break;
+ case DCOPCall:
+ case DCOPFind:
+ {
+ DCOPMsg *pMsg = 0;
+ IceReadMessageHeader(iceConn, sizeof(DCOPMsg), DCOPMsg, pMsg);
+ CARD32 key = pMsg->key;
+ QByteArray ba( length );
+ IceReadData(iceConn, length, ba.data() );
+ QDataStream ds( ba, IO_ReadOnly );
+ QCString fromApp = readQCString(ds);
+ QCString toApp = readQCString(ds);
+ DCOPConnection* target = findApp( toApp );
+ int datalen = ba.size();
+
+ if ( target ) {
+#ifdef DCOP_DEBUG
+if (opcode == DCOPCall)
+{
+ QCString obj = readQCString(ds);
+ QCString fun = readQCString(ds);
+ qWarning("Sending %d bytes from %s to %s. DCOPCall %s", length, fromApp.data(), toApp.data(), fun.data());
+}
+#endif
+ target->waitingForReply.append( iceConn );
+ conn->waitingOnReply.append( target->iceConn);
+
+ IceGetHeader( target->iceConn, majorOpcode, opcode,
+ sizeof(DCOPMsg), DCOPMsg, pMsg );
+ pMsg->key = key;
+ pMsg->length += datalen;
+ _DCOPIceSendBegin( target->iceConn );
+ DCOPIceSendData(target->iceConn, ba);
+ _DCOPIceSendEnd();
+ } else {
+ QCString replyType;
+ QByteArray replyData;
+ bool b = false;
+ // DCOPServer itself does not do DCOPFind.
+ if ( (opcode == DCOPCall) && (toApp == "DCOPServer") ) {
+ QCString obj = readQCString(ds);
+ QCString fun = readQCString(ds);
+ QByteArray data = readQByteArray(ds);
+ b = receive( toApp, obj, fun, data, replyType, replyData, iceConn );
+ if ( !b )
+ qWarning("%s failure: object '%s' has no function '%s'", toApp.data(), obj.data(), fun.data() );
+ }
+
+ if (b) {
+ QByteArray reply;
+ QDataStream replyStream( reply, IO_WriteOnly );
+ replyStream << toApp << fromApp << replyType << replyData.size();
+ int replylen = reply.size() + replyData.size();
+ IceGetHeader( iceConn, majorOpcode, DCOPReply,
+ sizeof(DCOPMsg), DCOPMsg, pMsg );
+ if ( key != 0 )
+ pMsg->key = key;
+ else
+ pMsg->key = serverKey++;
+ pMsg->length += replylen;
+ _DCOPIceSendBegin( iceConn );
+ DCOPIceSendData( iceConn, reply);
+ DCOPIceSendData( iceConn, replyData);
+ _DCOPIceSendEnd();
+ } else {
+ QByteArray reply;
+ QDataStream replyStream( reply, IO_WriteOnly );
+ replyStream << toApp << fromApp;
+ IceGetHeader( iceConn, majorOpcode, DCOPReplyFailed,
+ sizeof(DCOPMsg), DCOPMsg, pMsg );
+ if ( key != 0 )
+ pMsg->key = key;
+ else
+ pMsg->key = serverKey++;
+ pMsg->length += reply.size();
+ _DCOPIceSendBegin( iceConn );
+ DCOPIceSendData( iceConn, reply );
+ _DCOPIceSendEnd();
+ }
+ }
+ }
+ break;
+ case DCOPReply:
+ case DCOPReplyFailed:
+ case DCOPReplyWait:
+ {
+ DCOPMsg *pMsg = 0;
+ IceReadMessageHeader(iceConn, sizeof(DCOPMsg), DCOPMsg, pMsg);
+ CARD32 key = pMsg->key;
+ QByteArray ba( length );
+ IceReadData(iceConn, length, ba.data() );
+ QDataStream ds( ba, IO_ReadOnly );
+ QCString fromApp = readQCString(ds);
+ QCString toApp = readQCString(ds);
+
+ DCOPConnection* connreply = findApp( toApp );
+ int datalen = ba.size();
+
+ if ( !connreply )
+ qWarning("DCOPServer::DCOPReply for unknown connection.");
+ else {
+ conn->waitingForReply.removeRef( connreply->iceConn );
+ if ( opcode == DCOPReplyWait )
+ {
+ conn->waitingForDelayedReply.append( connreply->iceConn );
+ }
+ else
+ { // DCOPReply or DCOPReplyFailed
+ if (!connreply->waitingOnReply.removeRef(iceConn))
+ qWarning("DCOPServer::DCOPReply from %s to %s who wasn't waiting on one!",
+ fromApp.data(), toApp.data());
+ }
+ IceGetHeader( connreply->iceConn, majorOpcode, opcode,
+ sizeof(DCOPMsg), DCOPMsg, pMsg );
+ pMsg->key = key;
+ pMsg->length += datalen;
+ _DCOPIceSendBegin( connreply->iceConn );
+ DCOPIceSendData(connreply->iceConn, ba);
+ _DCOPIceSendEnd();
+ }
+ }
+ break;
+ default:
+ qWarning("DCOPServer::processMessage unknown message");
+ }
+}
+
+static const IcePaVersionRec DCOPServerVersions[] = {
+ { DCOPVersionMajor, DCOPVersionMinor, DCOPProcessMessage }
+};
+
+static const IcePoVersionRec DUMMYVersions[] = {
+ { DCOPVersionMajor, DCOPVersionMinor, 0 }
+};
+
+static Status DCOPServerProtocolSetupProc ( IceConn /*iceConn*/,
+ int majorVersion, int minorVersion,
+ char* vendor, char* release,
+ IcePointer *clientDataRet,
+ char ** /*failureReasonRet*/)
+{
+ /*
+ * vendor/release are undefined for ProtocolSetup in DCOP
+ */
+
+ if (vendor)
+ free (vendor);
+ if (release)
+ free (release);
+
+ *clientDataRet = 0;
+
+ return (majorVersion == DCOPVersionMajor && minorVersion == DCOPVersionMinor);
+}
+
+#ifndef Q_OS_WIN
+static int pipeOfDeath[2];
+
+static void sighandler(int sig)
+{
+ if (sig == SIGHUP) {
+ signal(SIGHUP, sighandler);
+ return;
+ }
+
+ write(pipeOfDeath[1], "x", 1);
+}
+#endif
+
+extern "C"
+{
+ extern int _kde_IceLastMajorOpcode; // from libICE
+}
+
+DCOPServer::DCOPServer(bool _suicide)
+ : QObject(0,0), currentClientNumber(0), appIds(263), clients(263)
+{
+ serverKey = 42;
+
+ suicide = _suicide;
+ shutdown = false;
+
+ dcopSignals = new DCOPSignals;
+
+ if (_kde_IceLastMajorOpcode < 1 )
+ IceRegisterForProtocolSetup(const_cast<char *>("DUMMY"),
+ const_cast<char *>("DUMMY"),
+ const_cast<char *>("DUMMY"),
+ 1, const_cast<IcePoVersionRec *>(DUMMYVersions),
+ DCOPAuthCount, const_cast<char **>(DCOPAuthNames),
+ DCOPClientAuthProcs, 0);
+ if (_kde_IceLastMajorOpcode < 1 )
+ qWarning("DCOPServer Error: incorrect major opcode!");
+
+ the_server = this;
+ if (( majorOpcode = IceRegisterForProtocolReply (const_cast<char *>("DCOP"),
+ const_cast<char *>(DCOPVendorString),
+ const_cast<char *>(DCOPReleaseString),
+ 1, const_cast<IcePaVersionRec *>(DCOPServerVersions),
+ 1, const_cast<char **>(DCOPAuthNames),
+ DCOPServerAuthProcs,
+ HostBasedAuthProc,
+ DCOPServerProtocolSetupProc,
+ NULL, /* IceProtocolActivateProc - we don't care about
+ when the Protocol Reply is sent, because the
+ session manager can not immediately send a
+ message - it must wait for RegisterClient. */
+ NULL /* IceIOErrorProc */
+ )) < 0)
+ {
+ qWarning("Could not register DCOP protocol with ICE");
+ }
+
+ char errormsg[256];
+ int orig_umask = umask(077); /*old libICE's don't reset the umask() they set */
+ if (!IceListenForConnections (&numTransports, &listenObjs,
+ 256, errormsg))
+ {
+ fprintf (stderr, "%s\n", errormsg);
+ exit (1);
+ } else {
+ (void) umask(orig_umask);
+ // publish available transports.
+ QCString fName = DCOPClient::dcopServerFile();
+ FILE *f;
+ if(!(f = ::fopen(fName.data(), "w+"))) {
+ fprintf (stderr, "Can not create file %s: %s\n",
+ fName.data(), ::strerror(errno));
+ exit(1);
+ }
+ char *idlist = IceComposeNetworkIdList(numTransports, listenObjs);
+ if (idlist != 0) {
+ fprintf(f, "%s", idlist);
+ free(idlist);
+ }
+ fprintf(f, "\n%i\n", getpid());
+ fclose(f);
+#ifndef Q_OS_WIN32
+ if (QCString(getenv("DCOPAUTHORITY")).isEmpty())
+ {
+ // Create a link named like the old-style (KDE 2.x) naming
+ QCString compatName = DCOPClient::dcopServerFileOld();
+ ::symlink(fName,compatName);
+ }
+#endif // Q_OS_WIN32
+ }
+
+#if 0
+ if (!SetAuthentication_local(numTransports, listenObjs))
+ qFatal("DCOPSERVER: authentication setup failed.");
+#endif
+ if (!SetAuthentication(numTransports, listenObjs, &authDataEntries))
+ qFatal("DCOPSERVER: authentication setup failed.");
+
+ IceAddConnectionWatch (DCOPWatchProc, static_cast<IcePointer>(this));
+ _IceWriteHandler = DCOPIceWriteChar;
+
+ listener.setAutoDelete( true );
+ DCOPListener* con;
+ for ( int i = 0; i < numTransports; i++) {
+ con = new DCOPListener( listenObjs[i] );
+ listener.append( con );
+ connect( con, SIGNAL( activated(int) ), this, SLOT( newClient(int) ) );
+ }
+ char c = 0;
+ write(ready[1], &c, 1); // dcopserver is started
+ close(ready[1]);
+
+ m_timer = new QTimer(this);
+ connect( m_timer, SIGNAL(timeout()), this, SLOT(slotTerminate()) );
+ m_deadConnectionTimer = new QTimer(this);
+ connect( m_deadConnectionTimer, SIGNAL(timeout()), this, SLOT(slotCleanDeadConnections()) );
+
+#ifdef Q_OS_WIN
+ char szEventName[256];
+ sprintf(szEventName,"dcopserver%i",GetCurrentProcessId());
+ m_evTerminate = CreateEventA(NULL,TRUE,FALSE,(LPCSTR)szEventName);
+ ResetEvent(m_evTerminate);
+ m_hTerminateThread = CreateThread(NULL,0,TerminatorThread,this,0,&m_dwTerminateThreadId);
+ if(m_hTerminateThread)
+ CloseHandle(m_hTerminateThread);
+#endif
+
+#ifdef DCOP_LOG
+ char hostname_buffer[256];
+ memset( hostname_buffer, 0, sizeof( hostname_buffer ) );
+ if ( gethostname( hostname_buffer, 255 ) < 0 )
+ hostname_buffer[0] = '\0';
+ m_logger = new QFile( QString( "%1/.dcop-%2.log" ).arg( QDir::homeDirPath() ).arg( hostname_buffer ) );
+ if ( m_logger->open( IO_WriteOnly ) ) {
+ m_stream = new QTextStream( m_logger );
+ }
+#endif
+}
+
+DCOPServer::~DCOPServer()
+{
+ system(findDcopserverShutdown()+" --nokill");
+ IceFreeListenObjs(numTransports, listenObjs);
+ FreeAuthenticationData(numTransports, authDataEntries);
+ delete dcopSignals;
+#ifdef DCOP_LOG
+ delete m_stream;
+ m_logger->close();
+ delete m_logger;
+#endif
+#ifdef Q_OS_WIN
+ SetEvent(m_evTerminate);
+ CloseHandle(m_evTerminate);
+#endif
+}
+
+DCOPConnection* DCOPServer::findApp( const QCString& appId )
+{
+ if ( appId.isNull() )
+ return 0;
+ DCOPConnection* conn = appIds.find( appId );
+ return conn;
+}
+
+/*!
+ Called by timer after write errors.
+ */
+void DCOPServer::slotCleanDeadConnections()
+{
+qWarning("DCOP Cleaning up dead connections.");
+ while(!deadConnections.isEmpty())
+ {
+ IceConn iceConn = deadConnections.take(0);
+ IceSetShutdownNegotiation (iceConn, False);
+ (void) IceCloseConnection( iceConn );
+ }
+}
+
+/*!
+ Called from our IceIoErrorHandler
+ */
+void DCOPServer::ioError( IceConn iceConn )
+{
+ deadConnections.removeRef(iceConn);
+ deadConnections.prepend(iceConn);
+ m_deadConnectionTimer->start(0, true);
+}
+
+
+void DCOPServer::processData( int /*socket*/ )
+{
+ IceConn iceConn = static_cast<const DCOPConnection*>(sender())->iceConn;
+ IceProcessMessagesStatus status = IceProcessMessages( iceConn, 0, 0 );
+ if ( status == IceProcessMessagesIOError ) {
+ deadConnections.removeRef(iceConn);
+ if (deadConnections.isEmpty())
+ m_deadConnectionTimer->stop();
+ IceSetShutdownNegotiation (iceConn, False);
+ (void) IceCloseConnection( iceConn );
+ }
+}
+
+void DCOPServer::newClient( int /*socket*/ )
+{
+ IceAcceptStatus status;
+ IceConn iceConn = IceAcceptConnection( static_cast<const DCOPListener*>(sender())->listenObj, &status);
+ if (!iceConn) {
+ if (status == IceAcceptBadMalloc)
+ qWarning("Failed to alloc connection object!\n");
+ else // IceAcceptFailure
+ qWarning("Failed to accept ICE connection!\n");
+ return;
+ }
+
+ IceSetShutdownNegotiation( iceConn, False );
+
+ IceConnectStatus cstatus;
+ while ((cstatus = IceConnectionStatus (iceConn))==IceConnectPending) {
+ (void) IceProcessMessages( iceConn, 0, 0 );
+ }
+
+ if (cstatus != IceConnectAccepted) {
+ if (cstatus == IceConnectIOError)
+ qWarning ("IO error opening ICE Connection!\n");
+ else
+ qWarning ("ICE Connection rejected!\n");
+ deadConnections.removeRef(iceConn);
+ (void) IceCloseConnection (iceConn);
+ }
+}
+
+void* DCOPServer::watchConnection( IceConn iceConn )
+{
+ DCOPConnection* con = new DCOPConnection( iceConn );
+ connect( con, SIGNAL( activated(int) ), this, SLOT( processData(int) ) );
+
+ clients.insert(iceConn, con );
+ fd_clients.insert( IceConnectionNumber(iceConn), con);
+
+ return static_cast<void*>(con);
+}
+
+void DCOPServer::removeConnection( void* data )
+{
+ DCOPConnection* conn = static_cast<DCOPConnection*>(data);
+
+ dcopSignals->removeConnections(conn);
+
+ clients.remove(conn->iceConn );
+ fd_clients.remove( IceConnectionNumber(conn->iceConn) );
+
+ // Send DCOPReplyFailed to all in conn->waitingForReply
+ while (!conn->waitingForReply.isEmpty()) {
+ IceConn iceConn = conn->waitingForReply.take(0);
+ if (iceConn) {
+ DCOPConnection* target = clients.find( iceConn );
+ qWarning("DCOP aborting call from '%s' to '%s'", target ? target->appId.data() : "<unknown>" , conn->appId.data() );
+ QByteArray reply;
+ DCOPMsg *pMsg;
+ IceGetHeader( iceConn, majorOpcode, DCOPReplyFailed,
+ sizeof(DCOPMsg), DCOPMsg, pMsg );
+ pMsg->key = 1;
+ pMsg->length += reply.size();
+ _DCOPIceSendBegin( iceConn );
+ DCOPIceSendData(iceConn, reply);
+ _DCOPIceSendEnd();
+ if (!target)
+ qWarning("DCOP Error: unknown target in waitingForReply");
+ else if (!target->waitingOnReply.removeRef(conn->iceConn))
+ qWarning("DCOP Error: client in waitingForReply wasn't waiting on reply");
+ }
+ }
+
+ // Send DCOPReplyFailed to all in conn->waitingForDelayedReply
+ while (!conn->waitingForDelayedReply.isEmpty()) {
+ IceConn iceConn = conn->waitingForDelayedReply.take(0);
+ if (iceConn) {
+ DCOPConnection* target = clients.find( iceConn );
+ qWarning("DCOP aborting (delayed) call from '%s' to '%s'", target ? target->appId.data() : "<unknown>", conn->appId.data() );
+ QByteArray reply;
+ DCOPMsg *pMsg;
+ IceGetHeader( iceConn, majorOpcode, DCOPReplyFailed,
+ sizeof(DCOPMsg), DCOPMsg, pMsg );
+ pMsg->key = 1;
+ pMsg->length += reply.size();
+ _DCOPIceSendBegin( iceConn );
+ DCOPIceSendData( iceConn, reply );
+ _DCOPIceSendEnd();
+ if (!target)
+ qWarning("DCOP Error: unknown target in waitingForDelayedReply");
+ else if (!target->waitingOnReply.removeRef(conn->iceConn))
+ qWarning("DCOP Error: client in waitingForDelayedReply wasn't waiting on reply");
+ }
+ }
+ while (!conn->waitingOnReply.isEmpty())
+ {
+ IceConn iceConn = conn->waitingOnReply.take(0);
+ if (iceConn) {
+ DCOPConnection* target = clients.find( iceConn );
+ if (!target)
+ {
+ qWarning("DCOP Error: still waiting for answer from non-existing client.");
+ continue;
+ }
+ qWarning("DCOP aborting while waiting for answer from '%s'", target->appId.data());
+ if (!target->waitingForReply.removeRef(conn->iceConn) &&
+ !target->waitingForDelayedReply.removeRef(conn->iceConn))
+ qWarning("DCOP Error: called client has forgotten about caller");
+ }
+ }
+
+ if ( !conn->appId.isNull() ) {
+#ifndef NDEBUG
+ qDebug("DCOP: unregister '%s'", conn->appId.data() );
+#endif
+ if ( !conn->daemon )
+ {
+ currentClientNumber--;
+ }
+
+ appIds.remove( conn->appId );
+
+ broadcastApplicationRegistration( conn, "applicationRemoved(QCString)", conn->appId );
+ }
+
+ delete conn;
+
+ if ( suicide && (currentClientNumber == 0) )
+ {
+ m_timer->start( 10000 ); // if within 10 seconds nothing happens, we'll terminate
+ }
+ if ( shutdown && appIds.isEmpty())
+ {
+ m_timer->start( 10 ); // Exit now
+ }
+}
+
+void DCOPServer::slotTerminate()
+{
+#ifndef NDEBUG
+ fprintf( stderr, "DCOPServer : slotTerminate() -> sending terminateKDE signal.\n" );
+#endif
+ QByteArray data;
+ dcopSignals->emitSignal(0L /* dcopserver */, "terminateKDE()", data, false);
+ disconnect( m_timer, SIGNAL(timeout()), this, SLOT(slotTerminate()) );
+ connect( m_timer, SIGNAL(timeout()), this, SLOT(slotSuicide()) );
+ system(findDcopserverShutdown()+" --nokill");
+}
+
+void DCOPServer::slotSuicide()
+{
+#ifndef NDEBUG
+ fprintf( stderr, "DCOPServer : slotSuicide() -> exit.\n" );
+#endif
+ exit(0);
+}
+
+void DCOPServer::slotShutdown()
+{
+#ifndef NDEBUG
+ fprintf( stderr, "DCOPServer : slotShutdown() -> waiting for clients to disconnect.\n" );
+#endif
+ char c;
+#ifndef Q_OS_WIN
+ read(pipeOfDeath[0], &c, 1);
+#endif
+ if (!shutdown)
+ {
+ shutdown = true;
+ QByteArray data;
+ dcopSignals->emitSignal(0L /* dcopserver */, "terminateKDE()", data, false);
+ m_timer->start( 10000 ); // if within 10 seconds nothing happens, we'll terminate
+ disconnect( m_timer, SIGNAL(timeout()), this, SLOT(slotTerminate()) );
+ connect( m_timer, SIGNAL(timeout()), this, SLOT(slotExit()) );
+ if (appIds.isEmpty())
+ slotExit(); // Exit now
+ }
+}
+
+void DCOPServer::slotExit()
+{
+#ifndef NDEBUG
+ fprintf( stderr, "DCOPServer : slotExit() -> exit.\n" );
+#endif
+#ifdef Q_OS_WIN
+ SetEvent(m_evTerminate);
+ if(m_dwTerminateThreadId != GetCurrentThreadId())
+ WaitForSingleObject(m_hTerminateThread,INFINITE);
+ CloseHandle(m_hTerminateThread);
+#endif
+ exit(0);
+}
+
+bool DCOPServer::receive(const QCString &/*app*/, const QCString &obj,
+ const QCString &fun, const QByteArray& data,
+ QCString& replyType, QByteArray &replyData,
+ IceConn iceConn)
+{
+#ifdef DCOP_LOG
+ (*m_stream) << "Received a message: obj =\""
+ << obj << "\", fun =\""
+ << fun << "\", replyType =\""
+ << replyType << "\", data.size() =\""
+ << data.size() << "\", replyData.size() ="
+ << replyData.size() << "\n";
+ m_logger->flush();
+#endif
+
+ if ( obj == "emit")
+ {
+ DCOPConnection* conn = clients.find( iceConn );
+ if (conn) {
+ //qDebug("DCOPServer: %s emits %s", conn->appId.data(), fun.data());
+ dcopSignals->emitSignal(conn, fun, data, false);
+ }
+ replyType = "void";
+ return true;
+ }
+ if ( fun == "setDaemonMode(bool)" ) {
+ QDataStream args( data, IO_ReadOnly );
+ if ( !args.atEnd() ) {
+ Q_INT8 iDaemon;
+ bool daemon;
+ args >> iDaemon;
+
+ daemon = static_cast<bool>( iDaemon );
+
+ DCOPConnection* conn = clients.find( iceConn );
+ if ( conn && !conn->appId.isNull() ) {
+ if ( daemon ) {
+ if ( !conn->daemon )
+ {
+ conn->daemon = true;
+
+#ifndef NDEBUG
+ qDebug( "DCOP: new daemon %s", conn->appId.data() );
+#endif
+
+ currentClientNumber--;
+
+// David says it's safer not to do this :-)
+// if ( currentClientNumber == 0 )
+// m_timer->start( 10000 );
+ }
+ } else
+ {
+ if ( conn->daemon ) {
+ conn->daemon = false;
+
+ currentClientNumber++;
+
+ m_timer->stop();
+ }
+ }
+ }
+
+ replyType = "void";
+ return true;
+ }
+ }
+ if ( fun == "registerAs(QCString)" ) {
+ QDataStream args( data, IO_ReadOnly );
+ if (!args.atEnd()) {
+ QCString app2 = readQCString(args);
+ QDataStream reply( replyData, IO_WriteOnly );
+ DCOPConnection* conn = clients.find( iceConn );
+ if ( conn && !app2.isEmpty() ) {
+ if ( !conn->appId.isNull() &&
+ appIds.find( conn->appId ) == conn ) {
+ appIds.remove( conn->appId );
+
+ }
+
+ QCString oldAppId;
+ if ( conn->appId.isNull() )
+ {
+ currentClientNumber++;
+ m_timer->stop(); // abort termination if we were planning one
+#ifndef NDEBUG
+ qDebug("DCOP: register '%s' -> number of clients is now %d", app2.data(), currentClientNumber );
+#endif
+ }
+#ifndef NDEBUG
+ else
+ {
+ oldAppId = conn->appId;
+ qDebug("DCOP: '%s' now known as '%s'", conn->appId.data(), app2.data() );
+ }
+#endif
+
+ conn->appId = app2;
+ if ( appIds.find( app2 ) != 0 ) {
+ // we already have this application, unify
+ int n = 1;
+ QCString tmp;
+ do {
+ n++;
+ tmp.setNum( n );
+ tmp.prepend("-");
+ tmp.prepend( app2 );
+ } while ( appIds.find( tmp ) != 0 );
+ conn->appId = tmp;
+ }
+ appIds.insert( conn->appId, conn );
+
+ int c = conn->appId.find( '-' );
+ if ( c > 0 )
+ conn->plainAppId = conn->appId.left( c );
+ else
+ conn->plainAppId = conn->appId;
+
+ if( !oldAppId.isEmpty())
+ broadcastApplicationRegistration( conn,
+ "applicationRemoved(QCString)", oldAppId );
+ broadcastApplicationRegistration( conn, "applicationRegistered(QCString)", conn->appId );
+ }
+ replyType = "QCString";
+ reply << conn->appId;
+ return true;
+ }
+ }
+ else if ( fun == "registeredApplications()" ) {
+ QDataStream reply( replyData, IO_WriteOnly );
+ QCStringList applications;
+ QAsciiDictIterator<DCOPConnection> it( appIds );
+ while ( it.current() ) {
+ applications << it.currentKey();
+ ++it;
+ }
+ replyType = "QCStringList";
+ reply << applications;
+ return true;
+ } else if ( fun == "isApplicationRegistered(QCString)" ) {
+ QDataStream args( data, IO_ReadOnly );
+ if (!args.atEnd()) {
+ QCString s = readQCString(args);
+ QDataStream reply( replyData, IO_WriteOnly );
+ int b = ( findApp( s ) != 0 );
+ replyType = "bool";
+ reply << b;
+ return true;
+ }
+ } else if ( fun == "setNotifications(bool)" ) {
+ QDataStream args( data, IO_ReadOnly );
+ if (!args.atEnd()) {
+ Q_INT8 notifyActive;
+ args >> notifyActive;
+ DCOPConnection* conn = clients.find( iceConn );
+ if ( conn ) {
+ if ( notifyActive )
+ conn->notifyRegister++;
+ else if ( conn->notifyRegister > 0 )
+ conn->notifyRegister--;
+ }
+ replyType = "void";
+ return true;
+ }
+ } else if ( fun == "connectSignal(QCString,QCString,QCString,QCString,QCString,bool)") {
+ DCOPConnection* conn = clients.find( iceConn );
+ if (!conn) return false;
+ QDataStream args(data, IO_ReadOnly );
+ if (args.atEnd()) return false;
+ QCString sender = readQCString(args);
+ QCString senderObj = readQCString(args);
+ QCString signal = readQCString(args);
+ QCString receiverObj = readQCString(args);
+ QCString slot = readQCString(args);
+ Q_INT8 Volatile;
+ args >> Volatile;
+ //qDebug("DCOPServer: connectSignal(sender = %s senderObj = %s signal = %s recvObj = %s slot = %s)", sender.data(), senderObj.data(), signal.data(), receiverObj.data(), slot.data());
+ bool b = dcopSignals->connectSignal(sender, senderObj, signal, conn, receiverObj, slot, (Volatile != 0));
+ replyType = "bool";
+ QDataStream reply( replyData, IO_WriteOnly );
+ reply << (Q_INT8) (b?1:0);
+ return true;
+ } else if ( fun == "disconnectSignal(QCString,QCString,QCString,QCString,QCString)") {
+ DCOPConnection* conn = clients.find( iceConn );
+ if (!conn) return false;
+ QDataStream args(data, IO_ReadOnly );
+ if (args.atEnd()) return false;
+ QCString sender = readQCString(args);
+ QCString senderObj = readQCString(args);
+ QCString signal = readQCString(args);
+ QCString receiverObj = readQCString(args);
+ QCString slot = readQCString(args);
+ //qDebug("DCOPServer: disconnectSignal(sender = %s senderObj = %s signal = %s recvObj = %s slot = %s)", sender.data(), senderObj.data(), signal.data(), receiverObj.data(), slot.data());
+ bool b = dcopSignals->disconnectSignal(sender, senderObj, signal, conn, receiverObj, slot);
+ replyType = "bool";
+ QDataStream reply( replyData, IO_WriteOnly );
+ reply << (Q_INT8) (b?1:0);
+ return true;
+ }
+
+ return false;
+}
+
+void DCOPServer::broadcastApplicationRegistration( DCOPConnection* conn, const QCString type,
+ const QCString& appId )
+{
+ QByteArray data;
+ QDataStream datas( data, IO_WriteOnly );
+ datas << appId;
+ QPtrDictIterator<DCOPConnection> it( clients );
+ QByteArray ba;
+ QDataStream ds( ba, IO_WriteOnly );
+ ds <<QCString("DCOPServer") << QCString("") << QCString("")
+ << type << data;
+ int datalen = ba.size();
+ DCOPMsg *pMsg = 0;
+ while ( it.current() ) {
+ DCOPConnection* c = it.current();
+ ++it;
+ if ( c->notifyRegister && (c != conn) ) {
+ IceGetHeader( c->iceConn, majorOpcode, DCOPSend,
+ sizeof(DCOPMsg), DCOPMsg, pMsg );
+ pMsg->key = 1;
+ pMsg->length += datalen;
+ _DCOPIceSendBegin(c->iceConn);
+ DCOPIceSendData( c->iceConn, ba );
+ _DCOPIceSendEnd();
+ }
+ }
+}
+
+void
+DCOPServer::sendMessage(DCOPConnection *conn, const QCString &sApp,
+ const QCString &rApp, const QCString &rObj,
+ const QCString &rFun, const QByteArray &data)
+{
+ QByteArray ba;
+ QDataStream ds( ba, IO_WriteOnly );
+ ds << sApp << rApp << rObj << rFun << data;
+ int datalen = ba.size();
+ DCOPMsg *pMsg = 0;
+
+ IceGetHeader( conn->iceConn, majorOpcode, DCOPSend,
+ sizeof(DCOPMsg), DCOPMsg, pMsg );
+ pMsg->length += datalen;
+ pMsg->key = 1; // important!
+
+#ifdef DCOP_LOG
+ (*m_stream) << "Sending a message: sApp =\""
+ << sApp << "\", rApp =\""
+ << rApp << "\", rObj =\""
+ << rObj << "\", rFun =\""
+ << rFun << "\", datalen ="
+ << datalen << "\n";
+ m_logger->flush();
+#endif
+
+ _DCOPIceSendBegin( conn->iceConn );
+ DCOPIceSendData(conn->iceConn, ba);
+ _DCOPIceSendEnd();
+}
+
+void IoErrorHandler ( IceConn iceConn)
+{
+ the_server->ioError( iceConn );
+}
+
+static bool isRunning(const QCString &fName, bool printNetworkId = false)
+{
+ if (::access(fName.data(), R_OK) == 0) {
+ QFile f(fName);
+ f.open(IO_ReadOnly);
+ int size = QMIN( 1024, f.size() ); // protection against a huge file
+ QCString contents( size+1 );
+ bool ok = f.readBlock( contents.data(), size ) == size;
+ contents[size] = '\0';
+ int pos = contents.find('\n');
+ ok = ok && ( pos != -1 );
+ pid_t pid = ok ? contents.mid(pos+1).toUInt(&ok) : 0;
+ f.close();
+ if (ok && pid && (kill(pid, SIGHUP) == 0)) {
+ if (printNetworkId)
+ qWarning("%s", contents.left(pos).data());
+ else
+ qWarning( "---------------------------------\n"
+ "It looks like dcopserver is already running. If you are sure\n"
+ "that it is not already running, remove %s\n"
+ "and start dcopserver again.\n"
+ "---------------------------------\n",
+ fName.data() );
+
+ // lock file present, die silently.
+ return true;
+ } else {
+ // either we couldn't read the PID or kill returned an error.
+ // remove lockfile and continue
+ unlink(fName.data());
+ }
+ } else if (errno != ENOENT) {
+ // remove lockfile and continue
+ unlink(fName.data());
+ }
+ return false;
+}
+
+const char* const ABOUT =
+"Usage: dcopserver [--nofork] [--nosid] [--help]\n"
+" dcopserver --serverid\n"
+"\n"
+"DCOP is KDE's Desktop Communications Protocol. It is a lightweight IPC/RPC\n"
+"mechanism built on top of the X Consortium's Inter Client Exchange protocol.\n"
+"It enables desktop applications to communicate reliably with low overhead.\n"
+"\n"
+"Copyright (C) 1999-2001, The KDE Developers <http://www.kde.org>\n"
+;
+
+extern "C" DCOP_EXPORT int kdemain( int argc, char* argv[] )
+{
+ bool serverid = false;
+ bool nofork = false;
+ bool nosid = false;
+ bool suicide = false;
+ for(int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "--nofork") == 0)
+ nofork = true;
+ else if (strcmp(argv[i], "--nosid") == 0)
+ nosid = true;
+ else if (strcmp(argv[i], "--nolocal") == 0)
+ ; // Ignore
+ else if (strcmp(argv[i], "--suicide") == 0)
+ suicide = true;
+ else if (strcmp(argv[i], "--serverid") == 0)
+ serverid = true;
+ else {
+ fprintf(stdout, "%s", ABOUT );
+ return 0;
+ }
+ }
+
+ if (serverid)
+ {
+ if (isRunning(DCOPClient::dcopServerFile(), true))
+ return 0;
+ return 1;
+ }
+
+ // check if we are already running
+ if (isRunning(DCOPClient::dcopServerFile()))
+ return 0;
+#ifndef Q_OS_WIN32
+ if (QCString(getenv("DCOPAUTHORITY")).isEmpty() &&
+ isRunning(DCOPClient::dcopServerFileOld()))
+ {
+ // Make symlink for compatibility
+ QCString oldFile = DCOPClient::dcopServerFileOld();
+ QCString newFile = DCOPClient::dcopServerFile();
+ symlink(oldFile.data(), newFile.data());
+ return 0;
+ }
+
+ struct rlimit limits;
+
+ int retcode = getrlimit(RLIMIT_NOFILE, &limits);
+ if (!retcode) {
+ if (limits.rlim_max > 512 && limits.rlim_cur < 512)
+ {
+ int cur_limit = limits.rlim_cur;
+ limits.rlim_cur = 512;
+ retcode = setrlimit(RLIMIT_NOFILE, &limits);
+
+ if (retcode != 0)
+ {
+ qWarning("dcopserver: Could not raise limit on number of open files.");
+ qWarning("dcopserver: Current limit = %d", cur_limit);
+ }
+ }
+ }
+#endif
+ pipe(ready);
+
+#ifndef Q_OS_WIN32
+ if (!nofork) {
+ pid_t pid = fork();
+ if (pid > 0) {
+ char c = 1;
+ close(ready[1]);
+ read(ready[0], &c, 1); // Wait till dcopserver is started
+ close(ready[0]);
+ // I am the parent
+ if (c == 0)
+ {
+ // Test whether we are functional.
+ DCOPClient client;
+ if (client.attach())
+ return 0;
+ }
+ qWarning("DCOPServer self-test failed.");
+ system(findDcopserverShutdown()+" --kill");
+ return 1;
+ }
+ close(ready[0]);
+
+ if (!nosid)
+ setsid();
+
+ if (fork() > 0)
+ return 0; // get rid of controlling terminal
+ }
+
+ pipe(pipeOfDeath);
+
+ signal(SIGHUP, sighandler);
+ signal(SIGTERM, sighandler);
+ signal(SIGPIPE, SIG_IGN);
+#else
+ {
+ char c = 1;
+ close(ready[1]);
+ read(ready[0], &c, 1); // Wait till dcopserver is started
+ close(ready[0]);
+ }
+#endif
+ putenv(strdup("SESSION_MANAGER="));
+
+ QApplication a( argc, argv, false );
+
+ IceSetIOErrorHandler (IoErrorHandler );
+ DCOPServer *server = new DCOPServer(suicide); // this sets the_server
+
+#ifdef Q_OS_WIN
+ SetConsoleCtrlHandler(DCOPServer::dcopServerConsoleProc,TRUE);
+#else
+ QSocketNotifier DEATH(pipeOfDeath[0], QSocketNotifier::Read, 0, 0);
+ server->connect(&DEATH, SIGNAL(activated(int)), SLOT(slotShutdown()));
+#endif
+
+ int ret = a.exec();
+ delete server;
+ return ret;
+}
+
+#ifdef Q_OS_WIN
+#include "dcopserver_win.cpp"
+#endif
+
+#include "dcopserver.moc"
diff --git a/dcop/dcopserver.h b/dcop/dcopserver.h
new file mode 100644
index 000000000..5b7f995b6
--- /dev/null
+++ b/dcop/dcopserver.h
@@ -0,0 +1,186 @@
+/*
+Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+Copyright (c) 1999 Matthias Ettrich <ettrich@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 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.
+*/
+#ifndef DCOPSERVER_H
+#define DCOPSERVER_H "$Id$"
+
+#include <qobject.h>
+
+#include <qstring.h>
+#include <qsocketnotifier.h>
+#include <qptrlist.h>
+#include <qvaluelist.h>
+#include <qcstring.h>
+#include <qdict.h>
+#include <qptrdict.h>
+#include <qintdict.h>
+#include <qapplication.h>
+
+#define INT32 QINT32
+#ifdef Q_WS_X11
+#include <X11/Xlib.h>
+#include <X11/Xmd.h>
+#endif
+#include <KDE-ICE/ICElib.h>
+extern "C" {
+#include <KDE-ICE/ICEutil.h>
+#include <KDE-ICE/ICEmsg.h>
+#include <KDE-ICE/ICEproto.h>
+}
+
+class DCOPConnection;
+class DCOPListener;
+class DCOPSignalConnectionList;
+class DCOPSignals;
+class QTimer;
+
+// If you enable the following define DCOP will create
+// $HOME/.dcop.log file which will list all signals passing
+// through it.
+//#define DCOP_LOG
+#ifdef DCOP_LOG
+class QTextStream;
+class QFile;
+#endif
+
+typedef QValueList<QCString> QCStringList;
+
+/**
+ * @internal
+ */
+class DCOPConnection : public QSocketNotifier
+{
+public:
+ DCOPConnection( IceConn conn );
+ ~DCOPConnection();
+
+ DCOPSignalConnectionList *signalConnectionList();
+
+ // Add the data from offset @p start in @p _data to the output
+ // buffer and schedule it for later transmission.
+ void waitForOutputReady(const QByteArray &_data, int start);
+
+ // Called from DCOPServer::slotOutputReady()
+ // Flush the output buffer.
+ void slotOutputReady();
+
+ QCString appId;
+ QCString plainAppId;
+ IceConn iceConn;
+ int notifyRegister;
+ /**
+ * When client A has called client B then for the duration of the call:
+ * A->waitingOnReply contains B
+ * and either
+ * B->waitingForReply contains A
+ * or
+ * B->waitingForDelayedReply contains A
+ *
+ * This allows us to do proper bookkeeping in case client A, client B
+ * or both unregister during the call.
+ */
+ QPtrList <_IceConn> waitingOnReply;
+ QPtrList <_IceConn> waitingForReply;
+ QPtrList <_IceConn> waitingForDelayedReply;
+ DCOPSignalConnectionList *_signalConnectionList;
+ bool daemon;
+ bool outputBlocked;
+ QValueList <QByteArray> outputBuffer;
+ unsigned long outputBufferStart;
+ QSocketNotifier *outputBufferNotifier;
+};
+
+
+/**
+ * @internal
+ */
+class DCOPServer : public QObject
+{
+ Q_OBJECT
+public:
+ DCOPServer(bool _suicide);
+ ~DCOPServer();
+
+ void* watchConnection( IceConn iceConn );
+ void removeConnection( void* data );
+ void processMessage( IceConn iceConn, int opcode, unsigned long length, Bool swap);
+ void ioError( IceConn iceConn );
+
+ bool receive(const QCString &app, const QCString &obj,
+ const QCString &fun, const QByteArray& data,
+ QCString& replyType, QByteArray &replyData, IceConn iceConn);
+
+ DCOPConnection *findApp(const QCString &appId);
+ DCOPConnection *findConn(IceConn iceConn)
+ { return clients.find(iceConn); }
+
+ void sendMessage(DCOPConnection *conn, const QCString &sApp,
+ const QCString &rApp, const QCString &rObj,
+ const QCString &rFun, const QByteArray &data);
+
+private slots:
+ void newClient( int socket );
+ void processData( int socket );
+ void slotTerminate();
+ void slotSuicide();
+ void slotShutdown();
+ void slotExit();
+ void slotCleanDeadConnections();
+ void slotOutputReady(int socket );
+
+#ifdef Q_OS_WIN
+public:
+ static BOOL WINAPI dcopServerConsoleProc(DWORD dwCtrlType);
+private:
+ static DWORD WINAPI TerminatorThread(void * pParam);
+#endif
+private:
+ void broadcastApplicationRegistration( DCOPConnection* conn, const QCString type,
+ const QCString& data );
+ bool suicide;
+ bool shutdown;
+ int majorOpcode;
+ int currentClientNumber;
+ CARD32 serverKey;
+ DCOPSignals *dcopSignals;
+ QTimer *m_timer;
+ QTimer *m_deadConnectionTimer;
+ QPtrList<DCOPListener> listener;
+ QAsciiDict<DCOPConnection> appIds; // index on app id
+ QPtrDict<DCOPConnection> clients; // index on iceConn
+ QIntDict<DCOPConnection> fd_clients; // index on fd
+ QPtrList<_IceConn> deadConnections;
+
+#ifdef Q_OS_WIN
+ HANDLE m_evTerminate;
+ HANDLE m_hTerminateThread;
+ DWORD m_dwTerminateThreadId;
+#endif
+
+#ifdef DCOP_LOG
+ QTextStream *m_stream;
+ QFile *m_logger;
+#endif
+};
+
+extern DCOPServer* the_server;
+
+#endif
diff --git a/dcop/dcopserver_shutdown.c b/dcop/dcopserver_shutdown.c
new file mode 100644
index 000000000..a9d7057ad
--- /dev/null
+++ b/dcop/dcopserver_shutdown.c
@@ -0,0 +1,204 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 1999 Waldo Bastian <bastian@kde.org>
+ (c) 1999 Mario Weilguni <mweilguni@sime.com>
+ (c) 2001 Lubos Lunak <l.lunak@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <signal.h>
+
+#define BUFFER_SIZE 4096
+
+static char *getDisplay()
+{
+ const char *display;
+ char *result;
+ char *screen;
+ char *colon;
+/*
+ don't test for a value from qglobal.h but instead distinguish
+ Qt/X11 from Qt/Embedded by the fact that Qt/E apps have -DQWS
+ on the commandline (which in qglobal.h however triggers Q_WS_QWS,
+ but we don't want to include that here) (Simon)
+#ifdef Q_WS_X11
+ */
+#if !defined(QWS)
+ display = getenv("DISPLAY");
+#else
+ display = getenv("QWS_DISPLAY");
+#endif
+ if (!display || !*display)
+ {
+ display = "NODISPLAY";
+ }
+ result = malloc(strlen(display)+1);
+ if (result == NULL)
+ return NULL;
+ strcpy(result, display);
+ screen = strrchr(result, '.');
+ colon = strrchr(result, ':');
+ if (screen && (screen > colon))
+ *screen = '\0';
+ return result;
+}
+
+static void getDCOPFile(char *dcop_file, char *dcop_file_old, int max_length)
+{
+ const char *home_dir;
+ const char *dcop_authority;
+ char *display;
+ char *i;
+ int n;
+
+ n = max_length;
+ home_dir = getenv("HOME");
+ strncpy(dcop_file, home_dir, n);
+ dcop_file[ n - 1 ] = '\0';
+ n -= strlen(home_dir);
+
+ strncat(dcop_file, "/.DCOPserver_", n);
+ n -= strlen("/.DCOPserver_");
+
+ if (gethostname(dcop_file+strlen(dcop_file), n) != 0)
+ {
+ perror("Error. Could not determine hostname: ");
+ dcop_file[0] = '\0';
+ return;
+ }
+ dcop_file[max_length] = '\0';
+ n = max_length - strlen(dcop_file);
+
+ strncat(dcop_file, "_", n);
+ n -= strlen("_");
+
+ display = getDisplay();
+ if (display == NULL)
+ {
+ dcop_file[0] = '\0';
+ return; /* barf */
+ }
+
+ strcpy(dcop_file_old, dcop_file);
+ strncat(dcop_file_old,display, n);
+ while((i = strchr(display, ':')))
+ *i = '_';
+ strncat(dcop_file, display, n);
+ free(display);
+
+ dcop_authority = getenv("DCOPAUTHORITY");
+ if (dcop_authority && *dcop_authority)
+ {
+ strncpy(dcop_file, dcop_authority, max_length);
+ dcop_file[ max_length - 1 ] = '\0';
+ }
+
+ return;
+}
+
+static void cleanupDCOPsocket(char *buffer)
+{
+ char cmd[BUFFER_SIZE];
+ const char *socket_file;
+ int l;
+
+ l = strlen(buffer);
+ if (!l)
+ return;
+ buffer[l-1] = '\0'; /* strip LF */
+
+ socket_file = strchr(buffer, ':');
+ if (socket_file)
+ socket_file++;
+
+ if (socket_file)
+ unlink(socket_file);
+
+ snprintf(cmd, BUFFER_SIZE, "iceauth remove netid='%s'", buffer);
+ system(cmd);
+}
+
+static void cleanupDCOP(int dont_kill_dcop, int wait_for_exit)
+{
+ FILE *f;
+ char dcop_file[2048+1];
+ char dcop_file_old[2048+1];
+ char buffer[2048+1];
+ pid_t pid = 0;
+
+ getDCOPFile(dcop_file, dcop_file_old, 2048);
+ if (strlen(dcop_file) == 0)
+ return;
+
+ f = fopen(dcop_file, "r");
+ unlink(dcop_file); /* Clean up .DCOPserver file */
+ unlink(dcop_file_old);
+ if (!f)
+ return;
+
+ while (!feof(f))
+ {
+ if (!fgets(buffer, 2048, f))
+ break;
+ pid = strtol(buffer, NULL, 10);
+ if (pid)
+ break;
+ cleanupDCOPsocket(buffer);
+ }
+ fclose(f);
+
+ if (!dont_kill_dcop && pid)
+ kill(pid, SIGTERM);
+
+ while(wait_for_exit && (kill(pid, 0) == 0))
+ {
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 100000;
+ select(0,0,0,0,&tv);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int dont_kill_dcop = (argc == 2) && (strcmp(argv[1], "--nokill") == 0);
+ int wait_for_exit = (argc == 2) && (strcmp(argv[1], "--wait") == 0);
+
+ cleanupDCOP(dont_kill_dcop, wait_for_exit);
+ return 0;
+}
diff --git a/dcop/dcopserver_shutdown_win.cpp b/dcop/dcopserver_shutdown_win.cpp
new file mode 100644
index 000000000..5e9c6b9ca
--- /dev/null
+++ b/dcop/dcopserver_shutdown_win.cpp
@@ -0,0 +1,210 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 1999 Waldo Bastian <bastian@kde.org>
+ (c) 1999 Mario Weilguni <mweilguni@sime.com>
+ (c) 2001 Lubos Lunak <l.lunak@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <sys/socket.h>
+#include <stdlib.h>
+#if 0
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <signal.h>
+#endif
+
+#define QT_CLEAN_NAMESPACE 1
+#include <qfile.h>
+
+#include <dcopclient.h>
+
+#define BUFFER_SIZE 4096
+
+extern QCString dcopServerFile(const QCString &hostname, bool old);
+
+static char *getDisplay()
+{
+ const char *display;
+ char *result;
+ char *screen;
+ char *colon;
+/*
+ don't test for a value from qglobal.h but instead distinguish
+ Qt/X11 from Qt/Embedded by the fact that Qt/E apps have -DQWS
+ on the commandline (which in qglobal.h however triggers Q_WS_QWS,
+ but we don't want to include that here) (Simon)
+#ifdef Q_WS_X11
+ */
+#if !defined(QWS)
+ display = getenv("DISPLAY");
+#else
+ display = getenv("QWS_DISPLAY");
+#endif
+ if (!display || !*display)
+ {
+ display = "NODISPLAY";
+ }
+ result = (char*)malloc(strlen(display)+1);
+ if (result == NULL)
+ return NULL;
+ strcpy(result, display);
+ screen = strrchr(result, '.');
+ colon = strrchr(result, ':');
+ if (screen && (screen > colon))
+ *screen = '\0';
+ return result;
+}
+
+static void cleanupDCOPsocket(const char *socketfile)
+{
+ char cmd[BUFFER_SIZE];
+ char buffer[BUFFER_SIZE];
+ const char *socket_file;
+ int l;
+
+ l = strlen(socketfile);
+ if (!l)
+ return;
+ strncpy(buffer,socketfile,l);
+ buffer[l-1] = '\0'; /* strip LF */
+
+ socket_file = strchr(buffer, ':');
+ if (socket_file)
+ socket_file++;
+
+ if (socket_file)
+ unlink(socket_file);
+
+ snprintf(cmd, BUFFER_SIZE, "iceauth remove netid='%s'", buffer);
+ system(cmd);
+}
+
+#ifdef Q_OS_WIN
+static void killDCOPWin(pid_t pid)
+{
+ char sz[256];
+ sprintf(sz,"dcopserver%i",pid);
+ HANDLE hEvent = CreateEventA(NULL,TRUE,FALSE,(LPCSTR)sz);
+ DWORD dwError = GetLastError();
+ printf("Signal event %s %p, %i\n",sz,hEvent,dwError);
+ if(hEvent != NULL)
+ {
+ SetEvent(hEvent);
+ CloseHandle(hEvent);
+ }
+}
+#endif
+
+static void cleanupDCOP(int dont_kill_dcop, int wait_for_exit)
+{
+ QCString host;
+ QCString strDCOPServer = DCOPClient::dcopServerFile(host);
+
+ if(strDCOPServer.isEmpty())
+ {
+ printf("no server file\n");
+ return;
+ }
+ printf("server file %s\n",(const char *)strDCOPServer);
+
+ pid_t pid = 0;
+ QFile f(strDCOPServer);
+ if(f.open(IO_ReadOnly))
+ {
+ QString str;
+ while(f.readLine(str,2048))
+ {
+ pid = str.toULong();
+ if (pid)
+ break;
+ cleanupDCOPsocket(str.ascii());
+ }
+ }
+ f.close();
+ /* Clean up .DCOPserver file */
+ QFile::remove(strDCOPServer);
+ printf("remove server file %s\n",(const char *)strDCOPServer);
+
+ if(pid)
+ {
+ if(!dont_kill_dcop)
+ {
+#ifdef Q_OS_WIN
+ killDCOPWin(pid);
+#else
+ kill(pid, SIGTERM);
+#endif
+ }
+ else
+ {
+#ifdef Q_OS_WIN
+ killDCOPWin(pid);
+#endif
+ }
+ }
+
+#ifdef Q_OS_WIN
+ if(wait_for_exit)
+ {
+ HANDLE hProcess = OpenProcess(SYNCHRONIZE,FALSE,(DWORD)pid);
+ if(hProcess)
+ {
+ WaitForSingleObject(hProcess,INFINITE);
+ CloseHandle(hProcess);
+ }
+ }
+#else
+ while(wait_for_exit && (kill(pid, 0) == 0))
+ {
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 100000;
+ select(0,0,0,0,&tv);
+ }
+#endif
+}
+
+int main(int argc, char **argv)
+{
+ QCString host;
+
+ int dont_kill_dcop = (argc == 2) && (strcmp(argv[1], "--nokill") == 0);
+ int wait_for_exit = (argc == 2) && (strcmp(argv[1], "--wait") == 0);
+
+ cleanupDCOP(dont_kill_dcop, wait_for_exit);
+ return 0;
+}
diff --git a/dcop/dcopserver_win.cpp b/dcop/dcopserver_win.cpp
new file mode 100644
index 000000000..6d6c37859
--- /dev/null
+++ b/dcop/dcopserver_win.cpp
@@ -0,0 +1,63 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (C) 2005 Andreas Roth <aroth@arsoft-online.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+//this file is included by dcopserver.cpp
+
+#include <qeventloop.h>
+
+DWORD WINAPI DCOPServer::TerminatorThread(void * pParam)
+{
+ DCOPServer * server = (DCOPServer*)pParam;
+
+ WaitForSingleObject(server->m_evTerminate,INFINITE);
+ fprintf( stderr, "DCOPServer : terminate event signaled\n" );
+ if(!server->shutdown) {
+
+ ResetEvent(server->m_evTerminate);
+ server->slotShutdown();
+
+ // Wait for main thread to tell us to realy terminate now
+ // Need some further event processing to get the timer signals
+ while(WaitForSingleObject(server->m_evTerminate,100) != WAIT_OBJECT_0)
+ QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput|QEventLoop::ExcludeSocketNotifiers);
+ fprintf( stderr, "DCOPServer : terminated event signaled the last time\n" );
+ }
+ fprintf( stderr, "DCOPServer : terminate thread teminated\n" );
+ return 0;
+}
+
+BOOL WINAPI DCOPServer::dcopServerConsoleProc(DWORD dwCtrlType)
+{
+ BOOL ret;
+ switch(dwCtrlType)
+ {
+ case CTRL_BREAK_EVENT:
+ case CTRL_CLOSE_EVENT:
+ case CTRL_LOGOFF_EVENT:
+ case CTRL_SHUTDOWN_EVENT:
+ case CTRL_C_EVENT:
+ system(findDcopserverShutdown()+" --nokill");
+ ret = TRUE;
+ break;
+ default:
+ ret = FALSE;
+ }
+ return ret;
+}
+
diff --git a/dcop/dcopsignals.cpp b/dcop/dcopsignals.cpp
new file mode 100644
index 000000000..05d674107
--- /dev/null
+++ b/dcop/dcopsignals.cpp
@@ -0,0 +1,274 @@
+/*
+Copyright (c) 2000 Waldo Bastian <bastian@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 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.
+*/
+
+#include <dcopserver.h>
+#include <dcopsignals.h>
+
+template class QPtrList<DCOPSignalConnection>;
+
+DCOPSignals::DCOPSignals()
+{
+ connections.setAutoDelete(true);
+}
+
+/**
+ * Client "conn" emits the signal "fun" with "data" as arguments.
+ *
+ * If "excludeSelf" is true, signal is never sent to "conn" itself.
+ */
+void
+DCOPSignals::emitSignal( DCOPConnection *conn, const QCString &_fun, const QByteArray &data, bool excludeSelf)
+{
+ QCString senderObj;
+ QCString fun = _fun;
+ int i = fun.find('#');
+ if (i > -1)
+ {
+ senderObj = fun.left(i);
+ fun = fun.mid(i+1);
+ }
+
+ DCOPSignalConnectionList *list = connections.find(fun);
+ if (!list) return;
+ for(DCOPSignalConnection *current = list->first(); current; current = list->next())
+ {
+ bool doSend = false;
+ if (current->senderConn)
+ {
+ if (current->senderConn == conn)
+ doSend = true;
+ }
+ else if (!current->sender.isEmpty())
+ {
+ if ((conn && current->sender == conn->appId) || (current->sender == "DCOPServer"))
+ doSend = true;
+ }
+ else
+ {
+ doSend = true;
+ }
+
+ if (!current->senderObj.isEmpty() &&
+ (current->senderObj != senderObj))
+ {
+ doSend = false;
+ }
+
+ if (excludeSelf && (conn == current->recvConn))
+ doSend = false;
+ if (doSend)
+ {
+ the_server->sendMessage(current->recvConn, conn ? conn->appId : QCString("DCOPServer"),
+ current->recvConn->appId, current->recvObj,
+ current->slot, data);
+ }
+ }
+}
+
+/**
+ * Connects "signal" of the client named "sender" with the "slot" of
+ * "receiverObj" in the "conn" client.
+ *
+ * If "Volatile" is true the connection will be removed when either
+ * "sender" or "conn" unregisters.
+ *
+ * If "Volatile" is false the connection will only be removed when
+ * "conn" unregisters.
+ */
+bool
+DCOPSignals::connectSignal( const QCString &sender, const QCString &senderObj,
+ const QCString &signal,
+ DCOPConnection *conn, const QCString &receiverObj,
+ const QCString &slot, bool Volatile)
+{
+ // TODO: Check if signal and slot match
+ QCString signalArgs, slotArgs;
+ int i,j;
+ i = signal.find('(');
+ if (i < 0) return false;
+ signalArgs = signal.mid(i+1);
+ j = signalArgs.find(')');
+ if (j < 0) return false;
+ signalArgs.truncate(j);
+ i = slot.find('(');
+ if (i < 0) return false;
+ slotArgs = slot.mid(i+1);
+ j = slotArgs.find(')');
+ if (j < 0) return false;
+ slotArgs.truncate(j);
+
+ if(signalArgs != slotArgs)
+ {
+ // Maybe the signal has more arguments than the slot...
+ if (signalArgs.length() <= slotArgs.length())
+ return false;
+ if ((slotArgs.length() > 0) && (signalArgs[slotArgs.length()] != ','))
+ return false;
+ if (signalArgs.left(slotArgs.length()) != slotArgs)
+ return false;
+ }
+
+ DCOPConnection *senderConn = 0;
+ if (Volatile)
+ {
+ senderConn = the_server->findApp(sender);
+ if (!senderConn)
+ return false; // Sender does not exist.
+ }
+ DCOPSignalConnection *current = new DCOPSignalConnection;
+ current->sender = sender;
+ current->senderObj = senderObj;
+ current->senderConn = senderConn;
+ current->signal = signal;
+ current->recvConn = conn;
+ current->recvObj = receiverObj;
+ current->slot = slot;
+
+ DCOPSignalConnectionList *list = connections.find(signal);
+ if (!list)
+ {
+ list = new DCOPSignalConnectionList;
+ connections.insert(signal, list);
+ }
+
+ list->append( current );
+ conn->signalConnectionList()->append(current);
+ if (senderConn && senderConn != conn)
+ senderConn->signalConnectionList()->append(current);
+ return true;
+}
+
+/**
+ * Disconnects "signal" of the client named "sender" from the "slot" of
+ * "receiverObj" in the "conn" client.
+ *
+ * Special case:
+ * If sender & signal are empty all connections that involve
+ * conn & receiverObj (either as receiver or as sender)
+ * are disconnected.
+ */
+bool
+DCOPSignals::disconnectSignal( const QCString &sender, const QCString &senderObj,
+ const QCString &signal,
+ DCOPConnection *conn, const QCString &receiverObj,
+ const QCString &slot)
+{
+ if (sender.isEmpty() && signal.isEmpty())
+ {
+ removeConnections(conn, receiverObj);
+ return true;
+ }
+
+ DCOPSignalConnectionList *list = connections.find(signal);
+ if (!list)
+ return false; // Not found...
+
+ DCOPSignalConnection *next = 0;
+ bool result = false;
+
+ for(DCOPSignalConnection *current = list->first(); current; current = next)
+ {
+ next = list->next();
+
+ if (current->recvConn != conn)
+ continue;
+
+ if (current->senderConn)
+ {
+ if (current->senderConn->appId != sender)
+ continue;
+ }
+ else if (current->sender != sender)
+ continue;
+
+ if (!senderObj.isEmpty() &&
+ (current->senderObj != senderObj))
+ continue;
+
+ if (!receiverObj.isEmpty() &&
+ (current->recvObj != receiverObj))
+ continue;
+
+ if (!slot.isEmpty() &&
+ (current->slot != slot))
+ continue;
+
+ result = true;
+ list->removeRef(current);
+ conn->signalConnectionList()->removeRef(current);
+ if (current->senderConn)
+ current->senderConn->signalConnectionList()->removeRef(current);
+ delete current;
+ }
+ return result;
+}
+
+/**
+ * Removes all connections related to "obj" in the "conn" client
+ * This means:
+ * All connections for which "conn"/"obj" is the receiver.
+ * All volatile connections for which "conn"/"obj" is the sender.
+ */
+void
+DCOPSignals::removeConnections(DCOPConnection *conn, const QCString &obj)
+{
+ DCOPSignalConnectionList *list = conn->_signalConnectionList;
+ if (!list)
+ return; // Nothing to do...
+
+ DCOPSignalConnection *next = 0;
+
+ for(DCOPSignalConnection *current = list->first(); current; current = next)
+ {
+ next = list->next();
+
+ if (!obj.isEmpty())
+ {
+ if ((current->senderConn == conn) && (current->senderObj != obj))
+ continue;
+
+ if ((current->recvConn == conn) && (current->recvObj != obj))
+ continue;
+ }
+
+ if (current->senderConn && (current->senderConn != conn))
+ current->senderConn->signalConnectionList()->removeRef(current);
+
+ if (current->recvConn != conn)
+ current->recvConn->signalConnectionList()->removeRef(current);
+
+ DCOPSignalConnectionList *signalList = connections.find(current->signal);
+ if (signalList)
+ {
+ signalList->removeRef(current);
+ if (signalList->isEmpty())
+ connections.remove(current->signal);
+ }
+ else
+ {
+ qDebug("Error: Signal Connection was not in signalList!\n");
+ }
+ list->removeRef(current);
+ delete current;
+ }
+}
+
+
diff --git a/dcop/dcopsignals.h b/dcop/dcopsignals.h
new file mode 100644
index 000000000..142d713cb
--- /dev/null
+++ b/dcop/dcopsignals.h
@@ -0,0 +1,158 @@
+/*
+Copyright (c) 2000 Waldo Bastian <bastian@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 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.
+*/
+
+#ifndef DCOPSIGNALS_H
+#define DCOPSIGNALS_H "$Id$"
+
+#include <qdict.h>
+#include <qasciidict.h>
+#include <qptrlist.h>
+#include <qstring.h>
+#include "kdelibs_export.h"
+
+class DCOPConnection;
+
+/** \internal
+ * This requires:
+ * DCOPSignalConnectionList * DCOPConnection::signalConnectionList()
+*/
+class DCOP_EXPORT DCOPSignalConnection
+{
+public:
+ QCString sender; // Sender client, empty means any client
+ DCOPConnection *senderConn; //Sender client.
+ QCString senderObj; // Object that sends the signal.
+ QCString signal; // Signal name. Connections are sorted on signal name.
+
+ DCOPConnection *recvConn; // Client that wants to receive the signal
+ QCString recvObj; // Object that wants to receive the signal
+ QCString slot; // Function to send to in the object.
+};
+
+/** \internal */
+class DCOP_EXPORT DCOPSignalConnectionList : public QPtrList<DCOPSignalConnection>
+{
+public:
+ DCOPSignalConnectionList() { };
+};
+
+/**
+ * @internal
+ */
+class DCOP_EXPORT DCOPSignals
+{
+public:
+ DCOPSignals();
+
+ /**
+ * Client "conn" emits the signal "fun" with "data" as arguments.
+ * conn is 0L if the dcopserver sends the signal itself
+ *
+ * The emitting object is encoded in "fun".
+ *
+ * If "excludeSelf" is true, signal is never send to "conn" itself.
+ */
+ void emitSignal( DCOPConnection *conn, const QCString &fun, const QByteArray &data, bool excludeSelf);
+
+ /**
+ * Connects "signal" of the client named "sender" with the "slot" of
+ * "receiverObj" in the "conn" client.
+ *
+ * If "Volatile" is true the connection will be removed when either
+ * "sender" or "conn" unregisters.
+ *
+ * If "Volatile" is false the connection will only be removed when
+ * "conn" unregisters.
+ *
+ * Returns true if succesfull. False on failure.
+ * An attempt to create a Volatile connection to a non-existing client
+ * results in a failure.
+ */
+ bool connectSignal( const QCString &sender, const QCString &senderObj,
+ const QCString &signal,
+ DCOPConnection *conn, const QCString &receiverObj,
+ const QCString &slot, bool Volatile);
+
+ /**
+ * Disconnects "signal" of the client named "sender" from the "slot" of
+ * "receiverObj" in the "conn" client.
+ *
+ * If "receiverObj" is empty, every object is disconnected.
+ * If "slot" is empty, every slot is disconnected.
+ *
+ * Returns true if successful, false if no connection was found.
+ */
+ bool disconnectSignal( const QCString &sender, const QCString &senderObj,
+ const QCString &signal,
+ DCOPConnection *conn, const QCString &receiverObj,
+ const QCString &slot);
+
+ /**
+ * Removes all connections related to the "conn" client.
+ * This means:
+ * All connections for which "conn" is the receiver.
+ * All volatile connections for which "conn" is the sender.
+ */
+ void removeConnections(DCOPConnection *conn, const QCString &obj=0);
+
+
+ /*
+ * The administration.
+ *
+ * All connections are sorted by "signal" and then inserted in the
+ * administration as a list.
+ *
+ * connections[signal] gives a list of all connections related to
+ * a given signal. The connections in this list may specify different
+ * senders and receiving clients/objects.
+ */
+ QAsciiDict<DCOPSignalConnectionList> connections;
+};
+
+//
+// connectSignal:
+//
+// Check whether signal and slot match wrt arguments.
+// A slot may ignore arguments from the signal.
+//
+// If volatile
+// then lookup senderConn...
+// If not found?
+// then return false
+// Create DCOPSignalConnection.
+// Add DCOPSignalConnection to "connections".
+// Add DCOPSignalConnection to conn->connectionList()
+// If volatile
+// then Add DCOPSignalConnection to senderConn->connectionList()
+// Return true
+
+
+// removeConnections:
+//
+// For each DCOPSignalConnection in conn->connectionList
+// if DCOPSignalConnection->sender == conn->appId
+// then remove DCOPSignalConnection from DCOPSIgnalConnection->conn
+// if DCOPSignalConnection->conn == conn
+// then.. this is ugly.. remove DCOPSignalConnection from DCOPSignalConnection->sender
+// WARNING: Take care when sender and conn are the same client!
+// Remove DCOPSignalConnection from connections[DCOPSignalConnection->signal]
+
+#endif
diff --git a/dcop/dcopstub.cpp b/dcop/dcopstub.cpp
new file mode 100644
index 000000000..8f69b1abe
--- /dev/null
+++ b/dcop/dcopstub.cpp
@@ -0,0 +1,98 @@
+/*****************************************************************
+
+Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+Copyright (c) 1999 Matthias Ettrich <ettrich@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 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.
+
+******************************************************************/
+
+#include "dcopstub.h"
+#include "dcopclient.h"
+#include "dcopref.h"
+
+class DCOPStubPrivate
+{
+public:
+ DCOPStubPrivate():dcopClient(0){}
+ DCOPClient* dcopClient;
+};
+
+DCOPStub::DCOPStub( const QCString& app, const QCString& obj )
+ : m_app( app ), m_obj( obj ), m_status( CallSucceeded ),d(0)
+{
+}
+
+DCOPStub::DCOPStub( DCOPClient* client, const QCString& app, const QCString& obj )
+ : m_app( app ), m_obj( obj ), m_status( CallSucceeded ),d(0)
+{
+ if ( client ) {
+ d = new DCOPStubPrivate;
+ d->dcopClient = client;
+ }
+}
+
+DCOPStub::DCOPStub( const DCOPRef& ref )
+ : m_app( ref.app() ), m_obj( ref.obj() ), m_status( CallSucceeded ),d(0)
+{
+}
+
+DCOPStub::~DCOPStub()
+{
+ delete d;
+}
+
+DCOPClient* DCOPStub::dcopClient()
+{
+ if ( d )
+ return d->dcopClient;
+ return DCOPClient::mainClient();
+}
+
+DCOPStub::Status DCOPStub::status() const
+{
+ return m_status;
+}
+
+void DCOPStub::setStatus( Status _status )
+{
+ m_status = _status;
+}
+
+bool DCOPStub::ok() const
+{
+ return m_status != CallFailed;
+}
+
+void DCOPStub::callFailed()
+{
+ setStatus( CallFailed );
+}
+
+QCString DCOPStub::app() const
+{
+ return m_app;
+}
+
+QCString DCOPStub::obj() const
+{
+ return m_obj;
+}
+
+void DCOPStub::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
diff --git a/dcop/dcopstub.h b/dcop/dcopstub.h
new file mode 100644
index 000000000..1ab46af24
--- /dev/null
+++ b/dcop/dcopstub.h
@@ -0,0 +1,145 @@
+/*
+Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+Copyright (c) 1999 Matthias Ettrich <ettrich@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
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef _DCOPSTUB_H
+#define _DCOPSTUB_H
+
+class DCOPClient;
+class DCOPRef;
+class DCOPStubPrivate;
+
+#include <stdlib.h>
+
+#include <qstring.h>
+#include "kdelibs_export.h"
+
+/**
+* Abstract base class for dcop stubs as created by the
+* dcopidl2cpp compiler.
+*
+*/
+
+class DCOP_EXPORT DCOPStub
+{
+public:
+ /**
+ Creates a DCOPStub for application @p app and object @p obj
+ @param app the application id
+ @param obj the object id
+ */
+ DCOPStub( const QCString& app, const QCString& obj );
+
+ /**
+ Creates a DCOPStub for application @p app and object @p obj
+ that operates on the DCOPClient @p client
+ @param client the DCOPClient
+ @param app the application id
+ @param obj the object id
+ */
+ DCOPStub( DCOPClient* client, const QCString& app, const QCString& obj );
+
+ /**
+ Creates a DCOPStub for application ref.app() and object ref.obj()
+ @param ref the DCOP reference
+ */
+ explicit DCOPStub( const DCOPRef& ref );
+ virtual ~DCOPStub();
+
+ /**
+ Return the application id.
+ @return the application id
+ */
+ QCString app() const;
+ /**
+ Return the object id.
+ @return the object id
+ */
+ QCString obj() const;
+
+ enum Status{ CallSucceeded, CallFailed };
+ /**
+ * Return the status of the last call, either @p CallSucceeded or
+ * @p CallFailed.
+ *
+ * @return the status of the last call
+ * @see ok();
+ */
+ Status status() const;
+
+
+ /**
+ * Return whether no error occurred,
+ *
+ * @return true if the last call was successful, false otherwise
+ * @see status();
+ */
+ bool ok() const;
+
+protected:
+
+ /**
+ Sets the status to status. Possible values are 'CallSucceeded' and 'CallFailed'
+ @param _status the new status
+ @see status()
+ */
+ void setStatus( Status _status );
+
+ /**
+ Invoked whenever a call fails. The default implementation
+ sets the status to CallFailed.
+ */
+ virtual void callFailed();
+
+ /**
+ The dcopClient this stub operates on. Either the specific one
+ specified in the constructor or DCOPClient::mainClient.
+ @return the stub's DCOPClient
+ */
+ DCOPClient* dcopClient();
+
+ /**
+ * @internal
+ * Never use. Used only for default ctors of inherited stubs,
+ * because of the way ctors of virtual base classes work.
+ * Otherwise dcopidl2cpp would have to call ctors of all, even
+ * indirect, bases.
+ * @since 3.1
+ */
+ enum never_use_t { never_use };
+ /**
+ * @internal
+ * @since 3.1
+ */
+ DCOPStub( never_use_t ) { abort(); }
+
+private:
+ QCString m_app;
+ QCString m_obj;
+ Status m_status;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ DCOPStubPrivate *d;
+};
+
+#endif
diff --git a/dcop/dcoptypes.h b/dcop/dcoptypes.h
new file mode 100644
index 000000000..60a121926
--- /dev/null
+++ b/dcop/dcoptypes.h
@@ -0,0 +1,91 @@
+/*
+Copyright (c) 2002 Matthias Ettrich <ettrich@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 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.
+*/
+
+#ifndef DCOPTYPES_H
+#define DCOPTYPES_H
+
+#include <dcopref.h>
+
+// standard c/c++ types
+inline const char* dcopTypeName( bool ) { return "bool"; }
+inline const char* dcopTypeName( char ) { return "char"; }
+inline const char* dcopTypeName( uchar ) { return "uchar"; }
+inline const char* dcopTypeName( int ) { return "int"; }
+inline const char* dcopTypeName( uint ) { return "uint"; }
+inline const char* dcopTypeName( long ) { return "long int"; }
+inline const char* dcopTypeName( ulong ) { return "ulong"; }
+inline const char* dcopTypeName( double ) { return "double"; }
+inline const char* dcopTypeName( float ) { return "float"; }
+inline const char* dcopTypeName( const char* ) { return "QCString"; }
+
+// dcop specialities
+class DCOPRef; inline const char* dcopTypeName( const DCOPRef& ) { return "DCOPRef"; }
+
+// Qt variant types
+class QString; inline const char* dcopTypeName( const QString& ) { return "QString"; }
+class QCString; inline const char* dcopTypeName( const QCString& ) { return "QCString"; }
+class QFont; inline const char* dcopTypeName( const QFont& ) { return "QFont"; }
+class QPixmap; inline const char* dcopTypeName( const QPixmap& ) { return "QPixmap"; }
+class QBrush; inline const char* dcopTypeName( const QBrush& ) { return "QBrush"; }
+class QRect; inline const char* dcopTypeName( const QRect& ) { return "QRect"; }
+class QPoint; inline const char* dcopTypeName( const QPoint& ) { return "QPoint"; }
+class QImage; inline const char* dcopTypeName( const QImage& ) { return "QImage"; }
+class QSize; inline const char* dcopTypeName( const QSize& ) { return "QSize"; }
+class QColor; inline const char* dcopTypeName( const QColor& ) { return "QColor"; }
+class QPalette; inline const char* dcopTypeName( const QPalette& ) { return "QPalette"; }
+class QColorGroup; inline const char* dcopTypeName( const QColorGroup& ) { return "QColorGroup"; }
+class QIconSet; inline const char* dcopTypeName( const QIconSet& ) { return "QIconSet"; }
+class QDataStream; inline const char* dcopTypeName( const QDataStream& ) { return "QDataStream"; }
+class QPointArray; inline const char* dcopTypeName( const QPointArray& ) { return "QPointArray"; }
+class QRegion; inline const char* dcopTypeName( const QRegion& ) { return "QRegion"; }
+class QBitmap; inline const char* dcopTypeName( const QBitmap& ) { return "QBitmap"; }
+class QCursor; inline const char* dcopTypeName( const QCursor& ) { return "QCursor"; }
+class QStringList; inline const char* dcopTypeName( const QStringList& ) { return "QStringList"; }
+class QSizePolicy; inline const char* dcopTypeName( const QSizePolicy& ) { return "QSizePolicy"; }
+class QDate; inline const char* dcopTypeName( const QDate& ) { return "QDate"; }
+class QTime; inline const char* dcopTypeName( const QTime& ) { return "QTime"; }
+class QDateTime; inline const char* dcopTypeName( const QDateTime& ) { return "QDateTime"; }
+class QBitArray; inline const char* dcopTypeName( const QBitArray& ) { return "QBitArray"; }
+class QKeySequence; inline const char* dcopTypeName( const QKeySequence& ) { return "QKeySequence"; }
+class QVariant; inline const char* dcopTypeName( const QVariant& ) { return "QVariant"; }
+
+// And some KDE types
+class KURL; inline const char* dcopTypeName( const KURL& ) { return "KURL"; }
+
+// generic template fallback for unknown types
+template <class T> inline const char* dcopTypeName( const T& ) { return "<unknown>"; }
+
+// type initialization for standard c/c++ types
+inline void dcopTypeInit(bool& b){b=false;}
+inline void dcopTypeInit(char& c){c=0;}
+inline void dcopTypeInit(uchar& c){c=0;}
+inline void dcopTypeInit(int& i){i=0;}
+inline void dcopTypeInit(uint& i){i=0;}
+inline void dcopTypeInit(long& l){l=0;}
+inline void dcopTypeInit(ulong& l){l=0;}
+inline void dcopTypeInit(float& f){f=0;}
+inline void dcopTypeInit(double& d){d=0;}
+inline void dcopTypeInit(const char* s ){s=0;}
+
+// generic template fallback for self-initializing classes
+template <class T> inline void dcopTypeInit(T&){}
+
+#endif
diff --git a/dcop/kdatastream.h b/dcop/kdatastream.h
new file mode 100644
index 000000000..2d9b65210
--- /dev/null
+++ b/dcop/kdatastream.h
@@ -0,0 +1,56 @@
+#ifndef __kdatastream__h
+#define __kdatastream__h
+
+#include <qdatastream.h>
+
+inline QDataStream & operator << (QDataStream & str, bool b)
+{
+ str << Q_INT8(b);
+ return str;
+}
+
+inline QDataStream & operator >> (QDataStream & str, bool & b)
+{
+ Q_INT8 l;
+ str >> l;
+ b = bool(l);
+ return str;
+}
+
+#if QT_VERSION < 0x030200 && !defined(Q_WS_WIN) && !defined(Q_WS_MAC)
+inline QDataStream & operator << (QDataStream & str, long long int ll)
+{
+ Q_UINT32 l1,l2;
+ l1 = ll & 0xffffffffLL;
+ l2 = ll >> 32;
+ str << l1 << l2;
+ return str;
+}
+
+inline QDataStream & operator >> (QDataStream & str, long long int&ll)
+{
+ Q_UINT32 l1,l2;
+ str >> l1 >> l2;
+ ll = ((unsigned long long int)(l2) << 32) + (long long int) l1;
+ return str;
+}
+
+inline QDataStream & operator << (QDataStream & str, unsigned long long int ll)
+{
+ Q_UINT32 l1,l2;
+ l1 = ll & 0xffffffffLL;
+ l2 = ll >> 32;
+ str << l1 << l2;
+ return str;
+}
+
+inline QDataStream & operator >> (QDataStream & str, unsigned long long int &ll)
+{
+ Q_UINT32 l1,l2;
+ str >> l1 >> l2;
+ ll = ((unsigned long long int)(l2) << 32) + (unsigned long long int) l1;
+ return str;
+}
+#endif
+
+#endif
diff --git a/dcop/libDCOP.nmcheck b/dcop/libDCOP.nmcheck
new file mode 100644
index 000000000..40fdae0db
--- /dev/null
+++ b/dcop/libDCOP.nmcheck
@@ -0,0 +1,14 @@
+# KDE namespace check file
+
+# DCOP classes
+DCOP*::*
+kde_*
+
+# from (KDE) ICE
+
+KDE_Ice*
+_kde_Ice*
+
+# these should preferably go in some namespace in KDE4
+operator>>
+operator<<
diff --git a/dcop/libDCOP_weak.nmcheck b/dcop/libDCOP_weak.nmcheck
new file mode 100644
index 000000000..ea0ce6844
--- /dev/null
+++ b/dcop/libDCOP_weak.nmcheck
@@ -0,0 +1,10 @@
+# KDE namespace check file
+
+# DCOP classes
+DCOP*::*
+
+# these should preferably go in some namespace in KDE4
+dcopTypeName
+
+operator>>
+operator<<
diff --git a/dcop/testdcop.cpp b/dcop/testdcop.cpp
new file mode 100644
index 000000000..a718442fc
--- /dev/null
+++ b/dcop/testdcop.cpp
@@ -0,0 +1,298 @@
+/*****************************************************************
+
+Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+Copyright (c) 1999 Matthias Ettrich <ettrich@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 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.
+
+******************************************************************
+*/
+
+#include <testdcop.h>
+#include <qtimer.h>
+
+#include <assert.h>
+
+DCOPClientTransaction *countDownAction = 0;
+int countDownCount = 0;
+
+DCOPClientTransaction *countDownAction2 = 0;
+int countDownCount2 = 0;
+DCOPClient *client = 0;
+
+bool MyDCOPObject::process(const QCString &fun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData)
+{
+ qDebug("in MyDCOPObject::process, fun = %s", fun.data());
+
+ // note "fun" is normlized here (i.e. whitespace clean)
+ if (fun == "aFunction(QString,int)") {
+ QDataStream args(data, IO_ReadOnly);
+ QString arg1;
+ int arg2;
+ args >> arg1 >> arg2;
+ function(arg1, arg2);
+ replyType = "void";
+ return true;
+ }
+ if (fun == "canLaunchRockets(QRect)") {
+ QDataStream args(data, IO_ReadOnly);
+ QRect arg1;
+ args >> arg1;
+
+ printf("Rect x = %d, y = %d, w = %d, h = %d\n", arg1.x(), arg1.y(), arg1.width(), arg1.height());
+
+ replyType = "QRect";
+ QDataStream reply( replyData, IO_WriteOnly );
+ QRect r(10,20,100,200);
+ reply << r;
+ return true;
+ }
+ if (fun == "isAliveSlot(int)") {
+
+ qDebug("isAliveSlot(int)");
+ bool connectResult = client->disconnectDCOPSignal("", objId(), "", objId(), "" );
+ qDebug("disconnectDCOPSignal returns %s", connectResult ? "true" : "false");
+ return true;
+ }
+ if (fun == "countDown()") {
+qDebug("countDown() countDownAction = %p", countDownAction);
+ if (countDownAction2)
+ {
+ replyType = "QString";
+ QDataStream reply( replyData, IO_WriteOnly );
+ reply << QString("Hey");
+ return true;
+ }
+
+ if (countDownAction == 0)
+ {
+ countDownCount = 10;
+ countDownAction = client->beginTransaction();
+ QTimer::singleShot(1000, this, SLOT(slotTimeout()));
+ }
+ else
+ {
+ countDownCount2 = 10;
+ countDownAction2 = client->beginTransaction();
+ QTimer::singleShot(1000, this, SLOT(slotTimeout2()));
+ }
+ return true;
+ }
+
+ return DCOPObject::process(fun, data, replyType, replyData);
+}
+
+void MyDCOPObject::slotTimeout()
+{
+ qDebug("MyDCOPObject::slotTimeout() %d", countDownCount);
+ countDownCount--;
+ if (countDownCount == 0)
+ {
+ QCString replyType = "QString";
+ QByteArray replyData;
+ QDataStream reply( replyData, IO_WriteOnly );
+ reply << QString("Hello World");
+ client->endTransaction(countDownAction, replyType, replyData);
+ countDownAction = 0;
+ }
+ else
+ {
+ QTimer::singleShot(1000, this, SLOT(slotTimeout()));
+ }
+}
+
+void MyDCOPObject::slotTimeout2()
+{
+ qDebug("MyDCOPObject::slotTimeout2() %d", countDownCount2);
+ countDownCount2--;
+ if (countDownCount2 == 0)
+ {
+ QCString replyType = "QString";
+ QByteArray replyData;
+ QDataStream reply( replyData, IO_WriteOnly );
+ reply << QString("Hello World");
+ client->endTransaction(countDownAction2, replyType, replyData);
+ countDownAction2 = 0;
+ }
+ else
+ {
+ QTimer::singleShot(1000, this, SLOT(slotTimeout2()));
+ }
+}
+
+QCStringList MyDCOPObject::functions()
+{
+ QCStringList result = DCOPObject::functions();
+ result << "QRect canLaunchRockets(QRect)";
+ return result;
+}
+
+TestObject::TestObject(const QCString& app)
+ : m_app(app)
+{
+ QTimer::singleShot(2500, this, SLOT(slotTimeout()));
+}
+
+void TestObject::slotTimeout()
+{
+ QCString replyType;
+ QByteArray data, reply;
+ qWarning("#3 Calling countDown");
+
+ if (!client->call(m_app, "object1", "countDown()", data, replyType, reply))
+ qDebug("#3 I couldn't call countDown");
+ else
+ qDebug("#3 countDown() return type was '%s'", replyType.data() );
+
+}
+
+void TestObject::slotCallBack(int callId, const QCString &replyType, const QByteArray &replyData)
+{
+ qWarning("Call Back! callId = %d", callId);
+ qWarning("Type = %s", replyType.data());
+
+ QDataStream args(replyData, IO_ReadOnly);
+ QString arg1;
+ args >> arg1;
+
+ qWarning("Value = %s", arg1.latin1());
+}
+
+#ifdef Q_OS_WIN
+# define main kdemain
+#endif
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv, "testdcop");
+
+ QCString replyType;
+ QByteArray data, reply;
+ client = new DCOPClient();
+
+ if (argc == 2)
+ {
+ QCString appId = argv[1];
+ TestObject obj(appId);
+ qWarning("#1 Calling countDown");
+ int result = client->callAsync(appId, "object1", "countDown()", data, &obj, SLOT(slotCallBack(int, const QCString&, const QByteArray&)));
+ qDebug("#1 countDown() call id = %d", result);
+ qWarning("#2 Calling countDown");
+ result = client->callAsync(appId, "object1", "countDown()", data, &obj, SLOT(slotCallBack(int, const QCString&, const QByteArray&)));
+ qDebug("#2 countDown() call id = %d", result);
+ app.exec();
+
+ return 0;
+ }
+
+// client->attach(); // attach to the server, now we can use DCOP service
+
+ client->registerAs( app.name(), false ); // register at the server, now others can call us.
+ qDebug("I registered as '%s'", client->appId().data() );
+
+ if ( client->isApplicationRegistered( app.name() ) )
+ qDebug("indeed, we are registered!");
+
+ QDataStream dataStream( data, IO_WriteOnly );
+ dataStream << (int) 43;
+ client->emitDCOPSignal("alive(int,QCString)", data);
+
+ MyDCOPObject *obj1 = new MyDCOPObject("object1");
+
+ bool connectResult = client->connectDCOPSignal("", "alive(int , QCString)", "object1", "isAliveSlot(int)", false);
+ qDebug("connectDCOPSignal returns %s", connectResult ? "true" : "false");
+
+ QDataStream ds(data, IO_WriteOnly);
+ ds << QString("fourty-two") << 42;
+ if (!client->call(app.name(), "object1", "aFunction(QString,int)", data, replyType, reply)) {
+ qDebug("I couldn't call myself");
+ assert( 0 );
+ }
+ else {
+ qDebug("return type was '%s'", replyType.data() );
+ assert( replyType == "void" );
+ }
+
+ client->send(app.name(), "object1", "aFunction(QString,int)", data );
+
+ int n = client->registeredApplications().count();
+ qDebug("number of attached applications = %d", n );
+
+ QObject::connect( client, SIGNAL( applicationRegistered( const QCString&)),
+ obj1, SLOT( registered( const QCString& )));
+
+ QObject::connect( client, SIGNAL( applicationRemoved( const QCString&)),
+ obj1, SLOT( unregistered( const QCString& )));
+
+ // Enable the above signals
+ client->setNotifications( true );
+
+ QCString foundApp;
+ QCString foundObj;
+
+ // Find a object called "object1" in any application that
+ // meets the criteria "canLaunchRockets()"
+// bool boolResult = client->findObject( "", "object1", "canLaunchRockets()", data, foundApp, foundObj);
+// qDebug("findObject: result = %s, %s, %s\n", boolResult ? "true" : "false",
+// foundApp.data(), foundObj.data());
+
+ // Find an application that matches with "konqueror*"
+ bool boolResult = client->findObject( "konqueror*", "", "", data, foundApp, foundObj);
+ qDebug("findObject: result = %s, %s, %s\n", boolResult ? "true" : "false",
+ foundApp.data(), foundObj.data());
+
+ // Find an object called "object1" in any application.
+ boolResult = client->findObject( "", "ksycoca", "", data, foundApp, foundObj);
+ qDebug("findObject: result = %s, %s, %s\n", boolResult ? "true" : "false",
+ foundApp.data(), foundObj.data());
+
+ // Find ourselves in any application.
+ boolResult = client->findObject( "testdcop", "ksycoca", "", data, foundApp, foundObj);
+ qDebug("findObject: result = %s, %s, %s\n", boolResult ? "true" : "false",
+ foundApp.data(), foundObj.data());
+
+ DCOPClient *client2 = new DCOPClient();
+ client2->registerAs(app.name(), false);
+ qDebug("I2 registered as '%s'", client2->appId().data() );
+
+qDebug("Sending to object1");
+ client2->send(app.name(), "object1", "aFunction(QString,int)", data );
+
+qDebug("Calling object1");
+ if (!client2->call(app.name(), "object1", "aFunction(QString,int)", data, replyType, reply))
+ qDebug("I couldn't call myself");
+ else
+ qDebug("return type was '%s'", replyType.data() );
+
+qDebug("Calling countDown() in object1");
+ if (!client2->call(app.name(), "object1", "countDown()", data, replyType, reply))
+ qDebug("I couldn't call myself");
+ else
+ qDebug("return type was '%s'", replyType.data() );
+
+ // Find ourselves in any application.
+ boolResult = client2->findObject( "testdcop", "object1", "", data, foundApp, foundObj);
+ qDebug("findObject: result = %s, %s, %s\n", boolResult ? "true" : "false",
+ foundApp.data(), foundObj.data());
+
+ client->detach();
+ return 0;
+}
+
+#include "testdcop.moc"
diff --git a/dcop/testdcop.h b/dcop/testdcop.h
new file mode 100644
index 000000000..935924d79
--- /dev/null
+++ b/dcop/testdcop.h
@@ -0,0 +1,77 @@
+/*****************************************************************
+
+Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+Copyright (c) 1999 Matthias Ettrich <ettrich@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 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.
+
+******************************************************************
+*/
+
+#ifndef _TESTDCOP_H_
+#define _TESTDCOP_H_
+
+#include <qapplication.h>
+#include <qbitarray.h>
+#include <dcopclient.h>
+#include <dcopobject.h>
+
+#include <qobject.h>
+
+#include <stdio.h>
+/**
+ $QTDIR/bin/moc testdcop.cpp -o testdcop.moc
+ g++ -o testdcop testdcop.cpp -I$QTDIR/include -L$QTDIR/lib
+ @internal
+
+**/
+
+class TestObject : public QObject
+{
+ Q_OBJECT
+public:
+ TestObject(const QCString &app);
+
+public slots:
+ void slotTimeout();
+ void slotCallBack(int, const QCString&, const QByteArray&);
+private:
+
+ QCString m_app;
+};
+
+
+class MyDCOPObject : public QObject, public DCOPObject
+{
+ Q_OBJECT
+public:
+ MyDCOPObject(const QCString &name) : DCOPObject(name) {}
+ bool process(const QCString &fun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData);
+ void function(const QString &arg1, int arg2) { qDebug("function got arg: %s and %d", arg1.utf8().data(), arg2); }
+public slots:
+ void slotTimeout();
+ void slotTimeout2();
+ void registered(const QCString &appName)
+ { printf("REGISTER: %s\n", appName.data()); }
+
+ void unregistered(const QCString &appName)
+ { printf("UNREGISTER: %s\n", appName.data()); }
+ QCStringList functions();
+};
+#endif
diff --git a/dcop/testdcopc.c b/dcop/testdcopc.c
new file mode 100644
index 000000000..1a340a683
--- /dev/null
+++ b/dcop/testdcopc.c
@@ -0,0 +1,11 @@
+#include <dcopc.h>
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+ const char *name;
+
+ name = dcop_register("test", 0);
+
+ printf("dcop_register returns \"%s\"\n", name);
+}
diff --git a/dcop/tests/Makefile.am b/dcop/tests/Makefile.am
new file mode 100644
index 000000000..16d8ac7e0
--- /dev/null
+++ b/dcop/tests/Makefile.am
@@ -0,0 +1,35 @@
+
+nothing:
+ @echo -e "dcop tests not run.\nRun make tests in the tests directory to make them"
+
+INCLUDES = $(all_includes)
+AM_LDFLAGS = $(all_libraries)
+
+METASOURCES = AUTO
+
+####### Files
+
+check_PROGRAMS = dcop_test driver
+
+dcop_test_SOURCES = test.cpp test.skel
+dcop_test_LDADD = $(LIB_KDECORE)
+dcop_test_LDFLAGS = $(KDE_RPATH)
+
+driver_SOURCES = driver.cpp test.stub
+driver_LDADD = $(LIB_KDECORE)
+driver_LDFLAGS = $(KDE_RPATH)
+
+CLEANFILES = batch.generated definitions.generated driver.generated shell.generated test.h
+
+BUILT_SOURCES = test.h
+
+test-clean:
+ rm batch.returns driver.returns shell.returns batch.stdout driver.stdout shell.stdout
+
+test.h: shell.generated
+
+shell.generated: $(srcdir)/testcases $(srcdir)/generate.pl
+ perl $(srcdir)/generate.pl < $(srcdir)/testcases
+
+check-local:
+ sh $(srcdir)/run-tests.sh
diff --git a/dcop/tests/README b/dcop/tests/README
new file mode 100644
index 000000000..3dec62986
--- /dev/null
+++ b/dcop/tests/README
@@ -0,0 +1,37 @@
+WHAT IS IT
+==========
+
+This is a test case for the dcop family of utils.
+
+
+HOW TO USE IT
+=============
+
+testcases is the important file, the rest is build system.
+It details what functions we should generate and with what arguments to call them
+
+'make'ing will generate a small dcop app which runs in two modes: the batch mode and the
+interactive mode. The batch mode simply runs all the tests inside the app, while in the interactive
+mode, the app goes to sleep and exactly the same tests are called from the outside. Should the results
+differ, we probably have a bug.
+
+
+HOW IT WORKS
+============
+
+Six files get generated:
+
+ local external shell
+ +-------------------+-----------------+-----------------+
+ | | | |
+ stdout | batch.stdout | dcop.stdout | shell.stdoud |
+ | | | |
+ +-------------------+-----------------+-----------------+
+ | | | |
+ return values | batch.returns | dcop.returns | shell.returns |
+ | | | |
+ +-------------------+-----------------+-----------------+
+
+The local column are the files generated in batch mode where the calls are made locally, the external and shell columns lists files made using dcop calls, "external" calls were made through an external program and shell call were made using the dcop shell client. The stdout row is what got printed to stdout and the returns row is what return values the various functions support. These are kept separate to simplify things.
+
+
diff --git a/dcop/tests/driver.cpp b/dcop/tests/driver.cpp
new file mode 100644
index 000000000..ac06d2873
--- /dev/null
+++ b/dcop/tests/driver.cpp
@@ -0,0 +1,65 @@
+#include "driver.h"
+#include <kapplication.h>
+#include <iostream>
+#include <dcopclient.h>
+#include <kcmdlineargs.h>
+#include <qtimer.h>
+#include <qtimer.h>
+
+using namespace std;
+
+#ifdef _MSC_VER
+#define __PRETTY_FUNCTION__ __FUNCTION__
+#endif
+
+Driver::Driver(const char* app)
+ :Test_stub( app, "TestInterface" ),
+ DCOPStub( app, "TestInterface" ), // DCOPStub is *virtual* inherited
+ count( 0 )
+{
+
+}
+
+QTextStream output( fopen( "driver.returns", "w" ) , IO_WriteOnly );
+#include <iostream>
+void Driver::test()
+{
+ // This is written like this to allow the potentially ASYNC calls to be syncronized
+ // Just sleeping would mean that no errors were reported until much later
+ // I could improve it, so that we don't sleep after a synchronous call, but I will
+ // leave it for later
+
+ std::cerr << __PRETTY_FUNCTION__ << " count: " << count << '\n';
+
+ Driver* object = this;
+ switch ( count ) {
+#include "driver.generated"
+ default:
+ exit( 0 );
+ }
+
+ ++count;
+ QTimer::singleShot( 100, this, SLOT( test() ) );
+}
+
+#include "driver.moc"
+
+#ifdef Q_OS_WIN
+# define main kdemain
+#endif
+
+int main(int argc, char** argv)
+{
+ if ( argc < 2 ) { qWarning("Usage: driver <appid>"); return 1; }
+ const char* appname = strdup( argv[ 1 ] );
+ argv[ 1 ] = 0; // sue me
+ KCmdLineArgs::init( argc, argv, "TestAppDriver", "Tests the dcop familly of tools + libraries", "1.0" ); // FIXME
+ KApplication app;
+ app.dcopClient()->attach( );
+ app.dcopClient()->registerAs( "TestAppDriver" );
+ Driver * object = new Driver( appname );
+ QTimer::singleShot( 10, object, SLOT( test() ) );
+ return app.exec();
+}
+
+
diff --git a/dcop/tests/driver.h b/dcop/tests/driver.h
new file mode 100644
index 000000000..ee4d5df57
--- /dev/null
+++ b/dcop/tests/driver.h
@@ -0,0 +1,21 @@
+#ifndef _OPT_KDECVS_SRC_KDELIBS_DCOP_TEST_TESTER_H
+#define _OPT_KDECVS_SRC_KDELIBS_DCOP_TEST_TESTER_H
+#include "test_stub.h"
+#include <qobject.h>
+
+
+
+class Driver : public QObject, public Test_stub
+{
+ Q_OBJECT
+
+ public:
+ Driver(const char*);
+ public slots:
+ void test();
+
+ private:
+ int count;
+};
+
+#endif // _OPT_KDE-CVS_SRC_KDELIBS_DCOP_TEST_TESTER_H
diff --git a/dcop/tests/generate.pl b/dcop/tests/generate.pl
new file mode 100755
index 000000000..cd4697d3f
--- /dev/null
+++ b/dcop/tests/generate.pl
@@ -0,0 +1,221 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+
+my $DERIVED_CLASS = 'Test';
+my $BASE_CLASS = 'Test';
+my $DCOP = '../client/dcop';
+my $TEST_APP = '$TEST_APP';
+my $OBJECT_NAME = 'TestInterface';
+
+
+sub shell_header {
+ print SHELL "TEST_APP=\`$DCOP 'TestApp-*'\`\n";
+}
+sub shell_footer {
+ print SHELL "$DCOP $TEST_APP 'MainApplication-Interface' quit";
+}
+
+sub test_h_header {
+print HEADER <<END;
+
+#ifndef MY_INTERFACE_H
+#define MY_INTERFACE_H
+
+/* This is combined with test.cpp and run_test a test case for dcop
+ * family of programms
+ */
+
+// some comment
+#include <dcopobject.h>
+#include <dcopref.h>
+
+class Test2;
+
+// this has to work too
+#include <qstring.h>
+
+
+
+namespace MyNamespace {
+ struct MyParentClass {
+ int x;
+ };
+}
+
+class Test : public MyNamespace::MyParentClass, virtual public DCOPObject
+{
+ K_DCOP
+
+public:
+ Test() : DCOPObject("TestInterface") {}
+ ~Test();
+k_dcop:
+
+END
+
+}
+
+sub test_h_footer {
+print HEADER <<END;
+
+};
+
+#endif // end
+
+END
+}
+
+
+
+sub getline {
+ local $_;
+ until (eof()) {
+ last unless defined($_ = <>);
+ chomp;
+ next if /^\s*#/;
+ return $_;
+ }
+ return '';
+}
+
+#sub getline {
+# print STDERR "HERE2\n";
+# my $res = &getlinereal;
+# print STDERR "G->" . $res . "<-\n";
+# return $res;
+#}
+
+
+# main();
+
+open(HEADER,'>test.h');
+open(IMPLEMENTATION,'>definitions.generated');
+open(BATCH, '>batch.generated');
+open(SHELL,'>shell.generated');
+open(DRIVER,'>driver.generated');
+
+&test_h_header;
+&shell_header;
+my $previous_comment;
+my $i = 0;
+my $i_1 = 1;
+until (eof()) {
+ my $comment = &getline;
+ next if $comment eq '';
+ my $return_type = $comment;
+ $previous_comment = $comment;
+ if ($comment =~ m#\s*//#) { $return_type = &getline; }
+ else { $comment = $previous_comment; }
+ my $function_name = &getline;
+ my $argument_types = &getline;
+ my $function_body = '';
+ my $line;
+ do {
+ $line = &getline;
+ $function_body .= $line;
+ } until ($line =~ /^}/);
+ my @shell_args = ();
+ my @cpp_args = ();
+ print STDERR "Working on function $function_name$argument_types\n";
+ while (1) {
+ local $_ = &getline;
+ chomp;
+ print STDERR "Looking at -$_-\n";
+ die 'I/O Error' if eof();
+ die 'I/O Error' unless defined($_); # should catch all previous IO errors as well
+
+ if (/^\s*$/ || /^-$/ ) {
+ if (scalar(@shell_args) == 0) {
+ @shell_args = ('');
+ @cpp_args = ('');
+ print STDERR "Function $function_name$argument_types: No arguments\n";
+ }
+ last;
+ }
+ /^(.*);(.*)$/ or last;
+ push @shell_args, ($1);
+ push @cpp_args, ($2);
+ print STDERR "Function $function_name$argument_types: args {-$1-} {-$2-}\n";
+ print STDERR "Function $function_name$argument_types: so far ", scalar(@shell_args), "\n";
+ }
+
+
+ $comment =~ s#^\s*//##;
+
+ print HEADER <<END;
+ // $comment
+ virtual $return_type ${function_name}_virtual $argument_types;
+ $return_type ${function_name} $argument_types;
+END
+
+ print IMPLEMENTATION <<END;
+ $return_type $DERIVED_CLASS :: ${function_name}_virtual $argument_types
+ $function_body
+
+ $return_type $BASE_CLASS :: ${function_name} $argument_types
+ $function_body
+END
+
+ my $cpp_cur = scalar(shift @cpp_args or '');
+ my $shell_cur = scalar(shift @shell_args or '');
+
+ if ($return_type ne 'void') {
+ print BATCH <<END;
+ output << "$return_type $function_name($argument_types)\\n{\\n";
+ output << "// $comment\\n";
+ output << object->$function_name($cpp_cur) << "\\n}\\n";
+ output << "$return_type ${function_name}_virtual($argument_types)\\n{\\n";
+ output << "// $comment\\n";
+ output << object->${function_name}_virtual($cpp_cur) << "\\n}\\n";
+END
+ } else {
+ print BATCH <<END;
+ // Void Functions:
+ object->$function_name();
+ object->${function_name}_virtual();
+END
+ }
+
+ print SHELL <<END;
+ echo "$return_type $function_name($argument_types)"
+ echo "{"
+ echo "// $comment";
+ $DCOP $TEST_APP $OBJECT_NAME $function_name $shell_cur
+ echo "}"
+ echo "$return_type ${function_name}_virtual($argument_types)"
+ echo "{"
+ echo "// $comment";
+ $DCOP $TEST_APP $OBJECT_NAME ${function_name}_virtual $shell_cur
+ echo "}"
+END
+
+ print DRIVER <<END;
+ case $i:
+ output << "$return_type $function_name($argument_types)\\n{\\n";
+ output << "// $comment\\n";
+ output << object->$function_name($cpp_cur) << '\\n';
+ output << "}\\n";
+ break;
+ case $i_1:
+ output << "$return_type ${function_name}_virtual($argument_types)\\n{\\n";
+ output << "// $comment\\n";
+ output << object->${function_name}_virtual($cpp_cur) << '\\n';
+ output << "}\\n";
+ break;
+END
+ $i += 2;
+ $i_1 = $i + 1;
+}
+
+&test_h_footer;
+&shell_footer;
+
+close HEADER;
+close IMPLEMENTATION;
+close BATCH;
+close SHELL;
+close DRIVER;
+
+1;
diff --git a/dcop/tests/run-tests.sh b/dcop/tests/run-tests.sh
new file mode 100644
index 000000000..216c29aef
--- /dev/null
+++ b/dcop/tests/run-tests.sh
@@ -0,0 +1,44 @@
+
+clean_up() {
+ rm -f batch.stdout shell.stdout shell.returns batch.returns
+}
+
+clean_up
+
+echo '* Running batch mode'
+./dcop_test --batch >batch.stdout
+
+echo -n '* Starting test app '
+./dcop_test >shell.stdout &
+
+while ! dcop | grep -q TestApp; do echo -n '.'; sleep 2; done
+
+echo ' started'
+
+echo '* Running driver mode'
+./driver `dcop 'TestApp-*'` >driver.stdout
+
+echo '* Running shell mode'
+source shell.generated >shell.returns
+
+echo -n '* Comparing ... '
+
+compare()
+{
+if ! diff -q --strip-trailing-cr $1 $2; then
+ echo "FAILED:"
+ diff -u $1 $2
+ exit 1;
+fi
+}
+
+compare batch.stdout shell.stdout
+compare batch.stdout driver.stdout
+compare batch.returns shell.returns
+compare batch.returns driver.returns
+
+clean_up
+
+echo "Passed"
+exit 0;
+
diff --git a/dcop/tests/test.cpp b/dcop/tests/test.cpp
new file mode 100644
index 000000000..025230547
--- /dev/null
+++ b/dcop/tests/test.cpp
@@ -0,0 +1,44 @@
+#include "test.h"
+#include <kapplication.h>
+#include <iostream>
+#include <dcopclient.h>
+#include <kcmdlineargs.h>
+
+
+
+Test::~Test()
+{
+}
+
+#include "definitions.generated"
+
+using namespace std;
+
+void batch()
+{
+ QTextStream output( fopen( "batch.returns", "w" ) , IO_WriteOnly );
+ Test* object = new Test;
+#include "batch.generated"
+}
+
+#ifdef Q_OS_WIN
+# define main kdemain
+#endif
+
+int main(int argc, char** argv)
+{
+ if ( argc > 1 ) {
+ batch();
+ return 0;
+ }
+ KCmdLineArgs::init( argc, argv, "TestApp", "Tests the dcop familly of tools + libraries", "1.0" ); // FIXME
+ KApplication app;
+ if(!app.dcopClient()->attach( ))
+ return 1;
+
+ app.dcopClient()->registerAs( "TestApp" );
+ new Test;
+ return app.exec();
+}
+
+
diff --git a/dcop/tests/testcases b/dcop/tests/testcases
new file mode 100644
index 000000000..0f16bdbe3
--- /dev/null
+++ b/dcop/tests/testcases
@@ -0,0 +1,105 @@
+# Format of this file:
+#
+# Lines beginning with '#' are comments
+# The file consists of a repetion of the following pattern
+# (\n means newline and + means you can repeat the line):
+#
+# // comment \n+
+# return_type \n
+# function_name \n
+# (argument_list) \n
+# { \n
+# body \n
+# } \n
+# arguments_to_use_in_shell;arguments_to_use_in_c++ \n+
+#
+# The last line has a few nuances:
+# 1. to call a void function you can use '-' or leave it out.
+#
+# 2. First you put shell like argument:
+# "string with spaces" 4 string_without_spaces
+# Then you should put c++ style arguments:
+# QString::fromLatin1("string with spaces"),4,"string_with_spaces"
+#
+# Note that the first argument has type QString and the last type const char*
+# (adapt accordingly)
+#
+// 1. easy case
+QString
+url
+()
+{
+return QString::fromLatin1( "http://www.kde.org/");
+}
+-
+
+// 2.1 overloading on number of args
+unsigned
+getObject
+( int num )
+{
+ return num;
+}
+42;42
+1;1
+
+
+
+unsigned int
+getObject
+( int x, int y)
+{
+ return x + y;
+}
+2 3;2,3
+
+
+
+
+// 2.2 overloading on type of args
+QString
+identity
+( QString x)
+{
+ return x;
+}
+"test";QString::fromLatin1("test")
+
+// 2.3 unsigned long int
+unsigned long int
+getObject23
+( int x, int y)
+{
+ return x + y;
+}
+2 3;2,3
+
+
+
+// 2.4 unsigned long int
+unsigned long int
+getObject24
+( unsigned long int x, int y)
+{
+ return x + y;
+}
+5 7;5,7
+
+
+
+#virtual QString identity( QCString );
+#
+#// 4. simple template argument:
+#virtual
+#
+#// 3. simple template return type:
+#virtual QValueList<DCOPRef> getWindows();
+#
+#
+#// spaces in the return value
+#virtual unsigned long int srvv();
+#unsigned long int srv();
+#
+#// spaces in the return value's template
+#QValueList< DCOPRef > srvtv();
+#QValueList< DCOPRef > srvt();
diff --git a/dcop/version.h b/dcop/version.h
new file mode 100644
index 000000000..c022cb9d5
--- /dev/null
+++ b/dcop/version.h
@@ -0,0 +1 @@
+#define DCOPSERVERID "DCOPServer v1.0"