# HG changeset patch # User jlarmour # Date 954252645 0 # Node ID 435cced73e2f8fb790ecf2779851cfdaad6e9f17 # Parent 41bf073c0c327292e82469644fa6c47d847284ae eCos v1.3.1 merged from eCos master repository on 2000-03-27-23:22:51-BST diff --git a/host/COPYING b/host/COPYING new file mode 100644 --- /dev/null +++ b/host/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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 + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/host/ChangeLog b/host/ChangeLog new file mode 100644 --- /dev/null +++ b/host/ChangeLog @@ -0,0 +1,54 @@ +2000-03-13 John Dallway + + * README: + Mention use of the short form of the path to the configure + script under Windows. + +2000-03-12 Bart Veer + + * acinclude.m4, and lots of other files: + Change the CYG_AC_PATH_TCL macro to use tclConfig.sh, make + appropriate adjustments elsewhere. Also, add dependencies + such that the commands now depend on the libraries. + +2000-03-08 Bart Veer + + * README: + Updated. + + * configure.in (ECOS_DIRS): + Use the infrastructure and Tcl macros at the toplevel, so that + configure --help gives the right information. + + * configure.in (ECOS_DIRS): + Look for the file tools/ecostest/common/configure, rather than + just the directory. + +2000-03-01 Bart Veer + + * Create toplevel ChangeLog for the eCos host-side. + +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### diff --git a/host/Makefile.am b/host/Makefile.am new file mode 100644 --- /dev/null +++ b/host/Makefile.am @@ -0,0 +1,45 @@ +## Process this file with automake to produce Makefile.in +## ===================================================================== +## +## Makefile.am +## +## eCos host-side software toplevel makefile +## +## ===================================================================== +######COPYRIGHTBEGIN#### +## +## ---------------------------------------------------------------------------- +## Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +## +## This file is part of the eCos host tools. +## +## This program is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 of the License, or (at your option) +## any later version. +## +## This program is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +## more details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +## +## ---------------------------------------------------------------------------- +## +######COPYRIGHTEND#### +## ===================================================================== +#######DESCRIPTIONBEGIN#### +## +## Author(s): bartv +## Contact(s): bartv +## Date: 1998/12/17 +## Version: 0.01 +## +######DESCRIPTIONEND#### +## ===================================================================== + +AUTOMAKE_OPTIONS = 1.3 cygnus +SUBDIRS = @ECOS_DIRS@ diff --git a/host/Makefile.in b/host/Makefile.in new file mode 100644 --- /dev/null +++ b/host/Makefile.in @@ -0,0 +1,336 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 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. + +######COPYRIGHTBEGIN#### +######COPYRIGHTEND#### +#######DESCRIPTIONBEGIN#### +######DESCRIPTIONEND#### + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = . + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CC = @CC@ +CXX = @CXX@ +ECOS_DIRS = @ECOS_DIRS@ +EXEEXT = @EXEEXT@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ +cyg_ac_tcl_incdir = @cyg_ac_tcl_incdir@ +cyg_ac_tcl_libdir = @cyg_ac_tcl_libdir@ +cyg_ac_tcl_libs = @cyg_ac_tcl_libs@ +cyg_ac_tcl_version = @cyg_ac_tcl_version@ +cyg_ac_tk_libs = @cyg_ac_tk_libs@ + +AUTOMAKE_OPTIONS = 1.3 cygnus +SUBDIRS = @ECOS_DIRS@ +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_CLEAN_FILES = +DIST_COMMON = README COPYING ChangeLog Makefile.am Makefile.in \ +acinclude.m4 aclocal.m4 config.guess config.sub configure configure.in \ +install-sh ltconfig ltmain.sh missing mkinstalldirs + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +all: all-redirect +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --cygnus Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ configure.in acinclude.m4 + cd $(srcdir) && $(ACLOCAL) + +config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck +$(srcdir)/configure: @MAINTAINER_MODE_TRUE@$(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. + +@SET_MAKE@ + +all-recursive install-data-recursive install-exec-recursive \ +installdirs-recursive install-recursive uninstall-recursive install-info-recursive \ +check-recursive installcheck-recursive info-recursive dvi-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ + rev="$$subdir $$rev"; \ + test "$$subdir" = "." && dot_seen=yes; \ + done; \ + test "$$dot_seen" = "no" && rev=". $$rev"; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + -rm -rf $(distdir) + GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + dc_install_base=`cd $(distdir)/=inst && pwd`; \ + cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) dist + -rm -rf $(distdir) + @banner="$(distdir).tar.gz is ready for distribution"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes" +dist: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +dist-all: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +distdir: $(DISTFILES) + -rm -rf $(distdir) + mkdir $(distdir) + -chmod 777 $(distdir) + @for file in $(DISTFILES); do \ + if test -f $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + cp -pr $$/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + for subdir in $(SUBDIRS); do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + chmod 777 $(distdir)/$$subdir; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \ + || exit 1; \ + fi; \ + done +info-am: +info: info-recursive +dvi-am: +dvi: dvi-recursive +check-am: +check: check-recursive +installcheck-am: +installcheck: installcheck-recursive +install-info-am: +install-info: install-info-recursive +install-exec-am: +install-exec: install-exec-recursive + +install-data-am: +install-data: install-data-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-recursive +uninstall-am: +uninstall: uninstall-recursive +all-am: Makefile +all-redirect: all-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: installdirs-recursive +installdirs-am: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-tags mostlyclean-generic + +mostlyclean: mostlyclean-recursive + +clean-am: clean-tags clean-generic mostlyclean-am + +clean: clean-recursive + +distclean-am: distclean-tags distclean-generic clean-am + +distclean: distclean-recursive + -rm -f config.status + +maintainer-clean-am: maintainer-clean-tags maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-recursive + -rm -f config.status + +.PHONY: install-data-recursive uninstall-data-recursive \ +install-exec-recursive uninstall-exec-recursive installdirs-recursive \ +uninstalldirs-recursive all-recursive check-recursive \ +installcheck-recursive info-recursive dvi-recursive \ +mostlyclean-recursive distclean-recursive clean-recursive \ +maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ +distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-info-am \ +install-info install-exec-am install-exec install-data-am install-data \ +install-am install uninstall-am uninstall all-redirect all-am all \ +installdirs-am installdirs mostlyclean-generic distclean-generic \ +clean-generic maintainer-clean-generic clean mostlyclean distclean \ +maintainer-clean + + +# 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/host/README b/host/README new file mode 100644 --- /dev/null +++ b/host/README @@ -0,0 +1,274 @@ + eCos Host-side Software + ======================= + +This directory contains the eCos host-side sources. This includes +libcdl, the CDL library which underlies the whole eCos configuration +system, and both the command-line and graphical configuration tools. + +The eCos host-side software is free software, released under the GNU +General Public License. See the file COPYING for further details. + + +Contents +======== + +The host-side sources include the following: + +infra/ + This is an implementation of the eCos infrastructure that can be + used on the host-side, and provides assertion, tracing and + testcase support. + + NOTE: the eCos infrastructure facilities are not especially + well-suited to host-side development, in particular they are not + C++-oriented. There are plans to remove the current infrastructure + completely and replace it with something more suitable. People + planning new projects should be aware of this, and may wish to + avoid using the current infrastructure. + +libcdl/ + The CDL library lies at the heart of the eCos configuration system. + +tools/configtool/ + The sources to the various configuration tools can be found here. + In particular the command line ecosconfig tool lives in + tools/configtool/standalone/common; the sources related to + makefile generation currently live in + tools/configtool/common/common, and the graphical configuration + tool is spread over various directories including + tools/configtool/common/win32 and tools/configtool/standalone/win32 + +There are various other sub-directories related to the admin tool, +testing support, and so on. + +It should be noted that the eCos host-side software is still +undergoing rapid development, and the sources are subject to change +and reorganization at any time. + +Much of the code is cross-platform. The obvious exception is the +graphical configuration tool which, at the time of writing, can only +be built for Windows hosts and requires Visual C++. It should be +possible to build the underlying libraries and the command-line +configuration tool using gcc/g++ on any Unix platform. A Unix version +of the graphical configuration tool is planned but not yet available. + +More Information +================ + +Please see the eCos web site, http://sourceware.cygnus.com/ecos/, for +further details. This includes the FAQ, a form for reporting problems, +and details of the various mailing lists +(http://sourceware.cygnus.com/ecos/intouch.html) +At the time of writing there are no separate mailing lists for the +eCos host-side sources, the main mailing list +ecos-discuss@sourceware.cygnus.com should be used instead. + + +Installation +============ + +Test builds of the eCos host-side generally happen on the following +platforms: Red Hat Linux 6.1 and later; Windows NT using cygwin 1.0 or +later; and Windows NT using VC++ 6.0. The graphical configuration tool +can only be built with VC++ and involves a Developer Studio project, +see tools/configtool/standalone/win32/Configtool.dsw. The other +software can be built using the conventional "configure/make/make +install" steps. It should be noted that the eCos host-side software is +not fully auto-confiscated, and some facilities like "make dist" will +not work. Also, the existing DejaGnu-based testing facilities are +minimal, only intended as a starting point, and may not work on all +platforms. + +The eCos host-side software has a dependency on Tcl. This is not +supplied with the sources, because many users will already have a +suitable installation. Any release of Tcl from 8.0 onwards should be +usable. There are some configure command-line options related to the +Tcl installation, as described below. + +The instructions for installing under Linux are given first. +Installation on other platforms is very similar, so only the +differences will be noted. + +Installing on Linux +=================== + +It is strongly recommended that a separate build tree is used, as +opposed to building directly in the source tree. The latter has not +been tested and, given some of the build steps, may not work very +well. + + $ mkdir build + $ cd build + +The next step is to run the toplevel configure script. It might be +possible to configure and build individual directories within the +host-side hierarchy, but again this has not been tested. + + $ /configure + +A list of the all the command-line options can be obtained by running +"configure --help". The most important ones are as follows: + +1) --prefix. This can be used to specify the location of the install + tree, defaulting to /usr/local, so the ecosconfig program ends up + in /usr/local/bin/ecosconfig and the CDL library ends up in + /usr/local/lib/libcdl.a. If an alternative location is preferred + this can be specified with --prefix, for example: + + $ /configure --prefix=/usr/local/ecos + +2) --enable-debug. By default all assertions and tracing are disabled. + When debugging any of the host-side software these must be enabled. + + $ /configure --enable-debug + + It is also possible to control most of the assertion and tracing + macros at a finer grain. This is likely to be useful only to the + main developers: + + --disable-asserts disable all assertions + --disable-preconditions disable a subset of the assertions + --disable-postconditions disable a subset of the assertions + --disable-invariants disable a subset of the assertions + --disable-loopinvariants disable a subset of the assertions + --disable-tracing disable tracing + --disable-fntracing disable function entry/exit tracing + +3) --with-tcl= and --with-tcl-version= + The host-side tools have a dependency on Tcl, which is not supplied + with the sources because many people will already have a suitable + installation. Specifically it is necessary to have the header file + tcl.h and appropriate libraries such that -ltcl will work - this + can involve either static or shared libraries. + + By default the configure script will assume that there is a + suitable Tcl installation in the install location, so if there is + no --prefix argument then it will look for /usr/local/include/tcl.h + and it will add -L/usr/local/lib to the library search path. If + Tcl is installed elsewhere then this can be specified with a + --with-tcl option. For example, if the default installation in + /usr should be used then the following configure option is + appropriate: + + $ /configure --with-tcl=/usr + + It is possible to have multiple versions of Tcl installed, for + example libtcl8.0.a, libtcl8.1.a, and so on. Typically linking with + -ltcl will result in the latest version being used. It is possible + to specify a different version using --with-tcl-version, e.g.: + + $ configure --with-tcl=/usr/local/scriptics --with-tcl-version=8.1 + +Following the configure step the build tree should be set up +correctly. All that remains is the actual build and install: + + $ make + $ make install + +This should result in an ecosconfig executable, plus appropriate +libraries and header files. + + +Installing on cygwin +==================== + +Installing under cygwin requires essentially the same steps as +under Linux. It is more likely that a suitable --prefix option will +have to be used, and that the location of the Tcl installation needs +to be specified with --with-tcl. However appropriate use of cygwin +mount points may avoid some of these problems. If the full path to +the configure script contains spaces, then the short form of the path +should be used when invoking configure. + +One issue to be aware of is the naming convention for the Tcl library. +On a Unix system this will typically be called libtcl8.0.a (adjusted +according to the version number), with a symbolic link from libtcl.a +to the most recent version. Under cygwin the equivalent library is +called libtcl80.a, and symbolic links are not used. For a standard +cygwin 1.0 installation the configure script knows how to pick up the +appropriate library, but if a more recent version of Tcl has been +installed then due care has to be taken with the --with-tcl-version +option. + + +Installing on NT with VC++ +========================== + +It is possible to build both the graphical configuration tool and the +ecosconfig command line tool using a Developer Studio project, +tools/ecosconfig/standalone/win32/Configtool.dsw + +It is also possible to build the command line tool and the various +libraries using the configure script. At the time of writing the +graphical configuration tool cannot yet be built that way. This still +requires a cygwin installation because it needs the bash shell and GNU +make. First, it is necessary to tell the configure script to use a +compiler other than gcc: + + $ mkdir build + $ cd build + $ CC=cl CXX=cl /configure + +The configure script will do the right thing if VC++ is specified in +this way. + +It is likely that /usr/local will be an inappropriate install location +for VC++ applications, so an alternative prefix needs to be specified: + + $ CC=cl CXX=cl /configure --prefix= + +Note that the install path should be a cygwin path, i.e. cygwin mount +points are accepted and forward slashes should be used. + +It is also necessary to use the right version of Tcl. For a VC++ build +the cygwin release of Tcl should not be used. Instead a suitable +prebuilt Tcl package can be obtained from http://www.scriptics.com/. +It is necessary to tell the configure script where this has been +installed, for example: + + $ CC=cl CXX=cl /configure --prefix= \ + --with-tcl=/d/local/scriptics/Tcl/tcl8.1 + +The library name will be of the form tcl81.lib, and there will not be +a symbolic link from tcl.lib to the appropriate version. Typically it +will be necessary to specify the Tcl version explicitly: + + $ CC=cl CXX=cl /configure --prefix= \ + --with-tcl=/d/local/scriptics/Tcl/tcl8.1 --with-tcl-version=81 + +Following a successful configure, the tools can be built and installed +in the normal fashion: + + $ make + $ make install + +This assumes that the cl.exe executable is on the shell's search path, +and that appropriate environment variables such as INCLUDE and LIB are +set up correctly. The VC++ documentation should be consulted for +further information. + + +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### diff --git a/host/acinclude.m4 b/host/acinclude.m4 new file mode 100644 --- /dev/null +++ b/host/acinclude.m4 @@ -0,0 +1,363 @@ +dnl Process this file with aclocal to get an aclocal.m4 file. Then +dnl process that with autoconf. +dnl ==================================================================== +dnl +dnl acinclude.m4 +dnl +dnl Various autoconf macros that are shared between different +dnl eCos packages. +dnl +dnl ==================================================================== +dnl####COPYRIGHTBEGIN#### +dnl +dnl ---------------------------------------------------------------------------- +dnl Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +dnl +dnl This file is part of the eCos host tools. +dnl +dnl This program is free software; you can redistribute it and/or modify it +dnl under the terms of the GNU General Public License as published by the Free +dnl Software Foundation; either version 2 of the License, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but WITHOUT +dnl ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +dnl FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +dnl more details. +dnl +dnl You should have received a copy of the GNU General Public License along with +dnl this program; if not, write to the Free Software Foundation, Inc., +dnl 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl ---------------------------------------------------------------------------- +dnl +dnl####COPYRIGHTEND#### +dnl ==================================================================== +dnl#####DESCRIPTIONBEGIN#### +dnl +dnl Author(s): bartv +dnl Contact(s): bartv +dnl Date: 1998/12/16 +dnl Version: 0.01 +dnl +dnl####DESCRIPTIONEND#### +dnl ==================================================================== + +dnl ==================================================================== +dnl The AM_INIT_AUTOMAKE() will define a symbol VERSION for the +dnl package's version number. Unfortunately this symbol is rather +dnl hard to share if several different packages are involved, so this +dnl macro is used to define an alternative symbol + +AC_DEFUN(CYG_AC_SUBST_VERSION,[ + AC_REQUIRE([AM_INIT_AUTOMAKE]) + ifelse($#,1,,AC_MSG_ERROR([Invalid number of arguments passed to CYG AC_SUBST_VERSION])) + AC_DEFINE_UNQUOTED($1, "$VERSION") +]) + +dnl ==================================================================== +dnl Provide support for an automake conditional MSVC. Also set a +dnl variable MSVC to true or false, which may help other tests. + +AC_DEFUN(CYG_AC_PROG_MSVC,[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_PROG_CXX]) + + AC_MSG_CHECKING("for Visual C++") + MSVC="no"; + if test "${CC}" = "cl" ; then + MSVC="yes" + fi + if test "${CXX}" = "cl" ; then + MSVC="yes" + fi + AM_CONDITIONAL(MSVC, test "${MSVC}" = "yes") + AC_MSG_RESULT(${MSVC}) +]) + +dnl ==================================================================== +dnl Set up sensible flags for the various different compilers. This +dnl is achieved by redefining CC and CXX. +dnl +dnl A better way of doing this sort of thing would be to detect +dnl arguments to add and remove to the set of compiler flags, and +dnl then update CFLAGS and CXXFLAGS (or even better, the AM +dnl versions of those flags?) +dnl +dnl There is no point in checking the cache, this macro does +dnl not do any feature tests. +dnl +dnl The VC++ variant might benefit from -Za, but the header files +dnl shipped with the compiler are incompatible with this option. + +AC_DEFUN(CYG_AC_PROG_STANDARD_COMPILER_FLAGS, [ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_PROG_CXX]) + AC_REQUIRE([CYG_AC_PROG_MSVC]) + + AC_MSG_CHECKING("the default compiler flags") + + dnl Add a user-settable flag to control whether or debugging info is + dnl incorporated at compile-time. + dnl + dnl NOTE: there may also have to be a flag to control whether or + dnl the VC++ multi-threading flags are enabled. + cygflags_enable_debug="no" + AC_ARG_ENABLE(debug,[ --enable-debug do a debug rather than a release build], + [case "${enableval}" in + yes) cygflags_enable_debug="yes" ;; + *) cygflags_enable_debug="no" ;; + esac]) + + dnl For VC++ builds also provide a flag for ANSI vs. unicode builds. + dnl For now this does not actually affect the compiler flags. + cygflags_enable_ansi="no" + if test "${MSVC}" = "yes" ; then + AC_ARG_ENABLE(ansi,[ --enable-ansi Do an ANSI rather than a unicode build], + [case "${enableval}" in + yes) cygflags_enable_ansi="yes" ;; + *) cygflags_enable_ansi="no" ;; + esac]) + fi + + if test "${GCC}" = "yes" ; then + CC="$CC -Wall -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs" + CXX="$CXX -Wall -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Woverloaded-virtual" + elif test "${MSVC}" = "yes" ; then + CC="$CC -nologo -W3" + CXX="$CXX -nologo -W3 -GR -GX" + if test "${cygflags_enable_debug}" = "yes" ; then + CC="$CC -MDd -Zi" + CXX="$CXX -MDd -Zi" + else + CC="$CC -MD -O2" + CXX="$CXX -MD -O2" + fi + else + AC_MSG_ERROR("default flags for ${CC} are not known") + fi + AC_MSG_RESULT(done) +]) + +dnl -------------------------------------------------------------------- +dnl User-settable options for assertions and tracing. +dnl +dnl The settable options are: +dnl --disable-asserts +dnl --disable-preconditions +dnl --disable-postconditions +dnl --disable-invariants +dnl --disable-loopinvariants +dnl --disable-tracing +dnl --disable-fntracing + +AC_DEFUN(CYG_AC_ARG_INFRASTRUCTURE, [ + +AC_REQUIRE([CYG_AC_PROG_STANDARD_COMPILER_FLAGS]) + +if test "${cygflags_enable_debug}" = "yes" ; then + cyginfra_asserts=yes + cyginfra_preconditions=yes + cyginfra_postconditions=yes + cyginfra_invariants=yes + cyginfra_loopinvariants=yes + cyginfra_tracing=yes + cyginfra_fntracing=yes +else + cyginfra_asserts=no + cyginfra_preconditions=no + cyginfra_postconditions=no + cyginfra_invariants=no + cyginfra_loopinvariants=no + cyginfra_tracing=no + cyginfra_fntracing=no +fi + +AC_ARG_ENABLE(asserts,[ --disable-asserts disable all assertions], +[case "${enableval}" in + yes) cyginfra_asserts=yes ;; + no) cyginfra_asserts=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for disable-asserts option]) ;; +esac]) +if test "${cyginfra_asserts}" = "yes"; then + AC_DEFINE(CYGDBG_USE_ASSERTS) +fi + +AC_ARG_ENABLE(preconditions, [ --disable-preconditions disable a subset of the assertions], +[case "${enableval}" in + yes) cyginfra_preconditions=yes ;; + no) cyginfra_preconditions=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for disable-preconditions option]) ;; +esac]) +if test "${cyginfra_preconditions}" = "yes"; then + AC_DEFINE(CYGDBG_INFRA_DEBUG_PRECONDITIONS) +fi + +AC_ARG_ENABLE(postconditions, [ --disable-postconditions disable a subset of the assertions], +[case "${enableval}" in + yes) cyginfra_postconditions=yes ;; + no) cyginfra_postconditions=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for disable-postconditions option]) ;; +esac]) +if test "${cyginfra_postconditions}" = "yes"; then + AC_DEFINE(CYGDBG_INFRA_DEBUG_POSTCONDITIONS) +fi + +AC_ARG_ENABLE(invariants, [ --disable-invariants disable a subset of the assertions], +[case "${enableval}" in + yes) cyginfra_invariants=yes ;; + no) cyginfra_invariants=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for disable-invariants option]) ;; +esac]) +if test "${cyginfra_invariants}" = "yes"; then + AC_DEFINE(CYGDBG_INFRA_DEBUG_INVARIANTS) +fi + +AC_ARG_ENABLE(loopinvariants, [ --disable-loopinvariants disable a subset of the assertions], +[case "${enableval}" in + yes) cyginfra_loopinvariants=yes ;; + no) cyginfra_loopinvariants=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for disable-loopinvariants option]) ;; +esac]) +if test "${cyginfra_loopinvariants}" = "yes"; then + AC_DEFINE(CYGDBG_INFRA_DEBUG_LOOP_INVARIANTS) +fi + +AC_ARG_ENABLE(tracing,[ --disable-tracing disable tracing], +[case "${enableval}" in + yes) cyginfra_tracing=yes ;; + no) cyginfra_tracing=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for disable-tracing option]) ;; +esac]) +if test "${cyginfra_tracing}" = "yes"; then + AC_DEFINE(CYGDBG_USE_TRACING) +fi + +AC_ARG_ENABLE(fntracing,[ --disable-fntracing disable function entry/exit tracing], +[case "${enableval}" in + yes) cyginfra_fntracing=yes ;; + no) cyginfra_fntracing=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for disable-fntracing option]) ;; +esac]) +if test "${cyginfra_fntracing}" = "yes"; then + AC_DEFINE(CYGDBG_INFRA_DEBUG_FUNCTION_REPORTS) +fi + +]) + +dnl -------------------------------------------------------------------- +dnl Convert a cygwin pathname to something acceptable to VC++ (but +dnl still invoked from bash and cygwin's make). This means using +dnl the cygpath utility and then translating any backslashes into +dnl forward slashes to avoid confusing make. + +AC_DEFUN(CYG_AC_MSVC_PATH, [ + AC_REQUIRE([CYG_AC_PROG_MSVC]) + ifelse($#, 1, , AC_MSG_ERROR("Invalid number of arguments passed to CYG AC_MSVC_PATH")) + + if test "${MSVC}" = "yes" ; then + $1=`cygpath -w ${$1} | tr \\\\\\\\ /` + fi +]) + + +dnl -------------------------------------------------------------------- +dnl Work out details of the Tcl installation that should be used. +dnl This adds two command-line options, --with-tcl= to +dnl specify the Tcl install directory, and --with-tcl-version= +dnl to control which version of Tcl should be used. +dnl +dnl On Unix systems and under cygwin there should be a file +dnl $(tcl_prefix)/lib/tclConfig.sh containing all the information +dnl needed for Tcl. This file are consulted and the appropriate +dnl variables extracted. +dnl +dnl To confuse matters, subtly different naming conventions are used +dnl under Unix and NT. Under Unix the Tcl library will be called +dnl libtcl8.0.a, libtcl8.1.a, etc. with a dot between the major and +dnl minor version. Under NT (including cygwin) the library will be +dnl called tcl80.lib, dnl tcl81.lib, libtcl80.a, libtcl81.a, etc. +dnl without a dot. +dnl +dnl The macro should really assume that it is running inside devo, +dnl with tcl and tcl8.1 directories present and already configured. +dnl This is tricky for a number of reasons, including confusion about +dnl the meaning of top_srcdir. +dnl +dnl This macro defines four new shell variables which will be +dnl substituted (typically into Makefile.in): +dnl +dnl cyg_ac_tcl_version - the version of Tcl that is to be used +dnl cyg_ac_tcl_incdir - location of etc al +dnl cyg_ac_tcl_libdir - location of libtcl.a/tcl.lib etc. +dnl cyg_ac_tcl_libs - all of the libraries that are needed for Tcl + +AC_DEFUN(CYG_AC_PATH_TCL, [ + +AC_REQUIRE([CYG_AC_PROG_MSVC]) +AC_REQUIRE([AC_CYGWIN]) + +dnl Look for the version of Tcl. If none is specified, default to +dnl 8.0 under VC++ and cygwin, nothing under Unix. A version has to be +dnl specified under NT because there is no symbolic link from libtcl.a +dnl to whatever happens to be the most recent installed version. + +AC_MSG_CHECKING(for Tcl version) +AC_ARG_WITH(tcl-version,[ --with-tcl-version= version of Tcl to be used],[ + cyg_ac_tcl_version=${with_tcl_version} +],[ + if test "${MSVC}" = "yes" ; then + cyg_ac_tcl_version=80 + else + if test "${ac_cv_cygwin}" = "yes" ; then + cyg_ac_tcl_version=80 + else + cyg_ac_tcl_version="" + fi + fi +]) +AC_MSG_RESULT(${cyg_ac_tcl_version}) +AC_SUBST(cyg_ac_tcl_version) + +dnl Where is the Tcl installation? By default assume Tcl is already +dnl installed in the same place as the eCos host-side. +AC_MSG_CHECKING(for Tcl installation) +AC_ARG_WITH(tcl,[ --with-tcl= location of Tcl header and libraries],[ + cyg_ac_tcl_incdir=${with_tcl}/include + cyg_ac_tcl_libdir=${with_tcl}/lib +],[ + cyg_ac_tcl_incdir=${prefix}/include + cyg_ac_tcl_libdir=${prefix}/lib +]) +AC_MSG_RESULT(${cyg_ac_tcl_libdir}) + +dnl Sanity check, make sure that there is a tcl.h header file. +dnl If not then there is no point in proceeding. +if test \! -r ${cyg_ac_tcl_incdir}/tcl.h ; then + AC_MSG_ERROR(unable to locate Tcl header file tcl.h) +fi + +dnl If using VC++ then there is no tclConfig.sh file, so the +dnl library information has to be hard-wired. Otherwise ther +dnl should be a tclConfig.sh file containing the necessary information. +if test "${MSVC}" = "yes" ; then + cyg_ac_tcl_libs="tcl${cyg_ac_tcl_version}.lib" + CYG_AC_MSVC_PATH(cyg_ac_tcl_incdir) + CYG_AC_MSVC_PATH(cyg_ac_tcl_libdir) +else + if test \! -r ${cyg_ac_tcl_libdir}/tclConfig.sh ; then + AC_MSG_ERROR(unable to locate Tcl config file tclConfig.sh) + else + . ${cyg_ac_tcl_libdir}/tclConfig.sh + cyg_ac_tcl_libs="-ltcl${cyg_ac_tcl_version} ${TCL_LIBS}" + fi +fi + +AC_SUBST(cyg_ac_tcl_incdir) +AC_SUBST(cyg_ac_tcl_libdir) +AC_SUBST(cyg_ac_tcl_libs) +AC_SUBST(cyg_ac_tk_libs) +]) + + + diff --git a/host/aclocal.m4 b/host/aclocal.m4 new file mode 100644 --- /dev/null +++ b/host/aclocal.m4 @@ -0,0 +1,501 @@ +dnl aclocal.m4 generated automatically by aclocal 1.4 + +dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without +dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A +dnl PARTICULAR PURPOSE. + +dnl Process this file with aclocal to get an aclocal.m4 file. Then +dnl process that with autoconf. +dnl ==================================================================== +dnl +dnl acinclude.m4 +dnl +dnl Various autoconf macros that are shared between different +dnl eCos packages. +dnl +dnl ==================================================================== +dnl####COPYRIGHTBEGIN#### +dnl +dnl ---------------------------------------------------------------------------- +dnl Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +dnl +dnl This file is part of the eCos host tools. +dnl +dnl This program is free software; you can redistribute it and/or modify it +dnl under the terms of the GNU General Public License as published by the Free +dnl Software Foundation; either version 2 of the License, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but WITHOUT +dnl ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +dnl FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +dnl more details. +dnl +dnl You should have received a copy of the GNU General Public License along with +dnl this program; if not, write to the Free Software Foundation, Inc., +dnl 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl ---------------------------------------------------------------------------- +dnl +dnl####COPYRIGHTEND#### +dnl ==================================================================== +dnl#####DESCRIPTIONBEGIN#### +dnl +dnl Author(s): bartv +dnl Contact(s): bartv +dnl Date: 1998/12/16 +dnl Version: 0.01 +dnl +dnl####DESCRIPTIONEND#### +dnl ==================================================================== + +dnl ==================================================================== +dnl The AM_INIT_AUTOMAKE() will define a symbol VERSION for the +dnl package's version number. Unfortunately this symbol is rather +dnl hard to share if several different packages are involved, so this +dnl macro is used to define an alternative symbol + +AC_DEFUN(CYG_AC_SUBST_VERSION,[ + AC_REQUIRE([AM_INIT_AUTOMAKE]) + ifelse($#,1,,AC_MSG_ERROR([Invalid number of arguments passed to CYG AC_SUBST_VERSION])) + AC_DEFINE_UNQUOTED($1, "$VERSION") +]) + +dnl ==================================================================== +dnl Provide support for an automake conditional MSVC. Also set a +dnl variable MSVC to true or false, which may help other tests. + +AC_DEFUN(CYG_AC_PROG_MSVC,[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_PROG_CXX]) + + AC_MSG_CHECKING("for Visual C++") + MSVC="no"; + if test "${CC}" = "cl" ; then + MSVC="yes" + fi + if test "${CXX}" = "cl" ; then + MSVC="yes" + fi + AM_CONDITIONAL(MSVC, test "${MSVC}" = "yes") + AC_MSG_RESULT(${MSVC}) +]) + +dnl ==================================================================== +dnl Set up sensible flags for the various different compilers. This +dnl is achieved by redefining CC and CXX. +dnl +dnl A better way of doing this sort of thing would be to detect +dnl arguments to add and remove to the set of compiler flags, and +dnl then update CFLAGS and CXXFLAGS (or even better, the AM +dnl versions of those flags?) +dnl +dnl There is no point in checking the cache, this macro does +dnl not do any feature tests. +dnl +dnl The VC++ variant might benefit from -Za, but the header files +dnl shipped with the compiler are incompatible with this option. + +AC_DEFUN(CYG_AC_PROG_STANDARD_COMPILER_FLAGS, [ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_PROG_CXX]) + AC_REQUIRE([CYG_AC_PROG_MSVC]) + + AC_MSG_CHECKING("the default compiler flags") + + dnl Add a user-settable flag to control whether or debugging info is + dnl incorporated at compile-time. + dnl + dnl NOTE: there may also have to be a flag to control whether or + dnl the VC++ multi-threading flags are enabled. + cygflags_enable_debug="no" + AC_ARG_ENABLE(debug,[ --enable-debug do a debug rather than a release build], + [case "${enableval}" in + yes) cygflags_enable_debug="yes" ;; + *) cygflags_enable_debug="no" ;; + esac]) + + dnl For VC++ builds also provide a flag for ANSI vs. unicode builds. + dnl For now this does not actually affect the compiler flags. + cygflags_enable_ansi="no" + if test "${MSVC}" = "yes" ; then + AC_ARG_ENABLE(ansi,[ --enable-ansi Do an ANSI rather than a unicode build], + [case "${enableval}" in + yes) cygflags_enable_ansi="yes" ;; + *) cygflags_enable_ansi="no" ;; + esac]) + fi + + if test "${GCC}" = "yes" ; then + CC="$CC -Wall -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs" + CXX="$CXX -Wall -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Woverloaded-virtual" + elif test "${MSVC}" = "yes" ; then + CC="$CC -nologo -W3" + CXX="$CXX -nologo -W3 -GR -GX" + if test "${cygflags_enable_debug}" = "yes" ; then + CC="$CC -MDd -Zi" + CXX="$CXX -MDd -Zi" + else + CC="$CC -MD -O2" + CXX="$CXX -MD -O2" + fi + else + AC_MSG_ERROR("default flags for ${CC} are not known") + fi + AC_MSG_RESULT(done) +]) + +dnl -------------------------------------------------------------------- +dnl User-settable options for assertions and tracing. +dnl +dnl The settable options are: +dnl --disable-asserts +dnl --disable-preconditions +dnl --disable-postconditions +dnl --disable-invariants +dnl --disable-loopinvariants +dnl --disable-tracing +dnl --disable-fntracing + +AC_DEFUN(CYG_AC_ARG_INFRASTRUCTURE, [ + +AC_REQUIRE([CYG_AC_PROG_STANDARD_COMPILER_FLAGS]) + +if test "${cygflags_enable_debug}" = "yes" ; then + cyginfra_asserts=yes + cyginfra_preconditions=yes + cyginfra_postconditions=yes + cyginfra_invariants=yes + cyginfra_loopinvariants=yes + cyginfra_tracing=yes + cyginfra_fntracing=yes +else + cyginfra_asserts=no + cyginfra_preconditions=no + cyginfra_postconditions=no + cyginfra_invariants=no + cyginfra_loopinvariants=no + cyginfra_tracing=no + cyginfra_fntracing=no +fi + +AC_ARG_ENABLE(asserts,[ --disable-asserts disable all assertions], +[case "${enableval}" in + yes) cyginfra_asserts=yes ;; + no) cyginfra_asserts=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for disable-asserts option]) ;; +esac]) +if test "${cyginfra_asserts}" = "yes"; then + AC_DEFINE(CYGDBG_USE_ASSERTS) +fi + +AC_ARG_ENABLE(preconditions, [ --disable-preconditions disable a subset of the assertions], +[case "${enableval}" in + yes) cyginfra_preconditions=yes ;; + no) cyginfra_preconditions=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for disable-preconditions option]) ;; +esac]) +if test "${cyginfra_preconditions}" = "yes"; then + AC_DEFINE(CYGDBG_INFRA_DEBUG_PRECONDITIONS) +fi + +AC_ARG_ENABLE(postconditions, [ --disable-postconditions disable a subset of the assertions], +[case "${enableval}" in + yes) cyginfra_postconditions=yes ;; + no) cyginfra_postconditions=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for disable-postconditions option]) ;; +esac]) +if test "${cyginfra_postconditions}" = "yes"; then + AC_DEFINE(CYGDBG_INFRA_DEBUG_POSTCONDITIONS) +fi + +AC_ARG_ENABLE(invariants, [ --disable-invariants disable a subset of the assertions], +[case "${enableval}" in + yes) cyginfra_invariants=yes ;; + no) cyginfra_invariants=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for disable-invariants option]) ;; +esac]) +if test "${cyginfra_invariants}" = "yes"; then + AC_DEFINE(CYGDBG_INFRA_DEBUG_INVARIANTS) +fi + +AC_ARG_ENABLE(loopinvariants, [ --disable-loopinvariants disable a subset of the assertions], +[case "${enableval}" in + yes) cyginfra_loopinvariants=yes ;; + no) cyginfra_loopinvariants=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for disable-loopinvariants option]) ;; +esac]) +if test "${cyginfra_loopinvariants}" = "yes"; then + AC_DEFINE(CYGDBG_INFRA_DEBUG_LOOP_INVARIANTS) +fi + +AC_ARG_ENABLE(tracing,[ --disable-tracing disable tracing], +[case "${enableval}" in + yes) cyginfra_tracing=yes ;; + no) cyginfra_tracing=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for disable-tracing option]) ;; +esac]) +if test "${cyginfra_tracing}" = "yes"; then + AC_DEFINE(CYGDBG_USE_TRACING) +fi + +AC_ARG_ENABLE(fntracing,[ --disable-fntracing disable function entry/exit tracing], +[case "${enableval}" in + yes) cyginfra_fntracing=yes ;; + no) cyginfra_fntracing=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for disable-fntracing option]) ;; +esac]) +if test "${cyginfra_fntracing}" = "yes"; then + AC_DEFINE(CYGDBG_INFRA_DEBUG_FUNCTION_REPORTS) +fi + +]) + +dnl -------------------------------------------------------------------- +dnl Convert a cygwin pathname to something acceptable to VC++ (but +dnl still invoked from bash and cygwin's make). This means using +dnl the cygpath utility and then translating any backslashes into +dnl forward slashes to avoid confusing make. + +AC_DEFUN(CYG_AC_MSVC_PATH, [ + AC_REQUIRE([CYG_AC_PROG_MSVC]) + ifelse($#, 1, , AC_MSG_ERROR("Invalid number of arguments passed to CYG AC_MSVC_PATH")) + + if test "${MSVC}" = "yes" ; then + $1=`cygpath -w ${$1} | tr \\\\\\\\ /` + fi +]) + + +dnl -------------------------------------------------------------------- +dnl Work out details of the Tcl installation that should be used. +dnl This adds two command-line options, --with-tcl= to +dnl specify the Tcl install directory, and --with-tcl-version= +dnl to control which version of Tcl should be used. +dnl +dnl On Unix systems and under cygwin there should be a file +dnl $(tcl_prefix)/lib/tclConfig.sh containing all the information +dnl needed for Tcl. This file are consulted and the appropriate +dnl variables extracted. +dnl +dnl To confuse matters, subtly different naming conventions are used +dnl under Unix and NT. Under Unix the Tcl library will be called +dnl libtcl8.0.a, libtcl8.1.a, etc. with a dot between the major and +dnl minor version. Under NT (including cygwin) the library will be +dnl called tcl80.lib, dnl tcl81.lib, libtcl80.a, libtcl81.a, etc. +dnl without a dot. +dnl +dnl The macro should really assume that it is running inside devo, +dnl with tcl and tcl8.1 directories present and already configured. +dnl This is tricky for a number of reasons, including confusion about +dnl the meaning of top_srcdir. +dnl +dnl This macro defines four new shell variables which will be +dnl substituted (typically into Makefile.in): +dnl +dnl cyg_ac_tcl_version - the version of Tcl that is to be used +dnl cyg_ac_tcl_incdir - location of etc al +dnl cyg_ac_tcl_libdir - location of libtcl.a/tcl.lib etc. +dnl cyg_ac_tcl_libs - all of the libraries that are needed for Tcl + +AC_DEFUN(CYG_AC_PATH_TCL, [ + +AC_REQUIRE([CYG_AC_PROG_MSVC]) +AC_REQUIRE([AC_CYGWIN]) + +dnl Look for the version of Tcl. If none is specified, default to +dnl 8.0 under VC++ and cygwin, nothing under Unix. A version has to be +dnl specified under NT because there is no symbolic link from libtcl.a +dnl to whatever happens to be the most recent installed version. + +AC_MSG_CHECKING(for Tcl version) +AC_ARG_WITH(tcl-version,[ --with-tcl-version= version of Tcl to be used],[ + cyg_ac_tcl_version=${with_tcl_version} +],[ + if test "${MSVC}" = "yes" ; then + cyg_ac_tcl_version=80 + else + if test "${ac_cv_cygwin}" = "yes" ; then + cyg_ac_tcl_version=80 + else + cyg_ac_tcl_version="" + fi + fi +]) +AC_MSG_RESULT(${cyg_ac_tcl_version}) +AC_SUBST(cyg_ac_tcl_version) + +dnl Where is the Tcl installation? By default assume Tcl is already +dnl installed in the same place as the eCos host-side. +AC_MSG_CHECKING(for Tcl installation) +AC_ARG_WITH(tcl,[ --with-tcl= location of Tcl header and libraries],[ + cyg_ac_tcl_incdir=${with_tcl}/include + cyg_ac_tcl_libdir=${with_tcl}/lib +],[ + cyg_ac_tcl_incdir=${prefix}/include + cyg_ac_tcl_libdir=${prefix}/lib +]) +AC_MSG_RESULT(${cyg_ac_tcl_libdir}) + +dnl Sanity check, make sure that there is a tcl.h header file. +dnl If not then there is no point in proceeding. +if test \! -r ${cyg_ac_tcl_incdir}/tcl.h ; then + AC_MSG_ERROR(unable to locate Tcl header file tcl.h) +fi + +dnl If using VC++ then there is no tclConfig.sh file, so the +dnl library information has to be hard-wired. Otherwise ther +dnl should be a tclConfig.sh file containing the necessary information. +if test "${MSVC}" = "yes" ; then + cyg_ac_tcl_libs="tcl${cyg_ac_tcl_version}.lib" + CYG_AC_MSVC_PATH(cyg_ac_tcl_incdir) + CYG_AC_MSVC_PATH(cyg_ac_tcl_libdir) +else + if test \! -r ${cyg_ac_tcl_libdir}/tclConfig.sh ; then + AC_MSG_ERROR(unable to locate Tcl config file tclConfig.sh) + else + . ${cyg_ac_tcl_libdir}/tclConfig.sh + cyg_ac_tcl_libs="-ltcl${cyg_ac_tcl_version} ${TCL_LIBS}" + fi +fi + +AC_SUBST(cyg_ac_tcl_incdir) +AC_SUBST(cyg_ac_tcl_libdir) +AC_SUBST(cyg_ac_tcl_libs) +AC_SUBST(cyg_ac_tk_libs) +]) + + + + +# Do all the work for Automake. This macro actually does too much -- +# some checks are only needed if your package does certain things. +# But this isn't really a big deal. + +# serial 1 + +dnl Usage: +dnl AM_INIT_AUTOMAKE(package,version, [no-define]) + +AC_DEFUN(AM_INIT_AUTOMAKE, +[AC_REQUIRE([AC_PROG_INSTALL]) +PACKAGE=[$1] +AC_SUBST(PACKAGE) +VERSION=[$2] +AC_SUBST(VERSION) +dnl test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi +ifelse([$3],, +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) +AC_REQUIRE([AM_SANITY_CHECK]) +AC_REQUIRE([AC_ARG_PROGRAM]) +dnl FIXME This is truly gross. +missing_dir=`cd $ac_aux_dir && pwd` +AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) +AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) +AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) +AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) +AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) +AC_REQUIRE([AC_PROG_MAKE_SET])]) + +# +# Check to make sure that the build environment is sane. +# + +AC_DEFUN(AM_SANITY_CHECK, +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "[$]*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "[$]*" != "X $srcdir/configure conftestfile" \ + && test "[$]*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "[$]2" = conftestfile + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +rm -f conftest* +AC_MSG_RESULT(yes)]) + +dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) +dnl The program must properly implement --version. +AC_DEFUN(AM_MISSING_PROG, +[AC_MSG_CHECKING(for working $2) +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if ($2 --version) < /dev/null > /dev/null 2>&1; then + $1=$2 + AC_MSG_RESULT(found) +else + $1="$3/missing $2" + AC_MSG_RESULT(missing) +fi +AC_SUBST($1)]) + +# Define a conditional. + +AC_DEFUN(AM_CONDITIONAL, +[AC_SUBST($1_TRUE) +AC_SUBST($1_FALSE) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi]) + +# Add --enable-maintainer-mode option to configure. +# From Jim Meyering + +# serial 1 + +AC_DEFUN(AM_MAINTAINER_MODE, +[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode is disabled by default + AC_ARG_ENABLE(maintainer-mode, +[ --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer], + USE_MAINTAINER_MODE=$enableval, + USE_MAINTAINER_MODE=no) + AC_MSG_RESULT($USE_MAINTAINER_MODE) + AM_CONDITIONAL(MAINTAINER_MODE, test $USE_MAINTAINER_MODE = yes) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST(MAINT)dnl +] +) + diff --git a/host/config.guess b/host/config.guess new file mode 100644 --- /dev/null +++ b/host/config.guess @@ -0,0 +1,1171 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 +# Free Software Foundation, Inc. +# +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Written by Per Bothner . +# Please send patches to . +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit system type (host/target name). +# +# Only a few systems have been added to this list; please add others +# (but try to keep the structure clean). +# + +# Use $HOST_CC if defined. $CC may point to a cross-compiler +if test x"$CC_FOR_BUILD" = x; then + if test x"$HOST_CC" != x; then + CC_FOR_BUILD="$HOST_CC" + else + if test x"$CC" != x; then + CC_FOR_BUILD="$CC" + else + CC_FOR_BUILD=cc + fi + fi +fi + + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 8/24/94.) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +dummy=dummy-$$ +trap 'rm -f $dummy.c $dummy.o $dummy; exit 1' 1 2 15 + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # Netbsd (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # Determine the machine/vendor (is the vendor relevant). + case "${UNAME_MACHINE}" in + amiga) machine=m68k-cbm ;; + arm32) machine=arm-unknown ;; + atari*) machine=m68k-atari ;; + sun3*) machine=m68k-sun ;; + mac68k) machine=m68k-apple ;; + macppc) machine=powerpc-apple ;; + hp3[0-9][05]) machine=m68k-hp ;; + ibmrt|romp-ibm) machine=romp-ibm ;; + *) machine=${UNAME_MACHINE}-unknown ;; + esac + # The Operating System including object format. + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + # The OS release + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit 0 ;; + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + cat <$dummy.s + .data +\$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main +main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + esac + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-cbm-sysv4 + exit 0;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + arc64:OpenBSD:*:*) + echo mips64el-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hkmips:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + atari*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + sun3*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy \ + && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i?86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:4) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` + if /usr/sbin/lsattr -EHl ${IBM_CPU_ID} | grep POWER >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=4.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + sed 's/^ //' << EOF >$dummy.c + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` + rm -f $dummy.c $dummy + esac + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i?86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + hppa*:OpenBSD:*:*) + echo hppa-unknown-openbsd + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*X-MP:*:*:*) + echo xmp-cray-unicos + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY-2:*:*:*) + echo cray2-cray-unicos + exit 0 ;; + F300:UNIX_System_V:*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + F301:UNIX_System_V:*:*) + echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'` + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + i?86:BSD/386:*:* | i?86:BSD/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + if test -x /usr/bin/objformat; then + if test "elf" = "`/usr/bin/objformat`"; then + echo ${UNAME_MACHINE}-unknown-freebsdelf`echo ${UNAME_RELEASE}|sed -e 's/[-_].*//'` + exit 0 + fi + fi + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i386-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + *:Linux:*:*) + + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + ld_help_string=`cd /; ld --help 2>&1` + ld_supported_emulations=`echo $ld_help_string \ + | sed -ne '/supported emulations:/!d + s/[ ][ ]*/ /g + s/.*supported emulations: *// + s/ .*// + p'` + case "$ld_supported_emulations" in + *ia64) + echo "${UNAME_MACHINE}-unknown-linux" + exit 0 + ;; + i?86linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 + ;; + i?86coff) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 + ;; + sparclinux) + echo "${UNAME_MACHINE}-unknown-linux-gnuaout" + exit 0 + ;; + armlinux) + echo "${UNAME_MACHINE}-unknown-linux-gnuaout" + exit 0 + ;; + elf32arm*) + echo "${UNAME_MACHINE}-unknown-linux-gnuoldld" + exit 0 + ;; + armelf_linux*) + echo "${UNAME_MACHINE}-unknown-linux-gnu" + exit 0 + ;; + m68klinux) + echo "${UNAME_MACHINE}-unknown-linux-gnuaout" + exit 0 + ;; + elf32ppc | elf32ppclinux) + # Determine Lib Version + cat >$dummy.c < +#if defined(__GLIBC__) +extern char __libc_version[]; +extern char __libc_release[]; +#endif +main(argc, argv) + int argc; + char *argv[]; +{ +#if defined(__GLIBC__) + printf("%s %s\n", __libc_version, __libc_release); +#else + printf("unkown\n"); +#endif + return 0; +} +EOF + LIBC="" + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null + if test "$?" = 0 ; then + ./$dummy | grep 1\.99 > /dev/null + if test "$?" = 0 ; then + LIBC="libc1" + fi + fi + rm -f $dummy.c $dummy + echo powerpc-unknown-linux-gnu${LIBC} + exit 0 + ;; + esac + + if test "${UNAME_MACHINE}" = "alpha" ; then + cat <$dummy.s + .data + \$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main + main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + LIBC="" + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + esac + + objdump --private-headers $dummy | \ + grep ld.so.1 > /dev/null + if test "$?" = 0 ; then + LIBC="libc1" + fi + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0 + elif test "${UNAME_MACHINE}" = "mips" ; then + cat >$dummy.c < /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif +#ifdef __MIPSEB__ + printf ("%s-unknown-linux-gnu\n", argv[1]); +#endif +#ifdef __MIPSEL__ + printf ("%sel-unknown-linux-gnu\n", argv[1]); +#endif + return 0; +} +EOF + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + elif test "${UNAME_MACHINE}" = "s390"; then + echo s390-ibm-linux && exit 0 + else + # Either a pre-BFD a.out linker (linux-gnuoldld) + # or one that does not give us useful --help. + # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout. + # If ld does not provide *any* "supported emulations:" + # that means it is gnuoldld. + echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:" + test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0 + + case "${UNAME_MACHINE}" in + i?86) + VENDOR=pc; + ;; + *) + VENDOR=unknown; + ;; + esac + # Determine whether the default compiler is a.out or elf + cat >$dummy.c < +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif +#ifdef __ELF__ +# ifdef __GLIBC__ +# if __GLIBC__ >= 2 + printf ("%s-${VENDOR}-linux-gnu\n", argv[1]); +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +#else + printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]); +#endif + return 0; +} +EOF + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + fi ;; +# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions +# are messed up and put the nodename in both sysname and nodename. + i?86:DYNIX/ptx:4*:*) + echo i386-sequent-sysv4 + exit 0 ;; + i?86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit 0 ;; + i?86:*:5:7*) + # Fixed at (any) Pentium or better + UNAME_MACHINE=i586 + if [ ${UNAME_SYSTEM} = "UnixWare" ] ; then + echo ${UNAME_MACHINE}-sco-sysv${UNAME_RELEASE}uw${UNAME_VERSION} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} + fi + exit 0 ;; + i?86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + i?86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i?86:LynxOS:2.*:* | i?86:LynxOS:3.[01]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:*:6*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + Power*:Mac*OS:*:*) + echo powerpc-apple-macos${UNAME_RELEASE} + exit 0 ;; + *:Mac*OS:*:*) + echo ${UNAME_MACHINE}-apple-macos${UNAME_RELEASE} + exit 0 ;; + *:QNX:*:4*) + echo i386-qnx-qnx${UNAME_VERSION} + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +#if !defined (ultrix) + printf ("vax-dec-bsd\n"); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0 +rm -f $dummy.c $dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +#echo '(Unable to guess system type)' 1>&2 + +exit 1 diff --git a/host/config.sub b/host/config.sub new file mode 100644 --- /dev/null +++ b/host/config.sub @@ -0,0 +1,1250 @@ +#! /bin/sh +# Configuration validation subroutine script, version 1.1. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 +# Free Software Foundation, Inc. +# +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Written by Per Bothner . +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +if [ x$1 = x ] +then + echo Configuration name missing. 1>&2 + echo "Usage: $0 CPU-MFR-OPSYS" 1>&2 + echo "or $0 ALIAS" 1>&2 + echo where ALIAS is a recognized configuration type. 1>&2 + exit 1 +fi + +# First pass through any local machine types. +case $1 in + *local*) + echo $1 + exit 0 + ;; + *) + ;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + linux-gnu*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \ + | arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \ + | 580 | i960 | h8300 \ + | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \ + | alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \ + | alphaev6[78] \ + | we32k | ns16k | clipper | i370 | sh | powerpc | powerpcle \ + | 1750a | dsp16xx | pdp11 | mips16 | mips64 | mipsel | mips64el \ + | mips64orion | mips64orionel | mipstx39 | mipstx39el \ + | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \ + | mips64vr5000 | miprs64vr5000el | mcore \ + | sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \ + | thumb | d10v | fr30 | avr) + basic_machine=$basic_machine-unknown + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | h8500 | w65 | pj | pjl) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i[34567]86) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + # FIXME: clean up the formatting here. + vax-* | tahoe-* | i[34567]86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \ + | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \ + | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ + | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \ + | xmp-* | ymp-* \ + | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* | hppa2.0n-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \ + | alphaev6[78]-* \ + | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \ + | clipper-* | orion-* \ + | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ + | sparc64-* | sparcv9-* | sparc86x-* | mips16-* | mips64-* | mipsel-* \ + | mips64el-* | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \ + | mipstx39-* | mipstx39el-* | mcore-* \ + | f301-* | armv*-* | s390-* | sv1-* | t3e-* \ + | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \ + | thumb-* | v850-* | d30v-* | tic30-* | c30-* | fr30-* ) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-cbm + ;; + amigaos | amigados) + basic_machine=m68k-cbm + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-cbm + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | ymp) + basic_machine=ymp-cray + os=-unicos + ;; + cray2) + basic_machine=cray2-cray + os=-unicos + ;; + [ctj]90-cray) + basic_machine=c90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i[34567]86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i[34567]86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i[34567]86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i[34567]86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + i386-go32 | go32) + basic_machine=i386-unknown + os=-go32 + ;; + i386-mingw32 | mingw32) + basic_machine=i386-unknown + os=-mingw32 + ;; + i386-qnx | qnx) + basic_machine=i386-qnx + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mipsel*-linux*) + basic_machine=mipsel-unknown + os=-linux-gnu + ;; + mips*-linux*) + basic_machine=mips-unknown + os=-linux-gnu + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + msdos) + basic_machine=i386-unknown + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + np1) + basic_machine=np1-gould + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexen) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexen-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=rs6000-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sparclite-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=t3e-cray + os=-unicos + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xmp) + basic_machine=xmp-cray + os=-unicos + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + mips) + if [ x$os = x-linux-gnu ]; then + basic_machine=mips-unknown + else + basic_machine=mips-mips + fi + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sparc | sparcv9) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + c4x*) + basic_machine=c4x-none + os=-coff + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -rhapsody* | -opened* | -openstep* | -oskit*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -ns2 ) + os=-nextstep2 + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -qnx) + os=-qnx4 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -*MiNT) + os=-mint + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f301-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -*MiNT) + vendor=atari + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os diff --git a/host/configure b/host/configure new file mode 100644 --- /dev/null +++ b/host/configure @@ -0,0 +1,2080 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer" +ac_help="$ac_help + --enable-debug do a debug rather than a release build" +ac_help="$ac_help + --enable-ansi Do an ANSI rather than a unicode build" +ac_help="$ac_help + --disable-asserts disable all assertions" +ac_help="$ac_help + --disable-preconditions disable a subset of the assertions" +ac_help="$ac_help + --disable-postconditions disable a subset of the assertions" +ac_help="$ac_help + --disable-invariants disable a subset of the assertions" +ac_help="$ac_help + --disable-loopinvariants disable a subset of the assertions" +ac_help="$ac_help + --disable-tracing disable tracing" +ac_help="$ac_help + --disable-fntracing disable function entry/exit tracing" +ac_help="$ac_help + --with-tcl-version= version of Tcl to be used" +ac_help="$ac_help + --with-tcl= location of Tcl header and libraries" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=config.guess + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:576: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:608: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 +echo "configure:661: checking whether build environment is sane" >&5 +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "$*" != "X $srcdir/configure conftestfile" \ + && test "$*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { echo "configure: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" 1>&2; exit 1; } + fi + + test "$2" = conftestfile + ) +then + # Ok. + : +else + { echo "configure: error: newly created file is older than distributed files! +Check your system clock" 1>&2; exit 1; } +fi +rm -f conftest* +echo "$ac_t""yes" 1>&6 +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:718: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +PACKAGE=eCos + +VERSION=2.0 + +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } +fi + + + +missing_dir=`cd $ac_aux_dir && pwd` +echo $ac_n "checking for working aclocal""... $ac_c" 1>&6 +echo "configure:757: checking for working aclocal" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (aclocal --version) < /dev/null > /dev/null 2>&1; then + ACLOCAL=aclocal + echo "$ac_t""found" 1>&6 +else + ACLOCAL="$missing_dir/missing aclocal" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 +echo "configure:770: checking for working autoconf" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoconf --version) < /dev/null > /dev/null 2>&1; then + AUTOCONF=autoconf + echo "$ac_t""found" 1>&6 +else + AUTOCONF="$missing_dir/missing autoconf" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working automake""... $ac_c" 1>&6 +echo "configure:783: checking for working automake" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (automake --version) < /dev/null > /dev/null 2>&1; then + AUTOMAKE=automake + echo "$ac_t""found" 1>&6 +else + AUTOMAKE="$missing_dir/missing automake" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 +echo "configure:796: checking for working autoheader" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoheader --version) < /dev/null > /dev/null 2>&1; then + AUTOHEADER=autoheader + echo "$ac_t""found" 1>&6 +else + AUTOHEADER="$missing_dir/missing autoheader" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 +echo "configure:809: checking for working makeinfo" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (makeinfo --version) < /dev/null > /dev/null 2>&1; then + MAKEINFO=makeinfo + echo "$ac_t""found" 1>&6 +else + MAKEINFO="$missing_dir/missing makeinfo" + echo "$ac_t""missing" 1>&6 +fi + + +echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6 +echo "configure:823: checking whether to enable maintainer-specific portions of Makefiles" >&5 + # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then + enableval="$enable_maintainer_mode" + USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + echo "$ac_t""$USE_MAINTAINER_MODE" 1>&6 + + +if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + MAINT=$MAINTAINER_MODE_TRUE + + + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:847: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6 +echo "configure:874: checking for Cygwin environment" >&5 +if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_cygwin=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_cygwin=no +fi +rm -f conftest* +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_cygwin" 1>&6 +CYGWIN= +test "$ac_cv_cygwin" = yes && CYGWIN=yes +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:909: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:939: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:990: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:1022: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 1033 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:1038: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:1064: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:1069: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:1097: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1133: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CXX="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CXX="$ac_cv_prog_CXX" +if test -n "$CXX"; then + echo "$ac_t""$CXX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$CXX" && break +done +test -n "$CXX" || CXX="gcc" + + +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:1165: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 + +ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + +cat > conftest.$ac_ext << EOF + +#line 1176 "configure" +#include "confdefs.h" + +int main(){return(0);} +EOF +if { (eval echo configure:1181: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cxx_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cxx_cross=no + else + ac_cv_prog_cxx_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cxx_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6 +if test $ac_cv_prog_cxx_works = no; then + { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:1207: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6 +cross_compiling=$ac_cv_prog_cxx_cross + +echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 +echo "configure:1212: checking whether we are using GNU C++" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.C <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gxx=yes +else + ac_cv_prog_gxx=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gxx" 1>&6 + +if test $ac_cv_prog_gxx = yes; then + GXX=yes +else + GXX= +fi + +ac_test_CXXFLAGS="${CXXFLAGS+set}" +ac_save_CXXFLAGS="$CXXFLAGS" +CXXFLAGS= +echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6 +echo "configure:1240: checking whether ${CXX-g++} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.cc +if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then + ac_cv_prog_cxx_g=yes +else + ac_cv_prog_cxx_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6 +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS="$ac_save_CXXFLAGS" +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi + +echo $ac_n "checking for object suffix""... $ac_c" 1>&6 +echo "configure:1272: checking for object suffix" >&5 +if eval "test \"`echo '$''{'ac_cv_objext'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + rm -f conftest* +echo 'int i = 1;' > conftest.$ac_ext +if { (eval echo configure:1278: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + for ac_file in conftest.*; do + case $ac_file in + *.c) ;; + *) ac_cv_objext=`echo $ac_file | sed -e s/conftest.//` ;; + esac + done +else + { echo "configure: error: installation or configuration problem; compiler does not work" 1>&2; exit 1; } +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_objext" 1>&6 +OBJEXT=$ac_cv_objext +ac_objext=$ac_cv_objext + +echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6 +echo "configure:1296: checking for mingw32 environment" >&5 +if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_mingw32=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_mingw32=no +fi +rm -f conftest* +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_mingw32" 1>&6 +MINGW32= +test "$ac_cv_mingw32" = yes && MINGW32=yes + + +echo $ac_n "checking for executable suffix""... $ac_c" 1>&6 +echo "configure:1327: checking for executable suffix" >&5 +if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$CYGWIN" = yes || test "$MINGW32" = yes; then + ac_cv_exeext=.exe +else + rm -f conftest* + echo 'int main () { return 0; }' > conftest.$ac_ext + ac_cv_exeext= + if { (eval echo configure:1337: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + for file in conftest.*; do + case $file in + *.c | *.o | *.obj | *.ilk | *.pdb) ;; + *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;; + esac + done + else + { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; } + fi + rm -f conftest* + test x"${ac_cv_exeext}" = x && ac_cv_exeext=no +fi +fi + +EXEEXT="" +test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext} +echo "$ac_t""${ac_cv_exeext}" 1>&6 +ac_exeext=$EXEEXT + + + + + + echo $ac_n "checking "for Visual C++"""... $ac_c" 1>&6 +echo "configure:1362: checking "for Visual C++"" >&5 + MSVC="no"; + if test "${CC}" = "cl" ; then + MSVC="yes" + fi + if test "${CXX}" = "cl" ; then + MSVC="yes" + fi + + +if test "${MSVC}" = "yes"; then + MSVC_TRUE= + MSVC_FALSE='#' +else + MSVC_TRUE='#' + MSVC_FALSE= +fi + echo "$ac_t""${MSVC}" 1>&6 + + +if test "${cross_compiling}" = "yes"; then + { echo "configure: error: cross-compilation of this package is not supported" 1>&2; exit 1; } +fi + + + + + + + echo $ac_n "checking "the default compiler flags"""... $ac_c" 1>&6 +echo "configure:1392: checking "the default compiler flags"" >&5 + + cygflags_enable_debug="no" + # Check whether --enable-debug or --disable-debug was given. +if test "${enable_debug+set}" = set; then + enableval="$enable_debug" + case "${enableval}" in + yes) cygflags_enable_debug="yes" ;; + *) cygflags_enable_debug="no" ;; + esac +fi + + + cygflags_enable_ansi="no" + if test "${MSVC}" = "yes" ; then + # Check whether --enable-ansi or --disable-ansi was given. +if test "${enable_ansi+set}" = set; then + enableval="$enable_ansi" + case "${enableval}" in + yes) cygflags_enable_ansi="yes" ;; + *) cygflags_enable_ansi="no" ;; + esac +fi + + fi + + if test "${GCC}" = "yes" ; then + CC="$CC -Wall -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs" + CXX="$CXX -Wall -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Woverloaded-virtual" + elif test "${MSVC}" = "yes" ; then + CC="$CC -nologo -W3" + CXX="$CXX -nologo -W3 -GR -GX" + if test "${cygflags_enable_debug}" = "yes" ; then + CC="$CC -MDd -Zi" + CXX="$CXX -MDd -Zi" + else + CC="$CC -MD -O2" + CXX="$CXX -MD -O2" + fi + else + { echo "configure: error: "default flags for ${CC} are not known"" 1>&2; exit 1; } + fi + echo "$ac_t""done" 1>&6 + + + + + +if test "${cygflags_enable_debug}" = "yes" ; then + cyginfra_asserts=yes + cyginfra_preconditions=yes + cyginfra_postconditions=yes + cyginfra_invariants=yes + cyginfra_loopinvariants=yes + cyginfra_tracing=yes + cyginfra_fntracing=yes +else + cyginfra_asserts=no + cyginfra_preconditions=no + cyginfra_postconditions=no + cyginfra_invariants=no + cyginfra_loopinvariants=no + cyginfra_tracing=no + cyginfra_fntracing=no +fi + +# Check whether --enable-asserts or --disable-asserts was given. +if test "${enable_asserts+set}" = set; then + enableval="$enable_asserts" + case "${enableval}" in + yes) cyginfra_asserts=yes ;; + no) cyginfra_asserts=no ;; + *) { echo "configure: error: bad value ${enableval} for disable-asserts option" 1>&2; exit 1; } ;; +esac +fi + +if test "${cyginfra_asserts}" = "yes"; then + cat >> confdefs.h <<\EOF +#define CYGDBG_USE_ASSERTS 1 +EOF + +fi + +# Check whether --enable-preconditions or --disable-preconditions was given. +if test "${enable_preconditions+set}" = set; then + enableval="$enable_preconditions" + case "${enableval}" in + yes) cyginfra_preconditions=yes ;; + no) cyginfra_preconditions=no ;; + *) { echo "configure: error: bad value ${enableval} for disable-preconditions option" 1>&2; exit 1; } ;; +esac +fi + +if test "${cyginfra_preconditions}" = "yes"; then + cat >> confdefs.h <<\EOF +#define CYGDBG_INFRA_DEBUG_PRECONDITIONS 1 +EOF + +fi + +# Check whether --enable-postconditions or --disable-postconditions was given. +if test "${enable_postconditions+set}" = set; then + enableval="$enable_postconditions" + case "${enableval}" in + yes) cyginfra_postconditions=yes ;; + no) cyginfra_postconditions=no ;; + *) { echo "configure: error: bad value ${enableval} for disable-postconditions option" 1>&2; exit 1; } ;; +esac +fi + +if test "${cyginfra_postconditions}" = "yes"; then + cat >> confdefs.h <<\EOF +#define CYGDBG_INFRA_DEBUG_POSTCONDITIONS 1 +EOF + +fi + +# Check whether --enable-invariants or --disable-invariants was given. +if test "${enable_invariants+set}" = set; then + enableval="$enable_invariants" + case "${enableval}" in + yes) cyginfra_invariants=yes ;; + no) cyginfra_invariants=no ;; + *) { echo "configure: error: bad value ${enableval} for disable-invariants option" 1>&2; exit 1; } ;; +esac +fi + +if test "${cyginfra_invariants}" = "yes"; then + cat >> confdefs.h <<\EOF +#define CYGDBG_INFRA_DEBUG_INVARIANTS 1 +EOF + +fi + +# Check whether --enable-loopinvariants or --disable-loopinvariants was given. +if test "${enable_loopinvariants+set}" = set; then + enableval="$enable_loopinvariants" + case "${enableval}" in + yes) cyginfra_loopinvariants=yes ;; + no) cyginfra_loopinvariants=no ;; + *) { echo "configure: error: bad value ${enableval} for disable-loopinvariants option" 1>&2; exit 1; } ;; +esac +fi + +if test "${cyginfra_loopinvariants}" = "yes"; then + cat >> confdefs.h <<\EOF +#define CYGDBG_INFRA_DEBUG_LOOP_INVARIANTS 1 +EOF + +fi + +# Check whether --enable-tracing or --disable-tracing was given. +if test "${enable_tracing+set}" = set; then + enableval="$enable_tracing" + case "${enableval}" in + yes) cyginfra_tracing=yes ;; + no) cyginfra_tracing=no ;; + *) { echo "configure: error: bad value ${enableval} for disable-tracing option" 1>&2; exit 1; } ;; +esac +fi + +if test "${cyginfra_tracing}" = "yes"; then + cat >> confdefs.h <<\EOF +#define CYGDBG_USE_TRACING 1 +EOF + +fi + +# Check whether --enable-fntracing or --disable-fntracing was given. +if test "${enable_fntracing+set}" = set; then + enableval="$enable_fntracing" + case "${enableval}" in + yes) cyginfra_fntracing=yes ;; + no) cyginfra_fntracing=no ;; + *) { echo "configure: error: bad value ${enableval} for disable-fntracing option" 1>&2; exit 1; } ;; +esac +fi + +if test "${cyginfra_fntracing}" = "yes"; then + cat >> confdefs.h <<\EOF +#define CYGDBG_INFRA_DEBUG_FUNCTION_REPORTS 1 +EOF + +fi + + + + + + + + + +echo $ac_n "checking for Tcl version""... $ac_c" 1>&6 +echo "configure:1586: checking for Tcl version" >&5 +# Check whether --with-tcl-version or --without-tcl-version was given. +if test "${with_tcl_version+set}" = set; then + withval="$with_tcl_version" + + cyg_ac_tcl_version=${with_tcl_version} + +else + + if test "${MSVC}" = "yes" ; then + cyg_ac_tcl_version=80 + else + if test "${ac_cv_cygwin}" = "yes" ; then + cyg_ac_tcl_version=80 + else + cyg_ac_tcl_version="" + fi + fi + +fi + +echo "$ac_t""${cyg_ac_tcl_version}" 1>&6 + + +echo $ac_n "checking for Tcl installation""... $ac_c" 1>&6 +echo "configure:1611: checking for Tcl installation" >&5 +# Check whether --with-tcl or --without-tcl was given. +if test "${with_tcl+set}" = set; then + withval="$with_tcl" + + cyg_ac_tcl_incdir=${with_tcl}/include + cyg_ac_tcl_libdir=${with_tcl}/lib + +else + + cyg_ac_tcl_incdir=${prefix}/include + cyg_ac_tcl_libdir=${prefix}/lib + +fi + +echo "$ac_t""${cyg_ac_tcl_libdir}" 1>&6 + +if test \! -r ${cyg_ac_tcl_incdir}/tcl.h ; then + { echo "configure: error: unable to locate Tcl header file tcl.h" 1>&2; exit 1; } +fi + +if test "${MSVC}" = "yes" ; then + cyg_ac_tcl_libs="tcl${cyg_ac_tcl_version}.lib" + + + + + if test "${MSVC}" = "yes" ; then + cyg_ac_tcl_incdir=`cygpath -w ${cyg_ac_tcl_incdir} | tr \\\\\\\\ /` + fi + + + + + + if test "${MSVC}" = "yes" ; then + cyg_ac_tcl_libdir=`cygpath -w ${cyg_ac_tcl_libdir} | tr \\\\\\\\ /` + fi + +else + if test \! -r ${cyg_ac_tcl_libdir}/tclConfig.sh ; then + { echo "configure: error: unable to locate Tcl config file tclConfig.sh" 1>&2; exit 1; } + else + . ${cyg_ac_tcl_libdir}/tclConfig.sh + cyg_ac_tcl_libs="-ltcl${cyg_ac_tcl_version} ${TCL_LIBS}" + fi +fi + + + + + + + +ECOS_DIRS="infra libcdl" + + + + +if test -f ${srcdir}/tools/ecostest/common/configure; then + ECOS_DIRS="${ECOS_DIRS} tools/ecostest/common" + +fi + +if test -d ${srcdir}/tools/configtool/standalone/common; then + ECOS_DIRS="${ECOS_DIRS} tools/configtool/standalone/common" + +fi + + +subdirs="${ECOS_DIRS}" + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +cat > conftest.defs <<\EOF +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g +s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g +s%\[%\\&%g +s%\]%\\&%g +s%\$%$$%g +EOF +DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` +rm -f conftest.defs + + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@host@%$host%g +s%@host_alias@%$host_alias%g +s%@host_cpu@%$host_cpu%g +s%@host_vendor@%$host_vendor%g +s%@host_os@%$host_os%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@PACKAGE@%$PACKAGE%g +s%@VERSION@%$VERSION%g +s%@ACLOCAL@%$ACLOCAL%g +s%@AUTOCONF@%$AUTOCONF%g +s%@AUTOMAKE@%$AUTOMAKE%g +s%@AUTOHEADER@%$AUTOHEADER%g +s%@MAKEINFO@%$MAKEINFO%g +s%@SET_MAKE@%$SET_MAKE%g +s%@MAINTAINER_MODE_TRUE@%$MAINTAINER_MODE_TRUE%g +s%@MAINTAINER_MODE_FALSE@%$MAINTAINER_MODE_FALSE%g +s%@MAINT@%$MAINT%g +s%@CC@%$CC%g +s%@CXX@%$CXX%g +s%@OBJEXT@%$OBJEXT%g +s%@EXEEXT@%$EXEEXT%g +s%@MSVC_TRUE@%$MSVC_TRUE%g +s%@MSVC_FALSE@%$MSVC_FALSE%g +s%@cyg_ac_tcl_version@%$cyg_ac_tcl_version%g +s%@cyg_ac_tcl_incdir@%$cyg_ac_tcl_incdir%g +s%@cyg_ac_tcl_libdir@%$cyg_ac_tcl_libdir%g +s%@cyg_ac_tcl_libs@%$cyg_ac_tcl_libs%g +s%@cyg_ac_tk_libs@%$cyg_ac_tk_libs%g +s%@ECOS_DIRS@%$ECOS_DIRS%g +s%@subdirs@%$subdirs%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + + test -d tools || mkdir tools + test -d tools/ecostest || mkdir tools/ecostest + test -d tools/ecostest/common || mkdir tools/ecostest/common + + + test -d tools || mkdir tools + test -d tools/configtool || mkdir tools/configtool + test -d tools/configtool/standalone || mkdir tools/configtool/standalone + test -d tools/configtool/standalone/common || mkdir tools/configtool/standalone/common + + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + +if test "$no_recursion" != yes; then + + # Remove --cache-file and --srcdir arguments so they do not pile up. + ac_sub_configure_args= + ac_prev= + for ac_arg in $ac_configure_args; do + if test -n "$ac_prev"; then + ac_prev= + continue + fi + case "$ac_arg" in + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + *) ac_sub_configure_args="$ac_sub_configure_args $ac_arg" ;; + esac + done + + for ac_config_dir in ${ECOS_DIRS}; do + + # Do not complain, so a configure script can configure whichever + # parts of a large source tree are present. + if test ! -d $srcdir/$ac_config_dir; then + continue + fi + + echo configuring in $ac_config_dir + + case "$srcdir" in + .) ;; + *) + if test -d ./$ac_config_dir || mkdir ./$ac_config_dir; then :; + else + { echo "configure: error: can not create `pwd`/$ac_config_dir" 1>&2; exit 1; } + fi + ;; + esac + + ac_popdir=`pwd` + cd $ac_config_dir + + # A "../" for each directory in /$ac_config_dir. + ac_dots=`echo $ac_config_dir|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'` + + case "$srcdir" in + .) # No --srcdir option. We are building in place. + ac_sub_srcdir=$srcdir ;; + /*) # Absolute path. + ac_sub_srcdir=$srcdir/$ac_config_dir ;; + *) # Relative path. + ac_sub_srcdir=$ac_dots$srcdir/$ac_config_dir ;; + esac + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_sub_srcdir/configure; then + ac_sub_configure=$ac_sub_srcdir/configure + elif test -f $ac_sub_srcdir/configure.in; then + ac_sub_configure=$ac_configure + else + echo "configure: warning: no configuration information is in $ac_config_dir" 1>&2 + ac_sub_configure= + fi + + # The recursion is here. + if test -n "$ac_sub_configure"; then + + # Make the cache file name correct relative to the subdirectory. + case "$cache_file" in + /*) ac_sub_cache_file=$cache_file ;; + *) # Relative path. + ac_sub_cache_file="$ac_dots$cache_file" ;; + esac + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo "running ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir" + # The eval makes quoting arguments work. + if eval ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir + then : + else + { echo "configure: error: $ac_sub_configure failed for $ac_config_dir" 1>&2; exit 1; } + fi + fi + + cd $ac_popdir + done +fi + diff --git a/host/configure.in b/host/configure.in new file mode 100644 --- /dev/null +++ b/host/configure.in @@ -0,0 +1,163 @@ +dnl Process this file with autoconf to produce a configure script. +dnl ==================================================================== +dnl +dnl configure.in +dnl +dnl Top-level configure script for eCos host-side software. +dnl +dnl ==================================================================== +dnl####COPYRIGHTBEGIN#### +dnl +dnl ---------------------------------------------------------------------------- +dnl Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +dnl +dnl This file is part of the eCos host tools. +dnl +dnl This program is free software; you can redistribute it and/or modify it +dnl under the terms of the GNU General Public License as published by the Free +dnl Software Foundation; either version 2 of the License, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but WITHOUT +dnl ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +dnl FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +dnl more details. +dnl +dnl You should have received a copy of the GNU General Public License along with +dnl this program; if not, write to the Free Software Foundation, Inc., +dnl 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl ---------------------------------------------------------------------------- +dnl +dnl####COPYRIGHTEND#### +dnl ==================================================================== +dnl#####DESCRIPTIONBEGIN#### +dnl +dnl Author(s): bartv +dnl Contact(s): bartv +dnl Date: 1998/12/17 +dnl Version: 0.01 +dnl +dnl####DESCRIPTIONEND#### +dnl ==================================================================== + +AC_INIT(config.guess) +AC_CANONICAL_HOST +AM_INIT_AUTOMAKE(eCos,2.0,0) +AM_MAINTAINER_MODE + +dnl Some of the decisions made depend on the compiler that is being used, +dnl so the usual set of compiler-related macros is needed here. +AC_PROG_MAKE_SET +AC_CYGWIN +AC_PROG_CC +AC_PROG_CXX +AC_OBJEXT +AC_EXEEXT +CYG_AC_PROG_MSVC + +dnl The eCos host-side only supports native builds, not cross-compilation. +dnl Cross-compilation should not be impossible, but various macros +dnl including testing for 64-bit require the ability to run code. +if test "${cross_compiling}" = "yes"; then + AC_MSG_ERROR(cross-compilation of this package is not supported) +fi + +dnl Allow the usual assertion and trace related options. +CYG_AC_ARG_INFRASTRUCTURE + +dnl What version of Tcl should be used? +CYG_AC_PATH_TCL + +dnl Some of the packages are compulsory and do not depend on the compiler +dnl that is being used. Other packages are only applicable to specific +dnl compilers, and in addition it should be possible to enable or +dnl disable them as convenient. +dnl +dnl The host-side infrastructure and libcdl are always needed. +ECOS_DIRS="infra libcdl" + +dnl -------------------------------------------------------------------- +dnl Experimental support for building the configtool in the autoconf +dnl world. This is not yet functional, so it is all commented out. + +dnl dnl Building of the standalone configtool and the configtool plugin +dnl dnl can be controlled by the user. The plugin is normally disabled, +dnl dnl unless the user specifies that IDE support is necessary. +dnl +dnl AC_ARG_ENABLE(standalone-configtool,[--enable-standalone-configtool enable the stand-alone configtool], +dnl [case "${enableval}" in +dnl yes) ecosflags_enable_standalone_configtool="yes" ;; +dnl *) ecosflags_enable_standalone_configtool="no" ;; +dnl esac +dnl ],[ +dnl ecosflags_enable_standalone_configtool="yes" +dnl ]) +dnl AC_ARG_ENABLE(configtool-plugin,[ --enable-configtool-plugin enable the IDE configtool plugin], +dnl [case "${enableval}" in +dnl yes) ecosflags_enable_configtool-plugin="yes" ;; +dnl *) ecosflags_enable_configtool-plugin="no" ;; +dnl esac +dnl ],[ +dnl ecosflags_enable_configtool_plugin="no" +dnl ]) +dnl +dnl dnl Initially only VC++ versions of the configtool are available. +dnl dnl If using another compiler then just disable these tools. +dnl if test "${MSVC}" = "no"; then +dnl ecosflags_enable_standalone_configtool="no" +dnl ecosflags_enable_configtool_plugin="no" +dnl fi +dnl +dnl if test "${ecosflags_enable_standalone_configtool}" = "yes"; then +dnl ECOS_DIRS="${ECOS_DIRS} tools/configtool/standalone/win32" +dnl fi +dnl AC_OUTPUT_COMMANDS([ +dnl if test "${ecosflags_enable_standalone_configtool}" = "yes"; then +dnl test -d tools || mkdir tools +dnl test -d tools/configtool || mkdir tools/configtool +dnl test -d tools/configtool/standalone || mkdir tools/configtool/standalone +dnl test -d tools/configtool/standalone/win32 || mkdir tools/configtool/standalone/win32 +dnl fi +dnl ],[ +dnl ecosflags_enable_standalone_configtool=${ecosflags_enable_standalone_configtool} +dnl ]) +dnl if test "${ecosflags_enable_configtool_plugin}" = "yes"; then +dnl ECOS_DIRS="${ECOS_DIRS} tools/configtool/plugin/win32" +dnl fi +dnl AC_OUTPUT_COMMANDS([ +dnl if test "${ecosflags_enable_configtool_plugin}" = "yes"; then +dnl test -d tools || mkdir tools +dnl test -d tools/configtool || mkdir tools/configtool +dnl test -d tools/configtool/plugin || mkdir tools/configtool/plugin +dnl test -d tools/configtool/plugin/win32 || mkdir tools/configtool/plugin/win32 +dnl fi +dnl ],[ +dnl ecosflags_enable_configtool_plugin=${ecosflags_enable_configtool_plugin} +dnl ]) + +dnl -------------------------------------------------------------------- + +dnl Add any other directories that are autoconfiscated and present +if test -f ${srcdir}/tools/ecostest/common/configure; then + ECOS_DIRS="${ECOS_DIRS} tools/ecostest/common" + AC_OUTPUT_COMMANDS([ + test -d tools || mkdir tools + test -d tools/ecostest || mkdir tools/ecostest + test -d tools/ecostest/common || mkdir tools/ecostest/common + ]) +fi + +if test -d ${srcdir}/tools/configtool/standalone/common; then + ECOS_DIRS="${ECOS_DIRS} tools/configtool/standalone/common" + AC_OUTPUT_COMMANDS([ + test -d tools || mkdir tools + test -d tools/configtool || mkdir tools/configtool + test -d tools/configtool/standalone || mkdir tools/configtool/standalone + test -d tools/configtool/standalone/common || mkdir tools/configtool/standalone/common + ]) +fi + +AC_SUBST(ECOS_DIRS) +AC_CONFIG_SUBDIRS(${ECOS_DIRS}) +AC_OUTPUT(Makefile) diff --git a/host/infra/ChangeLog b/host/infra/ChangeLog new file mode 100644 --- /dev/null +++ b/host/infra/ChangeLog @@ -0,0 +1,150 @@ +1999-08-12 Bart Veer + + * configure: + * stamp-h.in: + * hosttest.exp: + First attempt at autoconfiscating the configtool + +1999-07-05 Bart Veer + + * assert.cxx: + Added new function cyg_assert_quickfail(), to facilitate + generating a dump file from inside gdb. + +1999-06-03 Bart Veer + + * configure: + Regenerated after more updates to toplevel acinclude.m4 + +1999-06-02 Bart Veer + + * configure: + Updated toplevel acinclude.m4 to add --enable-debuginfo option. + +1999-04-13 Bart Veer + + * testsuite/Makefile.am: + * trace.cxx: + * infra.h: + * checkdata.cxx: + * basetype.h: + * assert.cxx: + Updated copyright banner + +1999-03-02 Bart Veer + + * testcase.cxx (cyg_test_output): + Update to match earlier testcase.h header file change + (new status codes GDBCMD and NA, change from int to enum) + +1999-01-26 Bart Veer + + * Makefile.in: + * aclocal.m4: + * configure: + * Makefile.in: + Update to use autoconf 2.13 and automake 1.4, plus to + reflect tweaks to toplevel acinclude.m4 + + * hosttest.exp: + Improve the way compiler and linker diagnostics get handled. + +1999-01-21 Jonathan Larmour + + * basetype.h: + Remove all traces of non-CYG_KERNEL_USE_INIT_PRIORITY code + +1999-01-21 Bart Veer + + * acconfig.h: + * configure.in: + * infra.h: + Use new macro CYG_AC_SUBST_VERSION to generate a version + symbol CYGNUM_INFRA_VERSION + +1999-01-19 Bart Veer + + * hosttest.exp: + Allow makefile variable assignments of the form := as well as = + + * trace.cxx (parse_msg): + Fixed off-by-one error in output formatting, and "improved" the + way function names get displayed. + +1999-01-11 Bart Veer + + * testcase.cxx (cyg_test_output): + Use const where appropriate. + +1999-01-07 Bart Veer + + * testsuite/cyginfra/trace.exp: + * testsuite/cyginfra/ttrace4.cxx: + Added new testcase + + * testsuite/cyginfra/tassert7.cxx (main): + * testsuite/cyginfra/tassert6.cxx (main): + Eliminate warning about possible setjmp() side effects. + + * trace.cxx (trace_callback): + Off by one error when dumping a trace vector. + + * hosttest.exp: + Relative paths in include and library search paths were causing + problems. + The wrong Makefile was being examined for variable settings. + +1999-01-06 Bart Veer + + * testsuite/cyginfra/trace.exp: + * testsuite/cyginfra/ttrace1.cxx: + * testsuite/cyginfra/ttrace2.cxx: + * testsuite/cyginfra/ttrace3.cxx: + New test cases + + * testsuite/config/default.exp: + There was an easier way to get hold of hosttest.exp + + * hosttest.exp: + Reordered compile and link command lines so as to pick up the + correct versions of the libraries. + Allow packages to extract information from the Makefile + + * trace.cxx: + Initialisation via static object constructors did not work, + constructor priority ordering problems. + + * assert.cxx (default_handler): + Removed spurious debugging lines. + + * Makefile.am (install-exec-local): + Tweaks needed for MSVC + +1998-12-24 Bart Veer + + * First check-in of host-side infrastructure. + +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### diff --git a/host/infra/Makefile.am b/host/infra/Makefile.am new file mode 100644 --- /dev/null +++ b/host/infra/Makefile.am @@ -0,0 +1,209 @@ +## Process this file with automake to produce Makefile.in +## ===================================================================== +## +## Makefile.am +## +## Host side implementation of the eCos infrastructure +## +## ===================================================================== +######COPYRIGHTBEGIN#### +## +## ---------------------------------------------------------------------------- +## Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +## +## This file is part of the eCos host tools. +## +## This program is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 of the License, or (at your option) +## any later version. +## +## This program is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +## more details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +## +## ---------------------------------------------------------------------------- +## +######COPYRIGHTEND#### +## ===================================================================== +#######DESCRIPTIONBEGIN#### +## +## Author(s): bartv +## Contact(s): bartv +## Date: 1998/07/13 +## Version: 0.01 +## +######DESCRIPTIONEND#### +## ===================================================================== + +AUTOMAKE_OPTIONS = 1.3 cygnus +SUBDIRS = testsuite + +## The generated makefile is responsible for the following: +## +## 1) copy across the shared header files cyg_type.h, cyg_ass.h and +## cyg_trac.h from the include directory into the appropriate part +## of the build tree. +## +## 2) on the target side the infrastructure headers depend on +## the configuration system via , and on the +## HAL package via . These two files need +## to be implemented somewhat differently on the host side. +## There are usable versions in the source tree. +## +## 3) build libcyginfra.a +## +## 4) allow the whole system to be installed, and all the usual +## makefile targets. + +## The main target is a static library. The problem is naming it +## correctly. automake seems to insist on calling it libcyginfra.a, +## even when compiling it with VC++. Various attempts to use +## cyginfra.lib instead with VC++ have failed. Instead the library +## will always be built as libcyginfra.a, but it may get installed +## as cyginfra.lib. + +noinst_LIBRARIES = libcyginfra.a +libcyginfra_a_SOURCES = assert.cxx \ + trace.cxx \ + checkdata.cxx \ + testcase.cxx + +if MSVC +all-local: cyginfra.lib + +cyginfra.lib: libcyginfra.a + $(INSTALL) $< $@ + +clean-local: + $(RM) cyginfra.lib + +install-exec-local: all-local + $(mkinstalldirs) $(DESTDIR)$(libdir) + $(INSTALL) cyginfra.lib $(DESTDIR)$(libdir)/cyginfra.lib + +else + +all-local: +clean-local: + +install-exec-local: libcyginfra.a + $(mkinstalldirs) $(DESTDIR)$(libdir) + $(INSTALL) libcyginfra.a $(DESTDIR)$(libdir)/libcyginfra.a + +endif + +## ---------------------------------------------------------------------------- +## The header files do not all belong in the same directory. This +## causes problems with automake. First list the header files. + +copies = cyg/infra/cyg_type.h \ + cyg/infra/cyg_ass.h \ + cyg/infra/cyg_trac.h \ + cyg/infra/testcase.h \ + cyg/hal/basetype.h \ + pkgconf/infra.h \ + pkgconf/hostinfra.h \ + hosttest.exp + +## The headers are not installed as part of the default install +## target, instead a data hook is used. This avoids problems when the +## appropriate directories do not yet exist in the install tree. +noinst_HEADERS = $(copies) + +install-data-local: $(copies) + $(mkinstalldirs) $(DESTDIR)$(includedir) \ + $(DESTDIR)$(includedir)/cyg \ + $(DESTDIR)$(includedir)/cyg/infra \ + $(DESTDIR)$(includedir)/cyg/hal \ + $(DESTDIR)$(includedir)/pkgconf + $(INSTALL_DATA) cyg/infra/cyg_type.h $(DESTDIR)$(includedir)/cyg/infra + $(INSTALL_DATA) cyg/infra/cyg_ass.h $(DESTDIR)$(includedir)/cyg/infra + $(INSTALL_DATA) cyg/infra/cyg_trac.h $(DESTDIR)$(includedir)/cyg/infra + $(INSTALL_DATA) cyg/infra/testcase.h $(DESTDIR)$(includedir)/cyg/infra + $(INSTALL_DATA) cyg/hal/basetype.h $(DESTDIR)$(includedir)/cyg/hal + $(INSTALL_DATA) pkgconf/infra.h $(DESTDIR)$(includedir)/pkgconf + $(INSTALL_DATA) pkgconf/hostinfra.h $(DESTDIR)$(includedir)/pkgconf + +## It is necessary to have an extra set of rules to copy the header files +## into the build tree, so that they are in a sensible location when +## building the sources in this package. There are explicit dependencies +## for all the object files on these headers. +## +## The header file copies should be part of the clean. +CLEANFILES = $(copies) + +cyg/infra/cyg_type.h: cyg_type.h + @if [ -d cyg ] ; then true ; else mkdir cyg ; fi + @if [ -d cyg/infra ] ; then true ; else mkdir cyg/infra ; fi + $(INSTALL_DATA) $(<) $(@) + +cyg/infra/cyg_ass.h: cyg_ass.h + @if [ -d cyg ] ; then true ; else mkdir cyg ; fi + @if [ -d cyg/infra ] ; then true ; else mkdir cyg/infra ; fi + $(INSTALL_DATA) $(<) $(@) + +cyg/infra/cyg_trac.h: cyg_trac.h + @if [ -d cyg ] ; then true ; else mkdir cyg ; fi + @if [ -d cyg/infra ] ; then true ; else mkdir cyg/infra ; fi + $(INSTALL_DATA) $(<) $(@) + +cyg/infra/testcase.h: testcase.h + @if [ -d cyg ] ; then true ; else mkdir cyg ; fi + @if [ -d cyg/infra ] ; then true ; else mkdir cyg/infra ; fi + $(INSTALL_DATA) $(<) $(@) + +pkgconf/infra.h : infra.h + @if [ -d pkgconf ] ; then true ; else mkdir pkgconf ; fi + $(INSTALL_DATA) $(<) $(@) + +pkgconf/hostinfra.h : hostinfra.h + @if [ -d pkgconf ] ; then true ; else mkdir pkgconf ; fi + $(INSTALL_DATA) $(<) $(@) + +cyg/hal/basetype.h : basetype.h + @if [ -d cyg ] ; then true ; else mkdir cyg ; fi + @if [ -d cyg/hal ] ; then true ; else mkdir cyg/hal ; fi + $(INSTALL_DATA) $(<) $(@) + +## ---------------------------------------------------------------------------- +## Add a rule for exporting hosttest.exp +dejagnudir = $(prefix)/share/dejagnu +dejagnu_DATA = hosttest.exp + +## ---------------------------------------------------------------------------- +## Add specific dependencies for all source files + +assert.$(OBJEXT) : Makefile \ + pkgconf/infra.h \ + pkgconf/hostinfra.h \ + cyg/infra/cyg_type.h \ + cyg/hal/basetype.h \ + cyg/infra/cyg_ass.h + +trace.$(OBJEXT) : Makefile \ + pkgconf/infra.h \ + pkgconf/hostinfra.h \ + cyg/infra/cyg_type.h \ + cyg/hal/basetype.h \ + cyg/infra/cyg_ass.h \ + cyg/infra/cyg_trac.h + +checkdata.$(OBJEXT) : Makefile \ + cyg/infra/cyg_ass.h \ + pkgconf/infra.h \ + pkgconf/hostinfra.h \ + cyg/infra/cyg_type.h \ + cyg/hal/basetype.h + +testcase.$(OBJEXT): Makefile \ + cyg/infra/testcase.h \ + cyg/infra/cyg_type.h \ + cyg/hal/basetype.h \ + pkgconf/infra.h \ + pkgconf/hostinfra.h diff --git a/host/infra/Makefile.in b/host/infra/Makefile.in new file mode 100644 --- /dev/null +++ b/host/infra/Makefile.in @@ -0,0 +1,574 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 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. + +######COPYRIGHTBEGIN#### +######COPYRIGHTEND#### +#######DESCRIPTIONBEGIN#### +######DESCRIPTIONEND#### + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = . + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CC = @CC@ +CXX = @CXX@ +EXEEXT = @EXEEXT@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +VERSION = @VERSION@ +cyg_ac_tcl_incdir = @cyg_ac_tcl_incdir@ +cyg_ac_tcl_libdir = @cyg_ac_tcl_libdir@ +cyg_ac_tcl_libs = @cyg_ac_tcl_libs@ +cyg_ac_tcl_version = @cyg_ac_tcl_version@ +cyg_ac_tk_libs = @cyg_ac_tk_libs@ + +AUTOMAKE_OPTIONS = 1.3 cygnus +SUBDIRS = testsuite + +noinst_LIBRARIES = libcyginfra.a +libcyginfra_a_SOURCES = assert.cxx trace.cxx checkdata.cxx testcase.cxx + + +copies = cyg/infra/cyg_type.h cyg/infra/cyg_ass.h cyg/infra/cyg_trac.h cyg/infra/testcase.h cyg/hal/basetype.h pkgconf/infra.h pkgconf/hostinfra.h hosttest.exp + + +noinst_HEADERS = $(copies) + +CLEANFILES = $(copies) + +dejagnudir = $(prefix)/share/dejagnu +dejagnu_DATA = hosttest.exp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs +CONFIG_HEADER = hostinfra.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +libcyginfra_a_LIBADD = +libcyginfra_a_OBJECTS = assert.$(OBJEXT) trace.$(OBJEXT) \ +checkdata.$(OBJEXT) testcase.$(OBJEXT) +AR = ar +CXXFLAGS = @CXXFLAGS@ +CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ +DATA = $(dejagnu_DATA) + +HEADERS = $(noinst_HEADERS) + +DIST_COMMON = ./stamp-h.in ChangeLog Makefile.am Makefile.in acconfig.h \ +acinclude.m4 aclocal.m4 config.h.in configure configure.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +SOURCES = $(libcyginfra_a_SOURCES) +OBJECTS = $(libcyginfra_a_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .cxx .o .obj .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --cygnus Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ configure.in acinclude.m4 + cd $(srcdir) && $(ACLOCAL) + +config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck +$(srcdir)/configure: @MAINTAINER_MODE_TRUE@$(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +hostinfra.h: stamp-h + @if test ! -f $@; then \ + rm -f stamp-h; \ + $(MAKE) stamp-h; \ + else :; fi +stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES= CONFIG_HEADERS=hostinfra.h:config.h.in \ + $(SHELL) ./config.status + @echo timestamp > stamp-h 2> /dev/null +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@$(srcdir)/stamp-h.in + @if test ! -f $@; then \ + rm -f $(srcdir)/stamp-h.in; \ + $(MAKE) $(srcdir)/stamp-h.in; \ + else :; fi +$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h + cd $(top_srcdir) && $(AUTOHEADER) + @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null + +mostlyclean-hdr: + +clean-hdr: + +distclean-hdr: + -rm -f hostinfra.h + +maintainer-clean-hdr: + +mostlyclean-noinstLIBRARIES: + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +distclean-noinstLIBRARIES: + +maintainer-clean-noinstLIBRARIES: + +.c.o: + $(COMPILE) -c $< + +# FIXME: We should only use cygpath when building on Windows, +# and only if it is available. +.c.obj: + $(COMPILE) -c `cygpath -w $<` + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + -rm -f *.$(OBJEXT) + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +libcyginfra.a: $(libcyginfra_a_OBJECTS) $(libcyginfra_a_DEPENDENCIES) + -rm -f libcyginfra.a + $(AR) cru libcyginfra.a $(libcyginfra_a_OBJECTS) $(libcyginfra_a_LIBADD) + $(RANLIB) libcyginfra.a +.cxx.o: + $(CXXCOMPILE) -c $< +.cxx.obj: + $(CXXCOMPILE) -c `cygpath -w $<` + +install-dejagnuDATA: $(dejagnu_DATA) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(dejagnudir) + @list='$(dejagnu_DATA)'; for p in $$list; do \ + if test -f $(srcdir)/$$p; then \ + echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(dejagnudir)/$$p"; \ + $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(dejagnudir)/$$p; \ + else if test -f $$p; then \ + echo " $(INSTALL_DATA) $$p $(DESTDIR)$(dejagnudir)/$$p"; \ + $(INSTALL_DATA) $$p $(DESTDIR)$(dejagnudir)/$$p; \ + fi; fi; \ + done + +uninstall-dejagnuDATA: + @$(NORMAL_UNINSTALL) + list='$(dejagnu_DATA)'; for p in $$list; do \ + rm -f $(DESTDIR)$(dejagnudir)/$$p; \ + done + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. + +@SET_MAKE@ + +all-recursive install-data-recursive install-exec-recursive \ +installdirs-recursive install-recursive uninstall-recursive install-info-recursive \ +check-recursive installcheck-recursive info-recursive dvi-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ + rev="$$subdir $$rev"; \ + test "$$subdir" = "." && dot_seen=yes; \ + done; \ + test "$$dot_seen" = "no" && rev=". $$rev"; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + -rm -rf $(distdir) + GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + dc_install_base=`cd $(distdir)/=inst && pwd`; \ + cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) dist + -rm -rf $(distdir) + @banner="$(distdir).tar.gz is ready for distribution"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes" +dist: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +dist-all: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +distdir: $(DISTFILES) + -rm -rf $(distdir) + mkdir $(distdir) + -chmod 777 $(distdir) + @for file in $(DISTFILES); do \ + if test -f $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + cp -pr $$/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + for subdir in $(SUBDIRS); do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + chmod 777 $(distdir)/$$subdir; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \ + || exit 1; \ + fi; \ + done +info-am: +info: info-recursive +dvi-am: +dvi: dvi-recursive +check-am: +check: check-recursive +installcheck-am: +installcheck: installcheck-recursive +install-info-am: +install-info: install-info-recursive +all-recursive-am: hostinfra.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +install-exec-am: install-exec-local +install-exec: install-exec-recursive + +install-data-am: install-dejagnuDATA install-data-local +install-data: install-data-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-recursive +uninstall-am: uninstall-dejagnuDATA +uninstall: uninstall-recursive +all-am: Makefile $(LIBRARIES) $(DATA) $(HEADERS) hostinfra.h all-local +all-redirect: all-recursive-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: installdirs-recursive +installdirs-am: + $(mkinstalldirs) $(DESTDIR)$(dejagnudir) + + +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-hdr mostlyclean-noinstLIBRARIES \ + mostlyclean-compile mostlyclean-tags \ + mostlyclean-generic + +mostlyclean: mostlyclean-recursive + +clean-am: clean-hdr clean-noinstLIBRARIES clean-compile clean-tags \ + clean-generic mostlyclean-am clean-local + +clean: clean-recursive + +distclean-am: distclean-hdr distclean-noinstLIBRARIES distclean-compile \ + distclean-tags distclean-generic clean-am + +distclean: distclean-recursive + -rm -f config.status + +maintainer-clean-am: maintainer-clean-hdr \ + maintainer-clean-noinstLIBRARIES \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-recursive + -rm -f config.status + +.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \ +mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ +clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile uninstall-dejagnuDATA install-dejagnuDATA \ +install-data-recursive uninstall-data-recursive install-exec-recursive \ +uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \ +all-recursive check-recursive installcheck-recursive info-recursive \ +dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \ +maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ +distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-info-am \ +install-info all-recursive-am install-exec-local install-exec-am \ +install-exec install-data-local install-data-am install-data install-am \ +install uninstall-am uninstall all-local all-redirect all-am all \ +installdirs-am installdirs mostlyclean-generic distclean-generic \ +clean-generic maintainer-clean-generic clean mostlyclean distclean \ +maintainer-clean + + +@MSVC_TRUE@all-local: cyginfra.lib + +@MSVC_TRUE@cyginfra.lib: libcyginfra.a +@MSVC_TRUE@ $(INSTALL) $< $@ + +@MSVC_TRUE@clean-local: +@MSVC_TRUE@ $(RM) cyginfra.lib + +@MSVC_TRUE@install-exec-local: all-local +@MSVC_TRUE@ $(mkinstalldirs) $(DESTDIR)$(libdir) +@MSVC_TRUE@ $(INSTALL) cyginfra.lib $(DESTDIR)$(libdir)/cyginfra.lib + +@MSVC_FALSE@all-local: +@MSVC_FALSE@clean-local: + +@MSVC_FALSE@install-exec-local: libcyginfra.a +@MSVC_FALSE@ $(mkinstalldirs) $(DESTDIR)$(libdir) +@MSVC_FALSE@ $(INSTALL) libcyginfra.a $(DESTDIR)$(libdir)/libcyginfra.a + +install-data-local: $(copies) + $(mkinstalldirs) $(DESTDIR)$(includedir) \ + $(DESTDIR)$(includedir)/cyg \ + $(DESTDIR)$(includedir)/cyg/infra \ + $(DESTDIR)$(includedir)/cyg/hal \ + $(DESTDIR)$(includedir)/pkgconf + $(INSTALL_DATA) cyg/infra/cyg_type.h $(DESTDIR)$(includedir)/cyg/infra + $(INSTALL_DATA) cyg/infra/cyg_ass.h $(DESTDIR)$(includedir)/cyg/infra + $(INSTALL_DATA) cyg/infra/cyg_trac.h $(DESTDIR)$(includedir)/cyg/infra + $(INSTALL_DATA) cyg/infra/testcase.h $(DESTDIR)$(includedir)/cyg/infra + $(INSTALL_DATA) cyg/hal/basetype.h $(DESTDIR)$(includedir)/cyg/hal + $(INSTALL_DATA) pkgconf/infra.h $(DESTDIR)$(includedir)/pkgconf + $(INSTALL_DATA) pkgconf/hostinfra.h $(DESTDIR)$(includedir)/pkgconf + +cyg/infra/cyg_type.h: cyg_type.h + @if [ -d cyg ] ; then true ; else mkdir cyg ; fi + @if [ -d cyg/infra ] ; then true ; else mkdir cyg/infra ; fi + $(INSTALL_DATA) $(<) $(@) + +cyg/infra/cyg_ass.h: cyg_ass.h + @if [ -d cyg ] ; then true ; else mkdir cyg ; fi + @if [ -d cyg/infra ] ; then true ; else mkdir cyg/infra ; fi + $(INSTALL_DATA) $(<) $(@) + +cyg/infra/cyg_trac.h: cyg_trac.h + @if [ -d cyg ] ; then true ; else mkdir cyg ; fi + @if [ -d cyg/infra ] ; then true ; else mkdir cyg/infra ; fi + $(INSTALL_DATA) $(<) $(@) + +cyg/infra/testcase.h: testcase.h + @if [ -d cyg ] ; then true ; else mkdir cyg ; fi + @if [ -d cyg/infra ] ; then true ; else mkdir cyg/infra ; fi + $(INSTALL_DATA) $(<) $(@) + +pkgconf/infra.h : infra.h + @if [ -d pkgconf ] ; then true ; else mkdir pkgconf ; fi + $(INSTALL_DATA) $(<) $(@) + +pkgconf/hostinfra.h : hostinfra.h + @if [ -d pkgconf ] ; then true ; else mkdir pkgconf ; fi + $(INSTALL_DATA) $(<) $(@) + +cyg/hal/basetype.h : basetype.h + @if [ -d cyg ] ; then true ; else mkdir cyg ; fi + @if [ -d cyg/hal ] ; then true ; else mkdir cyg/hal ; fi + $(INSTALL_DATA) $(<) $(@) + +assert.$(OBJEXT) : Makefile \ + pkgconf/infra.h \ + pkgconf/hostinfra.h \ + cyg/infra/cyg_type.h \ + cyg/hal/basetype.h \ + cyg/infra/cyg_ass.h + +trace.$(OBJEXT) : Makefile \ + pkgconf/infra.h \ + pkgconf/hostinfra.h \ + cyg/infra/cyg_type.h \ + cyg/hal/basetype.h \ + cyg/infra/cyg_ass.h \ + cyg/infra/cyg_trac.h + +checkdata.$(OBJEXT) : Makefile \ + cyg/infra/cyg_ass.h \ + pkgconf/infra.h \ + pkgconf/hostinfra.h \ + cyg/infra/cyg_type.h \ + cyg/hal/basetype.h + +testcase.$(OBJEXT): Makefile \ + cyg/infra/testcase.h \ + cyg/infra/cyg_type.h \ + cyg/hal/basetype.h \ + pkgconf/infra.h \ + pkgconf/hostinfra.h + +# 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/host/infra/acconfig.h b/host/infra/acconfig.h new file mode 100644 --- /dev/null +++ b/host/infra/acconfig.h @@ -0,0 +1,53 @@ +#ifndef CYGONCE_INFRA_CONFIG_H +# define CYGONCE_INFRA_CONFIG_H + +//====================================================================== +// +// acconfig.h +// +// Configuration header for host-side infrastructure +// +//====================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//====================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contact(s): bartv +// Date: 1998/12/16 +// Version: 0.01 +// +//####DESCRIPTIONEND#### +//====================================================================== + +#undef CYGNUM_INFRA_VERSION +#undef cyg_halint64 +#undef cyg_halcount64 +#undef CYGDBG_INFRA_DEBUG_FUNCTION_PSEUDOMACRO +#undef CYGNUM_INFRA_TRACE_VECTOR_SIZE + +#endif // CYGONCE_INFRA_CONFIG_H +// End of config.h diff --git a/host/infra/acinclude.m4 b/host/infra/acinclude.m4 new file mode 100644 --- /dev/null +++ b/host/infra/acinclude.m4 @@ -0,0 +1,130 @@ +dnl Process this file with aclocal to get an aclocal.m4 file. Then +dnl process that with autoconf. +dnl ==================================================================== +dnl +dnl acinclude.m4 +dnl +dnl Host side implementation of the eCos infrastructure. +dnl +dnl ==================================================================== +dnl####COPYRIGHTBEGIN#### +dnl +dnl ---------------------------------------------------------------------------- +dnl Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +dnl +dnl This file is part of the eCos host tools. +dnl +dnl This program is free software; you can redistribute it and/or modify it +dnl under the terms of the GNU General Public License as published by the Free +dnl Software Foundation; either version 2 of the License, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but WITHOUT +dnl ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +dnl FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +dnl more details. +dnl +dnl You should have received a copy of the GNU General Public License along with +dnl this program; if not, write to the Free Software Foundation, Inc., +dnl 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl ---------------------------------------------------------------------------- +dnl +dnl####COPYRIGHTEND#### +dnl ==================================================================== +dnl#####DESCRIPTIONBEGIN#### +dnl +dnl Author(s): bartv +dnl Contact(s): bartv +dnl Date: 1998/07/14 +dnl Version: 0.01 +dnl +dnl####DESCRIPTIONEND#### +dnl ==================================================================== + +dnl Access shared macros. +dnl AM_CONDITIONAL needs to be mentioned here or else aclocal does not +dnl incorporate the macro into aclocal.m4 +sinclude(../acinclude.m4) + + +dnl ==================================================================== +dnl Look for a 64 bit data type. It is necessary to check both C and C++ +dnl compilers. +dnl +dnl A better implementation would check whether or not AC_PROG_CC and +dnl AC_PROG_CXX have been invoked and only test the appropriate +dnl compiler. + +AC_DEFUN(CYG_AC_TYPE_64bit, [ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_PROG_CXX]) + + AC_CACHE_CHECK("for a 64 bit data type",cyg_ac_cv_type_64bit,[ + for type in "long" "long long" "__int64"; do + AC_LANG_SAVE + AC_LANG_C + AC_TRY_RUN([ + main() { + return 8 != sizeof($type); + } + ],ctype_64bit=$type,ctype_64bit="unknown",ctype_64bit="unknown") + AC_LANG_CPLUSPLUS + AC_TRY_RUN([ + int main(int argc, char ** argv) { + return 8 != sizeof($type); + } + ],cxxtype_64bit=$type,cxxtype_64bit="unknown",cxxtype_64bit="unknown") + AC_LANG_RESTORE + if test "${ctype_64bit}" = "${type}" -a "${cxxtype_64bit}" = "${type}"; then + cyg_ac_cv_type_64bit="${type}" + break + fi + done + ]) + if test "${cyg_ac_cv_type_64bit}" = ""; then + AC_MSG_ERROR(Unable to figure out how to do 64 bit arithmetic) + else + if test "${cyg_ac_cv_type_64bit}" != "long long"; then + AC_DEFINE_UNQUOTED(cyg_halint64,${cyg_ac_cv_type_64bit}) + AC_DEFINE_UNQUOTED(cyg_halcount64,${cyg_ac_cv_type_64bit}) + fi + fi +]) + +dnl ==================================================================== +dnl Check that both the C and C++ compilers support __PRETTY_FUNCTION__ + +AC_DEFUN(CYG_AC_C_PRETTY_FUNCTION,[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_PROG_CXX]) + + AC_CACHE_CHECK("for __PRETTY_FUNCTION__ support",cyg_ac_cv_c_pretty_function,[ + AC_LANG_SAVE + AC_LANG_C + AC_TRY_LINK( + [#include ], + [puts(__PRETTY_FUNCTION__);], + c_ok="yes", + c_ok="no" + ) + AC_LANG_CPLUSPLUS + AC_TRY_LINK( + [#include ], + [puts(__PRETTY_FUNCTION__);], + cxx_ok="yes", + cxx_ok="no" + ) + AC_LANG_RESTORE + if test "${c_ok}" = "yes" -a "${cxx_ok}" = "yes"; then + cyg_ac_cv_c_pretty_function="yes" + fi + ]) + if test "${cyg_ac_cv_c_pretty_function}" = "yes"; then + AC_DEFINE(CYGDBG_INFRA_DEBUG_FUNCTION_PSEUDOMACRO) + fi +]) + + + + diff --git a/host/infra/aclocal.m4 b/host/infra/aclocal.m4 new file mode 100644 --- /dev/null +++ b/host/infra/aclocal.m4 @@ -0,0 +1,291 @@ +dnl aclocal.m4 generated automatically by aclocal 1.4 + +dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without +dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A +dnl PARTICULAR PURPOSE. + +dnl Process this file with aclocal to get an aclocal.m4 file. Then +dnl process that with autoconf. +dnl ==================================================================== +dnl +dnl acinclude.m4 +dnl +dnl Host side implementation of the eCos infrastructure. +dnl +dnl ==================================================================== +dnl####COPYRIGHTBEGIN#### +dnl +dnl ---------------------------------------------------------------------------- +dnl Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +dnl +dnl This file is part of the eCos host tools. +dnl +dnl This program is free software; you can redistribute it and/or modify it +dnl under the terms of the GNU General Public License as published by the Free +dnl Software Foundation; either version 2 of the License, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but WITHOUT +dnl ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +dnl FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +dnl more details. +dnl +dnl You should have received a copy of the GNU General Public License along with +dnl this program; if not, write to the Free Software Foundation, Inc., +dnl 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl ---------------------------------------------------------------------------- +dnl +dnl####COPYRIGHTEND#### +dnl ==================================================================== +dnl#####DESCRIPTIONBEGIN#### +dnl +dnl Author(s): bartv +dnl Contact(s): bartv +dnl Date: 1998/07/14 +dnl Version: 0.01 +dnl +dnl####DESCRIPTIONEND#### +dnl ==================================================================== + +dnl Access shared macros. +dnl AM_CONDITIONAL needs to be mentioned here or else aclocal does not +dnl incorporate the macro into aclocal.m4 +sinclude(../acinclude.m4) + + +dnl ==================================================================== +dnl Look for a 64 bit data type. It is necessary to check both C and C++ +dnl compilers. +dnl +dnl A better implementation would check whether or not AC_PROG_CC and +dnl AC_PROG_CXX have been invoked and only test the appropriate +dnl compiler. + +AC_DEFUN(CYG_AC_TYPE_64bit, [ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_PROG_CXX]) + + AC_CACHE_CHECK("for a 64 bit data type",cyg_ac_cv_type_64bit,[ + for type in "long" "long long" "__int64"; do + AC_LANG_SAVE + AC_LANG_C + AC_TRY_RUN([ + main() { + return 8 != sizeof($type); + } + ],ctype_64bit=$type,ctype_64bit="unknown",ctype_64bit="unknown") + AC_LANG_CPLUSPLUS + AC_TRY_RUN([ + int main(int argc, char ** argv) { + return 8 != sizeof($type); + } + ],cxxtype_64bit=$type,cxxtype_64bit="unknown",cxxtype_64bit="unknown") + AC_LANG_RESTORE + if test "${ctype_64bit}" = "${type}" -a "${cxxtype_64bit}" = "${type}"; then + cyg_ac_cv_type_64bit="${type}" + break + fi + done + ]) + if test "${cyg_ac_cv_type_64bit}" = ""; then + AC_MSG_ERROR(Unable to figure out how to do 64 bit arithmetic) + else + if test "${cyg_ac_cv_type_64bit}" != "long long"; then + AC_DEFINE_UNQUOTED(cyg_halint64,${cyg_ac_cv_type_64bit}) + AC_DEFINE_UNQUOTED(cyg_halcount64,${cyg_ac_cv_type_64bit}) + fi + fi +]) + +dnl ==================================================================== +dnl Check that both the C and C++ compilers support __PRETTY_FUNCTION__ + +AC_DEFUN(CYG_AC_C_PRETTY_FUNCTION,[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_PROG_CXX]) + + AC_CACHE_CHECK("for __PRETTY_FUNCTION__ support",cyg_ac_cv_c_pretty_function,[ + AC_LANG_SAVE + AC_LANG_C + AC_TRY_LINK( + [#include ], + [puts(__PRETTY_FUNCTION__);], + c_ok="yes", + c_ok="no" + ) + AC_LANG_CPLUSPLUS + AC_TRY_LINK( + [#include ], + [puts(__PRETTY_FUNCTION__);], + cxx_ok="yes", + cxx_ok="no" + ) + AC_LANG_RESTORE + if test "${c_ok}" = "yes" -a "${cxx_ok}" = "yes"; then + cyg_ac_cv_c_pretty_function="yes" + fi + ]) + if test "${cyg_ac_cv_c_pretty_function}" = "yes"; then + AC_DEFINE(CYGDBG_INFRA_DEBUG_FUNCTION_PSEUDOMACRO) + fi +]) + + + + + +# Define a conditional. + +AC_DEFUN(AM_CONDITIONAL, +[AC_SUBST($1_TRUE) +AC_SUBST($1_FALSE) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi]) + +# Do all the work for Automake. This macro actually does too much -- +# some checks are only needed if your package does certain things. +# But this isn't really a big deal. + +# serial 1 + +dnl Usage: +dnl AM_INIT_AUTOMAKE(package,version, [no-define]) + +AC_DEFUN(AM_INIT_AUTOMAKE, +[AC_REQUIRE([AC_PROG_INSTALL]) +PACKAGE=[$1] +AC_SUBST(PACKAGE) +VERSION=[$2] +AC_SUBST(VERSION) +dnl test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi +ifelse([$3],, +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) +AC_REQUIRE([AM_SANITY_CHECK]) +AC_REQUIRE([AC_ARG_PROGRAM]) +dnl FIXME This is truly gross. +missing_dir=`cd $ac_aux_dir && pwd` +AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) +AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) +AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) +AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) +AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) +AC_REQUIRE([AC_PROG_MAKE_SET])]) + +# +# Check to make sure that the build environment is sane. +# + +AC_DEFUN(AM_SANITY_CHECK, +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "[$]*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "[$]*" != "X $srcdir/configure conftestfile" \ + && test "[$]*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "[$]2" = conftestfile + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +rm -f conftest* +AC_MSG_RESULT(yes)]) + +dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) +dnl The program must properly implement --version. +AC_DEFUN(AM_MISSING_PROG, +[AC_MSG_CHECKING(for working $2) +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if ($2 --version) < /dev/null > /dev/null 2>&1; then + $1=$2 + AC_MSG_RESULT(found) +else + $1="$3/missing $2" + AC_MSG_RESULT(missing) +fi +AC_SUBST($1)]) + +# Add --enable-maintainer-mode option to configure. +# From Jim Meyering + +# serial 1 + +AC_DEFUN(AM_MAINTAINER_MODE, +[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode is disabled by default + AC_ARG_ENABLE(maintainer-mode, +[ --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer], + USE_MAINTAINER_MODE=$enableval, + USE_MAINTAINER_MODE=no) + AC_MSG_RESULT($USE_MAINTAINER_MODE) + AM_CONDITIONAL(MAINTAINER_MODE, test $USE_MAINTAINER_MODE = yes) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST(MAINT)dnl +] +) + +# Like AC_CONFIG_HEADER, but automatically create stamp file. + +AC_DEFUN(AM_CONFIG_HEADER, +[AC_PREREQ([2.12]) +AC_CONFIG_HEADER([$1]) +dnl When config.status generates a header, we must update the stamp-h file. +dnl This file resides in the same directory as the config header +dnl that is generated. We must strip everything past the first ":", +dnl and everything past the last "/". +AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl +ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>, +<>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>, +<>; do + case " <<$>>CONFIG_HEADERS " in + *" <<$>>am_file "*<<)>> + echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx + ;; + esac + am_indx=`expr "<<$>>am_indx" + 1` +done<<>>dnl>>) +changequote([,]))]) + diff --git a/host/infra/assert.cxx b/host/infra/assert.cxx new file mode 100644 --- /dev/null +++ b/host/infra/assert.cxx @@ -0,0 +1,302 @@ +//{{{ Banner + +//============================================================================ +// +// assert.cxx +// +// Host side implementation of the infrastructure assertions. +// +//============================================================================ +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================ +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contact(s): bartv +// Date: 1998/11/27 +// Version: 0.01 +// Purpose: To provide a host-side implementation of the eCos assertion +// facilities. +// +//####DESCRIPTIONEND#### +//============================================================================ + +//}}} +//{{{ #include's + +#include "pkgconf/infra.h" +#include "cyg/infra/cyg_type.h" +// Without this symbol the header file has no effect +#define CYGDBG_USE_TRACING +// Make sure that the host-side extensions get prototyped +// as well. +#define CYG_DECLARE_HOST_ASSERTION_SUPPORT +#include "cyg/infra/cyg_ass.h" + +// STDIO is needed for the default assertion handler. +// STDLIB is needed for exit() and the status codes. +#include +#include + +// These are needed for the table of callbacks. +#include +#include +#include + +//}}} + +// ------------------------------------------------------------------------- +// Statics. The host-side assertion code requires two bits of data. +// +// The first identifies the function that should actually get invoked +// when an assertion is triggered. A default implementation is defined +// in this module, but applications may install a replacement. +// +// The second is a table of callback functions that various libraries +// or bits of application code may install. Each such callback gets invoked +// when an assertion triggers. + +// VC++ bogosity. Using a full function pointer prototype in a template +// confuses the compiler. It is still possible to declare the callbacks vector, +// but not any iterators for that vector. A typedef makes the problem go +// away. +typedef void (*cyg_callback_fn)(void (*)(const char*)); + + // The current assertion handler +static bool (*current_handler)( const char*, const char*, cyg_uint32, const char*) = 0; + + // The callback table. +static std::vector > callbacks; + +// ---------------------------------------------------------------------------- +// Many applications will want to handle assertion failures differently +// from the default, for example pipe the output into an emacs buffer +// rather than just generate a file. This routine allows a suitable +// function to be installed. + +extern "C" void +cyg_assert_install_failure_handler( bool(*fn)(const char*, const char*, cyg_uint32, const char*) ) +{ + current_handler = fn; +} + +// ---------------------------------------------------------------------------- +// Various different bits of the system may want to register callback functions +// that get invoked during an assertion failure and that output useful +// data. Typically this might happen in the constructor for a static object. +// A good example of such a callback is the implementation of the trace code. +// +// The implementation requires creating a new entry in the static vector. +// A memory exhaustion exception could occur but there is no sensible way of +// handling it at this level. +// +// Multiple callbacks with the same name are legal. Multiple callbacks with +// the same function are unlikely, but it is probably not worthwhile raising +// an exception (especially since this code may be called from C). +extern "C" void +cyg_assert_install_failure_callback( const char* name, void (*fn)(void (*)(const char*)) ) +{ + callbacks.push_back(std::make_pair(name, fn)); +} + +// ------------------------------------------------------------------------- +// Once an assertion has triggered either the default handler or the +// installed handler will want to invoke all the callbacks. Rather than +// provide direct access to the callback table and require the calling +// code to be in C++, a functional interface is provided instead. +extern "C" void +cyg_assert_failure_invoke_callbacks( + void (*first_fn)(const char*), + void (*data_fn)(const char*), + void (*final_fn)(void) ) +{ + std::vector >::const_iterator i; + + for ( i = callbacks.begin(); i != callbacks.end(); i++ ) { + + if (0 != first_fn) { + (*first_fn)(i->first); + } + if (0 != data_fn) { + (*(i->second))(data_fn); + } + if (0 != final_fn) { + (*final_fn)(); + } + } +} + +// ---------------------------------------------------------------------------- +// The default assertion handler. This assumes that the application is +// a console application with a sensible stderr stream. +// +// First some initial diagnostics are output immediately, in case +// subsequent attempts to output more data cause additional failures. It +// is worthwhile detecting recursive assertion failures. +// +// Assuming the table of callbacks is not empty it is possible to output +// some more data to a file. The tmpnam() function is used to get a filename. +// The file is opened and the callbacks are invoked. Three utilities have to +// be provided to do the real work, and a static is used to keep track of the +// FILE * pointer. +// +// The testcase tassert8, and in particular the associated Tcl proc +// tassert8_filter in testsuite/cyginfra/assert.exp, has detailed +// knowledge of the output format. Any changes here may need to be +// reflected in that test case. There are also support routines in +// hosttest.exp which may need to be updated. + +static FILE * default_handler_output_file = 0; +static bool body_contains_data = false; + + // output the callback name +static void +default_handler_first_fn(const char* name) +{ + if (0 != default_handler_output_file) { + fprintf(default_handler_output_file, "# {{{ %s\n\n", name); + } + body_contains_data = false; +} + + // output some actual text. +static void +default_handler_second_fn(const char* data) +{ + body_contains_data = true; + if (0 != default_handler_output_file) { + fputs(data, default_handler_output_file); + } +} + + // the end of a callback. +static void +default_handler_final_fn( void ) +{ + + if (0 != default_handler_output_file) { + if (body_contains_data) { + fputs("\n", default_handler_output_file); + } + fputs("# }}}\n", default_handler_output_file); + } +} + + +static void +default_handler(const char* fn, const char* file, cyg_uint32 lineno, const char* msg) +{ + static int invoke_count = 0; + if (2 == invoke_count) { + // The fprintf() immediately below causes an assertion failure + } else if (1 == invoke_count) { + invoke_count++; + fprintf(stderr, "Recursive assertion failure.\n"); + return; + } else { + invoke_count = 1; + } + + // There is an argument for using write() rather than fprintf() here, + // in case the C library has been corrupted. For now this has not been + // attempted. + if (0 == msg) + msg =""; + if (0 == file) + file = ""; + + fprintf(stderr, "Assertion failure: %s\n", msg); + fprintf(stderr, "File %s, line number %lu\n", file, (unsigned long) lineno); + if (0 != fn) + fprintf(stderr, "Function %s\n", fn); + + // Only create a logfile if more information is available. + if (0 != callbacks.size() ) { + char filename[L_tmpnam]; + if (0 == tmpnam(filename)) { + fprintf(stderr, "Unable to create a suitable output file for additional data.\n"); + } else { + + // No attempt is made to ensure that the file does not already + // exist. This would require POSIX calls rather than ISO C ones. + // The probability of a problem is considered to be too small + // to worry about. + default_handler_output_file = fopen(filename, "w"); + if (0 == default_handler_output_file) { + fprintf(stderr, "Unable to open output file %s\n", filename); + fputs("No further assertion information is available.\n", stderr); + } else { + fprintf(stderr, "Writing additional output to %s\n", filename); + + // Repeat the information about the assertion itself. + fprintf(default_handler_output_file, "Assertion failure: %s\n", msg); + fprintf(default_handler_output_file, "File %s, line number %lu\n", file, (unsigned long) lineno); + if (0 != fn) + fprintf(default_handler_output_file, "Function %s\n", fn); + fputs("\n", default_handler_output_file); + + // Now for the various callbacks. + cyg_assert_failure_invoke_callbacks( &default_handler_first_fn, + &default_handler_second_fn, &default_handler_final_fn ); + + // And close the file. + fputs("\nEnd of assertion data.\n", default_handler_output_file); + fclose(default_handler_output_file); + } + } + } + fflush(stderr); +} + +// ---------------------------------------------------------------------------- +// The assertion handler. This is the function that gets invoked when +// an assertion triggers. If a special assertion handler has been installed +// then this gets called. If it returns false or if no special handler is +// available then the default handler gets called instead. Typically the +// user will now have a lot of information about what happened to cause the +// assertion failure. The next stage is to invoke abort() which should +// terminate the program and generate a core dump for subsequent inspection +// (unless of course the application is already running in a debugger session). +// A final call to _exit() should be completely redundant. + +extern "C" void +cyg_assert_fail( const char* fn, const char* file, cyg_uint32 lineno, const char* msg ) +{ + + if ((0 == current_handler) || !(*current_handler)(fn, file, lineno, msg)) { + default_handler(fn, file, lineno, msg); + } + abort(); + _exit(0); +} + +// ---------------------------------------------------------------------------- +// A utility function, primarily intended to be called from inside gdb. +extern "C" void +cyg_assert_quickfail(void) +{ + cyg_assert_fail("gdb", "", 0, "manual call"); +} diff --git a/host/infra/basetype.h b/host/infra/basetype.h new file mode 100644 --- /dev/null +++ b/host/infra/basetype.h @@ -0,0 +1,98 @@ +#ifndef CYGONCE_HAL_BASETYPE_H +# define CYGONCE_HAL_BASETYPE_H + +//====================================================================== +// +// basetype.h +// +// HAL emulation for the host-side infrastructure. +// +//====================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//====================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contact(s): bartv +// Date: 1998/07/13 +// Version: 0.01 +// +//####DESCRIPTIONEND#### +//====================================================================== + +// The purpose of this header file is to replicate the functionality +// provided by on the target side. Essentially +// this file has to define endianness. Optionally it can also define +// the correct data types for e.g. cyg_count32 etc. +// +// On the host side portability is achieved by means of autoconf and +// feature tests, as opposed to re-implementing the HAL for each +// platform. In particular there will be a generated header file +// which gets filled in during the configure +// process. +// +// It has been decided that the host side should use exactly the same +// infrastructure header files as the target side (although extra +// functionality may be defined in these header files where +// appropriate). This means that the host side needs to provide +// , even though it does not contain a HAL. +// +// This implementation of reads in the +// configuration header generated by the configure script and adapts +// this information into whatever is required by +// . + +#ifndef CYGONCE_PKGCONF_INFRA_H +# include +#endif + +// The autoconf test for endianness will result in a #define for +// LITTLE_ENDIAN_HOST on appropriate platforms. This needs to be +// converted into a definition of CYG_BYTEORDER as per the target-side +// HAL headers. + +#ifdef WORDS_BIGENDIAN +# define CYG_BYTEORDER CYG_MSBFIRST +#else +# define CYG_BYTEORDER CYG_LSBFIRST +#endif + +// The default definitions for cyg_halint8/16/32 and cyg_halcount8/16/32 +// should be fine (although eventually we may come across a platform +// where int's are 64 bit). 64 bit arithmetic is a bit more of a problem. +// on the majority of systems so there is an autoconf test which will +// generate appropriate #define's for cyg_halint64 and cyg_halcount64, +// which means this header file does not to do anything more. +// cyg_halbool and cyg_halatomic should both be ok. + + +// Any symbols defined in which have been processed +// here should no longer be of any interest, and in the interests of +// reducing name space pollution they get undef'ed here. +#undef WORDS_BIGENDIAN + +#endif // CYGONCE_HAL_BASETYPE_H +// End of basetype.h diff --git a/host/infra/checkdata.cxx b/host/infra/checkdata.cxx new file mode 100644 --- /dev/null +++ b/host/infra/checkdata.cxx @@ -0,0 +1,74 @@ +//{{{ Banner + +//============================================================================ +// +// checkdata.cxx +// +// Host side implementation of the check_func() and check_data() +// utilities. +// +//============================================================================ +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================ +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contact(s): bartv +// Date: 1998/12/02 +// Version: 0.01 +// Purpose: To provide a host-side implementation of two of the +// eCos assertion facilities. facilities. +// +//####DESCRIPTIONEND#### +//============================================================================ + +//}}} +//{{{ #include's + +#include "cyg/infra/cyg_ass.h" + +//}}} + +// ------------------------------------------------------------------------- +// It is convenient to have cyg_check_data_ptr() and cyg_check_func_ptr() +// in a separate file from cyg_assert_fail(). That way users can override +// cyg_assert_fail() itself in application code without losing access to +// the check_data and check_func routines. +// +// The actual implementation is very limited. It might be possible to +// do better on specific platforms. + +extern "C" cyg_bool +cyg_check_data_ptr( void * ptr ) +{ + return 0 != ptr; +} + +extern "C" cyg_bool +cyg_check_func_ptr ( void (*ptr)(void) ) +{ + return 0 != ptr; +} diff --git a/host/infra/config.h.in b/host/infra/config.h.in new file mode 100644 --- /dev/null +++ b/host/infra/config.h.in @@ -0,0 +1,17 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define if your processor stores words with the most significant + byte first (like Motorola and SPARC, unlike Intel and VAX). */ +#undef WORDS_BIGENDIAN + +#undef CYGNUM_INFRA_VERSION +#undef cyg_halint64 +#undef cyg_halcount64 +#undef CYGDBG_INFRA_DEBUG_FUNCTION_PSEUDOMACRO +#undef CYGNUM_INFRA_TRACE_VECTOR_SIZE + +/* The number of bytes in a int *. */ +#undef SIZEOF_INT_P + +/* The number of bytes in a long. */ +#undef SIZEOF_LONG diff --git a/host/infra/configure b/host/infra/configure new file mode 100644 --- /dev/null +++ b/host/infra/configure @@ -0,0 +1,2320 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer" +ac_help="$ac_help + --enable-debug do a debug rather than a release build" +ac_help="$ac_help + --enable-ansi Do an ANSI rather than a unicode build" +ac_help="$ac_help + --with-tcl-version= version of Tcl to be used" +ac_help="$ac_help + --with-tcl= location of Tcl header and libraries" +ac_help="$ac_help + --enable-tracebufsize=X size of the trace buffer" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=assert.cxx + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +ac_aux_dir= +for ac_dir in .. $srcdir/..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in .. $srcdir/.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + + + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:566: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:599: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 +echo "configure:652: checking whether build environment is sane" >&5 +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "$*" != "X $srcdir/configure conftestfile" \ + && test "$*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { echo "configure: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" 1>&2; exit 1; } + fi + + test "$2" = conftestfile + ) +then + # Ok. + : +else + { echo "configure: error: newly created file is older than distributed files! +Check your system clock" 1>&2; exit 1; } +fi +rm -f conftest* +echo "$ac_t""yes" 1>&6 +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:709: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +PACKAGE=cyginfra + +VERSION=0.1 + +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } +fi + + + +missing_dir=`cd $ac_aux_dir && pwd` +echo $ac_n "checking for working aclocal""... $ac_c" 1>&6 +echo "configure:748: checking for working aclocal" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (aclocal --version) < /dev/null > /dev/null 2>&1; then + ACLOCAL=aclocal + echo "$ac_t""found" 1>&6 +else + ACLOCAL="$missing_dir/missing aclocal" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 +echo "configure:761: checking for working autoconf" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoconf --version) < /dev/null > /dev/null 2>&1; then + AUTOCONF=autoconf + echo "$ac_t""found" 1>&6 +else + AUTOCONF="$missing_dir/missing autoconf" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working automake""... $ac_c" 1>&6 +echo "configure:774: checking for working automake" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (automake --version) < /dev/null > /dev/null 2>&1; then + AUTOMAKE=automake + echo "$ac_t""found" 1>&6 +else + AUTOMAKE="$missing_dir/missing automake" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 +echo "configure:787: checking for working autoheader" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoheader --version) < /dev/null > /dev/null 2>&1; then + AUTOHEADER=autoheader + echo "$ac_t""found" 1>&6 +else + AUTOHEADER="$missing_dir/missing autoheader" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 +echo "configure:800: checking for working makeinfo" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (makeinfo --version) < /dev/null > /dev/null 2>&1; then + MAKEINFO=makeinfo + echo "$ac_t""found" 1>&6 +else + MAKEINFO="$missing_dir/missing makeinfo" + echo "$ac_t""missing" 1>&6 +fi + + + + + + cat >> confdefs.h <&6 +echo "configure:822: checking whether to enable maintainer-specific portions of Makefiles" >&5 + # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then + enableval="$enable_maintainer_mode" + USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + echo "$ac_t""$USE_MAINTAINER_MODE" 1>&6 + + +if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + MAINT=$MAINTAINER_MODE_TRUE + + + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:846: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:875: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:905: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:956: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:988: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 999 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:1004: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:1030: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:1035: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:1063: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1099: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CXX="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CXX="$ac_cv_prog_CXX" +if test -n "$CXX"; then + echo "$ac_t""$CXX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$CXX" && break +done +test -n "$CXX" || CXX="gcc" + + +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:1131: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 + +ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + +cat > conftest.$ac_ext << EOF + +#line 1142 "configure" +#include "confdefs.h" + +int main(){return(0);} +EOF +if { (eval echo configure:1147: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cxx_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cxx_cross=no + else + ac_cv_prog_cxx_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cxx_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6 +if test $ac_cv_prog_cxx_works = no; then + { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:1173: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6 +cross_compiling=$ac_cv_prog_cxx_cross + +echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 +echo "configure:1178: checking whether we are using GNU C++" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.C <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gxx=yes +else + ac_cv_prog_gxx=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gxx" 1>&6 + +if test $ac_cv_prog_gxx = yes; then + GXX=yes +else + GXX= +fi + +ac_test_CXXFLAGS="${CXXFLAGS+set}" +ac_save_CXXFLAGS="$CXXFLAGS" +CXXFLAGS= +echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6 +echo "configure:1206: checking whether ${CXX-g++} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.cc +if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then + ac_cv_prog_cxx_g=yes +else + ac_cv_prog_cxx_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6 +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS="$ac_save_CXXFLAGS" +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1240: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +echo $ac_n "checking for object suffix""... $ac_c" 1>&6 +echo "configure:1268: checking for object suffix" >&5 +if eval "test \"`echo '$''{'ac_cv_objext'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + rm -f conftest* +echo 'int i = 1;' > conftest.$ac_ext +if { (eval echo configure:1274: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + for ac_file in conftest.*; do + case $ac_file in + *.c) ;; + *) ac_cv_objext=`echo $ac_file | sed -e s/conftest.//` ;; + esac + done +else + { echo "configure: error: installation or configuration problem; compiler does not work" 1>&2; exit 1; } +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_objext" 1>&6 +OBJEXT=$ac_cv_objext +ac_objext=$ac_cv_objext + +echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6 +echo "configure:1292: checking for Cygwin environment" >&5 +if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_cygwin=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_cygwin=no +fi +rm -f conftest* +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_cygwin" 1>&6 +CYGWIN= +test "$ac_cv_cygwin" = yes && CYGWIN=yes +echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6 +echo "configure:1325: checking for mingw32 environment" >&5 +if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_mingw32=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_mingw32=no +fi +rm -f conftest* +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_mingw32" 1>&6 +MINGW32= +test "$ac_cv_mingw32" = yes && MINGW32=yes + + +echo $ac_n "checking for executable suffix""... $ac_c" 1>&6 +echo "configure:1356: checking for executable suffix" >&5 +if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$CYGWIN" = yes || test "$MINGW32" = yes; then + ac_cv_exeext=.exe +else + rm -f conftest* + echo 'int main () { return 0; }' > conftest.$ac_ext + ac_cv_exeext= + if { (eval echo configure:1366: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + for file in conftest.*; do + case $file in + *.c | *.o | *.obj | *.ilk | *.pdb) ;; + *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;; + esac + done + else + { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; } + fi + rm -f conftest* + test x"${ac_cv_exeext}" = x && ac_cv_exeext=no +fi +fi + +EXEEXT="" +test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext} +echo "$ac_t""${ac_cv_exeext}" 1>&6 +ac_exeext=$EXEEXT + + + + + + echo $ac_n "checking "for Visual C++"""... $ac_c" 1>&6 +echo "configure:1391: checking "for Visual C++"" >&5 + MSVC="no"; + if test "${CC}" = "cl" ; then + MSVC="yes" + fi + if test "${CXX}" = "cl" ; then + MSVC="yes" + fi + + +if test "${MSVC}" = "yes"; then + MSVC_TRUE= + MSVC_FALSE='#' +else + MSVC_TRUE='#' + MSVC_FALSE= +fi + echo "$ac_t""${MSVC}" 1>&6 + + + + + + + echo $ac_n "checking "the default compiler flags"""... $ac_c" 1>&6 +echo "configure:1416: checking "the default compiler flags"" >&5 + + cygflags_enable_debug="no" + # Check whether --enable-debug or --disable-debug was given. +if test "${enable_debug+set}" = set; then + enableval="$enable_debug" + case "${enableval}" in + yes) cygflags_enable_debug="yes" ;; + *) cygflags_enable_debug="no" ;; + esac +fi + + + cygflags_enable_ansi="no" + if test "${MSVC}" = "yes" ; then + # Check whether --enable-ansi or --disable-ansi was given. +if test "${enable_ansi+set}" = set; then + enableval="$enable_ansi" + case "${enableval}" in + yes) cygflags_enable_ansi="yes" ;; + *) cygflags_enable_ansi="no" ;; + esac +fi + + fi + + if test "${GCC}" = "yes" ; then + CC="$CC -Wall -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs" + CXX="$CXX -Wall -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Woverloaded-virtual" + elif test "${MSVC}" = "yes" ; then + CC="$CC -nologo -W3" + CXX="$CXX -nologo -W3 -GR -GX" + if test "${cygflags_enable_debug}" = "yes" ; then + CC="$CC -MDd -Zi" + CXX="$CXX -MDd -Zi" + else + CC="$CC -MD -O2" + CXX="$CXX -MD -O2" + fi + else + { echo "configure: error: "default flags for ${CC} are not known"" 1>&2; exit 1; } + fi + echo "$ac_t""done" 1>&6 + + +if test ${cross_compiling} = yes; then + { echo "configure: error: cross-compilation of this package is not supported" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 +echo "configure:1466: checking whether byte ordering is bigendian" >&5 +if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_bigendian=unknown +# See if sys/param.h defines the BYTE_ORDER macro. +cat > conftest.$ac_ext < +#include +int main() { + +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif +; return 0; } +EOF +if { (eval echo configure:1484: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + # It does; now see whether it defined to BIG_ENDIAN or not. +cat > conftest.$ac_ext < +#include +int main() { + +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif +; return 0; } +EOF +if { (eval echo configure:1499: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_bigendian=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_bigendian=no +fi +rm -f conftest* +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +if test $ac_cv_c_bigendian = unknown; then +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_c_bigendian=no +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_c_bigendian=yes +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_c_bigendian" 1>&6 +if test $ac_cv_c_bigendian = yes; then + cat >> confdefs.h <<\EOF +#define WORDS_BIGENDIAN 1 +EOF + +fi + + + + + + + echo $ac_n "checking "for a 64 bit data type"""... $ac_c" 1>&6 +echo "configure:1561: checking "for a 64 bit data type"" >&5 +if eval "test \"`echo '$''{'cyg_ac_cv_type_64bit'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + for type in "long" "long long" "__int64"; do + + ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + + if test "$cross_compiling" = yes; then + ctype_64bit="unknown" +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ctype_64bit=$type +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ctype_64bit="unknown" +fi +rm -fr conftest* +fi + + ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + + if test "$cross_compiling" = yes; then + cxxtype_64bit="unknown" +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + cxxtype_64bit=$type +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + cxxtype_64bit="unknown" +fi +rm -fr conftest* +fi + + ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + + if test "${ctype_64bit}" = "${type}" -a "${cxxtype_64bit}" = "${type}"; then + cyg_ac_cv_type_64bit="${type}" + break + fi + done + +fi + +echo "$ac_t""$cyg_ac_cv_type_64bit" 1>&6 + if test "${cyg_ac_cv_type_64bit}" = ""; then + { echo "configure: error: Unable to figure out how to do 64 bit arithmetic" 1>&2; exit 1; } + else + if test "${cyg_ac_cv_type_64bit}" != "long long"; then + cat >> confdefs.h <> confdefs.h <&6 +echo "configure:1666: checking size of int *" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_int_p'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext < +main() +{ + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof(int *)); + exit(0); +} +EOF +if { (eval echo configure:1685: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_sizeof_int_p=`cat conftestval` +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_sizeof_int_p=0 +fi +rm -fr conftest* +fi + +fi +echo "$ac_t""$ac_cv_sizeof_int_p" 1>&6 +cat >> confdefs.h <&6 +echo "configure:1705: checking size of long" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext < +main() +{ + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof(long)); + exit(0); +} +EOF +if { (eval echo configure:1724: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_sizeof_long=`cat conftestval` +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_sizeof_long=0 +fi +rm -fr conftest* +fi + +fi +echo "$ac_t""$ac_cv_sizeof_long" 1>&6 +cat >> confdefs.h <&6 +echo "configure:1749: checking "for __PRETTY_FUNCTION__ support"" >&5 +if eval "test \"`echo '$''{'cyg_ac_cv_c_pretty_function'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + + ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + + cat > conftest.$ac_ext < +int main() { +puts(__PRETTY_FUNCTION__); +; return 0; } +EOF +if { (eval echo configure:1770: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + c_ok="yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + c_ok="no" + +fi +rm -f conftest* + ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + + cat > conftest.$ac_ext < +int main() { +puts(__PRETTY_FUNCTION__); +; return 0; } +EOF +if { (eval echo configure:1796: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + cxx_ok="yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + cxx_ok="no" + +fi +rm -f conftest* + ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + + if test "${c_ok}" = "yes" -a "${cxx_ok}" = "yes"; then + cyg_ac_cv_c_pretty_function="yes" + fi + +fi + +echo "$ac_t""$cyg_ac_cv_c_pretty_function" 1>&6 + if test "${cyg_ac_cv_c_pretty_function}" = "yes"; then + cat >> confdefs.h <<\EOF +#define CYGDBG_INFRA_DEBUG_FUNCTION_PSEUDOMACRO 1 +EOF + + fi + + + + + + + + +echo $ac_n "checking for Tcl version""... $ac_c" 1>&6 +echo "configure:1836: checking for Tcl version" >&5 +# Check whether --with-tcl-version or --without-tcl-version was given. +if test "${with_tcl_version+set}" = set; then + withval="$with_tcl_version" + + cyg_ac_tcl_version=${with_tcl_version} + +else + + if test "${MSVC}" = "yes" ; then + cyg_ac_tcl_version=80 + else + if test "${ac_cv_cygwin}" = "yes" ; then + cyg_ac_tcl_version=80 + else + cyg_ac_tcl_version="" + fi + fi + +fi + +echo "$ac_t""${cyg_ac_tcl_version}" 1>&6 + + +echo $ac_n "checking for Tcl installation""... $ac_c" 1>&6 +echo "configure:1861: checking for Tcl installation" >&5 +# Check whether --with-tcl or --without-tcl was given. +if test "${with_tcl+set}" = set; then + withval="$with_tcl" + + cyg_ac_tcl_incdir=${with_tcl}/include + cyg_ac_tcl_libdir=${with_tcl}/lib + +else + + cyg_ac_tcl_incdir=${prefix}/include + cyg_ac_tcl_libdir=${prefix}/lib + +fi + +echo "$ac_t""${cyg_ac_tcl_libdir}" 1>&6 + +if test \! -r ${cyg_ac_tcl_incdir}/tcl.h ; then + { echo "configure: error: unable to locate Tcl header file tcl.h" 1>&2; exit 1; } +fi + +if test "${MSVC}" = "yes" ; then + cyg_ac_tcl_libs="tcl${cyg_ac_tcl_version}.lib" + + + + + if test "${MSVC}" = "yes" ; then + cyg_ac_tcl_incdir=`cygpath -w ${cyg_ac_tcl_incdir} | tr \\\\\\\\ /` + fi + + + + + + if test "${MSVC}" = "yes" ; then + cyg_ac_tcl_libdir=`cygpath -w ${cyg_ac_tcl_libdir} | tr \\\\\\\\ /` + fi + +else + if test \! -r ${cyg_ac_tcl_libdir}/tclConfig.sh ; then + { echo "configure: error: unable to locate Tcl config file tclConfig.sh" 1>&2; exit 1; } + else + . ${cyg_ac_tcl_libdir}/tclConfig.sh + cyg_ac_tcl_libs="-ltcl${cyg_ac_tcl_version} ${TCL_LIBS}" + fi +fi + + + + + + + + +# Check whether --enable-tracebufsize or --disable-tracebufsize was given. +if test "${enable_tracebufsize+set}" = set; then + enableval="$enable_tracebufsize" + + if test "$enableval" = "no" -o "$enableval" = "yes"; then + { echo "configure: error: "--enable-tracebufsize should be given a suitable value"" 1>&2; exit 1; } + else + cat >> confdefs.h < confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile:Makefile.in testsuite/Makefile:testsuite/Makefile.in hostinfra.h:config.h.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@host@%$host%g +s%@host_alias@%$host_alias%g +s%@host_cpu@%$host_cpu%g +s%@host_vendor@%$host_vendor%g +s%@host_os@%$host_os%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@PACKAGE@%$PACKAGE%g +s%@VERSION@%$VERSION%g +s%@ACLOCAL@%$ACLOCAL%g +s%@AUTOCONF@%$AUTOCONF%g +s%@AUTOMAKE@%$AUTOMAKE%g +s%@AUTOHEADER@%$AUTOHEADER%g +s%@MAKEINFO@%$MAKEINFO%g +s%@SET_MAKE@%$SET_MAKE%g +s%@MAINTAINER_MODE_TRUE@%$MAINTAINER_MODE_TRUE%g +s%@MAINTAINER_MODE_FALSE@%$MAINTAINER_MODE_FALSE%g +s%@MAINT@%$MAINT%g +s%@CC@%$CC%g +s%@CXX@%$CXX%g +s%@RANLIB@%$RANLIB%g +s%@OBJEXT@%$OBJEXT%g +s%@EXEEXT@%$EXEEXT%g +s%@MSVC_TRUE@%$MSVC_TRUE%g +s%@MSVC_FALSE@%$MSVC_FALSE%g +s%@cyg_ac_tcl_version@%$cyg_ac_tcl_version%g +s%@cyg_ac_tcl_incdir@%$cyg_ac_tcl_incdir%g +s%@cyg_ac_tcl_libdir@%$cyg_ac_tcl_libdir%g +s%@cyg_ac_tcl_libs@%$cyg_ac_tcl_libs%g +s%@cyg_ac_tk_libs@%$cyg_ac_tk_libs%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + + diff --git a/host/infra/configure.in b/host/infra/configure.in new file mode 100644 --- /dev/null +++ b/host/infra/configure.in @@ -0,0 +1,169 @@ +dnl Process this file with autoconf to produce a configure script. +dnl ==================================================================== +dnl +dnl configure.in +dnl +dnl Host side implementation of the eCos infrastructure. +dnl +dnl ==================================================================== +dnl####COPYRIGHTBEGIN#### +dnl +dnl ---------------------------------------------------------------------------- +dnl Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +dnl +dnl This file is part of the eCos host tools. +dnl +dnl This program is free software; you can redistribute it and/or modify it +dnl under the terms of the GNU General Public License as published by the Free +dnl Software Foundation; either version 2 of the License, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but WITHOUT +dnl ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +dnl FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +dnl more details. +dnl +dnl You should have received a copy of the GNU General Public License along with +dnl this program; if not, write to the Free Software Foundation, Inc., +dnl 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl ---------------------------------------------------------------------------- +dnl +dnl####COPYRIGHTEND#### +dnl ==================================================================== +dnl#####DESCRIPTIONBEGIN#### +dnl +dnl Author(s): bartv +dnl Contact(s): bartv +dnl Date: 1998/07/13 +dnl Version: 0.01 +dnl +dnl####DESCRIPTIONEND#### +dnl ==================================================================== + +dnl No infrastructure is complete without assertions. +AC_INIT(assert.cxx) + +dnl Pick up the support files from the top-level of the host source tree +AC_CONFIG_AUX_DIR(..) + +dnl Other standard options. +AC_CANONICAL_HOST + +dnl This package is called cyginfra. Hopefully this will not clash +dnl with any other Red Hat packages. The generated header file may +dnl get #include'd indirectly by other packages, so it is not a +dnl good idea to define package and version. +AM_INIT_AUTOMAKE(cyginfra, 0.1,0) +CYG_AC_SUBST_VERSION(CYGNUM_INFRA_VERSION) +AM_MAINTAINER_MODE + +dnl The package contains a library implemented in C++. It has to be +dnl buildable under NT. Only a static version of the library is +dnl of interest at the moment. +AC_PROG_MAKE_SET +AC_PROG_CC +AC_PROG_CXX +AC_PROG_RANLIB +AC_OBJEXT +AC_EXEEXT +CYG_AC_PROG_MSVC +CYG_AC_PROG_STANDARD_COMPILER_FLAGS + +dnl This package cannot be cross-compiled yet. +if test ${cross_compiling} = yes; then + AC_MSG_ERROR(cross-compilation of this package is not supported) +fi + +dnl Work out the endianness. The standard macro for this is used +dnl even though it will give warnings at autoconf time. +AC_C_BIGENDIAN + +dnl Work out a suitable datatype for 64 bit arithmetic. +CYG_AC_TYPE_64bit + +dnl Check the sizes of the pointer and long data types, so that +dnl CYG_ADDRWORD can be defined correctly. +AC_CHECK_SIZEOF(int *) +AC_CHECK_SIZEOF(long) + +dnl See whether or not the compiler provides __PRETTY_FUNCTION__ +CYG_AC_C_PRETTY_FUNCTION + +dnl What version of Tcl should be used? +CYG_AC_PATH_TCL + +dnl -------------------------------------------------------------------- +dnl User-settable options. Currently these are handled via --enable +dnl command line options, in the absence of an accepted and more rational +dnl alternative. + +AC_ARG_ENABLE(tracebufsize,[ --enable-tracebufsize=X size of the trace buffer],[ + if test "$enableval" = "no" -o "$enableval" = "yes"; then + AC_MSG_ERROR("--enable-tracebufsize should be given a suitable value") + else + AC_DEFINE_UNQUOTED(CYGNUM_INFRA_TRACE_VECTOR_SIZE,$enableval) + fi +]) + +dnl -------------------------------------------------------------------- +dnl Directory structures. +dnl +dnl The purpose of this infrastructure implementation is to provide a way +dnl of giving host code access to the same set of assertions and tracing +dnl facilities as are available on the target side. The implementations +dnl of these facilities has to be rather different, for example the host +dnl side has to worry about running in both command-line and GUI tools, +dnl not to mention supporting different languages such as Tcl as well +dnl as C and C++. +dnl +dnl After a successful build there should be a library libcyginfra.a +dnl which can be linked with the application code and which can get +dnl installed. In addition there will be a set of header files. +dnl +dnl The infrastructure exports four main header files: +dnl +dnl cyg/infra/cyg_type.h data types, useful macros, and a +dnl few compiler-related odds and ends +dnl +dnl cyg/infra/cyg_ass.h lots of lovely assertion macros +dnl +dnl cyg/infra/cyg_trac.h lots of lovely trace macros +dnl +dnl cyg/infra/testcase.h routines for use in testcases +dnl +dnl These header files are shared between host and target side, to make +dnl sure that a consistent set of macros is used between the two. There +dnl are a number of host-specific extensions in the header files as +dnl well. +dnl +dnl The header files rely on a number of other header files: +dnl +dnl pkgconf/infra.h +dnl cyg/hal/basetype.h +dnl +dnl Obviously cyg/hal/basetype.h cannot be shared between host and target, +dnl instead it has to depend on autoconf information. +dnl +dnl Sharing pkgconf/infra.h between host and target is slightly more feasible, +dnl especially if we get the configuration tool to a point where it can +dnl be used for both host and target. However for now this would create a +dnl bit of confusion because two configuration systems would be in use, and +dnl it seems better to stick with just autoconf for now. Therefore +dnl pkgconf/infra.h #include's the file generated by autoconf and +dnl generates the appropriate #define's (it is not a good idea to have +dnl autoconf generate pkgconf/infra.h directly, autoconf is slightly too +dnl eager to do substitutions). +dnl +dnl The configuration header file that is normally generated is +dnl config.h. It is more in keeping with eCos conventions to have +dnl a different header file hostinfra.h instead. This can +dnl achieved using the appropriate AM_CONFIG_HEADER macro. +dnl +dnl Making the copies of cyg_type.h etc. is the responsibility of +dnl Makefile.am, configure is responsible only for the makefile and for +dnl hostinfra.h. + +AM_CONFIG_HEADER(hostinfra.h:config.h.in) +AC_OUTPUT(Makefile:Makefile.in testsuite/Makefile:testsuite/Makefile.in) + diff --git a/host/infra/cyg_ass.h b/host/infra/cyg_ass.h new file mode 100644 --- /dev/null +++ b/host/infra/cyg_ass.h @@ -0,0 +1,599 @@ +#ifndef CYGONCE_INFRA_CYG_ASS_H +#define CYGONCE_INFRA_CYG_ASS_H + +//========================================================================== +// +// cyg_ass.h +// +// Macros and prototypes for the assert system +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1997, 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg from an original by hmt +// Contributors: nickg +// Date: 1997-09-08 +// Purpose: Use asserts to avoid writing duff code. +// Description: Runtime tests that compile to nothing in +// release versions of the code, to allow +// as-you-go testing of alternate builds. +// Usage: #include +// ... +// CYG_ASSERT( pcount > 0, "Number of probes should be > 0!" ); +// +// which can result, for example, in a message of the form: +// ASSERT FAILED: probemgr.cxx:1340, scan_probes() : +// number of probes should be > 0! +// if the boolean "pcount > 0" is false. +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include + +#include // for CYGBLD_ATTRIB_NORET + +// ------------------------------------------------------------------------- +// If we do not have a function name macro, define it ourselves + +#ifndef CYGDBG_INFRA_DEBUG_FUNCTION_PSEUDOMACRO + // __PRETTY_FUNCTION__ does not work +# ifndef __PRETTY_FUNCTION__ // And it is not already defined +# define __PRETTY_FUNCTION__ NULL +# endif +#endif + +// ------------------------------------------------------------------------- +// this is executed to deal with failure - breakpoint it first! + +externC void +cyg_assert_fail( const char* /* psz_func */, const char* /* psz_file */, + cyg_uint32 /* linenum */, const char* /* psz_msg */ ) + CYGBLD_ATTRIB_NORET; + +// ------------------------------------------------------------------------- + +#ifdef CYGDBG_USE_ASSERTS + +// ------------------------------------------------------------------------- +// We define macros and appropriate prototypes for the assert/fail +// system. These are: +// CYG_FAIL - unconditional panic +// CYG_ASSERT - panic if boolean expression is false +// CYG_ASSERTC - compact version of CYG_ASSERT + +# ifdef CYGDBG_INFRA_DEBUG_ASSERT_MESSAGE +# define CYG_ASSERT_DOCALL( _msg_ ) \ + cyg_assert_fail( __PRETTY_FUNCTION__, __FILE__, __LINE__, _msg_ ); +# else +# define CYG_ASSERT_DOCALL( _msg_ ) \ + CYG_MACRO_START \ + const char* _tmp1_ = _msg_; \ + _tmp1_ = _tmp1_; \ + cyg_assert_fail( __PRETTY_FUNCTION__, __FILE__, __LINE__, NULL ); \ + CYG_MACRO_END +# endif + +// unconditional failure; use like panic(), coredump() &c. +# define CYG_FAIL( _msg_ ) \ + CYG_MACRO_START \ + CYG_ASSERT_DOCALL( _msg_ ); \ + CYG_MACRO_END + +// conditioned assert; if the condition is false, fail. +# define CYG_ASSERT( _bool_, _msg_ ) \ + CYG_MACRO_START \ + if ( ! ( _bool_ ) ) \ + CYG_ASSERT_DOCALL( _msg_ ); \ + CYG_MACRO_END + +# define CYG_ASSERTC( _bool_ ) \ + CYG_MACRO_START \ + if ( ! ( _bool_ ) ) \ + CYG_ASSERT_DOCALL( #_bool_ );\ + CYG_MACRO_END + +#else // ! CYGDBG_USE_ASSERTS + +// ------------------------------------------------------------------------- +// No asserts: we define empty statements for assert & fail. + +# define CYG_FAIL( _msg_ ) CYG_EMPTY_STATEMENT +# define CYG_ASSERT( _bool_, _msg_ ) CYG_EMPTY_STATEMENT +# define CYG_ASSERTC( _bool_ ) CYG_EMPTY_STATEMENT + +#endif // ! CYGDBG_USE_ASSERTS + +// ------------------------------------------------------------------------- +// Pointer integrity checks. +// These check not only for NULL pointer, but can also check for pointers +// that are outside to defined memory areas of the platform or executable. +// We differentiate between data and function pointers, so that we can cope +// with different formats, and so we can check them against different memory +// regions. + +externC cyg_bool cyg_check_data_ptr(void *ptr); +externC cyg_bool cyg_check_func_ptr(void (*ptr)(void)); + +#ifdef CYGDBG_USE_ASSERTS + +# define CYG_CHECK_DATA_PTR( _ptr_, _msg_ ) \ + CYG_MACRO_START \ + if( !cyg_check_data_ptr((void *)(_ptr_))) \ + CYG_ASSERT_DOCALL( _msg_ ); \ + CYG_MACRO_END + +# define CYG_CHECK_FUNC_PTR( _ptr_, _msg_ ) \ + CYG_MACRO_START \ + if( !cyg_check_func_ptr((void (*)(void))(_ptr_))) \ + CYG_ASSERT_DOCALL( _msg_ ); \ + CYG_MACRO_END + +# define CYG_CHECK_DATA_PTRC( _ptr_ ) \ + CYG_MACRO_START \ + if ( !cyg_check_data_ptr((void *)(_ptr_))) \ + CYG_ASSERT_DOCALL("data pointer (" #_ptr_ ") is valid");\ + CYG_MACRO_END + +# define CYG_CHECK_FUNC_PTRC( _ptr_ ) \ + CYG_MACRO_START \ + if ( !cyg_check_func_ptr((void (*)(void))(_ptr_))) \ + CYG_ASSERT_DOCALL("function pointer (" #_ptr_ ") is valid"); \ + CYG_MACRO_END + +#else // CYGDBG_USE_ASSERTS + +# define CYG_CHECK_DATA_PTR( _ptr_, _msg_ ) CYG_EMPTY_STATEMENT +# define CYG_CHECK_FUNC_PTR( _ptr_, _msg_ ) CYG_EMPTY_STATEMENT +# define CYG_CHECK_DATA_PTRC( _ptr_ ) CYG_EMPTY_STATEMENT +# define CYG_CHECK_FUNC_PTRC( _ptr_ ) CYG_EMPTY_STATEMENT + +#endif // CYGDBG_USE_ASSERTS + +// ------------------------------------------------------------------------- +// Unconditional definitions: + +// Check an object for validity by calling its own checker. +// Usage: +// ClassThing *p = &classobject; +// CYG_ASSERTCLASS( p, "Object at p is broken!" ); + +// this enum gives some options as to how keenly to test; avoids cluttering +// the member function declaration if the implementor wants to do more +// zealous tests themselves. + +enum cyg_assert_class_zeal { + cyg_system_test = -1, + cyg_none = 0, + cyg_trivial, + cyg_quick, + cyg_thorough, + cyg_extreme +}; + +// ------------------------------------------------------------------------- +// Define macros for checking classes: +// +// CYG_ASSERT_CLASS - do proforma check on a class pointer +// CYG_ASSERT_CLASSO - do proforma check on a class object +// CYG_ASSERT_ZERO_OR_CLASS- a class pointer is NULL or valid +// CYG_ASSERT_THIS - "this" is valid +// + 3 compact variants and two aliases for backwards compatibility. +// +// All of these end up going via CYG_ASSERT(), which will be an empty +// statement if CYGDBG_USE_ASSERTS is disabled. There is no need to +// test CYGDBG_USE_ASSERTS again here. +// +// The idiom required is that a class have a member function called +// "bool check_this( cyg_assert_class_zeal ) const" that returns true +// iff the object is OK. This need not be conditionally compiled against +// CYGDBG_USE_ASSERTS but it can be if only this macro is used to +// invoke it. Alternatively it can be invoked by hand with other +// choices from the above enum. + +// Assert the checker function of an object by pointer, or in hand. + +#ifdef __cplusplus + +# ifndef CYG_ASSERT_CLASS_ZEAL +# define CYG_ASSERT_CLASS_ZEAL (cyg_quick) // can be redefined locally +# endif + +# define CYG_ASSERT_CLASS( _pobj_, _msg_ ) \ + CYG_ASSERT( ((0 != (_pobj_)) && \ + (_pobj_)->check_this( CYG_ASSERT_CLASS_ZEAL )), _msg_ ) + +# define CYG_ASSERTCLASS( _pobj_,_msg_) \ + CYG_ASSERT_CLASS( (_pobj_), _msg_ ) + +# define CYG_ASSERT_CLASSO( _obj_, _msg_ ) \ + CYG_ASSERT( (_obj_).check_this( CYG_ASSERT_CLASS_ZEAL ), _msg_ ) + +# define CYG_ASSERTCLASSO( _obj_, _msg_ ) \ + CYG_ASSERT_CLASSO( (_obj_), _msg_ ) + +# define CYG_ASSERT_ZERO_OR_CLASS( _pobj_, _msg_ ) \ + CYG_ASSERT( ((0 == (_pobj_)) || \ + (_pobj_)->check_this( CYG_ASSERT_CLASS_ZEAL )), _msg_ ) + +# define CYG_ASSERT_THIS( _msg_ ) \ + CYG_ASSERT( this->check_this( CYG_ASSERT_CLASS_ZEAL ), _msg_ ) + +# define CYG_ASSERT_CLASSC( _pobj_ ) \ + CYG_ASSERT_CLASS( (_pobj_), "class pointer (" #_pobj_ ") is valid" ) + +# define CYG_ASSERT_CLASSOC( _obj_ ) \ + CYG_ASSERT_CLASSO( (_obj_), "object (" #_obj_ ") is valid" ) + +# define CYG_ASSERT_ZERO_OR_CLASSC( _pobj_ ) \ + CYG_ASSERT_ZERO_OR_CLASS((_pobj_), \ + "class pointer (" #_pobj_ ") is zero or valid") + +# define CYG_ASSERT_THISC( ) \ + CYG_ASSERT_THIS( "\"this\" pointer is valid" ) + +#define CYGDBG_DEFINE_CHECK_THIS \ + bool check_this( cyg_assert_class_zeal zeal ) const; + +#endif // __cplusplus + +// ------------------------------------------------------------------------- +// Some alternative names for basic assertions that we can disable +// individually. +// +// CYG_PRECONDITION - argument checking etc +// CYG_POSTCONDITION - results etc +// CYG_LOOP_INVARIANT - for putting in loops +// +// C++ programmers have class-related variants of all of these. + +#ifdef CYGDBG_INFRA_DEBUG_PRECONDITIONS +# define CYG_PRECONDITION( _bool_ , _msg_ ) CYG_ASSERT( _bool_, _msg_ ) +# define CYG_PRECONDITIONC( _bool_ ) \ + CYG_ASSERT( _bool_, "precondition " #_bool_) +#else +# define CYG_PRECONDITION( _bool_ , _msg_ ) CYG_EMPTY_STATEMENT +# define CYG_PRECONDITIONC( _bool_ ) CYG_EMPTY_STATEMENT +#endif + +#ifdef CYGDBG_INFRA_DEBUG_POSTCONDITIONS +# define CYG_POSTCONDITION( _bool_ , _msg_ ) CYG_ASSERT( _bool_, _msg_ ) +# define CYG_POSTCONDITIONC( _bool_ ) \ + CYG_ASSERT( _bool_, "postcondition " #_bool_) +#else +# define CYG_POSTCONDITION( _bool_ , _msg_ ) CYG_EMPTY_STATEMENT +# define CYG_POSTCONDITIONC( _bool_ ) CYG_EMPTY_STATEMENT +#endif + +#ifdef CYGDBG_INFRA_DEBUG_LOOP_INVARIANTS +# define CYG_LOOP_INVARIANT( _bool_ , _msg_ ) CYG_ASSERT( _bool_, _msg_ ) +# define CYG_LOOP_INVARIANTC( _bool_ ) \ + CYG_ASSERT( _bool_, "loop invariant " #_bool_ ) +#else +# define CYG_LOOP_INVARIANT( _bool_ , _msg_ ) CYG_EMPTY_STATEMENT +# define CYG_LOOP_INVARIANTC( _bool_ ) CYG_EMPTY_STATEMENT +#endif + +#ifdef __cplusplus + +// All variants of _CLASS +# define CYG_PRECONDITION_CLASS( _pobj_, _msg_ ) \ + CYG_PRECONDITION( ((0 != (_pobj_)) && \ + (_pobj_)->check_this(CYG_ASSERT_CLASS_ZEAL)), _msg_) + +# define CYG_PRECONDITION_CLASSC( _pobj_ ) \ + CYG_PRECONDITION_CLASS( (_pobj_), \ + "precondition, class pointer (" #_pobj_ ") is valid" ) + +# define CYG_POSTCONDITION_CLASS( _pobj_, _msg_ ) \ + CYG_POSTCONDITION( ((0 != (_pobj_)) && \ + (_pobj_)->check_this(CYG_ASSERT_CLASS_ZEAL)), _msg_) + +# define CYG_POSTCONDITION_CLASSC( _pobj_ ) \ + CYG_POSTCONDITION_CLASS( (_pobj_), \ + "postcondition, class pointer (" #_pobj_ ") is valid" ) + +# define CYG_LOOP_INVARIANT_CLASS( _pobj_, _msg_) \ + CYG_LOOP_INVARIANT( ((0 != (_pobj_)) && \ + (_pobj_)->check_this(CYG_ASSERT_CLASS_ZEAL)), _msg_) + +# define CYG_LOOP_INVARIANT_CLASSC( _pobj_ ) \ + CYG_LOOP_INVARIANT_CLASS( (_pobj_), \ + "loop invariant, class pointer (" #_pobj_ ") is valid" ) + +// All variants of _CLASSO +# define CYG_PRECONDITION_CLASSO( _obj_, _msg_ ) \ + CYG_PRECONDITION( (_obj_).check_this(CYG_ASSERT_CLASS_ZEAL), _msg_) + +# define CYG_PRECONDITION_CLASSOC( _obj_ ) \ + CYG_PRECONDITION_CLASSO( (_obj_), \ + "precondition, object (" #_obj_ ") is valid" ) + +# define CYG_POSTCONDITION_CLASSO( _obj_, _msg_ ) \ + CYG_POSTCONDITION( (_obj_).check_this(CYG_ASSERT_CLASS_ZEAL), _msg_) + +# define CYG_POSTCONDITION_CLASSOC( _obj_ ) \ + CYG_POSTCONDITION_CLASSO( (_obj_), \ + "postcondition, object (" #_obj_ ") is valid" ) + +# define CYG_LOOP_INVARIANT_CLASSO( _obj_, _msg_) \ + CYG_LOOP_INVARIANT( (_obj_).check_this(CYG_ASSERT_CLASS_ZEAL), _msg_) + +# define CYG_LOOP_INVARIANT_CLASSOC( _obj_ ) \ + CYG_LOOP_INVARIANT_CLASSO( (_obj_), \ + "loop invariant, object (" #_obj_ ") is valid" ) + +// All variants of _ZERO_OR_CLASS +# define CYG_PRECONDITION_ZERO_OR_CLASS( _pobj_, _msg_ ) \ + CYG_PRECONDITION( ((0 == (_pobj_)) || \ + (_pobj_)->check_this(CYG_ASSERT_CLASS_ZEAL)), _msg_) + +# define CYG_PRECONDITION_ZERO_OR_CLASSC( _pobj_ ) \ + CYG_PRECONDITION_ZERO_OR_CLASS( (_pobj_), \ + "precondition, class pointer (" #_pobj_ ") is zero or valid" ) + +# define CYG_POSTCONDITION_ZERO_OR_CLASS( _pobj_, _msg_ ) \ + CYG_POSTCONDITION( ((0 == (_pobj_)) || \ + (_pobj_)->check_this(CYG_ASSERT_CLASS_ZEAL)), _msg_) + +# define CYG_POSTCONDITION_ZERO_OR_CLASSC( _pobj_ ) \ + CYG_POSTCONDITION_ZERO_OR_CLASS( (_pobj_), \ + "postcondition, class pointer (" #_pobj_ ") is zero or valid" ) + +# define CYG_LOOP_INVARIANT_ZERO_OR_CLASS( _pobj_, _msg_) \ + CYG_LOOP_INVARIANT( ((0 == (_pobj_)) || \ + (_pobj_)->check_this(CYG_ASSERT_CLASS_ZEAL)), _msg_) + +# define CYG_LOOP_INVARIANT_ZERO_OR_CLASSC( _pobj_ ) \ + CYG_LOOP_INVARIANT_ZERO_OR_CLASS( (_pobj_), \ + "loop invariant, class pointer (" #_pobj_ ") is zero or valid" ) + +// All variants of _THIS +# define CYG_PRECONDITION_THIS( _msg_ ) \ + CYG_PRECONDITION( this->check_this(CYG_ASSERT_CLASS_ZEAL), _msg_) + +# define CYG_PRECONDITION_THISC() \ + CYG_PRECONDITION_THIS( "precondition, \"this\" is valid" ) + +# define CYG_POSTCONDITION_THIS( _msg_ ) \ + CYG_POSTCONDITION( this->check_this(CYG_ASSERT_CLASS_ZEAL), _msg_) + +# define CYG_POSTCONDITION_THISC() \ + CYG_POSTCONDITION_THIS( "postcondition, \"this\" is valid" ) + +# define CYG_LOOP_INVARIANT_THIS( _msg_) \ + CYG_LOOP_INVARIANT( this->check_this(CYG_ASSERT_CLASS_ZEAL), _msg_) + +# define CYG_LOOP_INVARIANT_THISC() \ + CYG_LOOP_INVARIANT_THIS( "loop invariant, \"this\" is valid" ) + +#endif // __cplusplus + +// ------------------------------------------------------------------------- +// Invariants. These are a bit more interesting. The ordinary invariants +// take an arbitrary boolean expression, and C++ does not provide any way +// of evaluating this expression automatically on entry and exit - any +// attempt to use local objects leads to trying to evaluate the expression +// when it is not in scope. This problem does not arise with objects. +// +// For C++ objects it is possible to do a bit better. A template can be +// used to create a local object whose constructor will validate the +// target object and whose destructor will validate the target object +// again. Unfortunately it is necessary to pass the type as well as +// the object: typeof() is a gcc extension, and RTTI's typeid facility +// would provide the derived class and not what we actually want. + +#ifdef CYGDBG_INFRA_DEBUG_INVARIANTS + +# define CYG_INVARIANT( _bool_, _msg_ ) \ + CYG_MACRO_START \ + if ( ! ( _bool_ ) ) \ + CYG_ASSERT_DOCALL( _msg_ ); \ + CYG_MACRO_END + +# define CYG_INVARIANTC( _bool_ ) \ + CYG_MACRO_START \ + if ( ! ( _bool_ ) ) \ + CYG_ASSERT_DOCALL( "invariant (" #_bool_ ")" ); \ + CYG_MACRO_END + +# ifdef __cplusplus +// NOTE: if the compiler does not manage to inline the appropriate +// template functions then the impact on code size and performance becomes +// rather large. But there are significant performance overheads anyway +// simply because of the call to check_this()... +// +template class __CygInvariantObject { + + const X* rep; + + private: + // Prevent access to the default constructors. + __CygInvariantObject() { } + __CygInvariantObject( const __CygInvariantObject& arg ) { } + __CygInvariantObject & operator=( const __CygInvariantObject & arg) { return *this; } + + public: + __CygInvariantObject( X* arg, const char* msg ) : rep(arg) { + if ( !rep->check_this( CYG_ASSERT_CLASS_ZEAL ) ) + CYG_ASSERT_DOCALL( msg ); + } + __CygInvariantObject( X& arg, const char* msg ) : rep(&arg) { + if ( !rep->check_this( CYG_ASSERT_CLASS_ZEAL ) ) + CYG_ASSERT_DOCALL( msg ); + } + __CygInvariantObject( const X* arg, const char* msg ) : rep(arg) { + if ( !rep->check_this( CYG_ASSERT_CLASS_ZEAL ) ) + CYG_ASSERT_DOCALL( msg ); + } + __CygInvariantObject( const X& arg, const char* msg ) : rep(&arg) { + if ( !rep->check_this( CYG_ASSERT_CLASS_ZEAL ) ) + CYG_ASSERT_DOCALL( msg ); + } + ~__CygInvariantObject( ) { + if ( !rep->check_this( CYG_ASSERT_CLASS_ZEAL ) ) + CYG_ASSERT_DOCALL( "invariant, object valid on exit" ); + rep = 0; + }; +}; + +// +// These macros provide sensible concatenation facilities at +// the C preprocessor level, getting around complications in the +// macro expansion rules related to __LINE__ and __FILE__. + +# define __CYG_INVARIANT_CLASSNAME_AUX( a, b) a ## b +# define __CYG_INVARIANT_CLASSNAME( a, b ) \ + __CYG_INVARIANT_CLASSNAME_AUX( a, b ) + + +// These macro definitions do not use CYG_MACRO_START because +// I do not want the scope of the local objects to get confused. +// +// The first line of the macro expansion specifies the type of +// the local object being created. The second line invents a +// name for this object. The third line provides command-line +// arguments. + +# define CYG_INVARIANT_CLASS( _type_, _pobj_, _msg_ ) \ + __CygInvariantObject<_type_> \ + __CYG_INVARIANT_CLASSNAME( __invariant_class_, __LINE__ ) \ + ( _pobj_, _msg_ ) + +# define CYG_INVARIANT_CLASSC( _type_, _pobj_ ) \ + __CygInvariantObject<_type_> \ + __CYG_INVARIANT_CLASSNAME( __invariant_class_, __LINE__ ) \ + ( _pobj_, "invariant, class pointer (" #_pobj_ ") is valid" ) + +# define CYG_INVARIANT_CLASSO( _type_, _obj_, _msg_ ) \ + __CygInvariantObject<_type_> \ + __CYG_INVARIANT_CLASSNAME( __invariant_class_, __LINE__ ) \ + ( _obj_, _msg_ ) + +# define CYG_INVARIANT_CLASSOC( _type_, _obj_ ) \ + __CygInvariantObject<_type_> \ + __CYG_INVARIANT_CLASSNAME( __invariant_class_, __LINE__ ) \ + ( _obj_, "invariant, object (" #_obj_ ") is valid" ) + +# define CYG_INVARIANT_THIS( _type_, _msg_ ) \ + __CygInvariantObject<_type_> \ + __CYG_INVARIANT_CLASSNAME( __invariant_class_, __LINE__ ) \ + ( this, _msg_ ) + +# define CYG_INVARIANT_THISC( _type_ ) \ + __CygInvariantObject<_type_> \ + __CYG_INVARIANT_CLASSNAME( __invariant_class_, __LINE__ ) \ + ( this, "invariant, \"this\" is valid" ) + +# endif // __cplusplus + +#else // !CYGDBG_INFRA_DEBUG_INVARIANTS + +# define CYG_INVARIANT( _bool_, _msg_ ) CYG_EMPTY_STATEMENT +# define CYG_INVARIANTC( _bool_ ) CYG_EMPTY_STATEMENT + +# ifdef __cplusplus + +# define CYG_INVARIANT_CLASS( _type_, _pobj_, _msg_ ) +# define CYG_INVARIANT_CLASSC( _type_, _pobj_ ) +# define CYG_INVARIANT_CLASSO( _type_, _obj_, _msg_ ) +# define CYG_INVARIANT_CLASSOC( _type_, _obj_ ) +# define CYG_INVARIANT_THIS( _type_, _msg_ ) +# define CYG_INVARIANT_THISC( _type_ ) + +# endif + +#endif // CYGDBG_INFRA_DEBUG_INVARIANTS + +// ------------------------------------------------------------------------- +// Compile time failure; like #error but in a macro so we can use it in +// other definitions. +// +// Usage: +// #define new CYG_COMPILETIMEFAIL( "Do NOT use new!") + +#define CYG_COMPILETIMEFAIL( _msg_ ) !!!-- _msg_ --!!! + + +// ------------------------------------------------------------------------- +// The host-side implementation of the infrastructure provides a number +// of additional functions that allow applications to provide their own +// implementation of cyg_assert_fail(). This is not strictly necessary +// since the presence of cyg_assert_fail() in the application would +// override the one in the library anyway, but it is useful to make +// certain functionality more readily available. +// +// These declarations are only available if the symbol +// CYG_DECLARE_HOST_ASSERTION_SUPPORT is defined. +#ifdef CYG_DECLARE_HOST_ASSERTION_SUPPORT + +// The default assertion handler writes its output to a file and +// if possible a suitable message to stdout. It is possible to +// install an alternative handler. If this alternative returns false +// then the default handler will be invoked instead, otherwise the +// application will exit. +externC void cyg_assert_install_failure_handler( + bool (*)(const char* /* psz_func */, + const char* /* psz_file */, + cyg_uint32 /* linenum */, + const char* /* psz_msg */) ); + +// Register a callback that should get invoked as part of handling an +// assertion failure and that will typically produce some additional +// output. For example the trace code will install a callback to output +// trace information. +// +// The first argument is a string identifying the callback. The second +// argument is a function pointer for the callback itself, whose +// argument is another function that can be invoked for output. +externC void cyg_assert_install_failure_callback( + const char* /* name */, + void (*)( void (*)(const char*) )); + +// This function can be called by assert failure handlers to invoke +// the installed callbacks. The three arguments are function pointers +// that get invoked prior to callback invocation, by the callback itself, +// and after each callback. In the first case the argument will be the +// callback name. +externC void cyg_assert_failure_invoke_callbacks( + void (*)(const char* /* name */), + void (*)(const char* /* callback data */ ), + void (*)(void) ); + +// This function is intended to be called from inside gdb instead of +// cyg_assert_fail(),, without the need to specify a filename or +// anything else. +externC void cyg_assert_quickfail(void); + +#endif // CYG_DECLARE_HOST_ASSERTION_SUPPORT + +// ------------------------------------------------------------------------- + +#endif // CYGONCE_INFRA_CYG_ASS_H multiple inclusion protection +// EOF cyg_ass.h diff --git a/host/infra/cyg_trac.h b/host/infra/cyg_trac.h new file mode 100644 --- /dev/null +++ b/host/infra/cyg_trac.h @@ -0,0 +1,1647 @@ +#ifndef CYGONCE_INFRA_CYG_TRAC_H +#define CYGONCE_INFRA_CYG_TRAC_H + +//========================================================================== +// +// cyg_trac.h +// +// Macros and prototypes for the tracing system +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg from an original by hmt +// Contributors: nickg +// Date: 1998-04-23 +// Purpose: Use traces to log procedure entry, and "print" stuff +// Description: Runtime logging messages that compile to nothing in +// release versions of the code, to allow +// as-you-go tracing of alternate builds. +// Usage: #include +// ... +// CYG_TRACE2( PIPE_TRACE, "pipe %x, data %d", ppipe, oword ); +// +// which can result, for example, in a message of the form: +// "TRACE: pipemgr.cxx:1340, write_pipe(): pipe 0x8004c, data 17" +// +//####DESCRIPTIONEND#### +// + +/**************************************************************************** + +Explicit tracing +================ + +CYG_TRACE0( bool, msg ); +CYG_TRACE1( bool, msg, arg1 ); +CYG_TRACE2( bool, msg, arg1, arg2 ); +.... +CYG_TRACE8( bool, msg, .... [with 8 args] ); + +In general, the bool controls whether or not the tracing occurs for a +particular invocation of the macro. The msg is a printf-style string, +though exactly which formats are supported depends on the underlying +implementation. Typically, at least %d, %x, %08x, %c and %s will be +supported. Of course a most compact implementation might print + + TRACE:z1dbuff.c[92]get_nextdata(): data pointer %x offset %d: 42BD8 1C + +or some such, leaving you to work it out for yourself. + +It is expected that the boolean would rarely actually be a complex +expression; it is more likely that it would either be "1", tracing being +controlled for the whole compilation unit or subsystem by means of the +CYGDBG_USE_TRACING symbol, or a local symbol for tracing over the whole +file, defined to 0 or to 1. For runtime control of tracing in a debugging +session, it is typical to use symbols defined to expressions such as: + + static int xxx_trace = 0; + #define TL1 (0 < xxx_trace) + #define TL2 (1 < xxx_trace) + +so you set xxx_trace to 1 to enable those messages conditioned by TL1 +(trace level 1) and so on. + + CYG_TRACE1( TL1, "Major argument is %d", zz ); + CYG_TRACE4( TL2, "...minor details %d %d %d %d", m1, m2, m3 ,m4 ); + +To assist with the case where the same symbol or expression is used +throughout a compilation unit, the programmer can define the symbol +CYG_TRACE_USER_BOOL as they choose and then use convenience macros with the +suffix 'B' in the obvious manner: + + #define CYG_TRACE_USER_BOOL (xxx_trace > 0) + CYG_TRACE2B( "Counters are %d, %d", countlo, counthi ); + +For the case where you just want to print a load of numbers in hex, or +decimal, convenience suffices X, D and Y are provided. X uses %08x, D %d +and Y an unadorned %x for each argument. + + CYG_TRACE3D( TL2, m1, m2, d ); + +If you want to do something similar but with a little more comment, the +names (strictly spellings) of the variables you are printing can be used by +appending a V to the X, D or Y. + + CYG_TRACE3DV( TL2, m1, m2, d ); + +might output: + + TRACE:z1dbuff.c[92]get_nextdata(): m1=23 m2=-4 d=55 + +These conveniences can be combined, and they apply equally to tracing with +up to 8 variables; the B for Bool goes last: + + CYG_TRACE4DVB( i, i*i, i*i*i, i*i*i*i ); + +might output: + + TRACE:table.c[12]main(): i=3 i*i=9 i*i*i=27 i*i*i*i=81 + + +Function Tracing +================ + +There are also facities for easily reporting function entry and exit, +printing the function arguments, and detecting returns without logging (or +without a value!). + +The basic facility is + + CYG_REPORT_FUNCTION(); + +In C, place this between the local variable declarations and the first +statement or errors will ensue. C++ is more flexible; place the macro as +the first line of all functions you wish to trace. The following +variations are also provided: + + CYG_REPORT_FUNCTYPE( exitmsg ) provide a printf string for the type + of the returned value + CYG_REPORT_FUNCNAME( name ) supply a function name explicitly, for + if __FUNCTION__ is not supported + CYG_REPORT_FUNCNAMETYPE( name, exitmsg ) both of the above extensions + +These are unconditional; the assumption is that if function reporting is +used at all it will be used for all functions within a compilation unit. +However, it is useful to be able to control function reporting at finer +grain without editing the source files concerned, at compile time or at +runtime. To support this, conditioned versions (with suffix 'C') are +provided for the above four macros, which only procduce trace output if the +macro CYG_REPORT_USER_BOOL evaluates true. + + CYG_REPORT_FUNCTIONC() + CYG_REPORT_FUNCNAMEC( name ) + CYG_REPORT_FUNCTYPEC( exitmsg ) + CYG_REPORT_FUNCNAMETYPEC( name, exitmsg ) + +You can define CYG_REPORT_USER_BOOL to anything you like before invoking +these macros; using a simple -DCYG_REPORT_USER_BOOL=0 or ...=1 on the +compiler command line would do the trick, but there is more flexibility to +be gained by something like: + + #define CYG_REPORT_USER_BOOL (reporting_bool_FOO) + #ifdef TRACE_FOO + int reporting_bool_FOO = 1; + #else + int reporting_bool_FOO = 0; + #endif + +where FOO relates to the module name. Thus an external symbol sets the +default, but it can be overridden in a debugging session by setting the +variable reporting_bool_FOO. + +Note that the condition applied to the initial CYG_REPORT_FUNC...() macro +controls all function-related reporting (not tracing) from that function; +the underlying mechanisms still operate even if no output is created. Thus +no conditioned variants of CYG_REPORT_FUNCARG[s] nor of CYG_REPORT_RETURN +are needed. + +Examples: + int myfunction() + { + CYG_REPORT_FUNCTYPE( "recode is %d" ); + +A function return is traced using + + CYG_REPORT_RETURN() a void return + CYG_REPORT_RETVAL( value ) returning a value + +With the CYG_REPORT_FUNCTYPE example, the latter might produce a message +like: + + TRACE:myprog.c[40]fact(): enter + TRACE:myprog.c[53]fact(): retcode is 24 + +It is also useful to trace the values of the arguments to a function: + CYG_REPORT_FUNCARGVOID confirms that the function is void + CYG_REPORT_FUNCARG1( format, arg ) printf-style + to + CYG_REPORT_FUNCARG8( format, arg1...arg8 ) printf-style + +The CYG_REPORT_FUNCARG[1-8] macros are also offered with the convenience +extensions: D, X, or Y, and V like the explicit tracing macros. For +example: + + int fact( int number ) + { + CYG_REPORT_FUNCTYPE( "recode is %d" ); + CYG_REPORT_FUNCARG1DV( number ); + int result = number; + while ( --number > 1 ) result *= number + CYG_REPORT_RETVAL( result ); + return result; + } + +might produce: + + TRACE:myprog.c[40]fact(): enter + TRACE:myprog.c[40]fact(): number=4 + TRACE:myprog.c[53]fact(): retcode is 24 + +If no exit message is provided, a default of %08x is used. + + +General Configury +================= + +If CYGDBG_INFRA_DEBUG_FUNCTION_PSEUDOMACRO is *not* defined, it is assumed +that __PRETTY_FUNCTION__ or equivalents do not exist, so no function name +tracing is possible; only file and line number. + +If CYGDBG_INFRA_DEBUG_TRACE_MESSAGE is *not* defined, the message and +arguments to all tracing macros are not used; only "execution was here" +type information, by file, function and line number, is available. This +can greatly reduce the size of an image with tracing disabled, which may be +crucial in debugging on actual shipped hardware with limited memory. + +If configured for buffered tracing then CYG_TRACE_PRINT() can be used to +output the contents of the trace buffer on demand. + +CYG_TRACE_DUMP() outputs a form of "core dump" containing info on the +scheduler and threads at the time. This information will be invalid if +the kernel is not running. + +C/C++: in C++ the function reporting is implemented using a class object +with a destructor; this allows reporting of a return which has not been +explicitly reported, and detection of accidental multiple return reports. +This helps you write the function reporting correctly. In C it is not +possible to be so sophisticated, so the implementation is not so helpful in +detecting errors in the use of the tracing system. + +Note that for all of the above variations, the internal API to the +functions which are called in consequence of tracing remains the same, so +these variations can be mixed in the same executable, by configuring the +tracing macros differently in different compilation units or subsystems. + + +Summary +======= + +Explicit tracing +---------------- + +CYG_TRACE0( bool, msg ) if bool, print msg +CYG_TRACE1( bool, msg, arg ) if bool, printf-style + to +CYG_TRACE8( bool, msg, arg1...arg8 ) if bool, printf-style + +CYG_TRACE0B( msg, args... ) to CYG_TRACE8B() use CYG_TRACE_USER_BOOL + +CYG_TRACE1X( bool, args... ) to CYG_TRACE8X() print args using %08x +CYG_TRACE1Y( bool, args... ) to CYG_TRACE8Y() print args using %x +CYG_TRACE1D( bool, args... ) to CYG_TRACE8D() print args using %d + +CYG_TRACE1XV( bool, args... ) to CYG_TRACE8XV() print args using "arg=%08x" +CYG_TRACE1YV( bool, args... ) to CYG_TRACE8YV() print args using "arg=%x" +CYG_TRACE1DV( bool, args... ) to CYG_TRACE8DV() print args using "arg=%d" + +CYG_TRACE1XB( args... ) to CYG_TRACE8XB() print using %08x, no bool +CYG_TRACE1YB( args... ) to CYG_TRACE8YB() print using %x, no bool +CYG_TRACE1DB( args... ) to CYG_TRACE8DB() print using %d, no bool + +CYG_TRACE1XVB( args... ) to CYG_TRACE8XVB() use "arg=%08x", no bool +CYG_TRACE1YVB( args... ) to CYG_TRACE8YVB() use "arg=%x", no bool +CYG_TRACE1DVB( args... ) to CYG_TRACE8DVB() use "arg=%d", no bool + +Function tracing +---------------- + +CYG_REPORT_FUNCTION() default function entry +CYG_REPORT_FUNCNAME( name ) name the function +CYG_REPORT_FUNCTYPE( exitmsg ) printf for retval +CYG_REPORT_FUNCNAMETYPE( name, exitmsg ) both + +CYG_REPORT_FUNCTIONC() as above, but conditional +CYG_REPORT_FUNCNAMEC( name ) on CYG_REPORT_USER_BOOL +CYG_REPORT_FUNCTYPEC( exitmsg ) however it is defined +CYG_REPORT_FUNCNAMETYPEC( name, exitmsg ) ... + +CYG_REPORT_RETURN() void function exit +CYG_REPORT_RETVAL( value ) returning value + +CYG_REPORT_FUNCARGVOID() void function entry +CYG_REPORT_FUNCARG1( format, arg ) printf-style + to +CYG_REPORT_FUNCARG8( format, arg1...arg8 ) printf-style + +CYG_REPORT_FUNCARG1X( arg ) + to +CYG_REPORT_FUNCARG8X( arg1...arg8 ) use %08x +CYG_REPORT_FUNCARG1Y... use %x +CYG_REPORT_FUNCARG1D... use %d + +CYG_REPORT_FUNCARG1XV... use "arg=%08x" +CYG_REPORT_FUNCARG1YV... use "arg=%x" +CYG_REPORT_FUNCARG1DV... use "arg=%d" + +Other +----- + +CYG_TRACE_DUMP() dumps kernel state +CYG_TRACE_PRINT() prints buffered tracing + + +--------------------------------------------------------------------------- + +Internal Documentation +====================== + +The required functions which are used by the tracing macros are + + externC void + cyg_tracenomsg( char *psz_func, char *psz_file, cyg_uint32 linenum ); + + externC void + cyg_tracemsg( cyg_uint32 what, + char *psz_func, char *psz_file, cyg_uint32 linenum, + char *psz_msg ); + + externC void + cyg_tracemsg2( cyg_uint32 what, + char *psz_func, char *psz_file, cyg_uint32 linenum, + char *psz_msg, + CYG_ADDRWORD arg0, CYG_ADDRWORD arg1 ); + // extended in the obvious way for 4,6,8 arguments + +These functions should expect psz_func and psz_file to possibly be NULL in +case those facilities are not available in the compilation environment, and +do something safe in such cases. A NULL message should really be dealt +with safely also, just logging "execution here" info like cyg_tracenomsg(). + +Discussion of possible underlying implementations +------------------------------------------------- + +It is intended that the functions that get called can simply print the info +they are given in as fancy a format as you like, or they could do the +printf-type formatting and log the resulting text in a buffer. They get +told the type of event (function-entry, function-arguments, function-exit +or plain tracing info) and so can perform fancy indenting, for example, to +make call stack inspection more obvious to humans. It is also intended +that a more compact logging arrangement be possible, for example one which +records, in 32-bit words (CYG_ADDRWORDs), the addresses of the file, +function and msg strings, the line number and the arguments. This has the +implication that the msg string should not be constructed dynamically but +be static ie. a plain quoted C string. The number of arguments also must +be recorded, and if it is chosen to save string arguments in the buffer +rather than just their addresses (which could be invalid by the time the +logged information is processed) some flagging of which arguments are +strings must be provided. The system could also be extended to deal with +floats of whichever size fir in a CYG_ADDRWORD; these would probably +require special treatment also. With these considerations in mind, the +maximum number of parameters in a single trace message has been set to 8, +so that a byte bitset could be used to indicate which arguments are +strings, another for those which are floats, and the count of arguments +also fits in a byte as number or a bitset. + + +****************************************************************************/ + +#include + +#include + +// ------------------------------------------------------------------------- +// CYGDBG_INFRA_DEBUG_FUNCTION_PSEUDOMACRO is dealt with in cyg_ass.h. +// ------------------------------------------------------------------------- + +#ifdef CYGDBG_USE_TRACING + +// ------------------------------------------------------------------------- +// We define macros and appropriate prototypes for the trace/fail +// system. These are: +// CYG_TRACE0..8 - trace if boolean +// CYG_TRACEPROC - default no comment proc entry +// CYG_TRACEPROCOUT - default no comment proc exit +// CYG_TRACE_DUMP - outputs a form of "core dump", including the state +// of the kernel scheduler, threads, etc. +// CYG_TRACE_PRINT - Forces manual output of any trace info that has +// been buffered up. + +// these are executed to deal with tracing - breakpoint? + +externC void +cyg_tracenomsg( char *psz_func, char *psz_file, cyg_uint32 linenum ); + +externC void +cyg_trace_dump(void); + +#define CYG_TRACE_DUMP() cyg_trace_dump() + +#ifdef CYGDBG_INFRA_DEBUG_TRACE_ASSERT_BUFFER + +externC void +cyg_trace_print(void); + +#define CYG_TRACE_PRINT() cyg_trace_print() + +#else +#define CYG_TRACE_PRINT() CYG_EMPTY_STATEMENT +#endif + +// provide every other one of these as a space/caller bloat compromise. + +# ifdef CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + +enum cyg_trace_what{ + cyg_trace_trace = 0, + cyg_trace_enter, + cyg_trace_args, + cyg_trace_return, +// cyg_trace_, +// cyg_trace_, +}; + +externC void +cyg_tracemsg( cyg_uint32 what, + char *psz_func, char *psz_file, cyg_uint32 linenum, + char *psz_msg ); + +externC void +cyg_tracemsg2( cyg_uint32 what, + char *psz_func, char *psz_file, cyg_uint32 linenum, + char *psz_msg, + CYG_ADDRWORD arg0, CYG_ADDRWORD arg1 ); +externC void +cyg_tracemsg4( cyg_uint32 what, + char *psz_func, char *psz_file, cyg_uint32 linenum, + char *psz_msg, + CYG_ADDRWORD arg0, CYG_ADDRWORD arg1, + CYG_ADDRWORD arg2, CYG_ADDRWORD arg3 ); +externC void +cyg_tracemsg6( cyg_uint32 what, + char *psz_func, char *psz_file, cyg_uint32 linenum, + char *psz_msg, + CYG_ADDRWORD arg0, CYG_ADDRWORD arg1, + CYG_ADDRWORD arg2, CYG_ADDRWORD arg3, + CYG_ADDRWORD arg4, CYG_ADDRWORD arg5 ); +externC void +cyg_tracemsg8( cyg_uint32 what, + char *psz_func, char *psz_file, cyg_uint32 linenum, + char *psz_msg, + CYG_ADDRWORD arg0, CYG_ADDRWORD arg1, + CYG_ADDRWORD arg2, CYG_ADDRWORD arg3, + CYG_ADDRWORD arg4, CYG_ADDRWORD arg5, + CYG_ADDRWORD arg6, CYG_ADDRWORD arg7 ); + +#endif // CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + +// ------------------------------------------------------------------------- + +# ifdef CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + +# define CYG_TRACE_docall0( _msg_ ) \ + cyg_tracemsg( cyg_trace_trace, \ + __PRETTY_FUNCTION__, __FILE__, __LINE__, _msg_ ); + +# define CYG_TRACE_docall2( _msg_, _arg0_, _arg1_ ) \ + cyg_tracemsg2( cyg_trace_trace, \ + __PRETTY_FUNCTION__, __FILE__, __LINE__, _msg_, \ + (CYG_ADDRWORD)_arg0_, (CYG_ADDRWORD)_arg1_ ); + +# define CYG_TRACE_docall4( _msg_, _arg0_, _arg1_ , _arg2_, _arg3_ ) \ + cyg_tracemsg4( cyg_trace_trace, \ + __PRETTY_FUNCTION__, __FILE__, __LINE__, _msg_, \ + (CYG_ADDRWORD)_arg0_, (CYG_ADDRWORD)_arg1_, \ + (CYG_ADDRWORD)_arg2_, (CYG_ADDRWORD)_arg3_ ); + +# define CYG_TRACE_docall6( _msg_, _arg0_, _arg1_ , _arg2_, _arg3_, \ + _arg4_, _arg5_ ) \ + cyg_tracemsg6( cyg_trace_trace, \ + __PRETTY_FUNCTION__, __FILE__, __LINE__, _msg_, \ + (CYG_ADDRWORD)_arg0_, (CYG_ADDRWORD)_arg1_, \ + (CYG_ADDRWORD)_arg2_, (CYG_ADDRWORD)_arg3_, \ + (CYG_ADDRWORD)_arg4_, (CYG_ADDRWORD)_arg5_ ); + +# define CYG_TRACE_docall8( _msg_, _arg0_, _arg1_ , _arg2_, _arg3_, \ + _arg4_, _arg5_, _arg6_, _arg7_ ) \ + cyg_tracemsg8( cyg_trace_trace, \ + __PRETTY_FUNCTION__, __FILE__, __LINE__, _msg_, \ + (CYG_ADDRWORD)_arg0_, (CYG_ADDRWORD)_arg1_, \ + (CYG_ADDRWORD)_arg2_, (CYG_ADDRWORD)_arg3_, \ + (CYG_ADDRWORD)_arg4_, (CYG_ADDRWORD)_arg5_, \ + (CYG_ADDRWORD)_arg6_, (CYG_ADDRWORD)_arg7_ ); + +# else // do not CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + +# define CYG_TRACE_docall0( _msg_ ) \ + cyg_tracenomsg( __PRETTY_FUNCTION__, __FILE__, __LINE__ ); + +# define CYG_TRACE_docall2( _msg_, _arg0_, _arg1_ ) \ + cyg_tracenomsg( __PRETTY_FUNCTION__, __FILE__, __LINE__ ); + +# define CYG_TRACE_docall4( _msg_, _arg0_, _arg1_ , _arg2_, _arg3_ ) \ + cyg_tracenomsg( __PRETTY_FUNCTION__, __FILE__, __LINE__ ); + +# define CYG_TRACE_docall6( _msg_, _arg0_, _arg1_ , _arg2_, _arg3_, \ + _arg4_, _arg5_ ) \ + cyg_tracenomsg( __PRETTY_FUNCTION__, __FILE__, __LINE__ ); + +# define CYG_TRACE_docall8( _msg_, _arg0_, _arg1_, _arg2_, _arg3_, \ + _arg4_, _arg5_, _arg6_, _arg7_ ) \ + cyg_tracenomsg( __PRETTY_FUNCTION__, __FILE__, __LINE__ ); + +#endif + +// ------------------------------------------------------------------------- +// Conditioned trace; if the condition is false, fail. + +#define CYG_TRACE0( _bool_, _msg_ ) \ + CYG_MACRO_START \ + if ( ( _bool_ ) ) \ + CYG_TRACE_docall0( _msg_ ); \ + CYG_MACRO_END + +#define CYG_TRACE1( _bool_, _msg_, a ) \ + CYG_MACRO_START \ + if ( ( _bool_ ) ) \ + CYG_TRACE_docall2( _msg_, a, 0 ); \ + CYG_MACRO_END + +#define CYG_TRACE2( _bool_, _msg_, a, b ) \ + CYG_MACRO_START \ + if ( ( _bool_ ) ) \ + CYG_TRACE_docall2( _msg_, a, b ); \ + CYG_MACRO_END + +#define CYG_TRACE3( _bool_, _msg_, a, b, c ) \ + CYG_MACRO_START \ + if ( ( _bool_ ) ) \ + CYG_TRACE_docall4( _msg_, a, b, c, 0 ); \ + CYG_MACRO_END + +#define CYG_TRACE4( _bool_, _msg_, a, b, c, d ) \ + CYG_MACRO_START \ + if ( ( _bool_ ) ) \ + CYG_TRACE_docall4( _msg_, a, b, c, d ); \ + CYG_MACRO_END + +#define CYG_TRACE5( _bool_, _msg_, a, b, c, d, e ) \ + CYG_MACRO_START \ + if ( ( _bool_ ) ) \ + CYG_TRACE_docall6( _msg_, a, b, c, d, e, 0 ); \ + CYG_MACRO_END + +#define CYG_TRACE6( _bool_, _msg_, a, b, c, d, e, f ) \ + CYG_MACRO_START \ + if ( ( _bool_ ) ) \ + CYG_TRACE_docall6( _msg_, a, b, c, d, e, f ); \ + CYG_MACRO_END + +#define CYG_TRACE7( _bool_, _msg_, a, b, c, d, e, f, g ) \ + CYG_MACRO_START \ + if ( ( _bool_ ) ) \ + CYG_TRACE_docall8( _msg_, a, b, c, d, e, f, g, 0 ); \ + CYG_MACRO_END + +#define CYG_TRACE8( _bool_, _msg_, a, b, c, d, e, f, g, h ) \ + CYG_MACRO_START \ + if ( ( _bool_ ) ) \ + CYG_TRACE_docall8( _msg_, a, b, c, d, e, f, g, h ); \ + CYG_MACRO_END + +// ------------------------------------------------------------------------- +// Report function entry and exit. +// In C++ the macro CYG_REPORT_FUNCTION should appear as the first line of +// any function. It will generate a message whenever the function is entered +// and when it is exited. +// In C the macro should appear as the first statement after any local variable +// definitions. No exit message will be generated unless CYG_REPORT_RETURN is +// placed just before each return. +// Where a piece of code is to be compiled with both C and C++, the above +// rules for C should be followed. + +#ifdef CYGDBG_INFRA_DEBUG_FUNCTION_REPORTS + +#ifdef __cplusplus + +class Cyg_TraceFunction_Report_ +{ +public: + int cond; + char *func; + char *file; + cyg_uint32 lnum; +#ifdef CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + char *exitmsg; + CYG_ADDRWORD exitvalue; + enum { UNSET = 0, SET, VOID } exitset; +#endif + + Cyg_TraceFunction_Report_( + int condition, char *psz_func, char *psz_file, + cyg_uint32 linenum) + { + cond = condition; + func = psz_func; + file = psz_file; + lnum = linenum; + +#ifdef CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + exitmsg = NULL; + exitset = UNSET; + if ( cond ) + cyg_tracemsg( cyg_trace_enter, func, file, lnum, "enter"); +#else + if ( cond ) + cyg_tracenomsg( func, file, lnum ); +#endif + }; + + Cyg_TraceFunction_Report_( + int condition, char *psz_func, char *psz_file, + cyg_uint32 linenum, char *psz_exitmsg ) + { + cond = condition; + func = psz_func; + file = psz_file; + lnum = linenum; +#ifdef CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + exitmsg = psz_exitmsg; + exitset = UNSET; + if ( cond ) + cyg_tracemsg( cyg_trace_enter, func, file, lnum, "enter"); +#else + CYG_UNUSED_PARAM( char *, psz_exitmsg ); + if ( cond ) + cyg_tracenomsg( func, file, lnum ); +#endif + }; + + inline void set_exitvoid( cyg_uint32 linenum ) + { + lnum = linenum; +#ifdef CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + CYG_ASSERT( NULL == exitmsg, "exitvoid used in typed function" ); + CYG_ASSERT( UNSET == exitset, "exitvoid used when arg already set" ); + exitset = VOID; +#endif + } + + inline void set_exitvalue( cyg_uint32 linenum, CYG_ADDRWORD retcode ) + { + lnum = linenum; +#ifdef CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + CYG_ASSERT( UNSET == exitset, "exitvalue used when arg already set" ); + exitvalue = retcode; + exitset = SET; +#else + CYG_UNUSED_PARAM( CYG_ADDRWORD, retcode ); +#endif + } + + ~Cyg_TraceFunction_Report_() + { + if ( cond ) { +#ifdef CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + if ( VOID == exitset ) + cyg_tracemsg( cyg_trace_return, func, file, lnum, + "return void"); + else if ( UNSET == exitset ) + cyg_tracemsg( cyg_trace_return, func, file, lnum, + "RETURNING UNSET!"); + else if ( NULL == exitmsg ) + cyg_tracemsg2( cyg_trace_return, func, file, lnum, + "return %08x", exitvalue, 0 ); + else + cyg_tracemsg2( cyg_trace_return, func, file, lnum, + exitmsg, exitvalue, 0 ); +#else + cyg_tracenomsg( func, file, lnum ); +#endif + } + } +}; + +// These have no CYG_MACRO_START,END around because it is required +// that the scope of the object be the whole function body. Get it? + +// These are the unconditional versions: +#define CYG_REPORT_FUNCTION() \ + Cyg_TraceFunction_Report_ cyg_tracefunction_report_( \ + 1, __PRETTY_FUNCTION__, \ + __FILE__, __LINE__ ) + +#define CYG_REPORT_FUNCTYPE( _exitmsg_ ) \ + Cyg_TraceFunction_Report_ cyg_tracefunction_report_( \ + 1, __PRETTY_FUNCTION__, \ + __FILE__, __LINE__, _exitmsg_ ) + +#define CYG_REPORT_FUNCNAME( _name_ ) \ + Cyg_TraceFunction_Report_ cyg_tracefunction_report_( \ + 1, _name_, \ + __FILE__, __LINE__ ) + +#define CYG_REPORT_FUNCNAMETYPE( _name_, _exitmsg_ ) \ + Cyg_TraceFunction_Report_ cyg_tracefunction_report_( \ + 1, _name_, \ + __FILE__, __LINE__, _exitmsg_ ) + +// These are conditioned on macro CYG_REPORT_USER_BOOL +// (which you better have defined) +#define CYG_REPORT_FUNCTIONC() \ + Cyg_TraceFunction_Report_ cyg_tracefunction_report_( \ + CYG_REPORT_USER_BOOL, __PRETTY_FUNCTION__, \ + __FILE__, __LINE__ ) + +#define CYG_REPORT_FUNCTYPEC( _exitmsg_ ) \ + Cyg_TraceFunction_Report_ cyg_tracefunction_report_( \ + CYG_REPORT_USER_BOOL, __PRETTY_FUNCTION__, \ + __FILE__, __LINE__, _exitmsg_ ) + +#define CYG_REPORT_FUNCNAMEC( _name_ ) \ + Cyg_TraceFunction_Report_ cyg_tracefunction_report_( \ + CYG_REPORT_USER_BOOL, _name_, \ + __FILE__, __LINE__ ) + +#define CYG_REPORT_FUNCNAMETYPEC( _name_, _exitmsg_ ) \ + Cyg_TraceFunction_Report_ cyg_tracefunction_report_( \ + CYG_REPORT_USER_BOOL, _name_, \ + __FILE__, __LINE__, _exitmsg_ ) + + +#define CYG_REPORT_RETURN() CYG_MACRO_START \ + cyg_tracefunction_report_.set_exitvoid( __LINE__ ); \ +CYG_MACRO_END + +#define CYG_REPORT_RETVAL( _value_) CYG_MACRO_START \ + cyg_tracefunction_report_.set_exitvalue( \ + __LINE__, (CYG_ADDRWORD)(_value_) ); \ +CYG_MACRO_END + + +#else // not __cplusplus + + +struct Cyg_TraceFunction_Report_ +{ + int cond; + char *func; + char *file; /* not strictly needed in plain 'C' */ + cyg_uint32 lnum; /* nor this */ +#ifdef CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + char *exitmsg; + CYG_ADDRWORD exitvalue; + int exitset; +#endif + +}; + +#ifdef CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + +#define CYG_REPORT_FUNCTION_ENTER_INTERNAL() CYG_MACRO_START \ + if ( cyg_tracefunction_report_.cond ) \ + cyg_tracemsg( cyg_trace_enter, \ + cyg_tracefunction_report_.func, \ + cyg_tracefunction_report_.file, \ + cyg_tracefunction_report_.lnum, \ + "enter" ); \ +CYG_MACRO_END + +#define CYG_REPORT_FUNCTION_CONSTRUCT( _c_, _fn_,_fl_,_l_,_xm_,_xv_,_xs_ ) \ + { _c_, _fn_, _fl_, _l_, _xm_, _xv_, _xs_ } + +#else // do not CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + +#define CYG_REPORT_FUNCTION_ENTER_INTERNAL() CYG_MACRO_START \ + if ( cyg_tracefunction_report_.cond ) \ + cyg_tracenomsg( cyg_tracefunction_report_.func, \ + cyg_tracefunction_report_.file, \ + cyg_tracefunction_report_.lnum ); \ +CYG_MACRO_END + +#define CYG_REPORT_FUNCTION_CONSTRUCT( _c_, _fn_,_fl_,_l_,_xm_,_xv_,_xs_ ) \ + { _c_, _fn_, _fl_, _l_ } + +#endif // not CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + +// These have no CYG_MACRO_START,END around because it is required +// that the scope of the object be the whole function body. Get it? + +// These are the unconditional versions: +#define CYG_REPORT_FUNCTION() \ + struct Cyg_TraceFunction_Report_ cyg_tracefunction_report_ = \ + CYG_REPORT_FUNCTION_CONSTRUCT( \ + 1, __PRETTY_FUNCTION__, __FILE__, __LINE__, NULL, 0, 0 ); \ + CYG_REPORT_FUNCTION_ENTER_INTERNAL() + +#define CYG_REPORT_FUNCTYPE( _exitmsg_ ) \ + struct Cyg_TraceFunction_Report_ cyg_tracefunction_report_ = \ + CYG_REPORT_FUNCTION_CONSTRUCT( \ + 1, __PRETTY_FUNCTION__, __FILE__, __LINE__, _exitmsg_, 0, 0 ); \ + CYG_REPORT_FUNCTION_ENTER_INTERNAL() + +#define CYG_REPORT_FUNCNAME( _name_ ) \ + struct Cyg_TraceFunction_Report_ cyg_tracefunction_report_ = \ + CYG_REPORT_FUNCTION_CONSTRUCT( \ + 1, _name_, __FILE__, __LINE__, NULL, 0, 0 ); \ + CYG_REPORT_FUNCTION_ENTER_INTERNAL() + +#define CYG_REPORT_FUNCNAMETYPE( _name_, _exitmsg_ ) \ + struct Cyg_TraceFunction_Report_ cyg_tracefunction_report_ = \ + CYG_REPORT_FUNCTION_CONSTRUCT( \ + 1, _name_, __FILE__, __LINE__, _exitmsg_, 0, 0 ); \ + CYG_REPORT_FUNCTION_ENTER_INTERNAL() + +// These are conditioned on macro CYG_REPORT_USER_BOOL +// (which you better have defined) +#define CYG_REPORT_FUNCTIONC() \ + struct Cyg_TraceFunction_Report_ cyg_tracefunction_report_ = \ + CYG_REPORT_FUNCTION_CONSTRUCT( \ + CYG_REPORT_USER_BOOL, \ + __PRETTY_FUNCTION__, __FILE__, __LINE__, NULL, 0, 0 ); \ + CYG_REPORT_FUNCTION_ENTER_INTERNAL() + +#define CYG_REPORT_FUNCTYPEC( _exitmsg_ ) \ + struct Cyg_TraceFunction_Report_ cyg_tracefunction_report_ = \ + CYG_REPORT_FUNCTION_CONSTRUCT( \ + CYG_REPORT_USER_BOOL, \ + __PRETTY_FUNCTION__, __FILE__, __LINE__, _exitmsg_, 0, 0 ); \ + CYG_REPORT_FUNCTION_ENTER_INTERNAL() + +#define CYG_REPORT_FUNCNAMEC( _name_ ) \ + struct Cyg_TraceFunction_Report_ cyg_tracefunction_report_ = \ + CYG_REPORT_FUNCTION_CONSTRUCT( \ + CYG_REPORT_USER_BOOL, \ + _name_, __FILE__, __LINE__, NULL, 0, 0 ); \ + CYG_REPORT_FUNCTION_ENTER_INTERNAL() + +#define CYG_REPORT_FUNCNAMETYPEC( _name_, _exitmsg_ ) \ + struct Cyg_TraceFunction_Report_ cyg_tracefunction_report_ = \ + CYG_REPORT_FUNCTION_CONSTRUCT( \ + CYG_REPORT_USER_BOOL, \ + _name_, __FILE__, __LINE__, _exitmsg_, 0, 0 ); \ + CYG_REPORT_FUNCTION_ENTER_INTERNAL() + +#ifdef CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + +#define CYG_REPORT_RETURN() CYG_MACRO_START \ + CYG_ASSERT( NULL == cyg_tracefunction_report_.exitmsg, \ + "exitvoid used in typed function" ); \ + CYG_ASSERT( 0 == cyg_tracefunction_report_.exitset, \ + "exitvoid used when arg already set" ); \ + cyg_tracefunction_report_.lnum = __LINE__; \ + cyg_tracefunction_report_.exitset = 2; \ + if ( cyg_tracefunction_report_.cond ) \ + cyg_tracemsg( cyg_trace_return, \ + cyg_tracefunction_report_.func, \ + cyg_tracefunction_report_.file, \ + cyg_tracefunction_report_.lnum, \ + "return void" ); \ +CYG_MACRO_END + +#define CYG_REPORT_RETVAL( _value_ ) CYG_MACRO_START \ + CYG_ASSERT( 0 == cyg_tracefunction_report_.exitset, \ + "exitvalue used when arg already set" ); \ + cyg_tracefunction_report_.lnum = __LINE__; \ + cyg_tracefunction_report_.exitvalue = (CYG_ADDRWORD)(_value_); \ + cyg_tracefunction_report_.exitset = 1; \ + if ( cyg_tracefunction_report_.cond ) \ + cyg_tracemsg2( cyg_trace_return, \ + cyg_tracefunction_report_.func, \ + cyg_tracefunction_report_.file, \ + cyg_tracefunction_report_.lnum, \ + cyg_tracefunction_report_.exitmsg ? \ + cyg_tracefunction_report_.exitmsg : \ + "return %08x", \ + cyg_tracefunction_report_.exitvalue, 0 ); \ +CYG_MACRO_END + +#else // do not CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + +#define CYG_REPORT_RETURN() CYG_MACRO_START \ + cyg_tracefunction_report_.lnum = __LINE__; \ + if ( cyg_tracefunction_report_.cond ) \ + cyg_tracenomsg( cyg_tracefunction_report_.func, \ + cyg_tracefunction_report_.file, \ + cyg_tracefunction_report_.lnum ); \ +CYG_MACRO_END + +#define CYG_REPORT_RETVAL( _value_ ) CYG_MACRO_START \ + CYG_REPORT_RETURN(); \ +CYG_MACRO_END + +#endif // not CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + +#endif // not __cplusplus + +#ifdef CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + +#define CYG_REPORT_FUNCARGVOID() CYG_MACRO_START \ + if ( cyg_tracefunction_report_.cond ) \ + cyg_tracemsg( cyg_trace_args, \ + cyg_tracefunction_report_.func, \ + cyg_tracefunction_report_.file, \ + cyg_tracefunction_report_.lnum, \ + "(void)" \ + ); \ +CYG_MACRO_END + +#define CYG_REPORT_FUNCARG1( _format_, a ) CYG_MACRO_START \ + if ( cyg_tracefunction_report_.cond ) \ + cyg_tracemsg2( cyg_trace_args, \ + cyg_tracefunction_report_.func, \ + cyg_tracefunction_report_.file, \ + cyg_tracefunction_report_.lnum, \ + (_format_), \ + (CYG_ADDRWORD)a , 0 \ + ); \ +CYG_MACRO_END + +#define CYG_REPORT_FUNCARG2( _format_, a,b ) CYG_MACRO_START \ + if ( cyg_tracefunction_report_.cond ) \ + cyg_tracemsg2( cyg_trace_args, \ + cyg_tracefunction_report_.func, \ + cyg_tracefunction_report_.file, \ + cyg_tracefunction_report_.lnum, \ + (_format_), \ + (CYG_ADDRWORD)a, (CYG_ADDRWORD)b \ + ); \ +CYG_MACRO_END + +#define CYG_REPORT_FUNCARG3( _format_, a,b,c ) CYG_MACRO_START \ + if ( cyg_tracefunction_report_.cond ) \ + cyg_tracemsg4( cyg_trace_args, \ + cyg_tracefunction_report_.func, \ + cyg_tracefunction_report_.file, \ + cyg_tracefunction_report_.lnum, \ + (_format_), \ + (CYG_ADDRWORD)a, (CYG_ADDRWORD)b, \ + (CYG_ADDRWORD)c , 0 \ + ); \ +CYG_MACRO_END + +#define CYG_REPORT_FUNCARG4( _format_, a,b,c,d ) CYG_MACRO_START \ + if ( cyg_tracefunction_report_.cond ) \ + cyg_tracemsg4( cyg_trace_args, \ + cyg_tracefunction_report_.func, \ + cyg_tracefunction_report_.file, \ + cyg_tracefunction_report_.lnum, \ + (_format_), \ + (CYG_ADDRWORD)a, (CYG_ADDRWORD)b, \ + (CYG_ADDRWORD)c, (CYG_ADDRWORD)d \ + ); \ +CYG_MACRO_END + +#define CYG_REPORT_FUNCARG5( _format_, a,b,c,d,e ) CYG_MACRO_START \ + if ( cyg_tracefunction_report_.cond ) \ + cyg_tracemsg6( cyg_trace_args, \ + cyg_tracefunction_report_.func, \ + cyg_tracefunction_report_.file, \ + cyg_tracefunction_report_.lnum, \ + (_format_), \ + (CYG_ADDRWORD)a, (CYG_ADDRWORD)b, \ + (CYG_ADDRWORD)c, (CYG_ADDRWORD)d, \ + (CYG_ADDRWORD)e , 0 \ + ); \ +CYG_MACRO_END + +#define CYG_REPORT_FUNCARG6( _format_, a,b,c,d,e,f ) CYG_MACRO_START \ + if ( cyg_tracefunction_report_.cond ) \ + cyg_tracemsg6( cyg_trace_args, \ + cyg_tracefunction_report_.func, \ + cyg_tracefunction_report_.file, \ + cyg_tracefunction_report_.lnum, \ + (_format_), \ + (CYG_ADDRWORD)a, (CYG_ADDRWORD)b, \ + (CYG_ADDRWORD)c, (CYG_ADDRWORD)d, \ + (CYG_ADDRWORD)e, (CYG_ADDRWORD)f \ + ); \ +CYG_MACRO_END + +#define CYG_REPORT_FUNCARG7( _format_, a,b,c,d,e,f,g ) CYG_MACRO_START \ + if ( cyg_tracefunction_report_.cond ) \ + cyg_tracemsg8( cyg_trace_args, \ + cyg_tracefunction_report_.func, \ + cyg_tracefunction_report_.file, \ + cyg_tracefunction_report_.lnum, \ + (_format_), \ + (CYG_ADDRWORD)a, (CYG_ADDRWORD)b, \ + (CYG_ADDRWORD)c, (CYG_ADDRWORD)d, \ + (CYG_ADDRWORD)e, (CYG_ADDRWORD)f, \ + (CYG_ADDRWORD)g , 0 \ + ); \ +CYG_MACRO_END + +#define CYG_REPORT_FUNCARG8( _format_, a,b,c,d,e,f,g,h ) CYG_MACRO_START\ + if ( cyg_tracefunction_report_.cond ) \ + cyg_tracemsg8( cyg_trace_args, \ + cyg_tracefunction_report_.func, \ + cyg_tracefunction_report_.file, \ + cyg_tracefunction_report_.lnum, \ + (_format_), \ + (CYG_ADDRWORD)a, (CYG_ADDRWORD)b, \ + (CYG_ADDRWORD)c, (CYG_ADDRWORD)d, \ + (CYG_ADDRWORD)e, (CYG_ADDRWORD)f, \ + (CYG_ADDRWORD)g, (CYG_ADDRWORD)h \ + ); \ +CYG_MACRO_END + + +#else // do not CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + +#define CYG_REPORT_FUNCARGVOID() CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG1( _format_, a ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG2( _format_, a,b ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG3( _format_, a,b,c ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG4( _format_, a,b,c,d ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG5( _format_, a,b,c,d,e ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG6( _format_, a,b,c,d,e,f ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG7( _format_, a,b,c,d,e,f,g ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG8( _format_, a,b,c,d,e,f,g,h ) CYG_EMPTY_STATEMENT + +#endif // not CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + +#else // no CYGDBG_INFRA_DEBUG_FUNCTION_REPORTS + +#define CYG_REPORT_FUNCTION() CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCTYPE( _exitmsg_ ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCNAME( _name_ ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCNAMETYPE( _name_, _exitmsg_ ) CYG_EMPTY_STATEMENT + +#define CYG_REPORT_FUNCTIONC() CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCTYPEC( _exitmsg_ ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCNAMEC( _name_ ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCNAMETYPEC( _name_, _exitmsg_ ) CYG_EMPTY_STATEMENT + +#define CYG_REPORT_FUNCARGVOID() CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG1( _format_, a ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG2( _format_, a,b ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG3( _format_, a,b,c ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG4( _format_, a,b,c,d ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG5( _format_, a,b,c,d,e ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG6( _format_, a,b,c,d,e,f ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG7( _format_, a,b,c,d,e,f,g ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG8( _format_, a,b,c,d,e,f,g,h ) CYG_EMPTY_STATEMENT + +#define CYG_REPORT_RETURN() CYG_EMPTY_STATEMENT +#define CYG_REPORT_RETVAL( _value_ ) CYG_EMPTY_STATEMENT + +#endif // CYGDBG_INFRA_DEBUG_FUNCTION_REPORTS + +#else // ! CYGDBG_USE_TRACING + +// ------------------------------------------------------------------------- +// No traces: we define empty statements for trace macros. + +#define CYG_TRACE0( _bool_, _msg_ ) CYG_EMPTY_STATEMENT +#define CYG_TRACE1( _bool_, _msg_, a ) CYG_EMPTY_STATEMENT +#define CYG_TRACE2( _bool_, _msg_, a,b ) CYG_EMPTY_STATEMENT +#define CYG_TRACE3( _bool_, _msg_, a,b,c ) CYG_EMPTY_STATEMENT +#define CYG_TRACE4( _bool_, _msg_, a,b,c,d ) CYG_EMPTY_STATEMENT +#define CYG_TRACE5( _bool_, _msg_, a,b,c,d,e ) CYG_EMPTY_STATEMENT +#define CYG_TRACE6( _bool_, _msg_, a,b,c,d,e,f ) CYG_EMPTY_STATEMENT +#define CYG_TRACE7( _bool_, _msg_, a,b,c,d,e,f,g ) CYG_EMPTY_STATEMENT +#define CYG_TRACE8( _bool_, _msg_, a,b,c,d,e,f,g,h ) CYG_EMPTY_STATEMENT + +#define CYG_REPORT_FUNCTION() CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCTYPE( _exitmsg_ ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCNAME( _name_ ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCNAMETYPE( _name_, _exitmsg_ ) CYG_EMPTY_STATEMENT + +#define CYG_REPORT_FUNCTIONC() CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCTYPEC( _exitmsg_ ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCNAMEC( _name_ ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCNAMETYPEC( _name_, _exitmsg_ ) CYG_EMPTY_STATEMENT + +#define CYG_REPORT_FUNCARGVOID() CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG1( _format_, a ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG2( _format_, a,b ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG3( _format_, a,b,c ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG4( _format_, a,b,c,d ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG5( _format_, a,b,c,d,e ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG6( _format_, a,b,c,d,e,f ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG7( _format_, a,b,c,d,e,f,g ) CYG_EMPTY_STATEMENT +#define CYG_REPORT_FUNCARG8( _format_, a,b,c,d,e,f,g,h ) CYG_EMPTY_STATEMENT + +#define CYG_REPORT_RETURN() CYG_EMPTY_STATEMENT +#define CYG_REPORT_RETVAL( _value_ ) CYG_EMPTY_STATEMENT + +#define CYG_TRACE_PRINT() CYG_EMPTY_STATEMENT +#define CYG_TRACE_DUMP() CYG_EMPTY_STATEMENT + +#endif // ! CYGDBG_USE_TRACING + +// ------------------------------------------------------------------------- +// +// CYG_TRACEn{[XDY]{V}}{B} +// +// Convenience macros: these fall into a few dimensions, with suffix letters: +// First option: +// X: user need not supply a format string, %08x is used +// D: ditto but signed decimal, %d +// Y: ditto but just plain %x +// Second option, only meaningful with one of XDY: +// V: " = %..." is used, by stringifying the argument +// Third option: +// B: user need not supply a bool; the symbol CYG_TRACE_USER_BOOL is +// used (which we do not define, user must do this) + +#define CYG_TRACE0B( _msg_ ) \ + CYG_TRACE0( CYG_TRACE_USER_BOOL, _msg_ ) +#define CYG_TRACE1B( _msg_, a ) \ + CYG_TRACE1( CYG_TRACE_USER_BOOL, _msg_, a ) +#define CYG_TRACE2B( _msg_, a,b ) \ + CYG_TRACE2( CYG_TRACE_USER_BOOL, _msg_, a,b ) +#define CYG_TRACE3B( _msg_, a,b,c ) \ + CYG_TRACE3( CYG_TRACE_USER_BOOL, _msg_, a,b,c ) +#define CYG_TRACE4B( _msg_, a,b,c,d ) \ + CYG_TRACE4( CYG_TRACE_USER_BOOL, _msg_, a,b,c,d ) +#define CYG_TRACE5B( _msg_, a,b,c,d,e ) \ + CYG_TRACE5( CYG_TRACE_USER_BOOL, _msg_, a,b,c,d,e ) +#define CYG_TRACE6B( _msg_, a,b,c,d,e,f ) \ + CYG_TRACE6( CYG_TRACE_USER_BOOL, _msg_, a,b,c,d,e,f ) +#define CYG_TRACE7B( _msg_, a,b,c,d,e,f,g ) \ + CYG_TRACE7( CYG_TRACE_USER_BOOL, _msg_, a,b,c,d,e,f,g ) +#define CYG_TRACE8B( _msg_, a,b,c,d,e,f,g,h ) \ + CYG_TRACE8( CYG_TRACE_USER_BOOL, _msg_, a,b,c,d,e,f,g,h ) + +// long hex versions + +#define CYG_TRACE1X( _bool_, a ) \ + CYG_TRACE1( _bool_, "%08x", a ) +#define CYG_TRACE2X( _bool_, a,b ) \ + CYG_TRACE2( _bool_, "%08x %08x", a,b ) +#define CYG_TRACE3X( _bool_, a,b,c ) \ + CYG_TRACE3( _bool_, "%08x %08x %08x", a,b,c ) +#define CYG_TRACE4X( _bool_, a,b,c,d ) \ + CYG_TRACE4( _bool_, "%08x %08x %08x %08x", a,b,c,d ) +#define CYG_TRACE5X( _bool_, a,b,c,d,e ) \ + CYG_TRACE5( _bool_, "%08x %08x %08x %08x %08x", a,b,c,d,e ) +#define CYG_TRACE6X( _bool_, a,b,c,d,e,f ) \ + CYG_TRACE6( _bool_, "%08x %08x %08x %08x %08x %08x", \ + a,b,c,d,e,f ) +#define CYG_TRACE7X( _bool_, a,b,c,d,e,f,g ) \ + CYG_TRACE7( _bool_, "%08x %08x %08x %08x %08x %08x %08x", \ + a,b,c,d,e,f,g ) +#define CYG_TRACE8X( _bool_, a,b,c,d,e,f,g,h ) \ + CYG_TRACE8( _bool_, "%08x %08x %08x %08x %08x %08x %08x %08x", \ + a,b,c,d,e,f,g,h ) + +#define CYG_TRACE1XV( _bool_, a ) \ + CYG_TRACE1( _bool_, # a "=%08x ", a ) +#define CYG_TRACE2XV( _bool_, a,b ) \ + CYG_TRACE2( _bool_, \ + # a "=%08x " # b "=%08x " , a,b ) +#define CYG_TRACE3XV( _bool_, a,b,c ) \ + CYG_TRACE3( _bool_, \ + # a "=%08x " # b "=%08x " # c "=%08x " , a,b,c ) +#define CYG_TRACE4XV( _bool_, a,b,c,d ) \ + CYG_TRACE4( _bool_, \ + # a "=%08x " # b "=%08x " # c "=%08x " # d "=%08x " \ + , a,b,c,d ) +#define CYG_TRACE5XV( _bool_, a,b,c,d,e ) \ + CYG_TRACE5( _bool_, \ + # a "=%08x " # b "=%08x " # c "=%08x " # d "=%08x " \ + # e "=%08x " \ + , a,b,c,d,e ) +#define CYG_TRACE6XV( _bool_, a,b,c,d,e,f ) \ + CYG_TRACE6( _bool_, \ + # a "=%08x " # b "=%08x " # c "=%08x " # d "=%08x " \ + # e "=%08x " # f "=%08x " \ + , a,b,c,d,e,f ) +#define CYG_TRACE7XV( _bool_, a,b,c,d,e,f,g ) \ + CYG_TRACE7( _bool_, \ + # a "=%08x " # b "=%08x " # c "=%08x " # d "=%08x " \ + # e "=%08x " # f "=%08x " # g "=%08x " \ + , a,b,c,d,e,f,g ) +#define CYG_TRACE8XV( _bool_, a,b,c,d,e,f,g,h ) \ + CYG_TRACE8( _bool_, \ + # a "=%08x " # b "=%08x " # c "=%08x " # d "=%08x " \ + # e "=%08x " # f "=%08x " # g "=%08x " # h "=%08x " \ + , a,b,c,d,e,f,g,h ) + +#define CYG_TRACE1XB( a ) \ + CYG_TRACE1( CYG_TRACE_USER_BOOL, "%08x", a ) +#define CYG_TRACE2XB( a,b ) \ + CYG_TRACE2( CYG_TRACE_USER_BOOL, "%08x %08x", a,b ) +#define CYG_TRACE3XB( a,b,c ) \ + CYG_TRACE3( CYG_TRACE_USER_BOOL, "%08x %08x %08x", a,b,c ) +#define CYG_TRACE4XB( a,b,c,d ) \ + CYG_TRACE4( CYG_TRACE_USER_BOOL, "%08x %08x %08x %08x", a,b,c,d ) +#define CYG_TRACE5XB( a,b,c,d,e ) \ + CYG_TRACE5( CYG_TRACE_USER_BOOL, "%08x %08x %08x %08x %08x", a,b,c,d,e ) +#define CYG_TRACE6XB( a,b,c,d,e,f ) \ + CYG_TRACE6( CYG_TRACE_USER_BOOL, "%08x %08x %08x %08x %08x %08x", \ + a,b,c,d,e,f ) +#define CYG_TRACE7XB( a,b,c,d,e,f,g ) \ + CYG_TRACE7( CYG_TRACE_USER_BOOL, "%08x %08x %08x %08x %08x %08x %08x", \ + a,b,c,d,e,f,g ) +#define CYG_TRACE8XB( a,b,c,d,e,f,g,h ) \ + CYG_TRACE8( CYG_TRACE_USER_BOOL, "%08x %08x %08x %08x %08x %08x %08x %08x", \ + a,b,c,d,e,f,g,h ) + +#define CYG_TRACE1XVB( a ) \ + CYG_TRACE1( CYG_TRACE_USER_BOOL, # a "=%08x ", a ) +#define CYG_TRACE2XVB( a,b ) \ + CYG_TRACE2( CYG_TRACE_USER_BOOL, \ + # a "=%08x " # b "=%08x " , a,b ) +#define CYG_TRACE3XVB( a,b,c ) \ + CYG_TRACE3( CYG_TRACE_USER_BOOL, \ + # a "=%08x " # b "=%08x " # c "=%08x " , a,b,c ) +#define CYG_TRACE4XVB( a,b,c,d ) \ + CYG_TRACE4( CYG_TRACE_USER_BOOL, \ + # a "=%08x " # b "=%08x " # c "=%08x " # d "=%08x " \ + , a,b,c,d ) +#define CYG_TRACE5XVB( a,b,c,d,e ) \ + CYG_TRACE5( CYG_TRACE_USER_BOOL, \ + # a "=%08x " # b "=%08x " # c "=%08x " # d "=%08x " \ + # e "=%08x " \ + , a,b,c,d,e ) +#define CYG_TRACE6XVB( a,b,c,d,e,f ) \ + CYG_TRACE6( CYG_TRACE_USER_BOOL, \ + # a "=%08x " # b "=%08x " # c "=%08x " # d "=%08x " \ + # e "=%08x " # f "=%08x " \ + , a,b,c,d,e,f ) +#define CYG_TRACE7XVB( a,b,c,d,e,f,g ) \ + CYG_TRACE7( CYG_TRACE_USER_BOOL, \ + # a "=%08x " # b "=%08x " # c "=%08x " # d "=%08x " \ + # e "=%08x " # f "=%08x " # g "=%08x " \ + , a,b,c,d,e,f,g ) +#define CYG_TRACE8XVB( a,b,c,d,e,f,g,h ) \ + CYG_TRACE8( CYG_TRACE_USER_BOOL, \ + # a "=%08x " # b "=%08x " # c "=%08x " # d "=%08x " \ + # e "=%08x " # f "=%08x " # g "=%08x " # h "=%08x " \ + , a,b,c,d,e,f,g,h ) + +// decimal versions + +#define CYG_TRACE1D( _bool_, a ) \ + CYG_TRACE1( _bool_, "%d", a ) +#define CYG_TRACE2D( _bool_, a,b ) \ + CYG_TRACE2( _bool_, "%d %d", a,b ) +#define CYG_TRACE3D( _bool_, a,b,c ) \ + CYG_TRACE3( _bool_, "%d %d %d", a,b,c ) +#define CYG_TRACE4D( _bool_, a,b,c,d ) \ + CYG_TRACE4( _bool_, "%d %d %d %d", a,b,c,d ) +#define CYG_TRACE5D( _bool_, a,b,c,d,e ) \ + CYG_TRACE5( _bool_, "%d %d %d %d %d", a,b,c,d,e ) +#define CYG_TRACE6D( _bool_, a,b,c,d,e,f ) \ + CYG_TRACE6( _bool_, "%d %d %d %d %d %d", \ + a,b,c,d,e,f ) +#define CYG_TRACE7D( _bool_, a,b,c,d,e,f,g ) \ + CYG_TRACE7( _bool_, "%d %d %d %d %d %d %d", \ + a,b,c,d,e,f,g ) +#define CYG_TRACE8D( _bool_, a,b,c,d,e,f,g,h ) \ + CYG_TRACE8( _bool_, "%d %d %d %d %d %d %d %d", \ + a,b,c,d,e,f,g,h ) + +#define CYG_TRACE1DV( _bool_, a ) \ + CYG_TRACE1( _bool_, # a "=%d ", a ) +#define CYG_TRACE2DV( _bool_, a,b ) \ + CYG_TRACE2( _bool_, \ + # a "=%d " # b "=%d " , a,b ) +#define CYG_TRACE3DV( _bool_, a,b,c ) \ + CYG_TRACE3( _bool_, \ + # a "=%d " # b "=%d " # c "=%d " , a,b,c ) +#define CYG_TRACE4DV( _bool_, a,b,c,d ) \ + CYG_TRACE4( _bool_, \ + # a "=%d " # b "=%d " # c "=%d " # d "=%d " \ + , a,b,c,d ) +#define CYG_TRACE5DV( _bool_, a,b,c,d,e ) \ + CYG_TRACE5( _bool_, \ + # a "=%d " # b "=%d " # c "=%d " # d "=%d " \ + # e "=%d " \ + , a,b,c,d,e ) +#define CYG_TRACE6DV( _bool_, a,b,c,d,e,f ) \ + CYG_TRACE6( _bool_, \ + # a "=%d " # b "=%d " # c "=%d " # d "=%d " \ + # e "=%d " # f "=%d " \ + , a,b,c,d,e,f ) +#define CYG_TRACE7DV( _bool_, a,b,c,d,e,f,g ) \ + CYG_TRACE7( _bool_, \ + # a "=%d " # b "=%d " # c "=%d " # d "=%d " \ + # e "=%d " # f "=%d " # g "=%d " \ + , a,b,c,d,e,f,g ) +#define CYG_TRACE8DV( _bool_, a,b,c,d,e,f,g,h ) \ + CYG_TRACE8( _bool_, \ + # a "=%d " # b "=%d " # c "=%d " # d "=%d " \ + # e "=%d " # f "=%d " # g "=%d " # h "=%d " \ + , a,b,c,d,e,f,g,h ) + +#define CYG_TRACE1DB( a ) \ + CYG_TRACE1( CYG_TRACE_USER_BOOL, "%d", a ) +#define CYG_TRACE2DB( a,b ) \ + CYG_TRACE2( CYG_TRACE_USER_BOOL, "%d %d", a,b ) +#define CYG_TRACE3DB( a,b,c ) \ + CYG_TRACE3( CYG_TRACE_USER_BOOL, "%d %d %d", a,b,c ) +#define CYG_TRACE4DB( a,b,c,d ) \ + CYG_TRACE4( CYG_TRACE_USER_BOOL, "%d %d %d %d", a,b,c,d ) +#define CYG_TRACE5DB( a,b,c,d,e ) \ + CYG_TRACE5( CYG_TRACE_USER_BOOL, "%d %d %d %d %d", a,b,c,d,e ) +#define CYG_TRACE6DB( a,b,c,d,e,f ) \ + CYG_TRACE6( CYG_TRACE_USER_BOOL, "%d %d %d %d %d %d", \ + a,b,c,d,e,f ) +#define CYG_TRACE7DB( a,b,c,d,e,f,g ) \ + CYG_TRACE7( CYG_TRACE_USER_BOOL, "%d %d %d %d %d %d %d", \ + a,b,c,d,e,f,g ) +#define CYG_TRACE8DB( a,b,c,d,e,f,g,h ) \ + CYG_TRACE8( CYG_TRACE_USER_BOOL, "%d %d %d %d %d %d %d %d", \ + a,b,c,d,e,f,g,h ) + +#define CYG_TRACE1DVB( a ) \ + CYG_TRACE1( CYG_TRACE_USER_BOOL, # a "=%d ", a ) +#define CYG_TRACE2DVB( a,b ) \ + CYG_TRACE2( CYG_TRACE_USER_BOOL, \ + # a "=%d " # b "=%d " , a,b ) +#define CYG_TRACE3DVB( a,b,c ) \ + CYG_TRACE3( CYG_TRACE_USER_BOOL, \ + # a "=%d " # b "=%d " # c "=%d " , a,b,c ) +#define CYG_TRACE4DVB( a,b,c,d ) \ + CYG_TRACE4( CYG_TRACE_USER_BOOL, \ + # a "=%d " # b "=%d " # c "=%d " # d "=%d " \ + , a,b,c,d ) +#define CYG_TRACE5DVB( a,b,c,d,e ) \ + CYG_TRACE5( CYG_TRACE_USER_BOOL, \ + # a "=%d " # b "=%d " # c "=%d " # d "=%d " \ + # e "=%d " \ + , a,b,c,d,e ) +#define CYG_TRACE6DVB( a,b,c,d,e,f ) \ + CYG_TRACE6( CYG_TRACE_USER_BOOL, \ + # a "=%d " # b "=%d " # c "=%d " # d "=%d " \ + # e "=%d " # f "=%d " \ + , a,b,c,d,e,f ) +#define CYG_TRACE7DVB( a,b,c,d,e,f,g ) \ + CYG_TRACE7( CYG_TRACE_USER_BOOL, \ + # a "=%d " # b "=%d " # c "=%d " # d "=%d " \ + # e "=%d " # f "=%d " # g "=%d " \ + , a,b,c,d,e,f,g ) +#define CYG_TRACE8DVB( a,b,c,d,e,f,g,h ) \ + CYG_TRACE8( CYG_TRACE_USER_BOOL, \ + # a "=%d " # b "=%d " # c "=%d " # d "=%d " \ + # e "=%d " # f "=%d " # g "=%d " # h "=%d " \ + , a,b,c,d,e,f,g,h ) + +// short hex versions + +#define CYG_TRACE1Y( _bool_, a ) \ + CYG_TRACE1( _bool_, "%x", a ) +#define CYG_TRACE2Y( _bool_, a,b ) \ + CYG_TRACE2( _bool_, "%x %x", a,b ) +#define CYG_TRACE3Y( _bool_, a,b,c ) \ + CYG_TRACE3( _bool_, "%x %x %x", a,b,c ) +#define CYG_TRACE4Y( _bool_, a,b,c,d ) \ + CYG_TRACE4( _bool_, "%x %x %x %x", a,b,c,d ) +#define CYG_TRACE5Y( _bool_, a,b,c,d,e ) \ + CYG_TRACE5( _bool_, "%x %x %x %x %x", a,b,c,d,e ) +#define CYG_TRACE6Y( _bool_, a,b,c,d,e,f ) \ + CYG_TRACE6( _bool_, "%x %x %x %x %x %x", \ + a,b,c,d,e,f ) +#define CYG_TRACE7Y( _bool_, a,b,c,d,e,f,g ) \ + CYG_TRACE7( _bool_, "%x %x %x %x %x %x %x", \ + a,b,c,d,e,f,g ) +#define CYG_TRACE8Y( _bool_, a,b,c,d,e,f,g,h ) \ + CYG_TRACE8( _bool_, "%x %x %x %x %x %x %x %x", \ + a,b,c,d,e,f,g,h ) + +#define CYG_TRACE1YV( _bool_, a ) \ + CYG_TRACE1( _bool_, # a "=%x ", a ) +#define CYG_TRACE2YV( _bool_, a,b ) \ + CYG_TRACE2( _bool_, \ + # a "=%x " # b "=%x " , a,b ) +#define CYG_TRACE3YV( _bool_, a,b,c ) \ + CYG_TRACE3( _bool_, \ + # a "=%x " # b "=%x " # c "=%x " , a,b,c ) +#define CYG_TRACE4YV( _bool_, a,b,c,d ) \ + CYG_TRACE4( _bool_, \ + # a "=%x " # b "=%x " # c "=%x " # d "=%x " \ + , a,b,c,d ) +#define CYG_TRACE5YV( _bool_, a,b,c,d,e ) \ + CYG_TRACE5( _bool_, \ + # a "=%x " # b "=%x " # c "=%x " # d "=%x " \ + # e "=%x " \ + , a,b,c,d,e ) +#define CYG_TRACE6YV( _bool_, a,b,c,d,e,f ) \ + CYG_TRACE6( _bool_, \ + # a "=%x " # b "=%x " # c "=%x " # d "=%x " \ + # e "=%x " # f "=%x " \ + , a,b,c,d,e,f ) +#define CYG_TRACE7YV( _bool_, a,b,c,d,e,f,g ) \ + CYG_TRACE7( _bool_, \ + # a "=%x " # b "=%x " # c "=%x " # d "=%x " \ + # e "=%x " # f "=%x " # g "=%x " \ + , a,b,c,d,e,f,g ) +#define CYG_TRACE8YV( _bool_, a,b,c,d,e,f,g,h ) \ + CYG_TRACE8( _bool_, \ + # a "=%x " # b "=%x " # c "=%x " # d "=%x " \ + # e "=%x " # f "=%x " # g "=%x " # h "=%x " \ + , a,b,c,d,e,f,g,h ) + +#define CYG_TRACE1YB( a ) \ + CYG_TRACE1( CYG_TRACE_USER_BOOL, "%x", a ) +#define CYG_TRACE2YB( a,b ) \ + CYG_TRACE2( CYG_TRACE_USER_BOOL, "%x %x", a,b ) +#define CYG_TRACE3YB( a,b,c ) \ + CYG_TRACE3( CYG_TRACE_USER_BOOL, "%x %x %x", a,b,c ) +#define CYG_TRACE4YB( a,b,c,d ) \ + CYG_TRACE4( CYG_TRACE_USER_BOOL, "%x %x %x %x", a,b,c,d ) +#define CYG_TRACE5YB( a,b,c,d,e ) \ + CYG_TRACE5( CYG_TRACE_USER_BOOL, "%x %x %x %x %x", a,b,c,d,e ) +#define CYG_TRACE6YB( a,b,c,d,e,f ) \ + CYG_TRACE6( CYG_TRACE_USER_BOOL, "%x %x %x %x %x %x", \ + a,b,c,d,e,f ) +#define CYG_TRACE7YB( a,b,c,d,e,f,g ) \ + CYG_TRACE7( CYG_TRACE_USER_BOOL, "%x %x %x %x %x %x %x", \ + a,b,c,d,e,f,g ) +#define CYG_TRACE8YB( a,b,c,d,e,f,g,h ) \ + CYG_TRACE8( CYG_TRACE_USER_BOOL, "%x %x %x %x %x %x %x %x", \ + a,b,c,d,e,f,g,h ) + +#define CYG_TRACE1YVB( a ) \ + CYG_TRACE1( CYG_TRACE_USER_BOOL, # a "=%x ", a ) +#define CYG_TRACE2YVB( a,b ) \ + CYG_TRACE2( CYG_TRACE_USER_BOOL, \ + # a "=%x " # b "=%x " , a,b ) +#define CYG_TRACE3YVB( a,b,c ) \ + CYG_TRACE3( CYG_TRACE_USER_BOOL, \ + # a "=%x " # b "=%x " # c "=%x " , a,b,c ) +#define CYG_TRACE4YVB( a,b,c,d ) \ + CYG_TRACE4( CYG_TRACE_USER_BOOL, \ + # a "=%x " # b "=%x " # c "=%x " # d "=%x " \ + , a,b,c,d ) +#define CYG_TRACE5YVB( a,b,c,d,e ) \ + CYG_TRACE5( CYG_TRACE_USER_BOOL, \ + # a "=%x " # b "=%x " # c "=%x " # d "=%x " \ + # e "=%x " \ + , a,b,c,d,e ) +#define CYG_TRACE6YVB( a,b,c,d,e,f ) \ + CYG_TRACE6( CYG_TRACE_USER_BOOL, \ + # a "=%x " # b "=%x " # c "=%x " # d "=%x " \ + # e "=%x " # f "=%x " \ + , a,b,c,d,e,f ) +#define CYG_TRACE7YVB( a,b,c,d,e,f,g ) \ + CYG_TRACE7( CYG_TRACE_USER_BOOL, \ + # a "=%x " # b "=%x " # c "=%x " # d "=%x " \ + # e "=%x " # f "=%x " # g "=%x " \ + , a,b,c,d,e,f,g ) +#define CYG_TRACE8YVB( a,b,c,d,e,f,g,h ) \ + CYG_TRACE8( CYG_TRACE_USER_BOOL, \ + # a "=%x " # b "=%x " # c "=%x " # d "=%x " \ + # e "=%x " # f "=%x " # g "=%x " # h "=%x " \ + , a,b,c,d,e,f,g,h ) + +// ------------------------------------------------------------------------- +// +// CYG_REPORT_FUNCARGn{[XDY]{V}} +// +// Convenience macros two: these fall into a few dimensions, with suffix letters: +// First option: +// X: user need not supply a format string, %08x is used +// D: ditto but signed decimal, %d +// Y: ditto but just plain %x +// Second option, only meaningful with one of XDY: +// V: " = %..." is used, by stringifying the argument + +// long hex versions + +#define CYG_REPORT_FUNCARG1X( a ) \ + CYG_REPORT_FUNCARG1( "%08x", a ) +#define CYG_REPORT_FUNCARG2X( a,b ) \ + CYG_REPORT_FUNCARG2( "%08x %08x", a,b ) +#define CYG_REPORT_FUNCARG3X( a,b,c ) \ + CYG_REPORT_FUNCARG3( "%08x %08x %08x", a,b,c ) +#define CYG_REPORT_FUNCARG4X( a,b,c,d ) \ + CYG_REPORT_FUNCARG4( "%08x %08x %08x %08x", a,b,c,d ) +#define CYG_REPORT_FUNCARG5X( a,b,c,d,e ) \ + CYG_REPORT_FUNCARG5( "%08x %08x %08x %08x %08x", a,b,c,d,e ) +#define CYG_REPORT_FUNCARG6X( a,b,c,d,e,f ) \ + CYG_REPORT_FUNCARG6( "%08x %08x %08x %08x %08x %08x", \ + a,b,c,d,e,f ) +#define CYG_REPORT_FUNCARG7X( a,b,c,d,e,f,g ) \ + CYG_REPORT_FUNCARG7( "%08x %08x %08x %08x %08x %08x %08x", \ + a,b,c,d,e,f,g ) +#define CYG_REPORT_FUNCARG8X( a,b,c,d,e,f,g,h ) \ + CYG_REPORT_FUNCARG8( "%08x %08x %08x %08x %08x %08x %08x %08x", \ + a,b,c,d,e,f,g,h ) + +#define CYG_REPORT_FUNCARG1XV( a ) \ + CYG_REPORT_FUNCARG1( # a "=%08x ", a ) +#define CYG_REPORT_FUNCARG2XV( a,b ) \ + CYG_REPORT_FUNCARG2( \ + # a "=%08x " # b "=%08x " , a,b ) +#define CYG_REPORT_FUNCARG3XV( a,b,c ) \ + CYG_REPORT_FUNCARG3( \ + # a "=%08x " # b "=%08x " # c "=%08x " , a,b,c ) +#define CYG_REPORT_FUNCARG4XV( a,b,c,d ) \ + CYG_REPORT_FUNCARG4( \ + # a "=%08x " # b "=%08x " # c "=%08x " # d "=%08x " \ + , a,b,c,d ) +#define CYG_REPORT_FUNCARG5XV( a,b,c,d,e ) \ + CYG_REPORT_FUNCARG5( \ + # a "=%08x " # b "=%08x " # c "=%08x " # d "=%08x " \ + # e "=%08x " \ + , a,b,c,d,e ) +#define CYG_REPORT_FUNCARG6XV( a,b,c,d,e,f ) \ + CYG_REPORT_FUNCARG6( \ + # a "=%08x " # b "=%08x " # c "=%08x " # d "=%08x " \ + # e "=%08x " # f "=%08x " \ + , a,b,c,d,e,f ) +#define CYG_REPORT_FUNCARG7XV( a,b,c,d,e,f,g ) \ + CYG_REPORT_FUNCARG7( \ + # a "=%08x " # b "=%08x " # c "=%08x " # d "=%08x " \ + # e "=%08x " # f "=%08x " # g "=%08x " \ + , a,b,c,d,e,f,g ) +#define CYG_REPORT_FUNCARG8XV( a,b,c,d,e,f,g,h ) \ + CYG_REPORT_FUNCARG8( \ + # a "=%08x " # b "=%08x " # c "=%08x " # d "=%08x " \ + # e "=%08x " # f "=%08x " # g "=%08x " # h "=%08x " \ + , a,b,c,d,e,f,g,h ) + +// decimal versions + + +#define CYG_REPORT_FUNCARG1D( a ) \ + CYG_REPORT_FUNCARG1( "%d", a ) +#define CYG_REPORT_FUNCARG2D( a,b ) \ + CYG_REPORT_FUNCARG2( "%d %d", a,b ) +#define CYG_REPORT_FUNCARG3D( a,b,c ) \ + CYG_REPORT_FUNCARG3( "%d %d %d", a,b,c ) +#define CYG_REPORT_FUNCARG4D( a,b,c,d ) \ + CYG_REPORT_FUNCARG4( "%d %d %d %d", a,b,c,d ) +#define CYG_REPORT_FUNCARG5D( a,b,c,d,e ) \ + CYG_REPORT_FUNCARG5( "%d %d %d %d %d", a,b,c,d,e ) +#define CYG_REPORT_FUNCARG6D( a,b,c,d,e,f ) \ + CYG_REPORT_FUNCARG6( "%d %d %d %d %d %d", \ + a,b,c,d,e,f ) +#define CYG_REPORT_FUNCARG7D( a,b,c,d,e,f,g ) \ + CYG_REPORT_FUNCARG7( "%d %d %d %d %d %d %d", \ + a,b,c,d,e,f,g ) +#define CYG_REPORT_FUNCARG8D( a,b,c,d,e,f,g,h ) \ + CYG_REPORT_FUNCARG8( "%d %d %d %d %d %d %d %d", \ + a,b,c,d,e,f,g,h ) + +#define CYG_REPORT_FUNCARG1DV( a ) \ + CYG_REPORT_FUNCARG1( # a "=%d ", a ) +#define CYG_REPORT_FUNCARG2DV( a,b ) \ + CYG_REPORT_FUNCARG2( \ + # a "=%d " # b "=%d " , a,b ) +#define CYG_REPORT_FUNCARG3DV( a,b,c ) \ + CYG_REPORT_FUNCARG3( \ + # a "=%d " # b "=%d " # c "=%d " , a,b,c ) +#define CYG_REPORT_FUNCARG4DV( a,b,c,d ) \ + CYG_REPORT_FUNCARG4( \ + # a "=%d " # b "=%d " # c "=%d " # d "=%d " \ + , a,b,c,d ) +#define CYG_REPORT_FUNCARG5DV( a,b,c,d,e ) \ + CYG_REPORT_FUNCARG5( \ + # a "=%d " # b "=%d " # c "=%d " # d "=%d " \ + # e "=%d " \ + , a,b,c,d,e ) +#define CYG_REPORT_FUNCARG6DV( a,b,c,d,e,f ) \ + CYG_REPORT_FUNCARG6( \ + # a "=%d " # b "=%d " # c "=%d " # d "=%d " \ + # e "=%d " # f "=%d " \ + , a,b,c,d,e,f ) +#define CYG_REPORT_FUNCARG7DV( a,b,c,d,e,f,g ) \ + CYG_REPORT_FUNCARG7( \ + # a "=%d " # b "=%d " # c "=%d " # d "=%d " \ + # e "=%d " # f "=%d " # g "=%d " \ + , a,b,c,d,e,f,g ) +#define CYG_REPORT_FUNCARG8DV( a,b,c,d,e,f,g,h ) \ + CYG_REPORT_FUNCARG8( \ + # a "=%d " # b "=%d " # c "=%d " # d "=%d " \ + # e "=%d " # f "=%d " # g "=%d " # h "=%d " \ + , a,b,c,d,e,f,g,h ) + +// short hex versions + +#define CYG_REPORT_FUNCARG1Y( a ) \ + CYG_REPORT_FUNCARG1( "%x", a ) +#define CYG_REPORT_FUNCARG2Y( a,b ) \ + CYG_REPORT_FUNCARG2( "%x %x", a,b ) +#define CYG_REPORT_FUNCARG3Y( a,b,c ) \ + CYG_REPORT_FUNCARG3( "%x %x %x", a,b,c ) +#define CYG_REPORT_FUNCARG4Y( a,b,c,d ) \ + CYG_REPORT_FUNCARG4( "%x %x %x %x", a,b,c,d ) +#define CYG_REPORT_FUNCARG5Y( a,b,c,d,e ) \ + CYG_REPORT_FUNCARG5( "%x %x %x %x %x", a,b,c,d,e ) +#define CYG_REPORT_FUNCARG6Y( a,b,c,d,e,f ) \ + CYG_REPORT_FUNCARG6( "%x %x %x %x %x %x", \ + a,b,c,d,e,f ) +#define CYG_REPORT_FUNCARG7Y( a,b,c,d,e,f,g ) \ + CYG_REPORT_FUNCARG7( "%x %x %x %x %x %x %x", \ + a,b,c,d,e,f,g ) +#define CYG_REPORT_FUNCARG8Y( a,b,c,d,e,f,g,h ) \ + CYG_REPORT_FUNCARG8( "%x %x %x %x %x %x %x %x", \ + a,b,c,d,e,f,g,h ) + +#define CYG_REPORT_FUNCARG1YV( a ) \ + CYG_REPORT_FUNCARG1( # a "=%x ", a ) +#define CYG_REPORT_FUNCARG2YV( a,b ) \ + CYG_REPORT_FUNCARG2( \ + # a "=%x " # b "=%x " , a,b ) +#define CYG_REPORT_FUNCARG3YV( a,b,c ) \ + CYG_REPORT_FUNCARG3( \ + # a "=%x " # b "=%x " # c "=%x " , a,b,c ) +#define CYG_REPORT_FUNCARG4YV( a,b,c,d ) \ + CYG_REPORT_FUNCARG4( \ + # a "=%x " # b "=%x " # c "=%x " # d "=%x " \ + , a,b,c,d ) +#define CYG_REPORT_FUNCARG5YV( a,b,c,d,e ) \ + CYG_REPORT_FUNCARG5( \ + # a "=%x " # b "=%x " # c "=%x " # d "=%x " \ + # e "=%x " \ + , a,b,c,d,e ) +#define CYG_REPORT_FUNCARG6YV( a,b,c,d,e,f ) \ + CYG_REPORT_FUNCARG6( \ + # a "=%x " # b "=%x " # c "=%x " # d "=%x " \ + # e "=%x " # f "=%x " \ + , a,b,c,d,e,f ) +#define CYG_REPORT_FUNCARG7YV( a,b,c,d,e,f,g ) \ + CYG_REPORT_FUNCARG7( \ + # a "=%x " # b "=%x " # c "=%x " # d "=%x " \ + # e "=%x " # f "=%x " # g "=%x " \ + , a,b,c,d,e,f,g ) +#define CYG_REPORT_FUNCARG8YV( a,b,c,d,e,f,g,h ) \ + CYG_REPORT_FUNCARG8( \ + # a "=%x " # b "=%x " # c "=%x " # d "=%x " \ + # e "=%x " # f "=%x " # g "=%x " # h "=%x " \ + , a,b,c,d,e,f,g,h ) + + +#endif // CYGONCE_INFRA_CYG_TRAC_H multiple inclusion protection +// EOF cyg_trac.h diff --git a/host/infra/cyg_type.h b/host/infra/cyg_type.h new file mode 100644 --- /dev/null +++ b/host/infra/cyg_type.h @@ -0,0 +1,339 @@ +#ifndef CYGONCE_INFRA_CYG_TYPE_H +#define CYGONCE_INFRA_CYG_TYPE_H + +//========================================================================== +// +// cyg_type.h +// +// Standard types, and some useful coding macros. +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1997, 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg from an original by hmt +// Contributors: nickg +// Date: 1997-09-08 +// Purpose: share unambiguously sized types. +// Description: we typedef [cyg_][u]int8,16,32 &c for general use. +// Usage: #include "cyg/infra/cyg_type.h" +// ... +// cyg_int32 my_32bit_integer; +// +//####DESCRIPTIONEND#### +// + +#include // Definition of NULL from the compiler + +// ------------------------------------------------------------------------- +// Some useful macros. These are defined here by default. + +// externC is used in mixed C/C++ headers to force C linkage on an external +// definition. It avoids having to put all sorts of ifdefs in. + +#ifdef __cplusplus +# define externC extern "C" +#else +# define externC extern +#endif + + +// ------------------------------------------------------------------------- +// The header defines the base types used here. It is +// supplied either by the target architecture HAL, or by the host +// porting kit. They are all defined as macros, and only those that +// make choices other than the defaults given below need be defined. + +#define CYG_LSBFIRST 1234 +#define CYG_MSBFIRST 4321 + +#include + +#if (CYG_BYTEORDER != CYG_LSBFIRST) && (CYG_BYTEORDER != CYG_MSBFIRST) +# error You must define CYG_BYTEORDER to equal CYG_LSBFIRST or CYG_MSBFIRST +#endif + +#ifndef CYG_DOUBLE_BYTEORDER +#define CYG_DOUBLE_BYTEORDER CYG_BYTEORDER +#endif + +#ifndef cyg_halint8 +# define cyg_halint8 char +#endif +#ifndef cyg_halint16 +# define cyg_halint16 short +#endif +#ifndef cyg_halint32 +# define cyg_halint32 int +#endif +#ifndef cyg_halint64 +# define cyg_halint64 long long +#endif + +#ifndef cyg_halcount8 +# define cyg_halcount8 int +#endif +#ifndef cyg_halcount16 +# define cyg_halcount16 int +#endif +#ifndef cyg_halcount32 +# define cyg_halcount32 int +#endif +#ifndef cyg_halcount64 +# define cyg_halcount64 long long +#endif + +#ifndef cyg_haladdress +# define cyg_haladdress cyg_uint32 +#endif +#ifndef cyg_haladdrword +# define cyg_haladdrword cyg_uint32 +#endif + +#ifndef cyg_halbool +# ifdef __cplusplus +# define cyg_halbool bool +# else +# define cyg_halbool int +# endif +#endif + +#ifndef cyg_halatomic +# define cyg_halatomic cyg_halint8 +#endif + +// ------------------------------------------------------------------------- +// The obvious few that compilers may define for you. +// But in case they don't: + +#ifndef NULL +# define NULL 0 +#endif + +#ifndef __cplusplus + +typedef cyg_halbool bool; + +# ifndef false +# define false 0 +# endif + +# ifndef true +# define true (!false) +# endif + +#endif + +// ------------------------------------------------------------------------- +// Allow creation of procedure-like macros that are a single statement, +// and must be followed by a semi-colon + +#define CYG_MACRO_START do { +#define CYG_MACRO_END } while (0) + +#define CYG_EMPTY_STATEMENT CYG_MACRO_START CYG_MACRO_END + +#define CYG_UNUSED_PARAM( _type_, _name_ ) CYG_MACRO_START \ + _type_ __tmp1 = (_name_); \ + _type_ __tmp2 = __tmp1; \ + __tmp1 = __tmp2; \ +CYG_MACRO_END + + +// ------------------------------------------------------------------------- +// Reference a symbol without explicitly making use of it. Ensures that +// the object containing the symbol will be included when linking. + +#define CYG_REFERENCE_OBJECT(__object__) \ + CYG_MACRO_START \ + static void *__cygvar_discard_me__ __attribute__ ((unused)) = \ + &(__object__); \ + CYG_MACRO_END + +// ------------------------------------------------------------------------- +// Define basic types for using integers in memory and structures; +// depends on compiler defaults and CPU type. + +typedef unsigned cyg_halint8 cyg_uint8 ; +typedef signed cyg_halint8 cyg_int8 ; + +typedef unsigned cyg_halint16 cyg_uint16 ; +typedef signed cyg_halint16 cyg_int16 ; + +typedef unsigned cyg_halint32 cyg_uint32 ; +typedef signed cyg_halint32 cyg_int32 ; + +typedef unsigned cyg_halint64 cyg_uint64 ; +typedef signed cyg_halint64 cyg_int64 ; + +typedef cyg_halbool cyg_bool ; + +// ------------------------------------------------------------------------- +// Define types for using integers in registers for looping and the like; +// depends on CPU type, choose what it is most comfortable with, with at +// least the range required. + +typedef unsigned cyg_halcount8 cyg_ucount8 ; +typedef signed cyg_halcount8 cyg_count8 ; + +typedef unsigned cyg_halcount16 cyg_ucount16 ; +typedef signed cyg_halcount16 cyg_count16 ; + +typedef unsigned cyg_halcount32 cyg_ucount32 ; +typedef signed cyg_halcount32 cyg_count32 ; + +typedef unsigned cyg_halcount64 cyg_ucount64 ; +typedef signed cyg_halcount64 cyg_count64 ; + +// ------------------------------------------------------------------------- +// Define a type to be used for atomic accesses. This type is guaranteed +// to be read or written in a single uninterruptible operation. This type +// is at least a single byte. + +typedef volatile unsigned cyg_halatomic cyg_atomic; +typedef volatile unsigned cyg_halatomic CYG_ATOMIC; + +// ------------------------------------------------------------------------- +// Define types for access plain, on-the-metal memory or devices. + +typedef cyg_uint32 CYG_WORD; +typedef cyg_uint8 CYG_BYTE; +typedef cyg_uint16 CYG_WORD16; +typedef cyg_uint32 CYG_WORD32; +typedef cyg_uint64 CYG_WORD64; + +typedef cyg_haladdress CYG_ADDRESS; +typedef cyg_haladdrword CYG_ADDRWORD; + +// ------------------------------------------------------------------------- +// Constructor ordering macros. These are added as annotations to all +// static objects to order the constuctors appropriately. + +#if defined(__cplusplus) && defined(__GNUC__) +# define CYGBLD_ATTRIB_INIT_PRI( _pri_ ) __attribute__((init_priority(_pri_))) +#else +// FIXME: should maybe just bomb out if this is attempted anywhere else? +// Not sure +# define CYGBLD_ATTRIB_INIT_PRI( _pri_ ) +#endif + +// The following will be removed eventually as it doesn't allow the use of +// e.g. pri+5 format +#define CYG_INIT_PRIORITY( _pri_ ) CYGBLD_ATTRIB_INIT_PRI( CYG_INIT_##_pri_ ) + +#define CYGBLD_ATTRIB_INIT_BEFORE( _pri_ ) CYGBLD_ATTRIB_INIT_PRI(_pri_-100) +#define CYGBLD_ATTRIB_INIT_AFTER( _pri_ ) CYGBLD_ATTRIB_INIT_PRI(_pri_+100) + +#define CYG_INIT_HAL 10000 +#define CYG_INIT_SCHEDULER 11000 +#define CYG_INIT_INTERRUPTS 12000 +#define CYG_INIT_DRIVERS 13000 +#define CYG_INIT_CLOCK 14000 +#define CYG_INIT_IDLE_THREAD 15000 +#define CYG_INIT_THREADS 16000 +#define CYG_INIT_KERNEL 40000 +#define CYG_INIT_IO 49000 +#define CYG_INIT_LIBC 50000 +#define CYG_INIT_COMPAT 55000 +#define CYG_INIT_APPLICATION 60000 +#define CYG_INIT_PREDEFAULT 65534 +#define CYG_INIT_DEFAULT 65535 + +// ------------------------------------------------------------------------- +// COMPILER-SPECIFIC STUFF + +#ifdef __GNUC__ +// Force a 'C' routine to be called like a 'C++' contructor +# define CYGBLD_ATTRIB_CONSTRUCTOR __attribute__((constructor)) + +// Define a compiler-specific rune for saying a function doesn't return +# define CYGBLD_ATTRIB_NORET __attribute__((noreturn)) + +// How to define weak symbols - this is only relevant for ELF and a.out, +// but that won't be a problem for eCos +# define CYGBLD_ATTRIB_WEAK __attribute__ ((weak)) + +// How to define alias to symbols. Just pass in the symbol itself, not +// the string name of the symbol +# define CYGBLD_ATTRIB_ALIAS(__symbol__) \ + __attribute__ ((alias (#__symbol__))) + +// This effectively does the reverse of the previous macro. It defines +// a name that the attributed variable or function will actually have +// in assembler. +# define CYGBLD_ATTRIB_ASM_ALIAS(__symbol__) \ + __asm__ ( #__symbol__ ) + +// Shows that a function returns the same value when given the same args, but +// note this can't be used if there are pointer args +# define CYGBLD_ATTRIB_CONST __attribute__((const)) + +#else // non-GNU + +# define CYGBLD_ATTRIB_CONSTRUCTOR + +# define CYGBLD_ATTRIB_NORET + // This intentionally gives an error only if we actually try to + // use it. #error would give an error if we simple can't. +# define CYGBLD_ATTRIB_WEAK !!!-- Attribute weak not defined --!!! + +# define CYGBLD_ATTRIB_ALIAS(__x__) !!!-- Attribute alias not defined --!!! + +# define CYGBLD_ATTRIB_ASM_ALIAS(__symbol__) !!!-- Asm alias not defined --!!! + +# define CYGBLD_ATTRIB_CONST + +#endif + +// How to define weak aliases. Currently this is simply a mixture of the +// above + +# define CYGBLD_ATTRIB_WEAK_ALIAS(__symbol__) \ + CYGBLD_ATTRIB_WEAK CYGBLD_ATTRIB_ALIAS(__symbol__) + +// ------------------------------------------------------------------------- +// Label name macro. Some toolsets generate labels with initial +// underscores and others don't. This macro should be used on labels +// that are defined in assembly code or linker scripts so that we can +// do the right thing. + +#ifndef CYG_LABEL_NAME + +#define CYG_LABEL_NAME(_name_) _name_ + +#endif + +// ------------------------------------------------------------------------- +// Various "flavours" of memory regions that can be described by the +// Memory Layout Tool (MLT). + +#define CYGMEM_REGION_ATTR_R 0x01 // Region can be read +#define CYGMEM_REGION_ATTR_W 0x02 // Region can be written + +// ------------------------------------------------------------------------- +#endif // CYGONCE_INFRA_CYG_TYPE_H multiple inclusion protection +// EOF cyg_type.h diff --git a/host/infra/diag.h b/host/infra/diag.h new file mode 100644 --- /dev/null +++ b/host/infra/diag.h @@ -0,0 +1,106 @@ +#ifndef CYGONCE_INFRA_DIAG_H +#define CYGONCE_INFRA_DIAG_H + +/*============================================================================= +// +// diag.h +// +// Diagnostic Routines for Infra Development +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 1998-03-02 +// Purpose: Diagnostic Routines for Infra Development +// Description: Diagnostic routines for use during infra development. +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//==========================================================================*/ + +#include +#include + +#ifdef CYGDBG_INFRA_DIAG_PRINTF_USE_VARARG +#include +#endif + +#ifdef CYGDBG_INFRA_DIAG_USE_DEVICE +#include +#endif + +/*---------------------------------------------------------------------------*/ +/* Diagnostic routines */ + +externC void diag_init(void); /* Initialize, call before any others*/ + +externC void diag_write_char(char c); /* Write single char to output */ + +externC void diag_write_string(const char *psz); /* Write zero terminated string */ + +externC void diag_write_dec( cyg_int32 n); /* Write decimal value */ + +externC void diag_write_hex( cyg_uint32 n); /* Write hexadecimal value */ + +externC void diag_dump_buf(void *buf, CYG_ADDRWORD len); + +#ifdef CYGDBG_INFRA_DIAG_PRINTF_USE_VARARG + +externC void diag_printf( const char *fmt, ... ); /* Formatted print */ + +#else + +// This function deliberately has a K&R prototype to avoid having to use +// varargs, or pad arglists or anything grody like that. + +#warning CYGDBG_INFRA_DIAG_PRINTF_USE_VARARG not enabled +#warning Expect a "function declaration isn't a prototype" warning + +externC void diag_printf(/* const char *fmt, CYG_ADDRWORD, CYG_ADDRWORD, + CYG_ADDRWORD, CYG_ADDRWORD, CYG_ADDRWORD, + CYG_ADDRWORD, CYG_ADDRWORD, CYG_ADDRWORD */); + +#endif + +/*---------------------------------------------------------------------------*/ +/* Internal Diagnostic MACROS */ + +#ifdef CYGDBG_INFRA_DIAG_USE_DEVICE +#define DIAG_DEVICE_START_SYNC() diag_device_start_sync() +#define DIAG_DEVICE_END_SYNC() diag_device_end_sync() +#else +#define DIAG_DEVICE_START_SYNC() +#define DIAG_DEVICE_END_SYNC() +#endif + +/*---------------------------------------------------------------------------*/ +#endif /* CYGONCE_INFRA_DIAG_H */ +/* EOF diag.h */ diff --git a/host/infra/hosttest.exp b/host/infra/hosttest.exp new file mode 100644 --- /dev/null +++ b/host/infra/hosttest.exp @@ -0,0 +1,727 @@ +#=============================================================================== +# +# hosttest.exp +# +# Support for host-side testing +# +#=============================================================================== +######COPYRIGHTBEGIN#### +# +# ---------------------------------------------------------------------------- +# Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +# +# This file is part of the eCos host tools. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# ---------------------------------------------------------------------------- +# +######COPYRIGHTEND#### +#=============================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): bartv +# Contributors: bartv +# Date: 1998-11-25 +# Note: Arguably this should be a loadable package +# +#####DESCRIPTIONEND#### +#=============================================================================== +# + +# ---------------------------------------------------------------------------- +# This script gets loaded by host-side DejaGnu test harnesses to provide +# various utilities for testing eCos host applications. It lives in the +# host-side infrastructure directory and gets installed in +# $(PREFIX)/share/dejagnu. +# +# The script can assume that a number of globals from the site.exp +# file have been read in. These include: +# tool - name of the tool (i.e. the package) +# srcdir - location of the source directory +# objdir - location of the build tree +# host_alias - config triplet +# host_triplet - ditto +# +# The generated Makefile has some additional information that is useful. +# CC - name of the C compiler that is used +# CXX - name of the C++ compiler +# prefix - where everything gets installed +# OBJEXT - either o or obj +# EXEEXT - either nothing or .exe +# VERSION - the version number +# CFLAGS - flags to use when compiling C code +# CXXFLAGS - flags to use when compiling C++ code +# +# hosttest_initialize +# Perform any initialization steps that are needed. Currently this +# means reading in the Makefile from the top-level of the build tree +# and figuring out the values of CC, CXX, and anything else that is +# useful. Any errors should be reported via perror and then the +# script should exit. +# +# There is an optional argument, a list of additional variables which +# should be present in the makefile and whose values are desired. + +proc hosttest_initialize { { pkg_vars {} } } { + + # First check that this script is actually running inside DejaGnu + if { [info exists ::objdir] == 0 } { + puts "Variable ::objdir is not defined, is this script really running inside DejaGnu?" + exit 1 + } + + # The information is stored in an array hosttest_data. Make sure this + # array exists. + array set ::hosttest_data {} + + # Now clear out any entries in the array + foreach entry [array names ::hosttest_data] { + unset ::hosttest_data($entry) + } + + # Now read in the build tree's Makefile (and not the testsuite's Makefile) + set filename [file join $::objdir .. Makefile] + if { [file exists $filename] == 0 } { + perror "Initialization error: the build tree's Makefile $filename does not exist." + exit 1 + } + set status [ catch { + set fd [open $filename r] + set contents [read $fd] + close $fd + } message] + if { $status != 0 } { + perror "Error reading $filename.\n$message" + exit 1 + } + + # The data is available. Search it for each of the variables of + # interest. Some variables are optional and are given default + # values. + set ::hosttest_data(CFLAGS) "" + set ::hosttest_data(CXXFLAGS) "" + + set lines [split $contents "\n"] + + foreach var [concat { CC CXX prefix OBJEXT EXEEXT VERSION CFLAGS CXXFLAGS } $pkg_vars] { + + set pattern "^$var\[ \t\]*:?=\[ \t\]* (.*)\$" + set dummy "" + set match "" + + foreach line $lines { + if { [regexp -- $pattern $line dummy match] == 1 } { + set ::hosttest_data($var) $match + break + } + } + if { [info exists ::hosttest_data($var)] == 0 } { + perror "Variable $var is not defined in $filename" + exit 1 + } + } + + # If compiling with VC++ remove any cygwin-isms from the prefix + if { [string match "cl*" $::hosttest_data(CC)] } { + set status [catch "exec cygpath -w $::hosttest_data(prefix)" message] + if { $status == 0 } { + regsub -all -- {\\} $message {/} ::hosttest_data(prefix) + } else { + perror "Converting cygwin pathname $::hosttest_data(prefix)\n$message" + exit 1 + } + } +} + + +# ---------------------------------------------------------------------------- +# hosttest_extract_version +# Assuming there has been a call to initialize, the required information +# should be available in the hosttest_data array. The initialize +# function should have aborted if the data is not available. + +proc hosttest_extract_version { } { + + if { [info exists ::hosttest_data(VERSION)] == 0 } { + error "No version information - host testing has not been properly initialized." + } + + if { [info exists ::objdir] == 0 } { + error "Variable ::objdir is not defined, is this script really running inside DejaGnu?" + } + return $::hosttest_data(VERSION) +} + +# ---------------------------------------------------------------------------- +# hosttest_compile +# compile and link one or more source files. The arguments are: +# 1) the name of the test case +# 2) a list of one or more source files that need to be compiled. +# Both .c and .cxx files are supported, and the appropriate +# compiler will be used. If this list is empty then the +# code will look for a .c or a .cxx file which matches the +# name of the test executable. Source files are assumed to +# be relative to $::srcdir/$::subdir +# 3) a list (possibly empty) of directories that should be in the +# include path. The build tree's directory is automatically in +# the path, as is $(PREFIX)/include. Note that the build tree +# is actually one level above objdir, on the assumption that +# objdir is the testsuite subdirectory of the real objdir. +# 4) ditto for library search paths. +# 5) and a list of additional libraries that should be linked. +# +# Currently it is not possible to pass compiler flags since those +# might need translating between gcc and VC++. This may have to be +# resolved. +# +# Currently linking is not done via libtool. This may have to change. +# +# The various object files and the executable are placed in a directory +# testcase in the build tree, to avoid the risk of name clashes. This +# directory must not exist yet. There is a separate routine hosttest_clean +# which simply expunges the entire testcase directory. +# +# The output of a succesful compile or built is reported using +# verbose at level 2. Unsuccesful compiles or builts are reported using +# level 1. + +proc hosttest_compile { name sources incdirs libdirs libs } { + + # Make sure that the testcase directory does not yet exist, then + # create it. This guarantees a clean system and reasonable access + # permissions. Each testcase invocation should involve a call to + # the clean function. + set dirname [file join $::objdir "testcase"] + if { [file exists $dirname] != 0 } { + # An empty directory is ok. + if { [llength [glob -nocomplain -- [file join $dirname "*"]]] != 0 } { + error "hosttest_compile: $dirname already exists" + } + } + + set status [catch { file mkdir $dirname } message] + if { $status != 0 } { + error "hosttest_compile: unable to create directory $dirname" + } + + # The only argument that must be valid is the test name. + if { $name == "" } { + error "hosttest_compile: invalid test case name" + } + + # If the list of sources is empty then look for a suitable + # file in the appropriate directory. + if { [llength $sources] == 0 } { + set filename [file join $::srcdir $::subdir "${name}.c"] + if { [file exists $filename] && [file isfile $filename] } { + lappend sources [file tail $filename] + } else { + set filename [file join $::srcdir $::subdir "${name}.cxx"] + if { [file exists $filename] && [file isfile $filename] } { + lappend sources [file tail $filename] + } else { + error "hosttest_compile: no sources listed and unable to find ${name}.c or ${name}.cxx" + } + } + } + + # For each source file, generate a compile command line and try to execute + # it. The command line takes the form: + # (CC|CXX) -c (CFLAGS|CXXFLAGS) (INCDIRS) -o xxx yyy + # + # It is also useful to produce a list of the object files that need to + # linked later on, and to work out which tool should be invoked for + # linking. + set object_files {} + set has_cxx_files 0 + + foreach source $sources { + set commandline "" + if { [file extension $source] == ".c" } { + append commandline "$::hosttest_data(CC) -c $::hosttest_data(CFLAGS) " + } elseif { [file extension $source] == ".cxx" } { + set has_cxx_files 1 + append commandline "$::hosttest_data(CXX) -c $::hosttest_data(CXXFLAGS) " + } else { + error "hosttest_compile: files of type [file extension $source] ($source) are not yet supported." + } + + # Include path: start with the source tree. Then the build tree. + # Then any additional directories specified explicitly by the + # testcase. Finish off with the prefix. Note that header files + # in the prefix directory may be out of date, depending on whether + # or not there has been an install recently. + append commandline "-I[file join [pwd] [file dirname $::srcdir]] " + append commandline "-I[file join [pwd] [file dirname $::objdir]] " + foreach dir $incdirs { + append commandline "-I[file join [pwd] $dir] " + } + append commandline "-I[file join [pwd] $::hosttest_data(prefix) include] " + + # The output file must go into the testcase directory and have the right suffix + set objfile "[file root [file tail $source]].$::hosttest_data(OBJEXT)" + lappend object_files $objfile + if { [string match "cl*" $::hosttest_data(CC)] } { + append commandline "-Fo[file join $::objdir testcase $objfile] " + } else { + append commandline "-o [file join $::objdir testcase $objfile] " + } + + # Finally provide the source file. + append commandline "[file join $::srcdir $::subdir $source]" + verbose -log -- $commandline + + # Time to invoke the compiler. + set status [catch { set result [eval exec -keepnewline -- $commandline] } message] + if { $status == 0 } { + # The compile succeeded and the output is in result. Report the + # output. + verbose -log -- $result + } else { + # The compile failed and the output is in message. + verbose -log -- $message + error "hosttest_compile: failed to compile $source" + } + } + + # At this stage all the source files have been compiled, a list of + # object files has been constructed, and it is known whether or + # not any of the sources were c++. Time to construct a new command + # line. + set commandline "" + if { $has_cxx_files == 0 } { + append commandline "$::hosttest_data(CC) $::hosttest_data(CFLAGS) " + } else { + append commandline "$::hosttest_data(CXX) $::hosttest_data(CXXFLAGS) " + } + set exename [file join $::objdir "testcase" "$name$::hosttest_data(EXEEXT)"] + + # List all of the object files + foreach obj $object_files { + append commandline "[file join $::objdir "testcase" $obj] " + } + + # Now take care of libraries and search paths. This requires different + # code for gcc and VC++. + + if { [string match "cl*" $::hosttest_data(CC)] } { + append commandline "-Fe$exename " + + foreach lib $libs { + append commandline "${lib}.lib " + } + append commandline "-link " + append commandline "-libpath=[file join [pwd] [file dirname $::objdir]] " + foreach dir $libdirs { + append commandline "-libpath=[file join [pwd] $dir] " + } + append commandline "-libpath=[file join [pwd] $::hosttest_data(prefix) lib] " + } else { + append commandline "-o $exename " + append commandline "-L[file join [pwd] [file dirname $::objdir]] " + foreach dir $libdirs { + append commandline "-L[file join [pwd] $dir] " + } + append commandline "-L[file join [pwd] $::hosttest_data(prefix) lib] " + foreach lib $libs { + append commandline "-l$lib " + } + } + + # We have a command line, go for it. + verbose -log -- $commandline + set status [catch { set result [eval exec -keepnewline -- $commandline] } message] + if { $status == 0 } { + # The link has succeeded, we have an executable. + verbose -log -- $result + } else { + # The link failed and the output is in message. + # Report things are per compilation failures + verbose -log -- $message + error "hosttest_compile: failed to link $exename" + } + + # There should be a test executable. +} + +# ---------------------------------------------------------------------------- +# hosttest_clean +# Clean up a testcase directory. + +proc hosttest_clean { } { + + set dirname [file join $::objdir "testcase"] + if { [file exists $dirname] == 0 } { + + # Something must have gone seriously wrong during the build phase, + # there is nothing there. + return + } + + if { [file isdirectory $dirname] == 0 } { + error "hosttest_clean: $dirname should be a directory" + } + + foreach entry [glob -nocomplain -- [file join $dirname "*"]] { + set filename [file join $dirname $entry] + if { [file isfile $filename] == 0 } { + error "hosttest_clean: $filename is not a file" + } + set status [catch { file delete -force -- $filename } message] + if { $status != 0 } { + error "hosttest_clean: unable to delete $filename, $message" + } + } + set status [catch { file delete -force -- $dirname } message] + if { $status != 0 } { + error "hosttest_clean: unable to delete directory $dirname, $message" + } +} + +# ---------------------------------------------------------------------------- +# Run a test executable, returning the status code and the output. +# The results are returned in variables. It is assumed that some test cases +# will fail, so raising an exception is appropriate only if something +# has gone wrong at the test harness level. The argument list +# should be the name of the test case (from which the executable file name +# can be derived) and a list of arguments. + +proc hosttest_run { result_arg output_arg test args } { + + upvar $result_arg result + upvar $output_arg output + + # Figure out the filename corresponding to the test and make + # sure it exists. + set filename [file join $::objdir "testcase" $test] + append filename $::hosttest_data(EXEEXT) + if { ([file exists $filename] == 0) || ([file isfile $filename] == 0) } { + error "hosttest_run: testcase file $filename does not exist" + } + + # There is no need to worry about interacting with the program, + # just exec it. It is a good idea to do this in the testcase directory, + # so that any core dumps get cleaned up as well. + set current_dir [pwd] + set status [ catch { cd [file join $::objdir "testcase"] } message ] + if { $status != 0 } { + error "unable to change directory to [file join $::objdir testcase]\n$message" + } + + verbose -log -- $filename $args + set status [ catch { set result [eval exec -keepnewline -- $filename $args] } output] + if { $status == 0 } { + # The command has succeeded. The exit code is 0 and the output + # was returned by the exec. + set output $result + set result 0 + } else { + # The command has failed. The exit code is 1 and the output is + # already in the right place. + verbose -log -- $output + set result 1 + } + set status [catch { cd $current_dir } message] + if { $status != 0 } { + error "unable to change directory back to $current_dir" + } +} + +# ---------------------------------------------------------------------------- +# Given some test output, look through it for pass and fail messages. +# These should result in appropriate DejaGnu pass and fail calls. +# In addition, if the program exited with a non-zero status code but +# did not report any failures then a special failure is reported. + +proc hosttest_handle_output { name result output } { + + set passes 0 + set fails 0 + + foreach line [split $output "\n"] { + + # The output should be of one of the following forms: + # PASS: + # FAIL: Line: xx File: xx + # Whatever + # + # PASS and FAIL messages will be reported via DejaGnu pass and fail + # calls. Everything else gets passed to verbose, so the user gets + # to choose how much information gets reported. + + set dummy "" + set match1 "" + set match2 "" + + if { [regexp -- {^PASS:<(.*)>.*$} $line dummy match1] == 1 } { + pass $match1 + incr passes + } elseif { [regexp -- {^FAIL:<(.*)>(.*)$} $line dummy match1 match2] == 1 } { + fail "$match1 $match2" + incr fails + } else { + verbose $line + } + } + + if { ($result != 0) && ($fails == 0) } { + fail "program terminated with non-zero exit code but did not report any failures" + } elseif { ($passes == 0) && ($fails == 0) } { + unresolved "test case $name did not report any passes or failures" + } +} + +# ---------------------------------------------------------------------------- +# hosttest_run_test_with_filter +# This routines combines the compile, run and clean operations, +# plus it invokes a supplied callback to filter the output. The +# callback is passed three arguments: the test name, the exit code, +# and all of the program output. + +proc hosttest_run_test_with_filter { name filter sources incdirs libdirs libs args } { + + set result 0 + set output "" + + set status [ catch { hosttest_compile $name $sources $incdirs $libdirs $libs } message] + if { $status != 0 } { + fail "unable to compile test case $name, $message" + hosttest_clean + return + } + set status [ catch { hosttest_run result output $name $args } message] + if { $status != 0 } { + fail "unable to run test case $name, $message" + hosttest_clean + return + } + set status [ catch { $filter $name $result $output } message] + if { $status != 0 } { + fail "unable to parse output from test case $name" + hosttest_clean + return + } + + hosttest_clean +} + +# ---------------------------------------------------------------------------- +# hosttest_run_simple_test +# This routine combines the compile, run, output, and clean operations. +# The arguments are the same as for compilation, plus an additional +# list for run-time parameters to the test case. + +proc hosttest_run_simple_test { name sources incdirs libdirs libs args } { + + + set result 0 + set output "" + + set status [ catch { hosttest_compile $name $sources $incdirs $libdirs $libs } message] + if { $status != 0 } { + fail "unable to compile test case $name, $message" + hosttest_clean + return + } + set status [ catch { hosttest_run result output $name $args } message] + if { $status != 0 } { + fail "unable to run test case $name, $message" + hosttest_clean + return + } + set status [ catch { hosttest_handle_output $name $result $output } message] + if { $status != 0 } { + fail "unable to parse output from test case $name" + hosttest_clean + return + } + + hosttest_clean +} + +# ---------------------------------------------------------------------------- +# Filename translation. A particular file has been created and must now +# be accessed from Tcl. +# +# Under Unix everything just works. +# +# Under Windows, well there is cygwin and there is the Windows world. +# A file may have come from either. cygtclsh80 and hence DejaGnu is not +# fully integrated with cygwin, for example it does not know about +# cygwin mount points. There are also complications because of +# volume-relative filenames. +# +# The code here tries a number of different ways of finding a file which +# matches the name. It is possible that the result is not actually what +# was intended, but hopefully this case will never arise. + +proc hosttest_translate_existing_filename { name } { + + if { $::tcl_platform(platform) == "unix" } { + # The file should exist. It is worth checking just in case. + if { [file exists $name] == 0 } { + return "" + } else { + return $name + } + } + + if { $::tcl_platform(platform) != "windows" } { + perror "The testing framework does not know about platform $::tcl_platform(platform)" + return "" + } + + # Always get rid of any backslashes, they just cause trouble + regsub -all -- {\\} $name {/} name + + # If the name is already valid, great. + if { [file exists $name] } { + return $name + } + + # OK, try to use cygwin's cygpath utility to convert it. + set status [catch "exec cygpath -w $name" message] + if { $status == 0 } { + set cygwin_name "" + regsub -all -- {\\} $message {/} cygwin_name + if { [file exists $cygwin_name] } { + return $cygwin_name + } + } + + # Is the name volumerelative? If so work out the current volume + # from the current directory and prepend this. + if { [file pathtype $name] == "volumerelative" } { + append fullname [string range [pwd] 0 1] $name + if { [file exists $fullname] } { + return $fullname + } + } + + # There are other possibilities, e.g. d:xxx indicating a file + # relative to the current directory on drive d:. For now such + # Lovecraftian abominations are ignored. + return "" +} + +# ---------------------------------------------------------------------------- +# Support for assertion dumps. The infrastructure allows other subsystems +# to add their own callbacks which get invoked during a panic and which +# can write additional output to the dump file. For example it would be +# possible to output full details of the current configuration. These +# routines make it easier to write test cases for such callbacks. +# +# hosttest_assert_check(result output) +# Make sure that the test case really triggered an assertion. +# +# hosttest_assert_read_dump(output) +# Identify the temporary file used for the dump, read it in, delete +# it (no point in leaving such temporaries lying around when running +# testcases) and return the contents of the file. +# +# hosttest_assert_extract_callback(dump title) +# Given a dump output as returned by read_dump, look for a section +# generated by a callback with the given title. Return the contents +# of the callback. + +proc hosttest_assert_check { result output } { + + if { $result == 0 } { + return 0 + } + + foreach line [split $output "\n"] { + if { [string match "Assertion failure*" $line] } { + return 1 + } + } + return 0 +} + +# This routine assumes that assert_check has already been called. +proc hosttest_assert_read_dump { output } { + + foreach line [split $output "\n"] { + set dummy "" + set match "" + + if { [regexp -nocase -- {^writing additional output to (.*)$} $line dummy match] } { + + # The filename is in match, but it may not be directly accessible. + set filename [hosttest_translate_existing_filename $match] + if { $filename == "" } { + return "" + } + set status [ catch { + set fd [open $filename r] + set data [read $fd] + close $fd + file delete $filename + } message] + if { $status != 0 } { + unresolved "Unable to process assertion dump file $filename" + unresolved "File $filename may have to be deleted manually" + return "" + } + return $data + } + } + return "" +} + +# Look for the appropriate markers. Also clean up blank lines +# at the start and end. +proc hosttest_assert_extract_callback { dump title } { + + set lines [split $dump "\n"] + set result "" + + while { [llength $lines] > 0 } { + set line [lindex $lines 0] + set lines [lreplace $lines 0 0] + + if { [regexp -nocase -- "^\# \{\{\{.*${title}.*\$" $line] } { + + # Skip any blank lines at the start + while { [llength $lines] > 0 } { + set line [lindex $lines 0] + if { [regexp -- {^ *$} $line] == 0} { + break + } + set lines [lreplace $lines 0 0] + } + + # Now add any lines until the close marker. + # Nested folds are not supported yet. + while { [llength $lines] > 0 } { + set line [lindex $lines 0] + set lines [lreplace $lines 0 0] + if { [regexp -nocase -- {^\# \}\}\}.*$} $line] } { + break + } + append result $line "\n" + } + + return $result + } + } + + return "" +} + + + + diff --git a/host/infra/infra.h b/host/infra/infra.h new file mode 100644 --- /dev/null +++ b/host/infra/infra.h @@ -0,0 +1,116 @@ +#ifndef CYGONCE_PKGCONF_INFRA_H +# define CYGONCE_PKGCONF_INFRA_H + +//====================================================================== +// +// infra.h +// +// Host side implementation of the infrastructure configuration +// header. +// +//====================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//====================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contact(s): bartv +// Date: 1998/07/13 +// Version: 0.01 +// +//####DESCRIPTIONEND#### +//====================================================================== + +// The purpose of this header file is to replicate appropriate +// functionality from the target-side header file . +// This header file is intended to contain configuration options +// related to the implementation of the infrastructure, as opposed +// to how that infrastructure gets used by other packages. A good +// example would be a configuration option to control the size +// of the circular trace buffer. +// +// On the host side these things are handled by autoconf, and in +// particular the configure.in script will offer command-line +// arguments allowing the relevant options to be controlled. +// The relevant information will end up in +# include + +// Some options should always be enabled in this header file. +#define CYGDBG_INFRA_DIAG_PRINTF_USE_VARARG +#define CYGDBG_INFRA_DEBUG_ASSERT_MESSAGE +#define CYGDBG_INFRA_DEBUG_TRACE_MESSAGE + +// Other options should be decided on a package by package basis, +// e.g. whether or not assertions are used. On the host side it is +// not appropriate to control these globally, instead the infrastructure +// always provides the necessary functionality and it is up to the +// other parts of the system to decide whether or not the facilities +// get used. + +// A third set of options deal with the environment, e.g. the sizes +// of various data types. autoconf macros take care of most of the +// work, but some translation is needed into eCos-style names to +// avoid namespace pollution. + +// Process the definitions of SIZEOF_INT_P and SIZEOF_LONG to work +// out a sensible data type for CYG_ADDRESS and CYG_ADDRWORD. + +#if (!defined(SIZEOF_INT_P) || !defined(SIZEOF_LONG)) +# error "Configure problem: data type sizes not set" +#endif + +#if (SIZEOF_INT_P == 4) + // The default, nothing needs to be done +#elif (SIZEOF_INT_P == 8) +# define cyg_haladdress cyg_halint64 +#else +# error "Only 32 and 64 bit pointers are supported" +#endif + +#if ((SIZEOF_INT_P == 4) && (SIZEOF_LONG == 4)) + // The default, nothing needs to be done +#elif ((SIZEOF_INT_P <= 8) && (SIZEOF_LONG <= 8)) + // cyg_halint64 will have been defined appropriately. +# define cyg_haladdrword cyg_halint64 +#else +# error "Only 32 and 64 bit machine word sizes are supported" +#endif + +// Any symbols defined in which have been processed +// here should no longer be of any interest, and in the interests of +// reducing name space pollution they get undef'ed here. + +// In addition there are two #define's in the config.h header file +// which are always present and which have names that are rather too +// generic. These get removed here as well. The version is worth +// preserving under a different name. +#undef SIZEOF_INT_P +#undef SIZEOF_LONG +#undef PACKAGE +#undef VERSION + +#endif // CYGONCE_PKGCONF_INFRA_H +// End of infra.h diff --git a/host/infra/stamp-h.in b/host/infra/stamp-h.in new file mode 100644 --- /dev/null +++ b/host/infra/stamp-h.in @@ -0,0 +1,1 @@ +timestamp diff --git a/host/infra/testcase.cxx b/host/infra/testcase.cxx new file mode 100644 --- /dev/null +++ b/host/infra/testcase.cxx @@ -0,0 +1,92 @@ +//========================================================================== +// +// testcase.cxx +// +// Host side implementation of the test support routines. +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contributors: bartv +// Date: 1998-01-01 +// Purpose: +// Description: +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include + +#include + +// Initialization is a no-op for the host side testing infrastructure. +// Only batch programs are likely to use these testing facilities so +// it is safe to assume that stdio is available. + +externC void +cyg_test_init(void) +{ +} + +// This simply implements the current interface, warts and all. +// It is necessary to keep track of any failures or invalid +// calls. +static int failures = 0; + +externC void +cyg_test_output(Cyg_test_code status, const char* msg, int line_number, const char* file) +{ + if (CYGNUM_TEST_FAIL == status) + failures++; + + if (0 == msg) + msg = ""; + if (0 == file) + file = ""; + + if (CYGNUM_TEST_FAIL == status) { + printf("FAIL:<%s> Line: %d, File: %s\n", msg, line_number, file); + } else { + printf("%s:<%s>\n", + (CYGNUM_TEST_PASS == status) ? "PASS" : + (CYGNUM_TEST_EXIT == status) ? "EXIT" : + (CYGNUM_TEST_INFO == status) ? "INFO" : + (CYGNUM_TEST_GDBCMD == status) ? "GDBCMD" : + (CYGNUM_TEST_NA == status) ? "NA" : "UNKNOWN STATUS", + msg); + } + +} + +externC void +cyg_test_exit(void) +{ + exit( (0 < failures) ? EXIT_FAILURE : EXIT_SUCCESS ); +} diff --git a/host/infra/testcase.h b/host/infra/testcase.h new file mode 100644 --- /dev/null +++ b/host/infra/testcase.h @@ -0,0 +1,191 @@ +#ifndef CYGONCE_INFRA_TESTCASE_H +#define CYGONCE_INFRA_TESTCASE_H +//========================================================================== +// +// testcase.h +// +// Target side interface for tests +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): ctarpy +// Contributors: ctarpy, jlarmour +// Date: 1999-02-16 +// +// +//####DESCRIPTIONEND#### + +#include // Common type definitions and support + + +// CONSTANTS + +// Status codes + +typedef enum { + CYGNUM_TEST_FAIL, + CYGNUM_TEST_PASS, + CYGNUM_TEST_EXIT, + CYGNUM_TEST_INFO, + CYGNUM_TEST_GDBCMD, + CYGNUM_TEST_NA +} Cyg_test_code; + +// FUNCTION PROTOTYPES + +externC void +cyg_test_output(Cyg_test_code _status_, const char* _msg_, int _line_number_, + const char* _file_); + +// This should be called at the start of each test file +externC void +cyg_test_init(void); + +// This causes the test to exit +externC void +cyg_test_exit(void) CYGBLD_ATTRIB_NORET; + +// GLOBALS + +externC int cyg_test_is_simulator; // infrastructure changes as necessary + +// MACROS + +// ----------- Info ----------- +// +// Any macro with EXIT in it should only be used in a panic situation. It +// is synonymous with assert. If the test behaves as expected, it +// should call one of the FINISH macros. +// +// - Compound testcases +// If a testcase is capable of being part of a compound, then the following +// rules apply: +// - The testcase must only ever call one of the EXIT macros if it decides +// the state of the system is such that further testing is meaningless; +// such a call would prevent subsequent tests in the compound from being +// run. +// - In order to terminate the test, the testcase should call one of the +// FINISH macros. This must be done from within main(). + + + + +// The following is the testcase API to be used by testcases. + +#define CYG_TEST_INIT() cyg_test_init() + +#define CYG_TEST_INFO( _msg_ ) \ + cyg_test_output(CYGNUM_TEST_INFO, _msg_, __LINE__, __FILE__) + +#define CYG_TEST_PASS( _msg_ ) \ + cyg_test_output(CYGNUM_TEST_PASS, _msg_, __LINE__, __FILE__) + +#define CYG_TEST_FAIL( _msg_ ) \ + cyg_test_output(CYGNUM_TEST_FAIL, _msg_, __LINE__, __FILE__) + +#define CYG_TEST_EXIT( _msg_ ) \ + (cyg_test_output(CYGNUM_TEST_EXIT, _msg_, __LINE__, __FILE__), \ + cyg_test_exit()) + +// Use the following macro to instruct GDB to run a command when using +// the automatic testing infrastructure. This must be used *before* +// CYG_TEST_INIT() is called + +#define CYG_TEST_GDBCMD( _command_ ) \ + CYG_MACRO_START \ + cyg_test_output(CYGNUM_TEST_GDBCMD, _command_, __LINE__, __FILE__); \ + CYG_MACRO_END + +// Use the following macro to declare that a test is not applicable for +// some reason - perhaps not appropriate due to chosen hardware, +// configuration options governing the presence of a tested feature, or +// even configuration options governing the presence of a feature the +// test relies on _in_order_ to test the feature (despite being +// unrelated!) + +#define CYG_TEST_NA( _msg_ ) \ + CYG_MACRO_START \ + cyg_test_output(CYGNUM_TEST_NA, _msg_, __LINE__, __FILE__); \ + cyg_test_exit(); \ + CYG_MACRO_END + +#ifdef CYG_COMPOUND_TEST +# define CYG_TEST_FINISH( _msg_ ) \ + CYG_MACRO_START \ + cyg_test_output(CYGNUM_TEST_EXIT, _msg_, __LINE__, __FILE__); \ + return 0; \ + CYG_MACRO_END +#else +# define CYG_TEST_FINISH( _msg_ ) CYG_TEST_EXIT( _msg_ ) +#endif + +#define CYG_TEST_STILL_ALIVE( _ctr_ , _msg_ ) CYG_TEST_INFO( _msg_ ) + + +// ----- The following are convenience functions + +#define CYG_TEST_PASS_FINISH( _msg_ ) \ + CYG_MACRO_START \ + CYG_TEST_PASS( _msg_ ); \ + CYG_TEST_FINISH("done"); \ + CYG_MACRO_END + +#define CYG_TEST_FAIL_FINISH( _msg_ ) \ + CYG_MACRO_START \ + CYG_TEST_FAIL( _msg_ ); \ + CYG_TEST_FINISH("done"); \ + CYG_MACRO_END + + +#define CYG_TEST_CHECK( _chk_ , _msg_) \ + CYG_MACRO_START \ + (void)(( _chk_ ) || ( CYG_TEST_FAIL( _msg_ ) , cyg_test_exit(), 1)); \ + CYG_MACRO_END + +#define CYG_TEST_PASS_FAIL( _cdn_, _msg_ ) \ + CYG_MACRO_START \ + if ( _cdn_ ) CYG_TEST_PASS( _msg_ ); else CYG_TEST_FAIL( _msg_ ); \ + CYG_MACRO_END + + +// CYG_TEST_PASS_EXIT and CYG_TEST_FAIL_EXIT are now obscelete, +// but are here for now +// to avoid breaking testcases which still use them. They will +// soon go away. +#define CYG_TEST_PASS_EXIT( _msg_ ) \ + (cyg_test_output(CYGNUM_TEST_PASS, _msg_, __LINE__, __FILE__), \ + CYG_TEST_EXIT("done")) + +#define CYG_TEST_FAIL_EXIT( _msg_ ) \ + (cyg_test_output(CYGNUM_TEST_FAIL, _msg_, __LINE__, __FILE__), \ + CYG_TEST_EXIT("done")) + + +#endif // CYGONCE_INFRA_TESTCASE_H +// EOF testcase.h diff --git a/host/infra/testsuite/Makefile.am b/host/infra/testsuite/Makefile.am new file mode 100644 --- /dev/null +++ b/host/infra/testsuite/Makefile.am @@ -0,0 +1,44 @@ +## Process this file with automake to produce Makefile.in +## ===================================================================== +## +## Makefile.am +## +## Host side implementation of the eCos infrastructure assertions. +## +## ===================================================================== +######COPYRIGHTBEGIN#### +## +## ---------------------------------------------------------------------------- +## Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +## +## This file is part of the eCos host tools. +## +## This program is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 of the License, or (at your option) +## any later version. +## +## This program is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +## more details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +## +## ---------------------------------------------------------------------------- +## +######COPYRIGHTEND#### +## ===================================================================== +#######DESCRIPTIONBEGIN#### +## +## Author(s): bartv +## Contact(s): bartv +## Date: 1998/07/13 +## Version: 0.01 +## +######DESCRIPTIONEND#### +## ===================================================================== + +AUTOMAKE_OPTIONS = 1.3 cygnus dejagnu diff --git a/host/infra/testsuite/Makefile.in b/host/infra/testsuite/Makefile.in new file mode 100644 --- /dev/null +++ b/host/infra/testsuite/Makefile.in @@ -0,0 +1,223 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 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. + +######COPYRIGHTBEGIN#### +######COPYRIGHTEND#### +#######DESCRIPTIONBEGIN#### +######DESCRIPTIONEND#### + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CC = @CC@ +CXX = @CXX@ +EXEEXT = @EXEEXT@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +VERSION = @VERSION@ +cyg_ac_tcl_incdir = @cyg_ac_tcl_incdir@ +cyg_ac_tcl_libdir = @cyg_ac_tcl_libdir@ +cyg_ac_tcl_libs = @cyg_ac_tcl_libs@ +cyg_ac_tcl_version = @cyg_ac_tcl_version@ +cyg_ac_tk_libs = @cyg_ac_tk_libs@ + +AUTOMAKE_OPTIONS = 1.3 cygnus dejagnu +mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs +CONFIG_HEADER = ../hostinfra.h +CONFIG_CLEAN_FILES = +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +EXPECT = `if test -f $(top_builddir)/../expect/expect; then echo $(top_builddir)/../expect/expect; else echo expect; fi` +RUNTEST = `if test -f $(top_srcdir)/../dejagnu/runtest; then echo $(top_srcdir)/../dejagnu/runtest; else echo runtest; fi` +all: all-redirect +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --cygnus testsuite/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +tags: TAGS +TAGS: + + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = testsuite + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + if test -f $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + cp -pr $$/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + +RUNTESTFLAGS = + +DEJATOOL = $(PACKAGE) + +RUNTESTDEFAULTFLAGS = --tool $(DEJATOOL) --srcdir $$srcdir + +check-DEJAGNU: site.exp + srcdir=`cd $(srcdir) && pwd`; export srcdir; \ + EXPECT=$(EXPECT); export EXPECT; \ + if [ -f $(top_builddir)/../expect/expect ]; then \ + TCL_LIBRARY=`cd $(top_srcdir)/../tcl/library && pwd`; \ + export TCL_LIBRARY; \ + fi; \ + runtest=$(RUNTEST); \ + if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \ + $$runtest $(RUNTESTDEFAULTFLAGS) $(RUNTESTFLAGS); \ + else echo "WARNING: could not find \`runtest'" 1>&2; :;\ + fi +site.exp: Makefile + @echo 'Making a new site.exp file...' + @test ! -f site.bak || rm -f site.bak + @echo '## these variables are automatically generated by make ##' > $@-t + @echo '# Do not edit here. If you wish to override these values' >> $@-t + @echo '# edit the last section' >> $@-t + @echo 'set tool $(DEJATOOL)' >> $@-t + @echo 'set srcdir $(srcdir)' >> $@-t + @echo 'set objdir' `pwd` >> $@-t + @echo 'set host_alias $(host_alias)' >> $@-t + @echo 'set host_triplet $(host_triplet)' >> $@-t + @echo '## All variables above are generated by configure. Do Not Edit ##' >> $@-t + @test ! -f site.exp || sed '1,/^## All variables above are.*##/ d' site.exp >> $@-t + @test ! -f site.exp || mv site.exp site.bak + @mv $@-t site.exp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: + $(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU +check: check-am +installcheck-am: +installcheck: installcheck-am +install-info-am: +install-info: install-info-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: +uninstall: uninstall-am +all-am: Makefile +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-generic clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: tags distdir check-DEJAGNU info-am info dvi-am dvi check \ +check-am installcheck-am installcheck install-info-am install-info \ +install-exec-am install-exec install-data-am install-data install-am \ +install uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# 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/host/infra/testsuite/config/default.exp b/host/infra/testsuite/config/default.exp new file mode 100644 --- /dev/null +++ b/host/infra/testsuite/config/default.exp @@ -0,0 +1,116 @@ +#=============================================================================== +# +# default.exp +# +# Support for host-side testing +# +#=============================================================================== +######COPYRIGHTBEGIN#### +# +# ---------------------------------------------------------------------------- +# Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +# +# This file is part of the eCos host tools. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# ---------------------------------------------------------------------------- +# +######COPYRIGHTEND#### +#=============================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): bartv +# Contributors: bartv +# Date: 1998-11-24 +# +#####DESCRIPTIONEND#### +#=============================================================================== +# + +# The host-side infrastructure tests will only run on the hosts, i.e. +# only native testing is possible. +if { [isnative] != 1 } { + perror "Only native testing is supported." + exit 1 +} + +# Most of the test harness lives in a file hosttest.exp. This is part +# of the host-side infrastructure and gets installed in the directory +# $(PREFIX)/share/dejagnu. Other packages have to locate the file +# the hard way since the PREFIX is not provided automatically in +# the site.exp file, instead it is necessary to search through the +# build tree's Makefile. In the case of the infrastructure itself +# a shortcut is both possible and desirable because the script may +# not have been installed yet. +# +# Note that srcdir actually points at the testsuite subdirectory, not +# at the real srcdir. +set filename [file join $::srcdir .. hosttest.exp] +set status [ catch { source $filename } message] +if { $status != 0 } { + perror ("Unexpected error while reading in the support script $filename\n$message" +} + +# Now that the hosttest.exp utilities are available it is possible to do +# a bit more initialization. In particular it is possible to read in the +# build tree's Makefile and look for definitions of CC, CXX, and any +# other information from the Makefile that may prove useful. +hosttest_initialize + +# There are standard routines ${tool}_start, ${tool}_load, ${tool}_exit +# and ${tool}_version which test harnesses should normally implement. +# In practice runtest only invokes ${tool}_exit and ${tool}_version +# directly, the rest may or may not be invoked from inside the individual +# test scripts. +# +# ${tool}_version is relatively straightforward. The master version +# number is maintained in the configure.in script and is exported to +# the build tree's Makefile. There is a hosttest routine which does the +# hard work because getting the information is common to all host +# packages. The _version routine itself cannot be made completely generic +# because the first output is package-specific. + +proc ${tool}_version { } { + + set status [ catch { hosttest_extract_version } message] + if { $status != 0 } { + perror $message + return + } + clone_output "[file join $::objdir libcyginfra.a] $message" +} + +# ${tool}_start does not serve any useful purpose when it comes to +# testing libcyginfra.a - there is no tool which can be started up. +# Therefore none of the individual test scripts will invoke this +# routine. + +proc ${tool}_start { } { + perror "Cyginfra is a library, not a tool, and cannot be started." +} + +# ${tool}_load is used to load a test case into the tool. The exact +# meaning is not applicable. However it makes sense to have this +# routine provide an alias for hosttest_run_simple_test which provides +# all the libraries etc. that are going to be needed. + +proc ${tool}_load { program { args ""} } { + hosttest_run_simple_test $program {} {} {} cyginfra $args +} + +# ${tool}_exit does not serve any useful purpose here. +proc ${tool}_exit { } { +} diff --git a/host/infra/testsuite/cyginfra/assert.exp b/host/infra/testsuite/cyginfra/assert.exp new file mode 100644 --- /dev/null +++ b/host/infra/testsuite/cyginfra/assert.exp @@ -0,0 +1,341 @@ +#=============================================================================== +# +# assert.exp +# +# Assertion test cases +# +#=============================================================================== +######COPYRIGHTBEGIN#### +# +# ---------------------------------------------------------------------------- +# Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +# +# This file is part of the eCos host tools. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# ---------------------------------------------------------------------------- +# +######COPYRIGHTEND#### +#=============================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): bartv +# Contributors: bartv +# Date: 1998-11-25 +# +#####DESCRIPTIONEND#### +#=============================================================================== + +# ---------------------------------------------------------------------------- +# Start with the simple tests. +${tool}_load tassert1 +${tool}_load tassert2 +${tool}_load tassert3 +${tool}_load tassert4 + +# tassert5 is not buildable under Linux. It is a C program linked with +# a C++ library, and there are dependencies on the default new and +# delete operators which are not satisfied. + +if { [string match "cl*" $::hosttest_data(CC)] } { + ${tool}_load tassert5 +} else { + unsupported "using the infrastructure from C code" +} + +${tool}_load tassert6 +${tool}_load tassert7 + +# ---------------------------------------------------------------------------- +# tassert8 is a bit more complicated. It involves an assertion which +# is not caught in any way by the application code. Therefore the +# output of the program has to be analysed to make sure it is +# reasonable. There is also going to be a dump file that needs +# to be analysed and cleaned up. + +proc tassert8_filter { name result output } { + + set all_ok 1 + + if { $result == 0 } { + fail "testcase $name should have a non-zero exit code" + set all_ok 0 + } + + # Convert the output to a list of lines. + set lines [split $output "\n"] + + # The first line of interest should contain the phrase + # "Assertion failure" and the string embedded in tassert8.cxx + while { 1 } { + if { [llength $lines] == 0 } { + set all_ok 0 + fail "No \"Assertion failure\" message detected in program output" + break + } + set line [lindex $lines 0] + set lines [lreplace $lines 0 0] + if { [regexp -nocase -- {^assertion failure.*it seemed like a good idea at the time$} $line] } { + break + } + } + + # The next line should indicate the file and the line number + if { [llength $lines] == 0 } { + set all_ok 0 + fail "No file name or line number information" + } else { + set line [lindex $lines 0] + set lines [lreplace $lines 0 0] + if { [regexp -nocase -- {^file .*tassert8.cxx.*line number [0-9]+$} $line] == 0} { + fail "Output did not contain the expected filename and linenumber" + } + } + # There may or may not be a line containing the function name. + # This should not be checked, it depends on compiler support + # for __PRETTY_FUNCTION__. The next line of interest is + # "Writing additional output to xxx", where xxx is a filename. + while { 1 } { + if { [llength $lines] == 0 } { + set all_ok 0 + fail "Output did not specify where the dump information was stored" + break + } else { + set line [lindex $lines 0] + set lines [lreplace $lines 0 0] + set dummy "" + set match "" + if { [regexp -- {^Writing additional output to (.*)$} $line dummy match] } { + tassert8_process_dump $match all_ok + break + } + } + } + + if { $all_ok } { + pass "Assertions generate sensible output" + } + + return 0 +} + +proc tassert8_process_dump { filename all_ok_arg } { + + upvar $all_ok_arg all_ok + set realname [hosttest_translate_existing_filename $filename] + if { $realname == "" } { + set all_ok 0 + fail "Unable to find assertion dump file $filename" + return + } + set lines {} + set status [ catch { + set fd [open $realname r] + set data [read $fd] + close $fd + set lines [split $data "\n"] + if { [llength $lines] == 0 } { + set all_ok 0 + fail "The assertion dump file $realname contains no data" + } + } message ] + if { $status != 0 } { + set all_ok 0 + fail "Unable to open assertion output file $realname, $message" + } + set status [ catch { file delete $realname } message ] + if { $status != 0 } { + warning "Unable to delete assertion dump file $realname, $message" 0 + } + if { [llength $lines] == 0 } { + return + } + + # We have some data to process. The information should include + # the following: + # 1) a line Assertion failure msg + # 2) a line with the filename and the linenumber + # 3) optionally a line with the function name. This depends on + # compiler support. + # 4) information from callback1 + # 5) information from callback2 + # + # The relative order of (4) and (5) is not defined. + while { 1 } { + if { [llength $lines] == 0 } { + set all_ok 0 + fail "No \"Assertion failure\" message detected in output file" + break + } + set line [lindex $lines 0] + set lines [lreplace $lines 0 0] + if { [regexp -nocase -- {^assertion failure.*it seemed like a good idea at the time$} $line] } { + break + } + } + + if { [llength $lines] == 0 } { + set all_ok 0 + fail "No file name or line number information" + } else { + set line [lindex $lines 0] + set lines [lreplace $lines 0 0] + if { [regexp -nocase -- {^file .*tassert8.cxx.*line number [0-9]+$} $line] == 0} { + set all_ok 0 + fail "Output did not contain the expected filename and linenumber" + } + } + + set seen_callback1 0 + set seen_callback2 0 + while { [llength $lines] > 0 } { + + set line [lindex $lines 0] + set lines [lreplace $lines 0 0] + + if { [regexp -nocase -- {^\# \{\{\{.*callback1.*$} $line] } { + if { $seen_callback1 != 0 } { + set all_ok 0 + fail "Output contains multiple occurrences of callback1" + continue + } + set seen_callback1 1 + + while { [llength $lines] > 0 } { + set line [lindex $lines 0] + set lines [lreplace $lines 0 0] + + if { [regexp -nocase -- {^\# \}\}\}.*$} $line] } { + break + } + + # callback1 should not generate any output so only blank lines + # are acceptable + if { [regexp -nocase -- {^ *$} $line] != 1} { + set all_ok 0 + fail "Unexpected data in callback1 output: $line" + # Do not repeat this failure message. This break will + # do near enough the right thing. + break + } + } + + } elseif { [regexp -nocase -- {^\# \{\{\{.*callback2.*$} $line] } { + if { $seen_callback2 != 0 } { + set all_ok 0 + fail "Output contains multiple occurrences of callback2" + } + set seen_callback2 1 + + while { [llength $lines] > 0 } { + set line [lindex $lines 0] + set lines [lreplace $lines 0 0] + + if { [regexp -nocase -- {^\# \}\}\}.*$} $line] } { + break + } + + # callback2 is allowed to generate blank lines and + # fixed lines. + if { [regexp -nocase -- {^ *$} $line] == 1 } { + continue + } + if { $line == "callback2 output" } { + continue + } + set all_ok 0 + fail "Unexpected data in callback2 output: $line" + } + + } + } + if { ($seen_callback1 == 0) || ($seen_callback2 == 0) } { + set all_ok 0 + fail "Output did not contain all the callback information" + } +} + +hosttest_run_test_with_filter tassert8 tassert8_filter {} {} {} cyginfra {} + +# ---------------------------------------------------------------------------- +# Strictly speaking this is not an assertion test. However there are some +# support routines in hosttest.exp which are tried closely to the +# implementation of the assertion code, and it is worthwhile checking +# these. The tassert8 testcase can be reused for this. + +proc tassert9_filter { name result output } { + + if { [hosttest_assert_check $result $output] == 0 } { + fail "testcase did not generate a recognised assertion" + return + } + + set output [hosttest_assert_read_dump $output] + if { $output == "" } { + fail "testcase did not generate a recognised assertion dump" + return + } + + set all_ok 1 + + set callback1_output [hosttest_assert_extract_callback $output "callback1"] + set callback2_output [hosttest_assert_extract_callback $output "callback2"] + + # Callback1 output should be empty, all blank lines should have been filtered + # out. + if { $callback1_output != "" } { + set all_ok 0 + fail "callback1 output should be empty" + } + set lines [split $callback2_output "\n"] + if { [llength $lines] == 0 } { + set all_ok 0 + fail "callback2 should have produced some output" + } elseif { [llength $lines] < 10} { + set all_ok 0 + fail "callback2 is supposted to have at least ten lines of output" + } else { + # There should be ten lines of output, possibly followed by + # some blanks. + for { set i 0 } { $i < 10 } { incr i } { + set line [lindex $lines 0] + set lines [lreplace $lines 0 0] + if { $line != "callback2 output" } { + set all_ok 0 + fail "incorrect output from callback2" + break + } + } + + while { [llength $lines] > 0 } { + set line [lindex $lines 0] + set lines [lreplace $lines 0 0] + if { [regexp -- {^ *$} $line] != 1 } { + set all_ok 0 + fail "callback2 output contains unexpected data" + break + } + } + } + + if { $all_ok } { + pass "assertion output and dump file format match test harness expectations" + } + return 0 +} + +hosttest_run_test_with_filter tassert9 tassert9_filter tassert8.cxx {} {} cyginfra {} + diff --git a/host/infra/testsuite/cyginfra/regress.exp b/host/infra/testsuite/cyginfra/regress.exp new file mode 100644 --- /dev/null +++ b/host/infra/testsuite/cyginfra/regress.exp @@ -0,0 +1,40 @@ +#=============================================================================== +# +# regress.exp +# +# Regression test cases +# +#=============================================================================== +######COPYRIGHTBEGIN#### +# +# ---------------------------------------------------------------------------- +# Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +# +# This file is part of the eCos host tools. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# ---------------------------------------------------------------------------- +# +######COPYRIGHTEND#### +#=============================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): bartv +# Contributors: bartv +# Date: 1998-12-23 +# +#####DESCRIPTIONEND#### +#=============================================================================== diff --git a/host/infra/testsuite/cyginfra/tassert1.cxx b/host/infra/testsuite/cyginfra/tassert1.cxx new file mode 100644 --- /dev/null +++ b/host/infra/testsuite/cyginfra/tassert1.cxx @@ -0,0 +1,197 @@ +//========================================================================== +// +// tassert1.cxx +// +// Assertion test case +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contributors: bartv +// Date: 1998-11-27 +// Purpose: +// Description: By default all assertions should be disabled, but +// they should compile just fine. This module uses all +// assertions except CYGFAIL. As a fringe benefit, all +// of the macros get checked for correct argument usage. +// +//####DESCRIPTIONEND#### +//========================================================================== + + +#include +#include +#include + +#ifdef CYGDBG_USE_ASSERTS +# error Assertions should not be enabled by default. +#endif + +static const char message[] = "This should never be seen."; + +class dummy { + private: + int random; + public: + dummy() { + random = rand(); + } + ~dummy() { + random = 0; + } + void assertions(); + static void extern_assertions(dummy*); + bool check_this(cyg_assert_class_zeal) const; +}; + +int main(int argc, char** argv) +{ + dummy object; + + CYG_ASSERT( true, message); + CYG_ASSERT( false, message); + CYG_ASSERTC(true); + CYG_ASSERTC(false); + + CYG_FAIL(message); + + CYG_CHECK_DATA_PTR( &argc, message); + CYG_CHECK_DATA_PTR( 0, message); + CYG_CHECK_FUNC_PTR( &main, message); + CYG_CHECK_FUNC_PTR( 0, message); + CYG_CHECK_DATA_PTRC(&argc); + CYG_CHECK_DATA_PTRC(0); + CYG_CHECK_FUNC_PTRC(&main); + CYG_CHECK_FUNC_PTRC(0); + + CYG_ASSERT_CLASS( &object, message); + CYG_ASSERT_CLASSC( &object); + CYG_ASSERT_CLASSO( object, message); + CYG_ASSERT_CLASSOC( object); + CYG_ASSERTCLASS( &object, message); + CYG_ASSERTCLASSO( object, message); + + CYG_PRECONDITION(true, message); + CYG_PRECONDITION(false, message); + CYG_PRECONDITIONC(true); + CYG_PRECONDITIONC(false); + CYG_PRECONDITION_CLASS(&object, message); + CYG_PRECONDITION_CLASSC(&object); + CYG_PRECONDITION_CLASSO(object, message); + CYG_PRECONDITION_CLASSOC(object); + + CYG_POSTCONDITION(true, message); + CYG_POSTCONDITION(false, message); + CYG_POSTCONDITIONC(true); + CYG_POSTCONDITIONC(false); + CYG_POSTCONDITION_CLASS(&object, message); + CYG_POSTCONDITION_CLASSC(&object); + CYG_POSTCONDITION_CLASSO(object, message); + CYG_POSTCONDITION_CLASSOC(object); + + CYG_LOOP_INVARIANT(true, message); + CYG_LOOP_INVARIANT(false, message); + CYG_LOOP_INVARIANTC(true); + CYG_LOOP_INVARIANTC(false); + CYG_LOOP_INVARIANT_CLASS(&object, message); + CYG_LOOP_INVARIANT_CLASSC(&object); + CYG_LOOP_INVARIANT_CLASSO(object, message); + CYG_LOOP_INVARIANT_CLASSOC(object); + + CYG_INVARIANT(true, message); + CYG_INVARIANT(false, message); + CYG_INVARIANTC(true); + CYG_INVARIANTC(false); + + dummy::extern_assertions( &object); + dummy::extern_assertions( 0); + object.assertions( ); + + CYG_TEST_PASS_FINISH("disabled assertions do nothing"); + return 0; +} + +// A utility routine which performs assertions on this. +void +dummy::assertions() +{ + CYG_INVARIANT_THIS(dummy, message); + CYG_INVARIANT_THISC(dummy); + + CYG_ASSERT_THIS(message); + CYG_ASSERT_THISC(); + CYG_PRECONDITION_THIS(message); + CYG_PRECONDITION_THISC(); + CYG_POSTCONDITION_THIS(message); + CYG_POSTCONDITION_THISC(); + CYG_LOOP_INVARIANT_THIS(message); + CYG_LOOP_INVARIANT_THISC(); +} + +// Another utility which gets passed an object pointer. +// This is useful for the ZERO_OR_CLASS() variants. +void +dummy::extern_assertions(dummy* obj) +{ + dummy obj2; + CYG_INVARIANT_CLASSO(dummy, obj2, message); + CYG_INVARIANT_CLASSOC(dummy, obj2); + CYG_INVARIANT_CLASS(dummy, obj, message); + CYG_INVARIANT_CLASSC(dummy, obj); + CYG_ASSERT_ZERO_OR_CLASS(obj, message); + CYG_ASSERT_ZERO_OR_CLASSC(obj); + CYG_PRECONDITION_ZERO_OR_CLASS(obj, message); + CYG_PRECONDITION_ZERO_OR_CLASSC(obj); + CYG_POSTCONDITION_ZERO_OR_CLASS(obj, message); + CYG_POSTCONDITION_ZERO_OR_CLASSC(obj); + CYG_LOOP_INVARIANT_ZERO_OR_CLASS(obj, message); + CYG_LOOP_INVARIANT_ZERO_OR_CLASSC(obj); +} + +bool +dummy::check_this(cyg_assert_class_zeal zeal) const +{ + // The default zeal should be cyg_quick. + switch(zeal) { + case cyg_quick: + return true; + + case cyg_system_test: + case cyg_extreme: + case cyg_thorough: + case cyg_trivial: + case cyg_none: + CYG_TEST_FAIL_FINISH("incorrect default zeal passed to check_this() member function"); + + default: + CYG_TEST_FAIL_FINISH("invalid zeal passed to check_this() member function"); + } + return false; +} + diff --git a/host/infra/testsuite/cyginfra/tassert2.cxx b/host/infra/testsuite/cyginfra/tassert2.cxx new file mode 100644 --- /dev/null +++ b/host/infra/testsuite/cyginfra/tassert2.cxx @@ -0,0 +1,195 @@ +//========================================================================== +// +// tassert2.cxx +// +// Assertion test case +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contributors: bartv +// Date: 1998-12-21 +// Purpose: +// Description: All assertions are enabled but should pass. +// +//####DESCRIPTIONEND#### +//========================================================================== + +#define CYGDBG_USE_ASSERTS +#define CYGDBG_INFRA_DEBUG_PRECONDITIONS +#define CYGDBG_INFRA_DEBUG_POSTCONDITIONS +#define CYGDBG_INFRA_DEBUG_LOOP_INVARIANTS +#define CYGDBG_INFRA_DEBUG_INVARIANTS + +#include +#include +#include + + +static const char message[] = "This should never be seen."; + +class dummy { + private: + int random; + public: + dummy() { + random = rand(); + } + ~dummy() { + random = 0; + } + void assertions(); + void zero_assertions(); + static void extern_assertions(dummy*); + static void zero_assertions(dummy*); + bool check_this(cyg_assert_class_zeal) const; +}; + +int main(int argc, char** argv) +{ + dummy object; + + CYG_ASSERT( true, message); + CYG_ASSERTC(true); + + CYG_CHECK_DATA_PTR( &argc, message); + CYG_CHECK_FUNC_PTR( &main, message); + CYG_CHECK_DATA_PTRC(&argc); + CYG_CHECK_FUNC_PTRC(&main); + + CYG_ASSERT_CLASS( &object, message); + CYG_ASSERT_CLASSC( &object); + CYG_ASSERT_CLASSO( object, message); + CYG_ASSERT_CLASSOC( object); + CYG_ASSERTCLASS( &object, message); + CYG_ASSERTCLASSO( object, message); + + CYG_PRECONDITION(true, message); + CYG_PRECONDITIONC(true); + CYG_PRECONDITION_CLASS(&object, message); + CYG_PRECONDITION_CLASSC(&object); + CYG_PRECONDITION_CLASSO(object, message); + CYG_PRECONDITION_CLASSOC(object); + + CYG_POSTCONDITION(true, message); + CYG_POSTCONDITIONC(true); + CYG_POSTCONDITION_CLASS(&object, message); + CYG_POSTCONDITION_CLASSC(&object); + CYG_POSTCONDITION_CLASSO(object, message); + CYG_POSTCONDITION_CLASSOC(object); + + CYG_LOOP_INVARIANT(true, message); + CYG_LOOP_INVARIANTC(true); + CYG_LOOP_INVARIANT_CLASS(&object, message); + CYG_LOOP_INVARIANT_CLASSC(&object); + CYG_LOOP_INVARIANT_CLASSO(object, message); + CYG_LOOP_INVARIANT_CLASSOC(object); + + CYG_INVARIANT(true, message); + CYG_INVARIANTC(true); + + dummy::extern_assertions( &object); + dummy::zero_assertions( &object); + object.assertions( ); + + CYG_TEST_PASS_FINISH("true assertions do nothing"); + return 0; +} + +// A utility routine which performs assertions on this. +void +dummy::assertions() +{ + CYG_INVARIANT_THIS(dummy, message); + CYG_INVARIANT_THISC(dummy); + + CYG_ASSERT_THIS(message); + CYG_ASSERT_THISC(); + CYG_PRECONDITION_THIS(message); + CYG_PRECONDITION_THISC(); + CYG_POSTCONDITION_THIS(message); + CYG_POSTCONDITION_THISC(); + CYG_LOOP_INVARIANT_THIS(message); + CYG_LOOP_INVARIANT_THISC(); +} + +// Another utility which gets passed an object pointer. +// This is useful for the ZERO_OR_CLASS() variants. +void +dummy::extern_assertions(dummy* obj) +{ + dummy obj2; + CYG_INVARIANT_CLASSO(dummy, obj2, message); + CYG_INVARIANT_CLASSOC(dummy, obj2); + CYG_INVARIANT_CLASS(dummy, obj, message); + CYG_INVARIANT_CLASSC(dummy, obj); + + CYG_ASSERT_ZERO_OR_CLASS(obj, message); + CYG_ASSERT_ZERO_OR_CLASSC(obj); + CYG_PRECONDITION_ZERO_OR_CLASS(obj, message); + CYG_PRECONDITION_ZERO_OR_CLASSC(obj); + CYG_POSTCONDITION_ZERO_OR_CLASS(obj, message); + CYG_POSTCONDITION_ZERO_OR_CLASSC(obj); + CYG_LOOP_INVARIANT_ZERO_OR_CLASS(obj, message); + CYG_LOOP_INVARIANT_ZERO_OR_CLASSC(obj); +} + +void +dummy::zero_assertions(dummy* obj) +{ + CYG_ASSERT_ZERO_OR_CLASS(obj, message); + CYG_ASSERT_ZERO_OR_CLASSC(obj); + CYG_PRECONDITION_ZERO_OR_CLASS(obj, message); + CYG_PRECONDITION_ZERO_OR_CLASSC(obj); + CYG_POSTCONDITION_ZERO_OR_CLASS(obj, message); + CYG_POSTCONDITION_ZERO_OR_CLASSC(obj); + CYG_LOOP_INVARIANT_ZERO_OR_CLASS(obj, message); + CYG_LOOP_INVARIANT_ZERO_OR_CLASSC(obj); +} + +bool +dummy::check_this(cyg_assert_class_zeal zeal) const +{ + // The default zeal should be cyg_quick. + switch(zeal) { + case cyg_quick: + return true; + + case cyg_system_test: + case cyg_extreme: + case cyg_thorough: + case cyg_trivial: + case cyg_none: + CYG_TEST_FAIL_FINISH("incorrect default zeal passed to check_this() member function"); + + default: + CYG_TEST_FAIL_FINISH("invalid zeal passed to check_this() member function"); + } + return false; +} diff --git a/host/infra/testsuite/cyginfra/tassert3.cxx b/host/infra/testsuite/cyginfra/tassert3.cxx new file mode 100644 --- /dev/null +++ b/host/infra/testsuite/cyginfra/tassert3.cxx @@ -0,0 +1,345 @@ +//========================================================================== +// +// tassert3.cxx +// +// Assertion test case +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contributors: bartv +// Date: 1998-12-21 +// Purpose: +// Description: Check the host extensions. +// +//####DESCRIPTIONEND#### +//========================================================================== + +// ------------------------------------------------------------------------- +// The host-side assertion support has three extensions to the generic +// assertion support: +// +// 1) cyg_assert_install_failure_handler() +// Provide an alternative handler that gets invoked when an +// assertion fails. +// +// 2) cyg_assert_install_failure_callback() +// Provide an additional callback that should get invoked when an +// assertion triggers to provide additional information. +// +// 3) cyg_assert_failure_invoke_callbacks() +// Used by (1) to call the functions installed via (2). +// +// The tests make use of setjmp()/longjmp() buffer to avoid having to +// do lots of output parsing in the DejaGnu driver. + +#define CYG_DECLARE_HOST_ASSERTION_SUPPORT +#define CYGDBG_USE_ASSERTS +#define CYGDBG_INFRA_DEBUG_PRECONDITIONS +#define CYGDBG_INFRA_DEBUG_POSTCONDITIONS +#define CYGDBG_INFRA_DEBUG_LOOP_INVARIANTS +#define CYGDBG_INFRA_DEBUG_INVARIANTS + +#include +#include +#include +#include +#include + +// Forward declarations of some integers to allow the line number to be +// checked. +extern cyg_uint32 main_start, main_end; + +// This is used to "recover" from an assertion failure +static jmp_buf setjmp_buffer; + +// A constant string useful for comparisons. +static const char message[] = "fail"; + +// Some state information to make sure that the world is in the expected +// state +bool expecting_failure1 = false; +bool expecting_failure2 = false; +bool expecting_failure3 = false; + +// ------------------------------------------------------------------------- +// The first assertion handler. This is used to check that the arguments +// make sense. + +extern "C" +bool +failure_handler1(const char* fn, const char* file, cyg_uint32 line, const char* msg) +{ + if (!expecting_failure1) { + CYG_TEST_FAIL("assertion failure handler1 invoked unexpectedly"); + } + expecting_failure1 = false; + // The function should be 0 or contain main + if (0 != fn) { + if (0 == strstr(fn, "main")) { + CYG_TEST_FAIL("invalid function name passed to assertion failure handler"); + } + } + // The file name should always be valid and contain tassert3.cxx. + // It may contain path information as well. + if ( (0 == file) || (0 == strstr(file, "tassert3.cxx"))) { + CYG_TEST_FAIL("invalid file name passed to assertion failure handler"); + } + // The line number can be validated against some globals. + if ((line <= main_start) || (line >= main_end)) { + CYG_TEST_FAIL("invalid line number passed to assertion failure handler"); + } + // The message passed is known. + if (0 != strcmp(msg, message)) { + CYG_TEST_FAIL("invalid message passed to assertion failure handler"); + } + CYG_TEST_PASS("application-specific assertion failure handler"); + + // Everything OK, back to main() + longjmp(setjmp_buffer, 1); + CYG_TEST_FAIL_FINISH("longjmp() is not functional"); + return false; +} + +// ------------------------------------------------------------------------- +// A second assertion handler. This is used to make sure that assertion +// failure handlers can be overwritten. + +extern "C" +bool +failure_handler2(const char* fn, const char* file, cyg_uint32 line, const char* msg) +{ + if (!expecting_failure2) { + CYG_TEST_FAIL("assertion failure handler2 invoked incorrectly"); + } + expecting_failure2 = false; + CYG_TEST_PASS("assertion failure handlers can be replaced"); + longjmp(setjmp_buffer, 1); + CYG_TEST_FAIL_FINISH("longjmp() is not functional"); + return false; +} +// ------------------------------------------------------------------------- +// The third assertion handler. This time a couple of output callbacks are +// installed and the main failure handler has to invoke the output callbacks. +// A number of statics are used to make sure everything works ok. + +static const char callback1_title[] = "callback1_header"; +static const char callback2_title[] = "callback2_header"; +static const char callback2_data[] = "callback2 data\n"; +static bool seen_callback1_title = false; +static bool seen_callback2_title = false; +static bool callback1_done = false; +static bool callback2_done = false; +static int number_of_headers = 0; +static bool callback1_invoked = false; +static bool callback2_invoked = false; +static int number_of_lines_seen = 0; +const int callback2_lines = 16; +static int callback2_lines_seen = 0; +static int number_of_trailers = 0; + +extern "C" +void +callback1(void (*outputfn)(const char*)) +{ + if (callback1_invoked) { + CYG_TEST_FAIL("callback1 invoked multiple times"); + } + callback1_invoked = true; + + // This callback does nothing. +} + +extern "C" +void +callback2(void (*outputfn)(const char*)) +{ + if (callback2_invoked) { + CYG_TEST_FAIL("callback2 invoked multiple times"); + } + callback2_invoked = true; + for (int i = 0; i < callback2_lines; i++) { + (*outputfn)(callback2_data); + } +} + +// handle_callback_header() should be invoked at least twice, +// once with callback1_header and once with callback2_header +extern "C" +void +handle_callback_header(const char* name) +{ + number_of_headers++; + if (0 == strcmp(name, callback1_title)) { + if (seen_callback1_title) { + CYG_TEST_FAIL("callback1 title seen multiple times"); + } else { + seen_callback1_title = true; + } + } + if (0 == strcmp(name, callback2_title)) { + if (seen_callback2_title) { + CYG_TEST_FAIL("callback2 title seen multiple times"); + } else { + seen_callback2_title = true; + } + } +} + +// The body output function should be invoked zero times for +// callback1 and a fixed number of times for callback2. +extern "C" +void +handle_callback_body(const char* data) +{ + number_of_lines_seen++; + + if (seen_callback1_title && !callback1_done) { + CYG_TEST_FAIL("callback1 should not perform any output"); + } + if (seen_callback2_title && !callback2_done) { + callback2_lines_seen++; + if (0 != strcmp(data, callback2_data)) { + CYG_TEST_FAIL("callback2 has generated incorrect data"); + } + } +} + +// The trailer output function should be invoked at least twice, once +// for each callback. +extern "C" +void +handle_callback_trailer(void) +{ + if (0 == number_of_headers) { + CYG_TEST_FAIL("callback trailer seen before header"); + } + number_of_trailers++; + if (seen_callback1_title && !callback1_done) { + callback1_done = true; + } + if (seen_callback2_title && !callback2_done) { + callback2_done = true; + } +} + +// This is the failure handler. It causes the various callbacks to run, then +// checks the resulting values of the statics. +extern "C" +bool +failure_handler3(const char* fn, const char* file, cyg_uint32 line, const char* msg) +{ + if (!expecting_failure3) { + CYG_TEST_FAIL("assertion failure handler3 invoked incorrectly"); + } + expecting_failure3 = false; + + cyg_assert_failure_invoke_callbacks( + &handle_callback_header, + &handle_callback_body, + &handle_callback_trailer); + + bool all_ok = true; + if (!seen_callback1_title) { + CYG_TEST_FAIL("callback1's title not seen"); + all_ok = false; + } + if (!seen_callback2_title) { + CYG_TEST_FAIL("callback2's title not seen"); + all_ok = false; + } + if (number_of_headers != number_of_trailers) { + CYG_TEST_FAIL("headers and trailers do not match up"); + all_ok = false; + } + if (!callback1_done) { + CYG_TEST_FAIL("callback1 did not finish"); + all_ok = false; + } + if (!callback2_done) { + CYG_TEST_FAIL("callback2 did not finish"); + all_ok = false; + } + if (number_of_lines_seen < callback2_lines) { + CYG_TEST_FAIL("total number of output lines is less than expected"); + all_ok = false; + } + if (callback2_lines_seen != callback2_lines) { + CYG_TEST_FAIL("callback2 generated the wrong number of lines"); + all_ok = false; + } + + if (all_ok) { + CYG_TEST_PASS("assertion callbacks"); + } + + longjmp(setjmp_buffer, 1); + CYG_TEST_FAIL_FINISH("longjmp() is not functional"); + return false; +} + +// ---------------------------------------------------------------------------- +// main(). Perform the various assertion tests in order. + +cyg_uint32 main_start = (cyg_uint32) __LINE__; +int +main(int argc, char** argv) +{ + expecting_failure1 = true; + // First check, a very basic assertion invocation. + if (setjmp(setjmp_buffer) == 0) { + cyg_assert_install_failure_handler(&failure_handler1); + CYG_FAIL(message); + CYG_TEST_FAIL("assertion did not trigger"); + } + expecting_failure1 = false; + expecting_failure2 = true; + + // Now try installing a different assertion handler. + if (setjmp(setjmp_buffer) == 0) { + cyg_assert_install_failure_handler(&failure_handler2); + CYG_FAIL(message); + CYG_TEST_FAIL("assertion did not trigger"); + } + expecting_failure2 = false; + expecting_failure3 = true; + + if (setjmp(setjmp_buffer) == 0) { + cyg_assert_install_failure_callback(callback1_title, &callback1); + cyg_assert_install_failure_callback(callback2_title, &callback2); + cyg_assert_install_failure_handler(&failure_handler3); + CYG_FAIL(message); + CYG_TEST_FAIL("assertion did not trigger"); + } + expecting_failure3 = false; + + return 0; +} +cyg_uint32 main_end = (cyg_uint32) __LINE__; + diff --git a/host/infra/testsuite/cyginfra/tassert4.c b/host/infra/testsuite/cyginfra/tassert4.c new file mode 100644 --- /dev/null +++ b/host/infra/testsuite/cyginfra/tassert4.c @@ -0,0 +1,220 @@ +/* ========================================================================== + * + * tassert4.c + * + * Assertion test case + * + *========================================================================== + *####COPYRIGHTBEGIN#### + * + * ---------------------------------------------------------------------------- + * Copyright (C) 1998, 1999, 2000 Red Hat, Inc. + * + * This file is part of the eCos host tools. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * ---------------------------------------------------------------------------- + * + *####COPYRIGHTEND#### + *========================================================================== + *#####DESCRIPTIONBEGIN#### + * + * Author(s): bartv + * Contributors: bartv + * Date: 1998-11-27 + * Purpose: + * Description: A C equivalent of tassert1.cxx + * + *####DESCRIPTIONEND#### + *========================================================================== + */ + +#include +#include +#include + +#ifdef CYGDBG_USE_ASSERTS +# error Assertions should not be enabled by default. +#endif + +static const char message[] = "This should never be seen."; + +int main(int argc, char** argv) +{ + CYG_ASSERT( true, message); + CYG_ASSERT( false, message); + CYG_ASSERTC(true); + CYG_ASSERTC(false); + + CYG_FAIL(message); + + CYG_CHECK_DATA_PTR( &argc, message); + CYG_CHECK_DATA_PTR( 0, message); + CYG_CHECK_FUNC_PTR( &main, message); + CYG_CHECK_FUNC_PTR( 0, message); + CYG_CHECK_DATA_PTRC(&argc); + CYG_CHECK_DATA_PTRC(0); + CYG_CHECK_FUNC_PTRC(&main); + CYG_CHECK_FUNC_PTRC(0); + + CYG_PRECONDITION(true, message); + CYG_PRECONDITION(false, message); + CYG_PRECONDITIONC(true); + CYG_PRECONDITIONC(false); + + CYG_POSTCONDITION(true, message); + CYG_POSTCONDITION(false, message); + CYG_POSTCONDITIONC(true); + CYG_POSTCONDITIONC(false); + + CYG_LOOP_INVARIANT(true, message); + CYG_LOOP_INVARIANT(false, message); + CYG_LOOP_INVARIANTC(true); + CYG_LOOP_INVARIANTC(false); + + CYG_INVARIANT(true, message); + CYG_INVARIANT(false, message); + CYG_INVARIANTC(true); + CYG_INVARIANTC(false); + + CYG_TEST_PASS_FINISH("disabled assertions in C code do nothing"); + return 0; +} + +#ifdef CYG_ASSERT_CLASS +# error CYG_ASSERT_CLASS macro should not be defined in C code +#endif +#ifdef CYG_ASSERT_CLASSC +# error CYG_ASSERT_CLASSC macro should not be defined in C code +#endif +#ifdef CYG_ASSERT_CLASSO +# error CYG_ASSERT_CLASSO macro should not be defined in C code +#endif +#ifdef CYG_ASSERT_CLASSOC +# error CYG_ASSERT_CLASSOC macro should not be defined in C code +#endif +#ifdef CYG_ASSERT_ZERO_OR_CLASS +# error CYG_ASSERT_ZERO_OR_CLASS macro should not be defined in C code +#endif +#ifdef CYG_ASSERT_ZERO_OR_CLASSC +# error CYG_ASSERT_ZERO_OR_CLASSC macro should not be defined in C code +#endif +#ifdef CYG_ASSERT_THIS +# error CYG_ASSERT_THIS macro should not be defined in C code +#endif +#ifdef CYG_ASSERT_THISC +# error CYG_ASSERT_THISC macro should not be defined in C code +#endif +#ifdef CYGDBG_DEFINE_CHECK_THIS +# error CYGDBG_DEFINE_CHECK_THIS macro should not be defined in C code +#endif + +#ifdef CYG_PRECONDITION_CLASS +# error CYG_PRECONDITION_CLASS macro should not be defined in C code +#endif +#ifdef CYG_PRECONDITION_CLASSC +# error CYG_PRECONDITION_CLASSC macro should not be defined in C code +#endif +#ifdef CYG_PRECONDITION_CLASSO +# error CYG_PRECONDITION_CLASSO macro should not be defined in C code +#endif +#ifdef CYG_PRECONDITION_CLASSOC +# error CYG_PRECONDITION_CLASSOC macro should not be defined in C code +#endif +#ifdef CYG_PRECONDITION_ZERO_OR_CLASS +# error CYG_PRECONDITION_ZERO_OR_CLASS macro should not be defined in C code +#endif +#ifdef CYG_PRECONDITION_ZERO_OR_CLASSC +# error CYG_PRECONDITION_ZERO_OR_CLASSC macro should not be defined in C code +#endif +#ifdef CYG_PRECONDITION_THIS +# error CYG_PRECONDITION_THIS macro should not be defined in C code +#endif +#ifdef CYG_PRECONDITION_THISC +# error CYG_PRECONDITION_THISC macro should not be defined in C code +#endif + +#ifdef CYG_POSTCONDITION_CLASS +# error CYG_POSTCONDITION_CLASS macro should not be defined in C code +#endif +#ifdef CYG_POSTCONDITION_CLASSC +# error CYG_POSTCONDITION_CLASSC macro should not be defined in C code +#endif +#ifdef CYG_POSTCONDITION_CLASSO +# error CYG_POSTCONDITION_CLASSO macro should not be defined in C code +#endif +#ifdef CYG_POSTCONDITION_CLASSOC +# error CYG_POSTCONDITION_CLASSOC macro should not be defined in C code +#endif +#ifdef CYG_POSTCONDITION_ZERO_OR_CLASS +# error CYG_POSTCONDITION_ZERO_OR_CLASS macro should not be defined in C code +#endif +#ifdef CYG_POSTCONDITION_ZERO_OR_CLASSC +# error CYG_POSTCONDITION_ZERO_OR_CLASSC macro should not be defined in C code +#endif +#ifdef CYG_POSTCONDITION_THIS +# error CYG_POSTCONDITION_THIS macro should not be defined in C code +#endif +#ifdef CYG_POSTCONDITION_THISC +# error CYG_POSTCONDITION_THISC macro should not be defined in C code +#endif + +#ifdef CYG_LOOP_INVARIANT_CLASS +# error CYG_LOOP_INVARIANT_CLASS macro should not be defined in C code +#endif +#ifdef CYG_LOOP_INVARIANT_CLASSC +# error CYG_LOOP_INVARIANT_CLASSC macro should not be defined in C code +#endif +#ifdef CYG_LOOP_INVARIANT_CLASSO +# error CYG_LOOP_INVARIANT_CLASSO macro should not be defined in C code +#endif +#ifdef CYG_LOOP_INVARIANT_CLASSOC +# error CYG_LOOP_INVARIANT_CLASSOC macro should not be defined in C code +#endif +#ifdef CYG_LOOP_INVARIANT_ZERO_OR_CLASS +# error CYG_LOOP_INVARIANT_ZERO_OR_CLASS macro should not be defined in C code +#endif +#ifdef CYG_LOOP_INVARIANT_ZERO_OR_CLASSC +# error CYG_LOOP_INVARIANT_ZERO_OR_CLASSC macro should not be defined in C code +#endif +#ifdef CYG_LOOP_INVARIANT_THIS +# error CYG_LOOP_INVARIANT_THIS macro should not be defined in C code +#endif +#ifdef CYG_LOOP_INVARIANT_THISC +# error CYG_LOOP_INVARIANT_THISC macro should not be defined in C code +#endif + +#ifdef CYG_INVARIANT_CLASS +# error CYG_INVARIANT_CLASS macro should not be defined in C code +#endif +#ifdef CYG_INVARIANT_CLASSC +# error CYG_INVARIANT_CLASSC macro should not be defined in C code +#endif +#ifdef CYG_INVARIANT_CLASSO +# error CYG_INVARIANT_CLASSO macro should not be defined in C code +#endif +#ifdef CYG_INVARIANT_CLASSOC +# error CYG_INVARIANT_CLASSOC macro should not be defined in C code +#endif +#ifdef CYG_INVARIANT_THIS +# error CYG_INVARIANT_THIS macro should not be defined in C code +#endif +#ifdef CYG_INVARIANT_THISC +# error CYG_INVARIANT_THISC macro should not be defined in C code +#endif + + + diff --git a/host/infra/testsuite/cyginfra/tassert5.c b/host/infra/testsuite/cyginfra/tassert5.c new file mode 100644 --- /dev/null +++ b/host/infra/testsuite/cyginfra/tassert5.c @@ -0,0 +1,83 @@ +/* ========================================================================== + * + * tassert5.c + * + * Assertion test case + * + *========================================================================== + *####COPYRIGHTBEGIN#### + * + * ---------------------------------------------------------------------------- + * Copyright (C) 1998, 1999, 2000 Red Hat, Inc. + * + * This file is part of the eCos host tools. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * ---------------------------------------------------------------------------- + * + *####COPYRIGHTEND#### + *========================================================================== + *#####DESCRIPTIONBEGIN#### + * + * Author(s): bartv + * Contributors: bartv + * Date: 1998-11-27 + * Purpose: + * Description: A C equivalent of tassert2.cxx + * + *####DESCRIPTIONEND#### + *========================================================================== + */ + +#define CYGDBG_USE_ASSERTS +#define CYGDBG_INFRA_DEBUG_PRECONDITIONS +#define CYGDBG_INFRA_DEBUG_POSTCONDITIONS +#define CYGDBG_INFRA_DEBUG_LOOP_INVARIANTS +#define CYGDBG_INFRA_DEBUG_INVARIANTS + +#include +#include +#include + + +static const char message[] = "This should never be seen."; + +int main(int argc, char** argv) +{ + CYG_ASSERT( true, message); + CYG_ASSERTC(true); + + CYG_CHECK_DATA_PTR( &argc, message); + CYG_CHECK_FUNC_PTR( &main, message); + CYG_CHECK_DATA_PTRC(&argc); + CYG_CHECK_FUNC_PTRC(&main); + + CYG_PRECONDITION(true, message); + CYG_PRECONDITIONC(true); + + CYG_POSTCONDITION(true, message); + CYG_POSTCONDITIONC(true); + + CYG_LOOP_INVARIANT(true, message); + CYG_LOOP_INVARIANTC(true); + + CYG_INVARIANT(true, message); + CYG_INVARIANTC(true); + + CYG_TEST_PASS_FINISH("true assertions do nothing"); + return 0; +} + diff --git a/host/infra/testsuite/cyginfra/tassert6.cxx b/host/infra/testsuite/cyginfra/tassert6.cxx new file mode 100644 --- /dev/null +++ b/host/infra/testsuite/cyginfra/tassert6.cxx @@ -0,0 +1,501 @@ +//========================================================================== +// +// tassert6.cxx +// +// Assertion test case +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contributors: bartv +// Date: 1998-12-22 +// Purpose: +// Description: This routine checks that all the assertions can +// be triggered. +// +//####DESCRIPTIONEND#### +//========================================================================== + + +#define CYG_DECLARE_HOST_ASSERTION_SUPPORT +#define CYGDBG_USE_ASSERTS +#define CYGDBG_INFRA_DEBUG_PRECONDITIONS +#define CYGDBG_INFRA_DEBUG_POSTCONDITIONS +#define CYGDBG_INFRA_DEBUG_LOOP_INVARIANTS +#define CYGDBG_INFRA_DEBUG_INVARIANTS + +// Also redefine the zeal +#define CYG_ASSERT_CLASS_ZEAL (cyg_extreme) + +#include +#include +#include +#include +#include + + +// This is used to "recover" from an assertion failure +static jmp_buf setjmp_buffer; + +// The number of assertions that have triggered. +static int failed_assertions = 0; + +// The number of assertions that have been triggered. +static int counter = 0; + +static const char message[] = "beware of the leopard"; + +// A dummy class is needed for some of the assertions. +class dummy { + private: + int random; + public: + dummy() { + random = rand(); + } + ~dummy() { + random = 0; + } + void assertions(); + void invariant1(); + void invariant2(); + static void invariant3(dummy&); + static void invariant4(dummy&); + static void invariant5(dummy*); + static void invariant6(dummy*); + static void extern_assertions(dummy*); + bool check_this(cyg_assert_class_zeal) const; +}; + +bool +dummy::check_this(cyg_assert_class_zeal zeal) const +{ + // The default zeal should be cyg_quick. + switch(zeal) { + case cyg_extreme: + return false; + case cyg_system_test: + case cyg_thorough: + case cyg_quick: + case cyg_trivial: + case cyg_none: + CYG_TEST_FAIL_FINISH("incorrect default zeal passed to check_this() member function"); + break; + default: + CYG_TEST_FAIL_FINISH("invalid zeal passed to check_this() member function"); + break; + } + return false; +} + +void +dummy::invariant1(void) +{ + CYG_INVARIANT_THIS(dummy, message); + CYG_TEST_FAIL("CYG_INVARIANT_THIS() did not trigger"); +} + +void +dummy::invariant2(void) +{ + CYG_INVARIANT_THISC(dummy); + CYG_TEST_FAIL("CYG_INVARIANT_THISC() did not trigger"); +} + +void +dummy::invariant3(dummy& obj) +{ + CYG_INVARIANT_CLASSO(dummy, obj, message); + CYG_TEST_FAIL("CYG_INVARIANT_CLASSO() did not trigger"); +} + +void +dummy::invariant4(dummy& obj) +{ + CYG_INVARIANT_CLASSOC(dummy, obj); + CYG_TEST_FAIL("CYG_INVARIANT_CLASSOC() did not trigger"); +} + +void +dummy::invariant5(dummy* obj) +{ + CYG_INVARIANT_CLASS(dummy, obj, message); + CYG_TEST_FAIL("CYG_INVARIANT_CLASS() did not trigger"); +} + +void +dummy::invariant6(dummy* obj) +{ + CYG_INVARIANT_CLASSC(dummy, obj); + CYG_TEST_FAIL("CYG_INVARIANT_CLASSC() did not trigger"); +} + +void +dummy::assertions(void) +{ + switch(counter) { + + case 33: + CYG_ASSERT_THIS(message); + CYG_TEST_FAIL("CYG_ASSERT_THIS() did not trigger"); + break; + + case 34: + CYG_ASSERT_THISC(); + CYG_TEST_FAIL("CYG_ASSERT_THISC() did not trigger"); + break; + + case 35: + CYG_PRECONDITION_THIS(message); + CYG_TEST_FAIL("CYG_PRECONDITION_THIS() did not trigger"); + break; + + case 36: + CYG_PRECONDITION_THISC(); + CYG_TEST_FAIL("CYG_PRECONDITION_THISC() did not trigger"); + break; + + case 37: + CYG_POSTCONDITION_THIS(message); + CYG_TEST_FAIL("CYG_POSTCONDITION_THIS() did not trigger"); + break; + + case 38: + CYG_POSTCONDITION_THISC(); + CYG_TEST_FAIL("CYG_POSTCONDITION_THISC() did not trigger"); + break; + + case 39: + CYG_LOOP_INVARIANT_THIS(message); + CYG_TEST_FAIL("CYG_LOOP_INVARIANT_THIS() did not trigger"); + break; + + case 40: + CYG_LOOP_INVARIANT_THISC(); + CYG_TEST_FAIL("CYG_LOOP_INVARIANT_THISC() did not trigger"); + break; + + default: + CYG_TEST_FAIL("dummy::assertions() invoked for no reason"); + break; + } +} + +void +dummy::extern_assertions(dummy* obj) +{ + switch(counter) { + case 41: + CYG_ASSERT_ZERO_OR_CLASS(obj, message); + CYG_TEST_FAIL("CYG_ASSERT_ZERO_OR_CLASS() did not trigger"); + break; + + case 42: + CYG_ASSERT_ZERO_OR_CLASSC(obj); + CYG_TEST_FAIL("CYG_ASSERT_ZERO_OR_CLASSC() did not trigger"); + break; + + case 43: + CYG_PRECONDITION_ZERO_OR_CLASS(obj, message); + CYG_TEST_FAIL("CYG_PRECONDITION_ZERO_OR_CLASS() did not trigger"); + break; + + case 44: + CYG_PRECONDITION_ZERO_OR_CLASSC(obj); + CYG_TEST_FAIL("CYG_PRECONDITION_ZERO_OR_CLASSC() did not trigger"); + break; + + case 45: + CYG_POSTCONDITION_ZERO_OR_CLASS(obj, message); + CYG_TEST_FAIL("CYG_POSTCONDITION_ZERO_OR_CLASS() did not trigger"); + break; + + case 46: + CYG_POSTCONDITION_ZERO_OR_CLASSC(obj); + CYG_TEST_FAIL("CYG_POSTCONDITION_ZERO_OR_CLASSC() did not trigger"); + break; + + case 47: + CYG_LOOP_INVARIANT_ZERO_OR_CLASS(obj, message); + CYG_TEST_FAIL("CYG_LOOP_INVARIANT_ZERO_OR_CLASS() did not trigger"); + break; + + case 48: + CYG_LOOP_INVARIANT_ZERO_OR_CLASSC(obj); + CYG_TEST_FAIL("CYG_LOOP_INVARIANT_ZERO_OR_CLASSC() did not trigger"); + break; + + default: + CYG_TEST_FAIL("dummy::extern_assertions() invoked for no reason"); + break; + } + +} + +extern "C" +bool +failure_handler(const char* fn, const char* file, cyg_uint32 line, const char* msg) +{ + failed_assertions++; + counter++; + longjmp(setjmp_buffer, 1); + return true; +} + +int +main(int argc, char** argv) +{ + dummy object; + + cyg_assert_install_failure_handler(&failure_handler); + setjmp(setjmp_buffer); + + for ( bool done = false; !done; counter++ ) { + switch(counter) { + case 0: + CYG_ASSERT(false, message); + CYG_TEST_FAIL("CYG_ASSERT() did not trigger"); + break; + + case 1: + CYG_ASSERTC(false); + CYG_TEST_FAIL("CYG_ASSERTC() did not trigger"); + break; + + case 2: + CYG_FAIL(message); + CYG_TEST_FAIL("CYG_FAIL() did not trigger"); + break; + + case 3: + CYG_CHECK_DATA_PTR(0, message); + CYG_TEST_FAIL("CHECK_CHECK_DATA_PTR() did not trigger"); + break; + + case 4: + CYG_CHECK_DATA_PTRC(0); + CYG_TEST_FAIL("CHECK_CHECK_DATA_PTRC() did not trigger"); + break; + + case 5: + CYG_CHECK_FUNC_PTR(0, message); + CYG_TEST_FAIL("CHECK_CHECK_FUNC_PTR() did not trigger"); + break; + + case 6: + CYG_CHECK_DATA_PTRC(0); + CYG_TEST_FAIL("CHECK_CHECK_FUNC_PTRC() did not trigger"); + break; + + case 7: + CYG_ASSERT_CLASS(&object, message); + CYG_TEST_FAIL("CYG_ASSERT_CLASS() did not trigger"); + break; + + case 8: + CYG_ASSERT_CLASSC(&object); + CYG_TEST_FAIL("CYG_ASSERT_CLASSC() did not trigger"); + break; + + case 9: + CYG_ASSERT_CLASSO(object, message); + CYG_TEST_FAIL("CYG_ASSERT_CLASSO() did not trigger"); + break; + + case 10: + CYG_ASSERT_CLASSOC(object); + CYG_TEST_FAIL("CYG_ASSERT_CLASSOC() did not trigger"); + break; + + case 11: + CYG_PRECONDITION(false, message); + CYG_TEST_FAIL("CYG_PRECONDITION() did not trigger"); + break; + + case 12: + CYG_PRECONDITIONC(false); + CYG_TEST_FAIL("CYG_PRECONDITIONC() did not trigger"); + break; + + case 13: + CYG_PRECONDITION_CLASS(&object, message); + CYG_TEST_FAIL("CYG_PRECONDITION_CLASS() did not trigger"); + break; + + case 14: + CYG_PRECONDITION_CLASSC(&object); + CYG_TEST_FAIL("CYG_PRECONDITION_CLASSC() did not trigger"); + break; + + case 15: + CYG_PRECONDITION_CLASSO(object, message); + CYG_TEST_FAIL("CYG_PRECONDITION_CLASSO() did not trigger"); + break; + + case 16: + CYG_PRECONDITION_CLASSOC(object); + CYG_TEST_FAIL("CYG_PRECONDITION_CLASSOC() did not trigger"); + break; + + case 17: + CYG_POSTCONDITION(false, message); + CYG_TEST_FAIL("CYG_POSTCONDITION() did not trigger"); + break; + + case 18: + CYG_POSTCONDITIONC(false); + CYG_TEST_FAIL("CYG_POSTCONDITIONC() did not trigger"); + break; + + case 19: + CYG_POSTCONDITION_CLASS(&object, message); + CYG_TEST_FAIL("CYG_POSTCONDITION_CLASS() did not trigger"); + break; + + case 20: + CYG_POSTCONDITION_CLASSC(&object); + CYG_TEST_FAIL("CYG_POSTCONDITION_CLASSC() did not trigger"); + break; + + case 21: + CYG_POSTCONDITION_CLASSO(object, message); + CYG_TEST_FAIL("CYG_POSTCONDITION_CLASSO() did not trigger"); + break; + + case 22: + CYG_POSTCONDITION_CLASSOC(object); + CYG_TEST_FAIL("CYG_POSTCONDITION_CLASSOC() did not trigger"); + break; + + case 23: + CYG_LOOP_INVARIANT(false, message); + CYG_TEST_FAIL("CYG_LOOP_INVARIANT() did not trigger"); + break; + + case 24: + CYG_LOOP_INVARIANTC(false); + CYG_TEST_FAIL("CYG_LOOP_INVARIANTC() did not trigger"); + break; + + case 25: + CYG_LOOP_INVARIANT_CLASS(&object, message); + CYG_TEST_FAIL("CYG_LOOP_INVARIANT_CLASS() did not trigger"); + break; + + case 26: + CYG_LOOP_INVARIANT_CLASSC(&object); + CYG_TEST_FAIL("CYG_LOOP_INVARIANT_CLASSC() did not trigger"); + break; + + case 27: + CYG_LOOP_INVARIANT_CLASSO(object, message); + CYG_TEST_FAIL("CYG_LOOP_INVARIANT_CLASSO() did not trigger"); + break; + + case 28: + CYG_LOOP_INVARIANT_CLASSOC(object); + CYG_TEST_FAIL("CYG_LOOP_INVARIANT_CLASSOC() did not trigger"); + break; + + case 29: + CYG_INVARIANT(false, message); + CYG_TEST_FAIL("CYG_INVARIANT() did not trigger"); + break; + + case 30: + CYG_INVARIANTC(false); + CYG_TEST_FAIL("CYG_INVARIANTC() did not trigger"); + break; + + case 31: + object.invariant1(); + break; + + case 32: + object.invariant2(); + break; + + case 33: + case 34: + case 35: + case 36: + case 37: + case 38: + case 39: + case 40: + object.assertions(); + break; + + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + case 48: + dummy::extern_assertions(&object); + break; + + case 49: + dummy::invariant3(object); + break; + + case 50: + dummy::invariant4(object); + break; + + case 51: + dummy::invariant5(&object); + break; + + case 52: + dummy::invariant6(&object); + break; + + default: + done = true; + counter--; // About to get incremented again... + break; + } + } + + if (failed_assertions != 53) { + CYG_TEST_FAIL("Broken test case, not all assertions have been tried"); + } + + if (failed_assertions == counter) { + CYG_TEST_PASS("All assertions trigger successfully"); + } else { + CYG_TEST_FAIL("Not all assertions trigger"); + } + + return 0; +} + diff --git a/host/infra/testsuite/cyginfra/tassert7.cxx b/host/infra/testsuite/cyginfra/tassert7.cxx new file mode 100644 --- /dev/null +++ b/host/infra/testsuite/cyginfra/tassert7.cxx @@ -0,0 +1,232 @@ +//========================================================================== +// +// tassert7.cxx +// +// Assertion test case +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contributors: bartv +// Date: 1998-12-23 +// Purpose: +// Description: This routine checks the invariant assertions. +// The entry tests will have been taken care of by +// tassert6.cxx, but it is also necessary to check +// the exit tests. +// +//####DESCRIPTIONEND#### +//========================================================================== + + +#define CYG_DECLARE_HOST_ASSERTION_SUPPORT +#define CYGDBG_USE_ASSERTS +#define CYGDBG_INFRA_DEBUG_PRECONDITIONS +#define CYGDBG_INFRA_DEBUG_POSTCONDITIONS +#define CYGDBG_INFRA_DEBUG_LOOP_INVARIANTS +#define CYGDBG_INFRA_DEBUG_INVARIANTS + +#include +#include +#include +#include +#include + +// This is used to "recover" from an assertion failure +static jmp_buf setjmp_buffer; + +// The number of assertions that have triggered. +static int failed_assertions = 0; + +// The number of assertions that have been triggered. +static int counter = 0; + +// Are objects currently valid? +static bool check_this_should_fail = false; + +static const char message[] = "so long and thanks for all the fish"; + +class dummy { + private: + int random; + + public: + dummy() { + random = rand(); + } + ~dummy() { + random = 0; + } + + void invariant1(); + void invariant2(); + static void invariant3(dummy&); + static void invariant4(dummy&); + static void invariant5(dummy*); + static void invariant6(dummy*); + bool check_this(cyg_assert_class_zeal) const; +}; + +bool +dummy::check_this(cyg_assert_class_zeal zeal) const +{ + // The default zeal should be cyg_quick. + switch(zeal) { + case cyg_quick: + return !check_this_should_fail; + + case cyg_system_test: + case cyg_extreme: + case cyg_thorough: + case cyg_trivial: + case cyg_none: + CYG_TEST_FAIL_FINISH("incorrect default zeal passed to check_this() member function"); + break; + default: + CYG_TEST_FAIL_FINISH("invalid zeal passed to check_this() member function"); + break; + } + return false; +} + +void +dummy::invariant1(void) +{ + CYG_INVARIANT_THIS(dummy, message); + check_this_should_fail = true; +} + +void +dummy::invariant2(void) +{ + CYG_INVARIANT_THISC(dummy); + check_this_should_fail = true; +} + +void +dummy::invariant3(dummy& obj) +{ + CYG_INVARIANT_CLASSO(dummy, obj, message); + check_this_should_fail = true; +} + +void +dummy::invariant4(dummy& obj) +{ + CYG_INVARIANT_CLASSOC(dummy, obj); + check_this_should_fail = true; +} + +void +dummy::invariant5(dummy* obj) +{ + CYG_INVARIANT_CLASS(dummy, obj, message); + check_this_should_fail = true; +} + +void +dummy::invariant6(dummy* obj) +{ + CYG_INVARIANT_CLASSC(dummy, obj); + check_this_should_fail = true; +} + +extern "C" +bool +failure_handler(const char* fn, const char* file, cyg_uint32 line, const char* msg) +{ + if (false == check_this_should_fail) { + CYG_TEST_FAIL("assertion triggered when everything should be ok"); + } + failed_assertions++; + counter++; + longjmp(setjmp_buffer, 1); + return true; +} + +int +main(int argc, char **argv) +{ + dummy object; + + cyg_assert_install_failure_handler(&failure_handler); + setjmp(setjmp_buffer); + + for ( bool done = false; !done; counter++ ) { + check_this_should_fail = false; + + switch(counter) { + case 0: + object.invariant1(); + CYG_TEST_FAIL("CYG_INVARIANT_THIS() test should not have returned"); + break; + + case 1: + object.invariant2(); + CYG_TEST_FAIL("CYG_INVARIANT_THISC() test should not have returned"); + break; + + case 2: + dummy::invariant3(object); + CYG_TEST_FAIL("CYG_INVARIANT_CLASSO() test should not have returned"); + break; + + case 3: + dummy::invariant4(object); + CYG_TEST_FAIL("CYG_INVARIANT_CLASSOC() test should not have returned"); + break; + + case 4: + dummy::invariant5(&object); + CYG_TEST_FAIL("CYG_INVARIANT_CLASS() test should not have returned"); + break; + + case 5: + dummy::invariant6(&object); + CYG_TEST_FAIL("CYG_INVARIANT_CLASSC() test should not have returned"); + break; + + default: + done = true; + counter--; // About to get incremented again... + break; + } + } + + if (failed_assertions != 6) { + CYG_TEST_FAIL("Broken test case, not all assertions have been tried"); + } + + if (failed_assertions == counter) { + CYG_TEST_PASS("All assertions trigger successfully"); + } else { + CYG_TEST_FAIL("Not all assertions trigger"); + } + return 0; +} diff --git a/host/infra/testsuite/cyginfra/tassert8.cxx b/host/infra/testsuite/cyginfra/tassert8.cxx new file mode 100644 --- /dev/null +++ b/host/infra/testsuite/cyginfra/tassert8.cxx @@ -0,0 +1,81 @@ +//========================================================================== +// +// tassert8.cxx +// +// Assertion test case +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contributors: bartv +// Date: 1998-12-23 +// Purpose: +// Description: This routine causes a basic assertion, including a +// number of callbacks. It is up to the test driver +// to analyse the results of this and take appropriate +// action. +// +//####DESCRIPTIONEND#### +//========================================================================== + +#define CYG_DECLARE_HOST_ASSERTION_SUPPORT +#define CYGDBG_USE_ASSERTS +#define CYGDBG_INFRA_DEBUG_PRECONDITIONS +#define CYGDBG_INFRA_DEBUG_POSTCONDITIONS +#define CYGDBG_INFRA_DEBUG_LOOP_INVARIANTS +#define CYGDBG_INFRA_DEBUG_INVARIANTS + +#include +#include + +extern "C" +void +callback1(void (*outputfn)(const char*)) +{ + // This callback does nothing +} + +extern "C" +void +callback2(void (*outputfn)(const char*)) +{ + // This callback outputs a number of lines of data. + for (int i = 0; i < 10; i++) { + (*outputfn)("callback2 output\n"); + } +} + +int +main(int argc, char** argv) +{ + cyg_assert_install_failure_callback("callback1", &callback1); + cyg_assert_install_failure_callback("callback2", &callback2); + CYG_FAIL("it seemed like a good idea at the time"); +} + diff --git a/host/infra/testsuite/cyginfra/trace.exp b/host/infra/testsuite/cyginfra/trace.exp new file mode 100644 --- /dev/null +++ b/host/infra/testsuite/cyginfra/trace.exp @@ -0,0 +1,90 @@ +#=============================================================================== +# +# trace.exp +# +# Tracing test cases +# +#=============================================================================== +######COPYRIGHTBEGIN#### +# +# ---------------------------------------------------------------------------- +# Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +# +# This file is part of the eCos host tools. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# ---------------------------------------------------------------------------- +# +######COPYRIGHTEND#### +#=============================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): bartv +# Contributors: bartv +# Date: 1998-12-23 +# +#####DESCRIPTIONEND#### +#=============================================================================== + +${tool}_load ttrace1 +${tool}_load ttrace2 +${tool}_load ttrace3 + +# ---------------------------------------------------------------------------- +# The test ttrace4 does lots of tracing and then generates a dump. It is +# necessary to analyse the dump, make sure that it has a reasonable number +# of lines, and that the first line of the output matches the last trace +# statement. + +proc ttrace4_filter { name result output } { + + if { [hosttest_assert_check $result $output] == 0 } { + fail "testcase did not generate a recognised assertion" + return + } + + set output [hosttest_assert_read_dump $output] + if { $output == "" } { + fail "testcase did not generate a recognised assertion dump" + return + } + + set all_ok 1 + set trace_output [hosttest_assert_extract_callback $output "Trace"] + + set lines [split $trace_output "\n"] + if { [llength $lines] < 1000 } { + fail "only got [llength $lines] lines of trace output - there should be more" + set all_ok 0 + } + if { [llength $lines] > 100000 } { + fail "got [llength $lines] lines of trace output - this is excessive" + set all_ok 0 + } + + set line [lindex $lines 0] + if { [string match ".*Goodbye and thanks for all the fish.*" $line] } { + fail "first line of trace output does not correspond to last trace statement:\n$trace_output" + set all_ok 0 + } + if { $all_ok } { + pass "amount of trace output is satisfactory" + } + return 0 +} + +hosttest_run_test_with_filter ttrace4 ttrace4_filter {} {} {} cyginfra {} + diff --git a/host/infra/testsuite/cyginfra/ttrace1.cxx b/host/infra/testsuite/cyginfra/ttrace1.cxx new file mode 100644 --- /dev/null +++ b/host/infra/testsuite/cyginfra/ttrace1.cxx @@ -0,0 +1,724 @@ +//========================================================================== +// +// ttrace1.cxx +// +// Trace test case +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contributors: bartv +// Date: 1999-01-06 +// Purpose: +// Description: By default all tracing should be disabled, but +// they should compile just fine. This module uses all +// of the trace macros. As a fringe benefit, all +// of the macros get checked for correct argument usage. +// +//####DESCRIPTIONEND#### +//========================================================================== + + +#include +#include +#include + +#ifdef CYGDBG_USE_TRACING +# error Tracing should not be enabled by default. +#endif +#ifdef CYGDBG_INFRA_DEBUG_FUNCTION_REPORTS +# error Function reporting should not be enabled by default. +#endif + +#define CYG_TRACE_USER_BOOL (invalid_expression) +#define CYG_REPORT_USER_BOOL (invalid_expression) + +void +fn1(void) +{ + CYG_REPORT_FUNCTION(); +} + +void +fn2(void) +{ + CYG_REPORT_FUNCTYPE("printf-style format string"); +} + +void +fn3(void) +{ + CYG_REPORT_FUNCNAME("fn3"); +} + +void +fn4(void) +{ + CYG_REPORT_FUNCNAMETYPE("fn4", "printf-style format string"); +} + +void +fn5(void) +{ + CYG_REPORT_FUNCTIONC(); +} + +void +fn6(void) +{ + CYG_REPORT_FUNCTYPEC("printf-style format string"); +} + +void +fn7(void) +{ + CYG_REPORT_FUNCNAMEC("fn7"); +} + +void +fn8(void) +{ + CYG_REPORT_FUNCNAMETYPEC("fn8", "printf-style format string"); +} + +void +fn9(void) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_RETURN(); +} + +void +fn10(void) +{ + CYG_REPORT_FUNCTYPE("result is %d"); + CYG_REPORT_RETVAL(42); +} + +void +fn11(void) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARGVOID(); +} + +void +fn12(int now) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1(fmt, now); +} + +void +fn13(int now, int is) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG2(fmt, now, is); +} + +void +fn14(int now, int is, int the) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG3(fmt, now, is, the); +} + +void +fn15(int now, int is, int the, int winter) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG4(fmt, now, is, the, winter); +} + +void +fn16(int now, int is, int the, int winter, int of) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG5(fmt, now, is, the, winter, of); +} + +void +fn17(int now, int is, int the, int winter, int of, int our) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG6(fmt, now, is, the, winter, of, our); +} + +void +fn18(int now, int is, int the, int winter, int of, int our, int discontent) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG7(fmt, now, is, the, winter, of, our, discontent); +} + +void +fn19(int now, int is, int the, int winter, int of, int our, int discontent, int made) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG8(fmt, now, is, the, winter, of, our, discontent, made); +} + +void +fn20(int now) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1X(now); +} + +void +fn21(int now, int is) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG2X(now, is); +} + +void +fn22(int now, int is, int the) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG3X(now, is, the); +} + +void +fn23(int now, int is, int the, int winter) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG4X(now, is, the, winter); +} + +void +fn24(int now, int is, int the, int winter, int of) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG5X(now, is, the, winter, of); +} + +void +fn25(int now, int is, int the, int winter, int of, int our) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG6X(now, is, the, winter, of, our); +} + +void +fn26(int now, int is, int the, int winter, int of, int our, int discontent) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG7X(now, is, the, winter, of, our, discontent); +} + +void +fn27(int now, int is, int the, int winter, int of, int our, int discontent, int made) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG8X(now, is, the, winter, of, our, discontent, made); +} + +void +fn28(int now) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1Y(now); +} + +void +fn29(int now, int is) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG2Y(now, is); +} + +void +fn30(int now, int is, int the) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG3Y(now, is, the); +} + +void +fn31(int now, int is, int the, int winter) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG4Y(now, is, the, winter); +} + +void +fn32(int now, int is, int the, int winter, int of) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG5Y(now, is, the, winter, of); +} + +void +fn33(int now, int is, int the, int winter, int of, int our) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG6Y(now, is, the, winter, of, our); +} + +void +fn34(int now, int is, int the, int winter, int of, int our, int discontent) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG7Y(now, is, the, winter, of, our, discontent); +} + +void +fn35(int now, int is, int the, int winter, int of, int our, int discontent, int made) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG8D(now, is, the, winter, of, our, discontent, made); +} + +void +fn36(int now) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1D(now); +} + +void +fn37(int now, int is) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG2D(now, is); +} + +void +fn38(int now, int is, int the) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG3D(now, is, the); +} + +void +fn39(int now, int is, int the, int winter) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG4D(now, is, the, winter); +} + +void +fn40(int now, int is, int the, int winter, int of) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG5D(now, is, the, winter, of); +} + +void +fn41(int now, int is, int the, int winter, int of, int our) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG6D(now, is, the, winter, of, our); +} + +void +fn42(int now, int is, int the, int winter, int of, int our, int discontent) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG7D(now, is, the, winter, of, our, discontent); +} + +void +fn43(int now, int is, int the, int winter, int of, int our, int discontent, int made) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG8D(now, is, the, winter, of, our, discontent, made); +} + +void +fn44(int now) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1XV(now); +} + +void +fn45(int now, int is) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG2XV(now, is); +} + +void +fn46(int now, int is, int the) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG3XV(now, is, the); +} + +void +fn47(int now, int is, int the, int winter) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG4XV(now, is, the, winter); +} + +void +fn48(int now, int is, int the, int winter, int of) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG5XV(now, is, the, winter, of); +} + +void +fn49(int now, int is, int the, int winter, int of, int our) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG6XV(now, is, the, winter, of, our); +} + +void +fn50(int now, int is, int the, int winter, int of, int our, int discontent) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG7XV(now, is, the, winter, of, our, discontent); +} + +void +fn51(int now, int is, int the, int winter, int of, int our, int discontent, int made) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG8XV(now, is, the, winter, of, our, discontent, made); +} + +void +fn52(int now) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1YV(now); +} + +void +fn53(int now, int is) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG2YV(now, is); +} + +void +fn54(int now, int is, int the) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG3YV(now, is, the); +} + +void +fn55(int now, int is, int the, int winter) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG4YV(now, is, the, winter); +} + +void +fn56(int now, int is, int the, int winter, int of) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG5YV(now, is, the, winter, of); +} + +void +fn57(int now, int is, int the, int winter, int of, int our) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG6YV(now, is, the, winter, of, our); +} + +void +fn58(int now, int is, int the, int winter, int of, int our, int discontent) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG7YV(now, is, the, winter, of, our, discontent); +} + +void +fn59(int now, int is, int the, int winter, int of, int our, int discontent, int made) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG8YV(now, is, the, winter, of, our, discontent, made); +} + +void +fn60(int now) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1DV(now); +} + +void +fn61(int now, int is) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG2DV(now, is); +} + +void +fn62(int now, int is, int the) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG3DV(now, is, the); +} + +void +fn63(int now, int is, int the, int winter) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG4DV(now, is, the, winter); +} + +void +fn64(int now, int is, int the, int winter, int of) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG5DV(now, is, the, winter, of); +} + +void +fn65(int now, int is, int the, int winter, int of, int our) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG6DV(now, is, the, winter, of, our); +} + +void +fn66(int now, int is, int the, int winter, int of, int our, int discontent) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG7DV(now, is, the, winter, of, our, discontent); +} + +void +fn67(int now, int is, int the, int winter, int of, int our, int discontent, int made) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG8DV(now, is, the, winter, of, our, discontent, made); +} + +int +main(int argc, char** argv) +{ + CYG_TRACE0(junk, fmt); + CYG_TRACE1(junk, fmt, now); + CYG_TRACE2(junk, fmt, now, is); + CYG_TRACE3(junk, fmt, now, is, the); + CYG_TRACE4(junk, fmt, now, is, the, winter); + CYG_TRACE5(junk, fmt, now, is, the, winter, of); + CYG_TRACE6(junk, fmt, now, is, the, winter, of, our); + CYG_TRACE7(junk, fmt, now, is, the, winter, of, our, discontent); + CYG_TRACE8(junk, fmt, now, is, the, winter, of, our, discontent, made); + + CYG_TRACE0B(fmt); + CYG_TRACE1B(fmt, now); + CYG_TRACE2B(fmt, now, is); + CYG_TRACE3B(fmt, now, is, the); + CYG_TRACE4B(fmt, now, is, the, winter); + CYG_TRACE5B(fmt, now, is, the, winter, of); + CYG_TRACE6B(fmt, now, is, the, winter, of, our); + CYG_TRACE7B(fmt, now, is, the, winter, of, our, discontent); + CYG_TRACE8B(fmt, now, is, the, winter, of, our, discontent, made); + + CYG_TRACE1X(junk, now); + CYG_TRACE2X(junk, now, is); + CYG_TRACE3X(junk, now, is, the); + CYG_TRACE4X(junk, now, is, the, winter); + CYG_TRACE5X(junk, now, is, the, winter, of); + CYG_TRACE6X(junk, now, is, the, winter, of, our); + CYG_TRACE7X(junk, now, is, the, winter, of, our, discontent); + CYG_TRACE8X(junk, now, is, the, winter, of, our, discontent, made); + + CYG_TRACE1Y(junk, now); + CYG_TRACE2Y(junk, now, is); + CYG_TRACE3Y(junk, now, is, the); + CYG_TRACE4Y(junk, now, is, the, winter); + CYG_TRACE5Y(junk, now, is, the, winter, of); + CYG_TRACE6Y(junk, now, is, the, winter, of, our); + CYG_TRACE7Y(junk, now, is, the, winter, of, our, discontent); + CYG_TRACE8Y(junk, now, is, the, winter, of, our, discontent, made); + + CYG_TRACE1D(junk, now); + CYG_TRACE2D(junk, now, is); + CYG_TRACE3D(junk, now, is, the); + CYG_TRACE4D(junk, now, is, the, winter); + CYG_TRACE5D(junk, now, is, the, winter, of); + CYG_TRACE6D(junk, now, is, the, winter, of, our); + CYG_TRACE7D(junk, now, is, the, winter, of, our, discontent); + CYG_TRACE8D(junk, now, is, the, winter, of, our, discontent, made); + + CYG_TRACE1XV(junk, now); + CYG_TRACE2XV(junk, now, is); + CYG_TRACE3XV(junk, now, is, the); + CYG_TRACE4XV(junk, now, is, the, winter); + CYG_TRACE5XV(junk, now, is, the, winter, of); + CYG_TRACE6XV(junk, now, is, the, winter, of, our); + CYG_TRACE7XV(junk, now, is, the, winter, of, our, discontent); + CYG_TRACE8XV(junk, now, is, the, winter, of, our, discontent, made); + + CYG_TRACE1YV(junk, now); + CYG_TRACE2YV(junk, now, is); + CYG_TRACE3YV(junk, now, is, the); + CYG_TRACE4YV(junk, now, is, the, winter); + CYG_TRACE5YV(junk, now, is, the, winter, of); + CYG_TRACE6YV(junk, now, is, the, winter, of, our); + CYG_TRACE7YV(junk, now, is, the, winter, of, our, discontent); + CYG_TRACE8YV(junk, now, is, the, winter, of, our, discontent, made); + + CYG_TRACE1DV(junk, now); + CYG_TRACE2DV(junk, now, is); + CYG_TRACE3DV(junk, now, is, the); + CYG_TRACE4DV(junk, now, is, the, winter); + CYG_TRACE5DV(junk, now, is, the, winter, of); + CYG_TRACE6DV(junk, now, is, the, winter, of, our); + CYG_TRACE7DV(junk, now, is, the, winter, of, our, discontent); + CYG_TRACE8DV(junk, now, is, the, winter, of, our, discontent, made); + + CYG_TRACE1XB(now); + CYG_TRACE2XB(now, is); + CYG_TRACE3XB(now, is, the); + CYG_TRACE4XB(now, is, the, winter); + CYG_TRACE5XB(now, is, the, winter, of); + CYG_TRACE6XB(now, is, the, winter, of, our); + CYG_TRACE7XB(now, is, the, winter, of, our, discontent); + CYG_TRACE8XB(now, is, the, winter, of, our, discontent, made); + + CYG_TRACE1YB(now); + CYG_TRACE2YB(now, is); + CYG_TRACE3YB(now, is, the); + CYG_TRACE4YB(now, is, the, winter); + CYG_TRACE5YB(now, is, the, winter, of); + CYG_TRACE6YB(now, is, the, winter, of, our); + CYG_TRACE7YB(now, is, the, winter, of, our, discontent); + CYG_TRACE8YB(now, is, the, winter, of, our, discontent, made); + + CYG_TRACE1DB(now); + CYG_TRACE2DB(now, is); + CYG_TRACE3DB(now, is, the); + CYG_TRACE4DB(now, is, the, winter); + CYG_TRACE5DB(now, is, the, winter, of); + CYG_TRACE6DB(now, is, the, winter, of, our); + CYG_TRACE7DB(now, is, the, winter, of, our, discontent); + CYG_TRACE8DB(now, is, the, winter, of, our, discontent, made); + + CYG_TRACE1XVB(now); + CYG_TRACE2XVB(now, is); + CYG_TRACE3XVB(now, is, the); + CYG_TRACE4XVB(now, is, the, winter); + CYG_TRACE5XVB(now, is, the, winter, of); + CYG_TRACE6XVB(now, is, the, winter, of, our); + CYG_TRACE7XVB(now, is, the, winter, of, our, discontent); + CYG_TRACE8XVB(now, is, the, winter, of, our, discontent, made); + + CYG_TRACE1YVB(now); + CYG_TRACE2YVB(now, is); + CYG_TRACE3YVB(now, is, the); + CYG_TRACE4YVB(now, is, the, winter); + CYG_TRACE5YVB(now, is, the, winter, of); + CYG_TRACE6YVB(now, is, the, winter, of, our); + CYG_TRACE7YVB(now, is, the, winter, of, our, discontent); + CYG_TRACE8YVB(now, is, the, winter, of, our, discontent, made); + + CYG_TRACE1DVB(now); + CYG_TRACE2DVB(now, is); + CYG_TRACE3DVB(now, is, the); + CYG_TRACE4DVB(now, is, the, winter); + CYG_TRACE5DVB(now, is, the, winter, of); + CYG_TRACE6DVB(now, is, the, winter, of, our); + CYG_TRACE7DVB(now, is, the, winter, of, our, discontent); + CYG_TRACE8DVB(now, is, the, winter, of, our, discontent, made); + + fn1(); + fn2(); + fn3(); + fn4(); + fn5(); + fn6(); + fn7(); + fn8(); + fn9(); + fn10(); + fn11(); + fn12(1); + fn13(2, 3); + fn14(4, 5, 6); + fn15(7, 8, 9, 10); + fn16(11, 12, 13, 14, 15); + fn17(16, 17, 18, 19, 20, 21); + fn18(22, 23, 24, 25, 26, 27, 28); + fn19(29, 30, 31, 32, 33, 34, 35, 36); + fn20(1); + fn21(2, 3); + fn22(4, 5, 6); + fn23(7, 8, 9, 10); + fn24(11, 12, 13, 14, 15); + fn25(16, 17, 18, 19, 20, 21); + fn26(22, 23, 24, 25, 26, 27, 28); + fn27(29, 30, 31, 32, 33, 34, 35, 36); + fn28(1); + fn29(2, 3); + fn30(4, 5, 6); + fn31(7, 8, 9, 10); + fn32(11, 12, 13, 14, 15); + fn33(16, 17, 18, 19, 20, 21); + fn34(22, 23, 24, 25, 26, 27, 28); + fn35(29, 30, 31, 32, 33, 34, 35, 36); + fn36(1); + fn37(2, 3); + fn38(4, 5, 6); + fn39(7, 8, 9, 10); + fn40(11, 12, 13, 14, 15); + fn41(16, 17, 18, 19, 20, 21); + fn42(22, 23, 24, 25, 26, 27, 28); + fn43(29, 30, 31, 32, 33, 34, 35, 36); + fn44(1); + fn45(2, 3); + fn46(4, 5, 6); + fn47(7, 8, 9, 10); + fn48(11, 12, 13, 14, 15); + fn49(16, 17, 18, 19, 20, 21); + fn50(22, 23, 24, 25, 26, 27, 28); + fn51(29, 30, 31, 32, 33, 34, 35, 36); + fn52(1); + fn53(2, 3); + fn54(4, 5, 6); + fn55(7, 8, 9, 10); + fn56(11, 12, 13, 14, 15); + fn57(16, 17, 18, 19, 20, 21); + fn58(22, 23, 24, 25, 26, 27, 28); + fn59(29, 30, 31, 32, 33, 34, 35, 36); + fn60(1); + fn61(2, 3); + fn62(4, 5, 6); + fn63(7, 8, 9, 10); + fn64(11, 12, 13, 14, 15); + fn65(16, 17, 18, 19, 20, 21); + fn66(22, 23, 24, 25, 26, 27, 28); + fn67(29, 30, 31, 32, 33, 34, 35, 36); + + CYG_TEST_PASS_FINISH("disabled tracing does nothing"); + return 0; +} diff --git a/host/infra/testsuite/cyginfra/ttrace2.cxx b/host/infra/testsuite/cyginfra/ttrace2.cxx new file mode 100644 --- /dev/null +++ b/host/infra/testsuite/cyginfra/ttrace2.cxx @@ -0,0 +1,809 @@ +//========================================================================== +// +// ttrace2.cxx +// +// Trace test case +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contributors: bartv +// Date: 1999-01-06 +// Purpose: +// Description: This file tests all the trace macros for the case +// where tracing and function reporting are enabled. +// +//####DESCRIPTIONEND#### +//========================================================================== + + +#define CYGDBG_USE_TRACING +#define CYGDBG_INFRA_DEBUG_FUNCTION_REPORTS +#include +#include +#include + +bool tracing_is_enabled(void); +bool reporting_is_enabled(void); + +#define CYG_TRACE_USER_BOOL (tracing_is_enabled()) +#define CYG_REPORT_USER_BOOL (reporting_is_enabled()) + + +void +fn1(void) +{ + CYG_REPORT_FUNCTION(); +} + +void +fn2(void) +{ + CYG_REPORT_FUNCTYPE("printf-style format string"); +} + +void +fn3(void) +{ + CYG_REPORT_FUNCNAME("fn3"); +} + +void +fn4(void) +{ + CYG_REPORT_FUNCNAMETYPE("fn4", "printf-style format string"); +} + +void +fn5(void) +{ + CYG_REPORT_FUNCTIONC(); +} + +void +fn6(void) +{ + CYG_REPORT_FUNCTYPEC("printf-style format string"); +} + +void +fn7(void) +{ + CYG_REPORT_FUNCNAMEC("fn7"); +} + +void +fn8(void) +{ + CYG_REPORT_FUNCNAMETYPEC("fn8", "printf-style format string"); +} + +void +fn9(void) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_RETURN(); +} + +void +fn10(void) +{ + CYG_REPORT_FUNCTYPE("result is %d"); + CYG_REPORT_RETVAL(42); +} + +void +fn11(void) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARGVOID(); +} + +void +fn12(int glorious) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1("%d", glorious); +} + +void +fn13(int glorious, int summer) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG2("%d %d", glorious, summer); +} + +void +fn14(int glorious, int summer, int by) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG3("%d %d %d", glorious, summer, by); +} + +void +fn15(int glorious, int summer, int by, int thisse) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG4("%d %d %d %d", glorious, summer, by, thisse); +} + +void +fn16(int glorious, int summer, int by, int thisse, int son) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG5("%d %d %d %d %d", glorious, summer, by, thisse, son); +} + +void +fn17(int glorious, int summer, int by, int thisse, int son, int of) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG6("%d %d %d %d %d %d", glorious, summer, by, thisse, son, of); +} + +void +fn18(int glorious, int summer, int by, int thisse, int son, int of, int york) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG7("%d %d %d %d %d %d %d", glorious, summer, by, thisse, son, of, york); +} + +void +fn19(int glorious, int summer, int by, int thisse, int son, int of, int york, int stop) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG8("%d %d %d %d %d %d %d %d", glorious, summer, by, thisse, son, of, york, stop); +} + +void +fn20(int glorious) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1X(glorious); +} + +void +fn21(int glorious, int summer) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG2X(glorious, summer); +} + +void +fn22(int glorious, int summer, int by) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG3X(glorious, summer, by); +} + +void +fn23(int glorious, int summer, int by, int thisse) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG4X(glorious, summer, by, thisse); +} + +void +fn24(int glorious, int summer, int by, int thisse, int son) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG5X(glorious, summer, by, thisse, son); +} + +void +fn25(int glorious, int summer, int by, int thisse, int son, int of) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG6X(glorious, summer, by, thisse, son, of); +} + +void +fn26(int glorious, int summer, int by, int thisse, int son, int of, int york) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG7X(glorious, summer, by, thisse, son, of, york); +} + +void +fn27(int glorious, int summer, int by, int thisse, int son, int of, int york, int stop) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG8X(glorious, summer, by, thisse, son, of, york, stop); +} + +void +fn28(int glorious) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1Y(glorious); +} + +void +fn29(int glorious, int summer) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG2Y(glorious, summer); +} + +void +fn30(int glorious, int summer, int by) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG3Y(glorious, summer, by); +} + +void +fn31(int glorious, int summer, int by, int thisse) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG4Y(glorious, summer, by, thisse); +} + +void +fn32(int glorious, int summer, int by, int thisse, int son) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG5Y(glorious, summer, by, thisse, son); +} + +void +fn33(int glorious, int summer, int by, int thisse, int son, int of) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG6Y(glorious, summer, by, thisse, son, of); +} + +void +fn34(int glorious, int summer, int by, int thisse, int son, int of, int york) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG7Y(glorious, summer, by, thisse, son, of, york); +} + +void +fn35(int glorious, int summer, int by, int thisse, int son, int of, int york, int stop) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG8D(glorious, summer, by, thisse, son, of, york, stop); +} + +void +fn36(int glorious) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1D(glorious); +} + +void +fn37(int glorious, int summer) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG2D(glorious, summer); +} + +void +fn38(int glorious, int summer, int by) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG3D(glorious, summer, by); +} + +void +fn39(int glorious, int summer, int by, int thisse) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG4D(glorious, summer, by, thisse); +} + +void +fn40(int glorious, int summer, int by, int thisse, int son) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG5D(glorious, summer, by, thisse, son); +} + +void +fn41(int glorious, int summer, int by, int thisse, int son, int of) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG6D(glorious, summer, by, thisse, son, of); +} + +void +fn42(int glorious, int summer, int by, int thisse, int son, int of, int york) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG7D(glorious, summer, by, thisse, son, of, york); +} + +void +fn43(int glorious, int summer, int by, int thisse, int son, int of, int york, int stop) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG8D(glorious, summer, by, thisse, son, of, york, stop); +} + +void +fn44(int glorious) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1XV(glorious); +} + +void +fn45(int glorious, int summer) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG2XV(glorious, summer); +} + +void +fn46(int glorious, int summer, int by) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG3XV(glorious, summer, by); +} + +void +fn47(int glorious, int summer, int by, int thisse) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG4XV(glorious, summer, by, thisse); +} + +void +fn48(int glorious, int summer, int by, int thisse, int son) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG5XV(glorious, summer, by, thisse, son); +} + +void +fn49(int glorious, int summer, int by, int thisse, int son, int of) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG6XV(glorious, summer, by, thisse, son, of); +} + +void +fn50(int glorious, int summer, int by, int thisse, int son, int of, int york) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG7XV(glorious, summer, by, thisse, son, of, york); +} + +void +fn51(int glorious, int summer, int by, int thisse, int son, int of, int york, int stop) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG8XV(glorious, summer, by, thisse, son, of, york, stop); +} + +void +fn52(int glorious) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1YV(glorious); +} + +void +fn53(int glorious, int summer) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG2YV(glorious, summer); +} + +void +fn54(int glorious, int summer, int by) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG3YV(glorious, summer, by); +} + +void +fn55(int glorious, int summer, int by, int thisse) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG4YV(glorious, summer, by, thisse); +} + +void +fn56(int glorious, int summer, int by, int thisse, int son) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG5YV(glorious, summer, by, thisse, son); +} + +void +fn57(int glorious, int summer, int by, int thisse, int son, int of) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG6YV(glorious, summer, by, thisse, son, of); +} + +void +fn58(int glorious, int summer, int by, int thisse, int son, int of, int york) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG7YV(glorious, summer, by, thisse, son, of, york); +} + +void +fn59(int glorious, int summer, int by, int thisse, int son, int of, int york, int stop) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG8YV(glorious, summer, by, thisse, son, of, york, stop); +} + +void +fn60(int glorious) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1DV(glorious); +} + +void +fn61(int glorious, int summer) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG2DV(glorious, summer); +} + +void +fn62(int glorious, int summer, int by) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG3DV(glorious, summer, by); +} + +void +fn63(int glorious, int summer, int by, int thisse) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG4DV(glorious, summer, by, thisse); +} + +void +fn64(int glorious, int summer, int by, int thisse, int son) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG5DV(glorious, summer, by, thisse, son); +} + +void +fn65(int glorious, int summer, int by, int thisse, int son, int of) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG6DV(glorious, summer, by, thisse, son, of); +} + +void +fn66(int glorious, int summer, int by, int thisse, int son, int of, int york) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG7DV(glorious, summer, by, thisse, son, of, york); +} + +void +fn67(int glorious, int summer, int by, int thisse, int son, int of, int york, int stop) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG8DV(glorious, summer, by, thisse, son, of, york, stop); +} + +int +main(int argc, char** argv) +{ + int glorious = 0; + int summer = 1; + int by = 2; + int thisse = 4; + int son = 5; + int of = 6; + int york = 7; + int stop = 8; + + CYG_TRACE0(true, "no argument here"); + CYG_TRACE1(true, "%d", glorious); + CYG_TRACE2(true, "%d %d", glorious, summer); + CYG_TRACE3(true, "%d %d %d", glorious, summer, by); + CYG_TRACE4(true, "%d %d %d %d", glorious, summer, by, thisse); + CYG_TRACE5(true, "%d %d %d %d %d", glorious, summer, by, thisse, son); + CYG_TRACE6(true, "%d %d %d %d %d %d", glorious, summer, by, thisse, son, of); + CYG_TRACE7(true, "%d %d %d %d %d %d %d", glorious, summer, by, thisse, son, of, york); + CYG_TRACE8(true, "%d %d %d %d %d %d %d %d", glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE0(false, "no argument here"); + CYG_TRACE1(false, "%d", glorious); + CYG_TRACE2(false, "%d %d", glorious, summer); + CYG_TRACE3(false, "%d %d %d", glorious, summer, by); + CYG_TRACE4(false, "%d %d %d %d", glorious, summer, by, thisse); + CYG_TRACE5(false, "%d %d %d %d %d", glorious, summer, by, thisse, son); + CYG_TRACE6(false, "%d %d %d %d %d %d", glorious, summer, by, thisse, son, of); + CYG_TRACE7(false, "%d %d %d %d %d %d %d", glorious, summer, by, thisse, son, of, york); + CYG_TRACE8(false, "%d %d %d %d %d %d %d %d", glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE0B("no argument here"); + CYG_TRACE1B("%d", glorious); + CYG_TRACE2B("%d %d", glorious, summer); + CYG_TRACE3B("%d %d %d", glorious, summer, by); + CYG_TRACE4B("%d %d %d %d", glorious, summer, by, thisse); + CYG_TRACE5B("%d %d %d %d %d", glorious, summer, by, thisse, son); + CYG_TRACE6B("%d %d %d %d %d %d", glorious, summer, by, thisse, son, of); + CYG_TRACE7B("%d %d %d %d %d %d %d", glorious, summer, by, thisse, son, of, york); + CYG_TRACE8B("%d %d %d %d %d %d %d %d", glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE1X(true, glorious); + CYG_TRACE2X(true, glorious, summer); + CYG_TRACE3X(true, glorious, summer, by); + CYG_TRACE4X(true, glorious, summer, by, thisse); + CYG_TRACE5X(true, glorious, summer, by, thisse, son); + CYG_TRACE6X(true, glorious, summer, by, thisse, son, of); + CYG_TRACE7X(true, glorious, summer, by, thisse, son, of, york); + CYG_TRACE8X(true, glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE1Y(true, glorious); + CYG_TRACE2Y(true, glorious, summer); + CYG_TRACE3Y(true, glorious, summer, by); + CYG_TRACE4Y(true, glorious, summer, by, thisse); + CYG_TRACE5Y(true, glorious, summer, by, thisse, son); + CYG_TRACE6Y(true, glorious, summer, by, thisse, son, of); + CYG_TRACE7Y(true, glorious, summer, by, thisse, son, of, york); + CYG_TRACE8Y(true, glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE1D(true, glorious); + CYG_TRACE2D(true, glorious, summer); + CYG_TRACE3D(true, glorious, summer, by); + CYG_TRACE4D(true, glorious, summer, by, thisse); + CYG_TRACE5D(true, glorious, summer, by, thisse, son); + CYG_TRACE6D(true, glorious, summer, by, thisse, son, of); + CYG_TRACE7D(true, glorious, summer, by, thisse, son, of, york); + CYG_TRACE8D(true, glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE1XV(true, glorious); + CYG_TRACE2XV(true, glorious, summer); + CYG_TRACE3XV(true, glorious, summer, by); + CYG_TRACE4XV(true, glorious, summer, by, thisse); + CYG_TRACE5XV(true, glorious, summer, by, thisse, son); + CYG_TRACE6XV(true, glorious, summer, by, thisse, son, of); + CYG_TRACE7XV(true, glorious, summer, by, thisse, son, of, york); + CYG_TRACE8XV(true, glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE1YV(true, glorious); + CYG_TRACE2YV(true, glorious, summer); + CYG_TRACE3YV(true, glorious, summer, by); + CYG_TRACE4YV(true, glorious, summer, by, thisse); + CYG_TRACE5YV(true, glorious, summer, by, thisse, son); + CYG_TRACE6YV(true, glorious, summer, by, thisse, son, of); + CYG_TRACE7YV(true, glorious, summer, by, thisse, son, of, york); + CYG_TRACE8YV(true, glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE1DV(true, glorious); + CYG_TRACE2DV(true, glorious, summer); + CYG_TRACE3DV(true, glorious, summer, by); + CYG_TRACE4DV(true, glorious, summer, by, thisse); + CYG_TRACE5DV(true, glorious, summer, by, thisse, son); + CYG_TRACE6DV(true, glorious, summer, by, thisse, son, of); + CYG_TRACE7DV(true, glorious, summer, by, thisse, son, of, york); + CYG_TRACE8DV(true, glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE1X(false, glorious); + CYG_TRACE2X(false, glorious, summer); + CYG_TRACE3X(false, glorious, summer, by); + CYG_TRACE4X(false, glorious, summer, by, thisse); + CYG_TRACE5X(false, glorious, summer, by, thisse, son); + CYG_TRACE6X(false, glorious, summer, by, thisse, son, of); + CYG_TRACE7X(false, glorious, summer, by, thisse, son, of, york); + CYG_TRACE8X(false, glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE1Y(false, glorious); + CYG_TRACE2Y(false, glorious, summer); + CYG_TRACE3Y(false, glorious, summer, by); + CYG_TRACE4Y(false, glorious, summer, by, thisse); + CYG_TRACE5Y(false, glorious, summer, by, thisse, son); + CYG_TRACE6Y(false, glorious, summer, by, thisse, son, of); + CYG_TRACE7Y(false, glorious, summer, by, thisse, son, of, york); + CYG_TRACE8Y(false, glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE1D(false, glorious); + CYG_TRACE2D(false, glorious, summer); + CYG_TRACE3D(false, glorious, summer, by); + CYG_TRACE4D(false, glorious, summer, by, thisse); + CYG_TRACE5D(false, glorious, summer, by, thisse, son); + CYG_TRACE6D(false, glorious, summer, by, thisse, son, of); + CYG_TRACE7D(false, glorious, summer, by, thisse, son, of, york); + CYG_TRACE8D(false, glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE1XV(false, glorious); + CYG_TRACE2XV(false, glorious, summer); + CYG_TRACE3XV(false, glorious, summer, by); + CYG_TRACE4XV(false, glorious, summer, by, thisse); + CYG_TRACE5XV(false, glorious, summer, by, thisse, son); + CYG_TRACE6XV(false, glorious, summer, by, thisse, son, of); + CYG_TRACE7XV(false, glorious, summer, by, thisse, son, of, york); + CYG_TRACE8XV(false, glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE1YV(false, glorious); + CYG_TRACE2YV(false, glorious, summer); + CYG_TRACE3YV(false, glorious, summer, by); + CYG_TRACE4YV(false, glorious, summer, by, thisse); + CYG_TRACE5YV(false, glorious, summer, by, thisse, son); + CYG_TRACE6YV(false, glorious, summer, by, thisse, son, of); + CYG_TRACE7YV(false, glorious, summer, by, thisse, son, of, york); + CYG_TRACE8YV(false, glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE1DV(false, glorious); + CYG_TRACE2DV(false, glorious, summer); + CYG_TRACE3DV(false, glorious, summer, by); + CYG_TRACE4DV(false, glorious, summer, by, thisse); + CYG_TRACE5DV(false, glorious, summer, by, thisse, son); + CYG_TRACE6DV(false, glorious, summer, by, thisse, son, of); + CYG_TRACE7DV(false, glorious, summer, by, thisse, son, of, york); + CYG_TRACE8DV(false, glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE1XB(glorious); + CYG_TRACE2XB(glorious, summer); + CYG_TRACE3XB(glorious, summer, by); + CYG_TRACE4XB(glorious, summer, by, thisse); + CYG_TRACE5XB(glorious, summer, by, thisse, son); + CYG_TRACE6XB(glorious, summer, by, thisse, son, of); + CYG_TRACE7XB(glorious, summer, by, thisse, son, of, york); + CYG_TRACE8XB(glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE1YB(glorious); + CYG_TRACE2YB(glorious, summer); + CYG_TRACE3YB(glorious, summer, by); + CYG_TRACE4YB(glorious, summer, by, thisse); + CYG_TRACE5YB(glorious, summer, by, thisse, son); + CYG_TRACE6YB(glorious, summer, by, thisse, son, of); + CYG_TRACE7YB(glorious, summer, by, thisse, son, of, york); + CYG_TRACE8YB(glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE1DB(glorious); + CYG_TRACE2DB(glorious, summer); + CYG_TRACE3DB(glorious, summer, by); + CYG_TRACE4DB(glorious, summer, by, thisse); + CYG_TRACE5DB(glorious, summer, by, thisse, son); + CYG_TRACE6DB(glorious, summer, by, thisse, son, of); + CYG_TRACE7DB(glorious, summer, by, thisse, son, of, york); + CYG_TRACE8DB(glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE1XVB(glorious); + CYG_TRACE2XVB(glorious, summer); + CYG_TRACE3XVB(glorious, summer, by); + CYG_TRACE4XVB(glorious, summer, by, thisse); + CYG_TRACE5XVB(glorious, summer, by, thisse, son); + CYG_TRACE6XVB(glorious, summer, by, thisse, son, of); + CYG_TRACE7XVB(glorious, summer, by, thisse, son, of, york); + CYG_TRACE8XVB(glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE1YVB(glorious); + CYG_TRACE2YVB(glorious, summer); + CYG_TRACE3YVB(glorious, summer, by); + CYG_TRACE4YVB(glorious, summer, by, thisse); + CYG_TRACE5YVB(glorious, summer, by, thisse, son); + CYG_TRACE6YVB(glorious, summer, by, thisse, son, of); + CYG_TRACE7YVB(glorious, summer, by, thisse, son, of, york); + CYG_TRACE8YVB(glorious, summer, by, thisse, son, of, york, stop); + + CYG_TRACE1DVB(glorious); + CYG_TRACE2DVB(glorious, summer); + CYG_TRACE3DVB(glorious, summer, by); + CYG_TRACE4DVB(glorious, summer, by, thisse); + CYG_TRACE5DVB(glorious, summer, by, thisse, son); + CYG_TRACE6DVB(glorious, summer, by, thisse, son, of); + CYG_TRACE7DVB(glorious, summer, by, thisse, son, of, york); + CYG_TRACE8DVB(glorious, summer, by, thisse, son, of, york, stop); + + fn1(); + fn2(); + fn3(); + fn4(); + fn5(); + fn6(); + fn7(); + fn8(); + fn9(); + fn10(); + fn11(); + fn12(1); + fn13(2, 3); + fn14(4, 5, 6); + fn15(7, 8, 9, 10); + fn16(11, 12, 13, 14, 15); + fn17(16, 17, 18, 19, 20, 21); + fn18(22, 23, 24, 25, 26, 27, 28); + fn19(29, 30, 31, 32, 33, 34, 35, 36); + fn20(1); + fn21(2, 3); + fn22(4, 5, 6); + fn23(7, 8, 9, 10); + fn24(11, 12, 13, 14, 15); + fn25(16, 17, 18, 19, 20, 21); + fn26(22, 23, 24, 25, 26, 27, 28); + fn27(29, 30, 31, 32, 33, 34, 35, 36); + fn28(1); + fn29(2, 3); + fn30(4, 5, 6); + fn31(7, 8, 9, 10); + fn32(11, 12, 13, 14, 15); + fn33(16, 17, 18, 19, 20, 21); + fn34(22, 23, 24, 25, 26, 27, 28); + fn35(29, 30, 31, 32, 33, 34, 35, 36); + fn36(1); + fn37(2, 3); + fn38(4, 5, 6); + fn39(7, 8, 9, 10); + fn40(11, 12, 13, 14, 15); + fn41(16, 17, 18, 19, 20, 21); + fn42(22, 23, 24, 25, 26, 27, 28); + fn43(29, 30, 31, 32, 33, 34, 35, 36); + fn44(1); + fn45(2, 3); + fn46(4, 5, 6); + fn47(7, 8, 9, 10); + fn48(11, 12, 13, 14, 15); + fn49(16, 17, 18, 19, 20, 21); + fn50(22, 23, 24, 25, 26, 27, 28); + fn51(29, 30, 31, 32, 33, 34, 35, 36); + fn52(1); + fn53(2, 3); + fn54(4, 5, 6); + fn55(7, 8, 9, 10); + fn56(11, 12, 13, 14, 15); + fn57(16, 17, 18, 19, 20, 21); + fn58(22, 23, 24, 25, 26, 27, 28); + fn59(29, 30, 31, 32, 33, 34, 35, 36); + fn60(1); + fn61(2, 3); + fn62(4, 5, 6); + fn63(7, 8, 9, 10); + fn64(11, 12, 13, 14, 15); + fn65(16, 17, 18, 19, 20, 21); + fn66(22, 23, 24, 25, 26, 27, 28); + fn67(29, 30, 31, 32, 33, 34, 35, 36); + + CYG_TEST_PASS_FINISH("enabled tracing only slows things down"); + return 0; +} +// ---------------------------------------------------------------------------- +// These functions allow "dynamic" control over tracing and reporting. +// The assumption is that the compiler does not know enough about rand() +// to be able to optimise this away. +bool +tracing_is_enabled(void) +{ + return rand() >= 0; +} + +bool +reporting_is_enabled(void) +{ + return rand() >= 0; +} diff --git a/host/infra/testsuite/cyginfra/ttrace3.cxx b/host/infra/testsuite/cyginfra/ttrace3.cxx new file mode 100644 --- /dev/null +++ b/host/infra/testsuite/cyginfra/ttrace3.cxx @@ -0,0 +1,70 @@ +//========================================================================== +// +// ttrace3.cxx +// +// Trace test case +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contributors: bartv +// Date: 1999-01-06 +// Purpose: +// Description: Do an awful lot of tracing, to make sure that the +// circular buffer is circular. +// +//####DESCRIPTIONEND#### +//========================================================================== + + +#define CYGDBG_USE_TRACING +#define CYGDBG_INFRA_DEBUG_FUNCTION_REPORTS +#include +#include +#include + +void +dummy(void) +{ + CYG_REPORT_FUNCNAME("dummy"); + CYG_REPORT_RETURN(); +} + +int +main(int argc, char** argv) +{ + for (int i = 0; i < 1000000; i++) { + CYG_TRACE0(true, "no argument here"); + dummy(); + } + + CYG_TEST_PASS_FINISH("Lots of tracing is possible"); +} + + diff --git a/host/infra/testsuite/cyginfra/ttrace4.cxx b/host/infra/testsuite/cyginfra/ttrace4.cxx new file mode 100644 --- /dev/null +++ b/host/infra/testsuite/cyginfra/ttrace4.cxx @@ -0,0 +1,71 @@ +//========================================================================== +// +// ttrace4.cxx +// +// Trace test case +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contributors: bartv +// Date: 1999-01-06 +// Purpose: +// Description: Do lots of tracing and generate a dump. The test +// harness checks that there is lots of output and +// that the first line matches expectations. +// +//####DESCRIPTIONEND#### +//========================================================================== + + +#define CYGDBG_USE_ASSERTS +#define CYGDBG_USE_TRACING +#define CYGDBG_INFRA_DEBUG_FUNCTION_REPORTS +#include +#include +#include +#include + +void +dummy(void) +{ + CYG_REPORT_FUNCNAME("dummy"); + CYG_REPORT_RETURN(); +} + +int +main(int argc, char** argv) +{ + for (int i = 0; i < 100000; i++) { + CYG_TRACE0(true, "no argument here"); + dummy(); + } + CYG_TRACE0(true, "Goodbye and thanks for all the fish"); + CYG_FAIL("intentional"); +} diff --git a/host/infra/testsuite/lib/cyginfra.exp b/host/infra/testsuite/lib/cyginfra.exp new file mode 100644 --- /dev/null +++ b/host/infra/testsuite/lib/cyginfra.exp @@ -0,0 +1,43 @@ +#=============================================================================== +# +# cyginfra.exp +# +# Support for host-side testing +# +#=============================================================================== +######COPYRIGHTBEGIN#### +# +# ---------------------------------------------------------------------------- +# Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +# +# This file is part of the eCos host tools. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# ---------------------------------------------------------------------------- +# +######COPYRIGHTEND#### +#=============================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): bartv +# Contributors: bartv +# Date: 1998-11-24 +# +#####DESCRIPTIONEND#### +#=============================================================================== + +# At this stage there is nothing useful for this file to do. However its +# existence prevents DejaGnu from issuing a warning. diff --git a/host/infra/trace.cxx b/host/infra/trace.cxx new file mode 100644 --- /dev/null +++ b/host/infra/trace.cxx @@ -0,0 +1,683 @@ +//{{{ Banner + +//============================================================================ +// +// trace.cxx +// +// Host side implementation of the infrastructure trace facilities. +// +//============================================================================ +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================ +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contact(s): bartv +// Date: 1998/12/07 +// Version: 0.01 +// Purpose: To provide a host-side implementation of the eCos tracing +// facilities. +// +//####DESCRIPTIONEND#### +//============================================================================ + +//}}} +//{{{ #include's + +// Make sure that the host-side extensions get prototyped +// as well. Note that the tracing code needs to interact +// with the assertion facilities to set up an appropriate +// callback. +#define CYG_DECLARE_HOST_ASSERTION_SUPPORT +#include "pkgconf/infra.h" +#include "cyg/infra/cyg_type.h" +#include "cyg/infra/cyg_ass.h" + +// Without this #define the tracing enums and prototypes are +// not visible. +#define CYGDBG_USE_TRACING +#include "cyg/infra/cyg_trac.h" + +// The standard C++ string class is used extensively +#include + +// Add a few C headers +#include +#include +#include + +//}}} + +//{{{ Description + +// ------------------------------------------------------------------------- +// The tracing macros end up calling one of the following routines: +// +// void cyg_tracenomsg(cyg_uint32 what, char* fn, char* file, cyg_uint32 line) +// void cyg_tracemsg( ..., char* msg) +// void cyg_tracemsg2( ..., CYG_ADDRWORD arg0, CYG_ADDRWORD arg1 ) +// void cyg_tracemsg4( ..., CYG_ADDRWORD arg0, CYG_ADDRWORD arg1, ... ) +// void cyg_tracemsg6( ..., CYG_ADDRWORD arg0, CYG_ADDRWORD arg1, ... ) +// void cyg_tracemsg8( ..., CYG_ADDRWORD arg0, CYG_ADDRWORD arg1, ... ) +// +// For the 2/4/6/8 variants the msg argument is essentially a printf() +// style format string. However the intention is that the implementation +// of the trace code can delay doing the formatting until the trace +// information is actually needed (with obvious consequences for +// generated strings). Such an implementation would significantly +// reduce the overheads associated with tracing, and is what is implemented +// here. +// +// CYG_ADDRWORD is likely to be either "int" or the platform-specific +// 64 bit data type: it should be big enough to hold either a pointer +// or any normal integral type. This causes problems on machines which +// have e.g. 32 bit int and 64 bit long: any 32 bit quantities will +// have been converted to 64 bit quantities in the calling code, and +// it is no longer possible to just pass the format string to sprintf(). +// Instead what amounts to a re-implementation of sprintf() is needed +// here. +// +// The basic implementation of this trace code is as follows: +// +// 1) a static array of data structures to hold the trace data. The +// size can be configured. There is a current index into this +// array. +// +// 2) the various trace functions simply update this array and the +// counter. +// +// 3) all of the trace functions also check a static to see whether +// or not it is necessary to install a trace handler. This cannot +// be done by means of a static object due to constructor priority +// ordering problems. +// +// 4) the callback function does all the hardware of the formatting +// etc. + +//}}} +//{{{ Types and statics + +// ---------------------------------------------------------------------------- +// A data structure rather than a class is used to hold the trace data. +// This guarantees that the array gets put in the bss section and is properly +// zeroed. A "valid" field in the structure can be checked when dumping the +// array. + +typedef struct trace_entry { + bool valid; + cyg_uint32 what; + cyg_uint32 line; + char* fn; + char* file; + char* msg; + CYG_ADDRWORD data[8]; +} trace_entry; + +#ifndef CYGNUM_INFRA_TRACE_VECTOR_SIZE +# define CYGNUM_INFRA_TRACE_VECTOR_SIZE 2048 +#endif + +static trace_entry tracevec[CYGNUM_INFRA_TRACE_VECTOR_SIZE]; +static volatile int trace_index = 0; + +// Forward declaration of the callback function, for convenience. +static void trace_callback(void (*)(const char*)); + +// Has the callback been installed yet? +static bool callback_installed = false; + +//}}} +//{{{ The trace functions themselves + +// ---------------------------------------------------------------------------- +// The functions that get called by the trace macros. Typically these work +// as follows: +// +// 1) read and increment the trace index. This makes tracing marginally usable +// in multi-threaded systems. +// +// 2) invalidate the entry that is about to be updated. Again this helps a bit +// with multi-threaded systems. +// +// 3) fill in all the fields as per the command-line arguments, zeroing +// unused fields. +// +// 4) set the valid flag to true, which means the contents can now be output. +// +// This is by no means sufficient to guarantee that a call to dump the trace +// vector in some other thread can work safely, but it may help a little bit. + +extern "C" void +cyg_tracenomsg(char* fn, char* file, cyg_uint32 line) +{ + int i = trace_index; + tracevec[i].valid = false; + trace_index = (trace_index + 1) % CYGNUM_INFRA_TRACE_VECTOR_SIZE; + + tracevec[i].what = cyg_trace_trace; + tracevec[i].fn = fn; + tracevec[i].file = file; + tracevec[i].line = line; + tracevec[i].msg = 0; + tracevec[i].data[0] = 0; + tracevec[i].data[1] = 0; + tracevec[i].data[2] = 0; + tracevec[i].data[3] = 0; + tracevec[i].data[4] = 0; + tracevec[i].data[5] = 0; + tracevec[i].data[6] = 0; + tracevec[i].data[7] = 0; + tracevec[i].valid = true; + + if (!callback_installed) { + cyg_assert_install_failure_callback("Trace", &trace_callback); + callback_installed = true; + } +} + +extern "C" void +cyg_tracemsg(cyg_uint32 what, char* fn, char* file, cyg_uint32 line, char* msg) +{ + int i = trace_index; + tracevec[i].valid = false; + trace_index = (trace_index + 1) % CYGNUM_INFRA_TRACE_VECTOR_SIZE; + + tracevec[i].what = what; + tracevec[i].fn = fn; + tracevec[i].file = file; + tracevec[i].line = line; + tracevec[i].msg = msg; + tracevec[i].data[0] = 0; + tracevec[i].data[1] = 0; + tracevec[i].data[2] = 0; + tracevec[i].data[3] = 0; + tracevec[i].data[4] = 0; + tracevec[i].data[5] = 0; + tracevec[i].data[6] = 0; + tracevec[i].data[7] = 0; + tracevec[i].valid = true; + + if (!callback_installed) { + cyg_assert_install_failure_callback("Trace", &trace_callback); + callback_installed = true; + } +} + +extern "C" void +cyg_tracemsg2(cyg_uint32 what, char *fn, char* file, cyg_uint32 line, char *msg, + CYG_ADDRWORD arg0, CYG_ADDRWORD arg1) +{ + int i = trace_index; + tracevec[i].valid = false; + trace_index = (trace_index + 1) % CYGNUM_INFRA_TRACE_VECTOR_SIZE; + + tracevec[i].what = what; + tracevec[i].fn = fn; + tracevec[i].file = file; + tracevec[i].line = line; + tracevec[i].msg = msg; + tracevec[i].data[0] = arg0; + tracevec[i].data[1] = arg1; + tracevec[i].data[2] = 0; + tracevec[i].data[3] = 0; + tracevec[i].data[4] = 0; + tracevec[i].data[5] = 0; + tracevec[i].data[6] = 0; + tracevec[i].data[7] = 0; + tracevec[i].valid = true; + + if (!callback_installed) { + cyg_assert_install_failure_callback("Trace", &trace_callback); + callback_installed = true; + } +} + +extern "C" void +cyg_tracemsg4(cyg_uint32 what, char *fn, char* file, cyg_uint32 line, char *msg, + CYG_ADDRWORD arg0, CYG_ADDRWORD arg1, + CYG_ADDRWORD arg2, CYG_ADDRWORD arg3) +{ + int i = trace_index; + tracevec[i].valid = false; + trace_index = (trace_index + 1) % CYGNUM_INFRA_TRACE_VECTOR_SIZE; + + tracevec[i].what = what; + tracevec[i].fn = fn; + tracevec[i].file = file; + tracevec[i].line = line; + tracevec[i].msg = msg; + tracevec[i].data[0] = arg0; + tracevec[i].data[1] = arg1; + tracevec[i].data[2] = arg2; + tracevec[i].data[3] = arg3; + tracevec[i].data[4] = 0; + tracevec[i].data[5] = 0; + tracevec[i].data[6] = 0; + tracevec[i].data[7] = 0; + tracevec[i].valid = true; + + if (!callback_installed) { + cyg_assert_install_failure_callback("Trace", &trace_callback); + callback_installed = true; + } +} + +extern "C" void +cyg_tracemsg6(cyg_uint32 what, char *fn, char* file, cyg_uint32 line, char *msg, + CYG_ADDRWORD arg0, CYG_ADDRWORD arg1, + CYG_ADDRWORD arg2, CYG_ADDRWORD arg3, + CYG_ADDRWORD arg4, CYG_ADDRWORD arg5) +{ + int i = trace_index; + tracevec[i].valid = false; + trace_index = (trace_index + 1) % CYGNUM_INFRA_TRACE_VECTOR_SIZE; + + tracevec[i].what = what; + tracevec[i].fn = fn; + tracevec[i].file = file; + tracevec[i].line = line; + tracevec[i].msg = msg; + tracevec[i].data[0] = arg0; + tracevec[i].data[1] = arg1; + tracevec[i].data[2] = arg2; + tracevec[i].data[3] = arg3; + tracevec[i].data[4] = arg4; + tracevec[i].data[5] = arg5; + tracevec[i].data[6] = 0; + tracevec[i].data[7] = 0; + tracevec[i].valid = true; + + if (!callback_installed) { + cyg_assert_install_failure_callback("Trace", &trace_callback); + callback_installed = true; + } +} + +extern "C" void +cyg_tracemsg8(cyg_uint32 what, char *fn, char* file, cyg_uint32 line, char *msg, + CYG_ADDRWORD arg0, CYG_ADDRWORD arg1, + CYG_ADDRWORD arg2, CYG_ADDRWORD arg3, + CYG_ADDRWORD arg4, CYG_ADDRWORD arg5, + CYG_ADDRWORD arg6, CYG_ADDRWORD arg7) +{ + int i = trace_index; + tracevec[i].valid = false; + trace_index = (trace_index + 1) % CYGNUM_INFRA_TRACE_VECTOR_SIZE; + + tracevec[i].what = what; + tracevec[i].fn = fn; + tracevec[i].file = file; + tracevec[i].line = line; + tracevec[i].msg = msg; + tracevec[i].data[0] = arg0; + tracevec[i].data[1] = arg1; + tracevec[i].data[2] = arg2; + tracevec[i].data[3] = arg3; + tracevec[i].data[4] = arg4; + tracevec[i].data[5] = arg5; + tracevec[i].data[6] = arg6; + tracevec[i].data[7] = arg7; + tracevec[i].valid = true; + + if (!callback_installed) { + cyg_assert_install_failure_callback("Trace", &trace_callback); + callback_installed = true; + } +} + +//}}} +//{{{ Output callback + +// ---------------------------------------------------------------------------- +// Dumping the output. The assertion code will invoke a single callback +// function, cyg_trace_dummy::trace_callback(), with a function pointer +// that can be used for the actual output. +// +// The trace_callback() function loops through the various entries in the +// vector, ignoring invalid ones, and invoking output_entry() for the +// valid ones. +// +// There are a number of utility routines: +// +// trim_file() is used to take a full pathname and return just the +// final part of it as a C++ string. There is an upper bound on the +// length of this string. +// +// trim_linenum() formats the linenumber sensibly. +// +// trim_function() is used to parse a __PRETTY_FUNCTION__ value +// and produce something more manageable. +// +// parse_msg() is used to construct the full trace message. +// Because of possible 32/64 bit confusion it is not possible +// to just use sprintf() for this. + +static std::string +trim_file(char* file) +{ + // If the output is to look reasonable then the result should be a + // fixed length. 20 characters is reasonable for now. + const int max_filename_len = 20; + + if (0 == file) { + return std::string(max_filename_len, ' '); + } + + // Move to the end of the string, and then back again until + // a directory separator is found. Given the number of levels + // in a typical eCos directory hierarchy it is probably not + // worthwhile outputting any of that information. + char * pEnd = file + strlen(file); + while ((pEnd > file) && ('/' != *pEnd) && ('\\' != *pEnd)) { + pEnd--; + } + if (pEnd != file) + pEnd++; + + std::string result = ""; + int i = 0; + for ( ;(*pEnd != '\0') && (i < max_filename_len); i++, pEnd++) { + result += *pEnd; + } + for ( ; i < max_filename_len; i++) { + result += ' '; + } + + return result; +} + +// The linenumber output should be up to four digits, right-padded +// with spaces. sprintf() will do the trick nicely. + +static std::string +trim_linenum(cyg_uint32 line) +{ + char buf[32]; + sprintf(buf, "%-4d", (int) line); + return buf; +} + +// Extract a function name. On the target side function names +// are usually obtained via __PRETTY_FUNCTION__, and the resulting +// output is a bit on the large side: return value, arguments, etc +// are all included. On the host side the function name is normally +// supplied explicitly and should not be trimmed at all. +// +// Padding is not appropriate since the function name is likely +// to be followed immediately by the argument list. No maximum +// length is imposed - arguably that is a bad idea. +static std::string +trim_function(char* fn) +{ + if (0 == fn) { + return ""; + } + +#if 1 + return fn; +#else + // This implements the target-side behaviour. + // + // First locate the opening bracket. The function name can + // be identified by walking backwards from that. + char *s; + for (s = fn; ('\0' != *s) && ('(' != *s); s++); + for ( ; (s > fn) && (*s != ' '); s--); + if ( s > fn) s++; + + std::string result = ""; + while ( ('\0' != *s) && ('(' != *s) ) + result += *s++; + + return result; +#endif +} + +// The trace format string contained a %s. It is necessary to check +// whether the argument is still valid, and return a suitable +// approximation to the actual data. +static std::string +trim_string(char * arg) +{ + const int max_string_len = 20; + + std::string result = ""; + if (0 == arg) { + return result; + } + int i; + for ( i = 0; (i < max_string_len) && ('\0' != *arg) && isprint(*arg); i++, arg++) { + result += *arg; + } + return result; +} + +// ---------------------------------------------------------------------------- +// Parse a printf() style format string and do the appropriate expansions. +// Because of possible confusion between 32 and 64 bit integers it is not +// possible to use sprintf() itself. +// +// It is assumed that the format string is valid, as are most of the +// arguments. The possible exception is %s arguments where a little bit of +// checking happens first. + +static std::string +parse_msg(char* msg, trace_entry& entry) +{ + if (0 == msg) { + return ""; + } + // Keep track of the number of arguments in the trace_entry + // that have been processed. + int args_index = 0; + + // A utility buffer for sprintf(), e.g. for integer-> string conversions. + char util_buf[64]; + + std::string result = ""; + for ( ; '\0' != *msg; msg++) { + + if ('%' != *msg) { + result += *msg; + continue; + } + + // We have a format string. Extract all of it. + std::string format = "%"; + msg++; + + // The first part of the format string may be one or more flags. + while ( ('-' == *msg) || ('+' == *msg) || (' ' == *msg) || + ('#' == *msg) || ('0' == *msg) ) { + format += *msg++; + } + + // Next comes the width. If this is an asterix it is necessary to + // substitute in an actual argument. + if ('*' == *msg) { + int width = (args_index < 8) ? (int) entry.data[args_index++] : 0; + sprintf(util_buf, "%d", width); + format += util_buf; + msg++; + } else { + // Otherwise the width should be one or more digits + while( isdigit(*msg) ) { + format += *msg++; + } + } + + // Look for a precision, again coping with an asterix. + if ('.' == *msg) { + format += *msg++; + if ('*' == *msg) { + int precision = (args_index < 8) ? (int) entry.data[args_index++] : 0; + sprintf(util_buf, "%d", precision); + format += util_buf; + msg++; + } else { + // The precision should be one or more digits, with an optional - + if ('-' == *msg) { + format += *msg++; + } + while (isdigit(*msg)) { + format += *msg++; + } + } + } + + // Now look for h,l and L. These have to be remembered. + bool short_version = false; + bool long_version = false; + if ('h' == *msg) { + format += *msg++; + short_version = true; + } else if (('l' == *msg) || ('L' == *msg)) { + format += *msg++; + long_version = true; + } + + // The end of the format string has been reached. + int format_ch = *msg; + format += *msg; + + // If we have already formatted too many arguments, there is no point + // in trying to do the actual formatting. + if ( 8 <= args_index ) { + continue; + } + CYG_ADDRWORD val = entry.data[args_index++]; + + switch( format_ch ) { + case '%' : + result += '%'; + break; + + case 'd' : + case 'i' : + case 'o' : + case 'u' : + case 'x' : + case 'X' : + // "format" contains the appropriate format string. + // Invoke sprintf() using util_buf, doing the + // appropriate cast, and then append the output + // of util_buf. + // + // This is not totally robust. If a ridiculous + // precision has been specified then util_buf may + // overflow. + if (long_version) { + sprintf(util_buf, format.c_str(), (long) val); + } else { + // The implicit cast rules mean that shorts do not + // require any special attention. + sprintf(util_buf, format.c_str(), (int) val); + } + result += util_buf; + break; + + case 'c' : + sprintf(util_buf, format.c_str(), (int) val); + result += util_buf; + break; + + case 'p' : + sprintf(util_buf, format.c_str(), (void *) val); + result += util_buf; + break; + + case 's' : + { + std::string data = trim_string((char *) val); + sprintf(util_buf, format.c_str(), data.c_str()); + result += util_buf; + break; + } + + default : + // Any attempt to do floating point conversions would be + // rather tricky given the casts that have been applied. + // There is no point in doing anything for unrecognised + // sequences. + break; + } + } + return result; +} + +// ---------------------------------------------------------------------------- + + +static void +output_entry(void (*pOutputFn)(const char*), trace_entry& entry) +{ + std::string output = trim_file(entry.file) + " " + + trim_linenum(entry.line) + " " + + trim_function(entry.fn) + " "; + if (0 != entry.msg) { + + switch( entry.what) { + case cyg_trace_trace : output += " '"; break; + case cyg_trace_enter : output += "{{"; break; + case cyg_trace_args : output += "(("; break; + case cyg_trace_return : output += "}}"; break; + default : output += " ?"; + } + output += parse_msg(entry.msg, entry); + switch( entry.what) { + case cyg_trace_trace : output += "' "; break; + case cyg_trace_enter : break; + case cyg_trace_args : output += "))"; break; + case cyg_trace_return : break; + default : output += "? "; + } + } + output += "\n"; + (*pOutputFn)(output.c_str()); +} + +static void +trace_callback( void (*pOutputFn)(const char*)) +{ + if ((trace_index < 0) || (trace_index >= CYGNUM_INFRA_TRACE_VECTOR_SIZE)) + return; + + // Start at the last entry and work back down to zero, skipping + // invalid ones. Then go to the top and work back to the current index. + int i; + for (i = trace_index - 1; i >= 0; i--) { + if (tracevec[i].valid) { + output_entry(pOutputFn, tracevec[i]); + } + } + for (i = (CYGNUM_INFRA_TRACE_VECTOR_SIZE - 1); i >= trace_index; i--) { + if (tracevec[i].valid) { + output_entry(pOutputFn, tracevec[i]); + } + } +} + +//}}} diff --git a/host/install-sh b/host/install-sh new file mode 100644 --- /dev/null +++ b/host/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/host/libcdl/ChangeLog b/host/libcdl/ChangeLog new file mode 100644 --- /dev/null +++ b/host/libcdl/ChangeLog @@ -0,0 +1,676 @@ +2000-03-13 John Dallaway + + * cdl.dsp: + Modify libCDL custom build step to calculate the short form + of the host tools root directory to allow rebuilding using an + eCos installation in its default location (containing spaces). + + Use the presence of the last file generated by the + configure phase (the ecosconfig makefile) to determine whether + to invoke configure. This provides some further robustness + against failed or interrupted builds. + +2000-03-08 Simon FitzMaurice + * cdl.dsp : Modify libCDL custom build step to add --enable-maintainer-mode + +2000-03-08 John Dallaway + + * cdl.dsp: + Modify libCDL custom build step to configure in the host tools + directory rather than the root of the eCos repository. + +2000-03-08 Simon FitzMaurice + * cdl.dsp : Modify libCDL custom build step to avoid running configure every time. + +2000-03-07 John Dallaway + + * cdl.dsp: + Modify libCDL custom build step to accommodate the migration + if libCDL sources. + +2000-03-01 Bart Veer + + * expr.cxx (eval_internal): + If there is an eval exception, only manipulate conflicts if we are + in a transaction. + + * value.cxx: + Make the code more robust against eval exceptions + +2000-02-15 Bart Veer + + * build.cxx (generate_config_header): + Fix the symbol that gets used for define properties. + + * package.cxx (get_config_header): + Completely suppress the generation of until + further notice. Allow active_if properties in packages. + Comment a need for default_value properties. + +2000-02-11 John Dallaway + + * cdl.dsp + Configure and make 'quietly' for release builds to help contain + the length of the release logs. + + * cdl.mak: + Remove this obsolete file. + +2000-02-10 Bart Veer + + * package.cxx (parse_package): + Allow packages to have active_if properties. + Add a comment that default_value in a package should be allowed as + a way of controlling enabled/disabled state. + +2000-02-03 Bart Veer + + * infer.cxx (infer_handle_reference_bool): + Earlier fix missed yet more sub-transactions that should have been + cancelled. + +2000-02-02 Bart Veer + + * infer.cxx (infer_make_inactive): + Earlier fix missed a sub-transaction that should have been + cancelled. + + * value.cxx (implements_update_handler): + Also recalculate an interface if the destination is created. + Otherwise an interface will have the wrong value if it is loaded + after all its implementors. + + * infer.cxx, transact.cxx: + Make sure that sub-transactions are either cancelled or committed + before they get deleted. + +2000-01-26 Bart Veer + + * config.cxx (save): + Always output the description field for a standard savefile. + + * base.cxx (save_conflicts): + Add missing newline + + * infer.cxx (infer_subexpr_bool): + Fix the handling of && and || + + * infer.cxx (infer_handle_reference_value): + Do not try modifying inactive data items, there is no point + and it could cause an assertion failure + +2000-01-25 Bart Veer + + * config.cxx: + Extend the savefile support to remember which packages + belong to the hardware and which ones belong to the + template. + +2000-01-24 Bart Veer + + * cdlcore.hxx, parse.cxx, wizard.cxx (parse_screen): + Change parse_property_options() to parse_options() so that it can + be used for more than just properties + + * cdlcore.hxx, config.cxx: + Make sure that a LocalTransaction always gets cancelled if + things go wrong and an exception is thrown, prior to the + transaction being deleted. + + * base.cxx, interp.cxx, value.cxx: + Savefile format tweaks. + +2000-01-21 Bart Veer + + * base.cxx (add_node_to_toplevel): + When a loadable was re-added to the toplevel after an unload was + cancelled, its parent was not set correctly. + + * infer.cxx: + Add partial support for dependencies of the form X==Y + +2000-01-20 Bart Veer + + * Makefile.am, Makefile.in: + Fix dependencies for interface.cxx and transact.cxx, these + were sometimes rebuilt unnecessarily + + * cdlcore.hxx, base.cxx, transact.cxx, config.cxx, package.cxx: + All file I/O related operations now happen in the context + of a transaction. + +1999-12-17 Bart Veer + + * cdl.hxx, config.cxx, database.cxx: + Add support for set_value commands in ecos.db target entries. + + * database.cxx: + Remove old support for template definitions in ecos.db + +1999-12-16 Bart Veer + + * nearly all files: + Add support for memory leak detection, by maintaining per-class + object counts via the appropriate constructors and destructors. + + * database.cxx: + Plug a one-off memory leak. + +1999-12-14 John Dallaway + + * interp.cxx: + Modify CdlInterpreterBody::locate_subdirs(), + CdlInterpreterBody::locate_files(), + CdlInterpreterBody::is_directory() and + CdlInterpreterBody::is_file() to accommodate + spaces in paths. + +1999-12-13 Bart Veer + + * cdlcore.hxx, interface.cxx, transact.cxx, value.cxx: + Calculate values for interfaces. + + * base.cxx, cdl.hxx, cdlcore.hxx, component.cxx, config.cxx, + database.cxx, dialog.cxx, interface.cxx, interp.cxx, option.cxx, + package.cxx, value.cxx, wizard.cxx: + Implementation of templates in the form of the partial savefiles. + +1999-12-10 John Dallaway + + * cdlcore.hxx: + Use '#pragma warning()' under VC++ only. + +1999-12-09 Bart Veer + + * cdlmisc.cxx (compare_versions): + V1.3.1 and V1.3B6 were not compared correctly. + +1999-12-03 Bart Veer + + * build.cxx (update_header_file_info): + If a package has no include subdirectory and no include_files + property, search the package directory tree for anything + resembling a header file and install that. + +1999-11-30 Bart Veer + + * base.cxx: + Made the multiple conflict solution code more robust when side + effects occur. + + * transact.cxx: + When a new conflict is committed and becomes global its solution + must be cleared, since no attempt is made to preserve the validity + of global solutions. + + * transact.cxx (resolve): + Try to make sure that the inference callback gets invoked whenever + appropriate. + + * base.cxx: + When resolving multiple global conflicts, fixing the first one may + have the side effect of fixing subsequent ones as well, resulting + in an assertion failure because the inference engine reported a + success with no changes being required. This situation is now + checked for. + + * parse.cxx (parse_property_options): + Allow for a NULL options descriptor + +1999-11-28 Bart Veer + + * transact.cxx: + Global conflict resolution support + + * infer.cxx: + Clean-up for resolving global conflicts + Cancel undesirable transactions before they are deleted + + * conflict.cxx: + Add support for resolving global conflicts + Implement get_transaction() member + + * cdlcore.hxx: + Add support for resolving global conflicts + Tidy up the transaction and transaction callback classes a bit. + + * base.cxx: + Add support for resolving global conflicts + +1999-11-26 John Dallaway + + * build.cxx: + Modify CdlToplevelBody::generate_config_headers() and + compare_and_copy() to accommodate spaces in the path to the + headers directory. + +1999-11-23 Bart Veer + + * database.cxx (new_target): + command_prefix is no longer compulsory for ecos.db target entries, + since this is now handled in the config data. command_prefix and + cflags are still allowed in ecos.db for now, but will be removed + in future. + +1999-11-22 Bart Veer + + * base.cxx: + During an unload operation a conflict may be cleared for multiple + reasons: the requires condition may now be satisfied, e.g + "requires !xxx" where "xxx" is also being unloaded; and the + node containing the requires property may be disappearing as well. + + * transact.cxx (save_solution): + If any parts of a solution involve calculated options then there + is no point in exposing this to the user. The re-calculation will + happen automatically during the next propagation. + + * base.cxx: + * config.cxx: + Stop the inference engine from running when packages are loaded or + unloaded. The user has no opportunity to cancel or undo the + operation, and there may be unexpected behaviour because the + inference engine has no clear view of what the overall + configuration is going to be. + + * transact.cxx (resolve): + Resolving one conflict may affect others in the new_conflicts + list. Using an iterator to examine all conflicts is a bad idea. + Instead each loop needs to search for a conflict that may + have a solution. + + * base.cxx: + * config.cxx: + * cdlcore.hxx: + Rearrange how a CdlConfiguration gets destroyed, to allow dynamic + casts to be used on the toplevel as packages are unloaded. + +1999-11-22 John Dallaway + + * config.cxx: + Modify CdlConfigurationBody::load_package() to accommodate + spaces in the path to the eCos repository. + +1999-11-21 Bart Veer + + * infer.cxx: + * transact.cxx: + * cdlcore.hxx: + First implementation of inference code + + * conflict.cxx: + Added missing is_structural() member + +1999-11-18 Bart Veer + + * value.cxx: + Created a CdlSimpleValue constructor for booleans, to match the + assignment operator. + + * expr.cxx : + Modify list expression evaluation code so that any terms which + evaluate to empty strings are discarded. + +1999-11-08 Bart Veer + + * database.cxx: + Switched to ECOS_REPOSITORY environment variable. + + * transact.cxx: + * cdlcore.hxx: + Separated out normal and structural conflicts in the transaction + callback class. + + * value.cxx: + * interp.cxx: + * cdlcore.hxx: + Added new member CdlInterpreterBody::extend_comment(), for better + support of multiline comments in savefiles. + +1999-11-03 Bart Veer + + * cdlcore.hxx, base.cxx, transact.cxx, value.cxx: + Newly loaded nodes were starting out as active, and were not being + turned inactive if the parent was disabled. By default nodes are + now inactive and there is explicit code in the transaction + propagate member function to check whether or not each node should + be active. + + * Most files + Install the new transaction model + +1999-11-03 John Dallaway + + * value.cxx: + Apply patch to correct the omission of a comment char from + continuation lines of calculated value comments in + configuration save files. + +1999-10-25 Simon FitzMaurice + * value.cxx: + Apply fix (supplied by Bart) to correct omission of comment symbol + from start of second and subsequent lines of split statement. + +1999-10-14 Bart Veer + + * database.cxx: + * cdl.hxx: + Add support for new per-target commands enable and disable, + which provide limited control over hardware-related configuration + options. + + * config.cxx (set_hardware): + Process per-target enable/disable commands from the database + +1999-10-12 John Dallaway + + * build.cxx (generate_config_headers): + + Workaround problem with assignment of standard channels + which was causing system.h to not be generated. + +1999-10-08 John Dallaway + + * cdl.dsp, cdl.mak: + + Link against Tcl 8.2.1. + +1999-10-07 Bart Veer + + * value.cxx (get_widget_hint): + For some expressions this was corrupting the expression data, + because of the use of a reference rather than a pointer. + +1999-10-06 Bart Veer + + * cdlcore.hxx, database.cxx, expr.cxx, interface.cxx, value.cxx + Partial implementations of interfaces and get_widget_hint() + +1999-09-28 Bart Veer + + * interp.cxx: + Fix use of an uninitialized variable. + + * config.cxx: + Fix the handling of package versions in save files. + +1999-09-15 Bart Veer + + * value.cxx + Fix output of multiline legal_values expressions + + * value.cxx + Fix variable that might be used uninitialized. + + * all files + First implementation of the savefile support + +1999-09-07 John Dallaway + + * cdl.dsp, cdl.mak: + + Add ANSI build configurations. + +1999-09-07 John Dallaway + + * cdl.dsp, cdl.mak: + + Update libCDL project file and VC++ makefile to use current + configure switches. + +1999-08-12 Bart Veer + + * configure.in: + * configure: + * stamp-h.in: + First attempt at autoconfiscating the configtool + +1999-08-10 Bart Veer + + * expr.cxx, value.cxx: + Fixed some problems related to double precision numbers. + +1999-08-03 Bart Veer + + * parse.cxx: + Added an implementation of the "unknown" command which + goes via the normal diagnostics routines. + +1999-07-22 Bart Veer + + * cdlcore.hxx, value.cxx, expr.cxx, cdlmisc.cxx: + Try to preserve some input data formatting information, such as + whether a number appeared as decimal or hexadecimal. + +1999-07-21 Bart Veer + + * value.cxx: + Added some assertions to make sure that entities with a + "calculated" property cannot be modified. + +1999-07-20 Bart Veer + + * value.cxx, transact.cxx: + Fixed some value propagation problems. + + * cdlcore.hxx, value.cxx, expr.cxx: + Detect invalid numbers in expressions. + A CdlListValue object now contains a single vector of + CdlSimpleValue objects, not separate vectors of strings, integers + and doubles. This allows ordering to be preserved. + + * most files: + Sync development version with repository, there is now + full value support. + +1999-07-13 Bart Veer + + * expr.cxx: + Implement operator precedence + Fix parsing of conditional expressions. + +1999-07-12 Bart Veer + + * most files: + Sync development version with repository, there is now partial + expression support. + +1999-07-05 Bart Veer + + * all files: + Merge development work from the libcdl branch. + + +1999-06-10 John Dallaway + + * cdl.dsp: + Convert to a Visual C++ utility project. + +1999-06-08 John Dallaway + + * cdl.dsp: + Project file outputs libCDL to the project-specified output + directory rather than the intermediate directory + +1999-06-07 John Dallaway + + * cdl.dsp: + Project file is no-longer dependent on the ECOSHOME environment + variable + +1999-06-07 John Dallaway + + * cdl.dsp: + New Visual C++ 6.0 project file for libCDL + +1999-06-03 Bart Veer + + * configure: + Regenerated again after further updates to toplevel acinclude.m4 + +1999-06-02 Bart Veer + + * configure: + Regenerated after updating toplevel acinclude.m4, new + --enable-debuginfo option. + + * libcdl.hxx: + CdlBaseBody is now an ordinary base class for CdlContainerBody, + not a virtual base class, allowing old-style casts inside the + config tool to work. There is no need for virtual inheritance just + yet. + The CdlGoalExpressionBody copy constructor is now public, not + protected, for use by the config tool. + +1999-05-24 Bart Veer + + * package.cxx: + * component.cxx: + * option.cxx: + * base.cxx: + * libcdl.hxx: + Allow target and platform properties inside components and + options, and startup properties inside packages and components, + for continued compatibility with libnotcdl. + +1999-03-10 Bart Veer + + * option.cxx (parse_option): + * component.cxx (parse_component): + Fixed the handling of container inheritance for full libnotcdl + compatibility. + +1999-03-09 Bart Veer + + * parse.cxx (parse_...expression_property): + Do not try to parse options just yet, there is confusion if + the expression begins with a negative number. + +1999-03-08 Bart Veer + + * interp.cxx (eval): + Make sure that C strings passed to the Tcl interpreter + are properly terminated. + + * property.cxx: + Remove strict checking of property id's, so that the library + code can be re-used for other purposes e.g. hardware CDL. + + * expr.cxx: + Added temporary parsers for libnotcdl compatibility. + + * cdlmisc.cxx: + Added routines to convert between strings and flavors. + Added routines to validate CDL names. + Minor layout tweaks. + + * README: + Examples now refer to Tcl8.1b1 instead of 8.1a2, the alpha + version caused problems. + + +1999-02-02 Bart Veer + + * testsuite/libcdl/cdl1.cxx (test_double_to_string): + * cdlmisc.cxx (string_to_double): + Added double conversion support, needed for the CdlResult class + + * testsuite/libcdl/cdl5.cxx (main): + * database.cxx: + Change CdlInputOutputError to CdlInputOutputException in the + interests of a more consistent naming convention. + +1999-01-29 Bart Veer + + * interp.cxx (eval): + Add new member function to evaluate Tcl code embedded in + CDL data. + + * cdlmisc.cxx (is_valid_property_id): + Added the properties IncludeDir and ExportTo, and the flavor "dummy" + + +1999-01-26 Bart Veer + + * testsuite/libcdl/cdl4.cxx: + * testsuite/libcdl/cdl1.cxx (test_string_to_integer): + Change array initializers to avoid having to supply a constructor. + + * aclocal.m4: + * config.h.in: + * configure: + * stamp-h.in: + * testsuite/Makefile.in: + Updated to use autoconf 2.13 and automake 1.4, plus to reflect + tweaks to toplevel acinclude.m4 and local configure.in + + * configure.in: + No longer insist on the infra having been built already. This + allows a configure from the top-level to work. + + * testsuite/libcdl/cdl4.cxx: + Changed the initializer for a static array of structures to work + around compiler problems. + + * testsuite/libcdl/cdl3.cxx (main): + Changed the way inline Tcl scripts are defined to avoid compiler + problems. + + * testsuite/libcdl/cdl2.cxx (main): + Added missing return statement to avoid compiler warning. + + * testsuite/config/default.exp: + Use new variable cyg_ac_tcl_libs + + * interp.cxx (eval): + Do not distinguish between TCL_OK and TCL_RETURN return codes, + clients are unlikely to be interested. + Fix definition of set_assoc_data(). + + * cdlmisc.cxx (compare_versions): + Fix syntax problem in while loop. + +1999-01-22 Bart Veer + + * interp.cxx + (set_assoc_data): added new functions so that clients can + associate arbitrary data with interpreters + (set_variable) : and to provide access to Tcl global variables. + (make_safe) : also, the ability to make an interpreter safe. + (set_result) : not to mention, controlling the result field. + + * cdlmisc.cxx (compare_versions): + Added new function Cdl::compare_versions() + +1999-01-21 Bart Veer + + * cdlmisc.cxx + Added routines get_library_version(), set_interactive() and + get_interactive(). + +//=========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//=========================================================================== \ No newline at end of file diff --git a/host/libcdl/Makefile.am b/host/libcdl/Makefile.am new file mode 100644 --- /dev/null +++ b/host/libcdl/Makefile.am @@ -0,0 +1,159 @@ +## Process this file with automake to produce Makefile.in +## ===================================================================== +## +## Makefile.am +## +## libcdl.a +## +## ===================================================================== +######COPYRIGHTBEGIN#### +## +## ---------------------------------------------------------------------------- +## Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +## +## This file is part of the eCos host tools. +## +## This program is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 of the License, or (at your option) +## any later version. +## +## This program is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +## more details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +## +## ---------------------------------------------------------------------------- +## +######COPYRIGHTEND#### +## ===================================================================== +#######DESCRIPTIONBEGIN#### +## +## Author(s): bartv +## Contact(s): bartv +## Date: 1998/12/16 +## Version: 0.01 +## +######DESCRIPTIONEND#### +## ===================================================================== + +AUTOMAKE_OPTIONS = 1.3 cygnus +SUBDIRS = testsuite + +## Pick up an appropriate header file search path from configure +INCLUDES = @INCLUDES@ + +## This package exports its interface via cdl.hxx +include_HEADERS = cdlcore.hxx cdl.hxx + +## The main target is a static library. The problem is naming it +## correctly. automake seems to insist on calling it libcdl.a, +## even when compiling it with VC++. Various attempts to use +## cdl.lib instead with VC++ have failed. Instead the library +## will always be built as libcdl.a, but gets copied to cdl.lib +## when necessary. + +sources := interp.cxx \ + expr.cxx \ + refer.cxx \ + cdlmisc.cxx \ + conflict.cxx \ + property.cxx \ + parse.cxx \ + base.cxx \ + value.cxx \ + build.cxx \ + dialog.cxx \ + wizard.cxx \ + interface.cxx \ + transact.cxx \ + infer.cxx \ + database.cxx \ + config.cxx \ + package.cxx \ + component.cxx \ + option.cxx + +noinst_LIBRARIES = libcdl.a +libcdl_a_SOURCES = $(sources) + +if MSVC +all-local: cdl.lib + +cdl.lib: libcdl.a + $(INSTALL) $< $@ + +clean-local: + $(RM) cdl.lib + +install-exec-local: all-local + $(mkinstalldirs) $(DESTDIR)$(libdir) + $(INSTALL) cdl.lib $(DESTDIR)$(libdir)/cdl.lib + +else + +all-local: +clean-local: +install-exec-local: libcdl.a + $(mkinstalldirs) $(DESTDIR)$(libdir) + $(INSTALL) libcdl.a $(DESTDIR)$(libdir)/libcdl.a +endif + + +## Add specific dependencies for all source files. +## Every module in libcdl uses assertions and tracing. +## These pull in the others. +infra_headers := $(cyg_ac_infra_incdir)/cyg/infra/cyg_ass.h \ + $(cyg_ac_infra_incdir)/cyg/infra/cyg_trac.h \ + $(cyg_ac_infra_incdir)/pkgconf/infra.h \ + $(cyg_ac_infra_incdir)/pkgconf/hostinfra.h \ + $(cyg_ac_infra_incdir)/cyg/infra/cyg_type.h + +## Depending on the flavor of CDL being implemented, different +## headers will get included. +cdlcore_headers := cdlconfig.h cdlcore.hxx +cdl_headers := $(cdlcore_headers) cdl.hxx + +interp.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +expr.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +refer.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +cdlmisc.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +conflict.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +property.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +parse.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +base.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +value.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +build.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +dialog.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +wizard.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +interface.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +transact.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +database.$(OBJEXT) : Makefile $(cdl_headers) $(infra_headers) + +config.$(OBJEXT) : Makefile $(cdl_headers) $(infra_headers) + +package.$(OBJEXT) : Makefile $(cdl_headers) $(infra_headers) + +component.$(OBJEXT) : Makefile $(cdl_headers) $(infra_headers) + +option.$(OBJEXT) : Makefile $(cdl_headers) $(infra_headers) + + diff --git a/host/libcdl/Makefile.in b/host/libcdl/Makefile.in new file mode 100644 --- /dev/null +++ b/host/libcdl/Makefile.in @@ -0,0 +1,536 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 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. + +######COPYRIGHTBEGIN#### +######COPYRIGHTEND#### +#######DESCRIPTIONBEGIN#### +######DESCRIPTIONEND#### + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = . + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CC = @CC@ +CXX = @CXX@ +EXEEXT = @EXEEXT@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +VERSION = @VERSION@ +cyg_ac_infra_incdir = @cyg_ac_infra_incdir@ +cyg_ac_infra_libdir = @cyg_ac_infra_libdir@ +cyg_ac_tcl_incdir = @cyg_ac_tcl_incdir@ +cyg_ac_tcl_libdir = @cyg_ac_tcl_libdir@ +cyg_ac_tcl_libs = @cyg_ac_tcl_libs@ +cyg_ac_tcl_version = @cyg_ac_tcl_version@ +cyg_ac_tk_libs = @cyg_ac_tk_libs@ + +AUTOMAKE_OPTIONS = 1.3 cygnus +SUBDIRS = testsuite + +INCLUDES = @INCLUDES@ + +include_HEADERS = cdlcore.hxx cdl.hxx + +sources := interp.cxx expr.cxx refer.cxx cdlmisc.cxx conflict.cxx property.cxx parse.cxx base.cxx value.cxx build.cxx dialog.cxx wizard.cxx interface.cxx transact.cxx infer.cxx database.cxx config.cxx package.cxx component.cxx option.cxx + + +noinst_LIBRARIES = libcdl.a +libcdl_a_SOURCES = $(sources) + +infra_headers := $(cyg_ac_infra_incdir)/cyg/infra/cyg_ass.h $(cyg_ac_infra_incdir)/cyg/infra/cyg_trac.h $(cyg_ac_infra_incdir)/pkgconf/infra.h $(cyg_ac_infra_incdir)/pkgconf/hostinfra.h $(cyg_ac_infra_incdir)/cyg/infra/cyg_type.h + + +cdlcore_headers := cdlconfig.h cdlcore.hxx +cdl_headers := $(cdlcore_headers) cdl.hxx +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs +CONFIG_HEADER = cdlconfig.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +libcdl_a_LIBADD = +libcdl_a_OBJECTS = interp.$(OBJEXT) expr.$(OBJEXT) refer.$(OBJEXT) \ +cdlmisc.$(OBJEXT) conflict.$(OBJEXT) property.$(OBJEXT) parse.$(OBJEXT) \ +base.$(OBJEXT) value.$(OBJEXT) build.$(OBJEXT) dialog.$(OBJEXT) \ +wizard.$(OBJEXT) interface.$(OBJEXT) transact.$(OBJEXT) infer.$(OBJEXT) \ +database.$(OBJEXT) config.$(OBJEXT) package.$(OBJEXT) \ +component.$(OBJEXT) option.$(OBJEXT) +AR = ar +CXXFLAGS = @CXXFLAGS@ +CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ +HEADERS = $(include_HEADERS) + +DIST_COMMON = ./stamp-h.in ChangeLog Makefile.am Makefile.in TODO \ +acconfig.h acinclude.m4 aclocal.m4 config.h.in configure configure.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +SOURCES = $(libcdl_a_SOURCES) +OBJECTS = $(libcdl_a_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .cxx .o .obj .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --cygnus Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ configure.in acinclude.m4 + cd $(srcdir) && $(ACLOCAL) + +config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck +$(srcdir)/configure: @MAINTAINER_MODE_TRUE@$(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +cdlconfig.h: stamp-h + @if test ! -f $@; then \ + rm -f stamp-h; \ + $(MAKE) stamp-h; \ + else :; fi +stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES= CONFIG_HEADERS=cdlconfig.h:config.h.in \ + $(SHELL) ./config.status + @echo timestamp > stamp-h 2> /dev/null +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@$(srcdir)/stamp-h.in + @if test ! -f $@; then \ + rm -f $(srcdir)/stamp-h.in; \ + $(MAKE) $(srcdir)/stamp-h.in; \ + else :; fi +$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h + cd $(top_srcdir) && $(AUTOHEADER) + @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null + +mostlyclean-hdr: + +clean-hdr: + +distclean-hdr: + -rm -f cdlconfig.h + +maintainer-clean-hdr: + +mostlyclean-noinstLIBRARIES: + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +distclean-noinstLIBRARIES: + +maintainer-clean-noinstLIBRARIES: + +.c.o: + $(COMPILE) -c $< + +# FIXME: We should only use cygpath when building on Windows, +# and only if it is available. +.c.obj: + $(COMPILE) -c `cygpath -w $<` + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + -rm -f *.$(OBJEXT) + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +libcdl.a: $(libcdl_a_OBJECTS) $(libcdl_a_DEPENDENCIES) + -rm -f libcdl.a + $(AR) cru libcdl.a $(libcdl_a_OBJECTS) $(libcdl_a_LIBADD) + $(RANLIB) libcdl.a +.cxx.o: + $(CXXCOMPILE) -c $< +.cxx.obj: + $(CXXCOMPILE) -c `cygpath -w $<` + +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(includedir) + @list='$(include_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d= ; else d="$(srcdir)/"; fi; \ + echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/$$p"; \ + $(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/$$p; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + list='$(include_HEADERS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(includedir)/$$p; \ + done + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. + +@SET_MAKE@ + +all-recursive install-data-recursive install-exec-recursive \ +installdirs-recursive install-recursive uninstall-recursive install-info-recursive \ +check-recursive installcheck-recursive info-recursive dvi-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ + rev="$$subdir $$rev"; \ + test "$$subdir" = "." && dot_seen=yes; \ + done; \ + test "$$dot_seen" = "no" && rev=". $$rev"; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + -rm -rf $(distdir) + GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + dc_install_base=`cd $(distdir)/=inst && pwd`; \ + cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) dist + -rm -rf $(distdir) + @banner="$(distdir).tar.gz is ready for distribution"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes" +dist: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +dist-all: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +distdir: $(DISTFILES) + -rm -rf $(distdir) + mkdir $(distdir) + -chmod 777 $(distdir) + @for file in $(DISTFILES); do \ + if test -f $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + cp -pr $$/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + for subdir in $(SUBDIRS); do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + chmod 777 $(distdir)/$$subdir; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \ + || exit 1; \ + fi; \ + done +info-am: +info: info-recursive +dvi-am: +dvi: dvi-recursive +check-am: +check: check-recursive +installcheck-am: +installcheck: installcheck-recursive +install-info-am: +install-info: install-info-recursive +all-recursive-am: cdlconfig.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +install-exec-am: install-exec-local +install-exec: install-exec-recursive + +install-data-am: install-includeHEADERS +install-data: install-data-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-recursive +uninstall-am: uninstall-includeHEADERS +uninstall: uninstall-recursive +all-am: Makefile $(LIBRARIES) $(HEADERS) cdlconfig.h all-local +all-redirect: all-recursive-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: installdirs-recursive +installdirs-am: + $(mkinstalldirs) $(DESTDIR)$(includedir) + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-hdr mostlyclean-noinstLIBRARIES \ + mostlyclean-compile mostlyclean-tags \ + mostlyclean-generic + +mostlyclean: mostlyclean-recursive + +clean-am: clean-hdr clean-noinstLIBRARIES clean-compile clean-tags \ + clean-generic mostlyclean-am clean-local + +clean: clean-recursive + +distclean-am: distclean-hdr distclean-noinstLIBRARIES distclean-compile \ + distclean-tags distclean-generic clean-am + +distclean: distclean-recursive + -rm -f config.status + +maintainer-clean-am: maintainer-clean-hdr \ + maintainer-clean-noinstLIBRARIES \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-recursive + -rm -f config.status + +.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \ +mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ +clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile uninstall-includeHEADERS \ +install-includeHEADERS install-data-recursive uninstall-data-recursive \ +install-exec-recursive uninstall-exec-recursive installdirs-recursive \ +uninstalldirs-recursive all-recursive check-recursive \ +installcheck-recursive info-recursive dvi-recursive \ +mostlyclean-recursive distclean-recursive clean-recursive \ +maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ +distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-info-am \ +install-info all-recursive-am install-exec-local install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-local all-redirect all-am all installdirs-am \ +installdirs mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +@MSVC_TRUE@all-local: cdl.lib + +@MSVC_TRUE@cdl.lib: libcdl.a +@MSVC_TRUE@ $(INSTALL) $< $@ + +@MSVC_TRUE@clean-local: +@MSVC_TRUE@ $(RM) cdl.lib + +@MSVC_TRUE@install-exec-local: all-local +@MSVC_TRUE@ $(mkinstalldirs) $(DESTDIR)$(libdir) +@MSVC_TRUE@ $(INSTALL) cdl.lib $(DESTDIR)$(libdir)/cdl.lib + +@MSVC_FALSE@all-local: +@MSVC_FALSE@clean-local: +@MSVC_FALSE@install-exec-local: libcdl.a +@MSVC_FALSE@ $(mkinstalldirs) $(DESTDIR)$(libdir) +@MSVC_FALSE@ $(INSTALL) libcdl.a $(DESTDIR)$(libdir)/libcdl.a + +interp.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +expr.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +refer.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +cdlmisc.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +conflict.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +property.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +parse.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +base.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +value.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +build.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +dialog.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +wizard.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +interface.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +transact.$(OBJEXT) : Makefile $(cdlcore_headers) $(infra_headers) + +database.$(OBJEXT) : Makefile $(cdl_headers) $(infra_headers) + +config.$(OBJEXT) : Makefile $(cdl_headers) $(infra_headers) + +package.$(OBJEXT) : Makefile $(cdl_headers) $(infra_headers) + +component.$(OBJEXT) : Makefile $(cdl_headers) $(infra_headers) + +option.$(OBJEXT) : Makefile $(cdl_headers) $(infra_headers) + +# 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/host/libcdl/TODO b/host/libcdl/TODO new file mode 100644 --- /dev/null +++ b/host/libcdl/TODO @@ -0,0 +1,219 @@ + TODO List + --------- + +Minor +----- + +1) savefile support. Add option handling to the remaining savefile + commands, even if no options are currently defined. + +2) remember unrecognised options so that they can be written back + when the savefile is regenerated. Perhaps add option details + to the header? + +3) allow re-parenting below "". Make the orphans container disabled? + +4) get limbo working + +5) make cdl_interfaces into containers? How about cdl_options as well, + to avoid reparenting problems? + +6) allow components and options to be used interchangeably in savefiles. + +7) ecosconfig, create a paths file with details of the source tree + location etc? How about reporting the paths? + + > Huge> How about: put information about the source tree into the savefile BUT you + > Huge> can put + > Huge> ecosconfig --srcdir=/home/hmt/work/ecc/net/ecc/ecc + > Huge> and it'll say "Oi! You've changed the repository! Override [y/n]?" + > Huge> That lets you move them 'round. + > + > That is a possibility, but I am reluctant to add any interactive + > facilities to ecosconfig just yet + + OK, instead: + % ecosconfig --srcdir=/home/hmt/work/ecc/net/ecc/ + ecosconfig: Oi! You've changed the repository! Quitting. + ecosconfig: [Hint: Use --new-srcdir to override.] + % ecosconfig --new-srcdir=/home/hmt/work/ecc/net/ecc/ + ecosconfig: new repository selected: /home/hmt/work/ecc/net/ecc/ + % _ + There's interactive and interactive... ;-) + [*enable anyone? ;-)] + +8) savefiles, if an interface has no implementors then say so. + +9) CDL filenames in the savefile? This might be useful for people + wanting to look at the CDL sources, although all the interesting + information should already be in the savefile. + +10) what happens if a source file is listed for two separate options? + +11) define -format="\\\"%s\\\"" XYZ + This seems to do the wrong thing. Consider: + + cdl_option CYGNUM_LIBC_MAX_LOCALE_NAME_SIZE { + define -format="\\\"%s\\\"" XYZ + ... + } + + The output is: + + #define CYGNUM_LIBC_MAX_LOCALE_NAME_SIZE "16" + #define XYZ_16 + + BLV - may have been fixed on Feb 14th + +12) define -format="\"%s\"" XYZ + + This gives an internal error. Should it? + +13) make-object, check for priorities less than 200. It is not + sensible to build an object after the library has been + constructed. Also check that the target is a .o file. + +14) exported header files. Suppress obvious problems such as + CVS subdirectories and files ending with ~. See pkgconf::locate_files. + +15) diagnostics for inappropriate templates, e.g. the stubs template on simulators. + +16) custom build steps and generating exported header files. + + Priorities of custom build steps that should go before header file + generation? + Use of include_files property. + +17) what happens when several packages specify the same define_header? + +18) evalexception conflicts. What should happen if the node is disabled or inactive? + Especially if it is the default_value expression that is causing the problem. + +Intermediate +------------ + +1) integrate the makefile generation support into libcdl. + +2) implement the Tcl interface to the CDL data, especially tcl_get + and the appropriate Tcl variables. + +3) full definition of custom build steps and the build procedure + generally, including working out what should happen for + compiler flags. + + Dependency analysis in custom build steps. + +4) get safe interpreters working, and make sure that only safe + file I/O operations are permitted. + +5) diagnostic messages. These need to follow a suitable convention and + made generally more comprehensible. + + Huge> Oh yeah, if the cdl file quoted to a script in a package in ecos.db is + Huge> mis-named, there error message is something about "no package + Huge> versions found" - a simple "file not found: + Huge> /masala/hmt/work/ecc/net/ecc/ecc/net/drivers/eth/ebsa285/*/cdl/ebsa285_eth_drivers.cdl" + Huge> would be far more informative. + +6) extend the inference engine to support more operators. + +7) support disabled conflicts. + +8) full implementation of interfaces, including automatic creation. + +9) text aliases for legal_values lists? + +10) savefiles do not list `implements' properties + +11) ecosconfig verbosity. Add --silent and --verbose modes? + +12) header file dependencies. From Jesper and others: + + One alternative way of handling this is the way it's done in Linux + (which happened around 2.2.?, I think, and made for some + phenomenal build speedups): + + grep each source file foo.c for use of CYGxxx_ macros. Cat this list + into .foo.c.config_deps (or similar) with proper mangling so it + becomes a GCC dependency file (for foo.c) on "option files". + + Each option, opt_name, thus adds a dependency on + $build/config_deps/CYGxxx_opt_name. Whenever changing the config, + touch the relevant config_deps/ files. + + In short: when making general source file dependencies, exclude any + dependencies on $install/include/pkgconf/* and replace with + appropriate $build/config_deps/* dependencies. That makes for one + smoooking fast dependency system. It doesn't get finer-grained than + this. + +Major +----- + +1) implement and integrate a proper infrastructure. Generally sort out + the host-side build tree, including making libcdl into a Tcl + package. + +2) sort out the test suites. + +3) std::bad_alloc exceptions. These can happen just about anywhere. + Lots of places need to be hardened against this to avoid memory + leaks. A completely robust system is probably not possible + because cancelling a transaction may involve memory allocation. + +4) general code walk through to look for obvious inefficiencies, e.g. + passing things by value rather than by reference. + +5) generalise the build support for other languages such as Java. + +6) implement a proper database and associated admin tool. + +7) improved autoconfiscation support, in particular finding the + appropriate platform-specific library support. + +8) a suitable naming convention for data members and for arguments to + inline functions should be adopted, to prevent collisions with + #define'd symbols in application land. Possibilities include + _X_ and __X. + +9) work out how to extend Tcl to provide line number information. + +10) i18n support. + +11) currently the data type cdl_int is defined to be 64 bits. This should + probably be changed to arbitrary precision, so that e.g. processors + which can perform 128 bit arithmetic can be adequately supported. + +12) extend the CDL expression syntax with e.g. string operators. This + will impact the inference engine. + +13) add an interactive mode to ecosconfig resolve, allowing users to + confirm or cancel solutions? + +//=========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//=========================================================================== + diff --git a/host/libcdl/acconfig.h b/host/libcdl/acconfig.h new file mode 100644 --- /dev/null +++ b/host/libcdl/acconfig.h @@ -0,0 +1,60 @@ +#ifndef CYGONCE_LIBCDL_CONFIG_H +# define CYGONCE_LIBCDL_CONFIG_H + +//====================================================================== +// +// acconfig.h +// +// Configuration header for libcdl +// +//====================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//====================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contact(s): bartv +// Date: 1998/12/17 +// Version: 0.01 +// +//####DESCRIPTIONEND#### +//====================================================================== + +#undef PACKAGE +#undef VERSION +#undef CYGNUM_LIBCDL_VERSION + +#undef CYGDBG_USE_ASSERTS +#undef CYGDBG_INFRA_DEBUG_PRECONDITIONS +#undef CYGDBG_INFRA_DEBUG_POSTCONDITIONS +#undef CYGDBG_INFRA_DEBUG_INVARIANTS +#undef CYGDBG_INFRA_DEBUG_LOOP_INVARIANTS + +#undef CYGDBG_USE_TRACING +#undef CYGDBG_INFRA_DEBUG_FUNCTION_REPORTS + +#endif // CYGONCE_LIBCDL_CONFIG_H +// End of config.h diff --git a/host/libcdl/acinclude.m4 b/host/libcdl/acinclude.m4 new file mode 100644 --- /dev/null +++ b/host/libcdl/acinclude.m4 @@ -0,0 +1,46 @@ +dnl Process this file with aclocal to get an aclocal.m4 file. Then +dnl process that with autoconf. +dnl ==================================================================== +dnl +dnl acinclude.m4 +dnl +dnl ==================================================================== +dnl####COPYRIGHTBEGIN#### +dnl +dnl ---------------------------------------------------------------------------- +dnl Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +dnl +dnl This file is part of the eCos host tools. +dnl +dnl This program is free software; you can redistribute it and/or modify it +dnl under the terms of the GNU General Public License as published by the Free +dnl Software Foundation; either version 2 of the License, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but WITHOUT +dnl ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +dnl FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +dnl more details. +dnl +dnl You should have received a copy of the GNU General Public License along with +dnl this program; if not, write to the Free Software Foundation, Inc., +dnl 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl ---------------------------------------------------------------------------- +dnl +dnl####COPYRIGHTEND#### +dnl ==================================================================== +dnl#####DESCRIPTIONBEGIN#### +dnl +dnl Author(s): bartv +dnl Contact(s): bartv +dnl Date: 1998/12/16 +dnl Version: 0.01 +dnl +dnl####DESCRIPTIONEND#### +dnl ==================================================================== + +dnl Access shared macros. +dnl AM_CONDITIONAL needs to be mentioned here or else aclocal does not +dnl incorporate the macro into aclocal.m4 +sinclude(../acinclude.m4) diff --git a/host/libcdl/aclocal.m4 b/host/libcdl/aclocal.m4 new file mode 100644 --- /dev/null +++ b/host/libcdl/aclocal.m4 @@ -0,0 +1,207 @@ +dnl aclocal.m4 generated automatically by aclocal 1.4 + +dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without +dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A +dnl PARTICULAR PURPOSE. + +dnl Process this file with aclocal to get an aclocal.m4 file. Then +dnl process that with autoconf. +dnl ==================================================================== +dnl +dnl acinclude.m4 +dnl +dnl ==================================================================== +dnl####COPYRIGHTBEGIN#### +dnl +dnl ---------------------------------------------------------------------------- +dnl Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +dnl +dnl This file is part of the eCos host tools. +dnl +dnl This program is free software; you can redistribute it and/or modify it +dnl under the terms of the GNU General Public License as published by the Free +dnl Software Foundation; either version 2 of the License, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but WITHOUT +dnl ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +dnl FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +dnl more details. +dnl +dnl You should have received a copy of the GNU General Public License along with +dnl this program; if not, write to the Free Software Foundation, Inc., +dnl 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl ---------------------------------------------------------------------------- +dnl +dnl####COPYRIGHTEND#### +dnl ==================================================================== +dnl#####DESCRIPTIONBEGIN#### +dnl +dnl Author(s): bartv +dnl Contact(s): bartv +dnl Date: 1998/12/16 +dnl Version: 0.01 +dnl +dnl####DESCRIPTIONEND#### +dnl ==================================================================== + +dnl Access shared macros. +dnl AM_CONDITIONAL needs to be mentioned here or else aclocal does not +dnl incorporate the macro into aclocal.m4 +sinclude(../acinclude.m4) + +# Define a conditional. + +AC_DEFUN(AM_CONDITIONAL, +[AC_SUBST($1_TRUE) +AC_SUBST($1_FALSE) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi]) + +# Do all the work for Automake. This macro actually does too much -- +# some checks are only needed if your package does certain things. +# But this isn't really a big deal. + +# serial 1 + +dnl Usage: +dnl AM_INIT_AUTOMAKE(package,version, [no-define]) + +AC_DEFUN(AM_INIT_AUTOMAKE, +[AC_REQUIRE([AC_PROG_INSTALL]) +PACKAGE=[$1] +AC_SUBST(PACKAGE) +VERSION=[$2] +AC_SUBST(VERSION) +dnl test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi +ifelse([$3],, +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) +AC_REQUIRE([AM_SANITY_CHECK]) +AC_REQUIRE([AC_ARG_PROGRAM]) +dnl FIXME This is truly gross. +missing_dir=`cd $ac_aux_dir && pwd` +AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) +AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) +AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) +AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) +AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) +AC_REQUIRE([AC_PROG_MAKE_SET])]) + +# +# Check to make sure that the build environment is sane. +# + +AC_DEFUN(AM_SANITY_CHECK, +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "[$]*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "[$]*" != "X $srcdir/configure conftestfile" \ + && test "[$]*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "[$]2" = conftestfile + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +rm -f conftest* +AC_MSG_RESULT(yes)]) + +dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) +dnl The program must properly implement --version. +AC_DEFUN(AM_MISSING_PROG, +[AC_MSG_CHECKING(for working $2) +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if ($2 --version) < /dev/null > /dev/null 2>&1; then + $1=$2 + AC_MSG_RESULT(found) +else + $1="$3/missing $2" + AC_MSG_RESULT(missing) +fi +AC_SUBST($1)]) + +# Add --enable-maintainer-mode option to configure. +# From Jim Meyering + +# serial 1 + +AC_DEFUN(AM_MAINTAINER_MODE, +[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode is disabled by default + AC_ARG_ENABLE(maintainer-mode, +[ --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer], + USE_MAINTAINER_MODE=$enableval, + USE_MAINTAINER_MODE=no) + AC_MSG_RESULT($USE_MAINTAINER_MODE) + AM_CONDITIONAL(MAINTAINER_MODE, test $USE_MAINTAINER_MODE = yes) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST(MAINT)dnl +] +) + +# Like AC_CONFIG_HEADER, but automatically create stamp file. + +AC_DEFUN(AM_CONFIG_HEADER, +[AC_PREREQ([2.12]) +AC_CONFIG_HEADER([$1]) +dnl When config.status generates a header, we must update the stamp-h file. +dnl This file resides in the same directory as the config header +dnl that is generated. We must strip everything past the first ":", +dnl and everything past the last "/". +AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl +ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>, +<>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>, +<>; do + case " <<$>>CONFIG_HEADERS " in + *" <<$>>am_file "*<<)>> + echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx + ;; + esac + am_indx=`expr "<<$>>am_indx" + 1` +done<<>>dnl>>) +changequote([,]))]) + diff --git a/host/libcdl/base.cxx b/host/libcdl/base.cxx new file mode 100644 --- /dev/null +++ b/host/libcdl/base.cxx @@ -0,0 +1,3688 @@ +//{{{ Banner + +//============================================================================ +// +// base.cxx +// +// Implementations of the various base classes +// +//============================================================================ +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================ +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contact(s): bartv +// Date: 1999/02/18 +// Version: 0.02 +// Description: libcdl defines a hierarchy of base classes, used for +// constructing higher-level entities such as options +// and packages. +// +//####DESCRIPTIONEND#### +//============================================================================ + +//}}} +//{{{ #include's + +// ---------------------------------------------------------------------------- +#include "cdlconfig.h" + +// Get the infrastructure types, assertions, tracing and similar +// facilities. +#include +#include + +// defines everything implemented in this module. +// It implicitly supplies , and because +// the class definitions rely on these headers. +#include + +//}}} + +//{{{ Statics + +// ---------------------------------------------------------------------------- +CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlNodeBody); +CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlContainerBody); +CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlLoadableBody); +CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlToplevelBody); +CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlUserVisibleBody); +CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlParentableBody); + +//}}} +//{{{ CdlNodeBody + +//{{{ Construction + +// ---------------------------------------------------------------------------- +// The real constructor takes a string argument and should get invoked first. +// Because of the way virtual inheritance is used it is also necessary to have +// a default constructor, but that need not do anything. A newly constructed +// object does not yet live in the hierarchy. + +CdlNodeBody::CdlNodeBody(std::string name_arg) +{ + CYG_REPORT_FUNCNAME("CdlNode:: constructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITIONC("" != name_arg); + + name = name_arg; + parent = 0; + owner = 0; + toplevel = 0; + active = false; + remove_node_container_position = -1; + + // The STL containers will take care of themselves. + + cdlnodebody_cookie = CdlNodeBody_Magic; + CYGDBG_MEMLEAK_CONSTRUCTOR(); + + CYG_POSTCONDITION_THISC(); + CYG_REPORT_RETURN(); +} + +CdlNodeBody::CdlNodeBody() +{ + CYG_PRECONDITION_THISC(); +} + +//}}} +//{{{ Destructor + +// ---------------------------------------------------------------------------- +// By the time the destructor gets invoked the node should already +// have been unbound and removed from the hierarchy. + +CdlNodeBody::~CdlNodeBody() +{ + CYG_REPORT_FUNCNAME("CdlNode:: destructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + // Make sure that the node is unbound: all references to and from + // this node should have been destroyed already inside a + // transaction. + CYG_PRECONDITIONC(0 == referrers.size()); + + // Make sure that the node has been removed from the hierarchy + CYG_PRECONDITIONC(0 == toplevel); + CYG_PRECONDITIONC(0 == owner); + CYG_PRECONDITIONC(0 == parent); + + // Destroy all properties associated with this object. + std::vector::iterator prop_i; + for (prop_i= properties.begin(); prop_i != properties.end(); prop_i++) { + delete *prop_i; + *prop_i = 0; + } + properties.clear(); + + cdlnodebody_cookie = CdlNodeBody_Invalid; + name = ""; + active = false; + unsupported_savefile_strings.clear(); + + CYGDBG_MEMLEAK_DESTRUCTOR(); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ Trivial data access + +// ---------------------------------------------------------------------------- + +std::string +CdlNodeBody::get_name() const +{ + CYG_REPORT_FUNCNAME("CdlNode::get_name"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CYG_REPORT_RETURN(); + return name; +} + +void +CdlNodeBody::set_name(std::string name_arg) +{ + CYG_REPORT_FUNCNAME("CdlNode::set_name"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + name = name_arg; + + CYG_REPORT_RETURN(); +} + +CdlContainer +CdlNodeBody::get_parent() const +{ + CYG_REPORT_FUNCNAMETYPE("CdlNode::get_parent", "parent %p"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlContainer result = parent; + CYG_REPORT_RETVAL(result); + return result; +} + +CdlLoadable +CdlNodeBody::get_owner() const +{ + CYG_REPORT_FUNCNAMETYPE("CdlNode::get_owner", "owner %p"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlLoadable result = owner; + CYG_REPORT_RETVAL(result); + return result; +} + +CdlToplevel +CdlNodeBody::get_toplevel() const +{ + CYG_REPORT_FUNCNAMETYPE("CdlNode::get_toplevel", "toplevel %p"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlToplevel result = toplevel; + CYG_REPORT_RETVAL(result); + return result; +} + +std::string +CdlNodeBody::get_class_name() const +{ + CYG_REPORT_FUNCNAME("CdlNode::get_class_name"); + CYG_PRECONDITION_THISC(); + CYG_REPORT_RETURN(); + return "node"; +} + +//}}} +//{{{ The properties vector + +// ---------------------------------------------------------------------------- +// Trivial manipulation of the properties vector. + +const std::vector& +CdlNodeBody::get_properties() const +{ + CYG_REPORT_FUNCNAME("CdlNode::get_properties"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CYG_REPORT_RETURN(); + return properties; +} + +CdlProperty +CdlNodeBody::get_property(std::string id) const +{ + CYG_REPORT_FUNCNAMETYPE("CdlNode::get_property", "result %p"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlProperty result = 0; + std::vector::const_iterator prop_i; + for (prop_i = properties.begin(); prop_i != properties.end(); prop_i++) { + if ((*prop_i)->get_property_name() == id) { + result = *prop_i; + break; + } + } + + CYG_REPORT_RETVAL(result); + return result; +} + +void +CdlNodeBody::get_properties(std::string id, std::vector& result) const +{ + CYG_REPORT_FUNCNAME("CdlNode::get_properties"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + std::vector::const_iterator prop_i; + for (prop_i = properties.begin(); prop_i != properties.end(); prop_i++) { + if ((*prop_i)->get_property_name() == id) { + result.push_back(*prop_i); + } + } + + CYG_REPORT_RETURN(); +} + +std::vector +CdlNodeBody::get_properties(std::string id) const +{ + CYG_REPORT_FUNCNAME("CdlNode::get_properties"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + std::vector result; + std::vector::const_iterator prop_i; + for (prop_i = properties.begin(); prop_i != properties.end(); prop_i++) { + if ((*prop_i)->get_property_name() == id) { + result.push_back(*prop_i); + } + } + + CYG_REPORT_RETURN(); + return result; +} + +bool +CdlNodeBody::has_property(std::string id) const +{ + CYG_REPORT_FUNCNAMETYPE("CdlNode::has_property", "result %d"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + bool result = false; + std::vector::const_iterator prop_i; + for (prop_i = properties.begin(); prop_i != properties.end(); prop_i++) { + if ((*prop_i)->get_property_name() == id) { + result = true; + break; + } + } + + CYG_REPORT_RETVAL(result); + return result; +} + +int +CdlNodeBody::count_properties(std::string id) const +{ + CYG_REPORT_FUNCNAMETYPE("CdlNode::count_properties", "result %d"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + int result = 0; + std::vector::const_iterator prop_i; + for (prop_i = properties.begin(); prop_i != properties.end(); prop_i++) { + if ((*prop_i)->get_property_name() == id) { + result++; + } + } + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ Conflicts + +// ---------------------------------------------------------------------------- +// Provide access to the current set of conflicts. This operates on the global +// state, more commonly these changes happen in the context of a transaction. + +void +CdlNodeBody::get_conflicts(std::vector& result) const +{ + CYG_REPORT_FUNCNAME("CdlNode::get_conflicts"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + const std::list& conflicts = toplevel->get_all_conflicts(); + std::list::const_iterator conf_i; + for (conf_i = conflicts.begin(); conf_i != conflicts.end(); conf_i++) { + if ((*conf_i)->get_node() == this) { + result.push_back(*conf_i); + } + } + + CYG_REPORT_RETURN(); +} + +void +CdlNodeBody::get_conflicts(bool (*fn)(CdlConflict), std::vector& result) const +{ + CYG_REPORT_FUNCNAME("CdlNode::get_conflicts"); + CYG_REPORT_FUNCARG2XV(this, fn); + CYG_PRECONDITION_THISC(); + CYG_CHECK_FUNC_PTRC(fn); + + const std::list& conflicts = toplevel->get_all_conflicts(); + std::list::const_iterator conf_i; + for (conf_i = conflicts.begin(); conf_i != conflicts.end(); conf_i++) { + if (((*conf_i)->get_node() == this) && ((*fn)(*conf_i))) { + result.push_back(*conf_i); + } + } + + CYG_REPORT_RETURN(); +} + +void +CdlNodeBody::get_structural_conflicts(std::vector& result) const +{ + CYG_REPORT_FUNCNAME("CdlNode::get_structural_conflicts"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + const std::list& conflicts = toplevel->get_all_structural_conflicts(); + std::list::const_iterator conf_i; + for (conf_i = conflicts.begin(); conf_i != conflicts.end(); conf_i++) { + if ((*conf_i)->get_node() == this) { + result.push_back(*conf_i); + } + } + + CYG_REPORT_RETURN(); +} + +void +CdlNodeBody::get_structural_conflicts(bool (*fn)(CdlConflict), std::vector& result) const +{ + CYG_REPORT_FUNCNAME("CdlNode::get_conflicts"); + CYG_REPORT_FUNCARG2XV(this, fn); + CYG_PRECONDITION_THISC(); + CYG_CHECK_FUNC_PTRC(fn); + + const std::list& conflicts = toplevel->get_all_structural_conflicts(); + std::list::const_iterator conf_i; + for (conf_i = conflicts.begin(); conf_i != conflicts.end(); conf_i++) { + if (((*conf_i)->get_node() == this) && ((*fn)(*conf_i))) { + result.push_back(*conf_i); + } + } + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ Referrers + +// ---------------------------------------------------------------------------- +// And access to the referrers vector. +const std::vector& +CdlNodeBody::get_referrers() const +{ + CYG_REPORT_FUNCNAME("CdlNode::get_referrers"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CYG_REPORT_RETURN(); + return referrers; +} + +//}}} +//{{{ Property parsers + +// ---------------------------------------------------------------------------- +// Property parsing. For now there are now properties guaranteed to be +// associated with every node. This may change in future, e.g. +// internal debugging-related properties. +void +CdlNodeBody::add_property_parsers(std::vector& parsers) +{ + CYG_REPORT_FUNCNAME("CdlNode::add_property_parsers"); + CYG_REPORT_RETURN(); +} + +void +CdlNodeBody::check_properties(CdlInterpreter interp) +{ + CYG_REPORT_FUNCNAME("CdlNode::check_properties"); + CYG_REPORT_FUNCARG2XV(this, interp); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(interp); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ is_active() etc. + +// ---------------------------------------------------------------------------- +// Associated with every node is a boolean that holds the current +// "active" state. Changes to this happen only at transaction +// commit time. + +bool +CdlNodeBody::is_active() const +{ + CYG_REPORT_FUNCNAMETYPE("CdlNode::is_active", "result %d"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + bool result = active; + CYG_REPORT_RETVAL(result); + return result; +} + +bool +CdlNodeBody::is_active(CdlTransaction transaction) +{ + CYG_REPORT_FUNCNAMETYPE("CdlNode::is_active", "result %d"); + CYG_REPORT_FUNCARG2XV(this, transaction); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(transaction); + + bool result = transaction->is_active(this); + CYG_REPORT_RETVAL(result); + return result; +} + +// This virtual member function allows nodes to check whether or not +// they should be active. Derived classes may impose additional +// constraints. +bool +CdlNodeBody::test_active(CdlTransaction transaction) +{ + CYG_REPORT_FUNCNAMETYPE("CdlNode::test_active", "result %d"); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(transaction); + + bool result = false; + if ((0 != parent) && (transaction->is_active(parent))) { + CdlValuable valuable = dynamic_cast(parent); + if (0 == valuable) { + result = true; + } else if (valuable->is_enabled(transaction)) { + result = true; + } + } + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ Propagation support + +// ---------------------------------------------------------------------------- +// In the base class nothing needs doing for propagation. +void +CdlNodeBody::update(CdlTransaction transaction, CdlUpdate change) +{ + CYG_REPORT_FUNCNAME("CdlNode::update"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(transaction); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ Persistence support + +// ---------------------------------------------------------------------------- +// The CdlNode::save() member should never get invoked directly, it should +// get invoked indirectly from e.g. CdlOption::save(). Normally there is +// no information associated with a node that ends up in a save file +// (the calling code will have take care of the name etc.). However there +// is support in the library for storing application-specific data in the +// save file, for example GUI information, and this information must be +// preserved even if it is not recognised. Savefiles are self-describing, +// they contain details of all the commands that are applicable. +// CdlNode::save() is responsible for outputting the unrecognised strings +// to the save file. + +void +CdlNodeBody::save(CdlInterpreter interp, Tcl_Channel chan, int indentation, bool minimal) + throw(CdlInputOutputException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlNode::save"); + CYG_REPORT_FUNCARG5XV(this, interp, chan, indentation, minimal); + + if (unsupported_savefile_strings.size() != 0) { + // We should already be inside the body of a suitable command, + // e.g. cdl_option xyz { ... } + // CdlToplevel::savefile_handle_unsupported() is responsible for + // putting suitably formatted strings into the + // unsupported_savefile_strings vector, so all that is needed here + // is to dump those strings to the channel. + std::string data = "\n"; + std::vector::const_iterator str_i; + for (str_i = unsupported_savefile_strings.begin(); str_i != unsupported_savefile_strings.end(); str_i++) { + data += std::string(indentation, ' ') + *str_i + " ;\n"; + } + interp->write_data(chan, data); + } + + CYG_UNUSED_PARAM(bool, minimal); + CYG_REPORT_RETURN(); +} + +bool +CdlNodeBody::has_additional_savefile_information() const +{ + CYG_REPORT_FUNCNAMETYPE("CdlNode::has_additional_savefile_information", "result %d"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + bool result = (0 != unsupported_savefile_strings.size()); + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ check_this() + +// ---------------------------------------------------------------------------- +// Because of multiple and virtual inheritance, check_this() may +// get called rather a lot. Unfortunately all of the checks are +// useful. + +bool +CdlNodeBody::check_this(cyg_assert_class_zeal zeal) const +{ + if (CdlNodeBody_Magic != cdlnodebody_cookie) { + return false; + } + CYGDBG_MEMLEAK_CHECKTHIS(); + + if ("" == name) { + return false; + } + + // It is hard to validate the toplevel, owner, and parent + // fields. + // + // 1) when a node is newly created all three fields will + // be null. + // 2) the toplevel may be null if the node is in the process + // of being removed, e.g. during an unload operation. + // The node should still have a valid owner, and will + // have a parent unless the node is also the loadable. + // 3) some nodes are special, e.g. the orphans container, + // and do not have an owner. + // + // So the following combinations can occur: + // Toplevel Owner Parent + // 0 0 0 Creation & toplevel + // 0 Valid 0 Loadable being unloaded + // 0 Valid Valid Node being unloaded + // Valid 0 Valid Orphans container + // Valid Valid Valid Any node + if (0 != toplevel) { + if (0 == parent) { + return false; + } + } + + switch(zeal) { + case cyg_system_test : + case cyg_extreme : + { + if ((0 != toplevel) && (toplevel != this)) { + if (!toplevel->check_this(cyg_quick)) { + return false; + } + if (toplevel->lookup_table.find(name) == toplevel->lookup_table.end()) { + return false; + } + } + if (0 != parent) { + if (!parent->check_this(cyg_quick)) { + return false; + } + if (std::find(parent->contents.begin(), parent->contents.end(), this) == parent->contents.end()) { + return false; + } + } + if (0 != owner) { + if (!owner->check_this(cyg_quick)) { + return false; + } + if (std::find(owner->owned.begin(), owner->owned.end(), this) == owner->owned.end()) { + return false; + } + } + std::vector::const_iterator prop_i; + for (prop_i = properties.begin(); prop_i != properties.end(); prop_i++) { + if (!(*prop_i)->check_this(cyg_quick)) { + return false; + } + } + std::vector::const_iterator ref_i; + for (ref_i = referrers.begin(); ref_i != referrers.end(); ref_i++) { + if (!ref_i->check_this(cyg_quick)) { + return false; + } + } + } + case cyg_thorough : + case cyg_quick : + case cyg_trivial : + case cyg_none : + default : + break; + } + + return true; +} + +//}}} + +//}}} +//{{{ CdlContainerBody + +//{{{ Constructors + +// ---------------------------------------------------------------------------- +// A container simply holds other nodes in a hierarchy. Most +// containers correspond to data in CDL scripts, but there are +// exceptions. For example, if an option is reparented below some +// package or component that is not yet known then it can instead be +// reparented into an "orphans" container immediately below the +// toplevel. +// +// Adding and removing entries to a container is done inside the +// CdlToplevel add_node() and remove_node() members. These will update +// all the fields needed to keep the hierarchy consistent. This +// means that the CdlContainer class itself provides only limited +// functionality. + +CdlContainerBody::CdlContainerBody() +{ + CYG_REPORT_FUNCNAME("CdlContainer:: default constructor"); + CYG_REPORT_FUNCARG1XV(this); + + cdlcontainerbody_cookie = CdlContainerBody_Magic; + CYGDBG_MEMLEAK_CONSTRUCTOR(); + + CYG_POSTCONDITION_THISC(); + CYG_REPORT_RETURN(); +} + +// This variant is for internal use, to allow the library to create +// containers that do not correspond to CDL entities such as +// the orphans container. +CdlContainerBody::CdlContainerBody(std::string name_arg) + : CdlNodeBody(name_arg) +{ + CYG_REPORT_FUNCNAME("CdlContainerBody:: constructor (name)"); + CYG_REPORT_FUNCARG1XV(this); + + cdlcontainerbody_cookie = CdlContainerBody_Magic; + CYGDBG_MEMLEAK_CONSTRUCTOR(); + + CYG_POSTCONDITION_THISC(); + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ Destructor + +// ---------------------------------------------------------------------------- + +CdlContainerBody::~CdlContainerBody() +{ + CYG_REPORT_FUNCNAME("CdlContainer:: destructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + // Containers should always be empty by the time they + // get deleted. The toplevel and loadable destructors should + // guarantee this. + CYG_ASSERTC(0 == contents.size()); + + cdlcontainerbody_cookie = CdlContainerBody_Invalid; + CYGDBG_MEMLEAK_DESTRUCTOR(); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ Accessing the contents + +// ---------------------------------------------------------------------------- +// Simple contents access facilities, including searching. Note that +// the toplevel class maintains a map, which will usually +// be more efficient. + +const std::vector& +CdlContainerBody::get_contents() const +{ + CYG_REPORT_FUNCNAME("CdlContainer::get_contents"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CYG_REPORT_RETURN(); + return contents; +} + +bool +CdlContainerBody::contains(CdlConstNode node, bool recurse) const +{ + CYG_REPORT_FUNCNAMETYPE("CdlContainer::contains (node)", "result %d"); + CYG_REPORT_FUNCARG3XV(this, node, recurse); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(node); + + bool result = false; + std::vector::const_iterator node_i; + for (node_i = contents.begin(); node_i != contents.end(); node_i++) { + if (node == *node_i) { + result = true; + break; + } + if (recurse) { + CdlConstContainer child = dynamic_cast(*node_i); + if ((0 != child) && child->contains(node, true)) { + result = true; + break; + } + } + } + + CYG_REPORT_RETVAL(result); + return result; +} + +bool +CdlContainerBody::contains(const std::string name, bool recurse) const +{ + CYG_REPORT_FUNCNAMETYPE("CdlContainer::contains (name)", "result %d"); + CYG_REPORT_FUNCARG2XV(this, recurse); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITIONC("" != name); + + bool result = false; + std::vector::const_iterator node_i; + for (node_i = contents.begin(); node_i != contents.end(); node_i++) { + if ((*node_i)->get_name() == name) { + result = true; + break; + } + if (recurse) { + CdlConstContainer child = dynamic_cast(*node_i); + if ((0 != child) && child->contains(name, true)) { + result = true; + break; + } + } + } + + CYG_REPORT_RETVAL(result); + return result; +} + +CdlNode +CdlContainerBody::find_node(const std::string name, bool recurse) const +{ + CYG_REPORT_FUNCNAMETYPE("CdlContainer::find_node", "result %p"); + CYG_REPORT_FUNCARG2XV(this, recurse); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITIONC("" != name); + + CdlNode result = 0; + std::vector::const_iterator node_i; + for (node_i = contents.begin(); node_i != contents.end(); node_i++) { + if ((*node_i)->get_name() == name) { + result = *node_i; + break; + } + if (recurse) { + CdlConstContainer child = dynamic_cast(*node_i); + if (0 != child) { + result = child->find_node(name, true); + if (0 != result) { + break; + } + } + } + } + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ Misc + +// ---------------------------------------------------------------------------- + +std::string +CdlContainerBody::get_class_name() const +{ + CYG_REPORT_FUNCNAME("CdlContainer::get_class_name"); + CYG_PRECONDITION_THISC(); + CYG_REPORT_RETURN(); + return "container"; +} + +//}}} +//{{{ Propagation + +// ---------------------------------------------------------------------------- +// If a container becomes active and is enabled then it is necessary +// to check all the children in case they want to become active as well. + +void +CdlContainerBody::update(CdlTransaction transaction, CdlUpdate change) +{ + CYG_REPORT_FUNCNAME("CdlContainer::update"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(transaction); + + if ((CdlUpdate_ActiveChange != change) && (CdlUpdate_ValueChange != change)) { + CYG_REPORT_RETURN(); + return; + } + + if (transaction->is_active(this)) { + // The container has become active. It is necessary to check + // all the children. If any of them should be active as well + // but are not then this needs to change. + std::vector::iterator node_i; + + for (node_i = contents.begin(); node_i != contents.end(); node_i++) { + bool old_state = transaction->is_active(*node_i); + bool new_state = (*node_i)->test_active(transaction); + if (old_state != new_state) { + transaction->set_active(*node_i, new_state); + } + } + } else { + // The container has become inactive. Any children that were + // active should also become inactive. + std::vector::iterator node_i; + for (node_i = contents.begin(); node_i != contents.end(); node_i++) { + if (transaction->is_active(*node_i)) { + transaction->set_active(*node_i, false); + } + } + } + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ Persistence + +// ---------------------------------------------------------------------------- +// This member function is invoked while traversing the hierarchy. +// The container itself will have been saved already, this member +// is responsible only for the contents. There are marker comments +// in the output file to indicate a new level in the hierarchy. +// +// Note that this member can also be invoked for the "orphans" container. +// That container will not appear in the save file, but its contents +// will. + +void +CdlContainerBody::save(CdlInterpreter interp, Tcl_Channel chan, int indentation, bool minimal) + throw(CdlInputOutputException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlContainer::save"); + CYG_REPORT_FUNCARG4XV(this, interp, chan, indentation); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(interp); + CYG_PRECONDITIONC(0 == indentation); + + if (0 != contents.size()) { + if (!minimal) { + interp->write_data(chan, "# >\n"); + } + std::vector::const_iterator node_i; + for (node_i = contents.begin(); node_i != contents.end(); node_i++) { + (*node_i)->save(interp, chan, indentation, minimal); + } + if (!minimal) { + interp->write_data(chan, "# <\n"); + } + } + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ check_this() + +// ---------------------------------------------------------------------------- +bool +CdlContainerBody::check_this(cyg_assert_class_zeal zeal) const +{ + if (CdlContainerBody_Magic != cdlcontainerbody_cookie) { + return false; + } + CYGDBG_MEMLEAK_CHECKTHIS(); + + if (cyg_extreme == zeal) { + std::vector::const_iterator node_i; + for (node_i = contents.begin(); node_i != contents.end(); node_i++) { + if (!((*node_i)->check_this(cyg_quick))) { + return false; + } + } + } + return CdlNodeBody::check_this(zeal); +} + +//}}} + +//}}} +//{{{ CdlLoadableBody + +//{{{ Constructor + +// ---------------------------------------------------------------------------- +// A loadable object keeps track of all the nodes read in from a +// particular script, in an "owned" vector. Simply keeping things in a +// hierarchy is not enough because of possible re-parenting. Actual +// updates of the owned vector happen inside the CdlToplevel +// add_node() and remove_node() family. + +CdlLoadableBody::CdlLoadableBody(CdlToplevel toplevel, std::string dir) + : CdlContainerBody() +{ + CYG_REPORT_FUNCNAME("CdlLoadable:: constructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_CLASSC(toplevel); + + // Initialize enough of the object to support check_this() + directory = dir; + interp = 0; + remove_node_loadables_position = -1; + cdlloadablebody_cookie = CdlLoadableBody_Magic; + + // The owned vector takes care of itself. It is necessary + // to create a new slave interpreter, using the master + // interpreter from the toplevel. + CdlInterpreter master = toplevel->get_interpreter(); + CYG_ASSERTC(0 != master); + interp = master->create_slave(this, false); + CYGDBG_MEMLEAK_CONSTRUCTOR(); + + CYG_POSTCONDITION_THISC(); + CYG_REPORT_RETURN(); +} + +// Needed by derived classes, but should never actually be used. +CdlLoadableBody::CdlLoadableBody() +{ + CYG_FAIL("CdlLoadable default constructor should never get invoked"); +} + +//}}} +//{{{ Destructor + +// ---------------------------------------------------------------------------- +// The loadable destructor. This gets invoked from two places: after an +// unsuccessful load operation, and from inside the transaction commit +// code. Either way most of the clean-up will have happened already: +// all the nodes will have been removed from the toplevel's hierarchy, +// and all property references to and from this loadable will have been +// unbound. +// +// Since all nodes belonging to the loadable are also present in +// the owned vector, they must be destroyed before this destructor +// completes. Hence clearing out the contents cannot be left to +// the base CdlContainer destructor. + +CdlLoadableBody::~CdlLoadableBody() +{ + CYG_REPORT_FUNCNAME("CdlLoadable:: destructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + // Make sure that the loadable has already been removed from the + // hierarchy: it should not have a toplevel or a parent. + CYG_PRECONDITIONC(0 == toplevel); + CYG_PRECONDITIONC(0 == parent); + + // Containers must have been created before any of their contents. + // The only way to reverse this involves a parent property, but + // all such properties will have been unbound already such that + // the nodes can be safely deleted. The only worry is that + // loadables own themselves. + int i; + for (i = owned.size() - 1; i >= 0; i--) { + CdlNode node = owned[i]; + CYG_LOOP_INVARIANT_CLASSC(node); + + if (node != this) { + CdlToplevelBody::remove_node(this, node->parent, node); + delete node; + } + } + + // Now there should be exactly one entry in the owned vector, + // the loadable itself. We already know that this is no longer + // part of the toplevel and it does not have a parent, so + // the only field we need to worry about is the owner. + CYG_ASSERTC(1 == owned.size()); + CYG_ASSERTC(this == owned[0]); + this->owner = 0; + + // Strictly speaking the owned vector should be clear by now, + // but remove_node() does not actually bother to clear it. + owned.clear(); + + // The loadable should now be empty. It remains to clean up + // a few odds and ends. + cdlloadablebody_cookie = CdlLoadableBody_Invalid; + CYG_ASSERTC(0 == owned.size()); + delete interp; + interp = 0; + directory = ""; + + CYGDBG_MEMLEAK_DESTRUCTOR(); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ Simple information access + +// ---------------------------------------------------------------------------- + +const std::vector& +CdlLoadableBody::get_owned() const +{ + CYG_REPORT_FUNCNAME("CdlLoadable::get_owned"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CYG_REPORT_RETURN(); + return owned; +} + +bool +CdlLoadableBody::owns(CdlConstNode node) const +{ + CYG_REPORT_FUNCNAMETYPE("CdlLoadable::owns", "result %d"); + CYG_REPORT_FUNCARG2XV(this, node); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(node); + + bool result = false; + std::vector::const_iterator i = std::find(owned.begin(), owned.end(), node); + if (i != owned.end()) { + result = true; + } + + CYG_REPORT_RETVAL(result); + return result; +} + +CdlInterpreter +CdlLoadableBody::get_interpreter() const +{ + CYG_REPORT_FUNCNAMETYPE("CdlLoadable::get_interpreter", "result %p"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlInterpreter result = interp; + CYG_REPORT_RETVAL(result); + return result; +} + +std::string +CdlLoadableBody::get_directory() const +{ + CYG_REPORT_FUNCNAME("CdlLoadable::get_directory"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CYG_REPORT_RETURN(); + return directory; +} + +//}}} +//{{{ Bind/unbind support + +// ---------------------------------------------------------------------------- +// Binding a loadable. This involves checking every property of every node +// in the loadable, which the properties do themselves by a suitable +// update() virtual function. Next, there may be properties in the +// existing configuration which could not previously be bound: there +// will be structural conflicts for all of these. Once all the pointers +// go to the right places it is possible to calculate the default values +// and generally process the properties. Finally each node's active +// state is checked - the default inactive state will be inappropriate +// in many cases. +// +// FIXME: error recovery? + +void +CdlLoadableBody::bind(CdlTransaction transaction) +{ + CYG_REPORT_FUNCNAME("CdlLoadable::bind"); + CYG_REPORT_FUNCARG2XV(this, transaction); + CYG_INVARIANT_THISC(CdlLoadableBody); + CYG_INVARIANT_CLASSC(CdlTransactionBody, transaction); + + // The loadable must already be part of the hierarchy. + CdlToplevel toplevel = this->get_toplevel(); + CYG_ASSERT_CLASSC(toplevel); + + // As a first step, bind all references in this loadable. + // This is achieved via a Loaded update. + const std::vector& nodes = this->get_owned(); + std::vector::const_iterator node_i; + for (node_i = nodes.begin(); node_i != nodes.end(); node_i++) { + const std::vector& properties = (*node_i)->get_properties(); + std::vector::const_iterator prop_i; + for (prop_i = properties.begin(); prop_i != properties.end(); prop_i++) { + (*prop_i)->update(transaction, *node_i, 0, CdlUpdate_Loaded); + } + } + + // Next, look for all structural conflicts which are unresolved + // references and which can now be resolved. It is necessary + // to check per-transaction structural conflicts, plus those + // in any parent transactions, plus the global ones. + std::list::const_iterator conf_i; + CdlTransaction current_transaction = transaction; + do { + CYG_ASSERT_CLASSC(current_transaction); + const std::list& new_structural_conflicts = current_transaction->get_new_structural_conflicts(); + + for (conf_i = new_structural_conflicts.begin(); conf_i != new_structural_conflicts.end(); ) { + + CdlConflict conflict = *conf_i++; + CYG_LOOP_INVARIANT_CLASSC(conflict); + + CdlConflict_Unresolved unresolved_conflict = dynamic_cast(conflict); + if ((0 != unresolved_conflict) && !transaction->has_conflict_been_cleared(conflict)) { + CdlNode dest = toplevel->lookup(unresolved_conflict->get_target_name()); + if (0 != dest) { + CdlNode node = unresolved_conflict->get_node(); + CdlProperty prop = unresolved_conflict->get_property(); + prop->update(transaction, node, dest, CdlUpdate_Created); + } + } + } + current_transaction = current_transaction->get_parent(); + } while (0 != current_transaction); + + const std::list& structural_conflicts = toplevel->get_all_structural_conflicts(); + for (conf_i = structural_conflicts.begin(); conf_i != structural_conflicts.end(); ) { + + CdlConflict conflict = *conf_i++; + CYG_LOOP_INVARIANT_CLASSC(conflict); + + CdlConflict_Unresolved this_conflict = dynamic_cast(conflict); + if ((0 != this_conflict) && !transaction->has_conflict_been_cleared(conflict)) { + CdlNode dest = toplevel->lookup(this_conflict->get_target_name()); + if (0 != dest) { + CdlNode node = this_conflict->get_node(); + CdlProperty prop = this_conflict->get_property(); + prop->update(transaction, node, dest, CdlUpdate_Created); + } + } + } + + // Conflict resolution has happened. Next it is time + // to evaluate default_value expressions and the like + // in the new loadable. + for (node_i = nodes.begin(); node_i != nodes.end(); node_i++) { + const std::vector& properties = (*node_i)->get_properties(); + std::vector::const_iterator prop_i; + for (prop_i = properties.begin(); prop_i != properties.end(); prop_i++) { + (*prop_i)->update(transaction, *node_i, 0, CdlUpdate_Init); + } + } + + // Nodes start of inactive. Check each one whether or not it + // should be active. + // NOTE: possibly this should be done via a per-node init + // update instead. + for (node_i = nodes.begin(); node_i != nodes.end(); node_i++) { + bool current_state = transaction->is_active(*node_i); + bool new_state = (*node_i)->test_active(transaction); + if (current_state != new_state) { + transaction->set_active(*node_i, new_state); + } + } + + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- + +void +CdlLoadableBody::unbind(CdlTransaction transaction) +{ + CYG_REPORT_FUNCNAME("CdlLoadable::unbind"); + CYG_REPORT_FUNCARG2XV(this, transaction); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(transaction); + + // First take care of all references to nodes in the loadable + // that is disappearing. This involves a Destroyed update. + const std::vector& nodes = this->get_owned(); + std::vector::const_iterator node_i; + for (node_i = nodes.begin(); node_i != nodes.end(); node_i++) { + // The update will remove referrer objects, so it is best + // to work from the back. + std::vector& referrers = (*node_i)->referrers; + std::vector::reverse_iterator ref_i; + for (ref_i = referrers.rbegin(); ref_i != referrers.rend(); ref_i = referrers.rbegin()) { + ref_i->update(transaction, *node_i, CdlUpdate_Destroyed); + CYG_LOOP_INVARIANT(ref_i != referrers.rbegin(), "the vector should have shrunk"); + } + } + + // Now repeat the loop, but unbind references from the unloaded objects + // to ones which are going to stay loaded. This will not cause + // the properties to disappear. + for (node_i = nodes.begin(); node_i != nodes.end(); node_i++) { + const std::vector& properties = (*node_i)->get_properties(); + std::vector::const_iterator prop_i; + for (prop_i = properties.begin(); prop_i != properties.end(); prop_i++) { + (*prop_i)->update(transaction, *node_i, 0, CdlUpdate_Unloading); + } + } + + // Eliminate any conflicts that belong to this loadable. + // FIXME: why is his necessary? Should these conflicts not get + // eliminated by the above property iterations? + std::list::const_iterator conf_i; + const std::list& global_conflicts = toplevel->get_all_conflicts(); + for (conf_i = global_conflicts.begin(); conf_i != global_conflicts.end(); ) { + CdlConflict conflict = *conf_i++; + CYG_LOOP_INVARIANT_CLASSC(conflict); + CdlNode node = conflict->get_node(); + if ((node->get_owner() == this) && !transaction->has_conflict_been_cleared(conflict)) { + transaction->clear_conflict(conflict); + } + } + const std::list& global_structural_conflicts = toplevel->get_all_structural_conflicts(); + for (conf_i = global_structural_conflicts.begin(); conf_i != global_structural_conflicts.end(); ) { + CdlConflict conflict = *conf_i++; + CYG_LOOP_INVARIANT_CLASSC(conflict); + CdlNode node = conflict->get_node(); + if ((node->get_owner() == this) && !transaction->has_conflict_been_cleared(conflict)) { + transaction->clear_conflict(conflict); + } + } + const std::list& transaction_conflicts = transaction->get_new_conflicts(); + for (conf_i = transaction_conflicts.begin(); conf_i != transaction_conflicts.end(); ) { + CdlConflict conflict = *conf_i++; + CYG_LOOP_INVARIANT_CLASSC(conflict); + CdlNode node = conflict->get_node(); + if (node->get_owner() == this) { + transaction->clear_conflict(conflict); + } + } + const std::list& transaction_structural_conflicts = transaction->get_new_structural_conflicts(); + for (conf_i = transaction_structural_conflicts.begin(); conf_i != transaction_structural_conflicts.end(); ) { + CdlConflict conflict = *conf_i++; + CYG_LOOP_INVARIANT_CLASSC(conflict); + CdlNode node = conflict->get_node(); + if (node->get_owner() == this) { + transaction->clear_conflict(conflict); + } + } + + // FIXME: how about cleanup_orphans() + + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- +// These members are invoked for load and unload operations. +// +// Committing a load does not require anything, the loadable has +// already been fully bound and all propagation has happened. + +void +CdlLoadableBody::transaction_commit_load(CdlTransaction transaction, CdlLoadable loadable) +{ + CYG_REPORT_FUNCNAME("CdlLoadable::transaction_commit_load"); + CYG_REPORT_FUNCARG2XV(transaction, loadable); + CYG_PRECONDITION_CLASSC(transaction); + CYG_PRECONDITION_CLASSC(loadable); + + CYG_UNUSED_PARAM(CdlTransaction, transaction); + CYG_UNUSED_PARAM(CdlLoadable, loadable); + + CYG_REPORT_RETURN(); +} + +// Cancelling a load is more difficult. The loadable has to be +// unbound, removed from the toplevel, and deleted. If any of +// this fails then we are in trouble, there is no easy way to +// recover. +void +CdlLoadableBody::transaction_cancel_load(CdlTransaction transaction, CdlLoadable loadable) +{ + CYG_REPORT_FUNCNAME("CdlLoadable::transaction_cancel_load"); + CYG_REPORT_FUNCARG2XV(transaction, loadable); + CYG_PRECONDITION_CLASSC(transaction); + CYG_PRECONDITION_CLASSC(loadable); + + CdlToplevel toplevel = transaction->get_toplevel(); + CYG_PRECONDITION_CLASSC(toplevel); + CYG_ASSERTC(toplevel == loadable->get_toplevel()); + + loadable->unbind(transaction); + toplevel->remove_loadable_from_toplevel(loadable); + delete loadable; + + CYG_REPORT_RETURN(); +} + +// Committing an unload means that the loadable can now be deleted. +// It should already be unbound and removed from the toplevel. +void +CdlLoadableBody::transaction_commit_unload(CdlTransaction transaction, CdlLoadable loadable) +{ + CYG_REPORT_FUNCNAME("CdlLoadable::transaction_commit_unload"); + CYG_REPORT_FUNCARG2XV(transaction, loadable); + CYG_PRECONDITION_CLASSC(transaction); + CYG_PRECONDITION_CLASSC(loadable); + + CYG_UNUSED_PARAM(CdlTransaction, transaction); + delete loadable; + + CYG_REPORT_RETURN(); +} + +// Cancelling an unload means that the loadable has to be re-added +// to the hierarchy and then rebound. This implies that value +// propagation needs to happen. However, since all value changes +// since the very start of the transaction are held inside the +// transaction and will be eliminated, the original state will +// be restored anyway so the propagation is not actually required. +void +CdlLoadableBody::transaction_cancel_unload(CdlTransaction transaction, CdlLoadable loadable) +{ + CYG_REPORT_FUNCNAME("CdlLoadable::transaction_cancel_unload"); + CYG_REPORT_FUNCARG2XV(transaction, loadable); + CYG_PRECONDITION_CLASSC(transaction); + CYG_PRECONDITION_CLASSC(loadable); + + CdlToplevel toplevel = transaction->get_toplevel(); + CYG_PRECONDITION_CLASSC(toplevel); + toplevel->add_loadable_to_toplevel(loadable); + CYG_ASSERT_CLASSC(loadable); + loadable->bind(transaction); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ File search facilities + +// ---------------------------------------------------------------------------- +// File search facilities. Given a file name such as hello.cxx from a compile +// property, or doc.html from a doc property, find the corresponding filename, +// for example /usr/local/eCos/kernel/v1_3/doc/threads.html#create +// +// The second argument (default value "") indicates a preferred directory +// where searching should begin. This would be src for a source file, +// doc for a URL, etc. +// +// For some properties the data may refer to a URL rather than to a local +// filename. This is controlled by the third argument, allow_urls. +// If false then only local filenames will be considered. allow_urls +// also controls whether or not anchor processing is performed. +// +// RFC1807: a URL consists of :, where can be +// any sequence of lower-case letters, digits, plus, dot or hyphen. It +// is recommended that upper-case letters should be accepted as well. +// +// RFC1807: an anchor is everything after the first # in the URL. + +static char find_absolute_file_script[] = " \n\ +set cdl_anchor \"\" \n\ +if {$::cdl_allow_urls} { \n\ + if { [regexp -- {^[a-zA-Z+.-]*:.*$} $::cdl_target] } { \n\ + return $::cdl_target \n\ + } \n\ + set tmp \"\" \n\ + set non_anchor \"\" \n\ + if { [regexp -- {^([^#])(#.*$)} $::cdl_target tmp non_anchor cdl_anchor] } { \n\ + set ::cdl_target $non_anchor \n\ + } \n\ +} \n\ +if {$::cdl_prefdir != \"\"} { \n\ + set filename [file join $::cdl_topdir $::cdl_pkgdir $::cdl_prefdir $::cdl_target] \n\ + if {[file exists $filename]} { \n\ + return \"[set filename][set cdl_anchor]\" \n\ + } \n\ +} \n\ +set filename [file join $::cdl_topdir $::cdl_pkgdir $::cdl_target] \n\ +if {[file exists $filename]} { \n\ + return \"[set filename][set cdl_anchor]\" \n\ +} \n\ +return -error \"\" \n\ +"; + +std::string +CdlLoadableBody::find_absolute_file(std::string filename, std::string dirname, bool allow_urls) const +{ + CYG_REPORT_FUNCNAME("CdlLoadable::find_absolute_file"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITIONC("" != filename); + + // These variable names should be kept in step with CdlBuildable::update_all_build_info() + interp->set_variable("::cdl_topdir", get_toplevel()->get_directory()); + interp->set_variable("::cdl_pkgdir", directory); + interp->set_variable("::cdl_prefdir", dirname); + interp->set_variable("::cdl_target", filename); + interp->set_variable("::cdl_allow_urls", allow_urls ? "1" : "0"); + + std::string result; + int tmp = interp->eval(find_absolute_file_script, result); + if (tmp != TCL_OK) { + result = ""; + } + + // Replace any backslashes in the repository with forward slashes. + // The latter are used throughout the library + // NOTE: this is not i18n-friendly. + for (unsigned int i = 0; i < result.size(); i++) { + if ('\\' == result[i]) { + result[i] = '/'; + } + } + + CYG_REPORT_RETURN(); + return result; +} + +static char find_relative_file_script[] = " \n\ +if {$::cdl_prefdir != \"\"} { \n\ + set filename [file join $::cdl_prefdir $::cdl_target] \n\ + if {[file exists [file join $::cdl_topdir $::cdl_pkgdir $filename]]} { \n\ + return $filename \n\ + } \n\ +} \n\ +set filename $::cdl_target \n\ +if {[file exists [file join $::cdl_topdir $::cdl_pkgdir $filename]]} { \n\ + return \"[set filename][set cdl_anchor]\" \n\ +} \n\ +return -error \"\" \n\ +"; + +std::string +CdlLoadableBody::find_relative_file(std::string filename, std::string dirname) const +{ + CYG_REPORT_FUNCNAME("CdlLoadable::find_relative_file"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITIONC("" != filename); + + // These variable names should be kept in step with CdlBuildable::update_all_build_info() + interp->set_variable("::cdl_topdir", get_toplevel()->get_directory()); + interp->set_variable("::cdl_pkgdir", directory); + interp->set_variable("::cdl_prefdir", dirname); + interp->set_variable("::cdl_target", filename); + + std::string result; + int tmp = interp->eval(find_relative_file_script, result); + if (tmp != TCL_OK) { + result = ""; + } + + // Replace any backslashes in the repository with forward slashes. + // The latter are used throughout the library + // NOTE: this is not i18n-friendly. + for (unsigned int i = 0; i < result.size(); i++) { + if ('\\' == result[i]) { + result[i] = '/'; + } + } + + CYG_REPORT_RETURN(); + return result; +} + +static char has_subdirectory_script[] = " \n\ +set dirname [file join $::cdl_topdir $::cdl_pkgdir $::cdl_target] \n\ +if {[file isdirectory $dirname] == 0} { \n\ + return -error \"\" \n\ +} \n\ +return 0 \n\ +"; + +bool +CdlLoadableBody::has_subdirectory(std::string name) const +{ + CYG_REPORT_FUNCNAMETYPE("CdlLoadable::has_subdirectory", "result %d"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITIONC("" != name); + + bool result = false; + + interp->set_variable("::cdl_topdir", get_toplevel()->get_directory()); + interp->set_variable("::cdl_pkgdir", directory); + interp->set_variable("::cdl_target", name); + + std::string tcl_result; + int tmp = interp->eval(has_subdirectory_script, tcl_result); + if (TCL_OK == tmp) { + result = true; + } + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ Misc + +// ---------------------------------------------------------------------------- + +std::string +CdlLoadableBody::get_class_name() const +{ + CYG_REPORT_FUNCNAME("CdlLoadable::get_class_name"); + CYG_PRECONDITION_THISC(); + CYG_REPORT_RETURN(); + return "loadable"; +} + +//}}} +//{{{ check_this() + +// ---------------------------------------------------------------------------- +bool +CdlLoadableBody::check_this(cyg_assert_class_zeal zeal) const +{ + if (CdlLoadableBody_Magic != cdlloadablebody_cookie) { + return false; + } + CYGDBG_MEMLEAK_CHECKTHIS(); + + if ((zeal == cyg_extreme) || (zeal == cyg_thorough)) { + std::vector::const_iterator node_i; + for (node_i = owned.begin(); node_i != owned.end(); node_i++) { + if ((!(*node_i)->check_this(cyg_quick)) || ((*node_i)->get_owner() != this)) { + return false; + } + } + } + return CdlContainerBody::check_this(zeal); +} + +//}}} + +//}}} +//{{{ CdlToplevelBody + +//{{{ Constructor + +// ---------------------------------------------------------------------------- +// A toplevel is a container without a parent or owner. It keeps track +// of all the names in the hierarchy, thus guaranteeing uniqueness and +// providing a quick lookup facility. +// +// The member functions add_node() and remove_node() are the only +// way of modifying the hierarchy. Adding a node with a zero parent +// means adding it to a special container, Orphans. +// +// An interpreter object must be created explicitly, preventing +// toplevel objects from being statically allocated (although +// it is possible to play tricks with utility classes...) +// There are too many possible error conditions when creating +// an interpreter, so this should not happen until the world +// is ready to deal with such errors. + +CdlToplevelBody::CdlToplevelBody(CdlInterpreter interp_arg, std::string directory_arg) + : CdlContainerBody() +{ + CYG_REPORT_FUNCNAME("CdlToplevel:: constructor"); + CYG_REPORT_FUNCARG2XV(this, interp_arg); + CYG_PRECONDITION_CLASSC(interp_arg); + + // The STL containers will take care of themselves. + interp = interp_arg; + directory = directory_arg; + transaction = 0; + + // A toplevel is always active, override the default setting for a node + active = true; + + // Make the object valid before creating the orphans container. + orphans = 0; + description = ""; + cdltoplevelbody_cookie = CdlToplevelBody_Magic; + + // Arguably creating the orphans container should be left until + // it is actually needed. The advantage of creating it at the + // start is that it will appear in a fixed location in the contents, + // right at the start. Arguably the end would be better, but the + // end can move as loadables get added and removed. + // + // The GUI code will probably want to ignore any empty + // containers that are not valuables and not user-visible. + orphans = new CdlContainerBody("orphans"); + add_node(0, this, orphans); + + // Let the interpreter know about its owning toplevel, as well as + // vice versa. + interp->set_toplevel(this); + + // The orphans container needs to be active as well. + orphans->active = true; + + CYGDBG_MEMLEAK_CONSTRUCTOR(); + + CYG_POSTCONDITION_THISC(); + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ Destructor + +// ---------------------------------------------------------------------------- +// The toplevel should have been mostly cleared already, by the +// appropriate derived class. Without any loadables there should not +// be any conflicts. It is necessary to clean up the orphans +// container, since that was created by the CdlToplevel constructor. +// If there are any other special nodes then these should have been +// cleared by higher level code. + +CdlToplevelBody::~CdlToplevelBody() +{ + CYG_REPORT_FUNCNAME("CdlToplevel:: destructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CYG_PRECONDITIONC(0 == loadables.size()); + CYG_PRECONDITIONC(0 == conflicts.size()); + CYG_PRECONDITIONC(0 == structural_conflicts.size()); + CYG_PRECONDITIONC(0 == transaction); + + CYG_PRECONDITIONC(0 != orphans); + this->remove_node_from_toplevel(orphans); + CdlToplevelBody::remove_node(0, this, orphans); + delete orphans; + orphans = 0; + + CYG_PRECONDITIONC(0 == contents.size()); + + cdltoplevelbody_cookie = CdlToplevelBody_Magic; + description = ""; + limbo.clear(); + unsupported_savefile_toplevel_strings.clear(); + unsupported_savefile_commands.clear(); + unsupported_savefile_subcommands.clear(); + + // Since the interpreter is not created by the toplevel, it is + // not destroyed with the toplevel either. This leaves a potential + // big memory leak in application code. + interp = 0; + + CYGDBG_MEMLEAK_DESTRUCTOR(); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ Adding and removing nodes + +// ---------------------------------------------------------------------------- +// Adding and removing a node, and changing a parent. +// +// These routines allow the hierarchy to be manipulated. All nodes should +// exist in a hierarchy below a toplevel, except for brief periods after +// construction and during destruction. +// +// Most nodes will belong to a loadable. An owner of 0 is allowed, for +// objects internal to the library such as the orphans container. +// Everything else must have an owner, and specifically a loadable owns +// itself. + +void +CdlToplevelBody::add_node(CdlLoadable owner, CdlContainer parent, CdlNode node) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::add_node"); + CYG_REPORT_FUNCARG4XV(this, owner, parent, node); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_ZERO_OR_CLASSC(owner); + CYG_PRECONDITION_CLASSC(parent); + CYG_PRECONDITION_CLASSC(node); + + // The node must not be in the hierarchy already. + CYG_ASSERTC(0 == node->toplevel); + CYG_ASSERTC(0 == node->owner); + CYG_ASSERTC(0 == node->parent); + + // The node's name should be unique. Checks for that should have happened + // in higher-level code. + CYG_ASSERTC(lookup_table.find(node->name) == lookup_table.end()); + node->toplevel = this; + lookup_table[node->name] = node; + + node->owner = owner; + if (0 != owner) { + owner->owned.push_back(node); + } + + // If the node is in fact a loadable, it should own itself and + // in addition the toplevel class keeps track of its loadables + // in a separate vector. + if (0 != dynamic_cast(node)) { + CYG_ASSERTC(owner == dynamic_cast(node)); + this->loadables.push_back(owner); + } + + if (0 == parent) { + parent = orphans; + } + node->parent = parent; + parent->contents.push_back(node); + + CYG_REPORT_RETURN(); +} + +// Removing a node from a toplevel. This is the first step in deleting +// a node: the step may be undone by a call to add_node_to_toplevel(), +// or completed by a call to remove_node(). Removing a node from the +// toplevel involves undoing the name->node mapping. In the case +// of loadables, it also involves removing the node from the toplevel's +// contents and loadables containers. + +void +CdlToplevelBody::remove_node_from_toplevel(CdlNode node) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::remove_node_from_toplevel"); + CYG_REPORT_FUNCARG2XV(this, node); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(node); + CYG_ASSERTC(this == node->toplevel); + CYG_ASSERTC(lookup_table[node->name] == node); + + node->toplevel = 0; + lookup_table.erase(node->name); + + CdlLoadable loadable = dynamic_cast(node); + if (0 != loadable) { + CYG_ASSERTC(loadable == node->owner); + CYG_ASSERTC(this == node->parent); + + // Because remove_node_from_toplevel() is reversible, the + // loadable should reappear in its old position. Hence we + // had better keep track of that position. Note that + // this code assumed that the remove_node and add_node + // calls are exactly reversed. + int i; + for (i = 0; i < (int) this->contents.size(); i++) { + if (this->contents[i] == node) { + break; + } + } + CYG_ASSERTC(i < (int) this->contents.size()); + node->remove_node_container_position = i; + this->contents.erase(this->contents.begin() + i); + node->parent = 0; + + // It is not clear that preserving the order of the loadables + // in the toplevel is useful, but it is harmless. + for (i = 0; i < (int) this->loadables.size(); i++) { + if (this->loadables[i] == loadable) { + break; + } + } + CYG_ASSERTC(i < (int) this->loadables.size()); + loadable->remove_node_loadables_position = i; + this->loadables.erase(this->loadables.begin() + i); + } + + CYG_REPORT_RETURN(); +} + +void +CdlToplevelBody::remove_loadable_from_toplevel(CdlLoadable loadable) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::remove_loadable_from_toplevel"); + CYG_REPORT_FUNCARG2XV(this, loadable); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(loadable); + + const std::vector& contents = loadable->get_owned(); + for (int i = contents.size() - 1; i >= 0; i--) { + CdlToplevel toplevel = contents[i]->get_toplevel(); + CYG_LOOP_INVARIANT_ZERO_OR_CLASSC(toplevel); + if (0 != toplevel) { + CYG_LOOP_INVARIANTC(this == toplevel); + this->remove_node_from_toplevel(contents[i]); + } + } + + CYG_REPORT_RETURN(); +} + +// Re-adding a node to a toplevel. This needs to undo all of the changes +// that may have been done by remove_node_from_toplevel() above. +void +CdlToplevelBody::add_node_to_toplevel(CdlNode node) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::add_node_to_toplevel"); + CYG_REPORT_FUNCARG2XV(this, node); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(node); + CYG_ASSERTC(0 == node->toplevel); + CYG_ASSERTC(0 != node->owner); + + CYG_ASSERTC(lookup_table.find(node->name) == lookup_table.end()); + node->toplevel = this; + lookup_table[node->name] = node; + + CdlLoadable loadable = dynamic_cast(node); + if (0 != loadable) { + CYG_ASSERTC(loadable == node->owner); + CYG_ASSERTC(0 == node->parent); + CYG_ASSERTC(-1 != node->remove_node_container_position); + CYG_ASSERTC(node->remove_node_container_position <= (int) this->contents.size()); + + this->contents.insert(this->contents.begin() + node->remove_node_container_position, node); + node->remove_node_container_position = -1; + node->parent = this; + + CYG_ASSERTC(-1 != loadable->remove_node_loadables_position); + this->loadables.insert(this->loadables.begin() + loadable->remove_node_loadables_position, loadable); + loadable->remove_node_loadables_position = -1; + } + + CYG_REPORT_RETURN(); +} + +void +CdlToplevelBody::add_loadable_to_toplevel(CdlLoadable loadable) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::add_loadable_to_toplevel"); + CYG_REPORT_FUNCARG2XV(this, loadable); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(loadable); + + const std::vector& contents = loadable->get_owned(); + for (int i = 0; i < (int) contents.size(); i++) { + this->add_node_to_toplevel(contents[i]); + } + + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- +// The second stage remove operation. This cannot be undone, and +// happens just before the node gets deleted and after a succesful +// remove_node_from_toplevel(). +void +CdlToplevelBody::remove_node(CdlLoadable owner, CdlContainer parent, CdlNode node) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::remove_node"); + CYG_REPORT_FUNCARG3XV(owner, parent, node); + CYG_PRECONDITION_CLASSC(node); + CYG_PRECONDITION_ZERO_OR_CLASSC(owner); + CYG_PRECONDITION_ZERO_OR_CLASSC(parent); + CYG_PRECONDITIONC(node->owner == owner); + CYG_PRECONDITIONC(node->parent == parent); + CYG_PRECONDITIONC(0 == node->toplevel); + + if (0 != owner) { + node->owner = 0; + owner->owned.erase(std::find(owner->owned.begin(), owner->owned.end(), node)); + } + if (0 != parent) { + node->parent = 0; + parent->contents.erase(std::find(parent->contents.begin(), parent->contents.end(), node)); + } + + CYG_REPORT_RETURN(); +} + +// Changing a parent does not affect the node's standing in terms of the +// overall hierarchy or its owner, only the parent field. +void +CdlToplevelBody::change_parent(CdlLoadable owner, CdlContainer old_parent, CdlContainer new_parent, CdlNode node, int pos) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::change_parent"); + CYG_REPORT_FUNCARG6XV(this, owner, parent, new_parent, node, pos); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(old_parent); + CYG_PRECONDITION_ZERO_OR_CLASSC(new_parent); + CYG_PRECONDITION_CLASSC(node); + CYG_PRECONDITIONC(node->owner == owner); + CYG_PRECONDITIONC(node->parent == old_parent); + CYG_PRECONDITIONC(this == node->toplevel); + CYG_PRECONDITIONC(lookup_table[node->name] == node); + + if (0 == new_parent) { + new_parent = orphans; + } + old_parent->contents.erase(std::find(old_parent->contents.begin(), old_parent->contents.end(), node)); + node->parent = 0; + + if (-1 == pos) { + new_parent->contents.push_back(node); + } else { + CYG_ASSERTC(pos <= (int) new_parent->contents.size()); + new_parent->contents.insert(new_parent->contents.begin() + pos, node); + } + node->parent = new_parent; + + CYG_REPORT_RETURN(); +} + +// Cleaning up orphans. +// +// Right now this is only relevant for interfaces. Consider the case +// where a loadable is being removed and that loadable defines an +// interface. There may be other loadables which still have +// "implements" properties affecting that interface, so instead of +// deleting the cdl_interface object it is necessary to turn it into +// an auto-generated orphan. At some stage there may no longer be +// any references to an interface, in which case it can be removed +// safely. +// +// In practice it is quite hard to do a clean-up purely on the basis +// of implements properties, for example there may be an external +// "requires" property as well which would need to have its references +// cleaned up, then the expression needs to get re-evaluated, etc. +// The transaction class does not currently provide a clean way +// in which a single object can be destroyed. Instead the code below +// checks for any references whose source is not the interface itself. + +void +CdlToplevelBody::cleanup_orphans() +{ + CYG_REPORT_FUNCNAME("CdlToplevel::cleanup_orphans"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + // First figure out whether or not there are any interfaces along + // these lines. + std::vector interfaces; + const std::vector& contents = orphans->get_contents(); + std::vector::const_iterator node_i; + + for (node_i = contents.begin(); node_i != contents.end(); node_i++) { + CdlInterface intface = dynamic_cast(*node_i); + if (0 == intface) { + continue; + } + const std::vector& referrers = intface->get_referrers(); + std::vector::const_iterator ref_i; + for (ref_i = referrers.begin(); ref_i != referrers.end(); ref_i++) { + if (ref_i->get_source() != intface) { + break; + } + } + if (ref_i == referrers.end()) { + // None of the existing references involve an "implements" property, so + // this interface can be deleted. + interfaces.push_back(intface); + } + } + + if (0 != interfaces.size()) { + CYG_FAIL("Not yet implemented"); + } +} + +//}}} +//{{{ Basic information + +// ---------------------------------------------------------------------------- + +const std::vector& +CdlToplevelBody::get_loadables() const +{ + CYG_REPORT_FUNCNAMETYPE("CdlToplevel::get_loadables", "result %p"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + const std::vector& result = loadables; + CYG_REPORT_RETVAL(&result); + return result; +} + + +CdlNode +CdlToplevelBody::lookup(const std::string name) const +{ + CYG_REPORT_FUNCNAMETYPE("CdlToplevel::lookup", "result %p"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITIONC("" != name); + + CdlNode result = 0; + std::map::const_iterator i = lookup_table.find(name); + if (i != lookup_table.end()) { + result = i->second; + } + + CYG_REPORT_RETVAL(result); + return result; +} + +CdlInterpreter +CdlToplevelBody::get_interpreter() const +{ + CYG_REPORT_FUNCNAMETYPE("CdlToplevel::get_interpreter", "result %p"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlInterpreter result = interp; + CYG_REPORT_RETVAL(result); + return result; +} + +std::string +CdlToplevelBody::get_description() const +{ + CYG_REPORT_FUNCNAME("CdlToplevel::get_description"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CYG_REPORT_RETURN(); + return description; +} + +void +CdlToplevelBody::set_description(std::string new_description) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::set_description"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + description = new_description; + + CYG_REPORT_RETURN(); +} + +std::string +CdlToplevelBody::get_directory() const +{ + CYG_REPORT_FUNCNAME("CdlToplevel::get_directory"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CYG_REPORT_RETURN(); + return directory; +} + +std::string +CdlToplevelBody::get_class_name() const +{ + CYG_REPORT_FUNCNAME("CdlToplevel::get_class_name"); + CYG_PRECONDITION_THISC(); + CYG_REPORT_RETURN(); + return "toplevel"; +} + +CdlTransaction +CdlToplevelBody::get_active_transaction() const +{ + CYG_REPORT_FUNCNAMETYPE("CdlToplevel::get_active_transaction", "result %p"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlTransaction result = transaction; + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ Conflict support + +// ---------------------------------------------------------------------------- +const std::list& +CdlToplevelBody::get_all_conflicts() const +{ + CYG_REPORT_FUNCNAME("CdlToplevel::get_all_conflicts"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + const std::list& result = conflicts; + + CYG_REPORT_RETURN(); + return result; +} + +const std::list& +CdlToplevelBody::get_all_structural_conflicts() const +{ + CYG_REPORT_FUNCNAME("CdlToplevel::get_all_structural_conflicts"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + const std::list& result = structural_conflicts; + + CYG_REPORT_RETURN(); + return result; +} + +// ---------------------------------------------------------------------------- +// Resolve one or more conflicts. This involves creating a new transaction, +// invoking the per-transaction resolve code, and then CdlTransaction::body() +// takes care of everything else like propagation, further inference, +// callbacks, committing, ... +void +CdlToplevelBody::resolve_conflicts(const std::vector& conflicts_arg) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::resolve_conflicts"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlTransaction transact = CdlTransactionBody::make(this); + + std::vector::const_iterator conf_i; + for (conf_i = conflicts_arg.begin(); conf_i != conflicts_arg.end(); conf_i++) { + CYG_LOOP_INVARIANT_CLASSC(*conf_i); + CYG_LOOP_INVARIANTC(0 == (*conf_i)->get_transaction()); + + if (((*conf_i)->resolution_implemented()) && + !transact->has_conflict_been_cleared(*conf_i) && + !(*conf_i)->has_known_solution() && + !(*conf_i)->has_no_solution() ) { + transact->resolve(*conf_i); + } + } + transact->body(); + delete transact; + + CYG_REPORT_RETURN(); +} + +void +CdlToplevelBody::resolve_all_conflicts() +{ + CYG_REPORT_FUNCNAME("CdlToplevel::resolve_all_conflicts"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlTransaction transact = CdlTransactionBody::make(this); + std::list::const_iterator conf_i; + + for (conf_i = conflicts.begin(); conf_i != conflicts.end(); conf_i++) { + CYG_LOOP_INVARIANT_CLASSC(*conf_i); + CYG_LOOP_INVARIANTC(0 == (*conf_i)->get_transaction()); + if ((*conf_i)->resolution_implemented() && + !transact->has_conflict_been_cleared(*conf_i) && + !(*conf_i)->has_known_solution() && + !(*conf_i)->has_no_solution() ) { + transact->resolve(*conf_i); + } + } + for (conf_i = structural_conflicts.begin(); conf_i != structural_conflicts.end(); conf_i++) { + CYG_LOOP_INVARIANT_CLASSC(*conf_i); + CYG_LOOP_INVARIANTC(0 == (*conf_i)->get_transaction()); + if (((*conf_i)->resolution_implemented()) && + !transact->has_conflict_been_cleared(*conf_i) && + !(*conf_i)->has_known_solution() && + !(*conf_i)->has_no_solution() ) { + transact->resolve(*conf_i); + } + } + + transact->body(); + delete transact; + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ Limbo support + +// ---------------------------------------------------------------------------- +// Limbo support. This is basically trivial, an STL map does all the +// right things. +void +CdlToplevelBody::set_limbo_value(CdlValuable valuable) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::set_limbo_value"); + CYG_REPORT_FUNCARG2XV(this, valuable); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(valuable); + + limbo[valuable->get_name()] = valuable->get_whole_value(); + + CYG_REPORT_RETURN(); +} + +bool +CdlToplevelBody::has_limbo_value(std::string name) const +{ + CYG_REPORT_FUNCNAMETYPE("CdlToplevel::has_limbo_value", "result %d"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITIONC("" != name); + + bool result = false; + if (limbo.find(name) != limbo.end()) { + result = true; + } + + CYG_REPORT_RETVAL(result); + return result; +} + +CdlValue +CdlToplevelBody::get_limbo_value(std::string name) const +{ + CYG_REPORT_FUNCNAME("CdlToplevel::get_limbo_value"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITIONC("" != name); + + std::map::const_iterator limbo_i = limbo.find(name); + CYG_ASSERTC(limbo_i != limbo.end()); + + CYG_REPORT_RETURN(); + return limbo_i->second; +} + +CdlValue +CdlToplevelBody::get_and_remove_limbo_value(std::string name) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::get_and_remove_limbo_value"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITIONC("" != name); + + std::map::iterator limbo_i = limbo.find(name); + CYG_ASSERTC(limbo_i != limbo.end()); + + CdlValue local_copy = limbo_i->second; + limbo.erase(limbo_i); + + CYG_REPORT_RETURN(); + return local_copy; +} + +void +CdlToplevelBody::clear_limbo() +{ + CYG_REPORT_FUNCNAME("CdlToplevel::clear_limbo"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + limbo.clear(); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ Persistence support + +//{{{ Description + +// ---------------------------------------------------------------------------- +// Toplevels do not have any data specifically associated with them which +// should go into savefiles (not quite true, there is a description field, +// but that can be handled easily by the derived classes). +// +// However there is a need in the library for some generic savefile support: +// +// 1) it is an important goal that savefiles should be self-describing. +// This is handled by having a header section at the start of each +// savefile which describes what commands will appear in the savefile +// (note that savefiles are actually just Tcl scripts). In addition +// each savefile contains a version number so that individual commands +// can detect and adapt to older versions of the library. +// +// 2) savefiles should also be extensible, so for example a GUI tool should +// be able to add its own information. This can be toplevel information, +// i.e. a new command that gets executed at the savefile's toplevel, +// or it can be a subcommand extending an existing command such as +// cdl_option. Right now only one level of nesting is available, but +// this should suffice. +// +// 3) extensibility means that the application reading in a savefile may +// not support the same set of commands as the application that generated +// the savefile. Care is taken to avoid loss of data. However exact +// ordering is not guaranteed to be preserved, and neither is formatting. +// +// These needs are interrelated, and supported by the CdlToplevelBody +// class. The functions of interest are: +// +// virtual void initialize_savefile_support() +// This should be called from higher-level code such as +// CdlConfiguration::initialize_savefile_support() at the start of +// any savefile-related operation. +// +// The support operates on a per-application basis rather than a +// per-toplevel basis, in spite of being a virtual member function +// rather than a static. A virtual member function facilitates +// automatic initialization. This causes some problems if you need +// to load in toplevels with different application-specific +// extensions, but it makes life a lot simpler for the application. +// +// static bool savefile_support_initialized() +// Has there been a call to initialize_savefile_support() yet? +// +// virtual void add_savefile_command(std::string, CdlSaveCallback, CdlInterpreterCommand) +// Register a new savefile toplevel command. The string must be a +// valid command name. The callback function will be 0 for savedata +// supported directly by the library, non-zero for application-specific +// data, and is invoked during a save operation to allow application +// code to add extra data to the savefile. The command procedure must +// be provided and is registered with the Tcl interpreter. +// +// virtual void add_savefile_subcommand(std::string cmd, std::string subcommand, CdlSaveCallback, CdlInterpreterCommand) +// Typically savefile commands take the form , +// where contains a set of subcommands. This function is used +// to register a new subcommand. +// +// void save_command_details(CdlInterpreter, Tcl_Channel, int) +// This should be invoked early on when generating a savefile. Its +// purpose is to store information about the current set of savefile +// commands in the savefile, thus making savefiles self-describing. +// This command acts on a per-toplevel basis, since each toplevel +// may have been created via a load operation and hence may contain +// unrecognised commands. +// +// static void get_savefile_commands(std::vector&) +// Work out the set of commands that should be supported by the +// interpreter used to process a savefile. Note that this set gets +// updated magically by savefile_handle_command(). +// +// static void get_savefile_subcommands(std::string, std::vector&) +// Ditto for subcommands. +// +// static int savefile_handle_command(CdlInterpreter, int, char**) +// This implements cdl_savefile_command, and makes sure that +// all of the commands that may be present in the savefile will +// be processed. +// +// static int savefile_handle_unsupported(CdlInterpreter, int, char**) +// This takes care of commands present in the savefile which are +// not supported by the current application. +// +// static int savefile_handle_unknown(CdlInterpreter, int, char**) +// This is an implementation of "unknown" suitable for savefiles. +// All commands that may get used in a savefile should be specified +// via cdl_savefile_command, so an unknown command is an error. +// +// cdl_int get_library_savefile_version() +// Savefiles contain a format version number. This function can be used +// to determine the current version used in the library. +// +// int savefile_handle_version(CdlInterpreter, int, char**) +// This is the implementation of the cdl_savefile_version command. It +// stores the version information in the interpreter, allowing it +// to be retrieved by other commands. +// +// cdl_int get_savefile_version(CdlInterpreter) +// This can be used to retrieve the version number that was present +// in the current savefile. +// +// The version number should not be used for application-specific +// commands. It is possible for a savefile to be read in by a +// different program and then updated: the updated savefile will +// contain the unrecognised commands unchanged, but it will also +// have the version number corresponding to that program rather +// than to the original savefile. +// +// void save_conflicts(CdlInterpreter, Tcl_Channel, int) +// Output details of all the conflicts in the current configuration +// +// void save_separator(CdlInterpreter, Tcl_Channel, int) +// A utility to add a separator line to a savefile. This has to +// go somewhere.... +// +// FIXME: add limbo support + +//}}} +//{{{ Statics and initialization + +// ---------------------------------------------------------------------------- +bool CdlToplevelBody::savefile_commands_initialized = false; +std::vector CdlToplevelBody::savefile_commands; +std::map > CdlToplevelBody::savefile_subcommands; + +void +CdlToplevelBody::initialize_savefile_support() +{ + CYG_REPORT_FUNCNAME("CdlToplevel::initialize_savefile_support"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + // This assignment avoids circular dependencies. It is not + // completely accurate but close enough - the full set of + // commands will be initialised shortly. + savefile_commands_initialized = true; + + // The commands cdl_savefile_version and cdl_command are a core + // part of the CDL savefile support. + add_savefile_command("cdl_savefile_version", 0, &savefile_handle_version); + add_savefile_command("cdl_savefile_command", 0, &savefile_handle_command); + + CYG_REPORT_RETURN(); +} + +bool +CdlToplevelBody::savefile_support_initialized() +{ + CYG_REPORT_FUNCNAMETYPE("CdlToplevel::check_savefile_support_initialized", "result %d"); + + bool result = savefile_commands_initialized; + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ Command details + +// ---------------------------------------------------------------------------- +// These routines are used to keep track of the savefile commands that +// are understood by the current application. There may have been +// additional per-toplevel commands when a savefile was read in, but +// these are stored separately. +// +// Currently there is only support for toplevel savefile commands +// and for one level of subcommands. Multiple levels can probably +// be accommodated by using the equivalent of a directory separator +// in the savefile_subcommands map key. + +void +CdlToplevelBody::add_savefile_command(std::string name, CdlSaveCallback save_callback, CdlInterpreterCommand load_command) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::add_savefile_command"); + CYG_REPORT_FUNCARG3XV(this, save_callback, load_command); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITIONC("" != name); + + if (!savefile_commands_initialized) { + this->initialize_savefile_support(); + } + + std::vector::const_iterator cmd_i; + for (cmd_i = savefile_commands.begin(); cmd_i != savefile_commands.end(); cmd_i++) { + if (cmd_i->name == name) { + if ((cmd_i->save_callback != save_callback) || (cmd_i->load_command != load_command)) { + CYG_FAIL("Internal error: attempt to define two toplevel savefile commands with the same name."); + } + break; + } + } + if (cmd_i == savefile_commands.end()) { + CdlSavefileCommand cmd; + cmd.name = name; + cmd.save_callback = save_callback; + cmd.load_command = load_command; + savefile_commands.push_back(cmd); + + std::vector subcommands; + savefile_subcommands[name] = subcommands; + } + + CYG_REPORT_RETURN(); +} + +// Add a new subcommand for a given command. The command should have been +// defined already. +void +CdlToplevelBody::add_savefile_subcommand(std::string cmd, std::string subcommand, CdlSaveCallback save_callback, + CdlInterpreterCommand load_command) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::add_savefile_subcommand"); + CYG_REPORT_FUNCARG3XV(this, save_callback, load_command); + CYG_PRECONDITION_THISC(); + + if (!savefile_commands_initialized) { + this->initialize_savefile_support(); + } + + std::vector::iterator cmd_i; + for (cmd_i = savefile_commands.begin(); cmd_i != savefile_commands.end(); cmd_i++) { + if (cmd_i->name == cmd) { + break; + } + } + CYG_ASSERTC(cmd_i != savefile_commands.end()); + + for (cmd_i = savefile_subcommands[cmd].begin(); cmd_i != savefile_subcommands[cmd].end(); cmd_i++) { + if (cmd_i->name == subcommand) { + if ((cmd_i->save_callback != save_callback) || (cmd_i->load_command != load_command)) { + CYG_FAIL("Internal error: attempt to define two subcommands with the same name."); + } + } + } + if (cmd_i == savefile_subcommands[cmd].end()) { + CdlSavefileCommand new_subcommand; + new_subcommand.name = subcommand; + new_subcommand.save_callback = save_callback; + new_subcommand.load_command = load_command; + savefile_subcommands[cmd].push_back(new_subcommand); + } + + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- +// This member function is invoked by e.g. CdlConfiguraton::save() to +// take care of the generic savefile information, specifically the +// savefile format version number and the various commands and subcommands +// Note that it has to cope with per-toplevel commands from the original +// savefile, as well as the global set. + +void +CdlToplevelBody::save_command_details(CdlInterpreter interp, Tcl_Channel chan, int indentation, bool minimal) + throw(CdlInputOutputException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::save_command_details"); + CYG_REPORT_FUNCARG4XV(this, interp, chan, indentation); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(interp); + CYG_ASSERTC(0 == indentation); + + // The parent code should have provided the first couple of lines, + // identifying whether this is an eCos configuration or some other + // CDL-based entity. + // + // Immediately after these lines we want a nice big comment + // telling people that they can edit bits of this file, but + // that other bits are automatically generated and will + // be overwritten. + + if (!minimal) { + interp->write_data(chan, +"# This section contains information about the savefile format.\n\ +# It should not be edited. Any modifications made to this section\n\ +# may make it impossible for the configuration tools to read\n\ +# the savefile.\n\ +\n"); + } + + // Next output details of the savefile format version. This allows + // all other code to adapt to the version. + std::string savefile_data; + Cdl::integer_to_string(savefile_version, savefile_data); + savefile_data = "cdl_savefile_version " + savefile_data + ";\n"; + + std::vector::const_iterator cmd_i, cmd_j; + std::vector::const_iterator cmd_k, cmd_l; + + for (cmd_i = savefile_commands.begin(); cmd_i != savefile_commands.end(); cmd_i++) { + savefile_data += "cdl_savefile_command " + cmd_i->name + " "; + + if ((0 == savefile_subcommands[cmd_i->name].size()) && + (0 == this->unsupported_savefile_subcommands[cmd_i->name].size())) { + + savefile_data += "{};\n"; + + } else { + + savefile_data += "{"; + for (cmd_j = savefile_subcommands[cmd_i->name].begin(); + cmd_j != savefile_subcommands[cmd_i->name].end(); + cmd_j++) { + + savefile_data += " " + cmd_j->name; + } + for (cmd_l = this->unsupported_savefile_subcommands[cmd_i->name].begin(); + cmd_l != this->unsupported_savefile_subcommands[cmd_i->name].end(); + cmd_l++) { + + savefile_data += " " + *cmd_l; + } + savefile_data += " };\n"; + } + } + for (cmd_k = this->unsupported_savefile_commands.begin(); + cmd_k != this->unsupported_savefile_commands.end(); + cmd_k++) { + savefile_data += "cdl_savefile_command " + *cmd_k + " "; + if (0 == this->unsupported_savefile_subcommands[*cmd_k].size()) { + + savefile_data += "{};\n"; + + } else { + + savefile_data += "{"; + for (cmd_l = this->unsupported_savefile_subcommands[*cmd_k].begin(); + cmd_l != this->unsupported_savefile_subcommands[*cmd_k].end(); + cmd_l++) { + + savefile_data += " " + *cmd_l; + } + savefile_data += " };\n"; + } + } + savefile_data += "\n"; + + interp->write_data(chan, savefile_data); + + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- +// Get hold of the commands that should be added to the interpreter for +// processing a savefile. Note that this will only deal with commands +// supported by the library or the application, not any additional +// unsupported commands specified in the savefile itself. The latter +// will be taken care of magically by savefile_handle_command(). + +void +CdlToplevelBody::get_savefile_commands(std::vector& cmds) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::get_savefile_commands"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlInterpreterCommandEntry local_cmd; + std::vector::const_iterator cmd_i; + for (cmd_i = savefile_commands.begin(); cmd_i != savefile_commands.end(); cmd_i++) { + // NOTE: this use of c_str() is somewhat dubious, but the string should not + // change so the c_str() array should remain ok as well. + local_cmd.name = cmd_i->name; + local_cmd.command = cmd_i->load_command; + cmds.push_back(local_cmd); + } + + // There is no point in iterating over this->unsupported_savefile_commands, + // that vector should be empty since we have not actually started + // processing the savefile yet. + CYG_ASSERTC(0 == this->unsupported_savefile_commands.size()); + + // Add an implementation of the "unknown" command. + local_cmd.name = "unknown"; + local_cmd.command = &CdlToplevelBody::savefile_handle_unknown; + cmds.push_back(local_cmd); + + CYG_REPORT_RETURN(); +} + +// Having repeated calls of this for e.g. every cdl_option statement in +// a savefile is expensive. Some sort of caching mechanism should be +// used to avoid unnecessary overheads. +void +CdlToplevelBody::get_savefile_subcommands(std::string main_command, std::vector& cmds) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::get_savefile_subcommands"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlInterpreterCommandEntry local_cmd; + std::vector::const_iterator cmd_i; + for (cmd_i = savefile_subcommands[main_command].begin(); + cmd_i != savefile_subcommands[main_command].end(); + cmd_i++) { + + local_cmd.name = cmd_i->name.c_str(); + local_cmd.command = cmd_i->load_command; + cmds.push_back(local_cmd); + } + + std::vector::const_iterator cmd_j; + for (cmd_j = this->unsupported_savefile_subcommands[main_command].begin(); + cmd_j != this->unsupported_savefile_subcommands[main_command].end(); + cmd_j++) { + + local_cmd.name = cmd_j->c_str(); + local_cmd.command = &savefile_handle_unsupported; + cmds.push_back(local_cmd); + } + + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- +// This implements cdl_savefile_command which should appear near the +// start of savefiles. The command takes two arguments, a primary +// command name and a set of subcommand names. +int +CdlToplevelBody::savefile_handle_command(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::savefile_handle_command"); + CYG_REPORT_FUNCARG2XV(interp, argc); + CYG_PRECONDITION_CLASSC(interp); + + CdlToplevel toplevel = interp->get_toplevel(); + CYG_ASSERT_CLASSC(toplevel); + CYG_ASSERTC(toplevel->savefile_commands_initialized); + + if (1 == argc) { + CdlParse::report_error(interp, "expecting at least one argument to cdl_savefile_command"); + } else if (2 == argc) { + CdlParse::report_warning(interp, std::string("missing third argument to `cdl_savefile_command ") + argv[1] + + "'\n.Expecting an additional list of subcommands."); + } else if (3 != argc) { + CdlParse::report_warning(interp, std::string("unexpected additional arguments to `cdl_savefile_command ") + + argv[1] + " { " + argv[2] + " }"); + } + + // Is the primary command one of the known ones? + bool known_command = false; + std::vector::const_iterator cmd_i; + std::vector::const_iterator cmd_j; + + if (1 != argc) { + // Make sure that the primary command is known. + for (cmd_i = savefile_commands.begin(); cmd_i != savefile_commands.end(); cmd_i++) { + if (cmd_i->name == argv[1]) { + known_command = true; + break; + } + } + if (!known_command) { + // Detect duplicate definitions, just in case. + for (cmd_j = toplevel->unsupported_savefile_commands.begin(); + cmd_j != toplevel->unsupported_savefile_commands.end(); + cmd_j++) { + if (*cmd_j == argv[1]) { + break; + } + } + if (cmd_j == toplevel->unsupported_savefile_commands.end()) { + toplevel->unsupported_savefile_commands.push_back(argv[1]); + } + } + } + + // Now take care of all the subcommands. + if (2 != argc) { + + int list_count = 0; + char** list_entries = 0; + + try { + Tcl_Interp* tcl_interp = interp->get_tcl_interpreter(); + if (TCL_OK != Tcl_SplitList(tcl_interp, argv[2], &list_count, &list_entries)) { + CdlParse::report_error(interp, std::string("invalid subcommand list for `cdl_command ") + argv[1] + "'."); + } + + for (int i = 0; i < list_count; i++) { + bool known_subcommand = false; + if (known_command) { + for (cmd_i = savefile_subcommands[argv[1]].begin(); + cmd_i != savefile_subcommands[argv[1]].end(); + cmd_i++) { + + if (cmd_i->name == list_entries[i]) { + known_subcommand = true; + } + } + } + if (!known_subcommand) { + for (cmd_j = toplevel->unsupported_savefile_subcommands[argv[1]].begin(); + cmd_j != toplevel->unsupported_savefile_subcommands[argv[1]].end(); + cmd_j++) { + + if (*cmd_j == list_entries[i]) { + known_subcommand = true; + break; + } + } + } + if (!known_subcommand) { + toplevel->unsupported_savefile_subcommands[argv[1]].push_back(list_entries[i]); + } + + } + + if (0 != list_entries) { + Tcl_Free((char *)list_entries); + } + + } catch(...) { + if (0 != list_entries) { + Tcl_Free((char *)list_entries); + } + throw; + } + } + + return TCL_OK; +} + +//}}} +//{{{ handle_unsupported() + +// ---------------------------------------------------------------------------- +// This function is invoked when an unsupported command is detected in +// a savefile. It turns the data back into a string which can go back +// into the next savefile, thus avoiding loss of data. +// +// It is possible that the savefile contents involved variable or +// command substitution. If so then this information will have been +// lost, there is no simple way of retrieving this from the interpreter. +// Care has to be taken when generating the new command string to +// perform appropriate quoting. +// +// Ideally the original data could be extracted from the Tcl +// interpreter somehow. Currently this data is not readily available, +// and the resulting string may not match the original data exactly. +int +CdlToplevelBody::savefile_handle_unsupported(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAME("CdlNode::savefile_handle_unsupported"); + CYG_REPORT_FUNCARG2XV(interp, argc); + CYG_ASSERT_CLASSC(interp); + + CdlToplevel toplevel = interp->get_toplevel(); + CYG_ASSERT_CLASSC(toplevel); + CdlNode node = interp->get_node(); + CYG_ASSERT_ZERO_OR_CLASSC(node); + + std::string tmp = CdlInterpreterBody::quote(argv[0]); + for (int i = 1; i < argc; i++) { + tmp = tmp + " " + CdlInterpreterBody::quote(argv[i]); + } + // Unknown commands may occur at the toplevel or inside + // e.g. a cdl_option body. Toplevels are also nodes. + if (0 == node) { + toplevel->unsupported_savefile_toplevel_strings.push_back(tmp); + } else { + node->unsupported_savefile_strings.push_back(tmp); + } + + return TCL_OK; +} + +//}}} +//{{{ save_unsupported() + +// ---------------------------------------------------------------------------- +// This code deals with any toplevel data present in the original save +// file that was not recognised. +void +CdlToplevelBody::save_unsupported_commands(CdlInterpreter interp, Tcl_Channel chan, int indentation, bool minimal) + throw(CdlInputOutputException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlToplevelBody::save_unsupported_commands"); + CYG_REPORT_FUNCARG3XV(this, interp, chan); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(interp); + CYG_PRECONDITIONC(0 == indentation); + + std::string data = "\n"; + std::vector::const_iterator str_i; + for (str_i = unsupported_savefile_toplevel_strings.begin(); + str_i != unsupported_savefile_toplevel_strings.end(); + str_i++) { + data += *str_i + " ;\n"; + } + interp->write_data(chan, data); + + CYG_UNUSED_PARAM(bool, minimal); + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ handle_unknown() + +// ---------------------------------------------------------------------------- + +int +CdlToplevelBody::savefile_handle_unknown(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::savefile_handle_unknown"); + CYG_REPORT_FUNCARG2XV(interp, argc); + CYG_PRECONDITION_CLASSC(interp); + + std::string msg = std::string("Unknown command `") + argv[1] + "'."; + CdlParse::report_error(interp, msg); + + CYG_UNUSED_PARAM(int, argc); + return TCL_OK; +} + +//}}} +//{{{ versioning + +// ---------------------------------------------------------------------------- +// Savefiles include a version number that can be used by library +// commands to cope with old and incompatible savefiles. This +// version number should be changed only very rarely, hopefully never. +cdl_int CdlToplevelBody::savefile_version = 1; + +cdl_int +CdlToplevelBody::get_library_savefile_version() +{ + CYG_REPORT_FUNCNAMETYPE("CdlToplevel::get_library_savefile_version", "result %ld"); + + cdl_int result = savefile_version; + CYG_REPORT_RETVAL((long) result); + return result; +} + +// This implements the cdl_savefile_version command. It stores the +// version number with the interpreter, allowing it to be retrieved +// by other commands. +int +CdlToplevelBody::savefile_handle_version(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::savefile_handle_version"); + CYG_REPORT_FUNCARG2XV(interp, argc); + CYG_PRECONDITION_CLASSC(interp); + + if (1 == argc) { + CdlParse::report_warning(interp, "expecting one argument to cdl_savefile_version"); + } else { + if (2 != argc) { + CdlParse::report_warning(interp, std::string("unexpected number of arguments to cdl_savefile_version\n") + + "There should be exactly one argument, the savefile format version number."); + } + cdl_int tmp; + if (!Cdl::string_to_integer(argv[1], tmp)) { + CdlParse::report_error(interp, std::string("invalid version number `") + argv[1] + + "' for cdl_savefile_version"); + } else { + // Store the data in a Tcl variable. This is at least as convenient + // as assoc data. + interp->set_variable("cdl_savefile_version", argv[1]); + } + } + + return TCL_OK; +} + +cdl_int +CdlToplevelBody::get_savefile_version(CdlInterpreter interp) +{ + CYG_REPORT_FUNCNAMETYPE("CdlToplevel::get_savefile_version", "result %ld"); + CYG_REPORT_FUNCARG1XV(interp); + CYG_PRECONDITION_CLASSC(interp); + + cdl_int result = 0; + std::string version = interp->get_variable("cdl_savefile_version"); + if ("" != version) { + if (!Cdl::string_to_integer(version, result)) { + CdlParse::report_error(interp, std::string("invalid cdl_savefile_version number `") + version + "'"); + } + } + + CYG_REPORT_RETVAL((long) result); + return result; +} + +//}}} +//{{{ conflicts + +// ---------------------------------------------------------------------------- +void +CdlToplevelBody::save_conflicts(CdlInterpreter interp, Tcl_Channel chan, int indentation, bool minimal) + throw(CdlInputOutputException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::save_conflicts"); + CYG_REPORT_FUNCARG4XV(this, interp, chan, indentation); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(interp); + CYG_PRECONDITIONC(0 == indentation); + + // For now only comments are generated here, so in a minimal save + // there is no need for any of this data + if (!minimal) { + std::string data = ""; + if (0 == conflicts.size()) { + data += "# There are no conflicts.\n"; + } else { + std::string tmp; + Cdl::integer_to_string((cdl_int) this->conflicts.size(), tmp); + data += "# There are " + tmp + " conflicts.\n"; + + std::list::const_iterator conf_i; + for (conf_i = this->conflicts.begin(); conf_i != this->conflicts.end(); conf_i++) { + data += "#\n"; + + CdlNode node = (*conf_i)->get_node(); + CdlProperty prop = (*conf_i)->get_property(); + std::string description = (*conf_i)->get_explanation(); + data += "# " + node->get_class_name() + " " + node->get_name() + "\n"; + data += "# Property " + prop->get_property_name() + "\n"; + data += CdlInterpreterBody::multiline_comment(description, 0, 2) + "\n"; + } + data += '\n'; + } + data += '\n'; + + interp->write_data(chan, data); + } + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ save_separator() + +// ---------------------------------------------------------------------------- +void +CdlToplevelBody::save_separator(CdlInterpreter interp, Tcl_Channel chan, std::string msg, bool minimal) + throw(CdlInputOutputException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::save_separator"); + CYG_REPORT_FUNCARG1XV(interp); + CYG_PRECONDITION_CLASSC(interp); + + if (!minimal) { + std::string data = "# ---- " + msg + ' '; + if (72 > data.size()) { + data += std::string(72 - data.size(), '-'); + } + data += '\n'; + interp->write_data(chan, data); + } + + CYG_REPORT_RETURN(); +} + +//}}} + +//}}} +//{{{ check_this() + +// ---------------------------------------------------------------------------- +bool +CdlToplevelBody::check_this(cyg_assert_class_zeal zeal) const +{ + if (CdlToplevelBody_Magic != cdltoplevelbody_cookie) { + return false; + } + CYGDBG_MEMLEAK_CHECKTHIS(); + + if ((zeal == cyg_extreme) || (zeal == cyg_thorough)) { + if (!interp->check_this(cyg_quick)) { + return false; + } + if ((0 == orphans) || !orphans->check_this(cyg_quick)) { + return false; + } + if (orphans != *contents.begin()) { + return false; + } + if ((0 != transaction) && !transaction->check_this(cyg_quick)) { + return false; + } + } + + return CdlContainerBody::check_this(zeal); +} + +//}}} + +//}}} +//{{{ CdlUserVisiblebody + +//{{{ Basics + +// ---------------------------------------------------------------------------- +// All user-visible object can have (and usually should have) three +// properties: display (originally known as alias), description, and +// doc. There is no additional data associated with a user-visible +// object, everything is handled via the properties. + +CdlUserVisibleBody::CdlUserVisibleBody() +{ + CYG_REPORT_FUNCNAME("CdlUserVisible:: default constructor"); + CYG_REPORT_FUNCARG1XV(this); + + cdluservisiblebody_cookie = CdlUserVisibleBody_Magic; + CYGDBG_MEMLEAK_CONSTRUCTOR(); + + CYG_POSTCONDITION_THISC(); + CYG_REPORT_RETURN(); +} + +CdlUserVisibleBody::~CdlUserVisibleBody() +{ + CYG_REPORT_FUNCNAME("CdlUserVisible:: destructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + cdluservisiblebody_cookie = CdlUserVisibleBody_Invalid; + CYGDBG_MEMLEAK_DESTRUCTOR(); + + CYG_REPORT_RETURN(); +} + +std::string +CdlUserVisibleBody::get_class_name() const +{ + CYG_REPORT_FUNCNAME("CdlUserVisible::get_class_name"); + CYG_PRECONDITION_THISC(); + CYG_REPORT_RETURN(); + return "uservisible"; +} + +bool +CdlUserVisibleBody::check_this(cyg_assert_class_zeal zeal) const +{ + if (CdlUserVisibleBody_Magic != cdluservisiblebody_cookie) { + return false; + } + CYGDBG_MEMLEAK_CHECKTHIS(); + return CdlNodeBody::check_this(zeal); +} + +//}}} +//{{{ Extracting information + +// ---------------------------------------------------------------------------- +// Extracting the information. + +std::string +CdlUserVisibleBody::get_display() const +{ + CYG_REPORT_FUNCNAME("CdlUserVisible::get_display"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + std::string result = ""; + CdlProperty property = get_property(CdlPropertyId_Display); + if (0 != property) { + + CdlProperty_String string_property = dynamic_cast(property); + CYG_ASSERTC(0 != string_property); + + result = string_property->get_string(); + } + + CYG_REPORT_RETURN(); + return result; +} + +std::string +CdlUserVisibleBody::get_description() const +{ + CYG_REPORT_FUNCNAME("CdlUserVisible::get_description"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + std::string result = ""; + CdlProperty property = get_property(CdlPropertyId_Description); + if (0 != property) { + + CdlProperty_String string_property = dynamic_cast(property); + CYG_ASSERTC(0 != string_property); + + result = string_property->get_string(); + } + + CYG_REPORT_RETURN(); + return result; +} + +std::string +CdlUserVisibleBody::get_doc() const +{ + CYG_REPORT_FUNCNAME("CdlUserVisible::get_doc"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + std::string result = ""; + CdlProperty property = get_property(CdlPropertyId_Doc); + if (0 != property) { + + CdlProperty_String string_property = dynamic_cast(property); + CYG_ASSERTC(0 != string_property); + + result = string_property->get_string(); + } + + CYG_REPORT_RETURN(); + return result; +} + +std::string +CdlUserVisibleBody::get_doc_url() const +{ + CYG_REPORT_FUNCNAME("CdlUserVisible::get_doc_url"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + std::string result = ""; + std::string doc_property = get_doc(); + if ("" != doc_property) { + CdlLoadable owner = get_owner(); + CYG_ASSERTC(0 != owner); + result = owner->find_absolute_file(doc_property, "doc", true); + } + + CYG_REPORT_RETURN(); + return result; +} + +//}}} +//{{{ Parsing + +// ---------------------------------------------------------------------------- +// Parsing support. There are three property parsers to be added to +// the current set. The checking code should make sure that at most +// one of each property has been specified. In addition it is +// necessary to recurse into the base class. + +void +CdlUserVisibleBody::add_property_parsers(std::vector& parsers) +{ + CYG_REPORT_FUNCNAME("CdlUserVisible::add_property_parsers"); + + static CdlInterpreterCommandEntry commands[] = + { + CdlInterpreterCommandEntry("display", &parse_display), + CdlInterpreterCommandEntry("description", &parse_description), + CdlInterpreterCommandEntry("doc", &parse_doc), + CdlInterpreterCommandEntry("", 0) + }; + + for (int i = 0; commands[i].command != 0; i++) { + std::vector::const_iterator j; + for (j = parsers.begin(); j != parsers.end(); j++) { + if (commands[i].name == j->name) { + if (commands[i].command != j->command) { + CYG_FAIL("Property names are being re-used"); + } + break; + } + } + if (j == parsers.end()) { + parsers.push_back(commands[i]); + } + } + CdlNodeBody::add_property_parsers(parsers); + + CYG_REPORT_RETURN(); +} + +void +CdlUserVisibleBody::check_properties(CdlInterpreter interp) +{ + CYG_REPORT_FUNCNAME("CdlUserVisible::check_properties"); + CYG_REPORT_FUNCARG2XV(this, interp); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(interp); + + if (count_properties(CdlPropertyId_Display) > 1) { + CdlParse::report_error(interp, "There should be at most one display property."); + } + if (count_properties(CdlPropertyId_Description) > 1) { + CdlParse::report_error(interp, "There should be at most one description property."); + } + if (count_properties(CdlPropertyId_Doc) > 1) { + CdlParse::report_error(interp, "There should be at most one doc property."); + } + + // FIXME: more validation of the doc property, in particular check that + // the resulting URL would be either remote or to an existing file. + + CdlNodeBody::check_properties(interp); + + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- +// Syntax: description + +int +CdlUserVisibleBody::parse_description(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_description", "result %d"); + + int result = CdlParse::parse_string_property(interp, argc, argv, CdlPropertyId_Description, 0, 0); + + CYG_REPORT_RETVAL(result); + return result; +} + + +// ---------------------------------------------------------------------------- +// Syntax: display + +int +CdlUserVisibleBody::parse_display(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_display", "result %d"); + + int result = CdlParse::parse_string_property(interp, argc, argv, CdlPropertyId_Display, 0, 0); + + CYG_REPORT_RETVAL(result); + return result; +} + +// ---------------------------------------------------------------------------- +// Syntax: doc + +int +CdlUserVisibleBody::parse_doc(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_doc", "result %d"); + + int result = CdlParse::parse_string_property(interp, argc, argv, CdlPropertyId_Doc, 0, 0); + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ Persistence + +// ---------------------------------------------------------------------------- +// There is no data in a user visible object that users will want to edit, +// but the display string, the documentation, and the description are all +// useful and should be present in the savefile as comments. +// +// The intention is that the UserVisible information appears immediately +// above the option/component/whatever definition, e.g.: +// # +// # +// # + +void +CdlUserVisibleBody::save(CdlInterpreter interp, Tcl_Channel chan, int indentation, bool minimal) + throw(CdlInputOutputException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlUserVisible::save"); + CYG_REPORT_FUNCARG5XV(this, interp, chan, indentation, minimal); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(interp); + CYG_ASSERTC(0 == indentation); + + if (!minimal) { + std::string data = ""; + std::string display = get_display(); + if ("" != display) { + data = std::string("# ") + display + "\n"; + } + // Note that this uses get_doc(), not get_doc_url(). The latter + // would give an absolute pathname that is applicable to the + // current user, but it would change if a different user loaded + // and saved the file. This is a bad idea in terms of version + // control. + std::string doc = get_doc(); + if ("" != doc) { + data += "# doc: " + doc + "\n"; + } + std::string description = get_description(); + if ("" != description) { + unsigned int i = 0; + while (i < description.size()) { + data += "# "; + while ((i < description.size()) && isspace(description[i])) { + i++; + } + while ((i < description.size()) && ('\n' != description[i])) { + data += description[i++]; + } + data += '\n'; + } + } + data += "#\n"; + + interp->write_data(chan, data); + } + + CYG_REPORT_RETURN(); +} + +//}}} + +//}}} +//{{{ CdlParentableBody + +// ---------------------------------------------------------------------------- +// A parentable object can have the parent property, i.e. it can be +// positioned anywhere in the hierarchy. There is no data associated +// with such an object. + +CdlParentableBody::CdlParentableBody() +{ + CYG_REPORT_FUNCNAME("CdlParentable:: default constructor"); + CYG_REPORT_FUNCARG1XV(this); + + change_parent_save_position = -1; + cdlparentablebody_cookie = CdlParentableBody_Magic; + CYGDBG_MEMLEAK_CONSTRUCTOR(); + + CYG_POSTCONDITION_THISC(); + CYG_REPORT_RETURN(); +} + +CdlParentableBody::~CdlParentableBody() +{ + CYG_REPORT_FUNCNAME("CdlParentable:: destructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + cdlparentablebody_cookie = CdlParentableBody_Invalid; + CYGDBG_MEMLEAK_DESTRUCTOR(); + + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- + +std::string +CdlParentableBody::get_class_name() const +{ + CYG_REPORT_FUNCNAME("CdlParentable::get_class_name"); + CYG_PRECONDITION_THISC(); + CYG_REPORT_RETURN(); + return "parentable"; +} + +// ---------------------------------------------------------------------------- + +bool +CdlParentableBody::check_this(cyg_assert_class_zeal zeal) const +{ + if (CdlParentableBody_Magic != cdlparentablebody_cookie) { + return false; + } + CYGDBG_MEMLEAK_CHECKTHIS(); + return CdlNodeBody::check_this(zeal); +} + +// ---------------------------------------------------------------------------- +// Parsing support. There is just one property parser to be added. + +void +CdlParentableBody::add_property_parsers(std::vector& parsers) +{ + CYG_REPORT_FUNCNAME("CdlParentable::add_property_parsers"); + + static CdlInterpreterCommandEntry commands[] = + { + CdlInterpreterCommandEntry("parent", &CdlParentableBody::parse_parent), + CdlInterpreterCommandEntry("", 0) + }; + + for (int i = 0; commands[i].command != 0; i++) { + std::vector::const_iterator j; + for (j = parsers.begin(); j != parsers.end(); j++) { + if (commands[i].name == j->name) { + if (commands[i].command != j->command) { + CYG_FAIL("Property names are being re-used"); + } + break; + } + } + if (j == parsers.end()) { + parsers.push_back(commands[i]); + } + } + CdlNodeBody::add_property_parsers(parsers); + + CYG_REPORT_RETURN(); +} + +void +CdlParentableBody::check_properties(CdlInterpreter interp) +{ + CYG_REPORT_FUNCNAME("CdlParentable::check_properties"); + CYG_REPORT_FUNCARG2XV(this, interp); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(interp); + + if (has_property(CdlPropertyId_Parent)) { + if (count_properties(CdlPropertyId_Parent) > 1) { + CdlParse::report_error(interp, "There should be at most one `parent' property."); + } + CdlProperty_Reference refprop = dynamic_cast(get_property(CdlPropertyId_Parent)); + CYG_ASSERT_CLASSC(this); + if (get_name() == refprop->get_destination_name()) { + CdlParse::report_error(interp, std::string("Node ") + get_name() + " cannot be its own parent."); + } + } + + CdlNodeBody::check_properties(interp); + + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- +// Syntax:: parent + +void +CdlParentableBody::update_handler(CdlTransaction transaction, CdlNode source, CdlProperty prop, CdlNode dest, CdlUpdate change) +{ + CYG_REPORT_FUNCNAME("CdlParentable::update_handler"); + CYG_PRECONDITION_CLASSC(source); + CYG_PRECONDITION_ZERO_OR_CLASSC(dest); + + // Value and activity updates are of no interest. + if ((CdlUpdate_ValueChange == change) || (CdlUpdate_ActiveChange == change)) { + CYG_REPORT_RETURN(); + return; + } + + // Ditto for the second stage Init. + if (CdlUpdate_Init == change) { + CYG_REPORT_RETURN(); + return; + } + + // If this object is being unloaded then we need to clean up the hierarchy. + // Ordinary nodes must be re-parented below the owning loadable. The + // loadable itself must be re-parented below the toplevel. A subsequent + // calls to remove_loadable_from_toplevel() will ensure that the loadable + // is now completely isolated from the remaining configuration, but can + // still be put back. + if (CdlUpdate_Unloading == change) { + CdlToplevel toplevel = source->get_toplevel(); + CYG_ASSERT_CLASSC(toplevel); + CdlLoadable owner = source->get_owner(); + CYG_ASSERT_CLASSC(owner); + CdlLoadable loadable = dynamic_cast(source); + CYG_ASSERT_ZERO_OR_CLASSC(loadable); + + if (0 != loadable) { + toplevel->change_parent(owner, source->get_parent(), toplevel, source); + } else { + toplevel->change_parent(owner, source->get_parent(), owner, source); + } + + CYG_REPORT_RETURN(); + return; + } + + // We should have: + // 1) change == Loaded, dest == (0 | valid) + // 2) change == Created, dest == valid + // 3) change == Destroyed, dest == valid (still) + CYG_ASSERTC((CdlUpdate_Loaded == change) || (CdlUpdate_Created == change) || (CdlUpdate_Destroyed == change)); + CYG_ASSERTC((CdlUpdate_Created != change) || (0 != dest)); + CYG_ASSERTC((CdlUpdate_Destroyed != change) || (0 != dest)); + + if (CdlUpdate_Destroyed == change) { + dest = 0; + } + + // Now either dest is valid or it is not. If it is then we need to + // reparent below the destination. Otherwise we need to reparent + // below the orphans container. There are also a few nasty special + // cases to consider. + + if (0 == dest) { + // Orphan the node. It still has a parent, either as a + // consequence of the loading process or because of a previous + // binding operation. + CdlToplevel toplevel = source->get_toplevel(); + toplevel->change_parent(source->get_owner(), source->get_parent(), 0, source); + + // The Unresolved conflict is handled by + // CdlProperty_Reference::update(). The "else" code below may + // have created some additional data conflicts. + transaction->clear_structural_conflicts(source, prop, &CdlConflict_DataBody::test); + + // Changing the parent may affect the "active" status. + bool old_state = transaction->is_active(source); + bool new_state = source->test_active(transaction); + if (old_state != new_state) { + transaction->set_active(source, new_state); + } + + } else { + // The node should no longer be an orphan - probably. + + // Check that the destination is actually a container. If it is, + // reparenting is possible. + CdlContainer dest_container = dynamic_cast(dest); + if (0 == dest_container) { + + // The reference might be resolved, but reparenting is still not possible. + // Leave the object orphaned as at present, and create a suitable conflict + // object. + std::string msg = source->get_class_name() + " " + source->get_name() + " cannot be reparented below " + + dest->get_class_name() + " " + dest->get_name() + "\n The latter is not a container."; + CdlConflict_DataBody::make(transaction, source, prop, msg); + + } else { + + CdlContainer tmp = dynamic_cast(source); + if ((0 != tmp) && tmp->contains(dest_container, true)) { + + // Somebody trying to be clever and reparent an object + // below one of its existing children? Note that with + // sufficiently careful use of parent statements this + // might actually be legal, but for now treat it as + // too dangerous. + std::string msg = source->get_class_name() + " " + source->get_name() + " cannot be reparented below " + + dest->get_class_name() + " " + dest->get_name() + "\n This would introduce a cycle."; + CdlConflict_DataBody::make(transaction, source, prop, msg); + + } else { + + // It is possible to reparent the object to its correct location + CdlToplevel toplevel = source->get_toplevel(); + CYG_ASSERTC(toplevel == dest->get_toplevel()); + toplevel->change_parent(source->get_owner(), source->get_parent(), dest_container, source); + + bool old_state = transaction->is_active(source); + bool new_state = source->test_active(transaction); + if (old_state != new_state) { + transaction->set_active(source, new_state); + } + } + } + } + + CYG_REPORT_RETURN(); +} + +int +CdlParentableBody::parse_parent(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_parent", "result %d"); + + int result = CdlParse::parse_reference_property(interp, argc, argv, CdlPropertyId_Parent, 0, 0, &update_handler); + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} diff --git a/host/libcdl/build.cxx b/host/libcdl/build.cxx new file mode 100644 --- /dev/null +++ b/host/libcdl/build.cxx @@ -0,0 +1,2091 @@ +//{{{ Banner + +//========================================================================== +// +// build.cxx +// +// libcdl support for building and for header file generation +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contributors: bartv +// Date: 1999-06-018 +// +//####DESCRIPTIONEND#### +//========================================================================== + +//}}} +//{{{ #include's + +// ---------------------------------------------------------------------------- +#include "cdlconfig.h" + +// Get the infrastructure types, assertions, tracing and similar +// facilities. +#include +#include + +// defines everything implemented in this module. +// It implicitly supplies , and because +// the class definitions rely on these headers. +#include + +// split_custom_build_step() needs access to isspace() etc. +#include + +//}}} + +//{{{ Statics + +// ---------------------------------------------------------------------------- +CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlBuildLoadableBody); +CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlBuildableBody); +CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlDefineLoadableBody); +CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlDefinableBody); + +//}}} +//{{{ CdlBuildableBody + +//{{{ Basics + +// ---------------------------------------------------------------------------- +// There is little data specific to a buildable. The only distinguishing +// feature is the set of properties that are supported, plus a handful +// of functions to extract that information. + +CdlBuildableBody::CdlBuildableBody() +{ + CYG_REPORT_FUNCNAME("CdlBuildable:: default constructor"); + CYG_REPORT_FUNCARG1XV(this); + + // There is no data to initialize yet + cdlbuildablebody_cookie = CdlBuildableBody_Magic; + CYGDBG_MEMLEAK_CONSTRUCTOR(); + + CYG_POSTCONDITION_THISC(); + CYG_REPORT_RETURN(); +} + +CdlBuildableBody::~CdlBuildableBody() +{ + CYG_REPORT_FUNCNAME("CdlBuildable:: destructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + cdlbuildablebody_cookie = CdlBuildableBody_Invalid; + CYGDBG_MEMLEAK_DESTRUCTOR(); + + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- + +std::string +CdlBuildableBody::get_class_name() const +{ + CYG_REPORT_FUNCNAME("CdlBuildable::get_class_name"); + CYG_PRECONDITION_THISC(); + CYG_REPORT_RETURN(); + return "buildable"; +} + +// ---------------------------------------------------------------------------- + +bool +CdlBuildableBody::check_this(cyg_assert_class_zeal zeal) const +{ + if (CdlBuildableBody_Magic != cdlbuildablebody_cookie) { + return false; + } + CYGDBG_MEMLEAK_CHECKTHIS(); + return CdlNodeBody::check_this(zeal); +} + +//}}} +//{{{ Add and check property parsers + +// ---------------------------------------------------------------------------- + +void +CdlBuildableBody::add_property_parsers(std::vector& parsers) +{ + CYG_REPORT_FUNCNAME("CdlBuildable::add_property_parsers"); + + static CdlInterpreterCommandEntry commands[] = + { + CdlInterpreterCommandEntry("compile", &CdlBuildableBody::parse_compile ), + CdlInterpreterCommandEntry("object", &CdlBuildableBody::parse_object ), + CdlInterpreterCommandEntry("make_object", &CdlBuildableBody::parse_make_object), + CdlInterpreterCommandEntry("make", &CdlBuildableBody::parse_make ), + CdlInterpreterCommandEntry("build_proc", &CdlBuildableBody::parse_build_proc ), + CdlInterpreterCommandEntry("", 0 ), + }; + + for (int i = 0; commands[i].command != 0; i++) { + std::vector::const_iterator j; + for (j = parsers.begin(); j != parsers.end(); j++) { + if (commands[i].name == j->name) { + if (commands[i].command != j->command) { + CYG_FAIL("Property names are being re-used"); + } + break; + } + } + if (j == parsers.end()) { + parsers.push_back(commands[i]); + } + } + CdlNodeBody::add_property_parsers(parsers); + + CYG_REPORT_RETURN(); +} + +void +CdlBuildableBody::check_properties(CdlInterpreter interp) +{ + CYG_REPORT_FUNCNAME("CdlBuildable::check_properties"); + CYG_REPORT_FUNCARG2XV(this, interp); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(interp); + + // There are no real constraints on the number of compile + // properties etc. + // TODO: check that the relevant sources files exist, + // unless marked appropriately (build_proc can create + // new source files). + + CdlNodeBody::check_properties(interp); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ Property parsers + +// ---------------------------------------------------------------------------- +// Syntax: compile +// +// There are a couple of checks that could be performed here: +// +// 1) does each listed file actually exist? Unfortunately that approach +// falls foul of build_proc, which is allowed to generate source files +// on the fly. +// +// 2) does the file have a recognised suffix such as .c or .cxx. This +// relies libcdl having some way of knowing how to treat different +// files. +// +// For now there are no validity checks. +// +// A future extension may allow dependencies to be listed, as an +// option. This would allow component vendors to specify that +// particular custom build steps should happen before particular +// compilations, a more robust approach than the current priority +// scheme. + +int +CdlBuildableBody::parse_compile(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_compile", "result %d"); + static char* options[] = { + "library:", + 0 + }; + + int result = CdlParse::parse_stringvector_property(interp, argc, argv, CdlPropertyId_Compile, options, 0); + + CYG_REPORT_RETVAL(result); + return result; +} + +// ---------------------------------------------------------------------------- +// A utility to break a custom build step down into its three components. +// +// A custom build step takes the form: +// target : deps +// rules +// +// This utility function takes a single string of this form and breaks +// it down into its constituent parts. +// +// NOTE: this will need lots of extra code in future to allow for +// escaped characters, spaces in filenames, etc. For now just keep +// things simple. + +bool +CdlBuildableBody::split_custom_build_step(std::string str_data, std::string& target, std::string& deps, std::string& rules, + std::string& error_msg) +{ + CYG_REPORT_FUNCNAMETYPE("CdlBuildable::split_custom_build_step", "result %d"); + + target = ""; + deps = ""; + rules = ""; + error_msg = ""; + + const char* data = str_data.c_str(); + + // Skip any leading white space, and make sure that this leaves some real data. + while (('\0' != *data) && isspace(*data)) { + data++; + } + if ('\0' == *data) { + error_msg = "no data in custom build_step"; + CYG_REPORT_RETVAL(false); + return false; + } + + // Now extract the target. This consists of any sequence of characters + // upto space, tab, colon. + for ( ; ('\0' != *data) && (':' != *data) && (' ' != *data) && ('\t' != *data); data++) { + target += *data; + } + // Discard any spaces or tabs, they are of no interest + while ((' ' == *data) || ('\t' == *data)) { + data++; + } + // The current character should be a colon + if (':' != *data) { + error_msg = "expecting a colon `;' after the target `" + target + "'"; + CYG_REPORT_RETVAL(false); + return false; + } + + // Move past the colon, and skip any further spaces or tabs + data++; + while (('\0' != *data) && ((' ' == *data) || ('\t' == *data))) { + data++; + } + + // Everything from here until the end of line should be part of the deps field, + // including white space. + while (('\0' != *data) && ('\n' != *data) && (';' != *data)) { + deps += *data++; + } + + if ("" == deps) { + error_msg = "expecting dependency list after `" + target + ":'"; + CYG_REPORT_RETVAL(false); + return false; + } + + // Having some rules is compulsory. + if ('\0' == *data) { + error_msg = "expecting one or more rules after the dependency list"; + CYG_REPORT_RETVAL(false); + return false; + } else { + // We are currently at \n or ;, move on to the actual rules + data++; + } + + // Rules consist of one or more lines. Any leading white space on a given + // line should be discarded. + while ('\0' != *data) { + // Processing the current rule. Skip leading spaces and tabs + while ((' ' == *data) || ('\t' == *data)) { + data++; + } + // Now add everything up to the next newline or EOD to the rules. + while (('\0' != *data) && ('\n' != *data)) { + rules += *data++; + } + + // Terminate this line of the rules with a newline, even if that + // character is absent from the raw data. + rules += '\n'; + + // And ignore the newline in the raw data itself + if ('\n' == *data) { + data++; + } + } + + // Better make sure that there are some rules. All of the looping above + // may just have left white space + if ("" == rules) { + error_msg = "no rules provided"; + CYG_REPORT_RETVAL(false); + return false; + } + + // Everything is ok. + + CYG_REPORT_RETVAL(true); + return true; +} + + +// ---------------------------------------------------------------------------- +// syntax: make +// +// There is rather a lot of checking to be done. +// +// 1) the priority should be valid. In particular it should be a number +// within a reasonable range. +// +// 2) the rules should take the form: +// : ;|\n rules +// +// Where the target should be a single file, identical to the +// first property argument. + +static void +parse_make_final_check(CdlInterpreter interp, CdlProperty_String prop) +{ + CYG_REPORT_FUNCNAME("parse_make_final_check"); + CYG_PRECONDITION_CLASSC(interp); + CYG_PRECONDITION_CLASSC(prop); + + std::string prio_string = prop->get_option("priority"); + if ("" != prio_string) { + cdl_int tmp = 1; + if (!Cdl::string_to_integer(prio_string, tmp)) { + CdlParse::report_property_parse_error(interp, prop, + "Invalid priority option, priorities should be simple numbers."); + } else { + if ((tmp < 1) || (tmp > 1024)) { + CdlParse::report_property_parse_error(interp, prop, + "Invalid priority value, priorities should be in the range 1 to 1024."); + } + } + } + + std::string data = prop->get_string(); + std::string target; + std::string deps; + std::string rules; + std::string error_msg; + + if (!CdlBuildableBody::split_custom_build_step(data, target, deps, rules, error_msg)) { + CdlParse::report_property_parse_error(interp, prop, "Invalid custom build step, " + error_msg); + } +} + +int +CdlBuildableBody::parse_make(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_make", "result %d"); + static char* options[] = { + "priority:", + 0 + }; + + int result = CdlParse::parse_string_property(interp, argc, argv, CdlPropertyId_Make, options, &parse_make_final_check); + + CYG_REPORT_RETVAL(result); + return result; +} + + +// ---------------------------------------------------------------------------- +// syntax: make_object +// +// The rules here are much the same as for the "make" property. + +static void +parse_make_object_final_check(CdlInterpreter interp, CdlProperty_String prop) +{ + CYG_REPORT_FUNCNAME("parse_make_object_final_check"); + CYG_PRECONDITION_CLASSC(interp); + CYG_PRECONDITION_CLASSC(prop); + + + std::string prio_string = prop->get_option("priority"); + if ("" != prio_string) { + cdl_int tmp = 1; + if (!Cdl::string_to_integer(prio_string, tmp)) { + CdlParse::report_property_parse_error(interp, prop, + "Invalid priority option, priorities should be simple numbers."); + } else { + if ((tmp < 1) || (tmp > 1024)) { + CdlParse::report_property_parse_error(interp, prop, + "Invalid priority value, priorities should be in the range 1 to 1024."); + } + } + } + + std::string data = prop->get_string(); + std::string target; + std::string deps; + std::string rules; + std::string error_msg; + + if (!CdlBuildableBody::split_custom_build_step(data, target, deps, rules, error_msg)) { + CdlParse::report_property_parse_error(interp, prop, "Invalid custom build step, " + error_msg); + } +} + +int +CdlBuildableBody::parse_make_object(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_make_object", "result %d"); + static char* options[] = { + "library:", + "priority:", + 0 + }; + + int result = CdlParse::parse_string_property(interp, argc, argv, CdlPropertyId_MakeObject, options, + &parse_make_object_final_check); + + CYG_REPORT_RETVAL(result); + return result; +} + + +// ---------------------------------------------------------------------------- +// Syntax: object ... + +int +CdlBuildableBody::parse_object(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_object", "result %d"); + static char* options[] = { + "library:", + 0 + }; + + int result = CdlParse::parse_stringvector_property(interp, argc, argv, CdlPropertyId_Object, options, 0); + + CYG_REPORT_RETVAL(result); + return result; +} + +// ---------------------------------------------------------------------------- +// Syntax: build_proc { tcl code } + +int +CdlBuildableBody::parse_build_proc(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_build_proc", "result %d"); + + int result = CdlParse::parse_tclcode_property(interp, argc, argv, CdlPropertyId_BuildProc, 0, 0); + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ update_build_info() + +// ---------------------------------------------------------------------------- +// Most of the work is done in update_all_build_info(). The update_build_info() +// merely checks the active and enabled state first. +void +CdlBuildableBody::update_build_info(CdlBuildInfo_Loadable& build_info, std::string library) const +{ + CYG_REPORT_FUNCNAME("CdlBuildable::update_build_info"); + CYG_REPORT_FUNCARG2XV(this, &build_info); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITIONC("" != library); + + if (!is_active()) { + CYG_REPORT_RETURN(); + return; + } + + CdlConstValuable valuable = dynamic_cast(this); + if (0 != valuable) { + if (!valuable->is_enabled()) { + CYG_REPORT_RETURN(); + return; + } + } + + update_all_build_info(build_info, library); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ update_all_build_info() + +// ---------------------------------------------------------------------------- +// There are four properties to be considered, each of which may occur +// multiple times: "compile", "object", "make_object", and "make". +// Each of these will result in separate additions to the build_info +// structure. + +void +CdlBuildableBody::update_all_build_info(CdlBuildInfo_Loadable& build_info, std::string package_library) const +{ + CYG_REPORT_FUNCNAME("CdlBuildable::update_all_build_info"); + CYG_REPORT_FUNCARG2XV(this, &build_info); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITIONC("" != package_library); + + // Get some information about the owning loadable first. + CdlLoadable loadable = get_owner(); + CYG_ASSERT_CLASSC(loadable); + std::string directory = loadable->get_directory(); + CYG_ASSERTC("" != directory); + CdlInterpreter interp = loadable->get_interpreter(); + CYG_ASSERT_CLASSC(interp); + + // The interpreter needs some information about the locations + // of various things. This code has to be kept in step with + // CdlLoadable::find_relative_file() + interp->set_variable("::cdl_topdir", get_toplevel()->get_directory()); + interp->set_variable("::cdl_pkgdir", directory); + + // For many packages the sources will reside in a src subdirectory. + // For simple packages the sources may live directly at the toplevel + bool has_src_subdir = loadable->has_subdirectory("src"); + + // NOTE: the object property is not yet supported + std::vector compile_properties; + get_properties(CdlPropertyId_Compile, compile_properties); + std::vector makeobject_properties; + get_properties(CdlPropertyId_MakeObject, makeobject_properties); + std::vector make_properties; + get_properties(CdlPropertyId_Make, make_properties); + std::vector::const_iterator prop_i; + + for (prop_i = compile_properties.begin(); prop_i != compile_properties.end(); prop_i++) { + CdlProperty_StringVector compile_prop = dynamic_cast(*prop_i); + CYG_LOOP_INVARIANT_CLASSC(compile_prop); + + // Does this property have a library option? + std::string current_library = compile_prop->get_option("library"); + if ("" == current_library) { + current_library = package_library; + } + + const std::vector& files = compile_prop->get_strings(); + std::vector::const_iterator file_i; + + for (file_i = files.begin(); file_i != files.end(); file_i++) { + + // For each listed file, try to find it. If this is unsuccessful + // then assume that the file will be generated later on. + std::string path = loadable->find_relative_file(*file_i, "src"); + if ("" == path) { + if (has_src_subdir) { + path = "src/" + *file_i; + } else { + path = *file_i; + } + } + + // Now check whether or not the specified file is already present. + std::vector::const_iterator info_i; + for (info_i = build_info.compiles.begin(); info_i != build_info.compiles.end(); info_i++) { + if ((current_library == info_i->library) && (path == info_i->source)) { + break; + } + } + if (info_i == build_info.compiles.end()) { + CdlBuildInfo_Compile new_info; + new_info.library = current_library; + new_info.source = path; + build_info.compiles.push_back(new_info); + } + } + } + + for (prop_i = makeobject_properties.begin(); prop_i != makeobject_properties.end(); prop_i++) { + CdlProperty_String prop = dynamic_cast(*prop_i); + CYG_LOOP_INVARIANT_CLASSC(prop); + + // Does thie property have a library option? + std::string current_library = prop->get_option("library"); + if ("" == current_library) { + current_library = package_library; + } + + // How about a priority field? The default priority for make_object is 100 + // We can rely on the validation done during the parsing process + cdl_int priority = 100; + std::string priority_option = prop->get_option("priority"); + if ("" != priority_option) { + Cdl::string_to_integer(priority_option, priority); + } + + // What we need now is the separate target, deps, and rules. These + // can be obtained via a utility. The raw data will have been validated + // already. + std::string raw_data = prop->get_string(); + std::string target; + std::string deps; + std::string rules; + std::string error_msg; + bool result; + + result = CdlBuildableBody::split_custom_build_step(raw_data, target, deps, rules, error_msg); + CYG_ASSERTC(true == result); + + // Construct a local object, then copy it into the vector + CdlBuildInfo_MakeObject local_copy; + local_copy.priority = priority; + local_copy.library = current_library; + local_copy.object = target; + local_copy.deps = deps; + local_copy.rules = rules; + + build_info.make_objects.push_back(local_copy); + } + + for (prop_i = make_properties.begin(); prop_i != make_properties.end(); prop_i++) { + CdlProperty_String prop = dynamic_cast(*prop_i); + CYG_LOOP_INVARIANT_CLASSC(prop); + + // Is there a priority field? The default priority for make is + // 300 We can rely on the validation done during the parsing + // process + cdl_int priority = 300; + std::string priority_option = prop->get_option("priority"); + if ("" != priority_option) { + Cdl::string_to_integer(priority_option, priority); + } + + // What we need now is the separate target, deps, and rules. These + // can be obtained via a utility. The raw data will have been validated + // already. + std::string raw_data = prop->get_string(); + std::string target; + std::string deps; + std::string rules; + std::string error_msg; + bool result; + + result = CdlBuildableBody::split_custom_build_step(raw_data, target, deps, rules, error_msg); + CYG_ASSERTC(true == result); + + // Construct a local object, then copy it into the vector + CdlBuildInfo_Make local_copy; + local_copy.priority = priority; + local_copy.target = target; + local_copy.deps = deps; + local_copy.rules = rules; + + build_info.makes.push_back(local_copy); + } + + CYG_REPORT_RETURN(); +} + +//}}} + +//}}} +//{{{ CdlBuildLoadableBody + +//{{{ Class variables + +// ---------------------------------------------------------------------------- +// This variable controls the default library that should be generated. +// Some applications may wish to override this. +char* CdlBuildLoadableBody::default_library_name = "libtarget.a"; + +// The pattern that should be used to identify header files. +// FIXME: this information should come out of a data file +char* CdlBuildLoadableBody::default_headers_glob_pattern = "*.h *.hxx *.inl *.si *.inc"; + +//}}} +//{{{ The simple stuff + +// ---------------------------------------------------------------------------- + +CdlBuildLoadableBody::CdlBuildLoadableBody() + : CdlLoadableBody() +{ + CYG_REPORT_FUNCNAME("CdlBuildLoadable:: default constructor"); + CYG_REPORT_FUNCARG1XV(this); + + // There is no data to initialize + cdlbuildloadablebody_cookie = CdlBuildLoadableBody_Magic; + CYGDBG_MEMLEAK_CONSTRUCTOR(); + + CYG_POSTCONDITION_THISC(); + CYG_REPORT_RETURN(); +} + +CdlBuildLoadableBody::~CdlBuildLoadableBody() +{ + CYG_REPORT_FUNCNAME("CdlBuildLoadable:: destructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + cdlbuildloadablebody_cookie = CdlBuildLoadableBody_Invalid; + CYGDBG_MEMLEAK_DESTRUCTOR(); + + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- + +std::string +CdlBuildLoadableBody::get_class_name() const +{ + CYG_REPORT_FUNCNAME("CdlBuildLoadable::get_class_name"); + CYG_PRECONDITION_THISC(); + CYG_REPORT_RETURN(); + return "build_loadable"; +} + +// ---------------------------------------------------------------------------- + +bool +CdlBuildLoadableBody::check_this(cyg_assert_class_zeal zeal) const +{ + if (CdlBuildLoadableBody_Magic != cdlbuildloadablebody_cookie) { + return false; + } + CYGDBG_MEMLEAK_CHECKTHIS(); + return CdlContainerBody::check_this(zeal) && CdlNodeBody::check_this(zeal); +} + +//}}} +//{{{ Property parsers + +// ---------------------------------------------------------------------------- + +void +CdlBuildLoadableBody::add_property_parsers(std::vector& parsers) +{ + CYG_REPORT_FUNCNAME("CdlBuildLoadable::add_property_parsers"); + + static CdlInterpreterCommandEntry commands[] = + { + CdlInterpreterCommandEntry("library", &CdlBuildLoadableBody::parse_library ), + CdlInterpreterCommandEntry("makefile", &CdlBuildLoadableBody::parse_makefile ), + CdlInterpreterCommandEntry("include_dir", &CdlBuildLoadableBody::parse_include_dir ), + CdlInterpreterCommandEntry("include_files", &CdlBuildLoadableBody::parse_include_files ), + CdlInterpreterCommandEntry("", 0 ) + }; + + for (int i = 0; commands[i].command != 0; i++) { + std::vector::const_iterator j; + for (j = parsers.begin(); j != parsers.end(); j++) { + if (commands[i].name == j->name) { + if (commands[i].command != j->command) { + CYG_FAIL("Property names are being re-used"); + } + break; + } + } + if (j == parsers.end()) { + parsers.push_back(commands[i]); + } + } + + CYG_REPORT_RETURN(); +} + +void +CdlBuildLoadableBody::check_properties(CdlInterpreter interp) +{ + CYG_REPORT_FUNCNAME("CdlBuildLoadable::check_properties"); + CYG_REPORT_FUNCARG2XV(this, interp); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(interp); + + CdlNodeBody::check_properties(interp); + + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- +// syntax: library +// +// NOTE: there should probably be a check that the library name is in +// a valid format, i.e. libxxx.a + +int +CdlBuildLoadableBody::parse_library(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_library", "result %d"); + + int result = CdlParse::parse_string_property(interp, argc, argv, CdlPropertyId_Library, 0, 0); + + CYG_REPORT_RETVAL(result); + return result; +} + +// ---------------------------------------------------------------------------- +// syntax: makefile +// +// NOTE: possibly there should be a check that the makefile exists. +// Do we want to allow build_proc's to generate makefiles? +int +CdlBuildLoadableBody::parse_makefile(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_makefile", "result %d"); + + int result = CdlParse::parse_string_property(interp, argc, argv, CdlPropertyId_Makefile, 0, 0); + + CYG_REPORT_RETVAL(result); + return result; +} + +// ---------------------------------------------------------------------------- +// syntax: include_dir +int +CdlBuildLoadableBody::parse_include_dir(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_include_dir", "result %d"); + + int result = CdlParse::parse_string_property(interp, argc, argv, CdlPropertyId_IncludeDir, 0, 0); + + CYG_REPORT_RETVAL(result); + return result; +} + +// ---------------------------------------------------------------------------- +// Syntax: include_files +// +// This lists the header files that should be copied into the install tree +// as part of the build operation. In the absence of an include_files property +// there should be an include subdirectory, and all files in that subdirectory +// are assumed to be exportable headers. +// +// NOTE: add a finalizer to check that the files exist or get created. + +int +CdlBuildLoadableBody::parse_include_files(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_include_files", "result %d"); + + int result = CdlParse::parse_stringvector_property(interp, argc, argv, CdlPropertyId_IncludeFiles, 0, 0); + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ update_build_info() + +// ---------------------------------------------------------------------------- +// This utility routine takes care of filling in a Buildinfo_Loadable +// structure with the appropriate header file information. This involves +// the following: +// +// 1) there may be an include_dir property. This affects the destination +// of any header files that are listed. +// +// 2) the loadable may or may not have an include subdirectory. For +// non-trivial packages the include subdirectory provides a clean +// way of separating interface and implementation. For simple +// packages it is too heavyweight. +// +// 3) there may be one or more include_files property. If so then these +// specify all the files that should be exported. +// +// 4) otherwise if there is an include subdirectory then we need to +// know all the header files in that subdirectory. A Tcl script is +// used for this. +// +// 5) otherwise all the header files below the package directory itself +// are of interest. + +static void +update_header_file_info(CdlConstBuildLoadable loadable, CdlBuildInfo_Loadable& build_info) +{ + CYG_REPORT_FUNCNAME("update_header_file_info"); + CYG_REPORT_FUNCARG2XV(loadable, &build_info); + CYG_PRECONDITION_CLASSC(loadable); + + std::string dest_dir = ""; + CdlProperty include_dir_prop = loadable->get_property(CdlPropertyId_IncludeDir); + if (0 != include_dir_prop) { + CdlProperty_String strprop = dynamic_cast(include_dir_prop); + CYG_ASSERT_CLASSC(strprop); + dest_dir = strprop->get_string(); + } + + bool has_include_subdir = loadable->has_subdirectory("include"); + + std::vector include_file_properties; + loadable->get_properties(CdlPropertyId_IncludeFiles, include_file_properties); + if (include_file_properties.size() > 0) { + std::vector::const_iterator prop_i; + for (prop_i = include_file_properties.begin(); prop_i != include_file_properties.end(); prop_i++) { + + CdlProperty_StringVector strvprop = dynamic_cast(*prop_i); + CYG_ASSERT_CLASSC(strvprop); + + const std::vector& filenames = strvprop->get_strings(); + std::vector::const_iterator file_i; + for (file_i = filenames.begin(); file_i != filenames.end(); file_i++) { + std::string path = loadable->find_relative_file(*file_i, "include"); + // Assume that the header file will be generated by a build_proc + if ("" == path) { + if (has_include_subdir) { + path = "include/" + *file_i; + } else { + path = *file_i; + } + } + CdlBuildInfo_Header local_copy; + local_copy.source = path; + local_copy.destination = ""; + if ("" != dest_dir) { + local_copy.destination = dest_dir + "/"; + } + // At this stage "path" may begin with "include/", which should not + // be present in the destination. + const char* tmp = path.c_str(); + if (0 == strncmp("include/", tmp, 8)) { + local_copy.destination += &(tmp[8]); + } else { + local_copy.destination += path; + } + build_info.headers.push_back(local_copy); + } + } + CYG_REPORT_RETURN(); + return; + } + + // It is necessary to search for the appropriate files. + CdlInterpreter interp = loadable->get_interpreter(); + std::string path = loadable->get_toplevel()->get_directory() + "/" + loadable->get_directory(); + if (has_include_subdir) { + std::vector files; + std::vector::const_iterator file_i; + interp->locate_all_files(path + "/include", files); + for (file_i = files.begin(); file_i != files.end(); file_i++) { + // NOTE: for now discard any header files in the pkgconf subdirectory + if (0 == strncmp("pkgconf/", file_i->c_str(), 8)) { + continue; + } + CdlBuildInfo_Header local_copy; + local_copy.source = "include/" + *file_i; + local_copy.destination = ""; + if ("" != dest_dir) { + local_copy.destination = dest_dir + "/"; + } + local_copy.destination += *file_i; + build_info.headers.push_back(local_copy); + } + } else { + // Look for all header files, which for now means files with + // a .h, .hxx, .inl or .inc extension. + // FIXME: the definition of what constitutes a header file + // should not be hard-wired here. + std::vector files; + std::vector::const_iterator file_i; + interp->locate_all_files(path, files); + for (file_i = files.begin(); file_i != files.end(); file_i++) { + + // Problems with libstdc++ versions, use C comparisons instead. + const char* c_string = file_i->c_str(); + unsigned int len = strlen(c_string); + if (((len >= 2) && (0 == strncmp(c_string + len - 2, ".h", 2))) || + ((len >= 4) && (0 == strncmp(c_string + len - 4, ".hxx", 4))) || + ((len >= 4) && (0 == strncmp(c_string + len - 4, ".inl", 4))) || + ((len >= 4) && (0 == strncmp(c_string + len - 4, ".inc", 4)))) { + + CdlBuildInfo_Header local_copy; + local_copy.source = *file_i; + local_copy.destination = ""; + if ("" != dest_dir) { + local_copy.destination = dest_dir + "/"; + } + local_copy.destination += *file_i; + build_info.headers.push_back(local_copy); + } + } + } + + CYG_REPORT_RETURN(); + return; +} + +// ---------------------------------------------------------------------------- +// Updating a loadable build's info involves two steps. First, there +// is some information associated with the loadable as a whole such as +// header files. Second, each buildable in the loadable (including itself) +// may contain properties such as compile etc. This is all handled via +// a CdlBuildable member function. + +void +CdlBuildLoadableBody::update_build_info(CdlBuildInfo& build_info) const +{ + CYG_REPORT_FUNCNAME("CdlBuildLoadable::update_build_info"); + CYG_REPORT_FUNCARG2XV(this, &build_info); + CYG_PRECONDITION_THISC(); + + // It is not possible to disable a loadable itself: either the + // loadable is present or it is not (although in some cases users + // may be able to change versions). However, because of reparenting + // it is possible for a loadable to be below a disabled container, + // and hence it is still necessary to check whether or not the + // loadable is active. + if (!is_active()) { + CYG_REPORT_RETURN(); + return; + } + + // Time to add a new CdlBuildInfo_Loadable object to the current + // vector. The name and directory can be filled in straightaway, + // the vectors will all be initialized to empty. + CdlBuildInfo_Loadable tmp_info; + build_info.entries.push_back(tmp_info); + CdlBuildInfo_Loadable& this_info = *(build_info.entries.rbegin()); + this_info.name = get_name(); + this_info.directory = get_directory(); + + // Take care of the header files + update_header_file_info(this, this_info); + + // Work out the library name appropriate for this loadable. + // There may be a library property, otherwise the global default + // should be used. + std::string loadable_library = default_library_name; + if (has_property(CdlPropertyId_Library)) { + CdlProperty_String strprop = dynamic_cast(get_property(CdlPropertyId_Library)); + loadable_library = strprop->get_string(); + } + + const std::vector& contents = get_owned(); + std::vector::const_iterator node_i; + for (node_i = contents.begin(); node_i != contents.end(); node_i++) { + CdlBuildable buildable = dynamic_cast(*node_i); + if (0 != buildable) { + buildable->update_build_info(this_info, loadable_library); + } + } + + CYG_REPORT_RETURN(); +} + +// This is much the same as the above, but there is no test for +// active either at the loadable level or for the individual buildables. +void +CdlBuildLoadableBody::update_all_build_info(CdlBuildInfo& build_info) const +{ + CYG_REPORT_FUNCNAME("CdlBuildLoadable::update_all_build_info"); + CYG_REPORT_FUNCARG2XV(this, &build_info); + CYG_PRECONDITION_THISC(); + + CdlBuildInfo_Loadable tmp_info; + build_info.entries.push_back(tmp_info); + CdlBuildInfo_Loadable& this_info = *(build_info.entries.rbegin()); + this_info.name = get_name(); + this_info.directory = get_directory(); + + std::string loadable_library = default_library_name; + if (has_property(CdlPropertyId_Library)) { + CdlProperty_String strprop = dynamic_cast(get_property(CdlPropertyId_Library)); + loadable_library = strprop->get_string(); + } + + const std::vector& contents = get_owned(); + std::vector::const_iterator node_i; + for (node_i = contents.begin(); node_i != contents.end(); node_i++) { + CdlBuildable buildable = dynamic_cast(*node_i); + if (0 != buildable) { + buildable->update_build_info(this_info, loadable_library); + } + } + + CYG_REPORT_RETURN(); + CYG_REPORT_RETURN(); +} + +//}}} + +//}}} +//{{{ CdlDefinableBody + +//{{{ Basics + +// ---------------------------------------------------------------------------- + +CdlDefinableBody::CdlDefinableBody() +{ + CYG_REPORT_FUNCNAME("CdlDefinable:: default constructor"); + CYG_REPORT_FUNCARG1XV(this); + + // There is no data to initialize + cdldefinablebody_cookie = CdlDefinableBody_Magic; + CYGDBG_MEMLEAK_CONSTRUCTOR(); + + CYG_POSTCONDITION_THISC(); + CYG_REPORT_RETURN(); +} + +CdlDefinableBody::~CdlDefinableBody() +{ + CYG_REPORT_FUNCNAME("CdlDefinable:: destructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + cdldefinablebody_cookie = CdlDefinableBody_Invalid; + CYGDBG_MEMLEAK_DESTRUCTOR(); + + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- + +std::string +CdlDefinableBody::get_class_name() const +{ + CYG_REPORT_FUNCNAME("CdlDefinable::get_class_name"); + CYG_PRECONDITION_THISC(); + CYG_REPORT_RETURN(); + return "definable"; +} + +// ---------------------------------------------------------------------------- + +bool +CdlDefinableBody::check_this(cyg_assert_class_zeal zeal) const +{ + if (CdlDefinableBody_Magic != cdldefinablebody_cookie) { + return false; + } + CYGDBG_MEMLEAK_CHECKTHIS(); + return CdlNodeBody::check_this(zeal); +} + +//}}} +//{{{ add_property_parser() and check_properties() + +// ---------------------------------------------------------------------------- + +void +CdlDefinableBody::add_property_parsers(std::vector& parsers) +{ + CYG_REPORT_FUNCNAME("CdlDefinable::add_property_parsers"); + + static CdlInterpreterCommandEntry commands[] = + { + CdlInterpreterCommandEntry("no_define", &parse_no_define ), + CdlInterpreterCommandEntry("define", &parse_define ), + CdlInterpreterCommandEntry("define_format", &parse_define_format ), + CdlInterpreterCommandEntry("define_proc", &parse_define_proc ), + CdlInterpreterCommandEntry("if_define", &parse_if_define ), + CdlInterpreterCommandEntry("", 0 ) + }; + + for (int i = 0; commands[i].command != 0; i++) { + std::vector::const_iterator j; + for (j = parsers.begin(); j != parsers.end(); j++) { + if (commands[i].name == j->name) { + if (commands[i].command != j->command) { + CYG_FAIL("Property names are being re-used"); + } + break; + } + } + if (j == parsers.end()) { + parsers.push_back(commands[i]); + } + } + CdlNodeBody::add_property_parsers(parsers); + + CYG_REPORT_RETURN(); +} + +void +CdlDefinableBody::check_properties(CdlInterpreter interp) +{ + CYG_REPORT_FUNCNAME("CdlDefinable::check_properties"); + CYG_REPORT_FUNCARG2XV(this, interp); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(interp); + + // There should be at most one each of no_define and define_format. + if (count_properties(CdlPropertyId_NoDefine) > 1) { + CdlParse::report_error(interp, "There should be at most one no_define property."); + } + if (count_properties(CdlPropertyId_DefineFormat) > 1) { + CdlParse::report_error(interp, "There should be at most one define_format property."); + } + if (has_property(CdlPropertyId_NoDefine) && has_property(CdlPropertyId_DefineFormat)) { + CdlParse::report_error(interp, "The no_define and define_format properties are mutually exclusive."); + } + // FIXME: the define_format property only makes sense for certain + // flavors. However the flavor property may not have been processed yet. + + CdlNodeBody::check_properties(interp); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ Definable properties + +// ---------------------------------------------------------------------------- +// Syntax: no_define +int +CdlDefinableBody::parse_no_define(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_no_define", "result %d"); + + int result = CdlParse::parse_minimal_property(interp, argc, argv, CdlPropertyId_NoDefine, 0, 0); + + CYG_REPORT_RETVAL(result); + return result; +} + +// ---------------------------------------------------------------------------- +// syntax: define + +// The argument to "define" should be a valid C preprocessor symbol. +static void +parse_define_final_check(CdlInterpreter interp, CdlProperty_String prop) +{ + CYG_REPORT_FUNCNAME("parse_define_final_check"); + CYG_PRECONDITION_CLASSC(prop); + CYG_PRECONDITION_CLASSC(interp); + + const std::string& str = prop->get_string(); + + if (!Cdl::is_valid_c_preprocessor_symbol(str)) { + CdlParse::report_property_parse_error(interp, prop, str + " is not a valid C preprocessor symbol"); + } + + // There may be a file option. At this stage the only valid filename + // that can be used here is system.h + std::string file_option = prop->get_option("file"); + if (("" != file_option) && ("system.h" != file_option)) { + CdlParse::report_property_parse_error(interp, prop, "Invalid -file option " + file_option); + } + + // FIXME: validate the format string + + CYG_REPORT_RETURN(); +} + +int +CdlDefinableBody::parse_define(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_define", "result %d"); + + static char* options[] = { + "file:", + "format:", + 0 + }; + int result = CdlParse::parse_string_property(interp, argc, argv, CdlPropertyId_Define, options, &parse_define_final_check); + + CYG_REPORT_RETVAL(result); + return result; +} + + +// ---------------------------------------------------------------------------- +// syntax: define_format +// +// FIXME: it is possible to apply some checks to the string, e.g. that there +// is only one conversion operation. +// +// FIXME: also check that the flavor is sensible, define_format has no effect +// for none or bool +// +// FIXME: enforce mutual exclusion with no_define + +int +CdlDefinableBody::parse_define_format(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_format", "result %d"); + + int result = CdlParse::parse_string_property(interp, argc, argv, CdlPropertyId_DefineFormat, 0, 0); + + CYG_REPORT_RETVAL(result); + return result; +} +// ---------------------------------------------------------------------------- +// syntax: define_proc +int +CdlDefinableBody::parse_define_proc(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_define_proc", "result %d"); + + int result = CdlParse::parse_tclcode_property(interp, argc, argv, CdlPropertyId_DefineProc, 0, 0); + + CYG_REPORT_RETVAL(result); + return result; +} + +// ---------------------------------------------------------------------------- +// Syntax: if_define sym1 sym2 + +static void +parse_if_define_final_check(CdlInterpreter interp, CdlProperty_StringVector prop) +{ + CYG_REPORT_FUNCNAME("parse_if_define_final_check"); + CYG_PRECONDITION_CLASSC(interp); + CYG_PRECONDITION_CLASSC(prop); + + // There should be exactly two entries in the vector, and both of them should be + // valid preprocessor symbols. + const std::vector& strings = prop->get_strings(); + + if (2 != strings.size()) { + CdlParse::report_property_parse_error(interp, prop, "There should be exactly two arguments."); + } + if (!Cdl::is_valid_c_preprocessor_symbol(strings[0])) { + CdlParse::report_property_parse_error(interp, prop, strings[0] + " is not a valid C preprocessor symbol."); + } + if (!Cdl::is_valid_c_preprocessor_symbol(strings[1])) { + CdlParse::report_property_parse_error(interp, prop, strings[1] + " is not a valid C preprocessor symbol."); + } + + // There may be a file option. At this stage the only valid filename + // that can be used here is system.h + std::string file_option = prop->get_option("file"); + if (("" != file_option) && ("system.h" != file_option)) { + CdlParse::report_property_parse_error(interp, prop, "Invalid -file option " + file_option); + } +} + +int +CdlDefinableBody::parse_if_define(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_if_define", "result %d"); + + char* options[] = { + "file:", + 0 + }; + int result = CdlParse::parse_stringvector_property(interp, argc, argv, CdlPropertyId_IfDefine, options, + &parse_if_define_final_check); + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ generate_config_header() + +// ---------------------------------------------------------------------------- +// This code needs to allow for the following properties. +// +// 1) no_define. This suppresses the default #define generation. +// +// 2) define_format ][-format ] symbol +// +// 4) define_proc +// +// 5) if_define + +void +CdlDefinableBody::generate_config_header(Tcl_Channel this_hdr, Tcl_Channel system_h) const + throw(CdlInputOutputException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlDefinable::generate_config_header"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlLoadable loadable = get_owner(); + CdlInterpreter interp = loadable->get_interpreter(); + + // This definable is known to be active. However it may or may not be enabled. + CYG_PRECONDITIONC(is_active()); + + std::string name = get_name(); + CdlValueFlavor flavor = CdlValueFlavor_Bool; + std::string value = "1"; + CdlConstValuable valuable = dynamic_cast(this); + if (0 != valuable) { + // It is always possible to check the enabled() flag. + if (!valuable->is_enabled()) { + CYG_REPORT_RETURN(); + return; + } + // The value is only valid for BoolData and Data flavors, and may + // not have been provided. If there is no value then this option + // should not generate a #define + flavor = valuable->get_flavor(); + if ((CdlValueFlavor_BoolData == flavor) || (CdlValueFlavor_Data == flavor)) { + value = valuable->get_value(); + } + } + + // Flavor and value are now both set to sensible strings. + // First, check the no_define property. If this is present then the default + // #define generation should be suppressed. + if (!has_property(CdlPropertyId_NoDefine)) { + + // OK, it is necessary to generate at least one #define. + // If this node is actually a loadable then the #define should go + // into system.h, otherwise into the current header + Tcl_Channel chan = this_hdr; + if (dynamic_cast((CdlConstNode)this) == loadable) { + chan = system_h; + } + + // For flavors None and Bool, there should be just one #define + if ((CdlValueFlavor_None == flavor) || (CdlValueFlavor_Bool == flavor)) { + std::string define = "#define " + name + " 1\n"; + Tcl_Write(chan, const_cast(define.c_str()), -1); + } else { + // If there is a format string then that controls the default + // value display. + if (!has_property(CdlPropertyId_DefineFormat)) { + std::string define = "#define " + name + " " + value + "\n"; + Tcl_Write(chan, const_cast(define.c_str()), -1); + } else { + CdlProperty_String strprop = dynamic_cast(get_property(CdlPropertyId_DefineFormat)); + CYG_ASSERT_CLASSC(strprop); + std::string format = strprop->get_string(); + std::string cmd = "return \"#define " + name + " [format " + format + " " + value + "]\n\""; + std::string define; + if (TCL_OK != interp->eval(cmd, define)) { + throw CdlInputOutputException("Internal error executing tcl fragment to process define_format property"); + } + Tcl_Write(chan, const_cast(define.c_str()), -1); + } + + // There may also be a separate #define of the form _, + // if that is a valid preprocessor symbol. + std::string tmp = name + "_" + value; + if (Cdl::is_valid_c_preprocessor_symbol(tmp)) { + tmp = "#define "+ tmp + "\n"; + Tcl_Write(chan, const_cast(tmp.c_str()), -1); + } + } + } + + // Next, check for any additional define properties + std::vector define_props; + get_properties(CdlPropertyId_Define, define_props); + std::vector::const_iterator prop_i; + for (prop_i = define_props.begin(); prop_i != define_props.end(); prop_i++) { + CdlProperty_String strprop = dynamic_cast(*prop_i); + CYG_ASSERT_CLASSC(strprop); + std::string symbol = strprop->get_string(); + + std::string file = strprop->get_option("file"); + Tcl_Channel chan = this_hdr; + if (("" != file) && ("system.h" == file)) { + chan = system_h; + } + + if ((CdlValueFlavor_None == flavor) || (CdlValueFlavor_Bool == flavor)) { + std::string define = "#define " + symbol + " 1\n"; + Tcl_Write(chan, const_cast(define.c_str()), -1); + } else { + std::string format = strprop->get_option("format"); + if ("" == format) { + std::string define = "#define " + symbol + " " + value + "\n"; + Tcl_Write(chan, const_cast(define.c_str()), -1); + } else { + std::string cmd = "return \"#define " + symbol + " [format " + format + " " + value + "]\n\""; + std::string define; + if (TCL_OK != interp->eval(cmd, define)) { + throw CdlInputOutputException("Internal error executing tcl fragment to process format option"); + } + Tcl_Write(chan, const_cast(define.c_str()), -1); + } + + std::string tmp = symbol + "_" + value; + if (Cdl::is_valid_c_preprocessor_symbol(tmp)) { + tmp = "#define " + tmp + "\n"; + Tcl_Write(chan, const_cast(tmp.c_str()), -1); + } + } + } + + // Now check for if_define properties + std::vector if_define_props; + get_properties(CdlPropertyId_IfDefine, if_define_props); + for (prop_i = if_define_props.begin(); prop_i != if_define_props.end(); prop_i++) { + CdlProperty_StringVector strprop = dynamic_cast(*prop_i); + CYG_ASSERT_CLASSC(strprop); + CYG_ASSERTC(2 == strprop->get_number_of_strings()); + + std::string sym1 = strprop->get_string(0); + std::string sym2 = strprop->get_string(1); + + Tcl_Channel chan = this_hdr; + std::string file = strprop->get_option("file"); + if (("" != file) && ("system.h" == file)) { + chan = system_h; + } + std::string data = "#ifdef " + sym1 + "\n# define " + sym2 + " 1\n#endif\n"; + Tcl_Write(chan, const_cast(data.c_str()), -1); + } + + // And define_proc properties + std::vector define_proc_props; + get_properties(CdlPropertyId_DefineProc, define_proc_props); + for (prop_i = define_proc_props.begin(); prop_i != define_proc_props.end(); prop_i++) { + CdlProperty_TclCode codeprop = dynamic_cast(*prop_i); + CYG_ASSERT_CLASSC(codeprop); + + cdl_tcl_code code = codeprop->get_code(); + std::string result; + if (TCL_OK != interp->eval(code, result)) { + throw CdlInputOutputException("Error evaluating define_proc property for " + name + "\n" + result); + } + } + + + CYG_REPORT_RETURN(); +} + +//}}} + +//}}} +//{{{ CdlDefineLoadableBody + +//{{{ Basics + +// ---------------------------------------------------------------------------- + +CdlDefineLoadableBody::CdlDefineLoadableBody() +{ + CYG_REPORT_FUNCNAME("CdlDefineLoadable:: default constructor"); + CYG_REPORT_FUNCARG1XV(this); + + cdldefineloadablebody_cookie = CdlDefineLoadableBody_Magic; + CYGDBG_MEMLEAK_CONSTRUCTOR(); + + CYG_POSTCONDITION_THISC(); + CYG_REPORT_RETURN(); +} + +CdlDefineLoadableBody::~CdlDefineLoadableBody() +{ + CYG_REPORT_FUNCNAME("CdlDefineLoadable:: destructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + cdldefineloadablebody_cookie = CdlDefineLoadableBody_Invalid; + CYGDBG_MEMLEAK_DESTRUCTOR(); + + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- + +std::string +CdlDefineLoadableBody::get_class_name() const +{ + CYG_REPORT_FUNCNAME("CdlDefineLoadable::get_class_name"); + CYG_PRECONDITION_THISC(); + CYG_REPORT_RETURN(); + return "define_loadable"; +} + +// ---------------------------------------------------------------------------- + +bool +CdlDefineLoadableBody::check_this(cyg_assert_class_zeal zeal) const +{ + if (CdlDefineLoadableBody_Magic != cdldefineloadablebody_cookie) { + return false; + } + CYGDBG_MEMLEAK_CHECKTHIS(); + return CdlLoadableBody::check_this(zeal) && CdlNodeBody::check_this(zeal); +} + +//}}} +//{{{ Property parsing + +// ---------------------------------------------------------------------------- + +void +CdlDefineLoadableBody::add_property_parsers(std::vector& parsers) +{ + CYG_REPORT_FUNCNAME("CdlDefineLoadable::add_property_parsers"); + + static CdlInterpreterCommandEntry commands[] = + { + CdlInterpreterCommandEntry("define_header", &parse_define_header), + CdlInterpreterCommandEntry("", 0 ) + }; + + for (int i = 0; commands[i].command != 0; i++) { + std::vector::const_iterator j; + for (j = parsers.begin(); j != parsers.end(); j++) { + if (commands[i].name == j->name) { + if (commands[i].command != j->command) { + CYG_FAIL("Property names are being re-used"); + } + break; + } + } + if (j == parsers.end()) { + parsers.push_back(commands[i]); + } + } + CdlNodeBody::add_property_parsers(parsers); + + CYG_REPORT_RETURN(); +} + +void +CdlDefineLoadableBody::check_properties(CdlInterpreter interp) +{ + CYG_REPORT_FUNCNAME("CdlDefineLoadable::check_properties"); + CYG_REPORT_FUNCARG2XV(this, interp); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(interp); + + // There should be at most one define_header property + int count = count_properties(CdlPropertyId_DefineHeader); + if (count> 1) { + CdlParse::report_error(interp, "There should be at most one define_header property."); + } + // FIXME: filename validation + + CdlNodeBody::check_properties(interp); + + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- +// syntax: define_header
+int +CdlDefineLoadableBody::parse_define_header(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_define_header", "result %d"); + + int result = CdlParse::parse_string_property(interp, argc, argv, CdlPropertyId_DefineHeader, 0, 0); + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ generate_config_header() + +// ---------------------------------------------------------------------------- +void +CdlDefineLoadableBody::generate_config_header(Tcl_Channel this_hdr, Tcl_Channel system_h) const + throw(CdlInputOutputException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlDefineLoadable::generate_config_header"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlInterpreter interp = get_interpreter(); + Tcl_RegisterChannel(interp->get_tcl_interpreter(), this_hdr); + Tcl_RegisterChannel(interp->get_tcl_interpreter(), system_h); + + try { + interp->set_variable("::cdl_header", Tcl_GetChannelName(this_hdr)); + interp->set_variable("::cdl_system_header", Tcl_GetChannelName(system_h)); + + const std::vector& contents = get_owned(); + std::vector::const_iterator node_i; + for (node_i = contents.begin(); node_i != contents.end(); node_i++) { + CdlDefinable definable = dynamic_cast(*node_i); + if (0 == definable) { + continue; + } + if (!definable->is_active()) { + continue; + } + definable->generate_config_header(this_hdr, system_h); + } + + interp->unset_variable("::cdl_header"); + interp->unset_variable("::cdl_system_header"); + } catch(...) { + Tcl_UnregisterChannel(interp->get_tcl_interpreter(), this_hdr); + Tcl_UnregisterChannel(interp->get_tcl_interpreter(), system_h); + throw; + } + + Tcl_UnregisterChannel(interp->get_tcl_interpreter(), this_hdr); + Tcl_UnregisterChannel(interp->get_tcl_interpreter(), system_h); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ get_config_headers() + +// ---------------------------------------------------------------------------- +// What header file should be generated for this loadable? +// +// If there is a define_header property then this should be used. +// Otherwise a filename is constructed from the loadable's name. + +std::string +CdlDefineLoadableBody::get_config_header() const +{ + CYG_REPORT_FUNCNAME("CdlDefineLoadable::get_config_headers"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + std::string result = ""; + CdlProperty prop = get_property(CdlPropertyId_DefineHeader); + if (0 != prop) { + CdlProperty_String string_prop = dynamic_cast(prop); + CYG_ASSERT_CLASSC(string_prop); + result = string_prop->get_string(); + } else { + std::string tmp = get_name(); + result = Cdl::get_short_form(tmp); + result += ".h"; + } + CYG_REPORT_RETURN(); + return result; +} + +//}}} + +//}}} +//{{{ CdlToplevel + +//{{{ CdlToplevel::get_build_info() + +// ---------------------------------------------------------------------------- +// Essentially this code involves iterating over the loadables vector, +// looking for BuildLoadables and invoking their update_build_info() +// member function. In addition, if there is currently some data in +// the build_info vector (probably from a previous call) then that +// must be cleared. + +void +CdlToplevelBody::get_build_info(CdlBuildInfo& build_info) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::get_build_info"); + CYG_REPORT_FUNCARG2XV(this, &build_info); + CYG_PRECONDITION_THISC(); + + if (0 != build_info.entries.size()) { + build_info.entries.clear(); + } + + const std::vector& loadables = get_loadables(); + std::vector::const_iterator load_i; + for (load_i = loadables.begin(); load_i != loadables.end(); load_i++) { + CdlConstBuildLoadable bl = dynamic_cast(*load_i); + if (0 != bl) { + bl->update_build_info(build_info); + } + } + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ CdlToplevel::get_all_build_info() + +// ---------------------------------------------------------------------------- +// This is just like get_build_info(), but calls a different +// BuildLoadable member. + +void +CdlToplevelBody::get_all_build_info(CdlBuildInfo& build_info) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::get_all_build_info"); + CYG_REPORT_FUNCARG2XV(this, &build_info); + CYG_PRECONDITION_THISC(); + + if (0 != build_info.entries.size()) { + build_info.entries.clear(); + } + + const std::vector& loadables = get_loadables(); + std::vector::const_iterator load_i; + for (load_i = loadables.begin(); load_i != loadables.end(); load_i++) { + CdlConstBuildLoadable bl = dynamic_cast(*load_i); + if (0 != bl) { + bl->update_all_build_info(build_info); + } + } + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ CdlToplevel::generate_config_headers() + +// ---------------------------------------------------------------------------- +// Generating the config headers. This involves the following steps: +// +// 1) for every DefineLoadable, find out what header file should +// be generated. Note that some loadables may share a header file. +// +// 2) create a temporary version of system.h. Note that it is not +// a good idea to just overwrite an existing system.h, chances +// are pretty good that the file will not have changed, and +// updating it unnecessarily will result in unnecessary rebuilds +// due to header file dependencies. +// +// 3) for each file that should be generated, create a temporary +// version and allow all applicable loadables to update it. + +// A utility to compare two files and do the right thing. +// This requires some simple Tcl code. +static void +compare_and_copy(CdlInterpreter interp, std::string file1, std::string file2) +{ + CYG_REPORT_FUNCNAME("compare_and_copy"); + CYG_PRECONDITION_CLASSC(interp); + CYG_PRECONDITIONC("" != file1); + CYG_PRECONDITIONC("" != file2); + CYG_PRECONDITIONC(file1 != file2); + + static char compare_and_copy_script[] = "\ +if {[file exists \"$::cdl_compare_and_copy_file2\"] == 0} { \n\ + file rename -- \"$::cdl_compare_and_copy_file1\" \"$::cdl_compare_and_copy_file2\" \n\ + return \n\ +} \n\ +set fd [open \"$::cdl_compare_and_copy_file1\" r] \n\ +set data1 [read $fd] \n\ +close $fd \n\ +set fd [open \"$::cdl_compare_and_copy_file2\" r] \n\ +set data2 [read $fd] \n\ +close $fd \n\ +if {$data1 == $data2} { \n\ + file delete \"$::cdl_compare_and_copy_file1\" \n\ +} else { \n\ + file rename -force -- \"$::cdl_compare_and_copy_file1\" \"$::cdl_compare_and_copy_file2\" \n\ +} \n\ +"; + + interp->set_variable("::cdl_compare_and_copy_file1", file1); + interp->set_variable("::cdl_compare_and_copy_file2", file2); + std::string tcl_result; + if (TCL_OK != interp->eval(compare_and_copy_script, tcl_result)) { + throw CdlInputOutputException("internal error manipulating temporary header " + file1 + " and target " + file2 + + "\n" + tcl_result); + } +} + +void +CdlToplevelBody::generate_config_headers(std::string directory) + throw(CdlInputOutputException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlToplevel::generate_config_headers"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + CYG_ASSERTC("" != directory); + + // Replace any backslashes in the path with forward slashes. The + // latter are used throughout the library + // NOTE: this is not i18n-friendly. + for (unsigned int i = 0; i < directory.size(); i++) { + if ('\\' == directory[i]) { + directory[i] = '/'; + } + } + + CdlInterpreter interp = get_interpreter(); + std::string tcl_result; + if ((TCL_OK != interp->eval("file isdirectory \"" + directory + "\"", tcl_result)) || + (tcl_result != "1")) { + throw CdlInputOutputException("target " + directory + " is not a valid existing directory."); + } + + std::vector > headers; + const std::vector& loadables = get_loadables(); + std::vector::const_iterator load_i; + for (load_i = loadables.begin(); load_i != loadables.end(); load_i++) { + CdlDefineLoadable tmp = dynamic_cast(*load_i); + if (0 != tmp) { + std::string hdr = tmp->get_config_header(); + headers.push_back(std::make_pair(tmp, hdr)); + } + } + + static char banner_format[] = +"#ifndef CYGONCE_PKGCONF_%s\n\ +#define CYGONCE_PKGCONF_%s\n\ +/*\n\ + * File \n\ + *\n\ + * This file is generated automatically by the configuration\n\ + * system. It should not be edited. Any changes to this file\n\ + * may be overwritten.\n\ + */\n\ +\n"; +#ifdef _WIN32 + // Create three channels which Tcl will use for standard streams + // if these streams do not already exist. This avoids a Tcl + // problem which can prevent closure of system.h. (FIXME) + Tcl_Channel stdin_chan = Tcl_OpenFileChannel(interp->get_tcl_interpreter(), "nul", "w", 0666); + Tcl_Channel stdout_chan = Tcl_OpenFileChannel(interp->get_tcl_interpreter(), "nul", "w", 0666); + Tcl_Channel stderr_chan = Tcl_OpenFileChannel(interp->get_tcl_interpreter(), "nul", "w", 0666); + Tcl_RegisterChannel(0, stdin_chan); + Tcl_RegisterChannel(0, stdout_chan); + Tcl_RegisterChannel(0, stderr_chan); +#endif + // Assume for now that files __libcdl_file1 and __libcdl_file2 are + // legal on all platforms of interest, and that nobody is going to + // export to these. + std::string system_h_name = directory + "/__libcdl_file1"; + Tcl_Channel system_h = Tcl_OpenFileChannel(interp->get_tcl_interpreter(), + const_cast(system_h_name.c_str()), "w", 0666); + if (0 == system_h) { + throw CdlInputOutputException("Unable to open file " + system_h_name + "\n" + + interp->get_result()); + } + // The channel will be registered and unregistered in several + // different interpreters. This call prevents the channel from + // disappearing prematurely. + Tcl_RegisterChannel(0, system_h); + + // Make sure that this operation is undone if necessary. + try { + // Now fill in system.h with the appropriate data. Start with the banner. + char local_buf[512]; + sprintf(local_buf, banner_format, "SYSTEM_H", "SYSTEM_H", "system.h"); + Tcl_Write(system_h, local_buf, -1); + + // The rest of system.h will be filled in by the following loop. + // + // Next, walk down the previously constructed headers vector, + // create appropriate files, and let each DefineLoadable fill + // in the file for itself. + std::vector >::iterator outer_i; + std::vector >::iterator inner_i; + for (outer_i = headers.begin(); outer_i != headers.end(); outer_i++) { + if ("" == outer_i->second) { + continue; + } + std::string target_name = outer_i->second; + std::string header_name = directory + "/__libcdl_file2"; + Tcl_Channel header_h = Tcl_OpenFileChannel(interp->get_tcl_interpreter(), + const_cast(header_name.c_str()), "w", 0666); + if (0 == header_h) { + throw CdlInputOutputException("Unable to open file " + header_name + "\n" + + interp->get_result()); + } + // The channel may be used in several different interpreters, so + // do an extra register operation + Tcl_RegisterChannel(0, header_h); + + try { + // Output the banner. This requires an all-upper-case version of the + // header name. + std::string upper_case; + for (unsigned int i = 0; i < target_name.size(); i++) { + if (islower(target_name[i])) { + upper_case += toupper(target_name[i]); + } else if ('.' == target_name[i]) { + upper_case += '_'; + } else { + upper_case += target_name[i]; + } + } + sprintf(local_buf, banner_format, upper_case.c_str(), upper_case.c_str(), target_name.c_str()); + Tcl_Write(header_h, local_buf, -1); + + // Now iterate over all the loadables looking for ones which + // should generate #define's for this header, and invoke the + // appropriate member function. + for (inner_i = outer_i; inner_i != headers.end(); inner_i++) { + if (inner_i->second == target_name) { + inner_i->first->generate_config_header(header_h, system_h); + inner_i->second = ""; + } + } + + // The header file has now been updated. Close it and decide whether + // or not to replace the old version + Tcl_Write(header_h, "\n#endif\n", -1); + } catch(...) { + Tcl_UnregisterChannel(0, header_h); + throw; + } + Tcl_UnregisterChannel(0, header_h); + compare_and_copy(interp, header_name, directory + "/" + target_name); + } + + Tcl_Write(system_h, "\n#endif\n", -1); + } catch(...) { + Tcl_UnregisterChannel(0, system_h); + throw; + } + + // This call to UnregisterChannel automatically closes the + // channel, there is no need for an explicit Tcl_Close() call. + Tcl_UnregisterChannel(0, system_h); +#ifdef _WIN32 + Tcl_UnregisterChannel(0, stderr_chan); + Tcl_UnregisterChannel(0, stdout_chan); + Tcl_UnregisterChannel(0, stdin_chan); +#endif + compare_and_copy(interp, system_h_name, directory +"/system.h"); +} + +//}}} +//{{{ CdlToplevel::get_config_headers() + +// ---------------------------------------------------------------------------- +// Return details of the header files that should be generated. This +// allows higher-level code to detect files that should no longer +// be present, amongst other uses. +// +// The main complication is that some packages may wish to share the +// same header file, especially hardware packages. + +void +CdlToplevelBody::get_config_headers(std::vector& headers) +{ + CYG_REPORT_FUNCNAME("CdlToplevelBody::get_config_headers"); + CYG_REPORT_FUNCARG2XV(this, &headers); + CYG_PRECONDITION_THISC(); + + // Allow the vector argument to be re-used in multiple calls. + // Strictly speaking this is better done at the application + // level, but the behaviour is consistent with get_build_info(); + headers.clear(); + + // There will always be a system.h header file with details + // of the loadables. + // FIXME: the name of this file should probably be controllable + headers.push_back("system.h"); + + // Now check each loadable and adds its header file, assuming + // this is unique. + const std::vector& loadables = get_loadables(); + std::vector::const_iterator i; + for (i = loadables.begin(); i != loadables.end(); i++) { + CdlDefineLoadable current = dynamic_cast(*i); + if (0 != current) { + std::string its_file = current->get_config_header(); + CYG_LOOP_INVARIANTC("" != its_file); + if (std::find(headers.begin(), headers.end(), its_file) == headers.end()) { + headers.push_back(its_file); + } + } + } + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ CdlToplevel::generate_build_tree() + +void +CdlToplevelBody::generate_build_tree(std::string build_tree, std::string install_tree) + throw(CdlInputOutputException, std::bad_alloc) +{ +} + +//}}} + +//}}} diff --git a/host/libcdl/cdl.dsp b/host/libcdl/cdl.dsp new file mode 100644 --- /dev/null +++ b/host/libcdl/cdl.dsp @@ -0,0 +1,268 @@ +# Microsoft Developer Studio Project File - Name="cdl" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Generic Project" 0x010a + +CFG=cdl - Win32 ANSI Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "cdl.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "cdl.mak" CFG="cdl - Win32 ANSI Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "cdl - Win32 Release" (based on "Win32 (x86) Generic Project") +!MESSAGE "cdl - Win32 Debug" (based on "Win32 (x86) Generic Project") +!MESSAGE "cdl - Win32 ANSI Debug" (based on "Win32 (x86) Generic Project") +!MESSAGE "cdl - Win32 ANSI Release" (based on "Win32 (x86) Generic Project") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +MTL=midl.exe + +!IF "$(CFG)" == "cdl - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "V:\ide\Release\cdl" +# PROP Intermediate_Dir "V:\ide\Release\cdl\build" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "cdl - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "cdl___Win32_Debug" +# PROP BASE Intermediate_Dir "cdl___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "V:\ide\Debug\cdl" +# PROP Intermediate_Dir "V:\ide\Debug\cdl\build" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "cdl - Win32 ANSI Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "cdl___Win32_ANSI_Debug" +# PROP BASE Intermediate_Dir "cdl___Win32_ANSI_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "V:\ide\Debug\cdl" +# PROP Intermediate_Dir "V:\ide\Debug\cdl\build" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "cdl - Win32 ANSI Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "cdl___Win32_ANSI_Release" +# PROP BASE Intermediate_Dir "cdl___Win32_ANSI_Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "V:\ide\Release\cdl" +# PROP Intermediate_Dir "V:\ide\Release\cdl\build" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "cdl - Win32 Release" +# Name "cdl - Win32 Debug" +# Name "cdl - Win32 ANSI Debug" +# Name "cdl - Win32 ANSI Release" +# Begin Source File + +SOURCE=.\base.cxx +# End Source File +# Begin Source File + +SOURCE=.\build.cxx +# End Source File +# Begin Source File + +SOURCE=.\cdl.hxx +# End Source File +# Begin Source File + +SOURCE=.\cdlcore.hxx +# End Source File +# Begin Source File + +SOURCE=.\cdlmisc.cxx +# End Source File +# Begin Source File + +SOURCE=.\ChangeLog + +!IF "$(CFG)" == "cdl - Win32 Release" + +# Begin Custom Build - Performing Custom Build Step for libCDL +IntDir=V:\ide\Release\cdl\build +OutDir=V:\ide\Release\cdl +InputPath=.\ChangeLog + +BuildCmds= \ + if not exist $(IntDir)\tools\configtool\standalone\common\Makefile sh -c "ECOSHOST=`echo ""puts [ file attributes [ pwd ] -shortname ]"" | cygtclsh80`/.. ; echo ""ECOSHOST=$ECOSHOST"" ; echo ""TCLHOME=$TCLHOME"" ; mkdir -p `cygpath -u ""$(IntDir)""` ; cd `cygpath -u ""$(IntDir)""` && CC=cl CXX=cl `cygpath -u ""$ECOSHOST""`/configure --prefix=`cygpath -u ""$(OutDir)""` --with-tcl=`cygpath -u ""$TCLHOME""` --with-tcl_version=82" \ + cd $(IntDir) \ + v: \ + make --unix install \ + + +"$(OutDir)\lib\cdl.lib" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(OutDir)\lib\cyginfra.lib" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "cdl - Win32 Debug" + +# Begin Custom Build - Performing Custom Build Step for libCDL +IntDir=V:\ide\Debug\cdl\build +OutDir=V:\ide\Debug\cdl +InputPath=.\ChangeLog + +BuildCmds= \ + if not exist $(IntDir)\tools\configtool\standalone\common\Makefile sh -c "ECOSHOST=`echo ""puts [ file attributes [ pwd ] -shortname ]"" | cygtclsh80`/.. ; echo ""ECOSHOST=$ECOSHOST"" ; echo ""TCLHOME=$TCLHOME"" ; mkdir -p `cygpath -u ""$(IntDir)""` ; cd `cygpath -u ""$(IntDir)""` && CC=cl CXX=cl `cygpath -u ""$ECOSHOST""`/configure --prefix=`cygpath -u ""$(OutDir)""` --with-tcl=`cygpath -u ""$TCLHOME""` --with-tcl_version=82 --enable-debug --enable-maintainer-mode" \ + cd $(IntDir) \ + v: \ + make --unix install \ + + +"$(OutDir)\lib\cdl.lib" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(OutDir)\lib\cyginfra.lib" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "cdl - Win32 ANSI Debug" + +# Begin Custom Build - Performing Custom Build Step for libCDL +IntDir=V:\ide\Debug\cdl\build +OutDir=V:\ide\Debug\cdl +InputPath=.\ChangeLog + +BuildCmds= \ + if not exist $(IntDir)\tools\configtool\standalone\common\Makefile sh -c "ECOSHOST=`echo ""puts [ file attributes [ pwd ] -shortname ]"" | cygtclsh80`/.. ; echo ""ECOSHOST=$ECOSHOST"" ; echo ""TCLHOME=$TCLHOME"" ; mkdir -p `cygpath -u ""$(IntDir)""` ; cd `cygpath -u ""$(IntDir)""` && CC=cl CXX=cl `cygpath -u ""$ECOSHOST""`/configure --prefix=`cygpath -u ""$(OutDir)""` --with-tcl=`cygpath -u ""$TCLHOME""` --with-tcl_version=82 --enable-debug --enable-maintainer-mode" \ + cd $(IntDir) \ + v: \ + make --unix install \ + + +"$(OutDir)\lib\cdl.lib" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(OutDir)\lib\cyginfra.lib" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "cdl - Win32 ANSI Release" + +# Begin Custom Build - Performing Custom Build Step for libCDL +IntDir=V:\ide\Release\cdl\build +OutDir=V:\ide\Release\cdl +InputPath=.\ChangeLog + +BuildCmds= \ + if not exist $(IntDir)\tools\configtool\standalone\common\Makefile sh -c "ECOSHOST=`echo ""puts [ file attributes [ pwd ] -shortname ]"" | cygtclsh80`/.. ; echo ""ECOSHOST=$ECOSHOST"" ; echo ""TCLHOME=$TCLHOME"" ; mkdir -p `cygpath -u ""$(IntDir)""` ; cd `cygpath -u ""$(IntDir)""` && CC=cl CXX=cl `cygpath -u ""$ECOSHOST""`/configure --prefix=`cygpath -u ""$(OutDir)""` --with-tcl=`cygpath -u ""$TCLHOME""` --with-tcl_version=82" \ + cd $(IntDir) \ + v: \ + make --unix install \ + + +"$(OutDir)\lib\cdl.lib" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(OutDir)\lib\cyginfra.lib" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\component.cxx +# End Source File +# Begin Source File + +SOURCE=.\config.cxx +# End Source File +# Begin Source File + +SOURCE=.\conflict.cxx +# End Source File +# Begin Source File + +SOURCE=.\database.cxx +# End Source File +# Begin Source File + +SOURCE=.\dialog.cxx +# End Source File +# Begin Source File + +SOURCE=.\expr.cxx +# End Source File +# Begin Source File + +SOURCE=.\interface.cxx +# End Source File +# Begin Source File + +SOURCE=.\interp.cxx +# End Source File +# Begin Source File + +SOURCE=.\option.cxx +# End Source File +# Begin Source File + +SOURCE=.\package.cxx +# End Source File +# Begin Source File + +SOURCE=.\parse.cxx +# End Source File +# Begin Source File + +SOURCE=.\property.cxx +# End Source File +# Begin Source File + +SOURCE=.\refer.cxx +# End Source File +# Begin Source File + +SOURCE=.\transact.cxx +# End Source File +# Begin Source File + +SOURCE=.\value.cxx +# End Source File +# Begin Source File + +SOURCE=.\wizard.cxx +# End Source File +# End Target +# End Project diff --git a/host/libcdl/cdl.hxx b/host/libcdl/cdl.hxx new file mode 100644 --- /dev/null +++ b/host/libcdl/cdl.hxx @@ -0,0 +1,608 @@ +#ifndef __CDL_HXX +# define __CDL_HXX +//{{{ Banner + +//============================================================================ +// +// cdl.hxx +// +// This header file declares the classes related to software +// configuration. +// +//============================================================================ +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================ +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contact(s): bartv +// Date: 1998/02/09 +// Version: 0.02 +// Requires: cdlcore.hxx +// Usage: #include +// +//####DESCRIPTIONEND#### +//============================================================================ + +//}}} +//{{{ nested #include's + +// ---------------------------------------------------------------------------- +// Software CDL depends on the core but adds no new system requirements. + +#ifndef __CDLCORE_HXX +# include +#endif + +//}}} + +//{{{ Forward declarations of the body classes + +// ---------------------------------------------------------------------------- +// This section provides forward declarations of the main classes used +// for software configuration. + +class CdlConfigurationBody; +class CdlPackageBody; +class CdlComponentBody; +class CdlOptionBody; +class CdlPackagesDatabaseBody; + +typedef CdlConfigurationBody* CdlConfiguration; +typedef CdlPackageBody* CdlPackage; +typedef CdlComponentBody* CdlComponent; +typedef CdlOptionBody* CdlOption; +typedef CdlPackagesDatabaseBody* CdlPackagesDatabase; + +typedef const CdlConfigurationBody* CdlConstConfiguration; +typedef const CdlPackageBody* CdlConstPackage; +typedef const CdlComponentBody* CdlConstComponent; +typedef const CdlOptionBody* CdlConstOption; +typedef const CdlPackagesDatabaseBody* CdlConstPackagesDatabase; + +//}}} +//{{{ CdlPackagesDatabase class + +// ---------------------------------------------------------------------------- +// An eCos component repository can get to be quite complicated. There will +// be a number of core packages supplied by Red Hat. There may also be some +// number of third party and unsupported packages. Each package may come in +// several different versions. Keeping track of everything that has been +// installed should involve a separate administration tool, and there should +// be some sort of database of all this information. +// +// At the time of writing there is no such administration tool and there is +// no database with details of the various packages. Instead there is a +// static file "packages" at the top level of the component repository, +// containing some of the desired information. +// +// For now a temporary CdlPackagesDatabase class is provided. +// Essentially this provides C++ access to the packages file. In the +// long term this class will be replaced completely by a full and more +// rational implementation. +// +// The packages database class also, temporarily, provides information about +// targets and templates. This will change in future. A target will be specified +// by a save file, the output from Hardy. A template will also be specified by +// a save file, a partial software configuration. + +class CdlPackagesDatabaseBody { + + friend class CdlTest; + friend class CdlDbParser; + + public: + + static CdlPackagesDatabase make(std::string = "") throw(CdlInputOutputException,std::bad_alloc); + bool update(void) throw(CdlInputOutputException,std::bad_alloc); + ~CdlPackagesDatabaseBody(); + + std::string get_component_repository() const; + + const std::vector& get_packages(void) const; + bool is_known_package(std::string) const; + const std::string& get_package_description(std::string) const; + const std::vector& get_package_aliases(std::string) const; + const std::vector& get_package_versions(std::string) const; + const std::string& get_package_directory(std::string) const; + const std::string& get_package_script(std::string) const; + bool is_hardware_package(std::string) const; + + const std::vector& get_targets(void) const; + bool is_known_target(std::string) const; + const std::string& get_target_description(std::string) const; + const std::vector& get_target_aliases(std::string) const; + const std::vector& get_target_packages(std::string) const; + const std::string& get_target_command_prefix(std::string) const; + const std::vector >& get_target_compiler_flags(std::string) const; + const std::vector& get_target_enables(std::string) const; + const std::vector& get_target_disables(std::string) const; + const std::vector >& get_target_set_values(std::string) const; + + const std::vector& get_templates(void) const; + bool is_known_template(std::string) const; + std::string get_template_filename(std::string, std::string = "") const; + const std::vector& get_template_versions(std::string) const; + const std::string get_template_description(std::string, std::string = ""); + const std::vector& get_template_packages(std::string, std::string = ""); + static void extract_template_details(std::string /* filename */, std::string& /* description */, + std::vector& /* packages */); + + // What are the valid compiler flag variables (ARCHFLAGS, ERRFLAGS, ...)? + // For now the library provides a static vector of these things, but + // this area is likely to change in future + static const std::vector& get_valid_cflags(); + + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + private: + // The only valid constructor gets invoked from the make() member function. + // The argument should be a pathname for the component repository. The + // constructor is responsible for reading in the whole packages file. + CdlPackagesDatabaseBody(std::string) throw(CdlInputOutputException,std::bad_alloc); + + std::string component_repository; + std::vector package_names; + struct package_data { + public: + std::string description; + std::vector aliases; + std::vector versions; + std::string directory; + std::string script; + bool hardware; + }; + std::map packages; + + std::vector target_names; + struct target_data { + public: + std::string description; + std::vector aliases; + std::vector packages; + std::string command_prefix; + std::vector > cflags; + std::vector enable; + std::vector disable; + std::vector > set_values; + }; + std::map targets; + + std::vector template_names; + struct template_version_data { + public: + std::string description; + std::vector packages; + }; + struct template_data { + public: + std::vector versions; + std::map version_details; + }; + std::map templates; + + enum { + CdlPackagesDatabaseBody_Invalid = 0, + CdlPackagesDatabaseBody_Magic = 0x50896acb + } cdlpackagesdatabasebody_cookie; + + // This allows test cases to overwrite the name of the file + // containing the database information. + static char* database_name; + + // The default constructor, copy constructor and assignment operator are illegal. + CdlPackagesDatabaseBody(); + CdlPackagesDatabaseBody(const CdlPackagesDatabaseBody&); + CdlPackagesDatabaseBody& operator=(const CdlPackagesDatabaseBody&); + +}; + +//}}} +//{{{ CdlConfiguration class + +// ---------------------------------------------------------------------------- +// The CdlConfiguration class is the toplevel used for mainpulating +// software configurations. It consists of a number of loaded packages, +// each of which consists of some hierarchy of components and options, +// plus dialogs, wizards, and interfaces from the core. +// +// Typically an application will deal with only one configuration at a +// time. There will be exceptions. The most obvious example would be +// some sort of diff utility, but there may well be times when a user +// wants to edit multiple configurations. One example would be a board +// containing two separate processors, e.g. a conventional one coupled +// with a separate DSP, and eCos is supposed to run on both: the two +// chips will need to interact, and hence there may well be +// configurability dependencies between them. +// +// A configuration object does not exist in isolation. It must be tied +// to an eCos component repository via a database objects. It must +// also be supplied with a suitable Tcl interpreter. + +class CdlConfigurationBody : public virtual CdlToplevelBody +{ + friend class CdlTest; + + public: + + // ---------------------------------------------------------------------------- + // Create a new configuration. + // Currently this requires a name, a database and a master interpreter. + // The name is not used very much, but does appear in savefiles. + // The packages database and the interpreter must be created before + // any configuration object. + static CdlConfiguration make(std::string /* name */, CdlPackagesDatabase, CdlInterpreter); + CdlPackagesDatabase get_database() const; + + // Loading and unloading packages. This can happen in a number + // of different ways: + // + // 1) explicitly adding or removing a single package + // 2) changing the version of a package, which means unloading + // the old version and reloading the new one. Generally + // user settings should be preserved where possible. + // 3) loading in a full or minimal savefile. The library + // does not actually distinguish between the two when + // loading, only when saving. + // 4) adding a full or minimal savefile. + // 5) setting a template for the first time. This is much the + // same as adding a minimal savefile. However the library + // keeps track of the "current" template and only one + // can be loaded at a time. The library does not keep + // track of which savefile(s) have been added. + // 6) changing a template. This means unloading the packages + // that were loaded for the old template, then loading in + // the new one. + // 7) unsetting the template. This just involves an unload. + // 8) setting the hardware. Currently the database defines + // each supported target, listing the packages that should + // be loaded and possibly some option details. This is + // subject to change in future. + // 9) changing the hardware. This is much the same as changing + // the template. + // 10) unsetting the hardware. + // + // The unload operations are comparatively safe, although + // they can result in new conflicts and the user may well want + // to cancel the operation after discovering how many new + // problems there would be. The load operations are a bit more + // dangerous since they depend on external data and hence can + // fail for a variety of reasons: missing files, corrupt files, + // clashes with existing data, ... Changing e.g. a template + // is especially dangerous because of the number of things + // that can go wrong. All of these operations need to happen + // in a transaction which the user can cancel. There are two + // versions of all the relevant routines, one which operates + // in an existing transaction and one which creates a new + // one. + // + // Any operation that involves loading CDL data takes two + // CdlDiagnosticFnPtr arguments, one for errors and one for + // warnings. These should report the message to the user by + // some suitable means. The error fnptr may throw a + // CdlParseException to abort the current load immediately, + // otherwise the load operation will be aborted at the end + // if any errors were detected. New conflicts are not + // handled by these diagnostic functions, instead they + // are handled by the normal transaction methods. + + // A version argument of "" implies the most recent version. + void load_package(std::string /* name */, std::string /* version */, + CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc); + void load_package(CdlTransaction, std::string /* name */, std::string /* version */, + CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc); + + void unload_package(std::string /* name */, bool /* limbo */ = true); + void unload_package(CdlPackage, bool /* limbo */ = true); + void unload_package(CdlTransaction, std::string /* name */, bool /* limbo */ = true); + void unload_package(CdlTransaction, CdlPackage, bool /* limbo */ = true); + + void change_package_version(std::string /*name*/, std::string /*version*/, + CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc); + void change_package_version(CdlPackage, std::string /*version*/, CdlDiagnosticFnPtr /* error */, + CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc); + + void change_package_version(CdlTransaction, std::string /*name*/, std::string /*version*/, + CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc); + void change_package_version(CdlTransaction, CdlPackage, std::string /*version*/, CdlDiagnosticFnPtr /* error */, + CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc); + + // Loading a savefile is different in that it creates a new + // toplevel. Since transactions can only be created if the + // toplevel already exists, it is not possible to have a + // per-transaction load() operation. It is possible to have + // a per-transaction add() operation. + static CdlConfiguration load(std::string /* filename */, CdlPackagesDatabase, CdlInterpreter, + CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc); + + void add(std::string /* filename */, + CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc); + void add(CdlTransaction, std::string /* filename */, + CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc); + + // As with packages, a version of "" implies the most recent. + void set_template(std::string, std::string /* version */, + CdlDiagnosticFnPtr, CdlDiagnosticFnPtr /* warn */,bool /* limbo */ = true) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc); + void set_template_file(std::string, + CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc); + void set_template(CdlTransaction, std::string, std::string /* version */, + CdlDiagnosticFnPtr, CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc); + void set_template_file(CdlTransaction, std::string, + CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc); + void unload_template(bool /* limbo */ = true); + void unload_template(CdlTransaction, bool /* limbo */ = true); + std::string get_template() const; + void set_template_name(std::string); // Intended for library use only + + void set_hardware(std::string, + CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc); + void set_hardware(CdlTransaction, std::string, + CdlDiagnosticFnPtr /* error */, CdlDiagnosticFnPtr /* warn */, bool /* limbo */ = true) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc); + void unload_hardware(bool /* limbo */ = true); + void unload_hardware(CdlTransaction, bool /* limbo */ = true); + std::string get_hardware() const; + void set_hardware_name(std::string); // Intended for library use only + + // ---------------------------------------------------------------------------- + // Save a configuration to a file + void save(std::string, bool /* minimal */ = false) throw(CdlInputOutputException,std::bad_alloc); + void initialize_savefile_support(); + std::string get_save_file() const; + + // ---------------------------------------------------------------------------- + // Get rid of a configuration. + ~CdlConfigurationBody(); + + virtual std::string get_class_name() const; + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + private: + + // The only legal constructor, invoked from make() and load() + CdlConfigurationBody(std::string, CdlPackagesDatabase, CdlInterpreter); + + // The internal implementation of the persistence support + virtual void save(CdlInterpreter, Tcl_Channel, int, bool) throw(CdlInputOutputException, std::bad_alloc); + static int savefile_configuration_command(CdlInterpreter, int, char**); + static int savefile_description_command(CdlInterpreter, int, char**); + static int savefile_hardware_command(CdlInterpreter, int, char**); + static int savefile_template_command(CdlInterpreter, int, char**); + static int savefile_package_command(CdlInterpreter, int, char**); + + std::string current_hardware; + std::string current_template; + std::string description; + CdlPackagesDatabase database; + std::string save_file; + enum { + CdlConfigurationBody_Invalid = 0, + CdlConfigurationBody_Magic = 0x5c409a3d + } cdlconfigurationbody_cookie; + + // The constructor can only be invoked via the make() and load() + // members. Other constructors and the assignment operator are + // illegal. + CdlConfigurationBody(); + CdlConfigurationBody(const CdlConfigurationBody&); + CdlConfigurationBody& operator=(const CdlConfigurationBody&); + +}; + +//}}} +//{{{ CdlPackage class + +// ---------------------------------------------------------------------------- +// Packages inherit from most of the base classes. + +class CdlPackageBody : public virtual CdlNodeBody, + public virtual CdlContainerBody, + public virtual CdlUserVisibleBody, + public virtual CdlValuableBody, + public virtual CdlParentableBody, + public virtual CdlBuildableBody, + public virtual CdlDefinableBody, + public virtual CdlLoadableBody, + public virtual CdlBuildLoadableBody, + public virtual CdlDefineLoadableBody +{ + friend class CdlTest; + + // Packages should not be created by application code, but + // the CdlConfiguration class must be able to do so inside + // load_package(); + friend class CdlConfigurationBody; + + public: + + ~CdlPackageBody(); + + static int parse_package(CdlInterpreter, int, char**); + static int parse_hardware(CdlInterpreter, int, char**); + static int parse_install_proc(CdlInterpreter, int, char**); + static int parse_license_proc(CdlInterpreter, int, char**); + + // Override the CdlDefineLoadable member. Hardware packages always + // send their configuration options to hardware.h + virtual std::string get_config_header() const; + + bool is_hardware_package() const; + bool has_install_proc() const; + const cdl_tcl_code& get_install_proc() const; + bool has_license_proc() const; + const cdl_tcl_code& get_license_proc() const; + + // Propagation support. Because of multiple virtual inheritance + // it is necessary to invoke the container and valuable + // update members. + virtual void update(CdlTransaction, CdlUpdate); + + // Persistence support. + virtual void save(CdlInterpreter, Tcl_Channel, int, bool) throw(CdlInputOutputException, std::bad_alloc); + static void initialize_savefile_support(CdlToplevel); + static int savefile_package_command(CdlInterpreter, int, char**); + + // Was this package loaded because of a template or hardware setting? + bool belongs_to_template() const; + bool belongs_to_hardware() const; + + virtual std::string get_class_name() const; + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + private: + + // The only valid constructor requires a number of fields + CdlPackageBody(std::string /* name */, CdlConfiguration, std::string /* directory */); + + // Other constructors are illegal + CdlPackageBody(); + CdlPackageBody(const CdlPackageBody&); + CdlPackageBody& operator=(const CdlPackageBody&); + + bool loaded_for_template; + bool loaded_for_hardware; + + enum { + CdlPackageBody_Invalid = 0, + CdlPackageBody_Magic = 0x1d7c0d43 + } cdlpackagebody_cookie; +}; + +//}}} +//{{{ CdlComponent class + +// ---------------------------------------------------------------------------- +// Similarly components just inherit from the appropriate base classes. + +class CdlComponentBody : public virtual CdlNodeBody, + public virtual CdlContainerBody, + public virtual CdlUserVisibleBody, + public virtual CdlValuableBody, + public virtual CdlParentableBody, + public virtual CdlBuildableBody, + public virtual CdlDefinableBody +{ + friend class CdlTest; + + public: + + ~CdlComponentBody(); + static int parse_component(CdlInterpreter, int, char**); + static int parse_script(CdlInterpreter, int, char**); + + // Propagation support. Because of multiple virtual inheritance + // it is necessary to invoke the container and valuable + // update members. + virtual void update(CdlTransaction, CdlUpdate); + + // Persistence support. + virtual void save(CdlInterpreter, Tcl_Channel, int, bool) throw(CdlInputOutputException, std::bad_alloc); + static void initialize_savefile_support(CdlToplevel); + static int savefile_component_command(CdlInterpreter, int, char**); + + virtual std::string get_class_name() const; + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + private: + + // The only valid constructor requires a name. + CdlComponentBody(std::string); + + enum { + CdlComponentBody_Invalid = 0, + CdlComponentBody_Magic = 0x6359d9a7 + } cdlcomponentbody_cookie; + + // Other constructors are illegal + CdlComponentBody(); + CdlComponentBody(const CdlComponentBody&); + CdlComponentBody& operator=(const CdlComponentBody&); +}; + +//}}} +//{{{ CdlOption class + +// ---------------------------------------------------------------------------- +// Again options just inherit their functionality from the base classes. + +class CdlOptionBody : public virtual CdlNodeBody, + public virtual CdlUserVisibleBody, + public virtual CdlValuableBody, + public virtual CdlParentableBody, + public virtual CdlBuildableBody, + public virtual CdlDefinableBody +{ + friend class CdlTest; + + public: + ~CdlOptionBody(); + + static int parse_option(CdlInterpreter, int, char**); + + // Persistence support. + virtual void save(CdlInterpreter, Tcl_Channel, int, bool) throw(CdlInputOutputException, std::bad_alloc); + static void initialize_savefile_support(CdlToplevel); + static int savefile_option_command(CdlInterpreter, int, char**); + + virtual std::string get_class_name() const; + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + private: + CdlOptionBody(std::string); + + enum { + CdlOptionBody_Invalid = 0, + CdlOptionBody_Magic = 0x1c1162d1 + } cdloptionbody_cookie; + + CdlOptionBody(); + CdlOptionBody(const CdlOptionBody&); + CdlOptionBody& operator=(const CdlOptionBody&); +}; + +//}}} + +#endif /* !__CDL_HXX */ +// EOF cdl.hxx diff --git a/host/libcdl/cdlcore.hxx b/host/libcdl/cdlcore.hxx new file mode 100644 --- /dev/null +++ b/host/libcdl/cdlcore.hxx @@ -0,0 +1,5530 @@ +#ifndef __CDLCORE_HXX +# define __CDLCORE_HXX + +//{{{ Banner + +//========================================================================== +// +// cdlcore.hxx +// +// The core parts of the library. This header defines aspects of +// CDL that are shared between software cdl, hcdl, scdl, and any +// future languages based on the same core technology. +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contributors: bartv +// Date: 1999-04-15 +// +//####DESCRIPTIONEND#### +//========================================================================== + +//}}} +//{{{ Platform dependencies + +// ---------------------------------------------------------------------------- +// Visual C++ has the delightful feature that the source browser will generate +// warnings if there are any identifiers of length >= 256 characters, while at +// the same time use of templates in the standard C++ library can easily +// generate functions that long. It appears that the only way to disable the +// warnings is by use of a %$#@(%*&%! #pragma. +// +// Similarly, VC++ gives spurious warnings when it comes to multiple virtual +// inheritance. +#ifdef _MSC_VER +# pragma warning( disable: 4786 ) +# pragma warning( disable: 4250 ) +#endif + +//}}} +//{{{ nested #include's + +// ---------------------------------------------------------------------------- +// The libcdl API is defined using parts of the standard C++ library, +// including strings and various bits of STL. Therefore these headers must +// be #include'd here for the header file to work. +#include +#include +#include +#include +#include +#include +#include +#include + +// Now for some eCos host-side infrastructure headers. +// +// Get the cyg_int64 data type and CYG_UNUSED_PARAM() macro. +#include + +// Some of the classes need to reference the cyg_assert_class_zeal enum. +// Also inline functions may perform assertions. +#include + +// This header file also depends on having a suitable Tcl installation +// Unfortunately does some ugly things in the interests of +// portability, including defining symbols such as EXTERN when +// necessary, and this has to be patched up here as cleanly as possible. +#ifndef CONST +# define __CDL_CONST_UNDEFINED +#endif +#ifndef EXTERN +# define __CDL_EXTERN_UNDEFINED +#endif +#ifndef VOID +# define __CDL_VOID_UNDEFINED +#endif +#ifndef CHAR +# define __CDL_CHAR_UNDEFINED +#endif +#ifndef SHORT +# define __CDL_SHORT_UNDEFINED +#endif +#ifndef LONG +# define __CDL_LONG_UNDEFINED +#endif + +extern "C" { +#include +} + +#ifdef __CDL_CONST_UNDEFINED +# undef CONST +# undef __CDL_CONST_UNDEFINED +#endif +#ifdef __CDL_EXTERN_UNDEFINED +# undef EXTERN +# undef __CDL_EXTERN_UNDEFINED +#endif +#ifdef __CDL_VOID_UNDEFINED +# undef VOID +# undef __CDL_VOID_UNDEFINED +#endif +#ifdef __CDL_CHAR_UNDEFINED +# undef CHAR +# undef __CDL_CHAR_UNDEFINED +#endif +#ifdef __CDL_SHORT_UNDEFINED +# undef SHORT +# undef __CDL_SHORT_UNDEFINED +#endif +#ifdef __CDL_LONG_UNDEFINED +# undef LONG +# undef __CDL_LONG_UNDEFINED +#endif + +//}}} + +//{{{ Primitive types, constants:, enums, etc. + +// ---------------------------------------------------------------------------- +// The CDL languages are defined in terms of arbitrary precision +// arithmetic. This is necessary to allow e.g. pointers to be +// manipulated at the CDL level on 64 bit target processors. +// +// Temporarily it is not necessary to provide this precision, so it is +// convenient to stick to 64 bit integers as provided by the +// underlying infrastructure. However the API is defined in terms of +// the type cdl_int, so that it will be easier in future to make the +// change to the correct datatype. At that point cdl_int can be +// redefined to be a class which supports the appropriate operators. + +typedef cyg_int64 cdl_int; + +// --------------------------------------------------------------------------- +// A common concept in the CDL language is a small amount of TCL code. +// This is currently stored as a simple string. Conceivably it could +// be byte-compiled and stored accordingly. + +typedef std::string cdl_tcl_code; + +// ---------------------------------------------------------------------------- +// CDL values. +// +// CDL is a declarative programming language. It does involve the +// manipulation of values, but such values do not necessarily +// correspond to hardware-level entities such as integers or double +// precision numbers. Hence the term "type" is avoided, "flavor" +// is used instead. CDL understands four different flavors. +// +// None | Bool +// --------+-------- +// Data |BoolData +// +// +// The flavor "none" is used for entities that serve only as +// placeholders in the hierarchy, allowing other entities to be +// grouped more easily. +// +// Boolean entities can be either enabled or disabled. This is the +// most common flavor for software configuration options, the user can +// either enable or disable some unit of functionality. For software +// packages implemented in C or C++ the implementation is obvious: iff +// the entity is enabled then there will be a #define, and code will +// check the setting using e.g. #ifdef. +// +// The flavor "data" implies some arbitrary data. Internally this will +// be held as a string. Other properties such as legal_values, +// check_proc and entry_proc can be used to constrain the +// actual values, for example to an integer value within a certain +// range. +// +// The flavor "booldata" combines the previous two: it means that +// the option can be either enabled or disabled, and if it is +// enabled then it must have a value as per legal_values etc. +// One example of this is a software package: this may be either +// enabled or disabled, and if it is enabled then it has a value +// corresponding to the version string. Another example is a hardware +// pin: this may or may not be connected, and if it is connected +// then its value identifies some other pin. +// +// An entity's flavor is not always sufficient by itself to specify +// how the user can manipulate it in a graphical tool. Obviously an +// entity of flavor "none" cannot be manipulated at all. Flavor "bool" +// normally implies a checkbutton, but occasionally a radiobutton will +// be more appropriate. "Data" says very little about the user +// interaction, it will be necessary to examine other properties such +// as legal_values to determine a sensible representation. The same +// goes for "BoolData", with the additional possibility that the +// entity may be disabled. +// +// It can be argued that three of the flavors are redundant: both Bool +// and BoolData could be implemented as cases of "Data" with a special +// legal value "disabled" (or false, or whatever); "None" could be +// implemented as constant "Data"; effectively CDL would manipulate +// all data as strings, just like e.g. all variables in Tcl, or just +// like all scalars in Perl. This approach is certainly tempting and +// might well make it easier to document the language, but in practice +// it would result in more verbose CDL: boolean entities really are a +// different beast from data entities. +// +// It can also be argued that there should be more flavors. For +// example there could be separate flavors for integer data, floating +// point data, string data, and so on. There are a number of good +// reasons for not doing so: +// +// 1) applying separate constraints such as legal_values allows much +// finer control over the actual values, for example numbers within a +// given range. As likely as not, a value will be constrained to +// something smaller than the range MININT to MAXINT (whatever those +// happen to be for the current target). +// +// 2) where do you stop? Do you provide separate flavors for signed +// vs. unsigned? Char, wchar_t, short, int, long, long long? How about +// the eCos data types cyg_ucount8, cyg_uint8, ... Is there support +// for enums? Arrays? Bitfields? Structures? Unions? C++ classes? +// How about other programming languages such as Ada or Java? +// +// Any attempt to implement a grand union of all data types in CDL +// is doomed to failure and should not be attempted. Treating +// everything as a string instead has proven successful in a number +// of languages, including Tcl and Perl. +// +// 3) for some variants of CDL, for example hardware CDL, it may not +// make much sense to display a value directly and allow it to be +// manipulated directly. The value associated with a pin entity +// identifies the pin to which it is connected, and typically +// this value will be manipulated by drag and drop rather than by +// typing some characters. Such a value certainly does not correspond +// to any machine data type. +// +// Another reason for extending the number of flavors is to provide +// more information. For example there could be a specialized version +// of the boolean flavor called "radio". This would imply a specific +// representation in the user interface, and it would also impose +// a constraint that it implicitly precludes any other radio entities +// within the same group. However the same information can be specified +// by other more general means such as requires statements. + +enum CdlValueFlavor { + CdlValueFlavor_Invalid = 0, + CdlValueFlavor_None = 1, + CdlValueFlavor_Bool = 2, + CdlValueFlavor_BoolData = 3, + CdlValueFlavor_Data = 4 +}; + + +// Another important aspect of a value is where it came from. There +// are a number of possible sources: the default value, calculated +// from a default_value property; a value inferred by the inference +// engine; a value set by a wizard; and a value set explicitly by +// the user. These sources have different priorities, so for example +// the inference engine can safely replace a calculated default +// value without prompting the user, but changing a user-set value +// automatically is undesirable. +// +// Wizard-generated values are considered more valuable than default +// or inferred values (there is some user input involved), but less +// valuable than values set explicitly by the user: the idea is that +// a wizard asks fairly generic questions and makes a best guess at +// the correct values, which may not be precise enough for the +// user's needs. +// +// Arguably dialogs provide a level between wizards and users, in that +// a dialog can theoretically manipulate several entities in one go so +// it is a less precise way of setting values. At this stage it does +// not seem worthwhile to add this distinction. +// +// The library actually maintains separate values for each source, +// as well as the current source which is what actually gets used. +// In theory it is possible for the user interface code to let +// the user switch between these. It is not yet clear whether this +// makes sense from an end user's perspective. + +enum CdlValueSource { + CdlValueSource_Invalid = -1, // 0 is needed for array indexing + CdlValueSource_Default = 0, + CdlValueSource_Inferred = 1, + CdlValueSource_Wizard = 2, + CdlValueSource_User = 3, + CdlValueSource_Current = 4 +}; + +// ---------------------------------------------------------------------------- +// Update support. +// +// When there is a change to a node and there are references to that node, +// the referencing properties will want to be informed about this. There +// are various different kinds of changes, not all of which are always +// relevant. For example, if a CDL entity gets destroyed or unloaded then +// all referencing entities are likely to want to know about this, but +// if a container's value changes then this has no effect on a reference +// in e.g. a "parent" property. In some cases it is also useful to apply +// updates to nodes rather than properties, e.g. when a node becomes +// active or inactive. +// +// The generic update code is also used for initialization and finalization, +// i.e. when the source object itself has just been loaded or is +// being unloaded. +// +// For any particular update at most one bit set, but it is often +// appropriate to treat several different kinds of update with +// common code. Hence the enum values can be or'ed and and'ed. + +enum CdlUpdate { + CdlUpdate_Loaded = 0x0001, // The source has just been loaded + CdlUpdate_Init = 0x0002, // Second-phase of a load operation + CdlUpdate_Unloading = 0x0004, // The source is being unloaded + CdlUpdate_Created = 0x0008, // The destination has just been created + CdlUpdate_Destroyed = 0x0010, // The destination is being destroyed + CdlUpdate_ValueChange = 0x0020, // The destination's value has changed. + // This gets applied to nodes as well + CdlUpdate_ActiveChange = 0x0040 // The node has become active or inactive +}; + +// ---------------------------------------------------------------------------- +// Inference engine callback. +// +// During a transaction there may be one or more invocations of the inference +// engine, followed by a callback which should display the current transaction +// status to the user and allow one or more recommended fixes to be accepted. +// The callback's return code indicates what should happen next. "Cancel" +// is pretty obvious. "Continue" may result in a commit, or it may result in +// another iteration. + +enum CdlInferenceCallbackResult { + CdlInferenceCallbackResult_Continue = 0x01, + CdlInferenceCallbackResult_Cancel = 0x02 +}; + +// ---------------------------------------------------------------------------- +// Widget hints. +// +// The library can provide a hint to the GUI code as to a sensible +// widget to use for displaying a particular valuable. There are separate +// hints for the bool and data parts. + +enum CdlBoolWidget { + CdlBoolWidget_None = 0, // The boolean part is not applicable + CdlBoolWidget_CustomDialog = 1, // There is a valid custom dialog property + CdlBoolWidget_CheckButton = 2, // For simple booleans + CdlBoolWidget_Radio = 3, // For several mutual exclusive options, + // the data structure will provide a string identifier +}; + +enum CdlValueWidget { + CdlValueWidget_None = 0, // The value part is not applicable + CdlValueWidget_CustomDialog = 1, // There is a valid custom dialog property + CdlValueWidget_Loadable = 2, // Use package/version dialog + CdlValueWidget_EntryBox = 3, // Fallback + CdlValueWidget_MultilineString = 4, // For complicated strings + CdlValueWidget_DecimalRange = 5, // e.g. 1 to 16 + // Could be implemented as scale, radio buttons, entry, pull-down menu, + // combo box, ... depending on GUI conventions and number of entries + CdlValueWidget_HexRange = 6, // e.g. 0x01 to 0x10 + CdlValueWidget_OctalRange = 7, // e.g. 01 to 020 + CdlValueWidget_DoubleRange = 8, // e.g. 0.1 to 0.2 + CdlValueWidget_NumericSet = 9, // e.g. 1 2 4 8 16 + // The exact nature of the numbers is irrelevant, they will only + // get displayed, not edited + // Could be implemented as radio buttons, entry widget, pull-down menu, + // combo box, ... depending on GUI conventions and number of entries + // Each entry can have its own representation + CdlValueWidget_StringSet = 10 // e.g. "ram", "rom" + + // More to be added, e.g. for compiler flag handling +}; + +// ---------------------------------------------------------------------------- +// Value formats. +// +// The CDL input data can accept numbers in a variety of formats, +// for example hexadecimal as well as decimal. It is desirable to try +// to keep track of this formatting information where possible, so +// that what the user sees and what ends up in header files corresponds +// more closely to what is in the raw CDL data. For example, it is +// much easier to understand 0x7fffffff than its decimal equivalent. +// +// The information kept here is very imprecise, it provides only +// minimal formatting information. It is not clear yet whether this +// will suffice or whether something more exact is going to be needed. +enum CdlValueFormat +{ + CdlValueFormat_Default = 0, + CdlValueFormat_Hex = 1, + CdlValueFormat_Octal = 2 +}; + +//}}} +//{{{ Exception classes + +// ---------------------------------------------------------------------------- +// Some parts of the library make use of C++ exception handling. A number +// of exception classes related to this library are useful. In addition +// just about every part of the library can throw std::bad_alloc, but this +// is not checked for explicitly anywhere. + +// This class is used for all exceptions where an error message should +// be displayed to the user. There is a single string message associated +// with the exception. + +class CdlStringException { + friend class CdlTest; + + public: + CdlStringException(std::string message_arg) { + message = message_arg; + } + CdlStringException(const CdlStringException& original) { + message = original.message; + } + CdlStringException& operator=(const CdlStringException& original) { + message = original.message; + return *this; + } + ~CdlStringException() { + message = ""; + } + const std::string& get_message() const { + return message; + } + private: + std::string message; + CdlStringException(); +}; + +// CdlInputOutputException: this gets thrown when something goes wrong during +// file I/O operations, e.g. a file exists but cannot be opened. The +// exception contains a simple string explaining the error. This string +// may contain multiple lines, it is intended to be written to stderr +// or displayed in either a text widget or a dialog box. +// +// A separate class rather than a typedef is used to avoid any possible +// error message confusion. Everything gets inlined so there should be +// no performance issues. + +class CdlInputOutputException : public CdlStringException { + friend class CdlTest; + public: + CdlInputOutputException(std::string message_arg) : + CdlStringException(message_arg) { + } + CdlInputOutputException(const CdlInputOutputException& original) : + CdlStringException(original) { + } + CdlInputOutputException& operator=(const CdlInputOutputException& original) { + (void) CdlStringException::operator=(original); + return *this; + } +}; + +// This class is used when any parsing happens at the C++ level rather +// than at the Tcl level. The exception should be caught before it +// propagates through the Tcl interpreter, or the latter will end up +// in an inconsistent state. + +class CdlParseException : public CdlStringException { + friend class CdlTest; + public: + CdlParseException(std::string message_arg) : + CdlStringException(message_arg) { + } + CdlParseException(const CdlParseException& original) : + CdlStringException(original) { + } + CdlParseException& operator=(const CdlParseException& original) { + (void) CdlStringException::operator=(original); + return *this; + } +}; + +// Evaluating an expression may fail for a variety of reasons, e.g. because +// some referenced entity has not been loaded into the configuration. +// This exception can be thrown in such cases. + +class CdlEvalException : public CdlStringException { + friend class CdlTest; + public: + CdlEvalException(std::string message_arg) : + CdlStringException(message_arg) { + } + CdlEvalException(const CdlEvalException& original) : + CdlStringException(original) { + } + CdlEvalException& operator=(const CdlEvalException& original) { + (void) CdlStringException::operator=(original); + return *this; + } +}; + +//}}} +//{{{ Forward declarations of the body classes + +// ---------------------------------------------------------------------------- +// This section provides forward declarations of the main classes in +// the core of the library. Each variant of CDL will define additional +// classes, e.g. cdl_option, but these will usually be derived from +// the core ones. + +// There are three types of expression in CDL: +// 1) ordinary expressions evaluate to a single value. The most common +// use is for the legal_values property. +// 2) list expressions evaluate to a range of values, e.g. 1 to 10, +// and the most common use is for the legal_values property. +// 3) goal expressions evaluate to either true or false and are used +// for e.g. requires and active_if properties. +class CdlExpressionBody; +class CdlListExpressionBody; +class CdlGoalExpressionBody; + +// There are also objects for simple values, values and list values. +// These are expanded classes, there are no associated pointer +// types. It is quite likely that values need to be copied around +// on the stack. +class CdlSimpleValue; +class CdlValue; +class CdlListValue; + +// Properties. The base class is CdlProperty, and there are a number +// of derived classes provided as standard. Additional derived classes +// may be added in future. +class CdlPropertyBody; +class CdlProperty_MinimalBody; +class CdlProperty_StringBody; +class CdlProperty_TclCodeBody; +class CdlProperty_ReferenceBody; +class CdlProperty_StringVectorBody; +class CdlProperty_ExpressionBody; +class CdlProperty_ListExpressionBody; +class CdlProperty_GoalExpressionBody; + +// Base classes. CDL entities such as options and components derive +// from one or more of these, using virtual inheritance. +// +// The lowest-level class is CdlNodeBody. +// +// 1) a node usually lives in a hierarchy, below a toplevel +// and with a container object as the parent. However nodes +// can live outside a container on a temporary basis, +// and toplevel objects have no parent. +// +// 2) a node has a name that is unique within the hierarchy. +// +// 3) a node has a vector of properties. Actually some entities +// will have an empty vector, e.g. the orphans container +// that is internal to the library. However it is too +// inconvenient to have separate base classes for these. +// +// 4) nodes can be referred to by properties in other nodes. +class CdlNodeBody; + +// A container is a node that can contain other nodes. +class CdlContainerBody; + +// A loadable object is a container whose data has come out of a CDL +// script of some sort. It also stores details about all entities that +// were loaded via this script (even if some of them were reparented) +// thus supporting unload operations. +class CdlLoadableBody; + +// A toplevel object is a container that acts as the toplevel of +// a hierarchy, in other words its parent is always 0. In addition +// a toplevel keeps track of all the names used in the hierarchy, +// thus facilitating navigation. +class CdlToplevelBody; + +// The remaining classes all add functionality to CdlNode, directly or +// indirectly. +// +// A user-visible object is likely to appear in the user interface. +// This means it may have an alias string, a description, a +// documentation URL, and a gui_hint field. +class CdlUserVisibleBody; + +// A valuable object has a value that can be retrieved but not +// necessarily modified by the user. For example the value of an +// interface is always calculated and users can never change it. +// Valuable objects have a whole bunch of associated properties +// including dependencies. +class CdlValuableBody; + +// A parentable object has the parent property, i.e. it can +// be reparented to anywhere in the hierarchy +class CdlParentableBody; + +// A buildable object is a valuable object that may result in +// something being built, typically a library in the case of +// software packages. +class CdlBuildableBody; + +// A loadable that contains buildables +class CdlBuildLoadableBody; + +// A definable object is a valuable object whose value can result +// in #define statements in a header file +class CdlDefinableBody; + +// A loadable which can contain definables +class CdlDefineLoadableBody; + +// TODO: add instantiation support + +// Custom dialogs and wizards are provided by the core. +class CdlDialogBody; +class CdlWizardBody; +class CdlInterfaceBody; + +// Support for Tcl interpreters is also in the core, since it is +// difficult to do anything CDL-related without at least one Tcl +// interpreter lying around. +class CdlInterpreterBody; + +// The basic conflict class is part of the core library, as are a +// number of common derived classes for specific types of conflict. +class CdlConflictBody; +class CdlConflict_UnresolvedBody; +class CdlConflict_IllegalValueBody; +class CdlConflict_EvalExceptionBody; +class CdlConflict_RequiresBody; +class CdlConflict_DataBody; + +// Many operations happen (or may happen) in the context of a +// transaction. This is necessary to keep track of the various +// changes that can happen: for example, changing a component's +// value may require other entities' default values to be +// recalculated; it may change some legal_values list expressions, +// causing current values to become invalid; it may affect +// "requires" properties, causing goals to become satisfied or +// not-satisfied; it may change the "active" state of everything +// below the component, not to mention any entity with an +// "active_if" properties, and when an entity becomes active or +// inactive that may in turn affect other entities. +// +// Keeping track of all of this via recursion is possible, but there +// are problems. If an entity is updated multiple times, no +// optimizations are possible. It becomes much more difficult to +// detect cycles. During an unload operation things can get very +// messy. There is no easy way to track all of the changes and report +// them to higher level code via a callback. There is no support +// for any kind of rollback. A transaction model potentially +// provides support for all of this, at the cost of a more +// complex API. +class CdlTransactionBody; + +// This class is used to pass information back to the application +// about what has actually changed in a transaction. +class CdlTransactionCallback; + + +// Build info class. This is always an expanded object, but is +// needed here to break a circular dependency. +class CdlBuildInfo; + +// ---------------------------------------------------------------------------- +// Typedefs for the pointers. There are separate typedefs to cope with +// const vs. non-const objects. Otherwise you end up with the problem +// that "const CdlNode x" means that the pointer is const, not the +// object pointed at. + +typedef CdlExpressionBody* CdlExpression; +typedef CdlListExpressionBody* CdlListExpression; +typedef CdlGoalExpressionBody* CdlGoalExpression; + +typedef CdlPropertyBody* CdlProperty; +typedef CdlProperty_MinimalBody* CdlProperty_Minimal; +typedef CdlProperty_StringBody* CdlProperty_String; +typedef CdlProperty_TclCodeBody* CdlProperty_TclCode; +typedef CdlProperty_ReferenceBody* CdlProperty_Reference; +typedef CdlProperty_StringVectorBody* CdlProperty_StringVector; +typedef CdlProperty_ExpressionBody* CdlProperty_Expression; +typedef CdlProperty_ListExpressionBody* CdlProperty_ListExpression; +typedef CdlProperty_GoalExpressionBody* CdlProperty_GoalExpression; + +typedef CdlNodeBody* CdlNode; +typedef CdlContainerBody* CdlContainer; +typedef CdlLoadableBody* CdlLoadable; +typedef CdlToplevelBody* CdlToplevel; +typedef CdlUserVisibleBody* CdlUserVisible; +typedef CdlValuableBody* CdlValuable; +typedef CdlParentableBody* CdlParentable; +typedef CdlBuildableBody* CdlBuildable; +typedef CdlBuildLoadableBody* CdlBuildLoadable; +typedef CdlDefinableBody* CdlDefinable; +typedef CdlDefineLoadableBody* CdlDefineLoadable; + +typedef CdlDialogBody* CdlDialog; +typedef CdlWizardBody* CdlWizard; +typedef CdlInterfaceBody* CdlInterface; + +typedef CdlInterpreterBody* CdlInterpreter; + +typedef CdlConflictBody* CdlConflict; +typedef CdlConflict_UnresolvedBody* CdlConflict_Unresolved; +typedef CdlConflict_IllegalValueBody* CdlConflict_IllegalValue; +typedef CdlConflict_EvalExceptionBody* CdlConflict_EvalException; +typedef CdlConflict_RequiresBody* CdlConflict_Requires; +typedef CdlConflict_DataBody* CdlConflict_Data; + +typedef CdlTransactionBody* CdlTransaction; + +// ---------------------------------------------------------------------------- + +typedef const CdlExpressionBody* CdlConstExpression; +typedef const CdlListExpressionBody* CdlConstListExpression; +typedef const CdlGoalExpressionBody* CdlConstGoalExpression; + +typedef const CdlPropertyBody* CdlConstProperty; +typedef const CdlProperty_MinimalBody* CdlConstProperty_Minimal; +typedef const CdlProperty_StringBody* CdlConstProperty_String; +typedef const CdlProperty_TclCodeBody* CdlConstProperty_TclCode; +typedef const CdlProperty_ReferenceBody* CdlConstProperty_Reference; +typedef const CdlProperty_StringVectorBody* CdlConstProperty_StringVector; +typedef const CdlProperty_ExpressionBody* CdlConstProperty_Expression; +typedef const CdlProperty_ListExpressionBody* CdlConstProperty_ListExpression; +typedef const CdlProperty_GoalExpressionBody* CdlConstProperty_GoalExpression; + +typedef const CdlNodeBody* CdlConstNode; +typedef const CdlContainerBody* CdlConstContainer; +typedef const CdlLoadableBody* CdlConstLoadable; +typedef const CdlToplevelBody* CdlConstToplevel; +typedef const CdlUserVisibleBody* CdlConstUserVisible; +typedef const CdlValuableBody* CdlConstValuable; +typedef const CdlParentableBody* CdlConstParentable; +typedef const CdlBuildableBody* CdlConstBuildable; +typedef const CdlBuildLoadableBody* CdlConstBuildLoadable; +typedef const CdlDefinableBody* CdlConstDefinable; +typedef const CdlDefineLoadableBody* CdlConstDefineLoadable; + +typedef const CdlDialogBody* CdlConstDialog; +typedef const CdlWizardBody* CdlConstWizard; +typedef const CdlInterfaceBody* CdlConstInterface; + +typedef const CdlInterpreterBody* CdlConstInterpreter; + +typedef const CdlConflictBody* CdlConstConflict; +typedef const CdlConflict_UnresolvedBody* CdlConstConflict_Unresolved; +typedef const CdlConflict_IllegalValueBody* CdlConstConflict_IllegalValue; +typedef const CdlConflict_EvalExceptionBody* CdlConstConflict_EvalException; +typedef const CdlConflict_RequiresBody* CdlConstConflict_Requires; +typedef const CdlConflict_DataBody* CdlConstConflict_Data; + +typedef const CdlTransactionBody* CdlConstTransaction; + +//}}} +//{{{ Miscellaneous types etc. + +// ---------------------------------------------------------------------------- +// This section is used for data types, function prototypes, etc. which could +// not be defined until after the main CDL classes and handles. + +// This typedef is used for error and warning reporting functions. +// Typically such a function pointer will be passed when the library +// is asked to perform any non-trivial parsing operation, e.g. loading +// a package. +// +// If the error is fatal then this callback function should raise +// a CdlParseException. +typedef void (*CdlDiagnosticFnPtr)(std::string); + +// ---------------------------------------------------------------------------- +// This function is used for update handler. Whenever there is a change +// to CDL entity (it has just been loaded, or its value has changed, or +// whatever) this can affect other CDL entities that reference it. +// All such references occur via properties, and there should be +// update handlers associated with those properties. +// +// Update handlers are also invoked for initialization and finalization +// operations, i.e. when the source object itself has just been loaded +// or is in the process of being unloaded. +// +// The arguments to an update handler are: +// 1) the transaction in which the operation takes place +// 2) the source object containing the reference +// 3) the source property containing the reference +// 4) the destination object. This may be 0 for some update +// operations. +// 5) an indication of the change that has happened. This should +// be a CdlUpdate value. +typedef void (*CdlUpdateHandler)(CdlTransaction, CdlNode, CdlProperty, CdlNode, CdlUpdate); + +// ---------------------------------------------------------------------------- +// This function is also used for transactions. Typically during a +// transaction there will be one or more invocations of the inference engine, +// with callbacks in between to allow one or more of the recommended +// changes to be undone. +typedef CdlInferenceCallbackResult (*CdlInferenceCallback)(CdlTransaction); + +// ---------------------------------------------------------------------------- +// The TCL API and C++ do not always mesh cleanly, for example a lot +// happens in terms of ClientData which is a void* pointer. To avoid +// too many casts all over the place libcdl provides a CdlInterpreter +// class and the following alternative to Tcl_CmdProc*. A single +// function will be used for the TCL command: its ClientData will be +// the CdlInterpreterCommand, and the CdlInterpreter is accessible via +// AssocData. This does result in some overheads, but none of these +// should be in performance-critical code. +typedef int (*CdlInterpreterCommand)(CdlInterpreter, int, char*[]); + +// ---------------------------------------------------------------------------- +// In the libcdl world it is often convenient to swap whole sets of +// commands in and out. For example when executing the body of a +// cdl_component it is desirable to swap in commands for all the +// properties that make sense in a component and swap out all the +// commands that made sense in a higher level. It is assumed that none +// of the commands being swapped in or out are built-ins. Achieving +// this involves a vector of this simple utility structure. +class CdlInterpreterCommandEntry { + public: + std::string name; + CdlInterpreterCommand command; + + CdlInterpreterCommandEntry() : name(""), command(0) {} + CdlInterpreterCommandEntry(const char *name_arg, CdlInterpreterCommand command_arg) + : name(name_arg), command(command_arg) + { + } + CdlInterpreterCommandEntry(std::string name_arg, CdlInterpreterCommand command_arg) + : name(name_arg), command(command_arg) + { + } + ~CdlInterpreterCommandEntry() + { + name = ""; + command = 0; + } +}; + +// ---------------------------------------------------------------------------- +// Persistence support. +// Some applications want to be able to store additional information +// in savefiles, and essentially this involves extra commands that +// get executed when the savefile is executed. It is possible that +// the application reading back the savefile does not understand +// the same set of commands as the application that wrote back the +// data, so the library tries hard not to lose data. +// +// The CdlSaveCallback function typedef is used when installing +// an application-specific savefile command. The first argument +// indicates the node for which the callback is being invoked: +// this may be the entire toplevel, or just an option, or whatever. +// +// The CdlSavefileCommand structure keeps track of the command, +// the save callback if any (non-zero only for application-specific +// data, zero implies that the command is handled by the lirary). +// The load command is invoked when reading in a savefile and the +// appropriate command is executed: unrecognised commands will be +// processed by CdlToplevelBody::savefile_handle_unknown(). + +typedef void (*CdlSaveCallback)(CdlNode, CdlInterpreter, Tcl_Channel, int); + +struct CdlSavefileCommand { + std::string name; + CdlSaveCallback save_callback; + CdlInterpreterCommand load_command; +}; + +// ---------------------------------------------------------------------------- +// Widget hint. +// This structure provides widget hint information for a CdlValuable. +// There are separate hints for the bool and data parts, and possibly +// some additional data such as a string identifying the set of +// items in a radio button. +struct CdlWidgetHint { + CdlBoolWidget bool_widget; + CdlValueWidget value_widget; + std::string radio_button_interface; +}; + +//}}} +//{{{ Memory leak detection + +// ---------------------------------------------------------------------------- +// Provide some macros that are useful for detecting memory leaks. Basically +// there is a static counter for every class, which gets incremented by the +// constructor(s) and decremented by the destructor. Memory leak detection +// is currently enabled if tracing is enabled. It would be possible to use +// another configure-time option, but the overheads of tracing are likely +// to dwarf the overheads of memory leak detection. +// +// For now the memleak counters are always present, even in non-debug +// versions. The overhead is sufficiently small that it can be +// ignored.There is control over whether or not the counters get +// updated in the constructor or destructor. Otherwise there would be problems +// with whether or not there should be a semicolon at the end of the +// CYGDBG_DECLARE_MEMLEAK_COUNTER() macro definition. + +#define CYGDBG_DECLARE_MEMLEAK_COUNTER() static int memleak_counter +#define CYGDBG_DEFINE_MEMLEAK_COUNTER(class) int class::memleak_counter = 0 +#define CYGDBG_GET_MEMLEAK_COUNTER(class) class::memleak_counter + +#ifdef CYGDBG_USE_TRACING + +#define CYGDBG_MEMLEAK_CONSTRUCTOR() this->memleak_counter++; +#define CYGDBG_MEMLEAK_DESTRUCTOR() this->memleak_counter--; +#define CYGDBG_MEMLEAK_CHECKTHIS() if (this->memleak_counter < 0) { return false; } + +#else + +#define CYGDBG_MEMLEAK_CONSTRUCTOR() +#define CYGDBG_MEMLEAK_DESTRUCTOR() +#define CYGDBG_MEMLEAK_CHECKTHIS() + +#endif + +//}}} + +//{{{ Cdl class + +// --------------------------------------------------------------------------- +// The sole purpose of this class is to provide some utility functions with +// reasonable namespace protection, without requiring that the compiler +// implements namespaces. + +class Cdl { + + public: + + static bool is_valid_value_flavor(CdlValueFlavor); + static bool is_valid_value_source(CdlValueSource); + + static bool is_valid_cdl_name(const std::string&); + static bool is_valid_c_preprocessor_symbol(const std::string&); + + static bool string_to_integer(std::string, cdl_int&); + static bool string_to_double(std::string, double&); + static bool string_to_bool(std::string, bool&); + static void integer_to_string(cdl_int, std::string&, CdlValueFormat = CdlValueFormat_Default); + static std::string integer_to_string(cdl_int, CdlValueFormat = CdlValueFormat_Default); + static void double_to_string(double, std::string&, CdlValueFormat = CdlValueFormat_Default); + static std::string double_to_string(double, CdlValueFormat = CdlValueFormat_Default); + static void bool_to_string(bool, std::string&); + static std::string bool_to_string(bool); + static void integer_to_double(cdl_int, double&); + static double integer_to_double(cdl_int); + static bool double_to_integer(double, cdl_int&); + + static bool string_to_flavor(std::string, CdlValueFlavor&); + static bool flavor_to_string(CdlValueFlavor, std::string&); + static bool string_to_source(std::string, CdlValueSource&); + static bool source_to_string(CdlValueSource, std::string&); + + static std::string get_library_version(); + static void set_interactive(bool = true); + static bool is_interactive(); + + static bool truth() { return true; } + static bool falsehood() { return false; } + + // return values are -1,0,1 just like strcmp(). The most recent + // version is the smallest. + static int compare_versions(std::string, std::string); + + // Also provide an STL-friendly comparison class + class version_cmp { + public: + bool operator()(const std::string& v1, const std::string& v2) const { + return Cdl::compare_versions(v1,v2) < 0; + } + }; + + // It is occasionally useful to take a full CDL name such as CYGPKG_KERNEL + // and turn it into a short form, i.e. kernel. + static std::string get_short_form(const std::string&); + + private: + static bool interactive; +}; + +//}}} +//{{{ CdlInterpreter class + +// ---------------------------------------------------------------------------- +// libcdl requires access to a Tcl interpreter. For now the standard +// interpreter is used. In the long run it may be better to use a +// custom parser in places, if only to improve the diagnostics messages +// that users see. +// +// Consider the case of software CDL (other CDL variants will have +// similar requirements). A Tcl interpreter is needed to read in the +// data for a given package. It will also be needed at various stages +// when the data is being manipulated, e.g. to display a custom dialog +// or to execute e.g. a check_proc or a define_proc. Each package +// should run in its own safe interpreter with limited capabilities: +// file I/O is limited to read-only, but read-write in the build and +// install trees; network I/O is out of the question, at least until +// appropriate security support is added to the CDL language itself. +// However the interpreter should be extended with additional commands +// like cdl_get and cdl_set to access the configuration data. +// +// For security and robustness reasons it is desirable to have +// separate interpreters for the various packages. This leads to the +// concept of a master interpreter for the entire configuration, and a +// group of slave interpreters, one per package. In this model it +// is convenient to have the configuration and package entities +// associated directly with the interpreter. Note that a single +// application may have several configurations loaded in memory, +// so there may be several master interpreters. +// +// Some applications will want to support the graphical side of CDL, +// i.e. custom dialogs and wizards. This means linking in Tk, not to +// mention X11 (or the Windows equivalents), and making some/all of +// the Tk commands available to the safe interpreter. Arguably +// commands like toplevel should always be disabled. Not all clients +// of libcdl will want the overheads of linking with Tk and X, so this +// has to be made optional. +// +// The approach taken is as follows: +// +// 1) there is a class CdlInterpreter which provides access to Tcl +// interpreters. Amongst other things it takes care of converting +// between C and C++ strings. +// +// 2) every toplevel needs its own CdlInterpreter. The application +// code should supply this interpreter itself when the toplevel +// is instantiated, allowing it to decide whether or not Tk should +// be available. +// +// 3) each loadable gets its own safe slave interpreter, derived from +// the toplevel's interpreter. +// NOTE: initially the slave interpreters are not actually safe. It +// is not clear in the long term to what extent per-loadable +// interpreters need to be sandboxes, there are issues such as +// doing the equivalent of autoconf tests. + +class CdlInterpreterBody +{ + friend class CdlTest; + + public: + + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + // This is how a top-level (i.e. per-toplevel) interpreter + // should get created. + static CdlInterpreter make(Tcl_Interp* = 0); + + // Create a slave interpreter for reading in the data in e.g. a + // cdl_package + CdlInterpreter create_slave(CdlLoadable, bool /* safe */ = true); + + // Make the interpreter safe, a one-way operation. + void make_safe(); + + // The destructor is public. + virtual ~CdlInterpreterBody(); + + // Add or remove commands from an interpreter. This provides + // a more C++-friendly implementation of Tcl's + // CreateCommand() and DeleteCommand(). + void add_command(std::string, CdlInterpreterCommand); + void remove_command(std::string); + + // In the libcdl world it is also convenient to swap whole sets of + // commands in and out. This is achieved by push and pop operations. + // push returns the old set (0 at the toplevel). pop restores + // the old set. + std::vector* push_commands(std::vector&); + void pop_commands(std::vector*); + std::vector* get_pushed_commands() const; + + // Similarly, allow variables to be set, unset and queried + void set_variable(std::string, std::string); + void unset_variable(std::string); + std::string get_variable(std::string); + + // FIXME: add support for variable traces. These are needed + // for cdl_value and similar utilities. + + // Provide hooks into the AssocData() facilities associated with + // Tcl interpreters. This makes it possible to store arbitrary + // data with an interpreter, e.g. to keep track of current state. + void set_assoc_data(const char*, ClientData, Tcl_InterpDeleteProc* =0); + void delete_assoc_data(const char*); + ClientData get_assoc_data(const char*); + + // Evaluate a string as Tcl code. The return value comes from Tcl, e.g. + // TCL_OK or TCL_ERROR. The result string is also available. + int eval(std::string, std::string&); + + // Ditto for any Tcl code that comes from CDL files + int eval_cdl_code(const cdl_tcl_code, std::string&); + + // And support for evaluating an entire file + int eval_file(std::string, std::string&); + + // For use by commands implemented in C++, a way of setting the result + void set_result(std::string); + + // And a utility to get the result as well. This is useful for e.g. + // Tcl_OpenFileChannel which leaves a result string in the interpreter + std::string get_result(); + + // A utility to quote data that is going to end up in a TCL script. + static std::string quote(std::string); + + // Turn some multiline data into a comment. + static std::string multiline_comment(const std::string&, int, int = 0); + + // Add some data to a comment, allowing for newlines if necessary + static std::string extend_comment(const std::string&, int, int = 0); + + // Write some data to a savefile, throwing an exception on error + void write_data(Tcl_Channel, std::string) throw(CdlInputOutputException); + + // File-related utilities. + void locate_subdirs(std::string, std::vector&); + void locate_all_subdirs(std::string, std::vector&); + void locate_files(std::string, std::vector&); + void locate_all_files(std::string, std::vector&); + bool is_directory(std::string); + bool is_file(std::string); + + // When parsing a CDL script it is convenient to keep track of + // a number of items: + // + // 1) the toplevel, e.g. the entire configuration + // 2) the loadable, e.g. the current package + // 3) the parent of whatever is being processed at the moment + // 4) the entity, i.e. the thingamajig that is being processed. + // 5) the current file + // 6) an error reporting function + // + // This gives the various commands embedded in the Tcl interpreter + // enough information to do their job. Additional information can + // be provided via assoc_data() + // + // There should be only one call to set_toplevel(), for the + // master interpreter. All slaves inherit this, and the toplevel + // cannot be changed again. + // + // The loadable field is filled in via make_slave() + // + // For some members push and pop functions are more appropriate + // than set. + CdlToplevel get_toplevel() const; + CdlLoadable get_loadable() const; + CdlContainer get_container() const; + CdlNode get_node() const; + std::string get_filename() const; + CdlDiagnosticFnPtr get_error_fn_ptr() const; + CdlDiagnosticFnPtr get_warning_fn_ptr() const; + CdlTransaction get_transaction() const; + void set_toplevel(CdlToplevel); + void set_transaction(CdlTransaction); + CdlContainer push_container(CdlContainer); + void pop_container(CdlContainer); + CdlNode push_node(CdlNode); + void pop_node(CdlNode); + std::string push_filename(std::string); + void pop_filename(std::string); + CdlDiagnosticFnPtr push_error_fn_ptr(CdlDiagnosticFnPtr); + void pop_error_fn_ptr(CdlDiagnosticFnPtr); + CdlDiagnosticFnPtr push_warning_fn_ptr(CdlDiagnosticFnPtr); + void pop_warning_fn_ptr(CdlDiagnosticFnPtr); + + // Some command implementations may want to access other Tcl library + // routines such as Tcl_SplitList(). This requires convenient access + // to the underlying Tcl interpreter. + Tcl_Interp* get_tcl_interpreter() const; + + // For use by the assertion macros. + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + + private: + // This is the Tcl command proc that gets registered for all + // CdlInterpreterCommand instances. + static int tcl_command_proc(ClientData, Tcl_Interp*, int, char*[]); + + // This key is used to access the CdlInterpreter assoc data. + static char* cdlinterpreter_assoc_data_key; + + // Do not allow static instances of a Cdl interpreter. There are too + // many possible failure conditions. Cdl interpreters can only be + // created dynamically via make(), which will invoke this. + CdlInterpreterBody(Tcl_Interp*); + + // Default constructor, copy constructor and assignment are illegal + CdlInterpreterBody(); + CdlInterpreterBody(const CdlInterpreterBody&); + CdlInterpreterBody& operator=(const CdlInterpreterBody&); + + + Tcl_Interp* tcl_interp; // The underlying Tcl interpreter + bool owns_interp; // Was the Tcl interpreter created by the library? + std::vector slaves; // All slave interpreters + CdlInterpreter parent; // Or else the parent + CdlToplevel toplevel; // Data that gets used during the parsing process + CdlTransaction transaction; + CdlLoadable loadable; + CdlContainer container; + CdlNode node; + std::string filename; + CdlDiagnosticFnPtr error_fn_ptr; + CdlDiagnosticFnPtr warning_fn_ptr; + + std::vector* current_commands; // for push() and pop() + + enum { + CdlInterpreterBody_Invalid = 0, + CdlInterpreterBody_Magic = 0x0be67689 + } cdlinterpreterbody_cookie; +}; + +//}}} +//{{{ CdlReference/Referrer classes + +// --------------------------------------------------------------------------- +// CDL objects are organised primarily in a tree hierarchy. For +// example a package contains components, components contain options, +// and so on. The tree hierarchy tends to change rather infrequently, +// so it makes sense to have a quick way of navigating between +// entities without continuously having to do hash-table lookups. In +// addition it is very desirable to make the connectivity +// bidirectional: if a "requires" property in option A references +// option B then it would be useful to have a link back to A from B; +// that way, if the value of B changes it is a lot easier to keep +// things up to date. +// +// Terminology: the entity which contains the reference, e.g. a +// "requires" property, is the source. The relevant property is the +// "source property". The entity pointed at is the destination. +// +// Unfortunately there may be connections between CDL entities outside +// the tree hierarchy. In particular any property can contain one or +// more references to packages, components, options, wizards, or +// whatever. Often these references will be to options etc. within the +// same package, but some references will go to other packages. There +// may even be references to other configurations: for example a board +// may contain both an ordinary processor and a DSP; these two need +// their own configurations; however a package running on the DSP may +// need to interact with a package running on the processor, and vice +// versa. +// +// Also, a reference may occur inside an object that is not in the +// hierarchy. For example CDL expressions may get evaluated inside Tcl +// code rather than as part of a property. Such expressions may still +// contain references to entities in the current configuration. +// +// References may not be resolved. When reading in a CDL script there +// may be forward references. A reference may involve another package +// that has not yet been loaded, which is a conflict. +// +// Using simple pointers to store these connections is a bad idea. It +// makes it a lot harder to figure out what is connected to what, and +// it introduces horrible consistency problems when packages get +// loaded and unloaded. Instead libCDL provides a CdlReference class. +// Whenever a CdlProperty contains a reference to some other CDL +// entity there should be a CdlReference object corresponding to this. +// The reverse direction is handled via a CdlReferrer object. +// +// A CdlReference object can be either bound or unbound. By default it +// is unbound, containing only a string. It can then be bound via a +// member function, examined, and unbound again as required. Creating +// a binding automatically creates a CdlReferrer entry in the target +// object, thus avoiding any risk of inconsistencies. +// +// The CdlReference class should not be used outside the hierarchy, +// since every bound reference must have a referrer object pointing +// back, and this link back can only be valid within the hierarchy. +// Temporary CdlReference objects are useful during the construction +// of properties. +// +// It is possible that a given property (e.g. a complicated "requires" +// expression) has multiple references to another entity. Each of +// these involves a separate CdlReference/CdlReferrer pair. + +// ---------------------------------------------------------------------------- +// The actual CdlReference class. + +class CdlReference { + + friend class CdlTest; + + // CdlReferrer must be a friend so that when a package gets unloaded + // it can clean up all references to it. + friend class CdlReferrer; + + public: + + // The default constructor should not normally be used, instead + // a string should be supplied. However there are vectors of + // reference objects... + CdlReference(); + + // The main constructor supplies the name of the referenced + // entity. The resulting object will be unbound. + CdlReference(const std::string); + + // The copy constructor is legal for unbound objects only. + CdlReference(const CdlReference&); + + // The assignment operator is needed for STL operations. + // Again it only makes sense of unbound objects. + CdlReference& operator=(const CdlReference&); + + // The destructor is only valid for unbound objects. All references + // should be unbound before an entity can be destroyed. + ~CdlReference(); + + // Access the various fields. + void set_destination_name(const std::string); + const std::string& get_destination_name() const; + CdlNode get_destination() const; + + // Binding a reference. Obviously this can only be used when the + // reference is still unbound. When doing the binding it is + // necessary to know: + // (1) the object containing the reference. + // (2) the specific property that contains the reference. + // (3) the object being referred to. + // Binding a reference results in a new referrer entry in the + // destination. + void bind(CdlNode, CdlProperty, CdlNode); + + // Unbinding a reference. Typically this only happens when the + // destination is unloaded. The arguments provide the source and + // the source property. + void unbind(CdlNode, CdlProperty); + + // This is used by the ASSERT_CLASS() and ASSERT_THIS() macros. + bool check_this(cyg_assert_class_zeal cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + + private: + + // The data fields. The name is usually filled in by the + // constructor. The destination defaults to zero for an unbound + // object and gets filled in by the bind() operation. + std::string dest_name; + CdlNode dest; + + enum { + CdlReference_Invalid = 0, + CdlReference_Magic = 0x3f908608 + } cdlreference_cookie; +}; + +// ---------------------------------------------------------------------------- +// The CdlNode class (and hence just about everything) contains a +// vector of CdlReferrer objects. This keeps track of all entities +// that refer to this one, so if the value associated with this +// changes it is possible to work out the impact of this on all +// entities that rely on this value. +// +// Arguably this should work in terms of CdlValuable objects rather +// than CdlNode objects. However it is convenient to use references +// for the connection between e.g. an option and a dialog, where +// there is no value involved. The reverse connection is of little +// use in this circumstance. +// +// CdlReferrer objects are rarely accessed directly. Instead they will +// be filled in during a CdlReference::bind() operation and erased +// during a CdlReference::unbind() operation. The only operations that +// should be public allow access to the contained data. + +class CdlReferrer { + + friend class CdlTest; + + // CdlReference::bind() and unbind() have direct access to the + // members, since these two functions are really responsible for + // creating and destroying referrer objects. + friend class CdlReference; + + public: + + // The default constructor, copy constructor and assignment + // operator are all public to avoid problems with having vectors + // of referrer objects. Similarly the destructor is public. + // In practice updates actually happen as a consequence of + // CdlReference::bind() and CdlReference::unbind(). + CdlReferrer(); + CdlReferrer(const CdlReferrer&); + CdlReferrer& operator=(const CdlReferrer&); + ~CdlReferrer(); + + CdlNode get_source() const; + CdlProperty get_source_property() const; + void update(CdlTransaction, CdlNode, CdlUpdate); + bool check_this(cyg_assert_class_zeal=cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + private: + + CdlNode source; + CdlProperty source_property; + + enum { + CdlReferrer_Invalid = 0, + CdlReferrer_Magic = 0x70e1fc37 + } cdlreferrer_cookie; +}; + +//}}} +//{{{ Value and Expression classes + +//{{{ CdlEvalContext + +// ---------------------------------------------------------------------------- +// Expression evaluation always happens within a certain context. +// This may involve a transaction. Usually it involves a node and +// a property within that node, although it is possible to evaluate +// expressions from inside Tcl code. +// +// To avoid passing too many arguments around the various +// evaluation-related routines, a utility class is provided. + +class CdlEvalContext { + + friend class CdlTest; + + public: + + CdlTransaction transaction; + CdlNode node; + CdlProperty property; + CdlToplevel toplevel; + + CdlEvalContext(CdlTransaction, CdlNode, CdlProperty, CdlToplevel = 0); + ~CdlEvalContext(); + + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + + private: + // Illegal operation, the three fields must always be supplied, + // although they may be zero. + CdlEvalContext(); + + enum { + CdlEvalContext_Invalid = 0, + CdlEvalContext_Magic = 0x03434be9 + } cdlevalcontext_cookie; + +}; + +//}}} +//{{{ CdlSimpleValue + +// ---------------------------------------------------------------------------- +// Expression evaluation happens in terms of CdlSimpleValue objects. +// In CDL all values are strings, but for the purposes of arithmetic +// these strings sometimes have to be interpreted as integers or as +// double precision numbers. Sometimes there is a choice, for example +// the equality operator == can mean numerical or string comparison. +// The basic rules that get applied are: +// +// 1) if the current value has an integer representation then +// use this by preference. This means that an expression +// of the form (CYGNUM_XXX != 0x100) will do a integer +// comparison if possible. +// +// 2) otherwise if the current value can be interpreted as a +// double precision number, use that representation. +// All integers can be interpreted as doubles (at the risk +// of some loss of precision), so the representation as +// a double should only be used if the integer representation +// is inappropriate. +// +// 3) otherwise interpret the value as a string. +// +// The default value is 0. + +class CdlSimpleValue { + + friend class CdlTest; + + public: + + CdlSimpleValue(); + CdlSimpleValue(std::string); + CdlSimpleValue(cdl_int); + CdlSimpleValue(double); + CdlSimpleValue(const CdlSimpleValue&); + CdlSimpleValue(bool); + ~CdlSimpleValue(); + + CdlSimpleValue& operator=(const CdlSimpleValue&); + CdlSimpleValue& operator=(std::string); + CdlSimpleValue& operator=(cdl_int); + CdlSimpleValue& operator=(double); + + CdlSimpleValue& operator=(bool); + + bool operator==(const CdlSimpleValue&) const; + bool operator!=(const CdlSimpleValue&) const; + bool operator==(std::string arg) const + { + CdlSimpleValue val(arg); + return *this == val; + } + bool operator==(cdl_int arg) const + { + CdlSimpleValue val(arg); + return *this == val; + } + bool operator==(double arg) const + { + CdlSimpleValue val(arg); + return *this == val; + } + bool operator!=(std::string arg) const + { + CdlSimpleValue val(arg); + return *this != val; + } + bool operator!=(cdl_int arg) const + { + CdlSimpleValue val(arg); + return *this != val; + } + bool operator!=(double arg) const + { + CdlSimpleValue val(arg); + return *this != val; + } + + void set_value(std::string, CdlValueFormat = CdlValueFormat_Default); + std::string get_value() const; + + bool has_integer_value() const; + void set_integer_value(cdl_int, CdlValueFormat = CdlValueFormat_Default); + cdl_int get_integer_value() const; + + bool has_double_value() const; + void set_double_value(double, CdlValueFormat = CdlValueFormat_Default); + double get_double_value() const; + + CdlValueFormat get_value_format() const; + void set_value_format(CdlValueFormat); + void set_value_format(CdlSimpleValue&); + void set_value_format(CdlSimpleValue&, CdlSimpleValue&); + + static void eval_valuable(CdlEvalContext&, CdlValuable, CdlSimpleValue&); + + // For expression evaluation, it is often convenient to get hold + // of a boolean as well. This may indicate a non-empty string + // or a non-zero value. + bool get_bool_value() const; + + // This class is too simple to warrant even a cookie validation. + bool check_this(cyg_assert_class_zeal zeal = cyg_quick) const { + return true; + } + + protected: + + private: + enum { + int_valid = 0x01, + double_valid = 0x02, + string_valid = 0x04, + int_invalid = 0x08, + double_invalid = 0x10 + }; + mutable int valid_flags; + mutable std::string value; + mutable cdl_int int_value; + mutable double double_value; + CdlValueFormat format; +}; + +//}}} +//{{{ CdlListValue + +// ---------------------------------------------------------------------------- +// Evaluating a list expression results in a set of possible values, but +// unlike the original list expression these values are now constant and +// can have no dependencies on CDL entities. As with list expressions the +// main operation on a list value is to detect membership, but using +// list values allows multiple potential members to be tested without +// repeated expression evaluation. The main use of list values is implicit +// in libcdl, each list expression contains a mutable cached list value. +// +// A list value contains five sets of data: +// +// 1) separate vectors of strings, integers, and floating point constants. +// Having separate vectors of integers and floating points avoids +// problems when numbers can be represented in different formats. +// 2) a vector of cdl_int pairs for ranges of integer data +// 3) a vector of double pairs for ranges of floating point data +// +// Any of these vectors may be empty, but at least one of the vectors should +// contain useful data. Possibly there should also be tables for cdl_int and +// double to avoid unnecessary string conversions. + +class CdlListValue { + + friend class CdlTest; + + // A list value will only be filled in when a list expression is evaluated. + // The members cannot be updated by other means. + friend class CdlListExpressionBody; + + public: + + CdlListValue(); + ~CdlListValue(); + CdlListValue(const CdlListValue&); + CdlListValue& operator=(const CdlListValue&); + + bool is_member(CdlSimpleValue&) const; + bool is_member(std::string, bool = true) const; + bool is_member(cdl_int, bool = true) const; + bool is_member(double, bool = true) const; + + // These provide access to the raw data, for example if it is + // necessary to suggest a legal value to the user. + const std::vector& get_table() const; + const std::vector >& get_integer_ranges() const; + const std::vector >& get_double_ranges() const; + + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + private: + std::vector table; + std::vector > integer_ranges; + std::vector > double_ranges; + + enum { + CdlListValue_Invalid = 0, + CdlListValue_Magic = 0x2183a943 + } cdllistvalue_cookie; +}; + +//}}} +//{{{ CdlValue + +// ---------------------------------------------------------------------------- +// Values in CDL are non-trivial compared with some other languages. +// Even though CDL is not a fully-typed language, it does still have +// four different flavors to consider. There is also the problem that +// an entity may have up to four different values which should be +// stored (default, inferred, wizard, user), with the ability to +// switch between them. The CdlValue class provides support for this. +// +// CdlValue objects are not normally updated explicitly. Instead +// higher level code deals with CdlValuable objects, which inherit +// privately from CdlValue. Modifications to CdlValuables happen in +// the context of a transaction. +// +// The first concept to take into account is the flavor. There +// are four flavors, None, Bool, BoolData and Data. The member +// function get_flavor() can be used to obtain the current flavor. +// +// CdlValueFlavor CdlValue::get_flavor() const; +// +// Values may be enabled or disabled. Values of flavor None +// and Data are always enabled. Values of flavor Bool or BoolData +// may or may not be enabled, by default they are disabled. +// +// bool CdlValue::is_enabled(...) const; +// +// (The optional argument to is_enabled() is discussed later). +// +// Values of flavor BoolData and Data also have a string value, +// which can be interpreted as an integer or a double under +// the right circumstances. +// +// std::string CdlValue::get_value(...) const; +// bool CdlValue::has_integer_value(...) const; +// bool CdlValue::has_double_value(...) const; +// cdl_int CdlValue::get_integer_value(...) const; +// double CdlValue::get_double_value(...) const; +// +// This is equivalent to a CdlSimpleValue object, and in fact +// that is the internal representation. It is possible to +// get hold of the CdlSimpleValue object directly: +// +// CdlSimpleValue CdlValue::get_simple_value(...) const; +// +// The get_integer_value() and get_double_value() members should +// only be used if you are confident that the current value has +// an integer or double representation. Otherwise the result is +// undefined. +// +// The optional argument to these member functions represents +// the source. A value can be set from four different sources: +// the default value (usually either 0 or the result of +// evaluating a default_value property); an inferred value, +// determined by the inference engine; a wizard value, i.e. +// what a CDL wizard believes the correct value to be based +// on user input; and a user value, something explicitly +// set by the end user. These have different priorities: +// the inference engine can override default values but not +// user values. A CdlValue object keeps track of the current +// source. +// +// CdlValueSource CdlValue::get_source() const; +// +// If no argument is given to e.g. is_enabled() then the +// current source is used. Otherwise it is possible to find +// out whether or not the entity is enabled for each of the +// sources. +// +// The default source is always defined, the others may or +// may not be. It is possible to find out for each source +// whether or not a value has been set. +// +// bool CdlValue::has_source(CdlValueSource) const; +// +// +// Updating values normally happens in the CdlValuable class, +// but the member functions are the same. There is a member +// function to change the flavor: +// +// void CdlValue::set_flavor(CdlValueFlavor); +// +// However this member function is intended only for use by the +// library itself. An entity's flavor is normally defined by CDL data, +// and should not be updated explicitly by application code. +// +// There are two member functions to manipulate the value source: +// +// void CdlValue::set_source(CdlValueSource); +// void CdlValue::invalidate_source(CdlValueSource); +// +// The first function can be used if e.g. the user wants to +// change his or her mind and go back to the default value +// rather than a user value. The user value is not forgotten +// and can be reinstated. +// +// invalidate_source() can be used to completely cancel a +// value source. If that source happens to be the current one +// then the current source will be adjusted appropriately. +// It is illegal to attempt to invalidate the default source. +// +// For values with flavor Bool and BoolData, there are three +// member functions that can be used to control the enabled +// status: +// +// void CdlValue::set_enabled(bool, CdlValueSource); +// void CdlValue::enable(CdlValueSource); +// void CdlValue::disable(CdlValueSource); +// +// Note that when updating a CdlValue object the source should +// be known and must be specified. If the source has a higher +// priority than the current one then it will automatically +// become the new source. On the rare occasion that this is +// not desired, set_source() will have to be used afterwards +// to reset the current source. +// +// For values with flavor BoolData and Data the following +// member functions are available to change the value string: +// +// void CdlValue::set_value(std::string, CdlValueSource); +// void CdlValue::set_value(cdl_int, CdlValueSource); +// void CdlValue::set_value(double, CdlvalueSource); +// void CdlValue::set_value(CdlSimpleValue&, CdlValueSource); +// +// For values with flavor BoolData is is possible to +// combine updating the enabled flag and the string value: +// +// void CdlValue::set_enabled_and_value(bool, std::string, CdlValueSource); +// void CdlValue::set_enabled_and_value(bool, cdl_int, CdlValueSource); +// void CdlValue::set_enabled_and_value(bool, double, CdlValueSource); +// void CdlValue::set_enabled_and_value(bool, CdlSimpleValue&, CdlValueSource); +// void CdlValue::enable_and_set_value(std::string, CdlValueSource); +// void CdlValue::enable_and_set_value(cdl_int, CdlValueSource); +// void CdlValue::enable_and_set_value(double, CdlValueSource); +// void CdlValue::enable_and_set_value(CdlSimpleValue&, CdlValueSource); +// void CdlValue::disable_and_set_value(std::string, CdlValueSource); +// void CdlValue::disable_and_set_value(cdl_int, CdlValueSource); +// void CdlValue::disable_and_set_value(double, CdlValueSource); +// void CdlValue::disable_and_set_value(CdlSimpleValue&, CdlValueSource); +// +// Obviously many of these functions are just simple inlines. +// +// There is one final member function: +// +// void CdlValue::set(CdlSimpleValue, CdlValueSource); +// +// This member function is defined to do the right thing, +// whatever the flavor happens to be. + +class CdlValue { + + friend class CdlTest; + + public: + + CdlValue(CdlValueFlavor = CdlValueFlavor_Bool); + virtual ~CdlValue(); + CdlValue(const CdlValue&); + CdlValue& operator=(const CdlValue&); + + CdlValueFlavor get_flavor() const; + CdlValueSource get_source() const; + bool has_source(CdlValueSource) const; + + bool is_enabled(CdlValueSource = CdlValueSource_Current) const; + std::string get_value(CdlValueSource = CdlValueSource_Current) const; + bool has_integer_value(CdlValueSource = CdlValueSource_Current) const; + bool has_double_value(CdlValueSource = CdlValueSource_Current) const; + cdl_int get_integer_value(CdlValueSource = CdlValueSource_Current) const; + double get_double_value(CdlValueSource = CdlValueSource_Current) const; + CdlSimpleValue get_simple_value(CdlValueSource = CdlValueSource_Current) const; + + void set_source(CdlValueSource); + void invalidate_source(CdlValueSource); + + void set_enabled(bool, CdlValueSource); + void enable(CdlValueSource source) + { + set_enabled(true, source); + } + void disable(CdlValueSource source) + { + set_enabled(false, source); + } + + void set_value(CdlSimpleValue&, CdlValueSource); + void set_value(std::string data, CdlValueSource source) + { + CdlSimpleValue val(data); + set_value(val, source); + } + void set_integer_value(cdl_int data, CdlValueSource source) + { + CdlSimpleValue val(data); + set_value(val, source); + } + void set_double_value(double data, CdlValueSource source) + { + CdlSimpleValue val(data); + set_value(val, source); + } + void set_enabled_and_value(bool, CdlSimpleValue&, CdlValueSource); + void set_enabled_and_value(bool enabled, std::string data, CdlValueSource source) + { + CdlSimpleValue val(data); + set_enabled_and_value(enabled, val, source); + } + void set_enabled_and_value(bool enabled, cdl_int data, CdlValueSource source) + { + CdlSimpleValue val(data); + set_enabled_and_value(enabled, val, source); + } + void set_enabled_and_value(bool enabled, double data, CdlValueSource source) + { + CdlSimpleValue val(data); + set_enabled_and_value(enabled, val, source); + } + void enable_and_set_value(CdlSimpleValue& val, CdlValueSource source) + { + set_enabled_and_value(true, val, source); + } + void enable_and_set_value(std::string data, CdlValueSource source) + { + set_enabled_and_value(true, data, source); + } + void enable_and_set_value(cdl_int data, CdlValueSource source) + { + set_enabled_and_value(true, data, source); + } + void enable_and_set_value(double data, CdlValueSource source) + { + set_enabled_and_value(true, data, source); + } + void disable_and_set_value(CdlSimpleValue& val, CdlValueSource source) + { + set_enabled_and_value(false, val, source); + } + void disable_and_set_value(std::string data, CdlValueSource source) + { + set_enabled_and_value(false, data, source); + } + void disable_and_set_value(cdl_int data, CdlValueSource source) + { + set_enabled_and_value(false, data, source); + } + void disable_and_set_value(double data, CdlValueSource source) + { + set_enabled_and_value(false, data, source); + } + + void set(CdlSimpleValue&, CdlValueSource); + + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + // This should only be used by the library itself. + void set_flavor(CdlValueFlavor); + + protected: + + private: + + CdlValueFlavor flavor; + CdlValueSource current_source; + + // FIXME: a static const member should be used for the array + // sizes, but VC++ does not support that part of the language. + // FIXME: std::bitset should be used here. Using lots of separate + // bools here is inefficient. + bool source_valid[4]; + bool enabled[4]; + CdlSimpleValue values[4]; + + enum { + CdlValue_Invalid = 0, + CdlValue_Magic = 0x41837960 + } cdlvalue_cookie; +}; + +//}}} +//{{{ CdlSubexpression + +// ---------------------------------------------------------------------------- +// Expressions come into existence primarily as the result of reading +// in certain properties like default_value in CDL data. It is also +// possible for expressions to be generated and evaluated on the fly +// inside Tcl code, but that is expected to be a comparatively rare +// events. Expression objects always live on the heap, usually only +// in derived classes. +// +// An ordinary expression evaluates to a single value. There are two +// other types of expression in the CDL language, goal expressions and +// list expression. A goal expression is essentially a set of ordinary +// expressions with implicit &&'s between them. A list expression +// is a set of expressions that can be evaluated to a constant vector, +// plus pairs of expressions that constitute ranges. Again goal and +// list expressions only live on the heap. +// +// Both parsing an evaluation involve tokens for the various +// operators. The inference engine, conflict reporting code, and +// other diagnostic code will also need to have ready access to +// this information. Hence it makes a bit more sense to have +// the enum outside the expression class. + +enum CdlExprOp { + CdlExprOp_Invalid = 0, + CdlExprOp_EOD = 1, // End of data reached + CdlEXprOp_Command = 2, // [tcl code] + CdlExprOp_Variable = 3, // $tcl_variable + CdlExprOp_StringConstant = 4, // "hello" + CdlExprOp_IntegerConstant = 5, // 123 + CdlExprOp_DoubleConstant = 6, // 3.1415 + CdlExprOp_Reference = 7, // CYGPKG_INFRA + CdlExprOp_Range = 8, // x to y + CdlExprOp_Negate = 9, // -x + CdlExprOp_Plus = 10, // +x + CdlExprOp_LogicalNot = 11, // !x + CdlExprOp_BitNot = 12, // ~x + CdlExprOp_Indirect = 13, // *x + CdlExprOp_Active = 14, // ?x + CdlExprOp_Function = 15, // sin(x) + CdlExprOp_Multiply = 16, // x * y + CdlExprOp_Divide = 17, // x / y + CdlExprOp_Remainder = 18, // x % y + CdlExprOp_Add = 19, // x + y + CdlExprOp_Subtract = 20, // x - y + CdlExprOp_LeftShift = 21, // x << y + CdlExprOp_RightShift = 22, // x >> y + CdlExprOp_LessThan = 23, // x < y + CdlExprOp_LessEqual = 24, // x <= y + CdlExprOp_GreaterThan = 25, // x > y + CdlExprOp_GreaterEqual = 26, // x >= y + CdlExprOp_Equal = 27, // x == y + CdlExprOp_NotEqual = 28, // x != y + CdlExprOp_BitAnd = 29, // x & y + CdlExprOp_BitXor = 30, // x ^ y + CdlExprOp_BitOr = 31, // x | y + CdlExprOp_And = 32, // x && y + CdlExprOp_Or = 33, // x || y + CdlExprOp_Cond = 34, // x ? a : b +}; + +// ---------------------------------------------------------------------------- +// A subexpression consists of an operation, possibly some constant +// data, and possibly indices into the subexpression vector. +// Normally some unions would be used, but unions and objects such +// as std::string do not mix, and the amount of memory involved is +// not big enough to really worry about. + +struct CdlSubexpression { + + CdlExprOp op; + CdlSimpleValue constants; // String, integer or double constant + int reference_index; // iff CdlExprOp_Reference + + int lhs_index; // for all non-constant operators + int rhs_index; // for binary and ternary operators only + int rrhs_index; // only for ternary operators. +}; + +//}}} +//{{{ CdlExpression + +// ---------------------------------------------------------------------------- +// And now for the expression class itself. + +class CdlExpressionBody { + + friend class CdlTest; + + public: + + // The default constructor is basically a no-op, new expression + // objects only get created as a consequence of parsing. However + // it exists and is protected for the convenience of derived + // classes. The copy constructor is protected, allowing parsing + // code to first parse an expression and then copy the expression + // into a higher level object. The assignment operator is illegal. + // There is no reason to hide the destructor. + virtual ~CdlExpressionBody(); + + // An expression involves three pieces of data. There is a vector + // of subexpressions. It is also necessary to know where + // evaluation should being, in accordance with operator precedence + // rules. And there is a vector of CdlReference objects - this + // needs to be kept separate from the subexpression vector because + // CdlReference objects are comparatively tricky. + // + // All of this data is public and can be readily inspected by the + // inference engine, by conflict detection code, by diagnostic + // code, etc. + std::vector sub_expressions; + int first_subexpression; + std::vector references; + bool update(CdlTransaction, CdlNode, CdlProperty, CdlNode, CdlUpdate); + + // There are a number of parsing functions. The first one is + // used by higher-level code to parse a single expression. Its + // argument is a single string (which may be the result of + // concatenating several Tcl arguments), and at the end of the + // parse operation there should be no further data. The result + // will either be a new expression object or a parsing exception + // to be caught by higher level code. + static CdlExpression parse(std::string) + throw(CdlParseException,std::bad_alloc); + + // This is used when parsing list expressions, which involve a + // sequence of ordinary expressions and possibly range operators. + // The whole list expression lives in a single string, and it is + // necessary to provide an index indicating where in the string + // parsing should begin. It is also useful to return details of + // the token that caused parsing to terminate (EOD, Range, or + // the start of something else). + static CdlExpression parse(std::string, int&, CdlExprOp&, int&) + throw(CdlParseException, std::bad_alloc); + + // A goal expression is derived from an ordinary expression but + // has somewhat different rules for evaluating. Parsing a goal + // expression involves parsing a number of ordinary expressions + // with implicit && operators between them, and it requires + // a parsing function that can be used to extend an existing + // expression. + // + // NOTE: possibly this should should be a protected member, since + // its main use is in parsing goal expressions. + static void continue_parse(CdlExpression, std::string, int&, CdlExprOp&, int&) + throw(CdlParseException, std::bad_alloc); + + // Evaluating expressions. Note that this may fail at run-time + // because of errors that cannot be caught sensibly when the + // expression is read in, for example arithmetic overflow or + // division by zero. Because such failures are a possibility + // anyway no special action is taken to prevent an expression + // with e.g. an unresolved reference from being evaluated. + // + // eval() is the public interface, and manages + // CdlConflict_EvalException objects. eval_internal() is for use + // by list and goal expressions. + void eval(CdlEvalContext&, CdlSimpleValue&) + throw(CdlEvalException, std::bad_alloc); + void eval_internal(CdlEvalContext&, CdlSimpleValue&) + throw(CdlEvalException, std::bad_alloc); + + // The full original expression is useful for diagnostics purposes + std::string get_original_string() const; + + bool check_this(cyg_assert_class_zeal cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + + // The default constructor does very little, the main work + // is done by the various parsing functions. However it is + // available to derived classes, especially goal expressions. + CdlExpressionBody(); + + // The copy constructor has to be usable by derived classes, + // e.g. CdlExpressionProperty + CdlExpressionBody(const CdlExpressionBody&); + + private: + + + // The assignment operator is illegal. + CdlExpressionBody& operator=(const CdlExpressionBody&); + + // The string that was parsed originally + std::string expression_string; + + enum { + CdlExpressionBody_Invalid = 0, + CdlExpressionBody_Magic = 0x760293a3 + } cdlexpressionbody_cookie; +}; + +//}}} +//{{{ CdlListExpression + +// ---------------------------------------------------------------------------- +// The main use of list expressions is for the legal_values +// properties. Essentially a list expression is just a vector of +// ordinary expressions and ranges of expressions. + +class CdlListExpressionBody { + + friend class CdlTest; + + public: + + // Availability of constructors etc. is as per the ordinary + // expression class. + virtual ~CdlListExpressionBody(); + + // The data associated with a list expression is a vector of + // expressions, plus a vector of expression pairs constituting + // ranges. As with ordinary expressions the data is fully public + // and can be readily examined by e.g. the inference engine. + std::vector data; + std::vector > ranges; + + // Parsing. This involves taking a single string, typically from + // a CDL script, and parsing one or more ordinary expressions. + static CdlListExpression parse(std::string) + throw(CdlParseException, std::bad_alloc); + + // Evaluation support. A list expression evaluates to a list value. + void eval(CdlEvalContext&, CdlListValue&) + throw(CdlEvalException, std::bad_alloc); + + // More commonly client code is going to be interested in whether + // or not a particular value is a legal member. The result + // cache ensures that it is possible to + bool is_member(CdlEvalContext&, CdlSimpleValue&) + throw(CdlEvalException, std::bad_alloc); + bool is_member(CdlEvalContext&, std::string) + throw(CdlEvalException, std::bad_alloc); + bool is_member(CdlEvalContext&, cdl_int) + throw(CdlEvalException, std::bad_alloc); + bool is_member(CdlEvalContext&, double) + throw(CdlEvalException, std::bad_alloc); + + // The full original expression is useful for diagnostics purposes + std::string get_original_string() const; + + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + CdlListExpressionBody(const CdlListExpressionBody&); + bool update(CdlTransaction, CdlNode, CdlProperty, CdlNode, CdlUpdate); + + private: + + CdlListExpressionBody(); + CdlListExpressionBody& operator=(const CdlListExpressionBody&); + + void eval_internal(CdlEvalContext&, CdlListValue&) throw(CdlEvalException, std::bad_alloc); + + std::string expression_string; + + enum { + CdlListExpressionBody_Invalid = 0, + CdlListExpressionBody_Magic = 0x7da4bcc2 + } cdllistexpressionbody_cookie; +}; + +//}}} +//{{{ CdlGoalExpression + +// ---------------------------------------------------------------------------- +// A goal expression inherits privately from ordinary expressions. Essentially +// a goal expression is simply a set of ordinary expressions separated by &&, +// but it can only be evaluated to a boolean. The parse() and eval() members +// of the base class should not be exposed. There is a member to get hold of +// the underlying ordinary expression, for use by e.g. the inference engine. + +class CdlGoalExpressionBody : private CdlExpressionBody { + + friend class CdlTest; + + typedef CdlExpressionBody inherited; + + public: + virtual ~CdlGoalExpressionBody(); + + static CdlGoalExpression parse(std::string) + throw(CdlParseException, std::bad_alloc); + + // A few variants of the eval() member, with a choice of returning + // by value or by reference. The latter provide consistency with the + // other expression classes. + bool eval(CdlEvalContext&) + throw(CdlEvalException, std::bad_alloc); + void eval(CdlEvalContext&, bool&) + throw(CdlEvalException, std::bad_alloc); + + // Provide public access to the underlying expression object, + // useful for the inference engine + CdlExpression get_expression(); + + // The full original expression is useful for diagnostics purposes + std::string get_original_string() const; + + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + CdlGoalExpressionBody(const CdlGoalExpressionBody&); + + + private: + + CdlGoalExpressionBody(); + CdlGoalExpressionBody& operator=(const CdlGoalExpressionBody&); + void eval_internal(CdlEvalContext&, bool&) throw(CdlEvalException, std::bad_alloc); + + std::string expression_string; + + enum { + CdlGoalExpressionBody_Invalid = 0, + CdlGoalExpressionBody_Magic = 0x5a58bb24 + } cdlgoalexpressionbody_cookie; +}; + +//}}} + +//}}} +//{{{ CdlConflict classes + +// ---------------------------------------------------------------------------- +// As a configuration is created and modified there will be times when +// things are not completely consistent. There may be a reference to +// some option that is not in any package in the current +// configuration. An option may have an invalid value, possibly as a +// side effect of a change to some other option. There may be a +// dependency that is not satisfied. There may be other types of +// conflict. +// +// The library provides a base class CdlConflict, and a number of +// derived classes for common types of conflict such as unresolved +// references. All conflicts are associated with a CdlNode and a +// property within that. It is possible to use dynamic_cast<> to find +// out the exact type of a conflict, or alternatively to use the +// virtual member function get_explanation(). +// +// Conflicts may be disabled by the user if they are not actually +// important as far as application code is concerned. In other words +// the end user is allowed to override the constraints specified in +// the CDL. This information is saved with the configuration data. +// Preferably the user should give an explanation for why the conflict +// is disabled, to serve as a reminder some months later when the +// configuration is reloaded. +// +// +// Conflicts have a fairly complicated life cycle. First it is +// necessary to distinguish between structural and normal conflicts. A +// structural conflict is typically caused by a reference to a +// non-existent valuable. These conflicts are generally created only +// when something is loaded, and only go away when something is +// unloaded. A normal conflict is typically related to a value, for +// example a value outside the legal range, or a "requires" property +// that is not satisfied. +// +// Conflicts are created and destroyed in the context of a +// transaction, which in turn operates in the context of a toplevel. +// If the transaction is committed then new conflicts get added to the +// appropriate toplevel list, and destroyed conflicts get removed from +// the toplevel list. The transaction field indicates whether the +// conflict is currently per-transaction or global. +// +// Transactions may get nested, i.e. a conflict may get created as +// part of a sub-transaction, and when that sub-transaction is committed +// the conflict is moved to the parent transaction. +// +// For each toplevel, libcdl keeps track of all conflicts. This only +// applies to committed conflicts, per-transaction conflicts are not +// accessible in this way. +// +// As part of a transaction, libcdl may attempt to find solutions for +// particular conflicts, and those solutions may get installed +// automatically. No attempt is made to keep track of solutions +// on a global basis, only on a per-transaction basis. + +class CdlConflictBody { + + friend class CdlTest; + + // Transactions and conflicts are closely connected + friend class CdlTransactionBody; + + public: + + // Creation happens only inside a derived class. + // Clearing a conflict only happens inside transactions. + // Destroying a conflict only happens from inside a + // per-transaction clear(), or during a transaction commit. + + // Is this conflict part of a transaction, or has it been committed to the toplevel. + CdlTransaction get_transaction() const; + + // Is inference implemented for this type of conflict? + virtual bool resolution_implemented() const; + + // Try to resolve an existing global conflict. A new transaction + // is created for this operation, the conflict is resolved within + // that transaction, and then CdlTransaction::body() is used to + // handle inference callbacks, commits, etc. See also + // CdlToplevel::resolve_conflicts() and + // CdlToplevel::resolve_all_conflicts(). The conflict may cease to + // exist as a side-effect of this call. + void resolve(); + + // Keep track of whether or not this conflict has a solution + // 1) a conflict may have a current solution. This gets invalidated + // whenever there is a change to a value that was referenced + // while identifying the solution. + // + // A current solution is indicated by a non-empty solution vector. + // + // 2) a conflict may not have a current solution. Again this gets + // invalidated whenever a referred value changes. There is a boolean + // to keep track of this. + // + // 3) a conflict may not have a current solution, but another run of + // the inference engine may find one. + bool has_known_solution() const; + bool has_no_solution() const; + const std::vector >& get_solution() const; + const std::set& get_solution_references() const; + void clear_solution(); + + // Provide a text message "explaining" the conflict. + // This only makes sense for derived classes. + virtual std::string get_explanation() const = 0; + + // Basic information access. + CdlNode get_node() const; + CdlProperty get_property() const; + bool is_structural() const; + + // Enabling and disabling conflicts currently happens outside the + // context of any transaction. + // FIXME: these are not currently implemented. It would be necessary + // to store the information in the savefile, which requires an + // unambiguous way of identifying a conflict that is likely to + // survice package version changes. + void disable(std::string); + void enable(); + bool is_enabled() const; + std::string get_disabled_reason() const; + + bool check_this(cyg_assert_class_zeal zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + CdlConflictBody(CdlTransaction, CdlNode, CdlProperty, bool /* structural */); + + // The destructor gets accessed from inside the friend transaction class, + // either during a clear_conflict() or during a transaction commit. + virtual ~CdlConflictBody(); + + // All conflicts are associated with a node and a property. + // This information will be useful to derived classes' + // implementations of get_explanation() + CdlNode node; + CdlProperty property; + + private: + + // Attempt to resolve a conflict in a sub-transaction + // This is invoked from inside the transaction resolve code. + // There are additional exported interfaces inside and outside + // the transaction class. + virtual bool inner_resolve(CdlTransaction, int); + + // Keep track of the transaction in which this conflict was created. + // The field is cleared at the end of a transaction. + CdlTransaction transaction; + + // Usually the derived class will decide whether or not + // this conflict is structural in nature, but the data + // needs to be available at base constructor time so + // a virtual function is not appropriate. + bool structural; + + // Solution support + bool no_solution; + std::vector > solution; + std::set solution_references; + void update_solution_validity(CdlValuable); + + // Users may disable a conflict. Usually they will have to + // supply a reason for this. + bool enabled; + std::string reason; + + enum { + CdlConflictBody_Invalid = 0, + CdlConflictBody_Magic = 0x073e8853 + } cdlconflictbody_cookie; + + // Illegal operations. Conflicts always live on the heap. + CdlConflictBody(); + CdlConflictBody(const CdlConflictBody&); + CdlConflictBody& operator=(const CdlConflictBody&); +}; + +// ---------------------------------------------------------------------------- +// An unresolved conflict means that there is a reference in some +// property to an entity that is not yet in the current configuration. +// The class provides convenient access to the name of the unresolved +// entity. + +class CdlConflict_UnresolvedBody : public CdlConflictBody { + + friend class CdlTest; + public: + + static void make(CdlTransaction, CdlNode, CdlProperty, std::string); + + std::string get_target_name() const; + std::string get_explanation() const; + static bool test(CdlConflict); + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + + private: + virtual ~CdlConflict_UnresolvedBody(); + CdlConflict_UnresolvedBody(CdlTransaction, CdlNode, CdlProperty, std::string); + std::string target_name; + enum { + CdlConflict_UnresolvedBody_Invalid = 0, + CdlConflict_UnresolvedBody_Magic = 0x1b24bb8a + } cdlconflict_unresolvedbody_cookie; + + CdlConflict_UnresolvedBody(); + CdlConflict_UnresolvedBody(const CdlConflict_UnresolvedBody&); + CdlConflict_UnresolvedBody& operator=(const CdlConflict_UnresolvedBody&); +}; + +// ---------------------------------------------------------------------------- +// An illegal value can be caused because of a number of properties: +// legal_values, check_proc, entry_proc, ... In the case of the latter +// the Tcl code should provide text explaining why the value is +// illegal. + +class CdlConflict_IllegalValueBody : public CdlConflictBody { + + friend class CdlTest; + + public: + + static void make(CdlTransaction, CdlNode, CdlProperty); + + bool resolution_implemented() const; + + std::string get_explanation() const; + void set_explanation(std::string); + static bool test(CdlConflict); + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + + private: + virtual ~CdlConflict_IllegalValueBody(); + bool inner_resolve(CdlTransaction, int); + CdlConflict_IllegalValueBody(CdlTransaction, CdlNode, CdlProperty); + std::string explanation; + enum { + CdlConflict_IllegalValueBody_Invalid = 0, + CdlConflict_IllegalValueBody_Magic = 0x4fb27ed1 + } cdlconflict_illegalvaluebody_cookie; + + CdlConflict_IllegalValueBody(); + CdlConflict_IllegalValueBody(const CdlConflict_IllegalValueBody&); + CdlConflict_IllegalValueBody& operator=(const CdlConflict_IllegalValueBody&); +}; + +// ---------------------------------------------------------------------------- +// There are times when expression evaluation will fail, e.g. because of +// a division by zero. The explanation is supplied by the evaluation code. + +class CdlConflict_EvalExceptionBody : public CdlConflictBody { + + friend class CdlTest; + + public: + + static void make(CdlTransaction, CdlNode, CdlProperty, std::string); + + std::string get_explanation() const; + void set_explanation(std::string); // mainly for internal use + static bool test(CdlConflict); + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + + private: + virtual ~CdlConflict_EvalExceptionBody(); + CdlConflict_EvalExceptionBody(CdlTransaction, CdlNode, CdlProperty, std::string); + std::string explanation; + enum { + CdlConflict_EvalExceptionBody_Invalid = 0, + CdlConflict_EvalExceptionBody_Magic = 0x7e64bc41 + } cdlconflict_evalexceptionbody_cookie; +}; + +// ---------------------------------------------------------------------------- +// A goal expression evaluates to false. Producing sensible diagnostics +// depends on a detailed understanding of goal expressions, which will +// have to wait until the inference engine comes along. + +class CdlConflict_RequiresBody : public CdlConflictBody { + + friend class CdlTest; + + public: + + static void make(CdlTransaction, CdlNode, CdlProperty); + bool resolution_implemented() const; + + std::string get_explanation() const; + static bool test(CdlConflict); + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + + private: + virtual ~CdlConflict_RequiresBody(); + bool inner_resolve(CdlTransaction, int); + CdlConflict_RequiresBody(CdlTransaction, CdlNode, CdlProperty); + enum { + CdlConflict_RequiresBody_Invalid = 0, + CdlConflict_RequiresBody_Magic = 0x78436331 + } cdlconflict_requiresbody_cookie; +}; + +// ---------------------------------------------------------------------------- +// There is an unusual problem in the configuration data somewhere. +// For example, a parent property can be resolved but the target is +// not a container. There is not a lot that the user can do about +// problems like this, apart from complaining to the component vendor, +// but the problem should not be ignored either. + +class CdlConflict_DataBody : public CdlConflictBody { + + friend class CdlTest; + + public: + + static void make(CdlTransaction, CdlNode, CdlProperty, std::string); + + std::string get_explanation() const; + static bool test(CdlConflict); + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + + private: + virtual ~CdlConflict_DataBody(); + CdlConflict_DataBody(CdlTransaction, CdlNode, CdlProperty, std::string); + std::string message; + enum { + CdlConflict_DataBody_Invalid = 0, + CdlConflict_DataBody_Magic = 0x2cec7ad8 + } cdlconflict_databody_cookie; +}; + +//}}} +//{{{ CdlProperty class and derived classes + +//{{{ Description + +// --------------------------------------------------------------------------- +// There are many different kinds of property. An alias property contains +// a simple string. A check_proc property contains a fragment of Tcl code +// which can be represented internally as a string, as bytecodes, or both. +// A requires property contains a goal expression. ... +// +// The implementation involves a base class CdlProperty and various +// derived classes such as CdlProperty_StringBody and +// CdlProperty_ExpressionBody. +// +// New CdlProperty objects get created only when reading in CDL scripts, +// while executing commands like alias and requires. These commands are +// implemented as C++ functions hooked into the TCL interpreter. The +// property arguments are available as an argc/argv pair. Each command +// will parse and validate the arguments and then invoke an appropriate +// constructor. + +//}}} +//{{{ CdlPropertyId_xxx + +// ---------------------------------------------------------------------------- +// Properties are identified by strings rather than by an enum or anything +// like that. A string-based approach allows new properties to be added at +// any time without invalidating an existing enum, complicating switch() +// statements, etc. There are some performance issues but these are +// manageable. +// +// A disadvantage of using strings is that there is a problem with +// typos. Mistyping something like CdlPropertyId_Compile will generally +// result in a compile-time failure. Mistyping "Complie" will cause +// strange behaviour at run-time and is hard to track down. +// +// A compromise solution is to have #define'd string constants. + +#define CdlPropertyId_ActiveIf "ActiveIf" +#define CdlPropertyId_BuildProc "BuildProc" +#define CdlPropertyId_Calculated "Calculated" +#define CdlPropertyId_CancelProc "CancelProc" +#define CdlPropertyId_CheckProc "CheckProc" +#define CdlPropertyId_Compile "Compile" +#define CdlPropertyId_ConfirmProc "ConfirmProc" +#define CdlPropertyId_DecorationProc "DecorationProc" +#define CdlPropertyId_DefaultValue "DefaultValue" +#define CdlPropertyId_Define "Define" +#define CdlPropertyId_DefineHeader "DefineHeader" +#define CdlPropertyId_DefineProc "DefineProc" +#define CdlPropertyId_Description "Description" +#define CdlPropertyId_Dialog "Dialog" +#define CdlPropertyId_Display "Display" +#define CdlPropertyId_DisplayProc "DisplayProc" +#define CdlPropertyId_Doc "Doc" +#define CdlPropertyId_EntryProc "EntryProc" +#define CdlPropertyId_Flavor "Flavor" +#define CdlPropertyId_DefineFormat "DefineFormat" +#define CdlPropertyId_Group "Group" +#define CdlPropertyId_Hardware "Hardware" +#define CdlPropertyId_IfDefine "IfDefine" +#define CdlPropertyId_Implements "Implements" +#define CdlPropertyId_IncludeDir "IncludeDir" +#define CdlPropertyId_IncludeFiles "IncludeFiles" +#define CdlPropertyId_InitProc "InitProc" +#define CdlPropertyId_InstallProc "InstallProc" +#define CdlPropertyId_LegalValues "LegalValues" +#define CdlPropertyId_Library "Library" +#define CdlPropertyId_LicenseProc "LicenseProc" +#define CdlPropertyId_Make "Make" +#define CdlPropertyId_Makefile "Makefile" +#define CdlPropertyId_MakeObject "MakeObject" +#define CdlPropertyId_NoDefine "NoDefine" +#define CdlPropertyId_Object "Object" +#define CdlPropertyId_Parent "Parent" +#define CdlPropertyId_Requires "Requires" +#define CdlPropertyId_Screen "Screen" +#define CdlPropertyId_Script "Script" +#define CdlPropertyId_UpdateProc "UpdateProc" +#define CdlPropertyId_Wizard "Wizard" + +//}}} +//{{{ Base class + +// ---------------------------------------------------------------------------- +// The base class is never used directly. Instead the appropriate derived +// objects are instantiated and when appropriate it will be necessary to +// do a dynamic cast from a CdlProperty to e.g. a CdlProperty_String. + +class CdlPropertyBody { + + friend class CdlTest; + + public: + // The destructor is public, to avoid possible problems with STL. + virtual ~CdlPropertyBody(); + + // These routines provide access to the basic data. + std::string get_property_name() const; + + // Get hold of the arguments that were present in the original data. + int get_argc() const; + bool has_option(std::string) const; + std::string get_option(std::string) const; + const std::vector& get_argv() const; + const std::vector >& get_options() const; + + // Resolve any references, or generate/update appropriate conflict + // objects. The default implementation is a no-op because not all + // properties involve references. + virtual void update(CdlTransaction, CdlNode /* source */, CdlNode /* dest */, CdlUpdate); + + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + + // The legal constructor can only get invoked from a derived class + // constructor. The first argument identifies the property, e.g. + // CdlPropertyId_Doc (which is just #define'd to the string + // "doc"). + // + // The argc and argv fields provide access to the original + // data in the command that resulted in the property being + // constructed. Often but not always argv[0] will be the same as + // the property id. The argv information is stored mainly for + // diagnostics purposes, it may be removed in future to avoid + // wasting memory. + // + // The options field is the result of parsing options such + // as -library=libextras.a. It consists of a vector of + // pairs, and is usually obtained via + // CdlParse::parse_options(). + CdlPropertyBody(CdlNode, std::string, int argc, char** argv, std::vector >&); + + private: + // This string indicates the command used to define this property, + // e.g. "doc" or "define_proc". It is provided to the constructor. + std::string name; + + // All property data comes out of a file and gets rid via a + // Tcl interpreter. The raw file data is stored with the property, + // mainly for diagnostics purposes. + std::vector argv; + + std::vector > options; + + // The usual set of illegal operations. + CdlPropertyBody(); + CdlPropertyBody(const CdlPropertyBody&); + CdlPropertyBody& operator=(const CdlPropertyBody&); + + enum { + CdlPropertyBody_Invalid = 0, + CdlPropertyBody_Magic = 0x60dd58f4 + } cdlpropertybody_cookie; +}; + +//}}} +//{{{ CdlProperty_Minimal + +// ---------------------------------------------------------------------------- +// This class is used for properties that are simple flags, e.g. no_define. +// There should be no additional data associated with such properties. + +class CdlProperty_MinimalBody : public CdlPropertyBody { + + friend class CdlTest; + + public: + static CdlProperty_Minimal make(CdlNode, std::string, int, char**, std::vector >&); + virtual ~CdlProperty_MinimalBody( ); + bool check_this( cyg_assert_class_zeal = cyg_quick ) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + + private: + typedef CdlPropertyBody inherited; + + CdlProperty_MinimalBody(CdlNode, std::string, int, char**, std::vector >&); + enum { + CdlProperty_MinimalBody_Invalid = 0, + CdlProperty_MinimalBody_Magic = 0x25625b8c + } cdlproperty_minimalbody_cookie; + + CdlProperty_MinimalBody(); + CdlProperty_MinimalBody(const CdlProperty_MinimalBody&); + CdlProperty_MinimalBody& operator=(const CdlProperty_MinimalBody&); +}; + +//}}} +//{{{ CdlProperty_String + +// ---------------------------------------------------------------------------- +// A string property contains a single piece of additional data in the form +// of a string. + +class CdlProperty_StringBody : public CdlPropertyBody { + + friend class CdlTest; + + public: + static CdlProperty_String make(CdlNode, std::string, std::string, int, char**, + std::vector >&); + virtual ~CdlProperty_StringBody(); + + std::string get_string(void) const; + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + + private: + typedef CdlPropertyBody inherited; + + CdlProperty_StringBody(CdlNode, std::string /* id */, std::string /* data */, int, char**, + std::vector >&); + std::string data; + enum { + CdlProperty_StringBody_Invalid = 0, + CdlProperty_StringBody_Magic = 0x78d1ca94 + } cdlproperty_stringbody_cookie; + + // The only legal constructor supplies all the data. + CdlProperty_StringBody(); + CdlProperty_StringBody(const CdlProperty_StringBody&); + CdlProperty_StringBody& operator=(const CdlProperty_StringBody&); +}; + +//}}} +//{{{ CdlProperty_TclCode + +// ---------------------------------------------------------------------------- +// A TclCode property is currently equivalent to a string property. In +// future this may change to allow the byte-compiled versions of the +// script to be stored. +// +// One of the properties, "screen" inside a cdl_wizard, also takes +// an integer. Rather than create yet another class, this is handled +// by a separate constructor. + + +class CdlProperty_TclCodeBody : public CdlPropertyBody { + + friend class CdlTest; + + public: + static CdlProperty_TclCode make(CdlNode, std::string, cdl_tcl_code, int, char**, + std::vector >&); + static CdlProperty_TclCode make(CdlNode, std::string, cdl_int, cdl_tcl_code, int, char**, + std::vector >&); + virtual ~CdlProperty_TclCodeBody(); + + cdl_int get_number(void) const; + const cdl_tcl_code& get_code(void) const; + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + private: + typedef CdlPropertyBody inherited; + + CdlProperty_TclCodeBody(CdlNode, std::string, cdl_int, cdl_tcl_code, int, char**, + std::vector >&); + + cdl_int number; + cdl_tcl_code code; + enum { + CdlProperty_TclCodeBody_Invalid = 0, + CdlProperty_TclCodeBody_Magic = 0x7b14d4e5 + } cdlproperty_tclcodebody_cookie; + + CdlProperty_TclCodeBody(); + CdlProperty_TclCodeBody(const CdlProperty_TclCodeBody&); + CdlProperty_TclCodeBody& operator=(const CdlProperty_TclCodeBody&); + +}; + +//}}} +//{{{ CdlProperty_StringVector + +// ---------------------------------------------------------------------------- +// This is used for multiple constant strings, as opposed to a list +// expression which requires evaluation. One example is a list +// of aliases. + +class CdlProperty_StringVectorBody : public CdlPropertyBody { + + friend class CdlTest; + + public: + static CdlProperty_StringVector make(CdlNode, std::string, const std::vector&, int, char**, + std::vector >&); + virtual ~CdlProperty_StringVectorBody(); + + const std::vector& get_strings() const; + std::string get_first_string() const; + unsigned int get_number_of_strings() const; + std::string get_string(unsigned int) const; + bool check_this(cyg_assert_class_zeal zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + private: + typedef CdlPropertyBody inherited; + + CdlProperty_StringVectorBody(CdlNode, std::string, const std::vector&, int, char**, + std::vector >&); + + std::vector data; + enum { + CdlProperty_StringVectorBody_Invalid = 0, + CdlProperty_StringVectorBody_Magic = 0x4ed039f3 + } cdlproperty_stringvectorbody_cookie; + + CdlProperty_StringVectorBody(); + CdlProperty_StringVectorBody(const CdlProperty_StringVectorBody&); + CdlProperty_StringVectorBody& operator=(const CdlProperty_StringVectorBody&); +}; + +//}}} +//{{{ CdlProperty_Reference + +// ---------------------------------------------------------------------------- +// This is used for properties such as wizard and dialog, where the data +// identifies some other entity in the system. The class is both a property +// and a reference object. Most of the desired functionality is provided by +// inheritance from CdlReference. + +class CdlProperty_ReferenceBody : public CdlPropertyBody, public CdlReference { + + friend class CdlTest; + + public: + static CdlProperty_Reference make(CdlNode, std::string /* id */, std::string /* destination */, + CdlUpdateHandler, int, char**, + std::vector >&); + virtual ~CdlProperty_ReferenceBody(); + + void update(CdlTransaction, CdlNode, CdlNode, CdlUpdate); + + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + private: + typedef CdlPropertyBody inherited_property; + typedef CdlReference inherited_reference; + + CdlUpdateHandler update_handler; + + CdlProperty_ReferenceBody(CdlNode, std::string /* id */, std::string /* destination */, CdlUpdateHandler, int, char**, + std::vector >&); + enum { + CdlProperty_ReferenceBody_Invalid = 0, + CdlProperty_ReferenceBody_Magic = 0x78100339 + } cdlproperty_referencebody_cookie; + + CdlProperty_ReferenceBody(); + CdlProperty_ReferenceBody(const CdlProperty_ReferenceBody&); + CdlProperty_ReferenceBody& operator=(const CdlProperty_Reference&); +}; + +//}}} +//{{{ CdlProperty_Expression + +// ---------------------------------------------------------------------------- +// An expression property simply inherits its functionality from the basic +// property class and from the expression class. + +class CdlProperty_ExpressionBody : public CdlPropertyBody, public CdlExpressionBody { + + friend class CdlTest; + + public: + static CdlProperty_Expression make(CdlNode, std::string, CdlExpression, CdlUpdateHandler, int, char**, + std::vector >&); + virtual ~CdlProperty_ExpressionBody(); + void update(CdlTransaction, CdlNode, CdlNode, CdlUpdate); + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + private: + typedef CdlPropertyBody inherited_property; + typedef CdlExpressionBody inherited_expression; + + CdlProperty_ExpressionBody(CdlNode, std::string, CdlExpression, CdlUpdateHandler, int, char**, + std::vector >&); + + CdlUpdateHandler update_handler; + enum { + CdlProperty_ExpressionBody_Invalid = 0, + CdlProperty_ExpressionBody_Magic = 0x05fb4056 + } cdlproperty_expressionbody_cookie; + + CdlProperty_ExpressionBody(); + CdlProperty_ExpressionBody(const CdlProperty_ExpressionBody&); + CdlProperty_ExpressionBody& operator=(const CdlProperty_ExpressionBody&); +}; + +//}}} +//{{{ CdlProperty_ListExpression + +// ---------------------------------------------------------------------------- +// Similarly a list property simply inherits from property and from +// list expressions. + +class CdlProperty_ListExpressionBody : public CdlPropertyBody, public CdlListExpressionBody { + + friend class CdlTest; + + public: + static CdlProperty_ListExpression make(CdlNode, std::string, CdlListExpression, CdlUpdateHandler, int, char**, + std::vector >&); + virtual ~CdlProperty_ListExpressionBody(); + void update(CdlTransaction, CdlNode, CdlNode, CdlUpdate); + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + private: + typedef CdlPropertyBody inherited_property; + typedef CdlListExpressionBody inherited_expression; + + CdlProperty_ListExpressionBody(CdlNode, std::string, CdlListExpression, CdlUpdateHandler, int, char**, + std::vector >&); + + CdlUpdateHandler update_handler; + enum { + CdlProperty_ListExpressionBody_Invalid = 0, + CdlProperty_ListExpressionBody_Magic = 0x6b0136f5 + } cdlproperty_listexpressionbody_cookie; + + CdlProperty_ListExpressionBody(); + CdlProperty_ListExpressionBody(const CdlProperty_ListExpressionBody&); + CdlProperty_ListExpressionBody& operator=(const CdlProperty_ListExpressionBody&); +}; + +//}}} +//{{{ CdlProperty_GoalExpression + +// ---------------------------------------------------------------------------- +// And a goal property inherits from property and from goal expressions. + +class CdlProperty_GoalExpressionBody : public CdlPropertyBody, public CdlGoalExpressionBody { + + friend class CdlTest; + + public: + static CdlProperty_GoalExpression make(CdlNode, std::string, CdlGoalExpression, CdlUpdateHandler, int, char**, + std::vector >&); + virtual ~CdlProperty_GoalExpressionBody(); + void update(CdlTransaction, CdlNode, CdlNode, CdlUpdate); + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + private: + typedef CdlPropertyBody inherited_property; + typedef CdlGoalExpressionBody inherited_expression; + + CdlProperty_GoalExpressionBody(CdlNode, std::string, CdlGoalExpression, CdlUpdateHandler, int, char**, + std::vector >&); + + CdlUpdateHandler update_handler; + enum { + CdlProperty_GoalExpressionBody_Invalid = 0, + CdlProperty_GoalExpressionBody_Magic = 0x08b2b31e + } cdlproperty_goalexpressionbody_cookie; + + CdlProperty_GoalExpressionBody(); + CdlProperty_GoalExpressionBody(const CdlProperty_GoalExpressionBody&); + CdlProperty_GoalExpressionBody& operator=(const CdlProperty_GoalExpressionBody&); +}; + +//}}} + +//}}} +//{{{ CdlParse class + +// ---------------------------------------------------------------------------- +// This is another utility class for collecting together parsing-related +// functions. +// +// Note that this is only a utility class. When libcdl is used for parsing +// things not related to software configuration the new functionality +// does not have to reside inside the CdlParse class, but it may be +// possible to re-use some of the functionality in that class. + +class CdlParse { + + public: + // Utility routines. + static const char* get_tcl_cmd_name(const char*); + static std::string concatenate_argv(int, char**, int); + static int parse_options(CdlInterpreter, std::string /* diag_prefix */, char** /* options */, + int /* argc */, char** /* argv */, int /* start_index */, + std::vector >& /* result */); + static std::string get_diagnostic_prefix(CdlInterpreter); + static void report_error(CdlInterpreter, std::string); + static void report_warning(CdlInterpreter, std::string); + static void clear_error_count(CdlInterpreter); + static int get_error_count(CdlInterpreter); + static void incr_error_count(CdlInterpreter, int=1); + + // Support for Tcl's "unknown" command + static int unknown_command(CdlInterpreter, int, char**); + + // Property-related utilities + static std::string get_property_prefix(char*); + static std::string get_property_prefix(CdlProperty); + static void report_property_parse_error(CdlInterpreter, char*, std::string); + static void report_property_parse_error(CdlInterpreter, CdlProperty, std::string); + + // Utility parsing routines + static int parse_minimal_property(CdlInterpreter, int, char**, std::string, + char**, void (*)(CdlInterpreter, CdlProperty_Minimal)); + static int parse_string_property(CdlInterpreter, int, char**, std::string, + char**, void (*)(CdlInterpreter, CdlProperty_String)); + static int parse_tclcode_property(CdlInterpreter, int, char**, std::string, + char**, void (*)(CdlInterpreter, CdlProperty_TclCode)); + static int parse_stringvector_property(CdlInterpreter, int, char**, std::string, + char**, void (*)(CdlInterpreter, CdlProperty_StringVector)); + static int parse_reference_property(CdlInterpreter, int, char**, std::string, + char**, void (*)(CdlInterpreter, CdlProperty_Reference), + CdlUpdateHandler); + static int parse_expression_property(CdlInterpreter, int, char**, std::string, + char **, void (*)(CdlInterpreter, CdlProperty_Expression), + CdlUpdateHandler); + static int parse_listexpression_property(CdlInterpreter, int, char**, std::string, + char **, void (*)(CdlInterpreter, CdlProperty_ListExpression), + CdlUpdateHandler); + static int parse_goalexpression_property(CdlInterpreter, int, char**, std::string, + char **, void (*)(CdlInterpreter, CdlProperty_GoalExpression), + CdlUpdateHandler); +}; + +//}}} +//{{{ CdlNode + +// ---------------------------------------------------------------------------- +// A node object has a name and lives in a hierarchy. Each node keeps +// track of the toplevel and owner. The memory overheads are +// relatively small compared with the performance gains when such +// information is needed. +// +// A node object also has a vector of properties, and can be referred to +// by properties in other nodes. Some of the properties may result in +// conflicts. + +class CdlNodeBody { + + friend class CdlTest; + + // Adding and removing nodes from the hierarchy is done + // by CdlToplevel members. + friend class CdlToplevelBody; + + // CdlLoadable must be able to access the destructor + friend class CdlLoadableBody; + + // It is intended that CdlProperties will also add and remove themselves + friend class CdlPropertyBody; + + // CdlReference bind and unbind operations need access to + // the referrers vector. So does CdlTransaction::commit() + friend class CdlReference; + friend class CdlTransactionBody; + + public: + + // Basic information. + std::string get_name() const; + CdlContainer get_parent() const; + CdlLoadable get_owner() const; + CdlToplevel get_toplevel() const; + + // Propagation support. Some updates such as active/inactive changes + // get applied to nodes as well as to properties. Note that because + // of multiple inheritance this virtual call can get confusing. + virtual void update(CdlTransaction, CdlUpdate); + + // Is this node active or not? The is_active() call refers + // to the global state, things may be different inside a + // transaction. + bool is_active() const; + bool is_active(CdlTransaction transaction); + + // Generally nodes become active when the parent becomes + // active and enabled. Some derived classes may impose + // additional restrictions, for example because of + // active_if constraints. This routine can be used + // to check whether or not a node should become active. + virtual bool test_active(CdlTransaction); + + // Provide access to the various properties. Currently all this + // information is publicly available. + const std::vector& get_properties() const; + CdlProperty get_property(std::string) const; + void get_properties(std::string, std::vector&) const; + std::vector get_properties(std::string) const; + bool has_property(std::string) const; + int count_properties(std::string) const; + + // Provide access to the various global conflicts. More + // commonly conflicts are accessed on a per-transaction basis. + void get_conflicts(std::vector&) const; + void get_conflicts(bool (*)(CdlConflict), std::vector&) const; + void get_structural_conflicts(std::vector&) const; + void get_structural_conflicts(bool (*)(CdlConflict), std::vector&) const; + + // Provide access to all the referrers. This may not get used very + // much outside the library itself. + const std::vector& get_referrers() const; + + // Add property parsers and validation code appropriate for a + // node. Currently this is a no-op, there are no properties + // associated with every node, but this may change in future e.g. + // for diagnostics purposes. + static void add_property_parsers(std::vector& parsers); + void check_properties(CdlInterpreter); + + // Persistence support. The final classes such as cdl_option + // should provide implementations of these functions. The + // base function takes care of data that was present in an + // original save file but which was not recognised. + // + // Configuration save files are Tcl scripts, so it seems + // appropriate to handle the I/O via the Tcl library and + // to have a TCL interpreter available. + virtual void save(CdlInterpreter, Tcl_Channel, int, bool) throw(CdlInputOutputException, std::bad_alloc); + bool has_additional_savefile_information() const; + + // Mainly for diagnostics code, what is the actual name for this + // type of CDL object? This should be in terms of CDL data, e.g. + // "package" or "component", rather than in implementation terms + // such as "CdlPackageBody". + virtual std::string get_class_name() const; + + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + + // CdlNodeBodies are only instantiated by derived classes. + // They must always have a name. They need not be placed + // in the hierarchy immediately, that can wait until + // later. + CdlNodeBody(std::string); + // A dummy constructor is needed because of the virtual + // inheritance. + CdlNodeBody(); + + // Nodes cannot be destroyed directly by application code, + // only by higher-level library functions such as unload_package() + virtual ~CdlNodeBody(); + + // Updating the name is rarely required, but is useful for savefiles. + void set_name(std::string); + + // Is the node currently active? This applies to the global state + // only, not per-transaction state. Some derived classes may want + // to override the default value + bool active; + + private: + + // The basic data. The name is known during construction. + // The other three fields get updated by e.g. CdlToplevel::add_node(); + std::string name; + CdlContainer parent; + CdlLoadable owner; + CdlToplevel toplevel; + + // This is used by remove_node_from_toplevel()/add_node_to_toplevel() + // to allow the latter to exactly reverse the former + int remove_node_container_position; + + // Properties normally only get added during the parsing process, + // and only get removed when the object itself is destroyed. + // A vector is the obvious implementation. + std::vector properties; + + // Currently a vector of referrers is used. This vector is subject + // to change when packages get loaded and unloaded, possibly a + // list would be better. + std::vector referrers; + + // Savefiles may contain information that is not recognised by the + // current library, especially because of savefile hooks which + // allow e.g. the configuration tool to store its own information + // in save files. This information must not be lost, even if you are + // e.g. mixing command line and GUI tools. This vector holds + // the savefile information so that it can be put in the next + // savefile. + std::vector unsupported_savefile_strings; + + enum { + CdlNodeBody_Invalid = 0, + CdlNodeBody_Magic = 0x309595b5 + } cdlnodebody_cookie; + + // Illegal operations + CdlNodeBody(const CdlNodeBody&); + CdlNodeBody& operator=(const CdlNodeBody&); +}; + +//}}} +//{{{ CdlContainer + +// ---------------------------------------------------------------------------- +// A container is a node that can contain other nodes. + +class CdlContainerBody : virtual public CdlNodeBody { + + friend class Cdltest; + + // Allow CdlNode::check_this() access to the internals + friend class CdlNodeBody; + + // Adding a node to the hierarchy is done by a CdlToplevel member. + // Ditto for removing. + friend class CdlToplevelBody; + + // Deleting a container can happen inside CdlToplevel and CdlLoadable + friend class CdlLoadableBody; + + public: + + const std::vector& get_contents() const; + bool contains(CdlConstNode, bool /* recurse */ = false) const; + bool contains(const std::string, bool /* recurse */ = false) const; + CdlNode find_node(const std::string, bool /* recurse */ = false) const; + + // Propagation support. Some updates such as active/inactive changes + // get applied to nodes as well as to properties. + virtual void update(CdlTransaction, CdlUpdate); + + // Persistence support. + virtual void save(CdlInterpreter, Tcl_Channel, int, bool) throw(CdlInputOutputException, std::bad_alloc); + + virtual std::string get_class_name() const; + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + + // Containers cannot be destroyed explicitly, only via higher-level + // code such as unload_package(); + virtual ~CdlContainerBody(); + + CdlContainerBody(); + // Special constructor needed for internal use. + CdlContainerBody(std::string); + + // The CdlToplevel class needs access to its own contents. + std::vector contents; + + private: + enum { + CdlContainerBody_Invalid = 0, + CdlContainerBody_Magic = 0x543c5f1d + } cdlcontainerbody_cookie; + + // Illegal operations + CdlContainerBody(const CdlContainerBody&); + CdlContainerBody& operator=(const CdlContainerBody&); +}; + +//}}} +//{{{ CdlLoadable + +// ---------------------------------------------------------------------------- +// A loadable object is a container that gets loaded or unloaded +// atomically from a toplevel. The key difference is that a loadable +// keeps track of all nodes that were loaded as part of this +// operation, thus allowing unload operations to happen safely even if +// nodes get re-parented all over the hierarchy. In addition, there is +// a slave interpreter associated with every loadable. + +class CdlLoadableBody : virtual public CdlContainerBody { + + friend class CdlTest; + + // Allow CdlNode::check_this() access to the internals + friend class CdlNodeBody; + + // Adding nodes to the hierarchy is done by a toplevel member + friend class CdlToplevelBody; + + public: + virtual ~CdlLoadableBody(); + + + const std::vector& get_owned() const; + bool owns(CdlConstNode) const; + CdlInterpreter get_interpreter() const; + std::string get_directory() const; + + // Some properties such as doc and compile reference filenames. + // A search facility is useful. + virtual std::string find_relative_file(std::string /* filename */, std::string /* directory */ = "") const; + virtual std::string find_absolute_file(std::string, std::string, bool /* allow_urls */ = false) const; + virtual bool has_subdirectory(std::string) const; + + // These support load/unload operations inside transactions + // They are static members because some of them will want + // to delete the loadable. + static void transaction_commit_load(CdlTransaction, CdlLoadable); + static void transaction_cancel_load(CdlTransaction, CdlLoadable); + static void transaction_commit_unload(CdlTransaction, CdlLoadable); + static void transaction_cancel_unload(CdlTransaction, CdlLoadable); + + // Binding and unbinding of properties. This involves processing + // the various properties, calculating default values, etc. + void bind(CdlTransaction); + void unbind(CdlTransaction); + + virtual std::string get_class_name() const; + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + + CdlLoadableBody(CdlToplevel, std::string /* directory */); + + // Needed by derived classes, but not actually used. + CdlLoadableBody(); + + private: + + std::vector owned; + CdlInterpreter interp; + std::string directory; + + // Used by add/remove_node_from_toplevel() + int remove_node_loadables_position; + + enum { + CdlLoadableBody_Invalid = 0, + CdlLoadableBody_Magic = 0x488d6127 + } cdlloadablebody_cookie; + + // Invalid operations + CdlLoadableBody(const CdlLoadableBody&); + CdlLoadableBody& operator=(const CdlLoadableBody&); +}; + +//}}} +//{{{ CdlToplevel + +// ---------------------------------------------------------------------------- +// Toplevels are containers that live at the top of a hierarchy +// (surprise surprise). This means that they do not have a parent. +// In addition a toplevel object keeps track of all the names +// used, guaranteeing uniqueness and providing a quick lookup +// facility. +// +// Every container is also a node, so every toplevel is a node. +// Inheritance from CdlNode may seem wrong. However it achieves +// consistency, everything in the hierarchy including the toplevel +// is a node. The main disadvantage is that every toplevel now +// needs a name. + +class CdlToplevelBody : virtual public CdlContainerBody { + + friend class CdlTest; + + // Allow CdlNode::check_this() access to the internals + friend class CdlNodeBody; + + // The CdlTransaction class needs direct access to the lists + // of conflicts. + friend class CdlTransactionBody; + + public: + virtual ~CdlToplevelBody(); + + // Updating the hierarchy. This happens a node at a time. Adding a + // node involves updating the name->node map in the toplevel, + // setting the node's parent/owner/toplevel fields, and updating + // the parent and owner containers. The owner may be 0 for special + // nodes such as the orphans container. The parent must be known, + // although it may change later on during a change_parent() call. + // + // Removing a node is more complicated, and involves a two-stage + // process. First the node is removed from the toplevel, thus + // eliminating the name->node mapping. The owner and parent fields + // are preserved at this stage (except for the loadable itself), + // and the operation may be undone if the relevant transaction + // gets cancelled. If the transaction gets committed then the + // second remove operation handles the owner and parent fields, + // just prior to the node being deleted. For convenience there + // are also per-loadable variants for some of these. + // + // change_parent() is used to support parent-properties. + // A container of 0 indicates an orphan, i.e. a parent + // property that did not or does not correspond to a + // current container. + // + // There is also a clean-up call. This gets used for interfaces + // which may alternate between belonging to a loadable and + // being auto-created. + void add_node(CdlLoadable, CdlContainer, CdlNode); + void add_node_to_toplevel(CdlNode); + void remove_node_from_toplevel(CdlNode); + static void remove_node(CdlLoadable, CdlContainer, CdlNode); + void add_loadable_to_toplevel(CdlLoadable); + void remove_loadable_from_toplevel(CdlLoadable); + void change_parent(CdlLoadable, CdlContainer /* current */, CdlContainer /* new */, CdlNode, int /* pos */ = -1); + void cleanup_orphans(); + + // Toplevels keep track of all the loadables, in addition to + // inheriting tree behaviour from CdlContainer. This is convenient + // for some operations like determining build information + // which must operate on a per-loadable basis. + const std::vector& get_loadables() const; + + // Name uniqueness is guaranteed. It is convenient to have an STL + // map as a lookup service. + CdlNode lookup(const std::string) const; + + // There are two conflict lists associated with each toplevel. One + // is for "structural" conflicts, ones that can only be resolved + // by a fairly major change such as loading another package: a + // typical example is an unresolved parent reference. The other is + // for conflicts that can probably be resolved simply by changing + // some values. Both sets of conflicts are held as a simple list. + // + // The active vs. inactive state of a CDL entity affects the + // location of structural vs. non-structural conflicts. If an + // entity becomes inactive then structural conflicts are not + // affected, but non-structural conflicts are removed from the + // global list. If an entity's "requires" expression is not + // satisfied but the entity is inactive anyway then this is + // harmless. + const std::list& get_all_conflicts() const; + const std::list& get_all_structural_conflicts() const; + + // Try to resolve some or all conflicts. Typically a new transaction + // will be created for this. + void resolve_conflicts(const std::vector&); + void resolve_all_conflicts(); + + // Toplevels can have descriptions provided by the user. This is + // particularly important for pre-defined templates, target + // board descriptions, etc. where the user would like some + // extra information about the template before loading it in. + // The default value is an empty string. + std::string get_description() const; + void set_description(std::string); + + // Each toplevel must have an associated master Tcl interpreter. + CdlInterpreter get_interpreter() const; + + // Each toplevel should also have an associated directory for + // the component repository. It is not required that all loadables + // are relative to this, but that is the default behaviour. + std::string get_directory() const; + + // Each toplevel may have a single active main transaction. + // For now there is no support for concurrent transactions + // operating on a single toplevel (although nested transactions + // are allowed) + CdlTransaction get_active_transaction() const; + + // Build and define operations are available for all toplevels, + // even if they are not always applicable + void get_build_info(CdlBuildInfo&); + void get_all_build_info(CdlBuildInfo&); + void generate_config_headers(std::string) + throw(CdlInputOutputException, std::bad_alloc); + void get_config_headers(std::vector&); + void generate_build_tree(std::string, std::string = "") + throw(CdlInputOutputException, std::bad_alloc); + + // Values can be stored in limbo. This is useful when unloading + // and reloading packages, e.g. when changing a version the + // current settings can be preserved as much as possible. + void set_limbo_value(CdlValuable); + bool has_limbo_value(std::string) const; + CdlValue get_limbo_value(std::string) const; + CdlValue get_and_remove_limbo_value(std::string); + void clear_limbo(); + + // Persistence support. These are commented in the source code. + void initialize_savefile_support(); + static bool savefile_support_initialized(); + void add_savefile_command(std::string, CdlSaveCallback, CdlInterpreterCommand); + void add_savefile_subcommand(std::string, std::string, CdlSaveCallback, CdlInterpreterCommand); + void get_savefile_commands(std::vector&); + void get_savefile_subcommands(std::string, std::vector&); + void save_command_details(CdlInterpreter, Tcl_Channel, int, bool) + throw(CdlInputOutputException, std::bad_alloc); + static int savefile_handle_command(CdlInterpreter, int, char**); + static int savefile_handle_unsupported(CdlInterpreter, int, char**); + static int savefile_handle_unknown(CdlInterpreter, int, char**); + void save_unsupported_commands(CdlInterpreter, Tcl_Channel, int, bool) + throw(CdlInputOutputException, std::bad_alloc); + static cdl_int get_library_savefile_version(); + static int savefile_handle_version(CdlInterpreter, int, char**); + static cdl_int get_savefile_version(CdlInterpreter); + void save_conflicts(CdlInterpreter, Tcl_Channel, int, bool) throw(CdlInputOutputException, std::bad_alloc); + static void save_separator(CdlInterpreter, Tcl_Channel, std::string, bool) + throw(CdlInputOutputException, std::bad_alloc); + + virtual std::string get_class_name() const; + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + CdlToplevelBody(CdlInterpreter, std::string); + + private: + + std::map lookup_table; + std::vector loadables; + std::map limbo; + CdlInterpreter interp; + CdlContainer orphans; + std::string description; + std::string directory; + std::list conflicts; + std::list structural_conflicts; + + // The savefile support corresponding to this application. + static cdl_int savefile_version; + static bool savefile_commands_initialized; + static std::vector savefile_commands; + static std::map > savefile_subcommands; + + // Per-toplevel support. A savefile may contain unrecognised + // commands at the toplevel of a file, as well as unrecognised + // commands in e.g. the body of a cdl_configuration command. + // The latter is handled via the CdlNode base class. + std::vector unsupported_savefile_toplevel_strings; + std::vector unsupported_savefile_commands; + std::map > unsupported_savefile_subcommands; + + // Keep track of the current active transaction for this toplevel (if any) + CdlTransaction transaction; + + enum { + CdlToplevelBody_Invalid = 0, + CdlToplevelBody_Magic = 0x0834666e + } cdltoplevelbody_cookie; + + // Invalid operations + CdlToplevelBody(const CdlToplevelBody&); + CdlToplevelBody& operator=(const CdlToplevelBody&); +}; + +//}}} +//{{{ CdlUserVisible + +// ---------------------------------------------------------------------------- +// A user-visible object is likely to have properties such as display, +// description and doc. Many user-visible objects will have values but +// not all, for example custom dialogs are likely to have a doc +// property but they do not have a value. + +class CdlUserVisibleBody : virtual public CdlNodeBody { + + friend class CdlTest; + + public: + virtual ~CdlUserVisibleBody(); + + std::string get_display() const; + std::string get_description() const; + std::string get_doc() const; + + // NOTE: this will only work for absolute doc strings or for doc + // strings that are relative to the package. + std::string get_doc_url() const; + + // Add property parsers and validation code appropriate for a + // user-visible object such as doc and description + static void add_property_parsers(std::vector& parsers); + void check_properties(CdlInterpreter); + static int parse_description(CdlInterpreter, int, char**); + static int parse_display(CdlInterpreter, int, char**); + static int parse_doc(CdlInterpreter, int, char**); + + // Persistence support. The save code simply outputs some comments + // corresponding to the display, doc and description properties. + virtual void save(CdlInterpreter, Tcl_Channel, int, bool) throw(CdlInputOutputException, std::bad_alloc); + + virtual std::string get_class_name() const; + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + CdlUserVisibleBody(); + + private: + + enum { + CdlUserVisibleBody_Invalid = 0, + CdlUserVisibleBody_Magic = 0x13bbc817 + } cdluservisiblebody_cookie; + + // Illegal operations + CdlUserVisibleBody(const CdlUserVisibleBody&); + CdlUserVisibleBody& operator=(const CdlUserVisibleBody&); +}; + +//}}} +//{{{ CdlParentable + +// ---------------------------------------------------------------------------- +// A parentable object may have the parent property, redefining its +// position in the hierarchy. + +class CdlParentableBody : virtual public CdlNodeBody { + + friend class CdlTest; + + public: + virtual ~CdlParentableBody(); + + static void add_property_parsers(std::vector& parsers); + void check_properties(CdlInterpreter); + static int parse_parent(CdlInterpreter, int, char**); + static void update_handler(CdlTransaction, CdlNode, CdlProperty, CdlNode, CdlUpdate); + + virtual std::string get_class_name() const; + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + CdlParentableBody(); + + private: + + // Unloads may be cancelled. To restore the previous state exactly + // it is necessary to keep track of the old position. + int change_parent_save_position; + + enum { + CdlParentableBody_Invalid = 0, + CdlParentableBody_Magic = 0x40c6a077 + } cdlparentablebody_cookie; + + // Illegal operations + CdlParentableBody(const CdlParentableBody&); + CdlParentableBody& operator=(const CdlParentableBody&); +}; + +//}}} +//{{{ CdlValuable + +// ---------------------------------------------------------------------------- +// A valuable body has a value. Many valuables can be modified but not all. +// Some properties make a valuable object read-only. In future there is +// likely to be support for locked values as well. There is a member function +// to check whether or not a valuable object is modifiable. +// +// Relevant properties for a valuable object are: +// +// 1) flavor - readily available via CdlValue::get_flavor() +// 2) default_value - an expression +// 3) legal_values - a list expression +// 4) entry_proc - for validation purposes, in addition to legal_values +// 5) check_proc - ditto +// 6) active_if - goal expression +// 7) requires - goal expression +// 8) dialog - a custom dialog for editing this value +// 9) calculated - non-modifiable +// 10) implements - for interfaces +// +// A CdlValuable does not inherit directly from CdlValue, since it should +// not be possible to modify a Valuable directly. Instead it contains a +// CdlValue member, and provides essentially the same functions as +// a CdlValue. + +class CdlValuableBody : virtual public CdlNodeBody { + + friend class CdlTest; + + // Transaction commit operations require direct access to the CdlValue + friend class CdlTransactionBody; + + private: + CdlValue value; + + public: + virtual ~CdlValuableBody(); + + // Accessing the current value. There are variants for the global state + // and for per-transaction operations. + const CdlValue& get_whole_value() const; + + CdlValueFlavor get_flavor() const; + CdlValueFlavor get_flavor(CdlTransaction transaction) const + { // The transaction is irrelevant, it cannot change the flavor + return this->get_flavor(); + } + + CdlValueSource get_source() const; + bool has_source( CdlValueSource) const; + bool is_enabled( CdlValueSource = CdlValueSource_Current) const; + std::string get_value( CdlValueSource = CdlValueSource_Current) const; + bool has_integer_value( CdlValueSource = CdlValueSource_Current) const; + cdl_int get_integer_value( CdlValueSource = CdlValueSource_Current) const; + bool has_double_value( CdlValueSource = CdlValueSource_Current) const; + double get_double_value( CdlValueSource = CdlValueSource_Current) const; + CdlSimpleValue get_simple_value( CdlValueSource = CdlValueSource_Current) const; + + CdlValueSource get_source(CdlTransaction) const; + bool has_source( CdlTransaction, CdlValueSource) const; + bool is_enabled( CdlTransaction, CdlValueSource = CdlValueSource_Current) const; + std::string get_value( CdlTransaction, CdlValueSource = CdlValueSource_Current) const; + bool has_integer_value( CdlTransaction, CdlValueSource = CdlValueSource_Current) const; + cdl_int get_integer_value( CdlTransaction, CdlValueSource = CdlValueSource_Current) const; + bool has_double_value( CdlTransaction, CdlValueSource = CdlValueSource_Current) const; + double get_double_value( CdlTransaction, CdlValueSource = CdlValueSource_Current) const; + CdlSimpleValue get_simple_value( CdlTransaction, CdlValueSource = CdlValueSource_Current) const; + + // ----------------------------------------------------------------- + // Modify access. There are two variants of all the functions: + // + // 1) no transaction argument. A transaction will be created, + // committed, and destroyed for the change in question. + // + // 2) a transaction argument. The existing transaction will be + // updated but not committed. This allows multiple changes + // to be grouped together. + // + // There are only a handful of exported functions, but lots + // of inline variants. + void set_source(CdlValueSource); + void invalidate_source(CdlValueSource); + void set_enabled(bool, CdlValueSource); + void set_value(CdlSimpleValue&, CdlValueSource); + void set_enabled_and_value(bool, CdlSimpleValue&, CdlValueSource); + void set(CdlSimpleValue&, CdlValueSource); + + void set_source(CdlTransaction, CdlValueSource); + void invalidate_source(CdlTransaction, CdlValueSource); + void set_enabled(CdlTransaction, bool, CdlValueSource); + void set_value(CdlTransaction, CdlSimpleValue&, CdlValueSource); + void set_enabled_and_value(CdlTransaction, bool, CdlSimpleValue&, CdlValueSource); + void set(CdlTransaction, CdlSimpleValue&, CdlValueSource); + void set(CdlTransaction, const CdlValue&); + + void enable(CdlValueSource source) + { + set_enabled(true, source); + } + void disable(CdlValueSource source) + { + set_enabled(false, source); + } + void set_value(std::string data, CdlValueSource source) + { + CdlSimpleValue val(data); + set_value(val, source); + } + void set_integer_value(cdl_int data, CdlValueSource source) + { + CdlSimpleValue val(data); + set_value(val, source); + } + void set_double_value(double data, CdlValueSource source) + { + CdlSimpleValue val(data); + set_value(val, source); + } + void set_enabled_and_value(bool enabled, std::string data, CdlValueSource source) + { + CdlSimpleValue val(data); + set_enabled_and_value(enabled, val, source); + } + void set_enabled_and_value(bool enabled, cdl_int data, CdlValueSource source) + { + CdlSimpleValue val(data); + set_enabled_and_value(enabled, val, source); + } + void set_enabled_and_value(bool enabled, double data, CdlValueSource source) + { + CdlSimpleValue val(data); + set_enabled_and_value(enabled, val, source); + } + void enable_and_set_value(CdlSimpleValue& val, CdlValueSource source) + { + set_enabled_and_value(true, val, source); + } + void enable_and_set_value(std::string data, CdlValueSource source) + { + set_enabled_and_value(true, data, source); + } + void enable_and_set_value(cdl_int data, CdlValueSource source) + { + set_enabled_and_value(true, data, source); + } + void enable_and_set_value(double data, CdlValueSource source) + { + set_enabled_and_value(true, data, source); + } + void disable_and_set_value(CdlSimpleValue& val, CdlValueSource source) + { + set_enabled_and_value(false, val, source); + } + void disable_and_set_value(std::string data, CdlValueSource source) + { + set_enabled_and_value(false, data, source); + } + void disable_and_set_value(cdl_int data, CdlValueSource source) + { + set_enabled_and_value(false, data, source); + } + void disable_and_set_value(double data, CdlValueSource source) + { + set_enabled_and_value(false, data, source); + } + void enable(CdlTransaction transaction, CdlValueSource source) + { + set_enabled(transaction, true, source); + } + void disable(CdlTransaction transaction, CdlValueSource source) + { + set_enabled(transaction, false, source); + } + void set_value(CdlTransaction transaction, std::string data, CdlValueSource source) + { + CdlSimpleValue val(data); + set_value(transaction, val, source); + } + void set_integer_value(CdlTransaction transaction, cdl_int data, CdlValueSource source) + { + CdlSimpleValue val(data); + set_value(transaction, val, source); + } + void set_double_value(CdlTransaction transaction, double data, CdlValueSource source) + { + CdlSimpleValue val(data); + set_value(transaction, val, source); + } + void set_enabled_and_value(CdlTransaction transaction, bool enabled, std::string data, CdlValueSource source) + { + CdlSimpleValue val(data); + set_enabled_and_value(transaction, enabled, val, source); + } + void set_enabled_and_value(CdlTransaction transaction, bool enabled, cdl_int data, CdlValueSource source) + { + CdlSimpleValue val(data); + set_enabled_and_value(transaction, enabled, val, source); + } + void set_enabled_and_value(CdlTransaction transaction, bool enabled, double data, CdlValueSource source) + { + CdlSimpleValue val(data); + set_enabled_and_value(transaction, enabled, val, source); + } + void enable_and_set_value(CdlTransaction transaction, CdlSimpleValue& val, CdlValueSource source) + { + set_enabled_and_value(transaction, true, val, source); + } + void enable_and_set_value(CdlTransaction transaction, std::string data, CdlValueSource source) + { + set_enabled_and_value(transaction, true, data, source); + } + void enable_and_set_value(CdlTransaction transaction, cdl_int data, CdlValueSource source) + { + set_enabled_and_value(transaction, true, data, source); + } + void enable_and_set_value(CdlTransaction transaction, double data, CdlValueSource source) + { + set_enabled_and_value(transaction, true, data, source); + } + void disable_and_set_value(CdlTransaction transaction, CdlSimpleValue& val, CdlValueSource source) + { + set_enabled_and_value(transaction, false, val, source); + } + void disable_and_set_value(CdlTransaction transaction, std::string data, CdlValueSource source) + { + set_enabled_and_value(transaction, false, data, source); + } + void disable_and_set_value(CdlTransaction transaction, cdl_int data, CdlValueSource source) + { + set_enabled_and_value(transaction, false, data, source); + } + void disable_and_set_value(CdlTransaction transaction, double data, CdlValueSource source) + { + set_enabled_and_value(transaction, false, data, source); + } + + // ----------------------------------------------------------------- + virtual bool is_modifiable() const; + void get_widget_hint(CdlWidgetHint&); + + // ----------------------------------------------------------------- + // Propagation support. If a valuable becomes active or inactive + // because e.g. its parent is disabled then this may affect + // requires conflicts etc. + virtual void update(CdlTransaction, CdlUpdate); + + virtual bool test_active(CdlTransaction); + + // ----------------------------------------------------------------- + // Property-related stuff. + bool has_calculated_expression() const; + bool has_default_value_expression() const; + bool has_legal_values() const; + bool has_entry_proc() const; + bool has_check_proc() const; + bool has_active_if_conditions() const; + bool has_requires_goals() const; + bool has_dialog() const; + bool has_wizard() const; + + CdlProperty_Expression get_calculated_expression() const; + CdlProperty_Expression get_default_value_expression() const; + CdlProperty_ListExpression get_legal_values() const; + cdl_tcl_code get_entry_proc() const; + cdl_tcl_code get_check_proc() const; + void get_active_if_conditions(std::vector&) const; + void get_requires_goals(std::vector&) const; + CdlDialog get_dialog() const; + CdlWizard get_wizard() const; + void get_implemented_interfaces(std::vector&) const; + + // Add property parsers and validation code appropriate for a + // valuable object such as default_value and legal_values + static void add_property_parsers(std::vector& parsers); + void check_properties(CdlInterpreter); + static int parse_active_if(CdlInterpreter, int, char**); + static void active_if_update_handler(CdlTransaction, CdlNode, CdlProperty, CdlNode, CdlUpdate); + static int parse_calculated(CdlInterpreter, int, char**); + static void calculated_update_handler(CdlTransaction, CdlNode, CdlProperty, CdlNode, CdlUpdate); + static int parse_check_proc(CdlInterpreter, int, char**); + static int parse_default_value(CdlInterpreter, int, char**); + static void default_value_update_handler(CdlTransaction, CdlNode, CdlProperty, CdlNode, CdlUpdate); + static int parse_dialog(CdlInterpreter, int, char**); + static void dialog_update_handler(CdlTransaction, CdlNode, CdlProperty, CdlNode, CdlUpdate); + static int parse_entry_proc(CdlInterpreter, int, char**); + static int parse_flavor(CdlInterpreter, int, char**); + static int parse_group(CdlInterpreter, int, char**); + static int parse_implements(CdlInterpreter, int, char**); + static void implements_update_handler(CdlTransaction, CdlNode, CdlProperty, CdlNode, CdlUpdate); + static int parse_legal_values(CdlInterpreter, int, char**); + static void legal_values_update_handler(CdlTransaction, CdlNode, CdlProperty, CdlNode, CdlUpdate); + static int parse_requires(CdlInterpreter, int, char**); + static void requires_update_handler(CdlTransaction, CdlNode, CdlProperty, CdlNode, CdlUpdate); + static int parse_wizard(CdlInterpreter, int, char**); + static void wizard_update_handler(CdlTransaction, CdlNode, CdlProperty, CdlNode, CdlUpdate); + + // Persistence suppot + void save(CdlInterpreter, Tcl_Channel, int, bool /* modifiable */, bool /* minimal */) + throw(CdlInputOutputException, std::bad_alloc); + bool value_savefile_entry_needed() const; + static void initialize_savefile_support(CdlToplevel, std::string); + static int savefile_value_source_command(CdlInterpreter, int, char**); + static int savefile_user_value_command(CdlInterpreter, int, char**); + static int savefile_wizard_value_command(CdlInterpreter, int, char**); + static int savefile_inferred_value_command(CdlInterpreter, int, char**); + static int savefile_xxx_value_command(CdlInterpreter, int, char**, CdlValueSource); + + // Make sure that the current value is legal. This gets called automatically + // by all the members that modify values. It has to be a virtual function + // since some derived classes, e.g. hardware-related valuables, may impose + // constraints over and above legal_values etc. + virtual void check_value(CdlTransaction); + + // Similarly check the requires properties + void check_requires(CdlTransaction, CdlProperty_GoalExpression); + void check_requires(CdlTransaction); + + // Enabling or disabling a valuable may affect the active state of children + void check_children_active(CdlTransaction); + + virtual std::string get_class_name() const; + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + CdlValuableBody(CdlValueFlavor = CdlValueFlavor_Bool); + + + private: + + + enum { + CdlValuableBody_Invalid = 0, + CdlValuableBody_Magic = 0x2b2acc03 + } cdlvaluablebody_cookie; + + // Illegal operations + CdlValuableBody(const CdlValuableBody&); + CdlValuableBody& operator=(const CdlValuableBody&); +}; + +//}}} +//{{{ CdlTransaction etc. + +//{{{ Description + +// ---------------------------------------------------------------------------- +// Transactions. These are used for all changes to a configuration. In some +// cases a transaction is implicit: +// +// valuable->set_value(...) +// +// The actual implementation of this is: +// +// valuable->set_value(...) +// transact = CdlTransactionBody::make(valuable->get_toplevel()) +// valuable->set_value(transact, ...) +// +// transact->commit() +// delete transact +// +// Alternatively the use of transactions may be explicit. For implicit +// uses the library will invoke an inference callback at the +// appropriate time. For explicit transactions this is not necessary. +// +// The commit() operation invokes a transaction callback which should +// not be confused with the inference callback. The former is intended +// for display updates, it specifies everything that has changed +// during the transaction. The latter is used for reporting new +// conflicts to the user, suggesting fixes, etc. +// +// A whole bunch of information is associated with a transaction, +// including: all value changes, details of new conflicts, and details +// of existing conflicts that have gone away. The commit operation +// takes care of updating the toplevel. Until the commit happens +// the toplevel itself remains unchanged. It is also possible to cancel +// a transaction. +// +// An important concept related to transactions is propagation. +// Changing a value may have various effects, for example it may +// change the result of a legal_values list expression, resulting in a +// conflict object having to be created or destroyed. Changing one +// value may result in other value changes, e.g. because of a +// default_value property. All this is "propagation", and may +// happen multiple times within a single transaction. +// +// Transaction objects are also used during load or unload operations, +// but those are a little bit special. In particular it is not possible +// to cancel such a transaction, there will have been updates to the +// toplevel. Using a transaction is convenient because there is a +// need for propagation. +// +// Currently a transaction should be deleted immediately after a +// commit or cancel. This may change in future, in that transaction +// objects can be used to hold undo information. +// +// +// The other big concept related to transactions is inference. +// Changing a value may result in one or more new conflicts being +// created. In some cases the library can figure out for itself how to +// resolve these conflicts, using an inference engine. There are +// parameters to control the operation of the inference engine, +// including whether it runs at all, what changes it is allowed +// to make automatically (usually default and inferred values can +// be updated, but not wizard or user values), and how much +// recursion will happen. +// +// Assuming a default setup in a GUI environment, a typical +// sequence of events would be: +// +// valuable->set_value(...) +// transact = CdlTransactionBody::make(valuable->get_toplevel()) +// valuable->set_value(transact, ...) +// transact->set_whole_value(valuable, ...) +// transact->propagate() +// while (!finished) +// transact->resolve() +// +// invoke inference callback +// transact->apply_solution() (1 or more times) +// transact->set_whole_value(valuable, ...) (1 or more times) +// transact->propagate() +// transact->commit() | transact->cancel() +// delete transact +// +// Note that the propagation steps have to be invoked explicitly, +// allowing multiple changes to be processed in one go. There is +// a utility function which combines the functionality from +// the first propagate() call up to but not including the +// transaction delete operator. +// +// +// The inference engine itself is a complicated beast. There are +// a number of interfaces, but at the end of the day it ends up +// creating a sub-transaction and trying to resolve a single +// conflict in that sub-transaction. The conflict may belong to +// the current transaction or it may be global. +// +// +// for each conflict of interest +// make sure that there is not already a valid solution +// check that the inference engine can handle it +// create a sub-transaction, associated with the conflict +// apply the conflict resolution code +// if the solution is ok +// install it +// else if the solution might e.g. overwrite a user value +// keep it, the user can decide during the inference callback +// +// The conflict resolution typically works by attempting to change +// one or more values in the sub-transaction, propagating them, +// and seeing what new conflicts get created. If no new conflicts +// get created and one or more existing conflicts go away, groovy. +// Otherwise recursion can be used to try to resolve the new +// conflicts, or other strategies can be explored. +// +// NOTE: what is really necessary is some way of keeping track of the +// "best" solution to date, and allow exploration of alternatives. +// Or possibly keep track of all solutions. That has to be left to +// a future version. + +//}}} +//{{{ CdlTransactionCommitCancelOp + +// ---------------------------------------------------------------------------- +// The CdlTransaction class has built-in knowledge of how to handle values, +// active state, and a few things like that. However there are also more +// complicated operations such as loading and unloading, instantiating +// items, etc. which also need to happen in the context of a transaction +// but which the transaction class does not necessarily know about +// itself - or at least, not in any detail. Since the libcdl core is +// intended to be useful in various contexts, some sort of extensibility +// is essential. +// +// This is achieved by an auxiliary class, CdlTransactionCommitCancelOp. +// Clients of the transaction class can have their own utility class +// which derives from this, and create suitable objects. The transaction +// class maintains a vector of the pending commit/cancel operations. +// +// Each CdlTransactionCommitCancelOp object has two member functions, +// one for when the transaction gets committed and one for when it +// gets cancelled. If a sub-transaction gets committed then its +// pending ops are transferred across to the parent, allowing the +// parent to be cancelled sensibly: the commit ops only get run for +// the toplevel transaction. If a sub-transaction gets cancelled then +// the pending ops are invoked immediately. +// +// There is an assumption that commit/cancel ops get executed strictly +// in FIFO order. Specifically, commit ops get run from first one to +// the last one, allowing later operations in the transaction to +// overwrite earlier ones. Cancel ops get run in reverse order. + +class CdlTransactionCommitCancelOp { + friend class CdlTest; + + public: + + CdlTransactionCommitCancelOp() { } + virtual ~CdlTransactionCommitCancelOp() { }; + + // The default implementations of both of these do nothing. + // Derived classes should override at least one of these + // functions. + virtual void commit(CdlTransaction transaction) { + CYG_UNUSED_PARAM(CdlTransaction, transaction); + } + virtual void cancel(CdlTransaction transaction) { + CYG_UNUSED_PARAM(CdlTransaction, transaction); + } + + protected: + + private: +}; + +//}}} +//{{{ CdlTransaction class + +class CdlTransactionBody { + + friend class CdlTest; + + friend class CdlConflictBody; + friend class CdlValuableBody; + + public: + + // Create a toplevel transaction + static CdlTransaction make(CdlToplevel); + virtual ~CdlTransactionBody(); + CdlToplevel get_toplevel() const; + + // Or a sub-transaction. Usually these are created in the context of + // a conflict that is being resolved. + CdlTransaction make(CdlConflict = 0); + CdlTransaction get_parent() const; + CdlConflict get_conflict() const; + + // Commit all the changes. Essentially this means transferring + // all of the per-transaction data to the toplevel, and then + // invoking the transaction callback. All propagation, inference, + // etc. should happen before the commit() + // This routine can also be used to transfer changes from a + // sub-transaction to the parent. + void commit(); + + // A variant of the commit() operation can be used to + // store a sub-transaction in a conflict's solution vector, + // rather than updating the parent transaction. This is useful + // for inferred solutions which cannot be applied without + // user confirmation + void save_solution(); + + // Can a solution held in a sub-transaction be applied without + // e.g. overwriting a user value with an inferred value? + bool user_confirmation_required() const; + + // If the user has explicitly changed a value in the current transaction + // then the inference engine should not undo this or suggest a solution + // that will undo the change. + bool changed_by_user(CdlValuable) const; + + // A variant which is used for checking the hierarchy when disabling + // a container + bool subnode_changed_by_user(CdlContainer) const; + + // Is one transaction preferable to another? + bool is_preferable_to(CdlTransaction) const; + + // Find out about per-transaction conflicts. This is particularly + // useful for the inference callback. The other containers can + // be accessed as well, for completeness. + const std::list& get_new_conflicts() const; + const std::list& get_new_structural_conflicts() const; + const std::vector& get_deleted_conflicts() const; + const std::vector& get_deleted_structural_conflicts() const; + const std::vector& get_resolved_conflicts() const ; + const std::list& get_global_conflicts_with_solutions() const; + const std::map& get_changes() const; + const std::set& get_activated() const; + const std::set& get_deactivated() const; + const std::set& get_legal_values_changes() const; + + // Manipulate the current set of conflicts, allowing for nested + // transactions and toplevel conflicts as well. + void clear_conflict(CdlConflict); + bool has_conflict_been_cleared(CdlConflict); + + bool has_conflict(CdlNode, bool (*)(CdlConflict)); + CdlConflict get_conflict(CdlNode, bool (*)(CdlConflict)); + void get_conflicts(CdlNode, bool (*)(CdlConflict), std::vector&); + void clear_conflicts(CdlNode, bool (*)(CdlConflict)); + bool has_conflict(CdlNode, CdlProperty, bool (*)(CdlConflict)); + CdlConflict get_conflict(CdlNode, CdlProperty, bool (*)(CdlConflict)); + void get_conflicts(CdlNode, CdlProperty, bool (*)(CdlConflict), std::vector&); + void clear_conflicts(CdlNode, CdlProperty, bool (*)(CdlConflict)); + + bool has_structural_conflict(CdlNode, bool (*)(CdlConflict)); + CdlConflict get_structural_conflict(CdlNode, bool (*)(CdlConflict)); + void get_structural_conflicts(CdlNode, bool (*)(CdlConflict), std::vector&); + void clear_structural_conflicts(CdlNode, bool (*)(CdlConflict)); + bool has_structural_conflict(CdlNode, CdlProperty, bool (*)(CdlConflict)); + CdlConflict get_structural_conflict(CdlNode, CdlProperty, bool (*)(CdlConflict)); + void get_structural_conflicts(CdlNode, CdlProperty, bool (*)(CdlConflict), std::vector&); + void clear_structural_conflicts(CdlNode, CdlProperty, bool (*)(CdlConflict)); + + // During the inference callback the user may decide to + // apply one or more of the solutions. + void apply_solution(CdlConflict); + void apply_solutions(const std::vector&); + void apply_all_solutions(); + + // Cancel all the changes done in this transaction. Essentially + // this just involves clearing out all the STL containers. + void cancel(); + + // Support for commit/cancel ops. These are used for + // e.g. load and unload operations. + void add_commit_cancel_op(CdlTransactionCommitCancelOp *); + void cancel_last_commit_cancel_op(); + CdlTransactionCommitCancelOp* get_last_commit_cancel_op() const; + const std::vector& get_commit_cancel_ops() const; + + // Propagation support + void add_active_change(CdlNode); + void add_legal_values_change(CdlValuable); + void propagate(); + bool is_propagation_required() const; + + // Inference engine support. + void resolve(int = 0); // Process the new conflicts raised by this transaction + void resolve(CdlConflict, int = 0); + void resolve(const std::vector&, int = 0); + + // An auxiliary function called by the inference engine to perform recursion + bool resolve_recursion(int); + + // This function combines propagation, inference, and commit + // in one easy-to-use package + void body(); + + // Changes. + // There is a call to get hold of a CdlValue reference. Modifications + // should happen via a sequence of the form: + // + // valuable->set_value(transact, ...) + // const CdlValue& old_value = transact->get_whole_value(CdlValuable); + // CdlValue new_value = old_value; + // + // transact->set_whole_value(CdlValuable, old_value, new_value); + // + // When appropriate the get_whole_value() call takes care of + // updating the current conflict's solution_references vector. The + // set_whole_value() call updated the per-transaction changes map, + // and also stores sufficient information to support propagation. + // set_whole_value() requires both the old and new values, so + // that propagation can be optimized. + const CdlValue& get_whole_value(CdlConstValuable) const; + void set_whole_value(CdlValuable, const CdlValue&, const CdlValue&); + + // Control over active vs. inactive also needs to happen inside + // transactions + bool is_active(CdlNode) const; + void set_active(CdlNode, bool); + + // Callback and parameter settings + static void (*get_callback_fn())(const CdlTransactionCallback&); + static void set_callback_fn(void (*)(const CdlTransactionCallback&)); + static void set_inference_callback_fn(CdlInferenceCallback); + static CdlInferenceCallback get_inference_callback_fn(); + static void enable_automatic_inference(); + static void disable_automatic_inference(); + static bool is_automatic_inference_enabled(); + static void set_inference_recursion_limit(int); + static int get_inference_recursion_limit(); + // The override indicates the highest level of value source that the + // library can overwrite without needing user confirmation. The + // default value is CdlValueSource_Inferred, indicating that the + // library can overwrite default and inferred values but not + // wizard or user values. + static void set_inference_override(CdlValueSource); + static CdlValueSource get_inference_override(); + + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + + private: + + CdlTransactionBody(CdlToplevel, CdlTransaction, CdlConflict); + + // The associated toplevel and optionally the parent transaction + // and the conflict being worked on + CdlToplevel toplevel; + CdlTransaction parent; + CdlConflict conflict; + + // Per-transaction information. All value changes, new conflicts + // etc. first live in the context of a transaction. The global + // configuration only gets updated if the transaction is commited. + // There is also a vector of the pending commit/cancel ops. + std::vector commit_cancel_ops; + std::map changes; + std::list new_conflicts; + std::list new_structural_conflicts; + std::vector deleted_conflicts; // Existing global ones + std::vector deleted_structural_conflicts; + std::vector resolved_conflicts; // New ones already fixed by the inference engine + std::list global_conflicts_with_solutions; + std::set activated; + std::set deactivated; + std::set legal_values_changes; + bool dirty; + + // Change propagation. It is necessary to keep track of all + // pending value changes, active changes, and of things being + // loaded or unloaded. The set_value() call is used to update the + // value_changes container. + std::deque value_changes; + std::deque active_changes; + + + // Control over the inference engine etc. + static CdlInferenceCallback inference_callback; + static bool inference_enabled; + static int inference_recursion_limit; + static CdlValueSource inference_override; + static void (*callback_fn)(const CdlTransactionCallback&); + + enum { + CdlTransactionBody_Invalid = 0, + CdlTransactionBody_Magic = 0x3f91e4df + } cdltransactionbody_cookie; + + // Illegal operations + CdlTransactionBody(); + CdlTransactionBody(const CdlTransactionBody &); + CdlTransactionBody& operator=(const CdlTransactionBody&); +}; + +//}}} +//{{{ CdlTransactionCallback + +// ---------------------------------------------------------------------------- +// The callback class is used to inform applications about all the +// changes that are happening, including side effects. Application +// code can install a callback function which gets invoked at the +// end of every transaction. +// +// NOTE: this implementation is preliminary. In particular it is +// not extensible, it only deals with changes relevant to software +// configurations. + +class CdlTransactionCallback { + + friend class CdlTest; + friend class CdlTransactionBody; + + public: + CdlTransactionCallback(); + ~CdlTransactionCallback(); + static void (*get_callback_fn())(const CdlTransactionCallback&); + static void set_callback_fn(void (*)(const CdlTransactionCallback&)); + + // active_changes and legal_values_changes get updated as the + // transaction proceeds, so a set implementation is more + // efficient. The others get filled in during a commit operation. + // A transaction may result in multiple conflicts for a given node + // being eliminated, so again a set is appropriate. For the others + // there is no possibility of duplicates so a vector is better. + std::vector value_changes; + std::vector active_changes; + std::vector legal_values_changes; + std::vector value_source_changes; + std::vector new_conflicts; + std::vector new_structural_conflicts; + std::vector nodes_with_resolved_conflicts; + std::vector nodes_with_resolved_structural_conflicts; + + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + + protected: + + private: + + enum { + CdlTransactionCallback_Invalid = 0, + CdlTransactionCallback_Magic = 0x0cec3a95 + } cdltransactioncallback_cookie; +}; + +//}}} +//{{{ CdlLocalTransaction + +// ---------------------------------------------------------------------------- +// A utility class to create a per-function transaction object which gets +// cleaned up automatically should an exception happen. + +class CdlLocalTransaction { + + friend class CdlTrest; + + public: + CdlLocalTransaction(CdlToplevel toplevel) { + transaction = CdlTransactionBody::make(toplevel); + } + ~CdlLocalTransaction() { + // The destructor may get invoked during exception handling. + // It is assumed that cancelling the transaction would be a + // good thing when that happens. Normal operation should + // go through the body() or commit() members, which clear + // the transaction field. + // There is a slight consistency here. Normally after a + // transaction commit the transaction object is still + // around. Here the transaction object get deleted. This + // is unlikely to matter in practice. + if (0 != transaction) { + transaction->cancel(); + delete transaction; + } + } + CdlTransaction get() { + return transaction; + } + void body() { + transaction->body(); + delete transaction; + transaction = 0; + } + void commit() { + transaction->commit(); + delete transaction; + transaction = 0; + } + void propagate() { + transaction->propagate(); + } + void destroy() { + if (0 != transaction) { + transaction->cancel(); + delete transaction; + transaction = 0; + } + } + + private: + CdlTransaction transaction; + CdlLocalTransaction(); +}; + +//}}} + +//}}} +//{{{ Build and define information + +//{{{ Description + +// ---------------------------------------------------------------------------- +// There are two related concepts: buildable components, and +// definable components. The former typically refers to compiling +// sources files to produce libraries, although other types of build +// are possible. The latter refers to generating header files +// containing the current configuration data. Typically any loadable +// that is buildable is also definable, so that the source files can +// #include the appropriate generated headers and adapt to the +// configuration data that way. The inverse is not true: for example +// in HCDL it may be appropriate to generate a header file but there +// is nothing to be compiled, device drivers are software packages. +// +// The relevant base classes are as follows: +// +// 1) CdlBuildable - this object can have build-related properties. +// All buildables are also valuables. +// 2) CdlBuildLoadable - this is a base class for loadables, providing +// some extra properties that are relevant for +// loadables that can involve builds. +// 3) CdlDefinable - this object can result in #define's in a +// header file. All exportables are also +// valuables. +// 4) CdlDefineLoadable - this is a base class for any loadables that +// can contain buildables. +// +// Support for both buildable and exportable components is part of the +// core library for now. This may change in future, depending on how +// many CDL variants get implemented. +// +// There are various properties related to building. First, the +// ones applicable to the CdlBuildLoadable class. +// +// 1) library xyz. +// This specifies the default library for anything built in this +// loadable. If there is no library property then it defaults to +// libtarget.a (or rather to a class static that happens to be +// initialized to libtarget.a) +// +// 2) include_dir . +// This specifies where the loadable's exported header files should +// end up. The default value is the toplevel, but e.g. the eCos +// kernel specifies an include_dir of cyg/kernel. Note that fixed +// header files are associated with buildables, not definables, +// the latter deal with generated header files only. +// +// 3) include_files +// The recommended directory hierarchy for non-trivial packages +// involves separate subdirectories src, include, cdl, doc, and +// test. This is too heavyweight for very simple packages where it +// is better to keep everything in just one directory. However that +// introduces a potential conflict between public and private +// header files, which can be resolved by the include_files +// property. The actual rules are: +// +// a) if there an include_files property, that lists all the +// headers that should be exported. +// +// b) else if there is an include subdirectory, it is assumed that +// all files below that should be exported. +// +// c) otherwise all files matching a suitable glob pattern should +// be exported. The default pattern is *.h *.hxx *.inl, but can +// be overwritten. +// +// 4) makefile +// This allows component developers to provide a GNU makefile to be +// used for building, rather than specify the relevant information +// via properties. +// NOTE: this property is ignored for now. It is roughly +// equivalent to a custom build step where the command is +// "make -C -f ", but in addition it is necessary to +// worry about phony targets for default, clean, etc. +// +// A DefineLoadable adds the following property: +// +// 1) define_header +// This specifies the header file that will be generated. If this +// property is absent then the library will generate a default one +// based on the loadable's name, by discarding everything up to and +// including the first underscore, lowercasing the rest, and +// appending .h. For example, CYGPKG_KERNEL would result in a +// header file kernel.h. +// +// Hardware packages have an implicit "define_header hardware.h" +// property. +// +// A buildable has the following properties: +// +// 1) compile [-library xyz] ... +// This specifies one or more files that need to be compiled. +// By default the resulting object files will go into the +// current library (set via a higher-level library or +// defaulting to libtarget.a). +// +// Legitimate filename suffixes for compile statements are .c, .cxx +// and .S. Further suffixes may be supported in future. In the +// long term we will need some external data files defining how +// the various suffixes should be handled. +// +// Associated with every compilation are details of the compiler to +// be used and the compiler flags. For now no attempt is made +// to do anything interesting in this area, although there is +// sufficient information in the database for the needs of +// command line tools. +// +// Longer term there are complications. Packages may want some +// control over the compiler flags that should be used, e.g. +// "requires {!(flags ~= ".*-fno-rtti.*")}" to guarantee that the +// compiler flags do not include -fno-rtti, rather useful if the +// package's source code depends on that language feature. Mixed +// architecture systems (e.g. ARM/Thumb) will cause problems when +// it comes to selecting the compiler. The exact means by which +// all this will work is not yet clear. +// +// 2) object [-library xyz] ... +// This specifies one or more pre-built object files that should +// go into the appropriate library. +// +// The problem here is coping with different architectures, and for +// many architectures it will also be necessary to worry about +// multilibs. Third party component vendors are unlikely to supply +// separate object files for every supported architecture and every +// valid multilib within those architectures, so there are +// constraints on the multilib-related compiler flags used for +// building other packages and the application itself. +// +// NOTE: this property is ignored for now. +// +// 3) make_object [-library xyz] [-priority pri] +// +// For example: +// +// make_object toyslock.o { +// toyslock.o : toyslock.y +// yacc toyslock.y +// $(CC) $(CFLAGS) -o toyslock.o y.tab.c +// } +// +// This defines a custom build step for an object file that +// should go into a particular directory. A makefile syntax +// is used to define the rule simply because it is likely +// to be familiar to package developers, and does not +// imply that the builds will happen via a makefile. +// +// The optional priority field indicates at which stage during +// the build the rule should trigger. The default value is +// 100, which is the same as for all files specified in +// "compile" properties. A lower value means that the object +// will be generated earlier. Libraries are generated at +// priority 200, and "make" properties normally execute at +// priority 300. +// NOTE: it is not clear yet whether supporting priorities +// in this way is a good idea, or whether the dependencies +// information could be used instead. +// +// Unresolved issues: +// +// a) what commands can be used in the build rules? There +// should be a core set of supported commands, as per +// an eCos toolchain build. It should also be possible +// for packages to provide their own host tools. +// +// For sourceware folks, moving away from a single toolchain +// tarball and expecting them to download and install +// egcs, binutils and gdb separately is actually a bad +// idea in this regard, it makes it much more likely that +// some users will have an incomplete tools installation and +// hence that builds will fail. +// +// b) there is an obvious need for variable substitution in the +// rules, e.g. $(CC). At what stage do these variables get +// expanded, and where does the required information live? +// +// c) who is responsible for header file dependency analysis? +// Should the rules be modified automatically to do this, +// or do we leave this to the package developer? It may be +// very hard to do the former, but the latter will cause +// problems for IDE integration. +// +// d) in which directory will the rules get run? What prevents +// filename conflicts between different packages? +// +// NOTE: make_object is not actually required just yet, but the +// issues are much the same as for the "make" property which is +// required. +// +// 4) make [-priority pri] +// +// For example: +// +// make target.ld { +// target.ld : arm.ld +// $(CC) -E -P -xc $(CFLAGS) -o $@ $< +// } +// +// This defines a custom build step for a target that is not going +// to end up in a library. The main such targets at the moment are +// the linker script, vectors.o, and extras.o, but there may well +// be others in future. +// +// The default priority for "make" properties is 300, which means +// that the build rules trigger after all normal compilations and +// after the libraries are generated. It is possible to specify +// custom build steps that should run before any compilations +// using a priority < 100. +// +// Unresolved issues: +// +// a) what commands can be used? +// +// b) variable substitution? +// +// c) header file dependency analysis? +// +// d) directories and filenames? +// +// e) where should the resulting files end up? Currently they can +// all go into $(PREFIX)/lib, but in the long term we may +// need to be a bit more flexible. +// +// 5) build_proc +// +// This defines some Tcl code that should be run prior to any +// build, for example to generate a source file. It must run +// within the appropriate loadable's Tcl interpreter so that +// it can query the current configuration. +// +// NOTE: this property is not implemented yet. +// +// +// A definable has the following properties: +// +// 1) no_define +// Usually the library will generate either one or two #define's +// for every definable, inside the current header file. This can be +// suppressed by the no_define property, which is typically +// accompanied by some other #define-related property such as +// define_proc or define. +// +// 2) define [-file ] [-format ] symbol +// This will result in an additional #define for the specified +// symbol in the specified file. The only filenames that are valid +// are the loadable's current filename (as per define_header), and +// the global header file system.h. Use of the latter should be +// avoided. +// +// The optional format string behaves as per the define_format +// property below. +// +// 3) define_format +// This is only relevant for booldata or data flavors. By default +// two #define's will be generated (assuming the valuable is active +// and enabled): +// +// #define value +// #define _value +// +// The latter will only be generated if the resulting symbol is +// a valid C preprocessor symbol, and is intended to allow the +// use of #ifdef as well as #ifdef (useful if the value is +// non-numerical). +// +// The define_format property provides control over the first of +// these two #defines. The net result is that the #define will be +// generated by evaluating the following Tcl fragment: +// +// set result "#define [ ]" +// +// Command and variable substitution are available if desired, +// but for anything that complicated the define_proc property +// is normally more useful. +// +// define_format is only applicable to the default definition, +// so it cannot be used in conjunction with no_define. The +// define property supports a -format option. +// +// 4) define_proc +// This specifies some Tcl code that should be run when header +// file generation takes place, in addition to any #define's +// generated by default or courtesy of define properties. +// The define_proc property is commonly used in conjunction with +// no_define, but this is not required. +// +// There will be two channels already set up: cdl_header +// for the current loadable, and cdl_system_header for system.h. +// Writing data to system.h should be avoided. +// +// 5) if_define + +// This property provides direct support for a common programming +// paradigm. It allows direct generation of code like the +// following: +// +// #ifdef CYGSRC_TOYS_BLOCKS +// # define CYGDBG_INFRA_USE_PRECONDITIONS 1 +// #endif +// +// In this case CYGSRC_TOYS_BLOCKS is the condition and +// CYGDBG_INFRA_USE_PRECONDITIONS is the symbol. The +// #ifdef/#define sequence will be generated in addition to +// any other #define's resulting from the default behaviour, +// the define property, or the define_proc property. It is +// not affected by no_define. + +//}}} +//{{{ The build process + +// ---------------------------------------------------------------------------- +// For command-line operation the steps involved in doing a build are: +// +// 1) work out what needs to be built. +// +// 2) generate a build and install tree. This involves making sure that +// the various directories exist and are accessible. +// +// 3) generate or update the toplevel makefile. +// +// 4) generate the configuration header files. +// +// For operation in an IDE steps (2) and (3) will be handled by +// different code. +// +// There is a library call to get hold of all the build information: +// +// config->get_build_info(CdlBuildInfo &info); +// +// This erases anything previously present in the build-info argument +// and fills in the information appropriate to the current +// configuration, essentially by walking down the list of loadables +// and each loadable's list of nodes, checking for BuildLoadables +// and Buildables along the way. The BuildInfo class is defined +// further down. +// +// An alternative library call can be used to find out about all +// possible files that need to be compiled etc., irrespective of the +// current configuration settings. This could be useful when it +// comes to letting the user control compiler flags etc. +// +// config->get_all_build_info(CdlBuildInfo& info); +// +// There is another library call for step (4): +// +// config->generate_config_headers(std::string directory) +// throw(CdlInputOutputException, std::bad_alloc); +// +// This will create or update the header files appropriate to +// the current configuration. Temporary files will be generated, +// diff'ed with the current version, and existing files will +// only be modified if necessary. The directory argument +// indicates where the header files should go, i.e. it should +// be the equivalent of $(PREFIX)/include/pkgconf +// +// This library call does not delete any files it does not +// recognize, that is the responsibility of higher-level code. +// It is possible to get or update a list of the files that +// will be generated: +// +// config->get_config_headers(std::vector& headers) +// +// The argument will be cleared if necessary and then filled in with +// the current set of header files. Higher level code can compare the +// result with the current files in the directory and take or suggest +// remedial action. +// +// There is also a library call which combines all four stages: +// +// config->generate_build_tree(std::string build_tree, std::string prefix = $(BUILD)/install) +// +// +// The order in which the various build steps happen is important. +// +// 1) non-configuration headers must be copied from the component +// repository into $(PREFIX)/include. No compiles can happen +// before this. +// +// 2) all compile properties can happen in parallel. These have an +// effective priority of 100. +// +// 3) all make_object priorities can happen in parallel with +// compiles. These have a default priority of 100, but the +// priority can be modified. +// +// 4) the generated objects and any pre-built objects should be +// incorporated into the appropriate library. This happens +// at priority 200. +// +// 5) custom build steps associated with "make" properties should +// now run. These have a default priority of 300, but it is +// possible to override this. +// +// Usually all source files will come from the component repository, +// which means that they are read-only. Ideally it should also be +// possible for a source file to be copied into the build tree and +// edited there, and subsequent builds should pick up the copy rather +// than the original. The build data generated by libcdl will always +// be in the form of relative pathnames to facilitate this. + +//}}} +//{{{ CdlBuildInfo class + +// ---------------------------------------------------------------------------- +// Extracting the build information. +// +// libcdl.a defines the following classes related to build information. +// +// CdlBuildInfo +// CdlBuildInfo_Loadable +// CdlBuildInfo_Header +// CdlBuildInfo_Compile +// CdlBuildInfo_Object +// CdlBuildInfo_MakeObject +// CdlBuildInfo_Make +// +// The build information is organized on a per-loadable basis. +// Higher-level code may choose to flatten this or to keep the +// distinction. A CdlBuildInfo object is primarily a vector of +// CdlBuildInfo_Loadable objects. CdlBuildInfo objects can be created +// statically. +// +// In turn, each CdlBuildInfo_Loadable object is primarily a +// collection of five vectors, one each for Header, Compile, Object, +// MakeObject and Make. +// +// All pathnames in these data structures will use forward slashes as +// the directory separator, irrespective of the host platform. All +// pathnames will be relative. + +struct CdlBuildInfo_Header { + std::string source; /* include/cyg_ass.h */ + std::string destination; /* cyg/infra/cyg_ass.h */ +}; + +struct CdlBuildInfo_Compile { + std::string library; /* libtarget.a */ + std::string source; /* src/fancy.cxx */ + // Compiler and cflags data may be added in future. +}; + +struct CdlBuildInfo_Object { + std::string library; /* libtarget.a */ + std::string object; /* obj/hello.o */ +}; + +struct CdlBuildInfo_MakeObject { + cdl_int priority; /* 100 */ + std::string library; /* libtarget.a */ + std::string object; /* toyslock.o */ + std::string deps; /* toyslock.y */ + /* + It is not clear whether the deps field is actually useful in the + context of IDE integration, but see the note about arm.inc + above. + */ + std::string rules; + /* + A typical value for "rules" might be: + + yacc toyslock.y + $(CC) $(CFLAGS) -o toyslock.o y.tab.c + + Leading white space is not significant. Newlines are significant. + Backslash escapes in the text will not have been processed yet. + */ +}; + +struct CdlBuildInfo_Make { + cdl_int priority; /* 300 */ + std::string target; /* extras.o */ + std::string deps; /* libextras.a */ + std::string rules; + /* + Something like: + + $(CC) $(ARCHFLAGS) $(LDARCHFLAGS) -nostdlib -Wl,-r -Wl,--whole-archive $(PREFIX)/lib/libextras.a -o $(PREFIX)/lib/extras.o + + */ +}; + +class CdlBuildInfo_Loadable { + + friend class CdlTest; + + public: + std::string name; /* CYGPKG_INFRA */ + std::string directory; /* infra/current */ + std::vector headers; + std::vector compiles; + std::vector objects; + std::vector make_objects; + std::vector makes; + + protected: + + private: +}; + +class CdlBuildInfo { + + friend class CdlTest; + + public: + + std::vector entries; + + protected: + + private: +}; + +//}}} +//{{{ CdlBuildLoadable + +// ---------------------------------------------------------------------------- +// BuildLoadables are derived from Loadables and are appropriate for +// any loadables that can contain build information. There are a +// number of properties applicable at this level: makefile, +// include_dir, include_files and library. The main interface of +// interest is update_build_info(). +// +// It is likely that all BuildLoadables are also Buildables, but this +// is not required. + +class CdlBuildLoadableBody : virtual public CdlLoadableBody +{ + friend class CdlTest; + + public: + virtual ~CdlBuildLoadableBody(); + + // This is the main way to extract information about what should + // get built. It takes into account the active and enabled states, + // as appropriate. + void update_build_info(CdlBuildInfo&) const; + + // An alternative which ignores the active and enabled states. + void update_all_build_info(CdlBuildInfo&) const; + + // Property parsers and validation code appropriate for a + // build-loadable object such as makefile + static void add_property_parsers(std::vector& parsers); + void check_properties(CdlInterpreter); + static int parse_library(CdlInterpreter, int, char**); + static int parse_makefile(CdlInterpreter, int, char**); + static int parse_include_dir(CdlInterpreter, int, char**); + static int parse_include_files(CdlInterpreter, int, char**); + + // By default any compiled files will go into libtarget.a, which + // is the default value for this variable. Individual applications may + // specify an alternative default library. + static char* default_library_name; + + // When filling in a build_info structure the library needs to know + // what constitutes a header file. A glob pattern can be used for this. + // NOTE: in the long term this should come out of a data file. + static char* default_headers_glob_pattern; + + virtual std::string get_class_name() const; + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + CdlBuildLoadableBody(); + + private: + + enum { + CdlBuildLoadableBody_Invalid = 0, + CdlBuildLoadableBody_Magic = 0x55776643 + } cdlbuildloadablebody_cookie; + + // Illegal operations + CdlBuildLoadableBody(const CdlBuildLoadableBody&); + CdlBuildLoadableBody& operator=(const CdlBuildLoadableBody&); +}; + +//}}} +//{{{ CdlBuildable + +// ---------------------------------------------------------------------------- +// Buildable objects can have properties such as compile and +// make_object. These properties are not normally accessed +// directly. Instead there is a member function to update a +// CdlBuildInfo_Loadable object. +// +// The build properties for a given buildable have an effect iff +// that buildable is active, and in addition if the buildable is also +// a valuable then it must be enabled. + +class CdlBuildableBody : virtual public CdlNodeBody +{ + + friend class CdlTest; + + public: + virtual ~CdlBuildableBody(); + + // This is the main way to extract information about what should + // get built. It takes into account the active and enabled states, + // as appropriate. The second argument indicates the default + // library for the current loadable. + void update_build_info(CdlBuildInfo_Loadable&, std::string) const; + + // An alternative which ignores the active and enabled states. + void update_all_build_info(CdlBuildInfo_Loadable&, std::string) const; + + // Add property parsers and validation code appropriate for a + // buildable object such as compile and make_object + static void add_property_parsers(std::vector& parsers); + void check_properties(CdlInterpreter); + + static int parse_build_proc(CdlInterpreter, int, char**); + static int parse_compile(CdlInterpreter, int, char**); + static int parse_make(CdlInterpreter, int, char**); + static int parse_make_object(CdlInterpreter, int, char**); + static int parse_object(CdlInterpreter, int, char**); + static bool split_custom_build_step(std::string /* data */, std::string& /* target */, std::string& /* deps */, + std::string& /* rules*/, std::string& /* error_msg */); + + virtual std::string get_class_name() const; + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + CdlBuildableBody(); + + private: + + enum { + CdlBuildableBody_Invalid = 0, + CdlBuildableBody_Magic = 0x16eb1c04 + } cdlbuildablebody_cookie; + + // Illegal operations + CdlBuildableBody(const CdlBuildableBody&); + CdlBuildableBody& operator=(const CdlBuildableBody&); +}; + +//}}} +//{{{ CdlDefineLoadable + +// ---------------------------------------------------------------------------- +// DefineLoadables are derived from Loadables and are appropriate for +// any loadables that can result in generated header files containing +// configuration data. There is one applicable property, +// define_header. The main interface of interest is +// generate_config_headers(). + +class CdlDefineLoadableBody : virtual public CdlLoadableBody +{ + + friend class CdlTest; + + public: + virtual ~CdlDefineLoadableBody(); + + // Update the header file for this loadable. The first argument + // is a channel to the loadable-specific header file. The second + // argument is a channel to the global header file. + void generate_config_header(Tcl_Channel, Tcl_Channel) const + throw(CdlInputOutputException, std::bad_alloc); + + // What header file should be generated for this loadable? + virtual std::string get_config_header() const; + + // Add property parsers and validation code. + static void add_property_parsers(std::vector& parsers); + void check_properties(CdlInterpreter); + static int parse_define_header(CdlInterpreter, int, char**); + + virtual std::string get_class_name() const; + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + CdlDefineLoadableBody(); + + private: + + enum { + CdlDefineLoadableBody_Invalid = 0, + CdlDefineLoadableBody_Magic = 0x7e211709 + } cdldefineloadablebody_cookie; + + // Illegal operations + CdlDefineLoadableBody(const CdlDefineLoadableBody&); + CdlDefineLoadableBody& operator=(const CdlDefineLoadableBody&); +}; + +//}}} +//{{{ CdlDefinable + +// ---------------------------------------------------------------------------- +// Definables are derived from Valuables and provide support for +// outputting a configuration header file. + +class CdlDefinableBody : virtual public CdlValuableBody +{ + + friend class CdlTest; + + public: + virtual ~CdlDefinableBody(); + + // Update the header file for this definable. The loadable's Tcl + // interpreter will already have channels cdl_header and + // cdl_system_header set up appropriately. + void generate_config_header( Tcl_Channel, Tcl_Channel) const + throw(CdlInputOutputException, std::bad_alloc); + + // Add property parsers and validation code. + static void add_property_parsers(std::vector& parsers); + void check_properties(CdlInterpreter); + static int parse_define(CdlInterpreter, int, char**); + static int parse_define_format(CdlInterpreter, int, char**); + static int parse_define_proc(CdlInterpreter, int, char**); + static int parse_if_define(CdlInterpreter, int, char**); + static int parse_no_define(CdlInterpreter, int, char**); + + virtual std::string get_class_name() const; + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + protected: + CdlDefinableBody(); + + private: + + enum { + CdlDefinableBody_Invalid = 0, + CdlDefinableBody_Magic = 0x65a2c95a + } cdldefinablebody_cookie; + + // Illegal operations + CdlDefinableBody(const CdlDefinableBody&); + CdlDefinableBody& operator=(const CdlDefinableBody&); +}; + +//}}} + +//}}} +//{{{ CdlDialog + +// ---------------------------------------------------------------------------- +// A dialog simply inherits from CdlUserVisible and provides convenient +// access to several dialog-specific properties. + +class CdlDialogBody : + public virtual CdlUserVisibleBody, + public virtual CdlParentableBody +{ + friend class CdlTest; + + public: + + virtual ~CdlDialogBody(); + + // Dialogs may be enabled or disabled globally. This affects + // CdlValuable::get_widget_hint() if the valuable has an associated + // custom dialog. + static void disable_dialogs(); + static void enable_dialogs(); + static bool dialogs_are_enabled(); + + bool has_init_proc() const; + bool has_update_proc() const; + const cdl_tcl_code& get_init_proc() const; + const cdl_tcl_code& get_update_proc() const; + const cdl_tcl_code& get_display_proc() const; + const cdl_tcl_code& get_confirm_proc() const; + const cdl_tcl_code& get_cancel_proc() const; + + static int parse_dialog(CdlInterpreter, int, char**); + static int parse_display_proc(CdlInterpreter, int, char**); + static int parse_update_proc(CdlInterpreter, int, char**); + + // Persistence support. Dialogs should just be ignored when it + // comes to saving and restoring files. + virtual void save(CdlInterpreter, Tcl_Channel, int, bool) throw(CdlInputOutputException, std::bad_alloc); + + virtual std::string get_class_name() const; + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + private: + // The constructor only gets invoked from inside parse_dialog() + CdlDialogBody(std::string); + + static bool dialogs_enabled; + + enum { + CdlDialogBody_Invalid = 0, + CdlDialogBody_Magic = 0x3f4df391 + } cdldialogbody_cookie; + + // Illegal operations. The dialog name must be known at the time + // that the object is constructed. + CdlDialogBody(); + CdlDialogBody(const CdlDialogBody&); + CdlDialogBody& operator=(const CdlDialogBody&); +}; + +//}}} +//{{{ CdlWizard + +// ---------------------------------------------------------------------------- +// A wizard is very much like a dialog, just a different set of properties. + +class CdlWizardBody : + public virtual CdlUserVisibleBody, + public virtual CdlParentableBody +{ + friend class CdlTest; + + public: + + virtual ~CdlWizardBody(); + + bool has_init_proc() const; + bool has_decoration_proc() const; + const cdl_tcl_code& get_init_proc() const; + const cdl_tcl_code& get_decoration_proc() const; + const cdl_tcl_code& get_confirm_proc() const; + const cdl_tcl_code& get_cancel_proc() const; + bool has_screen(cdl_int) const; + cdl_int get_first_screen_number() const; + const cdl_tcl_code& get_first_screen() const; + const cdl_tcl_code& get_screen(cdl_int) const; + static int parse_wizard(CdlInterpreter, int, char**); + static int parse_cancel_proc(CdlInterpreter, int, char**); + static int parse_confirm_proc(CdlInterpreter, int, char**); + static int parse_decoration_proc(CdlInterpreter, int, char**); + static int parse_init_proc(CdlInterpreter, int, char**); + static int parse_screen(CdlInterpreter, int, char**); + + // Persistence support. Wizards should just be ignored when it + // comes to saving and restoring files. + virtual void save(CdlInterpreter, Tcl_Channel, int, bool) throw(CdlInputOutputException, std::bad_alloc); + + virtual std::string get_class_name() const; + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + private: + // The constructor only gets invoked from inside parse_wizard(). + CdlWizardBody(std::string); + + // Illegal operations. + CdlWizardBody(); + CdlWizardBody(const CdlWizardBody&); + CdlWizardBody& operator=(const CdlWizardBody&); + + enum { + CdlWizardBody_Invalid = 0, + CdlWizardBody_Magic = 0x4ec1c39a + } cdlwizardbody_cookie; +}; + +//}}} +//{{{ CdlInterface class + +// ---------------------------------------------------------------------------- +// Similarly for interfaces. + +class CdlInterfaceBody : public virtual CdlNodeBody, + public virtual CdlUserVisibleBody, + public virtual CdlValuableBody, + public virtual CdlParentableBody, + public virtual CdlBuildableBody, + public virtual CdlDefinableBody +{ + friend class CdlTest; + + public: + + ~CdlInterfaceBody(); + + void get_implementers(std::vector&) const; + void recalculate(CdlTransaction); + + static int parse_interface(CdlInterpreter, int, char**); + + // Persistence support. The interface data cannot sensibly be modified + // by users, it is all calculated. However it is useful to have the + // interface data present in the saved file so that users can examine + // dependencies etc. + virtual void save(CdlInterpreter, Tcl_Channel, int, bool) throw(CdlInputOutputException, std::bad_alloc); + static void initialize_savefile_support(CdlToplevel); + static int savefile_interface_command(CdlInterpreter, int, char**); + + bool was_generated() const; + virtual bool is_modifiable() const; + virtual std::string get_class_name() const; + bool check_this(cyg_assert_class_zeal = cyg_quick) const; + CYGDBG_DECLARE_MEMLEAK_COUNTER(); + + private: + CdlInterfaceBody(std::string, bool /* generated */); + bool generated; + + enum { + CdlInterfaceBody_Invalid = 0, + CdlInterfaceBody_Magic = 0x67f7fbe5 + } cdlinterfacebody_cookie; + CdlInterfaceBody(); + CdlInterfaceBody(const CdlInterfaceBody&); + CdlInterfaceBody& operator=(const CdlInterfaceBody&); +}; + +//}}} + +#endif /* !__CDLCORE_HXX */ +// EOF cdlcore.hxx diff --git a/host/libcdl/cdlmisc.cxx b/host/libcdl/cdlmisc.cxx new file mode 100644 --- /dev/null +++ b/host/libcdl/cdlmisc.cxx @@ -0,0 +1,1033 @@ +//{{{ Banner + +//============================================================================ +// +// cdlmisc.cxx +// +// Implementation of the various CDL utility member functions. +// +//============================================================================ +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================ +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contact(s): bartv +// Date: 1998/03/04 +// Version: 0.01 +// +//####DESCRIPTIONEND#### +//============================================================================ + +//}}} +//{{{ #include's + +// ---------------------------------------------------------------------------- +#include "cdlconfig.h" + +// Get the infrastructure types, assertions, tracing and similar +// facilities. +#include +#include + +// defines everything implemented in this module. +// It implicitly supplies , and because +// the class definitions rely on these headers. +#include + +// For access to the isdigit(), isupper(), tolower(), ... functions +#include + +// For access to sprintf(), specifically double to string conversions. +#include + +// For access to strtod() +#include + +// strtod() involves errno... +#include + +// For access to fmod() +#include + +// For access to DBL_DIG +#include + +//}}} + +//{{{ Cdl::is_valid_xxx() + +// --------------------------------------------------------------------------- + +bool +Cdl::is_valid_value_flavor(CdlValueFlavor data) +{ + bool result = false; + + switch(data) { + case CdlValueFlavor_None : + case CdlValueFlavor_Bool : + case CdlValueFlavor_BoolData : + case CdlValueFlavor_Data : + result = true; + break; + + default: + break; + } + + return result; +} + +bool +Cdl::is_valid_value_source(CdlValueSource data) +{ + bool result = false; + + switch(data) { + case CdlValueSource_Default : + case CdlValueSource_User : + case CdlValueSource_Wizard : + case CdlValueSource_Inferred : + result = true; + break; + + default: + break; + } + + return result; +} + +// ---------------------------------------------------------------------------- +// For now CDL names are restricted to what is acceptable to the C +// preprocessor. This may cause problems in future, e.g. i18n. + +bool +Cdl::is_valid_cdl_name(const std::string& name) +{ + CYG_REPORT_FUNCNAMETYPE("Cdl::is_valid_cdl_name", "result %d"); + + bool result = is_valid_c_preprocessor_symbol(name); + + CYG_REPORT_RETVAL(result); + return result; +} + +bool +Cdl::is_valid_c_preprocessor_symbol(const std::string& symbol) +{ + CYG_REPORT_FUNCNAMETYPE("Cdl::is_valid_c_preprocessor_symbol", "result %d"); + + bool result = true; + if ("" == symbol) { + result = false; + } else { + // A valid preprocessor symbol should begin with either an underscore + // or a letter. It should then be followed by some number of underscores, + // letters, or digits. + // + // In some locales isalpha() may succeed for characters which are not + // legal for C preprocessor symbols. Instead ASCII is assumed here. + if (('_' != symbol[0]) && + !(('a' <= symbol[0]) && (symbol[0] <= 'z')) && + !(('A' <= symbol[0]) && (symbol[0] <= 'Z'))) { + + result = false; + } else { + for (unsigned int i = 1; i < symbol.size(); i++) { + if (('_' != symbol[i]) && + !(('a' <= symbol[i]) && (symbol[i] <= 'z')) && + !(('A' <= symbol[i]) && (symbol[i] <= 'Z')) && + !(('0' <= symbol[i]) && (symbol[i] <= '9'))) { + + result = false; + break; + } + } + } + } + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ Cdl::xxx_to_yyy() - strings, ints, doubles, ... + +// --------------------------------------------------------------------------- +// Conversion routines between strings, integers, doubles, bools, ... +// +// Conversions to/from integers are complicated somewhat because the +// data type in question is cdl_int. In the initial implementation this +// is 64 bits. In the long term it will be arbitrary precision and +// the conversion routines will need to be reimplemented. +// +// ASCII rather than EBCDIC is assumed. +// +// Some of the routines may fail, e.g. string to integer conversions. +// Others are guaranteed to succeed. + +//{{{ string_to_integer() + +// ---------------------------------------------------------------------------- +bool +Cdl::string_to_integer(std::string data, cdl_int& target) +{ + CYG_REPORT_FUNCNAMETYPE("Cdl::string_to_integer", "success %d"); + + bool negative = false; + // Life is a bit easier if I can check for '\0' + const char* ptr = data.c_str(); + + // Not essential but harmless. + while (isspace(*ptr)) + ptr++; + + if ('-' == *ptr) { + negative = true; + ptr++; + } + + cdl_int acc = 0; + if ('0' == *ptr) { + // This happens sufficiently often to be worth a special case. + if ('\0' == ptr[1]) { + target = 0; + CYG_REPORT_RETVAL(true); + return true; + } + // Hex is always worth supporting. + if (('x' == ptr[1]) || ('X' == ptr[1])) { + ptr++; ptr++; + if (!isxdigit(*ptr)) { + CYG_REPORT_RETVAL(false); + return false; + } + while (isxdigit(*ptr)) { + cdl_int new_acc = acc * 16; + if (isdigit(*ptr)) { + new_acc += (*ptr - '0'); + } else if (('a' <= *ptr) && (*ptr <= 'f')) { + new_acc += (*ptr + 10 - 'a'); + } else if (('A' <= *ptr) && (*ptr <= 'F')) { + new_acc += (*ptr + 10 - 'A'); + } else { + CYG_FAIL("this platform's implementation of isxdigit() is broken"); + } + if (new_acc < acc) { + CYG_REPORT_RETVAL(false); + return false; + } + acc = new_acc; + ptr++; + } + if ('\0' != *ptr) { + CYG_REPORT_RETVAL(false); + return false; + } + if (negative) { + cdl_int new_acc = 0 - acc; + if (new_acc > 0) { + CYG_REPORT_RETVAL(false); + return false; + } else { + acc = new_acc; + } + } + target = acc; + CYG_REPORT_RETVAL(true); + return true; + } + + // Octal? Oh well, might as well be complete. + if (('0' <= ptr[1]) && (ptr[1] <= '7')) { + ptr++; + do { + cdl_int new_acc = 8 * acc; + new_acc += (*ptr - '0'); + if (new_acc < acc) { + CYG_REPORT_RETVAL(false); + return false; + } + acc = new_acc; + ptr++; + } while (('0' <= *ptr) && (*ptr <= '7')); + if ('\0' != *ptr) { + CYG_REPORT_RETVAL(false); + return false; + } + if (negative) { + cdl_int new_acc = 0 - acc; + if (new_acc > 0) { + CYG_REPORT_RETVAL(false); + return false; + } + else { + acc = new_acc; + } + } + target = acc; + CYG_REPORT_RETVAL(true); + return true; + } + + // Drop through for the case of a decimal. + } + + while(isdigit(*ptr)) { + cdl_int new_acc = 10 * acc; + new_acc += (*ptr - '0'); + if (new_acc < acc) { + CYG_REPORT_RETVAL(false); + return false; + } + acc = new_acc; + ptr++; + } + if ('\0' != *ptr) { + CYG_REPORT_RETVAL(false); + return false; + } + if (negative) { + cdl_int new_acc = 0 - acc; + if (new_acc > 0) { + CYG_REPORT_RETVAL(false); + return false; + } else { + acc = new_acc; + } + } + target = acc; + CYG_REPORT_RETVAL(true); + return true; +} + +//}}} +//{{{ string_to_double() + +// ---------------------------------------------------------------------------- +// There is no point in doing this the hard way, just use standard +// library calls. +// +// There is an obvious question as to how much precision can get lost +// doing the conversion to a string. In practice this should not matter +// too much, since the expression handling code generally keeps the +// original double precision lying around to be re-used. However it may +// be desirable to keep the libcdl behaviour in synch with Tcl's +// tcl_precision variable. + +bool +Cdl::string_to_double(std::string value, double& target) +{ + CYG_REPORT_FUNCNAMETYPE("Cdl::string_to_double", "success %d"); + + bool result = true; + const char* start_ptr = value.c_str(); + char* end_ptr; + int old_errno = errno; + + errno = 0; + double conv = strtod(start_ptr, &end_ptr); + if (0 != errno) { + CYG_ASSERT(ERANGE == errno, "standard-compliant C library"); + result = false; + } else if ('\0' != *end_ptr) { + result = false; + } else { + target = conv; + result = true; + } + + errno = old_errno; + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ string_to_bool() + +// ---------------------------------------------------------------------------- +// Conversions to and from bools. The only real issue here is exactly +// what strings should be accepted as synonyms for true and false. +// It is not actually clear that these functions are useful. +bool +Cdl::string_to_bool(std::string data, bool& target) +{ + CYG_REPORT_FUNCNAMETYPE("Cdl::string_to_bool", "success %d"); + + // Arguably there should be a precondition ( "" != data ) + bool result = false; + + // What is truth ? + if (( data == "1" ) || (data == "true") || + ( data == "True") || (data == "TRUE") ) { + result = true; + target = true; + } else if ((data == "0" ) || (data == "false") || + (data == "False") || (data == "FALSE") ) { + result = true; + target = false; + } + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} + +//{{{ integer_to_string() + +// ---------------------------------------------------------------------------- + +std::string +Cdl::integer_to_string(cdl_int value, CdlValueFormat format) +{ + std::string result; + Cdl::integer_to_string(value, result, format); + return result; +} + +void +Cdl::integer_to_string(cdl_int value, std::string& target, CdlValueFormat format) +{ + CYG_REPORT_FUNCNAME("Cdl::integer_to_string"); + CYG_REPORT_FUNCARG2XV((long) value, format); + + // Optimise this special case. + if (0 == value) { + if (CdlValueFormat_Hex == format) { + target = "0x0"; + } else { + target = "0"; + } + CYG_REPORT_RETVAL(true); + return; + } + + // A local buffer to construct partial strings. This avoids + // unnecessary std::string reallocation. + // 64 bits and three bits at a time for octal numbers gives 21 digits, + // plus spares for the leading '0' and the terminator. + char local_buf[24]; + char *local_ptr = &(local_buf[23]); + *local_ptr-- = '\0'; + + if (CdlValueFormat_Hex == format) { + + // Output the data as 0x... with either 8 or 16 digits, + // depending on the size. + int i; + for (i = 0; i < 8; i++) { + int tmp = (int) (value & 0x0F); + value = value >> 4; + if (tmp < 10) { + *local_ptr-- = '0' + tmp; + } else { + *local_ptr-- = 'A' + (tmp - 10); + } + } + // Beware of right shifts that preserve the sign bit. + { + int tmp1 = (value & 0x0FFFF); + int tmp2 = ((value >> 16) & 0x0FFFF); + value = (tmp2 << 16) + tmp1; + } + if (value != 0) { + for (i = 0; i < 8; i++) { + int tmp = (int) (value & 0x0F); + value = value >> 4; + if (tmp < 10) { + *local_ptr-- = '0' + tmp; + } else { + *local_ptr-- = 'A' + (tmp - 10); + } + } + } + *local_ptr-- = 'x'; + *local_ptr = '0'; + target = std::string(local_ptr); + + } else if (CdlValueFormat_Octal == format) { + + // Simply output the data three bits at a time, do not worry about any + // particular width restrictions. However it is necessary to worry + // about masking. + cdl_int mask = 0x1FFFFFFF; + mask = (mask << 16) | 0x0FFFF; + mask = (mask << 16) | 0x0FFFF; + + target = ""; + while (value > 0) { + int tmp = value & 0x07; + value = (value >> 3) & mask; + *local_ptr-- = '0' + tmp; + } + *local_ptr = '0'; + target = std::string(local_ptr); + + } else { + // A simple decimal number + // Switch to positive arithmetic. + bool negative = false; + if (value < 0) { + negative = true; + value = 0 - value; + // Only MININT cannot be converted using the above line + if (value < 0) { + target = "-9223372036854775808"; + CYG_REPORT_RETVAL(true); + return; + } + } + + while (value > 0) { + int rem = (int) (value % 10); + value = value / 10; + *local_ptr-- = '0' + rem; + } + if (negative) { + *local_ptr-- = '-'; + } + local_ptr++; + target = std::string(local_ptr); + } + + CYG_REPORT_RETURN(); + return; +} + +//}}} +//{{{ double_to_string() + +// ---------------------------------------------------------------------------- + +std::string +Cdl::double_to_string(double value, CdlValueFormat format) +{ + std::string result; + Cdl::double_to_string(value, result, format); + return result; +} + +void +Cdl::double_to_string(double value, std::string& result, CdlValueFormat format) +{ + CYG_REPORT_FUNCNAME("Cdl::double_to_String"); + + char buf[256]; // This should be plenty :-) + sprintf(buf, "%.*G", DBL_DIG, value); + result = buf; + + CYG_UNUSED_PARAM(CdlValueFormat, format); + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ bool_to_string() + +// ---------------------------------------------------------------------------- +// Should the string results be 1/0 or true/false? Not that +// it really matters. The testcase in cdl1.cxx expects 1/0. +std::string +Cdl::bool_to_string(bool value) +{ + std::string result; + Cdl::bool_to_string(value, result); + return result; +} + +void +Cdl::bool_to_string(bool value, std::string& target) +{ + CYG_REPORT_FUNCNAME("Cdl::bool_to_string"); + CYG_REPORT_FUNCARG1( "value arg %ld", (long) value); + + if (value) + target = "1"; + else + target = "0"; + + CYG_REPORT_RETURN(); +} + +//}}} + +//{{{ integer_to_double() + +// ---------------------------------------------------------------------------- +// Currently integer to double cannot fail, although there may well be loss +// of accurary. Eventually cdl_int may be an arbitrary precision integer +// in which case conversion to double is not guaranteed. +double +Cdl::integer_to_double(cdl_int value) +{ + CYG_REPORT_FUNCNAME("Cdl::integer_to_double"); + + double result = (double) value; + + CYG_REPORT_RETURN(); + return result; +} + +void +Cdl::integer_to_double(cdl_int value, double& target) +{ + CYG_REPORT_FUNCNAME("Cdl::integer_to_double"); + + target = (double) value; + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ double_to_integer() + +// Conversion from double to integer is only allowed if there is no loss +// of data. modf() is useful here +bool +Cdl::double_to_integer(double value, cdl_int& target) +{ + CYG_REPORT_FUNCNAMETYPE("Cdl::double_to_integer", "result %d"); + + bool result = false; + + double integral; + double frac; + + frac = modf(value, &integral); + if (0.0 == frac) { + // Looking good, but integral may still be too big. + cdl_int tmp = (cdl_int) integral; + if (tmp == value) { + // No fraction, no loss of data, everything looking good + target = tmp; + result = true; + } + } + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} + +//}}} +//{{{ Cdl::xxx_to_yyy() - CDL-specific data types + +// ---------------------------------------------------------------------------- +// Conversions between strings and flavors. + +static struct { + char* name; + CdlValueFlavor flavor; +} valid_flavors[] = { + { "none", CdlValueFlavor_None }, + { "bool", CdlValueFlavor_Bool }, + { "booldata", CdlValueFlavor_BoolData }, + { "data", CdlValueFlavor_Data }, + { 0, CdlValueFlavor_Invalid } +}; + +bool +Cdl::string_to_flavor(std::string name, CdlValueFlavor& target) +{ + CYG_REPORT_FUNCNAMETYPE("Cdl::string_to_flavor", "success %d"); + + bool result = false; + + // First convert the argument to lower case. Arguably this is incorrect, + // Tcl is a case-sensitive language, but the conversion is unlikely ever + // to be harmfull. + for (std::string::iterator str_i = name.begin(); str_i != name.end(); str_i++) { + if (isupper(*str_i)) { + *str_i = tolower(*str_i); + } + } + + // Now look for a match in the table. + int match = -1; + int i; + const char* c_str = name.c_str(); + int len = strlen(c_str); + + for (i = 0; 0 != valid_flavors[i].name; i++) { + if (0 == strncmp(c_str, valid_flavors[i].name, len)) { + // Check for an ambiguous string match. + // This cannot actually happen with the current flavor names. + if ( -1 != match) { + break; + } + match = i; + } + + } + if (-1 != match) { + target = valid_flavors[match].flavor; + result = true; + } + CYG_REPORT_RETVAL(result); + return result; +} + +bool +Cdl::flavor_to_string(CdlValueFlavor flavor, std::string& target) +{ + CYG_REPORT_FUNCNAMETYPE("Cdl::flavor_to_string", "success %d"); + + bool result = false; + + for (int i = 0; 0 != valid_flavors[i].name; i++) { + if (flavor == valid_flavors[i].flavor) { + target = valid_flavors[i].name; + result = true; + break; + } + } + + CYG_REPORT_RETVAL(result); + return result; +} + +// ---------------------------------------------------------------------------- +// Similar support for value sources. + +static struct { + char* name; + CdlValueSource source; +} valid_sources[] = { + { "default", CdlValueSource_Default }, + { "inferred", CdlValueSource_Inferred }, + { "wizard", CdlValueSource_Wizard }, + { "user", CdlValueSource_User }, + { 0, CdlValueSource_Invalid } +}; + +bool +Cdl::string_to_source(std::string name, CdlValueSource& target) +{ + CYG_REPORT_FUNCNAMETYPE("Cdl::string_to_source", "success %d"); + + bool result = false; + + // First convert the argument to lower case. Arguably this is incorrect, + // Tcl is a case-sensitive language, but the conversion is unlikely ever + // to be harmfull. + for (std::string::iterator str_i = name.begin(); str_i != name.end(); str_i++) { + if (isupper(*str_i)) { + *str_i = tolower(*str_i); + } + } + + // Now look for a match in the table. + int match = -1; + int i; + const char* c_str = name.c_str(); + int len = strlen(c_str); + + for (i = 0; 0 != valid_sources[i].name; i++) { + if (0 == strncmp(c_str, valid_sources[i].name, len)) { + // Check for an ambiguous string match. + // This cannot actually happen with the current source names. + if ( -1 != match) { + break; + } + match = i; + } + + } + if (-1 != match) { + target = valid_sources[match].source; + result = true; + } + CYG_REPORT_RETVAL(result); + return result; +} + +bool +Cdl::source_to_string(CdlValueSource source, std::string& target) +{ + CYG_REPORT_FUNCNAMETYPE("Cdl::source_to_string", "success %d"); + + bool result = false; + + for (int i = 0; 0 != valid_sources[i].name; i++) { + if (source == valid_sources[i].source) { + target = valid_sources[i].name; + result = true; + break; + } + } + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ Cdl::get_library_version() + +// ---------------------------------------------------------------------------- +// The version of the library actually lives inside configure.in. It gets +// exported into cdlconfig.h +std::string +Cdl::get_library_version(void) +{ + return std::string(CYGNUM_LIBCDL_VERSION); +} + +//}}} +//{{{ Cdl::set_interactive() + +// ---------------------------------------------------------------------------- +// Some CDL scripts and some bits of the library may want to adapt depending +// on whether or not the application is running fully interactively or in +// batch mode. The primary distinction is that a batch program should never +// attempt to obtain user input, whether via Tk widgets or by other means. + +bool Cdl::interactive = false; + +void +Cdl::set_interactive(bool value) +{ + CYG_REPORT_FUNCNAME("Cdl::set_interactive"); + CYG_REPORT_FUNCARG1D(value); + + interactive = value; +} + +bool +Cdl::is_interactive(void) +{ + CYG_REPORT_FUNCNAMETYPE("Cdl::is_interactive", "interactive %d"); + CYG_REPORT_RETVAL(interactive); + return interactive; +} + +//}}} +//{{{ Cdl::compare_versions() + +// ---------------------------------------------------------------------------- +// Packages may need to impose constraints on which versions of other +// packages they can coexist with. This requires some way of achieving +// a partial ordering of version numbers. Unfortunately there are many +// different ways of specifying a version number, and we cannot impose +// a single model on all third party package developers. Instead this +// routine performs some semi-intelligent comparisons of two version +// strings which should work in the vast majority of cases. +// +// The return value is as per strcmp(), -1 if the first entry is +// smaller (i.e. the more recent and hence hopefully the first in +// a list), +1 if the second entry is smaller, 0 if the two are +// identical. +// +// There is a big ambiguity between "derived" versions and "experimental" +// versions. Something like v0.3beta is experimental, i.e. it is older +// than the full release v0.3. On the other hand v0.3.p1 is a patched +// version of v0.3 and hence newer. This code uses the presence or otherwise +// of a separator to decide between the two cases. + +// A utility routine which checks whether or not a character counts +// as a separator. Currently the characters . - and _ are all accepted +// as field separators. +// +// Arguably - should not be accepted as a separator. Instead if it preceeds +// a digit it could be interpreted as part of a prerelease number. + +static bool +is_separator(int ch) +{ + return ('.' == ch) || ('-' == ch) || ('_' == ch); +} + +int +Cdl::compare_versions(std::string arg1, std::string arg2) +{ + CYG_REPORT_FUNCNAMETYPE("Cdl::compare_versions", "result %d"); + + if (arg1 == arg2) { + CYG_REPORT_RETVAL(0); + return 0; + } + + // The version number "current" is special, it always indicates the most + // recent version e.g. as checked out from a CVS repository. + if ("current" == arg1) { + CYG_REPORT_RETVAL(-1); + return -1; + } + if ("current" == arg2) { + CYG_REPORT_RETVAL(1); + return 1; + } + + const char* ptr1 = arg1.c_str(); + const char* ptr2 = arg2.c_str(); + int num1 = 0; + int num2 = 0; + + // If both strings start with 'v' or 'V', skip this. A minor variation in + // case at the start of a string should be ignored. + if ((('v' == *ptr1) || ('V' == *ptr1)) && + (('v' == *ptr2) || ('V' == *ptr2))) { + ptr1++; + ptr2++; + } + + // Now process the rest of the version string, one unit at a time. + while (1) { + + if (('\0' == *ptr1) && ('\0' == *ptr2)) { + // Both strings have terminated at the same time. There + // may have been some spurious leading zeroes in numbers, + // or irrelevant differences in the separators. + CYG_REPORT_RETVAL(0); + return 0; + } + + if ('\0' == *ptr1) { + // The first string has ended first. If the second string currently + // points at a separator then arg2 is a derived version, e.g. + // v0.3.p1, and hence newer. Otherwise arg2 is an experimental + // version v0.3beta and hence older. + if (is_separator(*ptr2)) { + CYG_REPORT_RETVAL(1); + return 1; + } else { + CYG_REPORT_RETVAL(-1); + return -1; + } + } + + if ('\0' == *ptr2) { + // As per the previous test. + if (is_separator(*ptr1)) { + CYG_REPORT_RETVAL(-1); + return -1; + } else { + CYG_REPORT_RETVAL(1); + return 1; + } + } + + // If both strings currently point at numerical data, do a conversion and + // a numerical comparison. + if (isdigit(*ptr1) && isdigit(*ptr2)) { + num1 = 0; + num2 = 0; + // Strictly speaking there should be some overflow tests here, but it + // is not worth the trouble. + do { + num1 = (10 * num1) + (*ptr1++ - '0'); + } while(isdigit(*ptr1)); + do { + num2 = (10 * num2) + (*ptr2++ - '0'); + } while(isdigit(*ptr2)); + // v2.0 is newer than v1.0 + if (num1 < num2) { + CYG_REPORT_RETVAL(1); + return 1; + } else if (num1 > num2) { + CYG_REPORT_RETVAL(-1); + return -1; + } else { + continue; + } + } + + // Non-numerical data. If the two characters are the same then + // move on. Note: this has to happen after numerical conversions + // to distinguish v10.0 and v1.0 + if (*ptr1 == *ptr2) { + ptr1++; ptr2++; + continue; + } + + // If both strings are currently at a separator then move on. All + // separators can be used interchangeably. + if (is_separator(*ptr1) && is_separator(*ptr2)) { + ptr1++; ptr2++; + continue; + } + + // If only one string is at a separator, special action + // is needed. v1.1alpha is interpreted as earlier than + // v1.1, but v1.1.3 is a later release. + if (is_separator(*ptr1)) { + return -1; + } else if (is_separator(*ptr2)) { + return 1; + } + + // Two different characters, e.g. v1.0alpha vs. v1.0beta + if (*ptr1 < *ptr2) { + CYG_REPORT_RETVAL(1); + return 1; + } else { + CYG_REPORT_RETVAL(-1); + return -1; + } + } + + // Not reachable. +} + +//}}} +//{{{ Cdl::get_short_form() + +// ---------------------------------------------------------------------------- +// It is occasionally useful to take a full CDL name such as CYgpkg_KERNEL +// and turn it into a short form such as "kernel". This involves discarding +// everything up to and including the first underscore, then lowercasing +// all subsequent characters. +std::string +Cdl::get_short_form(const std::string& original) +{ + CYG_REPORT_FUNCNAME("CdlMisc::get_short_form"); + + std::string result = ""; + unsigned int size = original.size(); + unsigned int i; + for (i = 0; i < size; i++) { + if ('_' == original[i]) { + i++; + break; + } + } + + // Either at end of string, or just past the first underscore + for ( ; i < size; i++) { + if (isupper(original[i])) { + result += tolower(original[i]); + } else { + result += original[i]; + } + } + + CYG_REPORT_RETURN(); + return result; +} + +//}}} diff --git a/host/libcdl/component.cxx b/host/libcdl/component.cxx new file mode 100644 --- /dev/null +++ b/host/libcdl/component.cxx @@ -0,0 +1,501 @@ +//{{{ Banner + +//============================================================================ +// +// component.cxx +// +// Implementation of the CdlComponent class +// +//============================================================================ +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================ +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contact(s): bartv +// Date: 1999/03/01 +// Version: 0.02 +// +//####DESCRIPTIONEND#### +//============================================================================ + +//}}} +//{{{ #include's + +// ---------------------------------------------------------------------------- +#include "cdlconfig.h" + +// Get the infrastructure types, assertions, tracing and similar +// facilities. +#include +#include + +// defines everything implemented in this module. +// It implicitly supplies , and because +// the class definitions rely on these headers. +#include + +//}}} + +//{{{ Statics + +// ---------------------------------------------------------------------------- +CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlComponentBody); + +//}}} +//{{{ Constructor + +// ---------------------------------------------------------------------------- +CdlComponentBody::CdlComponentBody(std::string name_arg) + : CdlNodeBody(name_arg), + CdlContainerBody(), + CdlUserVisibleBody(), + CdlValuableBody(), + CdlParentableBody(), + CdlBuildableBody(), + CdlDefinableBody() +{ + CYG_REPORT_FUNCNAME("CdlComponentBody:: constructor"); + CYG_REPORT_FUNCARG1XV(this); + + cdlcomponentbody_cookie = CdlComponentBody_Magic; + CYGDBG_MEMLEAK_CONSTRUCTOR(); + + CYG_POSTCONDITION_THISC(); + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ Destructor + +// ---------------------------------------------------------------------------- + +CdlComponentBody::~CdlComponentBody() +{ + CYG_REPORT_FUNCNAME("CdlComponentBody:: destructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + cdlcomponentbody_cookie = CdlComponentBody_Invalid; + CYGDBG_MEMLEAK_DESTRUCTOR(); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ parse_component() + +// ---------------------------------------------------------------------------- +// Parsing a component definition. This routine gets invoked directly from the +// Tcl interpreter. + +int +CdlComponentBody::parse_component(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("CdlComponentBody::parse_component", "result %d"); + CYG_REPORT_FUNCARG1("argc %d", argc); + CYG_PRECONDITION_CLASSC(interp); + + const char* diag_argv0 = CdlParse::get_tcl_cmd_name(argv[0]); + + CdlLoadable loadable = interp->get_loadable(); + CdlPackage package = dynamic_cast(loadable); + CdlContainer parent = interp->get_container(); + CdlToplevel toplevel = interp->get_toplevel(); + std::string filename = interp->get_filename(); + CYG_ASSERT_CLASSC(loadable); // There should always be a loadable during parsing + CYG_ASSERT_CLASSC(package); // And packages are the only loadable for software CDL. + CYG_ASSERT_CLASSC(parent); + CYG_ASSERT_CLASSC(toplevel); + CYG_ASSERTC("" != filename); + + // The new component should be created and added to the package + // early on. If there is a parsing error it will get cleaned up + // automatically as a consequence of the package destructor. + // However it is necessary to validate the name first. Errors + // should be reported via CdlParse::report_error(), + // which may result in an exception. + CdlComponent new_component = 0; + bool ok = true; + int result = TCL_OK; + try { + + // Currently there are no options. This may change in future. + if (3 != argc) { + CdlParse::report_error(interp, std::string("Incorrect number of arguments to ") + diag_argv0 + + "\n Expecting name and properties list."); + ok = false; + goto done; + } + if (!Tcl_CommandComplete(argv[2])) { + CdlParse::report_error(interp, std::string("Invalid property list for cdl_component ") + argv[1]); + ok = false; + goto done; + } + + if (0 != toplevel->lookup(argv[1])) { + CdlParse::report_error(interp, std::string("Component ") + argv[1] + " cannot be loaded.\n" + + " The name is already in use."); + ok = false; + } else { + new_component = new CdlComponentBody(argv[1]); + toplevel->add_node(package, parent, new_component); + } + + done: + if (!ok) { + // Just because this component cannot be created, that is no + // reason to abort the whole parsing process. + CYG_REPORT_RETVAL(TCL_OK); + return TCL_OK; + } + } catch(std::bad_alloc e) { + interp->set_result(CdlParse::get_diagnostic_prefix(interp) + "Out of memory."); + result = TCL_ERROR; + } catch(CdlParseException e) { + interp->set_result(e.get_message()); + result = TCL_ERROR; + } catch(...) { + interp->set_result(CdlParse::get_diagnostic_prefix(interp) + "internal error, unexpected C++ exception."); + result = TCL_ERROR; + } + if (TCL_OK != result) { + CYG_REPORT_RETVAL(result); + return result; + } + + // At this stage new_component has been created and added to the hierarchy. + // The main work now is to add the properties. + + // Push the component as the current node early on. This aids + // diagnostics. Also make it the new container. + CdlNode old_node = interp->push_node(new_component); + CdlContainer old_container = interp->push_container(new_component); + std::string old_filename; + CYG_ASSERTC(parent == old_container); + + // Declare these outside the scope of the try statement, to allow + // goto calls for the error handling. + std::string tcl_result; + std::vector new_commands; + std::vector* old_commands = 0; + static CdlInterpreterCommandEntry commands[] = + { + CdlInterpreterCommandEntry("script", &CdlComponentBody::parse_script ), + CdlInterpreterCommandEntry("cdl_component", &CdlComponentBody::parse_component ), + CdlInterpreterCommandEntry("cdl_option", &CdlOptionBody::parse_option ), + CdlInterpreterCommandEntry("cdl_interface", &CdlInterfaceBody::parse_interface ), + CdlInterpreterCommandEntry("cdl_dialog", &CdlDialogBody::parse_dialog ), + CdlInterpreterCommandEntry("cdl_wizard", &CdlWizardBody::parse_wizard ), + CdlInterpreterCommandEntry("", 0 ) + }; + static CdlInterpreterCommandEntry script_commands[] = + { + CdlInterpreterCommandEntry("cdl_component", &CdlComponentBody::parse_component ), + CdlInterpreterCommandEntry("cdl_option", &CdlOptionBody::parse_option ), + CdlInterpreterCommandEntry("cdl_interface", &CdlInterfaceBody::parse_interface ), + CdlInterpreterCommandEntry("cdl_dialog", &CdlDialogBody::parse_dialog ), + CdlInterpreterCommandEntry("cdl_wizard", &CdlWizardBody::parse_wizard ), + CdlInterpreterCommandEntry("", 0 ), + }; + int i; + + // All parsing errors may result in an exception, under the control of + // application code. This exception must not pass through the Tcl interpreter. + try { + + for (i = 0; 0 != commands[i].command; i++) { + new_commands.push_back(commands[i]); + } + CdlBuildableBody::add_property_parsers(new_commands); + CdlDefinableBody::add_property_parsers(new_commands); + CdlParentableBody::add_property_parsers(new_commands); + CdlValuableBody::add_property_parsers(new_commands); + CdlUserVisibleBody::add_property_parsers(new_commands); + CdlNodeBody::add_property_parsers(new_commands); + + // Now evaluate the body. If an error occurs then typically + // this will be reported via CdlParse::report_error(), + // but any exceptions will have been intercepted and + // turned into a Tcl error. + old_commands = interp->push_commands(new_commands); + result = interp->eval(argv[2], tcl_result); + interp->pop_commands(old_commands); + + if (TCL_OK != result) { + // No point in taking any further action, just go with the flow + goto done2; + } + + // Even if there were errors, they were not fatal. There may + // now be a number of properties for this component, and some + // validation should take place. Start with the base classes. + new_component->CdlNodeBody::check_properties(interp); + new_component->CdlUserVisibleBody::check_properties(interp); + new_component->CdlValuableBody::check_properties(interp); + new_component->CdlParentableBody::check_properties(interp); + new_component->CdlBuildableBody::check_properties(interp); + new_component->CdlDefinableBody::check_properties(interp); + + // There should be at most one each of wizard and script. + if (new_component->count_properties(CdlPropertyId_Wizard) > 1) { + CdlParse::report_error(interp, "A component should have at most one `wizard' property."); + } + if (new_component->count_properties(CdlPropertyId_Script) > 1) { + CdlParse::report_error(interp, "A component should have at most one `script' property."); + } + + // If there is a script property, life gets more interesting. + if (new_component->has_property(CdlPropertyId_Script)) { + CdlProperty_String prop = dynamic_cast(new_component->get_property(CdlPropertyId_Script)); + CYG_PRECONDITION_CLASSC(prop); + std::string script_name = prop->get_string(); + + // Try to locate this script. + std::string script_filename = package->find_absolute_file(script_name, "cdl", false); + if ("" == script_filename) { + CdlParse::report_error(interp, "Unable to find script " + script_name); + } else { + // The script exists, so we need to try and execute it. + // The current container is still set correctly, but we need + // to change the filename and install a different set + // of commands. + old_filename = interp->push_filename(script_filename); + new_commands.clear(); + for (i = 0; 0 != script_commands[i].command; i++) { + new_commands.push_back(script_commands[i]); + } + old_commands = interp->push_commands(new_commands); + result = interp->eval_file(script_filename, tcl_result); + interp->pop_commands(old_commands); + interp->pop_filename(old_filename); + } + } + + done2: + // Dummy command just to keep the compiler happy + filename = ""; + + } catch (std::bad_alloc e) { + // Errors at this stage should be reported via Tcl, not via C++. + // However there is no point in continuing with the parsing operation, + // just give up. + interp->set_result(CdlParse::get_diagnostic_prefix(interp) + "Out of memory."); + result = TCL_ERROR; + } catch (CdlParseException e) { + interp->set_result(e.get_message()); + result = TCL_ERROR; + } catch(...) { + interp->set_result(CdlParse::get_diagnostic_prefix(interp) + "internal error, unexpected C++ exception."); + result = TCL_ERROR; + } + + // Restore the interpreter to its prior state. + interp->pop_node(old_node); + interp->pop_container(old_container); + if (0 != old_commands) { + interp->pop_commands(old_commands); + } + + CYG_REPORT_RETVAL(result); + return result; +} + + +// ---------------------------------------------------------------------------- +// Syntax: script +int +CdlComponentBody::parse_script(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("parse_script", "result %d"); + + int result = CdlParse::parse_string_property(interp, argc, argv, CdlPropertyId_Script, 0, 0); + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ Propagation support + +// ---------------------------------------------------------------------------- +void +CdlComponentBody::update(CdlTransaction transaction, CdlUpdate update) +{ + CYG_REPORT_FUNCNAME("CdlComponent::update"); + + this->CdlValuableBody::update(transaction, update); + this->CdlContainerBody::update(transaction, update); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ Persistence support + +// ---------------------------------------------------------------------------- +void +CdlComponentBody::initialize_savefile_support(CdlToplevel toplevel) +{ + CYG_REPORT_FUNCNAME("CdlComponent::initialize_savefile_support"); + + toplevel->add_savefile_command("cdl_component", 0, &savefile_component_command); + CdlValuableBody::initialize_savefile_support(toplevel, "cdl_component"); + + CYG_REPORT_RETURN(); +} + +void +CdlComponentBody::save(CdlInterpreter interp, Tcl_Channel chan, int indentation, bool minimal) + throw(CdlInputOutputException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlComponent::save"); + CYG_REPORT_FUNCARG5XV(this, interp, chan, indentation, minimal); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(interp); + + if (!minimal || this->has_additional_savefile_information() || this->value_savefile_entry_needed()) { + // Start with the UserVisible data, which will result in a suitable set + // of comments before the package definition itself. + this->CdlUserVisibleBody::save(interp, chan, indentation, minimal); + + // Now output the line "cdl_component {" + // The name is guaranteed to be a valid C preprocessor symbol, so it + // is not going to need any quoting. + std::string data = std::string(indentation, ' ') + "cdl_component " + get_name() + " {\n"; + interp->write_data(chan, data); + + // Deal with the value + bool modifiable = !(CdlValueFlavor_None == this->get_flavor()) && + !this->has_property(CdlPropertyId_Calculated); + this->CdlValuableBody::save(interp, chan, indentation + 4, modifiable, minimal); + + // And with any unrecognised data + this->CdlNodeBody::save(interp, chan, indentation + 4, minimal); + + // Close the cdl_component body. A blank line is added here. + interp->write_data(chan, "};\n\n"); + } + + // Packages are containers, so dump the contents as well. + this->CdlContainerBody::save(interp, chan, indentation, minimal); + + CYG_REPORT_RETURN(); +} + +int +CdlComponentBody::savefile_component_command(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("CdlComponent::savefile_component_command", "result %d"); + CYG_PRECONDITION_CLASSC(interp); + + int result = TCL_OK; + CdlToplevel toplevel = interp->get_toplevel(); + CYG_ASSERT_CLASSC(toplevel); + CdlConfiguration config = dynamic_cast(toplevel); + CYG_ASSERT_CLASSC(config); + + std::vector subcommands; + std::vector* toplevel_commands = 0; + CdlNode old_node = 0; + + try { + + if (3 != argc) { + CdlParse::report_error(interp, "Invalid cdl_component command in savefile, expecting two arguments."); + } else { + + CdlNode current_node = config->lookup(argv[1]); + if (0 == current_node) { + // FIXME: save value in limbo + CdlParse::report_error(interp, + std::string("The savefile contains a cdl_component command for an unknown component `") + + argv[1] + "'"); + } else { + config->get_savefile_subcommands("cdl_component", subcommands); + toplevel_commands = interp->push_commands(subcommands); + old_node = interp->push_node(current_node); + + std::string tcl_result; + result = interp->eval(argv[2], tcl_result); + + interp->pop_commands(toplevel_commands); + toplevel_commands = 0; + interp->pop_node(old_node); + old_node = 0; + } + } + } catch(...) { + if (0 != old_node) { + interp->pop_node(old_node); + } + if (0 != toplevel_commands) { + interp->pop_commands(toplevel_commands); + } + throw; + } + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ check_this() + +// ---------------------------------------------------------------------------- + +bool +CdlComponentBody::check_this(cyg_assert_class_zeal zeal) const +{ + if (CdlComponentBody_Magic != cdlcomponentbody_cookie) { + return false; + } + CYGDBG_MEMLEAK_CHECKTHIS(); + + return CdlNodeBody::check_this(zeal) && + CdlContainerBody::check_this(zeal) && + CdlUserVisibleBody::check_this(zeal) && + CdlParentableBody::check_this(zeal) && + CdlValuableBody::check_this(zeal) && + CdlBuildableBody::check_this(zeal) && + CdlDefinableBody::check_this(zeal); +} + +//}}} +//{{{ Misc + +// ---------------------------------------------------------------------------- + +std::string +CdlComponentBody::get_class_name() const +{ + CYG_REPORT_FUNCNAME("CdlComponent::get_class_name"); + CYG_PRECONDITION_THISC(); + CYG_REPORT_RETURN(); + return "component"; +} + +//}}} diff --git a/host/libcdl/config.cxx b/host/libcdl/config.cxx new file mode 100644 --- /dev/null +++ b/host/libcdl/config.cxx @@ -0,0 +1,1857 @@ +//{{{ Banner + +//============================================================================ +// +// config.cxx +// +// Implementation of the CdlConfiguration class +// +//============================================================================ +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================ +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contact(s): bartv +// Date: 1999/03/06 +// Version: 0.02 +// +//####DESCRIPTIONEND#### +//============================================================================ + +//}}} +//{{{ #include's + +// ---------------------------------------------------------------------------- +#include "cdlconfig.h" + +// Get the infrastructure types, assertions, tracing and similar +// facilities. +#include +#include + +// defines everything implemented in this module. +// It implicitly supplies , and because +// the class definitions rely on these headers. +#include + +//}}} + +//{{{ CdlConfiguration constants and statics + +// ---------------------------------------------------------------------------- +CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlConfigurationBody); + +//}}} +//{{{ CdlConfiguration:: creation + +// ---------------------------------------------------------------------------- +// The toplevel class will take care of just about everything. + +CdlConfigurationBody::CdlConfigurationBody(std::string name, CdlPackagesDatabase db, CdlInterpreter interp) + : CdlNodeBody(name), + CdlToplevelBody(interp, db->get_component_repository()) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration:: constructor"); + CYG_REPORT_FUNCARG1XV(this); + + current_hardware = ""; + current_template = ""; + database = db; + save_file = ""; + description = ""; + + cdlconfigurationbody_cookie = CdlConfigurationBody_Magic; + CYGDBG_MEMLEAK_CONSTRUCTOR(); + + CYG_POSTCONDITION_THISC(); + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- +// The exported interface + +CdlConfiguration +CdlConfigurationBody::make(std::string name, CdlPackagesDatabase db, CdlInterpreter interp) +{ + CYG_REPORT_FUNCNAMETYPE("CdlConfiguration::make", "result %p"); + CYG_REPORT_FUNCARG2XV(db, interp); + CYG_PRECONDITIONC("" != name); + CYG_PRECONDITION_CLASSC(db); + CYG_PRECONDITION_CLASSC(interp); + + CdlConfiguration result = new CdlConfigurationBody(name, db, interp); + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ CdlConfiguration:: destructor + +// ---------------------------------------------------------------------------- +CdlConfigurationBody::~CdlConfigurationBody() +{ + CYG_REPORT_FUNCNAME("CdlConfiguration:: default destructor"); + CYG_REPORT_FUNCARG1("this %p", this); + CYG_PRECONDITION_THISC(); + + // Removing all the packages has to happen here, and in the + // context of a transaction. The main reason is the extensive + // use of dynamic casts, after this destructor returns + // any dynamic casts for this configuration will fail. + // + // Arguably some of the unloads should happen by clearing + // the hardware and template (assuming those are currently + // set). In practice that would not really gain anything. + // + // Unloading the individual packages is a bit more expensive + // than it should be, since lots of care is taken to keep + // remaining packages consistent and then those get unloaded + // as well. However it is the safe approach. + CdlLocalTransaction transaction(this); + const std::vector& loadables = this->get_loadables(); + for (int i = loadables.size() - 1; i >= 0; i--) { + CdlPackage pkg = dynamic_cast(loadables[i]); + if (0 != pkg) { + this->unload_package(transaction.get(), pkg); + } + } + transaction.propagate(); + transaction.commit(); + + cdlconfigurationbody_cookie = CdlConfigurationBody_Invalid; + current_hardware = ""; + current_template = ""; + database = 0; + save_file = ""; + + CYGDBG_MEMLEAK_DESTRUCTOR(); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ CdlConfiguration::check_this() + +// ---------------------------------------------------------------------------- +// There is very little information associated with a configuration. + +bool +CdlConfigurationBody::check_this(cyg_assert_class_zeal zeal) const +{ + if (CdlConfigurationBody_Magic != cdlconfigurationbody_cookie) { + return false; + } + CYGDBG_MEMLEAK_CHECKTHIS(); + + switch(zeal) { + case cyg_system_test : + case cyg_extreme : + if ((0 == database) || !database->check_this(cyg_quick)) { + return false; + } + case cyg_thorough : + if (("" != current_hardware) && !database->is_known_target(current_hardware)) { + return false; + } + if (("" != current_template) && !database->is_known_template(current_template)) { + return false; + } + case cyg_quick : + if (0 == database) { + return false; + } + case cyg_trivial : + case cyg_none : + default : + break; + } + + return CdlNodeBody::check_this(zeal) && CdlContainerBody::check_this(zeal) && CdlToplevelBody::check_this(zeal); +} + +//}}} +//{{{ CdlConfiguration:: basic info + +// ---------------------------------------------------------------------------- +// Provide ready access to configuration-specific data. + +CdlPackagesDatabase +CdlConfigurationBody::get_database() const +{ + CYG_REPORT_FUNCNAMETYPE("CdlConfiguration::get_database", "result %p"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CYG_REPORT_RETVAL(database); + return database; +} + +std::string +CdlConfigurationBody::get_hardware() const +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::get_hardware"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CYG_REPORT_RETURN(); + return current_hardware; +} + +void +CdlConfigurationBody::set_hardware_name(std::string new_name) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::set_hardware_name"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + current_hardware = new_name; + + CYG_REPORT_RETURN(); +} + +std::string +CdlConfigurationBody::get_template() const +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::get_template"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CYG_REPORT_RETURN(); + return current_template; +} + +void +CdlConfigurationBody::set_template_name(std::string new_name) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::set_template_name"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + current_template = new_name; + + CYG_REPORT_RETURN(); +} + +std::string +CdlConfigurationBody::get_save_file() const +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::get_save_file"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CYG_REPORT_RETURN(); + return save_file; +} + +// ---------------------------------------------------------------------------- + +std::string +CdlConfigurationBody::get_class_name() const +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::get_class_name"); + CYG_PRECONDITION_THISC(); + CYG_REPORT_RETURN(); + return "CdlConfiguration"; +} + +//}}} +//{{{ Load and unload operations - wrappers + +// ---------------------------------------------------------------------------- +// These members are basically wrappers for the functions that do the +// real work. They do things like running the real functions inside +// a newly created transaction. + +void +CdlConfigurationBody::load_package(std::string name, std::string version, + CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn, bool limbo) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::load_package"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlLocalTransaction transaction(this); + this->load_package(transaction.get(), name, version, error_fn, warn_fn, limbo); + transaction.body(); + + CYG_REPORT_RETURN(); +} + +void +CdlConfigurationBody::unload_package(std::string name, bool limbo) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::unload_package"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlLocalTransaction transaction(this); + this->unload_package(transaction.get(), name, limbo); + transaction.body(); + + CYG_REPORT_RETURN(); +} + +void +CdlConfigurationBody::unload_package(CdlPackage package, bool limbo) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::unload_package"); + CYG_REPORT_FUNCARG1XV(this); + + CdlLocalTransaction transaction(this); + this->unload_package(transaction.get(), package, limbo); + transaction.body(); + + CYG_REPORT_RETURN(); +} + +void +CdlConfigurationBody::unload_package(CdlTransaction transaction, std::string name, bool limbo) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::unload_package"); + CYG_REPORT_FUNCARG3XV(this, transaction, limbo); + CYG_INVARIANT_THISC(CdlConfigurationBody); + CYG_PRECONDITION_CLASSC(transaction); + + CdlNode node = lookup(name); + CYG_ASSERTC(0 != node); + CdlPackage package = dynamic_cast(node); + CYG_ASSERTC(0 != package); + + this->unload_package(transaction, package, limbo); + + CYG_REPORT_RETURN(); +} + +void +CdlConfigurationBody::change_package_version(std::string name, std::string version, + CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn, bool limbo) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::change_package_version"); + CYG_REPORT_FUNCARG1XV(this); + + CdlLocalTransaction transaction(this); + this->change_package_version(transaction.get(), name, version, error_fn, warn_fn, limbo); + transaction.body(); + + CYG_REPORT_RETURN(); +} + +void +CdlConfigurationBody::change_package_version(CdlPackage package, std::string version, + CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn, bool limbo) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::change_package_version"); + CYG_REPORT_FUNCARG1XV(this); + + CdlLocalTransaction transaction(this); + this->change_package_version(transaction.get(), package, version, error_fn, warn_fn, limbo); + transaction.body(); + + CYG_REPORT_RETURN(); +} + +void +CdlConfigurationBody::change_package_version(CdlTransaction transaction, std::string name, std::string new_version, + CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn, bool limbo) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::change_package_version"); + CYG_REPORT_FUNCARG2XV(this, transaction); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(transaction); + CYG_PRECONDITIONC("" != name); + + CdlPackage package = 0; + CdlNode node = this->lookup(name); + if (0 != node) { + package = dynamic_cast(node); + } + // For now it is illegal to change the version of package that has + // not been loaded yet + CYG_ASSERT_CLASSC(package); + + this->change_package_version(transaction, package, new_version, error_fn, warn_fn, limbo); + + CYG_REPORT_RETURN(); +} + +void +CdlConfigurationBody::add(std::string filename, + CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::add"); + CYG_REPORT_FUNCARG1XV(this); + + CdlLocalTransaction transaction(this); + this->add(transaction.get(), filename, error_fn, warn_fn); + transaction.body(); + + CYG_REPORT_RETURN(); +} + +void +CdlConfigurationBody::set_template(std::string name, std::string version, + CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn, bool limbo) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::set_template"); + CYG_REPORT_FUNCARG1XV(this); + + CdlLocalTransaction transaction(this); + this->set_template(transaction.get(), name, version, error_fn, warn_fn, limbo); + transaction.body(); + + CYG_REPORT_RETURN(); +} + +void +CdlConfigurationBody::set_template_file(std::string filename, + CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn, bool limbo) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::set_template_file"); + CYG_REPORT_FUNCARG1XV(this); + + CdlLocalTransaction transaction(this); + this->set_template_file(transaction.get(), filename, error_fn, warn_fn, limbo); + transaction.body(); + + CYG_REPORT_RETURN(); +} + +void +CdlConfigurationBody::set_template(CdlTransaction transaction, std::string template_name, std::string version, + CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn, bool limbo) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::set_template"); + CYG_REPORT_FUNCARG2XV(this, transaction); + + // Some consistency checks before doing anything damaging + if (!this->database->is_known_template(template_name)) { + throw CdlInputOutputException("Unknown template " + template_name); + } + std::string template_filename = this->database->get_template_filename(template_name, version); + if ("" == template_filename) { + if ("" == version) { + throw CdlInputOutputException("There is no template file corresponding to " + template_name); + } else { + throw CdlInputOutputException("There is no temmplate file corresponding to version " + + version + " of " + template_name); + } + } + + // Now use set_template_file() to do the hard work. + this->set_template_file(transaction, template_filename, error_fn, warn_fn, limbo); + current_template = template_name; + + CYG_REPORT_RETURN(); +} + +void +CdlConfigurationBody::unload_template(bool limbo) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::unload_template"); + CYG_REPORT_FUNCARG1XV(this); + + CdlLocalTransaction transaction(this); + this->unload_template(transaction.get(), limbo); + transaction.body(); + + CYG_REPORT_RETURN(); +} + +void +CdlConfigurationBody::set_hardware(std::string name, + CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn, bool limbo) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::set_hardware"); + CYG_REPORT_FUNCARG1XV(this); + + CdlLocalTransaction transaction(this); + this->set_hardware(transaction.get(), name, error_fn, warn_fn, limbo); + transaction.body(); + + CYG_REPORT_RETURN(); +} + +void +CdlConfigurationBody::unload_hardware(bool limbo) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::unload_hardware"); + CYG_REPORT_FUNCARG1XV(this); + + CdlLocalTransaction transaction(this); + this->unload_hardware(transaction.get(), limbo); + transaction.body(); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ Load and unload - transaction support + +// ---------------------------------------------------------------------------- +// A number of commit/cancel auxiliary classes are needed to allow the +// load/unload code to integrate properly with the transaction code. + +class CdlConfiguration_CommitCancelLoad : + public CdlTransactionCommitCancelOp +{ + friend class CdlTest; + + public: + + CdlConfiguration_CommitCancelLoad(CdlPackage package_arg) + : CdlTransactionCommitCancelOp() + { + CYG_ASSERT_CLASSC(package_arg); + package = package_arg; + } + ~CdlConfiguration_CommitCancelLoad() + { + package = 0; + } + void commit(CdlTransaction transaction) + { + CYG_ASSERT_CLASSC(package); + CdlLoadableBody::transaction_commit_load(transaction, package); + package = 0; + } + void cancel(CdlTransaction transaction) + { + CYG_ASSERT_CLASSC(package); + CdlLoadableBody::transaction_cancel_load(transaction, package); + package = 0; + } + + protected: + + private: + CdlConfiguration_CommitCancelLoad() + { + } + CdlPackage package; +}; + +class CdlConfiguration_CommitCancelUnload : + public CdlTransactionCommitCancelOp +{ + friend class CdlTest; + + public: + CdlConfiguration_CommitCancelUnload(CdlPackage package_arg) + : CdlTransactionCommitCancelOp() + { + CYG_ASSERT_CLASSC(package_arg); + package = package_arg; + } + ~CdlConfiguration_CommitCancelUnload() + { + package = 0; + } + void commit(CdlTransaction transaction) + { + CYG_PRECONDITION_CLASSC(package); + CdlLoadableBody::transaction_commit_unload(transaction, package); + package = 0; + } + void cancel(CdlTransaction transaction) + { + CYG_PRECONDITION_CLASSC(package); + CdlLoadableBody::transaction_cancel_unload(transaction, package); + package = 0; + } + + protected: + + private: + CdlConfiguration_CommitCancelUnload() + { + } + CdlPackage package; +}; + +// These utility classes can be used to control the hardware and +// template names. If the transaction is cancelled the previous +// name gets re-installed +class CdlConfiguration_CommitCancelHardwareName : + public CdlTransactionCommitCancelOp +{ + friend class CdlTest; + + public: + CdlConfiguration_CommitCancelHardwareName(std::string old_name_arg) + : CdlTransactionCommitCancelOp() + { + old_name = old_name_arg; + } + ~CdlConfiguration_CommitCancelHardwareName() + { + old_name = ""; + } + void commit(CdlTransaction transaction) + { + // The new name is already installed, nothing more needs to happen. + CYG_UNUSED_PARAM(CdlTransaction, transaction); + } + void cancel(CdlTransaction transaction) + { + // Restore the old name + CdlToplevel toplevel = transaction->get_toplevel(); + CYG_ASSERTC(0 != toplevel); + CdlConfiguration configuration = dynamic_cast(toplevel); + CYG_ASSERT_CLASSC(configuration); + + configuration->set_hardware_name(old_name); + CYG_UNUSED_PARAM(CdlTransaction, transaction); + } + + protected: + + private: + CdlConfiguration_CommitCancelHardwareName() + { + } + std::string old_name; +}; + +class CdlConfiguration_CommitCancelTemplateName : + public CdlTransactionCommitCancelOp +{ + friend class CdlTest; + + public: + CdlConfiguration_CommitCancelTemplateName(std::string old_name_arg) + : CdlTransactionCommitCancelOp() + { + old_name = old_name_arg; + } + ~CdlConfiguration_CommitCancelTemplateName() + { + old_name = ""; + } + void commit(CdlTransaction transaction) + { + // The new name is already installed, nothing more needs to happen. + CYG_UNUSED_PARAM(CdlTransaction, transaction); + } + void cancel(CdlTransaction transaction) + { + // Restore the old name + CdlToplevel toplevel = transaction->get_toplevel(); + CYG_ASSERTC(0 != toplevel); + CdlConfiguration configuration = dynamic_cast(toplevel); + CYG_ASSERT_CLASSC(configuration); + + configuration->set_template_name(old_name); + CYG_UNUSED_PARAM(CdlTransaction, transaction); + } + + protected: + + private: + CdlConfiguration_CommitCancelTemplateName() + { + } + std::string old_name; +}; + +//}}} +//{{{ CdlConfiguration::load_package() + +// ---------------------------------------------------------------------------- +// Loading a package into the current level. This involves the following +// stages. +// +// 1) check that the specified package name and version is valid, by +// comparing it with the database. When the database was created there +// will have been checks to make sure that the initial CDL script was +// present, but more checks can be done here. +// +// 2) before allocating any resources, check that there is no name conflict +// for the package itself. +// +// 3) create the package object, and add it to the toplevel of the current +// configuration. It may get reparented later on. Part of the creation +// process is to allocate a new slave interpreter, which can be updated +// with various bits of information. +// +// 4) evaluate the toplevel script. Subsidiary component scripts will +// get evaluated as a side effect. The various nodes will be added +// to the hierarchy as they are created, but no property binding +// happens yet. +// +// Any failure up to this point should result in the entire package +// being removed from the hierarchy and then destroyed, thus leaving +// the configuration in its original state. +// +// 5) now property binding needs to take place. This can have lots +// of side effects, e.g. default values may get calculated, the +// hierarchy may change because of parent properties, etc. +// The work is done inside CdlLoadable::bind() which will undo +// everything on failure - although bad_alloc is the only +// failure that should occur. +// +// 6) load operations can get cancelled, so a suitable commit/cancel +// operation needs to allocated and added to the transaction. +// +// 7) if limbo is enabled, previous values should be extracted from +// limbo if at all possible. In addition the package's value can +// be set to its version. + +void +CdlConfigurationBody::load_package(CdlTransaction transaction, std::string name, std::string version, + CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn, bool limbo) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::load_package"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(transaction); + CYG_PRECONDITIONC("" != name); + + // Locate the database entry. Also check the version (filling it in if necessary). + // Get hold of the package directory and the initial script. + if (!database->is_known_package(name)) { + throw CdlInputOutputException("Unknown package " + name); + } + const std::vector& versions = database->get_package_versions(name); + if ("" == version) { + version = *(versions.begin()); + } else { + if (std::find(versions.begin(), versions.end(), version) == versions.end()) { + throw CdlInputOutputException("Package " + name + " does not have an installed version " + version); + } + } + std::string directory = database->get_package_directory(name); + std::string script = database->get_package_script(name); + CYG_ASSERTC(("" != directory) && ("" != script)); + + // Check that the directory actually exists. For this the configuration's own + // interpreter can be used. + CdlInterpreter interp = get_interpreter(); + CYG_ASSERT_CLASSC(interp); + + std::string tcl_cmd = "regsub -all -- {\\\\} [file join " + directory + " " + version + "] / result; return $result"; + std::string tcl_result; + if (TCL_OK != interp->eval(tcl_cmd, tcl_result)) { + throw CdlInputOutputException("Cannot load package " + name + ", internal error constructing pathname"); + } + directory = tcl_result; + + tcl_cmd = "file isdirectory [file join \"" + database->get_component_repository() + "\" " + directory + "]"; + if ((TCL_OK != interp->eval(tcl_cmd, tcl_result)) || ("1" != tcl_result)) { + throw CdlInputOutputException("Cannot load package " + name + ", there is no directory " + directory); + } + + // Make sure that there is no name conflict. No resources have been allocated + // yet, so this is a good time. + CdlNode node = lookup(name); + if (0 != node) { + if (0 != dynamic_cast(node)) { + throw CdlInputOutputException("Package " + name + " is already loaded"); + } else { + + std::string msg = "Name clash for package " + name + ",there is a " + + node->get_class_name() + " " + name + " already loaded"; + CdlLoadable owner_pkg = node->get_owner(); + if (0 != owner_pkg) { + msg += " in package " + owner_pkg->get_name(); + } + throw CdlInputOutputException(msg); + } + } + + // Now create the package object itself. + CdlPackage package = 0; + bool bound = false; + CdlConfiguration_CommitCancelLoad* load_op = 0; + + try { + package = new CdlPackageBody(name, this, directory); + + // The package should be added to the hierarchy immediately. + // All nodes will get added to the hierarchy as they are + // created, an operation that has to be undone during + // failure. + this->add_node(package, this, package); + + // Load the package data. The various nodes will all end up + // in a hierarchy below the package, but without any checks + // for name conflicts etc and ignoring any re-parenting. + CdlInterpreter interp = package->get_interpreter(); + CYG_ASSERT_CLASSC(interp); + + interp->add_command("unknown", &CdlParse::unknown_command); + + // Next figure out the script name, and make sure that it exists. + std::string actual_script = package->find_absolute_file(script, "cdl"); + if ("" == actual_script) { + throw CdlInputOutputException("Package " + name + ", unable to find initial script " + script); + } + tcl_cmd = "file isfile \"" + actual_script + "\""; + if ((TCL_OK != interp->eval(tcl_cmd, tcl_result)) || ("1" != tcl_result)) { + throw CdlInputOutputException("Package " + name + ", " + actual_script + " is not a CDL script"); + } + + // The script is valid. Set up the interpreter appropriately. + CdlContainer old_container = interp->push_container(package); + std::string old_filename = interp->push_filename(actual_script); + CdlDiagnosticFnPtr old_error_fn = interp->push_error_fn_ptr(error_fn); + CdlDiagnosticFnPtr old_warn_fn = interp->push_warning_fn_ptr(warn_fn); + CdlParse::clear_error_count(interp); + + static CdlInterpreterCommandEntry commands[] = + { + CdlInterpreterCommandEntry("cdl_package", &CdlPackageBody::parse_package ), + CdlInterpreterCommandEntry("cdl_component", &CdlComponentBody::parse_component ), + CdlInterpreterCommandEntry("cdl_option", &CdlOptionBody::parse_option ), + CdlInterpreterCommandEntry("cdl_interface", &CdlInterfaceBody::parse_interface ), + CdlInterpreterCommandEntry("cdl_dialog", &CdlDialogBody::parse_dialog ), + CdlInterpreterCommandEntry("cdl_wizard", &CdlWizardBody::parse_wizard ), + CdlInterpreterCommandEntry("", 0 ) + }; + std::vector new_commands; + for (int i = 0; 0 != commands[i].command; i++) { + new_commands.push_back(commands[i]); + } + std::vector* old_commands = interp->push_commands(new_commands); + + // The interpreter is now ready. + if (TCL_OK != interp->eval_file(actual_script, tcl_result)) { + throw CdlInputOutputException("Package " + name + ", error executing CDL script.\n" + tcl_result); + } + + // Clean out the commands etc. This interpreter may get used again + // in future, and it should not be possible to define new options + // etc. in that invocation. + interp->remove_command("unknown"); + interp->pop_commands(old_commands); + interp->pop_container(old_container); + interp->pop_filename(old_filename); + interp->pop_error_fn_ptr(old_error_fn); + interp->pop_warning_fn_ptr(old_warn_fn); + + // All the data has been read in without generating an + // exception. However there may have been errors reported via + // the parse_error_fn, and any errors at all should result + // in an exception. + int error_count = CdlParse::get_error_count(interp); + if (error_count > 0) { + std::string tmp; + Cdl::integer_to_string(error_count, tmp); + throw CdlParseException("Package " + name + ", " + tmp + " error" + + ((error_count > 1) ? "s" : "") + + " occurred while reading in the CDL data."); + } + + // All the data has been read in, implying that there are no + // fatal problems with the data. Now try to bind all + // references to and from this loadable. + package->bind(transaction); + bound = true; + + // Finally, create a suitable transaction commit/cancel object + // and add it to the transaction. + load_op = new CdlConfiguration_CommitCancelLoad(package); + transaction->add_commit_cancel_op(load_op); + + } catch (...) { + + // Something went wrong during the create or load. It is necessary + // to delete the package. Undo all the operations above, in + // reverse order. The add_commit_cancel_op() was the last step, + // so need not be undone here. + if (0 != load_op) { + delete load_op; + } + + if (0 != package) { + // Note: no attempt is made to recover from errors here + if (bound) { + package->unbind(transaction); + } + this->remove_loadable_from_toplevel(package); + delete package; + } + throw; + } + + // FIXME: implement limbo support + + // We also have a sensible value for the package as a whole. + // Use this value for both default and user - after all the + // user has selected the package. + package->enable_and_set_value(transaction, version, CdlValueSource_Default); + package->enable_and_set_value(transaction, version, CdlValueSource_User); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ CdlConfiguration::unload_package() + +// ---------------------------------------------------------------------------- +// Unloading a package is very simple. If requested, save all current +// values to limbo: there is no point in saving default values, these +// will get recalculated from the default_value property anyway; +// inferred values should be saved, there is no guarantee that the exact +// same value will be calculated again, and if the inferred value is no +// longer correct then the inference engine can freely update it. +// +// Next, unbind the package and remove it from the hierarchy. These +// operations are reversible if the transaction gets cancelled. +// A suitable transaction commit/cancel object is created and +// added to the transaction. +void +CdlConfigurationBody::unload_package(CdlTransaction transaction, CdlPackage package, bool limbo) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::unload_package"); + CYG_REPORT_FUNCARG4XV(this, transaction, package, limbo); + CYG_INVARIANT_THISC(CdlConfigurationBody); + CYG_INVARIANT_CLASSC(CdlTransactionBody, transaction); + CYG_PRECONDITION_CLASSC(package); + + if (limbo) { + const std::vector& pkg_contents = package->get_owned(); + std::vector::const_iterator node_i; + + for (node_i = pkg_contents.begin(); node_i != pkg_contents.end(); node_i++) { + CdlValuable valuable = dynamic_cast(*node_i); + if (0 != valuable) { + if (valuable->has_source(CdlValueSource_Inferred) || + valuable->has_source(CdlValueSource_Wizard) || + valuable->has_source(CdlValueSource_User)) { + + set_limbo_value(valuable); + } + } + } + } + + bool unbound = false; + bool removed = false; + CdlConfiguration_CommitCancelUnload* unload_op = 0; + try { + + package->unbind(transaction); + unbound = true; + this->remove_loadable_from_toplevel(package); + removed = true; + unload_op = new CdlConfiguration_CommitCancelUnload(package); + transaction->add_commit_cancel_op(unload_op); + + } catch(...) { + if (0 != unload_op) { + delete unload_op; + } + if (removed) { + this->add_loadable_to_toplevel(package); + } + if (unbound) { + package->bind(transaction); + } + throw; + } + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ CdlConfiguration::change_package_version() + +// ---------------------------------------------------------------------------- +// Changing a package version is just a case of unloading the old version +// and then loading in the new version. Because this all happens in the +// context of a transaction it is possible to undo the unload on +// failure, and the whole transaction can be cancelled at a higher level. + +void +CdlConfigurationBody::change_package_version(CdlTransaction transaction, CdlPackage package, std::string new_version, + CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn, bool limbo) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::change_package_version"); + CYG_REPORT_FUNCARG3XV(this, transaction, package); + CYG_PRECONDITION_THISC(); + CYG_INVARIANT_CLASSC(CdlTransactionBody, transaction); + CYG_PRECONDITION_CLASSC(package); + // "" is valid for the version, it indicates the default + + // Since the package is already loaded it must be in the database, + // but it is possible that the desired version does not exist. + std::string name = package->get_name(); + const std::vector& pkg_versions = database->get_package_versions(name); + if ("" == new_version) { + new_version = *(pkg_versions.begin()); + } else if (std::find(pkg_versions.begin(), pkg_versions.end(), new_version) == pkg_versions.end()) { + throw CdlInputOutputException("Version " + new_version + " of package " + name + " is not installed."); + } + + bool unloaded = false; + try { + this->unload_package(transaction, package, limbo); + unloaded = true; + this->load_package(transaction, name, new_version, error_fn, warn_fn, limbo); + } catch(...) { + if (unloaded) { + // There should be a commit/cancel op for the unload package step. + // This can be undone. + CdlTransactionCommitCancelOp* unload_op = transaction->get_last_commit_cancel_op(); + CYG_ASSERTC(0 != unload_op); + CYG_ASSERTC(0 != dynamic_cast(unload_op)); + transaction->cancel_last_commit_cancel_op(); + CYG_UNUSED_PARAM(CdlTransactionCommitCancelOp*, unload_op); + } + throw; + } + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ CdlConfiguration::set_hardware() etc. + +// ---------------------------------------------------------------------------- +// Setting the hardware involves unloading the old hardware, if any, and +// then loading in the new one. Obviously this should only happen if +// the new hardware name is valid. It would be possible to optimise for +// the case where the old and new hardware are the same, subject +// to dynamic database reload support. + +void +CdlConfigurationBody::set_hardware(CdlTransaction transaction, std::string target_name, + CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn, bool limbo) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::set_hardware"); + CYG_REPORT_FUNCARG2XV(this, transaction); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(transaction); + + // Minimal consistency check before + if (!database->is_known_target(target_name)) { + throw CdlInputOutputException("Unknown target " + target_name); + } + + int i; + CdlConfiguration_CommitCancelHardwareName* rename_op = new CdlConfiguration_CommitCancelHardwareName(current_hardware); + try { + transaction->add_commit_cancel_op(rename_op); + const std::vector& loadables = this->get_loadables(); + for (i = (int) loadables.size() - 1; i >= 0; i--) { + CdlPackage package = dynamic_cast(loadables[i]); + if ((0 != package) && package->belongs_to_hardware()) { + this->unload_package(transaction, package, limbo); + } + } + current_hardware = ""; + + if ("" != target_name) { + + const std::vector& packages = database->get_target_packages(target_name); + std::vector::const_iterator name_i; + for (name_i = packages.begin(); name_i != packages.end(); name_i++) { + // It is possible for a hardware package to have been + // loaded separately, in which case there is no point in + // loading it again. + CYG_ASSERTC(database->is_known_package(*name_i)); + if (0 == this->lookup(*name_i)) { + this->load_package(transaction, *name_i, "", error_fn, warn_fn, limbo); + CdlPackage package = dynamic_cast(this->lookup(*name_i)); + CYG_LOOP_INVARIANT_CLASSC(package); + package->loaded_for_hardware = true; + } + } + } + current_hardware = target_name; + + } catch(...) { + // Cancel all operations up to and including the rename_op + CdlTransactionCommitCancelOp* cancel_op = 0; + do { + cancel_op = transaction->get_last_commit_cancel_op(); + CYG_LOOP_INVARIANTC(0 != cancel_op); + transaction->cancel_last_commit_cancel_op(); + } while(cancel_op != rename_op); + throw; + } + + // There may have been enables/disables and value data for that target + // FIXME: any problems get ignored quietly. There should at least + // be some warnings. + if ("" != target_name) { + const std::vector& enables = database->get_target_enables(target_name); + const std::vector& disables = database->get_target_disables(target_name); + const std::vector >& set_values = database->get_target_set_values(target_name); + + if ((0 != enables.size()) || (0 != disables.size()) || (0 != set_values.size())) { + std::vector::const_iterator opt_i; + CdlNode node; + CdlValuable valuable; + CdlValueFlavor flavor; + + for (opt_i = enables.begin(); opt_i != enables.end(); opt_i++) { + node = this->lookup(*opt_i); + if (0 != node) { + valuable = dynamic_cast(node); + if (0 != valuable) { + flavor = valuable->get_flavor(); + if ((CdlValueFlavor_Bool == flavor) || (CdlValueFlavor_BoolData == flavor)) { + valuable->enable(transaction, CdlValueSource_User); + } + } + } + } + for (opt_i = disables.begin(); opt_i != disables.end(); opt_i++) { + node = this->lookup(*opt_i); + if (0 != node) { + valuable = dynamic_cast(node); + if (0 != valuable) { + flavor = valuable->get_flavor(); + if ((CdlValueFlavor_Bool == flavor) || (CdlValueFlavor_BoolData == flavor)) { + valuable->disable(transaction, CdlValueSource_User); + } + } + } + } + std::vector >::const_iterator value_i; + for (value_i = set_values.begin(); value_i != set_values.end(); value_i++) { + node = this->lookup(value_i->first); + if (0 != node) { + valuable = dynamic_cast(node); + if (0 != valuable) { + flavor = valuable->get_flavor(); + if ((CdlValueFlavor_BoolData == flavor) || (CdlValueFlavor_Data == flavor)) { + valuable->set_value(transaction, value_i->second, CdlValueSource_User); + } + } + } + } + } + } + + CYG_REPORT_RETURN(); +} + +void +CdlConfigurationBody::unload_hardware(CdlTransaction transaction, bool limbo) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::unload_hardware"); + CYG_REPORT_FUNCARG3XV(this, transaction, limbo); + CYG_PRECONDITION_THISC(); + + CdlConfiguration_CommitCancelHardwareName* rename_op = new CdlConfiguration_CommitCancelHardwareName(current_hardware); + try { + transaction->add_commit_cancel_op(rename_op); + } catch(...) { + delete rename_op; + throw; + } + current_hardware = ""; + + try { + const std::vector& loadables = this->get_loadables(); + for (int i = (int) loadables.size() - 1; i >= 0; i--) { + CdlPackage package = dynamic_cast(loadables[i]); + if ((0 != package) && package->belongs_to_hardware()) { + this->unload_package(transaction, package, limbo); + } + } + } catch(...) { + CdlTransactionCommitCancelOp* cancel_op = 0; + do { + cancel_op = transaction->get_last_commit_cancel_op(); + CYG_LOOP_INVARIANTC(0 != cancel_op); + transaction->cancel_last_commit_cancel_op(); + } while(cancel_op != rename_op); + throw; + } + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ CdlConfiguration::set_template() etc + +// ---------------------------------------------------------------------------- +void +CdlConfigurationBody::set_template_file(CdlTransaction transaction, std::string filename, + CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn, bool limbo) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::set_template_file"); + CYG_REPORT_FUNCARG3XV(this, transaction, limbo); + CYG_PRECONDITION_THISC(); + + int i; + CdlConfiguration_CommitCancelTemplateName* rename_op = new CdlConfiguration_CommitCancelTemplateName(current_template); + + // The hard work is done by add(), which loads in a partial savefile. + // This can have undesirable side effects: changing the name, + // description, or hardware settings. It must be possible to undo + // these. + std::string saved_name = this->get_name(); + std::string saved_description = this->get_description(); + std::string saved_hardware = this->get_hardware(); + + // New packages will end up at the end of the loadables vector. + // Each new package needs to be registered as a template one. + // NOTE: this may break if we start doing more interesting things + // with savefiles. + const std::vector& loadables = this->get_loadables(); + unsigned int load_i = loadables.size(); + + try { + transaction->add_commit_cancel_op(rename_op); + const std::vector& loadables = this->get_loadables(); + for (i = (int) loadables.size() - 1; i >= 0; i--) { + CdlPackage package = dynamic_cast(loadables[i]); + if ((0 != package) && package->belongs_to_template()) { + this->unload_package(transaction, package, limbo); + } + } + current_template = ""; + + this->add(transaction, filename, error_fn, warn_fn); + this->current_template = filename; + this->set_name(saved_name); + this->description = saved_description; + this->current_hardware = saved_hardware; + + for ( ; load_i < loadables.size(); load_i++) { + CdlPackage pkg = dynamic_cast(loadables[load_i]); + CYG_ASSERT_CLASSC(pkg); + pkg->loaded_for_template = true; + } + + } catch(...) { + + this->set_name(saved_name); + this->description = saved_description; + this->current_hardware = saved_hardware; + + // Cancel all operations up to and including the rename_op + CdlTransactionCommitCancelOp* cancel_op = 0; + do { + cancel_op = transaction->get_last_commit_cancel_op(); + CYG_LOOP_INVARIANTC(0 != cancel_op); + transaction->cancel_last_commit_cancel_op(); + } while(cancel_op != rename_op); + throw; + } + + + CYG_REPORT_RETURN(); +} + +void +CdlConfigurationBody::unload_template(CdlTransaction transaction, bool limbo) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::unload_template"); + CYG_REPORT_FUNCARG2XV(this, transaction); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(transaction); + + CdlConfiguration_CommitCancelTemplateName* rename_op = new CdlConfiguration_CommitCancelTemplateName(current_template); + try { + transaction->add_commit_cancel_op(rename_op); + } catch(...) { + delete rename_op; + throw; + } + current_template = ""; + + try { + const std::vector& loadables = this->get_loadables(); + for (int i = (int) loadables.size() - 1; i >= 0; i--) { + CdlPackage package = dynamic_cast(loadables[i]); + if ((0 != package) && package->belongs_to_template()) { + this->unload_package(transaction, package, limbo); + } + } + } catch(...) { + CdlTransactionCommitCancelOp* cancel_op = 0; + do { + cancel_op = transaction->get_last_commit_cancel_op(); + CYG_LOOP_INVARIANTC(0 != cancel_op); + transaction->cancel_last_commit_cancel_op(); + } while(cancel_op != rename_op); + throw; + } + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ Persistence support + +//{{{ initialize_savefile_support() + +// ---------------------------------------------------------------------------- +// Initialization. The purpose of this code is to determine all the +// commands that can end up in a particular savefile. This includes +// the cdl_configuration command, commands relevant to packages, +// options, and components, the generic library commands, and +// application-specific commands. +// +// This is a virtual function, it may get invoked indirectly from +// e.g. CdlToplevel::add_savefile_command(). + +void +CdlConfigurationBody::initialize_savefile_support() +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::initialize_savefile_support"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + // Start with the generic stuff such as cdl_savefile_version and + // cdl_command. + this->CdlToplevelBody::initialize_savefile_support(); + + // Now add in the cdl_configuration command and its subcommands. + this->add_savefile_command("cdl_configuration", 0, &savefile_configuration_command); + this->add_savefile_subcommand("cdl_configuration", "description", 0, &savefile_description_command); + this->add_savefile_subcommand("cdl_configuration", "hardware", 0, &savefile_hardware_command); + this->add_savefile_subcommand("cdl_configuration", "template", 0, &savefile_template_command); + this->add_savefile_subcommand("cdl_configuration", "package", 0, &savefile_package_command); + + CdlPackageBody::initialize_savefile_support(this); + CdlComponentBody::initialize_savefile_support(this); + CdlOptionBody::initialize_savefile_support(this); + CdlInterfaceBody::initialize_savefile_support(this); +} + +//}}} +//{{{ CdlConfiguration::save() - internal + +// ---------------------------------------------------------------------------- +// The exported interface is CdlConfiguration::save(). This takes a single +// argument, a filename. It opens the file, and then invokes various +// functions that output the relevants bits of the file. +// +// This member function is responsible for outputting a cdl_configuration +// command. + +void +CdlConfigurationBody::save(CdlInterpreter interp, Tcl_Channel chan, int indentation, bool minimal) + throw(CdlInputOutputException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::save"); + CYG_REPORT_FUNCARG5XV(this, interp, chan, indentation, minimal); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(interp); + CYG_PRECONDITIONC(0 == indentation); + + std::string text = ""; + if (!minimal) { + text = +"# This section defines the toplevel configuration object. The only\n\ +# values that can be changed are the name of the configuration and\n\ +# the description field. It is not possible to modify the target,\n\ +# the template or the set of packages simply by editing the lines\n\ +# below because these changes have wide-ranging effects. Instead\n\ +# the appropriate tools should be used to make such modifications.\n\ +\n"; + } + + text += "cdl_configuration " + CdlInterpreterBody::quote(this->get_name()) + " {\n"; + + std::string config_data = this->get_description(); + if (!minimal || ("" != text)) { + text += " description " + CdlInterpreterBody::quote(config_data) + " ;\n"; + } + + // Repeat the warning. + if (!minimal) { + text += "\n # These fields should not be modified.\n"; + } + config_data = this->get_hardware(); + if ("" != config_data) { + text += " hardware " + CdlInterpreterBody::quote(config_data) + " ;\n"; + } + config_data = this->get_template(); + if ("" != config_data) { + text += " template " + CdlInterpreterBody::quote(config_data) + " ;\n"; + } + std::vector::const_iterator load_i; + const std::vector& packages = get_loadables(); + for (load_i = packages.begin(); load_i != packages.end(); load_i++) { + CdlPackage pkg = dynamic_cast(*load_i); + CYG_ASSERT_CLASSC(pkg); + text += " package "; + if (pkg->belongs_to_template()) { + text += "-template "; + } + if (pkg->belongs_to_hardware()) { + text += "-hardware "; + } + text += CdlInterpreterBody::quote(pkg->get_name()) + " " + CdlInterpreterBody::quote(pkg->get_value()) + " ;\n"; + } + + interp->write_data(chan, text); + + // If the package was loaded from a file then there may be additional + // data associated with the configuration that is not currently + // recognised. This call preserves that data. + this->CdlNodeBody::save(interp, chan, indentation + 4, minimal); + + interp->write_data(chan, "};\n\n"); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ CdlConfiguration::save() - exported interface + +// ---------------------------------------------------------------------------- +// This is the exported interface for saving a configuration. The specified +// file is opened via the appropriate Tcl library routines, and then the +// relevant member functions are invoked to output the actual configuration +// date. + +void +CdlConfigurationBody::save(std::string filename, bool minimal) + throw(CdlInputOutputException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::save"); + CYG_REPORT_FUNCARG2XV(this, minimal); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITIONC("" != filename); + + // Make sure that the savefile support is properly initialized. + // This happens during the first save or load operation, or when + // the application starts to register its own savefile extensions. + if (!CdlToplevelBody::savefile_support_initialized()) { + this->initialize_savefile_support(); + } + + // A Tcl interpreter is needed for the call to OpenFileChannel(), + // and will also be passed to the individual save functions. + CdlInterpreter interp = this->get_interpreter(); + CYG_ASSERT_CLASSC(interp); + + // Do not worry about forward vs. backward slashes, since the filename + // is not manipulated in any way. Instead just pass it to Tcl. + Tcl_Channel chan = Tcl_OpenFileChannel(interp->get_tcl_interpreter(), const_cast(filename.c_str()), "w", 0666); + if (0 == chan) { + throw CdlInputOutputException("Unable to open file " + filename + "\n" + interp->get_result()); + } + + // The channel may end up being registered in various different + // interpreters, so Tcl_Close() is not the right way to close down + // the channel. Instead Tcl_RegisterChannel() should be used here + // to provide reference counting semantics. + Tcl_RegisterChannel(0, chan); + + // A try/catch body is needed here to make sure that the file gets + // properly cleaned up. + std::string tmp; + try { + + if (!minimal) { + interp->write_data(chan, "# eCos saved configuration\n\n"); + } + + CdlToplevelBody::save_separator(interp, chan, "commands", minimal); + this->CdlToplevelBody::save_command_details(interp, chan, 0, minimal); + CdlToplevelBody::save_separator(interp, chan, "toplevel", minimal); + this->save(interp, chan, 0, minimal); + CdlToplevelBody::save_separator(interp, chan, "conflicts", minimal); + this->CdlToplevelBody::save_conflicts(interp, chan, 0, minimal); + CdlToplevelBody::save_separator(interp, chan, "contents", minimal); + this->CdlContainerBody::save(interp, chan, 0, minimal); + this->save_unsupported_commands(interp, chan, 0, minimal); + + } catch(...) { + Tcl_UnregisterChannel(0, chan); + // NOTE: deleting the file is necessary, it is a bad idea to + // end up with incomplete save files. It would be even better + // to write to a temporary file and only overwrite the old + // savefile on success. + // + // Tcl does not provide direct access to the file delete + // facility, so it is necessary to evaluate a script. This + // introduces quoting and security problems, since the + // filename might contain spaces, square brackets, braces... + // To avoid these problems a variable is used. + interp->set_variable("__cdlconfig_filename", filename); + interp->eval("file delete $__cdlconfig_filename", tmp); + interp->unset_variable("__cdlconfig_filename"); + + throw; + } + + // This call will perform the appropriate close. + Tcl_UnregisterChannel(0, chan); +} + +//}}} +//{{{ CdlConfiguration::load() and add() + +// ---------------------------------------------------------------------------- +// Most of the work is done in add(). load() simply creates a new configuration +// and then invokes add(). +CdlConfiguration +CdlConfigurationBody::load(std::string filename, CdlPackagesDatabase db, CdlInterpreter interp, + CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAMETYPE("CdlConfiguration::load", "result %p"); + CYG_REPORT_FUNCARG4XV(db, interp, error_fn, warn_fn); + CYG_PRECONDITION_CLASSC(db); + CYG_PRECONDITION_CLASSC(interp); + + CdlConfiguration result = CdlConfigurationBody::make("eCos", db, interp); + if (0 == result) { + CYG_REPORT_RETVAL(result); + return result; + } + + try { + result->add(filename, error_fn, warn_fn); + result->save_file = filename; + } catch(...) { + delete result; + throw; + } + + CYG_REPORT_RETVAL(result); + return result; +} + +// ---------------------------------------------------------------------------- +void +CdlConfigurationBody::add(CdlTransaction transaction, std::string filename, + CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn) + throw(CdlInputOutputException, CdlParseException, std::bad_alloc) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::add"); + CYG_REPORT_FUNCARG3XV(this, error_fn, warn_fn); + CYG_PRECONDITION_THISC(); + + // Initialize the savefile support, so that it is known what + // commands can occur in a savefile. + if (!CdlToplevelBody::savefile_support_initialized()) { + this->initialize_savefile_support(); + } + + // The interpreter should not have any left-over junk. + CdlInterpreter interp = this->get_interpreter(); + CYG_PRECONDITION_CLASSC(interp); + CYG_ASSERTC(0 == interp->get_loadable()); + CYG_ASSERTC(0 == interp->get_container()); + CYG_ASSERTC(0 == interp->get_node()); + CYG_ASSERTC(0 == interp->get_transaction()); + + // Keep track of enough information to undo all the changes. + std::string old_filename = interp->get_filename(); + CdlDiagnosticFnPtr old_error_fn = interp->get_error_fn_ptr(); + CdlDiagnosticFnPtr old_warn_fn = interp->get_warning_fn_ptr(); + std::vector* old_commands = 0; + std::vector commands; + + try { + + // Associate the right information with the interpreter + old_filename = interp->push_filename(filename); + old_error_fn = interp->push_error_fn_ptr(error_fn); + old_warn_fn = interp->push_warning_fn_ptr(warn_fn); + CdlParse::clear_error_count(interp); + + interp->set_transaction(transaction); + + this->get_savefile_commands(commands); + old_commands = interp->push_commands(commands); + + std::string tcl_result = ""; + if (TCL_OK != interp->eval_file(filename, tcl_result)) { + throw CdlInputOutputException("Invalid savefile \"" + filename + "\".\n" + tcl_result); + } + // All the data has been read in without generating an + // exception. However there may have been errors reported via + // the error_fn handling, and any errors at all should result + // in an exception. + int error_count = CdlParse::get_error_count(interp); + if (error_count > 0) { + std::string tmp; + Cdl::integer_to_string(error_count, tmp); + throw CdlInputOutputException("Invalid savefile \"" + filename + "\".\n" + + tmp + " error" + ((error_count > 1) ? "s" : "") + + " occurred while reading in the savefile data."); + } + + } catch(...) { + + if (0 != old_commands) { + interp->pop_commands(old_commands); + } + interp->pop_filename(old_filename); + interp->pop_error_fn_ptr(old_error_fn); + interp->pop_warning_fn_ptr(old_warn_fn); + interp->set_transaction(0); + throw; + } + + interp->pop_filename(old_filename); + interp->pop_error_fn_ptr(old_error_fn); + interp->pop_warning_fn_ptr(old_warn_fn); + interp->pop_commands(old_commands); + interp->set_transaction(0); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ savefile commands + +// ---------------------------------------------------------------------------- +// A cdl_configuration command does not actually do very much. It acts as +// a container for subcommands, and it can be used to change the name. +// +// The command could also check that the current configuration is empty. +// This is not done, to allow multiple savefiles to be loaded into +// a single configuration in future. +int +CdlConfigurationBody::savefile_configuration_command(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("CdlConfiguration::savefile_configuration_command", "result %d"); + CYG_PRECONDITION_CLASSC(interp); + + int result = TCL_OK; + CdlToplevel toplevel = interp->get_toplevel(); + CYG_ASSERT_CLASSC(toplevel); + CdlConfiguration config = dynamic_cast(toplevel); + CYG_ASSERT_CLASSC(config); + + std::vector subcommands; + std::vector* toplevel_commands = 0; + + try { + std::vector > options; + int data_index = CdlParse::parse_options(interp, "cdl_configuration command", 0, argc, argv, 1, options); + + // A broken cdl_configuration command is pretty fatal, chances are + // that the entire load is going to fail. + if (data_index != (argc - 2)) { + CdlParse::report_error(interp, "Invalid cdl_configuration command in savefile, expecting two arguments."); + } else { + config->set_name(argv[1]); + config->get_savefile_subcommands("cdl_configuration", subcommands); + toplevel_commands = interp->push_commands(subcommands); + + std::string tcl_result; + result = interp->eval(argv[2], tcl_result); + + interp->pop_commands(toplevel_commands); + toplevel_commands = 0; + } + + } catch(...) { + if (0 != toplevel_commands) { + interp->pop_commands(toplevel_commands); + } + throw; + } + + CYG_REPORT_RETVAL(result); + return result; +} + +// ---------------------------------------------------------------------------- +int +CdlConfigurationBody::savefile_description_command(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::savefile_description_command"); + CYG_PRECONDITION_CLASSC(interp); + + CdlToplevel toplevel = interp->get_toplevel(); + CYG_ASSERT_CLASSC(toplevel); + CdlConfiguration config = dynamic_cast(toplevel); + CYG_ASSERT_CLASSC(config); + + std::vector > options; + int data_index = CdlParse::parse_options(interp, "cdl_configuration/description command", 0, argc, argv, 1, options); + + if (data_index != (argc - 1)) { + CdlParse::report_warning(interp, + "Ignoring invalid configuration description command, expecting a single argument."); + } else { + config->description = argv[1]; + } + return TCL_OK; +} + +// ---------------------------------------------------------------------------- +int +CdlConfigurationBody::savefile_hardware_command(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::savefile_hardware_command"); + CYG_PRECONDITION_CLASSC(interp); + + CdlToplevel toplevel = interp->get_toplevel(); + CYG_ASSERT_CLASSC(toplevel); + CdlConfiguration config = dynamic_cast(toplevel); + CYG_ASSERT_CLASSC(config); + + std::vector > options; + int data_index = CdlParse::parse_options(interp, "cdl_configuration/hardware command", 0, argc, argv, 1, options); + + if (data_index != (argc - 1)) { + CdlParse::report_warning(interp, "Ignoring invalid configuration hardware command, expecting a single argument."); + } else { + config->current_hardware = argv[1]; + } + + return TCL_OK; +} + +// ---------------------------------------------------------------------------- +int +CdlConfigurationBody::savefile_template_command(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::savefile_template_command"); + CYG_PRECONDITION_CLASSC(interp); + + CdlToplevel toplevel = interp->get_toplevel(); + CYG_ASSERT_CLASSC(toplevel); + CdlConfiguration config = dynamic_cast(toplevel); + CYG_ASSERT_CLASSC(config); + + std::vector > options; + int data_index = CdlParse::parse_options(interp, "cdl_configuration/template command", 0, argc, argv, 1, options); + + if (data_index != (argc - 1)) { + CdlParse::report_warning(interp, "Ignoring invalid configuration template command, expecting a single argument."); + } else { + config->current_template = argv[1]; + } + + return TCL_OK; +} + +// ---------------------------------------------------------------------------- +int +CdlConfigurationBody::savefile_package_command(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAME("CdlConfiguration::savefile_package_command"); + CYG_PRECONDITION_CLASSC(interp); + + CdlToplevel toplevel = interp->get_toplevel(); + CYG_ASSERT_CLASSC(toplevel); + CdlConfiguration config = dynamic_cast(toplevel); + CYG_ASSERT_CLASSC(config); + CdlPackagesDatabase db = config->get_database(); + CYG_ASSERT_CLASSC(db); + + std::string pkgname; + std::string pkgversion; + CdlPackage pkg = 0; + + std::vector > options; + static char* optlist[] = { + "template:f", + "hardware:f", + 0 + }; + int data_index = CdlParse::parse_options(interp, "cdl_configuration/package command", optlist, argc, argv, 1, options); + + if (data_index == (argc - 1)) { + CdlParse::report_warning(interp, std::string("Missing version information for package ") + argv[argc - 1]); + pkgname = argv[argc - 1]; + pkgversion = ""; + } else if (data_index == (argc - 2)) { + pkgname = argv[argc - 2]; + pkgversion = argv[argc - 1]; + } else { + // If we cannot load all the packages then much of the + // savefile is likely to be problematical. + CdlParse::report_error(interp, "Invalid cdl_configuration/package command, expecting name and version"); + CYG_REPORT_RETURN(); + return TCL_OK; + } + + if (0 != config->lookup(pkgname)) { + // If the package was already loaded, check the version string. If the versions + // are identical then we do not need to worry any further. Otherwise a mismatch + // warning is appropriate. + CdlNode node = config->lookup(pkgname); + CYG_ASSERT_CLASSC(node); + pkg = dynamic_cast(node); + if (0 == pkg) { + // The name is in use, but it is not a package + CdlParse::report_error(interp, std::string("Unable to load package ") + pkgname + ", the name is already in use."); + } else if (pkgversion != pkg->get_value()) { + CdlParse::report_warning(interp, std::string("Cannot load version ") + pkgversion + " of package " + + pkgname + ", version " + pkg->get_value() + " already loaded."); + } + } else if (!db->is_known_package(pkgname)) { + CdlParse::report_error(interp, std::string("Attempt to load an unknown package ") + pkgname); + } else { + if ("" != pkgversion) { + const std::vector& versions = db->get_package_versions(pkgname); + if (versions.end() == std::find(versions.begin(), versions.end(), pkgversion)) { + CdlParse::report_warning(interp, std::string("The savefile specifies version `") + pkgversion + + "' for package `" + pkgname + "'\nThis version is not available.\n" + + "Using the most recent version instead."); + pkgversion = ""; + } + } + CdlDiagnosticFnPtr error_fn = interp->get_error_fn_ptr(); + CdlDiagnosticFnPtr warn_fn = interp->get_warning_fn_ptr(); + CdlTransaction transaction = interp->get_transaction(); + config->load_package(transaction, pkgname, pkgversion, error_fn, warn_fn, false); + CdlNode pkg_node = config->lookup(pkgname); + CYG_ASSERTC(0 != pkg_node); + pkg = dynamic_cast(pkg_node); + CYG_ASSERT_CLASSC(pkg); + } + + if ((0 != pkg) && (0 != options.size())) { + std::vector >::const_iterator opt_i; + for (opt_i = options.begin(); opt_i != options.end(); opt_i++) { + if (opt_i->first == "template") { + pkg->loaded_for_template = true; + } else if (opt_i->first == "hardware") { + pkg->loaded_for_hardware = true; + } + } + } + + return TCL_OK; +} + +//}}} + +//}}} + diff --git a/host/libcdl/config.h.in b/host/libcdl/config.h.in new file mode 100644 --- /dev/null +++ b/host/libcdl/config.h.in @@ -0,0 +1,21 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +#undef PACKAGE +#undef VERSION +#undef CYGNUM_LIBCDL_VERSION + +#undef CYGDBG_USE_ASSERTS +#undef CYGDBG_INFRA_DEBUG_PRECONDITIONS +#undef CYGDBG_INFRA_DEBUG_POSTCONDITIONS +#undef CYGDBG_INFRA_DEBUG_INVARIANTS +#undef CYGDBG_INFRA_DEBUG_LOOP_INVARIANTS + +#undef CYGDBG_USE_TRACING +#undef CYGDBG_INFRA_DEBUG_FUNCTION_REPORTS + +/* Name of package */ +#undef PACKAGE + +/* Version number of package */ +#undef VERSION + diff --git a/host/libcdl/configure b/host/libcdl/configure new file mode 100644 --- /dev/null +++ b/host/libcdl/configure @@ -0,0 +1,2154 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer" +ac_help="$ac_help + --enable-debug do a debug rather than a release build" +ac_help="$ac_help + --enable-ansi Do an ANSI rather than a unicode build" +ac_help="$ac_help + --disable-asserts disable all assertions" +ac_help="$ac_help + --disable-preconditions disable a subset of the assertions" +ac_help="$ac_help + --disable-postconditions disable a subset of the assertions" +ac_help="$ac_help + --disable-invariants disable a subset of the assertions" +ac_help="$ac_help + --disable-loopinvariants disable a subset of the assertions" +ac_help="$ac_help + --disable-tracing disable tracing" +ac_help="$ac_help + --disable-fntracing disable function entry/exit tracing" +ac_help="$ac_help + --with-tcl-version= version of Tcl to be used" +ac_help="$ac_help + --with-tcl= location of Tcl header and libraries" +ac_help="$ac_help + --with-infra=dir location of the infrastructure build tree" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=cdlcore.hxx + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +ac_aux_dir= +for ac_dir in .. $srcdir/..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in .. $srcdir/.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + + + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:580: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:613: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 +echo "configure:666: checking whether build environment is sane" >&5 +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "$*" != "X $srcdir/configure conftestfile" \ + && test "$*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { echo "configure: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" 1>&2; exit 1; } + fi + + test "$2" = conftestfile + ) +then + # Ok. + : +else + { echo "configure: error: newly created file is older than distributed files! +Check your system clock" 1>&2; exit 1; } +fi +rm -f conftest* +echo "$ac_t""yes" 1>&6 +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:723: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +PACKAGE=libcdl + +VERSION=0.2 + +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } +fi +cat >> confdefs.h <> confdefs.h <&6 +echo "configure:769: checking for working aclocal" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (aclocal --version) < /dev/null > /dev/null 2>&1; then + ACLOCAL=aclocal + echo "$ac_t""found" 1>&6 +else + ACLOCAL="$missing_dir/missing aclocal" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 +echo "configure:782: checking for working autoconf" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoconf --version) < /dev/null > /dev/null 2>&1; then + AUTOCONF=autoconf + echo "$ac_t""found" 1>&6 +else + AUTOCONF="$missing_dir/missing autoconf" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working automake""... $ac_c" 1>&6 +echo "configure:795: checking for working automake" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (automake --version) < /dev/null > /dev/null 2>&1; then + AUTOMAKE=automake + echo "$ac_t""found" 1>&6 +else + AUTOMAKE="$missing_dir/missing automake" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 +echo "configure:808: checking for working autoheader" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoheader --version) < /dev/null > /dev/null 2>&1; then + AUTOHEADER=autoheader + echo "$ac_t""found" 1>&6 +else + AUTOHEADER="$missing_dir/missing autoheader" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 +echo "configure:821: checking for working makeinfo" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (makeinfo --version) < /dev/null > /dev/null 2>&1; then + MAKEINFO=makeinfo + echo "$ac_t""found" 1>&6 +else + MAKEINFO="$missing_dir/missing makeinfo" + echo "$ac_t""missing" 1>&6 +fi + + + + + + cat >> confdefs.h <&6 +echo "configure:843: checking whether to enable maintainer-specific portions of Makefiles" >&5 + # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then + enableval="$enable_maintainer_mode" + USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + echo "$ac_t""$USE_MAINTAINER_MODE" 1>&6 + + +if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + MAINT=$MAINTAINER_MODE_TRUE + + + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:867: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:896: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:926: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:977: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:1009: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 1020 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:1025: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:1051: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:1056: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:1084: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1120: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CXX="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CXX="$ac_cv_prog_CXX" +if test -n "$CXX"; then + echo "$ac_t""$CXX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$CXX" && break +done +test -n "$CXX" || CXX="gcc" + + +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:1152: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 + +ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + +cat > conftest.$ac_ext << EOF + +#line 1163 "configure" +#include "confdefs.h" + +int main(){return(0);} +EOF +if { (eval echo configure:1168: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cxx_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cxx_cross=no + else + ac_cv_prog_cxx_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cxx_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6 +if test $ac_cv_prog_cxx_works = no; then + { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:1194: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6 +cross_compiling=$ac_cv_prog_cxx_cross + +echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 +echo "configure:1199: checking whether we are using GNU C++" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.C <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gxx=yes +else + ac_cv_prog_gxx=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gxx" 1>&6 + +if test $ac_cv_prog_gxx = yes; then + GXX=yes +else + GXX= +fi + +ac_test_CXXFLAGS="${CXXFLAGS+set}" +ac_save_CXXFLAGS="$CXXFLAGS" +CXXFLAGS= +echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6 +echo "configure:1227: checking whether ${CXX-g++} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.cc +if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then + ac_cv_prog_cxx_g=yes +else + ac_cv_prog_cxx_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6 +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS="$ac_save_CXXFLAGS" +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1261: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +echo $ac_n "checking for object suffix""... $ac_c" 1>&6 +echo "configure:1289: checking for object suffix" >&5 +if eval "test \"`echo '$''{'ac_cv_objext'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + rm -f conftest* +echo 'int i = 1;' > conftest.$ac_ext +if { (eval echo configure:1295: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + for ac_file in conftest.*; do + case $ac_file in + *.c) ;; + *) ac_cv_objext=`echo $ac_file | sed -e s/conftest.//` ;; + esac + done +else + { echo "configure: error: installation or configuration problem; compiler does not work" 1>&2; exit 1; } +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_objext" 1>&6 +OBJEXT=$ac_cv_objext +ac_objext=$ac_cv_objext + +echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6 +echo "configure:1313: checking for Cygwin environment" >&5 +if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_cygwin=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_cygwin=no +fi +rm -f conftest* +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_cygwin" 1>&6 +CYGWIN= +test "$ac_cv_cygwin" = yes && CYGWIN=yes +echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6 +echo "configure:1346: checking for mingw32 environment" >&5 +if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_mingw32=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_mingw32=no +fi +rm -f conftest* +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_mingw32" 1>&6 +MINGW32= +test "$ac_cv_mingw32" = yes && MINGW32=yes + + +echo $ac_n "checking for executable suffix""... $ac_c" 1>&6 +echo "configure:1377: checking for executable suffix" >&5 +if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$CYGWIN" = yes || test "$MINGW32" = yes; then + ac_cv_exeext=.exe +else + rm -f conftest* + echo 'int main () { return 0; }' > conftest.$ac_ext + ac_cv_exeext= + if { (eval echo configure:1387: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + for file in conftest.*; do + case $file in + *.c | *.o | *.obj | *.ilk | *.pdb) ;; + *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;; + esac + done + else + { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; } + fi + rm -f conftest* + test x"${ac_cv_exeext}" = x && ac_cv_exeext=no +fi +fi + +EXEEXT="" +test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext} +echo "$ac_t""${ac_cv_exeext}" 1>&6 +ac_exeext=$EXEEXT + + + + + + echo $ac_n "checking "for Visual C++"""... $ac_c" 1>&6 +echo "configure:1412: checking "for Visual C++"" >&5 + MSVC="no"; + if test "${CC}" = "cl" ; then + MSVC="yes" + fi + if test "${CXX}" = "cl" ; then + MSVC="yes" + fi + + +if test "${MSVC}" = "yes"; then + MSVC_TRUE= + MSVC_FALSE='#' +else + MSVC_TRUE='#' + MSVC_FALSE= +fi + echo "$ac_t""${MSVC}" 1>&6 + + + + + + + echo $ac_n "checking "the default compiler flags"""... $ac_c" 1>&6 +echo "configure:1437: checking "the default compiler flags"" >&5 + + cygflags_enable_debug="no" + # Check whether --enable-debug or --disable-debug was given. +if test "${enable_debug+set}" = set; then + enableval="$enable_debug" + case "${enableval}" in + yes) cygflags_enable_debug="yes" ;; + *) cygflags_enable_debug="no" ;; + esac +fi + + + cygflags_enable_ansi="no" + if test "${MSVC}" = "yes" ; then + # Check whether --enable-ansi or --disable-ansi was given. +if test "${enable_ansi+set}" = set; then + enableval="$enable_ansi" + case "${enableval}" in + yes) cygflags_enable_ansi="yes" ;; + *) cygflags_enable_ansi="no" ;; + esac +fi + + fi + + if test "${GCC}" = "yes" ; then + CC="$CC -Wall -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs" + CXX="$CXX -Wall -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Woverloaded-virtual" + elif test "${MSVC}" = "yes" ; then + CC="$CC -nologo -W3" + CXX="$CXX -nologo -W3 -GR -GX" + if test "${cygflags_enable_debug}" = "yes" ; then + CC="$CC -MDd -Zi" + CXX="$CXX -MDd -Zi" + else + CC="$CC -MD -O2" + CXX="$CXX -MD -O2" + fi + else + { echo "configure: error: "default flags for ${CC} are not known"" 1>&2; exit 1; } + fi + echo "$ac_t""done" 1>&6 + + + +if test ${cross_compiling} = yes; then + { echo "configure: error: cross-compilation of this package is not supported" 1>&2; exit 1; } +fi + + + + + +if test "${cygflags_enable_debug}" = "yes" ; then + cyginfra_asserts=yes + cyginfra_preconditions=yes + cyginfra_postconditions=yes + cyginfra_invariants=yes + cyginfra_loopinvariants=yes + cyginfra_tracing=yes + cyginfra_fntracing=yes +else + cyginfra_asserts=no + cyginfra_preconditions=no + cyginfra_postconditions=no + cyginfra_invariants=no + cyginfra_loopinvariants=no + cyginfra_tracing=no + cyginfra_fntracing=no +fi + +# Check whether --enable-asserts or --disable-asserts was given. +if test "${enable_asserts+set}" = set; then + enableval="$enable_asserts" + case "${enableval}" in + yes) cyginfra_asserts=yes ;; + no) cyginfra_asserts=no ;; + *) { echo "configure: error: bad value ${enableval} for disable-asserts option" 1>&2; exit 1; } ;; +esac +fi + +if test "${cyginfra_asserts}" = "yes"; then + cat >> confdefs.h <<\EOF +#define CYGDBG_USE_ASSERTS 1 +EOF + +fi + +# Check whether --enable-preconditions or --disable-preconditions was given. +if test "${enable_preconditions+set}" = set; then + enableval="$enable_preconditions" + case "${enableval}" in + yes) cyginfra_preconditions=yes ;; + no) cyginfra_preconditions=no ;; + *) { echo "configure: error: bad value ${enableval} for disable-preconditions option" 1>&2; exit 1; } ;; +esac +fi + +if test "${cyginfra_preconditions}" = "yes"; then + cat >> confdefs.h <<\EOF +#define CYGDBG_INFRA_DEBUG_PRECONDITIONS 1 +EOF + +fi + +# Check whether --enable-postconditions or --disable-postconditions was given. +if test "${enable_postconditions+set}" = set; then + enableval="$enable_postconditions" + case "${enableval}" in + yes) cyginfra_postconditions=yes ;; + no) cyginfra_postconditions=no ;; + *) { echo "configure: error: bad value ${enableval} for disable-postconditions option" 1>&2; exit 1; } ;; +esac +fi + +if test "${cyginfra_postconditions}" = "yes"; then + cat >> confdefs.h <<\EOF +#define CYGDBG_INFRA_DEBUG_POSTCONDITIONS 1 +EOF + +fi + +# Check whether --enable-invariants or --disable-invariants was given. +if test "${enable_invariants+set}" = set; then + enableval="$enable_invariants" + case "${enableval}" in + yes) cyginfra_invariants=yes ;; + no) cyginfra_invariants=no ;; + *) { echo "configure: error: bad value ${enableval} for disable-invariants option" 1>&2; exit 1; } ;; +esac +fi + +if test "${cyginfra_invariants}" = "yes"; then + cat >> confdefs.h <<\EOF +#define CYGDBG_INFRA_DEBUG_INVARIANTS 1 +EOF + +fi + +# Check whether --enable-loopinvariants or --disable-loopinvariants was given. +if test "${enable_loopinvariants+set}" = set; then + enableval="$enable_loopinvariants" + case "${enableval}" in + yes) cyginfra_loopinvariants=yes ;; + no) cyginfra_loopinvariants=no ;; + *) { echo "configure: error: bad value ${enableval} for disable-loopinvariants option" 1>&2; exit 1; } ;; +esac +fi + +if test "${cyginfra_loopinvariants}" = "yes"; then + cat >> confdefs.h <<\EOF +#define CYGDBG_INFRA_DEBUG_LOOP_INVARIANTS 1 +EOF + +fi + +# Check whether --enable-tracing or --disable-tracing was given. +if test "${enable_tracing+set}" = set; then + enableval="$enable_tracing" + case "${enableval}" in + yes) cyginfra_tracing=yes ;; + no) cyginfra_tracing=no ;; + *) { echo "configure: error: bad value ${enableval} for disable-tracing option" 1>&2; exit 1; } ;; +esac +fi + +if test "${cyginfra_tracing}" = "yes"; then + cat >> confdefs.h <<\EOF +#define CYGDBG_USE_TRACING 1 +EOF + +fi + +# Check whether --enable-fntracing or --disable-fntracing was given. +if test "${enable_fntracing+set}" = set; then + enableval="$enable_fntracing" + case "${enableval}" in + yes) cyginfra_fntracing=yes ;; + no) cyginfra_fntracing=no ;; + *) { echo "configure: error: bad value ${enableval} for disable-fntracing option" 1>&2; exit 1; } ;; +esac +fi + +if test "${cyginfra_fntracing}" = "yes"; then + cat >> confdefs.h <<\EOF +#define CYGDBG_INFRA_DEBUG_FUNCTION_REPORTS 1 +EOF + +fi + + + + + + + + + +echo $ac_n "checking for Tcl version""... $ac_c" 1>&6 +echo "configure:1637: checking for Tcl version" >&5 +# Check whether --with-tcl-version or --without-tcl-version was given. +if test "${with_tcl_version+set}" = set; then + withval="$with_tcl_version" + + cyg_ac_tcl_version=${with_tcl_version} + +else + + if test "${MSVC}" = "yes" ; then + cyg_ac_tcl_version=80 + else + if test "${ac_cv_cygwin}" = "yes" ; then + cyg_ac_tcl_version=80 + else + cyg_ac_tcl_version="" + fi + fi + +fi + +echo "$ac_t""${cyg_ac_tcl_version}" 1>&6 + + +echo $ac_n "checking for Tcl installation""... $ac_c" 1>&6 +echo "configure:1662: checking for Tcl installation" >&5 +# Check whether --with-tcl or --without-tcl was given. +if test "${with_tcl+set}" = set; then + withval="$with_tcl" + + cyg_ac_tcl_incdir=${with_tcl}/include + cyg_ac_tcl_libdir=${with_tcl}/lib + +else + + cyg_ac_tcl_incdir=${prefix}/include + cyg_ac_tcl_libdir=${prefix}/lib + +fi + +echo "$ac_t""${cyg_ac_tcl_libdir}" 1>&6 + +if test \! -r ${cyg_ac_tcl_incdir}/tcl.h ; then + { echo "configure: error: unable to locate Tcl header file tcl.h" 1>&2; exit 1; } +fi + +if test "${MSVC}" = "yes" ; then + cyg_ac_tcl_libs="tcl${cyg_ac_tcl_version}.lib" + + + + + if test "${MSVC}" = "yes" ; then + cyg_ac_tcl_incdir=`cygpath -w ${cyg_ac_tcl_incdir} | tr \\\\\\\\ /` + fi + + + + + + if test "${MSVC}" = "yes" ; then + cyg_ac_tcl_libdir=`cygpath -w ${cyg_ac_tcl_libdir} | tr \\\\\\\\ /` + fi + +else + if test \! -r ${cyg_ac_tcl_libdir}/tclConfig.sh ; then + { echo "configure: error: unable to locate Tcl config file tclConfig.sh" 1>&2; exit 1; } + else + . ${cyg_ac_tcl_libdir}/tclConfig.sh + cyg_ac_tcl_libs="-ltcl${cyg_ac_tcl_version} ${TCL_LIBS}" + fi +fi + + + + + + + + +echo $ac_n "checking for infrastructure files""... $ac_c" 1>&6 +echo "configure:1718: checking for infrastructure files" >&5 +# Check whether --with-infra or --without-infra was given. +if test "${with_infra+set}" = set; then + withval="$with_infra" + + cyg_ac_infra_incdir=${with_infra} + cyg_ac_infra_libdir=${with_infra} + +else + + if test -d ../infra ; then + cyg_ac_infra_incdir=../infra + cyg_ac_infra_libdir=../infra + else + cyg_ac_infra_incdir=${prefix}/include + cyg_ac_ac_infra_libdir=${prefix}/lib + fi + +fi + + + + + + if test "${MSVC}" = "yes" ; then + cyg_ac_infra_incdir=`cygpath -w ${cyg_ac_infra_incdir} | tr \\\\\\\\ /` + fi + + + + + + if test "${MSVC}" = "yes" ; then + cyg_ac_infra_libdir=`cygpath -w ${cyg_ac_infra_libdir} | tr \\\\\\\\ /` + fi + + + +echo "$ac_t""-I${cyg_ac_infra_incdir} -L${cyg_ac_infra_libdir}" 1>&6 + +if test "${MSVC}" = "yes" ; then + INCLUDES="\"-I`cygpath -w ${srcdir} | tr \\\\\\\\ /`\" \"-I${cyg_ac_infra_incdir}\" \"-I${cyg_ac_tcl_incdir}\"" +else + INCLUDES="-I${cyg_ac_infra_incdir} -I${cyg_ac_tcl_incdir}" +fi + + + + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile:Makefile.in testsuite/Makefile:testsuite/Makefile.in cdlconfig.h:config.h.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@host@%$host%g +s%@host_alias@%$host_alias%g +s%@host_cpu@%$host_cpu%g +s%@host_vendor@%$host_vendor%g +s%@host_os@%$host_os%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@PACKAGE@%$PACKAGE%g +s%@VERSION@%$VERSION%g +s%@ACLOCAL@%$ACLOCAL%g +s%@AUTOCONF@%$AUTOCONF%g +s%@AUTOMAKE@%$AUTOMAKE%g +s%@AUTOHEADER@%$AUTOHEADER%g +s%@MAKEINFO@%$MAKEINFO%g +s%@SET_MAKE@%$SET_MAKE%g +s%@MAINTAINER_MODE_TRUE@%$MAINTAINER_MODE_TRUE%g +s%@MAINTAINER_MODE_FALSE@%$MAINTAINER_MODE_FALSE%g +s%@MAINT@%$MAINT%g +s%@CC@%$CC%g +s%@CXX@%$CXX%g +s%@RANLIB@%$RANLIB%g +s%@OBJEXT@%$OBJEXT%g +s%@EXEEXT@%$EXEEXT%g +s%@MSVC_TRUE@%$MSVC_TRUE%g +s%@MSVC_FALSE@%$MSVC_FALSE%g +s%@cyg_ac_tcl_version@%$cyg_ac_tcl_version%g +s%@cyg_ac_tcl_incdir@%$cyg_ac_tcl_incdir%g +s%@cyg_ac_tcl_libdir@%$cyg_ac_tcl_libdir%g +s%@cyg_ac_tcl_libs@%$cyg_ac_tcl_libs%g +s%@cyg_ac_tk_libs@%$cyg_ac_tk_libs%g +s%@cyg_ac_infra_incdir@%$cyg_ac_infra_incdir%g +s%@cyg_ac_infra_libdir@%$cyg_ac_infra_libdir%g +s%@INCLUDES@%$INCLUDES%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/host/libcdl/configure.in b/host/libcdl/configure.in new file mode 100644 --- /dev/null +++ b/host/libcdl/configure.in @@ -0,0 +1,126 @@ +dnl Process this file with autoconf to produce a configure script. +dnl ==================================================================== +dnl +dnl configure.in +dnl +dnl libcdl.a +dnl +dnl ==================================================================== +dnl####COPYRIGHTBEGIN#### +dnl +dnl ---------------------------------------------------------------------------- +dnl Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +dnl +dnl This file is part of the eCos host tools. +dnl +dnl This program is free software; you can redistribute it and/or modify it +dnl under the terms of the GNU General Public License as published by the Free +dnl Software Foundation; either version 2 of the License, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but WITHOUT +dnl ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +dnl FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +dnl more details. +dnl +dnl You should have received a copy of the GNU General Public License along with +dnl this program; if not, write to the Free Software Foundation, Inc., +dnl 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl ---------------------------------------------------------------------------- +dnl +dnl####COPYRIGHTEND#### +dnl ==================================================================== +dnl#####DESCRIPTIONBEGIN#### +dnl +dnl Author(s): bartv +dnl Contact(s): bartv +dnl Date: 1998/12/16 +dnl Version: 0.01 +dnl +dnl####DESCRIPTIONEND#### +dnl ==================================================================== + +dnl The core header file had better be present. +AC_INIT(cdlcore.hxx) + +dnl Pick up the support files from the top-level of the source tree, +dnl one level above packages. +AC_CONFIG_AUX_DIR(..) + +dnl Other standard options. +AC_CANONICAL_HOST + +AM_INIT_AUTOMAKE(libcdl, 0.2) +CYG_AC_SUBST_VERSION(CYGNUM_LIBCDL_VERSION) +AM_MAINTAINER_MODE + +dnl The package contains a library implemented in C++. It has to be +dnl buildable under NT. Only a static version of the library is +dnl of interest at the moment. +AC_PROG_MAKE_SET +AC_PROG_CC +AC_PROG_CXX +AC_PROG_RANLIB +AC_OBJEXT +AC_EXEEXT +CYG_AC_PROG_MSVC +CYG_AC_PROG_STANDARD_COMPILER_FLAGS + +dnl AM_DISABLE_SHARED +dnl AM_PROG_LIBTOOL + +dnl This package cannot be cross-compiled yet. +if test ${cross_compiling} = yes; then + AC_MSG_ERROR(cross-compilation of this package is not supported) +fi + +dnl Allow the usual assertion and trace related options. +CYG_AC_ARG_INFRASTRUCTURE + +dnl What version of Tcl should be used? +CYG_AC_PATH_TCL + +dnl ------------------------------------------------------------------------ +dnl Where should the infrastructure headers come from? +dnl The default is ../../../../infra/current/host. If the +dnl appropriate header file is not found there, try +dnl $(DESTDIR)$(includedir). In addition allow the user to override +dnl the location with a suitable --with command line argument. + +AC_MSG_CHECKING(for infrastructure files) +AC_ARG_WITH(infra,[ --with-infra=dir location of the infrastructure build tree],[ + cyg_ac_infra_incdir=${with_infra} + cyg_ac_infra_libdir=${with_infra} +],[ + if test -d ../infra ; then + cyg_ac_infra_incdir=../infra + cyg_ac_infra_libdir=../infra + else + cyg_ac_infra_incdir=${prefix}/include + cyg_ac_ac_infra_libdir=${prefix}/lib + fi +]) +CYG_AC_MSVC_PATH(cyg_ac_infra_incdir) +CYG_AC_MSVC_PATH(cyg_ac_infra_libdir) +AC_SUBST(cyg_ac_infra_incdir) +AC_SUBST(cyg_ac_infra_libdir) +AC_MSG_RESULT(-I${cyg_ac_infra_incdir} -L${cyg_ac_infra_libdir}) + +dnl ------------------------------------------------------------------------ +dnl If VC++ is being used then srcdir is likely to be a cygwin path +dnl rather than a Windows path. This means that the default -I +dnl paths generated by automake will not be acceptable to the compiler. +dnl This should probably be fixed in automake's comp-vars.am file, +dnl but for now this suffices. It is also necessary to worry about +dnl infra_incdir and tcl_incdir +if test "${MSVC}" = "yes" ; then + INCLUDES="\"-I`cygpath -w ${srcdir} | tr \\\\\\\\ /`\" \"-I${cyg_ac_infra_incdir}\" \"-I${cyg_ac_tcl_incdir}\"" +else + INCLUDES="-I${cyg_ac_infra_incdir} -I${cyg_ac_tcl_incdir}" +fi +AC_SUBST(INCLUDES) + +dnl -------------------------------------------------------------------- +AM_CONFIG_HEADER(cdlconfig.h:config.h.in) +AC_OUTPUT(Makefile:Makefile.in testsuite/Makefile:testsuite/Makefile.in) diff --git a/host/libcdl/conflict.cxx b/host/libcdl/conflict.cxx new file mode 100644 --- /dev/null +++ b/host/libcdl/conflict.cxx @@ -0,0 +1,1039 @@ +//{{{ Banner + +//============================================================================ +// +// conflict.cxx +// +// The CdlConflict class +// +//============================================================================ +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================ +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contact(s): bartv +// Date: 1999/01/28 +// Version: 0.02 +// +//####DESCRIPTIONEND#### +//============================================================================ + +//}}} +//{{{ #include's + +// ---------------------------------------------------------------------------- +#include "cdlconfig.h" + +// Get the infrastructure types, assertions, tracing and similar +// facilities. +#include +#include + +// defines everything implemented in this module. +// It implicitly supplies , and because +// the class definitions rely on these headers. It also brings +// in +#include + +//}}} + +//{{{ Statics + +// ---------------------------------------------------------------------------- +CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlConflictBody); +CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlConflict_UnresolvedBody); +CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlConflict_IllegalValueBody); +CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlConflict_EvalExceptionBody); +CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlConflict_RequiresBody); +CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlConflict_DataBody); + +//}}} +//{{{ CdlConflict + +//{{{ Creation and destruction + +// ---------------------------------------------------------------------------- +// The basic conflicts. Conflicts are created in the context of a transaction. +// If the transaction gets committed then they are transferred to a toplevel. +// If the transaction gets cancelled then they just disappear. +// +// A conflict that is only part of a transaction may go away as that +// transaction proceeds, in which case it can be deleted immediately. +// A conflict that is already part of the toplevel cannot be +// destroyed, instead it gets marked in the transaction object. Only +// when the transaction is committed does the object get deleted. +// In addition within the context of a transaction old conflicts +// may hang around for a while. +// + +CdlConflictBody::CdlConflictBody(CdlTransaction trans_arg, CdlNode node_arg, CdlProperty property_arg, bool structural_arg) +{ + CYG_REPORT_FUNCNAME("CdlConflict:: constructor"); + CYG_REPORT_FUNCARG4XV(this, trans_arg, node_arg, property_arg); + CYG_PRECONDITION_CLASSC(trans_arg); + CYG_PRECONDITION_CLASSC(node_arg); + CYG_PRECONDITION_CLASSC(property_arg); + + node = node_arg; + property = property_arg; + transaction = trans_arg; + structural = structural_arg; + no_solution = false; + // The vectors take care of themselves + enabled = true; + reason = ""; + + transaction->dirty = true; + if (structural_arg) { + transaction->new_structural_conflicts.push_back(this); + } else { + transaction->new_conflicts.push_back(this); + } + + cdlconflictbody_cookie = CdlConflictBody_Magic; + CYGDBG_MEMLEAK_CONSTRUCTOR(); + + CYG_POSTCONDITION_THISC(); + CYG_REPORT_RETURN(); +} + + +// ---------------------------------------------------------------------------- +// The destructor can get invoked during a transaction commit, in the +// case of a global conflict, or from inside clear() for a per-transaction +// conflict. In all cases the calling code is responsible for removing +// the conflict from any STL containers. + +CdlConflictBody::~CdlConflictBody() +{ + CYG_REPORT_FUNCNAME("CdlConflict:: destructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + cdlconflictbody_cookie = CdlConflictBody_Invalid; + reason = ""; + enabled = false; + no_solution = false; + solution.clear(); + solution_references.clear(); + structural = false; + transaction = 0; + property = 0; + node = 0; + CYGDBG_MEMLEAK_DESTRUCTOR(); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ Solution support + +// ---------------------------------------------------------------------------- +bool +CdlConflictBody::has_known_solution() const +{ + CYG_REPORT_FUNCNAMETYPE("CdlConflict::has_solution", "result %d"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + bool result = (0 != solution.size()); + + CYG_REPORT_RETVAL(result); + return result; +} + +bool +CdlConflictBody::has_no_solution() const +{ + CYG_REPORT_FUNCNAMETYPE("CdlConflict::has_no_solution", "result %d"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + bool result = no_solution; + + CYG_REPORT_RETVAL(result); + return result; +} + +const std::vector >& +CdlConflictBody::get_solution() const +{ + CYG_REPORT_FUNCNAME("CdlConflict::get_solution"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CYG_REPORT_RETURN(); + return solution; +} + +const std::set& +CdlConflictBody::get_solution_references() const +{ + CYG_REPORT_FUNCNAME("CdlConflict::get_solution_references"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CYG_REPORT_RETURN(); + return solution_references; +} + +// ---------------------------------------------------------------------------- +// Try to resolve a conflict. If the conflict was created in a transaction, +// use that transaction. More commonly the conflict will be global and +// a new transaction will have to be created specially for it. Either +// way the conflict may cease to exist. +void +CdlConflictBody::resolve() +{ + CYG_REPORT_FUNCNAME("CdlConflict::resolve"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITIONC(0 == transaction); + + if (this->resolution_implemented()) { + CdlTransaction transact = CdlTransactionBody::make(this->get_node()->get_toplevel()); + transact->resolve(this); + transact->body(); + delete transact; + } + + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- +// A valuable has just been changed. If this value was relevant to the +// current solution (or lack thereof) then an update is necessary. +void +CdlConflictBody::update_solution_validity(CdlValuable valuable) +{ + CYG_REPORT_FUNCNAME("CdlConflict::update_solution_validity"); + CYG_REPORT_FUNCARG2XV(this, valuable); + CYG_PRECONDITION_THISC(); + + if (solution_references.find(valuable) != solution_references.end()) { + no_solution = false; + solution.clear(); + solution_references.clear(); + } + + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- +// Default implementations of the inference engine do not do a lot... +bool +CdlConflictBody::inner_resolve(CdlTransaction trans_arg, int level) +{ + CYG_REPORT_FUNCNAMETYPE("CdlConflict::inner_resolve", "result false"); + CYG_REPORT_FUNCARG3XV(this, trans_arg, level); + CYG_PRECONDITION_THISC(); + CYG_PRECONDITION_CLASSC(trans_arg); + + // Setting the no_solution flag while keeping a clear + // solution_accessed vector means that the no_solution flag should + // always remain set, and hence no further inference attempts will be made. + no_solution = true; + + CYG_REPORT_RETURN(); + return false; +} + +bool +CdlConflictBody::resolution_implemented() const +{ + CYG_REPORT_FUNCNAMETYPE("CdlConflict::resolution_implemented", "result %d"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CYG_REPORT_RETVAL(false); + return false; +} + +// ---------------------------------------------------------------------------- +// Clearing a solution. This is needed if the inference engine has +// failed to find a complete solution, because in attempting this the +// solution_references vector will have been filled in anyway. It may +// have some other uses as well. +void +CdlConflictBody::clear_solution() +{ + CYG_REPORT_FUNCNAME("CdlConflict::clear_solution"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + no_solution = false; + solution.clear(); + solution_references.clear(); + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ Basics + +// ---------------------------------------------------------------------------- + +CdlNode +CdlConflictBody::get_node() const +{ + CYG_REPORT_FUNCNAMETYPE("CdlConflict::get_node", "result %p"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlNode result = node; + CYG_REPORT_RETVAL(result); + return result; +} + +CdlProperty +CdlConflictBody::get_property() const +{ + CYG_REPORT_FUNCNAMETYPE("CdlConflict::get_property", "result %p"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlProperty result = property; + CYG_REPORT_RETVAL(result); + return result; +} + +bool +CdlConflictBody::is_structural() const +{ + CYG_REPORT_FUNCNAMETYPE("CdlConflict::is_structural", "result %d"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + bool result = structural; + CYG_REPORT_RETVAL(result); + return result; +} + +CdlTransaction +CdlConflictBody::get_transaction() const +{ + CYG_REPORT_FUNCNAMETYPE("CdlConflict::get_transaction", "result %p"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlTransaction result = transaction; + CYG_REPORT_RETVAL(result); + return result; +} + +// FIXME: these are not currently implemented. It would be necessary +// to store the information in the savefile, which requires an +// unambiguous way of identifying a conflict that is likely to +// survice package version changes. + +bool +CdlConflictBody::is_enabled() const +{ + CYG_REPORT_FUNCNAMETYPE("CdlConflict::is_enabled", "result %d"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + bool result = enabled; + CYG_REPORT_RETVAL(result); + return result; +} + +std::string +CdlConflictBody::get_disabled_reason() const +{ + CYG_REPORT_FUNCNAME("CdlConflict::get_disabled_reason"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + // Possibly there should be a check that the conflict is currently + // disabled, but it might be useful. + CYG_REPORT_RETURN(); + return reason; +} + +void +CdlConflictBody::disable(std::string reason_arg) +{ + CYG_REPORT_FUNCNAME("CdlConflict::disable"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + reason = reason_arg; + enabled = false; + + CYG_REPORT_RETURN(); +} + +void +CdlConflictBody::enable() +{ + CYG_REPORT_FUNCNAME("CdlConflict::enable"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + enabled = true; + // Leave "reason" alone, it may still be useful + + CYG_REPORT_RETURN(); +} + +//}}} +//{{{ check_this() + +// ---------------------------------------------------------------------------- +bool +CdlConflictBody::check_this(cyg_assert_class_zeal zeal) const +{ + if (CdlConflictBody_Magic != cdlconflictbody_cookie) { + return false; + } + CYGDBG_MEMLEAK_CHECKTHIS(); + if ((0 == node) || (0 == property)) { + return false; + } + switch(zeal) { + case cyg_system_test : + case cyg_extreme : + { + if (!node->check_this(cyg_quick)) { + return false; + } + // Accessing the properties would involve a function call. + + if (0 != transaction) { + if (!transaction->check_this(cyg_quick)) { + return false; + } + if (structural) { + // The conflict should exist in the new_structural_conflicts vector + // deleted_structural_conflicts is for toplevel ones. + if (std::find(transaction->new_structural_conflicts.begin(), + transaction->new_structural_conflicts.end(), this) == + transaction->new_structural_conflicts.end()) { + return false; + } + } else { + // The conflict may appear on the new_conflicts list + // or in the resolved_conflicts vector. + if (std::find(transaction->new_conflicts.begin(), transaction->new_conflicts.end(), this) == + transaction->new_conflicts.end()) { + + if (std::find(transaction->resolved_conflicts.begin(), transaction->resolved_conflicts.end(), this) == + transaction->resolved_conflicts.end()) { + + return false; + } + } + } + } + // Checking the toplevel lists would be good, but involves a + // further function call and hence nested assertions. + } + case cyg_thorough : + { + if (!node->check_this(cyg_quick)) { + return false; + } + if (!property->check_this(cyg_quick)) { + return false; + } + } + case cyg_quick : + { + if (no_solution && (0 != solution.size())) { + return false; + } + } + case cyg_trivial : + case cyg_none : + default: + break; + } + + return true; +} + +//}}} + +//}}} +//{{{ CdlConflict_Unresolved + +// ---------------------------------------------------------------------------- +// Unresolved references. Usually unresolved references occur inside +// expressions, but other properties that may be affected are parent, +// dialog and wizard. +// +// It is possible for a single expression to have multiple unresolved +// references, each of which will result in a separate conflict +// object. It is also possible for an expression to refer to the same +// unknown entity twice or more, in which case there would also be +// separate conflict objects. Unresolved references may also result in +// eval exceptions and in failed requires statements. Trying to cope +// with the various combinations as a single conflict seems too +// error-prone. + +void +CdlConflict_UnresolvedBody::make(CdlTransaction trans, CdlNode node_arg, CdlProperty prop_arg, std::string name_arg) +{ + CdlConflict_Unresolved tmp = new CdlConflict_UnresolvedBody(trans, node_arg, prop_arg, name_arg); + CYG_UNUSED_PARAM(CdlConflict_Unresolved, tmp); +} + +CdlConflict_UnresolvedBody::CdlConflict_UnresolvedBody(CdlTransaction trans_arg, CdlNode node_arg, CdlProperty prop_arg, + std::string target_name_arg) + : CdlConflictBody(trans_arg, node_arg, prop_arg, true) +{ + CYG_REPORT_FUNCNAME("CdlConflict_Unresolved:: constructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITIONC("" != target_name_arg); + + target_name = target_name_arg; + cdlconflict_unresolvedbody_cookie = CdlConflict_UnresolvedBody_Magic; + CYGDBG_MEMLEAK_CONSTRUCTOR(); + + CYG_POSTCONDITION_THISC(); + CYG_REPORT_RETURN(); +} + +CdlConflict_UnresolvedBody::~CdlConflict_UnresolvedBody() +{ + CYG_REPORT_FUNCNAME("CdlConflict_Unresolved:: destructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + cdlconflict_unresolvedbody_cookie = CdlConflict_UnresolvedBody_Invalid; + target_name = ""; + CYGDBG_MEMLEAK_DESTRUCTOR(); + + CYG_REPORT_RETURN(); +} + +std::string +CdlConflict_UnresolvedBody::get_target_name() const +{ + CYG_REPORT_FUNCNAME("CdlConflict_Unresolved::get_target_name"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CYG_REPORT_RETURN(); + return target_name; +} + +// For now, just report the node and property name, a brief text, and the +// entity being referenced. +// +// Eventually we can do clever things like looking up the name in a +// database. + +std::string +CdlConflict_UnresolvedBody::get_explanation() const +{ + CYG_REPORT_FUNCNAME("CdlConflict_Unresolved::get_explanation"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + std::string result; + result = node->get_name() + ", property " + property->get_property_name() + + ":\nReference to unknown object " + target_name; + + CYG_REPORT_RETURN(); + return result; +} + +bool +CdlConflict_UnresolvedBody::check_this(cyg_assert_class_zeal zeal) const +{ + if (CdlConflict_UnresolvedBody_Magic != cdlconflict_unresolvedbody_cookie) { + return false; + } + CYGDBG_MEMLEAK_CHECKTHIS(); + + // There is not a lot of checking that can be done on the name. + + return CdlConflictBody::check_this(zeal); +} + +bool +CdlConflict_UnresolvedBody::test(CdlConflict conf) +{ + CYG_REPORT_FUNCNAMETYPE("CdlConflict_Unresolved::test", "result %d"); + CYG_REPORT_FUNCARG1XV(conf); + CYG_PRECONDITION_CLASSC(conf); + + bool result = false; + CdlConflict_Unresolved tmp = dynamic_cast(conf); + if (0 != tmp) { + result = true; + } + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ CdlConflict_IllegalValue + +// ---------------------------------------------------------------------------- +// A valuable object has an illegal value. This can happen because the +// current value is not within the legal_values list, or because of a +// failure of check_proc or entry_proc. In the latter two cases the +// Tcl code should supply an explanation as to why the value is illegal. +// +// Note: if future variants of CDL implement some concept of a value +// that does not match the CdlValuable class then that will need a +// separate CdlConflict derived class. + +void +CdlConflict_IllegalValueBody::make(CdlTransaction trans, CdlNode node_arg, CdlProperty prop_arg) +{ + CdlConflict_IllegalValue tmp = new CdlConflict_IllegalValueBody(trans, node_arg, prop_arg); + CYG_UNUSED_PARAM(CdlConflict_IllegalValue, tmp); +} + +CdlConflict_IllegalValueBody::CdlConflict_IllegalValueBody(CdlTransaction trans, CdlNode node_arg, CdlProperty prop_arg) + : CdlConflictBody(trans, node_arg, prop_arg, false) +{ + CYG_REPORT_FUNCNAME("CdlConflict_IllegalValue:: constructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITIONC(0 != dynamic_cast(node_arg)); + + explanation = ""; + cdlconflict_illegalvaluebody_cookie = CdlConflict_IllegalValueBody_Magic; + CYGDBG_MEMLEAK_CONSTRUCTOR(); + + CYG_POSTCONDITION_THISC(); + CYG_REPORT_RETURN(); +} + +CdlConflict_IllegalValueBody::~CdlConflict_IllegalValueBody() +{ + CYG_REPORT_FUNCNAME("CdlConflict_IllegalValue:: destructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + cdlconflict_illegalvaluebody_cookie = CdlConflict_IllegalValueBody_Invalid; + explanation = ""; + CYGDBG_MEMLEAK_DESTRUCTOR(); + + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- +// If the property is legal_values then it should be a list expression +// property. Display the current value and the original expression. +// +// If the property is check_proc or entry_proc, the Tcl code should +// have produced an explanation string and stored it in the conflict +// object. +std::string +CdlConflict_IllegalValueBody::get_explanation() const +{ + CYG_REPORT_FUNCNAME("CdlConflict_IllegalValue::get_explanation()"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlConstValuable valuable = dynamic_cast(node); + CYG_ASSERTC(0 != valuable); + + std::string result = ""; + + // FIXME: analyse the current value and flavor a bit more + result += "Illegal current value " + valuable->get_value() + "\n"; + + if (CdlPropertyId_LegalValues == property->get_property_name()) { + + CdlConstProperty_ListExpression expr = dynamic_cast(property); + CYG_ASSERTC(0 != expr); + result += "Legal values are: " + expr->get_original_string(); + + } else if (explanation != "") { + + result += explanation; + } else { + + CYG_FAIL("Inexplicable illegal value"); + } + + CYG_REPORT_RETURN(); + return result; +} + +void +CdlConflict_IllegalValueBody::set_explanation(std::string explanation_arg) +{ + CYG_REPORT_FUNCNAME("CdlConflict_IllegalValue::set_explanation"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + explanation = explanation_arg; + + CYG_REPORT_RETURN(); +} + +// ---------------------------------------------------------------------------- +// Inference is implemented. The actual inference code is in infer.cxx +bool +CdlConflict_IllegalValueBody::resolution_implemented() const +{ + CYG_REPORT_FUNCNAME("CdlConflict_IllegalValue::resolution_implemented"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CYG_REPORT_RETURN(); + return true; +} + +// ---------------------------------------------------------------------------- +bool +CdlConflict_IllegalValueBody::check_this(cyg_assert_class_zeal zeal) const +{ + if (CdlConflict_IllegalValueBody_Magic != cdlconflict_illegalvaluebody_cookie) { + return false; + } + CYGDBG_MEMLEAK_CHECKTHIS(); + + return CdlConflictBody::check_this(zeal); +} + +bool +CdlConflict_IllegalValueBody::test(CdlConflict conf) +{ + CYG_REPORT_FUNCNAMETYPE("CdlConflict_IllegalValue::test", "result %d"); + CYG_REPORT_FUNCARG1XV(conf); + CYG_PRECONDITION_CLASSC(conf); + + bool result = false; + CdlConflict_IllegalValue tmp = dynamic_cast(conf); + if (0 != tmp) { + result = true; + } + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ CdlConflict_EvalException + +// ---------------------------------------------------------------------------- +// Run-time expression failures are possible because of division by +// zero, if for no other reason. The evaluation code should have +// stored a suitable diagnostic with the conflict. This is not part +// of the constructor, allowing the conflict object to be re-used +// if the detailed reason changes + +void +CdlConflict_EvalExceptionBody::make(CdlTransaction trans, CdlNode node_arg, CdlProperty prop_arg, std::string msg_arg) +{ + CdlConflict_EvalException tmp = new CdlConflict_EvalExceptionBody(trans, node_arg, prop_arg, msg_arg); + CYG_UNUSED_PARAM(CdlConflict_EvalException, tmp); +} + +CdlConflict_EvalExceptionBody::CdlConflict_EvalExceptionBody(CdlTransaction trans, CdlNode node_arg, CdlProperty prop_arg, + std::string msg_arg) + : CdlConflictBody(trans, node_arg, prop_arg, false) +{ + CYG_REPORT_FUNCNAME("CdlConflict_EvalException"); + CYG_REPORT_FUNCARG1XV(this); + + explanation = msg_arg; + cdlconflict_evalexceptionbody_cookie = CdlConflict_EvalExceptionBody_Magic; + CYGDBG_MEMLEAK_CONSTRUCTOR(); + + CYG_POSTCONDITION_THISC(); + CYG_REPORT_RETURN(); +} + +CdlConflict_EvalExceptionBody::~CdlConflict_EvalExceptionBody() +{ + CYG_REPORT_FUNCNAME("CdlConflict_EvalException"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + cdlconflict_evalexceptionbody_cookie = CdlConflict_EvalExceptionBody_Invalid; + explanation = ""; + CYGDBG_MEMLEAK_DESTRUCTOR(); + + CYG_REPORT_RETURN(); +} + +// If there has been an eval exception then the property must be an +// ordinary expression, a list expression, or a goal expression +std::string +CdlConflict_EvalExceptionBody::get_explanation() const +{ + CYG_REPORT_FUNCNAME("CdlConflict_EvalException::get_explanation"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + std::string result = node->get_name() + ", property " + property->get_property_name() + "\n"; + result += "Error while evaluation expression: "; + if ("" != explanation) { + result += explanation; + } + result += "\n"; + + if (CdlConstProperty_Expression expr = dynamic_cast(property)) { + + result += "Expression: " + expr->get_original_string(); + + } else if (CdlConstProperty_ListExpression lexpr = dynamic_cast(property)) { + + result += "List expression: " + lexpr->get_original_string(); + + } else if (CdlConstProperty_GoalExpression gexpr = dynamic_cast(property)) { + + result += "Goal expression: " + gexpr->get_original_string(); + + } else { + CYG_FAIL("Unknown expression type"); + } + + CYG_REPORT_RETURN(); + return result; +} + +void +CdlConflict_EvalExceptionBody::set_explanation(std::string explanation_arg) +{ + CYG_REPORT_FUNCNAME("CdlConflict_EvalException::set_explanation"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + explanation = explanation_arg; + + CYG_REPORT_RETURN(); +} + +bool +CdlConflict_EvalExceptionBody::check_this(cyg_assert_class_zeal zeal) const +{ + if (CdlConflict_EvalExceptionBody_Magic != cdlconflict_evalexceptionbody_cookie) { + return false; + } + CYGDBG_MEMLEAK_CHECKTHIS(); + return CdlConflictBody::check_this(zeal); +} + +bool +CdlConflict_EvalExceptionBody::test(CdlConflict conf) +{ + CYG_REPORT_FUNCNAMETYPE("CdlConflict_EvalException::test", "result %d"); + CYG_REPORT_FUNCARG1XV(conf); + CYG_PRECONDITION_CLASSC(conf); + + bool result = false; + CdlConflict_EvalException tmp = dynamic_cast(conf); + if (0 != tmp) { + result = true; + } + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ CdlConflict_Requires + +// ---------------------------------------------------------------------------- +// A requires constraint is not satisfied. Producing a decent diagnostic +// here requires a detailed understanding of goal expressions. For now +// there is no extra data associated with goal expressions. + +void +CdlConflict_RequiresBody::make(CdlTransaction trans, CdlNode node_arg, CdlProperty prop_arg) +{ + CdlConflict_Requires tmp = new CdlConflict_RequiresBody(trans, node_arg, prop_arg); + CYG_UNUSED_PARAM(CdlConflict_Requires, tmp); +} + +CdlConflict_RequiresBody::CdlConflict_RequiresBody(CdlTransaction trans, CdlNode node_arg, CdlProperty prop_arg) + : CdlConflictBody(trans, node_arg, prop_arg, false) +{ + CYG_REPORT_FUNCNAME("CdlConflict_Requires:: constructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITIONC(0 != dynamic_cast(prop_arg)); + + cdlconflict_requiresbody_cookie = CdlConflict_RequiresBody_Magic; + CYGDBG_MEMLEAK_CONSTRUCTOR(); + + CYG_POSTCONDITION_THISC(); + CYG_REPORT_RETURN(); +} + +CdlConflict_RequiresBody::~CdlConflict_RequiresBody() +{ + CYG_REPORT_FUNCNAME("CdlConflict_Requires:: destructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + cdlconflict_requiresbody_cookie = CdlConflict_RequiresBody_Invalid; + CYGDBG_MEMLEAK_DESTRUCTOR(); + + CYG_REPORT_RETURN(); +} + +// FIXME: implement properly +std::string +CdlConflict_RequiresBody::get_explanation() const +{ + CYG_REPORT_FUNCNAME("CdlConflict::get_explanation"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CdlConstProperty_GoalExpression gexpr = dynamic_cast(property); + CYG_ASSERTC(0 != gexpr); + + std::string result = ""; + result += "Requires constraint not satisfied: " + gexpr->get_original_string(); + + CYG_REPORT_RETURN(); + return result; +} + +// Inference is implemented, see infer.cxx +bool +CdlConflict_RequiresBody::resolution_implemented() const +{ + CYG_REPORT_FUNCNAME("CdlConflict_Requires"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + CYG_REPORT_RETURN(); + return true; +} + +bool +CdlConflict_RequiresBody::check_this(cyg_assert_class_zeal zeal) const +{ + if (CdlConflict_RequiresBody_Magic != cdlconflict_requiresbody_cookie) { + return false; + } + CYGDBG_MEMLEAK_CHECKTHIS(); + return CdlConflictBody::check_this(zeal); +} + +bool +CdlConflict_RequiresBody::test(CdlConflict conf) +{ + CYG_REPORT_FUNCNAMETYPE("CdlConflict_Requires::test", "result %d"); + CYG_REPORT_FUNCARG1XV(conf); + CYG_PRECONDITION_CLASSC(conf); + + bool result = false; + CdlConflict_Requires tmp = dynamic_cast(conf); + if (0 != tmp) { + result = true; + } + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} +//{{{ CdlConflict_Data + +// ---------------------------------------------------------------------------- +// There is some strange problem in the configuration data, for example +// a parent property that is resolved but the target is not a container. + +void +CdlConflict_DataBody::make(CdlTransaction trans, CdlNode node_arg, CdlProperty prop_arg, std::string message_arg) +{ + CdlConflict_Data tmp = new CdlConflict_DataBody(trans, node_arg, prop_arg, message_arg); + CYG_UNUSED_PARAM(CdlConflict_Data, tmp); +} + +CdlConflict_DataBody::CdlConflict_DataBody(CdlTransaction trans, CdlNode node_arg, CdlProperty prop_arg, + std::string message_arg) + : CdlConflictBody(trans, node_arg, prop_arg, true) +{ + CYG_REPORT_FUNCNAME("CdlConflict_Data:: constructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITIONC("" != message_arg); + + message = message_arg; + cdlconflict_databody_cookie = CdlConflict_DataBody_Magic; + CYGDBG_MEMLEAK_CONSTRUCTOR(); + + CYG_POSTCONDITION_THISC(); + CYG_REPORT_RETURN(); +} + +CdlConflict_DataBody::~CdlConflict_DataBody() +{ + CYG_REPORT_FUNCNAME("CdlConflict_ata: destructor"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + cdlconflict_databody_cookie = CdlConflict_DataBody_Invalid; + CYGDBG_MEMLEAK_DESTRUCTOR(); + + CYG_REPORT_RETURN(); +} + +std::string +CdlConflict_DataBody::get_explanation() const +{ + CYG_REPORT_FUNCNAME("CdlConflict_Data::get_explanation"); + CYG_REPORT_FUNCARG1XV(this); + CYG_PRECONDITION_THISC(); + + std::string result = message; + + CYG_REPORT_RETURN(); + return result; +} + +bool +CdlConflict_DataBody::check_this(cyg_assert_class_zeal zeal) const +{ + if (CdlConflict_DataBody_Magic != cdlconflict_databody_cookie) { + return false; + } + CYGDBG_MEMLEAK_CHECKTHIS(); + return CdlConflictBody::check_this(zeal); +} + +bool +CdlConflict_DataBody::test(CdlConflict conf) +{ + CYG_REPORT_FUNCNAMETYPE("CdlConflict_Data::test", "result %d"); + CYG_REPORT_FUNCARG1XV(conf); + CYG_PRECONDITION_CLASSC(conf); + + bool result = false; + CdlConflict_Data tmp = dynamic_cast(conf); + if (0 != tmp) { + result = true; + } + + CYG_REPORT_RETVAL(result); + return result; +} + +//}}} diff --git a/host/libcdl/database.cxx b/host/libcdl/database.cxx new file mode 100644 --- /dev/null +++ b/host/libcdl/database.cxx @@ -0,0 +1,1901 @@ +//{{{ Banner + +//============================================================================ +// +// database.cxx +// +// Temporary implementation of the CdlPackagesDatabase class +// Implementations of the temporary CdlTargetsDatabase and +// CdlTemplatesDatabase classes. +// +//============================================================================ +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1999, 2000 Red Hat, Inc. +// +// This file is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================ +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contact(s): bartv +// Date: 1999/01/21 +// Version: 0.02 +// +//####DESCRIPTIONEND#### +//============================================================================ + +//}}} +//{{{ #include's + +// ---------------------------------------------------------------------------- +#include "cdlconfig.h" + +// Get the infrastructure types, assertions, tracing and similar +// facilities. +#include +#include + +// defines everything implemented in this module. +// It implicitly supplies , and because +// the class definitions rely on these headers. +#include + +// strcmp() is useful when dealing with Tcl strings. +#include + +//}}} + +//{{{ Statics + +// ---------------------------------------------------------------------------- +// Some test cases may want to read in a file other than +// "ecos.db", e.g. to facilitate testing the error conditions. +char* +CdlPackagesDatabaseBody::database_name = "ecos.db"; + +// ---------------------------------------------------------------------------- +// The new_package etc. commands need to store the name of the +// current package so that subsequent commands can do the right thing. +// Using constant strings as the key avoids typo problems. +const char* dbparser_current_package = "::dbparser_current_package"; +const char* dbparser_current_target = "::dbparser_current_target"; +const char* dbparser_component_repository = "::component_repository"; +const char* dbparser_database_name = "::database_name"; +const char* dbparser_pkgdir = "::pkgdir"; +const char* dbparser_current_version = "::version"; +const char* dbparser_current_script = "::script"; +const char* dbparser_database_key = "dbparser_key"; // for assoc data +const char* template_description_key = "__cdl_extract_template_description"; // ditto +const char* template_packages_key = "_cdl_extract_template_packages"; + +CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlPackagesDatabaseBody); + +//}}} +//{{{ Utility Tcl scripts + +// ---------------------------------------------------------------------------- +// Utility scripts. +// +// Given a directory and a filename relative to that directory, +// extract the contents of that file and store it in a variable +// "script". + +static char* read_file_script = " \n\ +if {[file pathtype $::database_name] != \"relative\"} { \n\ + error \"Database name \\\"$::database_name\\\" should be relative\" \n\ +} \n\ +set filename [file join $::component_repository $::database_name] \n\ +if {0 == [file exists $filename]} { \n\ + error \"Component repository database $filename does not exist\" \n\ +} \n\ +if {0 == [file readable $filename]} { \n\ + error \"Component repository database $filename is not readable\" \n\ +} \n\ +set fd \"\" \n\ +set script \"\" \n\ +set status [catch { \n\ + set fd [open $filename r] \n\ + set script [read $fd] \n\ +} message] \n\ +if {$fd != \"\"} { \n\ + close $fd \n\ +} \n\ +if { $status != 0 } { \n\ + error $message \n\ +} \n\ +"; + +//}}} +//{{{ Tcl commands for the parser + +//{{{ CdlDbParser class + +// ---------------------------------------------------------------------------- +// Commands that get invoked from inside the Tcl interpreter. These +// need access to the internals of the database objects, which can be +// achieved by making them static members of a CdlDbParser class. + +class CdlDbParser { + public: + static int new_package(CdlInterpreter, int, char**); + static int package_description(CdlInterpreter, int, char**); + static int package_alias(CdlInterpreter, int, char**); + static int package_directory(CdlInterpreter, int, char**); + static int package_script(CdlInterpreter, int, char**); + static int package_hardware(CdlInterpreter, int, char**); + + static int new_target(CdlInterpreter, int, char**); + static int target_description(CdlInterpreter, int, char**); + static int target_alias(CdlInterpreter, int, char**); + static int target_packages(CdlInterpreter, int, char**); + static int target_command_prefix(CdlInterpreter, int, char**); + static int target_cflags(CdlInterpreter, int, char**); + static int target_enable(CdlInterpreter, int, char**); + static int target_disable(CdlInterpreter, int, char**); + static int target_set_value(CdlInterpreter, int, char**); +}; + +//}}} +//{{{ CdlDbParser::package-related + +// ---------------------------------------------------------------------------- +// package + +int +CdlDbParser::new_package(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("CdlDbParser::new_package", "result %d"); + CYG_REPORT_FUNCARG1XV(argc); + CYG_PRECONDITION_CLASSC(interp); + + CdlPackagesDatabase db = static_cast(interp->get_assoc_data(dbparser_database_key)); + CYG_INVARIANT_CLASSC(CdlPackagesDatabaseBody, db); + + if (3 != argc) { + interp->set_result("A package definition should include name and contents"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + std::string pkg_name = argv[1]; + std::string msg = std::string("Package ") + pkg_name + ": "; + + // Better make sure that this is not a duplicate definition. + if (std::find(db->package_names.begin(), db->package_names.end(), pkg_name) != db->package_names.end()) { + interp->set_result(msg + "a package can only be defined once"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + // Add this package to the list. + db->package_names.push_back(pkg_name); + + // Also create a new package structure. This requires a default structure, + // which cannot be filled in until the body is executed. + CdlPackagesDatabaseBody::package_data tmp_struct; + db->packages[pkg_name] = tmp_struct; + + CdlPackagesDatabaseBody::package_data& package = db->packages[pkg_name]; + // aliases and versions are vectors and will take care of themselves + package.description = ""; + package.directory = ""; + package.script = ""; + package.hardware = false; + + // Sort out the commands, then invoke the script in argv[2]. There is + // no need to worry about error recovery here, any errors will be + // fatal anyway. + CdlInterpreterCommandEntry commands[] = { + CdlInterpreterCommandEntry("description", &CdlDbParser::package_description ), + CdlInterpreterCommandEntry("alias", &CdlDbParser::package_alias ), + CdlInterpreterCommandEntry("directory", &CdlDbParser::package_directory ), + CdlInterpreterCommandEntry("script", &CdlDbParser::package_script ), + CdlInterpreterCommandEntry("hardware", &CdlDbParser::package_hardware ), + CdlInterpreterCommandEntry("", 0 ) + }; + int i; + std::vector new_commands; + for (i = 0; 0 != commands[i].command; i++) { + new_commands.push_back(commands[i]); + } + std::vector* old_commands = interp->push_commands(new_commands); + interp->set_variable(dbparser_current_package, pkg_name); + std::string str_result; + if (TCL_OK != interp->eval(argv[2], str_result)) { + interp->set_result(msg + str_result); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + interp->pop_commands(old_commands); + interp->unset_variable(dbparser_current_package); + + // Some of the fields are compulsory. + if ("" == package.directory) { + interp->set_result(msg + "missing directory specification"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + if ("" == package.script) { + interp->set_result(msg + "missing script specification"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + if (0 == package.aliases.size()) { + interp->set_result(msg + "at least one alias should be supplied"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + CYG_REPORT_RETVAL(TCL_OK); + return TCL_OK; +} + +// Syntax: description +int +CdlDbParser::package_description(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("CdlDbParser::package_description", "result %d"); + CYG_REPORT_FUNCARG1XV(argc); + CYG_PRECONDITION_CLASSC(interp); + + CdlPackagesDatabase db = static_cast(interp->get_assoc_data(dbparser_database_key)); + CYG_INVARIANT_CLASSC(CdlPackagesDatabaseBody, db); + + std::string name = interp->get_variable(dbparser_current_package); + CYG_ASSERTC("" != name); + CYG_ASSERTC(db->packages.find(name) != db->packages.end()); + + CdlPackagesDatabaseBody::package_data& package = db->packages[name]; + std::string msg = "Package " + name + ": "; + + if (2 != argc) { + interp->set_result(msg + "the package description should be a single string"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + if ("" != package.description) { + interp->set_result(msg + "a package can have only one description"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + + package.description = argv[1]; + + CYG_REPORT_RETVAL(TCL_OK); + return TCL_OK; +} + +// Syntax: alias +// For example: alias { "This is an alias" another_alias dummy_name } +int +CdlDbParser::package_alias(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("CdlDbParser::package_alias", "result %d"); + CYG_REPORT_FUNCARG1XV(argc); + CYG_PRECONDITION_CLASSC(interp); + + CdlPackagesDatabase db = static_cast(interp->get_assoc_data(dbparser_database_key)); + CYG_INVARIANT_CLASSC(CdlPackagesDatabaseBody, db); + + std::string name = interp->get_variable(dbparser_current_package); + CYG_ASSERTC("" != name); + CYG_ASSERTC(db->packages.find(name) != db->packages.end()); + + CdlPackagesDatabaseBody::package_data& package = db->packages[name]; + std::string msg = "Package " + name + ": "; + + // The alias command should be used only once + if (0 < package.aliases.size()) { + interp->set_result(msg + "there should be only one list of aliases"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + // There should be one argument, a list of valid packages. + if (2 != argc) { + interp->set_result(msg + "alias should be followed by a list of known aliases"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + int list_count = 0; + char** list_entries = 0; + Tcl_Interp* tcl_interp = interp->get_tcl_interpreter(); + if (TCL_OK != Tcl_SplitList(tcl_interp, argv[1], &list_count, &list_entries)) { + interp->set_result(msg + Tcl_GetStringResult(tcl_interp)); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + if (0 == list_count) { + interp->set_result(msg + "at least one alias should be supplied"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + for (int i = 0; i < list_count; i++) { + package.aliases.push_back(list_entries[i]); + } + Tcl_Free((char*)list_entries); + + CYG_REPORT_RETVAL(TCL_OK); + return TCL_OK; +} + +// Syntax: directory +// The path is of course relative to the component repository. +int +CdlDbParser::package_directory(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("CdlDbParser::package_directory", "result %d"); + CYG_REPORT_FUNCARG1XV(argc); + CYG_PRECONDITION_CLASSC(interp); + + CdlPackagesDatabase db = static_cast(interp->get_assoc_data(dbparser_database_key)); + CYG_INVARIANT_CLASSC(CdlPackagesDatabaseBody, db); + + std::string name = interp->get_variable(dbparser_current_package); + CYG_ASSERTC("" != name); + CYG_ASSERTC(db->packages.find(name) != db->packages.end()); + + CdlPackagesDatabaseBody::package_data& package = db->packages[name]; + std::string msg = "Package " + name + ": "; + + // The directory command should be used only once + if ("" != package.directory) { + interp->set_result(msg + "a package can be located in only one directory"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + // And there should be exactly one argument. + if (2 != argc) { + interp->set_result(msg + "only one directory can be specified"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + + package.directory = argv[1]; + CYG_REPORT_RETVAL(TCL_OK); + return TCL_OK; +} + +// Syntax: hardware +// There are no arguments. +int +CdlDbParser::package_hardware(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("CdlDbParser::package_hardware", "result %d"); + CYG_REPORT_FUNCARG1XV(argc); + CYG_PRECONDITION_CLASSC(interp); + + CdlPackagesDatabase db = static_cast(interp->get_assoc_data(dbparser_database_key)); + CYG_INVARIANT_CLASSC(CdlPackagesDatabaseBody, db); + + std::string name = interp->get_variable(dbparser_current_package); + CYG_ASSERTC("" != name); + CYG_ASSERTC(db->packages.find(name) != db->packages.end()); + + CdlPackagesDatabaseBody::package_data& package = db->packages[name]; + std::string msg = "Package " + name + ": "; + + if (1 != argc) { + interp->set_result(msg + "there should be no further data after hardware"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + if (package.hardware) { + interp->set_result(msg + "the hardware property should be specified only once"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + package.hardware = true; + + CYG_REPORT_RETVAL(TCL_OK); + return TCL_OK; +} + +// Syntax: script +int +CdlDbParser::package_script(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("CdlDbParser::package_script", "result %d"); + CYG_REPORT_FUNCARG1XV(argc); + CYG_PRECONDITION_CLASSC(interp); + + CdlPackagesDatabase db = static_cast(interp->get_assoc_data(dbparser_database_key)); + CYG_INVARIANT_CLASSC(CdlPackagesDatabaseBody, db); + + std::string name = interp->get_variable(dbparser_current_package); + CYG_ASSERTC("" != name); + CYG_ASSERTC(db->packages.find(name) != db->packages.end()); + + CdlPackagesDatabaseBody::package_data& package = db->packages[name]; + std::string msg = "Package " + name + ": "; + + // The script command should be used only once + if ("" != package.script) { + interp->set_result(msg + "a package can have only one starting CDL script"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + // And there should be exactly one argument. + if (2 != argc) { + interp->set_result(msg + "only one CDL script can be specified"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + package.script = argv[1]; + + CYG_REPORT_RETVAL(TCL_OK); + return TCL_OK; +} + +//}}} +//{{{ CdlDbParser::target-related + +// ---------------------------------------------------------------------------- +// target + +int +CdlDbParser::new_target(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("CdlDbParser::new_target", "result %d"); + CYG_REPORT_FUNCARG1XV(argc); + CYG_PRECONDITION_CLASSC(interp); + + CdlPackagesDatabase db = static_cast(interp->get_assoc_data(dbparser_database_key)); + CYG_INVARIANT_CLASSC(CdlPackagesDatabaseBody, db); + + if (3 != argc) { + interp->set_result("A target definition should include name and contents"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + std::string target_name = argv[1]; + std::string msg = std::string("Target ") + target_name + ": "; + + // Better make sure that this is not a duplicate definition. + if (std::find(db->target_names.begin(), db->target_names.end(), target_name) != db->target_names.end()) { + interp->set_result(msg + "a target can only be defined once"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + // Add this target to the list. + db->target_names.push_back(target_name); + + // Also create a new target structure. This requires a default structure, + // which cannot be filled in until the body is executed. + CdlPackagesDatabaseBody::target_data tmp_struct; + db->targets[target_name] = tmp_struct; + + CdlPackagesDatabaseBody::target_data& target = db->targets[target_name]; + // aliases, packages and compiler_flags are vectors and will take care of themselves + target.description = ""; + target.command_prefix = ""; + + // Sort out the commands, then invoke the script in argv[2]. There is + // no need to worry about error recovery here, any errors will be + // fatal anyway. + CdlInterpreterCommandEntry commands[] = { + CdlInterpreterCommandEntry("description", &CdlDbParser::target_description ), + CdlInterpreterCommandEntry("alias", &CdlDbParser::target_alias ), + CdlInterpreterCommandEntry("packages", &CdlDbParser::target_packages ), + CdlInterpreterCommandEntry("command_prefix", &CdlDbParser::target_command_prefix ), + CdlInterpreterCommandEntry("cflags", &CdlDbParser::target_cflags ), + CdlInterpreterCommandEntry("enable", &CdlDbParser::target_enable ), + CdlInterpreterCommandEntry("disable", &CdlDbParser::target_disable ), + CdlInterpreterCommandEntry("set_value", &CdlDbParser::target_set_value ), + CdlInterpreterCommandEntry("", 0 ) + }; + int i; + std::vector new_commands; + for (i = 0; 0 != commands[i].command; i++) { + new_commands.push_back(commands[i]); + } + std::vector* old_commands = interp->push_commands(new_commands); + interp->set_variable(dbparser_current_target, target_name); + std::string str_result; + if (TCL_OK != interp->eval(argv[2], str_result)) { + interp->set_result(msg + str_result); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + interp->pop_commands(old_commands); + interp->unset_variable(dbparser_current_target); + + // Some of the fields are compulsory. + if (0 == target.aliases.size()) { + interp->set_result(msg + "at least one alias should be supplied"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } +#if 0 + // command_prefix is now handled in the configuration data. + if ("" == target.command_prefix) { + interp->set_result(msg + "missing command prefix specification"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } +#endif + // There is no check for > 0 hardware packages. This is an unlikely + // scenario but should be allowed for. + + CYG_REPORT_RETVAL(TCL_OK); + return TCL_OK; +} + +// Syntax: description +int +CdlDbParser::target_description(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("CdlDbParser::target_description", "result %d"); + CYG_REPORT_FUNCARG1XV(argc); + CYG_PRECONDITION_CLASSC(interp); + + CdlPackagesDatabase db = static_cast(interp->get_assoc_data(dbparser_database_key)); + CYG_INVARIANT_CLASSC(CdlPackagesDatabaseBody, db); + + std::string name = interp->get_variable(dbparser_current_target); + CYG_ASSERTC("" != name); + CYG_ASSERTC(db->targets.find(name) != db->targets.end()); + + CdlPackagesDatabaseBody::target_data& target = db->targets[name]; + std::string msg = "Target " + name + ": "; + + if (2 != argc) { + interp->set_result(msg + "the target description should be a single string"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + if ("" != target.description) { + interp->set_result(msg + "a target can have only one description"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + + target.description = argv[1]; + + CYG_REPORT_RETVAL(TCL_OK); + return TCL_OK; +} + +// Syntax: alias +// For example: alias { "This is an alias" another_alias dummy_name } +int +CdlDbParser::target_alias(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("CdlDbParser::target_alias", "result %d"); + CYG_REPORT_FUNCARG1XV(argc); + CYG_PRECONDITION_CLASSC(interp); + + CdlPackagesDatabase db = static_cast(interp->get_assoc_data(dbparser_database_key)); + CYG_INVARIANT_CLASSC(CdlPackagesDatabaseBody, db); + + std::string name = interp->get_variable(dbparser_current_target); + CYG_ASSERTC("" != name); + CYG_ASSERTC(db->targets.find(name) != db->targets.end()); + + CdlPackagesDatabaseBody::target_data& target = db->targets[name]; + std::string msg = "Target " + name + ": "; + + // The alias command should be used only once + if (0 < target.aliases.size()) { + interp->set_result(msg + "there should be only one list of aliases"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + // There should be one argument, a list of valid aliases + if (2 != argc) { + interp->set_result(msg + "alias should be followed by a list of known aliases"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + int list_count = 0; + char** list_entries = 0; + Tcl_Interp* tcl_interp = interp->get_tcl_interpreter(); + if (TCL_OK != Tcl_SplitList(tcl_interp, argv[1], &list_count, &list_entries)) { + interp->set_result(msg + Tcl_GetStringResult(tcl_interp)); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + if (0 == list_count) { + interp->set_result(msg + "at least one alias should be supplied"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + for (int i = 0; i < list_count; i++) { + target.aliases.push_back(list_entries[i]); + } + Tcl_Free((char*)list_entries); + + CYG_REPORT_RETVAL(TCL_OK); + return TCL_OK; +} + +// Syntax: packages ... +// For example: packages { CYGPKG_HAL_XXX CYGPKG_HAL_YYY } +int +CdlDbParser::target_packages(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("CdlDbParser::target_packages", "result %d"); + CYG_REPORT_FUNCARG1XV(argc); + CYG_PRECONDITION_CLASSC(interp); + + CdlPackagesDatabase db = static_cast(interp->get_assoc_data(dbparser_database_key)); + CYG_INVARIANT_CLASSC(CdlPackagesDatabaseBody, db); + + std::string name = interp->get_variable(dbparser_current_target); + CYG_ASSERTC("" != name); + CYG_ASSERTC(db->targets.find(name) != db->targets.end()); + + CdlPackagesDatabaseBody::target_data& target = db->targets[name]; + std::string msg = "Target " + name + ": "; + + // The packages command should be used only once + if (0 < target.packages.size()) { + interp->set_result(msg + "there should be only one list of packages"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + // There should be one argument, a list of valid packages. + if (2 != argc) { + interp->set_result(msg + "packages should be followed by a list of known packages"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + int list_count = 0; + char** list_entries = 0; + Tcl_Interp* tcl_interp = interp->get_tcl_interpreter(); + if (TCL_OK != Tcl_SplitList(tcl_interp, argv[1], &list_count, &list_entries)) { + interp->set_result(msg + Tcl_GetStringResult(tcl_interp)); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + if (0 == list_count) { + interp->set_result(msg + "at least one package should be supplied"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + for (int i = 0; i < list_count; i++) { + target.packages.push_back(list_entries[i]); + } + Tcl_Free((char*)list_entries); + + CYG_REPORT_RETVAL(TCL_OK); + return TCL_OK; +} + +// Syntax: command_prefix +int +CdlDbParser::target_command_prefix(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("CdlDbParser::target_command_prefix", "result %d"); + CYG_REPORT_FUNCARG1XV(argc); + CYG_PRECONDITION_CLASSC(interp); + + CdlPackagesDatabase db = static_cast(interp->get_assoc_data(dbparser_database_key)); + CYG_INVARIANT_CLASSC(CdlPackagesDatabaseBody, db); + + std::string name = interp->get_variable(dbparser_current_target); + CYG_ASSERTC("" != name); + CYG_ASSERTC(db->targets.find(name) != db->targets.end()); + + CdlPackagesDatabaseBody::target_data& target = db->targets[name]; + std::string msg = "Target " + name + ": "; + + // The command_prefix command should be used only once + if ("" != target.command_prefix) { + interp->set_result(msg + "a target can have only one command_prefix string"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + // And there should be exactly one argument. + if (2 != argc) { + interp->set_result(msg + "only one command_prefix can be specified"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + + target.command_prefix = argv[1]; + CYG_REPORT_RETVAL(TCL_OK); + return TCL_OK; +} + +// Syntax: cflags ... +// For example: cflags { ERRFLAGS "-Wall" DBGFLAGS "-g" } +int +CdlDbParser::target_cflags(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("CdlDbParser::target_cflags", "result %d"); + CYG_REPORT_FUNCARG1XV(argc); + CYG_PRECONDITION_CLASSC(interp); + + CdlPackagesDatabase db = static_cast(interp->get_assoc_data(dbparser_database_key)); + CYG_INVARIANT_CLASSC(CdlPackagesDatabaseBody, db); + + std::string name = interp->get_variable(dbparser_current_target); + CYG_ASSERTC("" != name); + CYG_ASSERTC(db->targets.find(name) != db->targets.end()); + + CdlPackagesDatabaseBody::target_data& target = db->targets[name]; + std::string msg = "Target " + name + ": "; + + // The cflags command should be used only once + if (0 < target.cflags.size()) { + interp->set_result(msg + "there should be only one set of compiler flags"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + // There should be one argument, a list of valid flags. + if (2 != argc) { + interp->set_result(msg + "cflags should be followed by a list of compiler flag/value pairs"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + int list_count = 0; + char** list_entries = 0; + Tcl_Interp* tcl_interp = interp->get_tcl_interpreter(); + if (TCL_OK != Tcl_SplitList(tcl_interp, argv[1], &list_count, &list_entries)) { + interp->set_result(msg + Tcl_GetStringResult(tcl_interp)); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + if (0 != (list_count % 2)) { + interp->set_result(msg + "compiler flags and values must occur in pairs"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + int i; + const std::vector& valid_cflags = CdlPackagesDatabaseBody::get_valid_cflags(); + for (i = 0; i < list_count; i+= 2) { + std::vector::const_iterator j; + for (j = valid_cflags.begin(); j != valid_cflags.end(); j++) { + if (*j == list_entries[i]) { + break; + } + if (j == valid_cflags.end()) { + interp->set_result(msg + "invalid cflag name " + list_entries[i]); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + } + } + // NOTE: do the quote marks have to be removed explicitly or is that done + // by splitlist? + for (i = 0; i < list_count; i+= 2) { + target.cflags.push_back(std::make_pair(list_entries[i], list_entries[i+1])); + } + Tcl_Free((char*)list_entries); + + CYG_REPORT_RETVAL(TCL_OK); + return TCL_OK; +} + +// Syntax: enable { opt1 opt2 ... } +// For example: enable { CYGPKG_HAL_ARM_CL7xxx_7211 } +int +CdlDbParser::target_enable(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("CdlDbParser::target_enable", "result %d"); + CYG_REPORT_FUNCARG1XV(argc); + CYG_PRECONDITION_CLASSC(interp); + + CdlPackagesDatabase db = static_cast(interp->get_assoc_data(dbparser_database_key)); + CYG_INVARIANT_CLASSC(CdlPackagesDatabaseBody, db); + + std::string name = interp->get_variable(dbparser_current_target); + CYG_ASSERTC("" != name); + CYG_ASSERTC(db->targets.find(name) != db->targets.end()); + + CdlPackagesDatabaseBody::target_data& target = db->targets[name]; + std::string msg = "Target " + name + ": "; + + // There should be one argument, a list of valid flags. + if (2 != argc) { + interp->set_result(msg + "enable should be followed by a list of CDL options"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + int list_count = 0; + char** list_entries = 0; + Tcl_Interp* tcl_interp = interp->get_tcl_interpreter(); + if (TCL_OK != Tcl_SplitList(tcl_interp, argv[1], &list_count, &list_entries)) { + interp->set_result(msg + Tcl_GetStringResult(tcl_interp)); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + for (int i = 0; i < list_count; i++) { + target.enable.push_back(list_entries[i]); + } + Tcl_Free((char *) list_entries); + + CYG_REPORT_RETVAL(TCL_OK); + return TCL_OK; +} + + +// Syntax: disable { opt1 opt2 ... } +// For example: disable { CYGPKG_HAL_ARM_CL7xxx_7111 } +int +CdlDbParser::target_disable(CdlInterpreter interp, int argc, char** argv) +{ + CYG_REPORT_FUNCNAMETYPE("CdlDbParser::target_disable", "result %d"); + CYG_REPORT_FUNCARG1XV(argc); + CYG_PRECONDITION_CLASSC(interp); + + CdlPackagesDatabase db = static_cast(interp->get_assoc_data(dbparser_database_key)); + CYG_INVARIANT_CLASSC(CdlPackagesDatabaseBody, db); + + std::string name = interp->get_variable(dbparser_current_target); + CYG_ASSERTC("" != name); + CYG_ASSERTC(db->targets.find(name) != db->targets.end()); + + CdlPackagesDatabaseBody::target_data& target = db->targets[name]; + std::string msg = "Target " + name + ": "; + + // There should be one argument, a list of valid flags. + if (2 != argc) { + interp->set_result(msg + "disable should be followed by a list of CDL options"); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + int list_count = 0; + char** list_entries = 0; + Tcl_Interp* tcl_interp = interp->get_tcl_interpreter(); + if (TCL_OK != Tcl_SplitList(tcl_interp, argv[1], &list_count, &list_entries)) { + interp->set_result(msg + Tcl_GetStringResult(tcl_interp)); + CYG_REPORT_RETVAL(TCL_ERROR); + return TCL_ERROR; + } + for (int i = 0; i < list_count; i++) { + target.disable.push_back(list_entries[i]); + } + Tcl_Free((char *) list_entries); + + CYG_REPORT_RETVAL(TCL_OK); + return TCL_OK; +} + +// Syntax: set_value