]> rtime.felk.cvut.cz Git - frescor/frsh-forb.git/commitdiff
Add 'src/forb/' from commit '1ef7503676513a85e80eda0950d0cae8b60d7cdd'
authorMichal Sojka <sojkam1@fel.cvut.cz>
Thu, 27 Jan 2011 13:43:12 +0000 (14:43 +0100)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Thu, 27 Jan 2011 13:43:12 +0000 (14:43 +0100)
git-subtree-dir: src/forb
git-subtree-mainline: 0ab53f8d451359d07df47e14f6cd84e93010392b
git-subtree-split: 1ef7503676513a85e80eda0950d0cae8b60d7cdd

116 files changed:
src/forb/.gitignore [new file with mode: 0644]
src/forb/COPYING [new file with mode: 0644]
src/forb/Doxyfile [new file with mode: 0644]
src/forb/Makefile [new file with mode: 0644]
src/forb/Makefile.omk [new file with mode: 0644]
src/forb/README [new file with mode: 0644]
src/forb/TODO [new file with mode: 0644]
src/forb/doc/forb.vpp [new file with mode: 0644]
src/forb/forb-idl/Makefile [new file with mode: 0644]
src/forb/forb-idl/Makefile.am [new file with mode: 0644]
src/forb/forb-idl/Makefile.in [new file with mode: 0644]
src/forb/forb-idl/Makefile.omk [new file with mode: 0644]
src/forb/forb-idl/Makefile.rules [new file with mode: 0644]
src/forb/forb-idl/ORBit-idl-2.0.pc.in [new file with mode: 0644]
src/forb/forb-idl/config.h [new file with mode: 0644]
src/forb/forb-idl/forb-idl-backend.c [new file with mode: 0644]
src/forb/forb-idl/forb-idl-backend.h [new file with mode: 0644]
src/forb/forb-idl/forb-idl-c-backend.c [new file with mode: 0644]
src/forb/forb-idl/forb-idl-c-backend.h [new file with mode: 0644]
src/forb/forb-idl/forb-idl-c-common.c [new file with mode: 0644]
src/forb/forb-idl/forb-idl-c-deps.c [new file with mode: 0644]
src/forb/forb-idl/forb-idl-c-headers.c [new file with mode: 0644]
src/forb/forb-idl/forb-idl-c-imodule.c [new file with mode: 0644]
src/forb/forb-idl/forb-idl-c-skelimpl.c [new file with mode: 0644]
src/forb/forb-idl/forb-idl-c-skels.c [new file with mode: 0644]
src/forb/forb-idl/forb-idl-c-stubs.c [new file with mode: 0644]
src/forb/forb-idl/forb-idl-c-typecode.c [new file with mode: 0644]
src/forb/forb-idl/forb-idl-c-utils.c [new file with mode: 0644]
src/forb/forb-idl/forb-idl-driver.c [new file with mode: 0644]
src/forb/forb-idl/forb-idl-main.c [new file with mode: 0644]
src/forb/forb-idl/forb-idl-utils.c [new file with mode: 0644]
src/forb/forb-idl/forb-idl2.h [new file with mode: 0644]
src/forb/forb-idl/forb-idl3-types.h [new file with mode: 0644]
src/forb/forb-idl/forb_config.h [new file with mode: 0644]
src/forb/src/Makefile [new file with mode: 0644]
src/forb/src/Makefile.omk [new file with mode: 0644]
src/forb/src/basic_types.h [new file with mode: 0644]
src/forb/src/cdr.c [new file with mode: 0644]
src/forb/src/cdr.h [new file with mode: 0644]
src/forb/src/cdr_codec.h [new file with mode: 0644]
src/forb/src/daemon.c [new file with mode: 0644]
src/forb/src/discovery.c [new file with mode: 0644]
src/forb/src/discovery.h [new file with mode: 0644]
src/forb/src/exec_req.c [new file with mode: 0644]
src/forb/src/exec_req.h [new file with mode: 0644]
src/forb/src/executor.c [new file with mode: 0644]
src/forb/src/executor.h [new file with mode: 0644]
src/forb/src/forb-idl.idl [new file with mode: 0644]
src/forb/src/forb-internal.h [new file with mode: 0644]
src/forb/src/forb.c [new file with mode: 0644]
src/forb/src/forb.h [new file with mode: 0644]
src/forb/src/forb_endian.h [new file with mode: 0644]
src/forb/src/forb_utils.h [new file with mode: 0644]
src/forb/src/iop-idl.idl [new file with mode: 0644]
src/forb/src/iop.c [new file with mode: 0644]
src/forb/src/iop.h [new file with mode: 0644]
src/forb/src/object.c [new file with mode: 0644]
src/forb/src/object.h [new file with mode: 0644]
src/forb/src/object_type.h [new file with mode: 0644]
src/forb/src/peer.c [new file with mode: 0644]
src/forb/src/peer.h [new file with mode: 0644]
src/forb/src/port.c [new file with mode: 0644]
src/forb/src/port.h [new file with mode: 0644]
src/forb/src/proto.c [new file with mode: 0644]
src/forb/src/proto.h [new file with mode: 0644]
src/forb/src/proto_inet.c [new file with mode: 0644]
src/forb/src/proto_inet.h [new file with mode: 0644]
src/forb/src/proto_unix.c [new file with mode: 0644]
src/forb/src/proto_unix.h [new file with mode: 0644]
src/forb/src/refcnt.c [new file with mode: 0644]
src/forb/src/refcnt.h [new file with mode: 0644]
src/forb/src/regref.c [new file with mode: 0644]
src/forb/src/regref.h [new file with mode: 0644]
src/forb/src/request.c [new file with mode: 0644]
src/forb/src/request.h [new file with mode: 0644]
src/forb/src/server_id.h [new file with mode: 0644]
src/forb/src/sha1.c [new file with mode: 0644]
src/forb/src/sha1.h [new file with mode: 0644]
src/forb/src/syncobj.c [new file with mode: 0644]
src/forb/src/syncobj.h [new file with mode: 0644]
src/forb/src/tests/Makefile [new file with mode: 0644]
src/forb/src/tests/Makefile.omk [new file with mode: 0644]
src/forb/src/tests/discovery.c [new file with mode: 0644]
src/forb/src/tests/hello.idl [new file with mode: 0644]
src/forb/src/tests/hello_impl.c [new file with mode: 0644]
src/forb/src/tests/hello_impl.h [new file with mode: 0644]
src/forb/src/tests/hello_inproc.c [new file with mode: 0644]
src/forb/src/tests/hello_remote.c [new file with mode: 0644]
src/forb/src/tests/object_to_string/Makefile [new file with mode: 0644]
src/forb/src/tests/object_to_string/Makefile.omk [new file with mode: 0644]
src/forb/src/tests/object_to_string/interface.idl [new file with mode: 0644]
src/forb/src/tests/object_to_string/obj2str.c [new file with mode: 0644]
src/forb/src/tests/objref/Makefile [new file with mode: 0644]
src/forb/src/tests/objref/Makefile.omk [new file with mode: 0644]
src/forb/src/tests/objref/objref.c [new file with mode: 0644]
src/forb/src/tests/objref/objref.idl [new file with mode: 0644]
src/forb/src/tests/regobjref.c [new file with mode: 0644]
src/forb/src/tests/sequence.c [new file with mode: 0644]
src/forb/src/tests/sequence.idl [new file with mode: 0644]
src/forb/src/tests/test_proto_inet.c [new file with mode: 0644]
src/forb/src/tests/test_proto_unix.c [new file with mode: 0644]
src/forb/src/tests/test_syncobj.c [new file with mode: 0644]
src/forb/src/types.idl [new file with mode: 0644]
src/forb/src/ul_log_domains [new file with mode: 0755]
src/forb/src/uuid.c [new file with mode: 0644]
src/forb/src/uuid.h [new file with mode: 0644]
src/forb/tests-idl/Makefile [new file with mode: 0644]
src/forb/tests-idl/Makefile.omk [new file with mode: 0644]
src/forb/tests-idl/enum.idl [new file with mode: 0644]
src/forb/tests-idl/example_client.c [new file with mode: 0644]
src/forb/tests-idl/example_server.c [new file with mode: 0644]
src/forb/tests-idl/myinterface.idl [new file with mode: 0644]
src/forb/tests-idl/sequence.idl [new file with mode: 0644]
src/forb/tests-idl/string_test.idl [new file with mode: 0644]
src/forb/tests-idl/struct.idl [new file with mode: 0644]
src/forb/tests-idl/typedef.idl [new file with mode: 0644]

diff --git a/src/forb/.gitignore b/src/forb/.gitignore
new file mode 100644 (file)
index 0000000..3fb95a8
--- /dev/null
@@ -0,0 +1,11 @@
+_build/
+_compiled/
+*~
+config.omk-default
+cscope.*
+config.omk
+sources.txt
+TAGS
+*.kdevelop*
+.emacs*
+*.kdevses
diff --git a/src/forb/COPYING b/src/forb/COPYING
new file mode 100644 (file)
index 0000000..e37680c
--- /dev/null
@@ -0,0 +1,280 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
diff --git a/src/forb/Doxyfile b/src/forb/Doxyfile
new file mode 100644 (file)
index 0000000..c9f6d9d
--- /dev/null
@@ -0,0 +1,1417 @@
+# Doxyfile 1.5.6
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file 
+# that follow. The default is UTF-8 which is also the encoding used for all 
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the 
+# iconv built into libc) for the transcoding. See 
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = "FORB (Frescor Object Request Broker)"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, 
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), 
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, 
+# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, 
+# and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like regular Qt-style comments 
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will 
+# interpret the first line (until the first dot) of a Qt-style 
+# comment as the brief description. If set to NO, the comments 
+# will behave just like regular Qt-style comments (thus requiring 
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP         = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Java. For instance, namespaces will be presented as packages, qualified 
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL 
+# sources. Doxygen will then generate output that is tailored for 
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 
+# to include (a tag file for) the STL sources as input, then you should 
+# set this tag to YES in order to let doxygen match functions declarations and 
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
+# func(std::string) {}). This also make the inheritance and collaboration 
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. 
+# Doxygen will parse them like normal C++ but will assume all classes use public 
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter 
+# and setter methods for a property. Setting this option to YES (the default) 
+# will make doxygen to replace the get and set methods by a property in the 
+# documentation. This will only work if the methods are indeed getting or 
+# setting a simple type. If this is not the case, or you want to show the 
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = YES
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum 
+# is documented as struct, union, or enum with the name of the typedef. So 
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct 
+# with name TypeT. When disabled the typedef will appear as a member of a file, 
+# namespace, or class. And the struct will be named TypeS. This can typically 
+# be useful for C code in case the coding convention dictates that all compound 
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be 
+# extracted and appear in the documentation as a namespace called 
+# 'anonymous_namespace{file}', where file will be replaced with the base 
+# name of the file that contains the anonymous namespace. By default 
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the 
+# hierarchy of group names into alphabetical order. If set to NO (the default) 
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the 
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the 
+# Namespaces page.  This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from 
+# the version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the program writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = src
+
+# This tag can be used to specify the character encoding of the source files 
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 
+# also the default input encoding. Doxygen uses libiconv (or the iconv built 
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for 
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS          = 
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories. Note that the wildcards are matched 
+# against the file with absolute path, so to exclude all test directories 
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = 
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 
+# (namespaces, classes, functions, etc.) that should be excluded from the 
+# output. The symbol name can be a fully qualified name, a word, or if the 
+# wildcard * is used, a substring. Examples: ANamespace, AClass, 
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = .
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.  Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code 
+# will point to the HTML generated by the htags(1) tool instead of doxygen 
+# built-in source browser. The htags tool is part of GNU's global source 
+# tagging system (see http://www.gnu.org/software/global/global.html). You 
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files 
+# will be generated that can be used as input for Apple's Xcode 3 
+# integrated development environment, introduced with OSX 10.5 (Leopard). 
+# To create a documentation set, doxygen will generate a Makefile in the 
+# HTML output directory. Running make will produce the docset in that 
+# directory and running "make install" will install the docset in 
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find 
+# it at startup.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the 
+# feed. A documentation feed provides an umbrella under which multiple 
+# documentation sets from a single provider (such as a company or product suite) 
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that 
+# should uniquely identify the documentation set bundle. This should be a 
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen 
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 
+# documentation will contain sections that can be hidden and shown after the 
+# page has loaded. For this to work a browser that supports 
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox 
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING     = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to FRAME, a side panel will be generated
+# containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature. Other possible values 
+# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
+# and Class Hiererachy pages using a tree view instead of an ordered list;
+# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
+# disables this behavior completely. For backwards compatibility with previous
+# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
+# respectively.
+
+GENERATE_TREEVIEW      = NONE
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# Use this tag to change the font size of Latex formulas included 
+# as images in the HTML documentation. The default is 10. Note that 
+# when you change the font size after a successful doxygen run you need 
+# to manually remove any form_*.png images from the HTML output directory 
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse 
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option is superseded by the HAVE_DOT option below. This is only a 
+# fallback. It is recommended to install and use dot, since it yields more 
+# powerful graphs.
+
+CLASS_DIAGRAMS         = NO
+
+# You can define message sequence charts within doxygen comments using the \msc 
+# command. Doxygen will then run the mscgen tool (see 
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the 
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where 
+# the mscgen tool resides. If left empty the tool is assumed to be found in the 
+# default search path.
+
+MSCGEN_PATH            = 
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = YES
+
+# By default doxygen will write a font called FreeSans.ttf to the output 
+# directory and reference it in all dot files that doxygen generates. This 
+# font does not include all possible unicode characters however, so when you need 
+# these (or just want a differently looking font) you can specify the font name 
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font, 
+# which can be done by putting it in a standard location or by setting the 
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory 
+# containing the font.
+
+DOT_FONTNAME           = FreeSans
+
+# By default doxygen will tell dot to use the output directory to look for the 
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a 
+# different font using DOT_FONTNAME you can set the path where dot 
+# can find it using this tag.
+
+DOT_FONTPATH           = 
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = YES
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then 
+# doxygen will generate a call dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable call graphs 
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then 
+# doxygen will generate a caller dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable caller 
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of 
+# nodes that will be shown in the graph. If the number of nodes in a graph 
+# becomes larger than this value, doxygen will truncate the graph, which is 
+# visualized by representing a node as a red box. Note that doxygen if the 
+# number of direct children of the root node in a graph is already larger than 
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note 
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that the size of a graph can be further restricted by 
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is enabled by default, which results in a transparent 
+# background. Warning: Depending on the platform used, enabling this option 
+# may lead to badly anti-aliased labels on the edges of a graph (i.e. they 
+# become hard to read).
+
+DOT_TRANSPARENT        = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
diff --git a/src/forb/Makefile b/src/forb/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/src/forb/Makefile.omk b/src/forb/Makefile.omk
new file mode 100644 (file)
index 0000000..e34fb4a
--- /dev/null
@@ -0,0 +1,2 @@
+SUBDIRS = tests-idl src
+EXTRA_RULES_SUBDIRS = forb-idl
diff --git a/src/forb/README b/src/forb/README
new file mode 100644 (file)
index 0000000..f6969c0
--- /dev/null
@@ -0,0 +1,22 @@
+Compilation
+===========
+
+1. Download FRESCOR SVN repositories fosa and omk-build
+
+2. Download ulut (from
+   http://sourceforge.net/project/showfiles.php?group_id=118937&package_id=130840)
+
+3. Create symbolic links to forb, fosa and ulut sources inside
+   omk-build/aquosa:
+
+   cd omk-build/aquosa
+   ln -s some-path/fosa .
+   ln -s some-path/ulut .
+   ln -s path-to-this-directory/forb .
+
+3. Configure the sources:
+       make default-config
+
+5. Compile it:
+       make    
+       
diff --git a/src/forb/TODO b/src/forb/TODO
new file mode 100644 (file)
index 0000000..8c14cc8
--- /dev/null
@@ -0,0 +1,10 @@
+* Add forb_init() parameters: argc, argv and orb_id
+
+* More flexible handling of log messages (dynamic registration,
+   parsing of command line parameters).
+
+* Add FNA as transport protocol (probably with some reliable protocol
+   on top of FNA)
+
+* Add routing layer
+   
diff --git a/src/forb/doc/forb.vpp b/src/forb/doc/forb.vpp
new file mode 100644 (file)
index 0000000..1ea834e
Binary files /dev/null and b/src/forb/doc/forb.vpp differ
diff --git a/src/forb/forb-idl/Makefile b/src/forb/forb-idl/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/src/forb/forb-idl/Makefile.am b/src/forb/forb-idl/Makefile.am
new file mode 100644 (file)
index 0000000..b45cae2
--- /dev/null
@@ -0,0 +1,46 @@
+bin_PROGRAMS = orbit-idl-2
+
+orbit_backends_dir = $(libdir)/orbit-2.0/idl-backends
+
+INCLUDES =                                                     \
+       -I$(top_builddir)                                       \
+       -I$(top_builddir)/include                               \
+       -I$(top_srcdir)                                         \
+       -I$(top_srcdir)/include                                 \
+       -DORBIT_BACKENDS_DIR="\"$(orbit_backends_dir)\""        \
+       -DVERSION=\"$(ORBIT_VERSION)\"                          \
+       -DORBIT2_INTERNAL_API                                   \
+       $(WARN_CFLAGS)                                          \
+       $(DISABLE_DEPRECATED_CFLAGS)                            \
+       $(ORBIT_IDL_CFLAGS)
+
+orbit_idl_2_LDADD =                     \
+       $(ORBIT_IDL_LIBS)               \
+       $(LIBM)
+
+orbit_idl_2_SOURCES =                  \
+       orbit-idl-main.c                \
+       orbit-idl-driver.c              \
+       orbit-idl-backend.c             \
+       orbit-idl-backend.h             \
+       orbit-idl-utils.c               \
+       orbit-idl2.h                    \
+       orbit-idl3-types.h              \
+        orbit-idl-c-backend.h          \
+        orbit-idl-c-backend.c          \
+        orbit-idl-c-stubs.c            \
+        orbit-idl-c-skels.c            \
+        orbit-idl-c-headers.c          \
+        orbit-idl-c-common.c           \
+       orbit-idl-c-imodule.c           \
+        orbit-idl-c-skelimpl.c         \
+        orbit-idl-c-utils.c            \
+        orbit-idl-c-typecode.c         \
+        orbit-idl-c-deps.c             \
+       orbit-idl2.h
+
+orbitidlincludedir = $(includedir)/orbit-2.0/orbit-idl
+orbitidlinclude_HEADERS = orbit-idl-backend.h
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = ORBit-idl-2.0.pc
diff --git a/src/forb/forb-idl/Makefile.in b/src/forb/forb-idl/Makefile.in
new file mode 100644 (file)
index 0000000..e7fb770
--- /dev/null
@@ -0,0 +1,614 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+bin_PROGRAMS = orbit-idl-2$(EXEEXT)
+subdir = src/idl-compiler
+DIST_COMMON = $(orbitidlinclude_HEADERS) $(srcdir)/Makefile.am \
+       $(srcdir)/Makefile.in $(srcdir)/ORBit-idl-2.0.pc.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+       $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = ORBit-idl-2.0.pc
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgconfigdir)" \
+       "$(DESTDIR)$(orbitidlincludedir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
+am_orbit_idl_2_OBJECTS = orbit-idl-main.$(OBJEXT) \
+       orbit-idl-driver.$(OBJEXT) orbit-idl-backend.$(OBJEXT) \
+       orbit-idl-utils.$(OBJEXT) orbit-idl-c-backend.$(OBJEXT) \
+       orbit-idl-c-stubs.$(OBJEXT) orbit-idl-c-skels.$(OBJEXT) \
+       orbit-idl-c-headers.$(OBJEXT) orbit-idl-c-common.$(OBJEXT) \
+       orbit-idl-c-imodule.$(OBJEXT) orbit-idl-c-skelimpl.$(OBJEXT) \
+       orbit-idl-c-utils.$(OBJEXT) orbit-idl-c-typecode.$(OBJEXT) \
+       orbit-idl-c-deps.$(OBJEXT)
+orbit_idl_2_OBJECTS = $(am_orbit_idl_2_OBJECTS)
+am__DEPENDENCIES_1 =
+orbit_idl_2_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+       $(LDFLAGS) -o $@
+SOURCES = $(orbit_idl_2_SOURCES)
+DIST_SOURCES = $(orbit_idl_2_SOURCES)
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+pkgconfigDATA_INSTALL = $(INSTALL_DATA)
+DATA = $(pkgconfig_DATA)
+orbitidlincludeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(orbitidlinclude_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+pkglibdir = @pkglibdir@
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISABLE_DEPRECATED_CFLAGS = @DISABLE_DEPRECATED_CFLAGS@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GLIB_REQUIRED = @GLIB_REQUIRED@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBIDL_REQUIRED = @LIBIDL_REQUIRED@
+LIBM = @LIBM@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LINC_CFLAGS = @LINC_CFLAGS@
+LINC_LIBS = @LINC_LIBS@
+LN_S = @LN_S@
+LOCAL_LINC_CFLAGS = @LOCAL_LINC_CFLAGS@
+LOCAL_LINC_LIBS = @LOCAL_LINC_LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+LT_VERSION = @LT_VERSION@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MINGW_LDFLAGS = @MINGW_LDFLAGS@
+MKDIR_P = @MKDIR_P@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+ORBIT_ALIGNOF_CORBA_BOOLEAN = @ORBIT_ALIGNOF_CORBA_BOOLEAN@
+ORBIT_ALIGNOF_CORBA_CHAR = @ORBIT_ALIGNOF_CORBA_CHAR@
+ORBIT_ALIGNOF_CORBA_DOUBLE = @ORBIT_ALIGNOF_CORBA_DOUBLE@
+ORBIT_ALIGNOF_CORBA_FLOAT = @ORBIT_ALIGNOF_CORBA_FLOAT@
+ORBIT_ALIGNOF_CORBA_LONG = @ORBIT_ALIGNOF_CORBA_LONG@
+ORBIT_ALIGNOF_CORBA_LONG_DOUBLE = @ORBIT_ALIGNOF_CORBA_LONG_DOUBLE@
+ORBIT_ALIGNOF_CORBA_LONG_LONG = @ORBIT_ALIGNOF_CORBA_LONG_LONG@
+ORBIT_ALIGNOF_CORBA_OCTET = @ORBIT_ALIGNOF_CORBA_OCTET@
+ORBIT_ALIGNOF_CORBA_POINTER = @ORBIT_ALIGNOF_CORBA_POINTER@
+ORBIT_ALIGNOF_CORBA_SHORT = @ORBIT_ALIGNOF_CORBA_SHORT@
+ORBIT_ALIGNOF_CORBA_STRUCT = @ORBIT_ALIGNOF_CORBA_STRUCT@
+ORBIT_ALIGNOF_CORBA_WCHAR = @ORBIT_ALIGNOF_CORBA_WCHAR@
+ORBIT_CFLAGS = @ORBIT_CFLAGS@
+ORBIT_IDL_CFLAGS = @ORBIT_IDL_CFLAGS@
+ORBIT_IDL_LIBS = @ORBIT_IDL_LIBS@
+ORBIT_LIBS = @ORBIT_LIBS@
+ORBIT_MAJOR_VERSION = @ORBIT_MAJOR_VERSION@
+ORBIT_MICRO_VERSION = @ORBIT_MICRO_VERSION@
+ORBIT_MINOR_VERSION = @ORBIT_MINOR_VERSION@
+ORBIT_NAME_CFLAGS = @ORBIT_NAME_CFLAGS@
+ORBIT_NAME_LIBS = @ORBIT_NAME_LIBS@
+ORBIT_SERIAL = @ORBIT_SERIAL@
+ORBIT_VERSION = @ORBIT_VERSION@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+orbit_backends_dir = $(libdir)/orbit-2.0/idl-backends
+INCLUDES = \
+       -I$(top_builddir)                                       \
+       -I$(top_builddir)/include                               \
+       -I$(top_srcdir)                                         \
+       -I$(top_srcdir)/include                                 \
+       -DORBIT_BACKENDS_DIR="\"$(orbit_backends_dir)\""        \
+       -DVERSION=\"$(ORBIT_VERSION)\"                          \
+       -DORBIT2_INTERNAL_API                                   \
+       $(WARN_CFLAGS)                                          \
+       $(DISABLE_DEPRECATED_CFLAGS)                            \
+       $(ORBIT_IDL_CFLAGS)
+
+orbit_idl_2_LDADD = \
+       $(ORBIT_IDL_LIBS)               \
+       $(LIBM)
+
+orbit_idl_2_SOURCES = \
+       orbit-idl-main.c                \
+       orbit-idl-driver.c              \
+       orbit-idl-backend.c             \
+       orbit-idl-backend.h             \
+       orbit-idl-utils.c               \
+       orbit-idl2.h                    \
+       orbit-idl3-types.h              \
+        orbit-idl-c-backend.h          \
+        orbit-idl-c-backend.c          \
+        orbit-idl-c-stubs.c            \
+        orbit-idl-c-skels.c            \
+        orbit-idl-c-headers.c          \
+        orbit-idl-c-common.c           \
+       orbit-idl-c-imodule.c           \
+        orbit-idl-c-skelimpl.c         \
+        orbit-idl-c-utils.c            \
+        orbit-idl-c-typecode.c         \
+        orbit-idl-c-deps.c             \
+       orbit-idl2.h
+
+orbitidlincludedir = $(includedir)/orbit-2.0/orbit-idl
+orbitidlinclude_HEADERS = orbit-idl-backend.h
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = ORBit-idl-2.0.pc
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  src/idl-compiler/Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --gnu  src/idl-compiler/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+ORBit-idl-2.0.pc: $(top_builddir)/config.status $(srcdir)/ORBit-idl-2.0.pc.in
+       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+install-binPROGRAMS: $(bin_PROGRAMS)
+       @$(NORMAL_INSTALL)
+       test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+         if test -f $$p \
+            || test -f $$p1 \
+         ; then \
+           f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+          echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+          $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+         else :; fi; \
+       done
+
+uninstall-binPROGRAMS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+         echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+         rm -f "$(DESTDIR)$(bindir)/$$f"; \
+       done
+
+clean-binPROGRAMS:
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+         echo " rm -f $$p $$f"; \
+         rm -f $$p $$f ; \
+       done
+orbit-idl-2$(EXEEXT): $(orbit_idl_2_OBJECTS) $(orbit_idl_2_DEPENDENCIES) 
+       @rm -f orbit-idl-2$(EXEEXT)
+       $(LINK) $(orbit_idl_2_OBJECTS) $(orbit_idl_2_LDADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/orbit-idl-backend.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/orbit-idl-c-backend.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/orbit-idl-c-common.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/orbit-idl-c-deps.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/orbit-idl-c-headers.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/orbit-idl-c-imodule.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/orbit-idl-c-skelimpl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/orbit-idl-c-skels.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/orbit-idl-c-stubs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/orbit-idl-c-typecode.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/orbit-idl-c-utils.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/orbit-idl-driver.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/orbit-idl-main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/orbit-idl-utils.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@   $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+install-pkgconfigDATA: $(pkgconfig_DATA)
+       @$(NORMAL_INSTALL)
+       test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)"
+       @list='$(pkgconfig_DATA)'; for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         f=$(am__strip_dir) \
+         echo " $(pkgconfigDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+         $(pkgconfigDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgconfigdir)/$$f"; \
+       done
+
+uninstall-pkgconfigDATA:
+       @$(NORMAL_UNINSTALL)
+       @list='$(pkgconfig_DATA)'; for p in $$list; do \
+         f=$(am__strip_dir) \
+         echo " rm -f '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+         rm -f "$(DESTDIR)$(pkgconfigdir)/$$f"; \
+       done
+install-orbitidlincludeHEADERS: $(orbitidlinclude_HEADERS)
+       @$(NORMAL_INSTALL)
+       test -z "$(orbitidlincludedir)" || $(MKDIR_P) "$(DESTDIR)$(orbitidlincludedir)"
+       @list='$(orbitidlinclude_HEADERS)'; for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         f=$(am__strip_dir) \
+         echo " $(orbitidlincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(orbitidlincludedir)/$$f'"; \
+         $(orbitidlincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(orbitidlincludedir)/$$f"; \
+       done
+
+uninstall-orbitidlincludeHEADERS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(orbitidlinclude_HEADERS)'; for p in $$list; do \
+         f=$(am__strip_dir) \
+         echo " rm -f '$(DESTDIR)$(orbitidlincludedir)/$$f'"; \
+         rm -f "$(DESTDIR)$(orbitidlincludedir)/$$f"; \
+       done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+           $$tags $$unique; \
+       fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       test -z "$(CTAGS_ARGS)$$tags$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$tags $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(DATA) $(HEADERS)
+installdirs:
+       for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(orbitidlincludedir)"; do \
+         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+       done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-orbitidlincludeHEADERS install-pkgconfigDATA
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-orbitidlincludeHEADERS \
+       uninstall-pkgconfigDATA
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+       clean-generic clean-libtool ctags distclean distclean-compile \
+       distclean-generic distclean-libtool distclean-tags distdir dvi \
+       dvi-am html html-am info info-am install install-am \
+       install-binPROGRAMS install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-info install-info-am install-man \
+       install-orbitidlincludeHEADERS install-pdf install-pdf-am \
+       install-pkgconfigDATA install-ps install-ps-am install-strip \
+       installcheck installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-compile \
+       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+       tags uninstall uninstall-am uninstall-binPROGRAMS \
+       uninstall-orbitidlincludeHEADERS uninstall-pkgconfigDATA
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/forb/forb-idl/Makefile.omk b/src/forb/forb-idl/Makefile.omk
new file mode 100644 (file)
index 0000000..657ae33
--- /dev/null
@@ -0,0 +1,19 @@
+bin_PROGRAMS = forb-idl
+
+#GLIB_FLAGS := $(shell pkg-config --cflags glib-2.0)
+IDL_FLAGS := $(shell pkg-config --cflags libIDL-2.0)
+CFLAGS += $(IDL_FLAGS) -DFORB_BACKENDS_DIR=\"/orbit-backend-dir\" -DVERSION=\"0.1\"
+CFLAGS := $(filter-out -fmudflapth,$(CFLAGS))
+LDFLAGS := $(filter-out -fmudflapth,$(LDFLAGS))
+LDFLAGS := $(filter-out -lmudflapth,$(LDFLAGS))
+
+forb-idl_SOURCES = forb-idl-backend.c forb-idl-backend.h       \
+                  forb-idl-c-backend.c forb-idl-c-backend.h    \
+                  forb-idl-c-common.c forb-idl-c-deps.c        \
+                  forb-idl-c-headers.c forb-idl-c-imodule.c    \
+                  forb-idl-c-skelimpl.c forb-idl-c-skels.c     \
+                  forb-idl-c-stubs.c forb-idl-c-typecode.c     \
+                  forb-idl-c-utils.c forb-idl-driver.c         \
+                  forb-idl-main.c forb-idl-utils.c forb-idl2.h \
+                  forb-idl3-types.h
+forb-idl_LIBS = IDL-2 glib-2.0 
diff --git a/src/forb/forb-idl/Makefile.rules b/src/forb/forb-idl/Makefile.rules
new file mode 100644 (file)
index 0000000..e5b6684
--- /dev/null
@@ -0,0 +1,1323 @@
+#                   Version for Linux/RTLinux builds.        #OMK@linux
+#
+#  Makefile.rules - OCERA make framework common project rules -*- makefile -*- #OMK@base
+#
+#  (C) Copyright 2003 by Pavel Pisa - OCERA team member
+#  (C) Copyright 2006 by Michal Sojka - Czech Technical University, FEE, DCE
+#
+#  Homepage: http://rtime.felk.cvut.cz/omk/
+#
+# The OMK build system is distributed under the GNU General Public
+# License.  See file COPYING for details.
+#
+# input variables
+# V                .. if set to 1, full command text is shown else short form is used
+# W                .. whole tree - if set to 1, make is always called from the top-level directory
+# SUBDIRS          .. list of subdirectories intended for make from actual directory
+# default_CONFIG   .. list of default config assignments CONFIG_XXX=y/n ...
+# LN_HEADERS       .. if "y", header files are symbolicaly linked instead of copied. #OMK@include
+#                                                            #OMK@linux
+# input variables
+# lib_LIBRARIES    .. list of the user-space libraries
+# shared_LIBRARIES .. list of the user-space shared libraries
+# kernel_LIBRARIES .. list of the kernel-space libraries
+# rtlinux_LIBRARIES.. list of the RT-Linux kernel-space libraries
+# include_HEADERS  .. list of the user-space public header files
+# nobase_include_HEADERS .. public headers copied even with directory part
+# renamed_include_HEADERS .. public headers copied to the different target name
+# kernel_HEADERS   .. list of the kernel-space public header files
+# rtlinux_HEADERS  .. list of the RT-Linux kernel-space public header files
+# bin_PROGRAMS     .. list of the require binary programs
+# utils_PROGRAMS   .. list of the development utility programs
+# test_PROGRAMS    .. list of the testing programs
+# kernel_MODULES   .. list of the kernel side modules/applications
+# rtlinux_MODULES  .. list of RT-Linux the kernel side modules/applications
+# xxx_SOURCES      .. list of specific target sources
+# xxx_LIBS         .. list of specific target libraries
+# INCLUDES         .. additional include directories and defines for user-space
+# kernel_INCLUDES  .. additional include directories and defines for kernel-space
+# rtlinux_INCLUDES .. additional include directories and defines for RT-Linux
+# OMIT_KERNEL_PASSES  if defined, all kernel passes are omited
+#
+# LINUX_DIR        .. location of Linux kernel sources
+# RTL_DIR          .. location of RT-Linux sources
+# CFLAGS           .. C compiler flags
+# CXXFLAGS         .. C++ compiler flags
+# CPPFLAGS        .. C preprocessor flags
+# LDFLAGS         .. linker flags for programs linking
+# LOCAL_CONFIG_H   .. name of local config.h file generated from values #OMK@config_h
+#                     of options defined in the current directory
+# config_include_HEADERS .. names of global config files (possibly
+#                     with subdirectories)
+# xxx_DEFINES      .. list of config directives to be included in
+#                     config header file of the name <somedir>/xxx.h
+# DOXYGEN          .. if non-empty, generated headers includes Doxygen's @file
+#                    command, so it is possible to document config
+#                    variables.
+# QT_SUBDIRS       .. subdirectories where to build QT applications using qmake #OMK@qt
+# QTDIR                   .. where QT resides
+OMK_RULES_TYPE=linux                                         #OMK@__type
+                                                             #OMK@base
+# We need to ensure definition of sources directory first
+ifndef SOURCES_DIR
+# Only shell built-in pwd understands -L
+SOURCES_DIR := $(shell ( pwd -L ) )
+endif
+
+# If we are not called by OMK leaf Makefile...
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(abspath $(dir $(filter %Makefile.rules,$(MAKEFILE_LIST))))
+endif
+
+# OUTPUT_DIR is the place where _compiled, _build and possible other
+# files/directories are created. By default is the same as
+# $(MAKERULES_DIR).
+ifndef OUTPUT_DIR
+OUTPUT_DIR := $(MAKERULES_DIR)
+endif
+
+.PHONY: all default check-make-ver omkize
+
+ifdef W
+  ifeq ("$(origin W)", "command line")
+    OMK_WHOLE_TREE:=$(W)
+  endif
+endif
+ifndef OMK_WHOLE_TREE
+  OMK_WHOLE_TREE:=0
+endif
+
+ifneq ($(OMK_WHOLE_TREE),1)
+all: check-make-ver default
+       @echo "Compilation finished"
+else
+# Run make in the top-level directory
+all:
+       @$(MAKE) -C $(MAKERULES_DIR) OMK_SERIALIZE_INCLUDED=n SOURCES_DIR=$(MAKERULES_DIR) RELATIVE_DIR="" $(MAKECMDGOALS) W=0
+endif
+
+ifdef OMK_TESTSROOT
+# Usage: $(call canttest,<error message>)
+define canttest
+       ( echo "$(1)" > $(OUTPUT_DIR)/_canttest; echo "$(1)"; exit 1 )
+endef
+else
+define canttest
+       echo "$(1)"
+endef
+endif
+
+#=========================
+# Include the config file
+
+# FIXME: I think CONFIG_FILE_OK variable is useless. We have three
+# config files and it is not clearly defined to which file is this
+# variable related.
+ifneq ($(CONFIG_FILE_OK),y)
+ifndef CONFIG_FILE
+CONFIG_FILE      := $(OUTPUT_DIR)/config.omk
+endif
+ifneq ($(wildcard $(CONFIG_FILE)-default),)
+-include $(CONFIG_FILE)-default
+else
+ifneq ($(MAKECMDGOALS),default-config)
+$(warning Please, run "make default-config" first)
+endif
+endif
+
+-include $(OUTPUT_DIR)/config.target
+
+ifneq ($(wildcard $(CONFIG_FILE)),)
+-include $(CONFIG_FILE)
+CONFIG_FILE_OK = y
+endif
+endif #$(CONFIG_FILE_OK)
+
+
+CONFIG_FILES ?= $(wildcard $(CONFIG_FILE)-default) $(wildcard $(OUTPUT_DIR)/config.target) $(wildcard $(CONFIG_FILE))
+
+
+export SOURCES_DIR MAKERULES_DIR RELATIVE_DIR
+export CONFIG_FILE CONFIG_FILES OMK_SERIALIZE_INCLUDED OMK_VERBOSE OMK_SILENT
+# OMK_SERIALIZE_INCLUDED has to be exported to submakes because passes
+# must to be serialized only in the toplevel make.
+
+ifndef RELATIVE_DIR
+RELATIVE_DIR := $(SOURCES_DIR:$(OUTPUT_DIR)%=%)
+endif
+#$(warning  === RELATIVE_DIR = "$(RELATIVE_DIR)" ===)
+override RELATIVE_DIR := $(RELATIVE_DIR:/%=%)
+override RELATIVE_DIR := $(RELATIVE_DIR:\\%=%)
+#$(warning  RELATIVE_DIR = "$(RELATIVE_DIR)")
+override BACK2TOP_DIR := $(shell echo $(RELATIVE_DIR)/ | sed -e 's_//_/_g' -e 's_/\./_/_g' -e 's_^\./__g'  -e 's_\([^/][^/]*\)_.._g' -e 's_/$$__')
+#$(warning  BACK2TOP_DIR = "$(BACK2TOP_DIR)")
+
+#$(warning SOURCES_DIR = "$(SOURCES_DIR)")
+#$(warning MAKERULES_DIR = "$(OUTPUT_DIR)")
+#$(warning RELATIVE_DIR = "$(RELATIVE_DIR)")
+
+# We have to use RELATIVE_PREFIX because of mingw
+override RELATIVE_PREFIX := $(RELATIVE_DIR)/
+override RELATIVE_PREFIX := $(RELATIVE_PREFIX:/%=%)
+
+#vpath %.c $(SOURCES_DIR)
+#vpath %.cc $(SOURCES_DIR)
+#vpath %.cxx $(SOURCES_DIR)
+
+# Define srcdir for Automake compatibility
+srcdir = $(SOURCES_DIR)
+
+# Defines for quiet compilation
+ifdef V
+  ifeq ("$(origin V)", "command line")
+    OMK_VERBOSE = $(V)
+  endif
+endif
+ifndef OMK_VERBOSE
+  OMK_VERBOSE = 0
+endif
+ifneq ($(OMK_VERBOSE),0)
+  Q =
+else
+  Q = @
+endif
+ifneq ($(findstring s,$(MAKEFLAGS)),)
+  QUIET_CMD_ECHO = true
+  OMK_SILENT = 1
+else
+  QUIET_CMD_ECHO = echo
+endif
+
+MAKEFILE_OMK=Makefile.omk
+# All subdirectories (even linked ones) containing Makefile.omk
+# Usage in Makefile.omk: SUBDIRS = $(ALL_OMK_SUBDIRS)
+ALL_OMK_SUBDIRS = $(patsubst %/$(MAKEFILE_OMK),%,$(patsubst $(SOURCES_DIR)/%,%,$(wildcard $(SOURCES_DIR)/*/$(MAKEFILE_OMK))))
+
+# ===================================================================
+# We have set up all important variables, so we can check and include
+# real OCERA style Makefile.omk now
+ifndef OMK_INCLUDED
+include $(SOURCES_DIR)/$(MAKEFILE_OMK)
+ifeq ($(AUTOMATIC_SUBDIRS),y)
+SUBDIRS?=$(ALL_OMK_SUBDIRS)
+endif
+OMK_INCLUDED := 1
+endif
+
+check-make-ver:
+       @GOOD_MAKE_VERSION=`echo $(MAKE_VERSION) | sed -n -e 's/^[4-9]\..*\|^3\.9[0-9].*\|^3\.8[1-9].*/y/p'` ; \
+       if [ x$$GOOD_MAKE_VERSION != xy ] ; then \
+               echo "Your make program version is too old and does not support OMK system." ; \
+               echo "Please update to make program 3.81beta1 or newer." ; exit 1 ; \
+       fi
+
+distclean dist-clean:
+       @$(QUIET_CMD_ECHO) "  RM      $(COMPILED_DIR_NAME) $(BUILD_DIR_NAME)"
+       @rm -fr $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)  $(OUTPUT_DIR)/$(BUILD_DIR_NAME)
+
+# Common OMK templates
+# ====================
+
+# Syntax: $(call mkdir,<dir name>)
+define mkdir_def
+       [ -d $(1) ] || mkdir -p $(1) || exit 1
+endef
+
+ifneq ($(OMK_VERBOSE),2)
+NO_PRINT_DIRECTORY := --no-print-directory
+endif
+
+ifeq ($(USE_LEAF_MAKEFILES),n)
+export USE_LEAF_MAKEFILES
+SUBDIR_MAKEFILE=$(MAKERULES_DIR)/Makefile.rules
+SOURCESDIR_MAKEFILE=$(MAKERULES_DIR)/Makefile.rules
+else
+SUBDIR_MAKEFILE=$(SOURCES_DIR)/$(3)/Makefile
+SOURCESDIR_MAKEFILE=$(SOURCES_DIR)/Makefile
+endif
+
+pass = $(strip $(1))
+
+# Call a pass in a subdirectory
+# Usage: $(call omk_pass_subdir_template,<pass name>,<build dir>,<subdir>)
+define omk_pass_subdir_template
+.PHONY: $(pass)-$(3)-subdir
+$(pass)-submakes: $(pass)-$(3)-subdir
+$(pass)-$(3)-subdir:
+       @$(call mkdir_def,$(2)/$(3))
+       +@$(MAKE) SOURCES_DIR=$(SOURCES_DIR)/$(3) $(NO_PRINT_DIRECTORY) \
+               RELATIVE_DIR=$(RELATIVE_PREFIX)$(3) -C $(2)/$(3) \
+               -f $(SUBDIR_MAKEFILE) $(pass)-submakes
+# In subdirectories we can call submakes directly since passes are
+# already searialized on the toplevel make.
+endef
+
+ifdef OMK_TESTSROOT
+check-target = $(1:%=%-check)
+endif
+
+# Call a pass in a subdirectory
+# Usage: $(call extra_rules_subdir_template,<subdir>)
+define extra_rules_subdir_template
+extra-rules-subdirs: extra-rules-$(1)
+extra-rules-$(1):
+       +@$(MAKE) OMK_SERIALIZE_INCLUDED=n MAKERULES_DIR=$(SOURCES_DIR)/$(1) OUTPUT_DIR=$(OUTPUT_DIR) \
+               SOURCES_DIR=$(SOURCES_DIR)/$(1) RELATIVE_DIR=$(RELATIVE_PREFIX)$(1) -C $(SOURCES_DIR)/$(1)
+endef
+
+.PHONY: extra-rules-subdirs
+extra-rules-subdirs:
+
+$(foreach subdir,$(EXTRA_RULES_SUBDIRS),$(eval $(call extra_rules_subdir_template,$(subdir))))
+
+# Usage: $(call omk_pass_template,<pass name>,<build dir>,[<local make flags>],[<local enable condition>])
+define omk_pass_template
+.PHONY: $(pass) $(pass)-local $(pass)-check $(pass)-submakes
+$(foreach subdir,$(SUBDIRS),$(eval $(call omk_pass_subdir_template,$(pass),$(2),$(subdir))))
+$(pass):
+# Submakes have to be called this way and not as dependecies for pass
+# serialization to work
+       +@$(MAKE) SOURCES_DIR=$(SOURCES_DIR) $(NO_PRINT_DIRECTORY) \
+               RELATIVE_DIR=$(RELATIVE_DIR) \
+               -f $(SOURCESDIR_MAKEFILE) $(pass)-submakes
+$(pass)-submakes:
+       @true                   # Do not emit "nothing to be done" messages
+
+ifneq ($(4)$($(pass)_HOOKS),)
+$(pass)-submakes: $(pass)-this-dir
+$(pass)-this-dir: $(foreach subdir,$(SUBDIRS),$(pass)-$(subdir)-subdir)
+       +@echo "make[omk]: $(pass) in $(RELATIVE_DIR)"
+       @$(call mkdir_def,$(2))
+       +@$(MAKE) $(NO_PRINT_DIRECTORY) SOURCES_DIR=$(SOURCES_DIR) RELATIVE_DIR=$(RELATIVE_DIR) -C $(2) \
+               -f $(SOURCESDIR_MAKEFILE) $(3) $(check-target) $(1:%=%-local)
+$(pass)-local: $($(pass)_HOOKS)
+endif
+endef
+
+# =======================
+# DEFAULT CONFIG PASS
+
+default-config:
+       @echo "# Start of OMK config file" > "$(CONFIG_FILE)-default"
+       @echo "# This file should not be altered manually" >> "$(CONFIG_FILE)-default"
+       @echo "# Overrides should be stored in file $(notdir $(CONFIG_FILE))" >> "$(CONFIG_FILE)-default"
+       @echo >> "$(CONFIG_FILE)-default"
+       @$(MAKE) $(NO_PRINT_DIRECTORY) -C $(OUTPUT_DIR) \
+               RELATIVE_DIR="" SOURCES_DIR=$(OUTPUT_DIR) \
+               -f $(OUTPUT_DIR)/Makefile default-config-pass
+
+$(eval $(call omk_pass_template,default-config-pass,$$(LOCAL_BUILD_DIR),,always))
+
+default-config-pass-local:
+#      @echo Default config for $(RELATIVE_DIR)
+       @echo "# Config for $(RELATIVE_DIR)" >> "$(CONFIG_FILE)-default"
+       @$(foreach x, $(default_CONFIG), echo '$(x)' | \
+               sed -e 's/^[^=]*=x$$/#\0/' >> "$(CONFIG_FILE)-default" ; )
+
+
+omkize:
+       $(Q)if ! grep -q MAKERULES_DIR Makefile; then \
+          echo "Makefile is not OMK leaf makefile!" >&2; exit 1; \
+       fi
+       $(Q)for i in `find -L . -name Makefile.omk` ; do \
+          d=`dirname $${i}`; \
+          if ! test -f "$${d}/Makefile.rules" && ( ! test -f "$${d}/Makefile" || ! cmp --silent Makefile "$${d}/Makefile" ); then \
+             rm -f "$${d}/Makefile"; \
+             cp -v Makefile "$${d}/Makefile"; \
+          fi \
+       done
+ifeq ($(OMK_VERBOSE),1)                                      #OMK@include
+CPHEADER_FLAGS += -v
+LNHEADER_FLAGS += -v
+endif
+
+ifneq ($(LN_HEADERS),y)
+define cp_cmd
+( echo "  CP      $(1:$(OUTPUT_DIR)/%=%) -> $(2:$(OUTPUT_DIR)/%=%)"; cp $(CPHEADER_FLAGS) $(1) $(2) )
+endef
+else
+define cp_cmd
+( echo "  LN      $(1:$(OUTPUT_DIR)/%=%) -> $(2:$(OUTPUT_DIR)/%=%)"; [ -f $(1) ] && ln -sf $(LNHEADER_FLAGS) $(1) $(2) )
+endef
+endif
+
+# TODO: Check modification date of changed header files. If it is
+# newer that in source dir, show a warning.
+
+# Syntax: $(call include-pass-template,<include dir>,<keyword>)
+define include-pass-template
+include-pass-local: include-pass-local-$(2)
+include-pass-local-$(2): $$($(2)_GEN_HEADERS) $$(foreach f,$$(renamed_$(2)_GEN_HEADERS),$$(shell echo '$$(f)' | sed -e 's/^\(.*\)->.*$$$$/\1/'))
+       @$$(foreach f, $$($(2)_HEADERS), cmp --quiet $$(SOURCES_DIR)/$$(f) $(1)/$$(notdir $$(f)) \
+          || $$(call cp_cmd,$$(SOURCES_DIR)/$$(f),$(1)/$$(notdir $$(f))) || exit 1 ; )
+       @$$(foreach f, $$($(2)_GEN_HEADERS), cmp --quiet $$(f) $(1)/$$(notdir $$(f)) \
+          || $$(call cp_cmd,$$(LOCAL_BUILD_DIR)/$$(f),$(1)/$$(notdir $$(f))) || exit 1 ; ) # FIXME: Use correct build dir, then document it
+       @$$(foreach f, $$(nobase_$(2)_HEADERS), cmp --quiet $$(SOURCES_DIR)/$$(f) $(1)/$$(f) \
+          || ( mkdir -p $(1)/$$(dir $$(f)) && $$(call cp_cmd,$$(SOURCES_DIR)/$$(f),$(1)/$$(f)) ) || exit 1 ; )
+       @$$(foreach f, $$(renamed_$(2)_HEADERS), \
+          srcfname=`echo '$$(f)' | sed -e 's/^\(.*\)->.*$$$$/\1/'` ; destfname=`echo '$$(f)' | sed -e 's/^.*->\(.*\)$$$$/\1/'` ; \
+          cmp --quiet $$(SOURCES_DIR)/$$$${srcfname} $(1)/$$$${destfname} \
+          || ( mkdir -p `dirname $(1)/$$$${destfname}` && $$(call cp_cmd,$$(SOURCES_DIR)/$$$${srcfname},$(1)/$$$${destfname}) ) || exit 1 ; )
+       @$$(foreach f, $$(renamed_$(2)_GEN_HEADERS), \
+          srcfname=`echo '$$(f)' | sed -e 's/^\(.*\)->.*$$$$/\1/'` ; destfname=`echo '$$(f)' | sed -e 's/^.*->\(.*\)$$$$/\1/'` ; \
+          cmp --quiet $$$${srcfname} $(1)/$$$${destfname} \
+          || ( mkdir -p `dirname $(1)/$$$${destfname}` && $$(call cp_cmd,$$(LOCAL_BUILD_DIR)/$$$${srcfname},$(1)/$$$${destfname}) ) || exit 1 ; )
+endef
+
+# Local Variables:
+# mode:makefile
+# End:
+                                                             #OMK@linux
+# Hack to check RT-Linux rules
+#LINUX_DIR := /home/cvs/ocera/ocera-build/kernel/linux
+#RTL_DIR := /home/cvs/ocera/ocera-build/kernel/rtlinux
+#CONFIG_RTLINUX = y
+#OCERA_DIR := $(shell ( cd -L $(OUTPUT_DIR)/../../.. ; pwd -L ) )
+
+-include $(OUTPUT_DIR)/OCERA_TOP_DIR
+
+BUILD_DIR_NAME = _build
+COMPILED_DIR_NAME = _compiled
+ifndef GROUP_DIR_NAME
+GROUP_DIR_NAME = nogroup
+endif
+
+ifdef OCERA_DIR
+ifeq ($(wildcard $(OCERA_DIR)/ocera.mk),)
+$(warning "ocera.mk" file does not exist. Adapt Makefile.rules for standalone compilation)
+$(warning (comment out definition of OCERA_DIR line and optionally select RTL_DIR) )
+$(error or go to the ocera/ directory and do 'make' to generate the "ocera.mk" file first, please)
+endif
+include $(OCERA_DIR)/ocera.mk
+KERN_INCLUDE_DIR := $(OCERA_KERNEL_INCLUDES_DIR)
+KERN_LIB_DIR     := $(OCERA_KERNEL_LIBRARIES_DIR)
+KERN_MODULES_DIR := $(OCERA_MODULES_DIR)
+KERN_BUILD_DIR   := $(BUILD_DIR)/kern/$(GROUP_DIR_NAME)
+KERN_MODPOST_DIR := $(BUILD_DIR)/kern-modpost
+USER_INCLUDE_DIR := $(OCERA_USER_INCLUDES_DIR)
+USER_LIB_DIR     := $(OCERA_USER_LIBRARIES_DIR)
+USER_UTILS_DIR   := $(TARGET_DIR)/usr/bin
+USER_TESTS_DIR   := $(TARGET_DIR)/usr/bin
+USER_BIN_DIR     := $(TARGET_DIR)/usr/bin
+USER_BUILD_DIR   := $(BUILD_DIR)/user/$(GROUP_DIR_NAME)
+#LINUX_DIR        := $(OCERA_DIR)/kernel/linux
+#RTL_DIR          := $(OCERA_DIR)/kernel/rtlinux
+#CONFIG_FILE      := $(OCERA_DIR)/emdebsys/.config 
+ifneq ($(wildcard $(CONFIG_FILE)),)
+CONFIG_FILE_OK = y
+endif
+else # OCERA_DIR
+KERN_INCLUDE_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/include-kern
+KERN_LIB_DIR     := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/lib-kern
+KERN_MODULES_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/modules
+KERN_BUILD_DIR   := $(OUTPUT_DIR)/$(BUILD_DIR_NAME)/kern
+KERN_MODPOST_DIR := $(OUTPUT_DIR)/$(BUILD_DIR_NAME)/kern-modpost
+USER_INCLUDE_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/include
+USER_LIB_DIR     := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/lib
+USER_UTILS_DIR   := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin-utils
+USER_TESTS_DIR   := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin-tests
+USER_BIN_DIR     := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin
+USER_BUILD_DIR   := $(OUTPUT_DIR)/$(BUILD_DIR_NAME)/user
+
+ifndef LINUX_VERSION
+LINUX_VERSION=$(shell uname -r)
+endif
+ifndef LINUX_DIR
+LINUX_DIR=/lib/modules/$(LINUX_VERSION)/build
+endif
+endif # OCERA_DIR
+
+ifeq ($(BUILD_OS),)
+  # Check for target
+  ifeq ($(OS),Windows_NT)
+    BUILD_OS := win32
+  else
+    BUILD_OS := $(shell uname | tr '[A-Z]' '[a-z]' )
+    #$(warning BUILD_OS=$(BUILD_OS))
+  endif
+endif
+
+ifeq ($(TARGET_OS),)
+  TARGET_OS := $(BUILD_OS)
+endif
+
+LOCAL_BUILD_DIR  = $(USER_OBJS_DIR)
+
+# Assign default values to CFLAGS variable. If the variable is defined
+# earlier (i.g. in config.omk), it is not overriden here.
+CFLAGS ?= -O2 -Wall
+CXXFLAGS ?= -O2 -Wall
+
+
+CPPFLAGS  += -I $(USER_INCLUDE_DIR)
+
+LOADLIBES += -L$(USER_LIB_DIR) 
+
+LOADLIBES += $(lib_LOADLIBES:%=-l%)
+
+LIB_CPPFLAGS += $(CPPFLAGS)
+LIB_CFLAGS   += $(CFLAGS)
+
+ifeq ($(TARGET_OS),win32)
+  SOLIB_EXT = dll
+else
+  SOLIB_EXT = so
+  SOLIB_PICFLAGS += -fpic
+endif
+
+#vpath %.c $(SOURCES_DIR)
+#vpath %.cc $(SOURCES_DIR)
+#vpath %.cxx $(SOURCES_DIR)
+
+USER_OBJS_DIR = $(USER_BUILD_DIR)/$(RELATIVE_DIR)
+KERN_OBJS_DIR = $(KERN_BUILD_DIR)/$(RELATIVE_DIR)
+
+.PHONY: dep subdirs clean clean-custom cleandepend check-dir
+
+# Some support to serialize some targets for parallel make
+ifneq ($(OMK_SERIALIZE_INCLUDED),y)
+include-pass: check-dir
+library-pass: include-pass
+binary-pass: library-pass
+kernel-lib-pass: include-pass
+kernel-mod-pass: kernel-lib-pass
+kernel-modpost-pass: kernel-mod-pass
+kernel-pass: kernel-mod-pass kernel-modpost-pass
+
+override OMK_SERIALIZE_INCLUDED = y
+MAKEOVERRIDES := $(filter-out OMK_SERIALIZE_INCLUDED=n,$(MAKEOVERRIDES))
+endif
+
+# Checks for OMK tester
+ifdef OMK_TESTSROOT
+default-config-pass-check include-pass-check:
+library-pass-check binary-pass-check:
+       @[ -x "$(shell which $(CC))" ] || $(call canttest,Cannot find compiler: $(CC))
+endif
+
+#=====================================================================
+# User-space rules and templates to compile programs, libraries etc.
+
+ifdef USER_RULE_TEMPLATES
+
+USER_SOURCES2OBJS = .o/.c .o/.cc .o/.cxx .o/.S .o/.o
+
+USER_SOURCES2OBJSLO = .lo/.c .lo/.cc .lo/.cxx .lo/.S .lo/.lo
+
+#%.lo: %.c
+#      $(CC) -o $@ $(LCFLAGS) -c $<
+
+c_o_COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -DOMK_FOR_USER
+
+cc_o_COMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -DOMK_FOR_USER
+
+S_o_COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) $(ASFLAGS) -DOMK_FOR_USER
+
+idl_COMPILE = $(IDL_COMPILER)
+
+# Check GCC version for user build
+ifndef CC_MAJOR_VERSION
+CC_MAJOR_VERSION := $(shell $(CC) -dumpversion | sed -e 's/\([^.]\)\..*/\1/')
+endif
+# Prepare suitable define for dependency building
+ifeq ($(CC_MAJOR_VERSION),2)
+CC_DEPFLAGS = -Wp,-MD,"$@.d.tmp"
+else
+CC_DEPFLAGS = -MT $@ -MD -MP -MF "$@.d.tmp"
+endif
+
+
+# Syntax: $(call COMPILE_c_o_template,<source>,<target>,<additional c-flags>)
+define COMPILE_c_o_template
+$(2): $(1) $$(GEN_HEADERS)
+       @$(QUIET_CMD_ECHO) "  CC      $$@"
+       $(Q) if $$(c_o_COMPILE) $$(CC_DEPFLAGS) $(3) -o $$@ -c $$< ; \
+       then mv -f "$$@.d.tmp" "$$@.d" ; \
+       else rm -f "$$@.d.tmp" ; exit 1; \
+       fi
+endef
+
+
+# Syntax: $(call COMPILE_cc_o_template,<source>,<target>,<additional c-flags>)
+define COMPILE_cc_o_template
+$(2): $(1) $$(GEN_HEADERS)
+       @$(QUIET_CMD_ECHO) "  CXX     $$@"
+       $(Q) if $$(cc_o_COMPILE) $$(CC_DEPFLAGS) $(3) -o $$@ -c $$< ; \
+       then mv -f "$$@.d.tmp" "$$@.d" ; \
+       else rm -f "$$@.d.tmp" ; exit 1; \
+       fi
+endef
+
+
+# Syntax: $(call COMPILE_S_o_template,<source>,<target>,<additional c-flags>)
+define COMPILE_S_o_template
+$(2): $(1) $$(GEN_HEADERS)
+       @$(QUIET_CMD_ECHO) "  AS      $$@"
+       $(Q) if $$(S_o_COMPILE) -D__ASSEMBLY__ $$(CC_DEPFLAGS) $(3) -o $$@ -c $$< ; \
+       then mv -f "$$@.d.tmp" "$$@.d" ; \
+       else rm -f "$$@.d.tmp" ; exit 1; \
+       fi
+endef
+
+
+# Syntax: $(call CMETRIC_o_h_template,<object_file>,<target_header>)
+define CMETRIC_o_h_template
+$(2): $(1)
+       @$(QUIET_CMD_ECHO) "  CMETRIC $$@"
+       $(Q)if [ -n `dirname $$@` ] ; then \
+             if [ ! -e `dirname $$@` ] ; then \
+               mkdir -p `dirname $$@` ; fi ; fi
+       $(Q)echo >$$@ '/* Automatically generated from $$< */'
+       $(Q)echo >>$$@ '/* Conditionals to control compilation */'
+       $(Q)set -o pipefail ; $(NM) $$< \
+               | sed -n 's/^ *0*\(0[0-9A-Fa-f]*\) *A *_cmetric2cond_\([A-Za-z_0-9]*\) */#define \2 0x\1/p' \
+               | sort >>$$@
+       $(Q)echo >>$$@ '/* Defines from the values defined to symbols */'
+       $(Q)set -o pipefail ; $(NM) $$< \
+               | sed -n 's/^ *0*\(0[0-9A-Fa-f]*\) *A *_cmetric2def_\([A-Za-z_0-9]*\) */#define \2 0x\1/p' \
+               | sort >>$$@
+endef
+
+
+
+define COMPILE_idl_template
+$(2).c $(2)-stubs.c $(2)-skels.c $(2)-common.c $(2).h: $(1)
+       @$(QUIET_CMD_ECHO) "  IDL     $$@"
+       $(Q) $$(idl_COMPILE) $(1)
+endef
+
+
+# Syntax: $(call PROGRAM_template,<dir>,<executable-name>,<executable-suffix>,<linker-sript>)
+# FIXME: ???????? asi je tu blbej komentar
+define PROGRAM_template
+
+USER_IDLS  += $$($(1)_SERVER_IDL) $$($(1)_CLIENT_IDL) $$($(1)_IDL)
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_SERVER_IDL:%.idl=%-skels.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_SERVER_IDL:%.idl=%-common.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_CLIENT_IDL:%.idl=%-stubs.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_CLIENT_IDL:%.idl=%-common.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_IDL:%.idl=%.c))
+USER_GEN_SOURCES += $$($(1)_GEN_SOURCES)
+
+$(foreach x, $(USER_SOURCES2OBJS),
+$(1)_OBJS += $$(patsubst %$(notdir $(x)),%$(dir $(x)),$$(filter %$(notdir $(x)),\
+               $$($(1)_SOURCES) $$($(1)_GEN_SOURCES)))
+)
+$(1)_OBJS := $$(sort $$($(1)_OBJS:%/=%))
+
+USER_OBJS  += $$($(1)_OBJS)
+USER_SOURCES += $$($(1)_SOURCES)
+
+$(2)/$(1)$(3): $$($(1)_OBJS)
+       @$(QUIET_CMD_ECHO) "  LINK    $$@"
+       $(Q) $$(if $$(filter %.cc,$$($(1)_SOURCES:%.cxx=%.cc)),$$(CXX),$$(CC)) \
+         $$($(1)_OBJS) $$($(1)_LIBS:%=-l%) $$(LOADLIBES) $$(LDFLAGS) -Wl,-Map,$(USER_OBJS_DIR)/$(1).exe.map -o $$@
+       @echo "$(2)/$(1)$(3): \\" >$(USER_OBJS_DIR)/$(1).exe.d
+       @sed -n -e 's|^LOAD \(.*\)$$$$|  \1  \&|p' $(USER_OBJS_DIR)/$(1).exe.map|tr '&' '\134'  >>$(USER_OBJS_DIR)/$(1).exe.d
+       @echo >>$(USER_OBJS_DIR)/$(1).exe.d
+endef
+
+
+# Syntax: $(call LIBRARY_template,<library-name>)
+define LIBRARY_template
+
+USER_IDLS  += $$($(1)_SERVER_IDL) $$($(1)_CLIENT_IDL) $$($(1)_IDL)
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_SERVER_IDL:%.idl=%-skels.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_SERVER_IDL:%.idl=%-common.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_CLIENT_IDL:%.idl=%-stubs.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_CLIENT_IDL:%.idl=%-common.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_IDL:%.idl=%.c))
+USER_GEN_SOURCES += $$($(1)_GEN_SOURCES)
+
+$(foreach x, $(USER_SOURCES2OBJS),
+$(1)_OBJS += $$(patsubst %$(notdir $(x)),%$(dir $(x)),$$(filter %$(notdir $(x)),\
+               $$($(1)_SOURCES) $$($(1)_GEN_SOURCES)))
+)
+$(1)_OBJS := $$(sort $$($(1)_OBJS:%/=%))
+
+USER_OBJS  += $$($(1)_OBJS)
+USER_SOURCES += $$($(1)_SOURCES)
+
+$(USER_LIB_DIR)/lib$(1).a: $$($(1)_OBJS)
+       @$(QUIET_CMD_ECHO) "  AR      $$@"
+       $(Q) $(AR) rcs $$@ $$^
+endef
+
+
+# Syntax: $(call SOLIB_template,<library-name>)
+define SOLIB_template
+
+USER_IDLS  += $$($(1)_SERVER_IDL) $$($(1)_CLIENT_IDL) $$($(1)_IDL)
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_SERVER_IDL:%.idl=%-skels.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_SERVER_IDL:%.idl=%-common.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_CLIENT_IDL:%.idl=%-stubs.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_CLIENT_IDL:%.idl=%-common.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_IDL:%.idl=%.c))
+SOLIB_GEN_SOURCES += $$($(1)_GEN_SOURCES)
+
+$(foreach x, $(USER_SOURCES2OBJSLO),
+$(1)_OBJSLO += $$(patsubst %$(notdir $(x)),%$(dir $(x)),$$(filter %$(notdir $(x)),\
+               $$($(1)_SOURCES) $$($(1)_GEN_SOURCES)))
+)
+$(1)_OBJSLO := $$(sort $$($(1)_OBJSLO:%/=%))
+
+SOLIB_OBJS  += $$($(1)_OBJSLO)
+SOLIB_SOURCES += $$($(1)_SOURCES)
+
+$(USER_LIB_DIR)/lib$(1).$(SOLIB_EXT): $$($(1)_OBJSLO)
+       @$(QUIET_CMD_ECHO) "  LINK    $$@"
+       $(Q) $(CC) --shared -Xlinker -soname=lib$(1).$(SOLIB_EXT) -o $$@ $$^ $$(LOADLIBES) $$($(1)_LIBS:%=-l%)
+endef
+
+
+
+library-pass-local: $(addprefix $(USER_INCLUDE_DIR)/,$(cmetric_include_HEADERS)) \
+                   $(lib_LIBRARIES:%=$(USER_LIB_DIR)/lib%.a) $(shared_LIBRARIES:%=$(USER_LIB_DIR)/lib%.$(SOLIB_EXT))
+
+binary-pass-local: $(bin_PROGRAMS:%=$(USER_BIN_DIR)/%$(EXE_SUFFIX)) $(utils_PROGRAMS:%=$(USER_UTILS_DIR)/%$(EXE_SUFFIX)) $(test_PROGRAMS:%=$(USER_TESTS_DIR)/%$(EXE_SUFFIX))
+
+# Special rules for CMETRIC generated headers
+
+$(foreach cmetrh,$(cmetric_include_HEADERS),$(eval $(call COMPILE_c_o_template,\
+               $(SOURCES_DIR)/$($(basename $(notdir $(cmetrh)))_CMETRIC_SOURCES),\
+               $($(basename $(notdir $(cmetrh)))_CMETRIC_SOURCES:%.c=%.o),)))
+$(foreach cmetrh,$(cmetric_include_HEADERS),$(eval $(call CMETRIC_o_h_template,\
+               $($(basename $(notdir $(cmetrh)))_CMETRIC_SOURCES:%.c=%.o),\
+               $(addprefix $(USER_INCLUDE_DIR)/,$(cmetrh)))))
+
+GEN_HEADERS+=$(cmetric_include_HEADERS:%=$(USER_INCLUDE_DIR)/%)
+
+GEN_HEADERS+=$(filter %.h,$(USER_IDLS:%.idl=%.h))
+
+# Generate rules for compilation of programs and libraries
+
+$(foreach prog,$(utils_PROGRAMS),$(eval $(call PROGRAM_template,$(prog),$(USER_UTILS_DIR),$(EXE_SUFFIX))))
+
+$(foreach prog,$(test_PROGRAMS),$(eval $(call PROGRAM_template,$(prog),$(USER_TESTS_DIR),$(EXE_SUFFIX))))
+
+$(foreach prog,$(bin_PROGRAMS),$(eval $(call PROGRAM_template,$(prog),$(USER_BIN_DIR),$(EXE_SUFFIX))))
+
+$(foreach lib,$(lib_LIBRARIES),$(eval $(call LIBRARY_template,$(lib))))
+
+$(foreach lib,$(shared_LIBRARIES),$(eval $(call SOLIB_template,$(lib))))
+
+-include $(USER_OBJS_DIR)/*.d
+
+endif
+
+#=====================================================================
+# Kernel-space rules and templates to compile modules, libraries etc.
+
+ifdef KERN_RULE_TEMPLATES
+
+$(KERN_LIB_DIR)/kernel.mk: $(LINUX_DIR)/.config $(MAKERULES_DIR)/kernelcfg2mk
+       @$(QUIET_CMD_ECHO) "  KCFG2MK $$@"
+       $(Q) $(MAKERULES_DIR)/kernelcfg2mk $(LINUX_DIR) $(KERN_LIB_DIR)
+
+ifeq ($(CONFIG_RTLINUX),y)
+include $(RTL_DIR)/rtl.mk
+
+KERN_CC = $(CC)
+kern_GCCLIB_DIR=$(shell LANG=C LC_ALL=C LC_MESSAGES=C $(CC) -print-search-dirs | sed -n -e 's/^install: \(.*\)$$/\1/p' )
+INCLUDES := -I $(KERN_INCLUDE_DIR) $(INCLUDE) $(rtlinux_INCLUDES) $(kernel_INCLUDES)
+#-DEXPORT_NO_SYMBOLS
+c_o_kern_COMPILE = $(KERN_CC) -idirafter $(kern_GCCLIB_DIR)/include $(INCLUDES)  $(CFLAGS) -DOMK_FOR_KERNEL -DEXPORT_SYMTAB -nostdinc
+cc_o_kern_COMPILE = $(CXX) $(INCLUDES) $(CXXFLAGS) -DOMK_FOR_KERNEL -DEXPORT_SYMTAB
+KERN_EXE_SUFFIX := .o
+KERN_ARCH = $(ARCH)
+KERN_LD = $(LD)
+KERN_AR = $(AR)
+
+else # CONFIG_RTLINUX
+
+include $(KERN_LIB_DIR)/kernel.mk
+
+ifeq ($(LINUX_SRC),)
+LINUX_SRC = $(LINUX_DIR)
+endif
+kernel_INCLUDES += -I $(LINUX_DIR) -idirafter $(LINUX_SRC)/include/linux
+
+ifdef LINUX_CC
+KERN_CC = $(LINUX_CC)
+kern_GCCLIB_DIR=$(shell LANG=C LC_ALL=C LC_MESSAGES=C $(LINUX_CC) -print-search-dirs | sed -n -e 's/^install: \(.*\)$$/\1/p' )
+else
+KERN_CC = echo KERN_CC not defined - compilation skipped
+endif
+c_o_kern_COMPILE = $(KERN_CC) $(kernel_INCLUDES) -idirafter $(kern_GCCLIB_DIR)/include $(LINUX_CPPFLAGS) $(LINUX_CFLAGS) $(LINUX_CFLAGS_MODULE) -DOMK_FOR_KERNEL -DEXPORT_SYMTAB -nostdinc
+cc_o_kern_COMPILE = $(KERN_CC) $(kernel_INCLUDES) -idirafter $(kern_GCCLIB_DIR)/include $(LINUX_CPPFLAGS) $(LINUX_CFLAGS) $(LINUX_CFLAGS_MODULE) -DOMK_FOR_KERNEL -DEXPORT_SYMTAB
+S_o_kern_COMPILE = $(KERN_CC) $(kernel_INCLUDES) -idirafter $(kern_GCCLIB_DIR)/include $(LINUX_CPPFLAGS) $(LINUX_AFLAGS) $(LINUX_CFLAGS_MODULE) -DOMK_FOR_KERNEL -DEXPORT_SYMTAB
+KERN_EXE_SUFFIX := $(LINUX_MODULE_EXT)
+KERN_LDFLAGS = $(LINUX_LDFLAGS)
+ifdef LINUX_ARCH
+KERN_ARCH = $(LINUX_ARCH)
+else
+KERN_ARCH = echo KERN_ARCH not defined - skipped
+endif
+ifdef LINUX_LD
+KERN_LD = $(LINUX_LD)
+else
+KERN_LD = echo KERN_LD  not defined - skipped
+endif
+ifneq ($(LINUX_AR),)
+KERN_AR = $(LINUX_AR)
+else
+KERN_AR = $(AR)
+endif
+ifeq ($(LINUX_QUOTE_MODNAME),y)
+KERN_MQ=\"
+KERN_KBUILD_MODNAME=-D"KBUILD_MODNAME=((THIS_MODULE)?(THIS_MODULE)->name:NULL)"
+endif
+endif # CONFIG_RTLINUX
+
+KERN_LOADLIBES += -L$(KERN_LIB_DIR) 
+
+KERN_LOADLIBES += $(rtlinux_LOADLIBES:%=-l%)
+KERN_LOADLIBES += $(kernel_LOADLIBES:%=-l%)
+
+
+
+# Check GCC version for kernel part of build
+ifndef kern_CC_MAJOR_VERSION
+kern_CC_MAJOR_VERSION := $(shell $(KERN_CC) -dumpversion | sed -e 's/\([^.]\)\..*/\1/')
+endif
+# Prepare suitable define for dependency building
+ifeq ($(kern_CC_MAJOR_VERSION),2)
+kern_CC_DEPFLAGS = -Wp,-MD,"$@.d.tmp"
+else
+kern_CC_DEPFLAGS = -MT $@ -MD -MP -MF "$@.d.tmp"
+endif
+
+ifeq ($(KERN_EXE_SUFFIX),.ko)
+ifeq ($(wildcard $(LINUX_DIR)/scripts/mod/modpost),)
+KERN_MODPOST = $(LINUX_DIR)/scripts/modpost
+else
+KERN_MODPOST = $(LINUX_DIR)/scripts/mod/modpost
+endif
+KERN_MODULES_LINK_DIR = $(KERN_MODPOST_DIR)
+KERN_LINK_SUFFIX = .o
+else
+KERN_MODULES_LINK_DIR = $(KERN_MODULES_DIR)
+KERN_LINK_SUFFIX = $(KERN_EXE_SUFFIX)
+endif
+
+define COMPILE_c_o_kern_template
+
+$(2): $(1)
+       @$(QUIET_CMD_ECHO) "  CC [K]  $$@"
+       $(Q) if $$(c_o_kern_COMPILE) $$(kern_CC_DEPFLAGS) $(3) $(KERN_KBUILD_MODNAME) \
+       -D"KBUILD_BASENAME=$(KERN_MQ)$(notdir $(basename $(1)))$(KERN_MQ)" \
+       -o $$@ -c $$< ; \
+       then mv -f "$$@.d.tmp" "$$@.d" ; \
+       else rm -f "$$@.d.tmp" ; exit 1; \
+       fi
+endef
+
+
+
+define COMPILE_cc_o_kern_template
+
+$(2): $(1)
+       @$(QUIET_CMD_ECHO) "  CXX [K] $$@"
+       $(Q) if $$(cc_o_kern_COMPILE) $$(kern_CC_DEPFLAGS) $(3) $(KERN_KBUILD_MODNAME) \
+       -D"KBUILD_BASENAME=$(KERN_MQ)$(notdir $(basename $(1)))$(KERN_MQ)" \
+       -o $$@ -c $$< ; \
+       then mv -f "$$@.d.tmp" "$$@.d" ; \
+       else rm -f "$$@.d.tmp" ; exit 1; \
+       fi
+endef
+
+
+
+define COMPILE_S_o_kern_template
+
+$(2): $(1)
+       @$(QUIET_CMD_ECHO) "  AS [K]  $$@"
+       $(Q) if $$(S_o_kern_COMPILE) $$(kern_CC_DEPFLAGS) $(3) $(KERN_KBUILD_MODNAME) \
+       -D"KBUILD_BASENAME=$(KERN_MQ)$(notdir $(basename $(1)))$(KERN_MQ)" \
+       -o $$@ -c $$< ; \
+       then mv -f "$$@.d.tmp" "$$@.d" ; \
+       else rm -f "$$@.d.tmp" ; exit 1; \
+       fi
+endef
+
+
+
+define MODULE_kern_template
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.c=%.o))
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.cc=%.o))
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.cxx=%.o))
+$(1)_OBJS := $$(sort $$($(1)_OBJS))
+
+KERN_OBJS  += $$($(1)_OBJS)
+KERN_SOURCES += $$($(1)_SOURCES)
+
+# this is hack to build "__this_module" structure for 2.6.x kernels
+# modpost is used for that purpose now
+
+#$(1).mod.c:
+#      echo  "\
+#      #include <linux/version.h>@\
+#      #include <linux/module.h>@\
+#      #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,5))@\
+#      #include <linux/vermagic.h>@\
+#      #include <linux/compiler.h>@\
+#      @\
+#      MODULE_INFO(vermagic, VERMAGIC_STRING);@\
+#      @\
+#      #undef unix@\
+#      struct module __this_module@\
+#      __attribute__((section(\".gnu.linkonce.this_module\"))) = {@\
+#       .name = __stringify(KBUILD_MODNAME),@\
+#       .init = init_module,@\
+#      #ifdef CONFIG_MODULE_UNLOAD@\
+#       .exit = cleanup_module,@\
+#      #endif@\
+#      };@\
+#      #endif@\
+#      " | tr @ \\n >$$@ 
+
+
+#$(eval $(call COMPILE_c_o_kern_template,$(1).mod.c,$(1).mod.o,-DKBUILD_MODNAME=$(1)))
+
+$(2)/$(1)$(KERN_LINK_SUFFIX): $$($(1)_OBJS)
+       @$(QUIET_CMD_ECHO) "  LD [K]  $$@"
+       $(Q) $$(KERN_LD) $$(KERN_LDFLAGS) -r $$($(1)_OBJS) -L$$(kern_GCCLIB_DIR) $$($(1)_LIBS:%=-l%) $$(KERN_LOADLIBES) -Map $(KERN_OBJS_DIR)/$(1).mod.map -o $$@
+       @echo "$(2)/$(1)$(KERN_LINK_SUFFIX): \\" >$(KERN_OBJS_DIR)/$(1).mod.d
+       @sed -n -e 's/^LOAD \(.*\)$$$$/  \1  \\/p' $(KERN_OBJS_DIR)/$(1).mod.map  >>$(KERN_OBJS_DIR)/$(1).mod.d
+       @echo >>$(KERN_OBJS_DIR)/$(1).mod.d
+       @if [ "$(KERN_EXE_SUFFIX)" = ".ko" ] ; then \
+         echo $(1) >>$(KERN_MODPOST_DIR)/module-changes ; \
+         echo $(1) >>$(KERN_MODPOST_DIR)/$(1).mod.stamp ; \
+       fi
+
+endef
+
+
+
+define LIBRARY_kern_template
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.c=%.o))
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.cc=%.o))
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.cxx=%.o))
+$(1)_OBJS := $$(sort $$($(1)_OBJS))
+
+KERN_OBJS  += $$($(1)_OBJS)
+KERN_SOURCES += $$($(1)_SOURCES)
+
+$(KERN_LIB_DIR)/lib$(1).a: $$($(1)_OBJS)
+       @$(QUIET_CMD_ECHO) "  AR [K]  $$@"
+       $(Q) $(KERN_AR) rcs $$@ $$^
+endef
+
+
+ifdef LINUX_DIR
+
+kernel-lib-pass-local: $(kernel_LIBRARIES:%=$(KERN_LIB_DIR)/lib%.a)
+
+kernel-mod-pass-local: $(kernel_MODULES:%=$(KERN_MODULES_LINK_DIR)/%$(KERN_LINK_SUFFIX))
+
+$(foreach module,$(kernel_MODULES),$(eval $(call MODULE_kern_template,$(module),$(KERN_MODULES_LINK_DIR))))
+
+$(foreach lib,$(kernel_LIBRARIES),$(eval $(call LIBRARY_kern_template,$(lib))))
+
+endif
+
+
+ifeq ($(CONFIG_RTLINUX),y)
+
+kernel-mod-pass-local: $(rtlinux_MODULES:%=$(KERN_MODULES_LINK_DIR)/%$(KERN_LINK_SUFFIX))
+
+kernel-lib-pass-local: $(rtlinux_LIBRARIES:%=$(KERN_LIB_DIR)/lib%.a)
+
+$(foreach module,$(rtlinux_MODULES),$(eval $(call MODULE_kern_template,$(module),$(KERN_MODULES_LINK_DIR))))
+
+$(foreach lib,$(rtlinux_LIBRARIES),$(eval $(call LIBRARY_kern_template,$(lib))))
+
+endif
+
+ifeq ($(KERN_MODPOST_PASS),y)
+
+MODULES_LIST :=        $(wildcard *.mod.stamp)
+MODULES_LIST := $(MODULES_LIST:%.mod.stamp=%)
+
+define MODPOST_kern_template
+$(2) : $(1)$(KERN_LINK_SUFFIX) $(1).mod.c
+       @$(QUIET_CMD_ECHO) "  LD [M]  $$@"
+       $(Q) $$(cc_o_kern_COMPILE) -D"KBUILD_BASENAME=$(KERN_MQ)$(1)$(KERN_MQ)" \
+               -D"KBUILD_MODNAME=$(KERN_MQ)$(1)$(KERN_MQ)" \
+               -o $(1).mod.o -c $(1).mod.c
+       $(Q) $$(KERN_LD) $$(KERN_LDFLAGS) $(1)$(KERN_LINK_SUFFIX) $(1).mod.o -r -o $$@
+endef
+
+kernel-modpost-versions: $(wildcard $(LINUX_DIR)/Module.symvers)
+       @$(QUIET_CMD_ECHO) "  MODPOST    $(KERN_MODPOST_DIR)"
+       @echo  >$(KERN_MODPOST_DIR)/modpost-running
+       @rm -f $(KERN_MODPOST_DIR)/module-changes
+       $(Q) $(KERN_MODPOST) $(MODULES_LIST:%=%$(KERN_LINK_SUFFIX)) $(^:%=-i %)
+
+$(MODULES_LIST:%=%.mod.c) : kernel-modpost-versions
+
+kernel-modpost-pass-local: $(MODULES_LIST:%=$(KERN_MODULES_DIR)/%$(KERN_EXE_SUFFIX))
+       @rm -f $(KERN_MODPOST_DIR)/modpost-running
+
+$(foreach module,$(MODULES_LIST),$(eval $(call MODPOST_kern_template,$(module),$(module:%=$(KERN_MODULES_DIR)/%$(KERN_EXE_SUFFIX)))))
+
+endif
+
+-include $(KERN_OBJS_DIR)/*.d
+
+endif
+
+#=====================================================================
+
+# Kernel requires its own set of configuration header-files
+ifneq ($(kernel_LIBRARIES)$(rtlinux_LIBRARIES)$(kernel_MODULES)$(rtlinux_MODULES)$(kernel_HEADERS)$(rtlinux_HEADERS)$(kernel_HEADERS)$(rtlinux_HEADERS)$(nobase_kernel_HEADERS)$(nobase_rtlinux_HEADERS)$(renamed_kernel_HEADERS)$(renamed_rtlinux_HEADERS),)
+KERN_CONFIG_HEADERS_REQUIRED = y
+endif
+
+$(eval $(call omk_pass_template, kernel-lib-pass,$(KERN_OBJS_DIR),KERN_RULE_TEMPLATES=y,$(kernel_LIBRARIES)$(rtlinux_LIBRARIES)))
+$(eval $(call omk_pass_template, kernel-mod-pass,$(KERN_OBJS_DIR),KERN_RULE_TEMPLATES=y,$(kernel_MODULES)$(rtlinux_MODULES)))
+
+kernel-modpost-pass:
+       +@if [ -e "$(KERN_MODPOST_DIR)/module-changes" -o -e "$(KERN_MODPOST_DIR)/modpost-running" ] ; \
+       then \
+           $(MAKE) --no-print-directory -C $(KERN_MODPOST_DIR) \
+              -f $(SOURCES_DIR)/Makefile KERN_RULE_TEMPLATES=y KERN_MODPOST_PASS=y $(@:%=%-local) ; \
+       fi
+
+$(eval $(call omk_pass_template, library-pass,$(USER_OBJS_DIR),USER_RULE_TEMPLATES=y,$(lib_LIBRARIES)$(shared_LIBRARIES)))
+$(eval $(call omk_pass_template, binary-pass, $(USER_OBJS_DIR),USER_RULE_TEMPLATES=y,$(bin_PROGRAMS)$(utils_PROGRAMS)$(test_PROGRAMS)))
+
+$(eval $(call omk_pass_template,clean,$(USER_OBJS_DIR),,always))
+$(eval $(call omk_pass_template,install,$(USER_OBJS_DIR),,always))
+$(eval $(call omk_pass_template,include-pass,$(USER_OBJS_DIR),USER_RULE_TEMPLATES=y,always))
+
+check-dir::
+       @$(call mkdir_def,$(USER_BUILD_DIR))
+       @$(call mkdir_def,$(KERN_BUILD_DIR))
+       @$(call mkdir_def,$(USER_INCLUDE_DIR))
+       @$(call mkdir_def,$(KERN_INCLUDE_DIR))
+       @$(call mkdir_def,$(USER_LIB_DIR))
+       @$(call mkdir_def,$(KERN_LIB_DIR))
+       @$(call mkdir_def,$(USER_BIN_DIR))
+       @$(call mkdir_def,$(USER_UTILS_DIR))
+       @$(call mkdir_def,$(USER_TESTS_DIR))
+       @$(call mkdir_def,$(KERN_MODULES_DIR))
+       @$(call mkdir_def,$(KERN_MODPOST_DIR))
+
+install-local:                 # TODO
+
+$(eval $(call include-pass-template,$(USER_INCLUDE_DIR),include))
+$(eval $(call include-pass-template,$(KERN_INCLUDE_DIR),kernel))
+ifeq ($(CONFIG_RTLINUX),y)
+$(eval $(call include-pass-template,$(KERN_INCLUDE_DIR),rtlinux))
+endif
+
+
+ifdef USER_RULE_TEMPLATES
+
+# User-space static libraries and applications object files
+
+USER_SOURCES := $(sort $(USER_SOURCES))
+
+USER_GEN_SOURCES := $(sort $(USER_GEN_SOURCES))
+
+#$(warning USER_SOURCES = $(USER_SOURCES))
+
+$(foreach src,$(filter %.c,$(USER_SOURCES)),$(eval $(call COMPILE_c_o_template,$(SOURCES_DIR)/$(src),$(src:%.c=%.o),)))
+
+$(foreach src,$(filter %.cc,$(USER_SOURCES)),$(eval $(call COMPILE_cc_o_template,$(SOURCES_DIR)/$(src),$(src:%.cc=%.o),)))
+
+$(foreach src,$(filter %.cxx,$(USER_SOURCES)),$(eval $(call COMPILE_cc_o_template,$(SOURCES_DIR)/$(src),$(src:%.cxx=%.o),)))
+
+$(foreach src,$(filter %.S,$(USER_SOURCES)),$(eval $(call COMPILE_S_o_template,$(SOURCES_DIR)/$(src),$(src:%.S=%.o),)))
+
+$(foreach src,$(filter %.c,$(USER_GEN_SOURCES)),$(eval $(call COMPILE_c_o_template,$(src),$(src:%.c=%.o),)))
+
+# User-space shared libraries object files
+
+SOLIB_SOURCES := $(sort $(SOLIB_SOURCES))
+
+SOLIB_GEN_SOURCES := $(sort $(SOLIB_GEN_SOURCES))
+
+#$(warning SOLIB_SOURCES = $(SOLIB_SOURCES))
+#$(warning SOLIB_GEN_SOURCES = $(SOLIB_GEN_SOURCES))
+
+$(foreach src,$(filter %.c,$(SOLIB_SOURCES)),$(eval $(call COMPILE_c_o_template,$(SOURCES_DIR)/$(src),$(src:%.c=%.lo),$(SOLIB_PICFLAGS))))
+
+$(foreach src,$(filter %.cc,$(SOLIB_SOURCES)),$(eval $(call COMPILE_cc_o_template,$(SOURCES_DIR)/$(src),$(src:%.cc=%.lo),$(SOLIB_PICFLAGS))))
+
+$(foreach src,$(filter %.cxx,$(SOLIB_SOURCES)),$(eval $(call COMPILE_cc_o_template,$(SOURCES_DIR)/$(src),$(src:%.cxx=%.lo),$(SOLIB_PICFLAGS))))
+
+$(foreach src,$(filter %.S,$(SOLIB_SOURCES)),$(eval $(call COMPILE_S_o_template,$(SOURCES_DIR)/$(src),$(src:%.S=%.lo),$(SOLIB_PICFLAGS))))
+
+$(foreach src,$(filter %.c,$(SOLIB_GEN_SOURCES)),$(eval $(call COMPILE_c_o_template,$(src),$(src:%.c=%.lo),$(SOLIB_PICFLAGS))))
+
+# IDL compilation
+
+USER_IDLS := $(sort $(USER_IDLS))
+
+$(foreach src,$(filter %.idl,$(USER_IDLS)),$(eval $(call COMPILE_idl_template,$(SOURCES_DIR)/$(src),$(src:%.idl=%))))
+
+endif
+
+ifdef KERN_RULE_TEMPLATES
+
+KERN_SOURCES := $(sort $(KERN_SOURCES))
+
+#$(warning KERN_SOURCES = $(KERN_SOURCES))
+
+$(foreach src,$(filter %.c,$(KERN_SOURCES)),$(eval $(call COMPILE_c_o_kern_template,$(SOURCES_DIR)/$(src),$(src:%.c=%.o),)))
+
+$(foreach src,$(filter %.cc,$(KERN_SOURCES)),$(eval $(call COMPILE_cc_o_kern_template,$(SOURCES_DIR)/$(src),$(src:%.cc=%.o),)))
+
+$(foreach src,$(filter %.cxx,$(KERN_SOURCES)),$(eval $(call COMPILE_cc_o_kern_template,$(SOURCES_DIR)/$(src),$(src:%.cxx=%.o),)))
+
+$(foreach src,$(filter %.S,$(USER_SOURCES)),$(eval $(call COMPILE_S_o_kern_template,$(SOURCES_DIR)/$(src),$(src:%.S=%.o),)))
+endif
+
+clean-local: clean-custom
+       @echo Cleaning in $(KERN_OBJS_DIR) and $(USER_OBJS_DIR)
+       @rm -f $(KERN_OBJS_DIR)/*.o $(USER_OBJS_DIR)/*.[och] $(USER_OBJS_DIR)/*.lo\
+              $(KERN_OBJS_DIR)/*.d $(USER_OBJS_DIR)/*.d \
+              $(KERN_OBJS_DIR)/*.map $(USER_OBJS_DIR)/*.map \
+              $(KERN_OBJS_DIR)/*.mod.c \
+              $(kernel_MODULES:%=$(KERN_MODPOST_DIR)/%.*) \
+              $(LOCAL_CONFIG_H:%=$(KERN_OBJS_DIR)/%) \
+              $(LOCAL_CONFIG_H:%=$(USER_OBJS_DIR)/%)
+       @if [ -e $(KERN_LIB_DIR)/kernel.mk ] ; then \
+           touch -t 200001010101 $(KERN_LIB_DIR)/kernel.mk ; \
+       fi
+
+include-pass-submakes: extra-rules-subdirs
+
+# We must go to EXTRA_RULES_SUBDIRS beofre going to any other
+# directory, since the executables compiled in EXTRA_RULES_SUBDIRS
+# might be needed there.
+include-pass-this-dir $(foreach subdir,$(SUBDIRS),include-pass-$(subdir)-subdir): extra-rules-subdirs
+
+default: include-pass library-pass binary-pass
+ifndef OMIT_KERNEL_PASSES
+# Also make kernel passes if not disabled
+default: kernel-lib-pass kernel-pass
+endif
+
+# Local Variables:
+# mode:makefile
+# End:
+                                                             #OMK@config_h
+# Syntax: $(call BUILD_CONFIG_H_template,<stamp_dir>,<header_file_path>,<list_of_options_to_export>,<header_barrier>)
+define BUILD_CONFIG_H_template
+
+$(addprefix $(1)/,$(notdir $(addsuffix .stamp,$(2)))) : $(CONFIG_FILES)
+       @$(QUIET_CMD_ECHO) "  CONFGEN $$(@:%.stamp=%)"
+       @if [ ! -d `dirname $(2).tmp` ] ; then \
+               mkdir -p `dirname $(2).tmp` ; fi
+       @echo "/* Automatically generated from */" > "$(2).tmp"
+       @echo "/* config files: $$(^:$(OUTPUT_DIR)/%=%) */" >> "$(2).tmp"
+       $(if $(DOXYGEN),@echo "/** @file */" >> "$(2).tmp")
+       @echo "#ifndef $(4)" >> "$(2).tmp"
+       @echo "#define $(4)" >> "$(2).tmp"
+       @( $(foreach x, $(shell echo '$($(3))' | tr 'x\t ' 'x\n\n' | sed -e 's/^\([^ =]*\)\(=[^ ]\+\|\)$$/\1/' ), \
+               echo '$(x).$($(x))' ; ) echo ; ) | \
+               sed -e '/^[^.]*\.n$$$$/d' -e '/^[^.]*\.$$$$/d' -e 's/^\([^.]*\)\.[ym]$$$$/\1.1/' | \
+               sed -n -e 's/^\([^.]*\)\.\(.*\)$$$$/#define \1 \2/p' \
+                 >> "$(2).tmp"
+       @echo "#endif /*$(4)*/" >> "$(2).tmp"
+       @touch "$$@"
+       @if cmp --quiet "$(2).tmp" "$(2)" ; then rm "$(2).tmp"; \
+       else mv "$(2).tmp" "$(2)" ; \
+       echo "Updated configuration $(2)" ; fi
+
+endef
+
+ifdef LOCAL_CONFIG_H
+
+# This must be declared after the default cflags are assigned!
+# Override is used to override command line assignemnt.
+override CFLAGS += -I.
+$(eval $(call BUILD_CONFIG_H_template,$(USER_OBJS_DIR),$(USER_OBJS_DIR)/$(LOCAL_CONFIG_H),default_CONFIG,_LOCAL_CONFIG_H) )
+
+endif
+
+# Special rules for configuration exported headers
+
+#FIXME: The directory for headers should not be specified here.
+$(foreach confh,$(config_include_HEADERS),$(eval $(call BUILD_CONFIG_H_template,$(USER_OBJS_DIR),$(addprefix $(USER_INCLUDE_DIR)/,$(confh)),$(basename $(notdir $(confh)))_DEFINES,\
+_$(basename $(notdir $(confh)))_H \
+)))
+
+config_h_stamp_files = $(addprefix $(USER_OBJS_DIR)/,$(notdir $(addsuffix .stamp,$(config_include_HEADERS) $(LOCAL_CONFIG_H))))
+
+# Add some hooks to standard passes
+include-pass-local: $(config_h_stamp_files)
+
+ifneq ($(KERN_CONFIG_HEADERS_REQUIRED),)
+
+ifdef LOCAL_CONFIG_H
+$(eval $(call BUILD_CONFIG_H_template,$(KERN_OBJS_DIR),$(KERN_OBJS_DIR)/$(LOCAL_CONFIG_H),default_CONFIG,_LOCAL_CONFIG_H) )
+endif
+
+$(foreach confh,$(config_include_HEADERS),$(eval $(call BUILD_CONFIG_H_template,$(KERN_OBJS_DIR),$(addprefix $(KERN_INCLUDE_DIR)/,$(confh)),$(basename $(notdir $(confh)))_DEFINES,\
+_$(basename $(notdir $(confh)))_H \
+)))
+
+kern_config_h_stamp_files = $(addprefix $(KERN_OBJS_DIR)/,$(notdir $(addsuffix .stamp,$(config_include_HEADERS) $(LOCAL_CONFIG_H))))
+
+# Add some hooks to standard passes
+include-pass-local: $(kern_config_h_stamp_files)
+
+endif
+
+clean-local: clean-local-config-h
+
+clean-local-config-h:
+       @$(foreach confh,$(config_h_stamp_files) $(kern_config_h_stamp_files),\
+           if [ -e $(confh) ] ; then rm $(confh) ; fi ; \
+       )
+
+
+# Local Variables:
+# mode:makefile
+# End:
+                                                             #OMK@qt
+ifneq ($(QT_SUBDIRS),)
+
+.PHONY: qt-subpass clean-qt distclean-qt
+
+# Usage: $(call qt_makefile_template,<qt-subdir>)
+define qt_makefile_template
+$(SOURCES_DIR)/$(1)/Makefile: $(wildcard $(SOURCES_DIR)/$(1)/*.pro)
+       cd $(SOURCES_DIR)/$(1); $(QTDIR:%=%/bin/)qmake TOP_DIR=$(OUTPUT_DIR) \
+            RELATIVE_DIR=$(RELATIVE_PREFIX)$(1) $(QTDIR:%=QTDIR=%) CC=$(CC) \
+            CXX=$(CXX) LIBS+="-L$(USER_LIB_DIR)" INCLUDEPATH+="$(USER_INCLUDE_DIR)"
+endef
+$(foreach dir,$(QT_SUBDIRS), $(eval $(call qt_makefile_template,$(dir))))
+
+qt-subpass: $(foreach dir,$(QT_SUBDIRS), $(SOURCES_DIR)/$(dir)/Makefile)
+       $(foreach dir,$(QT_SUBDIRS),\
+               $(MAKE) SOURCES_DIR=$(SOURCES_DIR)/$(dir) \
+               RELATIVE_DIR=$(RELATIVE_PREFIX)$(dir) -C $(SOURCES_DIR)/$(dir) \
+               -f $(SOURCES_DIR)/$(dir)/Makefile || exit 1 ;)
+
+# Hook to binary pass
+binary-pass-submakes: qt-subpass
+
+# Hook to clean pass
+clean-local: clean-qt
+clean-qt:
+       +@$(foreach dir, $(QT_SUBDIRS), \
+               $(if $(wildcard $(SOURCES_DIR)/$(dir)/Makefile), \
+               @$(QUIET_CMD_ECHO) "  CLEAN   $(dir)"; \
+               $(MAKE) SOURCES_DIR=$(SOURCES_DIR)/$(dir) \
+               RELATIVE_DIR=$(RELATIVE_PREFIX)$(dir) -C $(SOURCES_DIR)/$(dir) \
+               -f $(SOURCES_DIR)/$(dir)/Makefile clean|| exit 1 ;))
+
+
+# Hook to distclean
+distclean: distclean-qt
+
+# TODO: Add distclean-qt-pass to handle QT_SUBDIRS in the whole
+# tree. This way we only distclean toplevel subdirs.
+distclean-qt:
+       +@$(foreach dir, $(QT_SUBDIRS), \
+               $(if $(wildcard $(SOURCES_DIR)/$(dir)/Makefile), \
+               @$(QUIET_CMD_ECHO) "  DISTCLEAN $(dir)"; \
+               $(MAKE) SOURCES_DIR=$(SOURCES_DIR)/$(dir) \
+               RELATIVE_DIR=$(RELATIVE_PREFIX)$(dir) -C $(SOURCES_DIR)/$(dir) \
+               -f $(SOURCES_DIR)/$(dir)/Makefile distclean|| exit 1 ;))
+endif
+
+# Local Variables:
+# mode:makefile
+# End:
+                                                             #OMK@sources-list
+# Rules that creates the list of files which are used during
+# compilation. The list reflects conditional compilation depending on
+# config.omk and other variables.
+
+SOURCES_LIST_FN=sources.txt
+ifndef SOURCES_LIST
+SOURCES_LIST_DIR:=$(RELATIVE_DIR)
+SOURCES_LIST:=$(OUTPUT_DIR)/$(SOURCES_LIST_DIR)/$(SOURCES_LIST_FN)
+SOURCES_LIST_D := $(LOCAL_BUILD_DIR)/$(SOURCES_LIST_FN).d
+export SOURCES_LIST SOURCES_LIST_DIR SOURCES_LIST_D
+endif
+
+ifeq ($(MAKECMDGOALS),sources-list)
+NEED_SOURCES_LIST=y
+endif
+ifeq ($(MAKECMDGOALS),TAGS)
+NEED_SOURCES_LIST=y
+endif
+ifeq ($(MAKECMDGOALS),tags)
+NEED_SOURCES_LIST=y
+endif
+
+ifeq ($(NEED_SOURCES_LIST),y) # avoid execution of find command bellow if it is not useful
+.PHONY: sources-list
+sources-list: $(SOURCES_LIST)
+
+$(SOURCES_LIST): $(CONFIG_FILES) $(shell find -name $(MAKEFILE_OMK))
+       @echo -n "" > "$(SOURCES_LIST).tmp"
+       @echo -n "" > "$(SOURCES_LIST_D).tmp"
+       @$(MAKE) --no-print-directory sources-list-pass
+       @echo "# Automatically generated list of files in '$(RELATIVE_DIR)' that are used during OMK compilation" > "$(SOURCES_LIST).tmp2"
+       @cat "$(SOURCES_LIST).tmp"|sort|uniq >> "$(SOURCES_LIST).tmp2"
+       @rm "$(SOURCES_LIST).tmp"
+       @mv "$(SOURCES_LIST).tmp2" "$(SOURCES_LIST)"
+       @echo "$(SOURCES_LIST): \\" > "$(SOURCES_LIST_D).tmp2"
+       @cat "$(SOURCES_LIST_D).tmp"|grep -v "$(SOURCES_LIST_D).tmp"|sort|uniq|\
+               sed -e 's/$$/\\/' >> "$(SOURCES_LIST_D).tmp2"
+       @rm "$(SOURCES_LIST_D).tmp"
+       @mv "$(SOURCES_LIST_D).tmp2" "$(SOURCES_LIST_D)"
+endif
+
+$(eval $(call omk_pass_template,sources-list-pass,$$(LOCAL_BUILD_DIR),,always))
+
+sources-list-pass-local:
+       @$(foreach m,$(MAKEFILE_LIST),echo '  $(m)' >> "$(SOURCES_LIST_D).tmp";)
+       @$(foreach h,$(include_HEADERS) $(nobase_include_HEADERS) $(kernel_HEADERS),\
+         echo "$(RELATIVE_DIR:$(SOURCES_LIST_DIR)/%=%)/$(h)" >> "$(SOURCES_LIST).tmp";)
+       @$(foreach ch,$(config_include_HEADERS), \
+         echo "$(USER_INCLUDE_DIR:$(OUTPUT_DIR)/$(addsuffix /,$(SOURCES_LIST_DIR))%=%)/$(ch)" >> "$(SOURCES_LIST).tmp";)
+       @$(foreach h,$(renamed_include_HEADERS),echo '$(h)'|sed -e 's/\(.*\)->.*/$(RELATIVE_DIR:$(SOURCES_LIST_DIR)/%=%)\1/' >> "$(SOURCES_LIST).tmp";)
+       @$(foreach bin,$(lib_LIBRARIES) $(shared_LIBRARIES) $(bin_PROGRAMS) $(test_PROGRAMS) $(utils_PROGRAMS) \
+         $(kernel_LIBRARIES) $(rtlinux_LIBRARIES) $(kernel_MODULES),\
+         $(foreach src,$(filter-out %.o,$($(bin)_SOURCES)),echo "$(addsuffix /,$(RELATIVE_DIR:$(SOURCES_LIST_DIR)/%=%))$(src)" >> "$(SOURCES_LIST).tmp";))
+
+############ TAGS ###########
+
+ifeq ($(MAKECMDGOALS),TAGS)
+ETAGS=etags
+TAGS_CMD = $(ETAGS)
+TAGS: $(SOURCES_LIST)
+       @$(MAKE) --no-print-directory do-tags
+endif
+ifeq ($(MAKECMDGOALS),tags) 
+CTAGS=ctags -N
+TAGS_CMD = $(CTAGS)
+tags: $(SOURCES_LIST)
+       @$(MAKE) --no-print-directory do-tags
+endif
+export TAGS_CMD
+
+ifeq ($(MAKECMDGOALS),do-tags)
+.PHONY: do-tags
+do-tags: $(shell sed -e '/^\#/d' $(SOURCES_LIST))
+       @$(QUIET_CMD_ECHO) "  TAGS    $(SOURCES_LIST_FN)"
+       $(Q)$(TAGS_CMD) $^
+endif
+
+############ CSCOPE ###########
+
+cscope: $(SOURCES_LIST)
+       @$(QUIET_CMD_ECHO) "  CSCOPE  < $(SOURCES_LIST_FN)"
+       $(Q)sed -e '/^#/d' $(SOURCES_LIST)|cscope -b -i-
+#FIXME: see doc to -i in cscope(1)
+
+# Local Variables:
+# mode:makefile
+# End:
diff --git a/src/forb/forb-idl/ORBit-idl-2.0.pc.in b/src/forb/forb-idl/ORBit-idl-2.0.pc.in
new file mode 100644 (file)
index 0000000..219e7d2
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+backendsdir=@libdir@/orbit-2.0/idl-backends
+
+Name: ORBit-idl-2.0
+Description: ORBit-2.0 IDL Compiler Backend Interface
+Version: @ORBIT_VERSION@
+Requires: libIDL-2.0
+Libs: 
+Cflags: -I${includedir}/orbit-2.0/orbit-idl
diff --git a/src/forb/forb-idl/config.h b/src/forb/forb-idl/config.h
new file mode 100644 (file)
index 0000000..922426b
--- /dev/null
@@ -0,0 +1,202 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define if HTTP connections are available */
+/* #undef ENABLE_HTTP */
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/nameser.h> header file. */
+#define HAVE_ARPA_NAMESER_H 1
+
+/* Define to 1 if you have the `basename' function. */
+#define HAVE_BASENAME 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Define to 1 if you have the <endian.h> header file. */
+#define HAVE_ENDIAN_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if getaddrinfo() is available */
+#define HAVE_GETADDRINFO 1
+
+/* Define if getnameinfo() is available */
+#define HAVE_GETNAMEINFO 1
+
+/* Define if inet_pton() is available */
+#define HAVE_INET_PTON 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+/* #undef HAVE_LIBNSL */
+
+/* Define to 1 if you have the `resolv' library (-lresolv). */
+/* #undef HAVE_LIBRESOLV */
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
+
+/* Define to 1 if you have the <linux/socket.h> header file. */
+#define HAVE_LINUX_SOCKET_H 1
+
+/* Define to 1 if you have the <machine/endian.h> header file. */
+/* #undef HAVE_MACHINE_ENDIAN_H */
+
+/* Define to 1 if you have the <machine/types.h> header file. */
+/* #undef HAVE_MACHINE_TYPES_H */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define to 1 if you have the `poll' function. */
+#define HAVE_POLL 1
+
+/* Define to 1 if you have the <resolv.h> header file. */
+#define HAVE_RESOLV_H 1
+
+/* Define if sockaddr has sa_len member */
+/* #undef HAVE_SOCKADDR_SA_LEN */
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define to 1 if you have the <sys/endian.h> header file. */
+/* #undef HAVE_SYS_ENDIAN_H */
+
+/* Define to 1 if you have the <sys/isa_defs.h> header file. */
+/* #undef HAVE_SYS_ISA_DEFS_H */
+
+/* Define to 1 if you have the <sys/machine.h> header file. */
+/* #undef HAVE_SYS_MACHINE_H */
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+/* #undef HAVE_SYS_SOCKIO_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define to 1 if you have the <sys/utime.h> header file. */
+/* #undef HAVE_SYS_UTIME_H */
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the <wchar.h> header file. */
+#define HAVE_WCHAR_H 1
+
+/* Define to 1 if you have the <wcstr.h> header file. */
+/* #undef HAVE_WCSTR_H */
+
+/* Define to 1 if you have the <wctype.h> header file. */
+#define HAVE_WCTYPE_H 1
+
+/* Define to 1 if you have the <winsock2.h> header file. */
+/* #undef HAVE_WINSOCK2_H */
+
+/* defined if purify is enabled */
+/* #undef ORBIT_PURIFY */
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "http://bugzilla.gnome.org/enter_bug.cgi?product=ORBit2"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "ORBit2"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "ORBit2 2.14.13"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "ORBit2"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "2.14.13"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+   significant byte first (like Motorola and SPARC, unlike Intel and VAX). */
+#if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+#elif ! defined __LITTLE_ENDIAN__
+/* # undef WORDS_BIGENDIAN */
+#endif
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define socklen_t to be of type size_t */
+/* #undef socklen_t */
diff --git a/src/forb/forb-idl/forb-idl-backend.c b/src/forb/forb-idl/forb-idl-backend.c
new file mode 100644 (file)
index 0000000..ecd3730
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * orbit-idl-backend.c:
+ *
+ * Copyright (C) 2002 Sun Microsystems, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *     Mark McLoughlin <mark@skynet.ie>
+ */
+
+#include "config.h"
+
+#include "forb-idl-backend.h"
+#include "forb-idl2.h"
+
+#include <glib.h>
+#include <gmodule.h>
+
+#if 0
+static GSList *
+prepend_from_env_var (GSList     *paths,
+                     const char *env_var)
+{
+       char  *val;
+       char **strv;
+       int    i;
+
+       if (!(val = getenv ("GNOME2_PATH")))
+               return paths;
+
+       strv = g_strsplit (val, ";", -1);
+       for (i = 0; strv [i]; i++)
+               paths = g_slist_prepend (
+                               paths, g_strconcat (strv [i], "/lib/forb-2.0/idl-backends", NULL));
+
+       g_strfreev (strv);
+
+       return paths;
+}
+
+static ForbIDLBackendFunc
+load_language_backend (const char *path,
+                      const char *language)
+{
+       ForbIDLBackendFunc  retval = NULL;
+       GModule             *module;
+       char                *modname;
+       char                *modpath;
+
+       modname = g_strconcat ("forb-idl-backend-", language, NULL);
+       modpath = g_module_build_path (path, modname);
+       g_free (modname);
+
+       if (!(module = g_module_open (modpath, G_MODULE_BIND_LAZY))) {
+               g_free (modpath);
+               return NULL;
+       }
+
+       if (!g_module_symbol (module, "forb_idl_backend_func", (gpointer *) &retval))
+               g_warning ("backend %s has no \"forb_idl_backend_func\" defined", modpath);
+
+       g_free (modpath);
+
+       return retval;
+}
+
+gboolean
+forb_idl_backend_output (OIDL_Run_Info *rinfo,
+                         IDL_tree       tree)
+{
+       ForbIDLBackendFunc     func = NULL;
+       ForbIDLBackendContext  context;
+       GSList                 *paths = NULL;
+       GSList                 *l;
+
+       paths = prepend_from_env_var (paths, "GNOME2_PATH");
+       paths = prepend_from_env_var (paths, "FORB_BACKENDS_PATH");
+
+       paths = g_slist_prepend (paths, g_strdup (FORB_BACKENDS_DIR));
+
+       if (rinfo->backend_directory)
+               paths = g_slist_prepend (paths, g_strdup (rinfo->backend_directory));
+
+       for (l = paths; l; l = l->next) {
+               func = load_language_backend (l->data, rinfo->output_language);
+
+               g_free (l->data);
+
+               if (func)
+                       break;
+       }
+
+       g_slist_free (paths);
+
+       if (!func) {
+               g_warning("idl-compiler backend not found.");
+               return FALSE;
+       }
+
+       context.tree      = tree;
+       context.filename  = rinfo->input_filename;
+       context.do_stubs  = (rinfo->enabled_passes & OUTPUT_STUBS ? 1 : 0);
+       context.do_skels  = (rinfo->enabled_passes & OUTPUT_SKELS ? 1 : 0);
+       context.do_common = (rinfo->enabled_passes & OUTPUT_COMMON ? 1 : 0);
+
+       return func (&context);
+}
+#endif
diff --git a/src/forb/forb-idl/forb-idl-backend.h b/src/forb/forb-idl/forb-idl-backend.h
new file mode 100644 (file)
index 0000000..4460e94
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * forb-idl-backend.h:
+ *
+ * Copyright (C) 2002 Sun Microsystems, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *     Mark McLoughlin <mark@skynet.ie>
+ */
+
+#ifndef __FORB_IDL_BACKEND_H__
+#define __FORB_IDL_BACKEND_H__
+
+#include <glib.h>
+#include <libIDL/IDL.h>
+
+G_BEGIN_DECLS
+
+typedef struct {
+       IDL_tree  tree;
+       char     *filename;
+
+       guint     do_stubs  : 1;
+       guint     do_skels  : 1;
+       guint     do_common : 1;
+} ForbIDLBackendContext;
+
+/* Define a function with this signature and named "forb_idl_backend_func"
+ * in the module.
+ *
+ * The module should be named libforb-idl-backend-$(language).so. $(language)
+ * is defined with the --lang idl-compiler command line option.
+ *
+ * Modules are searched for in the following order:
+ *   1. The directory specified by the --backenddir option.
+ *   2. %(prefix)/lib/forb-2.0/idl-backends/, where $(prefix) is the prefix
+ *      Forb2 was installed in.
+ *   3. For each $(path) in the $FORB_BACKENDS_PATH environment variable,
+ *      the module is searched for in $(path)/lib/forb-2.0/idl-backends/
+ *   4. For each $(path) in the $GNOME2_PATH environment variable,
+ *      the module is searched for in $(path)/lib/forb-2.0/idl-backends/
+ */
+
+typedef gboolean (*ForbIDLBackendFunc) (ForbIDLBackendContext *context);
+
+G_END_DECLS
+
+#endif
diff --git a/src/forb/forb-idl/forb-idl-c-backend.c b/src/forb/forb-idl/forb-idl-c-backend.c
new file mode 100644 (file)
index 0000000..9c574c1
--- /dev/null
@@ -0,0 +1,166 @@
+#include "config.h"
+
+#include "forb-idl-c-backend.h"
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <glib/gstdio.h>
+
+static FILE *out_for_pass(const char *input_filename, int pass, 
+                         OIDL_Run_Info *rinfo);
+
+gboolean
+forb_idl_output_c (IDL_tree       tree,
+                   OIDL_Run_Info *rinfo)
+{
+  int i;
+  char *ctmp;
+  OIDL_C_Info ci;
+
+  ci.base_name = g_path_get_basename(rinfo->input_filename);
+  ctmp = strrchr(ci.base_name, '.');
+  g_assert(ctmp);
+  *ctmp = '\0';
+
+  ci.c_base_name = g_strdup(ci.base_name);
+  if(!isalpha((guchar)ci.c_base_name[0]))
+    ci.c_base_name[0] = '_';
+  for(i = 0; ci.c_base_name[i]; i++) {
+    if(!isalnum((guchar)ci.c_base_name[i])) ci.c_base_name[i] = '_';
+  }
+
+  ci.ext_dcls = g_string_new(NULL);
+
+  ci.do_impl_hack = 1;
+  ci.do_skel_defs = rinfo->do_skel_defs;
+  for(i = 0; i < OUTPUT_NUM_PASSES; i++) {
+    if( (1 << i) & rinfo->enabled_passes) {
+      ci.fh = out_for_pass(rinfo->input_filename, 1 << i, rinfo);
+      
+      switch(1 << i) {
+      case OUTPUT_STUBS:
+       forb_idl_output_c_stubs(tree, rinfo, &ci);
+       break;
+      case OUTPUT_SKELS:
+       forb_idl_output_c_skeletons(tree, rinfo, &ci);
+       break;
+      case OUTPUT_COMMON:
+       forb_idl_output_c_common(tree, rinfo, &ci);
+       break;
+      case OUTPUT_HEADERS:
+       forb_idl_output_c_headers(tree, rinfo, &ci);
+       break;
+      case OUTPUT_SKELIMPL:
+       forb_idl_output_c_skelimpl(tree, rinfo, &ci);
+       break;
+      case OUTPUT_IMODULE:
+       forb_idl_output_c_imodule(tree, rinfo, &ci);
+       break;
+      case OUTPUT_DEPS:
+       forb_idl_output_c_deps(tree, rinfo, &ci);
+       break;
+      }
+      fclose(ci.fh);
+    }
+  }
+  g_string_free(ci.ext_dcls,TRUE);
+
+  return TRUE;
+}
+
+char *
+forb_idl_c_filename_for_pass (const char *input_filename, 
+                               int pass)
+{
+       char *filename;
+       char *basename;
+       char *dot;
+       const char *tack_on = NULL;
+  
+       basename = g_path_get_basename (input_filename);
+       dot = strrchr (basename, '.');
+       if (dot != NULL)
+               *dot = '\0';
+
+       switch (pass) {
+       case OUTPUT_STUBS:
+               tack_on = "-stubs.c";
+               break;
+       case OUTPUT_SKELS:
+               tack_on = "-skels.c";
+               break;
+       case OUTPUT_COMMON:
+               tack_on = "-common.c";
+               break;
+       case OUTPUT_HEADERS:
+               tack_on = ".h";
+               break;
+       case OUTPUT_SKELIMPL:
+               tack_on = "-skelimpl.c";
+               break;
+       case OUTPUT_IMODULE:
+               tack_on = "-imodule.c";
+               break;
+       default:
+               g_error("Unknown output pass");
+               break;
+       }
+
+       filename = g_strconcat (basename, tack_on, NULL);
+       g_free (basename);
+
+       return filename;
+}
+
+static FILE *
+out_for_pass (const char    *input_filename,
+             int            pass,
+             OIDL_Run_Info *rinfo)
+{
+       FILE *fp;
+       char *output_filename;
+       gchar *output_full_path = NULL;
+
+
+        if ((strlen(rinfo->output_directory)) && (!g_file_test (rinfo->output_directory, G_FILE_TEST_IS_DIR))) {
+               g_error ("ouput directory '%s' does not exist",
+                        rinfo->output_directory);
+               return NULL;
+       }
+       
+       if (pass == OUTPUT_DEPS) {
+               if (!g_file_test (".deps", G_FILE_TEST_IS_DIR)) {
+                       if (g_mkdir (".deps", 0775) < 0) {
+                               g_warning ("failed to create '.deps' directory '%s'",
+                                          g_strerror (errno));
+                               return NULL;
+                       }
+               }
+               
+               if (rinfo->deps_file)
+                       fp =  g_fopen (rinfo->deps_file, "w");
+               else
+                       fp = NULL;
+
+               if (fp == NULL) 
+                       g_warning ("failed to open '%s': %s\n",
+                                  rinfo->deps_file, g_strerror (errno));
+               
+       } else {
+               output_filename = forb_idl_c_filename_for_pass (input_filename, pass);
+               output_full_path = g_build_path (G_DIR_SEPARATOR_S, rinfo->output_directory, output_filename, NULL);
+               g_free (output_filename);
+
+               fp = g_fopen (output_full_path, "w+");
+               if (fp == NULL)
+                       g_error ("failed to fopen '%s': %s\n", output_full_path, g_strerror(errno));
+
+               g_free (output_full_path);
+       }
+
+       return fp;
+}
diff --git a/src/forb/forb-idl/forb-idl-c-backend.h b/src/forb/forb-idl/forb-idl-c-backend.h
new file mode 100644 (file)
index 0000000..b1a3870
--- /dev/null
@@ -0,0 +1,86 @@
+#ifndef FORB_IDL_C_BACKEND_H
+#define FORB_IDL_C_BACKEND_H
+
+#include "forb-idl2.h"
+#include <stdbool.h>
+
+#define OIDL_C_WARNING "/*\n * This file was generated by forb-idl - DO NOT EDIT!\n */\n\n"
+
+typedef struct {
+       char     *base_name;
+       char     *c_base_name;
+       FILE     *fh;
+       GString  *ext_dcls;
+       gboolean  do_impl_hack;
+       gboolean  do_skel_defs;
+} OIDL_C_Info;
+
+enum forb_ser {
+  DESERIALIZE,
+  SERIALIZE
+};
+
+void
+forb_cbe_write_ser_var(FILE *of, IDL_tree ts, IDL_tree name, bool use_name,
+                      char *var_prefix, enum forb_ser serialization);
+
+
+gboolean  forb_idl_output_c       (IDL_tree       tree,
+                                   OIDL_Run_Info *rinfo);
+void  forb_idl_output_c_headers   (IDL_tree       tree,
+                                   OIDL_Run_Info *rinfo,
+                                   OIDL_C_Info   *ci);
+void  forb_idl_output_c_stubs     (IDL_tree       tree,
+                                   OIDL_Run_Info *rinfo,
+                                   OIDL_C_Info   *ci);
+void  forb_idl_output_c_skeletons (IDL_tree       tree,
+                                   OIDL_Run_Info *rinfo,
+                                   OIDL_C_Info   *ci);
+void  forb_idl_output_c_common    (IDL_tree       tree,
+                                   OIDL_Run_Info *rinfo,
+                                   OIDL_C_Info   *ci);
+void  forb_idl_output_c_skelimpl  (IDL_tree       tree,
+                                   OIDL_Run_Info *rinfo,
+                                   OIDL_C_Info   *ci);
+void  forb_idl_output_c_imodule   (IDL_tree       tree,
+                                   OIDL_Run_Info *rinfo,
+                                   OIDL_C_Info   *ci);
+void  forb_idl_output_c_deps      (IDL_tree       tree,
+                                   OIDL_Run_Info *rinfo,
+                                   OIDL_C_Info   *ci);
+
+void forb_output_typecode (OIDL_C_Info *ci, IDL_tree ts);
+
+char *forb_idl_c_filename_for_pass (const char *input_filename, int pass);
+
+/* utils */
+char    *forb_cbe_get_typespec_str     (IDL_tree    tree);
+void     forb_cbe_write_typespec       (FILE       *of,
+                                        IDL_tree    tree);
+void     forb_cbe_write_param_typespec (FILE       *of,
+                                        IDL_tree    tree);
+void     forb_cbe_op_write_proto       (FILE       *of,
+                                        IDL_tree    op,
+                                        const char *nom_prefix,
+                                        gboolean    for_epv);
+IDL_tree forb_cbe_get_typespec         (IDL_tree    tree);
+void     forb_cbe_write_const          (FILE       *of,
+                                        IDL_tree    tree);
+gboolean forb_cbe_type_is_fixed_length (IDL_tree    ts);
+gboolean forb_cbe_type_is_builtin      (IDL_tree    tree);
+void     forb_cbe_id_define_hack       (FILE       *fh,
+                                        const char *def_prefix,
+                                        const char *def_name,
+                                        const char *def_value);
+void     forb_cbe_id_cond_hack         (FILE       *fh,
+                                        const char *def_prefix,
+                                        const char *def_name,
+                                        const char *def_value);
+char    *forb_cbe_get_typecode_name    (IDL_tree    tree);
+void     forb_cbe_flatten_args         (IDL_tree    tree,
+                                        FILE       *of,
+                                        const char *name);
+void     forb_cbe_unflatten_args       (IDL_tree    tree,
+                                        FILE       *of,
+                                        const char *name);
+#endif
diff --git a/src/forb/forb-idl/forb-idl-c-common.c b/src/forb/forb-idl/forb-idl-c-common.c
new file mode 100644 (file)
index 0000000..b2e4ec7
--- /dev/null
@@ -0,0 +1,896 @@
+#include "config.h"
+
+#include "forb-idl-c-backend.h"
+
+#include <string.h>
+
+typedef struct {
+       IDL_tree tree;
+       GSList  *methods; /* IDLN_OP_DCLs */
+} Interface;
+
+typedef struct {
+       FILE     *of;
+       IDL_tree cur_node; /* Current Interface */
+       char     *cur_id;
+       guint    parents;
+} CCSmallInterfaceTraverseInfo;
+
+/* TypeCodes */
+
+/* static void cc_output_typecodes (IDL_tree     tree, */
+/*                              OIDL_C_Info *ci); */
+
+/* static void */
+/* cc_typecode_prep_sequence (IDL_tree     tree, */
+/*                        OIDL_C_Info *ci) */
+/* { */
+/*     IDL_tree  seq_type; */
+/*     IDL_tree  fake_seq_type = NULL; */
+/*     char     *type_str; */
+/*     char     *seq_type_str; */
+
+/*     seq_type = forb_cbe_get_typespec (IDL_TYPE_SEQUENCE (tree).simple_type_spec); */
+
+/*     if (IDL_NODE_TYPE (seq_type) != IDLN_INTERFACE) */
+/*             seq_type_str = forb_cbe_get_typespec_str (seq_type); */
+/*     else { */
+/*             seq_type_str = g_strdup ("CORBA_Object"); */
+/*             fake_seq_type = IDL_type_object_new (); */
+/*     } */
+
+/*     type_str = forb_cbe_get_typespec_str (IDL_TYPE_SEQUENCE (tree).simple_type_spec); */
+
+/*     if (strcmp (type_str, seq_type_str)) { */
+/*             IDL_tree fake_seq; */
+
+/*             fake_seq = IDL_type_sequence_new ( */
+/*                             fake_seq_type ? fake_seq_type : seq_type, */
+/*                             NULL); */
+/*             IDL_NODE_UP (fake_seq) = IDL_NODE_UP (tree); */
+
+/*             cc_output_typecodes (fake_seq, ci); */
+
+/*             IDL_TYPE_SEQUENCE (fake_seq).simple_type_spec = NULL; */
+/*             IDL_tree_free (fake_seq); */
+/*     } */
+
+/*     if (fake_seq_type) */
+/*             IDL_tree_free (fake_seq_type); */
+
+/*     g_free (type_str); */
+/*     g_free (seq_type_str); */
+/* } */
+/* static gboolean */
+/* cc_output_tc_walker (IDL_tree_func_data *tfd, */
+/*                  OIDL_C_Info        *ci) */
+/* { */
+/*     IDL_tree tree = tfd->tree; */
+
+/*     switch(IDL_NODE_TYPE (tree)) { */
+/*     case IDLN_CONST_DCL: */
+/*     case IDLN_ATTR_DCL: */
+/*     case IDLN_OP_DCL: */
+/*             return FALSE; /\* dont recurse into these *\/ */
+
+/*     case IDLN_TYPE_SEQUENCE: */
+/*             if (!tfd->step) { */
+/*                     cc_typecode_prep_sequence (tree, ci); */
+/*                     break; */
+/*             } */
+/*             /\* drop through *\/ */
+
+/*     case IDLN_INTERFACE: */
+/*     case IDLN_EXCEPT_DCL: */
+/*     case IDLN_TYPE_STRUCT: */
+/*     case IDLN_TYPE_UNION: */
+/*     case IDLN_TYPE_DCL: */
+/*     case IDLN_TYPE_ENUM: */
+/*     case IDLN_TYPE_FIXED: */
+/*             if (tfd->step) */
+/*                     forb_output_typecode (ci, tree); */
+/*             break; */
+/*     default: */
+/*             break; */
+/*     } */
+
+/*     return TRUE; /\* continue walking *\/ */
+/* } */
+
+/* static void */
+/* cc_output_typecodes (IDL_tree     tree, */
+/*                  OIDL_C_Info *ci) */
+/* { */
+/*     IDL_tree_walk2 (tree, NULL, IDL_WalkF_TypespecOnly, */
+/*                     (IDL_tree_func) cc_output_tc_walker, */
+/*                     (IDL_tree_func) cc_output_tc_walker, */
+/*                     ci); */
+/* } */
+
+/* serialization */
+
+static void
+cc_output_ser_struct(OIDL_C_Info *ci,
+                    IDL_tree     s)
+{
+       IDL_tree cur, curmem;
+       char *id;
+       id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_TYPE_STRUCT(s).ident), "_", 0);
+       
+       fprintf(ci->fh, "CORBA_boolean %s_serialize(FORB_CDR_Codec *codec, const %s *ptr)\n", id, id);
+       fprintf(ci->fh, "{\n");
+       for(cur = IDL_TYPE_STRUCT(s).member_list; cur; cur = IDL_LIST(cur).next) {
+               for(curmem = IDL_MEMBER(IDL_LIST(cur).data).dcls; curmem; curmem = IDL_LIST(curmem).next) {
+                       forb_cbe_write_ser_var(
+                               ci->fh,
+                               IDL_MEMBER(IDL_LIST(cur).data).type_spec,
+                               IDL_LIST(curmem).data,
+                               true,
+                               "ptr->",
+                               SERIALIZE);
+               }
+       }
+       
+       fprintf(ci->fh, "  return CORBA_TRUE;\n"
+                       "ser_exception:\n"
+                       "  return CORBA_FALSE;\n"
+                       "}\n\n");
+
+       fprintf(ci->fh, "CORBA_boolean %s_deserialize(FORB_CDR_Codec *codec, %s *ptr)\n", id, id);
+       fprintf(ci->fh, "{\n");
+       for(cur = IDL_TYPE_STRUCT(s).member_list; cur; cur = IDL_LIST(cur).next) {
+               for(curmem = IDL_MEMBER(IDL_LIST(cur).data).dcls; curmem; curmem = IDL_LIST(curmem).next) {
+                       forb_cbe_write_ser_var(
+                               ci->fh,
+                               IDL_MEMBER(IDL_LIST(cur).data).type_spec,
+                               IDL_LIST(curmem).data,
+                               true,
+                               "ptr->",
+                               DESERIALIZE);
+               }
+       }
+       
+       fprintf(ci->fh, "  return CORBA_TRUE;\n"
+                       "ser_exception:\n"
+                       "  return CORBA_FALSE;\n"
+                       "}\n\n");
+
+
+       g_free(id);
+}
+
+static void
+cc_output_ser_seqence(OIDL_C_Info *ci,
+                     IDL_tree     s)
+{
+        //IDL_tree cur, curmem;
+       char *id, *type;
+       IDL_tree tts;
+       gboolean fake_if;
+       id = forb_cbe_get_typespec_str(s);
+       type = forb_cbe_get_typespec_str(IDL_TYPE_SEQUENCE(s).simple_type_spec);
+/*{
+       CORBA_boolean r;                                                
+       int i;                                                  
+       r = CORBA_unsigned_long_serialize(codec, (val)->_length); 
+       for (i=0; i<(val)->_length && r; i++)                   
+               r = type ## _serialize(codec, &((val)->_buffer[i])); 
+}*/
+       tts = forb_cbe_get_typespec(IDL_TYPE_SEQUENCE(s).simple_type_spec);
+       fake_if = (IDL_NODE_TYPE(tts) == IDLN_INTERFACE);
+       if (fake_if) {
+               /* Header file already contains defines for CORBA_sequence_Object_[de]serialize */
+               return;
+       }
+
+       fprintf(ci->fh, "CORBA_boolean %s_serialize(FORB_CDR_Codec *codec, const %s *seq)\n", id, id);
+       fprintf(ci->fh, "{\n"
+                       "  int i;\n"
+                       "  CORBA_boolean ok;\n"
+                       "  ok = CORBA_unsigned_long_serialize(codec, &seq->_length);\n"
+                       "  for (i = 0; i<seq->_length && ok; i++)\n");
+       fprintf(ci->fh, "    ok = %s_serialize(codec, &(seq->_buffer[i]));\n", type);
+       
+       fprintf(ci->fh, "  return ok;\n"
+                       "}\n\n");
+
+       fprintf(ci->fh, "CORBA_boolean %s_deserialize(FORB_CDR_Codec *codec, %s *seq)\n", id, id);
+       fprintf(ci->fh, "{\n"
+                       "  CORBA_unsigned_long i;\n"
+                       "  CORBA_boolean ok;\n"
+                       "  ok = CORBA_unsigned_long_deserialize(codec, &i);\n"
+                       "  if (ok) {\n"
+                       "    ok = forb_sequence_alloc_buf(seq, i);\n"
+                       "    seq->_length = i;\n"
+                       "    CORBA_sequence_set_release(seq, CORBA_TRUE);\n"
+                       "  }\n"
+                       "  for (i = 0; i<seq->_length && ok; i++)\n");
+       fprintf(ci->fh, "    ok = %s_deserialize(codec, &(seq->_buffer[i]));\n", type);
+       
+       fprintf(ci->fh, "  return ok;\n"
+                       "}\n\n");
+
+       g_free(id);
+       g_free(type);
+}
+
+static void
+cc_output_ser_typedef_array(OIDL_C_Info *ci,
+                      IDL_tree     tree)
+{
+       IDL_tree cur;
+       char *id;
+       
+       for(cur = IDL_TYPE_DCL(tree).dcls; cur; cur = IDL_LIST(cur).next) {
+               if (IDL_NODE_TYPE(IDL_LIST(cur).data) == IDLN_TYPE_ARRAY) {
+                       id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_TYPE_ARRAY(IDL_LIST(cur).data).ident), "_", 0);
+                       fprintf(ci->fh, "CORBA_boolean %s_serialize(FORB_CDR_Codec *codec, const %s array)\n", id, id);
+                       fprintf(ci->fh, "{\n");
+                       forb_cbe_write_ser_var(
+                               ci->fh,
+                               IDL_TYPE_DCL(tree).type_spec,
+                               IDL_LIST(cur).data,
+                               false,
+                               "array",
+                               SERIALIZE);
+                       fprintf(ci->fh, "  return CORBA_TRUE;\n"
+                               "ser_exception:\n"
+                               "  return CORBA_FALSE;\n"
+                               "}\n\n");
+
+                       fprintf(ci->fh, "CORBA_boolean %s_deserialize(FORB_CDR_Codec *codec, %s array)\n", id, id);
+                       fprintf(ci->fh, "{\n");
+                       forb_cbe_write_ser_var(
+                               ci->fh,
+                               IDL_TYPE_DCL(tree).type_spec,
+                               IDL_LIST(cur).data,
+                               false,
+                               "array",
+                               DESERIALIZE);
+                       fprintf(ci->fh, "  return CORBA_TRUE;\n"
+                               "ser_exception:\n"
+                               "  return CORBA_FALSE;\n"
+                               "}\n\n");
+                       g_free(id);
+               }
+       }
+}
+
+void
+forb_output_serialization (OIDL_C_Info *ci,
+                          IDL_tree     node)
+{
+       switch (IDL_NODE_TYPE (node)) {
+       case IDLN_TYPE_DCL:
+               cc_output_ser_typedef_array(ci, node);
+               break;
+       case IDLN_TYPE_STRUCT:
+               cc_output_ser_struct(ci, node);
+               break;
+       case IDLN_TYPE_UNION:
+       case IDLN_TYPE_ENUM:
+       case IDLN_EXCEPT_DCL:
+       case IDLN_INTERFACE:
+               break;
+       case IDLN_TYPE_SEQUENCE:
+               cc_output_ser_seqence(ci, node);
+               break;
+       default:
+               g_error ("You can't produce a serialization for a %s", 
+                        IDL_tree_type_names[IDL_NODE_TYPE (node)]);
+       }
+
+/*     tci.ts            = node; */
+/*     tci.structname    = forb_generate_tcstruct_name (node); */
+/*     tci.substructname = NULL; */
+/*     tci.array_gen_ctr = 0; */
+
+/*     cbe_tc_generate (ci, &tci); */
+
+/*     g_free (tci.structname); */
+}
+
+static gboolean
+cc_output_serialization_walker (IDL_tree_func_data *tfd,
+                               OIDL_C_Info        *ci)
+{
+       IDL_tree tree = tfd->tree;
+
+       switch(IDL_NODE_TYPE (tree)) {
+       case IDLN_CONST_DCL:
+       case IDLN_ATTR_DCL:
+       case IDLN_OP_DCL:
+               return FALSE; /* dont recurse into these */
+
+       case IDLN_TYPE_SEQUENCE:
+/*             if (!tfd->step) { */
+/*                     cc_typecode_prep_sequence (tree, ci); */
+/*                     break; */
+/*             } */
+               /* drop through */
+
+       case IDLN_INTERFACE:
+       case IDLN_EXCEPT_DCL:
+       case IDLN_TYPE_STRUCT:
+       case IDLN_TYPE_UNION:
+       case IDLN_TYPE_DCL:
+       case IDLN_TYPE_ENUM:
+       case IDLN_TYPE_FIXED:
+               if (tfd->step)
+                       forb_output_serialization (ci, tree);
+               break;
+       case IDLN_SRCFILE:
+               if (!IDL_SRCFILE(tree).isTop) {
+                       return FALSE;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return TRUE; /* continue walking */
+}
+
+static void
+cc_output_serialization (IDL_tree     tree,
+                        OIDL_C_Info *ci)
+{
+       IDL_tree_walk2 (tree, NULL, IDL_WalkF_TypespecOnly,
+                       (IDL_tree_func) cc_output_serialization_walker,
+                       (IDL_tree_func) cc_output_serialization_walker,
+                       ci);
+}
+
+
+
+/* class ids */
+
+/* static void */
+/* cc_output_class_id (IDL_tree       tree, */
+/*                        OIDL_Run_Info *rinfo, */
+/*                        OIDL_C_Info   *ci) */
+/* { */
+/*     char *iface_id; */
+
+/*     iface_id = IDL_ns_ident_to_qstring ( */
+/*             IDL_IDENT_TO_NS (IDL_INTERFACE (tree).ident), "_", 0); */
+
+/*     fprintf (ci->fh, "\n#ifndef FORB_IDL_C_IMODULE_%s\n",ci->c_base_name); */
+/*     fprintf (ci->fh, "CORBA_unsigned_long %s__classid = 0;\n", iface_id); */
+/*     fprintf (ci->fh, "#endif\n"); */
+
+/*     g_free (iface_id); */
+/* } */
+
+/* static void */
+/* cc_output_class_ids (IDL_tree       tree, */
+/*                  OIDL_Run_Info *rinfo, */
+/*                  OIDL_C_Info   *ci) */
+/* { */
+/*     if (!tree || (tree->declspec & IDLF_DECLSPEC_PIDL)) */
+/*             return; */
+
+/*     switch (IDL_NODE_TYPE (tree)) { */
+/*     case IDLN_MODULE: */
+/*             cc_output_class_ids (IDL_MODULE (tree).definition_list, rinfo, ci); */
+/*             break; */
+/*     case IDLN_LIST: { */
+/*             IDL_tree node; */
+
+/*             for (node = tree; node; node = IDL_LIST (node).next) */
+/*                     cc_output_class_ids (IDL_LIST (node).data, rinfo, ci); */
+/*             break; */
+/*             } */
+/*     case IDLN_INTERFACE: */
+/*             cc_output_class_id (tree, rinfo, ci); */
+/*             break; */
+/*     default: */
+/*             break; */
+/*     } */
+/* } */
+
+/* IInterfaces */
+
+/* static void */
+/* cc_output_iargs (FILE *of, const char *method, IDL_tree tree) */
+/* { */
+/*     IDL_tree sub; */
+/*     int      arg_count = 0; */
+
+/*     /\* Build a list of IArgs *\/ */
+/*     for (sub = IDL_OP_DCL (tree).parameter_dcls; sub; */
+/*          sub = IDL_LIST (sub).next) { */
+/*             IDL_tree parm; */
+/*             char    *tc; */
+
+/*             if (!arg_count) */
+/*                     fprintf (of, "static Forb_IArg %s__arginfo [] = {\n", method); */
+
+/*             parm = IDL_LIST(sub).data; */
+
+/*             fprintf (of, "\t{ "); */
+
+/*             /\* TypeCode tc *\/ */
+/*             tc = forb_cbe_get_typecode_name ( */
+/*                     IDL_PARAM_DCL (parm).param_type_spec); */
+/*             if (!tc) { */
+/*                     g_warning ("Can't get typecode"); */
+/*                     tc = g_strdup ("NULL /\* no typecode *\/"); */
+/*             } */
+/*             fprintf (of, "%s, ", tc); */
+
+/*             /\* IArgFlag flags *\/ */
+/*             switch (IDL_PARAM_DCL (parm).attr) { */
+/*             case IDL_PARAM_IN: */
+/*                     fprintf (of, " Forb_I_ARG_IN "); */
+/*                     break; */
+/*             case IDL_PARAM_OUT: */
+/*                     fprintf (of, " Forb_I_ARG_OUT "); */
+/*                     break; */
+/*             case IDL_PARAM_INOUT: */
+/*                     fprintf (of, " Forb_I_ARG_INOUT "); */
+/*                     break; */
+/*             } */
+
+/*             if (forb_cbe_type_is_fixed_length ( */
+/*                     IDL_PARAM_DCL (parm).param_type_spec)) */
+/*                     fprintf (of, "| Forb_I_COMMON_FIXED_SIZE"); */
+
+/*             else if (IDL_PARAM_DCL(parm).attr == IDL_PARAM_OUT) { */
+
+/*                     IDL_tree ts = forb_cbe_get_typespec ( */
+/*                             IDL_PARAM_DCL (parm).param_type_spec); */
+
+/*                     switch(IDL_NODE_TYPE (ts)) { */
+/*                     case IDLN_TYPE_STRUCT: */
+/*                     case IDLN_TYPE_UNION: */
+/*                     case IDLN_TYPE_ARRAY: */
+/* /\*                         fprintf (of, "| FORB_I_ARG_FIXED");*\/ */
+/*                             break; */
+/*                     default: */
+/*                             break; */
+/*                     }; */
+/*             } */
+
+/*             fprintf (of, ", "); */
+
+/*             /\* string name *\/ */
+/*             fprintf (of, "(char *)\"%s\"", IDL_IDENT (IDL_PARAM_DCL ( */
+/*                     IDL_LIST (sub).data).simple_declarator).str); */
+
+/*             fprintf (of, " }%s\n", IDL_LIST (sub).next ? "," : ""); */
+
+/*             g_free (tc); */
+/*             arg_count++; */
+/*     } */
+
+/*     if (arg_count) */
+/*             fprintf (of, "};\n"); */
+/* } */
+
+/* static void */
+/* cc_output_contexts (FILE *of, const char *method, IDL_tree tree) */
+/* { */
+/*     /\* Build a list of contest names *\/ */
+/*     if (IDL_OP_DCL (tree).context_expr) { */
+/*             IDL_tree curitem; */
+
+/*             fprintf (of, "/\* Exceptions *\/\n"); */
+/*             fprintf (of, "static CORBA_string %s__contextinfo [] = {\n", */
+/*                      method); */
+
+/*             for (curitem = IDL_OP_DCL (tree).context_expr; curitem; */
+/*                  curitem = IDL_LIST (curitem).next) { */
+/*                     fprintf (of, "\"%s\"%c",  */
+/*                              IDL_STRING (IDL_LIST (curitem).data).value, */
+/*                              IDL_LIST (curitem).next ? ',' : ' '); */
+/*             } */
+
+/*             fprintf (of, "};\n"); */
+/*     } */
+/* } */
+
+/* static void */
+/* cc_output_exceptinfo (FILE *of, const char *method, IDL_tree tree) */
+/* { */
+/*     /\* Build a list of exception typecodes *\/ */
+/*     if (IDL_OP_DCL (tree).raises_expr) { */
+/*             IDL_tree curitem; */
+
+/*             fprintf (of, "/\* Exceptions *\/\n"); */
+/*             fprintf (of, "static CORBA_TypeCode %s__exceptinfo [] = {\n", */
+/*                      method); */
+               
+/*             for (curitem = IDL_OP_DCL (tree).raises_expr; curitem; */
+/*                  curitem = IDL_LIST(curitem).next) { */
+/*                     char *type_id; */
+/*                     IDL_tree curnode = IDL_LIST(curitem).data; */
+                       
+/*                     type_id = forb_cbe_get_typecode_name (curnode); */
+/*                     fprintf (of, "\t%s,\n", type_id); */
+/*                     g_free (type_id); */
+/*             } */
+/*             fprintf (of, "\tNULL\n};\n"); */
+/*     } */
+/* } */
+
+/* static void */
+/* cc_output_method_bits (IDL_tree tree, const char *id, OIDL_C_Info *ci) */
+/* { */
+/*     FILE *of = ci->fh; */
+/*     char *fullname; */
+
+/*     fullname = g_strconcat (id, "_", IDL_IDENT ( */
+/*             IDL_OP_DCL (tree).ident).str, NULL); */
+
+/*     cc_output_iargs (of, fullname, tree); */
+
+/*     cc_output_contexts (of, fullname, tree); */
+
+/*     cc_output_exceptinfo (of, fullname, tree); */
+
+/*     g_free (fullname); */
+/* } */
+
+/* static void */
+/* cc_output_method (FILE *of, IDL_tree tree, const char *id) */
+/* { */
+/*     int arg_count; */
+/*     int except_count; */
+/*     int context_count; */
+/*     const char *method; */
+/*     char       *fullname; */
+
+/*     fullname = g_strconcat (id, "_", IDL_IDENT ( */
+/*             IDL_OP_DCL (tree).ident).str, NULL); */
+
+/*     arg_count = IDL_list_length (IDL_OP_DCL (tree).parameter_dcls); */
+/*     except_count = IDL_list_length (IDL_OP_DCL (tree).raises_expr); */
+/*     context_count = IDL_list_length (IDL_OP_DCL (tree).context_expr); */
+       
+/*     fprintf (of, "\t{\n"); */
+
+/*     /\* IArgs arguments *\/ */
+/*     if (arg_count) */
+/*             fprintf (of, "\t\t{ %d, %d, %s__arginfo, FALSE },\n", */
+/*                      arg_count, arg_count, fullname); */
+/*     else */
+/*             fprintf (of, "\t\t{ 0, 0, NULL, FALSE },\n"); */
+
+/*     /\* IContexts contexts *\/ */
+/*     if (context_count) */
+/*             fprintf (of, "\t\t{ %d, %d, %s__contextinfo, FALSE },\n", */
+/*                      context_count, context_count, fullname); */
+/*     else */
+/*             fprintf (of, "\t\t{ 0, 0, NULL, FALSE },\n"); */
+               
+/*     /\* ITypes exceptions *\/ */
+/*     if (IDL_OP_DCL (tree).raises_expr) */
+/*             fprintf (of, "\t\t{ %d, %d, %s__exceptinfo, FALSE },\n", */
+/*                      except_count, except_count, fullname); */
+/*     else */
+/*             fprintf (of, "\t\t{ 0, 0, NULL, FALSE },\n"); */
+
+/*     /\* TypeCode ret *\/ */
+/*     if (IDL_OP_DCL (tree).op_type_spec) { */
+/*             char *type_id; */
+
+/*             type_id = forb_cbe_get_typespec_str ( */
+/*                     IDL_OP_DCL (tree).op_type_spec); */
+/*             fprintf (of, "\t\tTC_%s, ", type_id); */
+/*             g_free (type_id); */
+/*     } else */
+/*             fprintf (of, "TC_void, "); */
+
+/*     /\* string name, long name_len *\/ */
+/*     method = IDL_IDENT (IDL_OP_DCL (tree).ident).str; */
+/*     fprintf (of, "(char *)\"%s\", %d,\n", method, strlen (method)); */
+
+/*     /\* IMethodFlags flags *\/ */
+/*     fprintf (of, "\t\t0"); */
+
+/*     if (IDL_OP_DCL(tree).f_oneway) */
+/*             fprintf (of, " | Forb_I_METHOD_1_WAY"); */
+
+/* /\* FIXME: re-scan for no_out *\/ */
+/* /\* if (no_out) */
+/*     fprintf (of, " | Forb_I_METHOD_NO_OUT");*\/ */
+
+/*     if (IDL_OP_DCL (tree).op_type_spec && */
+/*         forb_cbe_type_is_fixed_length ( */
+/*                 IDL_OP_DCL (tree).op_type_spec)) */
+/*             fprintf (of, "| Forb_I_COMMON_FIXED_SIZE"); */
+
+/*     if (IDL_OP_DCL(tree).context_expr) */
+/*             fprintf (of, "| Forb_I_METHOD_HAS_CONTEXT"); */
+
+/*     fprintf (of, "\n}\n"); */
+
+/*     g_free (fullname); */
+/* } */
+
+/* static void */
+/* cc_output_base_itypes(IDL_tree node, CCSmallInterfaceTraverseInfo *iti) */
+/* { */
+/*     if (iti->cur_node == node) */
+/*             return; */
+
+/*     fprintf (iti->of, "(char *)\"%s\",\n", */
+/*              IDL_IDENT(IDL_INTERFACE(node).ident).repo_id); */
+
+/*     iti->parents++; */
+/* } */
+
+/* static void */
+/* cc_output_itypes (GSList *list, OIDL_C_Info *ci) */
+/* { */
+/*     GSList *l; */
+/*     FILE   *of = ci->fh; */
+
+/*     for (l = list; l; l = l->next) { */
+/*             CCSmallInterfaceTraverseInfo iti; */
+/*             Interface *i = l->data; */
+/*             char      *id; */
+/*             GSList    *m; */
+
+/*             id = IDL_ns_ident_to_qstring (IDL_IDENT_TO_NS ( */
+/*                     IDL_INTERFACE (i->tree).ident), "_", 0); */
+
+/*             for (m = i->methods; m; m = m->next) */
+/*                     cc_output_method_bits (m->data, id, ci); */
+
+/*             if (i->methods) { */
+/*                     fprintf (of, "\n#ifdef FORB_IDL_C_IMODULE_%s\n", */
+/*                              ci->c_base_name); */
+/*                     fprintf (of, "static\n"); */
+/*                     fprintf (of, "#endif\n"); */
+
+/*                     fprintf (of, "Forb_IMethod %s__imethods [] = {\n", id); */
+
+/*                     if (!(m = i->methods)) */
+/*                             fprintf (of, "{{0}}"); */
+
+/*                     else for (; m; m = m->next) { */
+/*                             cc_output_method (of, m->data, id); */
+/*                             if (m->next) */
+/*                                     fprintf(of, ", "); */
+/*                     } */
+
+/*                     fprintf (of, "};\n\n"); */
+/*             } */
+
+/*             fprintf (of, "static CORBA_string %s__base_itypes[] = {\n", id); */
+
+/*             iti.of = of; */
+/*             iti.cur_node = i->tree; */
+/*             iti.cur_id = id; */
+/*             iti.parents = 0; */
+/*             IDL_tree_traverse_parents(i->tree, (GFunc)cc_output_base_itypes, &iti); */
+
+/*             fprintf (of, "(char *)\"IDL:omg.org/CORBA/Object:1.0\"\n};"); */
+
+/*             fprintf (of, "\n#ifdef FORB_IDL_C_IMODULE_%s\n", */
+/*                      ci->c_base_name); */
+/*             fprintf (of, "static\n"); */
+/*             fprintf (of, "#endif\n"); */
+/*             fprintf (of, "Forb_IInterface %s__iinterface = {\n", id); */
+/*             fprintf (of, "TC_%s,", id); */
+/*             fprintf (of, "{%d, %d, %s__imethods, FALSE},\n", */
+/*                      g_slist_length (i->methods), */
+/*                      g_slist_length (i->methods), id); */
+
+/*             fprintf (of, "{%d, %d, %s__base_itypes, FALSE}\n",  */
+/*                      iti.parents + 1, iti.parents + 1, id); */
+
+/*             fprintf (of, "};\n\n"); */
+
+/*             g_free (id); */
+/*     } */
+
+/*     for (l = list; l; l = l->next) { */
+/*             g_slist_free (((Interface *)l->data)->methods); */
+/*             g_free (l->data); */
+/*     } */
+
+/*     g_slist_free (list); */
+/* } */
+
+/* static GSList * */
+/* cc_build_interfaces (GSList *list, IDL_tree tree) */
+/* { */
+/*     if (!tree) */
+/*             return list; */
+
+/*     switch (IDL_NODE_TYPE (tree)) { */
+/*     case IDLN_MODULE: */
+/*             list = cc_build_interfaces ( */
+/*                     list, IDL_MODULE (tree).definition_list); */
+/*             break; */
+/*     case IDLN_LIST: { */
+/*             IDL_tree sub; */
+/*             for (sub = tree; sub; sub = IDL_LIST (sub).next) */
+/*                     list = cc_build_interfaces ( */
+/*                             list, IDL_LIST (sub).data); */
+/*             break; */
+/*     } */
+/*     case IDLN_ATTR_DCL: { */
+/*             IDL_tree curitem; */
+      
+/*             for (curitem = IDL_ATTR_DCL (tree).simple_declarations; */
+/*                  curitem; curitem = IDL_LIST (curitem).next) { */
+/*                     OIDL_Attr_Info *ai = IDL_LIST (curitem).data->data; */
+       
+/*                     list = cc_build_interfaces (list, ai->op1); */
+/*                     if (ai->op2) */
+/*                             list = cc_build_interfaces (list, ai->op2); */
+/*             } */
+/*             break; */
+/*     } */
+/*     case IDLN_INTERFACE: { */
+/*             Interface *i = g_new0 (Interface, 1); */
+
+/*             i->tree = tree; */
+
+/*             list = g_slist_append (list, i); */
+
+/*             list = cc_build_interfaces (list, IDL_INTERFACE(tree).body); */
+
+/*             break; */
+/*     } */
+/*     case IDLN_OP_DCL: { */
+/*             Interface *i; */
+
+/*             g_return_val_if_fail (list != NULL, NULL); */
+
+/*             i = ( g_slist_last(list) )->data; */
+/*             i->methods = g_slist_append (i->methods, tree); */
+/*             break; */
+/*     } */
+/*     case IDLN_EXCEPT_DCL: */
+/*             break; */
+/*     default: */
+/*             break; */
+/*     } */
+
+/*     return list; */
+/* } */
+
+/* static void */
+/* cc_output_skel (IDL_tree     tree, */
+/*             OIDL_C_Info *ci, */
+/*             int         *idx) */
+/* { */
+/*     IDL_tree  intf; */
+/*     gboolean  has_retval; */
+/*     char     *opname; */
+/*     char     *ifname; */
+
+/*     g_return_if_fail (idx != NULL); */
+
+/*     intf = IDL_get_parent_node (tree, IDLN_INTERFACE, NULL); */
+
+/*     has_retval = IDL_OP_DCL (tree).op_type_spec != NULL; */
+
+/*     opname = IDL_ns_ident_to_qstring (IDL_IDENT_TO_NS (IDL_OP_DCL (tree).ident), "_", 0); */
+/*     ifname = IDL_ns_ident_to_qstring (IDL_IDENT_TO_NS (IDL_INTERFACE (intf).ident), "_", 0); */
+
+/*     fprintf (ci->fh, "void _FORB_skel_small_%s(" */
+/*                             "POA_%s             *_o_servant, " */
+/*                             "gpointer            _o_retval," */
+/*                             "gpointer           *_o_args," */
+/*                             "CORBA_Context       _o_ctx," */
+/*                             "CORBA_Environment  *_o_ev,\n", opname, ifname); */
+
+/*     forb_cbe_op_write_proto (ci->fh, tree, "_impl_", TRUE); */
+
+/*     fprintf (ci->fh, ") {\n"); */
+
+/*     if (has_retval) { */
+/*             fprintf (ci->fh, "*("); */
+/*             forb_cbe_write_param_typespec (ci->fh, tree); */
+/*             fprintf (ci->fh, " *)_o_retval = "); */
+/*     } */
+
+/*     fprintf (ci->fh, "_impl_%s (_o_servant, ", IDL_IDENT (IDL_OP_DCL (tree).ident).str); */
+  
+/*     forb_cbe_unflatten_args (tree, ci->fh, "_o_args"); */
+
+/*     if (IDL_OP_DCL (tree).context_expr) */
+/*             fprintf (ci->fh, "_o_ctx, "); */
+
+/*     fprintf (ci->fh, "_o_ev);\n"); */
+
+/*     fprintf (ci->fh, "}\n"); */
+
+/*     g_free (opname); */
+/*     g_free (ifname); */
+
+/*     (*idx)++; */
+/* } */
+
+/* static void */
+/* cc_output_skels (IDL_tree       tree, */
+/*              OIDL_Run_Info *rinfo, */
+/*              OIDL_C_Info   *ci, */
+/*              int           *idx) */
+/* { */
+/*     if (!tree || (tree->declspec & IDLF_DECLSPEC_PIDL)) */
+/*             return; */
+
+/*     switch (IDL_NODE_TYPE (tree)) { */
+/*     case IDLN_MODULE: */
+/*             cc_output_skels (IDL_MODULE (tree).definition_list, rinfo, ci, idx); */
+/*             break; */
+/*     case IDLN_LIST: { */
+/*             IDL_tree node; */
+
+/*             for (node = tree; node; node = IDL_LIST (node).next) */
+/*                     cc_output_skels (IDL_LIST (node).data, rinfo, ci, idx); */
+/*             break; */
+/*             } */
+/*     case IDLN_ATTR_DCL: { */
+/*             OIDL_Attr_Info *ai = tree->data; */
+/*             IDL_tree        node; */
+      
+/*             for (node = IDL_ATTR_DCL (tree).simple_declarations; node; node = IDL_LIST (node).next) { */
+/*                     ai = IDL_LIST (node).data->data; */
+       
+/*                     cc_output_skels (ai->op1, rinfo, ci, idx); */
+/*                     if (ai->op2) */
+/*                             cc_output_skels (ai->op2, rinfo, ci, idx); */
+/*             } */
+/*             break; */
+/*             } */
+/*     case IDLN_INTERFACE: { */
+/*             int real_idx = 0; */
+
+/*             cc_output_skels (IDL_INTERFACE (tree).body, rinfo, ci, &real_idx); */
+/*             } */
+/*             break; */
+/*     case IDLN_OP_DCL: */
+/*             cc_output_skel (tree, ci, idx); */
+/*             break; */
+/*     default: */
+/*             break; */
+/*     } */
+/* } */
+
+void
+forb_idl_output_c_common (IDL_tree       tree,
+                          OIDL_Run_Info *rinfo,
+                          OIDL_C_Info   *ci)
+{
+       fprintf (ci->fh, OIDL_C_WARNING);
+/*     fprintf (ci->fh, "#include <string.h>\n"); */
+/*     fprintf (ci->fh, "#define FORB2_STUBS_API\n"); */
+/*     fprintf (ci->fh, "#define FORB_IDL_C_COMMON\n"); */
+/*     fprintf (ci->fh, "#define %s_COMMON\n", ci->c_base_name); */
+       fprintf (ci->fh, "#include \"%s.h\"\n", ci->base_name);
+       fprintf (ci->fh, "#include <forb/cdr.h>\n");
+       fprintf (ci->fh, "#include <forb/object.h>\n\n");
+/*     fprintf (ci->fh, "static const CORBA_unsigned_long Forb_zero_int = 0;\n"); */
+
+       /* FIXME: this is slightly nasty, but we need these in common,
+          and this fixes an internal build issue */
+/*     if (rinfo->enabled_passes & OUTPUT_SKELS || */
+/*         rinfo->enabled_passes & OUTPUT_STUBS) { */
+/*             fprintf (ci->fh, "\n#ifndef FORB_IDL_C_IMODULE_%s\n",ci->c_base_name); */
+/*             cc_output_skels (tree, rinfo, ci, NULL); */
+/*             fprintf (ci->fh, "\n#endif\n"); */
+/*     } */
+
+       cc_output_serialization (tree, ci);
+/*     cc_output_typecodes (tree, ci); */
+       
+/*     cc_output_class_ids (tree, rinfo, ci); */
+
+/*     if (rinfo->idata) { */
+/*             GSList *list = NULL; */
+
+/*             fprintf (ci->fh, "\n/\* Interface type data *\/\n\n"); */
+
+/*             list = cc_build_interfaces (list, tree); */
+/*             cc_output_itypes (list, ci); */
+/*     } */
+}
diff --git a/src/forb/forb-idl/forb-idl-c-deps.c b/src/forb/forb-idl/forb-idl-c-deps.c
new file mode 100644 (file)
index 0000000..0717cb3
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2001 Maciej Stachowiak, Ximian Inc.
+ */
+
+#include "config.h"
+#include "forb-idl-c-backend.h"
+
+#include <string.h>
+#include <ctype.h>
+
+static void
+output_deps (IDL_tree tree, 
+            OIDL_Run_Info *rinfo, 
+            OIDL_C_Info *ci)
+{
+       if (!tree)
+               return;
+
+       switch (IDL_NODE_TYPE (tree)) {
+       case IDLN_SRCFILE: {
+               char *idlfn = IDL_SRCFILE (tree).filename;
+               fprintf (ci->fh, " \\\n\t%s", idlfn);
+               break;
+       }
+
+       case IDLN_MODULE:
+               output_deps (IDL_MODULE (tree).definition_list, rinfo, ci);
+               break;
+
+       case IDLN_LIST: {
+               IDL_tree sub;
+
+               for (sub = tree; sub; sub = IDL_LIST (sub).next)
+                       output_deps (IDL_LIST (sub).data, rinfo, ci);
+               break;
+       }
+
+       case IDLN_INTERFACE:
+               output_deps (IDL_INTERFACE (tree).body, rinfo, ci);
+               break;
+
+       default:
+               break;
+       }
+}
+
+void
+forb_idl_output_c_deps (IDL_tree       tree,
+                        OIDL_Run_Info *rinfo, 
+                        OIDL_C_Info   *ci)
+{
+       int i;
+
+       g_return_if_fail (ci->fh != NULL);
+
+       for (i = 0; i < OUTPUT_NUM_PASSES - 1; i++) {
+               char *name = forb_idl_c_filename_for_pass (
+                       rinfo->input_filename, 1 << i);
+               fprintf (ci->fh, "%s ", name);
+               g_free (name);
+       }
+
+       fprintf (ci->fh, ": ");
+  
+       output_deps (tree, rinfo, ci);
+
+       fprintf (ci->fh, "\n");
+}
diff --git a/src/forb/forb-idl/forb-idl-c-headers.c b/src/forb/forb-idl/forb-idl-c-headers.c
new file mode 100644 (file)
index 0000000..6bb62b5
--- /dev/null
@@ -0,0 +1,1346 @@
+#include "config.h"
+#include "forb-idl-c-backend.h"
+#include "forb_config.h"
+
+#include <string.h>
+#include <ctype.h>
+#include <inttypes.h>
+
+/* ch = C header */
+static void ch_output_types(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci);
+/* static void ch_output_poa(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci); */
+/* static void ch_output_itypes (IDL_tree tree, OIDL_C_Info *ci); */
+static void ch_output_stub_protos(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci);
+/* static void ch_output_skel_protos(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci); */
+static GSList *ch_build_interfaces (GSList *list, IDL_tree tree);
+static void ch_output_method (FILE *of, IDL_tree tree, const char *id);
+/* static void ch_output_imethods_index (GSList *list, OIDL_C_Info *ci); */
+
+typedef struct {
+    IDL_tree tree;
+    GSList  *methods; /* IDLN_OP_DCLs */
+} Interface;
+
+/* this is hardcopy from cc_build_interfaces() defined in forb-idl-c-common.c */
+static GSList *
+ch_build_interfaces (GSList *list, IDL_tree tree)
+{
+       if (!tree)
+               return list;
+
+       switch (IDL_NODE_TYPE (tree)) {
+       case IDLN_MODULE:
+               list = ch_build_interfaces (
+                       list, IDL_MODULE (tree).definition_list);
+               break;
+       case IDLN_LIST: {
+               IDL_tree sub;
+               for (sub = tree; sub; sub = IDL_LIST (sub).next)
+                       list = ch_build_interfaces (
+                               list, IDL_LIST (sub).data);
+               break;
+       }
+       case IDLN_ATTR_DCL: {
+               IDL_tree curitem;
+      
+               for (curitem = IDL_ATTR_DCL (tree).simple_declarations;
+                    curitem; curitem = IDL_LIST (curitem).next) {
+                       OIDL_Attr_Info *ai = IDL_LIST (curitem).data->data;
+       
+                       list = ch_build_interfaces (list, ai->op1);
+                       if (ai->op2)
+                               list = ch_build_interfaces (list, ai->op2);
+               }
+               break;
+       }
+       case IDLN_INTERFACE: {
+               Interface *i = g_new0 (Interface, 1);
+
+               i->tree = tree;
+
+               list = g_slist_append (list, i);
+
+               list = ch_build_interfaces (list, IDL_INTERFACE(tree).body);
+
+               break;
+       }
+       case IDLN_OP_DCL: {
+               Interface *i;
+
+               g_return_val_if_fail (list != NULL, NULL);
+
+               i = ( g_slist_last(list) )->data;
+               i->methods = g_slist_append (i->methods, tree);
+               break;
+       }
+       case IDLN_EXCEPT_DCL:
+               break;
+       default:
+               break;
+       }
+
+       return list;
+}
+                                                                                                   
+static void
+ch_output_method (FILE *of, IDL_tree tree, const char *id)
+{
+       char *fullname = NULL;
+
+       fullname = g_strconcat (id, "_", IDL_IDENT (
+               IDL_OP_DCL (tree).ident).str, NULL);
+
+       fprintf (of, "\t%s__method_index", fullname);
+
+       g_free (fullname);
+}
+
+static void
+ch_output_method_indices (GSList *list, OIDL_C_Info *ci)
+{
+       GSList *l;
+       FILE *of = ci->fh;
+
+       for (l = list; l; l = l->next) {
+               Interface *i = l->data;
+               char      *id;
+               GSList    *m;
+
+               id = IDL_ns_ident_to_qstring (IDL_IDENT_TO_NS (
+                       IDL_INTERFACE (i->tree).ident), "_", 0);
+
+               if (i->methods) {
+
+                       fprintf (of, "#ifndef __%s__method_indices\n", id);
+                       fprintf (of, "#define __%s__method_indices\n", id);
+
+                       fprintf (of, "typedef enum {\n");
+
+                       for (m = i->methods; m; m = m->next) {
+                               ch_output_method (of, m->data, id);
+                               if (m->next)
+                                       fprintf(of, ",\n");
+                               else
+                                       fprintf(of, "\n");
+                       }
+
+                       fprintf (of, "} %s__method_indices;\n", id);
+                       fprintf (of, "#endif /* __%s__method_indices */\n\n", id);
+               }
+
+               g_free (id);
+       }
+
+       for (l = list; l; l = l->next) {
+               g_slist_free (((Interface *)l->data)->methods);
+               g_free (l->data);
+       }
+
+       g_slist_free (list);
+}
+
+
+#if 0
+static gboolean is_native(IDL_tree_func_data *tfd, gpointer user_data)
+{
+       IDL_tree tree = tfd->tree;
+       if (IDL_NODE_TYPE (tree) == IDLN_NATIVE) {
+               *(bool*)user_data = true;
+               return FALSE;   /* Stop recursing */
+       }
+       return TRUE;            /* continue */
+}
+
+static bool
+contains_native_type(IDL_tree tree)
+{
+       bool found = false;
+       IDL_tree_walk_in_order(tree, is_native, &found);
+       return found;
+}
+#endif
+
+void
+forb_idl_output_c_headers (IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
+{
+  fprintf (ci->fh, OIDL_C_WARNING);
+  fprintf(ci->fh, "#ifndef %s%s_H\n", rinfo->header_guard_prefix, ci->c_base_name);
+  fprintf(ci->fh, "#define %s%s_H 1\n", rinfo->header_guard_prefix, ci->c_base_name);
+
+  fprintf(ci->fh, "#define FORB_IDL_SERIAL %d\n", FORB_CONFIG_SERIAL);
+
+  fprintf(ci->fh, "#include <forb/cdr_codec.h>\n");
+  if (!rinfo->is_pidl) {
+    fprintf(ci->fh, "#include <forb/object_type.h>\n");
+  }
+  fprintf(ci->fh, "#include <forb/basic_types.h>\n");
+  if (rinfo->include) {
+         fprintf(ci->fh, "#include <%s>\n", rinfo->include);
+  }
+  fprintf(ci->fh, "\n");
+
+  fprintf(ci->fh, "#ifdef __cplusplus\n");
+  fprintf(ci->fh, "extern \"C\" {\n");
+  fprintf(ci->fh, "#endif /* __cplusplus */\n\n");
+
+  /* Do all the typedefs, etc. */
+  fprintf(ci->fh, "\n/** typedefs **/\n");
+  ch_output_types(tree, rinfo, ci);
+  
+  if ( ci->do_skel_defs ) {
+/*     /\* Do all the POA structures, etc. *\/ */
+/*     fprintf(ci->fh, "\n/\** POA structures **\/\n"); */
+/*     ch_output_poa(tree, rinfo, ci); */
+
+/*     fprintf(ci->fh, "\n/\** skel prototypes **\/\n"); */
+/*     fprintf(ci->fh, "/\* FIXME: Maybe we don't need this for FORB. *\/\n"); */
+/*     ch_output_skel_protos(tree, rinfo, ci); */
+  }
+  fprintf(ci->fh, "\n/** stub prototypes **/\n");
+  ch_output_stub_protos(tree, rinfo, ci);
+
+/*   if ( ci->ext_dcls && ci->ext_dcls->str ) */
+/*     fputs( ci->ext_dcls->str, ci->fh);      /\* this may be huge! *\/ */
+
+/*   if (rinfo->idata) { */
+/*     /\* FIXME: hackish ? *\/ */
+/*     fprintf(ci->fh, "#include <forb/orb-core/forb-interface.h>\n\n"); */
+
+/*     ch_output_itypes(tree, ci); */
+/*   } */
+
+  if (rinfo->idata) {
+       GSList *list = NULL;
+       fprintf (ci->fh, "\n/** Method indices */\n\n");
+                                                                                                           
+       list = ch_build_interfaces (list, tree);
+       ch_output_method_indices (list, ci);
+  }
+
+  fprintf(ci->fh, "#ifdef __cplusplus\n");
+  fprintf(ci->fh, "}\n");
+  fprintf(ci->fh, "#endif /* __cplusplus */\n\n");
+
+/*   fprintf(ci->fh, "#ifndef EXCLUDE_FORB_H\n"); */
+/*   fprintf(ci->fh, "#include <forb.h>\n\n"); */
+/*   fprintf(ci->fh, "#endif /\* EXCLUDE_FORB_H *\/\n"); */
+
+  fprintf(ci->fh, "#endif\n");
+
+  fprintf(ci->fh, "#undef FORB_IDL_SERIAL\n");
+}
+
+static void
+ch_output_var(IDL_tree val, IDL_tree name, OIDL_C_Info *ci)
+{
+  forb_cbe_write_typespec(ci->fh, val);
+
+  fprintf(ci->fh, " ");
+  switch(IDL_NODE_TYPE(name)) {
+  case IDLN_IDENT:
+    fprintf(ci->fh, "%s", IDL_IDENT(name).str);
+    break;
+  case IDLN_TYPE_ARRAY:
+    {
+      IDL_tree curitem;
+
+      fprintf(ci->fh, "%s", IDL_IDENT(IDL_TYPE_ARRAY(name).ident).str);
+      for(curitem = IDL_TYPE_ARRAY(name).size_list; curitem; curitem = IDL_LIST(curitem).next) {
+       fprintf(ci->fh, "[%" PRId64 "]", IDL_INTEGER(IDL_LIST(curitem).data).value);
+      }
+    }
+    break;
+  default:
+    g_error("Weird varname - %s", IDL_tree_type_names[IDL_NODE_TYPE(name)]);
+    break;
+  }
+  fprintf(ci->fh, ";\n");
+}
+
+static void ch_output_interface(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci);
+static void ch_output_type_struct(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci);
+static void ch_output_type_enum(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci);
+static void ch_output_type_dcl(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci);
+/* static void ch_output_native(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci); */
+static void ch_output_type_union(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci);
+static void ch_output_codefrag(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci);
+static void ch_output_const_dcl(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci);
+static void ch_prep(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci);
+/* static void ch_type_alloc_and_tc(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci, gboolean do_alloc); */
+
+static void
+ch_output_types (IDL_tree       tree,
+                OIDL_Run_Info *rinfo,
+                OIDL_C_Info   *ci)
+{
+       if (!tree)
+               return;
+       
+       switch (IDL_NODE_TYPE (tree)) {
+       case IDLN_EXCEPT_DCL: {
+         IDL_tree_warning(tree, IDL_WARNING1, "Exceptions are not supperted\n");
+/*             char *id; */
+
+/*             id = IDL_ns_ident_to_qstring ( */
+/*                     IDL_IDENT_TO_NS (IDL_EXCEPT_DCL (tree).ident), "_", 0); */
+
+/*             fprintf (ci->fh, "#undef ex_%s\n", id); */
+/*             fprintf (ci->fh, "#define ex_%s \"%s\"\n", */
+/*                             id, IDL_IDENT (IDL_EXCEPT_DCL (tree).ident).repo_id); */
+
+/*             g_free (id); */
+
+/*             ch_output_type_struct (tree, rinfo, ci); */
+               }
+               break;
+       case IDLN_FORWARD_DCL:
+       case IDLN_INTERFACE:
+               ch_output_interface (tree, rinfo, ci);
+               break;
+       case IDLN_TYPE_STRUCT:
+               ch_output_type_struct (tree, rinfo, ci);
+               break;
+       case IDLN_TYPE_ENUM:
+               ch_output_type_enum (tree, rinfo, ci);
+               break;
+       case IDLN_TYPE_DCL:
+               ch_output_type_dcl (tree, rinfo, ci);
+               break;
+       case IDLN_TYPE_UNION:
+               ch_output_type_union (tree, rinfo, ci);
+               break;
+       case IDLN_CODEFRAG:
+               ch_output_codefrag (tree, rinfo, ci);
+               break;
+       case IDLN_SRCFILE: {
+               char *idlfn = IDL_SRCFILE (tree).filename;
+               if (rinfo->onlytop) {
+
+                       if (!IDL_SRCFILE (tree).seenCnt &&
+                           !IDL_SRCFILE(tree).isTop    &&
+                           !IDL_SRCFILE(tree).wasInhibit) {
+                               gchar *hfn, *htail;
+
+                               hfn   = g_path_get_basename (idlfn);
+                               htail = strrchr (hfn,'.');
+
+                               g_assert (htail && strlen (htail) >= 2);
+
+                               htail [1] = 'h';
+                               htail [2] = 0;
+
+                               fprintf (ci->fh, "#include \"%s\"\n", hfn);
+
+                               g_free (hfn);
+                       }
+               } else {
+               fprintf (ci->fh, "/* from IDL source file \"%s\" "
+                                "(seen %d, isTop %d, wasInhibit %d) */ \n", 
+                                       idlfn,
+                                       IDL_SRCFILE (tree).seenCnt,
+                                       IDL_SRCFILE (tree).isTop,
+                                       IDL_SRCFILE (tree).wasInhibit);
+               }
+               }
+               break;
+       case IDLN_CONST_DCL:
+               ch_output_const_dcl (tree, rinfo, ci);
+               break;
+/*     case IDLN_NATIVE: */
+/*             ch_output_native (tree, rinfo, ci); */
+/*             break; */
+       default:
+               break;
+       }
+
+       switch (IDL_NODE_TYPE (tree)) {
+       case IDLN_MODULE:
+               ch_output_types (IDL_MODULE (tree).definition_list, rinfo, ci);
+               break;
+       case IDLN_LIST: {
+               IDL_tree sub;
+
+               for (sub = tree; sub; sub = IDL_LIST (sub).next) {
+                       ch_output_types (IDL_LIST (sub).data, rinfo, ci);
+               }
+               }
+               break;
+       case IDLN_INTERFACE:
+               ch_output_types (IDL_INTERFACE (tree).body, rinfo, ci);
+               break;
+       default:
+               break;
+       }
+}
+
+static void
+ch_output_impl_struct_members(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
+{
+  if(!tree) return;
+
+  switch(IDL_NODE_TYPE(tree)) {
+  case IDLN_LIST:
+    {
+      IDL_tree sub;
+
+      for(sub = tree; sub; sub = IDL_LIST(sub).next) {
+       ch_output_stub_protos(IDL_LIST(sub).data, rinfo, ci);
+      }
+    }
+    break;
+  case IDLN_INTERFACE:
+    {
+      IDL_tree sub;
+
+/*       if(IDL_INTERFACE(tree).inheritance_spec) { */
+/*     InheritedOutputInfo ioi; */
+/*     ioi.of = ci->fh; */
+/*     ioi.realif = tree; */
+/*     IDL_tree_traverse_parents(IDL_INTERFACE(tree).inheritance_spec, (GFunc)ch_output_inherited_protos, &ioi); */
+/*       } */
+
+      for(sub = IDL_INTERFACE(tree).body; sub; sub = IDL_LIST(sub).next) {
+       IDL_tree cur;
+
+       cur = IDL_LIST(sub).data;
+
+       switch(IDL_NODE_TYPE(cur)) {
+       case IDLN_OP_DCL:
+         forb_idl_check_oneway_op (cur);
+         fprintf(ci->fh, "  ");
+         forb_cbe_op_write_proto(ci->fh, cur, "", TRUE);
+         fprintf(ci->fh, ";\n");
+         break;
+/*     case IDLN_ATTR_DCL: */
+/*       { */
+/*         OIDL_Attr_Info *ai; */
+/*         IDL_tree curitem; */
+
+/*         for(curitem = IDL_ATTR_DCL(cur).simple_declarations; curitem; curitem = IDL_LIST(curitem).next) { */
+/*           ai = IDL_LIST(curitem).data->data; */
+             
+/*           forb_cbe_op_write_proto(ci->fh, ai->op1, "", FALSE); */
+/*           fprintf(ci->fh, ";\n"); */
+             
+/*           if(ai->op2) { */
+/*             forb_cbe_op_write_proto(ci->fh, ai->op2, "", FALSE); */
+/*             fprintf(ci->fh, ";\n"); */
+/*           } */
+/*         } */
+/*       } */
+/*       break; */
+       default:
+         break;
+       }
+      }
+    }
+    break;
+  default:
+    break;
+  }
+}
+static void
+ch_output_impl_struct(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
+{
+    char *fullname;
+    fullname = forb_cbe_get_typespec_str(tree);
+    fprintf(ci->fh, "struct forb_%s_impl {\n", fullname);
+    ch_output_impl_struct_members(tree, rinfo, ci);
+    fprintf(ci->fh, "};\n\n");
+    g_free(fullname);
+}
+
+static void
+ch_output_interface(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
+{
+    char *fullname;
+    fullname = forb_cbe_get_typespec_str(tree);
+    fprintf(ci->fh, "#if !defined(FORB_DECL_%s)\n"
+                   "#define FORB_DECL_%s 1\n",
+                   fullname, fullname);
+
+    if ( tree->declspec & IDLF_DECLSPEC_PIDL ) {
+        /* PIDL interfaces are not normal CORBA Objects */
+      fprintf(ci->fh, "// PIDL: %s\n", fullname);
+/*             fprintf(ci->fh, "typedef struct %s_type *%s;\n", fullname, fullname); */
+/*     fprintf(ci->fh, "#ifndef TC_%s\n", fullname); */
+/*     fprintf(ci->fh, "#  define TC_%s TC_CORBA_Object\n", fullname); */
+/*     fprintf(ci->fh, "#endif\n"); */
+    } else {
+
+        fprintf(ci->fh, "  #if !defined(_%s_defined)\n"
+                       "  #define _%s_defined 1\n",
+                       fullname, fullname);
+/*         fprintf(ci->fh, "#define %s__freekids CORBA_Object__freekids\n", fullname); */
+       fprintf(ci->fh, "    typedef forb_object %s;\n"
+                       "  #endif\n", fullname);
+       fprintf(ci->fh, "  #define %s_serialize(codec, obj) forb_object_serialize((codec), (obj))\n", fullname);
+       fprintf(ci->fh, "  #define %s_deserialize(codec, obj) forb_object_deserialize((codec), (obj))\n", fullname);
+/*             fprintf(ci->fh, "extern CORBA_unsigned_long %s__classid;\n", fullname); */
+
+       ch_output_impl_struct(tree, rinfo, ci);
+
+/*     fprintf(ci->fh, "void forb_register_%s_interface(void);\n", fullname); */
+       fprintf(ci->fh, "  %s forb_%s_new(forb_orb orb,\n"
+                       "                 const struct forb_%s_impl *impl,\n"
+                       "                 void *instance_data);\n\n",
+               fullname, fullname, fullname);
+       
+       /* ch_type_alloc_and_tc(tree, rinfo, ci, FALSE); */
+    }
+
+    fprintf(ci->fh, "#endif\n\n");
+    g_free(fullname);
+}
+
+static void
+ch_output_type_enum (IDL_tree       tree,
+                    OIDL_Run_Info *rinfo,
+                    OIDL_C_Info   *ci)
+{
+       IDL_tree  l;
+       char     *enumid;
+
+       /* CORBA spec says to do
+        * typedef unsigned int enum_name;
+        * and then #defines for each enumerator.
+        * This works just as well and seems cleaner.
+        */
+
+       enumid = IDL_ns_ident_to_qstring (
+                       IDL_IDENT_TO_NS (IDL_TYPE_ENUM (tree).ident), "_", 0);
+       fprintf (ci->fh, "#if !defined(_%s_defined)\n#define _%s_defined 1\n", enumid, enumid);
+       fprintf (ci->fh, "typedef enum {\n");
+
+       for (l = IDL_TYPE_ENUM (tree).enumerator_list; l; l = IDL_LIST (l).next) {
+               char *id;
+
+               id = IDL_ns_ident_to_qstring (
+                       IDL_IDENT_TO_NS (IDL_LIST (l).data), "_", 0);
+
+               fprintf (ci->fh, "  %s%s\n", id, IDL_LIST (l).next ? "," : "");
+
+               g_free (id);
+       }
+
+       fprintf (ci->fh, "} %s;\n", enumid);
+
+       /* ch_type_alloc_and_tc (tree, rinfo, ci, FALSE); */
+       fprintf (ci->fh, "#define %s_serialize(codec, val) CORBA_unsigned_long_serialize(codec, val)\n", enumid);
+       fprintf (ci->fh, "#define %s_deserialize(codec, val) CORBA_unsigned_long_deserialize(codec, val)\n", enumid);
+
+       fprintf (ci->fh, "#endif\n\n");
+
+       g_free (enumid);
+}
+
+static void
+ch_output_type_dcl(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
+{
+       IDL_tree  l;
+
+       ch_prep (IDL_TYPE_DCL (tree).type_spec, rinfo, ci);
+
+       for (l = IDL_TYPE_DCL (tree).dcls; l; l = IDL_LIST (l).next) {
+               char *ctmp = NULL;
+
+               IDL_tree ent = IDL_LIST (l).data;
+
+               switch (IDL_NODE_TYPE(ent)) {
+               case IDLN_IDENT:
+                       ctmp = IDL_ns_ident_to_qstring (
+                                       IDL_IDENT_TO_NS (ent), "_", 0);
+                       break;
+               case IDLN_TYPE_ARRAY:
+                       ctmp = IDL_ns_ident_to_qstring (
+                                       IDL_IDENT_TO_NS (IDL_TYPE_ARRAY (ent).ident), "_", 0);
+                       break;
+               default:
+                       g_assert_not_reached ();
+                       break;
+               }
+
+               fprintf (ci->fh, "#if !defined(_%s_defined)\n#define _%s_defined 1\n", ctmp, ctmp);
+               fprintf (ci->fh, "typedef ");
+               forb_cbe_write_typespec (ci->fh, IDL_TYPE_DCL (tree).type_spec);
+
+               switch (IDL_NODE_TYPE (ent)) {
+               case IDLN_IDENT:
+                       fprintf (ci->fh, " %s;\n", ctmp);
+                       fprintf (ci->fh, "#define %s_serialize(x,y) ", ctmp);
+                       forb_cbe_write_typespec (ci->fh, IDL_TYPE_DCL (tree).type_spec);
+                       fprintf (ci->fh, "_serialize((x),(y))\n");
+
+                       fprintf (ci->fh, "#define %s_deserialize(x,y) ", ctmp);
+                       forb_cbe_write_typespec (ci->fh, IDL_TYPE_DCL (tree).type_spec);
+                       fprintf (ci->fh, "_deserialize((x),(y))\n");
+                       break;
+               case IDLN_TYPE_ARRAY: {
+                       IDL_tree sub;
+
+                       fprintf (ci->fh, " %s", ctmp);
+                       for (sub = IDL_TYPE_ARRAY (ent).size_list; sub; sub = IDL_LIST (sub).next)
+                               fprintf (ci->fh, "[%" PRId64 "]",
+                                        IDL_INTEGER (IDL_LIST (sub).data).value);
+
+                       fprintf (ci->fh, ";\n");
+                       fprintf(ci->fh, "CORBA_boolean %s_serialize(FORB_CDR_Codec *codec, const %s array);\n", ctmp, ctmp);
+                       fprintf(ci->fh, "CORBA_boolean %s_deserialize(FORB_CDR_Codec *codec, %s array);\n", ctmp, ctmp);
+/*                     fprintf (ci->fh, "typedef "); */
+/*                     forb_cbe_write_typespec (ci->fh, IDL_TYPE_DCL (tree).type_spec); */
+/*                     fprintf (ci->fh, " %s_slice", ctmp); */
+/*                     for (sub = IDL_LIST (IDL_TYPE_ARRAY (ent).size_list).next; */
+/*                          sub; sub = IDL_LIST (sub).next) */
+/*                             fprintf (ci->fh, "[%" PRId64 "d]", IDL_INTEGER (IDL_LIST (sub).data).value); */
+/*                     fprintf(ci->fh, ";\n"); */
+                       }
+                       break;
+               default:
+                       break;
+               }
+
+               /* ch_type_alloc_and_tc (ent, rinfo, ci, TRUE); */
+               fprintf (ci->fh, "#endif\n");
+               g_free (ctmp);
+       }
+}
+
+/* static void */
+/* ch_output_native(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci) */
+/* { */
+/*     char *ctmp; */
+/*     IDL_tree id = IDL_NATIVE(tree).ident; */
+/*     ctmp = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(id), "_", 0); */
+/*     fprintf(ci->fh, "#if !defined(_%s_defined)\n#define _%s_defined 1\n", ctmp, ctmp); */
+/*     fprintf(ci->fh, "typedef struct %s_type *%s;\n", ctmp, ctmp); */
+/*     /\* Dont even think about emitting a typecode. *\/ */
+/*     fprintf(ci->fh, "#endif\n"); */
+/*     g_free(ctmp); */
+/* } */
+
+static void
+ch_output_type_struct(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
+{
+  char *id;
+  IDL_tree cur, curmem;
+
+  id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_TYPE_STRUCT(tree).ident), 
+    "_", 0);
+  fprintf(ci->fh, "#if !defined(_%s_defined)\n#define _%s_defined 1\n", id, id);
+  /* put typedef out first for recursive seq */
+  fprintf(ci->fh, "typedef struct %s_type %s;\n", id, id);
+
+  /* Scan for any nested decls */
+  for(cur = IDL_TYPE_STRUCT(tree).member_list; cur; cur = IDL_LIST(cur).next) {
+    IDL_tree ts;
+    ts = IDL_MEMBER(IDL_LIST(cur).data).type_spec;
+    ch_prep(ts, rinfo, ci);
+  }
+
+  fprintf(ci->fh, "struct %s_type {\n", id);
+
+  for(cur = IDL_TYPE_STRUCT(tree).member_list; cur; cur = IDL_LIST(cur).next) {
+    for(curmem = IDL_MEMBER(IDL_LIST(cur).data).dcls; curmem; curmem = IDL_LIST(curmem).next) {
+      ch_output_var(IDL_MEMBER(IDL_LIST(cur).data).type_spec, IDL_LIST(curmem).data, ci);
+    }
+  }
+  if(!IDL_TYPE_STRUCT(tree).member_list)
+    fprintf(ci->fh, "int dummy;\n");
+  fprintf(ci->fh, "};\n");
+
+  fprintf(ci->fh, "CORBA_boolean %s_serialize(FORB_CDR_Codec *codec, const %s *ptr);\n", id, id);
+  fprintf(ci->fh, "CORBA_boolean %s_deserialize(FORB_CDR_Codec *codec, %s *ptr);\n", id, id);
+
+  /* ch_type_alloc_and_tc(tree, rinfo, ci, TRUE); */
+
+  fprintf(ci->fh, "#endif\n\n");
+
+  g_free(id);
+}
+
+
+static void
+ch_output_type_union(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
+{
+  char *id;
+  IDL_tree curitem;
+
+  if (IDL_NODE_TYPE (IDL_TYPE_UNION (tree).switch_type_spec) == IDLN_TYPE_ENUM)
+    ch_output_type_enum (IDL_TYPE_UNION (tree).switch_type_spec, rinfo, ci);
+
+  id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_TYPE_UNION(tree).ident), "_", 0);
+  fprintf(ci->fh, "#if !defined(_%s_defined)\n#define _%s_defined 1\n", id, id);
+  fprintf(ci->fh, "typedef struct %s_type %s;\n", id, id);
+
+  /* Scan for any nested decls */
+  for(curitem = IDL_TYPE_UNION(tree).switch_body; curitem; curitem = IDL_LIST(curitem).next) {
+    IDL_tree member = IDL_CASE_STMT(IDL_LIST(curitem).data).element_spec;
+    ch_prep(IDL_MEMBER(member).type_spec, rinfo, ci);
+  }
+
+  fprintf(ci->fh, "struct %s_type {\n", id);
+  forb_cbe_write_typespec(ci->fh, IDL_TYPE_UNION(tree).switch_type_spec);
+  fprintf(ci->fh, " _d;\nunion {\n");
+
+  for(curitem = IDL_TYPE_UNION(tree).switch_body; curitem; curitem = IDL_LIST(curitem).next) {
+    IDL_tree member;
+
+    member = IDL_CASE_STMT(IDL_LIST(curitem).data).element_spec;
+    ch_output_var(IDL_MEMBER(member).type_spec,
+                 IDL_LIST(IDL_MEMBER(member).dcls).data,
+                 ci);
+  }
+
+  fprintf(ci->fh, "} _u;\n};\n");
+
+  /* ch_type_alloc_and_tc(tree, rinfo, ci, TRUE); */
+
+  fprintf(ci->fh, "#endif\n");
+
+  g_free(id);
+}
+
+static void
+ch_output_codefrag(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
+{
+  GSList *list;
+
+  for(list = IDL_CODEFRAG(tree).lines; list;
+      list = g_slist_next(list)) {
+    if(!strncmp(list->data,
+               "#pragma include_defs",
+               sizeof("#pragma include_defs")-1)) {
+       char *ctmp, *cte;
+       ctmp = ((char *)list->data) + sizeof("#pragma include_defs");
+       while(*ctmp && (isspace((int)*ctmp) || *ctmp == '"')) ctmp++;
+       cte = ctmp;
+       while(*cte && !isspace((int)*cte) && *cte != '"') cte++;
+       *cte = '\0';
+      fprintf(ci->fh, "#include <%s>\n", ctmp);
+    } else
+      fprintf(ci->fh, "%s\n", (char *)list->data);
+  }
+}
+
+static void
+ch_output_const_dcl(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
+{
+       char    *id;
+       IDL_tree ident;
+       IDL_tree typespec;
+
+       ident = IDL_CONST_DCL (tree).ident;
+       id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS (ident), "_", 0);
+
+       fprintf(ci->fh, "#ifndef %s\n", id);
+       fprintf(ci->fh, "#define %s ", id);
+
+       forb_cbe_write_const(ci->fh,
+                             IDL_CONST_DCL(tree).const_exp);
+
+       typespec = forb_cbe_get_typespec (IDL_CONST_DCL(tree).const_type);
+       if (IDL_NODE_TYPE (typespec) == IDLN_TYPE_INTEGER &&
+           !IDL_TYPE_INTEGER (typespec).f_signed)
+               fprintf(ci->fh, "U");
+
+       fprintf(ci->fh, "\n");
+       fprintf(ci->fh, "#endif /* !%s */\n\n", id);
+
+       g_free(id);
+}
+
+static void
+ch_prep_fixed(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
+{
+  char *ctmp;
+
+  ctmp = forb_cbe_get_typespec_str(tree);
+  fprintf(ci->fh,
+         "typedef struct { CORBA_unsigned_short _digits; CORBA_short _scale; CORBA_char _value[%d]; } %s;\n",
+         (int) (IDL_INTEGER(IDL_TYPE_FIXED(tree).positive_int_const).value + 2)/2,
+         ctmp);
+  g_free(ctmp);
+
+  /* ch_type_alloc_and_tc(tree, rinfo, ci, TRUE); */
+}
+
+static void
+ch_prep_sequence(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
+{
+  char *ctmp, *fullname, *fullname_def, *ctmp2;
+  IDL_tree tts;
+  gboolean separate_defs, fake_if;
+  IDL_tree fake_seq = NULL;
+
+  tts = forb_cbe_get_typespec(IDL_TYPE_SEQUENCE(tree).simple_type_spec);
+  ctmp = forb_cbe_get_typespec_str(IDL_TYPE_SEQUENCE(tree).simple_type_spec);
+  ctmp2 = forb_cbe_get_typespec_str(tts);
+  fake_if = (IDL_NODE_TYPE(tts) == IDLN_INTERFACE);
+  if(fake_if)
+    {
+      g_free(ctmp2);
+      ctmp2 = g_strdup("CORBA_Object");
+    }
+  separate_defs = false; //strcmp(ctmp, ctmp2);
+  fullname = forb_cbe_get_typespec_str(tree);
+  //printf("YYY %s\n", fullname);
+
+  if(separate_defs)
+    {
+      char *member_type;
+      //printf("XXXXXXXX Separate defs %s, %s\n", ctmp, ctmp2);
+      //forb_idl_print_node(tree, 2);
+      if(fake_if)
+       tts = IDL_type_object_new();
+      fake_seq = IDL_type_sequence_new(tts, NULL);
+      IDL_NODE_UP(fake_seq) = IDL_NODE_UP(tree);
+      ch_prep_sequence(fake_seq, rinfo, ci);
+      member_type = forb_cbe_type_is_builtin (tts) ?
+       ctmp2 + strlen ("CORBA_") : ctmp2;
+      fullname_def = g_strdup_printf("CORBA_sequence_%s", member_type);
+
+      if(!fake_if)
+       IDL_TYPE_SEQUENCE(fake_seq).simple_type_spec = NULL;
+    }
+  else
+    fullname_def = g_strdup(fullname);
+
+  if(IDL_NODE_TYPE(IDL_TYPE_SEQUENCE(tree).simple_type_spec)
+     == IDLN_TYPE_SEQUENCE)
+    ch_prep_sequence(IDL_TYPE_SEQUENCE(tree).simple_type_spec, rinfo, ci);
+
+  /* NOTE: FORB_DECL_%s protects redef of everything (struct,TC,externs)
+   * while _%s_defined protects only the struct */
+
+  fprintf(ci->fh, "#if !defined(FORB_DECL_%s)\n#define FORB_DECL_%s 1\n",
+         fullname, fullname);
+/*   if ( ci->do_impl_hack ) */
+/*       forb_cbe_id_define_hack(ci->fh, "FORB_IMPL", fullname, ci->c_base_name); */
+
+  if(separate_defs)
+    {
+      fprintf(ci->fh, "#if !defined(_%s_defined)\n#define _%s_defined 1\n",
+             fullname, fullname);
+      if(!strcmp(ctmp, "CORBA_RepositoryId"))
+       fprintf(ci->fh, "/* CRACKHEADS */\n");
+      fprintf(ci->fh, "typedef %s\n  %s;\n", fullname_def, fullname);
+      fprintf(ci->fh, "#endif\n");
+      /* ch_type_alloc_and_tc(tree, rinfo, ci, FALSE); */
+/*       fprintf(ci->fh, "#define %s__alloc %s__alloc\n", */
+/*           fullname, fullname_def); */
+/*       fprintf(ci->fh, "#define %s__freekids %s__freekids\n", */
+/*           fullname, fullname_def); */
+      fprintf(ci->fh, "#define CORBA_sequence_%s_allocbuf(l) %s_allocbuf(l)\n",
+             ctmp, fullname_def);
+      fprintf(ci->fh, "#define %s_serialize(x,y) %s_serialize((x),(y))\n", fullname, fullname_def);
+
+      fprintf(ci->fh, "#define %s_deserialize(x,y) %s_deserialize((x),(y))\n", fullname, fullname_def);
+      IDL_tree_free(fake_seq);
+    }
+  else
+    {
+      char *member_type;
+
+      fprintf(ci->fh, "#if !defined(_%s_defined)\n#define _%s_defined 1\n",
+             fullname, fullname);
+      fprintf(ci->fh, "typedef struct { CORBA_unsigned_long _maximum, _length; ");
+      forb_cbe_write_typespec(ci->fh, IDL_TYPE_SEQUENCE(tree).simple_type_spec);
+      fprintf(ci->fh, "* _buffer; CORBA_boolean _release; }\n  ");
+      forb_cbe_write_typespec(ci->fh, tree);
+      fprintf(ci->fh, ";\n#endif\n");
+
+      fprintf(ci->fh, "CORBA_boolean %s_serialize(FORB_CDR_Codec *codec, const %s *ptr);\n", fullname, fullname);
+      fprintf(ci->fh, "CORBA_boolean %s_deserialize(FORB_CDR_Codec *codec, %s *ptr);\n", fullname, fullname);
+      /* ch_type_alloc_and_tc(tree, rinfo, ci, TRUE); */
+
+/*       tc = forb_cbe_get_typecode_name (forb_cbe_get_typespec (tree)); */
+      member_type = forb_cbe_type_is_builtin (IDL_TYPE_SEQUENCE (tree).simple_type_spec) ?
+       ctmp + strlen ("CORBA_") : ctmp;
+
+      fprintf (ci->fh, "#define CORBA_sequence_%s_allocbuf(l) "
+                      "((%s*)forb_malloc(sizeof(%s)*(l)))\n",
+                      member_type, ctmp, ctmp);
+
+/*       g_free (tc); */
+    }
+
+  fprintf(ci->fh, "#endif\n\n");
+
+  g_free(ctmp2);
+  g_free(ctmp);
+  g_free(fullname);
+  g_free(fullname_def);
+}
+
+static
+void ch_prep (IDL_tree       tree,
+             OIDL_Run_Info *rinfo,
+             OIDL_C_Info   *ci)
+{
+       switch (IDL_NODE_TYPE (tree)) {
+       case IDLN_TYPE_SEQUENCE:
+               ch_prep_sequence (tree, rinfo, ci);
+               break;
+       case IDLN_TYPE_FIXED:
+               ch_prep_fixed (tree, rinfo, ci);
+               break;
+       case IDLN_TYPE_STRUCT:
+               ch_output_type_struct (tree, rinfo, ci);
+               break;
+       case IDLN_TYPE_ENUM:
+               ch_output_type_enum (tree, rinfo, ci);
+               break;
+       default:
+               break;
+       }
+}
+
+/* static void */
+/* ch_type_alloc_and_tc(IDL_tree tree, OIDL_Run_Info *rinfo, */
+/*                  OIDL_C_Info *ci, gboolean do_alloc) */
+/* { */
+/*   char *ctmp; */
+/*   IDL_tree tts; */
+
+/*   ctmp = forb_cbe_get_typespec_str(tree); */
+
+/*   if ( ci->do_impl_hack ) { */
+/*       fprintf(ci->fh, "#if !defined(TC_IMPL_TC_%s_0)\n", ctmp); */
+/*       forb_cbe_id_define_hack(ci->fh, "TC_IMPL_TC", ctmp, ci->c_base_name); */
+/*   } */
+
+/*   fprintf (ci->fh, "#ifdef FORB_IDL_C_IMODULE_%s\n", ci->c_base_name); */
+/*   fprintf (ci->fh, "static\n"); */
+/*   fprintf (ci->fh, "#else\n"); */
+/*   fprintf (ci->fh, "extern\n"); */
+/*   fprintf (ci->fh, "#endif\n"); */
+/*   fprintf (ci->fh, "FORB2_MAYBE_CONST struct CORBA_TypeCode_struct TC_%s_struct;\n", ctmp); */
+
+/*   fprintf (ci->fh, "#define TC_%s ((CORBA_TypeCode)&TC_%s_struct)\n", ctmp, ctmp); */
+/*   if (ci->do_impl_hack) */
+/*       fprintf (ci->fh, "#endif\n"); */
+
+/*   if(do_alloc) { */
+/*       char *tc; */
+
+/*       tts = forb_cbe_get_typespec(tree); */
+
+/*       tc = forb_cbe_get_typecode_name (tts); */
+
+/*       fprintf (ci->fh, "#define %s__alloc() ((%s%s *)Forb_small_alloc (%s))\n", */
+/*                ctmp, ctmp, (IDL_NODE_TYPE(tree) == IDLN_TYPE_ARRAY)?"_slice":"", tc); */
+
+/*       fprintf (ci->fh, "#define %s__freekids(m,d) Forb_small_freekids (%s,(m),(d))\n", ctmp, tc); */
+
+/*       if ( IDL_NODE_TYPE(tts) == IDLN_TYPE_SEQUENCE ) */
+/*       { */
+/*     char *member_type = forb_cbe_get_typespec_str(IDL_TYPE_SEQUENCE(tts).simple_type_spec); */
+/*     char *member_name = forb_cbe_type_is_builtin (IDL_TYPE_SEQUENCE (tts).simple_type_spec) ? */
+/*       member_type + strlen ("CORBA_") : member_type; */
+       
+/*     fprintf (ci->fh, "#define %s_allocbuf(l) " */
+/*              "((%s*)Forb_small_allocbuf (%s, (l)))\n", */
+/*              ctmp, member_name, tc); */
+       
+/*     g_free (member_type); */
+/*       } */
+       
+/*       g_free (tc); */
+/*   } */
+
+/*   g_free(ctmp); */
+/* } */
+
+/************************/
+/* static void */
+/* cbe_header_interface_print_vepv(IDL_tree node, FILE *of) */
+/* { */
+/*   char *id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(node).ident), */
+/*                                  "_", 0); */
+/*   fprintf(of, "  POA_%s__epv *%s_epv;\n", id, id); */
+/*   g_free(id); */
+
+/* } */
+
+/* static void */
+/* ch_output_poa(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci) */
+/* { */
+/*   if(!tree) return; */
+
+/*   if ( tree->declspec & IDLF_DECLSPEC_PIDL ) */
+/*     return; */
+
+/*   switch(IDL_NODE_TYPE(tree)) { */
+/*   case IDLN_MODULE: */
+/*     ch_output_poa(IDL_MODULE(tree).definition_list, rinfo, ci); */
+/*     break; */
+/*   case IDLN_LIST: */
+/*     { */
+/*       IDL_tree sub; */
+
+/*       for(sub = tree; sub; sub = IDL_LIST(sub).next) { */
+/*     ch_output_poa(IDL_LIST(sub).data, rinfo, ci); */
+/*       } */
+/*     } */
+/*     break; */
+/*   case IDLN_INTERFACE: */
+/*     { */
+/*       IDL_tree sub; */
+/*       char *id; */
+
+
+/*       id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(tree).ident), "_", 0); */
+
+/*       fprintf(ci->fh, "#ifndef _defined_POA_%s\n#define _defined_POA_%s 1\n",  */
+/*         id, id); */
+
+/*       /\* First, do epv for this interface, then vepv, then servant *\/ */
+/*       fprintf(ci->fh, "typedef struct {\n"); */
+/*       fprintf(ci->fh, "  void *_private;\n"); */
+/*       for(sub = IDL_INTERFACE(tree).body; sub; sub = IDL_LIST(sub).next) { */
+/*     IDL_tree cur; */
+
+/*     cur = IDL_LIST(sub).data; */
+
+/*     switch(IDL_NODE_TYPE(cur)) { */
+/*     case IDLN_OP_DCL: */
+/*       forb_cbe_op_write_proto(ci->fh, cur, "", TRUE); */
+/*       fprintf(ci->fh, ";\n"); */
+/*       break; */
+/*     case IDLN_ATTR_DCL: */
+/*       { */
+/*         OIDL_Attr_Info *ai; */
+/*         IDL_tree curitem; */
+
+/*         for(curitem = IDL_ATTR_DCL(cur).simple_declarations; curitem; curitem = IDL_LIST(curitem).next) { */
+/*           ai = IDL_LIST(curitem).data->data; */
+             
+/*           forb_cbe_op_write_proto(ci->fh, ai->op1, "", TRUE); */
+/*           fprintf(ci->fh, ";\n"); */
+             
+/*           if(ai->op2) { */
+/*             forb_cbe_op_write_proto(ci->fh, ai->op2, "", TRUE); */
+/*             fprintf(ci->fh, ";\n"); */
+/*           } */
+/*         } */
+/*       } */
+/*       break; */
+/*     default: */
+/*       break; */
+/*     } */
+/*       } */
+
+/*       fprintf(ci->fh, "} POA_%s__epv;\n", id); */
+
+/*       fprintf(ci->fh, "typedef struct {\n"); */
+/*       fprintf(ci->fh, "  PortableServer_ServantBase__epv *_base_epv;\n"); */
+/*       IDL_tree_traverse_parents(tree, (GFunc)cbe_header_interface_print_vepv, ci->fh); */
+/*       fprintf(ci->fh, "} POA_%s__vepv;\n", id); */
+
+/*       fprintf(ci->fh, "typedef struct {\n"); */
+/*       fprintf(ci->fh, "  void *_private;\n"); */
+/*       fprintf(ci->fh, "  POA_%s__vepv *vepv;\n", id); */
+/*       fprintf(ci->fh, "} POA_%s;\n", id); */
+
+/*       fprintf(ci->fh, */
+/*           "extern void POA_%s__init(PortableServer_Servant servant, CORBA_Environment *ev);\n", id); */
+/*       fprintf(ci->fh, */
+/*           "extern void POA_%s__fini(PortableServer_Servant servant, CORBA_Environment *ev);\n", id); */
+
+/*       fprintf(ci->fh, "#endif /\* _defined_POA_%s *\/\n", id); */
+
+/*       g_free(id); */
+/*     } */
+/*     break; */
+/*   default: */
+/*     break; */
+/*   } */
+/* } */
+
+/************************/
+typedef struct {
+  FILE *of;
+  IDL_tree realif;
+} InheritedOutputInfo;
+static void ch_output_inherited_protos(IDL_tree curif, InheritedOutputInfo *ioi);
+
+static void
+ch_output_stub_protos(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
+{
+  if(!tree) return;
+
+
+  switch(IDL_NODE_TYPE(tree)) {
+  case IDLN_MODULE:
+    ch_output_stub_protos(IDL_MODULE(tree).definition_list, rinfo, ci);
+    break;
+  case IDLN_LIST:
+    {
+      IDL_tree sub;
+
+      for(sub = tree; sub; sub = IDL_LIST(sub).next) {
+       ch_output_stub_protos(IDL_LIST(sub).data, rinfo, ci);
+      }
+    }
+    break;
+  case IDLN_INTERFACE:
+    {
+      IDL_tree sub;
+
+      if(IDL_INTERFACE(tree).inheritance_spec) {
+       InheritedOutputInfo ioi;
+       ioi.of = ci->fh;
+       ioi.realif = tree;
+       IDL_tree_traverse_parents(IDL_INTERFACE(tree).inheritance_spec, (GFunc)ch_output_inherited_protos, &ioi);
+      }
+
+      for(sub = IDL_INTERFACE(tree).body; sub; sub = IDL_LIST(sub).next) {
+       IDL_tree cur;
+
+       cur = IDL_LIST(sub).data;
+
+       switch(IDL_NODE_TYPE(cur)) {
+       case IDLN_OP_DCL:
+         forb_idl_check_oneway_op (cur);
+         forb_cbe_op_write_proto(ci->fh, cur, "", FALSE);
+         fprintf(ci->fh, ";\n");
+         break;
+       case IDLN_ATTR_DCL:
+         {
+           OIDL_Attr_Info *ai;
+           IDL_tree curitem;
+
+           for(curitem = IDL_ATTR_DCL(cur).simple_declarations; curitem; curitem = IDL_LIST(curitem).next) {
+             ai = IDL_LIST(curitem).data->data;
+             
+             forb_cbe_op_write_proto(ci->fh, ai->op1, "", FALSE);
+             fprintf(ci->fh, ";\n");
+             
+             if(ai->op2) {
+               forb_cbe_op_write_proto(ci->fh, ai->op2, "", FALSE);
+               fprintf(ci->fh, ";\n");
+             }
+           }
+         }
+         break;
+       default:
+         break;
+       }
+      }
+    }
+    break;
+  default:
+    break;
+  }
+}
+
+static void
+ch_output_inherited_protos(IDL_tree curif, InheritedOutputInfo *ioi)
+{
+  char *id, *realid;
+  IDL_tree curitem;
+
+  if(curif == ioi->realif)
+    return;
+
+  realid = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(ioi->realif).ident), "_", 0);
+  id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(curif).ident), "_", 0);
+
+  for(curitem = IDL_INTERFACE(curif).body; curitem; curitem = IDL_LIST(curitem).next) {
+    IDL_tree curop = IDL_LIST(curitem).data;
+
+    switch(IDL_NODE_TYPE(curop)) {
+    case IDLN_OP_DCL:
+      fprintf(ioi->of, "#define %s_%s %s_%s\n",
+             realid, IDL_IDENT(IDL_OP_DCL(curop).ident).str,
+             id, IDL_IDENT(IDL_OP_DCL(curop).ident).str);
+      break;
+    case IDLN_ATTR_DCL:
+      {
+       IDL_tree curitem;
+
+       /* We don't use OIDL_Attr_Info here because inherited ops may go back into trees that are output-inhibited
+          and therefore don't have the OIDL_Attr_Info generated on them */
+
+       for(curitem = IDL_ATTR_DCL(curop).simple_declarations; curitem; curitem = IDL_LIST(curitem).next) {
+         IDL_tree ident;
+
+         ident = IDL_LIST(curitem).data;
+         
+         fprintf(ioi->of, "#define %s__get_%s %s__get_%s\n",
+                 realid, IDL_IDENT(ident).str,
+                 id, IDL_IDENT(ident).str);
+
+         if(!IDL_ATTR_DCL(curop).f_readonly)
+           fprintf(ioi->of, "#define %s__set_%s %s__set_%s\n",
+                   realid, IDL_IDENT(ident).str,
+                   id, IDL_IDENT(ident).str);
+       }
+      }
+      break;
+       default:
+         break;
+    }
+  }
+
+  g_free(id);
+  g_free(realid);
+}
+
+/* static void */
+/* doskel(IDL_tree cur, OIDL_Run_Info *rinfo, char *ifid, OIDL_C_Info *ci) */
+/* { */
+/*   char *id; */
+
+/*   id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_OP_DCL(cur).ident), "_", 0); */
+
+/*   fprintf(ci->fh, "void _forb_skel_%s(" */
+/*       "FORB_CDR_Codec *codec, %s *obj", */
+/*       id, ifid); */
+/* /\*   forb_cbe_op_write_proto(ci->fh, cur, "_impl_", TRUE); *\/ */
+/*   fprintf(ci->fh, ");\n"); */
+
+/*   g_free(id); */
+/* } */
+
+/* static void */
+/* ch_output_skel_protos(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci) */
+/* { */
+/*   if(!tree) return; */
+
+/*   if ( tree->declspec & IDLF_DECLSPEC_PIDL ) */
+/*     return; */
+
+/*   switch(IDL_NODE_TYPE(tree)) { */
+/*   case IDLN_MODULE: */
+/*     ch_output_skel_protos(IDL_MODULE(tree).definition_list, rinfo, ci); */
+/*     break; */
+/*   case IDLN_LIST: */
+/*     { */
+/*       IDL_tree sub; */
+
+/*       for(sub = tree; sub; sub = IDL_LIST(sub).next) { */
+/*     ch_output_skel_protos(IDL_LIST(sub).data, rinfo, ci); */
+/*       } */
+/*     } */
+/*     break; */
+/*   case IDLN_INTERFACE: */
+/*     { */
+/*       IDL_tree sub; */
+/*       char *ifid; */
+
+/*       ifid = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(tree).ident), "_", 0); */
+
+/*       for(sub = IDL_INTERFACE(tree).body; sub; sub = IDL_LIST(sub).next) { */
+/*     IDL_tree cur; */
+
+/*     cur = IDL_LIST(sub).data; */
+
+/*     switch(IDL_NODE_TYPE(cur)) { */
+/*     case IDLN_OP_DCL: */
+/*       doskel(cur, rinfo, ifid, ci); */
+/*       break; */
+/*     case IDLN_ATTR_DCL: */
+/*       IDL_tree_warning(cur, IDL_WARNING1, "Attributes are not supperted\n"); */
+/* /\*           { *\/ */
+/* /\*             OIDL_Attr_Info *ai = cur->data; *\/ */
+/* /\*             IDL_tree curitem; *\/ */
+
+/* /\*             for(curitem = IDL_ATTR_DCL(cur).simple_declarations; curitem; curitem = IDL_LIST(curitem).next) { *\/ */
+/* /\*               ai = IDL_LIST(curitem).data->data; *\/ */
+             
+/* /\*               doskel(ai->op1, rinfo, ifid, ci); *\/ */
+/* /\*               if(ai->op2) *\/ */
+/* /\*                 doskel(ai->op2, rinfo, ifid, ci); *\/ */
+/* /\*             } *\/ */
+/* /\*           } *\/ */
+/*       break; */
+/*     default: */
+/*       break; */
+/*     } */
+/*       } */
+/*       g_free(ifid); */
+/*     } */
+/*     break; */
+/*   default: */
+/*     break; */
+/*   } */
+/* } */
+
+/* static void */
+/* ch_output_itypes (IDL_tree tree, OIDL_C_Info *ci) */
+/* { */
+/*     static int num_methods = 0; */
+
+/*     if (!tree) */
+/*             return; */
+
+/*     switch(IDL_NODE_TYPE(tree)) { */
+/*     case IDLN_MODULE: */
+/*             ch_output_itypes (IDL_MODULE(tree).definition_list, ci); */
+/*             break; */
+/*     case IDLN_LIST: { */
+/*             IDL_tree sub; */
+/*             for (sub = tree; sub; sub = IDL_LIST(sub).next) */
+/*                     ch_output_itypes (IDL_LIST(sub).data, ci); */
+/*     } */
+/*     break; */
+/*     case IDLN_ATTR_DCL: { */
+/*             OIDL_Attr_Info *ai = tree->data; */
+
+/*             IDL_tree curitem; */
+      
+/*             for(curitem = IDL_ATTR_DCL(tree).simple_declarations; curitem; */
+/*                 curitem = IDL_LIST(curitem).next) { */
+/*                     ai = IDL_LIST(curitem).data->data; */
+       
+/*                     ch_output_itypes (ai->op1, ci); */
+/*                     if(ai->op2) */
+/*                             ch_output_itypes (ai->op2, ci); */
+/*             } */
+/*     } */
+/*     break; */
+
+/*     case IDLN_INTERFACE: { */
+/*             char  *id; */
+
+/*             id = IDL_ns_ident_to_qstring (IDL_IDENT_TO_NS ( */
+/*                     IDL_INTERFACE (tree).ident), "_", 0); */
+
+/*             ch_output_itypes (IDL_INTERFACE(tree).body, ci); */
+      
+/*             fprintf (ci->fh, "#ifdef FORB_IDL_C_IMODULE_%s\n", */
+/*                      ci->c_base_name); */
+/*             fprintf (ci->fh, "static \n"); */
+/*             fprintf (ci->fh, "#else\n"); */
+/*             fprintf (ci->fh, "extern \n"); */
+/*             fprintf (ci->fh, "#endif\n"); */
+/*             fprintf (ci->fh, "Forb_IInterface %s__iinterface;\n", id); */
+
+/*             fprintf (ci->fh, "#define %s_IMETHODS_LEN %d\n", id, num_methods); */
+
+/*             if (num_methods == 0) */
+/*                     fprintf (ci->fh, "#define %s__imethods (Forb_IMethod*) NULL\n", id); */
+/*             else { */
+/*                     fprintf (ci->fh, "#ifdef FORB_IDL_C_IMODULE_%s\n", */
+/*                              ci->c_base_name); */
+/*                     fprintf (ci->fh, "static \n"); */
+/*                     fprintf (ci->fh, "#else\n"); */
+/*                     fprintf (ci->fh, "extern \n"); */
+/*                     fprintf (ci->fh, "#endif\n"); */
+/*                     fprintf (ci->fh, "Forb_IMethod %s__imethods[%s_IMETHODS_LEN];\n", id, id); */
+/*             } */
+
+
+/*             num_methods = 0; */
+
+/*             break; */
+/*     } */
+
+/*     case IDLN_OP_DCL: */
+/*             num_methods++; */
+/*             break; */
+/*     default: */
+/*             break; */
+/*     } */
+/* } */
diff --git a/src/forb/forb-idl/forb-idl-c-imodule.c b/src/forb/forb-idl/forb-idl-c-imodule.c
new file mode 100644 (file)
index 0000000..d4525ae
--- /dev/null
@@ -0,0 +1,235 @@
+#include "config.h"
+
+#include "forb-idl-c-backend.h"
+
+#include <string.h>
+#include "forb_config.h"
+
+static void
+ci_build_interfaces (OIDL_C_Info *ci,
+                    IDL_tree     tree)
+{
+       if (!tree)
+               return;
+
+       switch (IDL_NODE_TYPE (tree)) {
+       case IDLN_MODULE:
+               ci_build_interfaces (
+                       ci, IDL_MODULE (tree).definition_list);
+               break;
+       case IDLN_LIST: {
+               IDL_tree sub;
+               for (sub = tree; sub; sub = IDL_LIST (sub).next)
+                       ci_build_interfaces (
+                               ci, IDL_LIST (sub).data);
+               break;
+       }
+       case IDLN_INTERFACE: {
+               char *id;
+
+               id = IDL_ns_ident_to_qstring (IDL_IDENT_TO_NS (
+                       IDL_INTERFACE (tree).ident), "_", 0);
+
+               fprintf (ci->fh, "\t&%s__iinterface,\n", id);
+
+               g_free (id);
+
+               ci_build_interfaces (
+                       ci, IDL_INTERFACE(tree).body);
+               break;
+       }
+       default:
+               break;
+       }
+}
+
+static void
+ci_build_types (OIDL_C_Info *ci,
+               IDL_tree     tree,
+               guint       *count)
+{
+       if (!tree)
+               return;
+
+       switch (IDL_NODE_TYPE (tree)) {
+       case IDLN_MODULE:
+               ci_build_types (
+                       ci, IDL_MODULE (tree).definition_list, count);
+               break;
+       case IDLN_LIST: {
+               IDL_tree sub;
+               for (sub = tree; sub; sub = IDL_LIST (sub).next)
+                       ci_build_types (
+                               ci, IDL_LIST (sub).data, count);
+               break;
+       }
+       case IDLN_INTERFACE:
+               ci_build_types (
+                       ci, IDL_INTERFACE(tree).body, count);
+               break;
+       case IDLN_TYPE_DCL: {
+           IDL_tree sub;
+           for (sub = IDL_TYPE_DCL (tree).dcls; sub; sub = IDL_LIST (sub).next) {
+               IDL_tree ent = IDL_LIST (sub).data;
+               gchar *id;
+
+               id = forb_cbe_get_typespec_str (ent);
+
+               fprintf (ci->fh, "\tTC_%s,\n", id);
+               (*count)++;
+
+               g_free (id);
+           }
+
+           break;
+       }
+       case IDLN_TYPE_STRUCT: {
+               gchar *id;
+               IDL_tree l;
+
+               id = forb_cbe_get_typespec_str (tree);
+
+               fprintf (ci->fh, "\tTC_%s,\n", id);
+               (*count)++;
+
+               g_free (id);
+
+               /* check for nested structs/enums */
+               for (l = IDL_TYPE_STRUCT (tree).member_list; l; l = IDL_LIST (l).next) {
+                       IDL_tree dcl;
+
+                       g_assert (IDL_NODE_TYPE (IDL_LIST (l).data) == IDLN_MEMBER);
+                       dcl = IDL_MEMBER (IDL_LIST (l).data).type_spec;
+
+                       /* skip straight declarations */
+                       if (IDL_NODE_TYPE(dcl) == IDLN_TYPE_STRUCT ||
+                           IDL_NODE_TYPE(dcl) == IDLN_TYPE_UNION ||
+                           IDL_NODE_TYPE(dcl) == IDLN_TYPE_ENUM)
+                               ci_build_types (ci, dcl, count);
+               }
+               break;
+       };
+       case IDLN_TYPE_UNION: {
+               gchar *id;
+               IDL_tree l;
+
+               id = forb_cbe_get_typespec_str (tree);
+
+               fprintf (ci->fh, "\tTC_%s,\n", id);
+               (*count)++;
+
+               g_free (id);
+
+               /* if discriminator is an enum, register it */
+               if (IDL_NODE_TYPE (IDL_TYPE_UNION (tree).switch_type_spec) == IDLN_TYPE_ENUM)
+                       ci_build_types (
+                               ci, IDL_TYPE_UNION (tree).switch_type_spec, count);
+
+               /* check for nested structs/enums */
+               for (l = IDL_TYPE_UNION (tree).switch_body; l; l = IDL_LIST (l).next) {
+                       IDL_tree dcl;
+
+                       g_assert (IDL_NODE_TYPE (IDL_LIST (l).data) == IDLN_CASE_STMT);
+                       dcl = IDL_MEMBER (
+                                IDL_CASE_STMT (IDL_LIST (l).data).element_spec).type_spec;
+
+                       if (IDL_NODE_TYPE(dcl) == IDLN_TYPE_STRUCT ||
+                           IDL_NODE_TYPE(dcl) == IDLN_TYPE_UNION ||
+                           IDL_NODE_TYPE(dcl) == IDLN_TYPE_ENUM)
+                               ci_build_types (ci, dcl, count);
+               }
+               break;
+       }
+       case IDLN_EXCEPT_DCL: {
+               gchar *id;
+               IDL_tree l;
+
+               id = forb_cbe_get_typespec_str (tree);
+
+               fprintf (ci->fh, "\tTC_%s,\n", id);
+               (*count)++;
+
+               g_free (id);
+
+               /* check for nested structs/enums */
+               for (l = IDL_EXCEPT_DCL (tree).members; l; l = IDL_LIST (l).next) {
+                       IDL_tree dcl;
+
+                       g_assert (IDL_NODE_TYPE (IDL_LIST (l).data) == IDLN_MEMBER);
+                       dcl = IDL_MEMBER (IDL_LIST (l).data).type_spec;
+
+                       /* skip straight declarations */
+                       if (IDL_NODE_TYPE(dcl) == IDLN_TYPE_STRUCT ||
+                           IDL_NODE_TYPE(dcl) == IDLN_TYPE_UNION ||
+                           IDL_NODE_TYPE(dcl) == IDLN_TYPE_ENUM)
+                               ci_build_types (ci, dcl, count);
+               }
+               break;
+       }
+       case IDLN_TYPE_INTEGER:
+       case IDLN_TYPE_ANY:
+       case IDLN_TYPE_STRING:
+       case IDLN_TYPE_WIDE_STRING:
+       case IDLN_TYPE_CHAR:
+       case IDLN_TYPE_WIDE_CHAR:
+       case IDLN_TYPE_FLOAT:
+       case IDLN_TYPE_BOOLEAN:
+       case IDLN_TYPE_OCTET:
+       case IDLN_TYPE_SEQUENCE:
+       case IDLN_TYPE_ENUM:
+       case IDLN_IDENT:
+       case IDLN_FORWARD_DCL:
+       case IDLN_TYPE_OBJECT: {
+               gchar *id;
+
+               id = forb_cbe_get_typespec_str (tree);
+
+               fprintf (ci->fh, "\tTC_%s,\n", id);
+               (*count)++;
+
+               g_free (id);
+
+               break;
+       }
+       default:
+               break;
+       }
+}
+
+void
+forb_idl_output_c_imodule (IDL_tree       tree,
+                           OIDL_Run_Info *rinfo,
+                           OIDL_C_Info   *ci)
+{
+       guint count;
+
+       fprintf (ci->fh, OIDL_C_WARNING);
+       fprintf (ci->fh, "#include <string.h>\n");
+       fprintf (ci->fh, "#define FORB_IDL_C_IMODULE_%s\n\n",ci->c_base_name);
+
+       fprintf (ci->fh, "#include \"%s-common.c\"\n\n", ci->base_name);
+
+       fprintf (ci->fh, "#include <forb/orb-core/forb-small.h>\n\n");
+
+       fprintf (ci->fh, "static CORBA_TypeCode %s__itypes[] = {\n",
+                ci->c_base_name);
+
+       count = 0;
+       ci_build_types (ci, tree, &count);
+
+       fprintf (ci->fh, "\tNULL\n};\n\n");
+
+       fprintf (ci->fh, "static Forb_IInterface *%s__iinterfaces[] = {\n",
+                ci->c_base_name);
+
+       ci_build_interfaces (ci, tree);
+
+       fprintf (ci->fh, "\tNULL\n};\n");
+
+       fprintf (ci->fh, "Forb_IModule forb_imodule_data = {\n");
+       fprintf (ci->fh, "   %d,\n", FORB_CONFIG_SERIAL);
+       fprintf (ci->fh, "   %s__iinterfaces,\n", ci->c_base_name);
+       fprintf (ci->fh, " { %u, %u, %s__itypes, FALSE }\n",
+                count, count, ci->c_base_name);
+       fprintf (ci->fh, "};\n\n");
+}
diff --git a/src/forb/forb-idl/forb-idl-c-skelimpl.c b/src/forb/forb-idl/forb-idl-c-skelimpl.c
new file mode 100644 (file)
index 0000000..923b12c
--- /dev/null
@@ -0,0 +1,603 @@
+#include "config.h"
+
+#include "forb-idl-c-backend.h"
+
+/* This file copied from the old IDL compiler forb-c-skelimpl.c, with minimal changes. */
+
+static void forb_cbe_write_skelimpl(FILE *outfile, IDL_tree tree, const char *hdrname);
+
+void
+forb_idl_output_c_skelimpl(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
+{
+       forb_cbe_write_skelimpl(ci->fh, tree, ci->base_name);
+}
+
+#include <ctype.h>
+#include <errno.h>
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* Abbreviations used here:
+   "cbe" stands for "C backend"
+   "hdr" -> "header" (duh :)
+   "of" -> "output file"
+   "ns" -> "name space"
+*/
+
+typedef struct {
+       FILE *of;
+       IDL_tree tree;
+       enum { PASS_SERVANTS, PASS_PROTOS, PASS_EPVS, PASS_VEPVS,
+              PASS_IMPLSTUBS, PASS_LAST } pass;
+} CBESkelImplInfo;
+
+static const char *passnames[] = {
+       "App-specific servant structures",
+       "Implementation stub prototypes",
+       "epv structures",
+       "vepv structures",
+       "Stub implementations",
+       "Boohoo!"
+};
+
+static void forb_cbe_ski_process_piece(CBESkelImplInfo *ski);
+static void cbe_ski_do_list(CBESkelImplInfo *ski);
+static void cbe_ski_do_inherited_attr_dcl(CBESkelImplInfo *ski, IDL_tree current_interface);
+static void cbe_ski_do_attr_dcl(CBESkelImplInfo *ski);
+static void cbe_ski_do_inherited_op_dcl(CBESkelImplInfo *ski, IDL_tree current_interface);
+static void cbe_ski_do_op_dcl(CBESkelImplInfo *ski);
+static void cbe_ski_do_param_dcl(CBESkelImplInfo *ski);
+static void cbe_ski_do_interface(CBESkelImplInfo *ski);
+static void cbe_ski_do_module(CBESkelImplInfo *ski);
+
+static void
+forb_cbe_write_skelimpl(FILE *outfile, IDL_tree tree, const char *hdrname)
+{
+       CBESkelImplInfo ski = {NULL, NULL, PASS_SERVANTS};
+
+       ski.of = outfile;
+       ski.tree = tree;
+
+       g_return_if_fail(IDL_NODE_TYPE(tree) == IDLN_LIST);
+
+       fprintf(outfile, "/* This is a template file generated by command */\n");
+       fprintf(outfile, "/* forb-idl-2 --skeleton-impl %s.idl */\n", hdrname);
+       fprintf(outfile, "/* User must edit this file, inserting servant  */\n");
+       fprintf(outfile, "/* specific code between markers. */\n\n");
+
+       fprintf(outfile, "#include \"%s.h\"\n", hdrname);
+
+       for(ski.pass = PASS_SERVANTS; ski.pass < PASS_LAST; ski.pass++) {
+               fprintf(ski.of, "\n/*** %s ***/\n\n", passnames[ski.pass]);
+               forb_cbe_ski_process_piece(&ski);
+       }
+}
+
+static void
+forb_cbe_ski_process_piece(CBESkelImplInfo *ski)
+{
+       /* I'm not implementing this as an array of function pointers
+          because we may want to do special logic for particular cases in
+          the future. Hope this is clear enough. -ECL */
+
+       switch(IDL_NODE_TYPE(ski->tree)) {
+       case IDLN_ATTR_DCL:
+               cbe_ski_do_attr_dcl(ski);
+               break;
+       case IDLN_INTERFACE:
+               cbe_ski_do_interface(ski);
+               break;
+       case IDLN_LIST:
+               cbe_ski_do_list(ski);
+               break;
+       case IDLN_MODULE:
+               cbe_ski_do_module(ski);
+               break;
+       case IDLN_OP_DCL:
+               cbe_ski_do_op_dcl(ski);
+               break;
+       case IDLN_PARAM_DCL:
+               cbe_ski_do_param_dcl(ski);
+               break;
+       default:
+               break;
+       }
+}
+
+static void
+cbe_ski_do_module(CBESkelImplInfo *ski)
+{
+       CBESkelImplInfo subski = *ski;
+       subski.tree = IDL_MODULE(ski->tree).definition_list;
+       cbe_ski_do_list(&subski);
+}
+
+/* Returns 1 if the previous character written to f  */
+/* was '\n', 0 otherwise. */
+static inline unsigned char 
+prev_char_is_nl(FILE *f)
+{
+        char c;
+       long pos;
+       size_t count;
+        unsigned char retv = 0;
+
+       pos = ftell(f);
+       if (pos < sizeof(char)) 
+               return 0; /* beginning of file */
+
+        if (fseek(f, (-1)*sizeof(char), SEEK_CUR)) 
+               goto out;
+
+       count = fread((void*)&c, sizeof(char), 1, f);
+        if (sizeof(char) == count) 
+               retv = ('\n' == c) ? 1 : 0;
+       
+out:
+       fseek(f, pos, SEEK_SET);
+        return retv;
+}
+
+static void
+cbe_ski_do_list(CBESkelImplInfo *ski)
+{
+       CBESkelImplInfo subski = *ski;
+       IDL_tree curitem;
+
+       for(curitem = ski->tree; curitem; curitem = IDL_LIST(curitem).next) {
+               subski.tree = IDL_LIST(curitem).data;
+               forb_cbe_ski_process_piece(&subski);
+               if(!prev_char_is_nl(ski->of))
+                       fprintf(ski->of, "\n");
+       }
+}
+
+static void 
+cbe_ski_do_attr_dcl_internal(CBESkelImplInfo *ski, IDL_tree current_interface, gboolean inherited)
+{
+       IDL_tree curop, curitem;
+       GString *attrname = g_string_new(NULL);
+       CBESkelImplInfo subski = *ski;
+
+       if(ski->pass == PASS_SERVANTS) {
+               for(curitem = IDL_ATTR_DCL(ski->tree).simple_declarations; curitem;
+                   curitem = IDL_LIST(curitem).next) {
+                       forb_cbe_write_typespec(ski->of, IDL_ATTR_DCL(ski->tree).param_type_spec);
+                       fprintf(ski->of, " attr_%s;\n", IDL_IDENT(IDL_LIST(curitem).data).str);
+               }
+       }
+
+       for(curitem = IDL_ATTR_DCL(ski->tree).simple_declarations;
+           curitem; curitem = IDL_LIST(curitem).next) {
+
+               /* Fake the attribute get/set methods as operation declarations */
+               IDL_tree ident, ns_data_save;
+               int i;
+
+               for (i = 0; i < 2; ++i) {
+
+                       if (i && IDL_ATTR_DCL(ski->tree).f_readonly)
+                               break;
+                       /* Output the operation on this attribute */
+                       g_string_printf(attrname, i ? "_set_%s" : "_get_%s",
+                                       IDL_IDENT(IDL_LIST(curitem).data).str);
+                       ident = IDL_ident_new(g_strdup(attrname->str));
+           
+                       /* Tell the ident where our namespace node is, and request a return value
+                          if this is the _get operation */
+                       IDL_IDENT_TO_NS(ident) = IDL_IDENT_TO_NS(IDL_LIST(curitem).data);
+                       curop = IDL_op_dcl_new(0, i == 0 ?
+                                              IDL_ATTR_DCL(ski->tree).param_type_spec : NULL,
+                                              ident, NULL, NULL, NULL);
+           
+                       curop->up = ski->tree->up;
+                       subski.tree = curop;
+           
+                       /* Save the namespace ident (IDL_GENTREE data) reference, assign
+                          back to the temporary tree, output the operation, then restore
+                          the namespace ident link */
+                       ns_data_save = IDL_GENTREE(IDL_IDENT_TO_NS(IDL_LIST(curitem).data)).data;
+                       IDL_GENTREE(IDL_IDENT_TO_NS(IDL_LIST(curitem).data)).data = ident;
+
+                       if (i) {
+                               /* The set routine also needs the value, so we
+                                  temporarily add that to the operation
+                                  declaration */
+                               IDL_OP_DCL(curop).parameter_dcls = IDL_list_new(
+                                       IDL_param_dcl_new(IDL_PARAM_IN,
+                                                         IDL_ATTR_DCL(ski->tree).param_type_spec,
+                                                         IDL_ident_new(g_strdup("value"))));
+                       }
+           
+                       if(inherited==TRUE)
+                               cbe_ski_do_inherited_op_dcl(&subski, current_interface);
+                       else
+                               forb_cbe_ski_process_piece(&subski);
+
+                       /* Restore the fake link to the original in the namespace */
+                       IDL_GENTREE(IDL_IDENT_TO_NS(IDL_LIST(curitem).data)).data = ns_data_save;
+
+                       if (i) {
+                               /* Free only what we've created for the fake node, so remove 
+                                  the attribute node element and then free the rest */
+                               IDL_PARAM_DCL(IDL_LIST(
+                                                     IDL_OP_DCL(curop).parameter_dcls).data).param_type_spec = NULL;
+                       }
+           
+                       /* Remove what we've "borrowed" from ATTR_DCL from the
+                          fake curop node then free the rest */
+                       IDL_OP_DCL(curop).op_type_spec = NULL;
+                       IDL_tree_free(curop);
+               }
+       }
+
+       g_string_free(attrname, TRUE);
+}
+
+static void 
+cbe_ski_do_attr_dcl(CBESkelImplInfo *ski)
+{
+       cbe_ski_do_attr_dcl_internal(ski, NULL, FALSE);
+}
+
+void
+cbe_ski_do_inherited_attr_dcl(CBESkelImplInfo *ski, IDL_tree current_interface)
+{
+       cbe_ski_do_attr_dcl_internal(ski, current_interface, TRUE);
+}
+
+static void
+cbe_ski_do_op_dcl(CBESkelImplInfo *ski)
+{
+       /* If you fix anything here, please also fix it in
+          cbe_ski_do_inherited_op_dcl(), which is almost a
+          cut-and-paste of this routine */
+
+       char *id, *id2;
+       IDL_tree curitem, op;
+       int level;
+       CBESkelImplInfo subski = *ski;
+
+       switch(ski->pass) {
+       case PASS_PROTOS:
+       case PASS_IMPLSTUBS:
+               curitem = IDL_get_parent_node(ski->tree, IDLN_INTERFACE, &level);
+               g_assert(curitem);
+
+               id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_OP_DCL(ski->tree).ident), "_", 0);    
+               id2 = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(curitem).ident), "_", 0);
+
+               /* protect with #ifdef block  */
+               if(PASS_PROTOS == ski->pass) 
+                       fprintf(ski->of, "#if !defined(_decl_impl_");
+               else
+                       fprintf(ski->of, "#if !defined(_impl_");
+               fprintf(ski->of, "%s_)\n", id);
+
+               if(PASS_PROTOS == ski->pass) 
+                       fprintf(ski->of, "#define _decl_impl_");
+               else
+                       fprintf(ski->of, "#define _impl_");
+               fprintf(ski->of, "%s_ 1\n", id);
+
+               fprintf(ski->of, "static ");
+               forb_cbe_write_param_typespec(ski->of, ski->tree);    
+               fprintf(ski->of, "\nimpl_%s(impl_POA_%s *servant,\n", id, id2);
+               g_free(id); g_free(id2);
+    
+               op = ski->tree;
+               for(curitem = IDL_OP_DCL(ski->tree).parameter_dcls;
+                   curitem; curitem = IDL_LIST(curitem).next) {
+                       subski.tree = IDL_LIST(curitem).data;
+                       forb_cbe_ski_process_piece(&subski);
+               }
+
+               if(IDL_OP_DCL(op).context_expr)
+                       fprintf(ski->of, "CORBA_Context ctx,\n");
+
+               fprintf(ski->of, "CORBA_Environment *ev)");
+               if(ski->pass == PASS_IMPLSTUBS) {
+                       fprintf(ski->of, "\n{\n");
+                       if(IDL_OP_DCL(op).op_type_spec) {
+                               forb_cbe_write_param_typespec(ski->of, ski->tree);
+                               fprintf(ski->of, " retval;\n");
+                               fprintf(ski->of, " /* ------   insert method code here   ------ */\n");
+                               fprintf(ski->of, " /* ------ ---------- end ------------ ------ */\n");
+                               fprintf(ski->of, "\nreturn retval;\n");
+                       }
+                       else
+                       {       
+                               fprintf(ski->of, " /* ------   insert method code here   ------ */\n");
+                               fprintf(ski->of, " /* ------ ---------- end ------------ ------ */\n");
+                       }
+                       fprintf(ski->of, "}\n");
+               } else /* PASS_PROTOS */
+                       fprintf(ski->of, ";\n");
+
+               fprintf(ski->of, "#endif\n\n"); /* end of protective #ifdef block */
+               break; /* End PASS_PROTOS | PASS_IMPLSTUBS */
+       case PASS_EPVS:
+               id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_OP_DCL(ski->tree).ident), "_", 0);
+               fprintf(ski->of, "(gpointer)&impl_%s,\n", id);
+               g_free(id);
+               break;
+       default:
+               break;
+       }
+}
+
+static void
+cbe_ski_do_inherited_op_dcl(CBESkelImplInfo *ski, IDL_tree current_interface)
+{
+       char *id, *id2;
+       IDL_tree ident, curitem, intf, op;
+       int level;
+       CBESkelImplInfo subski = *ski;
+
+       id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(current_interface).ident), "_", 0);
+       intf = IDL_get_parent_node(ski->tree, IDLN_INTERFACE, NULL);
+       id2 = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(intf).ident), "_", 0);
+
+       ident=IDL_OP_DCL(ski->tree).ident;
+       g_assert(ident);
+
+       switch(ski->pass) {
+       case PASS_PROTOS:
+       case PASS_IMPLSTUBS:
+               curitem = IDL_get_parent_node(ski->tree, IDLN_INTERFACE, &level);
+               g_assert(curitem);
+
+               /* protect with #ifdef block  */
+               if(PASS_PROTOS == ski->pass) 
+                       fprintf(ski->of, "#if !defined(_decl_impl_");
+               else
+                       fprintf(ski->of, "#if !defined(_impl_");
+               fprintf(ski->of, "%s_%s_)\n", id, IDL_IDENT(ident).str);
+
+               if(PASS_PROTOS == ski->pass) 
+                       fprintf(ski->of, "#define _decl_impl_");
+               else
+                       fprintf(ski->of, "#define _impl_");
+               fprintf(ski->of, "%s_%s_ 1\n", id, IDL_IDENT(ident).str);
+
+               fprintf(ski->of, "static ");
+               forb_cbe_write_param_typespec(ski->of, ski->tree);
+               fprintf(ski->of, "\nimpl_%s_%s(impl_POA_%s *servant,\n", id, IDL_IDENT(ident).str, id);
+    
+               op = ski->tree;
+               for(curitem = IDL_OP_DCL(ski->tree).parameter_dcls;
+                   curitem; curitem = IDL_LIST(curitem).next) {
+                       subski.tree = IDL_LIST(curitem).data;
+                       forb_cbe_ski_process_piece(&subski);
+               }
+
+               if(IDL_OP_DCL(op).context_expr)
+                       fprintf(ski->of, "CORBA_Context ctx,\n");
+
+               fprintf(ski->of, "CORBA_Environment *ev)");
+               if(ski->pass == PASS_IMPLSTUBS) {
+                       fprintf(ski->of, "\n{\n");
+                       if(IDL_OP_DCL(op).op_type_spec) {
+                               forb_cbe_write_param_typespec(ski->of, ski->tree);
+                               fprintf(ski->of, " retval;\n");
+                               fprintf(ski->of, " /* ------   insert method code here   ------ */\n");
+                               fprintf(ski->of, " /* ------ ---------- end ------------ ------ */\n");
+                               fprintf(ski->of, "\nreturn retval;\n");
+                       }
+                       else
+                       {       
+                               fprintf(ski->of, " /* ------   insert method code here   ------ */\n");
+                               fprintf(ski->of, " /* ------ ---------- end ------------ ------ */\n");
+                       }
+                       fprintf(ski->of, "}\n");
+               } else /* PASS_PROTOS */
+                       fprintf(ski->of, ";\n");
+
+               fprintf(ski->of, "#endif\n\n"); /* end of protective #ifdef block */
+               break; /* End PASS_PROTOS | PASS_IMPLSTUBS */
+       case PASS_EPVS:
+               ident=IDL_OP_DCL(ski->tree).ident;
+               g_assert(ident);
+
+               fprintf(ski->of, "(gpointer)&impl_%s_%s,\n", id, IDL_IDENT(ident).str);
+       default:
+               break;
+       }
+
+       g_free(id);
+       g_free(id2);
+}
+
+static void
+cbe_ski_do_param_dcl(CBESkelImplInfo *ski)
+{
+       forb_cbe_write_param_typespec(ski->of, ski->tree);
+       fprintf(ski->of, " %s,\n", IDL_IDENT(IDL_PARAM_DCL(ski->tree).simple_declarator).str);
+}
+
+static void
+cbe_ski_do_interface_vepv_entry(IDL_tree interface, CBESkelImplInfo *ski)
+{
+       char *id, *inherit_id;
+
+       if(interface==ski->tree) {
+               id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(ski->tree).ident), "_", 0);
+               fprintf(ski->of, "&impl_%s_epv,\n", id);
+               g_free(id);
+               return;
+       }
+
+       id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(ski->tree).ident), "_", 0);
+       inherit_id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(interface).ident),
+                                            "_", 0);
+       fprintf(ski->of, "&impl_%s_%s_epv,\n", id, inherit_id);
+
+       g_free(id);
+       g_free(inherit_id);
+}
+
+static void
+cbe_ski_do_inherited_methods(IDL_tree interface, CBESkelImplInfo *ski)
+{
+       CBESkelImplInfo subski= *ski;
+       IDL_tree curitem;
+       char *id = NULL, *inherit_id = NULL; /* Quiet gcc */
+
+       if(interface==ski->tree)
+               return;
+
+       if(ski->pass==PASS_EPVS) {
+               id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(ski->tree).ident),
+                                            "_", 0);
+               inherit_id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(interface).ident),
+                                                    "_", 0);
+               /* protect with #ifdef block  */
+               fprintf(ski->of, "#if !defined(_impl_%s_%s_epv_)\n", id, inherit_id);
+               fprintf(ski->of, "#define _impl_%s_%s_epv_ 1\n", id, inherit_id);
+               fprintf(ski->of, "static POA_%s__epv impl_%s_%s_epv = {\nNULL, /* _private */\n", inherit_id, id, inherit_id);
+       }
+
+       for(curitem = IDL_INTERFACE(interface).body; curitem; curitem=IDL_LIST(curitem).next) {
+               subski.tree=IDL_LIST(curitem).data;
+
+               switch(IDL_NODE_TYPE(IDL_LIST(curitem).data)) {
+               case IDLN_OP_DCL:
+                       cbe_ski_do_inherited_op_dcl(&subski, ski->tree);
+                       break;
+               case IDLN_ATTR_DCL:
+                       cbe_ski_do_inherited_attr_dcl(&subski, ski->tree);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       if(ski->pass==PASS_EPVS) {
+               fprintf(ski->of, "};\n"); 
+               fprintf(ski->of, "#endif\n"); /* end of protective #ifdef block */
+
+               g_free(id);
+               g_free(inherit_id);
+       }
+}
+
+static void
+cbe_ski_do_interface(CBESkelImplInfo *ski)
+{
+       char *id;
+       CBESkelImplInfo subski = *ski;
+
+       id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(ski->tree).ident), "_", 0);
+
+       switch(ski->pass) {
+       case PASS_SERVANTS:
+               /* protect with #ifdef block  */
+               fprintf(ski->of, "#if !defined(_typedef_impl_POA_%s_)\n", id);
+               fprintf(ski->of, "#define _typedef_impl_POA_%s_ 1\n", id);
+
+               fprintf(ski->of, "typedef struct {\nPOA_%s servant;\nPortableServer_POA poa;\n", id);
+               subski.tree = IDL_INTERFACE(ski->tree).body;
+               cbe_ski_do_list(&subski);
+               IDL_tree_traverse_parents(ski->tree, (GFunc)&cbe_ski_do_inherited_methods, ski);
+               fprintf(ski->of, "   /* ------ add private attributes here ------ */\n");
+               fprintf(ski->of, "   /* ------ ---------- end ------------ ------ */\n");
+               fprintf(ski->of, "} impl_POA_%s;\n", id);
+
+               fprintf(ski->of, "#endif\n\n"); /* end of protective #ifdef block */
+               break;
+       case PASS_EPVS:
+               /* protect with #ifdef block  */
+               fprintf(ski->of, "#if !defined(_impl_%s_base_epv_)\n", id);
+               fprintf(ski->of, "#define _impl_%s_base_epv_ 1\n", id);
+               fprintf(ski->of, "static PortableServer_ServantBase__epv impl_%s_base_epv = {\n", id);
+               fprintf(ski->of, "NULL,             /* _private data */\n");
+               fprintf(ski->of, "(gpointer) & impl_%s__destroy, /* finalize routine */\n", id);
+               fprintf(ski->of, "NULL,             /* default_POA routine */\n");
+               fprintf(ski->of, "};\n");
+               fprintf(ski->of, "#endif\n\n"); /* end of protective #ifdef block */
+
+               /* protect with #ifdef block  */
+               fprintf(ski->of, "#if !defined(_impl_%s_epv_)\n", id);
+               fprintf(ski->of, "#define _impl_%s_epv_ 1\n", id);
+               fprintf(ski->of, "static POA_%s__epv impl_%s_epv = {\nNULL, /* _private */\n", id, id);
+               subski.tree = IDL_INTERFACE(ski->tree).body;
+               cbe_ski_do_list(&subski);
+               fprintf(ski->of, "};\n");
+               fprintf(ski->of, "#endif\n\n"); /* end of protective #ifdef block */
+
+               IDL_tree_traverse_parents(ski->tree, (GFunc)&cbe_ski_do_inherited_methods, ski);
+               break;
+       case PASS_VEPVS:
+               /* protect with #ifdef block  */
+               fprintf(ski->of, "#if !defined(_impl_%s_vepv_)\n", id);
+               fprintf(ski->of, "#define _impl_%s_vepv_ 1\n", id);
+
+               fprintf(ski->of, "static POA_%s__vepv impl_%s_vepv = {\n", id, id);
+               fprintf(ski->of, "&impl_%s_base_epv,\n", id);
+               IDL_tree_traverse_parents(ski->tree, (GFunc)&cbe_ski_do_interface_vepv_entry, ski);
+               fprintf(ski->of, "};\n");
+
+               fprintf(ski->of, "#endif\n\n"); /* end of protective #ifdef block */
+               break;
+       case PASS_IMPLSTUBS:
+               /* protect __create with #ifdef block  */
+               fprintf(ski->of, "#if !defined(_impl_%s__create_)\n", id);
+               fprintf(ski->of, "#define _impl_%s__create_ 1\n", id);
+               fprintf(ski->of, "static %s impl_%s__create(PortableServer_POA poa, CORBA_Environment *ev)\n", id, id);
+               fprintf(ski->of, "{\n%s retval;\nimpl_POA_%s *newservant;\nPortableServer_ObjectId *objid;\n\n", id, id);
+               fprintf(ski->of, "newservant = g_new0(impl_POA_%s, 1);\n", id);
+               fprintf(ski->of, "newservant->servant.vepv = &impl_%s_vepv;\n", id);
+               fprintf(ski->of, "newservant->poa = (PortableServer_POA) CORBA_Object_duplicate((CORBA_Object)poa, ev);\n");
+               fprintf(ski->of, "POA_%s__init((PortableServer_Servant)newservant, ev);\n", id);
+               fprintf(ski->of, "   /* Before servant is going to be activated all\n");
+               fprintf(ski->of, "    * private attributes must be initialized.  */\n"); 
+               fprintf(ski->of, "\n");
+               fprintf(ski->of, "   /* ------ init private attributes here ------ */\n");
+               fprintf(ski->of, "   /* ------ ---------- end ------------- ------ */\n");
+               fprintf(ski->of, "\n");
+               fprintf(ski->of, "objid = PortableServer_POA_activate_object(poa, newservant, ev);\n");
+               fprintf(ski->of, "CORBA_free(objid);\n");
+               fprintf(ski->of, "retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);\n");
+               fprintf(ski->of, "\nreturn retval;\n}\n");
+               fprintf(ski->of, "#endif\n\n"); /* end of protective #ifdef block */
+
+               /* protect __destroy with #ifdef block  */
+               fprintf(ski->of, "#if !defined(_impl_%s__destroy_)\n", id);
+               fprintf(ski->of, "#define _impl_%s__destroy_ 1\n", id);
+               fprintf(ski->of, "static void\nimpl_%s__destroy(impl_POA_%s *servant, CORBA_Environment *ev)\n{\n", id, id);
+               fprintf(ski->of, "    CORBA_Object_release ((CORBA_Object) servant->poa, ev);\n\n");
+               fprintf(ski->of, "    /* No further remote method calls are delegated to \n");
+               fprintf(ski->of, "    * servant and you may free your private attributes. */\n");
+               fprintf(ski->of, "   /* ------ free private attributes here ------ */\n");
+               fprintf(ski->of, "   /* ------ ---------- end ------------- ------ */\n");
+               fprintf(ski->of, "\nPOA_%s__fini((PortableServer_Servant)servant, ev);\n", id);
+               fprintf(ski->of, "\ng_free (servant);\n");
+               fprintf(ski->of, "}\n");
+               fprintf(ski->of, "#endif\n\n"); /* end of protective #ifdef block */
+
+               subski.tree = IDL_INTERFACE(ski->tree).body;
+               cbe_ski_do_list(&subski);
+               IDL_tree_traverse_parents(ski->tree, (GFunc)&cbe_ski_do_inherited_methods, ski);
+               break;
+       case PASS_PROTOS:
+               /* protect __destroy declaration with #ifdef block  */
+               fprintf(ski->of, "#if !defined(_decl_impl_%s__destroy_)\n", id);
+               fprintf(ski->of, "#define _decl_impl_%s__destroy_ 1\n", id);
+               fprintf(ski->of, "static void impl_%s__destroy(impl_POA_%s *servant,\nCORBA_Environment *ev);\n", id, id);
+               fprintf(ski->of, "#endif\n\n"); /* end of protective #ifdef block */
+
+               subski.tree = IDL_INTERFACE(ski->tree).body;
+               cbe_ski_do_list(&subski);
+               IDL_tree_traverse_parents(ski->tree, (GFunc)&cbe_ski_do_inherited_methods, ski);
+               break;
+       default:
+               break;
+       }
+
+       g_free(id);
+}
diff --git a/src/forb/forb-idl/forb-idl-c-skels.c b/src/forb/forb-idl/forb-idl-c-skels.c
new file mode 100644 (file)
index 0000000..1d35338
--- /dev/null
@@ -0,0 +1,542 @@
+#include "config.h"
+
+#include "forb-idl-c-backend.h"
+
+#include <string.h>
+
+typedef struct {
+       OIDL_C_Info *ci;
+       GSList      *oplist;
+       int          curlevel;
+} CBESkelInterfaceTraverseInfo;
+
+typedef struct {
+       char     *iface_id;
+       char     *opname;
+       IDL_tree  op;
+       int       idx;
+} CBESkelOpInfo;
+
+static void cbe_skel_do_interface(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci);
+
+static void
+ck_output_poastuff(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
+{
+  if( !tree || (tree->declspec & IDLF_DECLSPEC_PIDL)!=0 ) 
+    return;
+
+  switch(IDL_NODE_TYPE(tree)) {
+  case IDLN_MODULE:
+    ck_output_poastuff(IDL_MODULE(tree).definition_list, rinfo, ci);
+    break;
+  case IDLN_LIST:
+    {
+      IDL_tree sub;
+      for(sub = tree; sub; sub = IDL_LIST(sub).next) {
+       ck_output_poastuff(IDL_LIST(sub).data, rinfo, ci);
+      }
+    }
+    break;
+  case IDLN_INTERFACE:
+    cbe_skel_do_interface(tree, rinfo, ci);
+    break;
+  default:
+    break;
+  }
+}
+
+/* static gint */
+/* cbe_skel_compare_op_dcls(CBESkelOpInfo *op1, CBESkelOpInfo *op2) */
+/* { */
+/*   return strcmp(op1->opname, op2->opname); */
+/* } */
+
+/* static void */
+/* cbe_skel_free_op_info(CBESkelOpInfo *op) */
+/* { */
+/*   g_free(op->opname); */
+/*   g_free(op->iface_id); */
+/*   g_free(op); */
+/* } */
+
+/* static void */
+/* cbe_skel_interface_add_relayer (IDL_tree intf, CBESkelInterfaceTraverseInfo *iti) */
+/* { */
+/*   CBESkelOpInfo *newopi; */
+/*   IDL_tree curitem, curdcl, curattr, curattrdcl; */
+/*   char *iface_id; */
+/*   int   idx = 0; */
+
+/*   iface_id = */
+/*     IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(intf).ident), */
+/*                         "_", 0); */
+
+/*   for(curitem = IDL_INTERFACE(intf).body; curitem; */
+/*       curitem = IDL_LIST(curitem).next) { */
+/*     curdcl = IDL_LIST(curitem).data; */
+
+/*     switch(IDL_NODE_TYPE(curdcl)) { */
+/*     case IDLN_OP_DCL: */
+/*       newopi = g_new0(CBESkelOpInfo, 1); */
+/*       newopi->iface_id = g_strdup(iface_id); */
+/*       newopi->opname = g_strdup(IDL_IDENT(IDL_OP_DCL(curdcl).ident).str); */
+/*       newopi->idx = idx++; */
+/*       iti->oplist = g_slist_insert_sorted(iti->oplist, newopi, */
+/*                                       (GCompareFunc)cbe_skel_compare_op_dcls); */
+/*       break; */
+/*     case IDLN_ATTR_DCL: */
+/*       for(curattr = IDL_ATTR_DCL(curdcl).simple_declarations; */
+/*       curattr; curattr = IDL_LIST(curattr).next) { */
+/*     curattrdcl = IDL_LIST(curattr).data; */
+
+/*     newopi = g_new0(CBESkelOpInfo, 1); */
+/*     newopi->iface_id = g_strdup(iface_id); */
+/*     newopi->opname = g_strdup_printf("_get_%s", IDL_IDENT(curattrdcl).str); */
+/*     newopi->idx = idx++; */
+/*     iti->oplist = g_slist_insert_sorted(iti->oplist, newopi, */
+/*                                         (GCompareFunc)cbe_skel_compare_op_dcls); */
+/*     if(!IDL_ATTR_DCL(curdcl).f_readonly) { */
+/*       newopi = g_new0(CBESkelOpInfo, 1); */
+/*       newopi->iface_id = g_strdup(iface_id); */
+/*       newopi->opname = g_strdup_printf("_set_%s", IDL_IDENT(curattrdcl).str); */
+/*       newopi->idx = idx++; */
+/*       iti->oplist = g_slist_insert_sorted(iti->oplist, newopi, */
+/*                                           (GCompareFunc)cbe_skel_compare_op_dcls); */
+/*     } */
+/*       } */
+/*       break; */
+/*     default: */
+/*       break; */
+/*     } */
+/*   } */
+
+/*   g_free(iface_id); */
+/* } */
+
+/* static void */
+/* cbe_skel_interface_print_relayers(const CBESkelInterfaceTraverseInfo *iti) */
+/* { */
+/*   CBESkelInterfaceTraverseInfo subiti = *iti; */
+/*   GSList *curnode; */
+/*   CBESkelOpInfo *opi; */
+/*   char curchar; */
+
+/*   curnode = iti->oplist; */
+/*   subiti.curlevel = iti->curlevel+1; */
+/*   fprintf(iti->ci->fh, "switch(opname[%d]) {\n", iti->curlevel); */
+/*   while(curnode) { */
+/*     opi = (CBESkelOpInfo *)curnode->data; */
+/*     if(iti->curlevel > strlen(opi->opname)) { */
+/*       curnode = g_slist_next(curnode); */
+/*       continue; */
+/*     } */
+/*     curchar = opi->opname[iti->curlevel]; */
+/*     if(curchar) */
+/*       fprintf(iti->ci->fh, "case '%c':\n", curchar); */
+/*     else */
+/*       fprintf(iti->ci->fh, "case '\\0':\n"); */
+/*     subiti.oplist = NULL; */
+/*     while(curnode && ((CBESkelOpInfo *)curnode->data)->opname[iti->curlevel] */
+/*       == curchar) { */
+/*       subiti.oplist = g_slist_append(subiti.oplist, curnode->data); */
+/*       curnode = g_slist_next(curnode); */
+/*     } */
+
+/*     if(g_slist_length(subiti.oplist) > 1) { */
+/*       if(curchar) */
+/*     cbe_skel_interface_print_relayers(&subiti); */
+/*       else */
+/*     g_error("two ops with same name!!!!"); */
+/*     } else { */
+/*       if(strlen(opi->opname + iti->curlevel)) */
+/*     fprintf(iti->ci->fh, "if(strcmp((opname + %d), \"%s\")) break;\n", */
+/*             iti->curlevel + 1, opi->opname + iti->curlevel+1); */
+/*       fprintf(iti->ci->fh, "*impl = (gpointer)servant->vepv->%s_epv->%s;\n", */
+/*           opi->iface_id, opi->opname); */
+/*       fprintf(iti->ci->fh, "{Forb_IInterface *volatile _t_=&%s__iinterface;*m_data = (gpointer)&_t_->methods._buffer [%d];}\n", */
+/*           opi->iface_id, opi->idx); */
+/*       fprintf(iti->ci->fh, "return (ForbSmallSkeleton)_FORB_skel_small_%s_%s;\n", */
+/*           opi->iface_id, opi->opname); */
+/*     } */
+/*     fprintf(iti->ci->fh, "break;\n"); */
+/*     g_slist_free(subiti.oplist); */
+/*   } */
+/*   fprintf(iti->ci->fh, "default: break; \n}\n"); */
+/* } */
+
+/* static void */
+/* cbe_skel_interface_print_relayer(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci) */
+/* { */
+/*   char *id; */
+/*   CBESkelInterfaceTraverseInfo iti; */
+
+/*   id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(tree).ident), "_", 0); */
+/*   fprintf(ci->fh, "static ForbSmallSkeleton get_skel_small_%s(POA_%s *servant,\nconst char *opname," */
+/*       "gpointer *m_data, gpointer *impl)\n{\n", id, id); */
+
+/*   iti.ci = ci; */
+/*   iti.oplist = NULL; */
+/*   iti.curlevel = 0; */
+
+/*   IDL_tree_traverse_parents(tree, */
+/*                         (GFunc)cbe_skel_interface_add_relayer, &iti); */
+
+/*   cbe_skel_interface_print_relayers(&iti); */
+
+/*   g_slist_foreach(iti.oplist, (GFunc)cbe_skel_free_op_info, NULL); */
+/*   g_slist_free(iti.oplist); */
+
+/*   fprintf(ci->fh, "return NULL;\n"); */
+/*   fprintf(ci->fh, "}\n\n"); */
+
+/*   g_free(id); */
+/* } */
+
+typedef struct {
+       OIDL_C_Info *ci;
+       const char  *for_id;
+} CBESkelVEPVMapTraverseInfo;
+
+/* static void */
+/* cbe_skel_interface_print_vepvmap_offsets (IDL_tree node, CBESkelVEPVMapTraverseInfo *ti) */
+/* { */
+/*     char *id; */
+/*     id = IDL_ns_ident_to_qstring (IDL_IDENT_TO_NS (IDL_INTERFACE (node).ident), "_", 0); */
+/*     fprintf (ti->ci->fh, "(CORBA_unsigned_long) %s__classid,\n", id); */
+/*     fprintf (ti->ci->fh, "FORB_VEPV_OFFSET (POA_%s__vepv, %s_epv),\n", ti->for_id, id); */
+/*     g_free (id); */
+/* } */
+
+/**
+ * If the type specified in @a type_spec is dynamically allocated
+ * (such as string, sequence or object reference), the parameters of
+ * this type must be freed after they are not needed. For input
+ * parameter this is after the implementation is called, for out and
+ * inout return parameters after the returned value is serialized.
+ */
+static void free_memory_if_needed(IDL_tree type_spec, const char *name, int n, OIDL_C_Info *ci)
+{
+  type_spec = forb_cbe_get_typespec(type_spec);
+  /* forb_idl_print_node(type_spec, 7); */
+  switch(IDL_NODE_TYPE(type_spec)) {
+  case IDLN_TYPE_STRING:
+  case IDLN_TYPE_WIDE_STRING:
+    fprintf(ci->fh, "    ");
+    fprintf(ci->fh, "forb_free(%s);\n", name);
+    break;
+  case IDLN_TYPE_ARRAY:
+    break;
+  case IDLN_TYPE_SEQUENCE: {
+    char *dot = n==2?"->":".";
+    IDL_tree simple_type = forb_cbe_get_typespec(IDL_TYPE_SEQUENCE(type_spec).simple_type_spec);
+
+    fprintf(ci->fh, "    if (CORBA_sequence_get_release(%s%s)) {\n",
+           n==2?"":"&",name);
+    if (IDLN_NATIVE == IDL_NODE_TYPE(simple_type)) {
+      fprintf(ci->fh, "      int i;\n"
+                     "      for (i=0; i<%s%s_length; i++)\n"
+                     "          %s_free(%s%s_buffer[i]);\n",
+             name, dot, forb_cbe_get_typespec_str(IDL_NATIVE(type_spec).ident),
+             name, dot);
+    }
+    fprintf(ci->fh, "      forb_free(%s%s_buffer);\n"
+                   "    }\n", name, dot);
+    if (n==2) {
+           fprintf(ci->fh, "    ");
+           fprintf(ci->fh, "forb_free(%s);\n", name);
+    }
+    break;
+  }
+  case IDLN_NATIVE:
+    fprintf(ci->fh, "    ");
+    fprintf(ci->fh, "%s_free(%s);\n",
+           forb_cbe_get_typespec_str(IDL_NATIVE(type_spec).ident),
+           name);
+    return;
+  case IDLN_INTERFACE:
+    fprintf(ci->fh, "    ");
+    fprintf(ci->fh, "forb_object_release(%s);\n", name);
+    break;
+  default:
+    break;
+  }
+
+}
+
+static void ck_output_op_skel(IDL_tree op, char *intf_id, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
+{
+       char *id, *id_plain;
+       IDL_tree sub;
+       gboolean  has_retval, has_args;
+       const char *const seq_init = " = {0,0,NULL}";
+
+       has_retval = IDL_OP_DCL (op).op_type_spec != NULL;
+       has_args   = IDL_OP_DCL (op).parameter_dcls != NULL;
+       
+       id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_OP_DCL(op).ident), "_", 0);
+       id_plain = IDL_IDENT(IDL_OP_DCL(op).ident).str;
+       fprintf(ci->fh, "static void\n"
+               "forb_skel_%s(FORB_CDR_Codec *cin, FORB_CDR_Codec *cout, %s _obj, struct forb_env *env)\n"
+               "{\n",
+               id, intf_id);
+/*     fprintf(ci->fh, "  if (_obj->interface != %s_interface) {\n", intf_id); */
+/*     fprintf(ci->fh, "    env->major = FORB_EX_BAD_OPERATION;\n" */
+/*                     "    return;\n" */
+/*                     "  }\n"); */
+       fprintf(ci->fh, "  if (_%s_impl(_obj) && _%s_impl(_obj)->%s) {\n", intf_id, intf_id, id_plain);
+
+       /* Declare variables for parameters */
+       for (sub = IDL_OP_DCL (op).parameter_dcls; sub; sub = IDL_LIST (sub).next) {
+               IDL_tree        parm = IDL_LIST (sub).data;
+               IDL_ParamRole   role;
+               IDL_tree        ts = forb_cbe_get_typespec(parm);
+               gboolean        isSlice;
+               int             n;
+               char            *name = IDL_IDENT(IDL_PARAM_DCL(parm).simple_declarator).str;
+               role = oidl_attr_to_paramrole(IDL_PARAM_DCL(parm).attr);
+               n = oidl_param_info (ts, role, &isSlice);
+
+               fprintf(ci->fh, "    ");
+               forb_cbe_write_typespec(ci->fh, IDL_PARAM_DCL(parm).param_type_spec);
+               fprintf(ci->fh, " %s%s%s;\n",
+                       n == 2 ? "*":"",
+                       name,
+                       (n < 2 && IDL_NODE_TYPE(ts) == IDLN_TYPE_SEQUENCE)?seq_init : "");
+       }
+       if (has_retval) {
+               fprintf (ci->fh, "    ");
+               forb_cbe_write_param_typespec (ci->fh, op);
+               fprintf (ci->fh, " _forb_ret;\n"); /* TODO: seq_init */
+       }
+
+       /* Deserialize in parameters */
+       for (sub = IDL_OP_DCL (op).parameter_dcls; sub; sub = IDL_LIST (sub).next) {
+               IDL_tree        parm = IDL_LIST (sub).data;
+               IDL_ParamRole   role;
+               role = oidl_attr_to_paramrole(IDL_PARAM_DCL(parm).attr);
+               if (role == DATA_IN || role == DATA_INOUT) {
+                       char *name = IDL_IDENT(IDL_PARAM_DCL(parm).simple_declarator).str;
+                       fprintf(ci->fh, "    if (!");
+                       forb_cbe_write_typespec(ci->fh, IDL_PARAM_DCL(parm).param_type_spec);
+                       fprintf(ci->fh, "_deserialize(cin, &%s)) {\n", name);
+                       fprintf(ci->fh, "      env->major = FORB_EX_MARSHAL; goto exception;\n    }\n");
+               }
+       }
+
+       /* Call the implementation */
+       fprintf(ci->fh, "    ");
+       if (has_retval)
+               fprintf(ci->fh, "_forb_ret = ");
+       fprintf(ci->fh, "_%s_impl(_obj)->%s(_obj, ",
+               intf_id, id_plain);
+       for (sub = IDL_OP_DCL (op).parameter_dcls; sub; sub = IDL_LIST (sub).next) {
+               IDL_tree        parm = IDL_LIST (sub).data;
+               IDL_ParamRole   role;
+               IDL_tree        ts = forb_cbe_get_typespec(parm);
+               gboolean        isSlice;
+               int             n;
+               char            *name = IDL_IDENT(IDL_PARAM_DCL(parm).simple_declarator).str;
+               role = oidl_attr_to_paramrole(IDL_PARAM_DCL(parm).attr);
+               n = oidl_param_info (ts, role, &isSlice);
+
+               fprintf(ci->fh, "%s%s, ", n?"&":"", name);
+       }
+       fprintf(ci->fh, "env);\n");
+       fprintf(ci->fh,
+               "    if (forb_exception_occurred(env)) goto exception;\n");
+       if (has_retval) {
+         fprintf(ci->fh, "    ");
+         forb_cbe_write_typespec(ci->fh, IDL_OP_DCL(op).op_type_spec);
+         fprintf(ci->fh, "_serialize(cout, &_forb_ret);\n");
+       }
+       for (sub = IDL_OP_DCL (op).parameter_dcls; sub; sub = IDL_LIST (sub).next) {
+               IDL_tree        parm = IDL_LIST (sub).data;
+               IDL_ParamRole   role;
+               IDL_tree        ts = forb_cbe_get_typespec(parm);
+               gboolean        isSlice;
+               int             n;
+               char            *name = IDL_IDENT(IDL_PARAM_DCL(parm).simple_declarator).str;
+               role = oidl_attr_to_paramrole(IDL_PARAM_DCL(parm).attr);
+               n = oidl_param_info (ts, role, &isSlice);
+               if (role == DATA_OUT || role == DATA_INOUT) {
+                 fprintf(ci->fh, "    ");
+                 forb_cbe_write_typespec(ci->fh, IDL_PARAM_DCL(parm).param_type_spec);
+                 fprintf(ci->fh, "_serialize(cout, %s%s);\n", n==2?"":"&", name);
+               }
+       }
+       fprintf(ci->fh, "exception:;\n");
+
+       /* Free all dynamically allocated parameteres and retvals */
+       if (has_retval) {
+               free_memory_if_needed(IDL_OP_DCL(op).op_type_spec, "_forb_ret", 0, ci);
+       }
+       for (sub = IDL_OP_DCL (op).parameter_dcls; sub; sub = IDL_LIST (sub).next) {
+               IDL_tree        parm = IDL_LIST (sub).data;
+               char *name = IDL_IDENT(IDL_PARAM_DCL(parm).simple_declarator).str;
+               IDL_ParamRole   role;
+               IDL_tree        ts = forb_cbe_get_typespec(parm);
+               gboolean        isSlice;
+               int             n;
+               role = oidl_attr_to_paramrole(IDL_PARAM_DCL(parm).attr);
+               n = oidl_param_info (ts, role, &isSlice);
+               free_memory_if_needed(IDL_PARAM_DCL(parm).param_type_spec, name, n, ci);
+       }
+
+       fprintf(ci->fh, "  } else {\n");
+       fprintf(ci->fh, "    env->major = FORB_EX_NO_IMPLEMENT;\n");
+       fprintf(ci->fh, "  }\n");
+       fprintf(ci->fh, "}\n\n");
+       g_free(id);
+}
+
+static void
+cbe_skel_do_interface(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
+{
+  char *id;
+  IDL_tree pnt;
+  IDL_tree sub;
+  //int i;
+  //CBESkelVEPVMapTraverseInfo ti;
+  int num_methods = 0;
+
+  /* PIDL methods dont have normal skel functions. */
+  for ( pnt=tree; pnt; pnt=IDL_NODE_UP(pnt) ) {
+      if ( pnt->declspec & IDLF_DECLSPEC_PIDL )
+       return;
+  }
+
+  id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_INTERFACE(tree).ident), "_", 0);
+
+  fprintf(ci->fh, "#define _%s_impl(obj) ((struct forb_%s_impl*)(obj)->implementation)\n\n", id, id);
+  fprintf(ci->fh, "static const struct forb_interface %s_interface;\n\n", id);
+  
+  for(sub = IDL_INTERFACE(tree).body; sub; sub = IDL_LIST(sub).next) {
+    IDL_tree cur = IDL_LIST(sub).data;
+    
+    switch(IDL_NODE_TYPE(cur)) {
+    case IDLN_OP_DCL:
+      ck_output_op_skel(cur, id, rinfo, ci);
+      num_methods++;
+      break;
+    default:
+      break;
+    }
+  }
+
+  fprintf(ci->fh, "static const forb_skel_func %s_skeletons[%d] = {\n",
+         id, num_methods);
+  for(sub = IDL_INTERFACE(tree).body; sub; sub = IDL_LIST(sub).next) {
+    IDL_tree cur = IDL_LIST(sub).data;
+    
+    switch(IDL_NODE_TYPE(cur)) {
+    case IDLN_OP_DCL: {
+      char *op_id;
+      op_id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_OP_DCL(cur).ident), "_", 0);
+      fprintf(ci->fh, "  forb_skel_%s,\n", op_id);
+      g_free(op_id);
+      break;
+    }
+    default:
+      break;
+    }
+  }
+  fprintf(ci->fh, "};\n\n");
+
+  fprintf(ci->fh, "static const struct forb_interface %s_interface = {\n", id);
+  fprintf(ci->fh, "  .name = \"%s\",\n", id);
+  fprintf(ci->fh, "  .num_methods = %d,\n", num_methods);
+  fprintf(ci->fh, "  .skeletons = %s_skeletons,\n", id);
+  fprintf(ci->fh, "  .type_hash = 0 /* not implemented */\n");
+  fprintf(ci->fh, "};\n\n");
+
+/*   fprintf(ci->fh, "void forb_register_%s_interface(void)\n" */
+/*               "{\n" */
+/*               "  forb_register_interface(&%s_interface);\n" */
+/*               "}\n\n", id, id); */
+
+  fprintf(ci->fh, "%s forb_%s_new(forb_orb orb, const struct forb_%s_impl *impl,"
+                 "void *instance_data)\n"
+                 "{\n"
+                 "  %s obj = forb_object_new(orb, NULL, 0);\n"
+                 "  if (obj) {\n"
+                 "    obj->instance_data = instance_data;\n"
+                 "    obj->implementation = impl;\n"
+                 "    obj->interface = &%s_interface;\n"
+                 "  }\n"
+                 "  return obj;\n"
+         "}\n\n", id, id, id, id, id);
+  fprintf(ci->fh, "\n");
+  
+
+/*   cbe_skel_interface_print_relayer(tree, rinfo, ci); */
+
+/*   fprintf(ci->fh, */
+/*       "void POA_%s__init(PortableServer_Servant servant,\nCORBA_Environment *env)\n", */
+/*       id); */
+/*   fprintf(ci->fh, "{\n"); */
+/*   fprintf(ci->fh,"  static PortableServer_ClassInfo class_info = {"); */
+
+/*   fprintf(ci->fh, "NULL, (Forb_small_impl_finder)&get_skel_small_%s, ", id); */
+
+/*   fprintf(ci->fh,"\"%s\", &%s__classid, NULL, &%s__iinterface};\n", */
+/*       IDL_IDENT(IDL_INTERFACE(tree).ident).repo_id, id, id); */
+
+/*   fprintf(ci->fh,"  PortableServer_ServantBase__init (" */
+/*              "       ((PortableServer_ServantBase *)servant), env);\n"); */
+
+/*   for(curitem = IDL_INTERFACE(tree).inheritance_spec; curitem; */
+/*       curitem = IDL_LIST(curitem).next) { */
+/*     id2 = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_LIST(curitem).data), */
+/*                               "_", 0); */
+/*     fprintf(ci->fh, "  POA_%s__init(servant, env);\n", id2); */
+/*     g_free(id2); */
+/*   } */
+
+  /* registering after other __inits() makes the classids increment nicely. */
+/*   fprintf (ci->fh, "   Forb_skel_class_register (&class_info,\n"); */
+/*   fprintf (ci->fh, "   (PortableServer_ServantBase *)servant, POA_%s__fini,\n", id); */
+/*   fprintf (ci->fh, "   FORB_VEPV_OFFSET (POA_%s__vepv, %s_epv),\n", id, id); */
+/*   ti.for_id = id; ti.ci = ci; */
+/*   IDL_tree_traverse_parents_full (tree, (GFunc) cbe_skel_interface_print_vepvmap_offsets, &ti, FALSE); */
+/*   fprintf (ci->fh, "   (CORBA_unsigned_long) 0);"); */
+
+/*   fprintf(ci->fh, "}\n\n"); */
+
+/*   fprintf(ci->fh, */
+/*       "void POA_%s__fini(PortableServer_Servant servant,\nCORBA_Environment *env)\n", */
+/*       id); */
+/*   fprintf(ci->fh, "{\n"); */
+/*   if(IDL_INTERFACE(tree).inheritance_spec) */
+/*     { */
+/*       for(i = IDL_list_length(IDL_INTERFACE(tree).inheritance_spec) - 1; */
+/*       i >= 0; i--) { */
+/*     curitem = IDL_list_nth(IDL_INTERFACE(tree).inheritance_spec, i); */
+/*     id2 = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(IDL_LIST(curitem).data), */
+/*                                   "_", 0); */
+/*     /\* XXX fixme - this is going to call ServantBase__fini multiple times *\/ */
+/*     fprintf(ci->fh, "  POA_%s__fini(servant, env);\n", */
+/*             id2); */
+/*     g_free(id2); */
+/*       } */
+/*     } */
+/*   fprintf(ci->fh, "  PortableServer_ServantBase__fini(servant, env);\n"); */
+/*   fprintf(ci->fh, "}\n\n"); */
+
+  g_free(id);
+}
+
+void
+forb_idl_output_c_skeletons (IDL_tree       tree,
+                             OIDL_Run_Info *rinfo,
+                             OIDL_C_Info   *ci)
+{
+       fprintf (ci->fh, OIDL_C_WARNING);
+/*     fprintf (ci->fh, "#include <string.h>\n"); */
+/*     fprintf (ci->fh, "#define FORB2_STUBS_API\n"); */
+       fprintf (ci->fh, "#include \"%s.h\"\n\n", ci->base_name);
+       fprintf(ci->fh, "#include <forb/cdr.h>\n");
+       fprintf(ci->fh, "#include <forb/forb-internal.h>\n");
+       fprintf(ci->fh, "#include <forb/object.h>\n\n");
+
+       ck_output_poastuff (tree, rinfo, ci);
+}
diff --git a/src/forb/forb-idl/forb-idl-c-stubs.c b/src/forb/forb-idl/forb-idl-c-stubs.c
new file mode 100644 (file)
index 0000000..f553283
--- /dev/null
@@ -0,0 +1,208 @@
+#include "config.h"
+
+#include "forb-idl-c-backend.h"
+
+#include <string.h>
+
+static void
+cs_output_stub (IDL_tree     tree,
+               OIDL_C_Info *ci,
+               int         *idx)
+{
+       FILE     *of = ci->fh;
+       IDL_tree  sub;
+       char     *iface_id;
+       char     *opname;
+       char     *opname_plain;
+       gboolean  has_retval, has_args;
+
+       g_return_if_fail (idx != NULL);
+
+       iface_id = IDL_ns_ident_to_qstring (
+                       IDL_IDENT_TO_NS (IDL_INTERFACE (
+                               IDL_get_parent_node (tree, IDLN_INTERFACE, NULL)
+                                       ).ident), "_", 0);
+       opname_plain = IDL_IDENT(IDL_OP_DCL (tree).ident).str;
+       opname = IDL_ns_ident_to_qstring (IDL_IDENT_TO_NS (IDL_OP_DCL (tree).ident), "_", 0);
+
+       has_retval = IDL_OP_DCL (tree).op_type_spec != NULL;
+       has_args   = IDL_OP_DCL (tree).parameter_dcls != NULL;
+
+       forb_cbe_op_write_proto (of, tree, "", FALSE);
+
+       fprintf (of, "\n{\n");
+
+       if (has_retval) {
+               fprintf (of, "  ");
+               forb_cbe_write_param_typespec (of, tree);
+               fprintf (of, " " FORB_RETVAL_VAR_NAME ";\n");
+       }
+
+/*     fprintf(of, "  if (_obj->type != %s_type) {\n" */
+/*                 "    ev->major = FORB_EX_BAD_OPERATION;\n", iface_id); */
+/*     if (has_retval) { */
+/*             fprintf(of, "    return "FORB_RETVAL_VAR_NAME";\n"); */
+/*     } */
+        fprintf(of, "  if (ev) ev->major = FORB_EX_NONE;\n");
+        fprintf(of, "  if (forb_object_is_local(_obj)) {\n");
+        fprintf(of, "    if (!_obj->interface ||\n"
+                    "        strncmp(_obj->interface->name, \"%s\", %zd) != 0) {\n"
+                    "      ev->major = FORB_EX_BAD_OPERATION;\n"
+                    "      return %s;\n"
+                    "    }\n", iface_id, strlen(iface_id), has_retval ? FORB_RETVAL_VAR_NAME : "");
+       fprintf(of, "    ");
+       if (has_retval) {
+               fprintf(of, FORB_RETVAL_VAR_NAME " = ");
+       }
+       fprintf(of, "_%s_impl(_obj)->%s(_obj, ",
+               iface_id, opname_plain);
+       for (sub = IDL_OP_DCL (tree).parameter_dcls; sub; sub = IDL_LIST (sub).next) {
+               IDL_tree parm = IDL_LIST (sub).data;
+               fprintf (of, "%s, ", IDL_IDENT (IDL_PARAM_DCL (parm).simple_declarator).str);
+       }
+       fprintf(of, "ev);\n");
+       
+       fprintf(of, "  } else {\n");
+       fprintf(of, "    /* remote object */\n"
+                   "    forb_request_t req;\n");
+       fprintf(of, "    ex_on_fail(forb_request_init(&req, _obj) == 0, FORB_EX_INTERNAL);\n");
+       fprintf(of, "    forb_iop_prepare_request(&req, \"%s\", FORB_METHOD_INDEX(%s), ev);\n",
+               iface_id, opname);
+       fprintf(of, "    if (forb_exception_occurred(ev)) goto exception;\n");
+       for (sub = IDL_OP_DCL (tree).parameter_dcls; sub; sub = IDL_LIST (sub).next) {
+               IDL_tree        parm = IDL_LIST (sub).data;
+               IDL_ParamRole   role;
+               role = oidl_attr_to_paramrole(IDL_PARAM_DCL(parm).attr);
+               if (role == DATA_IN || role == DATA_INOUT) {
+                 char      *name = IDL_IDENT(IDL_PARAM_DCL(parm).simple_declarator).str;
+                 gboolean  isSlice;
+                 IDL_tree  ts = forb_cbe_get_typespec(parm);
+                 int       n = oidl_param_info (ts, role, &isSlice);
+                 fprintf(of, "    ex_on_fail(");
+                 forb_cbe_write_typespec(of, IDL_PARAM_DCL(parm).param_type_spec);
+                 fprintf(of, "_serialize(&req.cdr_request, %s%s), FORB_EX_IMP_LIMIT);\n",
+                         n == 0 ? "&":"", name);
+               }
+       }
+       fprintf(of, "    forb_request_send(&req, ev);\n");
+       fprintf(of, "    if (forb_exception_occurred(ev)) goto exception;\n");
+       fprintf(of, "    forb_request_wait_for_reply(&req);\n");
+       fprintf(of, "    if (forb_exception_occurred(ev)) goto exception;\n");
+       if (has_retval) {
+         fprintf(of, "    ");
+         forb_cbe_write_typespec(of, IDL_OP_DCL(tree).op_type_spec);
+         fprintf(of, "_deserialize(req.cdr_reply, &"FORB_RETVAL_VAR_NAME");\n");
+       }
+       for (sub = IDL_OP_DCL (tree).parameter_dcls; sub; sub = IDL_LIST (sub).next) {
+               IDL_tree        parm = IDL_LIST (sub).data;
+               IDL_ParamRole   role;
+               role = oidl_attr_to_paramrole(IDL_PARAM_DCL(parm).attr);
+               if (role == DATA_OUT || role == DATA_INOUT) {
+                 char *name = IDL_IDENT(IDL_PARAM_DCL(parm).simple_declarator).str;
+                 gboolean  isSlice;
+                 IDL_tree  ts = forb_cbe_get_typespec(parm);
+                 int       n = oidl_param_info (ts, role, &isSlice);
+                 if (IDL_NODE_TYPE(forb_cbe_get_typespec(parm)) == IDLN_TYPE_SEQUENCE &&
+                     role == DATA_OUT) { /* Allocate out sequence */
+                         fprintf(ci->fh, "    *%s = forb_malloc(sizeof(**%s));\n", name, name);
+                         fprintf(ci->fh, "    if (!*%s) { ev->major = FORB_EX_NO_MEMORY; goto exception; }\n", name);
+                         fprintf(ci->fh, "    memset(*%s, 0, sizeof(**%s));\n", name, name);
+                         fprintf(ci->fh, "    CORBA_sequence_set_release(*%s, CORBA_TRUE);\n", name);
+                         /* TODO: Free previously allocated parameters on no memory error. */
+                 }
+                 fprintf(of, "    ");
+                 forb_cbe_write_typespec(of, IDL_PARAM_DCL(parm).param_type_spec);
+                 fprintf(ci->fh, "_deserialize(req.cdr_reply, %s%s);\n", n==2?"*":"", name);
+               }
+       }
+       fprintf(of, "    forb_request_signal_processed(&req);\n"
+                   "exception:\n"
+                   "    forb_request_destroy(&req);\n");
+       fprintf(of, "  }\n");
+       if (has_retval) {
+               fprintf(of, "  return " FORB_RETVAL_VAR_NAME ";\n");
+       }
+
+       fprintf (of, "}\n\n");
+
+       g_free (iface_id);
+       g_free (opname);
+
+       (*idx)++;
+}
+
+static void
+cs_output_stubs (IDL_tree     tree,
+                OIDL_C_Info *ci,
+                int         *idx)
+{
+       if (!tree)
+               return;
+
+       switch (IDL_NODE_TYPE (tree)) {
+       case IDLN_MODULE:
+               cs_output_stubs (IDL_MODULE (tree).definition_list, ci, idx);
+               break;
+       case IDLN_LIST: {
+               IDL_tree sub;
+
+               for (sub = tree; sub; sub = IDL_LIST (sub).next)
+                       cs_output_stubs (IDL_LIST (sub).data, ci, idx);
+               break;
+               }
+       case IDLN_ATTR_DCL: {
+/*             IDL_tree node; */
+      
+/*             for (node = IDL_ATTR_DCL (tree).simple_declarations; node; node = IDL_LIST (node).next) { */
+/*                     OIDL_Attr_Info *ai; */
+
+/*                     ai = IDL_LIST (node).data->data; */
+       
+/*                     cs_output_stubs (ai->op1, ci, idx); */
+
+/*                     if (ai->op2) */
+/*                             cs_output_stubs (ai->op2, ci, idx); */
+/*             } */
+               break;
+               }
+       case IDLN_INTERFACE: {
+               int real_idx = 0;
+               char *id;
+               /* Do not output skeletons for PIDL interfaces */
+               if ((tree->declspec & IDLF_DECLSPEC_PIDL) == 0) {
+                 id = IDL_ns_ident_to_qstring (IDL_INTERFACE (tree).ident, "_", 0);
+                 fprintf(ci->fh, "#define _%s_impl(obj) ((struct forb_%s_impl*)(obj)->implementation)\n\n",
+                         id, id);
+                 g_free(id);
+                 cs_output_stubs (IDL_INTERFACE (tree).body, ci, &real_idx);
+               }
+               break;
+               }
+       case IDLN_OP_DCL:
+               cs_output_stub (tree, ci, idx);
+               break;
+       default:
+               break;
+       }
+}
+
+void
+forb_idl_output_c_stubs (IDL_tree       tree,
+                         OIDL_Run_Info *rinfo,
+                         OIDL_C_Info   *ci)
+{
+       fprintf (ci->fh, OIDL_C_WARNING);
+       fprintf (ci->fh, "#include <string.h>\n");
+/*     fprintf (ci->fh, "#define FORB2_STUBS_API\n"); */
+       fprintf (ci->fh, "#include <forb/forb-internal.h>\n");
+       fprintf (ci->fh, "#include <forb/request.h>\n");
+       fprintf (ci->fh, "#include <forb/iop.h>\n");
+       fprintf (ci->fh, "#include <forb/cdr.h>\n");
+       fprintf (ci->fh, "#include <forb/object.h>\n\n");
+       fprintf (ci->fh, "#include \"%s.h\"\n\n", ci->base_name);
+
+       fprintf (ci->fh, "#define ex_on_fail(command, ex) if (!(command)) do { ev->major = (ex); goto exception; } while(0)\n");
+       fprintf (ci->fh, "#define FORB_REQEST_HDR_SIZE (forb_iop_MESSAGE_HEADER_SIZE + forb_iop_REQUEST_HEADER_SIZE)\n\n");
+
+       cs_output_stubs (tree, ci, NULL);
+}
diff --git a/src/forb/forb-idl/forb-idl-c-typecode.c b/src/forb/forb-idl/forb-idl-c-typecode.c
new file mode 100644 (file)
index 0000000..c0023fb
--- /dev/null
@@ -0,0 +1,1039 @@
+#include "forb-idl-c-backend.h"
+
+#include <string.h>
+#include <inttypes.h>
+
+typedef struct {
+       IDL_tree     ts;
+       char        *structname;
+       char        *substructname;
+       int          array_gen_ctr;
+} CBETCGenInfo;
+
+static int random_id = 0;
+
+static char *forb_generate_tcstruct_name (IDL_tree     ts);
+static void  cbe_tc_generate              (OIDL_C_Info *ci, CBETCGenInfo *tci);
+
+void
+forb_output_typecode (OIDL_C_Info *ci,
+                      IDL_tree     node)
+{
+       CBETCGenInfo tci;
+
+       switch (IDL_NODE_TYPE (node)) {
+       case IDLN_TYPE_DCL:
+       case IDLN_TYPE_STRUCT:
+       case IDLN_TYPE_UNION:
+       case IDLN_TYPE_ENUM:
+       case IDLN_EXCEPT_DCL:
+       case IDLN_TYPE_SEQUENCE:
+       case IDLN_INTERFACE:
+               break;
+       default:
+               g_error ("You can't produce a typecode for a %s", 
+                        IDL_tree_type_names[IDL_NODE_TYPE (node)]);
+       }
+
+       tci.ts            = node;
+       tci.structname    = forb_generate_tcstruct_name (node);
+       tci.substructname = NULL;
+       tci.array_gen_ctr = 0;
+
+       cbe_tc_generate (ci, &tci);
+
+       g_free (tci.structname);
+}
+
+static char *
+forb_generate_tcstruct_name (IDL_tree node)
+{
+       GString *tmpstr;
+       char    *retval;
+
+       tmpstr = g_string_new (NULL);
+
+       switch (IDL_NODE_TYPE (node)) {
+       case IDLN_TYPE_INTEGER:
+       case IDLN_TYPE_ANY:
+       case IDLN_TYPE_STRING:
+       case IDLN_TYPE_WIDE_STRING:
+       case IDLN_TYPE_CHAR:
+       case IDLN_TYPE_WIDE_CHAR:
+       case IDLN_TYPE_FLOAT:
+       case IDLN_TYPE_BOOLEAN:
+       case IDLN_TYPE_OCTET:
+       case IDLN_TYPE_SEQUENCE:
+       case IDLN_TYPE_STRUCT:
+       case IDLN_TYPE_UNION:
+       case IDLN_TYPE_ENUM:
+       case IDLN_IDENT:
+       case IDLN_EXCEPT_DCL:
+       case IDLN_INTERFACE:
+       case IDLN_FORWARD_DCL:
+       case IDLN_TYPE_OBJECT: {
+               char *typespec = forb_cbe_get_typespec_str (node);
+
+               g_string_printf (tmpstr, "TC_%s", typespec);
+
+               g_free (typespec);
+               }
+               break;
+       default:
+               g_string_printf (tmpstr, "anonTC_%d", random_id++);
+               break;
+       }
+
+       retval = tmpstr->str;
+       g_string_free (tmpstr, FALSE);
+
+       return retval;
+}
+
+static void
+forb_output_tcstruct_anon_subnames_array (FILE *fh, IDL_tree node, int subnames_id)
+{
+       IDL_tree l;
+
+       switch (IDL_NODE_TYPE (node)) {
+       case IDLN_TYPE_ENUM:
+               if (!IDL_TYPE_ENUM (node).enumerator_list)
+                       break;
+
+               fprintf (fh, "static const char *anon_subnames_array%d[] = {", subnames_id);
+
+               for (l = IDL_TYPE_ENUM (node).enumerator_list; l; l = IDL_LIST (l).next) {
+                       g_assert (IDL_NODE_TYPE (IDL_LIST (l).data) == IDLN_IDENT);
+
+                       fprintf (fh, "\"%s\"", IDL_IDENT (IDL_LIST (l).data).str );
+                       if (IDL_LIST (l).next)
+                               fprintf (fh, ", ");
+               }
+
+               fprintf (fh, "};\n");
+               break;
+       case IDLN_EXCEPT_DCL:
+       case IDLN_TYPE_STRUCT:
+               if (!IDL_TYPE_STRUCT (node).member_list)
+                       break;
+
+               fprintf (fh, "static const char *anon_subnames_array%d[] = {", subnames_id);
+
+               for (l = IDL_TYPE_STRUCT (node).member_list; l; l = IDL_LIST (l).next) {
+                       IDL_tree dcl;
+
+                       g_assert (IDL_NODE_TYPE (IDL_LIST (l).data) == IDLN_MEMBER);
+
+                       for (dcl = IDL_MEMBER (IDL_LIST (l).data).dcls; dcl;
+                            dcl = IDL_LIST (dcl).next) {
+                               IDL_tree p = IDL_LIST (dcl).data;
+
+                               g_assert (IDL_NODE_TYPE (p) == IDLN_IDENT ||
+                                         IDL_NODE_TYPE (p) == IDLN_TYPE_ARRAY);
+
+                               if (IDL_NODE_TYPE (p) == IDLN_IDENT)
+                                       fprintf (fh, "\"%s\"", IDL_IDENT (p).str);
+
+                               else /* IDLN_TYPE_ARRAY */
+                                       fprintf (fh, "\"%s\"", 
+                                                IDL_IDENT (IDL_TYPE_ARRAY (p).ident).str);
+       
+                               if (IDL_LIST (dcl).next || IDL_LIST (l).next)
+                                       fprintf (fh, ", ");
+                       }
+               }
+
+               fprintf (fh, "};\n");
+               break;
+       case IDLN_TYPE_UNION:
+               if (!IDL_TYPE_UNION (node).switch_body)
+                       break;
+
+               fprintf (fh, "static const char * anon_subnames_array%d[] = {", subnames_id);
+
+               for (l = IDL_TYPE_UNION (node).switch_body; l; l = IDL_LIST (l).next) {
+                       IDL_tree dcl, label;
+                       const char *subname;
+
+                       g_assert (IDL_NODE_TYPE (IDL_LIST (l).data) == IDLN_CASE_STMT);
+
+                       dcl = IDL_LIST (IDL_MEMBER (
+                               IDL_CASE_STMT (IDL_LIST (l).data).element_spec).dcls).data;
+
+                       g_assert (IDL_NODE_TYPE (dcl) == IDLN_IDENT ||
+                                 IDL_NODE_TYPE (dcl) == IDLN_TYPE_ARRAY);
+
+                       if (IDL_NODE_TYPE (dcl) == IDLN_IDENT)
+                               subname = IDL_IDENT (dcl).str;
+                       else /* IDLN_TYPE_ARRAY */
+                               subname = IDL_IDENT (IDL_TYPE_ARRAY (dcl).ident).str;
+
+                       /* output the name once for each label */
+                       for (label = IDL_CASE_STMT (IDL_LIST (l).data).labels;
+                            label != NULL; label = IDL_LIST (label).next) {
+                               fprintf (fh, "\"%s\"", subname);
+                               if (IDL_LIST (label).next)
+                                       fprintf (fh, ", ");
+                       }
+
+                       if (IDL_LIST (l).next)
+                               fprintf (fh, ", ");
+               }
+               fprintf (fh, "};\n");
+               break;
+       default:
+               break;
+       }
+}
+
+static void
+forb_output_tcstruct_anon_subtypes_array (FILE     *fh,
+                                          IDL_tree  node,
+                                          int       subtypes_id,
+                                          char     *substructname)
+{
+       IDL_tree l;
+
+       switch (IDL_NODE_TYPE (node)) {
+       case IDLN_EXCEPT_DCL:
+       case IDLN_TYPE_STRUCT:
+               if (!IDL_TYPE_STRUCT (node).member_list)
+                       break;
+
+               fprintf (fh, "static FORB2_MAYBE_CONST CORBA_TypeCode anon_subtypes_array%d[] = {",
+                        subtypes_id);
+
+               for (l = IDL_TYPE_STRUCT (node).member_list; l; l = IDL_LIST (l).next) {
+                       IDL_tree  dcl;
+                       char     *tmpstr;
+
+                       dcl = IDL_MEMBER (IDL_LIST (l).data).type_spec;
+
+                       switch (IDL_NODE_TYPE (dcl)) {
+                       case IDLN_IDENT:
+                       case IDLN_INTERFACE:
+                       case IDLN_TYPE_OBJECT:
+                       case IDLN_FORWARD_DCL:
+                               dcl = forb_cbe_get_typespec (dcl);
+
+                               if (IDL_NODE_DECLSPEC (dcl) & IDLF_DECLSPEC_PIDL &&
+                                  (IDL_NODE_TYPE (dcl) == IDLN_INTERFACE ||
+                                   IDL_NODE_TYPE (dcl) == IDLN_FORWARD_DCL))
+                                       tmpstr = g_strdup ("Object");
+                               else
+                                       tmpstr = forb_cbe_get_typespec_str (
+                                                       IDL_MEMBER (IDL_LIST (l).data).type_spec);
+                               break;
+                       default:
+                               tmpstr = forb_cbe_get_typespec_str (
+                                               IDL_MEMBER (IDL_LIST (l).data).type_spec);
+                               break;
+                       }
+
+                       g_assert (IDL_NODE_TYPE (IDL_LIST (l).data) == IDLN_MEMBER);
+
+                       for (dcl = IDL_MEMBER (IDL_LIST (l).data).dcls; dcl;
+                            dcl = IDL_LIST (dcl).next) {
+
+                               fprintf (fh, "(CORBA_TypeCode)&TC_%s_struct", tmpstr);
+
+                               if (IDL_LIST (dcl).next || IDL_LIST (l).next)
+                                       fprintf (fh, ", ");
+                       }
+
+                       g_free (tmpstr);
+               }
+
+               fprintf (fh, "};\n");
+
+               break;
+       case IDLN_TYPE_UNION:
+               if (!IDL_TYPE_UNION (node).switch_body)
+                       break;
+
+               fprintf (fh, "static FORB2_MAYBE_CONST CORBA_TypeCode anon_subtypes_array%d[] = {", subtypes_id);
+
+               for (l = IDL_TYPE_UNION (node).switch_body; l; l = IDL_LIST (l).next) {
+                       IDL_tree  label, dcl;
+                       char     *tmpstr;
+
+                       g_assert (IDL_NODE_TYPE (IDL_LIST (l).data) == IDLN_CASE_STMT);
+
+                       dcl = IDL_MEMBER (IDL_CASE_STMT (IDL_LIST (l).data).element_spec).type_spec;
+
+                       switch (IDL_NODE_TYPE (forb_cbe_get_typespec (dcl))) {
+                       case IDLN_INTERFACE:
+                       case IDLN_FORWARD_DCL:
+                               if (IDL_NODE_DECLSPEC (dcl) & IDLF_DECLSPEC_PIDL)
+                                       tmpstr = g_strdup ( "Object");
+                               else
+                                       tmpstr = forb_cbe_get_typespec_str (dcl);
+                               break;
+                       default:
+                               tmpstr = forb_cbe_get_typespec_str (dcl);
+                               break;
+                       }
+
+                       for (label = IDL_CASE_STMT (IDL_LIST (l).data).labels; label;
+                            label = IDL_LIST (label).next) {
+                               fprintf (fh, "(CORBA_TypeCode)&TC_%s_struct", tmpstr);
+
+                               if (IDL_LIST (label).next || IDL_LIST (l).next)
+                                       fprintf (fh, ", ");
+                       }
+
+                       g_free (tmpstr);
+               }
+
+               fprintf (fh, "};\n");
+
+               break;
+       case IDLN_TYPE_SEQUENCE: {
+               IDL_tree  seqts;
+               char     *tmpstr;
+
+               seqts = forb_cbe_get_typespec (IDL_TYPE_SEQUENCE (node).simple_type_spec);
+
+               fprintf (fh, "static FORB2_MAYBE_CONST CORBA_TypeCode anon_subtypes_array%d[] = ", subtypes_id);
+
+               switch (IDL_NODE_TYPE (seqts)) {
+               case IDLN_INTERFACE:
+               case IDLN_FORWARD_DCL:
+                       if (IDL_NODE_DECLSPEC (seqts) && IDLF_DECLSPEC_PIDL)
+                               tmpstr = g_strdup ("Object");
+                       else
+                               tmpstr = forb_cbe_get_typespec_str (
+                                               IDL_TYPE_SEQUENCE (node).simple_type_spec);
+                       break;
+               default:
+                       tmpstr = forb_cbe_get_typespec_str (
+                                               IDL_TYPE_SEQUENCE (node).simple_type_spec);
+                       break;
+               }
+
+               fprintf (fh, "{(CORBA_TypeCode)&TC_%s_struct};\n", tmpstr);
+               g_free (tmpstr);
+
+               }
+               break;
+       case IDLN_TYPE_ARRAY:
+       case IDLN_IDENT:
+               fprintf (fh, "static FORB2_MAYBE_CONST CORBA_TypeCode anon_subtypes_array%d[] = ", subtypes_id);
+               fprintf (fh, "{(CORBA_TypeCode)&%s_struct};\n", substructname);
+               break;
+       default:
+               break;
+       }
+}
+
+static int
+forb_output_tcstruct_anon_sublabels_array (FILE     *fh, 
+                                           IDL_tree  node,
+                                           int       sublabels_id)
+{
+       IDL_tree l, label;
+       int      index = 0;
+       int      default_index = -1;
+
+       if (IDL_NODE_TYPE (node) != IDLN_TYPE_UNION ||
+           !IDL_TYPE_UNION (node).switch_body)
+               return default_index;
+
+       fprintf (fh, "static FORB2_MAYBE_CONST CORBA_long anon_sublabels_array%d[] = {", sublabels_id);
+
+       for (l = IDL_TYPE_UNION (node).switch_body; l; l = IDL_LIST (l).next)
+               for (label = IDL_CASE_STMT (IDL_LIST (l).data).labels; label;
+                    label = IDL_LIST (label).next, index++) {
+
+                       if (IDL_LIST (label).data) {
+                               fprintf (fh, "(CORBA_long) ");
+
+                               forb_cbe_write_const (fh, IDL_LIST (label).data);
+
+                       } else { /* default case */
+                               fprintf (fh, "-1");
+                               default_index = index;
+                       }
+
+                       if (IDL_LIST (label).next || IDL_LIST (l).next)
+                               fprintf (fh, ", ");
+               }
+
+       fprintf (fh, "};\n");
+
+       return default_index;
+}
+
+static void
+forb_output_tcstruct_parent (FILE *fh)
+{
+       fprintf (fh, "{&Forb_TypeCode_epv, FORB_REFCOUNT_STATIC}");
+}
+
+static void
+forb_output_tcstruct_kind (FILE *fh, IDL_tree node, int array_gen_ctr)
+{
+       switch (IDL_NODE_TYPE (node)) {
+       case IDLN_TYPE_ARRAY:
+               if (array_gen_ctr)
+                       fprintf (fh, "CORBA_tk_array");
+               else
+                       fprintf (fh, "CORBA_tk_alias");
+               break;
+       case IDLN_IDENT:
+               fprintf (fh, "CORBA_tk_alias");
+               break;
+       case IDLN_TYPE_STRUCT:
+               fprintf (fh, "CORBA_tk_struct");
+               break;
+       case IDLN_TYPE_UNION:
+               fprintf (fh, "CORBA_tk_union");
+               break;
+       case IDLN_TYPE_ENUM:
+               fprintf (fh, "CORBA_tk_enum");
+               break;
+       case IDLN_TYPE_OBJECT:
+       case IDLN_INTERFACE:
+       case IDLN_FORWARD_DCL:
+               fprintf (fh, "CORBA_tk_objref");
+               break;
+       case IDLN_EXCEPT_DCL:
+               fprintf (fh, "CORBA_tk_except");
+               break;
+       case IDLN_TYPE_INTEGER:
+               fprintf (fh, "CORBA_tk_");
+
+               if (!IDL_TYPE_INTEGER (node).f_signed)
+                       fprintf (fh, "u");
+
+               switch (IDL_TYPE_INTEGER (node).f_type) {
+               case IDL_INTEGER_TYPE_SHORT:
+                       fprintf (fh, "short");
+                       break;
+               case IDL_INTEGER_TYPE_LONG:
+                       fprintf (fh, "long");
+                       break;
+               case IDL_INTEGER_TYPE_LONGLONG:
+                       fprintf (fh, "longlong");
+                       break;
+               }
+               break;
+       case IDLN_TYPE_FLOAT:
+               fprintf (fh, "CORBA_tk_");
+
+               switch (IDL_TYPE_FLOAT (node).f_type) {
+               case IDL_FLOAT_TYPE_FLOAT:
+                       fprintf (fh, "float");
+                       break;
+               case IDL_FLOAT_TYPE_DOUBLE:
+                       fprintf (fh, "double");
+                       break;
+               case IDL_FLOAT_TYPE_LONGDOUBLE:
+                       fprintf (fh, "longdouble");
+                       break;
+               }
+               break;
+       case IDLN_TYPE_BOOLEAN:
+               fprintf (fh, "CORBA_tk_boolean");
+               break;
+       case IDLN_TYPE_OCTET:
+               fprintf (fh, "CORBA_tk_octet");
+               break;
+       case IDLN_TYPE_STRING:
+               fprintf (fh, "CORBA_tk_string");
+               break;
+       case IDLN_TYPE_WIDE_STRING:
+               fprintf (fh, "CORBA_tk_wstring");
+               break;
+       case IDLN_TYPE_CHAR:
+               fprintf (fh, "CORBA_tk_char");
+               break;
+       case IDLN_TYPE_WIDE_CHAR:
+               fprintf (fh, "CORBA_tk_wchar");
+               break;
+       case IDLN_TYPE_ANY:
+               fprintf (fh, "CORBA_tk_any");
+               break;
+       case IDLN_TYPE_SEQUENCE:
+               fprintf (fh, "CORBA_tk_sequence");
+               break;
+       default:
+               g_message ("Type %s has no tk constant!",
+                          IDL_tree_type_names[IDL_NODE_TYPE (node)]);
+       }
+}
+
+static void
+forb_output_tcstruct_name (FILE *fh, IDL_tree node, int array_gen_ctr)
+{
+       switch (IDL_NODE_TYPE (node)) {
+       case IDLN_TYPE_STRUCT:
+               fprintf (fh, "(char *)\"%s\"", IDL_IDENT (IDL_TYPE_STRUCT (node).ident).str);
+               break;
+       case IDLN_TYPE_UNION:
+               fprintf (fh, "(char *)\"%s\"", IDL_IDENT (IDL_TYPE_UNION (node).ident).str);
+               break;
+       case IDLN_TYPE_ENUM:
+               fprintf (fh, "(char *)\"%s\"", IDL_IDENT (IDL_TYPE_ENUM (node).ident).str);
+               break;
+       case IDLN_INTERFACE:
+       case IDLN_FORWARD_DCL:
+               fprintf (fh, "(char *)\"%s\"", IDL_IDENT (IDL_INTERFACE (node).ident).str);
+               break;
+       case IDLN_EXCEPT_DCL:
+               fprintf (fh, "(char *)\"%s\"", IDL_IDENT (IDL_EXCEPT_DCL (node).ident).str);
+               break;
+       case IDLN_IDENT:
+               fprintf (fh, "(char *)\"%s\"", IDL_IDENT (node).str);
+               break;
+       case IDLN_TYPE_ARRAY:
+               if (!array_gen_ctr)
+                       fprintf (fh, "(char *)\"%s\"", 
+                                IDL_IDENT (IDL_TYPE_ARRAY (node).ident).str);
+               else
+                       fprintf (fh, "NULL");
+               break;
+       default:
+               fprintf (fh, "NULL");
+               break;
+       }
+}
+
+static void
+forb_output_tcstruct_repo_id (FILE *fh, IDL_tree node, int array_gen_ctr)
+{
+       switch (IDL_NODE_TYPE (node)) {
+       case IDLN_TYPE_STRUCT:
+               fprintf (fh, "(char *)\"%s\"", IDL_IDENT (IDL_TYPE_STRUCT (node).ident).repo_id);
+               break;
+       case IDLN_TYPE_UNION:
+               fprintf (fh, "(char *)\"%s\"", IDL_IDENT (IDL_TYPE_UNION (node).ident).repo_id);
+               break;
+       case IDLN_TYPE_ENUM:
+               fprintf (fh, "(char *)\"%s\"", IDL_IDENT (IDL_TYPE_ENUM (node).ident).repo_id);
+               break;
+       case IDLN_INTERFACE:
+       case IDLN_FORWARD_DCL:
+               fprintf (fh, "(char *)\"%s\"", IDL_IDENT (IDL_INTERFACE (node).ident).repo_id);
+               break;
+       case IDLN_EXCEPT_DCL:
+               fprintf (fh, "(char *)\"%s\"", IDL_IDENT (IDL_EXCEPT_DCL (node).ident).repo_id);
+               break;
+       case IDLN_IDENT:
+               fprintf (fh, "(char *)\"%s\"", IDL_IDENT (node).repo_id);
+               break;
+       case IDLN_TYPE_ARRAY:
+               if (!array_gen_ctr)
+                       fprintf (fh, "(char *)\"%s\"", IDL_IDENT (IDL_TYPE_ARRAY (node).ident).repo_id);
+               else
+                       fprintf (fh, "NULL");
+               break;
+       default:
+               fprintf (fh, "NULL");
+               break;
+       }
+}
+
+static void
+forb_output_tcstruct_length (FILE *fh, IDL_tree node, int array_gen_ctr)
+{
+       int length = 0;
+
+       switch (IDL_NODE_TYPE (node)) {
+       case IDLN_TYPE_SEQUENCE:
+               if (IDL_TYPE_SEQUENCE (node).positive_int_const)
+                       length = IDL_INTEGER (IDL_TYPE_SEQUENCE (node).positive_int_const).value;
+               break;
+       case IDLN_TYPE_STRING:
+               if (IDL_TYPE_STRING (node).positive_int_const)
+                       length = IDL_INTEGER (IDL_TYPE_STRING (node).positive_int_const).value;
+               break;
+       case IDLN_TYPE_WIDE_STRING:
+               if (IDL_TYPE_WIDE_STRING (node).positive_int_const)
+                       length = IDL_INTEGER (IDL_TYPE_STRING (node).positive_int_const).value;
+               break;
+       case IDLN_TYPE_ARRAY:
+               if (array_gen_ctr) {
+                       IDL_tree sizer;
+
+                       sizer = IDL_list_nth (IDL_TYPE_ARRAY (node).size_list,
+                                             array_gen_ctr - 1);
+
+                       g_assert (IDL_NODE_TYPE (IDL_LIST (sizer).data) == IDLN_INTEGER);
+
+                       length = IDL_INTEGER (IDL_LIST (sizer).data).value;
+               }
+               break;
+       default:
+               length = 0;
+               break;
+       }
+
+       fprintf (fh, "%d", length);
+}
+
+static void
+forb_output_tcstruct_sub_parts (FILE *fh, IDL_tree node)
+{
+       int length = 0;
+
+       switch (IDL_NODE_TYPE (node)) {
+       case IDLN_TYPE_STRUCT:
+       case IDLN_EXCEPT_DCL: {
+               IDL_tree l;
+
+               for (l = IDL_TYPE_STRUCT (node).member_list; l; l = IDL_LIST (l).next) {
+                       IDL_tree member;
+
+                       member = IDL_LIST (l).data;
+
+                       g_assert (IDL_NODE_TYPE (member) == IDLN_MEMBER);
+
+                       length += IDL_list_length (IDL_MEMBER (member).dcls);
+               }
+               }
+               break;
+       case IDLN_TYPE_UNION: {
+               IDL_tree l;
+
+               for (l = IDL_TYPE_UNION (node).switch_body; l; l = IDL_LIST (l).next) {
+                       IDL_tree case_stmt;
+
+                       case_stmt = IDL_LIST (l).data;
+
+                       g_assert (IDL_NODE_TYPE (case_stmt) == IDLN_CASE_STMT);
+
+                       length += IDL_list_length (IDL_CASE_STMT (case_stmt).labels);
+               }
+               }
+               break;
+       case IDLN_TYPE_ENUM:
+               length = IDL_list_length (IDL_TYPE_ENUM (node).enumerator_list);
+               break;
+       case IDLN_IDENT:
+       case IDLN_TYPE_SEQUENCE:
+       case IDLN_TYPE_ARRAY:
+               length = 1;
+               break;
+       default:
+               length = 0;
+               break;
+       }
+
+       fprintf (fh, "%d\n", length);
+}
+
+static void
+forb_output_tcstruct_subnames (FILE *fh, IDL_tree node, int subnames_id)
+{
+       switch (IDL_NODE_TYPE (node)) {
+       case IDLN_TYPE_ENUM:
+               if (IDL_TYPE_ENUM (node).enumerator_list)
+                       fprintf (fh, "(char **)anon_subnames_array%d", subnames_id);
+               else
+                       fprintf (fh, "NULL");
+               break;
+       case IDLN_TYPE_UNION:
+               if (IDL_TYPE_UNION (node).switch_body)
+                       fprintf (fh, "(char **)anon_subnames_array%d", subnames_id);
+               else
+                       fprintf (fh, "NULL");
+               break;
+       case IDLN_TYPE_STRUCT:
+       case IDLN_EXCEPT_DCL:
+               if (IDL_TYPE_STRUCT (node).member_list)
+                       fprintf (fh, "(char **)anon_subnames_array%d", subnames_id);
+               else
+                       fprintf (fh, "NULL");
+               break;
+       default:
+               fprintf (fh, "NULL");
+               break;
+       }
+}
+
+static void
+forb_output_tcstruct_subtypes (FILE *fh, IDL_tree node, int subtypes_id)
+{
+       switch (IDL_NODE_TYPE (node)) {
+       case IDLN_EXCEPT_DCL:
+       case IDLN_TYPE_STRUCT:
+               if (IDL_TYPE_STRUCT (node).member_list)
+                       fprintf (fh, "(CORBA_TypeCode *)anon_subtypes_array%d", subtypes_id);
+               else
+                       fprintf (fh, "NULL");
+               break;
+       case IDLN_TYPE_UNION:
+               if (IDL_TYPE_UNION (node).switch_body)
+                       fprintf (fh, "(CORBA_TypeCode *)anon_subtypes_array%d", subtypes_id);
+               else
+                       fprintf (fh, "NULL");
+               break;
+       case IDLN_TYPE_SEQUENCE:
+       case IDLN_TYPE_ARRAY:
+       case IDLN_IDENT:
+               fprintf (fh, "(CORBA_TypeCode *)anon_subtypes_array%d", subtypes_id);
+               break;
+       default:
+               fprintf (fh, "NULL");
+               break;
+       }
+}
+
+static void
+forb_output_tcstruct_sublabels (FILE *fh, IDL_tree node, int sublabels_id)
+{
+       switch (IDL_NODE_TYPE (node)) {
+       case IDLN_TYPE_UNION:
+               fprintf (fh, "(CORBA_long *)anon_sublabels_array%d", sublabels_id);
+               break;
+       default:
+               fprintf (fh, "NULL");
+               break;
+       }
+}
+
+static void
+forb_output_tcstruct_discriminator (FILE *fh, IDL_tree node)
+{
+       switch (IDL_NODE_TYPE (node)) {
+       case IDLN_TYPE_UNION: {
+               char *switch_type_spec_str;
+
+               switch_type_spec_str = 
+                       forb_cbe_get_typespec_str (IDL_TYPE_UNION (node).switch_type_spec);
+
+               fprintf (fh, "(CORBA_TypeCode)&TC_%s_struct", switch_type_spec_str);
+
+               g_free (switch_type_spec_str);
+               }
+               break;
+       default:
+               fprintf (fh, "CORBA_OBJECT_NIL");
+               break;
+       }
+}
+
+static void
+forb_output_tcstruct_recurse_depth (FILE *fh)
+{
+       fprintf (fh, "0");
+}
+
+static void
+forb_output_tcstruct_default_index (FILE *fh, int union_default_index)
+{
+       fprintf (fh, "%d", union_default_index);
+}
+
+static void
+forb_output_tcstruct_digits_scale (FILE *fh, IDL_tree node)
+{
+       if (IDL_NODE_TYPE (node) == IDLN_TYPE_FIXED) {
+               fprintf (fh, "%" PRId64 ", %" PRId64 ,
+                        IDL_INTEGER (IDL_TYPE_FIXED (node).positive_int_const).value,
+                        IDL_INTEGER (IDL_TYPE_FIXED (node).integer_lit).value);
+       }
+       else
+               fprintf (fh, "0, 0");
+}
+
+static void
+forb_add_align (GSList **max, const char *str)
+{
+       GSList *l;
+
+       for (l = *max; l; l = l->next) {
+               if (!strcmp (l->data, str))
+                       return;
+       }
+       *max = g_slist_prepend (*max, (gpointer) str);
+}
+
+static GSList *
+forb_find_c_align (GSList *max, IDL_tree node)
+{
+       node = forb_cbe_get_typespec (node);    
+
+       switch (IDL_NODE_TYPE (node)) {
+       case IDLN_TYPE_INTEGER:
+               switch (IDL_TYPE_INTEGER (node).f_type) {
+               case IDL_INTEGER_TYPE_SHORT:
+                       forb_add_align (&max, "FORB_ALIGNOF_CORBA_SHORT");
+                       break;
+               case IDL_INTEGER_TYPE_LONG:
+                       forb_add_align (&max, "FORB_ALIGNOF_CORBA_LONG");
+                       break;
+               case IDL_INTEGER_TYPE_LONGLONG:
+                       forb_add_align (&max, "FORB_ALIGNOF_CORBA_LONG_LONG");
+                       break;
+               }
+               break;
+       case IDLN_TYPE_FLOAT:
+               switch (IDL_TYPE_FLOAT (node).f_type) {
+               case IDL_FLOAT_TYPE_FLOAT:
+                       forb_add_align (&max, "FORB_ALIGNOF_CORBA_FLOAT");
+                       break;
+               case IDL_FLOAT_TYPE_DOUBLE:
+                       forb_add_align (&max, "FORB_ALIGNOF_CORBA_DOUBLE");
+                       break;
+               case IDL_FLOAT_TYPE_LONGDOUBLE:
+                       forb_add_align (&max, "FORB_ALIGNOF_CORBA_LONG_DOUBLE");
+                       break;
+               }
+               break;
+       case IDLN_TYPE_ENUM:
+               forb_add_align (&max, "FORB_ALIGNOF_CORBA_LONG");
+               break;
+       case IDLN_TYPE_CHAR: /* drop through */
+       case IDLN_TYPE_BOOLEAN:
+       case IDLN_TYPE_OCTET:
+               forb_add_align (&max, "FORB_ALIGNOF_CORBA_CHAR");
+               break;
+       case IDLN_TYPE_WIDE_CHAR:
+               forb_add_align (&max, "FORB_ALIGNOF_CORBA_SHORT");
+               break;
+       case IDLN_TYPE_UNION: {
+               IDL_tree l = IDL_TYPE_UNION (node).switch_body;
+
+               forb_add_align (&max, "FORB_ALIGNOF_CORBA_STRUCT");
+
+               for (; l; l = IDL_LIST (l).next) {
+                       IDL_tree subtype = IDL_MEMBER (IDL_CASE_STMT (
+                               IDL_LIST (l).data).element_spec).type_spec;
+                       max = forb_find_c_align (max, subtype);
+               }
+               break;
+       }
+       case IDLN_EXCEPT_DCL: /* drop through */
+       case IDLN_TYPE_STRUCT: {
+               IDL_tree l = IDL_TYPE_STRUCT (node).member_list;
+                                       
+               for (; l; l = IDL_LIST (l).next) {
+                       IDL_tree member = IDL_MEMBER (IDL_LIST (l).data).type_spec;
+
+                       max = forb_find_c_align (max, member);
+               }
+               break;
+       }
+       case IDLN_TYPE_STRING: /* drop through */
+       case IDLN_TYPE_WIDE_STRING:
+       case IDLN_TYPE_OBJECT:
+       case IDLN_TYPE_TYPECODE:
+       case IDLN_FORWARD_DCL:
+       case IDLN_INTERFACE:
+               forb_add_align (&max, "FORB_ALIGNOF_CORBA_POINTER");
+               break;
+       case IDLN_TYPE_ARRAY: {
+               IDL_tree subtype = IDL_TYPE_DCL (
+                       IDL_get_parent_node (node, IDLN_TYPE_DCL, NULL)).type_spec;
+               max = forb_find_c_align (max, subtype);
+               break;
+       }
+       case IDLN_TYPE_SEQUENCE:
+               forb_add_align (&max, "FORB_ALIGNOF_CORBA_STRUCT");
+               forb_add_align (&max, "FORB_ALIGNOF_CORBA_LONG");
+               forb_add_align (&max, "FORB_ALIGNOF_CORBA_POINTER");
+               break;
+       case IDLN_TYPE_ANY:
+               forb_add_align (&max, "FORB_ALIGNOF_CORBA_STRUCT");
+               forb_add_align (&max, "FORB_ALIGNOF_CORBA_POINTER");
+               break;
+       default:
+               g_error ("Can't find alignment %s\n", 
+                        IDL_tree_type_names[IDL_NODE_TYPE (node)]);
+               break;
+       }
+
+       return max;
+}
+
+static void
+forb_output_tcstruct_c_align (FILE *fh, IDL_tree node)
+{
+       GSList *max;
+       GString *str = g_string_sized_new (120);
+
+       max = forb_find_c_align (NULL, node);
+
+       if (!max)
+               g_string_append (str, "1");
+
+       else if (!max->next)
+               g_string_append (str, max->data);
+
+       else {
+               int i = 0;
+               GSList *l;
+
+               for (l = max; l; l = l->next) {
+                       g_string_append (str, "MAX (");
+                       g_string_append (str, l->data);
+                       g_string_append (str, ", ");
+                       i++;
+               }
+               
+               g_string_append (str, "1");
+               for (; i > 0; i--)
+                       g_string_append_c (str, ')');
+       }
+
+       fprintf (fh, "%s", str->str);
+
+       g_string_free (str, TRUE);
+}
+
+static void
+cbe_tc_generate (OIDL_C_Info  *ci,
+                CBETCGenInfo *tci)
+{
+       CBETCGenInfo  subtci;
+       IDL_tree      curitem;
+       char         *ctmp;
+       int           union_default_index = -1,
+                     subnames_id  = random_id++,
+                     subtypes_id  = random_id++,
+                     sublabels_id = random_id++;
+
+       if (strncmp (tci->structname, "anon", 4)) {
+               fprintf (ci->fh, "#if ");
+               forb_cbe_id_cond_hack (ci->fh, "TC_IMPL",
+                                       tci->structname, ci->c_base_name);
+               fprintf (ci->fh, " && !defined(TC_DEF_%s)\n", tci->structname);
+               fprintf (ci->fh, "#define TC_DEF_%s 1\n", tci->structname);
+       }
+
+       if (IDL_NODE_TYPE (tci->ts) == IDLN_TYPE_DCL) {
+               subtci = *tci;
+
+               curitem = IDL_TYPE_DCL (tci->ts).type_spec;
+               subtci.substructname = ctmp = forb_generate_tcstruct_name (curitem);
+
+               /* 
+                * The only type not already defined elsewhere
+                * that can be in the left half of a TypeCode.
+                */
+               if (IDL_NODE_TYPE (curitem) == IDLN_TYPE_SEQUENCE) {
+                       subtci.structname = ctmp;
+                       subtci.ts         = curitem;
+                       cbe_tc_generate (ci, &subtci);
+               }
+
+               for (curitem = IDL_TYPE_DCL (tci->ts).dcls; curitem;
+                    curitem = IDL_LIST (curitem).next) {
+                       subtci.ts = IDL_LIST (curitem).data;
+
+                       if (IDL_NODE_TYPE (subtci.ts) == IDLN_TYPE_ARRAY)
+                               subtci.structname = forb_generate_tcstruct_name (
+                                                       IDL_TYPE_ARRAY (subtci.ts).ident);
+                       else
+                               subtci.structname = forb_generate_tcstruct_name (subtci.ts);
+
+                       cbe_tc_generate (ci, &subtci);
+                       g_free (subtci.structname);
+               }
+
+       g_free (ctmp);
+       return;
+       }
+
+       /* Do magic here - nesting of typecodes for arrays */
+       if (IDL_NODE_TYPE (tci->ts) == IDLN_TYPE_ARRAY && 
+            (IDL_list_length (IDL_TYPE_ARRAY (tci->ts).size_list) > tci->array_gen_ctr)) {
+
+               curitem = IDL_list_nth (IDL_TYPE_ARRAY (tci->ts).size_list,
+                                       tci->array_gen_ctr - 1);
+
+               subtci = *tci;
+               subtci.structname = ctmp = forb_generate_tcstruct_name (curitem);
+               subtci.array_gen_ctr++;
+
+               cbe_tc_generate (ci, &subtci);
+
+               tci->substructname = ctmp; /* FIXME: memory leak */
+       }
+
+       forb_output_tcstruct_anon_subnames_array  (ci->fh, tci->ts, subnames_id);
+       forb_output_tcstruct_anon_subtypes_array  (ci->fh, tci->ts, subtypes_id,
+                                                   tci->substructname);
+
+       union_default_index = forb_output_tcstruct_anon_sublabels_array (
+                                       ci->fh, tci->ts, sublabels_id);
+
+       if (!strncmp (tci->structname, "anon", 4))
+               fprintf (ci->fh, "static ");
+       else {
+               fprintf (ci->fh, "#ifdef FORB_IDL_C_IMODULE_%s\n",
+                        ci->c_base_name);
+               fprintf (ci->fh, "static\n");
+               fprintf (ci->fh, "#endif\n");
+       }
+
+       fprintf (ci->fh, "FORB2_MAYBE_CONST struct CORBA_TypeCode_struct %s_struct = {\n",
+                               tci->structname);
+
+       forb_output_tcstruct_parent (ci->fh);
+
+       fprintf (ci->fh, ",\n");
+
+       forb_output_tcstruct_kind (ci->fh, tci->ts, tci->array_gen_ctr);
+
+       fprintf (ci->fh, ",\n");
+
+       /* flags */
+       fprintf (ci->fh, "0,\n");
+
+       /* c_length */
+       fprintf (ci->fh, "0,\n");
+
+       forb_output_tcstruct_c_align (ci->fh, tci->ts);
+
+       fprintf (ci->fh, ",\n");
+
+       forb_output_tcstruct_length (ci->fh, tci->ts, tci->array_gen_ctr);
+
+       fprintf (ci->fh, ",\n");
+
+       forb_output_tcstruct_sub_parts (ci->fh, tci->ts);
+
+       fprintf (ci->fh, ",\n");
+
+       forb_output_tcstruct_subtypes (ci->fh, tci->ts, subtypes_id);
+
+       fprintf (ci->fh, ",\n");
+
+       forb_output_tcstruct_discriminator (ci->fh, tci->ts);
+
+       fprintf (ci->fh, ",\n");
+
+       forb_output_tcstruct_name (ci->fh, tci->ts, tci->array_gen_ctr);
+
+       fprintf (ci->fh, ",\n");
+
+       forb_output_tcstruct_repo_id (ci->fh, tci->ts, tci->array_gen_ctr);
+
+       fprintf (ci->fh, ",\n");
+
+       forb_output_tcstruct_subnames (ci->fh, tci->ts, subnames_id);
+
+       fprintf (ci->fh, ",\n");
+
+       forb_output_tcstruct_sublabels (ci->fh, tci->ts, sublabels_id);
+
+       fprintf (ci->fh, ",\n");
+
+       forb_output_tcstruct_default_index (ci->fh, union_default_index);
+
+       fprintf (ci->fh, ",\n");
+
+       forb_output_tcstruct_recurse_depth (ci->fh);
+
+       fprintf (ci->fh, ",\n");
+
+       forb_output_tcstruct_digits_scale (ci->fh, tci->ts);
+
+       fprintf (ci->fh, "\n};\n");
+
+       if (strncmp (tci->structname, "anon", 4))
+               fprintf (ci->fh, "#endif\n");
+}
diff --git a/src/forb/forb-idl/forb-idl-c-utils.c b/src/forb/forb-idl/forb-idl-c-utils.c
new file mode 100644 (file)
index 0000000..3d8aee6
--- /dev/null
@@ -0,0 +1,837 @@
+#include "config.h"
+
+#include "forb-idl-c-backend.h"
+
+#include <string.h>
+#include <inttypes.h>
+
+/** 
+ * 
+ * 
+ * @param of 
+ * @param ts Type spec.
+ * @param name decl
+ * @param use_name use identifier from name 
+ * @param var_prefix prefix for identifier taken from name
+ * @param serialization 
+ */
+void
+forb_cbe_write_ser_var(FILE *of, IDL_tree ts, IDL_tree name,
+                      bool use_name,
+                      char *var_prefix,
+                      enum forb_ser serialization)
+{
+       int indent = 0, i;
+       GString *id = g_string_new("");
+       char *serialize = (serialization == SERIALIZE) ? "serialize" : "deserialize";
+       gboolean use_ampersand = TRUE;
+
+       switch(IDL_NODE_TYPE(name)) {
+       case IDLN_IDENT:
+               fprintf(of, "  ");
+               if (use_name)
+                       g_string_assign(id, IDL_IDENT(name).str);
+               
+               if (IDL_NODE_TYPE(forb_cbe_get_typespec(ts)) == IDLN_TYPE_ARRAY)
+                 use_ampersand = FALSE;
+
+/*             printf("%s%s:\n", var_prefix, use_name ? id->str:""); */
+/*             forb_idl_print_node(forb_cbe_get_typespec(ts), 2); */
+       
+               break;
+       case IDLN_TYPE_ARRAY:
+       {
+               IDL_tree curitem;
+               char var;
+               if (use_name)
+                       g_string_assign(id, IDL_IDENT(IDL_TYPE_ARRAY(name).ident).str);
+
+               var = 'i';
+               fprintf(of, "  {\n    CORBA_unsigned_long ");
+               for(curitem = IDL_TYPE_ARRAY(name).size_list; curitem; curitem = IDL_LIST(curitem).next) {
+                       fprintf(of, "%c", var);
+                       if (IDL_LIST(curitem).next)
+                               fprintf(of, ", ");
+                       g_string_append_printf(id, "[%c]", var);
+                       var++;
+               }
+               fprintf(of, ";\n");
+
+               var = 'i';
+               for(curitem = IDL_TYPE_ARRAY(name).size_list; curitem; curitem = IDL_LIST(curitem).next) {
+                       indent++;
+                       for (i=0; i<indent+1; i++)
+                               fprintf(of, "  ");
+                       fprintf(of, "for (%c=0; %c<%" PRId64 "; %c++) \n",
+                               var, var, IDL_INTEGER(IDL_LIST(curitem).data).value, var);
+                       var++;
+               }
+
+
+               for (i=0; i<indent+2; i++)
+                       fprintf(of, "  ");
+
+       }
+       break;
+       default:
+               g_error("Weird varname - %s", IDL_tree_type_names[IDL_NODE_TYPE(name)]);
+               break;
+       }
+       fprintf(of, "if (!");
+       forb_cbe_write_typespec(of, ts);
+       fprintf(of, "_%s(codec, %s%s%s)) goto ser_exception;\n",
+               serialize, use_ampersand ? "&":"", var_prefix, id->str);
+       if (indent)
+               fprintf(of, "  }\n");
+
+       g_string_free(id, TRUE);
+}
+
+
+char *
+forb_cbe_get_typecode_name (IDL_tree tree)
+{
+       if (!tree)
+               return g_strdup ("TC_FIXME");
+       else
+               return g_strconcat ("TC_", forb_cbe_get_typespec_str (tree), NULL);
+}
+
+gboolean
+forb_cbe_type_is_builtin(IDL_tree tree)
+{ 
+/*   return FALSE; */
+  switch(IDL_NODE_TYPE(tree)) {
+  case IDLN_LIST:
+  case IDLN_GENTREE:
+  case IDLN_MEMBER:
+  case IDLN_CASE_STMT:
+  case IDLN_MODULE:
+  case IDLN_BINOP:
+  case IDLN_UNARYOP:
+  case IDLN_CODEFRAG:
+    g_error("Strange type for being a builtin");
+    break;
+  case IDLN_INTEGER:
+  case IDLN_STRING:
+  case IDLN_WIDE_STRING:
+  case IDLN_CHAR:
+  case IDLN_WIDE_CHAR:
+  case IDLN_FIXED:
+  case IDLN_FLOAT:
+  case IDLN_BOOLEAN:
+  case IDLN_CONST_DCL:
+  case IDLN_TYPE_INTEGER:
+  case IDLN_TYPE_FLOAT:
+  case IDLN_TYPE_CHAR:
+  case IDLN_TYPE_WIDE_CHAR:
+  case IDLN_TYPE_STRING:
+  case IDLN_TYPE_WIDE_STRING:
+  case IDLN_TYPE_BOOLEAN:
+  case IDLN_TYPE_OCTET:
+  case IDLN_TYPE_ANY:
+  case IDLN_TYPE_OBJECT:
+  case IDLN_TYPE_TYPECODE:
+  case IDLN_TYPE_ENUM:
+  case IDLN_TYPE_SEQUENCE:
+    return TRUE;
+    break;
+  case IDLN_TYPE_DCL:
+  case IDLN_EXCEPT_DCL:
+  case IDLN_ATTR_DCL:
+  case IDLN_OP_DCL:
+  case IDLN_PARAM_DCL:
+  case IDLN_TYPE_FIXED:
+  case IDLN_TYPE_ARRAY:
+  case IDLN_TYPE_STRUCT:
+  case IDLN_TYPE_UNION:
+  case IDLN_IDENT:
+  case IDLN_INTERFACE:
+  case IDLN_FORWARD_DCL:
+  case IDLN_NATIVE:
+  default:
+    return FALSE;
+    break;
+  }
+
+  return FALSE;
+}
+
+/**
+    Gets the "type" of {tree} as known in C.
+    The return value was alloc'd via g_malloc, and must be g_free'd.
+**/
+char *
+forb_cbe_get_typespec_str(IDL_tree tree)
+{
+  char *retval = NULL;
+  GString *tmpstr = NULL;
+
+  if(!tree) {
+    return g_strdup("void");
+  }
+
+  switch(IDL_NODE_TYPE(tree)) {
+  case IDLN_MEMBER:
+    return forb_cbe_get_typespec_str(IDL_MEMBER(tree).type_spec);
+    break;
+  case IDLN_TYPE_ANY:
+    retval = "CORBA_any";
+    break;
+  case IDLN_TYPE_FLOAT:
+    switch(IDL_TYPE_FLOAT(tree).f_type) {
+    case IDL_FLOAT_TYPE_FLOAT:
+      retval = "CORBA_float";
+      break;
+    case IDL_FLOAT_TYPE_DOUBLE:
+      retval = "CORBA_double";
+      break;
+    case IDL_FLOAT_TYPE_LONGDOUBLE:
+      retval = "CORBA_long_double";
+      break;
+    }
+    break;
+  case IDLN_TYPE_FIXED:
+    return g_strdup_printf( "CORBA_fixed_%" PRId64 "_%" PRId64 "",
+                    IDL_INTEGER(IDL_TYPE_FIXED(tree).positive_int_const).value,
+                    IDL_INTEGER(IDL_TYPE_FIXED(tree).integer_lit).value);
+    break;
+  case IDLN_TYPE_INTEGER:
+    tmpstr = g_string_new(NULL);
+    g_string_append(tmpstr, "CORBA_");
+    if(!IDL_TYPE_INTEGER(tree).f_signed)
+       g_string_append(tmpstr, "unsigned_");
+
+    switch(IDL_TYPE_INTEGER(tree).f_type) {
+    case IDL_INTEGER_TYPE_SHORT:
+       g_string_append(tmpstr, "short");
+       break;
+    case IDL_INTEGER_TYPE_LONGLONG:
+       g_string_append(tmpstr, "long_");
+       /* FALLTHROUGH */
+    case IDL_INTEGER_TYPE_LONG:
+       g_string_append(tmpstr, "long");
+       break;
+    }
+    break;
+  case IDLN_TYPE_STRING:
+    retval = "CORBA_string";   /* this is non-standard! */
+    break;
+  case IDLN_TYPE_OCTET:
+    retval = "CORBA_octet";
+    break;
+  case IDLN_TYPE_WIDE_STRING:
+    retval = "CORBA_wstring";  /* this is non-standard! */
+    break;
+  case IDLN_TYPE_CHAR:
+    retval = "CORBA_char";
+    break;
+  case IDLN_TYPE_WIDE_CHAR:
+    retval = "CORBA_wchar";
+    break;
+  case IDLN_TYPE_BOOLEAN:
+    retval = "CORBA_boolean";
+    break;
+  case IDLN_TYPE_STRUCT:
+    return forb_cbe_get_typespec_str(IDL_TYPE_STRUCT(tree).ident);
+  case IDLN_EXCEPT_DCL:
+    return forb_cbe_get_typespec_str(IDL_EXCEPT_DCL(tree).ident);
+  case IDLN_TYPE_ARRAY:
+    return forb_cbe_get_typespec_str(IDL_TYPE_ARRAY(tree).ident);
+  case IDLN_TYPE_UNION:
+    return forb_cbe_get_typespec_str(IDL_TYPE_UNION(tree).ident);
+  case IDLN_TYPE_ENUM:
+    return forb_cbe_get_typespec_str(IDL_TYPE_ENUM(tree).ident);
+  case IDLN_IDENT:
+    return IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(tree), "_", 0);
+  case IDLN_PARAM_DCL:
+    return forb_cbe_get_typespec_str(IDL_PARAM_DCL(tree).param_type_spec);
+  case IDLN_TYPE_SEQUENCE:
+    {
+       IDL_tree subtype = IDL_TYPE_SEQUENCE(tree).simple_type_spec;
+        char *ctmp, *base;
+        ctmp = forb_cbe_get_typespec_str(subtype);
+       /* We should have built-in alias to make this next line not needed */
+       base = forb_cbe_type_is_builtin(subtype)
+         ? ctmp + strlen("CORBA_") : ctmp;
+       retval = g_strdup_printf( "CORBA_sequence_%s", base);
+        g_free(ctmp);
+        return retval;
+    }
+    break;
+  case IDLN_NATIVE:
+    retval = forb_cbe_get_typespec_str(IDL_NATIVE(tree).ident);
+    break;
+  case IDLN_FORWARD_DCL:
+  case IDLN_INTERFACE:
+    return forb_cbe_get_typespec_str(IDL_INTERFACE(tree).ident);
+  case IDLN_TYPE_OBJECT:
+    retval = "CORBA_Object";
+    break;
+  case IDLN_TYPE_TYPECODE:
+    retval = "CORBA_TypeCode";
+    break;
+  default:
+    g_error("We were asked to get a typename for a %s",
+           IDL_tree_type_names[IDL_NODE_TYPE(tree)]);
+    break;
+  }
+
+  if (retval)
+    return g_strdup (retval);
+  else
+    return g_string_free (tmpstr, FALSE);
+}
+
+void
+forb_cbe_write_typespec(FILE *of, IDL_tree tree)
+{
+    char *name = forb_cbe_get_typespec_str(tree);
+    fprintf( of, name);
+    g_free(name);
+}
+
+/**
+    Parameters (e.g., arguments to methods, and the return value
+    have some complicated rules in the C mapping for how many
+    levels of pointer and the exact type involved. This function
+    generates the externally visible parameter type.
+
+    Note the hack below because "const CORBA_string" is not
+    promotable to "const CORBA_char*" (the later the standard
+    to which apps are written, while the former is what would
+    be produced without the hack).
+**/
+static char *
+forb_cbe_write_param_typespec_str(IDL_tree ts, IDL_ParamRole role)
+{
+       int      i, n;
+       gboolean isSlice;
+       char    *name;
+       GString *str = g_string_sized_new (23);
+       IDL_tree typedef_spec;
+       char *typedef_name;
+
+       n = oidl_param_info (ts, role, &isSlice);
+       name = forb_cbe_get_typespec_str (ts);
+
+       if ( role == DATA_IN ) {
+               /* We want to check if this is a typedef for CORBA_string so we can do special handling 
+                * in that case. 
+                */
+               typedef_spec = forb_cbe_get_typespec (ts);
+               typedef_name = forb_cbe_get_typespec_str (typedef_spec);
+
+               g_string_printf (str, "const %s", 
+                                !strcmp (typedef_name, "CORBA_string") ?
+                                "CORBA_char *" : name);
+
+               g_free (typedef_name);
+       } else
+               g_string_printf (str, "%s", name);
+
+       g_free (name);
+
+       if ( isSlice )
+               g_string_append (str, "_slice");
+
+       for (i = 0; i < n; i++)
+               g_string_append_c (str, '*');
+
+       return g_string_free (str, FALSE);
+}
+
+static void
+forb_cbe_write_param_typespec_raw (FILE *of, IDL_tree ts, IDL_ParamRole role)
+{
+    char *str;
+    str = forb_cbe_write_param_typespec_str (ts, role);
+    fprintf (of, str);
+    g_free (str);
+}
+
+void
+forb_cbe_write_param_typespec(FILE *of, IDL_tree tree) {
+    IDL_tree           ts = NULL /* Quiet gcc */;
+    IDL_ParamRole      role = 0 /* Quiet gcc */;
+
+    switch ( IDL_NODE_TYPE(tree) ) {
+    case IDLN_OP_DCL: /* means return value of method */
+        ts = IDL_OP_DCL(tree).op_type_spec;
+       role = DATA_RETURN;
+        break;
+    case IDLN_PARAM_DCL: /* one of the parameters */
+        ts = IDL_PARAM_DCL(tree).param_type_spec;
+       role = oidl_attr_to_paramrole(IDL_PARAM_DCL(tree).attr);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    forb_cbe_write_param_typespec_raw(of, ts, role);
+}
+
+void
+forb_cbe_op_write_proto (FILE       *of,
+                         IDL_tree    op,
+                         const char *nom_prefix,
+                         gboolean    for_epv)
+{
+       IDL_tree  sub;
+       char     *id;
+
+       g_assert (IDL_NODE_TYPE(op) == IDLN_OP_DCL);
+
+       forb_cbe_write_param_typespec (of, op);
+
+       id = IDL_ns_ident_to_qstring (
+               IDL_IDENT_TO_NS (IDL_INTERFACE (
+                       IDL_get_parent_node (op, IDLN_INTERFACE, NULL)).ident), "_", 0);
+
+       if (for_epv)
+               fprintf (of, "\t(*%s%s)", nom_prefix ? nom_prefix : "",
+                        IDL_IDENT(IDL_OP_DCL(op).ident).str);
+       else 
+               fprintf (of, " %s%s_%s", nom_prefix ? nom_prefix : "",
+                        id, IDL_IDENT (IDL_OP_DCL (op).ident).str);
+
+       fprintf (of, "(");
+
+/*     if (for_epv) */
+/*             fprintf (of, "PortableServer_Servant _servant, "); */
+/*     else */
+               fprintf (of, "%s _obj, ", id);
+
+       g_free (id);
+
+       for (sub = IDL_OP_DCL (op).parameter_dcls; sub; sub = IDL_LIST (sub).next) {
+               IDL_tree parm = IDL_LIST (sub).data;
+
+               forb_cbe_write_param_typespec (of, parm);
+
+               fprintf (of, " %s, ", IDL_IDENT (IDL_PARAM_DCL (parm).simple_declarator).str);
+       }
+
+       if (IDL_OP_DCL (op).context_expr)
+               fprintf (of, "CORBA_Context _ctx, ");
+
+       fprintf (of, "CORBA_Environment *ev)");
+}
+
+/* Writes the value of the constant in 'tree' to file handle 'of' */
+static char *
+forb_cbe_get_const(IDL_tree tree)
+{
+  char *opc = NULL, *retval, *ctmp;
+  GString *tmpstr = g_string_new(NULL);
+
+  switch(IDL_NODE_TYPE(tree)) {
+  case IDLN_BOOLEAN:
+    g_string_printf(tmpstr, "%s", IDL_BOOLEAN(tree).value?"CORBA_TRUE":"CORBA_FALSE");
+    break;
+  case IDLN_CHAR:
+    g_string_printf(tmpstr, "'\\x%X'", *(unsigned char *)IDL_CHAR(tree).value);
+    break;
+  case IDLN_FLOAT:
+    g_string_printf(tmpstr, "%f", IDL_FLOAT(tree).value);
+    break;
+  case IDLN_INTEGER:
+    g_string_printf(tmpstr, "%" PRId64 "", IDL_INTEGER(tree).value);
+    break;
+  case IDLN_STRING:
+    g_string_printf(tmpstr, "\"%s\"", IDL_STRING(tree).value);
+    break;
+  case IDLN_WIDE_CHAR:
+    g_string_printf(tmpstr, "L'%ls'", IDL_WIDE_CHAR(tree).value);
+    break;
+  case IDLN_WIDE_STRING:
+    g_string_printf(tmpstr, "L\"%ls\"", IDL_WIDE_STRING(tree).value);
+    break;
+  case IDLN_BINOP:
+    g_string_printf(tmpstr, "(");
+    ctmp = forb_cbe_get_const(IDL_BINOP(tree).left);
+    g_string_append(tmpstr, ctmp);
+    g_free(ctmp);
+    switch(IDL_BINOP(tree).op) {
+    case IDL_BINOP_OR:
+      opc = "|";
+      break;
+    case IDL_BINOP_XOR:
+      opc = "^";
+      break;
+    case IDL_BINOP_AND:
+      opc = "&";
+      break;
+    case IDL_BINOP_SHR:
+      opc = ">>";
+      break;
+    case IDL_BINOP_SHL:
+      opc = "<<";
+      break;
+    case IDL_BINOP_ADD:
+      opc = "+";
+      break;
+    case IDL_BINOP_SUB:
+      opc = "-";
+      break;
+    case IDL_BINOP_MULT:
+      opc = "*";
+      break;
+    case IDL_BINOP_DIV:
+      opc = "/";
+      break;
+    case IDL_BINOP_MOD:
+      opc = "%";
+      break;
+    }
+    g_string_append_printf(tmpstr, " %s ", opc);
+    ctmp = forb_cbe_get_const(IDL_BINOP(tree).right);
+    g_string_append_printf(tmpstr, "%s)", ctmp);
+    g_free(ctmp);
+    break;
+  case IDLN_UNARYOP:
+    switch(IDL_UNARYOP(tree).op) {
+    case IDL_UNARYOP_PLUS: opc = "+"; break;
+    case IDL_UNARYOP_MINUS: opc = "-"; break;
+    case IDL_UNARYOP_COMPLEMENT: opc = "~"; break;
+    }
+    ctmp = forb_cbe_get_const(IDL_UNARYOP(tree).operand);
+    g_string_printf(tmpstr, "%s%s", opc, ctmp);
+    g_free(ctmp);
+    break;
+  case IDLN_IDENT:
+    {
+      char *id;
+      id = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(tree), "_", 0);
+      g_string_printf(tmpstr, "%s", id);
+      g_free(id);
+    }
+    break;
+  default:
+    g_error("We were asked to print a constant for %s", IDL_tree_type_names[tree->_type]);
+    break;
+  }
+
+  retval = tmpstr->str;
+
+  g_string_free(tmpstr, FALSE);
+
+  return retval;
+}
+
+void
+forb_cbe_write_const(FILE *of, IDL_tree tree)
+{
+  char *ctmp;
+
+  ctmp = forb_cbe_get_const(tree);
+  fprintf(of, "%s", ctmp);
+  g_free(ctmp);
+}
+
+/* This is the WORST HACK in the WORLD, really truly, but the C preprocessor doesn't allow us to use
+   strings, so we have to work around it by using individual characters. */
+void
+forb_cbe_id_define_hack(FILE *fh, const char *def_prefix, const char *def_name, const char *def_value)
+{
+  int i, n;
+  n = strlen(def_value);
+  for(i = 0; i < n; i++)
+    fprintf(fh, "#define %s_%s_%d '%c'\n", def_prefix, def_name, i, def_value[i]);
+}
+
+void
+forb_cbe_id_cond_hack(FILE *fh, const char *def_prefix, const char *def_name, const char *def_value)
+{
+  int i, n;
+  n = strlen(def_value);
+  if(n <= 0)
+    return;
+
+  fprintf(fh, "(");
+
+  for(i = 0; i < n; i++)
+    fprintf(fh, "%s (%s_%s_%d == '%c') \\\n", i?"&&":"", def_prefix, def_name, i, def_value[i]);
+  fprintf(fh, ")");
+}
+
+#define BASE_TYPES \
+            IDLN_TYPE_INTEGER: \
+       case IDLN_TYPE_FLOAT: \
+       case IDLN_TYPE_ENUM: \
+        case IDLN_TYPE_BOOLEAN: \
+       case IDLN_TYPE_CHAR: \
+       case IDLN_TYPE_WIDE_CHAR: \
+       case IDLN_TYPE_OCTET
+
+#define STRING_TYPES \
+            IDLN_TYPE_STRING: \
+       case IDLN_TYPE_WIDE_STRING
+
+#define OBJREF_TYPES \
+            IDLN_TYPE_OBJECT: \
+       case IDLN_INTERFACE: \
+       case IDLN_FORWARD_DCL
+
+static const char *
+forb_cbe_flatten_ref (IDL_ParamRole role, IDL_tree typespec)
+{
+       gboolean is_fixed;
+
+       is_fixed = forb_cbe_type_is_fixed_length (typespec);
+
+       switch (role) {
+       case DATA_IN:
+               switch (IDL_NODE_TYPE (typespec)) {
+               case BASE_TYPES:
+               case STRING_TYPES:
+               case OBJREF_TYPES:
+               case IDLN_TYPE_TYPECODE:
+               case IDLN_NATIVE:
+                       return "(gpointer)&";
+
+               case IDLN_TYPE_STRUCT:
+               case IDLN_TYPE_UNION:
+               case IDLN_TYPE_ANY:
+               case IDLN_TYPE_SEQUENCE:
+               case IDLN_TYPE_ARRAY:
+                       return "(gpointer)";
+                       
+               default:
+               case IDLN_TYPE_FIXED:
+                       g_error ("Hit evil type %d", IDL_NODE_TYPE (typespec));
+               };
+               return NULL;
+
+       case DATA_INOUT:
+               switch (IDL_NODE_TYPE (typespec)) {
+               case BASE_TYPES:
+               case STRING_TYPES:
+               case OBJREF_TYPES:
+               case IDLN_TYPE_TYPECODE:
+               case IDLN_TYPE_STRUCT:
+               case IDLN_TYPE_UNION:
+               case IDLN_TYPE_ARRAY:
+               case IDLN_NATIVE:
+               case IDLN_TYPE_ANY:
+               case IDLN_TYPE_SEQUENCE:
+                       return "";
+
+               default:
+               case IDLN_TYPE_FIXED:
+                       g_error ("Hit evil type %d", IDL_NODE_TYPE (typespec));
+               };
+               return NULL;
+
+       case DATA_OUT:
+               switch (IDL_NODE_TYPE (typespec)) {
+               case BASE_TYPES:
+               case STRING_TYPES:
+               case OBJREF_TYPES:
+               case IDLN_TYPE_TYPECODE:
+               case IDLN_NATIVE:
+                       return "&";
+
+               case IDLN_TYPE_STRUCT:
+               case IDLN_TYPE_UNION:
+               case IDLN_TYPE_ARRAY:
+                       if (is_fixed)
+                               return "&";
+                       else /* drop through */
+
+               case IDLN_TYPE_SEQUENCE:
+               case IDLN_TYPE_ANY:
+                       return "";
+
+               default:
+               case IDLN_TYPE_FIXED:
+                       g_error ("Hit evil type %d", IDL_NODE_TYPE (typespec));
+               };
+               return NULL;
+
+       case DATA_RETURN:
+               g_error ("No data return handler");
+               return NULL;
+       }
+
+       return NULL;
+}
+
+void
+forb_cbe_flatten_args (IDL_tree tree, FILE *of, const char *name)
+{
+       int i = 0;
+       IDL_tree l;
+
+       for (l = IDL_OP_DCL(tree).parameter_dcls; l;
+            l = IDL_LIST(l).next)
+               i++;
+
+       fprintf (of, "gpointer %s[%d];\n", name, i);
+       
+       i = 0;
+       for (l = IDL_OP_DCL(tree).parameter_dcls; l;
+            l = IDL_LIST(l).next) {
+               IDL_tree decl = IDL_LIST (l).data;
+               IDL_tree tspec = forb_cbe_get_typespec (decl);
+               IDL_ParamRole r = 0;
+
+               switch(IDL_PARAM_DCL(decl).attr) {
+               case IDL_PARAM_IN:    r = DATA_IN;    break;
+               case IDL_PARAM_INOUT: r = DATA_INOUT; break;
+               case IDL_PARAM_OUT:   r = DATA_OUT;   break;
+               default:
+                       g_error("Unknown IDL_PARAM type");
+               }
+               
+               fprintf (of, "%s[%d] = %s%s;\n",
+                        name, i,
+                        forb_cbe_flatten_ref (r, tspec),
+                        IDL_IDENT (IDL_PARAM_DCL (decl).simple_declarator).str);
+               i++;
+       }
+}
+
+static char *
+forb_cbe_unflatten_ref (IDL_ParamRole role, IDL_tree typespec)
+{
+       gboolean is_fixed;
+       char    *typestr;
+       char    *retval;
+
+       is_fixed = forb_cbe_type_is_fixed_length (typespec);
+
+       typestr = forb_cbe_write_param_typespec_str (typespec, role);
+
+       switch (role) {
+       case DATA_IN:
+               switch (IDL_NODE_TYPE (typespec)) {
+               case BASE_TYPES:
+               case STRING_TYPES:
+               case OBJREF_TYPES:
+               case IDLN_TYPE_TYPECODE:
+               case IDLN_NATIVE:
+                       retval = g_strdup_printf ("*(%s *)", typestr);
+                       break;
+
+
+               case IDLN_TYPE_ARRAY:
+                       retval = g_strdup_printf ("(%s_slice *)", typestr);
+                       break;
+
+               case IDLN_TYPE_STRUCT:
+               case IDLN_TYPE_UNION:
+               case IDLN_TYPE_ANY:
+               case IDLN_TYPE_SEQUENCE:
+                       retval = g_strdup_printf ("(%s)", typestr);
+                       break;
+                       
+               default:
+               case IDLN_TYPE_FIXED:
+                       g_error ("Hit evil type %d", IDL_NODE_TYPE (typespec));
+                       retval = NULL;
+                       break;
+               };
+               break;
+
+       case DATA_INOUT:
+               switch (IDL_NODE_TYPE (typespec)) {
+               case IDLN_TYPE_ARRAY:
+                       retval = g_strdup_printf ("(%s_slice *)", typestr);
+                       break;
+
+               case BASE_TYPES:
+               case STRING_TYPES:
+               case OBJREF_TYPES:
+               case IDLN_TYPE_TYPECODE:
+               case IDLN_TYPE_STRUCT:
+               case IDLN_TYPE_UNION:
+               case IDLN_NATIVE:
+               case IDLN_TYPE_ANY:
+               case IDLN_TYPE_SEQUENCE:
+                       retval = g_strdup_printf ("(%s)", typestr);
+                       break;
+
+               default:
+               case IDLN_TYPE_FIXED:
+                       g_error ("Hit evil type %d", IDL_NODE_TYPE (typespec));
+                       retval = NULL;
+                       break;
+               };
+               break;
+
+       case DATA_OUT:
+               switch (IDL_NODE_TYPE (typespec)) {
+               case BASE_TYPES:
+               case STRING_TYPES:
+               case OBJREF_TYPES:
+               case IDLN_TYPE_TYPECODE:
+               case IDLN_NATIVE:
+                       retval = g_strdup_printf ("*(%s *)", typestr);
+                       break;
+
+               case IDLN_TYPE_ARRAY:
+                       if (is_fixed) {
+                               retval = g_strdup_printf ("*(%s_slice **)", typestr);
+                               break;
+                       }
+                       /* drop through */
+
+               case IDLN_TYPE_STRUCT:
+               case IDLN_TYPE_UNION:
+                       if (is_fixed) {
+                               retval = g_strdup_printf ("*(%s *)", typestr);
+                               break;
+                       }
+                       /* drop through */
+
+               case IDLN_TYPE_SEQUENCE:
+               case IDLN_TYPE_ANY:
+                       retval = g_strdup_printf ("(%s)", typestr);
+                       break;
+
+               default:
+               case IDLN_TYPE_FIXED:
+                       g_error ("Hit evil type %d", IDL_NODE_TYPE (typespec));
+                       retval = NULL;
+                       break;
+               };
+               break;
+
+       case DATA_RETURN:
+       default:
+               g_error ("No data return handler");
+               retval = NULL;
+               break;
+       }
+
+       g_free (typestr);
+
+       return retval;
+}
+
+void
+forb_cbe_unflatten_args (IDL_tree tree, FILE *of, const char *name)
+{
+       IDL_tree l;
+       int      i = 0;
+
+       for (l = IDL_OP_DCL(tree).parameter_dcls; l;
+            l = IDL_LIST(l).next) {
+               IDL_tree decl = IDL_LIST (l).data;
+               IDL_tree tspec = forb_cbe_get_typespec (decl);
+               IDL_ParamRole r = 0;
+               char *unflatten;
+
+               switch(IDL_PARAM_DCL(decl).attr) {
+               case IDL_PARAM_IN:    r = DATA_IN;    break;
+               case IDL_PARAM_INOUT: r = DATA_INOUT; break;
+               case IDL_PARAM_OUT:   r = DATA_OUT;   break;
+               default:
+                       g_error("Unknown IDL_PARAM type");
+               }
+
+               unflatten = forb_cbe_unflatten_ref (r, tspec);
+               fprintf (of, "%s%s[%d], ", unflatten, name, i++);
+               g_free (unflatten);
+       }
+}
diff --git a/src/forb/forb-idl/forb-idl-driver.c b/src/forb/forb-idl/forb-idl-driver.c
new file mode 100644 (file)
index 0000000..adc860f
--- /dev/null
@@ -0,0 +1,100 @@
+/**************************************************************************
+
+    forb-idl-driver.c (Dispatch parsed tree to various backends)
+
+    Copyright (C) 1999 Elliot Lee
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    $Id: forb-idl-driver.c 1302 2002-09-04 10:38:18Z mmclouglin $
+
+***************************************************************************/
+
+#include "config.h"
+
+#include "forb-idl2.h"
+#include "forb-idl-backend.h"
+#include "forb-idl-c-backend.h"
+
+#include <string.h>
+
+static void
+forb_idl_tree_fake_ops (IDL_tree tree, IDL_ns ns)
+{
+       IDL_tree node;
+
+       if (!tree)
+               return;
+
+       switch(IDL_NODE_TYPE(tree)) {
+       case IDLN_MODULE:
+               forb_idl_tree_fake_ops (IDL_MODULE (tree).definition_list, ns);
+               break;
+       case IDLN_INTERFACE:
+               forb_idl_tree_fake_ops (IDL_INTERFACE (tree).body, ns);
+               break;
+       case IDLN_LIST:
+               for (node = tree; node; node = IDL_LIST (node).next)
+                       forb_idl_tree_fake_ops (IDL_LIST (node).data, ns);
+               break;
+       case IDLN_ATTR_DCL:
+               forb_idl_attr_fake_ops (tree, ns);
+               break;
+       default:
+               break;
+       }
+}
+
+gboolean
+forb_idl_to_backend (const char    *filename,
+                     OIDL_Run_Info *rinfo)
+{
+       IDL_ns   ns;
+       IDL_tree tree;
+       int      errcode;
+       gboolean retval;
+
+       errcode = IDL_parse_filename (
+                       filename, rinfo->cpp_args, NULL,
+                       &tree, &ns,
+                       (rinfo->show_cpp_errors ? IDLF_SHOW_CPP_ERRORS : 0) |
+                       (rinfo->is_pidl ? IDLF_XPIDL : 0) |
+                       (rinfo->onlytop ? IDLF_INHIBIT_INCLUDES : 0) |
+                       IDLF_TYPECODES |
+                       IDLF_SRCFILES |
+                       IDLF_CODEFRAGS,
+                       rinfo->idl_warn_level);
+
+       rinfo->ns = ns;
+
+       if (rinfo->debug_level > 3)
+               forb_idl_print_node (tree, 0);
+
+       if (errcode != IDL_SUCCESS) {
+               if (errcode == -1)
+                       g_warning ("Parse of %s failed: %s", filename, g_strerror (errno));
+
+               return 0;
+       }
+
+       forb_idl_tree_fake_ops (tree, ns);
+
+       if (!strcmp (rinfo->output_language, "c")) 
+               retval = forb_idl_output_c (tree, rinfo);
+//     else
+//             retval = forb_idl_backend_output (rinfo, tree);
+
+       return retval;
+}
diff --git a/src/forb/forb-idl/forb-idl-main.c b/src/forb/forb-idl/forb-idl-main.c
new file mode 100644 (file)
index 0000000..d872360
--- /dev/null
@@ -0,0 +1,297 @@
+/**************************************************************************
+
+    forb-idl-main.c (Driver program for the IDL parser & backend)
+
+    Copyright (C) 1999 Elliot Lee
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    $Id: forb-idl-main.c 2060 2008-05-19 21:11:07Z tml $
+
+***************************************************************************/
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <glib.h>
+#include <libIDL/IDL.h>
+#include <glib/goption.h>
+#include <glib/gi18n.h>
+#include "forb_config.h"
+
+#include "forb-idl2.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* FIXME: this program doesn't seem to support i18n? */
+#ifndef GETTEXT_PACKAGE
+#define GETTEXT_PACKAGE NULL
+#endif
+
+/* Settings made from the command line (prefaced with cl_) */
+static gboolean cl_disable_stubs = FALSE,
+  cl_disable_skels = FALSE,
+  cl_disable_common = FALSE,
+  cl_disable_headers = FALSE;
+  /* cl_enable_skeleton_impl = FALSE */
+static int cl_idlwarnlevel = 2;
+static int cl_debuglevel = 0;
+static int cl_is_pidl = 0;
+static int cl_disable_idata = 0;
+/* static int cl_enable_imodule = 0; */
+/* static int cl_add_imodule = 0; */
+static gboolean cl_disable_defs_skels = FALSE;
+static gboolean cl_showcpperrors = FALSE;
+static char *cl_output_lang = "c";
+static char *cl_include = NULL;
+static char *cl_header_guard_prefix = "";
+static char *cl_backend_dir = NULL;
+static gboolean cl_onlytop = TRUE;
+static char *cl_deps_file = NULL;
+static char *cl_output_directory = "";
+static char **idl_files = NULL;
+
+#define BASE_CPP_ARGS "-D__FORB_IDL__ "
+static GString *cl_cpp_args;
+
+/* Callbacks for goption */
+
+static gboolean
+cl_libIDL_version_callback (const char *option_name,
+                           const char *value,
+                           gpointer data,
+                           GError **error)
+{
+  g_print("libIDL %s (CORBA %s)\n",
+         IDL_get_libver_string(),
+         IDL_get_IDLver_string());
+  exit(0);
+}
+
+static gboolean
+cl_cpp_define_callback (const char *option_name,
+                       const char *value,
+                       gpointer data,
+                       GError **error)
+{
+  g_string_append_printf (cl_cpp_args, "-D%s ", value);
+  return TRUE;
+}
+
+static gboolean
+cl_cpp_include_callback (const char *option_name,
+                        const char *value,
+                        gpointer data,
+                        GError **error)
+{
+  g_string_append_printf (cl_cpp_args, "-I%s ", value);
+  return TRUE;
+}
+
+static gboolean
+cl_version_callback (const char *option_name,
+                    const char *value,
+                    gpointer data,
+                    GError **error)
+{
+  g_print ("forb-idl-2 %s - serial %d\n",
+           VERSION, FORB_CONFIG_SERIAL);
+  exit(0);
+}
+
+/* static gboolean */
+/* cl_c_output_formatter_callback (const char *option_name, */
+/*                             const char *value, */
+/*                             gpointer data, */
+/*                             GError **error) */
+/* { */
+/*   g_warning ("Do not use the 'c-output-formatter' option. It is ignored and will soon go away."); */
+/*   return TRUE; */
+/* } */
+
+static const GOptionEntry cl_libIDL_goptions[] = {
+  { "libIDL-version", 0, 0, G_OPTION_ARG_CALLBACK, cl_libIDL_version_callback, N_("Show version of libIDL used"), NULL },
+  { NULL }
+};
+
+static const GOptionEntry cl_cpp_goptions[] = {
+  { "define", 'D', G_OPTION_FLAG_FILENAME, G_OPTION_ARG_CALLBACK, cl_cpp_define_callback, N_("Define value in preprocessor"), N_("DEFINE") },
+  { "include", 'I', G_OPTION_FLAG_FILENAME, G_OPTION_ARG_CALLBACK, cl_cpp_include_callback, N_("Add search path for include files"), N_("DIR") },
+  { NULL }
+};
+
+static const GOptionEntry goptions[] = {
+  { "version", 'v', 0, G_OPTION_ARG_CALLBACK, cl_version_callback, N_("Output compiler version and serial"), NULL },
+  { "lang", 'l', 0, G_OPTION_ARG_STRING, &cl_output_lang, N_("Output language (default is C)"), N_("LANG") },
+  { "debug", 'd', 0, G_OPTION_ARG_INT, &cl_debuglevel, N_("Debug level (0 to 4)"), N_("LEVEL") },
+  { "idlwarnlevel", 0, 0, G_OPTION_ARG_INT, &cl_idlwarnlevel, N_("IDL warning level (0 to 4, default is 2)"), N_("LEVEL") },
+  { "showcpperrors", 0, 0, G_OPTION_ARG_NONE, &cl_showcpperrors, N_("Show CPP errors"), NULL },
+  { "nostubs", 0, 0, G_OPTION_ARG_NONE, &cl_disable_stubs, N_("Don't output stubs"), NULL },
+  { "noskels", 0, 0, G_OPTION_ARG_NONE, &cl_disable_skels, N_("Don't output skels"), NULL },
+  { "nocommon", 0, 0, G_OPTION_ARG_NONE, &cl_disable_common, N_("Don't output common"), NULL },
+  { "noheaders", 0, 0, G_OPTION_ARG_NONE, &cl_disable_headers, N_("Don't output headers"), NULL },
+  { "include", 0, 0, G_OPTION_ARG_STRING, &cl_include, N_("Put #include <FILE> to the generated header (for native types)"), N_("FILE") },
+/*   { "noidata", 0, 0, G_OPTION_ARG_NONE, &cl_disable_idata, N_("Don't generate Interface type data"), NULL }, */
+/*   { "imodule", 'i', 0, G_OPTION_ARG_NONE, &cl_enable_imodule, N_("Output only an imodule file"), NULL }, */
+/*   { "add-imodule", 0, 0, G_OPTION_ARG_NONE, &cl_add_imodule, N_("Output an imodule file"), NULL }, */
+/*   { "skeleton-impl", 0, 0, G_OPTION_ARG_NONE, &cl_enable_skeleton_impl, N_("Output skeleton implementation"), NULL }, */
+  { "backenddir", 0, 0, G_OPTION_ARG_FILENAME, &cl_backend_dir, N_("Override IDL backend library directory"), N_("DIR") },
+/*   { "c-output-formatter", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, &cl_c_output_formatter_callback, "DEPRECATED and IGNORED", "PROGRAM" }, */
+  { "onlytop", 0, 0, G_OPTION_ARG_NONE, &cl_onlytop, N_("Inhibit includes"), NULL },
+  { "pidl", 0, 0, G_OPTION_ARG_NONE, &cl_is_pidl, N_("Treat as Pseudo IDL"), NULL },
+  { "nodefskels", 0, 0, G_OPTION_ARG_NONE, &cl_disable_defs_skels, N_("Don't output defs for skels in header"), NULL },
+  { "deps", 0, 0,  G_OPTION_ARG_FILENAME, &cl_deps_file, N_("Generate dependency info suitable for inclusion in Makefile"), N_("FILENAME") },
+  { "headerguardprefix", 0, 0, G_OPTION_ARG_STRING, &cl_header_guard_prefix, N_("Prefix for #ifdef header guards. Sometimes useful to avoid conflicts."), N_("PREFIX") },
+  { "output-dir", 0, 0, G_OPTION_ARG_FILENAME, &cl_output_directory, N_("Where to put generated files. This directory must exist."), N_("DIR") },
+  { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &idl_files, NULL, N_("<IDL files>") },
+  { NULL }
+};
+
+/********** main routines **********/
+int main(int argc, char *argv[])
+{
+  GOptionContext *context;
+  GOptionGroup *group;
+  GError *error = NULL;
+  OIDL_Run_Info rinfo;
+  GPtrArray *args;
+  int retval = 0;
+  gboolean result;
+  gpointer freeme;
+  guint i;
+
+  /* Argument parsing, etc. */
+  cl_cpp_args = g_string_new("-D__FORB_IDL__ ");
+
+  /* GOption cannot parse single-letter options without space
+   * between option and argument (-I../dir) or single-dash options.
+   * So fix those up before parsing, to retain command line compatibility
+   * with previous popt based versions of forb-idl-2
+   */
+  args = g_ptr_array_sized_new (2 * argc);
+  g_ptr_array_add (args, g_strdup (argv[0]));
+
+  for (i = 1; i < argc; ++i) {
+    if (argv[i][0] == '-' &&
+       (argv[i][1] == 'D' || argv[i][1] == 'I') &&
+       argv[i][2] != '\0') {
+      g_ptr_array_add (args, g_strndup (argv[i], 2));
+      g_ptr_array_add (args, g_strdup (argv[i] + 2));
+    } else if (strcmp (argv[i], "-define") == 0 ||
+               strcmp (argv[i], "-include") == 0) {
+      g_ptr_array_add (args, g_strdup_printf ("-%s", argv[i]));
+    } else {
+      g_ptr_array_add (args, g_strdup (argv[i]));
+    }
+  }
+
+  /* Parsing will modify the array; memdup it beforehand
+   * so we can free it correctly
+   */
+  argc = args->len;
+  argv = freeme = g_memdup (args->pdata, argc * sizeof (gpointer));
+  g_ptr_array_add (args, NULL); /* so we can use g_strfreev */
+
+  /* Now parse the options */
+  context = g_option_context_new ("");
+  g_option_context_add_main_entries (context, goptions, GETTEXT_PACKAGE);
+
+  group = g_option_group_new ("libIDL", N_("libIDL options"), N_("Show libIDL options"), NULL, NULL);
+  g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
+  g_option_group_add_entries (group, cl_libIDL_goptions);
+  g_option_context_add_group (context, group);
+
+  group = g_option_group_new ("cpp", N_("Preprocessor options"), N_("Show preprocessor options"), NULL, NULL);
+  g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
+  g_option_group_add_entries (group, cl_cpp_goptions);
+  g_option_context_add_group (context, group);
+
+  result = g_option_context_parse (context, &argc, &argv, &error);
+  g_option_context_free (context);
+  g_strfreev ((char **) g_ptr_array_free (args, FALSE));
+  g_free (freeme);
+
+  if (!result) {
+    g_print ("forb-idl-2: %s\n", error->message);
+    g_error_free (error);
+    exit (1);
+  }
+
+  if (!idl_files) {
+    g_print ("No input files given!\n");
+    exit (1);
+  }
+
+  /* Prep our run info for the backend */
+  rinfo.cpp_args = cl_cpp_args->str;
+  rinfo.debug_level = cl_debuglevel;
+  rinfo.idl_warn_level = cl_idlwarnlevel;
+  rinfo.show_cpp_errors = cl_showcpperrors;
+  rinfo.is_pidl = cl_is_pidl;
+  rinfo.do_skel_defs = !cl_disable_defs_skels;
+  rinfo.enabled_passes =
+     (cl_disable_stubs?0:OUTPUT_STUBS)
+    |(cl_disable_skels?0:OUTPUT_SKELS)
+    |(cl_disable_common?0:OUTPUT_COMMON)
+    |(cl_disable_headers?0:OUTPUT_HEADERS)
+/*     |(cl_enable_skeleton_impl?OUTPUT_SKELIMPL:0) */
+/*     |(cl_add_imodule?OUTPUT_IMODULE:0) */
+    |(cl_deps_file != NULL?OUTPUT_DEPS:0)
+    ;
+
+  rinfo.deps_file = cl_deps_file;
+
+/*   if (cl_enable_imodule) /\* clobber *\/ */
+/*     rinfo.enabled_passes = */
+/*       OUTPUT_COMMON | OUTPUT_HEADERS | OUTPUT_IMODULE; */
+
+  rinfo.output_language = cl_output_lang;
+  rinfo.header_guard_prefix = cl_header_guard_prefix;
+  rinfo.include = cl_include;
+  rinfo.output_directory = cl_output_directory;
+  rinfo.backend_directory = cl_backend_dir;
+  rinfo.onlytop = cl_onlytop;
+  rinfo.idata = !cl_disable_idata;
+
+  if (cl_debuglevel) {
+  printf ("forb-idl-2 " VERSION " compiling\n");
+  printf (" %s mode, %s preprocessor errors, passes: %s%s%s%s%s%s\n\n",
+         rinfo.is_pidl ? "pidl" : "",
+         rinfo.show_cpp_errors ? "show" : "hide",
+         rinfo.enabled_passes&OUTPUT_STUBS ? "stubs " : "",
+         rinfo.enabled_passes&OUTPUT_SKELS ? "skels " : "",
+         rinfo.enabled_passes&OUTPUT_COMMON ? "common " : "",
+         rinfo.enabled_passes&OUTPUT_HEADERS ? "headers " : "",
+         rinfo.enabled_passes&OUTPUT_SKELIMPL ? "skel_impl " : "",
+         rinfo.enabled_passes&OUTPUT_IMODULE ? "imodule" : "");
+  }
+  
+  /* Do it */
+  for (i = 0; idl_files[i]; ++i) {
+    if (cl_debuglevel) g_print ("Processing file %s\n", idl_files[i]);
+    rinfo.input_filename = idl_files[i];
+    if (!forb_idl_to_backend(idl_files[i], &rinfo)) {
+      g_warning("%s compilation failed", idl_files[i]);
+      retval = 1;
+    }
+  }
+
+  exit (retval);
+}
diff --git a/src/forb/forb-idl/forb-idl-utils.c b/src/forb/forb-idl/forb-idl-utils.c
new file mode 100644 (file)
index 0000000..759aff2
--- /dev/null
@@ -0,0 +1,718 @@
+#include "config.h"
+#include "forb-idl2.h"
+#include <string.h>
+#include <inttypes.h>
+
+void
+forb_idl_check_oneway_op (IDL_tree op)
+{
+       g_assert (IDL_NODE_TYPE(op) == IDLN_OP_DCL);
+
+       if (IDL_OP_DCL (op).f_oneway) {
+               IDL_tree sub;
+
+               for (sub = IDL_OP_DCL (op).parameter_dcls; sub; sub = IDL_LIST (sub).next) {
+                       IDL_tree param = IDL_LIST (sub).data;
+
+                       if (IDL_PARAM_DCL (param).attr == IDL_PARAM_OUT ||
+                           IDL_PARAM_DCL (param).attr == IDL_PARAM_INOUT) {
+                               g_warning ("Out or Inout parameter in declaration of oneway '%s'",
+                                          IDL_IDENT(IDL_OP_DCL(op).ident).str);
+                               break;
+                       }
+               }
+
+               if (IDL_OP_DCL (op).op_type_spec)
+                       g_warning ("Return value in declaration of oneway '%s'",
+                                  IDL_IDENT(IDL_OP_DCL(op).ident).str);
+       }
+}
+
+void
+forb_idl_attr_fake_ops(IDL_tree attr, IDL_ns ns)
+{
+  IDL_tree attr_name, ident, curnode, op1, op2, intf;
+  GString *attrname;
+  OIDL_Attr_Info *setme;
+
+  g_assert(attr && IDL_NODE_TYPE(attr) == IDLN_ATTR_DCL);
+
+  attrname = g_string_new(NULL);
+
+  for(curnode = IDL_ATTR_DCL(attr).simple_declarations; curnode; curnode = IDL_LIST(curnode).next) {
+    op1 = op2 = NULL;
+
+    attr_name = IDL_LIST(curnode).data;
+
+    g_string_printf(attrname, "_get_%s",
+                    IDL_IDENT(attr_name).str);
+    ident = IDL_ident_new(g_strdup(attrname->str));
+    IDL_IDENT_TO_NS(ident) = IDL_IDENT_TO_NS(attr_name);
+    op1 = IDL_op_dcl_new(0, IDL_ATTR_DCL(attr).param_type_spec, ident, NULL, NULL, NULL);
+    IDL_NODE_UP(op1) = IDL_NODE_UP(attr);
+    intf = IDL_NODE_UP (IDL_NODE_UP (op1));
+    IDL_NS(ns).current = IDL_IDENT_TO_NS (IDL_INTERFACE (intf).ident);
+    IDL_ns_place_new(ns, ident);
+
+    if(!IDL_ATTR_DCL(attr).f_readonly) {
+      g_string_printf(attrname, "_set_%s",
+                      IDL_IDENT(attr_name).str);
+      ident = IDL_ident_new(g_strdup(attrname->str));
+      IDL_IDENT_TO_NS(ident) = IDL_IDENT_TO_NS(attr_name);
+      op2 = IDL_op_dcl_new(0, NULL, ident, NULL, NULL, NULL);
+      IDL_NODE_UP(op2) = IDL_NODE_UP(attr);
+      intf = IDL_NODE_UP (IDL_NODE_UP (op2));
+      IDL_NS(ns).current = IDL_IDENT_TO_NS (IDL_INTERFACE (intf).ident);
+      IDL_ns_place_new(ns, ident);
+      IDL_OP_DCL(op2).parameter_dcls = IDL_list_new(
+                                                   IDL_param_dcl_new(IDL_PARAM_IN,
+                                                                     IDL_ATTR_DCL(attr).param_type_spec,
+                                                                     IDL_ident_new(g_strdup("value"))));
+    }
+
+    setme = g_new0(OIDL_Attr_Info, 1);
+    setme->op1 = op1;
+    setme->op2 = op2;
+    attr_name->data = setme;
+  }
+
+  g_string_free(attrname, TRUE);
+}
+
+#define INDENT_INCREMENT_1 2
+#define INDENT_INCREMENT_2 4
+
+static void do_indent(int level) {
+  int i;
+  for(i = 0; i < level; i++) g_print(" ");
+}
+
+void
+forb_idl_print_node(IDL_tree node, int indent_level)
+{
+  IDL_tree curnode;
+  char *s;
+
+  do_indent(indent_level);
+
+  if(node == NULL) {
+    g_print("(null)\n");
+    return;
+  }
+
+  g_print("[%d] ", IDL_NODE_REFS(node));
+
+  switch(IDL_NODE_TYPE(node)) {
+
+  case IDLN_NONE:
+    g_print("NONE\n");
+    break;
+
+  case IDLN_LIST:
+    g_print("LIST:\n");
+    for(curnode = node; curnode;
+       curnode = IDL_LIST(curnode).next) {
+      forb_idl_print_node(IDL_LIST(curnode).data, indent_level + INDENT_INCREMENT_1);
+    }
+    break;
+
+  case IDLN_GENTREE:
+    break;
+
+  case IDLN_INTEGER:
+    g_print("INTEGER: %" PRId64 "\n", IDL_INTEGER(node).value);
+    break;
+
+  case IDLN_STRING:
+    g_print("STRING: %s\n", IDL_STRING(node).value);
+    break;
+
+  case IDLN_WIDE_STRING:
+    g_print("WIDE STRING: %ls\n", IDL_WIDE_STRING(node).value);
+    break;
+
+  case IDLN_CHAR:
+    g_print("CHAR: %s\n", IDL_CHAR(node).value);
+    break;
+
+  case IDLN_WIDE_CHAR:
+    g_print("WIDE CHAR: %ls\n", IDL_WIDE_CHAR(node).value);
+    break;
+
+  case IDLN_FIXED:
+    g_print("FIXED: %s\n", IDL_FIXED(node).value);
+    break;
+
+  case IDLN_FLOAT:
+    g_print("FLOAT: %f\n", IDL_FLOAT(node).value);
+    break;
+
+  case IDLN_BOOLEAN:
+    g_print("BOOLEAN: %s\n", (IDL_BOOLEAN(node).value)?"True":"False");
+    break;
+
+  case IDLN_IDENT:
+    s = IDL_ns_ident_to_qstring(IDL_IDENT_TO_NS(node), "_", 0);
+    g_print("IDENT: %s NSQ: %s RID: \"%s\"\n",
+           IDL_IDENT(node).str, s,
+           IDL_IDENT_REPO_ID(node) ? IDL_IDENT_REPO_ID(node) : "");
+    g_free(s);
+    break;
+
+  case IDLN_TYPE_DCL:
+    g_print("TYPE DCL:\n");
+    forb_idl_print_node(IDL_TYPE_DCL(node).type_spec, indent_level + INDENT_INCREMENT_1);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("decls:\n");
+    forb_idl_print_node(IDL_TYPE_DCL(node).dcls, indent_level + INDENT_INCREMENT_2);
+    break;
+
+  case IDLN_CONST_DCL:
+    g_print("CONST DCL:\n");
+    forb_idl_print_node(IDL_CONST_DCL(node).const_type, indent_level + INDENT_INCREMENT_1);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("ident:\n");
+    forb_idl_print_node(IDL_CONST_DCL(node).ident, indent_level + INDENT_INCREMENT_2);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("const_exp:\n");
+    forb_idl_print_node(IDL_CONST_DCL(node).const_exp, indent_level + INDENT_INCREMENT_2);
+    break;
+
+  case IDLN_EXCEPT_DCL:
+    g_print("EXCEPT DCL:\n");
+    forb_idl_print_node(IDL_EXCEPT_DCL(node).ident, indent_level + INDENT_INCREMENT_1);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("members:\n");
+    forb_idl_print_node(IDL_EXCEPT_DCL(node).members, indent_level + INDENT_INCREMENT_2);
+    break;
+
+  case IDLN_ATTR_DCL:
+    g_print("ATTR_DCL (%s):\n", (IDL_ATTR_DCL(node).f_readonly)?"readonly":"rw");
+    forb_idl_print_node(IDL_ATTR_DCL(node).param_type_spec, indent_level + INDENT_INCREMENT_1);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("simple_declarations:\n");
+    forb_idl_print_node(IDL_ATTR_DCL(node).simple_declarations, indent_level + INDENT_INCREMENT_2);
+    break;
+
+  case IDLN_OP_DCL:
+    g_print("OP DCL (%s):\n", (IDL_OP_DCL(node).f_oneway)?"oneway":"normal");
+    forb_idl_print_node(IDL_OP_DCL(node).ident, indent_level + INDENT_INCREMENT_1);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("op_type_spec:\n");
+    forb_idl_print_node(IDL_OP_DCL(node).op_type_spec, indent_level + INDENT_INCREMENT_2);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("parameter_dcls:\n");
+    forb_idl_print_node(IDL_OP_DCL(node).parameter_dcls, indent_level + INDENT_INCREMENT_2);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("raises_expr:\n");
+    forb_idl_print_node(IDL_OP_DCL(node).raises_expr, indent_level + INDENT_INCREMENT_2);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("context_expr:\n");
+    forb_idl_print_node(IDL_OP_DCL(node).context_expr, indent_level + INDENT_INCREMENT_2);
+    break;
+
+  case IDLN_PARAM_DCL:
+    g_print("PARAM DCL: ");
+    switch(IDL_PARAM_DCL(node).attr) {
+    case IDL_PARAM_IN: g_print("(in)\n"); break;
+    case IDL_PARAM_OUT: g_print("(out)\n"); break;
+    case IDL_PARAM_INOUT: g_print("(inout)\n"); break;
+    }
+    forb_idl_print_node(IDL_PARAM_DCL(node).param_type_spec, indent_level + INDENT_INCREMENT_1);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("simple_declarator:\n");
+    forb_idl_print_node(IDL_PARAM_DCL(node).simple_declarator, indent_level + INDENT_INCREMENT_2);
+    break;
+  case IDLN_FORWARD_DCL:
+    g_print("FORWARD DCL:\n");
+    forb_idl_print_node(IDL_FORWARD_DCL(node).ident, indent_level + INDENT_INCREMENT_1);
+    break;
+  case IDLN_INTERFACE:
+    g_print("INTERFACE:\n");
+    forb_idl_print_node(IDL_INTERFACE(node).ident, indent_level + INDENT_INCREMENT_1);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("inheritance_spec:\n");
+    forb_idl_print_node(IDL_INTERFACE(node).inheritance_spec, indent_level + INDENT_INCREMENT_2);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("body:\n");
+    forb_idl_print_node(IDL_INTERFACE(node).body, indent_level + INDENT_INCREMENT_2);
+    break;
+  case IDLN_MODULE:
+    g_print("MODULE:\n");
+    forb_idl_print_node(IDL_MODULE(node).ident, indent_level + INDENT_INCREMENT_1);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("definition_list:\n");
+    forb_idl_print_node(IDL_MODULE(node).definition_list, indent_level + INDENT_INCREMENT_2);
+    break;
+
+  case IDLN_TYPE_INTEGER:
+    if(!IDL_TYPE_INTEGER(node).f_signed) g_print("TYPE unsigned ");
+    switch(IDL_TYPE_INTEGER(node).f_type) {
+    case IDL_INTEGER_TYPE_SHORT: g_print("short\n"); break;
+    case IDL_INTEGER_TYPE_LONG: g_print("long\n"); break;
+    case IDL_INTEGER_TYPE_LONGLONG: g_print("long long\n"); break;
+    }
+    break;
+  case IDLN_TYPE_FLOAT:
+    switch(IDL_TYPE_FLOAT(node).f_type) {
+    case IDL_FLOAT_TYPE_FLOAT: g_print("TYPE float\n"); break;
+    case IDL_FLOAT_TYPE_DOUBLE: g_print("TYPE double\n"); break;
+    case IDL_FLOAT_TYPE_LONGDOUBLE: g_print("TYPE long double\n"); break;
+    }
+    break;
+  case IDLN_TYPE_FIXED:
+    g_print("TYPE fixed:\n");
+    forb_idl_print_node(IDL_TYPE_FIXED(node).positive_int_const, indent_level + INDENT_INCREMENT_1);
+    forb_idl_print_node(IDL_TYPE_FIXED(node).integer_lit, indent_level + INDENT_INCREMENT_1);
+    break;
+  case IDLN_TYPE_STRING:
+    g_print("TYPE string:\n");
+    forb_idl_print_node(IDL_TYPE_STRING(node).positive_int_const, indent_level + INDENT_INCREMENT_1);
+    break;
+  case IDLN_TYPE_WIDE_STRING:
+    g_print("TYPE wide string:\n");
+    forb_idl_print_node(IDL_TYPE_WIDE_STRING(node).positive_int_const, indent_level + INDENT_INCREMENT_1);
+    break;
+  case IDLN_TYPE_ENUM:
+    g_print("TYPE enum:\n");
+    forb_idl_print_node(IDL_TYPE_ENUM(node).ident, indent_level + INDENT_INCREMENT_1);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("enumerator_list:\n");
+    forb_idl_print_node(IDL_TYPE_ENUM(node).enumerator_list, indent_level + INDENT_INCREMENT_2);
+    break;
+  case IDLN_TYPE_ARRAY:
+    g_print("TYPE array:\n");
+    forb_idl_print_node(IDL_TYPE_ARRAY(node).ident, indent_level + INDENT_INCREMENT_1);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("size_list:\n");
+    forb_idl_print_node(IDL_TYPE_ARRAY(node).size_list, indent_level + INDENT_INCREMENT_2);
+    break;
+  case IDLN_TYPE_SEQUENCE:
+    g_print("TYPE sequence:\n");
+    forb_idl_print_node(IDL_TYPE_SEQUENCE(node).simple_type_spec, indent_level + INDENT_INCREMENT_1);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("positive_int_const:\n");
+    forb_idl_print_node(IDL_TYPE_SEQUENCE(node).positive_int_const, indent_level + INDENT_INCREMENT_2);
+    break;
+  case IDLN_TYPE_STRUCT:
+    g_print("TYPE struct:\n");
+    forb_idl_print_node(IDL_TYPE_STRUCT(node).ident, indent_level + INDENT_INCREMENT_1);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("member_list:\n");
+    forb_idl_print_node(IDL_TYPE_STRUCT(node).member_list, indent_level + INDENT_INCREMENT_2);
+    break;
+  case IDLN_TYPE_UNION:
+    g_print("TYPE union:\n");
+    forb_idl_print_node(IDL_TYPE_UNION(node).ident, indent_level + INDENT_INCREMENT_1);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("switch_type_spec:\n");
+    forb_idl_print_node(IDL_TYPE_UNION(node).switch_type_spec, indent_level + INDENT_INCREMENT_2);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("switch_body:\n");
+    forb_idl_print_node(IDL_TYPE_UNION(node).switch_body, indent_level + INDENT_INCREMENT_2);
+    break;
+  case IDLN_MEMBER:
+    g_print("MEMBER:\n");
+    forb_idl_print_node(IDL_MEMBER(node).type_spec, indent_level + INDENT_INCREMENT_1);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("dcls:\n");
+    forb_idl_print_node(IDL_MEMBER(node).dcls, indent_level + INDENT_INCREMENT_2);
+    break;
+  case IDLN_CASE_STMT:
+    g_print("CASE_STMT:\n");
+    forb_idl_print_node(IDL_CASE_STMT(node).labels, indent_level + INDENT_INCREMENT_1);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("element_spec:\n");
+    forb_idl_print_node(IDL_CASE_STMT(node).element_spec, indent_level + INDENT_INCREMENT_2);
+    break;
+  case IDLN_BINOP:
+    g_print("BINOP ");
+    switch(IDL_BINOP(node).op) {
+    case IDL_BINOP_OR: g_print("or:\n"); break;
+    case IDL_BINOP_XOR: g_print("xor:\n"); break;
+    case IDL_BINOP_AND: g_print("and:\n"); break;
+    case IDL_BINOP_SHR: g_print("shr:\n"); break;
+    case IDL_BINOP_SHL: g_print("shl:\n"); break;
+    case IDL_BINOP_ADD: g_print("add:\n"); break;
+    case IDL_BINOP_SUB: g_print("sub:\n"); break;
+    case IDL_BINOP_MULT: g_print("mult:\n"); break;
+    case IDL_BINOP_DIV: g_print("div:\n"); break;
+    case IDL_BINOP_MOD: g_print("mod:\n"); break;
+    }
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("left:\n");
+    forb_idl_print_node(IDL_BINOP(node).left, indent_level + INDENT_INCREMENT_2);
+    do_indent(indent_level + INDENT_INCREMENT_1); g_print("right:\n");
+    forb_idl_print_node(IDL_BINOP(node).right, indent_level + INDENT_INCREMENT_2);
+    break;
+  case IDLN_UNARYOP:
+    g_print("UNARYOP ");
+    switch(IDL_UNARYOP(node).op) {
+    case IDL_UNARYOP_PLUS: g_print("plus:\n"); break;
+    case IDL_UNARYOP_MINUS: g_print("minus:\n"); break;
+    case IDL_UNARYOP_COMPLEMENT: g_print("complement:\n"); break;
+    }
+    forb_idl_print_node(IDL_UNARYOP(node).operand, indent_level + INDENT_INCREMENT_1);
+    break;
+  case IDLN_TYPE_CHAR:
+    g_print("TYPE char\n");
+    break;
+  case IDLN_TYPE_WIDE_CHAR:
+    g_print("TYPE wide char\n");
+    break;
+  case IDLN_TYPE_BOOLEAN:
+    g_print("TYPE boolean\n");
+    break;
+  case IDLN_TYPE_OCTET:
+    g_print("TYPE octet\n");
+    break;
+  case IDLN_TYPE_OBJECT:
+    g_print("TYPE object\n");
+    break;
+  case IDLN_TYPE_ANY:
+    g_print("TYPE any\n");
+    break;
+  case IDLN_TYPE_TYPECODE:
+    g_print("TYPE TypeCode\n");
+    break;
+  case IDLN_CODEFRAG:
+    g_print("CODEFRAG\n");
+    break;
+  case IDLN_SRCFILE:
+    g_print("SRCFILE %s\n", IDL_SRCFILE(node).filename);
+    break;
+  default:
+    g_print("unhandled %d\n", IDL_NODE_TYPE(node));
+  }
+}
+
+static void
+IDL_tree_traverse_helper(IDL_tree p, GFunc f,
+                        gconstpointer func_data,
+                        GHashTable *visited_nodes,
+                        gboolean    include_self)
+{
+       IDL_tree curitem;
+
+       if (g_hash_table_lookup (visited_nodes, p))
+               return;
+
+       g_hash_table_insert (visited_nodes, p, ((gpointer)1));
+
+       for (curitem = IDL_INTERFACE (p).inheritance_spec; curitem;
+            curitem = IDL_LIST (curitem).next) {
+               IDL_tree_traverse_helper (IDL_get_parent_node 
+                       (IDL_LIST (curitem).data, IDLN_INTERFACE, NULL), f, func_data, visited_nodes, TRUE);
+       }
+
+       if (include_self)
+               f(p, (gpointer)func_data);
+}
+
+void
+IDL_tree_traverse_parents_full (IDL_tree      p,
+                               GFunc         f,
+                               gconstpointer func_data,
+                               gboolean      include_self)
+{
+       GHashTable *visited_nodes = g_hash_table_new (NULL, g_direct_equal);
+
+       if (!(p && f))
+               return;
+
+       if (IDL_NODE_TYPE(p) != IDLN_INTERFACE)
+               p = IDL_get_parent_node (p, IDLN_INTERFACE, NULL);
+
+       if (!p)
+               return;
+
+       IDL_tree_traverse_helper (p, f, func_data, visited_nodes, include_self);
+
+       g_hash_table_destroy (visited_nodes);
+}
+
+void
+IDL_tree_traverse_parents (IDL_tree p,
+                          GFunc f,
+                          gconstpointer func_data)
+{
+       IDL_tree_traverse_parents_full (p, f, func_data, TRUE);
+}
+
+/* For use by below function */
+static const int *
+forb_cbe_get_typeoffsets_table (void)
+{
+  static int typeoffsets[IDLN_LAST];
+  static gboolean initialized = FALSE;
+  
+  if (!initialized) {
+    int i;
+
+    for (i = 0; i < IDLN_LAST; ++i)
+      typeoffsets[i] = -1;
+
+    typeoffsets[IDLN_FORWARD_DCL] = 8; /* (same as objref) */
+    typeoffsets[IDLN_TYPE_INTEGER] = 0;
+    typeoffsets[IDLN_TYPE_FLOAT] = 0;
+    typeoffsets[IDLN_TYPE_FIXED] = 3;
+    typeoffsets[IDLN_TYPE_CHAR] = 5;
+    typeoffsets[IDLN_TYPE_WIDE_CHAR] = 6;
+    typeoffsets[IDLN_TYPE_STRING] = 12;
+    typeoffsets[IDLN_TYPE_WIDE_STRING] = 13;
+    typeoffsets[IDLN_TYPE_BOOLEAN] = 4;
+    typeoffsets[IDLN_TYPE_OCTET] = 7;
+    typeoffsets[IDLN_TYPE_ANY] = 16;
+    typeoffsets[IDLN_TYPE_OBJECT] = 9;
+    typeoffsets[IDLN_TYPE_TYPECODE] = 9;
+    typeoffsets[IDLN_TYPE_ENUM] = 8;
+    typeoffsets[IDLN_TYPE_SEQUENCE] = 14;
+    typeoffsets[IDLN_TYPE_ARRAY] = 15;
+    typeoffsets[IDLN_TYPE_STRUCT] = 10;
+    typeoffsets[IDLN_TYPE_UNION] = 11;
+    typeoffsets[IDLN_NATIVE] = 15; /* no pointers ever, same as fixed array */
+    typeoffsets[IDLN_INTERFACE] = 9; /* (same as objref) */
+    
+    initialized = TRUE;
+  }
+  
+  return typeoffsets;
+}
+
+
+/**
+       This is a rather hairy function. Its purpose is to output the
+       required number of *'s that indicate the amount of indirection
+       for input, output, & input-output parameters, and return
+       values.  We do this by having a table of the number of *'s for
+       each type and purpose (nptrrefs_required), taken from 19.20
+       of the CORBA 2.2 spec, and then having a table that translates
+       from the IDLN_* enums into an index into nptrrefs_required (typeoffsets)
+**/
+gint
+oidl_param_info(IDL_tree in_param, IDL_ParamRole role, gboolean *isSlice)
+{
+       IDL_tree param;
+       const int * const typeoffsets = forb_cbe_get_typeoffsets_table ();
+       const int nptrrefs_required[][4] = {
+               {0,1,1,0} /* float */,
+               {0,1,1,0} /* double */,
+               {0,1,1,0} /* long double */,
+               {1,1,1,0} /* fixed_d_s 3 */, 
+               {0,1,1,0} /* boolean */,
+               {0,1,1,0} /* char */,
+               {0,1,1,0} /* wchar */,
+               {0,1,1,0} /* octet */,
+               {0,1,1,0} /* enum */,
+               {0,1,1,0} /* objref */,
+               {1,1,1,0} /* fixed struct 10 */,
+               {1,1,1,0} /* fixed union */,
+               {0,1,1,0} /* string */,
+               {0,1,1,0} /* wstring */,
+               {1,1,2,1} /* sequence */,
+               {0,0,0,0} /* fixed array */,
+               {1,1,2,1} /* any 16 */
+       };
+       int retval = 0;
+       int typeidx;
+
+       *isSlice = FALSE;
+
+       if(!in_param)
+               return 0; /* void */
+
+       /* Now, how do we use this table? :) */
+       param = forb_cbe_get_typespec (in_param);
+
+       g_assert (param);
+
+       switch (IDL_NODE_TYPE (param)) {
+       case IDLN_TYPE_STRUCT:
+       case IDLN_TYPE_UNION:
+               if (((role == DATA_RETURN) || (role == DATA_OUT)) &&
+                   !forb_cbe_type_is_fixed_length(param))
+                       retval++;
+               break;
+
+       case IDLN_TYPE_ARRAY:
+               if ( role == DATA_RETURN ) {
+                       *isSlice = TRUE;
+                       retval = 1;
+
+               } else if (role == DATA_OUT &&
+                          !forb_cbe_type_is_fixed_length (param)) {
+                       *isSlice = TRUE;
+                       retval = 2;
+               }
+               break;
+
+       case IDLN_NATIVE:
+               if ( IDL_NATIVE (param).user_type
+                    && strcmp (IDL_NATIVE (param).user_type,
+                               "IDL_variable_length_struct") == 0 ) {
+                       return role == DATA_OUT ? 2 : 1;
+               }
+               else {
+                       return role == DATA_IN ? 0 : 1;
+                 
+               }
+               break;
+
+       case IDLN_EXCEPT_DCL:
+               fprintf (stderr, "Error: exception declared at '%s:%d' cannot be "
+                        "used as a method parameter\n", in_param->_file,
+                        in_param->_line);
+               exit (1);
+               break;
+       default:
+               break;
+       }
+
+       /* ERROR ! */
+       typeidx = typeoffsets [IDL_NODE_TYPE (param)];
+       g_assert (typeidx >= 0);
+
+       switch (role) {
+       case DATA_IN:
+               role = 0;
+               break;
+       case DATA_INOUT:
+               role = 1;
+               break;
+       case DATA_OUT:
+               role = 2;
+               break;
+       case DATA_RETURN:
+               role = 3;
+               break;
+       default:
+               g_assert_not_reached ();
+               break;
+       }
+
+       retval += nptrrefs_required [typeidx] [role];
+
+       return retval;
+}
+
+/**
+    Fixed-length-ness is a property that CORBA defines, and it is
+    a property of each type, not each kind.  Furthermore, it doesnt
+    depend on the language mapping. Generally, the GIOP coding
+    a fixed length variable will be a known length (determined by the TC),
+    regardless of the data within the variable.
+
+    With the C mapping, fixed --> nothing to free in this node
+    Note that in the C mapping, everything is a struct and is
+    fixed length in that sense. Thus variable length types show
+    up in C as pointers.
+
+    Recursive types introduced by sequences are not a problem for this
+    func, because sequences are not fixed length, and terminate
+    the recursion.
+**/
+gboolean
+forb_cbe_type_is_fixed_length(IDL_tree ts)
+{
+  gboolean is_fixed = TRUE;
+  IDL_tree curitem;
+
+  ts = forb_cbe_get_typespec(ts);
+  switch(IDL_NODE_TYPE(ts)) {
+  case IDLN_TYPE_FLOAT:
+  case IDLN_TYPE_INTEGER:
+  case IDLN_TYPE_ENUM:
+  case IDLN_TYPE_CHAR:
+  case IDLN_TYPE_WIDE_CHAR:
+  case IDLN_TYPE_OCTET:
+  case IDLN_TYPE_BOOLEAN:
+    return TRUE;
+    break;
+  case IDLN_TYPE_SEQUENCE:
+  case IDLN_TYPE_STRING:
+  case IDLN_TYPE_WIDE_STRING:
+  case IDLN_TYPE_OBJECT:
+  case IDLN_FORWARD_DCL:
+  case IDLN_INTERFACE:
+  case IDLN_TYPE_ANY:
+  case IDLN_NATIVE:
+  case IDLN_TYPE_TYPECODE:
+    return FALSE;
+    break;
+  case IDLN_TYPE_UNION:
+    for(curitem = IDL_TYPE_UNION(ts).switch_body; curitem;
+       curitem = IDL_LIST(curitem).next) {
+      is_fixed &= forb_cbe_type_is_fixed_length(IDL_LIST(IDL_CASE_STMT(IDL_LIST(curitem).data).element_spec).data);
+    }
+    return is_fixed;
+    break;
+  case IDLN_EXCEPT_DCL:
+  case IDLN_TYPE_STRUCT:
+    for(curitem = IDL_TYPE_STRUCT(ts).member_list; curitem;
+       curitem = IDL_LIST(curitem).next) {
+      is_fixed &= forb_cbe_type_is_fixed_length(IDL_LIST(curitem).data);
+    }
+    return is_fixed;
+    break;
+  case IDLN_TYPE_ARRAY:
+    return forb_cbe_type_is_fixed_length(IDL_TYPE_DCL(IDL_get_parent_node(ts, IDLN_TYPE_DCL, NULL)).type_spec);
+    break;
+  case IDLN_TYPE_DCL:
+    return forb_cbe_type_is_fixed_length(IDL_TYPE_DCL(ts).type_spec);
+    break;
+  case IDLN_IDENT:
+  case IDLN_LIST:
+    return forb_cbe_type_is_fixed_length(IDL_NODE_UP(ts));
+    break;
+  case IDLN_MEMBER:
+    return forb_cbe_type_is_fixed_length(IDL_MEMBER(ts).type_spec);
+    break;
+  default:
+    g_warning("I'm not sure if type %s is fixed-length", IDL_tree_type_names[IDL_NODE_TYPE(ts)]);
+    return FALSE;
+  }
+}
+
+IDL_tree
+forb_cbe_get_typespec(IDL_tree node)
+{
+  if(node == NULL)
+    return NULL;
+
+  switch(IDL_NODE_TYPE(node)) {
+  case IDLN_TYPE_INTEGER:
+  case IDLN_TYPE_FLOAT:
+  case IDLN_TYPE_FIXED:
+  case IDLN_TYPE_CHAR:
+  case IDLN_TYPE_WIDE_CHAR:
+  case IDLN_TYPE_STRING:
+  case IDLN_TYPE_WIDE_STRING:
+  case IDLN_TYPE_BOOLEAN:
+  case IDLN_TYPE_OCTET:
+  case IDLN_TYPE_ANY:
+  case IDLN_TYPE_OBJECT:
+  case IDLN_TYPE_ENUM:
+  case IDLN_TYPE_SEQUENCE:
+  case IDLN_TYPE_ARRAY:
+  case IDLN_TYPE_STRUCT:
+  case IDLN_TYPE_UNION:
+  case IDLN_EXCEPT_DCL:
+  case IDLN_FORWARD_DCL:
+  case IDLN_INTERFACE:
+  case IDLN_NATIVE:
+  case IDLN_TYPE_TYPECODE:
+    return node;
+    break;
+  case IDLN_TYPE_DCL:
+    return forb_cbe_get_typespec(IDL_TYPE_DCL(node).type_spec);
+    break;
+  case IDLN_PARAM_DCL:
+    return forb_cbe_get_typespec(IDL_PARAM_DCL(node).param_type_spec);
+    break;
+  case IDLN_MEMBER:
+    return forb_cbe_get_typespec(IDL_MEMBER(node).type_spec);
+    break;
+  case IDLN_LIST:
+  case IDLN_IDENT:
+    return forb_cbe_get_typespec(IDL_get_parent_node(node, IDLN_ANY, NULL));
+    break;
+  default:
+    g_error("Unhandled node type %s!", IDL_tree_type_names[IDL_NODE_TYPE(node)]);
+    return NULL;
+  }
+}
+
+IDL_ParamRole
+oidl_attr_to_paramrole(enum IDL_param_attr attr)
+{
+  switch(attr) {
+  case IDL_PARAM_IN:
+    return DATA_IN;
+  case IDL_PARAM_OUT:
+    return DATA_OUT;
+  case IDL_PARAM_INOUT:
+    return DATA_INOUT;
+  default:
+    g_warning("Unknown IDL_param_attr %d", attr);
+    return -1;
+  }
+}
diff --git a/src/forb/forb-idl/forb-idl2.h b/src/forb/forb-idl/forb-idl2.h
new file mode 100644 (file)
index 0000000..d9b60c2
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef FORB_IDL2_H
+#define FORB_IDL2_H 1
+
+#include "forb-idl3-types.h"
+
+gboolean forb_idl_to_backend     (const char    *filename,
+                                  OIDL_Run_Info *rinfo);
+
+gboolean forb_idl_backend_output (OIDL_Run_Info *rinfo,
+                                  IDL_tree       tree);
+
+/* Utils */
+void     forb_idl_attr_fake_ops         (IDL_tree      attr,
+                                         IDL_ns        ns);
+void     forb_idl_print_node            (IDL_tree      node,
+                                         int           indent_level);
+void     IDL_tree_traverse_parents       (IDL_tree      p,
+                                         GFunc         f,
+                                         gconstpointer func_data);
+void     IDL_tree_traverse_parents_full  (IDL_tree      p,
+                                         GFunc         f,
+                                         gconstpointer func_data, 
+                                         gboolean      include_self);
+gboolean forb_cbe_type_contains_complex (IDL_tree      ts);
+void     forb_idl_check_oneway_op       (IDL_tree      op);
+
+typedef enum { DATA_IN=1, DATA_INOUT=2, DATA_OUT=4, DATA_RETURN=8 } IDL_ParamRole;
+gint oidl_param_info(IDL_tree param, IDL_ParamRole role, gboolean *isSlice);
+
+gboolean forb_cbe_type_is_fixed_length(IDL_tree ts);
+IDL_tree forb_cbe_get_typespec(IDL_tree node);
+IDL_ParamRole oidl_attr_to_paramrole(enum IDL_param_attr attr);
+
+#define FORB_RETVAL_VAR_NAME "_forb_retval"
+#define FORB_EPV_VAR_NAME    "_FORB_epv"
+
+#endif /* FORB_IDL2_H */
diff --git a/src/forb/forb-idl/forb-idl3-types.h b/src/forb/forb-idl/forb-idl3-types.h
new file mode 100644 (file)
index 0000000..984df0e
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef ORBIT_IDL3_TYPES_H
+#define ORBIT_IDL3_TYPES_H 1
+
+#include <errno.h>
+#include <stdio.h>
+#include <libIDL/IDL.h>
+/* #include <orbit/util/orbit-util.h> */
+/* #include <orbit/orbit-config.h> */
+
+typedef struct _OIDL_Marshal_Context OIDL_Marshal_Context;
+
+#define OUTPUT_NUM_PASSES 7
+
+typedef struct {
+  char *cpp_args;
+  int debug_level;
+  int idl_warn_level;
+  int show_cpp_errors;
+  int is_pidl;
+  int do_skel_defs;    /* gen defs within the header file */
+
+  enum { OUTPUT_STUBS=1<<0,
+        OUTPUT_SKELS=1<<1,
+        OUTPUT_COMMON=1<<2,
+        OUTPUT_HEADERS=1<<3,
+        OUTPUT_SKELIMPL=1<<4,
+        OUTPUT_IMODULE=1<<5,
+        OUTPUT_DEPS=1<<6 /* Make sure this is always the last pass or dep output will break. */
+  } enabled_passes;
+
+  char *output_language;
+  char *input_filename;
+  char *include;
+  char *backend_directory;
+  char *deps_file;
+  char *header_guard_prefix;
+  char *output_directory;
+  gboolean onlytop;
+  gboolean idata;
+
+  IDL_ns ns; /* Use ns instead of namespace because that's a C++ reserved keyword */
+} OIDL_Run_Info;
+
+typedef struct {
+  IDL_tree op1;
+  IDL_tree op2;
+} OIDL_Attr_Info;
+
+#endif
diff --git a/src/forb/forb-idl/forb_config.h b/src/forb/forb-idl/forb_config.h
new file mode 100644 (file)
index 0000000..a8834b5
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef FORB_CONFIG_H
+#define FORB_CONFIG_H
+
+/* #define WORDS_BIGENDIAN */
+#undef WORDS_BIGENDIAN
+
+#define FORB_CONFIG_SERIAL 0
+
+#endif
diff --git a/src/forb/src/Makefile b/src/forb/src/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/src/forb/src/Makefile.omk b/src/forb/src/Makefile.omk
new file mode 100644 (file)
index 0000000..8a382b8
--- /dev/null
@@ -0,0 +1,75 @@
+SUBDIRS = tests
+
+CFLAGS += -I.
+
+# IDL_COMPILER += --pidl
+
+shared_LIBRARIES += forb
+forb_SOURCES = forb.c cdr.c sha1.c uuid.c iop.c proto.c syncobj.c      \
+              request.c executor.c object.c peer.c port.c refcnt.c     \
+              exec_req.c regref.c discovery.c daemon.c
+forb_CLIENT_IDL = types.idl iop-idl.idl forb-idl.idl
+forb_SERVER_IDL = forb-idl.idl
+
+to_forb_subdir=$(1)->forb/$(strip $(1))
+
+ifeq ($(CONFIG_FORB_PROTO_UNIX),y)
+forb_SOURCES += proto_unix.c
+renamed_include_HEADERS += $(call to_forb_subdir, proto_unix.h) 
+endif
+
+# TODO: proto_inet should be a separate library as it should be used
+# only by FCB
+forb_SOURCES += proto_inet.c
+renamed_include_HEADERS += $(call to_forb_subdir, proto_inet.h) 
+
+
+include_HEADERS = forb.h
+renamed_include_HEADERS += \
+       $(call to_forb_subdir, basic_types.h) \
+       $(call to_forb_subdir, cdr.h) \
+       $(call to_forb_subdir, cdr_codec.h) \
+       $(call to_forb_subdir, executor.h) \
+       $(call to_forb_subdir, exec_req.h) \
+       $(call to_forb_subdir, forb-internal.h) \
+       $(call to_forb_subdir, iop.h) \
+       $(call to_forb_subdir, object.h) \
+       $(call to_forb_subdir, object_type.h) \
+       $(call to_forb_subdir, port.h) \
+       $(call to_forb_subdir, refcnt.h) \
+       $(call to_forb_subdir, request.h) \
+       $(call to_forb_subdir, syncobj.h) \
+       $(call to_forb_subdir, server_id.h) \
+       $(call to_forb_subdir, peer.h) \
+       $(call to_forb_subdir, uuid.h)
+
+renamed_include_GEN_HEADERS = \
+       $(call to_forb_subdir,forb-idl.h) \
+       $(call to_forb_subdir,iop-idl.h) \
+       $(call to_forb_subdir,types.h)
+
+default_CONFIG = CONFIG_FORB_PROTO_UNIX=y \
+                CONFIG_FORB_RECV_BUF_SIZE=4096 \
+                CONFIG_FORB_PROTO_INET_DEFAULT=n
+
+config_include_HEADERS = forb/config.h
+config_DEFINES = CONFIG_FORB_PROTO_UNIX \
+                CONFIG_FORB_RECV_BUF_SIZE \
+                CONFIG_FORB_PROTO_INET_DEFAULT \
+                CONFIG_FCB     # To see whether we are compiled with FRSH_FORB
+
+include-pass_HOOKS = log_domains.inc #request_gavl.inc
+
+log_domains.inc: $(addprefix $(SOURCES_DIR)/,ul_log_domains $(forb_SOURCES))
+       @echo "  UL_LOG  $@"
+       $(Q)$(SOURCES_DIR)/ul_log_domains --array forb_logreg_domains_array \
+               $(SOURCES_DIR) > $@
+
+clean-custom:
+       -$(Q)rm log_domains.inc
+
+# request_gavl.inc: $(SOURCES_DIR)/request_gavl.c
+#      @echo "  CPP     $@"
+#      $(Q)$(c_o_COMPILE) -o $@.tmp -E $<
+#      $(Q)tail -n 1 $@.tmp|indent > $@
+
diff --git a/src/forb/src/basic_types.h b/src/forb/src/basic_types.h
new file mode 100644 (file)
index 0000000..2985a4d
--- /dev/null
@@ -0,0 +1,153 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+#ifndef BASIC_TYPES_H
+#define BASIC_TYPES_H 1
+
+#include <stdint.h>
+#include <string.h>
+
+enum {
+       CORBA_FALSE = 0,
+       CORBA_TRUE  = 1
+};
+
+typedef int16_t   CORBA_short;
+typedef int32_t   CORBA_long;
+typedef int64_t   CORBA_long_long;
+typedef uint16_t  CORBA_unsigned_short;
+typedef uint32_t  CORBA_unsigned_long;
+typedef uint64_t  CORBA_unsigned_long_long;
+typedef float     CORBA_float;
+typedef double    CORBA_double;
+typedef char     CORBA_char;
+typedef int16_t   CORBA_wchar;
+typedef uint8_t   CORBA_boolean;
+typedef uint8_t   CORBA_octet;
+typedef double    CORBA_long_double;
+
+/*
+ * Bad hack, oh well
+ */
+
+typedef CORBA_char  *CORBA_string;
+typedef CORBA_wchar *CORBA_wstring;
+
+#define CORBA_sequence_get_release(seq) ((seq)->_release)
+/** 
+ * CORBA_sequence_set_release can be used to set the state of the release flag.
+ * 
+ * @param seq
+ * 
+ * @param val The value of the release flag.  If the flag is set to
+ * TRUE, the sequence effectively "owns" the storage pointed to by
+ * _buffer; if FALSE, the programmer is responsible for the storage
+ * [99-07-35.pdf].
+ */
+#define CORBA_sequence_set_release(seq, val) ((seq)->_release = (val))
+
+CORBA_boolean
+__forb_sequence_alloc_buf_internal(void *seq, size_t seq_size,
+                                  void **buf_pptr, CORBA_unsigned_long *maximum_ptr,
+                                  CORBA_unsigned_long num_elements, size_t elem_size);
+
+/** @name Sequence helper macros */
+/**@{*/
+/**
+ *
+ *
+ * @param seq
+ * @param num_elements
+ *
+ * @return CORBA_TRUE if the allocation was sucessfull, CORBA_FALSE if wasn't.
+ */
+#define forb_sequence_alloc_buf(seq, num_elements)                     \
+       __forb_sequence_alloc_buf_internal((seq), sizeof(*(seq)),       \
+                                          (void**)&(seq)->_buffer, &(seq)->_maximum, \
+                                          (num_elements), sizeof(*(seq)->_buffer))
+
+#define forb_sequence_alloc(seq, num_elements) do {            \
+               (seq) = forb_malloc(sizeof(*(seq)));            \
+               memset((seq), 0, sizeof(*(seq)));               \
+               forb_sequence_alloc_buf((seq), (num_elements)); \
+       } while(0)
+
+static inline void forb_no_destructor() {}
+
+#define forb_sequence_free_buf(seq, elem_destructor) do {              \
+               if (CORBA_sequence_get_release(seq)) {                  \
+                       CORBA_unsigned_long i;                          \
+                       for (i=0; i<(seq)->_length; i++) {              \
+                               elem_destructor(&(seq)->_buffer[i]);    \
+                       }                                               \
+                       forb_free((seq)->_buffer);                      \
+               }                                                       \
+       } while(0)
+
+#define forb_sequence_free(seq, elem_destructor) do {                  \
+               forb_sequence_free_buf((seq), (elem_destructor));       \
+               forb_free(seq);                                         \
+       } while(0)
+
+#define forb_sequence_elem(seq, index) ((seq)->_buffer[(index)])
+
+#define forb_sequence_length(seq) ((seq)->_length)
+#define forb_sequence_allocated(seq) ((seq)->_maximum)
+#define forb_sequence_ensure_allocated(seq, num)                       \
+       ((seq)->_buffer =                                               \
+        (forb_sequence_allocated(seq) < (num)) ?                       \
+               (forb_sequence_allocated(seq) = (num),                  \
+                realloc((seq)->_buffer, (num)*sizeof(*(seq)->_buffer))) : \
+        (seq)->_buffer)
+
+#define forb_sequence_foreach(seq, elemptr)          \
+       for ((elemptr)=&forb_sequence_elem((seq), 0); \
+            (elemptr)<&forb_sequence_elem((seq), forb_sequence_length(seq)); \
+            (elemptr)++)
+
+/**@}*/
+
+#endif
diff --git a/src/forb/src/cdr.c b/src/forb/src/cdr.c
new file mode 100644 (file)
index 0000000..2012b8e
--- /dev/null
@@ -0,0 +1,508 @@
+/*
+ *  $Id: cdr.c,v 0.0.0.1                2004/11/26
+ *
+ *                      CDR codeing
+ *
+ *  -------------------------------------------------------------------  
+ *                                ORTE                                 
+ *                      Open Real-Time Ethernet                       
+ *                                                                    
+ *                      Copyright (C) 2001-2006                       
+ *  Department of Control Engineering FEE CTU Prague, Czech Republic  
+ *                      http://dce.felk.cvut.cz                       
+ *                      http://www.ocera.org                          
+ *                                                                    
+ *  Author:             Petr Smolik    petr.smolik@wo.cz             
+ *  Advisor:            Pavel Pisa                                   
+ *  Project Responsible: Zdenek Hanzalek
+ *  
+ *  Modified for FORB by Michal Sojka <sojkam1@fel.cvut.cz>, 2008
+ *  --------------------------------------------------------------------
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  Original of source was from ORBit: A CORBA v2.2 ORB
+ *
+ */
+
+#include <forb/cdr.h>
+#include "forb.h"
+#include "forb_endian.h"
+#include <string.h>
+
+#define ALIGN_ADDRESS(this, boundary) \
+  ((void*)((( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))))
+
+#define FORB_CDR_GROW_AMOUNT 128
+
+CORBA_boolean 
+FORB_CDR_buffer_init(FORB_CDR_Codec *codec, const unsigned int size, const unsigned int first)
+{
+
+       if(codec->release_buffer) {
+               forb_free(codec->buffer);
+       }
+
+       if (first > size) {
+               return CORBA_FALSE;
+       }
+       codec->buffer=(CORBA_octet *)forb_malloc(size);
+       if (!codec->buffer) {
+               return CORBA_FALSE;
+       }
+       codec->buf_len=size;
+        codec->wptr_max=size;
+       FORB_CDR_buffer_reset(codec, first);
+        codec->release_buffer=CORBA_TRUE;
+
+       return CORBA_TRUE;
+}
+
+CORBA_boolean 
+FORB_CDR_buffer_reset(FORB_CDR_Codec *codec, const unsigned int first)
+{
+       if (first > codec->buf_len) {
+               return CORBA_FALSE;
+       }
+       codec->rptr = codec->wptr = codec->wptr_last = first;
+       return CORBA_TRUE;
+}
+
+CORBA_boolean 
+FORB_CDR_buffer_prepend(FORB_CDR_Codec *codec, const unsigned int len)
+{
+       if (codec->rptr < len) {
+               return CORBA_FALSE;
+       }
+       codec->rptr -= len;
+
+       codec->wptr = codec->rptr;
+
+       return CORBA_TRUE;
+}
+
+/*
+CORBA_boolean 
+FORB_CDR_buffer_grow(FORB_CDR_Codec *codec, const unsigned int growth)
+{
+       unsigned int real_growth,quot;
+
+       if(codec->release_buffer) {
+                quot = growth / FORB_CDR_GROW_AMOUNT;
+               real_growth=FORB_CDR_GROW_AMOUNT * (quot+1);
+               
+               codec->buffer=(CORBA_octet *)REALLOC(codec->buffer,
+                                                    codec->buf_len
+                                                    +real_growth);
+       }
+
+       return CORBA_TRUE;
+}
+*/
+CORBA_boolean 
+FORB_CDR_buffer_puts(FORB_CDR_Codec *codec, const void *data, const unsigned int len)
+{
+       if(codec->wptr+len > codec->wptr_max) {
+               return CORBA_FALSE; 
+       }
+
+       memcpy(&codec->buffer[codec->wptr], data, len);
+       codec->wptr+=len;
+       if (codec->wptr > codec->wptr_last) codec->wptr_last = codec->wptr;
+
+       return CORBA_TRUE;
+}
+
+CORBA_boolean 
+FORB_CDR_buffer_gets(FORB_CDR_Codec *codec, void *dest, const unsigned int len)
+{
+       if(codec->rptr+len > codec->buf_len) {
+               return CORBA_FALSE; 
+       }
+
+       memcpy(dest, &codec->buffer[codec->rptr], len);
+       codec->rptr+=len;
+
+       return CORBA_TRUE;
+}
+
+CORBA_boolean 
+FORB_CDR_buffer_put(FORB_CDR_Codec *codec, void *datum)
+{
+       if(codec->wptr+1 > codec->wptr_max) {
+               return(CORBA_FALSE);
+       }
+
+       codec->buffer[codec->wptr++]=*(unsigned char *)datum;
+       if (codec->wptr > codec->wptr_last) codec->wptr_last = codec->wptr;
+       return CORBA_TRUE;
+}
+
+CORBA_boolean 
+FORB_CDR_buffer_get(FORB_CDR_Codec *codec, void *dest)
+{
+       if(codec->rptr+1 > codec->buf_len) {
+               return(CORBA_FALSE);
+       }
+
+       *(CORBA_octet *)dest=codec->buffer[codec->rptr++];
+       return CORBA_TRUE;
+}
+
+#define FORB_CDR_buffer_put2(codec, datum) FORB_CDR_buffer_putn(codec, datum, 2)
+#define FORB_CDR_buffer_put4(codec, datum) FORB_CDR_buffer_putn(codec, datum, 4)
+#define FORB_CDR_buffer_put8(codec, datum) FORB_CDR_buffer_putn(codec, datum, 8)
+#define FORB_CDR_buffer_put16(codec, datum) FORB_CDR_buffer_putn(codec, datum, 16)
+#define FORB_CDR_buffer_get2(codec, dest) FORB_CDR_buffer_getn(codec, dest, 2)
+#define FORB_CDR_buffer_get4(codec, dest) FORB_CDR_buffer_getn(codec, dest, 4)
+#define FORB_CDR_buffer_get8(codec, dest) FORB_CDR_buffer_getn(codec, dest, 8)
+#define FORB_CDR_buffer_get16(codec, dest) FORB_CDR_buffer_getn(codec, dest, 16)
+
+static CORBA_boolean
+FORB_CDR_buffer_getn(FORB_CDR_Codec *codec, void *dest, int bsize)
+{
+       codec->rptr = (unsigned long)ALIGN_ADDRESS(codec->rptr, bsize);
+       if(codec->host_endian==codec->data_endian)
+               memcpy(dest, codec->buffer + codec->rptr, bsize);
+       else
+               forb_byteswap(dest, codec->buffer + codec->rptr, bsize);
+       codec->rptr += bsize;
+
+       return CORBA_TRUE;
+}
+
+static CORBA_boolean
+FORB_CDR_buffer_putn(FORB_CDR_Codec *codec, void *datum, int bsize)
+{
+        unsigned long forward,i;
+       
+       forward = (unsigned long)ALIGN_ADDRESS(codec->wptr, bsize);
+       if (forward+bsize > codec->wptr_max) {
+               return CORBA_FALSE;
+       }       
+
+       i = codec->wptr;
+        while(forward > i)
+               codec->buffer[i++] = '\0';
+
+       codec->wptr = forward;
+       if(codec->host_endian==codec->data_endian)
+               memcpy(codec->buffer + codec->wptr, datum, bsize);
+       else
+               forb_byteswap(codec->buffer + codec->wptr, datum, bsize);
+       codec->wptr += bsize;
+       if (codec->wptr > codec->wptr_last) codec->wptr_last = codec->wptr;
+
+       return CORBA_TRUE;
+}
+
+CORBA_boolean FORB_CDR_put_align(FORB_CDR_Codec *codec, unsigned bsize)
+{
+        unsigned long forward,i;
+       
+       forward = (unsigned long)ALIGN_ADDRESS(codec->wptr, bsize);
+       if (forward+bsize > codec->wptr_max) {
+               return CORBA_FALSE;
+       }       
+
+       i = codec->wptr;
+        while(forward > i)
+               codec->buffer[i++] = '\0';
+
+       codec->wptr = forward;
+       if (codec->wptr > codec->wptr_last) codec->wptr_last = codec->wptr;
+       return CORBA_TRUE;
+}
+
+CORBA_boolean FORB_CDR_get_align(FORB_CDR_Codec *codec, unsigned bsize)
+{
+       codec->rptr = (unsigned long)ALIGN_ADDRESS(codec->rptr, bsize);
+       return codec->rptr <= codec->wptr_max;
+}
+
+#define FORB_CDR_swap2(d,s) forb_byteswap((d), (s), 2)
+#define FORB_CDR_swap4(d,s) forb_byteswap((d), (s), 4)
+#define FORB_CDR_swap8(d,s) forb_byteswap((d), (s), 8)
+#define FORB_CDR_swap16(d,s) forb_byteswap((d), (s), 16)
+
+inline CORBA_boolean 
+FORB_CDR_put_short(FORB_CDR_Codec *codec, CORBA_short s)
+{
+       return FORB_CDR_buffer_put2(codec, &s);
+}
+
+inline CORBA_boolean 
+FORB_CDR_get_short(FORB_CDR_Codec *codec, CORBA_short *s)
+{
+       return FORB_CDR_buffer_get2(codec, s);
+}
+
+inline CORBA_boolean 
+FORB_CDR_put_ushort(FORB_CDR_Codec *codec, CORBA_unsigned_short us)
+{
+       return FORB_CDR_buffer_put2(codec, &us);
+}
+
+inline CORBA_boolean 
+FORB_CDR_get_ushort(FORB_CDR_Codec *codec, CORBA_unsigned_short *us)
+{
+       return FORB_CDR_buffer_get2(codec, us);
+}
+
+inline CORBA_boolean 
+FORB_CDR_put_long(FORB_CDR_Codec *codec, CORBA_long l)
+{
+       return FORB_CDR_buffer_put4(codec, &l);
+}
+
+inline CORBA_boolean 
+FORB_CDR_get_long(FORB_CDR_Codec *codec, CORBA_long *l)
+{
+       return FORB_CDR_buffer_get4(codec, l);
+}
+
+inline CORBA_boolean 
+FORB_CDR_put_ulong(FORB_CDR_Codec *codec, CORBA_unsigned_long ul)
+{
+       return FORB_CDR_buffer_put4(codec, &ul);
+}
+
+inline CORBA_boolean 
+FORB_CDR_get_ulong(FORB_CDR_Codec *codec, CORBA_unsigned_long *ul)
+{
+       return FORB_CDR_buffer_get4(codec, ul);
+}
+
+//#ifdef HAVE_CORBA_LONG_LONG
+inline CORBA_boolean 
+FORB_CDR_get_long_long(FORB_CDR_Codec *codec, CORBA_long_long *ul)
+{
+       return FORB_CDR_buffer_get8(codec, ul);
+}
+
+inline CORBA_boolean 
+FORB_CDR_put_long_long(FORB_CDR_Codec *codec, CORBA_long_long ll)
+{
+       return FORB_CDR_buffer_put8(codec, &ll);
+}
+
+inline CORBA_boolean 
+FORB_CDR_put_ulong_long(FORB_CDR_Codec *codec, CORBA_unsigned_long_long ll)
+{
+       return FORB_CDR_buffer_put8(codec, &ll);
+}
+
+inline CORBA_boolean 
+FORB_CDR_get_ulong_long(FORB_CDR_Codec *codec, CORBA_unsigned_long_long *ull)
+{
+       return FORB_CDR_buffer_get8(codec, ull);
+}
+//#endif /* HAVE_CORBA_LONG_LONG */
+
+inline CORBA_boolean 
+FORB_CDR_put_float(FORB_CDR_Codec *codec, CORBA_float f)
+{
+       return FORB_CDR_buffer_put4(codec, &f);
+}
+
+inline CORBA_boolean 
+FORB_CDR_get_float(FORB_CDR_Codec *codec, CORBA_float *f)
+{
+       return FORB_CDR_buffer_get4(codec, f);
+}
+
+inline CORBA_boolean 
+FORB_CDR_put_double(FORB_CDR_Codec *codec, CORBA_double d)
+{
+       return FORB_CDR_buffer_put8(codec, &d);
+}
+
+inline CORBA_boolean 
+FORB_CDR_get_double(FORB_CDR_Codec *codec, CORBA_double *d)
+{
+       return FORB_CDR_buffer_get8(codec, d);
+}
+
+inline CORBA_boolean 
+FORB_CDR_put_long_double(FORB_CDR_Codec *codec, CORBA_long_double ld)
+{
+       return FORB_CDR_buffer_put16(codec, &ld);
+}
+
+inline CORBA_boolean 
+FORB_CDR_put_octet(FORB_CDR_Codec *codec, CORBA_octet datum)
+{
+       return FORB_CDR_buffer_put(codec, &datum);
+}
+
+inline CORBA_boolean 
+FORB_CDR_get_octet(FORB_CDR_Codec *codec, CORBA_octet *datum)
+{
+       return(FORB_CDR_buffer_get(codec, datum));
+}
+
+inline CORBA_boolean 
+FORB_CDR_put_octets(FORB_CDR_Codec *codec, void *data, unsigned long len)
+{
+       return FORB_CDR_buffer_puts(codec, data, len);
+}
+
+inline CORBA_boolean 
+FORB_CDR_put_char(FORB_CDR_Codec *codec, CORBA_char c)
+{
+       return FORB_CDR_buffer_put(codec, &c);
+}
+
+inline CORBA_boolean 
+FORB_CDR_get_char(FORB_CDR_Codec *codec, CORBA_char *c)
+{
+       return FORB_CDR_buffer_get(codec, c);
+}
+
+inline CORBA_boolean 
+FORB_CDR_put_boolean(FORB_CDR_Codec *codec, CORBA_boolean datum)
+{
+       datum = datum&&1;
+       return FORB_CDR_buffer_put(codec, &datum);
+}
+
+inline CORBA_boolean 
+FORB_CDR_get_boolean(FORB_CDR_Codec *codec, CORBA_boolean *b)
+{
+       return FORB_CDR_buffer_get(codec, b);
+}
+
+CORBA_boolean 
+FORB_CDR_put_string(FORB_CDR_Codec *codec, const CORBA_char *str)
+{
+       unsigned int len;
+
+       if (str) 
+               len=strlen(str)+1;
+       else
+               len=0;
+
+       if (FORB_CDR_put_ulong(codec, len)==CORBA_FALSE) return -1;
+       return FORB_CDR_buffer_puts(codec, str, len);
+}
+
+CORBA_boolean 
+FORB_CDR_get_string_static(FORB_CDR_Codec *codec,CORBA_char **str)
+{
+       CORBA_unsigned_long len;
+
+       if(FORB_CDR_get_ulong(codec, (CORBA_unsigned_long *)&len)==CORBA_FALSE)
+               return CORBA_FALSE;
+
+       if((codec->rptr + len) > codec->buf_len)
+               return CORBA_FALSE;
+
+       *str = ((CORBA_char *)codec->buffer) + codec->rptr;
+
+       codec->rptr += len;
+
+       return CORBA_TRUE;
+}
+
+CORBA_boolean 
+FORB_CDR_get_string(FORB_CDR_Codec *codec, CORBA_char **str)
+{
+       CORBA_unsigned_long len;
+
+       if(FORB_CDR_get_ulong(codec, (CORBA_unsigned_long *)&len)==CORBA_FALSE)
+               return(CORBA_FALSE);
+
+       if(len==0)
+               return(CORBA_FALSE);
+
+       *str=forb_malloc(len);
+
+       if(FORB_CDR_buffer_gets(codec, *str, len)==CORBA_FALSE) {
+               forb_free(*str);
+               return(CORBA_FALSE);
+       }
+
+       if((*str)[len-1]!='\0') {
+               (*str)[len-1]='\0';
+       }
+
+       return(CORBA_TRUE);
+}
+
+CORBA_boolean 
+FORB_CDR_get_string_buff(FORB_CDR_Codec *codec, CORBA_char *str)
+{
+       CORBA_unsigned_long len;
+
+       if(FORB_CDR_get_ulong(codec, (CORBA_unsigned_long *)&len)==CORBA_FALSE)
+               return(CORBA_FALSE);
+
+       if(len==0)
+               return(CORBA_FALSE);
+
+       if(FORB_CDR_buffer_gets(codec, str, len)==CORBA_FALSE) {
+               return(CORBA_FALSE);
+       }
+
+       if(str[len-1]!='\0') {
+               str[len-1]='\0';
+       }
+
+       return(CORBA_TRUE);
+}
+
+CORBA_boolean 
+FORB_CDR_get_seq_begin(FORB_CDR_Codec *codec, CORBA_unsigned_long *ul)
+{
+       return(FORB_CDR_get_ulong(codec, (CORBA_unsigned_long *)ul));
+}
+
+FORB_CDR_Codec *
+FORB_CDR_codec_init_static(FORB_CDR_Codec *codec, forb_orb orb)
+{
+       memset(codec, 0, sizeof(FORB_CDR_Codec));
+
+       codec->host_endian = FLAG_ENDIANNESS;
+       codec->data_endian = FLAG_ENDIANNESS;
+       codec->orb = orb;
+
+       return codec;
+}
+
+FORB_CDR_Codec *
+FORB_CDR_codec_init(forb_orb orb)
+{
+       FORB_CDR_Codec *c;
+
+       c=forb_malloc(sizeof(FORB_CDR_Codec));
+       if (c) {
+               FORB_CDR_codec_init_static(c, orb);
+       }
+
+       return(c);
+}
+
+void 
+FORB_CDR_codec_release_buffer(FORB_CDR_Codec *codec)
+{
+       if(codec->release_buffer) {
+               forb_free(codec->buffer);
+               codec->release_buffer = CORBA_FALSE;
+       }
+}
+
+
+void 
+FORB_CDR_codec_free(FORB_CDR_Codec *codec)
+{
+       FORB_CDR_codec_release_buffer(codec);
+       forb_free(codec);
+}
diff --git a/src/forb/src/cdr.h b/src/forb/src/cdr.h
new file mode 100644 (file)
index 0000000..8eaa1d3
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ *  $Id: cdr.h,v 0.0.0.1                2004/11/26 
+ *
+ *  -------------------------------------------------------------------  
+ *                                ORTE                                 
+ *                      Open Real-Time Ethernet                       
+ *                                                                    
+ *                      Copyright (C) 2001-2006                       
+ *  Department of Control Engineering FEE CTU Prague, Czech Republic  
+ *                      http://dce.felk.cvut.cz                       
+ *                      http://www.ocera.org                          
+ *                                                                    
+ *  Author:             Petr Smolik    petr.smolik@wo.cz
+ *  Advisor:            Pavel Pisa                                   
+ *  Project Responsible: Zdenek Hanzalek
+ *  
+ *  Modified for FORB by Michal Sojka <sojkam1@fel.cvut.cz>, 2008
+ *  --------------------------------------------------------------------
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *  
+ *  Original of source was from ORBit: A CORBA v2.2 ORB
+ */
+/**
+ * @file   cdr.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 16:55:44 2008
+ * 
+ * @brief Handling of serialization/deserialization.
+ *
+ * Forked from ORTE project.
+ * 
+ * 
+ */
+#ifndef _FORB_CDR_H_
+#define _FORB_CDR_H_
+
+#include "basic_types.h"
+#include "cdr_codec.h"
+#include "object_type.h"
+
+/*
+ * Alignment of CORBA types mapped to C.
+ * These have *nothing* to do with CDR alignment.
+ */
+#define ORTE_ALIGNOF_CORBA_OCTET        1
+#define ORTE_ALIGNOF_CORBA_BOOLEAN      1
+#define ORTE_ALIGNOF_CORBA_CHAR         1
+#define ORTE_ALIGNOF_CORBA_WCHAR        2
+#define ORTE_ALIGNOF_CORBA_SHORT        2
+#define ORTE_ALIGNOF_CORBA_LONG         4
+#define ORTE_ALIGNOF_CORBA_LONG_LONG    8
+#define ORTE_ALIGNOF_CORBA_FLOAT        4
+#define ORTE_ALIGNOF_CORBA_DOUBLE       8
+#define ORTE_ALIGNOF_CORBA_LONG_DOUBLE  16
+#define ORTE_ALIGNOF_CORBA_STRUCT       1
+#define ORTE_ALIGNOF_CORBA_POINTER      4
+
+typedef enum {
+       BigEndian=0,
+       LittleEndian=1
+} FORB_CDR_Endianness;
+
+/**
+ * Codec used for serialization/deserialization
+ * 
+ * @host_endian: 
+ * @data_endian: 
+ * @buffer: buffer for data
+ * @buf_len: buffer length
+ * @wptr_max: maximal size of writing data 
+ * @wptr: write index
+ * @wptr_last: index of the data after the last written data
+ * @rptr: read index
+ * @readonly: readonly attribute 
+ * @release_buffer: use CORBA_TRUE if is necessary to free buffer memory after destruction of structure
+ * @orb: Needed for deserialization of object references.
+ *
+ * Struct @FORB_CDR_Codec is used by serialization and deserialization functions.
+ */
+struct FORB_CDR_Codec {
+       FORB_CDR_Endianness host_endian;
+       FORB_CDR_Endianness data_endian;
+       CORBA_octet *buffer;
+       unsigned int buf_len;
+       unsigned int wptr_max;
+       unsigned int wptr;
+       unsigned int wptr_last;
+       unsigned int rptr;
+       CORBA_boolean readonly;
+       CORBA_boolean release_buffer;
+       forb_orb orb;
+};
+
+#define HEXDIGIT(c) (isdigit((guchar)(c))?(c)-'0':tolower((guchar)(c))-'a'+10)
+#define HEXOCTET(a,b) ((HEXDIGIT((a)) << 4) | HEXDIGIT((b)))
+
+static inline CORBA_long FORB_CDR_data_size(FORB_CDR_Codec *codec)
+{
+       return codec->wptr_last - codec->rptr;
+}
+
+extern CORBA_boolean FORB_CDR_buffer_init(FORB_CDR_Codec *codec, const unsigned int size, const unsigned int first);
+extern CORBA_boolean FORB_CDR_buffer_reset(FORB_CDR_Codec *codec, const unsigned int first);
+extern CORBA_boolean FORB_CDR_buffer_prepend(FORB_CDR_Codec *codec, const unsigned int len);
+extern FORB_CDR_Codec *FORB_CDR_codec_init(forb_orb orb);
+extern FORB_CDR_Codec *FORB_CDR_codec_init_static(FORB_CDR_Codec *codec, forb_orb orb);
+extern void FORB_CDR_codec_release_buffer(FORB_CDR_Codec *codec);
+extern void FORB_CDR_codec_free(FORB_CDR_Codec *);
+
+extern CORBA_boolean FORB_CDR_buffer_puts(FORB_CDR_Codec *codec, const void *data, const unsigned int len);
+extern CORBA_boolean FORB_CDR_buffer_gets(FORB_CDR_Codec *codec, void *dest, const unsigned int len);
+
+extern CORBA_boolean FORB_CDR_put_short(FORB_CDR_Codec *codec, CORBA_short s);
+extern CORBA_boolean FORB_CDR_put_ushort(FORB_CDR_Codec *codec, CORBA_unsigned_short us);
+extern CORBA_boolean FORB_CDR_put_long(FORB_CDR_Codec *codec, CORBA_long l);
+extern CORBA_boolean FORB_CDR_put_ulong(FORB_CDR_Codec *codec, CORBA_unsigned_long ul);
+/* #ifdef HAVE_CORBA_LONG_LONG */
+extern CORBA_boolean FORB_CDR_put_long_long(FORB_CDR_Codec *codec, CORBA_long_long ll);
+extern CORBA_boolean FORB_CDR_put_ulong_long(FORB_CDR_Codec *codec, CORBA_unsigned_long_long ull);
+extern CORBA_boolean FORB_CDR_get_ulong_long(FORB_CDR_Codec *codec, CORBA_unsigned_long_long *ul);
+extern CORBA_boolean FORB_CDR_get_long_long(FORB_CDR_Codec *codec, CORBA_long_long *ul);
+/* #endif */
+extern CORBA_boolean FORB_CDR_put_float(FORB_CDR_Codec *codec, CORBA_float f);
+extern CORBA_boolean FORB_CDR_put_double(FORB_CDR_Codec *codec, CORBA_double d);
+extern CORBA_boolean FORB_CDR_put_long_double(FORB_CDR_Codec *codec, CORBA_long_double ld);
+extern CORBA_boolean FORB_CDR_put_octet(FORB_CDR_Codec *codec, CORBA_octet datum);
+extern CORBA_boolean FORB_CDR_put_octets(FORB_CDR_Codec *codec, void *data, unsigned long len);
+extern CORBA_boolean FORB_CDR_put_char(FORB_CDR_Codec *codec, CORBA_char c);
+extern CORBA_boolean FORB_CDR_put_boolean(FORB_CDR_Codec *codec, CORBA_boolean datum);
+extern CORBA_boolean FORB_CDR_put_string(FORB_CDR_Codec *codec, const CORBA_char *str);
+extern CORBA_boolean FORB_CDR_buffer_gets(FORB_CDR_Codec *codec, void *dest, const unsigned int len);
+extern CORBA_boolean FORB_CDR_get_short(FORB_CDR_Codec *codec, CORBA_short *us);
+extern CORBA_boolean FORB_CDR_get_ushort(FORB_CDR_Codec *codec, CORBA_unsigned_short *us);
+extern CORBA_boolean FORB_CDR_get_long(FORB_CDR_Codec *codec, CORBA_long *l);
+extern CORBA_boolean FORB_CDR_get_ulong(FORB_CDR_Codec *codec, CORBA_unsigned_long *ul);
+extern CORBA_boolean FORB_CDR_get_octet(FORB_CDR_Codec *codec, CORBA_octet *datum);
+extern CORBA_boolean FORB_CDR_get_boolean(FORB_CDR_Codec *codec, CORBA_boolean *b);
+extern CORBA_boolean FORB_CDR_get_char(FORB_CDR_Codec *codec, CORBA_char *c);
+extern CORBA_boolean FORB_CDR_get_string(FORB_CDR_Codec *codec, CORBA_char **str);
+extern CORBA_boolean FORB_CDR_get_string_buff(FORB_CDR_Codec *codec, CORBA_char *str);
+extern CORBA_boolean FORB_CDR_get_string_static(FORB_CDR_Codec *codec, CORBA_char **str);
+extern CORBA_boolean FORB_CDR_get_seq_begin(FORB_CDR_Codec *codec, CORBA_unsigned_long *ul);
+extern CORBA_boolean FORB_CDR_get_float(FORB_CDR_Codec *codec, CORBA_float *f);
+extern CORBA_boolean FORB_CDR_get_double(FORB_CDR_Codec *codec, CORBA_double *d);
+
+extern CORBA_boolean FORB_CDR_put_align(FORB_CDR_Codec *codec, unsigned bsize);
+extern CORBA_boolean FORB_CDR_get_align(FORB_CDR_Codec *codec, unsigned bsize);
+
+
+/* serialization functions */
+#define CORBA_short_serialize(x,y)             FORB_CDR_put_short((x),*(y))
+#define CORBA_long_serialize(x,y)              FORB_CDR_put_long((x),*(y))
+#define CORBA_long_long_serialize(x,y)         FORB_CDR_put_long_long((x),*(y))
+#define CORBA_unsigned_short_serialize(x,y)    FORB_CDR_put_ushort((x),*(y))
+#define CORBA_unsigned_long_serialize(x,y)     FORB_CDR_put_ulong((x),*(y))
+#define CORBA_unsigned_long_long_serialize(x,y) FORB_CDR_put_ulong_long((x),*(y))
+#define CORBA_float_serialize(x,y)             FORB_CDR_put_float((x),*(y))
+#define CORBA_double_serialize(x,y)            FORB_CDR_put_double((x),*(y))
+#define CORBA_char_serialize(x,y)              FORB_CDR_put_char((x),*(y))
+#define CORBA_boolean_serialize(x,y)           FORB_CDR_put_boolean((x),*(y))
+#define CORBA_octet_serialize(x,y)             FORB_CDR_put_octet((x),*(y))
+#define CORBA_long_double_serialize(x,y)       FORB_CDR_put_long_double((x),*(y))
+#define CORBA_string_serialize(x,y)            FORB_CDR_put_string((x),*(y))
+
+/* deserialization functions */
+#define CORBA_short_deserialize(x,y)           FORB_CDR_get_short((x),(y))
+#define CORBA_long_deserialize(x,y)            FORB_CDR_get_long((x),(y))
+#define CORBA_long_long_deserialize(x,y)       FORB_CDR_get_long_long((x),(y))
+#define CORBA_unsigned_short_deserialize(x,y)  FORB_CDR_get_ushort((x),(y))
+#define CORBA_unsigned_long_deserialize(x,y)   FORB_CDR_get_ulong((x),(y))
+#define CORBA_unsigned_long_long_deserialize(x,y) FORB_CDR_get_ulong_long((x),(y))
+#define CORBA_float_deserialize(x,y)           FORB_CDR_get_float((x),(y))
+#define CORBA_double_deserialize(x,y)          FORB_CDR_get_double((x),(y))
+#define CORBA_char_deserialize(x,y)            FORB_CDR_get_char((x),(y))
+#define CORBA_boolean_deserialize(x,y)         FORB_CDR_get_boolean((x),(y))
+#define CORBA_octet_deserialize(x,y)           FORB_CDR_get_octet((x),(y))
+#define CORBA_long_double_deserialize(x,y)     FORB_CDR_get_long_double((x),(y))
+#define CORBA_string_deserialize(x,y)          FORB_CDR_get_string((x),(y))
+
+
+#endif /* !_FORB_CDR_H_ */
diff --git a/src/forb/src/cdr_codec.h b/src/forb/src/cdr_codec.h
new file mode 100644 (file)
index 0000000..96cda1b
--- /dev/null
@@ -0,0 +1,63 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   cdr_codec.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 16:53:47 2008
+ * 
+ * @brief  Definition of FORB_CDR_Codec type.
+ * 
+ * The definition here is incomplete, which means we can use pointers
+ * to this type without having knowledge about internal structorue of
+ * this type.
+ */
+#ifndef FORB_CDR_CODEC_H
+#define FORB_CDR_CODEC_H
+
+typedef struct FORB_CDR_Codec FORB_CDR_Codec;
+
+#endif
diff --git a/src/forb/src/daemon.c b/src/forb/src/daemon.c
new file mode 100644 (file)
index 0000000..a734136
--- /dev/null
@@ -0,0 +1,55 @@
+#include <forb.h>
+#include <stdio.h>
+#include <unistd.h>
+
+/* Helper functions to "daemonize" forb servers. To make debugging
+ * easier, we do not detach from terminal. The idea behind daemonizing
+ * is to exit the parent when the server is ready to receive requests,
+ * so that is is not necessary to put delays between invocation of
+ * different servers. */
+
+static int daemon_pipe[2] = { 0, 0 };
+
+void forb_daemon_prepare(const char *pid)
+{
+       pid_t child;
+       int ret;
+       FILE *f;
+       char tmp;
+
+       ret = pipe(daemon_pipe);
+       if (ret) {
+               perror("pipe");
+               exit(1);
+       }
+       child = fork();
+       if (child == -1) {
+               perror("fork");
+               exit(1);
+       }
+       if (child > 0) {
+               close(daemon_pipe[1]);
+               ret = read(daemon_pipe[0], &tmp, 1);
+               if (pid) {
+                       f = fopen(pid, "w");
+                       if (f) {
+                               fprintf(f, "%d\n", child);
+                               fclose(f);
+                       }
+               }
+               exit(ret > 0 ? 0 : 1);
+       } else {
+               close(daemon_pipe[0]);
+       }
+}
+
+/** 
+ * Signal the parent that the daemon is ready so that the parent can
+ * exit().
+ */
+void forb_daemon_ready()
+{
+       if (daemon_pipe[1])
+               write(daemon_pipe[1], "", 1);
+}
+
diff --git a/src/forb/src/discovery.c b/src/forb/src/discovery.c
new file mode 100644 (file)
index 0000000..a0391a9
--- /dev/null
@@ -0,0 +1,273 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   discovery.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Wed May 27 19:28:30 2009
+ * 
+ * @brief  Discovery functions
+ * 
+ */
+
+#include "discovery.h"
+#include <ul_log.h>
+#include "object.h"
+#include <forb/config.h>
+#include "iop.h"
+
+extern UL_LOG_CUST(ulogd_forb_discovery);
+
+GAVL_CUST_NODE_INT_DEC(forb_peer_nolock,/* cust_prefix */
+                      forb_t,          /* cust_root_t */
+                      forb_peer_t,     /* cust_item_t */
+                      forb_server_id,  /* cust_key_t */
+                      peers,           /* cust_root_node */
+                      gnode,           /* cust_item_node */
+                      server_id,       /* cust_item_key */
+                      forb_server_id_cmp)/* cust_cmp_fnc */
+
+GAVL_CUST_NODE_INT_IMP(forb_peer_nolock,/* cust_prefix */
+                      forb_t,          /* cust_root_t */
+                      forb_peer_t,     /* cust_item_t */
+                      forb_server_id,  /* cust_key_t */
+                      peers,           /* cust_root_node */
+                      gnode,           /* cust_item_node */
+                      server_id,       /* cust_item_key */
+                      forb_server_id_cmp);/* cust_cmp_fnc */
+
+int forb_discovery_init(forb_t *forb)
+{
+       if (fosa_mutex_init(&forb->peer_mutex, 0) != 0) return -1;
+       forb_peer_nolock_init_root_field(forb);
+
+       if (fosa_mutex_init(&forb->objkey_mutex, 0) != 0) return -1;
+       forb_objects_nolock_init_root_field(forb);
+       return 0;
+}
+
+static inline void
+forb_peer_insert(forb_t *forb, forb_peer_t *peer)
+{
+       fosa_mutex_lock(&forb->peer_mutex);
+       forb_peer_get(peer);
+       forb_peer_nolock_insert(forb, peer);
+       fosa_mutex_unlock(&forb->peer_mutex);
+}
+
+static inline void
+forb_peer_delete(forb_t *forb, forb_peer_t *peer)
+{
+       fosa_mutex_lock(&forb->peer_mutex);
+       forb_peer_nolock_delete(forb, peer);
+       forb_peer_put(peer);
+       fosa_mutex_unlock(&forb->peer_mutex);
+}
+
+/** 
+ * Finds peer with given @a server_id.
+ * 
+ * @param forb 
+ * @param server_id 
+ * 
+ * @return The found peer or NULL if no peer is found. You have to
+ * call forb_peer_put() after you finish working with the non NULL
+ * retuned value.
+ */
+forb_peer_t *
+forb_peer_find(forb_t *forb, forb_server_id *server_id)
+{
+       forb_peer_t *ret;
+       fosa_mutex_lock(&forb->peer_mutex);
+       ret = forb_peer_nolock_find(forb, server_id);
+       if (ret) {
+               forb_peer_get(ret);
+       }
+       fosa_mutex_unlock(&forb->peer_mutex);
+       return ret;
+}
+
+/** 
+ * Finds the peer with given @a server_id. If the peer is not
+ * currently known (not yet discovered or not available), this
+ * function waits at maximum @a timeout for the peer to be discovered.
+ * 
+ * @param forb 
+ * @param server_id 
+ * @param timeout 
+ * 
+ * @return The peer structure or NULL if the peer is not known even
+ * after the timeout elapses.
+ * 
+ * @note After the returned peer is not needed, forb_peer_put() must
+ * called on it.
+ */
+forb_peer_t *
+forb_peer_find_timed(forb_t *forb, forb_server_id *server_id,
+                    fosa_abs_time_t *timeout)
+{
+       forb_peer_t *peer;
+       bool peer_allocated = false;
+       
+       fosa_mutex_lock(&forb->peer_mutex);
+       peer = forb_peer_nolock_find(forb, server_id);
+       if (!peer && !timeout) goto unlock;
+       if (peer) {
+               forb_peer_get(peer);
+       } else {
+               /* We are the first who want to contact this peer */
+               peer = forb_peer_new();
+               if (!peer) goto unlock;
+               peer->server_id = *server_id;
+               peer->state = FORB_PEER_WANTED;
+               forb_peer_nolock_insert(forb, forb_peer_get(peer));
+               peer_allocated = true;
+       }
+       while (peer->state == FORB_PEER_WANTED) {
+               int ret;
+               /* Wait for the peer to be discovered. */
+               ret = fosa_cond_timedwait(&peer->cond,
+                                         &forb->peer_mutex,
+                                         timeout);
+               if (ret == FOSA_ETIMEDOUT) {
+                       /* No peer discovered within timeout */
+                       if (peer_allocated) {
+                               forb_peer_nolock_delete(forb, peer);
+                               forb_peer_put(peer);
+                       }
+                       forb_peer_put(peer);
+                       peer = NULL;
+                       break;
+               }
+       }
+unlock:        
+       fosa_mutex_unlock(&forb->peer_mutex);
+
+       return peer;
+}
+
+/** 
+ * 
+ * @param port 
+ * @param peer 
+ * @param server_id 
+ * @param addr 
+ * @param orb_id
+ * 
+ * @warning This function has to be called either from receiver thread
+ * of when the recevier thread is not running.
+ */
+void forb_new_peer_discovered(forb_port_t *port, forb_peer_t *peer,
+                        forb_server_id server_id, void *addr,
+                        CORBA_string orb_id)
+{
+       forb_t *forb = port->forb;
+       bool notify_waiters = false;
+       if (peer && peer->state == FORB_PEER_WANTED) {
+               notify_waiters = true;
+       } else if (!peer) {
+               peer = forb_peer_new();
+       }
+       if (!peer)
+               return;
+
+       fosa_mutex_lock(&forb->peer_mutex);
+       peer->server_id = server_id;
+       peer->port = port;
+       peer->addr = addr;
+       peer->orb_id = orb_id;
+       peer->state = FORB_PEER_DISCOVERED;
+       if (notify_waiters) {
+               fosa_cond_broadcast(&peer->cond);
+       } else {
+               forb_peer_nolock_insert(forb, forb_peer_get(peer));
+       }
+       forb_port_peer_ins_tail(port, forb_peer_get(peer));
+       fosa_mutex_unlock(&forb->peer_mutex);
+       {
+               char str[60];
+               ul_logdeb("new peer discovered %s (orb_id '%s')\n",
+                         forb_server_id_to_string(str, &peer->server_id, sizeof(str)),
+                         orb_id);
+       }
+#ifdef CONFIG_FORB_PROTO_INET_DEFAULT
+       if (forb->attr.redistribute_hellos) {
+               forb_peer_t *p;
+               ul_list_for_each(forb_port_peer, port, p) {
+                       if (p != peer &&
+                           forb_server_id_cmp(&p->server_id, &forb->server_id) != 0) {
+                               forb_iop_redistribute_hello_to(p, peer); /* Introduce new peer to others */
+                               forb_iop_redistribute_hello_to(peer, p); /* Introduce other peers to the new one */
+                       }
+               }
+       }
+#endif
+       if (forb->attr.peer_discovery_callback) {
+               forb_orb peer_orb = forb_object_new(forb->orb, &peer->server_id, 0);
+               forb->attr.peer_discovery_callback(peer_orb, orb_id);
+               forb_object_release(peer_orb);
+       }
+       forb_peer_put(peer);
+
+       /* Broadcast our hello packet now */
+       forb_syncobj_signal(&port->hello);
+}
+
+/** 
+ * 
+ * 
+ * @param peer 
+ *
+ * @warning This function has to be called either from receiver thread
+ * of when the recevier thread is not running.
+ */
+void forb_peer_disconnected(forb_peer_t *peer)
+{
+       forb_peer_delete(peer->port->forb, peer);
+       forb_port_peer_delete(peer->port, peer);
+       forb_peer_put(peer);    /* This should release the peer and in case on proto_inet close the socker. */
+}
+
diff --git a/src/forb/src/discovery.h b/src/forb/src/discovery.h
new file mode 100644 (file)
index 0000000..5425e29
--- /dev/null
@@ -0,0 +1,69 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+#ifndef DISCOVERY_H
+#define DISCOVERY_H
+
+#include "peer.h"
+#include "port.h"
+
+int forb_discovery_init(forb_t *forb);
+
+void forb_new_peer_discovered(forb_port_t *port, forb_peer_t *peer,
+                             forb_server_id server_id, void *addr,
+                             CORBA_string orb_id);
+
+
+void forb_peer_disconnected(forb_peer_t *peer);
+
+forb_peer_t *
+forb_peer_find(forb_t *forb, forb_server_id *server_id);
+
+forb_peer_t *
+forb_peer_find_timed(forb_t *forb, forb_server_id *server_id,
+                    fosa_abs_time_t *timeout);
+
+#endif
diff --git a/src/forb/src/exec_req.c b/src/forb/src/exec_req.c
new file mode 100644 (file)
index 0000000..e5b9c76
--- /dev/null
@@ -0,0 +1,122 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+/**
+ * @file   exec_req.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 16:47:25 2008
+ * 
+ * @brief  Hanlding of requests in executors.
+ * 
+ */
+
+#include "exec_req.h"
+#include "executor.h"
+#include <stdbool.h>
+#include "forb-internal.h"
+#include "object.h"
+#include "iop-idl.h"
+#include <ul_log.h>
+#include "iop.h"
+
+extern UL_LOG_CUST(ulogd_forb_exec_req);
+
+void forb_exec_req_process(forb_exec_req_t *exec_req)
+{
+       FORB_CDR_Codec reply_codec;
+       struct forb_env env;
+       const forb_skel_func *skeletons;
+       forb_t *forb = forb_object_to_forb(exec_req->obj);
+       CORBA_boolean ret;
+       
+       FORB_CDR_codec_init_static(&reply_codec, exec_req->obj->orb);   
+       ret = FORB_CDR_buffer_init(&reply_codec, 4096,
+                             forb_iop_MESSAGE_HEADER_SIZE +
+                             forb_iop_REPLY_HEADER_SIZE);
+       if (!ret) {
+               /* Without codec, we cannot send any reply so return silently. */
+               ul_logerr("No memory for reply buffer\n");
+               return;
+       }
+
+       env.major = FORB_EX_NONE;
+
+       /* Allow the implementation to know about request details
+        * (e.g. source). */
+       exec_req->obj->exec_req = exec_req;
+
+       /* Invoke the skeleton */
+       skeletons = exec_req->obj->interface->skeletons;
+       skeletons[exec_req->method_index](&exec_req->codec,
+                                        &reply_codec,
+                                        exec_req->obj,
+                                        &env);
+       
+       forb_iop_send_reply(forb, &exec_req->source,
+                           &reply_codec,
+                           exec_req->request_id, &env);
+       FORB_CDR_codec_release_buffer(&reply_codec);
+       forb_exec_req_destroy(exec_req);
+}
+
+void forb_exec_req_ins_tail(forb_executor_t *executor,
+                           forb_exec_req_t *exec_req)
+{
+       bool was_empty;
+       fosa_mutex_lock(&executor->mutex);
+       was_empty = forb_exec_req_nolock_is_empty(executor);
+       forb_exec_req_nolock_ins_tail(executor, exec_req);
+       if (was_empty) {
+               fosa_cond_signal(&executor->new_request_in_empty_list);
+       }
+       fosa_mutex_unlock(&executor->mutex);
+}
+
+void forb_exec_req_destroy(forb_exec_req_t *exec_req)
+{
+       forb_object_release(exec_req->obj);
+       FORB_CDR_codec_release_buffer(&exec_req->codec);
+       forb_free(exec_req);
+}
diff --git a/src/forb/src/exec_req.h b/src/forb/src/exec_req.h
new file mode 100644 (file)
index 0000000..57b17ba
--- /dev/null
@@ -0,0 +1,92 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   exec_req.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 16:21:40 2008
+ * 
+ * @brief  Data type and functions prototypes for requests to executors.
+ * 
+ * 
+ */
+
+#ifndef FORB_EXEC_REQ_H
+#define FORB_EXEC_REQ_H
+
+#include <forb.h>
+#include <forb/cdr_codec.h>
+#include <forb/cdr.h>
+#include <ul_list.h>
+#include "executor.h"
+
+/**
+ * Request for ::forb_executor_t.
+ * 
+ */
+typedef struct forb_exec_req {
+       unsigned request_id;    /**< Request ID. Used to prepare reply message. */
+       forb_server_id source;  /**< Source of this request. */
+       forb_object obj;        /**< Object which is requested */
+       unsigned method_index;  /**< Mehotd number to be invoked on the object @a obj. */
+       FORB_CDR_Codec codec;   /**< Bufffer with serialized request parameters. */
+       ul_list_node_t node;    /**< Node for forb_executor_t::requests. */
+} forb_exec_req_t;
+
+UL_LIST_CUST_DEC(forb_exec_req_nolock, /* cust_prefix */
+                forb_executor_t, /* cust_head_t */
+                forb_exec_req_t, /* cust_item_t */
+                requests, /* cust_head_field */
+                node); /* cust_node_field */
+                
+
+void forb_exec_req_process(forb_exec_req_t *exec_req);
+
+void forb_exec_req_ins_tail(forb_executor_t *executor,
+                           forb_exec_req_t *exec_req);
+void forb_exec_req_destroy(forb_exec_req_t *exec_req);
+
+#endif
diff --git a/src/forb/src/executor.c b/src/forb/src/executor.c
new file mode 100644 (file)
index 0000000..da1a4d7
--- /dev/null
@@ -0,0 +1,175 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   executor.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 16:18:04 2008
+ * 
+ * @brief  Implementation of executors.
+ */
+
+
+#include "executor.h"
+#include "exec_req.h"
+#include "object.h"
+#include <ul_log.h>
+
+extern UL_LOG_CUST(ulogd_forb_executor);
+
+/** 
+ * Initializes executor.
+ * 
+ * @param executor 
+ * 
+ * @return Zero on success, FOSA error code on error.
+ */
+int forb_executor_init(forb_executor_t *executor)
+{
+       int ret;
+       ret = fosa_mutex_init(&executor->mutex, 0);
+       if (ret) return ret;
+
+       ret = fosa_cond_init(&executor->new_request_in_empty_list);
+       if (ret) return ret;
+
+       forb_exec_req_nolock_init_head(executor);
+       return 0;
+}
+
+void forb_executor_destroy(forb_executor_t *executor)
+{
+       /* TODO: */
+}
+
+/** 
+ * Setup the object @a obj so that requests to it are executed within
+ * the thread of the @a executor.
+ * 
+ * @param executor
+ * @param obj 
+ * 
+ * @return Zero on success, non-zero on error.
+ */
+int forb_executor_register_object(forb_executor_t *executor, forb_object obj)
+{
+       if (!obj || obj->executor)
+               return -1;
+
+       obj->executor = executor;
+       return 0;
+}
+
+/** 
+ * Unregisteres the object @a obj from @a executor.
+ * 
+ * @param executor
+ * @param obj 
+ */
+void forb_executor_unregister_object(forb_executor_t *executor, forb_object obj)
+{
+       if (obj) {
+               obj->executor = NULL;
+       }
+}
+
+/** 
+ * Executor's main loop which executes object implementation methods
+ * upon request.
+ *
+ * The requests are represented by ::forb_exec_req_t and are enqueued
+ * to the executor's request queue by receiver threads of individual
+ * ports (forb_iop_receiver_thread()).
+ * 
+ * @param executor 
+ * 
+ * @return Zero on normal termination, non-zero error codes will be
+ * defined later.
+ */
+int forb_executor_run(forb_executor_t *executor)
+{
+       fosa_mutex_lock(&executor->mutex);
+       while (1) {
+               fosa_cond_wait(&executor->new_request_in_empty_list,
+                              &executor->mutex);
+               while (!forb_exec_req_nolock_is_empty(executor)) {
+                       forb_exec_req_t *exec_req;
+                       exec_req = forb_exec_req_nolock_cut_first(executor);
+                       fosa_mutex_unlock(&executor->mutex);
+
+                       forb_exec_req_process(exec_req);
+
+                       fosa_mutex_lock(&executor->mutex);
+               }
+       }
+       fosa_mutex_unlock(&executor->mutex);
+       return 0;
+}
+
+/** 
+ * Convenience function for executing only one object in one executor.
+ * 
+ * @param obj The object to execute.
+ * 
+ * @return Zero in case of success, error code on error.
+ */
+int forb_execute_object(forb_object obj)
+{
+       forb_executor_t executor;
+       int ret;
+       
+       ret = forb_executor_init(&executor);
+       if (ret) goto error;
+       ret = forb_executor_register_object(&executor, obj);
+       if (ret) goto destroy_and_error;
+       
+       ret = forb_executor_run(&executor);
+
+destroy_and_error:
+       forb_executor_destroy(&executor);
+error:
+       return ret;
+}
diff --git a/src/forb/src/executor.h b/src/forb/src/executor.h
new file mode 100644 (file)
index 0000000..0d08f4f
--- /dev/null
@@ -0,0 +1,88 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+/**
+ * @file   executor.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 16:19:24 2008
+ * 
+ * @brief  Executor type and prototypes.
+ * 
+ * 
+ */
+
+#ifndef EXECUTOR_H
+#define EXECUTOR_H
+
+#include <fosa.h>
+#include <ul_list.h>
+#include <forb/object_type.h>
+
+/**
+ * Executor structure.
+ *
+ * Executors provide a way for applications to determine which thread
+ * will execute requests for a particular object. After the executor
+ * structure is initialized by forb_executor_init(), several objects
+ * can be registered to it by forb_executor_register_object(). Then a
+ * loop which waits for requests and executes them by calling object
+ * implementations is started by forb_executor_run().
+ */
+typedef struct forb_executor {
+       fosa_mutex_t mutex;     /**< Mutex for protecting forb_executor_t::requests. */
+       fosa_cond_t new_request_in_empty_list; /**< Signaled when a request was added to the empty list. */
+       ul_list_head_t requests; /**< List of pending requests for this executor. */
+} forb_executor_t;
+
+int forb_executor_init(forb_executor_t *executor);
+void forb_executor_destroy(forb_executor_t *executor);
+int forb_executor_register_object(forb_executor_t *executor, forb_object obj);
+void forb_executor_unregister_object(forb_executor_t *executor, forb_object obj);
+int forb_executor_run(forb_executor_t *executor);
+
+int forb_execute_object(forb_object obj);
+
+
+#endif
diff --git a/src/forb/src/forb-idl.idl b/src/forb/src/forb-idl.idl
new file mode 100644 (file)
index 0000000..101ddb6
--- /dev/null
@@ -0,0 +1,21 @@
+/**
+ * @file   forb-idl.idl
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Mon Oct 13 13:41:54 2008
+ * 
+ * @brief  Remote interface for FORB
+ * 
+ */
+
+
+module forb {
+       /**
+        * Remote interface for FORB obejcts
+        * 
+        * Every FORB provides this interface to remote forbs so that
+        * other FORBs can obtain information about other FORBs.
+        */
+       interface orb {
+               void is_alive(); /**< Empty function intended to check whether the FORB is active or not. */
+       };
+};
diff --git a/src/forb/src/forb-internal.h b/src/forb/src/forb-internal.h
new file mode 100644 (file)
index 0000000..77f3f50
--- /dev/null
@@ -0,0 +1,126 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   forb-internal.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * 
+ * @brief  Declarationd necessary for IDL-generated code and other parts of FORB.
+ *
+ * This header is not intended to be included by applications.
+ * 
+ */
+
+#ifndef FORB_INTERNAL_H
+#define FORB_INTERNAL_H
+
+#include <forb/basic_types.h>
+#include <forb/cdr.h>
+#include <forb.h>
+#include <forb/uuid.h>
+#include <ul_list.h>
+#include <ul_gavlcust.h>
+#include <forb.h>
+#include <string.h>
+#include <forb/server_id.h>
+
+
+/**
+ * Temporary directory for FORB's housekeeping.
+ *
+ * It is used for proto_unix.c sockets and for registered references
+ * (forb_register_reference()).
+ */
+#define FORB_TMP_DIR "/tmp/forb"
+
+#define FORB_METHOD_INDEX(m) (m ## __method_index)
+
+/**
+ * Internal data of every FORB instance.
+ * 
+ */
+typedef struct forb {
+       forb_server_id server_id;
+       char server_id_str[sizeof(forb_server_id)*2+1]; /**< Server ID string - for easier debuggin messages */
+       forb_orb orb;           /**< Object reference of this forb */
+
+       forb_init_attr_t attr;  /**< Initialization attributes */
+
+       fosa_mutex_t request_id_mutex;  /**< Mutex for request_id */
+       CORBA_long request_id;  /**< Value of next sent request_id */
+
+       fosa_mutex_t objkey_mutex; /**< Mutex for objkey and objects */
+       forb_object_key objkey; /**< Objkey value of last created object  */
+       gavl_cust_root_field_t objects; /**< Tree of objects registered with this FORB. */
+
+       //forb_rt rt;           /**< Routing table */
+       //gavl_cust_root_field_t types;
+
+       fosa_mutex_t request_mutex; /**< Mutex for requests */
+       gavl_cust_root_field_t requests; /**< Container for ::forb_request_t */
+
+       fosa_mutex_t port_mutex;
+       ul_list_head_t ports;   /**< Container for ::forb_port_t */
+
+       fosa_mutex_t peer_mutex; /**< Mutex for @a peers */
+       gavl_cust_root_field_t peers; /**< Container for ::forb_peer_t */
+
+       fosa_mutex_t regref_mutex;
+       gavl_cust_root_field_t regrefs; /**< Container for ::forb_regref_t */
+
+       fosa_thread_id_t execution_thread; /**< Thread which executes remote requests for this forb::orb interface. */
+} forb_t;
+
+typedef void (*forb_skel_func)(FORB_CDR_Codec *cin,
+                              FORB_CDR_Codec *cout,
+                              struct _forb_object *obj,
+                              struct forb_env *env);
+
+
+int
+forb_init_tmp_dir(void);
+
+#endif
diff --git a/src/forb/src/forb.c b/src/forb/src/forb.c
new file mode 100644 (file)
index 0000000..2b31722
--- /dev/null
@@ -0,0 +1,567 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   forb.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 16:57:01 2008
+ * 
+ * @brief  Implementation of basic FORB's functions.
+ * 
+ * 
+ */
+
+#ifndef _BSD_SOURCE
+#define _BSD_SOURCE            /* Because of on_exit()  */
+#endif
+#include "proto.h"
+#include "regref.h"
+#include <forb/config.h>
+#include <forb/forb-internal.h>
+#include <forb.h>
+#include "forb-idl.h"
+#include <forb/iop.h>
+#include <forb/object.h>
+#include <forb/uuid.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <ul_gavlcust.h>
+#include <ul_log.h>
+#include <ul_logreg.h>
+#include <unistd.h>
+#include "discovery.h"
+#ifdef CONFIG_FORB_PROTO_UNIX
+#include <forb/proto_unix.h>
+#endif
+#ifdef CONFIG_FORB_PROTO_INET_DEFAULT
+#include <forb/proto_inet.h>
+#endif
+#ifdef CONFIG_FCB
+#include <fcb.h>
+#include <fcb_contact_info.h>
+#endif
+#include <fcntl.h>
+
+#ifdef DEBUG
+#define UL_LOGL_DEF UL_LOGL_DEB
+#else
+#define UL_LOGL_DEF UL_LOGL_ERR
+#endif
+#include "log_domains.inc"
+
+extern UL_LOG_CUST(ulogd_forb);
+static int init_ul_log(void);
+
+UL_LOGREG_DOMAINS_INIT_FUNCTION(forb_logreg_domains, forb_logreg_domains_array);
+
+#if 0
+static void
+destroy_forb_on_exit(int exitcode, void *arg)
+{
+       forb_orb orb = arg;
+       forb_destroy(orb);
+}
+#endif
+
+static void
+forb_is_alive(forb_orb _obj, CORBA_Environment *ev)
+{
+       ul_logdeb("%s called\n", __FUNCTION__);
+}
+
+static struct forb_forb_orb_impl forb_implementation = {
+       .is_alive = forb_is_alive,
+};
+
+/**
+ * Prepares #FORB_TMP_DIR directory for use by forb
+ *
+ * @return Zero on succes, -1 on error and errno is set appropriately.
+ */
+int
+forb_init_tmp_dir(void)
+{
+       struct stat st;
+       int ret;
+
+       ret = stat(FORB_TMP_DIR, &st);
+
+       if (ret == 0 && !S_ISDIR(st.st_mode)) {
+               ret = unlink(FORB_TMP_DIR);
+               if (ret) return -1;
+       } else if (ret == 0) {
+               return 0;
+       }
+       return mkdir(FORB_TMP_DIR, 0777);
+}
+
+/** 
+ * Thread for execution of remote requests for a FORB object.
+ * 
+ * @param arg 
+ * 
+ * @return 
+ */
+static void *
+forb_execution_thread(void *arg)
+{
+       forb_orb orb = arg;
+
+       forb_execute_object(orb);
+       return NULL;
+}
+
+#ifdef CONFIG_FCB
+void hack_register_fcb(forb_orb orb, forb_port_t *port)
+{
+       forb_object fcb = forb_object_new(orb, &FCB_SERVER_ID, 1);
+       if (!fcb) {
+               ul_logerr("Cannot allocate FCB reference\n");
+               return;
+       }
+       forb_register_reference(fcb, fres_contract_broker_reg_name);
+       forb_object_release(fcb);
+}
+#else
+#define hack_register_fcb(orb)
+#endif
+
+
+
+forb_orb
+forb_init(int *argc, char **argv[], const struct forb_init_attr *attr)
+{
+       forb_orb orb;
+       forb_t *forb;
+       int ret;
+
+       forb = forb_malloc(sizeof(*forb));
+       if (!forb) goto err;
+       memset(forb, 0, sizeof(*forb));
+
+       /* Initialize ULUT logging facility */
+       init_ul_log();
+       forb_logreg_domains();
+
+       if (attr) {
+               forb->attr = *attr;
+       } else {
+               memset(&forb->attr, 0, sizeof(forb->attr));
+       }
+
+       if (forb_server_id_empty(&forb->attr.fixed_server_id)) {
+               forb_server_id_init(&forb->server_id);
+       } else {
+               forb->server_id = forb->attr.fixed_server_id;
+       }
+       forb_server_id_to_string(forb->server_id_str, &forb->server_id,
+                                sizeof(forb->server_id_str));
+       ul_logdeb("Initializing forb %s\n", forb->server_id_str);
+
+       if (fosa_mutex_init(&forb->request_id_mutex, 0) != 0) goto err2;
+       if (fosa_mutex_init(&forb->port_mutex, 0) != 0) goto err2;
+       forb_port_init_head(forb);
+       
+       if (fosa_mutex_init(&forb->request_mutex, 0) != 0) goto err2;
+       forb_request_nolock_init_root_field(forb);
+
+       if (forb_discovery_init(forb) != 0) goto err2;
+
+       if (fosa_mutex_init(&forb->regref_mutex, 0) != 0) goto err2;
+       forb_regref_nolock_init_root_field(forb);
+
+       ret = forb_init_tmp_dir();
+       if (ret != 0) {
+               ul_logerr("Cannot prepare " FORB_TMP_DIR "\n");
+               return NULL;
+       }
+
+       orb = forb_forb_orb_new(NULL, &forb_implementation, forb);
+       if (!orb) goto err2;
+       /* Server ID must be assigned manualy */
+       orb->server = forb->server_id;
+
+       forb->orb = orb;
+
+       /* Insert our object reference to objects tree, so that we
+        * can accept remote request to our new ORB. */
+       forb_objects_nolock_insert(forb, orb);
+
+       ret = fosa_thread_create(&forb->execution_thread, NULL,
+                                forb_execution_thread, orb);
+       if (ret != 0)
+               goto err2;
+
+       /* FIXME: I do not know how to deregister the exit handler if
+        * forb_destroy() is called manually. */
+       /* on_exit(destroy_forb_on_exit, orb); */
+
+#ifdef CONFIG_FORB_PROTO_UNIX
+       {
+               forb_port_t *port = forb_malloc(sizeof(*port));
+               if (port) {
+                       memset(port, 0, sizeof(*port));
+                       ret = forb_unix_port_init(&port->desc, &forb->server_id);
+                       if (ret) goto err_free_unix;
+                       ret = forb_register_port(orb, port);
+                       if (ret) goto err_free_unix; /* TODO: forb_unix_port_done() */
+                       goto unix_ok;
+               }
+       err_free_unix:
+               free(port);
+               goto err2;
+       unix_ok:;
+       }
+#endif
+#ifdef CONFIG_FORB_PROTO_INET_DEFAULT
+       {
+               forb_port_t *port = forb_malloc(sizeof(*port));
+               if (port) {
+                       struct in_addr listen_on;
+
+                       memset(port, 0, sizeof(*port));
+                       listen_on.s_addr = INADDR_ANY;
+                       ret = forb_inet_port_init(&port->desc, listen_on,
+                                                 forb->attr.fixed_tcp_port);
+                       if (ret) goto err_free_inet;
+                       ret = forb_register_port(orb, port);
+                       if (ret) goto err_free_inet; /* TODO: forb_inet_port_done() */
+                       goto inet_ok;
+               }
+       err_free_inet:
+               free(port);
+               goto err2;
+       inet_ok:;
+               hack_register_fcb(orb, port);
+       }
+#endif
+       return orb;
+
+err2:  forb_free(forb);
+err:   return NULL;
+}
+
+void forb_destroy(forb_orb orb)
+{
+       forb_t *forb = forb_object_to_forb(orb);
+       forb_port_t *port;
+       forb_regref_t *regref;
+
+       pthread_cancel(forb->execution_thread.pthread_id);
+       pthread_join(forb->execution_thread.pthread_id, NULL);
+       
+       /* Unregister all registered references */
+       while ((regref = forb_regref_first(forb))) {
+               forb_unregister_reference(orb, regref->name.str);
+       }
+       
+       ul_list_for_each_cut(forb_port, forb, port) {
+               forb_destroy_port(port);
+       }
+       forb_object_release(orb);
+       forb_free(forb);
+}
+
+/* void */
+/* forb_register_interface(const struct forb_interface *interface) */
+/* { */
+/*     gavl_insert(&type_registry, &interface->node); */
+/* } */
+
+/** 
+ * Initializes server ID variable.
+ * 
+ * @param server_id Serer ID to initialize.
+ */
+void
+forb_server_id_init(forb_server_id *server_id)
+{
+       forb_uuid_generate((forb_uuid_t*)server_id->uuid);
+}
+
+/** 
+ * Checks whether the @a object is stale. Stale object is an object
+ * reference whose server cannot be contacted to handle requests.
+ * 
+ * @param object Object reference to check.
+ * 
+ * @return True if the object is stale, false otherwise.
+ */
+bool forb_object_is_stale(forb_object object)
+{
+       forb_orb remote_orb;
+       struct forb_env env;
+       bool stale = true;
+       
+       remote_orb = forb_get_orb_of(object);
+       if (!remote_orb) {      /* This shohuld never happen */
+               goto err;
+       }
+       /* TODO: Check not only the ORB, but also whether the object
+        * is still registered with the remote orb. */
+       forb_orb_is_alive(remote_orb, &env);
+       if (env.major == FORB_EX_COMM_FAILURE) {
+               /* Orb is not alive */
+               stale = true;
+       } else {
+               if (forb_exception_occurred(&env)) {
+                       ul_logerr("%s: unexpected exception: %s\n", __FUNCTION__, forb_strerror(&env));
+               }
+               stale = false;  
+       }
+
+       forb_object_release(remote_orb);
+err:
+       return stale;
+}
+
+
+/** 
+ * Returns object reference of forb::orb object associated with the
+ * given object.
+ * 
+ * @param obj 
+ * 
+ * @return 
+ */
+forb_orb
+forb_get_orb_of(const forb_object obj)
+{
+       forb_orb orb;
+
+       if (forb_server_id_cmp(&obj->server, &obj->orb->server) == 0) {
+               orb = forb_object_duplicate(obj->orb);
+       } else {
+               orb = forb_object_new(obj->orb, &obj->server, 0);
+       }
+       return orb;
+}
+
+/** 
+ * Returns server ID of an object reference.
+ * 
+ * @param obj 
+ * @param dest 
+ */
+void
+forb_get_server_id(const forb_object obj, forb_server_id *dest)
+{
+       if (obj) {
+               *dest = obj->server;
+       }
+}
+
+
+/** 
+ * Return instance data registered when the object was created by
+ * forb_XXX_new().
+ * 
+ * @param obj Object reference
+ * 
+ * @return Pointer to the registered data.
+ */
+void *
+forb_instance_data(const forb_object obj)
+{
+       return forb_object_instance_data(obj);
+}
+
+/** 
+ * Returns error message correspondings FORB exception.
+ * 
+ * @param env Environemnt
+ * 
+ * @return Non-NULL pointer to a string.
+ */
+const char *
+forb_strerror(CORBA_Environment *env)
+{
+       if (!env) {
+               return "Invalid environemnt";
+       }
+#define ex(e) case FORB_EX_##e: return #e; break;
+       switch (env->major) {
+       ex(NONE);
+       ex(UNKNOWN);
+       ex(BAD_PARAM);
+       ex(NO_MEMORY);
+       ex(IMP_LIMIT);
+       ex(COMM_FAILURE);
+       ex(INV_OBJREF);
+       ex(NO_PERMISSION);
+       ex(INTERNAL);
+       ex(MARSHAL);
+       ex(INITIALIZE);
+       ex(NO_IMPLEMENT);
+       ex(BAD_OPERATION);
+       ex(NO_RESOURCES);
+       ex(NO_RESPONSE);
+       ex(TRANSIENT);
+       ex(FREE_MEM);
+       ex(INV_IDENT);
+       ex(INV_FLAG);
+       ex(DATA_CONVERSION);
+       ex(OBJECT_NOT_EXIST);
+       ex(TIMEOUT);
+       ex(APPLICATION);
+       }
+#undef ex
+       return "Invalid error number";
+}
+
+/** 
+ * Return server id of the requesting application.
+ *
+ * This function should be only called from within interface
+ * implementation,
+ * 
+ * @param[in] obj Object being requested
+ * @param[out] req_source Server ID of the requesting application
+ */
+void
+forb_get_req_source(const forb_object obj, forb_server_id *req_source)
+{
+       if (req_source) {
+               if (obj && obj->exec_req) {
+                       *req_source = obj->exec_req->source;
+               } else {
+                       memset(req_source, 0, sizeof(*req_source));
+               }
+       }
+}
+
+/**
+ * Internal function for allocation of sequence bufers. Used by
+ * forb_sequence_alloc_buf().
+ *
+ * @param seq
+ * @param seq_size
+ * @param buf_pptr
+ * @param maximum_ptr
+ * @param num_elements
+ * @param elem_size
+ *
+ * @return CORBA_TRUE if the allocation was sucessfull, CORBA_FALSE if
+ * it wasn't.
+ */
+CORBA_boolean
+__forb_sequence_alloc_buf_internal(void *seq, size_t seq_size,
+                                  void **buf_pptr, CORBA_unsigned_long *maximum_ptr,
+                                  unsigned num_elements, size_t elem_size)
+{
+       memset(seq, 0, seq_size);
+       /*(seq)._length = 0;*/
+       if (num_elements && elem_size) *buf_pptr = forb_malloc(num_elements * elem_size);
+       else *buf_pptr = NULL;
+       *maximum_ptr = *buf_pptr ? num_elements : 0;
+       return (*buf_pptr != NULL) || (num_elements == 0);
+}
+
+static FILE *forb_ul_log_file;
+static char progname[64] = "";
+
+void
+forb_ul_log_fnc(ul_log_domain_t *domain, int level,
+               const char *format, va_list ap)
+{
+       struct timespec now;
+       if(!(level&UL_LOGL_CONT)) {
+               level&=UL_LOGL_MASK;
+               clock_gettime(CLOCK_MONOTONIC, &now);
+               fprintf(forb_ul_log_file,"%ld.%6ld: ", now.tv_sec, now.tv_nsec/1000);
+               if (progname[0])
+                       fprintf(forb_ul_log_file,"%s: ", progname);
+               if(domain && domain->name)
+                       fprintf(forb_ul_log_file,"%s: ",domain->name);
+       }
+       vfprintf(forb_ul_log_file, format, ap);
+       fflush(forb_ul_log_file);
+}
+
+static int init_ul_log(void)
+{
+       char *s;
+       char *log_fname;
+       int fd;
+       int flg = 0;
+       char path[128];
+
+/*     if(ul_log_output != NULL) */
+/*             return 0; */
+
+       fd = open("/proc/self/cmdline", O_RDONLY);
+       if (fd >= 0) {
+               int ret;
+               ret = read(fd, path, sizeof(path)-1);
+               if (ret > 0) {
+                       path[ret]=0;
+                       s = strrchr(path, '/');
+                       if (s) s++;
+                       else s = path;
+                       strncpy(progname, s, sizeof(progname)-1);
+               }
+               close(fd);
+       }
+
+       if((log_fname=getenv("UL_LOG_FILENAME"))!=NULL){
+               forb_ul_log_file=fopen(log_fname,"a");
+       }
+       if(forb_ul_log_file==NULL)
+               forb_ul_log_file=stderr;
+       
+       if((s=getenv("UL_DEBUG_FLG")) != NULL){
+               flg=atoi(s);
+       }
+
+       ul_log_redir(forb_ul_log_fnc, flg);
+
+       if((s = getenv("UL_LOG_LEVELS")) != NULL)
+               ul_log_domain_arg2levels(s);
+
+       return 0;
+}
diff --git a/src/forb/src/forb.h b/src/forb/src/forb.h
new file mode 100644 (file)
index 0000000..9e26590
--- /dev/null
@@ -0,0 +1,240 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   forb.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Fri Aug 29 09:37:27 2008
+ * 
+ * @brief  Public interface to FORB. To be used by applications (both servers and clients).
+ * 
+ * 
+ */
+
+/**
+@mainpage
+
+@section Introduction
+
+FORB is a CORBA-like middleware build on top of FOSA (FRESCOR
+Operating System Adaptation). Its main purpose is to provide unified
+in-process, inter-process and inter-node communication mechanism
+needed for implementation of FRESCOR in modular way. FORB is heavily
+inspired by CORBA, but provides only a very limited number of CORBA
+features.
+
+FORB supports one communication primitive, which is synchronous call
+of a remote method. This operation is mapped to a local function call,
+so that programmer cannot see the difference between the local and
+remote invocation. FORB implements all of the operations needed for
+such kind of communication which is:
+
+- serialization and deserialization of parameters and return values,
+- communication protocol to pass requests and replies between
+  processes,
+- finding the process, where the remote operation is implemented.
+
+FORB is composed of the two following components:
+- IDL compiler (called @c forb-idl) and
+- FORB runtime represented by @c libforb library.
+
+This documentation documents the @c libforb library. The IDL compiler
+is derived form Orbit project, and its documentation is out of scope
+of this document.
+
+@section Compilation
+
+See README file.
+
+@section Usage
+
+To use FORB in an application, an IDL (Interface Description Language)
+file has to be created first. This IDL file describes the interfaces
+used in the the application, their methods, parameters and types. The
+IDL language is similar to a subset of C language and is defined in <a
+href="http://www.omg.org/spec/CORBA/3.1/Interfaces/PDF/">OMG CORBA
+specification version 3.1, part 1</a> (chapter 7: OMG IDL Syntax and
+Semantics).
+
+An example IDL file called @c myinterface.idl can look like this:
+@include tests-idl/myinterface.idl
+
+It defines the interface called @c myinterface and some other
+(non-basic) types used in interface methods. To implement this
+interface, we process this file with the IDL compiler:
+
+\verbatim
+$ forb-idl myinterface.idl
+\endverbatim
+
+It generates four files: @c myinterface.h, @c myinterface-stubs.c, @c
+myinterface-skels.c and @c myinterface-common.c. 
+
+The code of a server which implements the first two methods of this
+interface could look like this:
+
+@include tests-idl/example_server.c
+
+We have to compile this file and link it with @c -skels.c and @c
+-common.c files and the following libraries (under Linux): forb fosa
+pthread rt ulut.
+
+The client code which uses our implementation of @c myinterface could
+look like this:
+
+@include tests-idl/example_client.c
+
+It has to be compiled and linked with @c myinterface-stubs.c and @c
+myinterface-common.c files and with the following libraries (under
+Linux): forb fosa pthread rt ulut.
+
+Note that in these examples we intentionally skipped checking for
+errors to achieve more readable code.
+*/
+
+
+#ifndef FORB_H
+#define FORB_H
+
+#include <forb/forb-idl.h>
+#include <forb/basic_types.h>
+#include <fosa.h>
+#include <forb/types.h>
+#include <forb/executor.h>
+#include <forb/object_type.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Incomplete types - declared in forb-internal.h */
+struct forb_interface;
+typedef struct forb_interface forb_interface_t;
+
+typedef struct forb_init_attr {
+       const char *orb_id;             /**< Name of the FORB used for debugging purposes */
+       void (*peer_discovery_callback)(const forb_orb peer_orb, const char *orb_id);
+       void (*peer_dead_callback)(const forb_orb peer_orb, const char *orb_id);
+       uint16_t fixed_tcp_port; /**< If we want FORB's inet protocol to listen on a fixed port... */
+       forb_server_id fixed_server_id; /**< If we do not want the ID to be random. (HACK) */
+       bool redistribute_hellos;
+
+} forb_init_attr_t;
+
+/** 
+ * Initializes FORB. This function has to be called before any other
+ * FORB function.
+ * 
+ * Any command line arguments used by FORB are removed from the array
+ * and @a argc and @a argv are updated accordingly.
+ * 
+ * @param argc a pointer to the number of command line arguments.
+ * @param argv a pointer to the array of command line arguments.
+ * @param attr attributes that control FORB initialization.
+ * 
+ * @return FORB object reference of NULL in case of error.
+ */
+forb_orb forb_init(int *argc, char **argv[], const forb_init_attr_t *attr);
+
+/** 
+ * Deallocates all resources consumed by FORB.
+ *
+ * @note Called automatically on application exit.
+ * 
+ * @param orb FORB object reference to destroy.
+ */
+void forb_destroy(forb_orb orb);
+
+void
+forb_object_release(forb_object obj);
+
+forb_object
+forb_object_duplicate(const forb_object obj);
+
+void *
+forb_instance_data(const forb_object obj);
+
+int
+forb_register_reference(forb_object object, const char *name);
+
+int
+forb_unregister_reference(forb_orb orb, const char *name);
+
+forb_object
+forb_resolve_reference(const forb_orb orb, const char *name);
+
+forb_object
+forb_string_to_object(const forb_orb orb, const char *string);
+
+char *
+forb_object_to_string(const forb_object obj);
+
+bool forb_object_is_stale(forb_object object);
+
+forb_orb
+forb_get_orb_of(const forb_object obj);
+
+void
+forb_get_server_id(const forb_object obj, forb_server_id *dest);
+
+void
+forb_get_req_source(const forb_object obj, forb_server_id *req_source);
+
+const char *
+forb_strerror(CORBA_Environment *env);
+
+void
+forb_daemon_prepare(const char *pid);
+
+void
+forb_daemon_ready();
+
+
+#ifdef __cplusplus
+} /* extern "C"*/
+#endif
+
+#endif
diff --git a/src/forb/src/forb_endian.h b/src/forb/src/forb_endian.h
new file mode 100644 (file)
index 0000000..863312e
--- /dev/null
@@ -0,0 +1,85 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+#ifndef FORB_ENDIAN_H
+#define FORB_ENDIAN_H 1
+
+#include <endian.h>
+#ifdef __BYTE_ORDER
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define WORDS_BIGENDIAN 1
+#endif
+#endif
+
+
+#define FLAG_BIG_ENDIAN 0
+#define FLAG_LITTLE_ENDIAN 1
+
+#if WORDS_BIGENDIAN
+
+# define FLAG_ENDIANNESS FLAG_BIG_ENDIAN
+# define conversion_needed(to_endianness) ((to_endianness)!=FLAG_BIG_ENDIAN)
+
+#else
+
+# define FLAG_ENDIANNESS FLAG_LITTLE_ENDIAN
+# define conversion_needed(to_endianness) ((to_endianness)!=FLAG_LITTLE_ENDIAN)
+
+#endif
+
+static inline 
+void forb_byteswap(uint8_t *outdata,
+                         const uint8_t *data,
+                         uint32_t datalen)
+{
+  const uint8_t *source_ptr = data;
+  uint8_t *dest_ptr = outdata + datalen - 1;
+  while(dest_ptr >= outdata)
+    *dest_ptr-- = *source_ptr++;
+}
+
+
+#endif /* FLAG_ENDIANNESS */
diff --git a/src/forb/src/forb_utils.h b/src/forb/src/forb_utils.h
new file mode 100644 (file)
index 0000000..b630655
--- /dev/null
@@ -0,0 +1,76 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   forb_utils.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 16:59:57 2008
+ * 
+ * @brief  Miscellaneous FORB utilites.
+ * 
+ * 
+ */
+
+#ifndef FORB_UTILS_H
+#define FORB_UTILS_H
+
+#include <stdlib.h>
+
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+/** 
+ * Cast a member of a structure out to the containing structure.
+ * 
+ * @param ptr the pointer to the member.
+ * @param type the type of the container struct this is embedded in.
+ * @param member the name of the member within the struct.
+ */
+#define container_of(ptr, type, member) ({                     \
+       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+       (type *)( (char *)__mptr - offsetof(type,member) );})
+
+
+#endif
diff --git a/src/forb/src/iop-idl.idl b/src/forb/src/iop-idl.idl
new file mode 100644 (file)
index 0000000..3acb452
--- /dev/null
@@ -0,0 +1,107 @@
+////////////////////////////////////////////////////////////////////////////
+// ---------------------------------------------------------------------- //
+// Copyright (C) 2006 - 2008 FRESCOR consortium partners:                //
+//                                                                       //
+//   Universidad de Cantabria,              SPAIN                        //
+//   University of York,                    UK                           //
+//   Scuola Superiore Sant'Anna,            ITALY                        //
+//   Kaiserslautern University,             GERMANY                      //
+//   Univ. Politécnica  Valencia,           SPAIN                       //
+//   Czech Technical University in Prague,  CZECH REPUBLIC               //
+//   ENEA                                   SWEDEN                       //
+//   Thales Communication S.A.              FRANCE                       //
+//   Visual Tools S.A.                      SPAIN                        //
+//   Rapita Systems Ltd                     UK                           //
+//   Evidence                               ITALY                        //
+//                                                                       //
+//   See http://www.frescor.org for a link to partners' websites         //
+//                                                                       //
+//          FRESCOR project (FP6/2005/IST/5-034026) is funded            //
+//       in part by the European Union Sixth Framework Programme         //
+//       The European Union is not liable of any use that may be         //
+//       made of this code.                                              //
+//                                                                       //
+//                                                                       //
+//  This file is part of FORB (Frescor Object Request Broker)            //
+//                                                                       //
+// FORB is free software; you can redistribute it and/or modify it       //
+// under terms of the GNU General Public License as published by the     //
+// Free Software Foundation; either version 2, or (at your option) any   //
+// later version.  FORB is distributed in the hope that 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 FORB; see file      //
+// COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  //
+// Cambridge, MA 02139, USA.                                             //
+//                                                                       //
+// As a special exception, including FORB header files in a file,        //
+// instantiating FORB generics or templates, or linking other files      //
+// with FORB objects to produce an executable application, does not      //
+// by itself cause the resulting executable application to be covered    //
+// by the GNU General Public License. This exception does not            //
+// however invalidate any other reasons why the executable file might be  //
+// covered by the GNU Public License.                                    //
+////////////////////////////////////////////////////////////////////////////
+
+#include "types.idl"
+
+/**
+ * @file   iop-idl.idl
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 16:52:08 2008
+ * 
+ * @brief  Definitions for FORB's IOP (Inter-ORB protocol).
+ * 
+ * 
+ */
+
+
+/// FORB namespace
+module forb {
+       /// Inter-ORB protocol namespace
+       module iop {
+               
+               typedef octet message_type;
+
+               const message_type REQUEST = 0;
+               const message_type REPLY   = 1;
+               const message_type HELLO   = 2;
+
+               /// Version of FORB IOP protocol
+               struct version {
+                       octet major, minor;
+               };
+
+               typedef octet message_flags;
+
+               const message_flags LITTLE_ENDIAN = 1;
+
+               /// Common header of all FORB IOP messages
+               struct message_header {
+                       version       proto_version;
+                        message_type  message_type;
+                       message_flags flags;
+                       unsigned long message_size;
+               };
+               const long MESSAGE_HEADER_SIZE = 8;
+
+               /// Header of REQUEST message
+               struct request_header {
+                       unsigned long request_id;
+                       string iface;
+                       object_key objkey;
+                       short method_index;
+                       server_id source; ///< Server ID of request originator
+               };
+
+               typedef unsigned short reply_flags;
+               const reply_flags FLAG_EXCEPTION = 1;
+               /// Header of REPLY message
+               struct reply_header {
+                       unsigned long request_id;
+                       reply_flags flags;
+               };
+               const long REPLY_HEADER_SIZE = 8;
+       };
+};
diff --git a/src/forb/src/iop.c b/src/forb/src/iop.c
new file mode 100644 (file)
index 0000000..5133069
--- /dev/null
@@ -0,0 +1,793 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   iop.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Mon Sep  1 21:51:58 2008
+ * 
+ * @brief  Implementation of Inter-ORB protocol.
+ * 
+ * 
+ */
+#include "iop.h"
+#include <forb/cdr.h>
+#include <forb/object.h>
+#include "proto.h"
+#include <ul_log.h>
+#include "exec_req.h"
+#include <errno.h>
+#include "peer.h"
+#include "discovery.h"
+
+/** Version of the protocol */
+#define VER_MAJOR 0
+#define VER_MINOR 0
+
+#define VER(major, minor) ((major)<<8 || (minor))
+
+extern UL_LOG_CUST(ulogd_forb_iop);
+
+
+CORBA_boolean
+forb_iop_prepend_message_header(FORB_CDR_Codec *codec, forb_iop_message_type mt)
+{
+       CORBA_boolean ret;
+       forb_iop_message_header mh;
+       mh.proto_version.major = VER_MAJOR;
+       mh.proto_version.minor = VER_MINOR;
+       mh.message_type = mt;
+       mh.flags = (codec->data_endian == LittleEndian) ? forb_iop_LITTLE_ENDIAN : 0;
+       mh.message_size = FORB_CDR_data_size(codec);
+       ret = FORB_CDR_buffer_prepend(codec, forb_iop_MESSAGE_HEADER_SIZE);
+       if (ret) {
+               ret = forb_iop_message_header_serialize(codec, &mh);
+       }
+       return ret;
+}
+
+CORBA_boolean
+forb_iop_prepare_request(forb_request_t *req,
+                        char *iface,
+                        unsigned method_ind,
+                        CORBA_Environment *env)
+{
+       CORBA_boolean ret;
+       forb_iop_request_header rh;
+
+       rh.request_id = req->request_id;
+       rh.iface = iface;
+       rh.objkey = forb_object_to_key(req->obj);
+       rh.method_index = method_ind;
+       rh.source = forb_object_to_forb(req->obj)->server_id;
+       ret = forb_iop_request_header_serialize(&req->cdr_request, &rh);
+       if (ret) {
+               /* Request body is 8 byte aligned */
+               ret = FORB_CDR_put_align(&req->cdr_request, 8);
+               char str[50];
+               ul_logdeb("preparing request: id=%d  dest=%s  iface=%s method=%d\n", req->request_id,
+                         forb_server_id_to_string(str, &req->obj->server, sizeof(str)),
+                         iface, method_ind);
+       }
+       return ret;
+}
+
+static CORBA_boolean
+forb_iop_prepare_hello(FORB_CDR_Codec *codec,
+                      const forb_server_id *server_id,
+                      const void *src_addr,
+                      CORBA_boolean (*serialize_addr)(FORB_CDR_Codec *codec, const void *addr),
+                      const CORBA_char *orb_id)
+{
+       if (!forb_server_id_serialize(codec, server_id)) return CORBA_FALSE;
+       if (serialize_addr) {
+               if (!serialize_addr(codec, src_addr)) return CORBA_FALSE;
+       }
+       if (!CORBA_string_serialize(codec, &orb_id)) return CORBA_FALSE;
+       /* All headers must be 8 byte aligned so align the length of
+        * this message */
+       if (!FORB_CDR_put_align(codec, 8)) return CORBA_FALSE; 
+       if (!forb_iop_prepend_message_header(codec, forb_iop_HELLO)) return CORBA_FALSE;
+       return CORBA_TRUE;
+}
+
+int forb_iop_send_hello_to(forb_peer_t *peer)
+{
+       forb_port_t *port = peer->port;
+       FORB_CDR_Codec codec;
+       int ret;
+       FORB_CDR_codec_init_static(&codec, port->forb->orb);
+       if (!FORB_CDR_buffer_init(&codec, 1024, 0))
+               return -1;              
+       if (!FORB_CDR_buffer_reset(&codec, forb_iop_MESSAGE_HEADER_SIZE)) {
+               ret = -1;
+               goto free;
+       }
+       if (!forb_iop_prepare_hello(&codec, &port->forb->server_id,
+                                   port->desc.addr,
+                                   port->desc.proto->serialize_addr,
+                                   port->forb->attr.orb_id)) {
+               ret = -1;
+               goto free;
+       }
+       ret = forb_proto_send(peer, &codec);
+       if (ret > 0) ret = 0;
+free:
+       FORB_CDR_codec_release_buffer(&codec);
+       return ret;
+}
+
+int
+forb_iop_redistribute_hello_to(forb_peer_t *dest, forb_peer_t *peer)
+{
+       forb_port_t *port = peer->port;
+       FORB_CDR_Codec codec;
+       int ret;
+       FORB_CDR_codec_init_static(&codec, port->forb->orb);
+       if (!FORB_CDR_buffer_init(&codec, 1024, 0))
+               return -1;              
+       if (!FORB_CDR_buffer_reset(&codec, forb_iop_MESSAGE_HEADER_SIZE)) {
+               ret = -1;
+               goto free;
+       }
+       if (!forb_iop_prepare_hello(&codec, &peer->server_id,
+                                   peer->addr,
+                                   peer->port->desc.proto->serialize_addr,
+                                   peer->orb_id)) {
+               ret = -1;
+               goto free;
+       }
+       ul_logdeb("redistributing hello of %s (%s) to %s (%s)\n",
+                 ""/*TODO:id*/, peer->orb_id, "", dest->orb_id);
+       ret = forb_proto_send(dest, &codec);
+       if (ret > 0) ret = 0;
+free:
+       FORB_CDR_codec_release_buffer(&codec);
+       return ret;
+}
+
+bool
+forb_iop_process_message_header(forb_iop_message_header *mh, FORB_CDR_Codec *codec)
+{
+       /* FIXME: If we have multiple protocol versions, use different
+        * type (independent from version) for return value instead of
+        * mh */
+       forb_iop_version_deserialize(codec, &mh->proto_version);
+       switch (VER(mh->proto_version.major, mh->proto_version.minor)) {
+               case VER(VER_MAJOR, VER_MINOR):
+                       forb_iop_message_type_deserialize(codec, &mh->message_type);
+                       forb_iop_message_flags_deserialize(codec, &mh->flags);
+                       /* Check whwther the type is meaningfull */
+                       switch (mh->message_type) {
+                               case forb_iop_REQUEST:
+                               case forb_iop_REPLY:
+                               case forb_iop_HELLO:
+                                       break;
+                               default:
+                                       ul_logerr("rcvd wrong message type: %d\n",
+                                                 mh->message_type);
+                                       return false;
+                       }
+                       codec->data_endian = (mh->flags && forb_iop_LITTLE_ENDIAN) ?
+                               LittleEndian : BigEndian;                       
+                       CORBA_unsigned_long_deserialize(codec, &mh->message_size);
+                       return true;
+                       break;                  
+               default:
+                       ul_logerr("rcvd wrong protocol versio: %d.%d\n",
+                                 mh->proto_version.major, mh->proto_version.minor);
+                       return false;
+       }
+}
+
+static inline CORBA_boolean
+forb_exception_serialize(FORB_CDR_Codec *codec, struct forb_env *env)
+{
+       return CORBA_long_serialize(codec, &env->major);
+}
+
+static inline CORBA_boolean
+forb_exception_deserialize(FORB_CDR_Codec *codec, struct forb_env *env)
+{
+       /* TODO: Declare exceptions in IDL and don't typecast here. */
+       return CORBA_long_deserialize(codec, (CORBA_long*)&env->major);
+}
+
+void
+forb_iop_send_reply(forb_t *forb,
+          forb_server_id *dest,
+          FORB_CDR_Codec *codec,
+          CORBA_long request_id,
+          struct forb_env *env)
+{
+       forb_iop_reply_header reply_header;
+       CORBA_boolean ret;
+       forb_peer_t *peer;
+       fosa_abs_time_t timeout;
+       
+       reply_header.request_id = request_id;
+       reply_header.flags = 0;
+       if (forb_exception_occurred(env)) {
+               reply_header.flags |= forb_iop_FLAG_EXCEPTION;
+               FORB_CDR_buffer_reset(codec, forb_iop_MESSAGE_HEADER_SIZE +
+                                            forb_iop_REPLY_HEADER_SIZE);
+               forb_exception_serialize(codec, env);
+       }
+       /* All headers must be 8 byte aligned so align the length of
+        * this message */
+       if (!FORB_CDR_put_align(codec, 8)) {
+               ul_logerr("Not enough space for tail align\n");
+               return;         /* FIXME: handle error (goto above)*/
+       }
+       /* forb_iop_REPLY_HEADER_SIZE equals to 8 even if the real
+        * header is shorter. We want reply data to be 8 byte
+        * aligned */
+       ret = FORB_CDR_buffer_prepend(codec, forb_iop_REPLY_HEADER_SIZE);
+       if (!ret) {
+               goto err;
+       }
+       ret = forb_iop_reply_header_serialize(codec, &reply_header);
+       if (!ret) {
+               goto err;
+       }
+       forb_iop_prepend_message_header(codec, forb_iop_REPLY);
+
+       fosa_clock_get_time(FOSA_CLOCK_ABSOLUTE, &timeout);
+       timeout = fosa_abs_time_incr(timeout,
+                                    fosa_msec_to_rel_time(1000));
+
+       peer = forb_get_next_hop(forb, dest, &timeout);
+       if (!peer) {
+               char str[60];
+               forb_server_id_to_string(str, dest, sizeof(str));
+               ul_logerr("Reply destination not found: %s\n", str);
+               goto err;
+       } else {
+               char str[60];
+               forb_server_id_to_string(str, dest, sizeof(str));
+               ul_logdeb("sending reply: dest=%s, id=%u\n", str, request_id);
+       }
+       forb_proto_send(peer, codec);
+       forb_peer_put(peer);
+err:
+       ;
+}
+
+static void
+process_request(forb_port_t *port, FORB_CDR_Codec *codec, uint32_t message_size)
+{
+       forb_iop_request_header request_header;
+       CORBA_boolean ret;
+       forb_object obj;
+       size_t n;
+       forb_t *forb = port->forb;
+       struct forb_env env;
+       FORB_CDR_Codec reply_codec;
+       forb_exec_req_t *exec_req;
+       uint32_t req_size, data_size, header_size;
+       char str[32];
+       forb_peer_t *peer;
+
+       data_size = FORB_CDR_data_size(codec);
+       ret = forb_iop_request_header_deserialize(codec, &request_header);
+       if (!ret) {
+               ul_logerr("Malformed request recevied\n");
+               env.major = FORB_EX_COMM_FAILURE;
+               goto out;
+       }
+       ret = FORB_CDR_get_align(codec, 8);
+       if (!ret) {
+               ul_logerr("Malformed request recevied\n");
+               env.major = FORB_EX_COMM_FAILURE;
+               goto out;
+       }
+
+       header_size = data_size - FORB_CDR_data_size(codec);
+       req_size = message_size - header_size;
+
+       ul_logdeb("rcvd request: src=%s, id=%u, iface=%s, method=%hd\n",
+                 forb_server_id_to_string(str, &request_header.source, sizeof(str)),
+                 request_header.request_id,
+                 request_header.iface,
+                 request_header.method_index);
+
+       if (port->new_peer) {
+               /* Request from a new peer was reported by the underlaying protocol */
+               peer = forb_peer_find(port->forb, &request_header.source);
+               if (peer) {
+                       /* We already know this peer */
+                       /* TODO: Can it be in FORB_PEER_WANTED state?
+                        * If yes, we cannot simply igore this. */
+                       ul_logmsg("new_peer was already known\n");
+                       forb_peer_put(port->new_peer);
+                       port->new_peer = NULL;
+               } else {
+                       ul_logdeb("discovered new_peer from incomming connection\n");
+                       peer = port->new_peer;
+                       port->new_peer = NULL;
+                       forb_new_peer_discovered(port, peer, request_header.source,
+                                                peer->addr, peer->orb_id);
+               }
+               
+       }
+       
+       obj = forb_key_to_object(forb, request_header.objkey);
+       if (!obj) {
+               ul_logerr("Nonexistent object key\n");
+               env.major = FORB_EX_OBJECT_NOT_EXIST;
+               goto send_execption;
+       }
+
+       n = strlen(request_header.iface);
+       ret = strncmp(request_header.iface, obj->interface->name, n);
+       forb_free(request_header.iface);
+       request_header.iface = NULL;
+       if (ret != 0) {
+               env.major = FORB_EX_INV_OBJREF;
+               ul_logerr("Object reference has incorrect type\n");
+               goto send_execption;
+       }
+       
+       if (request_header.method_index >= obj->interface->num_methods) {
+               env.major = FORB_EX_INV_IDENT;
+               ul_logerr("To high method number\n");
+               goto send_execption;
+       }
+
+       if (!obj->executor) {
+               env.major = FORB_EX_NO_IMPLEMENT;
+               ul_logerr("No executor for object\n");
+               goto send_execption;
+
+       }
+
+       /* Enqueue execution request */
+       exec_req = forb_malloc(sizeof(*exec_req));
+       if (exec_req) {
+               memset(exec_req, 0, sizeof(exec_req));
+               exec_req->request_id = request_header.request_id;
+               exec_req->source = request_header.source;
+               exec_req->obj = obj;
+               exec_req->method_index = request_header.method_index;
+               /* Copy the request to exec_req */
+               FORB_CDR_codec_init_static(&exec_req->codec, codec->orb);
+               ret = FORB_CDR_buffer_init(&exec_req->codec,
+                                     req_size,
+                                     0);
+               if (!ret) {
+                       env.major = FORB_EX_NO_MEMORY;
+                       ul_logerr("No memory for executor request bufer of size %d (header_size=%d)\n",
+                                 req_size, header_size);
+                       goto send_execption;
+               }
+               exec_req->codec.data_endian = codec->data_endian;
+               FORB_CDR_buffer_gets(codec, exec_req->codec.buffer, req_size);
+               /* TODO: Use better data structure for incomming
+                  buffer to achieve zero-copy behaviour. */
+               forb_exec_req_ins_tail(obj->executor, exec_req);
+       } else {
+               env.major = FORB_EX_NO_MEMORY;
+               ul_logerr("No memory for executor request\n");
+               goto send_execption;
+       }
+       
+out:
+       return;
+       
+send_execption:
+       FORB_CDR_codec_init_static(&reply_codec, codec->orb);   
+       ret = FORB_CDR_buffer_init(&reply_codec, 4096,
+                             forb_iop_MESSAGE_HEADER_SIZE +
+                             forb_iop_REPLY_HEADER_SIZE);
+       if (!ret) {
+               ul_logerr("No memory for exception reply buffer\n");
+               return;
+       }
+
+       forb_iop_send_reply(port->forb, &request_header.source,
+                           &reply_codec, request_header.request_id, &env);
+       FORB_CDR_codec_release_buffer(&reply_codec);
+       /* TODO: relese exec_req etc. */
+}
+
+static void
+process_reply(forb_port_t *port, FORB_CDR_Codec *codec)
+{
+       forb_iop_reply_header rh;
+       forb_t *forb = port->forb;
+       forb_request_t *req;
+
+       forb_iop_reply_header_deserialize(codec, &rh);
+       /* Reply data are 8 byte aligned */
+       FORB_CDR_get_align(codec, 8);
+       ul_logdeb("rcvd reply: id=%u\n", rh.request_id);
+       req = forb_request_find(forb, &rh.request_id);
+       if (!req) {
+               ul_logerr("Received reply to unknown request_id %u\n", rh.request_id);
+               return;
+       }
+       forb_request_delete(forb, req); /* Deregister request from forb */
+
+       if (rh.flags & forb_iop_FLAG_EXCEPTION) {
+               forb_exception_deserialize(codec, req->env);
+       } else {
+               req->cdr_reply = codec;
+       }
+
+       /* Tell the stub where to signal that reply processing is
+        * finished */
+       req->reply_processed = &port->reply_processed;
+
+       /* Resume the stub waiting in forb_wait_for_reply() */
+       forb_syncobj_signal(&req->reply_ready);
+
+       /* Wait for stub to process the results from the codec's buffer */
+       forb_syncobj_wait(&port->reply_processed);
+}
+
+/** 
+ * Process incomming HELLO messages.
+ *
+ * For every incomming HELLO message the peer table is searched
+ * whether it already contains a record for that peer or not. If not,
+ * the new peer is added to the table and another hello message is
+ * sent so that the new peer discovers us quickly.
+ * 
+ * @param port Port, where hello was received
+ * @param codec Buffer with the hello message
+ */
+static void
+process_hello(forb_port_t *port, FORB_CDR_Codec *codec)
+{
+       forb_server_id server_id;
+       void *addr = NULL;
+       forb_peer_t *peer;
+       forb_t *forb = port->forb;
+       CORBA_string peer_orb_id = NULL;
+
+/*     printf("Hello received at port %p\n", port); */
+
+       forb_server_id_deserialize(codec, &server_id);
+       if (port->desc.proto->deserialize_addr) {
+               port->desc.proto->deserialize_addr(codec, &addr);
+       }
+       {
+               char str[60], addrstr[60];
+               if (port->desc.proto->addr2str) {
+                       port->desc.proto->addr2str(addrstr, sizeof(addrstr), addr);
+               } else
+                       addrstr[0] = 0;
+               ul_logdeb("rcvd hello from %s (addr %s)\n",
+                         forb_server_id_to_string(str, &server_id, sizeof(str)),
+                         addrstr);
+       }
+       CORBA_string_deserialize(codec, &peer_orb_id);
+       if (forb_server_id_cmp(&server_id, &forb->server_id) != 0) {
+               peer = forb_peer_find(forb, &server_id);
+               if (peer && peer->state == FORB_PEER_DISCOVERED) {
+                       /* TODO: Update last hello receive time */
+                       if (port->new_peer) {
+                               ul_logdeb("peer already discovered but not connected - replacing\n");
+                               forb_peer_disconnected(peer);
+                               forb_peer_put(peer);
+                               peer = port->new_peer;
+                               port->new_peer = NULL;
+                               forb_new_peer_discovered(port, peer, server_id, addr, peer_orb_id);
+                       } else {
+                               ul_logdeb("peer already discovered - ignoring\n");
+                               if (addr)
+                                       forb_free(addr);
+                               if (peer_orb_id)
+                                       forb_free(peer_orb_id);
+                               forb_peer_put(peer);
+                       }
+               } else {
+                       if (port->new_peer) {
+                               if (peer) {
+                                       ul_logerr("Unahandled case - FORB_PEER_WANTED && port->new_peer\n");
+                                       forb_peer_put(peer);
+                               }
+                               peer = port->new_peer;
+                               port->new_peer = NULL;
+                       }
+
+                       forb_new_peer_discovered(port, peer, server_id, addr, peer_orb_id);
+               }
+       }
+}
+
+static void
+process_message(forb_port_t *port, const forb_iop_message_header *mh,
+               FORB_CDR_Codec *codec)
+{
+       CORBA_long data_size = FORB_CDR_data_size(codec);
+       /* TODO: Check destination address, whether the message is for
+        * us or should be routed. */
+
+       /* TODO: If there is some processing error, skip the rest of
+        * the message according mh.message_size. */
+       switch (mh->message_type) {
+               case forb_iop_REQUEST:
+                       process_request(port, codec, mh->message_size);
+                       break;
+               case forb_iop_REPLY:
+                       process_reply(port, codec);
+                       break;
+               case forb_iop_HELLO:
+                       process_hello(port, codec);
+                       break;
+               default:
+                       ul_logmsg("rcvd unknown message type\n");
+                       break;
+       }
+       if (port->new_peer) {
+               /* If for some reaseon the new_peer was not processed so free it here. */
+               ul_logmsg("Forgotten new_peer\n");
+               forb_peer_put(port->new_peer);
+               port->new_peer = NULL;
+       }
+
+       FORB_CDR_get_align(codec, 8);
+
+       if (FORB_CDR_data_size(codec) != data_size - mh->message_size) {
+               size_t processed = data_size - FORB_CDR_data_size(codec);
+               ul_logmsg("Message of type %d handled incorrectly (size=%d, processed=%zu); fixing\n",
+                         mh->message_type, mh->message_size, processed);
+               ;
+               codec->rptr += mh->message_size - processed;
+       }
+}
+
+/** 
+ * Thread run for every port to receive FORB messages from that port. 
+ * 
+ * @param arg Pointer to ::forb_port_t typecasted to void *.
+ * 
+ * @return Always NULL
+ */
+void *forb_iop_receiver_thread(void *arg)
+{
+       forb_port_t *port = arg;
+       const forb_proto_t *proto = port->desc.proto;
+       FORB_CDR_Codec *c = &port->codec;
+       ssize_t rcvd;
+       size_t len;
+       forb_iop_message_header mh;
+       bool header_received = false;
+
+       while (!port->finish) {
+               if (c->rptr == c->wptr) {
+                       /* The buffer is empty now - start writing from begining*/
+                       FORB_CDR_buffer_reset(c, 0);
+               }
+               /* TODO: If there is not enough space for reception,
+                * we should shift the already received data to the
+                * beginning of the buffer. */
+               rcvd = proto->recv(port,
+                                  &c->buffer[c->wptr],
+                                  c->wptr_max - c->wptr);
+               if (rcvd < 0) {
+                       ul_logerr("recv returned error %zd (%s), exiting\n", rcvd, strerror(errno));
+                       return NULL;
+               }
+               c->wptr += rcvd;
+                c->wptr_last = c->wptr;
+
+               /* While there are some data in the buffer, process them. */
+               while (FORB_CDR_data_size(c) > 0) {
+                       len = FORB_CDR_data_size(c);
+                       /* Wait for and then process message header */
+                       if (!header_received) {
+                               if (len >= forb_iop_MESSAGE_HEADER_SIZE) {
+                                       if (c->rptr % 8 != 0) {
+                                               ul_logerr("Header doesn't start at 8 byte bounday\n");
+                                       }
+                                       header_received = forb_iop_process_message_header(&mh, c);
+                                       if (!header_received) {
+                                               ul_logerr("Wrong header received\n");
+                                               /* TODO: We should probably reset the buffer here */
+                                       }
+                                       len = FORB_CDR_data_size(c);
+                               } else {
+                                       break; /* Wait for more data to arrive*/
+                               }
+                       }
+                       
+                       /* Wait for and then process the message body */
+                       if (header_received) {
+                               if (len >= mh.message_size) {
+                                       process_message(port, &mh, c);
+                                       /* Wait for the next message */
+                                       header_received = false;
+                               } else {
+                                       break; /* Wait for more data to arrive*/
+                               }
+                       }
+               }
+       }
+       return NULL;
+}
+
+static void
+discovery_cleanup(void *codec)
+{
+       FORB_CDR_codec_release_buffer((FORB_CDR_Codec*)codec);
+       /* TODO: Broadcast some kind of bye bye message */
+}
+
+
+/** 
+ * Thread run for every port to broadcast HELLO messages. These
+ * messages are used for a FORB to discover all peers (and in future
+ * also to detect their disconnection).
+ * 
+ * @param arg Pointer to ::forb_port_t typecasted to void *.
+ * 
+ * @return Always NULL
+ */
+void *forb_iop_discovery_thread(void *arg)
+{
+       forb_port_t *port = arg;
+       const forb_proto_t *proto = port->desc.proto;
+       FORB_CDR_Codec codec;
+       fosa_abs_time_t hello_time;
+       fosa_rel_time_t hello_interval = fosa_msec_to_rel_time(1000*proto->hello_interval);
+       int ret;
+
+       FORB_CDR_codec_init_static(&codec, port->forb->orb);
+       FORB_CDR_buffer_init(&codec, 1024, 0);
+
+       pthread_cleanup_push(discovery_cleanup, &codec);
+       
+       /* Next hello interval is now */
+       fosa_clock_get_time(FOSA_CLOCK_ABSOLUTE, &hello_time);
+       
+       while (!port->finish) {
+               /* Wait for next hello interval or until somebody
+                * signals us. */
+               ret = forb_syncobj_timedwait(&port->hello, &hello_time);
+               /* sem_timedwait would be more appropriate */
+               if (ret == FOSA_ETIMEDOUT) {
+                       hello_time = fosa_abs_time_incr(hello_time, hello_interval);
+               } else if (ret != 0) {
+                       ul_logerr("hello syncobj error: %s\n", strerror(ret));
+               }
+
+               if (port->finish) break;
+
+               FORB_CDR_buffer_reset(&codec, forb_iop_MESSAGE_HEADER_SIZE);
+               forb_iop_prepare_hello(&codec, &port->forb->server_id, port->desc.addr,
+                                      proto->serialize_addr, port->forb->attr.orb_id);
+/*             printf("Broadcasting hello from port %p\n", port);  */
+               proto->broadcast(port, &codec.buffer[codec.rptr],
+                                FORB_CDR_data_size(&codec));
+       }
+
+       pthread_cleanup_pop(1);
+       return NULL;
+}
+
+/** 
+ * Sends REQUEST message to another FORB.
+ *
+ * The request @a req has to be prepared by
+ * forb_iop_prepare_request(). Then, this function adds a message
+ * header, connects to the destination FORB and sends the request.
+ *
+ * If no exception is reported, then the caller must wait for response
+ * by calling forb_wait_for_reply().
+ * 
+ * @param req A request prepared by forb_iop_prepare_request()
+ * @param env Environment for returning exceptions
+ */
+void
+forb_request_send(forb_request_t *req, CORBA_Environment *env)
+{
+       CORBA_boolean ret;
+       forb_peer_t *peer;
+       ssize_t size;
+       size_t len;
+       fosa_abs_time_t timeout;
+       forb_t *forb = forb_object_to_forb(req->obj);
+
+       if (!forb) {
+               env->major = FORB_EX_INTERNAL;
+               return;
+       }
+
+       req->env = env;     /* Remember, where to return exceptions */
+
+       /* All headers must be 8 byte aligned so align the length of
+        * this message */
+       if (!FORB_CDR_put_align(&req->cdr_request, 8)) {
+               env->major = FORB_EX_INTERNAL;
+               ul_logerr("Not enough space for tail align\n");
+               return;
+       }
+
+       ret = forb_iop_prepend_message_header(&req->cdr_request, forb_iop_REQUEST);
+       if (!ret) {
+               /* This should never happen */
+               env->major = FORB_EX_INTERNAL;
+               return;
+       }
+
+       fosa_clock_get_time(FOSA_CLOCK_ABSOLUTE, &timeout);
+       timeout = fosa_abs_time_incr(timeout,
+                                    fosa_msec_to_rel_time(1000));
+       peer = forb_get_next_hop(forb, &req->obj->server, &timeout);
+       if (!peer) {
+               char str[50];
+               ul_logerr("Cannot find peer to send request for server %s\n",
+                         forb_server_id_to_string(str, &req->obj->server, sizeof(str)));
+               env->major = FORB_EX_COMM_FAILURE;
+               return;
+       }
+       /* Register the request with forb so we can match incomming
+        * reply to this request. */
+       ret = forb_request_insert(forb, req);
+       if (ret <= 0) {
+               ul_logerr("Insert request error %d\n", ret);
+               env->major = FORB_EX_INTERNAL;
+               goto err_peer_put;
+       }
+
+       {
+               char str[50];
+               ul_logdeb("sending request: id=%d  dest=%s\n", req->request_id,
+                         forb_server_id_to_string(str, &req->obj->server, sizeof(str)));
+       }
+       len = FORB_CDR_data_size(&req->cdr_request);
+       fosa_mutex_lock(&peer->send_lock);
+       size = forb_proto_send(peer, &req->cdr_request);
+       fosa_mutex_unlock(&peer->send_lock);
+       if (size <= 0 || size != len) {
+               env->major = FORB_EX_COMM_FAILURE;
+               /* Request is deleted when the stub calls forb_request_destroy() */
+       }
+ err_peer_put:
+       forb_peer_put(peer);
+}
diff --git a/src/forb/src/iop.h b/src/forb/src/iop.h
new file mode 100644 (file)
index 0000000..e257309
--- /dev/null
@@ -0,0 +1,101 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   iop.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 17:00:39 2008
+ * 
+ * @brief  Interface to Inter-ORB Protocol.
+ * 
+ * 
+ */
+
+#ifndef FORB_IOP_H
+#define FORB_IOP_H
+
+#include <forb/iop-idl.h>
+#include <forb/cdr.h>
+#include <forb/request.h>
+#include <forb/peer.h>
+
+CORBA_boolean
+forb_iop_prepend_message_header(FORB_CDR_Codec *codec, forb_iop_message_type mt);
+
+CORBA_boolean
+forb_iop_prepare_request(forb_request_t *req,
+                        char *iface,
+                        unsigned method_ind,
+                        CORBA_Environment *env);
+
+bool
+forb_iop_process_message_header(forb_iop_message_header *mh, FORB_CDR_Codec *codec);
+
+void
+forb_iop_process_message(forb_iop_message_header *mh, FORB_CDR_Codec *codec);
+
+void
+forb_iop_send_reply(forb_t *forb,
+                   forb_server_id *dest,
+                   FORB_CDR_Codec *codec,
+                   CORBA_long request_id,
+                   struct forb_env *env);
+
+void *
+forb_iop_receiver_thread(void *arg);
+void *
+forb_iop_discovery_thread(void *arg);
+
+/* TODO: rename to forb_iop_send_request */
+void
+forb_request_send(forb_request_t *req, CORBA_Environment *env);
+
+int
+forb_iop_send_hello_to(forb_peer_t *peer);
+int
+forb_iop_redistribute_hello_to(forb_peer_t *dest, forb_peer_t *peer);
+
+#endif
diff --git a/src/forb/src/object.c b/src/forb/src/object.c
new file mode 100644 (file)
index 0000000..7fdac27
--- /dev/null
@@ -0,0 +1,323 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   object.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 17:03:06 2008
+ * 
+ * @brief  Functions for manipulation with FORB's object references.
+ * 
+ * 
+ */
+
+#include <forb/forb-internal.h>
+#include <forb/object.h>
+#include <stdio.h>
+#include <forb/cdr_codec.h>
+#include <forb/cdr.h>
+#include "forb_utils.h"
+#include <inttypes.h>
+
+GAVL_CUST_NODE_INT_IMP(forb_objects_nolock /* cust_prefix */,
+                      forb_t /* cust_root_t */,
+                      struct _forb_object /* cust_item_t */,
+                      forb_object_key /* cust_key_t */,
+                      objects /* cust_root_node */,
+                      node /* cust_item_node */,
+                      objkey /* cust_item_key */,
+                      forb_objkey_cmp/* cust_cmp_fnc */);
+
+/** 
+ * Creates a new object reference.
+ * 
+ * @param orb FORB object this object reference is handled by. This
+ * can be NULL only when local forb_orb reference is created in
+ * forb_init().
+ * 
+ * @param server_id Server ID of the remote FORB, where this object is
+ * implemented or NULL if the object is implemented locally by @a orb.
+ * 
+ * @param key Key of the remote object. If server_id is NULL this
+ * value is ignored and objkey is assigned internally.
+ * 
+ * @return FORB object reference of NULL in case of error.
+ */
+forb_object
+forb_object_new(forb_orb orb,
+              forb_server_id *server_id,
+              forb_object_key key)
+{
+       forb_object obj = forb_malloc(sizeof(*obj));
+       if (obj) {
+               memset(obj, 0, sizeof(*obj));
+               forb_ref_init(&obj->ref);
+               obj->orb = orb ? orb : obj;
+               if (server_id) {
+                       /* remote object */
+                       obj->server = *server_id;
+                       obj->objkey = key;
+               } else {
+                       /* local object */
+                       if (orb) {
+                               /* Normal local object */
+                               forb_t *forb = forb_object_to_forb(obj);
+                               obj->server = forb->server_id;
+                               fosa_mutex_lock(&forb->objkey_mutex);
+                               obj->objkey = ++forb->objkey;
+                               /* We do not use object references for tree pointers. */
+                               forb_objects_nolock_insert(forb, obj);
+                               fosa_mutex_unlock(&forb->objkey_mutex);
+                       } else {
+                               /* forb_orb object. The forb_init()
+                                *  function must assign server field
+                                *  and put the object into the
+                                *  forb->objects  */
+                               obj->objkey = 0;
+                       }
+               }
+       }
+       return obj;
+}
+
+/** 
+ * This function does the real release of memory when reference count
+ * is zero.
+ *
+ * @note We add this function the _real suffix because the
+ * forb_object_release() is meant for applications use and we want the
+ * name similar to CORBA_Object_release().
+ */
+static void
+forb_object_release_real(forb_ref_t *ref)
+{
+       forb_object obj = container_of(ref, struct _forb_object, ref);
+       
+       if (obj->orb) {
+               forb_t *forb = forb_object_to_forb(obj);
+               if (forb_server_id_cmp(&obj->server, &forb->server_id) == 0) {
+                       /* Local object - unregister it from FORB. */
+                       forb_objects_delete(forb, obj);
+               }
+       }
+       forb_free(obj);
+}
+
+static inline void forb_object_get(forb_object obj)
+{
+       forb_ref_get(&obj->ref);
+}
+
+static inline void forb_object_put(forb_object obj)
+{
+       forb_ref_put(&obj->ref, forb_object_release_real);
+       /* TODO: Exit executor. Question: Shall the executor have its
+        * own refcount? Is so, how do we know to exit/kill it?
+        * Possible answer: The executor might be notified from here
+        * and then exit if it owns the last reference. */
+}
+
+/** 
+ * Releases all memory associated with a object reference and
+ * deregister the object from FORB.
+ * 
+ * @param obj Object reference to release
+ */
+void forb_object_release(forb_object obj)
+{
+       forb_object_put(obj);
+}
+
+/** 
+ * Returns the object's key.
+ * 
+ * @param obj 
+ * 
+ * @return The key.
+ */
+forb_object_key forb_object_to_key(forb_object obj)
+{
+       return obj->objkey;
+}
+
+/** 
+ * Returns the objects reference of a given key.
+ * 
+ * @param forb 
+ * @param key 
+ * 
+ * @return The object reference or NULL in case the object with a
+ * given key doesn't exist.
+ */
+forb_object forb_key_to_object(forb_t *forb, forb_object_key key)
+{
+       forb_object obj;
+       obj = forb_objects_find(forb, key);
+       return obj;
+}
+
+/** 
+ * Converts object reference to string.
+ * 
+ * @param obj Object reference to convert.
+ * 
+ * @return String, which must be freed by forb_free() or NULL in case
+ * of error.
+ */
+char *
+forb_object_to_string(const forb_object obj)
+{
+       char *str;
+       size_t s;
+       forb_object_key key;
+       char server_id[65];
+       
+       s = 2*sizeof(forb_server_id)+1+2*sizeof(size_t)+1;
+       str = malloc(s);
+       if (!str) {
+               return NULL;
+       }
+
+       forb_server_id_to_string(server_id, &obj->server, s);
+       key = forb_object_to_key(obj);
+       snprintf(str, s, "%s-%"PRIu64, server_id, key);
+
+       return str;
+}
+
+/** 
+ * Creates object reference from string.
+ *
+ * The string should be generated by forb_object_to_string() in the
+ * same or another FORB. When the returned reference is not needed, it
+ * should be freed by forb_object_release().
+ * 
+ * @param orb FORB which should handle the object.
+ * @param string The string returned by forb_object_to_string().
+ * 
+ * @return FORB object reference or NULL in case of error.
+ */
+forb_object
+forb_string_to_object(const forb_orb orb, const char *string)
+{
+       forb_object obj;
+       forb_object_key key;
+       forb_server_id server_id;
+       int ret;
+
+       if (forb_server_id_from_string(&server_id, string) == NULL)
+               return NULL;
+
+       if (string[2*sizeof(server_id)] != '-')
+               return NULL;
+
+       ret = sscanf(&string[2*sizeof(server_id)+1], "%"SCNu64, &key);
+       if (ret == 0 || ret == EOF)
+               return NULL;
+
+       obj = forb_object_new(orb, &server_id, key);
+       
+       return obj;
+}
+
+/** 
+ * Duplicates the object reference.
+ * 
+ * @param obj Object reference to duplicate.
+ * 
+ * @return The new copy of @a obj or NULL in case of error. The
+ * duplicated object should be released later by forb_object_release().
+ */
+forb_object
+forb_object_duplicate(const forb_object obj)
+{
+       if (!obj) {
+               return NULL;
+       }
+       forb_object_get(obj);
+       return obj;
+}
+
+/** 
+ * Serialize the object reference.
+ * 
+ * @param codec 
+ * @param obj 
+ * 
+ * @return CORBA_TRUE on success, CORBA_FALSE on error.
+ */
+CORBA_boolean
+forb_object_serialize(FORB_CDR_Codec *codec, const forb_object *obj)
+{
+       if (!forb_server_id_serialize(codec, &(*obj)->server))
+               return CORBA_FALSE;
+       if (!forb_object_key_serialize(codec, &(*obj)->objkey))
+               return CORBA_FALSE;
+       return CORBA_TRUE;
+}
+
+/** 
+ * Creates the object reference by deserialization from ::FORB_CDR_Codec.
+ * 
+ * @param codec 
+ * @param obj 
+ * 
+ * @return CORBA_TRUE on success, CORBA_FALSE on error.
+ */
+CORBA_boolean
+forb_object_deserialize(FORB_CDR_Codec *codec, forb_object *obj)
+{
+       forb_server_id server_id;
+       forb_object_key objkey;
+       if (!forb_server_id_deserialize(codec, &server_id))
+               return CORBA_FALSE;
+       if (!forb_object_key_deserialize(codec, &objkey))
+               return CORBA_FALSE;
+       if (!codec->orb)
+               return CORBA_FALSE;
+       *obj = forb_object_new(codec->orb, &server_id, objkey);
+       return CORBA_TRUE;
+}
diff --git a/src/forb/src/object.h b/src/forb/src/object.h
new file mode 100644 (file)
index 0000000..fd255cc
--- /dev/null
@@ -0,0 +1,258 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   object.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 17:03:44 2008
+ * 
+ * @brief  Declarations for FORB's object references.
+ * 
+ * 
+ */
+
+#ifndef FORB_OBJECT_H
+#define FORB_OBJECT_H
+
+#include <ul_gavlcust.h>
+#include <forb/forb-internal.h>
+#include <stdbool.h>
+#include <forb/refcnt.h>
+#include <forb/basic_types.h>
+#include <forb/executor.h>
+#include <forb/exec_req.h>
+
+/**
+ * Object reference structure.
+ *
+ * The only ways for applications to create an object reference are:
+ * - call IDL generated forb_<interface>_new() function,
+ * - call forb_string_to_object().
+ * - call forb_get_orb_of()
+ * - call forb_init()
+ *
+ * When the created object is not needed, the application should call
+ * forb_object_release().
+ *
+ * If the object reference is passed as a parameter of interface
+ * method, the same rules as in CORBA C mapping objref_ptr applies,
+ * which is:
+ * 
+ * - if the method needs to store the object reference, it must call
+ *   forb_object_duplicate() and store the duplicate.
+ */
+struct _forb_object {
+       /** @name Fields valid for both local and remote object references */
+       /*@{*/
+       
+       /** Server implementing this object. @see forb::server_id */
+       forb_server_id server;
+       /** Object key of the object. @see forb::object_key */
+       forb_object_key objkey;
+
+       forb_orb orb;           /**< FORB reference */
+       forb_ref_t ref;         /**< Reference count */
+       /*@}*/
+
+       /** @name Fields used only in implementation (server) */
+       /*@{*/
+
+       /** Any data for implementation */
+       void *instance_data;
+
+       /** Description of interface implemented by this object (for
+        * servers); FIXME: What about clients? */
+       const forb_interface_t *interface;
+
+       /** Pointer to the object implementation methods or NULL in
+        * case of remote object. */
+       const void *implementation;
+
+       /** Executor object, which represents the thread the requests
+        * are executed in. */
+       forb_executor_t *executor;
+
+       /**
+        * Pointer to the execute request in case of remote
+        * invocation.
+        *
+        * @warning If the object can be called both localy and
+        * remotely this field may contain wrong value as the local
+        * and remote requests can be executed in parallel, in
+        * different threads. This will be fixed after even local
+        * invocations will be executed through executors. */
+       forb_exec_req_t *exec_req;
+
+       gavl_node_t node;       /**< Node for forb->objects tree */
+       /*@}*/
+};
+
+/**
+ * Description of an IDL interface.
+ *
+ * Instances of this structure are generated by forb-idl (IDL compiler).
+ */
+struct forb_interface {
+       char *name;             /**< Name of the interface */
+       unsigned num_methods;   /**< Number of methods */
+       const forb_skel_func *skeletons; /**< Array of pointers to skeleton functions (one function for every method) */
+       uint32_t type_hash;     /**< Not implemented */
+};
+
+/**
+ * Returns forb_object::instance_data of an object.
+ * 
+ */
+#define forb_object_instance_data(obj) ((obj)->instance_data)
+
+/** Return forb_t from an object reference. */
+static inline forb_t *
+forb_data(forb_orb orb)
+{ return forb_object_instance_data(orb); }
+
+
+/** 
+ * Returns pointer to forb_t from any object reference.
+ * 
+ * @param obj Object reference.
+ * 
+ * @return Pointer to forb_t which handles the @a obj.
+ */
+static inline forb_t *
+forb_object_to_forb(forb_object obj)
+{ return forb_data(obj->orb); }
+
+forb_object_key forb_object_to_key(forb_object obj);
+forb_object forb_key_to_object(forb_t *forb, forb_object_key key);
+
+static inline int forb_objkey_cmp(const forb_object_key *a, const forb_object_key *b)
+{
+       return (*a<*b) ? -1 :
+               ((*a>*b) ? +1 :
+                0);
+}
+
+forb_object
+forb_object_new(forb_orb orb,
+               forb_server_id *server_id,
+               forb_object_key key);
+
+/* Declaration of typesafe function for storing objects in GAVL tree
+ * ordered by object keys. */
+GAVL_CUST_NODE_INT_DEC(forb_objects_nolock /* cust_prefix */,
+                      forb_t /* cust_root_t */,
+                      struct _forb_object /* cust_item_t */,
+                      forb_object_key /* cust_key_t */,
+                      objects /* cust_root_node */,
+                      node /* cust_item_node */,
+                      objkey /* cust_item_key */,
+                      forb_objkey_cmp/* cust_cmp_fnc */);
+
+
+/** 
+ * Deletes object reference of an implementation from forb_t::objects.
+ * 
+ * @param forb 
+ * @param obj 
+ */
+static inline void
+forb_objects_delete(forb_t *forb, forb_object obj)
+{
+       fosa_mutex_lock(&forb->objkey_mutex);
+       forb_objects_nolock_delete(forb, obj);
+       fosa_mutex_unlock(&forb->objkey_mutex);
+}
+
+/** 
+ * Finds implementation of an object with a given key.
+ * 
+ * @param forb 
+ * @param objkey 
+ * 
+ * @return Object references if it exists or NULL otherwise.
+ */
+static inline forb_object
+forb_objects_find(forb_t *forb, forb_object_key objkey)
+{
+       forb_object ret;
+       fosa_mutex_lock(&forb->objkey_mutex);
+       ret = forb_objects_nolock_find(forb, &objkey);
+       ret = forb_object_duplicate(ret);
+       fosa_mutex_unlock(&forb->objkey_mutex);
+       return ret;
+}
+
+/** 
+ * Determines whether the object is local (in-process) or remote.
+ * 
+ * @param obj 
+ * 
+ * @return true if local, false otherwise or in case of invalid object reference.
+ */
+static inline bool
+forb_object_is_local(forb_object obj)
+{
+       return obj && obj->implementation;
+}
+/** 
+ * Determines whether the object is remote.
+ * 
+ * @param obj 
+ * 
+ * @return true if remote, false otherwise or in case of invalid object reference.
+ */
+static inline bool
+forb_object_is_remote(forb_object obj)
+{
+       return obj && (obj->implementation == NULL);
+}
+
+CORBA_boolean
+forb_object_serialize(FORB_CDR_Codec *codec, const forb_object *obj);
+CORBA_boolean
+forb_object_deserialize(FORB_CDR_Codec *codec, forb_object *obj);
+
+#endif
diff --git a/src/forb/src/object_type.h b/src/forb/src/object_type.h
new file mode 100644 (file)
index 0000000..59b8140
--- /dev/null
@@ -0,0 +1,134 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   object_type.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 16:19:24 2008
+ * 
+ * @brief  Incomplete declarations of forb_object type and all associated stuff.
+ * 
+ * 
+ */
+
+#ifndef FORB_FORB_OBJECT_H
+#define FORB_FORB_OBJECT_H
+
+#include <forb/basic_types.h>
+#include <stdlib.h>
+#include <forb/types.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct _forb_object;
+
+/** Opaque object reference type. */
+typedef struct _forb_object *forb_object;
+typedef forb_object CORBA_Object;
+
+#if !defined(_forb_orb_defined)
+#define _forb_orb_defined 1
+typedef forb_object forb_orb;
+#endif
+
+/**
+ * FORB exception types. Inspired by CORBA's standard system
+ * exceptions.
+ */
+enum forb_exception {
+       FORB_EX_NONE,           /* 0 */
+       FORB_EX_UNKNOWN,        /* 1 */
+       FORB_EX_BAD_PARAM,      /* 2 */
+       FORB_EX_NO_MEMORY,      /* 3 */
+       FORB_EX_IMP_LIMIT,      /* 4 */
+       FORB_EX_COMM_FAILURE,   /* 5 */
+       FORB_EX_INV_OBJREF,     /* 6 */
+       FORB_EX_NO_PERMISSION,  /* 7 */
+       FORB_EX_INTERNAL,       /* 8 */
+       FORB_EX_MARSHAL,        /* 9 */
+       FORB_EX_INITIALIZE,     /* 10 */
+       FORB_EX_NO_IMPLEMENT,   /* 11 */
+       FORB_EX_BAD_OPERATION,  /* 12 */
+       FORB_EX_NO_RESOURCES,   /* 13 */
+       FORB_EX_NO_RESPONSE,    /* 14 */
+       FORB_EX_TRANSIENT,      /* 15 */
+       FORB_EX_FREE_MEM,       /* 16 */
+       FORB_EX_INV_IDENT,      /* 17 */
+       FORB_EX_INV_FLAG,       /* 18 */
+       FORB_EX_DATA_CONVERSION,  /* 19 */
+       FORB_EX_OBJECT_NOT_EXIST, /* 20 */
+       FORB_EX_TIMEOUT,          /* 21 */
+       FORB_EX_APPLICATION,      /* 22 */ /**< Application defined exception - TODO: Add minor number to forb_env */
+};
+
+/** 
+ * Environment for FORB invocations.
+ * 
+ */
+struct forb_env {
+       enum forb_exception major; /**< Exception number */
+};
+
+typedef struct forb_env CORBA_Environment;
+
+static inline CORBA_boolean forb_exception_occurred(CORBA_Environment *env)
+{
+       return (env->major != FORB_EX_NONE);
+}
+
+#define forb_malloc(size) malloc(size)
+#define forb_free(ptr) free(ptr)
+
+#define CORBA_malloc(size) forb_malloc(size)
+#define CORBA_free(ptr) forb_free(ptr)
+
+#ifdef __cplusplus
+} /* extern "C"*/
+#endif
+
+#endif
diff --git a/src/forb/src/peer.c b/src/forb/src/peer.c
new file mode 100644 (file)
index 0000000..946674d
--- /dev/null
@@ -0,0 +1,88 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   peer.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 17:30:27 2008
+ * 
+ * @brief  Implementation of peer manipulation functions.
+ * 
+ * 
+ */
+
+#include "peer.h"
+#include "forb_utils.h"
+#include "proto.h"
+
+forb_peer_t *
+forb_peer_new(void)
+{
+       forb_peer_t *peer;
+       
+       peer = forb_malloc(sizeof(*peer));
+       if (peer) {
+               memset(peer, 0, sizeof(*peer));
+               fosa_cond_init(&peer->cond);
+               forb_ref_init(&peer->ref);
+               fosa_mutex_init(&peer->send_lock, 0);
+       }
+       return peer;
+}
+
+void
+forb_peer_release(forb_ref_t *ref)
+{
+       forb_peer_t *peer = container_of(ref, forb_peer_t, ref);
+       if (peer->port &&
+           peer->port->desc.proto->peer_destroy) {
+               peer->port->desc.proto->peer_destroy(peer);
+       }
+       if (peer->addr)
+               forb_free(peer->addr);
+       
+       forb_free(peer);
+}
diff --git a/src/forb/src/peer.h b/src/forb/src/peer.h
new file mode 100644 (file)
index 0000000..d6587f9
--- /dev/null
@@ -0,0 +1,125 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   peer.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 17:31:51 2008
+ * 
+ * @brief  Declarations of peer data structure and functions.
+ * 
+ * 
+ */
+
+#ifndef FORB_PEER_H
+#define FORB_PEER_H
+
+#include <forb/forb-internal.h>
+#include "port.h"
+#include "refcnt.h"
+#include <ul_gavl.h>
+#include <ul_list.h>
+#include <fosa_mutexes_and_condvars.h>
+/**
+ * State of a peer.
+ * 
+ */
+enum forb_peer_state {
+       FORB_PEER_WANTED,       /**< Somebody is waiting for the peer to be discovered. In this state, only @a server_id field is set. */
+       FORB_PEER_DISCOVERED,   /**< The peer is already discovered, so it is addr is known and messages can be sent to him. */
+};
+
+/**
+ * Description of a peer FORB. We consider peers only in one-hop
+ * distance. For more distant forbs, we need to use a routing table.
+ *
+ * @note This structure is reference counted. Use forb_peer_get() when
+ * you copy a pointer to peer and forb_peer_put() when the pointer is
+ * not needed.
+ */
+typedef struct forb_peer {
+        forb_server_id server_id; /**< Server_id of the peer */
+        forb_port_t *port;     /**< Port of this peer is connected to */
+        void *addr;            /**< Protocol specific address of the peer. */
+        char *orb_id;          /**< ORB ID of the peer */
+        void *proto_priv;      /**< Protocol private data (e.g. info about established connection) */
+        gavl_node_t gnode;     /**< Node of forb_t::peers tree */
+        ul_list_node_t lnode;  /**< Node of forb_port_t::peers list */
+        forb_ref_t ref;        /**< Reference count */
+        enum forb_peer_state state;
+        fosa_cond_t cond;      /**< Condition variable for waiting after the peer is discovered. Used together with forb_t::peer_mutex. */
+        fosa_mutex_t send_lock;
+} forb_peer_t;
+
+UL_LIST_CUST_DEC(forb_port_peer, /* cust_prefix */
+                forb_port_t,    /* cust_head_t */
+                forb_peer_t,    /* cust_item_t */
+                peers,          /* cust_head_field */
+                lnode)          /* cust_node_field */
+
+forb_peer_t *
+forb_peer_new(void);
+
+void
+forb_peer_release(forb_ref_t *ref);
+
+static inline forb_peer_t *
+forb_peer_get(forb_peer_t *peer)
+{
+       forb_ref_get(&peer->ref);
+       return peer;
+}
+       
+static inline void
+forb_peer_put(forb_peer_t *peer)
+{
+       forb_ref_put(&peer->ref, forb_peer_release);
+}
+
+void
+forb_peer_delete_by_port(forb_t *forb, forb_port_t *port);
+
+#endif
diff --git a/src/forb/src/port.c b/src/forb/src/port.c
new file mode 100644 (file)
index 0000000..0c54c40
--- /dev/null
@@ -0,0 +1,193 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   port.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 17:36:13 2008
+ * 
+ * @brief  Implementation of port manipulation functions.
+ * 
+ * 
+ */
+
+
+#include "port.h"
+#include "proto.h"
+#include "object.h"
+#include <forb/config.h>
+#include "iop.h"
+#include <ul_log.h>
+#include "discovery.h"
+
+extern UL_LOG_CUST(ulogd_forb_port);
+
+/** 
+ * Registers a new port in FORB and run receiver thread on it to
+ * receive FORB messages through this prot. 
+ * 
+ * @param forb Where to register the new port.
+ * 
+ * @param port Port to register. The @c desc field should be
+ * initialized prior calling this function. The memory for @a port
+ * should be forb_malloced, since forb_free() is called on the port on
+ * destroy operation.
+ *
+ * @return Zero on success, FOSA error code on error.
+ */
+int forb_register_port(forb_orb orb, forb_port_t *port)
+{
+       int ret;
+       forb_t *forb = forb_data(orb);
+       
+       port->forb = forb;
+       port->finish = false;
+
+       forb_port_peer_init_head(port);
+       
+       fosa_mutex_lock(&forb->port_mutex);
+       forb_port_insert(forb, port);
+       fosa_mutex_unlock(&forb->port_mutex);
+
+       forb_syncobj_init(&port->hello, 0);
+       forb_syncobj_init(&port->reply_processed, 0);
+
+       FORB_CDR_codec_init_static(&port->codec, forb->orb);
+       if (!FORB_CDR_buffer_init(&port->codec, CONFIG_FORB_RECV_BUF_SIZE, 0)) {
+               ret = FOSA_ENOMEM;
+               goto err;
+       }
+
+       if (port->desc.proto->register_cb) {
+               port->desc.proto->register_cb(port);
+       }
+       
+       ret = fosa_thread_create(&port->receiver_thread, NULL,
+                                forb_iop_receiver_thread, port);
+       if (ret != 0)
+               goto err2;
+#ifndef CONFIG_FORB_PROTO_INET_DEFAULT
+       /* For reliability reasons, we do not use discovery protocol
+        * when INET is the default communication protocol. */
+       ret = fosa_thread_create(&port->discovery_thread, NULL,
+                                forb_iop_discovery_thread, port);
+       if (ret != 0)
+               goto err3;
+#endif
+       return 0;
+#ifndef CONFIG_FORB_PROTO_INET_DEFAULT
+err3:
+       port->finish = true;
+       /* FIXME: This is Aquosa specific - cancelation should be
+        * added to FOSA. */
+       pthread_cancel(port->receiver_thread.pthread_id);
+       pthread_cancel(port->discovery_thread.pthread_id);
+
+       pthread_join(port->receiver_thread.pthread_id, NULL);
+       pthread_join(port->discovery_thread.pthread_id, NULL);
+#endif
+err2:
+       FORB_CDR_codec_release_buffer(&port->codec);
+err:
+       fosa_mutex_lock(&forb->port_mutex);
+       forb_port_delete(forb, port);
+       fosa_mutex_unlock(&forb->port_mutex);
+       
+       return ret;
+}
+
+/** 
+ * Destroys the port and all resources associated with it.
+ * 
+ * @param port 
+ */
+void forb_destroy_port(forb_port_t *port)
+{
+       forb_t *forb = port->forb;
+       void *thread_return;
+
+       port->finish = true;    /* Exit all the threads */
+       
+       /* FIXME: There is no FOSA API for thread cancelation. */
+       pthread_cancel(port->receiver_thread.pthread_id);
+
+       /* FIXME: Canceling discovery thread sometimes didn't
+        * work. The discovery thread stayed forever in the
+        * pthread_cond_timedwait(). */
+       //pthread_cancel(port->discovery_thread.pthread_id);
+
+       /* Sometimes, cancelation doesn't work and the
+        * discovery_thread hangs in pthread_cond_timedwait
+        * infinitely. */
+       forb_syncobj_signal(&port->hello);
+       
+       pthread_join(port->receiver_thread.pthread_id, &thread_return);
+#ifndef CONFIG_FORB_PROTO_INET_DEFAULT
+       pthread_join(port->discovery_thread.pthread_id, &thread_return);
+#endif
+
+       /* Because of no locking of port->peers, this must be called
+        * after receiver thread is stopped. */
+       forb_peer_t *peer;
+       ul_list_for_each_cut(forb_port_peer, port, peer) {
+               forb_peer_get(peer);
+               forb_peer_disconnected(peer);
+               forb_peer_put(peer);
+       }
+
+       if (port->desc.proto->port_destroy) {
+               port->desc.proto->port_destroy(port);
+       }
+
+       FORB_CDR_codec_release_buffer(&port->codec);
+
+       fosa_mutex_lock(&forb->port_mutex);
+       forb_port_delete(forb, port);
+       fosa_mutex_unlock(&forb->port_mutex);
+
+       /* TODO: reference counting */
+       forb_free(port);
+}
diff --git a/src/forb/src/port.h b/src/forb/src/port.h
new file mode 100644 (file)
index 0000000..b5b97fa
--- /dev/null
@@ -0,0 +1,114 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   port.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 17:36:39 2008
+ * 
+ * @brief  Declarations of port types and functions.
+ * 
+ * 
+ */
+
+#ifndef FORB_PORT_H
+#define FORB_PORT_H
+
+#include <forb/forb-internal.h>
+#include <forb/syncobj.h>
+
+struct forb_proto;
+struct forb_peer;
+
+/**
+ * Description of a port. Needs to be filled for forb_register_port().
+ */
+struct forb_port_desc {
+       const struct forb_proto *proto;   /**< Protocol used on this port */
+       void *proto_priv;                 /**< Protocol specific data */
+       void *addr;                       /**< Port's address in a protocol specific format. */
+};
+
+/**
+ * Represents one (of possibly multiple) ports using a specific
+ * FORB transport protocol (see ::forb_proto).
+ *
+ * Every port runs its own thread for receiving messages
+ * (forb_iop_receiver_thread()) and another thread
+ * (forb_iop_discovery_thread()) for periodic broadcasting of HELLO
+ * messages to discover peers connected to the same network.
+ */
+typedef struct forb_port {
+       struct forb_port_desc desc;       /**< Description of the port */
+       forb_t *forb;                     /**< FORB, this port is registered in. */
+       fosa_thread_id_t receiver_thread; /**< The thread running forb_port_receiver_thread() */
+       fosa_thread_id_t discovery_thread;/**< The thread for periodic sending HELLO messages */
+       forb_syncobj_t hello;             /**< Synchronization object for signaling the discovery thread to send the hello messages now. */
+       forb_syncobj_t reply_processed;   /**< Synchronization object for signaling the receiver thread to continue processing after the reply is processed by a stub. */
+       FORB_CDR_Codec codec;             /**< Receiving buffer for receiver thread */
+       ul_list_node_t node;              /**< Node in forb's port list */
+       ul_list_head_t peers;             /**< Peers discovered on this port by discovery protocol */
+       bool finish;                      /**< True when the threads should finish their execution, false otherwise. */
+
+       /** Peer discovered by another mean than discovery
+        * protocol. This field may be set by the protocol whenever it
+        * receives a message (e.g. request) from a new peer. This is
+        * to overcome limitations of discovery protocol on unreliable
+        * medium. */
+       struct forb_peer *new_peer;
+} forb_port_t;
+
+UL_LIST_CUST_DEC(forb_port,    /* cust_prefix */
+                forb_t,        /* cust_head_t */
+                forb_port_t,   /* cust_item_t */
+                ports,         /* cust_head_field */
+                node)          /* cust_node_field */
+
+int forb_register_port(forb_orb orb, forb_port_t *port);
+void forb_destroy_port(forb_port_t *port);
+
+
+#endif
diff --git a/src/forb/src/proto.c b/src/forb/src/proto.c
new file mode 100644 (file)
index 0000000..3caab33
--- /dev/null
@@ -0,0 +1,112 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+/**
+ * @file   proto.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 17:43:28 2008
+ * 
+ * @brief  
+ * 
+ * 
+ */
+
+#include "proto.h"
+#include <forb/forb-internal.h>
+#include <forb/config.h>
+#include <stdio.h>
+#include <forb/object.h>
+#include <ul_log.h>
+#include "discovery.h"
+
+extern UL_LOG_CUST(ulogd_forb_proto);
+
+ssize_t forb_proto_send(forb_peer_t *peer, FORB_CDR_Codec *codec)
+{
+       
+#if 0
+       {
+               int i, j;
+               char m[1000];
+               i=j=0;
+               while (i<CDR_data_size(codec) && j<sizeof(m)-3) {
+                       if (i>0 && i%4 == 0) {
+                               m[j++] = ' ';
+                       }
+                       sprintf(&m[j], "%02x", codec->buffer[i+codec->rptr]);
+                       j+=2;
+                       i+=1;
+               }
+               ul_logdeb("sending: %s\n", m);
+       }
+#endif
+       
+       return peer->port->desc.proto->send(peer, &codec->buffer[codec->rptr],
+                                           FORB_CDR_data_size(codec));
+}
+
+
+/** 
+ * Finds next hop on the way to the particular server.
+ *
+ * Currently, as routing is not implemented, this function searches
+ * only peers.
+ * 
+ * @param forb Forb to ask.
+ * @param server_id Destination server.
+ * 
+ * @return Next hop peer of NULL, if the destination is not found.
+ * 
+ * @note After the returned peer is not needed, forb_peer_put() must
+ * called on it.
+ */
+forb_peer_t *
+forb_get_next_hop(forb_t *forb, forb_server_id *server_id, fosa_abs_time_t *timeout)
+{
+       forb_peer_t *peer;
+       peer = forb_peer_find_timed(forb, server_id, timeout);
+       return peer;
+
+}
diff --git a/src/forb/src/proto.h b/src/forb/src/proto.h
new file mode 100644 (file)
index 0000000..1fb9d4e
--- /dev/null
@@ -0,0 +1,162 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   proto.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Thu Aug 28 10:36:23 2008
+ * 
+ * @brief  FORB transport protocol declarations
+ * 
+ * 
+ */
+
+#ifndef FORB_PROTO_H
+#define FORB_PROTO_H
+
+#include "forb-internal.h"
+#include "syncobj.h"
+#include "request.h"
+#include <ul_logbase.h>
+#include "port.h"
+#include "peer.h"
+
+typedef struct forb_proto forb_proto_t;
+
+/**
+ * Description of a FORB transport protocol.
+ */
+struct forb_proto {
+       /** Number of seconds between sending of HELLO messages for discovery process */
+       unsigned hello_interval;
+
+       /** 
+        * Called to free any protocol resources associated with the port.
+        * 
+        * @param port The port to be destroyed.
+        * 
+        * @return Zero on success, negatove error code on error.
+        */
+       int (*port_destroy)(forb_port_t *port);
+
+       /** 
+        * Sends data to a peer.
+        *
+        * If the protocol is connection-oriented, the connection data
+        * can be stored at @c port->proto_priv and used by later
+        * requests.
+        * 
+        * @param peer Peer to send data
+        * @param buf Data to send
+        * @param len Length of data to send
+        * 
+        * @return Length of the sent data (should be equal to @a len on
+        * success) or negative error code on error.
+        */
+       ssize_t (*send)(forb_peer_t *peer, const void *buf, size_t len);
+
+       /** 
+        * Called to free any protocol resources associated with the
+        * peer.
+        * 
+        * @param peer Peer to destroy
+        * 
+        * @note The memory allocated by @a deserialize_addr (if any)
+        * is deallocated by FORB and should not be deallocated here.
+        */
+       void (*peer_destroy)(forb_peer_t *peer);
+       /** 
+        * Receives data through a port
+        * 
+        * @param port Port to use 
+        * @param buf Where to store the received data
+        * @param len Length the buffer @a buf
+        * 
+        * @return Length of the received data or negative error code
+        * on error.
+        */
+       ssize_t (*recv)(forb_port_t *port, void *buf, size_t len);
+
+       /** 
+        * Broadcasts/multicasts a message. All FORBs connected the
+        * the network/bus represented by the @a port should receive
+        * it.
+        *
+        * This function is used by peer discovery protocol.
+        * 
+        * @param port Port to use 
+        * @param buf Data to broadcast 
+        * @param len Length of the @a data
+        * 
+        * @return Zero or positive number on success, negative error
+        * code on error.
+        */
+       ssize_t (*broadcast)(forb_port_t *port, const void *buf, size_t len);
+
+       /** Serializes the protocol specific address */
+       CORBA_boolean (*serialize_addr)(FORB_CDR_Codec *codec, const void *addr);
+
+       /** Deserializes the protocol specific address. The memory for
+        * storing the address should be allocated by forb_malloc(). */
+       CORBA_boolean (*deserialize_addr)(FORB_CDR_Codec *codec, void **addr);
+
+       /** Converts protocol specific address to string */
+       size_t (*addr2str)(char *dest, size_t maxlen, const void *addr);
+
+       /**
+        * Callback caled when the port is registered to FORB just
+        * before reception and discovery threads are started.
+        */
+       void (*register_cb)(forb_port_t *port);
+};
+
+ssize_t forb_proto_send(forb_peer_t *peer, FORB_CDR_Codec *codec);
+
+forb_peer_t *
+forb_get_next_hop(forb_t *forb, forb_server_id *server, fosa_abs_time_t *timeout);
+
+
+#endif
diff --git a/src/forb/src/proto_inet.c b/src/forb/src/proto_inet.c
new file mode 100644 (file)
index 0000000..39ff70e
--- /dev/null
@@ -0,0 +1,701 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+#include "proto.h"
+#include <arpa/inet.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <forb/proto_inet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <sys/epoll.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <ul_log.h>
+#include <unistd.h>
+#include <forb/config.h>
+#include "discovery.h"
+#include <stdlib.h>
+#include <netinet/tcp.h>
+#include "iop.h" /* FIXME: Sending hello should be handled in IOP layer */
+
+/**
+ * @file   proto_inet.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 16:10:23 2008
+ * 
+ * @brief  FORB transport protocol based on INET family sockets.
+ * 
+ * UDP is used for broadcasts and TCP for requests/replies. There
+ * exist two uni-drectional connections between any two communicating
+ * peers.
+ */
+
+extern UL_LOG_CUST(ulogd_forb_proto_inet);
+
+#define MCAST_PORT 15514       /**< Port used for multicasts */
+#define MCAST_ADDR "225.15.5.14"
+
+/** Address used by inet protocol. All values are stored in network
+ * byte order. */
+struct inet_addr {
+       struct in_addr addr;
+       uint16_t port;          /**< TCP listening port */
+};
+
+/** INET protocol data for ports. */
+struct inet_port {
+       int udp_socket;         /**< Socket for sending and receiving broadcasts */
+       int listen_socket;      /*  */
+       int epoll_fd;           /**< File descriptor used by epoll() in inet_receive(). */
+       struct inet_addr addr;  /**< Address of this port */
+       int last_recv_fd;       /**< Used in inet_recv() to read data longer than receiving buffer */
+       struct in_addr multicast_addr;
+       ul_list_head_t new_peers; /**< List of just connected peers which did not send any data yet. */
+};
+
+UL_LIST_CUST_DEC(inet_port_new_peer, /* cust_prefix */
+                struct inet_port,   /* cust_head_t */
+                forb_peer_t,        /* cust_item_t */
+                new_peers,          /* cust_head_field */
+                lnode)              /* cust_node_field */
+
+
+/** INET protocol data associated with every peer */
+struct inet_peer {
+       int socket;             /**< Connected socket to the peer */
+};
+
+/* static struct inet_port* */
+/* peer_to_inet_port(forb_peer_t *peer) { return peer->port->desc.proto_priv; } */
+
+static CORBA_boolean
+inet_serialize_addr(FORB_CDR_Codec *codec, const void *addr)
+{
+       const struct inet_addr *a = addr;
+       CORBA_unsigned_long haddr = ntohl(a->addr.s_addr);
+       CORBA_unsigned_short hport = ntohs(a->port);
+       CORBA_boolean ret;
+       ret = CORBA_unsigned_long_serialize(codec, &haddr);
+       if (!ret)
+               return ret;
+       return CORBA_unsigned_short_serialize(codec, &hport);
+}
+
+static CORBA_boolean
+inet_deserialize_addr(FORB_CDR_Codec *codec, void **addr)
+{
+       struct inet_addr *a;
+       CORBA_unsigned_long s_addr;
+       CORBA_unsigned_short port;
+       CORBA_boolean ret;
+
+       a = forb_malloc(sizeof(*a));
+       if (!a)
+               return CORBA_FALSE;
+       ret = CORBA_unsigned_long_deserialize(codec, &s_addr);
+       if (!ret)
+               return ret;
+       ret = CORBA_unsigned_short_deserialize(codec, &port);
+       a->addr.s_addr = htonl(s_addr);
+       a->port = htons(port);
+       *addr = a;
+       return ret;
+}
+
+static int
+setnonblocking(int fd);
+
+static int
+setnodelay(int fd)
+{
+       int ret = 0;
+#if 0                          /* For nice graphs in benchmarks */
+       int yes = 1;
+       ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes));
+       if (ret < 0) {
+               ul_logerr("setsockopt(TCP_NODELAY): %s\n", strerror(errno));
+       }
+#endif
+       return ret;
+       
+}
+
+static int
+inet_connect(forb_peer_t *peer)
+{
+       struct inet_peer *ipeer;
+       struct sockaddr_in sa;
+       struct inet_addr *addr = peer->addr;
+       int ret;
+
+       if (!addr) {
+               ul_logerr("No address to connect\n");
+               goto err;
+       }
+       ipeer = forb_malloc(sizeof(*ipeer));
+       if (!ipeer)
+               goto err;
+       ipeer->socket = socket(PF_INET, SOCK_STREAM, 0);
+       if (!ipeer->socket) {
+               ul_logerr("socket(): %s\n", strerror(errno));
+               goto err_free;
+       }
+       sa.sin_family = AF_INET;
+       sa.sin_port = addr->port;
+       sa.sin_addr = addr->addr;
+       ul_logtrash("connect to %s:%u\n", inet_ntoa(sa.sin_addr), ntohs(sa.sin_port));
+       ret = connect(ipeer->socket, (struct sockaddr*)&sa, sizeof(sa));
+       if (ret) {
+               ul_logerr("connect error: %s\n", strerror(errno));
+               goto err_close;
+       }
+
+       setnonblocking(ipeer->socket);
+       setnodelay(ipeer->socket);
+
+       struct epoll_event ev;
+       struct inet_port *p = peer->port->desc.proto_priv;
+       memset(&ev, 0, sizeof(ev));
+       ev.events = EPOLLIN | EPOLLET;
+       ev.data.fd = ipeer->socket;
+       ret = epoll_ctl(p->epoll_fd, EPOLL_CTL_ADD, ipeer->socket, &ev);
+       if (ret) {
+               ul_logerr("epoll_ctl on connect failed: %s\n", strerror(errno));
+               goto err_close;
+       }
+
+       peer->proto_priv = ipeer;
+
+#ifndef TEST /* FIXME: Move hello to IOP, introduce proto connect callback */
+       ret = forb_iop_send_hello_to(peer);
+       if (ret) {
+               goto err_close;
+       }
+#endif
+
+       return 0;
+err_close:
+       close(ipeer->socket);
+err_free:
+       forb_free(ipeer);
+err:
+       return -1;
+       
+}
+
+static ssize_t
+inet_send(forb_peer_t *peer, const void *buf, size_t len)
+{
+       struct inet_peer *ipeer = peer->proto_priv;
+       ssize_t ret, sent;
+
+       if (!ipeer) {
+               ret = inet_connect(peer);
+               if (ret) {
+                       return ret;
+               }
+               ipeer = peer->proto_priv;
+       }
+
+       sent = 0;
+       ul_logtrash("send fd=%d len=%zu\n", ipeer->socket, len);
+       do {
+               ret = send(ipeer->socket, buf, len, 0);
+               if (ret < 0) {
+                       ul_logerr("send error: %s\n", strerror(errno));
+                       return ret;
+               }
+               sent += ret;
+               buf += ret;
+               len -= ret;
+       } while (len > 0);
+
+       return sent;
+}
+
+/*----------------------------------------------------------------------
+ Portable function to set a socket into nonblocking mode.
+ Calling this on a socket causes all future read() and write() calls on
+ that socket to do only as much as they can immediately, and return 
+ without waiting.
+ If no data can be read or written, they return -1 and set errno
+ to EAGAIN (or EWOULDBLOCK).
+ Thanks to Bjorn Reese for this code.
+----------------------------------------------------------------------*/
+int setnonblocking(int fd)
+{
+    int flags;
+
+    /* If they have O_NONBLOCK, use the Posix way to do it */
+#if defined(O_NONBLOCK)
+    /* Fixme: O_NONBLOCK is defined but broken on SunOS 4.1.x and AIX 3.2.5. */
+    if (-1 == (flags = fcntl(fd, F_GETFL, 0)))
+        flags = 0;
+    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+#else
+    /* Otherwise, use the old way of doing it */
+    flags = 1;
+    return ioctl(fd, FIOBIO, &flags);
+#endif
+}     
+
+static int
+inet_accept_connection(forb_port_t *port)
+{
+       struct inet_port *p = port->desc.proto_priv;
+       int client;
+       struct sockaddr_in addr;
+       socklen_t addrlen = sizeof(addr);
+       struct epoll_event ev;
+       int ret;
+       forb_peer_t *peer;
+                               
+       client = accept(p->listen_socket, (struct sockaddr *) &addr, &addrlen);
+       if (client < 0){
+               //perror("accept");
+               return -1;
+       }
+       ret = setnonblocking(client);
+       if (ret) {
+               close(client);
+               return -1;
+       }
+       setnodelay(client);
+
+       peer = forb_peer_new();
+       if (peer) {
+               struct inet_peer *ipeer;
+
+               ipeer = forb_malloc(sizeof(*ipeer));
+               if (ipeer) {
+                       ipeer->socket = client;
+                       peer->proto_priv = ipeer;
+                       peer->port = port;
+                       peer->state = FORB_PEER_DISCOVERED;
+                       inet_port_new_peer_insert(p, peer);
+               } else {
+                       forb_peer_put(peer);
+               }
+       }
+       
+       memset(&ev, 0, sizeof(ev));
+       ev.events = EPOLLIN | EPOLLET;
+       ev.data.fd = client;
+       return epoll_ctl(p->epoll_fd, EPOLL_CTL_ADD, client, &ev);
+}
+
+static ssize_t
+inet_recv(forb_port_t *port, void *buf, size_t len)
+{
+       struct inet_port *iport = port->desc.proto_priv;
+#if 1
+       struct epoll_event ev;
+       ssize_t ret;
+       int nfds;
+       forb_peer_t *peer;
+       bool exported_new_peer = false;
+       
+       for (;;) {
+               if (iport->last_recv_fd == -1) {
+                       nfds = epoll_wait(iport->epoll_fd, &ev, 1, -1);
+                       if (nfds == -1 && errno == EINTR)
+                               continue;
+                       if (nfds < 1)
+                               return -1;
+                       if (ev.data.fd == iport->listen_socket) {
+                               ret = inet_accept_connection(port);
+                               if (ret) {
+                                       ul_logerr("inet_accept_connection error: %s\n", strerror(errno));
+                                       return -1;
+                               } else
+                                       continue;
+                       } else {
+                               iport->last_recv_fd = ev.data.fd;
+                       }
+               }
+               /* Check for first reception form a just connected peer */
+               ul_list_for_each(inet_port_new_peer, iport, peer) {
+                       struct inet_peer *ipeer = peer->proto_priv;
+                       //printf("checking new peer with fd=%d\n", ipeer->socket);
+                       if (ipeer->socket == iport->last_recv_fd) {
+                               inet_port_new_peer_delete(iport, peer);
+
+                               if (port->new_peer) forb_peer_put(peer);
+
+                               /* Let the upper layer assign forb ID
+                                * to this peer according to the request*/
+                               port->new_peer = peer;
+                               exported_new_peer = true;
+                               break;
+                       }
+               }
+
+               //printf("recv fd=%d\n", iport->last_recv_fd);
+               ret = recv(iport->last_recv_fd, buf, len, 0);
+               if (ret == -1) {
+                       if (exported_new_peer) {
+                               forb_peer_put(peer);
+                               port->new_peer = NULL;
+                       }
+                       if (errno != EAGAIN) {
+                               ul_logerr("recv fd=%d error: %s\n", iport->last_recv_fd, strerror(errno));
+                       }
+                       iport->last_recv_fd = -1;
+                       continue;
+               }
+               if (ret == 0) {
+                       if (exported_new_peer) {
+                               forb_peer_put(peer);
+                               port->new_peer = NULL;
+                       }
+                       ul_logtrash("recv fd=%d disconnect\n", iport->last_recv_fd);
+                       ul_list_for_each(forb_port_peer, port, peer) {
+                               struct inet_peer *ipeer = peer->proto_priv;
+                               if (ipeer && ipeer->socket == iport->last_recv_fd) {
+                                       forb_peer_disconnected(peer);
+                                       break;
+                               }
+                       }
+                       iport->last_recv_fd = -1;
+                       continue;
+               }
+               ul_logtrash("recv fd=%d len=%zd\n", iport->last_recv_fd, ret);
+               return ret;
+       }
+#else
+       return recv(iport->udp_socket, buf, len, 0);    
+#endif
+}
+
+static int
+inet_port_destroy(forb_port_t * port)
+{
+       struct inet_port *pd = port->desc.proto_priv;
+       close(pd->epoll_fd);
+       close(pd->udp_socket);
+       close(pd->listen_socket);
+       forb_free(pd);
+       return 0;
+}
+
+static ssize_t
+inet_broadcast(forb_port_t *port, const void *buf, size_t len)
+{
+       struct inet_port *p = port->desc.proto_priv;
+       struct sockaddr_in addr;
+       ssize_t ret;
+       
+       addr.sin_family = AF_INET;
+       addr.sin_port = htons(MCAST_PORT);
+       addr.sin_addr = p->multicast_addr;
+       
+       ret = sendto(p->udp_socket, buf, len, 0,
+                    (struct sockaddr*)&addr, sizeof(addr));
+       return ret;
+}
+
+static void
+inet_peer_destroy(forb_peer_t *peer)
+{
+       struct inet_peer *ipeer = peer->proto_priv;
+       if (ipeer) {
+               peer->proto_priv = NULL;
+               ul_logtrash("destroying peer fd=%d (orb_id=%s)\n",
+                           ipeer->socket, peer->orb_id);
+               close(ipeer->socket);
+               free(ipeer);
+       }
+}
+
+size_t inet_addr2str(char *dest, size_t maxlen, const void *addr)
+{
+       const struct inet_addr *a = addr;
+       size_t ret = 0;
+       if (addr) {
+               snprintf(dest, maxlen, "%s:%d", inet_ntoa(a->addr), ntohs(a->port));
+       }
+       return ret;
+}
+
+#if CONFIG_FCB && CONFIG_FORB_PROTO_INET_DEFAULT
+
+#include <fcb.h>
+#include <fcb_contact_info.h>
+
+static void inet_register_cb(forb_port_t *port)
+{
+       struct inet_addr *ia;
+       
+       ia = malloc(sizeof(*ia));
+       if (!ia) return;
+
+       char *fcb_addr = getenv("FCB_ADDR");
+       if (!fcb_addr) fcb_addr = "127.0.0.1";
+       ia->addr.s_addr = inet_addr(fcb_addr);
+       ia->port = htons(FCB_TCP_PORT);
+       forb_new_peer_discovered(port, NULL, FCB_SERVER_ID, ia, "");
+}
+#else
+#define inet_register_cb NULL
+#endif
+
+static const forb_proto_t proto_inet = {
+       .hello_interval = 40 /* seconds */,
+       .port_destroy = inet_port_destroy,
+       .peer_destroy = inet_peer_destroy,
+       .send = inet_send,
+       .recv = inet_recv,
+       .broadcast = inet_broadcast,
+       .serialize_addr = inet_serialize_addr,
+       .deserialize_addr = inet_deserialize_addr,
+       .addr2str = inet_addr2str,
+       .register_cb = inet_register_cb,
+};
+
+#define MAX_INTERFACES 10
+int get_local_address(int sock, struct in_addr *addr)
+{
+       struct ifconf  ifc;
+       struct ifreq   *ifr, req[MAX_INTERFACES];
+       char *env;
+       bool loopback = false;
+       int ret;
+       struct in_addr env_addr;
+       
+       env = getenv("FORB_EXTERNAL_IP");
+       if (env) {
+               if (inet_aton(env, &env_addr) == 0) {
+                       ul_logerr("Cannot convert FORB_EXTERNAL_IP\n");
+                       errno = EINVAL;
+                       return -1;
+               }
+       }
+
+       ifc.ifc_len = sizeof(req);
+       ifc.ifc_req = req;
+
+       if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
+               return -1;
+       for (ifr = req; ifr < &req[MAX_INTERFACES]; ifr++) {
+               struct sockaddr_in ia;
+               memcpy(&ia, &ifr->ifr_addr, sizeof(ia));
+               ret = ioctl(sock, SIOCGIFFLAGS, ifr);
+               if ((ret == 0) && (ifr->ifr_flags & IFF_UP)) {
+                       if (env && env_addr.s_addr == ia.sin_addr.s_addr) {
+                               *addr = env_addr;
+                               return 0;
+                       }
+                       if (!(ifr->ifr_flags & IFF_LOOPBACK)) {
+                               if (!env) {
+                                       *addr = ia.sin_addr;
+                                       return 0;
+                               }
+                       } else {
+                               *addr = ia.sin_addr;
+                               loopback = true;
+                       }
+               }
+       }
+       if (env) {
+               ul_logerr("FORB_EXTERNAL_IP doesn't match local interface\n");
+               errno = ENODEV;
+               return -1;
+       }
+       if (loopback)
+               return 0;
+       else
+               return -1;
+}
+
+/** 
+ * Initializes INET protocol port.
+ * 
+ * @param port_desc Port description to initialize.
+ * @return Zero on success, -1 on error and errno is set
+ * appropriately.
+ */
+int
+forb_inet_port_init(struct forb_port_desc *port_desc, struct in_addr listen_on,
+                   uint16_t port)
+{
+       int ret;       
+       struct inet_port *port_priv;
+       struct sockaddr_in addr;
+       socklen_t len;
+       struct epoll_event ev;
+       
+       port_priv = forb_malloc(sizeof(*port_priv));
+       if (!port_priv)
+               return -1;
+
+       memset(port_priv, 0, sizeof(*port_priv));
+       port_priv->last_recv_fd = -1;
+       inet_port_new_peer_init_head(port_priv);
+       
+       /* Initialize UDP multicast socket */
+       port_priv->udp_socket = socket(PF_INET, SOCK_DGRAM, 0);
+       if (port_priv->udp_socket == -1) goto err_free;
+       
+       int yes = 1;
+       ret = setsockopt(port_priv->udp_socket, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));
+       if (ret)
+               goto err_close_udp;
+
+       int reuse = 1;
+       setsockopt(port_priv->udp_socket, SOL_SOCKET, SO_REUSEADDR, (int *) &reuse, sizeof(reuse));
+       if (ret)
+               goto err_close_udp;
+
+       setnonblocking(port_priv->udp_socket);
+
+#ifndef CONFIG_FORB_PROTO_INET_DEFAULT
+       struct ip_mreq mreq;
+       inet_aton(MCAST_ADDR, &port_priv->multicast_addr);
+       mreq.imr_multiaddr = port_priv->multicast_addr;
+       mreq.imr_interface.s_addr = INADDR_ANY;
+       ret = setsockopt(port_priv->udp_socket, IPPROTO_IP,
+                        IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
+       if (ret)
+               goto err_close_udp;
+#endif
+
+       addr.sin_family = AF_INET;
+       addr.sin_port = htons(MCAST_PORT);
+       addr.sin_addr = port_priv->multicast_addr;
+
+       ret = bind(port_priv->udp_socket, (struct sockaddr *)&addr, sizeof(addr));
+       if (ret != 0) goto err_close_udp;
+
+       char loop = 1;
+       unsigned loop_size = sizeof(loop);
+       ret = setsockopt(port_priv->udp_socket, IPPROTO_IP,
+                        IP_MULTICAST_LOOP, &loop, loop_size);
+       if (ret)
+               goto err_close_udp;
+       
+
+       /* Initialize TCP socket */
+       port_priv->listen_socket = socket(PF_INET, SOCK_STREAM, 0);
+       if (port_priv->listen_socket == -1) goto err_close_udp;
+
+       reuse = 1;
+       setsockopt(port_priv->listen_socket, SOL_SOCKET, SO_REUSEADDR, (int *) &reuse, sizeof(reuse));
+       if (ret)
+               goto err_close_listen;
+
+       addr.sin_family = AF_INET;
+       addr.sin_port = htons(port);
+       addr.sin_addr = listen_on;
+       ret = bind(port_priv->listen_socket, (struct sockaddr *)&addr, sizeof(addr));
+       if (ret != 0) goto err_close_listen;
+       if (setnonblocking(port_priv->listen_socket))
+               goto err_close_listen;
+
+       ret = listen(port_priv->listen_socket, 10);
+       if (ret)
+               goto err_close_listen;
+
+       /* Determine our address and port*/
+       len = sizeof(addr);
+       ret = getsockname(port_priv->listen_socket, (struct sockaddr *)&addr, &len);
+       if (ret) {
+               ul_logerr("Non-loopback inet address not found\n");
+               goto err_close_listen;
+       }
+
+       port_priv->addr.port = addr.sin_port;
+       if (listen_on.s_addr == INADDR_ANY) {
+               if (get_local_address(port_priv->listen_socket, &port_priv->addr.addr)) {
+                       goto err_close_listen;
+               }
+       } else
+               port_priv->addr.addr = listen_on;
+
+       /* Initialize epoll descriptor */
+       port_priv->epoll_fd = epoll_create(10);
+       if (port_priv->epoll_fd == -1)
+               goto err_close_listen;
+
+       memset(&ev, 0, sizeof(ev));
+       ev.events = EPOLLIN | EPOLLET;
+       ev.data.fd = port_priv->listen_socket;
+       ret = epoll_ctl(port_priv->epoll_fd, EPOLL_CTL_ADD,
+                       port_priv->listen_socket, &ev);
+       if (ret)
+               goto err_close_epoll;
+
+#ifndef CONFIG_FORB_PROTO_INET_DEFAULT 
+       ev.events = EPOLLIN | EPOLLET;
+       ev.data.fd = port_priv->udp_socket;
+       ret = epoll_ctl(port_priv->epoll_fd, EPOLL_CTL_ADD,
+                       port_priv->udp_socket, &ev);
+       if (ret)
+               goto err_close_epoll;
+#endif
+
+       port_desc->proto = &proto_inet;
+       port_desc->proto_priv = port_priv;
+       port_desc->addr = &port_priv->addr;
+       return 0;
+err_close_epoll:
+       close(port_priv->epoll_fd);
+err_close_listen:
+       ret = errno;
+       close(port_priv->listen_socket);
+       errno = ret;
+err_close_udp:
+       ret = errno;
+       close(port_priv->udp_socket);
+       errno = ret;
+err_free:
+       ret = errno;
+       forb_free(port_priv);
+       errno = ret;
+       return -1;
+}
diff --git a/src/forb/src/proto_inet.h b/src/forb/src/proto_inet.h
new file mode 100644 (file)
index 0000000..ad3a048
--- /dev/null
@@ -0,0 +1,66 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/** 
+ * 
+ * @file   proto_inet.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 19:03:10 2008
+ * 
+ * @brief  Prototypes for INET transport protocol
+ */
+
+#ifndef FORB_PROTO_INET_H
+#define FORB_PROTO_INET_H
+
+#include <forb/port.h>
+#include <netinet/in.h>
+#include <stdint.h>
+
+int forb_inet_port_init(struct forb_port_desc *port_desc, struct in_addr listen_on,
+                       uint16_t port);
+
+#endif
diff --git a/src/forb/src/proto_unix.c b/src/forb/src/proto_unix.c
new file mode 100644 (file)
index 0000000..a49a9a6
--- /dev/null
@@ -0,0 +1,231 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+#include <dirent.h>
+#include "proto.h"
+#include <forb/proto_unix.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+
+/**
+ * @file   proto_unix.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 16:10:23 2008
+ * 
+ * @brief  FORB transport protocol based on UNIX DGRAM sockets.
+ * 
+ * The sockets are created in filesystem in #FORB_TMP_DIR directory.
+ */
+
+
+typedef struct sockaddr_un unix_addr_t;
+
+/** UNIX protocol data for ports. */
+struct unix_port {
+       int socket;
+       unix_addr_t addr;
+};
+
+static struct unix_port*
+peer_to_uport(forb_peer_t *peer) { return peer->port->desc.proto_priv; }
+
+static void
+unix_server_to_addr(unix_addr_t *addr, const forb_server_id *server)
+{
+       char str[65];
+       addr->sun_family = AF_UNIX;
+       sprintf(addr->sun_path, FORB_TMP_DIR "/sock.%s",
+               forb_uuid_to_string(str, (forb_uuid_t*)server->uuid, sizeof(str)));
+}
+
+static ssize_t
+unix_send(forb_peer_t *peer, const void *buf, size_t len)
+{
+       unix_addr_t addr;
+       struct unix_port *p = peer_to_uport(peer);
+       //printf("send to %s\n", c->addr.sun_path);
+        unix_server_to_addr(&addr, &peer->server_id);
+       return sendto(p->socket, buf, len, 0,
+                     (struct sockaddr*)&addr, sizeof(addr));
+}
+
+static ssize_t
+unix_recv(forb_port_t *port, void *buf, size_t len)
+{
+       struct unix_port *p = port->desc.proto_priv;
+       return recv(p->socket, buf, len, 0);
+}
+
+static int
+unix_port_destroy(forb_port_t * port)
+{
+       struct unix_port *pd = port->desc.proto_priv;
+       unix_addr_t addr;
+       socklen_t len = sizeof(addr);
+       getsockname(pd->socket, (struct sockaddr*)&addr, &len);
+       if (addr.sun_family == AF_UNIX)
+               unlink(addr.sun_path);
+       close(pd->socket);
+       forb_free(pd);
+       return 0;
+}
+
+static ssize_t
+unix_broadcast(forb_port_t *port, const void *buf, size_t len)
+{
+       struct unix_port *p = port->desc.proto_priv;
+       DIR *dir;
+       struct dirent *dirent;
+       unix_addr_t addr;
+       int ret;
+       int success = 0;
+       
+       dir = opendir(FORB_TMP_DIR);
+       if (!dir) return -errno;
+
+       addr.sun_family = AF_UNIX;
+       
+       while ((dirent = readdir(dir))) {
+               bool forb_socket = 
+#ifdef _DIRENT_HAVE_D_TYPE
+                       (dirent->d_type == DT_SOCK ||
+                        dirent->d_type == DT_UNKNOWN) &&
+#else
+#warning This system does not support _DIRENT_HAVE_D_TYPE
+#endif
+                       (strncmp(dirent->d_name, "sock.", 5) == 0);
+               
+/*             printf("d_name=%s d_type=%d (%d)\n", dirent->d_name, dirent->d_type, DT_SOCK); */
+               if (forb_socket)
+               {
+                       strcpy(addr.sun_path, FORB_TMP_DIR "/");
+                       strncat(addr.sun_path, dirent->d_name, sizeof(addr.sun_path));
+/*                     printf("Broadcasting to %s\n", addr.sun_path); */
+                       ret = sendto(p->socket, buf, len, 0,
+                                    (struct sockaddr*)&addr, sizeof(addr));
+                       /* We do not care about errors in brodcasts -
+                        * the socket may nomore be active */
+                       if (ret == len) {
+                               success++;
+                       } else if (ret < 0 && errno == ECONNREFUSED) {
+                               /* Try to unlink stale socket */
+                               unlink(addr.sun_path);
+                       } else {
+/*                             perror("unix_broadcast"); */
+/*                             return ret; */
+                       }
+               }
+                       
+       }
+       closedir(dir);
+       if (success) {
+               ret = len;
+       } else {
+               ret = -1;
+       }
+       return ret;
+}
+
+static const forb_proto_t proto_unix = {
+       .hello_interval = 40 /* seconds */,
+       .port_destroy = unix_port_destroy,
+       .peer_destroy = NULL,
+       .send = unix_send,
+       .recv = unix_recv,
+       .broadcast = unix_broadcast,
+       /* We do not need the following functions, sice the address
+        * can be derived from server_id */
+       .serialize_addr = NULL,
+       .deserialize_addr = NULL,
+};
+
+/** 
+ * Initializes UNIX protocol port.
+ * 
+ * @param port Port to initialize.
+ * @param server Server this port belongs to.
+ * 
+ * @return Zero on success, -1 on error and errno is set
+ * appropriately.
+ */
+int
+forb_unix_port_init(struct forb_port_desc *port_desc, const forb_server_id *server)
+{
+       
+       int ret;       
+       struct unix_port *pd;
+
+       ret = forb_init_tmp_dir();
+
+       pd = forb_malloc(sizeof(*pd));
+       if (!pd)
+               return -1;
+       
+       pd->socket = socket(PF_UNIX, SOCK_DGRAM, 0);
+       if (pd->socket == -1) goto err1;
+
+       unix_server_to_addr(&pd->addr, server);
+       /* unlink(pd->addr.sun_path); */ /* TODO: What to do when the socket already exist? */
+       ret = bind(pd->socket, (struct sockaddr*)&pd->addr, sizeof(pd->addr));
+       chmod(pd->addr.sun_path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+       if (ret == -1) goto err;
+
+       port_desc->proto = &proto_unix;
+       port_desc->proto_priv = pd;
+       return 0;
+err:
+       ret = errno;
+       close(pd->socket);
+       errno = ret;
+err1:
+       ret = errno;
+       forb_free(pd);
+       errno = ret;
+       return -1;
+}
diff --git a/src/forb/src/proto_unix.h b/src/forb/src/proto_unix.h
new file mode 100644 (file)
index 0000000..fb44b32
--- /dev/null
@@ -0,0 +1,62 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/** 
+ * 
+ * @file   proto_unix.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 19:03:10 2008
+ * 
+ * @brief  Prototypes for UNIX transport protocol
+ */
+
+#ifndef FORB_PROTO_UNIX_H
+#define FORB_PROTO_UNIX_H
+
+int forb_unix_port_init(struct forb_port_desc *port_desc,
+                       const forb_server_id *server);
+
+#endif
diff --git a/src/forb/src/refcnt.c b/src/forb/src/refcnt.c
new file mode 100644 (file)
index 0000000..9c76737
--- /dev/null
@@ -0,0 +1,103 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   refcnt.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Wed Oct  1 09:23:40 2008
+ * 
+ * @brief  Atomic reference counting operations.
+ *
+ * @note To provide portable atomicity, we use GCC's builtin
+ * functions introduced in GCC 4.1.
+ * 
+ */
+#include "refcnt.h"
+
+void forb_ref_set(struct forb_ref *ref, int num)
+{
+       ref->refcount = num;
+}
+
+/** 
+ * Initializes reference count to 1.
+ * 
+ * @param ref 
+ */
+void forb_ref_init(struct forb_ref *ref)
+{
+       forb_ref_set(ref, 1);
+}
+
+/** 
+ * Atomicaly increases reference count
+ * 
+ * @param ref 
+ */
+void forb_ref_get(struct forb_ref *ref)
+{
+       __sync_add_and_fetch(&ref->refcount, 1);
+}
+
+/** 
+ * Atomicaly decreases reference count and if zero is reached calls, @a
+ * release function (destructor).
+ * 
+ * @param ref Reference to act on.
+ * @param release Release function called when reference count reaches zero.
+ * 
+ * @return 1 if the @a release function was called, zero othewise
+ * (which doesn't mean that the object still exist in memory as it
+ * might be released by somebody else in the mean time).
+ */
+int forb_ref_put(struct forb_ref *ref, void (*release) (struct forb_ref *ref))
+{
+       if (__sync_add_and_fetch(&ref->refcount, -1) == 0) {
+               release(ref);
+               return 1;
+       }
+       return 0;
+}
diff --git a/src/forb/src/refcnt.h b/src/forb/src/refcnt.h
new file mode 100644 (file)
index 0000000..cd6a314
--- /dev/null
@@ -0,0 +1,77 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+#ifndef FORB_REFCNT_H
+#define FORB_REFCNT_H
+
+/**
+ * @file   refcnt.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 16:03:51 2008
+ * 
+ * @brief  Atomic reference counting types and prototypes. 
+ * 
+ * 
+ */
+
+
+/**
+ * Reference counter type
+ * 
+ */
+struct forb_ref {
+       unsigned refcount;
+};
+
+typedef struct forb_ref forb_ref_t;
+
+void forb_ref_set(struct forb_ref *ref, int num);
+void forb_ref_init(struct forb_ref *ref);
+void forb_ref_get(struct forb_ref *ref);
+int forb_ref_put(struct forb_ref *ref, void (*release) (struct forb_ref *ref));
+       
+
+#endif
diff --git a/src/forb/src/regref.c b/src/forb/src/regref.c
new file mode 100644 (file)
index 0000000..1d6f62c
--- /dev/null
@@ -0,0 +1,366 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+#include "regref.h"
+#include "object.h"
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ul_log.h>
+#include <forb/config.h>
+
+extern UL_LOG_CUST(ulogd_forb_regref);
+
+static inline int forb_regref_cmp(const forb_regref_name_t *a, const forb_regref_name_t *b)
+{
+       return strncmp(a->str, b->str, FORB_REGREF_NAME_LEN);
+}
+
+GAVL_CUST_NODE_INT_IMP(forb_regref_nolock /* cust_prefix */,
+                      forb_t /* cust_root_t */,
+                      forb_regref_t /* cust_item_t */,
+                      forb_regref_name_t /* cust_key_t */,
+                      regrefs /* cust_root_node */,
+                      node /* cust_item_node */,
+                      name /* cust_item_key */,
+                      forb_regref_cmp/* cust_cmp_fnc */);
+
+/** 
+ * Allocates a new ::forb_regref_t structure and fills it with data.
+ * 
+ * @param object Object reference to register.
+ * 
+ * @param name Name of the registered object reference, which can be
+ * used by other applications in forb_resolve_reference().
+ * 
+ * @return Pointer to the newly allocated regref of NULL in case of error.
+ */
+forb_regref_t *
+forb_regref_new(forb_object object, forb_regref_name_t name)
+{
+       forb_regref_t *regref;
+
+       regref = forb_malloc(sizeof(*regref));
+       if (regref) {
+               regref->name = name;
+               regref->object = forb_object_duplicate(object);
+       }
+       return regref;
+}
+
+/** 
+ * Releases ::forb_regref_t previously allocated by forb_regref_new().
+ * 
+ * @param regref Regref to release.
+ */
+void 
+forb_regref_release(forb_regref_t *regref)
+{
+       if (regref) {
+               forb_object_release(regref->object);
+               forb_free(regref);
+       }
+}
+
+
+
+#ifndef CONFIG_FORB_PROTO_INET_DEFAULT
+/** 
+ * 
+ * 
+ * @param fd 
+ * @param objref 
+ * 
+ * @return Zero on success, -1 on error.
+ */
+static int
+rewrite_regref(int fd, const char *objref)
+{
+       int ret;
+       int len = strlen(objref);
+       lseek(fd, 0, SEEK_SET);
+       ftruncate(fd, 0);
+               
+       while (len > 0) {
+               ret = write(fd, objref, len);
+               if (ret < 0) goto out;
+               len -= ret;
+               objref += ret;
+       }
+       ret = 0;        /* Success */
+out:
+       return ret;
+}
+
+/** 
+ * 
+ * 
+ * @param orb 
+ * @param fn File name
+ * @param objref string form of the object reference
+ * 
+ * @return -1 on error, 0 if reference was replaced and 1 in the
+ * reference is valid.
+ */
+static int
+replace_regref_if_stale(forb_orb orb, const char *fn, const char *objref)
+{
+       int fd, ret = 0; 
+       char str[100];
+       forb_object object;
+       
+       fd = open(fn, O_RDWR);
+       if (fd < 0) {
+               ret = -1;
+               goto out;
+       }
+       ret = lockf(fd, F_LOCK, 0);
+       if (ret < 0) goto close_err;
+       ret = read(fd, str, sizeof(str)-1);
+       if (ret < 0) goto unlock_err;
+       /* TODO: Check that we have read the whole file */
+       
+       str[ret] = '\0';
+       object = forb_string_to_object(orb, str);
+       if (!object) {
+               /* reference is unreadable, so we can replace it */
+               ret = rewrite_regref(fd, objref);
+               /* We are done for now */
+               goto unlock_err;
+       }
+       if (forb_object_is_stale(object)) {
+               /* Orb is not alive */
+               ret = rewrite_regref(fd, objref);
+       } else {
+               /* Reference's FORB is alive :-( */
+               ret = 1;        
+       }
+
+       forb_object_release(object);
+unlock_err:    
+       lockf(fd, F_ULOCK, 0);
+close_err:
+       close(fd);
+out:
+       return ret;
+}
+#endif
+
+/** 
+ * Registers a given object reference so that other FORBs on the same
+ * node can find it by using forb_resolve_reference().
+ * 
+ * @param object Object reference to register.
+ * @param name Name under which to register the reference.
+ *
+ * @return Zero on success, -1 on error.
+ */
+int
+forb_register_reference(forb_object object, const char *name)
+{
+       forb_regref_t *regref;
+       forb_regref_name_t regname;
+       forb_t *forb = forb_object_to_forb(object);
+
+       strncpy(regname.str, name, FORB_REGREF_NAME_LEN-1);
+       regname.str[FORB_REGREF_NAME_LEN-1]='\0';
+
+       regref = forb_regref_new(object, regname);
+       if (!regref) goto err;
+
+       forb_regref_insert(forb, regref);
+
+#ifdef CONFIG_FORB_PROTO_INET_DEFAULT
+       return 0;
+#else
+       char fn[100], fntmp[100];
+       char *objref;
+       FILE *f;
+       int ret;
+       snprintf(fn,    sizeof(fn),    FORB_TMP_DIR "/%s",    regname.str);
+       snprintf(fntmp, sizeof(fntmp), FORB_TMP_DIR "/%s.%s", regname.str,
+                forb->server_id_str);
+
+       f = fopen(fntmp, "w");
+       if (!f) goto unalloc_err;
+       
+       objref = forb_object_to_string(object);
+       if (!objref) goto unlink_err;
+
+       ret = fprintf(f, "%s", objref);
+       if (ret < 0) goto free_objref_err;
+
+       ret = fclose(f);
+       if (ret == EOF) goto free_objref_err;
+
+       /* Make the atomic registration in filesystem */
+       ret = link(fntmp, fn);
+       
+       if (ret < 0 && errno == EEXIST) {
+               /* The reference exists. Try whether it is still
+                * active. */
+               if (replace_regref_if_stale(object->orb, fn, objref) != 0) {
+                       goto free_objref_err;
+               }
+               ul_logdeb("Stale registration replaced\n");
+       } else if (ret < 0) {
+               goto free_objref_err;
+       }
+
+       forb_free(objref);
+
+       /* Unlink the temporary filename */
+       unlink(fntmp);
+       
+       return 0;
+free_objref_err:
+       ret = errno;
+       forb_free(objref);
+       errno = ret;
+unlink_err:
+       ret = errno;
+       unlink(fntmp);
+       errno = ret;
+unalloc_err:
+       ret = errno;
+       forb_regref_delete(forb, regref);
+       forb_regref_release(regref);
+       errno = ret;
+#endif
+err:
+       return -1;
+}
+
+/** 
+ * Unregister reference previously registered by
+ * forb_register_reference().
+ * 
+ * @param orb forb::orb reference
+ * @param name Name to unregister.
+ * 
+ * @return Zero on success, -1 on error.
+ */
+int
+forb_unregister_reference(forb_orb orb, const char *name)
+{
+       forb_regref_t *regref;
+       forb_regref_name_t regname;
+       forb_t *forb = forb_object_to_forb(orb);
+
+       strncpy(regname.str, name, FORB_REGREF_NAME_LEN-1);
+       regname.str[FORB_REGREF_NAME_LEN-1]='\0';
+
+       regref = forb_regref_find(forb, &regname);
+       if (!regref) goto err;
+
+       forb_regref_delete(forb, regref);
+       forb_regref_release(regref);
+
+#ifndef CONFIG_FORB_PROTO_INET_DEFAULT
+       char fn[100];
+       snprintf(fn,    sizeof(fn),    FORB_TMP_DIR "/%s",    regname.str);
+       return unlink(fn);
+#endif
+
+       return 0;
+err:
+       return -1;
+}
+
+/** 
+ * Returns a named reference previously registered by
+ * forb_register_reference(). This function can be called even if the
+ * reference was registered in a diferent process (but on the same
+ * node).
+ * 
+ * @param orb Local orb object reference
+ * @param name Name under which the reference was registered.
+ * 
+ * @return Object reference on NULL in case of error.
+ */
+forb_object
+forb_resolve_reference(const forb_orb orb, const char *name)
+{
+       forb_regref_name_t regname;
+       forb_object object;
+
+       strncpy(regname.str, name, FORB_REGREF_NAME_LEN-1);
+       regname.str[FORB_REGREF_NAME_LEN-1]='\0';
+
+#ifdef CONFIG_FORB_PROTO_INET_DEFAULT
+       forb_regref_t *regref;
+       forb_t *forb = forb_object_to_forb(orb);
+
+       regref = forb_regref_find(forb, &regname);
+       if (!regref) return NULL;
+
+       object = forb_object_duplicate(regref->object);
+       return object;
+
+#else
+       char fn[100];
+       char str[100];
+       int fd, ret;
+
+       snprintf(fn,    sizeof(fn),    FORB_TMP_DIR "/%s",    regname.str);
+
+       fd = open(fn, 0);
+       if (fd < 0) {
+               return NULL;
+       }
+       ret = read(fd, str, sizeof(str)-1);
+       /* TODO: Check that we have read the whole file */
+       str[ret] = '\0';
+       object = forb_string_to_object(orb, str);
+       close(fd);
+#endif
+
+       if (forb_object_is_stale(object)) {
+               forb_object_release(object);
+               object = NULL;
+       }
+       return object;
+}
diff --git a/src/forb/src/regref.h b/src/forb/src/regref.h
new file mode 100644 (file)
index 0000000..1ec9c54
--- /dev/null
@@ -0,0 +1,137 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   regref.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sat Oct 11 14:46:08 2008
+ * 
+ * @brief Handling of registered object references.
+ * 
+ * 
+ */
+
+#ifndef FORB_REGREF_H
+#define FORB_REGREF_H
+
+#include <forb.h>
+#include <forb/forb-internal.h>
+#include <ul_gavl.h>
+
+#define FORB_REGREF_NAME_LEN 32
+
+/**
+ * Type for registered names
+ *
+ * We must encapsulate the array in structure in order to behave as
+ * normal C object. This is necessary for usage as GAVL key. The
+ * reason is that typeof(&array) == typeof(array).
+ */
+typedef struct {
+       char str[FORB_REGREF_NAME_LEN];
+} forb_regref_name_t;
+
+struct forb_regref {
+       forb_regref_name_t name; /**< Name of the registered reference */
+       forb_object object;      /**< Registered object reference */
+       gavl_node_t node;        /**< Node for forb->regrefs tree */
+};
+
+typedef struct forb_regref forb_regref_t;
+
+GAVL_CUST_NODE_INT_DEC(forb_regref_nolock /* cust_prefix */,
+                      forb_t /* cust_root_t */,
+                      forb_regref_t /* cust_item_t */,
+                      forb_regref_name_t /* cust_key_t */,
+                      regrefs /* cust_root_node */,
+                      node /* cust_item_node */,
+                      name /* cust_item_key */,
+                      forb_regref_cmp/* cust_cmp_fnc */);
+
+
+forb_regref_t *
+forb_regref_new(forb_object object, forb_regref_name_t name);
+
+void 
+forb_regref_release(forb_regref_t *regref);
+
+static inline void
+forb_regref_insert(forb_t *forb, forb_regref_t *regref)
+{
+       pthread_mutex_lock(&forb->regref_mutex);
+       forb_regref_nolock_insert(forb, regref);
+       pthread_mutex_unlock(&forb->regref_mutex);
+}
+
+static inline void
+forb_regref_delete(forb_t *forb, forb_regref_t *regref)
+{
+       pthread_mutex_lock(&forb->regref_mutex);
+       forb_regref_nolock_delete(forb, regref);
+       pthread_mutex_unlock(&forb->regref_mutex);
+}
+
+static inline forb_regref_t *
+forb_regref_find(forb_t *forb, forb_regref_name_t const *name)
+{
+       forb_regref_t *regref;
+       pthread_mutex_lock(&forb->regref_mutex);
+       regref = forb_regref_nolock_find(forb, name);
+       pthread_mutex_unlock(&forb->regref_mutex);
+       return regref;
+}
+
+static inline forb_regref_t *
+forb_regref_first(forb_t *forb)
+{
+       forb_regref_t *regref;
+       pthread_mutex_lock(&forb->regref_mutex);
+       regref = forb_regref_nolock_first(forb);
+       pthread_mutex_unlock(&forb->regref_mutex);
+       return regref;
+}
+
+#endif
diff --git a/src/forb/src/request.c b/src/forb/src/request.c
new file mode 100644 (file)
index 0000000..b6b1196
--- /dev/null
@@ -0,0 +1,162 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   request.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 19:04:21 2008
+ * 
+ * @brief  Implementation of request handling functions
+ * 
+ * 
+ */
+
+#include <forb/forb-internal.h>
+#include "request.h"
+#include <forb/iop-idl.h>
+#include <forb/object.h>
+#include "peer.h"
+#include "iop.h"
+#include "proto.h"
+#include <ul_log.h>
+
+extern UL_LOG_CUST(ulogd_forb_request);
+
+static inline int forb_request_cmp(const CORBA_unsigned_long *a,
+                                  const CORBA_unsigned_long *b)
+{
+       return (*a<*b) ? -1 :
+               ((*a>*b) ? +1 :
+                0);
+}
+
+GAVL_CUST_NODE_INT_IMP(forb_request_nolock /* cust_prefix */,
+                      forb_t /* cust_root_t */,
+                      forb_request_t /* cust_item_t */,
+                      CORBA_unsigned_long /* cust_key_t */,
+                      requests /* cust_root_node */,
+                      node /* cust_item_node */,
+                      request_id /* cust_item_key */,
+                      forb_request_cmp/* cust_cmp_fnc */);
+
+/** 
+ * Initializes @a req structure for sending new request to object @a obj.
+ * 
+ * @param req Request structure to initialize
+ * @param obj Destination object
+ *
+ * @return Zero on success, FOSA error code on error.
+ */
+int
+forb_request_init(forb_request_t *req, forb_object obj)
+{
+       int ret = 0;
+       forb_t *forb = forb_object_to_forb(obj);
+       CORBA_boolean bret;
+
+       memset(req, 0, sizeof(*req));
+       req->obj = obj;
+
+       fosa_mutex_lock(&forb->request_id_mutex);
+       req->request_id = forb->request_id++;
+       fosa_mutex_unlock(&forb->request_id_mutex);
+
+       FORB_CDR_codec_init_static(&req->cdr_request, obj->orb);
+       bret = FORB_CDR_buffer_init(&req->cdr_request, 4096-8, forb_iop_MESSAGE_HEADER_SIZE);
+       if (bret == CORBA_FALSE) {
+               return FOSA_ENOMEM;
+       }
+       
+       ret = forb_syncobj_init(&req->reply_ready, 0);
+       return ret;
+}
+
+void
+forb_request_destroy(forb_request_t *req)
+{
+       forb_t *forb = forb_object_to_forb(req->obj);
+
+       forb_request_delete(forb, req);
+       FORB_CDR_codec_release_buffer(&req->cdr_request);
+       forb_syncobj_destroy(&req->reply_ready);
+}
+
+void
+forb_request_signal_reply(forb_request_t *req)
+{
+       forb_syncobj_signal(&req->reply_ready); 
+}
+
+void
+forb_request_wait_for_reply(forb_request_t *req)
+{
+       fosa_abs_time_t timeout;
+       int ret;
+
+       /* FIXME: What is the appropriate length for timeout? Maybe,
+        * we can specify timeout in forb_env, but since it is
+        * out-direction parameter, we cannot distinguish between
+        * initialized and uninitialized env.timeout.  */
+       fosa_clock_get_time(FOSA_CLOCK_ABSOLUTE, &timeout);
+       timeout = fosa_abs_time_incr(timeout,
+                                    fosa_msec_to_rel_time(10000));
+
+       ret = forb_syncobj_timedwait(&req->reply_ready, &timeout);
+
+       if (ret == ETIMEDOUT) {
+               req->env->major = FORB_EX_TIMEOUT;
+       } else if (ret) {
+               req->env->major = FORB_EX_INTERNAL;
+       }
+}
+
+void
+forb_request_signal_processed(forb_request_t *req)
+{
+       /* Signal, that we are done */
+       forb_syncobj_signal(req->reply_processed);
+}
+
diff --git a/src/forb/src/request.h b/src/forb/src/request.h
new file mode 100644 (file)
index 0000000..1b1d0fc
--- /dev/null
@@ -0,0 +1,138 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+#ifndef REQUEST_H
+#define REQUEST_H
+
+/**
+ * @file   request.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 15:50:30 2008
+ * 
+ * @brief  Data type and functions for manipulation with requests.
+ * 
+ * 
+ */
+
+
+#include <forb.h>
+#include <forb/cdr.h>
+#include <forb/basic_types.h>
+#include <forb/syncobj.h>
+#include <ul_gavlcust.h>
+#include <forb/forb-internal.h>
+
+
+
+/**
+ * Helper structure for sending ORB requests.
+ *
+ * Its purpose is to match incomming reply messages to previously sent
+ * requests. It is allocated in stub's stack and during waiting for
+ * reply is stored in forb_t::requests tree.
+ * 
+ */
+struct forb_request {
+       CORBA_unsigned_long request_id; /**< Numeric ID of this request. Used to match replies agains this request. */
+       FORB_CDR_Codec cdr_request;     /**< Buffer for the request serialization. */
+       FORB_CDR_Codec *cdr_reply;      /**< Buffer with received reply. */
+       gavl_node_t node;       /**< forb_t::requests node */
+       forb_object obj;        /**< Object being requested. */
+       struct forb_env *env;   /**< Where to store exception returned in reply */
+       forb_syncobj_t reply_ready; /**< Synchronization object for waiting for reply */
+       forb_syncobj_t *reply_processed; /**< Synchronization object for receiver thread to wait for stub. */
+};
+
+typedef struct forb_request forb_request_t;
+
+/* Declaration of AVL tree for storing sent requests. */
+GAVL_CUST_NODE_INT_DEC(forb_request_nolock /* cust_prefix */,
+                      forb_t /* cust_root_t */,
+                      forb_request_t /* cust_item_t */,
+                      CORBA_unsigned_long /* cust_key_t */,
+                      requests /* cust_root_node */,
+                      node /* cust_item_node */,
+                      request_id /* cust_item_key */,
+                      forb_request_cmp/* cust_cmp_fnc */);
+
+static inline int
+forb_request_insert(forb_t *forb, forb_request_t *req)
+{
+       int ret;
+       fosa_mutex_lock(&forb->request_mutex);
+       ret = forb_request_nolock_insert(forb, req);
+       fosa_mutex_unlock(&forb->request_mutex);
+       return ret;
+}
+
+static inline void
+forb_request_delete(forb_t *forb, forb_request_t *req)
+{
+       fosa_mutex_lock(&forb->request_mutex);
+       forb_request_nolock_delete(forb, req);
+       fosa_mutex_unlock(&forb->request_mutex);
+}
+
+static inline forb_request_t *
+forb_request_find(forb_t *forb, CORBA_unsigned_long *request_id)
+{
+       forb_request_t *ret;
+       fosa_mutex_lock(&forb->request_mutex);
+       ret = forb_request_nolock_find(forb, request_id);
+       fosa_mutex_unlock(&forb->request_mutex);
+       return ret;
+}
+
+int
+forb_request_init(forb_request_t *req, forb_object obj);
+void
+forb_request_destroy(forb_request_t *req);
+void
+forb_request_wait_for_reply(forb_request_t *req);
+void
+forb_request_signal_processed(forb_request_t *req);
+
+#endif
diff --git a/src/forb/src/server_id.h b/src/forb/src/server_id.h
new file mode 100644 (file)
index 0000000..17effdc
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef FORB_SERVER_ID_H
+#define FORB_SERVER_ID_H
+
+#include <forb/uuid.h>
+#include <forb/types.h>
+
+void
+forb_server_id_init(forb_server_id *serer);
+
+/** 
+ * Compares to server IDs.
+ * 
+ * @param id1 
+ * @param id2 
+ * 
+ * @return -1, 0 or 1 if the @a id1 is less, equal on greated to @a id2 respectively.
+ */
+static inline int forb_server_id_cmp(const forb_server_id *id1, const forb_server_id *id2)
+{
+       return memcmp(id1, id2, sizeof(forb_server_id));
+}
+
+/** 
+ * Converts a server ID to string.
+ * 
+ * @param dest Where to store the converted string.
+ * @param server_id Server ID to convert.
+ * @param n The size of @a dest memory buffer.
+ * 
+ * @return Same value as @a dest.
+ */
+static inline char *
+forb_server_id_to_string(char *dest, const forb_server_id *server_id, size_t n)
+{
+       return forb_uuid_to_string(dest, (forb_uuid_t*)server_id->uuid, n);
+}
+
+/** 
+ * Initializes server ID from string.
+ * 
+ * @param server_id Initialized server ID.
+ * @param string String form of server ID.
+ * 
+ * @return Same value as @a server_id.
+ */
+static inline forb_server_id * 
+forb_server_id_from_string(forb_server_id *server_id, const char *string)
+{
+       return (forb_server_id *)forb_uuid_from_string((forb_uuid_t*)&server_id->uuid, string);
+}
+
+
+static inline bool
+forb_server_id_empty(const forb_server_id *server_id)
+{
+       unsigned i;
+       for (i=0; i<sizeof(server_id); i++) {
+               if (server_id->uuid[i] != 0)
+                       return false;
+       }
+       return true;
+}
+
+#endif
diff --git a/src/forb/src/sha1.c b/src/forb/src/sha1.c
new file mode 100644 (file)
index 0000000..a490d26
--- /dev/null
@@ -0,0 +1,269 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/*
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+  A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+  84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+  34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+/* #define LITTLE_ENDIAN * This should be #define'd if true. */
+/* #define SHA1HANDSOFF * Copies data before messing with it. */
+
+/* #include <stdio.h> */
+#include <inttypes.h>
+#include <string.h>
+#include "sha1.h"
+
+/* Extract endinaning from glibc */
+#include <endian.h>
+#undef LITTLE_ENDIAN
+#ifdef __BYTE_ORDER
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define LITTLE_ENDIAN
+#endif
+#endif
+
+void SHA1Transform(uint32_t state[5], uint8_t buffer[64]);
+void SHA1Init(SHA1_CTX* context);
+void SHA1Update(SHA1_CTX* context, uint8_t* data, unsigned int len);
+void SHA1Final(uint8_t digest[20], SHA1_CTX* context);
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#ifdef LITTLE_ENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+    |(rol(block->l[i],8)&0x00FF00FF))
+#else
+#define blk0(i) block->l[i]
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+    ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void SHA1Transform(uint32_t state[5], uint8_t buffer[64])
+{
+uint32_t a, b, c, d, e;
+typedef union {
+    uint8_t c[64];
+    uint32_t l[16];
+} CHAR64LONG16;
+CHAR64LONG16* block;
+#ifdef SHA1HANDSOFF
+static uint8_t workspace[64];
+    block = (CHAR64LONG16*)workspace;
+    memcpy(block, buffer, 64);
+#else
+    block = (CHAR64LONG16*)buffer;
+#endif
+    /* Copy context->state[] to working vars */
+    a = state[0];
+    b = state[1];
+    c = state[2];
+    d = state[3];
+    e = state[4];
+    /* 4 rounds of 20 operations each. Loop unrolled. */
+    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+    /* Add the working vars back into context.state[] */
+    state[0] += a;
+    state[1] += b;
+    state[2] += c;
+    state[3] += d;
+    state[4] += e;
+    /* Wipe variables */
+    a = b = c = d = e = 0;
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void SHA1Init(SHA1_CTX* context)
+{
+    /* SHA1 initialization constants */
+    context->state[0] = 0x67452301;
+    context->state[1] = 0xEFCDAB89;
+    context->state[2] = 0x98BADCFE;
+    context->state[3] = 0x10325476;
+    context->state[4] = 0xC3D2E1F0;
+    context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void SHA1Update(SHA1_CTX* context, uint8_t* data, unsigned int len)
+{
+unsigned int i, j;
+
+    j = (context->count[0] >> 3) & 63;
+    if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
+    context->count[1] += (len >> 29);
+    if ((j + len) > 63) {
+        memcpy(&context->buffer[j], data, (i = 64-j));
+        SHA1Transform(context->state, context->buffer);
+        for ( ; i + 63 < len; i += 64) {
+            SHA1Transform(context->state, &data[i]);
+        }
+        j = 0;
+    }
+    else i = 0;
+    memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/* Add padding and return the message digest. */
+
+void SHA1Final(uint8_t digest[20], SHA1_CTX* context)
+{
+unsigned long i, j;
+uint8_t finalcount[8];
+
+    for (i = 0; i < 8; i++) {
+        finalcount[i] = (uint8_t)((context->count[(i >= 4 ? 0 : 1)]
+         >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
+    }
+    SHA1Update(context, (uint8_t *)"\200", 1);
+    while ((context->count[0] & 504) != 448) {
+        SHA1Update(context, (uint8_t *)"\0", 1);
+    }
+    SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
+    for (i = 0; i < 20; i++) {
+        digest[i] = (uint8_t)
+         ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+    }
+    /* Wipe variables */
+    i = j = 0;
+    memset(context->buffer, 0, 64);
+    memset(context->state, 0, 20);
+    memset(context->count, 0, 8);
+    memset(&finalcount, 0, 8);
+#ifdef SHA1HANDSOFF  /* make SHA1Transform overwrite it's own static vars */
+    SHA1Transform(context->state, context->buffer);
+#endif
+}
+
+
+/*************************************************************/
+
+#if 0
+#include <stdio.h>
+
+int main(int argc, char** argv)
+{
+int i, j;
+SHA1_CTX context;
+uint8_t digest[20], buffer[16384];
+FILE* file;
+
+    if (argc > 2) {
+        puts("Public domain SHA-1 implementation - by Steve Reid <steve@edmweb.com>");
+        puts("Produces the SHA-1 hash of a file, or stdin if no file is specified.");
+        exit(0);
+    }
+    if (argc < 2) {
+        file = stdin;
+    }
+    else {
+        if (!(file = fopen(argv[1], "rb"))) {
+            fputs("Unable to open file.", stderr);
+            exit(-1);
+        }
+    } 
+    SHA1Init(&context);
+    while (!feof(file)) {  /* note: what if ferror(file) */
+        i = fread(buffer, 1, 16384, file);
+        SHA1Update(&context, buffer, i);
+    }
+    SHA1Final(digest, &context);
+    fclose(file);
+    for (i = 0; i < 5; i++) {
+        for (j = 0; j < 4; j++) {
+            printf("%02X", digest[i*4+j]);
+        }
+        putchar(' ');
+    }
+    putchar('\n');
+    exit(0);
+}
+#endif
diff --git a/src/forb/src/sha1.h b/src/forb/src/sha1.h
new file mode 100644 (file)
index 0000000..e76f3dc
--- /dev/null
@@ -0,0 +1,64 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/*
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+*/
+
+#include <inttypes.h>
+
+typedef struct {
+    unsigned long count[2];
+    uint32_t state[5];
+    uint8_t buffer[64];
+} SHA1_CTX;
+
+void SHA1Transform(uint32_t state[5], uint8_t buffer[64]);
+void SHA1Init(SHA1_CTX* context);
+void SHA1Update(SHA1_CTX* context, uint8_t* data, unsigned int len);
+void SHA1Final(uint8_t digest[20], SHA1_CTX* context);
diff --git a/src/forb/src/syncobj.c b/src/forb/src/syncobj.c
new file mode 100644 (file)
index 0000000..7efb289
--- /dev/null
@@ -0,0 +1,202 @@
+//----------------------------------------------------------------------
+//  Copyright (C) 2006 - 2007 by the FRESCOR consortium:
+//
+//    Universidad de Cantabria,              SPAIN
+//    University of York,                    UK
+//    Scuola Superiore Sant'Anna,            ITALY
+//    Kaiserslautern University,             GERMANY
+//    Univ. Politecnica  Valencia,           SPAIN
+//    Czech Technical University in Prague,  CZECH REPUBLIC
+//    ENEA                                   SWEDEN
+//    Thales Communication S.A.              FRANCE
+//    Visual Tools S.A.                      SPAIN
+//    Rapita Systems Ltd                     UK
+//    Evidence                               ITALY
+//
+//    See http://www.frescor.org
+//
+//        The FRESCOR project (FP6/2005/IST/5-034026) is funded
+//        in part by the European Union Sixth Framework Programme
+//        The European Union is not liable of any use that may be
+//        made of this code.
+//
+//
+//  based on previous work (FSF) done in the FIRST project
+//
+//   Copyright (C) 2005  Mälardalen University, SWEDEN
+//                       Scuola Superiore S.Anna, ITALY
+//                       Universidad de Cantabria, SPAIN
+//                       University of York, UK
+//
+// This file is part of DTM (Distributed Transaction Manager)
+//
+// DTM is free software; you can redistribute it and/or modify it
+// under terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option) any
+// later version.  DTM is distributed in the hope that 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 DTM; see file
+// COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
+// Cambridge, MA 02139, USA.
+//
+// As a special exception, including DTM header files in a file,
+// instantiating DTM generics or templates, or linking other files
+// with DTM objects to produce an executable application, does not
+// by itself cause the resulting executable application to be covered
+// by the GNU General Public License. This exception does not
+// however invalidate any other reasons why the executable file might be
+// covered by the GNU Public License.
+// -----------------------------------------------------------------------
+
+/**
+ * @file 
+ *
+ * @brief Synchronization object used in FORB
+ *
+ * @author
+ *      Michael Gonzalez Harbour <mgh@unican.es>
+ *      Michal Sojka <sojkam1@fel.cvut.cz>
+ *      Daniel Sangorrin <daniel.sangorrin@unican.es>
+ *
+ * @comments
+ *
+ * This module contains the definition of the data object and operations to
+ * create a pool of objects, obtain the id of an unused object, wait upon it,
+ * signal it, and finish using it.
+ *
+ * @license
+ *
+ * See the COPYING file in the FORB's root directory
+ *
+ */
+
+#include "syncobj.h"
+
+/**
+ * Initializes the synchronization object.
+ *
+ * @return Zero on success, FOSA error code on error.
+ **/
+
+int forb_syncobj_init(forb_syncobj_t *syncobj, int ceiling)
+{
+        int err;
+
+       err = fosa_cond_init(&syncobj->cond);
+        if (err != 0) return err;
+
+        syncobj->is_work_done = false;
+
+        err = fosa_mutex_init(&syncobj->mutex, ceiling);
+        if (err != 0) return err;
+
+        return 0;
+}
+
+/**
+ * Destroys all resources related to the synchronization object.
+ **/
+
+int forb_syncobj_destroy(forb_syncobj_t *syncobj)
+{
+        int err;
+
+       err = fosa_cond_destroy(&syncobj->cond);
+       if (err != 0) return err;
+       
+       err = fosa_mutex_destroy(&syncobj->mutex);
+       if (err != 0) return err;
+
+        return 0;
+}
+
+/**
+ * Signal the synchronization object.
+ **/
+
+int forb_syncobj_signal(forb_syncobj_t *syncobj)
+{
+        int err;
+
+        err = fosa_mutex_lock(&syncobj->mutex);
+        if (err != 0) return err;
+
+       syncobj->is_work_done = true;
+
+       err = fosa_cond_signal(&syncobj->cond);
+       if (err != 0) goto locked_error;
+
+        err = fosa_mutex_unlock(&syncobj->mutex);
+        if (err != 0) return err;
+
+        return 0;
+
+locked_error:
+        fosa_mutex_unlock(&syncobj->mutex);
+        return err;
+}
+
+static void
+syncobj_cleanup(void *syncobj)
+{
+       forb_syncobj_t *s = syncobj;
+       fosa_mutex_unlock(&s->mutex);
+}
+
+/**
+ * Wait on the synchronization object.
+ **/
+
+int forb_syncobj_wait(forb_syncobj_t *syncobj)
+{
+        int err = 0;
+
+        err = fosa_mutex_lock(&syncobj->mutex);
+        if (err != 0) return err;
+       pthread_cleanup_push(syncobj_cleanup, syncobj);
+
+       while (syncobj->is_work_done == false) {
+               err = fosa_cond_wait(&syncobj->cond,
+                                    &syncobj->mutex);
+               if (err != 0) goto locked_error;
+       }
+       
+       syncobj->is_work_done = false;
+
+locked_error:;
+       pthread_cleanup_pop(1);
+        return err;
+;
+}
+
+/**
+ * Wait on the synchronization object with a timeout.
+ *
+ * @return Zero on success, ETIMEDOUT on timeout or other FOSA error
+ * code on error.
+ **/
+
+int forb_syncobj_timedwait(forb_syncobj_t *syncobj,
+                          const struct timespec *abstime)
+{
+        int err = 0;
+
+        err = fosa_mutex_lock(&syncobj->mutex);
+        if (err != 0) return err;
+       pthread_cleanup_push(syncobj_cleanup, syncobj);
+
+        while (syncobj->is_work_done == false) {
+                err = fosa_cond_timedwait(&syncobj->cond,
+                                          &syncobj->mutex,
+                                          abstime);
+                if (err != 0) goto locked_error;
+        }
+
+        syncobj->is_work_done = false;
+
+locked_error:;
+       pthread_cleanup_pop(1);
+        return err;
+}
diff --git a/src/forb/src/syncobj.h b/src/forb/src/syncobj.h
new file mode 100644 (file)
index 0000000..6127858
--- /dev/null
@@ -0,0 +1,99 @@
+#ifndef SYNC_OBJ_H
+#define SYNC_OBJ_H
+
+//----------------------------------------------------------------------
+//  Copyright (C) 2006 - 2007 by the FRESCOR consortium:
+//
+//    Universidad de Cantabria,              SPAIN
+//    University of York,                    UK
+//    Scuola Superiore Sant'Anna,            ITALY
+//    Kaiserslautern University,             GERMANY
+//    Univ. Politecnica  Valencia,           SPAIN
+//    Czech Technical University in Prague,  CZECH REPUBLIC
+//    ENEA                                   SWEDEN
+//    Thales Communication S.A.              FRANCE
+//    Visual Tools S.A.                      SPAIN
+//    Rapita Systems Ltd                     UK
+//    Evidence                               ITALY
+//
+//    See http://www.frescor.org
+//
+//        The FRESCOR project (FP6/2005/IST/5-034026) is funded
+//        in part by the European Union Sixth Framework Programme
+//        The European Union is not liable of any use that may be
+//        made of this code.
+//
+//
+//  based on previous work (FSF) done in the FIRST project
+//
+//   Copyright (C) 2005  Mälardalen University, SWEDEN
+//                       Scuola Superiore S.Anna, ITALY
+//                       Universidad de Cantabria, SPAIN
+//                       University of York, UK
+//
+// This file is part of DTM (Distributed Transaction Manager)
+//
+// DTM is free software; you can redistribute it and/or modify it
+// under terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option) any
+// later version.  DTM is distributed in the hope that 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 DTM; see file
+// COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
+// Cambridge, MA 02139, USA.
+//
+// As a special exception, including DTM header files in a file,
+// instantiating DTM generics or templates, or linking other files
+// with DTM objects to produce an executable application, does not
+// by itself cause the resulting executable application to be covered
+// by the GNU General Public License. This exception does not
+// however invalidate any other reasons why the executable file might be
+// covered by the GNU Public License.
+// -----------------------------------------------------------------------
+
+/*!
+ * @file syncobj.h
+ *
+ * @brief Synchronization objects
+ *
+ * This module contains the definition of simple synchronization
+ * objects built on top FOSA condition variables.
+ *
+ * @author Michael Gonzalez Harbour <mgh@unican.es>
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @author Daniel Sangorrin <daniel.sangorrin@unican.es>
+ *
+ */
+
+#ifndef _SYNC_OBJ_H_
+#define _SYNC_OBJ_H_
+
+#include <fosa_mutexes_and_condvars.h>
+#include <time.h> /* for timespec */
+#include <fosa_opaque_types.h> /* for FOSA_ETIMEDOUT */
+
+/**
+ * Semaphore-like synchronization object build on top of FOSA's
+ * condition variables.
+ */
+typedef struct forb_syncobj {
+        bool is_work_done;
+        fosa_cond_t cond;
+        fosa_mutex_t mutex;
+} forb_syncobj_t;
+
+
+extern int forb_syncobj_init(forb_syncobj_t *syncobj, int ceiling);
+extern int forb_syncobj_destroy(forb_syncobj_t *syncobj);
+extern int forb_syncobj_signal(forb_syncobj_t *syncobj);
+extern int forb_syncobj_wait(forb_syncobj_t *syncobj);
+extern int forb_syncobj_timedwait(forb_syncobj_t *syncobj,
+                                 const struct timespec *abstime);
+#define FORB_ETIMEDOUT FOSA_ETIMEDOUT
+
+#endif // _SYNC_OBJ_H_
+
+
+#endif
diff --git a/src/forb/src/tests/Makefile b/src/forb/src/tests/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/src/forb/src/tests/Makefile.omk b/src/forb/src/tests/Makefile.omk
new file mode 100644 (file)
index 0000000..a81f884
--- /dev/null
@@ -0,0 +1,46 @@
+SUBDIRS = $(ALL_OMK_SUBDIRS)
+
+test_PROGRAMS += hello_inproc hello_remote test_proto_inet discovery   \
+               syncobj regobjref
+ifeq ($(CONFIG_FORB_PROTO_UNIX),y)
+test_PROGRAMS += test_proto_unix
+endif
+
+wvtest_PROGRAMS += sequence
+sequence_SOURCES = sequence.c
+sequence_CLIENT_IDL = sequence.idl
+sequence_LIBS = wvtest
+
+CFLAGS += -DTEST -DWVTEST_CONFIGURED
+INCLUDES += -I.
+
+lib_LOADLIBES = forb ulut fosa rt
+
+hello_inproc_SOURCES = hello_inproc.c hello_impl.c
+hello_inproc_CLIENT_IDL = hello.idl
+hello_inproc_SERVER_IDL = hello.idl
+
+hello_remote_SOURCES = hello_remote.c hello_impl.c
+hello_remote_CLIENT_IDL = hello.idl
+hello_remote_SERVER_IDL = hello.idl
+
+regobjref_SOURCES = regobjref.c hello_impl.c
+regobjref_CLIENT_IDL = hello.idl
+regobjref_SERVER_IDL = hello.idl
+
+include_GEN_HEADERS = hello.h
+
+# test_PROGRAMS += hello_client
+# hello_client_SOURCES = hello_client.c
+# hello_inproc_CLIENT_IDL = hello.idl
+
+# test_PROGRAMS += hello_server
+# hello_server_SOURCES = hello_server.c
+# hello_inproc_SERVER_IDL = hello.idl
+
+test_proto_unix_SOURCES = test_proto_unix.c
+test_proto_inet_SOURCES = test_proto_inet.c
+
+discovery_SOURCES = discovery.c
+
+syncobj_SOURCES = test_syncobj.c
diff --git a/src/forb/src/tests/discovery.c b/src/forb/src/tests/discovery.c
new file mode 100644 (file)
index 0000000..48b0a08
--- /dev/null
@@ -0,0 +1,118 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   discovery.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 19:05:27 2008
+ * 
+ * @brief  Test for correctness of peer discovery protocol
+ * 
+ * Multiple FORB obejcts are created and it is tested whether every
+ * FORB automatically discovers the other FORBs.
+ */
+
+#include <stdbool.h>
+#include <forb.h>
+#include <forb/object.h>
+#include <forb/forb-internal.h>
+#include <forb/config.h>
+#include <unistd.h>
+#include "../proto.h"
+#include "../discovery.h"
+#include <error.h>
+#include <fosa.h>
+#include <stdio.h>
+
+#define NUM_ORBS 5
+
+#if !CONFIG_FORB_PROTO_UNIX && !CONFIG_FORB_PROTO_INET_DEFAULT
+#error This test should only work if there is some local protocol enabled.
+#endif
+
+int main(int argc, char *argv[])
+{
+       forb_orb orb[NUM_ORBS];
+       int i;
+       bool all_peers_found = true;
+       fosa_abs_time_t timeout;
+
+       for (i=0; i<NUM_ORBS; i++) {
+               orb[i] = forb_init(&argc, &argv, NULL);
+               if (!orb[i]) {
+                       error(1, errno, "Orb no. %d was not created\n", i);
+               }
+       }
+
+       fosa_clock_get_time(FOSA_CLOCK_ABSOLUTE, &timeout);
+       timeout = fosa_abs_time_incr(timeout,
+                                    fosa_msec_to_rel_time(1000));
+
+       /* Check whether all the peers are found */
+       for (i=0; i<NUM_ORBS && all_peers_found; i++) {
+               int j;
+               forb_peer_t *peer;
+               for (j=0; j<NUM_ORBS && all_peers_found; j++) {
+                       if (i==j) continue;
+                       peer = forb_peer_find_timed(forb_data(orb[i]),
+                                                   &forb_data(orb[j])->server_id,
+                                                   &timeout);
+
+                       all_peers_found &= (peer != NULL);
+                       if (!all_peers_found) {
+                               char id[100];
+                               error(1, 0, "Peer %d (%s) was not discovered on node %d",
+                                     j, forb_uuid_to_string(id,
+                                                            (forb_uuid_t*)&forb_data(orb[i])->server_id.uuid,
+                                                            sizeof(id)),
+                                     i);
+                       }
+               }
+       }
+
+       printf("OK\n");
+       return 0;
+}
diff --git a/src/forb/src/tests/hello.idl b/src/forb/src/tests/hello.idl
new file mode 100644 (file)
index 0000000..6bcb4d6
--- /dev/null
@@ -0,0 +1,12 @@
+/**
+ * @file   hello.idl
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 19:07:24 2008
+ * 
+ * @brief  Definition of hello interface
+ * 
+ * 
+ */
+interface hello {
+       void message(in string msg);
+};
diff --git a/src/forb/src/tests/hello_impl.c b/src/forb/src/tests/hello_impl.c
new file mode 100644 (file)
index 0000000..8f4ffdf
--- /dev/null
@@ -0,0 +1,73 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   hello_impl.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 19:07:44 2008
+ * 
+ * @brief Implementation of hello interfaces shared between multiple
+ * tests.
+ * 
+ * 
+ */
+
+#include <hello.h>
+#include <stdio.h>
+
+static void message(hello _obj, const CORBA_char * msg, CORBA_Environment *ev)
+{
+       printf("Hello object received: %s\n", msg);
+}
+
+static const struct forb_hello_impl impl = {
+       message
+};
+
+forb_object hello_impl_initialize(forb_orb orb)
+{
+       return forb_hello_new(orb, &impl, NULL);
+}
diff --git a/src/forb/src/tests/hello_impl.h b/src/forb/src/tests/hello_impl.h
new file mode 100644 (file)
index 0000000..677ca8b
--- /dev/null
@@ -0,0 +1,64 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   hello_impl.h
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 19:08:20 2008
+ * 
+ * @brief  Interface to the common hello implementation
+ * 
+ * 
+ */
+
+#ifndef HELLO_IMPL_H
+#define HELLO_IMPL_H
+
+#include <hello.h>
+
+forb_object hello_impl_initialize(forb_orb orb);
+
+#endif
diff --git a/src/forb/src/tests/hello_inproc.c b/src/forb/src/tests/hello_inproc.c
new file mode 100644 (file)
index 0000000..701c908
--- /dev/null
@@ -0,0 +1,83 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   hello_inproc.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 19:08:46 2008
+ * 
+ * @brief  Test of in-process invocation
+ * 
+ * 
+ */
+
+#include <hello.h>
+#include "hello_impl.h"
+#include <forb.h>
+#include <error.h>
+
+int main(int argc, char *argv[])
+{
+       forb_orb orb;
+       hello hobj;
+       struct forb_env env;
+       struct forb_init_attr attr = {
+               .orb_id = "hello_inproc"
+       };
+               
+       orb = forb_init(&argc, &argv, &attr);
+       if (!orb) {
+               error(1, errno, "Cannot initialize FORB");
+       }
+       hobj = hello_impl_initialize(orb);
+
+       hello_message(hobj, "Hello world!", &env);
+       if (forb_exception_occurred(&env)) {
+               error(1, 0, "FORB exception %d", env.major);
+       }
+               
+       return 0;       
+}
diff --git a/src/forb/src/tests/hello_remote.c b/src/forb/src/tests/hello_remote.c
new file mode 100644 (file)
index 0000000..aa6f726
--- /dev/null
@@ -0,0 +1,142 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   hello_remote.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Thu Sep 25 16:05:27 2008
+ * 
+ * @brief  Test of remote invocation.
+ *
+ * In this test, two FORBs are created, one for running the server of
+ * hello interface and the second for running the client code. Since
+ * the client and server are registered in different FORBs, remote
+ * communication is used even if the two FORBs share the same
+ * memory. This way we can easily test remote communication without
+ * writing separate applications for client and server.
+ */
+
+#include <hello.h>
+#include "hello_impl.h"
+#include <forb.h>
+#include <error.h>
+#include <fosa.h>
+#include <forb/executor.h>
+
+int argc_g;
+char **argv_g;
+
+void *server_thread(void *arg)
+{
+       hello hobj = arg;
+
+       forb_execute_object(hobj);
+       return NULL;
+}
+
+char *start_server()
+{
+       forb_orb orb;
+       hello hobj;
+
+       fosa_thread_id_t tid;
+       struct forb_init_attr attr = {
+               .orb_id = "hello_remote_server"
+       };
+               
+       orb = forb_init(&argc_g, &argv_g, &attr);
+       if (!orb) {
+               error(1, errno, "Cannot initialize FORB for server");
+       }
+       hobj = hello_impl_initialize(orb);
+       fosa_thread_create(&tid, NULL, server_thread, hobj);
+
+       return forb_object_to_string(hobj);
+}
+
+
+
+void client(void *arg)
+{
+       forb_orb orb;
+       hello hobj;
+       struct forb_env env;
+       char *objref = arg;
+       struct forb_init_attr attr = {
+               .orb_id = "hello_remote_client"
+       };
+               
+       orb = forb_init(&argc_g, &argv_g, &attr);
+       if (!orb) {
+               error(1, errno, "Cannot initialize FORB for server");
+       }
+
+       hobj = forb_string_to_object(orb, objref);
+       if (!hobj) {
+               error(1, 0, "Cannot create object reference from the string (%s)\n", objref);
+       }
+
+       hello_message(hobj, "Hello world!", &env);
+       if (forb_exception_occurred(&env)) {
+               error(1, 0, "FORB exception %d", env.major);
+       }
+
+}
+
+int main(int argc, char *argv[])
+{
+
+       char *objref_str;
+       
+       argc_g = argc;
+       argv_g = argv;
+
+       objref_str = start_server();
+
+       client(objref_str);
+               
+       return 0;       
+}
diff --git a/src/forb/src/tests/object_to_string/Makefile b/src/forb/src/tests/object_to_string/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/src/forb/src/tests/object_to_string/Makefile.omk b/src/forb/src/tests/object_to_string/Makefile.omk
new file mode 100644 (file)
index 0000000..f8ca37d
--- /dev/null
@@ -0,0 +1,8 @@
+test_PROGRAMS = obj2str
+obj2str_SOURCES = obj2str.c
+obj2str_SERVER_IDL = interface.idl
+
+CFLAGS += -I.
+
+
+lib_LOADLIBES = forb ulut fosa rt
diff --git a/src/forb/src/tests/object_to_string/interface.idl b/src/forb/src/tests/object_to_string/interface.idl
new file mode 100644 (file)
index 0000000..6661304
--- /dev/null
@@ -0,0 +1,3 @@
+interface i {
+       void method();
+};
diff --git a/src/forb/src/tests/object_to_string/obj2str.c b/src/forb/src/tests/object_to_string/obj2str.c
new file mode 100644 (file)
index 0000000..8fe6545
--- /dev/null
@@ -0,0 +1,103 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   obj2str.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 19:10:23 2008
+ * 
+ * @brief  Test for forb_object_to_string() and forb_string_to_object()
+ * 
+ * 
+ */
+
+#include <forb.h>
+#include <stdio.h>
+#include "interface.h"
+#include <error.h>
+#include <string.h>
+
+struct forb_i_impl i_impl =  { NULL };
+
+int main(int argc, char *argv[])
+{
+       forb_object orb, obj, obj2;
+       char *str, *str2;
+       struct forb_init_attr attr = {
+               .orb_id = "obj2str"
+       };
+               
+       orb = forb_init(&argc, &argv, &attr);
+
+       obj = forb_i_new(orb, &i_impl, NULL);
+       if (!obj) {
+               error(1, errno, "Object was not created");
+       }
+
+       str = forb_object_to_string(obj);
+       if (str) {
+               printf("Object reference1: %s\n", str);
+       } else {
+               return 1;
+       }
+
+       obj2 = forb_string_to_object(orb, str);
+
+       str2 = forb_object_to_string(obj2);
+       if (str) {
+               printf("Object reference2: %s\n", str2);
+       } else {
+               return 1;
+       }
+
+       if (strcmp(str, str2) != 0) 
+               error(1, 0, "Object references should be the same");
+       
+       forb_free(str);
+       forb_free(str2);
+
+       return 0;
+}
diff --git a/src/forb/src/tests/objref/Makefile b/src/forb/src/tests/objref/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/src/forb/src/tests/objref/Makefile.omk b/src/forb/src/tests/objref/Makefile.omk
new file mode 100644 (file)
index 0000000..a4e580e
--- /dev/null
@@ -0,0 +1,9 @@
+test_PROGRAMS = objref
+
+lib_LOADLIBES = forb ulut fosa rt
+
+objref_SOURCES = objref.c
+objref_CLIENT_IDL = objref.idl
+objref_SERVER_IDL = objref.idl
+
+INCLUDES += -I$(USER_OBJS_DIR)
diff --git a/src/forb/src/tests/objref/objref.c b/src/forb/src/tests/objref/objref.c
new file mode 100644 (file)
index 0000000..f16058a
--- /dev/null
@@ -0,0 +1,172 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   objref.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Thu Oct  2 15:32:17 2008
+ * 
+ * @brief  Test for passing object references as method parameters
+ *
+ * In this test a client calls server's method call_me_back(), which
+ * takes a client object reference as parameter. The server then
+ * invokes the callback() method on the received object reference.
+ * 
+ */
+
+#include <forb.h>
+#include <error.h>
+#include <fosa.h>
+#include <forb/executor.h>
+#include "objref.h"
+#include <stdio.h>
+#include <stdbool.h>
+
+int argc_g;
+char **argv_g;
+
+static void call_me_back(server _obj, const client obj, CORBA_Environment *ev)
+{
+       CORBA_Environment env;
+       printf("Server called\n");
+       client_callback(obj, &env);
+}
+
+static const struct forb_server_impl server_impl = {
+       .call_me_back = call_me_back
+};
+
+
+void *server_thread(void *arg)
+{
+       server s = arg;
+       forb_execute_object(s);
+       return NULL;
+}
+
+char *start_server()
+{
+       forb_orb orb;
+       server s;
+       fosa_thread_id_t tid;
+       struct forb_init_attr attr = {
+               .orb_id = "objref_server"
+       };
+               
+       orb = forb_init(&argc_g, &argv_g, &attr);
+       s = forb_server_new(orb, &server_impl, NULL);
+       fosa_thread_create(&tid, NULL, server_thread, s);
+
+       return forb_object_to_string(s);
+}
+
+unsigned callback_called = 0;
+
+static void callback(client _obj, CORBA_Environment *ev)
+{
+       callback_called++;
+       printf("Client callback called %d times\n", callback_called);
+}
+
+static const struct forb_client_impl client_impl = {
+       .callback = callback
+};
+
+void *client_thread(void *arg)
+{
+       client c = arg;
+       forb_execute_object(c);
+       return NULL;
+}
+
+
+void start_client(void *arg)
+{
+       char *objref = arg;
+       forb_orb orb;
+       server serv;
+       client me;
+       struct forb_env env;
+       fosa_thread_id_t tid;
+       struct forb_init_attr attr = {
+               .orb_id = "objref_client"
+       };
+               
+       orb = forb_init(&argc_g, &argv_g, &attr);
+
+       me = forb_client_new(orb, &client_impl, NULL);
+       fosa_thread_create(&tid, NULL, client_thread, me);
+
+       serv = forb_string_to_object(orb, objref);
+       if (!serv) {
+               error(1, 0, "Cannot create object reference from the string (%s)\n", objref);
+       }
+
+       server_call_me_back(serv, me, &env);
+       if (forb_exception_occurred(&env)) {
+               error(1, 0, "FORB exception %d", env.major);
+       }
+
+       forb_object_release(me);
+}
+
+int main(int argc, char *argv[])
+{
+
+       char *objref_str;
+
+       argc_g = argc;
+       argv_g = argv;
+       
+       objref_str = start_server();
+
+       start_client(objref_str);
+
+       if (callback_called == 0) {
+               error(1, 0, "Callback was not called");
+       }
+       return 0;       
+}
diff --git a/src/forb/src/tests/objref/objref.idl b/src/forb/src/tests/objref/objref.idl
new file mode 100644 (file)
index 0000000..24d6e66
--- /dev/null
@@ -0,0 +1,7 @@
+interface client {
+       void callback();
+};
+
+interface server {
+       void call_me_back(in client obj);
+};
diff --git a/src/forb/src/tests/regobjref.c b/src/forb/src/tests/regobjref.c
new file mode 100644 (file)
index 0000000..814d1ae
--- /dev/null
@@ -0,0 +1,135 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   regobjref.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sat Oct 11 21:12:09 2008
+ * 
+ * @brief  Test for forb_register_reference() and forb_resolve_reference()
+ *
+ * This test is the same as hello_remote.c. The only difference is
+ * that in hello_remote.c, the object reference of the server is
+ * passed as a string to the client, whereas here we use
+ * forb_register_reference()/forb_resolve_reference() for this.
+ */
+
+
+#include <hello.h>
+#include "hello_impl.h"
+#include <forb.h>
+#include <error.h>
+#include <fosa.h>
+#include <forb/executor.h>
+
+int argc_g;
+char **argv_g;
+
+void *server_thread(void *arg)
+{
+       hello hobj = arg;
+
+       forb_execute_object(hobj);
+       return NULL;
+}
+
+void start_server()
+{
+       forb_orb orb;
+       hello hobj;
+       int ret;
+
+       fosa_thread_id_t tid;
+       struct forb_init_attr attr = {
+               .orb_id = "hello_remote_server"
+       };
+
+       orb = forb_init(&argc_g, &argv_g, &attr);
+       hobj = hello_impl_initialize(orb);
+       fosa_thread_create(&tid, NULL, server_thread, hobj);
+
+       ret = forb_register_reference(hobj, "hello");
+       if (ret != 0) {
+               error(1, errno, "Cannot register reference to hello");
+       }
+}
+
+
+
+void client(void)
+{
+       forb_orb orb;
+       hello hobj;
+       struct forb_env env;
+       struct forb_init_attr attr = {
+               .orb_id = "hello_remote_client"
+       };
+               
+       orb = forb_init(&argc_g, &argv_g, &attr);
+
+       hobj = forb_resolve_reference(orb, "hello");
+       if (!hobj) {
+               error(1, errno, "Cannot resolve reference to hello server)");
+       }
+
+       hello_message(hobj, "Hello world!", &env);
+       if (forb_exception_occurred(&env)) {
+               error(1, 0, "FORB exception %d", env.major);
+       }
+}
+
+int main(int argc, char *argv[])
+{
+
+       argc_g = argc;
+       argv_g = argv;
+
+       start_server();
+
+       client();
+               
+       return 0;       
+}
diff --git a/src/forb/src/tests/sequence.c b/src/forb/src/tests/sequence.c
new file mode 100644 (file)
index 0000000..92c5448
--- /dev/null
@@ -0,0 +1,60 @@
+#include <forb.h>
+#include <wvtest.h>
+#include "sequence.h"
+
+int destructor_called;
+int sum_of_destructed;
+
+void destructor(int *elem)
+{
+       destructor_called++;
+       sum_of_destructed += *elem;
+}
+
+WVTEST_MAIN("sequence manipulation")
+{
+       CORBA_sequence_long *s;
+       int i, *e, foreach_retuned_sum = 0;
+       forb_sequence_alloc(s, 10);
+       WVPASS(s);
+       WVPASS(forb_sequence_allocated(s) == 10);
+       bool initialized_to_zero = true;
+       for (i=0; i<10; i++)
+               initialized_to_zero &= forb_sequence_elem(s, i) == 0;
+       WVPASS(initialized_to_zero);
+       WVPASS(forb_sequence_elem(s, 9) = 1);
+       WVPASS(forb_sequence_ensure_allocated(s, 1000) != NULL);
+       WVPASS(forb_sequence_allocated(s) == 1000);
+       WVPASS(forb_sequence_elem(s, 9) == 1);
+       WVPASS(forb_sequence_elem(s, 999) = 1);
+       CORBA_sequence_set_release(s, 1);
+       WVPASS(forb_sequence_length(s) == 0);
+       forb_sequence_free(s, destructor);
+       WVPASS(destructor_called == 0);
+
+       forb_sequence_alloc(s, 10);
+       WVPASS(s);
+       for (i=0; i<10; i++)
+               forb_sequence_elem(s, i) = i;
+       forb_sequence_length(s) = 10;
+       WVPASS(forb_sequence_length(s) == 10);
+       forb_sequence_free(s, destructor);
+       WVPASS(destructor_called == 0);
+
+       forb_sequence_alloc(s, 10);
+       WVPASS(s);
+       CORBA_sequence_set_release(s, 1);
+       for (i=0; i<10; i++)
+               forb_sequence_elem(s, i) = i;
+       forb_sequence_length(s) = 10;
+       WVPASS(forb_sequence_length(s) == 10);
+
+       forb_sequence_foreach(s, e) {
+               foreach_retuned_sum += *e;
+       }
+       WVPASS(foreach_retuned_sum == 45);
+       
+       forb_sequence_free(s, destructor);
+       WVPASS(destructor_called == 10);
+       WVPASS(sum_of_destructed == 45);
+}
diff --git a/src/forb/src/tests/sequence.idl b/src/forb/src/tests/sequence.idl
new file mode 100644 (file)
index 0000000..8ab9d63
--- /dev/null
@@ -0,0 +1,12 @@
+interface MyIface {
+       void MyOp();
+};
+
+struct SeqStruct {
+       sequence<long,10> MyLongs;
+       sequence<octet> MyOctets;
+//     sequence<MyIface> Interfaces; FIXME: This is bugy: sequence-common.c:124: undefined reference to `CORBA_sequence_Object_deserialize
+       sequence<sequence<short> > SeqSeq;
+};
+
+typedef sequence<string> MyStrings;
diff --git a/src/forb/src/tests/test_proto_inet.c b/src/forb/src/tests/test_proto_inet.c
new file mode 100644 (file)
index 0000000..25e8348
--- /dev/null
@@ -0,0 +1,147 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   test_proto_inet.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Thu Aug 28 15:20:37 2008
+ * 
+ * @brief Unit test for INET socket based FORB transport protocol
+ */
+
+#include <error.h>
+#include "../proto_inet.c"
+
+const char *msg = "Hello world!";
+const char *msg2 = "Blablabla!";
+#define NUM_PORTS 10
+
+char *timeout_msg = "timeout\n";
+
+void timeout(int signal)
+{
+       error(1, 0, timeout_msg);
+}
+
+int main()
+{
+       int len;
+       struct inet_addr addr[NUM_PORTS];
+       forb_port_t port[NUM_PORTS];
+       int i, ret;
+
+       signal(SIGALRM, timeout);
+
+       memset(port, 0, sizeof(port));
+
+       for (i=0; i<NUM_PORTS; i++) {
+               addr[i].addr.s_addr = htonl(0x7f000001+i);
+               if (forb_inet_port_init(&port[i].desc, addr[i].addr, 0) != 0)
+                       error(1, errno, "forb_inet_port_init(%d)", i);
+       }
+
+
+       /* Send from zeroth node to all others (starting from 1) */
+       for (i=1; i<NUM_PORTS; i++) {
+               forb_peer_t *peer;
+               char buf[100];
+               char tmsg[100];
+
+               peer = forb_peer_new();
+               peer->addr = port[i].desc.addr;
+               peer->port = &port[0];
+               
+               len = strlen(msg)+1;
+               ret = inet_send(peer, msg, len);
+
+               peer->addr = NULL;
+               forb_peer_put(peer);
+               if (ret != len)
+                       error(1, errno, "send(to %d) = %d", i, ret);
+
+               sprintf(tmsg, "Timeout when sending from 0 to %d\n", i);
+               timeout_msg = tmsg;
+               alarm(1);       /* timeout 1s */
+               ret = inet_recv(&port[i], buf, sizeof(buf));
+               alarm(0);
+               if (ret != len)
+                       error(1, errno, "recv(port[%d]) = %d", i, ret);
+
+               if (strcmp(msg, buf) != 0)
+                       error(1, errno, "port %d: received wrong data", i);
+
+       }
+
+       len = strlen(msg2)+1;
+       ret = inet_broadcast(&port[0], msg2, len);
+       if (ret != len) 
+               error(1, errno, "broadcast(port[0]) = %d should be %d", ret, len);
+       
+       for (i=0; i<NUM_PORTS; i++) {
+               char buf[100];
+               char tmsg[100];
+
+               sprintf(tmsg, "Timeout when receiving broadcast for port %d\n", i);
+               timeout_msg = tmsg;
+               alarm(1);
+               ret = inet_recv(&port[i], buf, sizeof(buf));
+               alarm(0);
+               if (ret != len) 
+                       error(1, errno, "broadcast recv(port[%d]) = %d should be %d (errno=%d)", i, ret, len, errno);
+               //printf("broadcast received: %s\n", buf);
+
+               if (strcmp(msg2, buf) != 0)
+                       error(1, errno, "port %d: broadcast received wrong data", i);
+
+       }
+
+       for (i=0; i<NUM_PORTS; i++) {
+               inet_port_destroy(&port[i]);
+       }
+
+       printf("OK\n");
+       return 0;
+}
diff --git a/src/forb/src/tests/test_proto_unix.c b/src/forb/src/tests/test_proto_unix.c
new file mode 100644 (file)
index 0000000..b920b19
--- /dev/null
@@ -0,0 +1,141 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   test_proto_unix.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Thu Aug 28 15:20:37 2008
+ * 
+ * @brief Unit test for UNIX socket based FORB transport protocol
+ */
+
+#include <error.h>
+#include "../proto_unix.c"
+
+const char *msg = "Hello world!";
+const char *msg2 = "Blablabla!";
+#define NUM_PORTS 10
+
+char *timeout_msg = "timeout\n";
+
+void timeout(int signal)
+{
+       error(1, 0, timeout_msg);
+}
+
+int main()
+{
+       int len;
+       forb_server_id server[NUM_PORTS];
+       forb_port_t port[NUM_PORTS];
+       int i, ret;
+
+       signal(SIGALRM, timeout);
+
+       for (i=0; i<NUM_PORTS; i++) {
+               forb_server_id_init(&server[i]);
+               if (forb_unix_port_init(&port[i].desc, &server[i]) != 0)
+                       error(1, errno, "forb_unix_port_init(%d)", i);
+       }
+
+
+       /* Send from zeroth node to all others (starting from 1) */
+       for (i=1; i<NUM_PORTS; i++) {
+               forb_peer_t peer;
+               char buf[100];
+               char tmsg[100];
+
+               peer.server_id = server[i];
+               peer.port = &port[0];
+               
+               len = strlen(msg)+1;
+               ret = unix_send(&peer, msg, len);
+               if (ret != len) 
+                       error(1, errno, "send(to %d) = %d", i, ret);
+
+               sprintf(tmsg, "Timeout when sending from 0 to %d\n", i);
+               timeout_msg = tmsg;
+               alarm(1);       /* timeout 1s */
+               ret = unix_recv(&port[i], buf, sizeof(buf));
+               alarm(0);
+               if (ret != len) 
+                       error(1, errno, "recv(port[%d]) = %d", i, ret);
+
+               if (strcmp(msg, buf) != 0)
+                       error(1, errno, "port %d: received wrong data", i);
+
+       }
+
+
+       len = strlen(msg2)+1;
+       ret = unix_broadcast(&port[0], msg2, len);
+       if (ret != len) 
+               error(1, errno, "broadcast(port[0]) = %d should be %d", ret, len);
+       
+       for (i=0; i<NUM_PORTS; i++) {
+               char buf[100];
+               char tmsg[100];
+
+               sprintf(tmsg, "Timeout when receiving broadcast for port %d\n", i);
+               timeout_msg = tmsg;
+               alarm(1);
+               ret = unix_recv(&port[i], buf, sizeof(buf));
+               alarm(0);
+               if (ret != len) 
+                       error(1, errno, "broadcast recv(port[%d]) = %d should be %d", i, ret, len);
+               //printf("broadcast received: %s\n", buf);
+
+               if (strcmp(msg2, buf) != 0)
+                       error(1, errno, "port %d: broadcast received wrong data", i);
+
+       }
+
+       for (i=0; i<NUM_PORTS; i++) {
+               unix_port_destroy(&port[i]);
+       }
+
+       return 0;
+}
diff --git a/src/forb/src/tests/test_syncobj.c b/src/forb/src/tests/test_syncobj.c
new file mode 100644 (file)
index 0000000..7e75a3c
--- /dev/null
@@ -0,0 +1,108 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   test_syncobj.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 19:09:45 2008
+ * 
+ * @brief  Test of synchronization obects
+ * 
+ * 
+ */
+
+#include <stdio.h>
+#include <forb/syncobj.h>
+#include <fosa.h>
+#include <error.h>
+
+forb_syncobj_t syncobj;
+
+void *thread(void *arg)
+{
+       fosa_abs_time_t now, hello_time;
+       fosa_rel_time_t hello_interval = fosa_msec_to_rel_time(2000);
+       int ret;
+
+       fosa_clock_get_time(FOSA_CLOCK_ABSOLUTE, &hello_time);
+       hello_time = fosa_abs_time_incr(hello_time, hello_interval);
+       ret = forb_syncobj_timedwait(&syncobj, &hello_time);
+       if (ret != 0) {
+               error(1, errno, "forb_syncobj_timedwait() error %d\n", ret);
+       }
+
+       fosa_clock_get_time(FOSA_CLOCK_ABSOLUTE, &now);
+       if (fosa_abs_time_smaller_or_equal(hello_time, now)) {
+               error(1, 0, "Should not wait longet than timeout\n");
+       }
+       return NULL;
+}
+
+int main()
+{
+       fosa_abs_time_t now, hello_time;
+       fosa_rel_time_t hello_interval = fosa_msec_to_rel_time(1000);
+       int ret;
+       fosa_thread_id_t tid;
+
+       forb_syncobj_init(&syncobj, 0);
+
+       fosa_clock_get_time(FOSA_CLOCK_ABSOLUTE, &hello_time);
+       hello_time = fosa_abs_time_incr(hello_time, hello_interval);
+
+       ret = forb_syncobj_timedwait(&syncobj, &hello_time);
+       if (ret != 0 && ret != FOSA_ETIMEDOUT) {
+               error(1, errno, "forb_syncobj_timedwait() error %d\n", ret);
+       }
+       fosa_clock_get_time(FOSA_CLOCK_ABSOLUTE, &now);
+       if (fosa_abs_time_smaller_or_equal(now, hello_time)) {
+               error(1, 0, "Wait less then timeout\n");
+       }
+
+       fosa_thread_create(&tid, NULL, thread, NULL);
+       forb_syncobj_signal(&syncobj);
+       return 0;
+}
diff --git a/src/forb/src/types.idl b/src/forb/src/types.idl
new file mode 100644 (file)
index 0000000..b4b4ea3
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+ * @file   types.idl
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Sun Oct 12 17:12:30 2008
+ * 
+ * @brief  Types used internally by FORB.
+ * 
+ * 
+ */
+
+module forb {
+       /**
+        * Object key for distinguishing different objects in a FORB.
+        */
+       typedef long long object_key;
+
+       typedef char uuid[8];
+
+       /**
+        * Server ID for identifying different FORBs.
+        *
+        * The ID is based on universal unique identifiers (UUID).
+        */
+
+       struct server_id {
+               uuid uuid;
+       };
+};
diff --git a/src/forb/src/ul_log_domains b/src/forb/src/ul_log_domains
new file mode 100755 (executable)
index 0000000..3723907
--- /dev/null
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+ARRAY_NAME=ul_log_domains_array
+
+DIRS=""
+
+while [ $# -gt 0 ] ; do
+  case "x${1}x" in
+    "x--helpx" | "x-hx" )
+      echo -e Usage: `basename ${0}`" [options] <srcdir> .."
+      echo -e "      -h --help       help"
+      echo -e "      -a --array      identifier of log domain array variable"
+      exit 0
+      ;;
+    "x--arrayx" | "x-ax" )
+      shift 1
+      ARRAY_NAME="${1}"
+      ;;
+    "x--"* )
+      echo "Unknown option"
+      exit 2
+      ;;
+    * )
+      DIRS="$DIRS ${1}"
+      ;;
+  esac
+  shift 1
+done
+
+DOMAINS=$( for d in $DIRS ; do find -L $d '(' -name '*.c' -o -name '*.cc' ')' -exec grep UL_LOG_CUST '{}' ';' | \
+  sed -n -e 's/^.*UL_LOG_CUST(\([^)]*\)).*$/\1/p' ; done | sort -u )
+
+#echo $DOMAINS
+
+#echo -e "#define UL_LOGL_DEF UL_LOGL_DEB\n"
+
+echo "/*"
+echo " * This is generated file, do not edit it directly."
+echo " * Take it from standard output of \"ul_log_domains\""
+echo " * script called in the top level project directory"
+echo " */"
+
+for i in $DOMAINS ; do
+  echo "ul_log_domain_t $i     = {UL_LOGL_DEF, \"$(echo -n $i | sed -n -e 's/ulogd_\(.*\)/\1/pg' )\"};"
+done
+
+echo
+echo "ul_log_domain_t *$ARRAY_NAME[] = {"
+
+for i in $DOMAINS ; do
+  echo "  &$i,"
+done
+
+echo "};"
diff --git a/src/forb/src/uuid.c b/src/forb/src/uuid.c
new file mode 100644 (file)
index 0000000..c601432
--- /dev/null
@@ -0,0 +1,155 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   uuid.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Tue Aug 26 09:17:31 2008
+ * 
+ * @brief  Unix version of UUID generator
+ * 
+ */
+#include <forb/uuid.h>
+#include <sys/time.h>
+#include <time.h>
+#include "sha1.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/** 
+ * Generates universally unique ID.
+ * 
+ * @param dest Where to store the newly generated UUID.
+ * 
+ * @return Same as @a dest.
+ */
+forb_uuid_t *forb_uuid_generate(forb_uuid_t *dest)
+{
+       SHA1_CTX ctx;
+       struct timeval  tv;
+       pid_t pid = getpid();
+       unsigned char digest[20];
+       int i, r;
+       
+       gettimeofday(&tv, 0);
+
+       SHA1Init(&ctx);
+       SHA1Update(&ctx, (unsigned char*)&tv, sizeof(tv));
+       SHA1Update(&ctx, (unsigned char*)&pid, sizeof(pid));
+
+       /* Crank the random number generator a few times */
+       gettimeofday(&tv, 0);
+       for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--) {
+               r = rand();
+               SHA1Update(&ctx, (unsigned char*)&r, sizeof(r));
+       }
+
+       /* Also try to use /dev/urnadom to get some randomnes */
+       
+       /* This should be enough for localhost process.
+        * TODO: Add network addresses for distributed operation! */
+       SHA1Final(digest, &ctx);
+       memcpy(dest, digest, sizeof(forb_uuid_t));
+       return dest;
+}
+
+/** 
+ * Converts UUID to string.
+ * 
+ * @param dest Where to store the result.
+ * @param uuid The UUID to convert.
+ * @param n Size of @a dest buffer.
+ * 
+ * @return The same value as @a dest.
+ */
+char *forb_uuid_to_string(char *dest, const forb_uuid_t *uuid, size_t n)
+{
+       int i;
+       for (i = 0; i<sizeof(uuid->byte) && 2*(i+1) < n; i++)
+               sprintf(dest + 2*i, "%02hhx", uuid->byte[i]);
+       dest[2*i] = '\0';
+       return dest;
+}
+
+static inline int hexval(char c)
+{
+       if (c >= '0' && c <= '9')
+               return c-'0';
+       if (c >= 'a' && c <= 'f')
+               return 10+c-'a';
+       if (c >= 'A' && c <= 'F')
+               return 10+c-'A';
+       return -1;
+}
+
+/** 
+ * Creates UUID from string form.
+ * 
+ * @param dest Where to store the UUID.
+ * @param string UUID in the string form.
+ * 
+ * @return @a dest in case of success, NULL in case of error.
+ */
+forb_uuid_t *forb_uuid_from_string(forb_uuid_t *dest, const char *string)
+{
+       int i;
+       
+       for (i = 0; i<sizeof(dest->byte); i++) {
+               int a, b;
+               a = hexval(string[2*i]);
+               if (a < 0)
+                       return NULL;
+               b = hexval(string[2*i+1]);
+               if (b < 0)
+                       return NULL;
+
+               dest->byte[i] = (a << 4) + b;
+       }
+       return dest;
+}
+
diff --git a/src/forb/src/uuid.h b/src/forb/src/uuid.h
new file mode 100644 (file)
index 0000000..7279ed8
--- /dev/null
@@ -0,0 +1,76 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FORB (Frescor Object Request Broker)            */
+/*                                                                       */
+/* FORB is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FORB is distributed in the hope that 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 FORB; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FORB header files in a file,        */
+/* instantiating FORB generics or templates, or linking other files      */
+/* with FORB objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+#ifndef FORB_UUID_H
+#define FORB_UUID_H
+
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Universally unique ID type.
+ */
+typedef struct {
+       char byte[8];
+} forb_uuid_t;
+
+static inline int forb_uuid_cmp(forb_uuid_t u1, forb_uuid_t u2)
+{
+       return memcmp(&u1, &u2, sizeof(forb_uuid_t));
+}
+
+forb_uuid_t *forb_uuid_generate(forb_uuid_t *dest);
+char *forb_uuid_to_string(char *dest, const forb_uuid_t *uuid, size_t n);
+forb_uuid_t *forb_uuid_from_string(forb_uuid_t *dest, const char *string);
+
+#ifdef __cplusplus
+} /* extern "C"*/
+#endif
+
+#endif
diff --git a/src/forb/tests-idl/Makefile b/src/forb/tests-idl/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/src/forb/tests-idl/Makefile.omk b/src/forb/tests-idl/Makefile.omk
new file mode 100644 (file)
index 0000000..0990c42
--- /dev/null
@@ -0,0 +1,23 @@
+#SUBDIRS = $(ALL_OMK_SUBDIRS)
+
+USER_IDLS += $(notdir $(wildcard $(SOURCES_DIR)/*.idl))
+
+library-pass_HOOKS = $(foreach idl,$(USER_IDLS),$(idl:%.idl=%.h))
+
+lib_LIBRARIES = forb-idl-tests
+# Test whether are the generated files compilable
+forb-idl-tests_GEN_SOURCES = $(addsuffix -skels.c,$(basename $(USER_IDLS))) \
+                            $(addsuffix -stubs.c,$(basename $(USER_IDLS))) \
+                            $(addsuffix -common.c,$(basename $(USER_IDLS)))
+
+test_PROGRAMS += example_server
+INCLUDES += -I$(USER_OBJS_DIR)
+example_server_SOURCES = example_server.c
+example_server_LIBS = fosa pthread rt forb ulut
+example_server_SERVER_IDL = myinterface.idl
+
+test_PROGRAMS += example_client
+INCLUDES += -I$(USER_OBJS_DIR)
+example_client_SOURCES = example_client.c
+example_client_LIBS = fosa pthread rt forb ulut
+example_client_CLIENT_IDL = myinterface.idl
diff --git a/src/forb/tests-idl/enum.idl b/src/forb/tests-idl/enum.idl
new file mode 100644 (file)
index 0000000..7151efa
--- /dev/null
@@ -0,0 +1,6 @@
+enum MyEnum {
+       ONE_VALUE,
+       SECOND_VALUE
+};
+
+typedef MyEnum TypedeffedEnum;
diff --git a/src/forb/tests-idl/example_client.c b/src/forb/tests-idl/example_client.c
new file mode 100644 (file)
index 0000000..f06931b
--- /dev/null
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#include <forb.h>
+#include "myinterface.h"  /* IDL compiler generated prototypes etc. */
+
+int main(int argc, char *argv[])
+{
+       forb_orb orb;
+       myinterface example;
+       CORBA_Environment env;
+       CORBA_long sum, a, b;
+
+       orb = forb_init(&argc, &argv, NULL); /* FORB initialization */
+
+       /* Find our implementation */
+       example = forb_resolve_reference(orb, "example");
+
+       /* Call our implementation */
+       sum = myinterface_add(example, 2, 3, &env);
+       printf("2+3=%d\n", sum);
+
+       /* Call our implementation again */
+       myinterface_get_last(example, &a, &b, &env);
+       printf("last used values: %d and %d\n", a, b);
+
+       return 0;
+}
diff --git a/src/forb/tests-idl/example_server.c b/src/forb/tests-idl/example_server.c
new file mode 100644 (file)
index 0000000..15c0b04
--- /dev/null
@@ -0,0 +1,52 @@
+#include <forb.h>
+#include "myinterface.h"  /* IDL compiler generated prototypes etc. */
+
+/* Internal data of our object implementing myinterface */
+struct example_data {
+       int last_a, last_b;
+};
+
+/* Implementation of add method */
+CORBA_long example_add(myinterface obj, const CORBA_long a,
+                      const CORBA_long b, CORBA_Environment *ev)
+{
+       struct example_data *ed = forb_instance_data(obj);
+       ed->last_a = a;
+       ed->last_b = b;
+       return a + b;
+}
+
+/* Implementation of get_last method */
+void example_get_last(myinterface obj, CORBA_long* a,
+                     CORBA_long* b, CORBA_Environment *ev)
+{
+       struct example_data *ed = forb_instance_data(obj);
+       *a = ed->last_a;
+       *b = ed->last_b;
+}
+
+/* Table of implemented methods */
+struct forb_myinterface_impl example_implementation = {
+       .add = example_add,
+       .get_last = example_get_last,
+};
+
+int main(int argc, char *argv[])
+{
+       forb_orb orb;
+       myinterface example;
+       struct example_data example_data;
+       
+       orb = forb_init(&argc, &argv, NULL); /* FORB initialization */
+       /* Cration of an object implementing myinterface */
+       example = forb_myinterface_new(orb, &example_implementation,
+                                      &example_data);
+       /* We can register our object under a name, so that other
+        * processes can use it. */
+       forb_register_reference(example, "example");
+
+       /* Process incomming requests to this object */
+       forb_execute_object(example);
+       
+       return 0;               /* Never returns */
+}
diff --git a/src/forb/tests-idl/myinterface.idl b/src/forb/tests-idl/myinterface.idl
new file mode 100644 (file)
index 0000000..f2a674a
--- /dev/null
@@ -0,0 +1,16 @@
+struct struct_t {
+       long a, b;
+};
+
+typedef long mytype;
+
+interface myinterface {
+       long add(in long a, in long b);
+       void get_last(out long a, out long b);
+       void square(inout long r);
+       void message(in string msg);
+       void last_message(out string msg);
+       void struct_method(in struct_t s, out struct_t ss);
+       void obj_method(in myinterface mi, out myinterface mo);
+       void mytype_method(in mytype mt, out mytype mtt);
+};
diff --git a/src/forb/tests-idl/sequence.idl b/src/forb/tests-idl/sequence.idl
new file mode 100644 (file)
index 0000000..1a71a48
--- /dev/null
@@ -0,0 +1,12 @@
+interface MyIface {
+       void MyOp();
+};
+
+struct SeqStruct {
+       sequence<long,10> MyLongs;
+       sequence<octet> MyOctets;
+       sequence<MyIface> Interfaces;
+       sequence<sequence<short> > SeqSeq;
+};
+
+typedef sequence<string> MyStrings;
diff --git a/src/forb/tests-idl/string_test.idl b/src/forb/tests-idl/string_test.idl
new file mode 100644 (file)
index 0000000..899010a
--- /dev/null
@@ -0,0 +1,7 @@
+struct StringStruct {
+       string x;
+};
+
+interface StringIntf {
+       void method(in string s1, out string s2);
+};
diff --git a/src/forb/tests-idl/struct.idl b/src/forb/tests-idl/struct.idl
new file mode 100644 (file)
index 0000000..66cfe68
--- /dev/null
@@ -0,0 +1,7 @@
+struct MyStruct {
+       short d1, d2;
+       long d3[3][6];
+       struct InnerStruct {
+               long data;
+       } d4;
+};
diff --git a/src/forb/tests-idl/typedef.idl b/src/forb/tests-idl/typedef.idl
new file mode 100644 (file)
index 0000000..4319cec
--- /dev/null
@@ -0,0 +1,4 @@
+#include "struct.idl"
+
+typedef MyStruct TypedefedStruct;
+typedef long MyLong, MyLongArray[20];