diff --git a/HeaderDoc-1.3-strict.dtd b/HeaderDoc-1.3-strict.dtd new file mode 100644 index 0000000..0081da5 --- /dev/null +++ b/HeaderDoc-1.3-strict.dtd @@ -0,0 +1,451 @@ + + + + + + + + + + + + + + + + + + + + + +%htmlDTD; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/HeaderDoc-1.3.dtd b/HeaderDoc-1.3.dtd new file mode 100644 index 0000000..3668396 --- /dev/null +++ b/HeaderDoc-1.3.dtd @@ -0,0 +1,662 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/HeaderDoc-1.4-strict.dtd b/HeaderDoc-1.4-strict.dtd new file mode 100644 index 0000000..b360f7d --- /dev/null +++ b/HeaderDoc-1.4-strict.dtd @@ -0,0 +1,452 @@ + + + + + + + + + + + + + + + + + + + + + +%htmlDTD; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/HeaderDoc-1.4.dtd b/HeaderDoc-1.4.dtd new file mode 100644 index 0000000..07c3a47 --- /dev/null +++ b/HeaderDoc-1.4.dtd @@ -0,0 +1,663 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/HeaderDoc-1.5-strict.dtd b/HeaderDoc-1.5-strict.dtd new file mode 100644 index 0000000..b41e280 --- /dev/null +++ b/HeaderDoc-1.5-strict.dtd @@ -0,0 +1,454 @@ + + + + + + + + + + + + + + + + + + + + + +%htmlDTD; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/HeaderDoc-1.5.dtd b/HeaderDoc-1.5.dtd new file mode 100644 index 0000000..606f101 --- /dev/null +++ b/HeaderDoc-1.5.dtd @@ -0,0 +1,665 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/HeaderDoc-1.6-strict.dtd b/HeaderDoc-1.6-strict.dtd new file mode 100644 index 0000000..49e524b --- /dev/null +++ b/HeaderDoc-1.6-strict.dtd @@ -0,0 +1,476 @@ + + + + + + + + + + + + + + + + + + + + + +%htmlDTD; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/HeaderDoc-1.6.dtd b/HeaderDoc-1.6.dtd new file mode 100644 index 0000000..a5e3a7f --- /dev/null +++ b/HeaderDoc-1.6.dtd @@ -0,0 +1,687 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Makefile b/Makefile index eb55744..dc7b36b 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,8 @@ ## -bindir = /usr/bin -confdir = /Library/Preferences/ +bindir = $(DEVELOPER_DIR)/usr/bin +confdir = $(DEVELOPER_DIR)/usr/share/headerdoc/conf/ conffile = com.apple.headerDoc2HTML.config templatefile = com.apple.headerdoc.exampletocteplate.html # docsDir = /Developer/Documentation/DeveloperTools @@ -22,12 +22,13 @@ perl_libdir := $(subst Perl,Perl/Extras,$(perl_libdir)) endif endif startperl := $(shell perl -e 'require Config; print "$$Config::Config{'startperl'}\n";') +testsuite_version := $(shell cat testsuite/version) all: all_internal test apidoc # Override the default compiler to GCC 4.0 if building for Snow Leopard internally. all_internal: - cd xmlman ; make all CC=`if [ "$$DEVELOPER_BIN_DIR" != "" -a "$(building_ppc)" != "0" ] ; then echo "gcc-4.0" ; else echo "cc"; fi` ARCH=`uname` VERS=`sw_vers -productVersion | sed 's/\([0-9][0-9]*\)\.\([0-9][0-9]*\)\..*/\1.\2/'` ; cd .. + cd xmlman ; make all CC=`if [ "$$DEVELOPER_BIN_DIR" != "" -a "$(building_ppc)" != "0" ] ; then echo "gcc-4.0" ; else echo "cc"; fi` ARCH=`uname` VERS=`{ echo "10.8"; sw_vers -productVersion | sed 's/\([0-9][0-9]*\)\.\([0-9][0-9]*\)\..*/\1.\2/'; } | sort | head -n 1` ; cd .. clean: cd xmlman ; make clean ; cd .. @@ -42,12 +43,17 @@ installhdrs: build: test: + rm -f /tmp/xref_out + rm -rf /tmp/hdtest_perm + rm -rf /tmp/hdtest_out + ./headerDoc2HTML.pl -T run; \ if [ "$$?" -ne 0 ] ; then \ echo "Test suite failed."; \ exit 1; \ fi + rm -f /tmp/xref_out rm -rf /tmp/hdtest_perm rm -rf /tmp/hdtest_out mkdir /tmp/hdtest_perm @@ -73,6 +79,7 @@ test: realinstall: all_internal DSTROOT="" make installsub + DSTROOT="" make installtests install: all_internal @echo ; \ @@ -83,9 +90,12 @@ install: all_internal echo " $$DSTROOT" ; \ echo "" ; \ echo "This is primarily intended for building packages." ; \ - echo "If you want to actually install over your" ; \ - echo "existing installation, cancel this make and run" ; \ - echo "\"sudo make realinstall\" instead." ; \ + echo "If you want to actually install over an existing" ; \ + echo "installation in /usr, cancel this make and run" ; \ + echo "\"sudo make realinstall\" instead, or to update" ; \ + echo "an installed copy of Xcode, set the DEVELOPER_DIR" ; \ + echo "environment variable to, for example," ; \ + echo "/Applications/Xcode.app/Contents/Developer/" ; \ \ sleep 5 ; \ make installsub @@ -94,9 +104,15 @@ installsub: @echo "Destination is: \"${DSTROOT}\"" - umask 022 && install -d $(DSTROOT)$(perl_libdir)/HeaderDoc - install -c -m 444 Modules/HeaderDoc/*.pm $(DSTROOT)$(perl_libdir)/HeaderDoc - install -c -m 444 Modules/HeaderDoc/Availability.list $(DSTROOT)$(perl_libdir)/HeaderDoc + # umask 022 && install -d $(DSTROOT)$(perl_libdir)/HeaderDoc + + # install -c -m 444 Modules/HeaderDoc/*.pm $(DSTROOT)$(perl_libdir)/HeaderDoc + mkdir -p $(DSTROOT)$(DEVELOPER_DIR)/usr/share/headerdoc/Modules/HeaderDoc + install -c -m 444 Modules/HeaderDoc/*.pm $(DSTROOT)$(DEVELOPER_DIR)/usr/share/headerdoc/Modules/HeaderDoc + + # install -c -m 444 Modules/HeaderDoc/Availability.list $(DSTROOT)$(perl_libdir)/HeaderDoc + install -c -m 444 Modules/HeaderDoc/Availability.list $(DSTROOT)$(DEVELOPER_DIR)/usr/share/headerdoc + if [ -f "Modules/HeaderDoc/LinkResolver.pm" ] ; then \ rm -f $(DSTROOT)$(perl_libdir)/HeaderDoc/LinkResolver.pm ; \ umask 022 && install -d $(DSTROOT)/AppleInternal/Library/Perl/HeaderDoc ; \ @@ -108,7 +124,7 @@ installsub: umask 022 && install -d $(DSTROOT)$(bindir) umask 022 && install -d $(DSTROOT)$(confdir) install -c -m 755 headerDoc2HTML.config-xcodecolors $(DSTROOT)$(confdir)$(conffile) - install -c -m 444 exampletoctemplate.html $(DSTROOT)$(confdir)$(templatefile) + install -c -m 444 $(templatefile) $(DSTROOT)$(confdir)$(templatefile) if [ "$(SYMROOT)" != "" ] ; then \ install -c -m 755 xmlman/xml2man $(SYMROOT)$(bindir)/xml2man; \ dsymutil -o $(SYMROOT)$(bindir)/xml2man.dSYM $(SYMROOT)$(bindir)/xml2man; \ @@ -122,6 +138,7 @@ installsub: install -s -c -m 755 xmlman/resolveLinks $(DSTROOT)$(bindir)/resolveLinks install -c -m 755 headerDoc2HTML.pl $(DSTROOT)$(bindir)/$(program1) perl -i -pe 's|^#!/usr/bin/perl.*$$|$(startperl)|;' $(DSTROOT)$(bindir)/$(program1) + perl -i -pe 's|^\$$HeaderDoc::testsuite_version="\d+";|\$$HeaderDoc::testsuite_version="$(testsuite_version)";|;' $(DSTROOT)$(bindir)/$(program1) chmod 555 $(DSTROOT)$(bindir)/$(program1) umask 022 && install -d $(DSTROOT)$(bindir) install -c -m 755 gatherHeaderDoc.pl $(DSTROOT)$(bindir)/$(program2) @@ -129,43 +146,46 @@ installsub: chmod 555 $(DSTROOT)$(bindir)/$(program2) # umask 022 && install -d $(DSTROOT)$(docsDir)/HeaderDoc # install -c -m 444 Documentation/*.html $(DSTROOT)$(docsDir)/HeaderDoc - umask 022 && install -d $(DSTROOT)/usr/share/man/man1 - install -c -m 444 Documentation/man/*.1 $(DSTROOT)/usr/share/man/man1 - umask 022 && install -d $(DSTROOT)/usr/share/man/man5 - install -c -m 444 Documentation/man/*.5 $(DSTROOT)/usr/share/man/man5 + umask 022 && install -d $(DSTROOT)$(DEVELOPER_DIR)/usr/share/man/man1 + install -c -m 444 Documentation/man/*.1 $(DSTROOT)$(DEVELOPER_DIR)/usr/share/man/man1 + umask 022 && install -d $(DSTROOT)$(DEVELOPER_DIR)/usr/share/man/man5 + install -c -m 444 Documentation/man/*.5 $(DSTROOT)$(DEVELOPER_DIR)/usr/share/man/man5 cd xmlman ; make clean ; cd .. +installtests: # Install test suite - umask 022 && install -d $(DSTROOT)/usr/share/headerdoc/testsuite - umask 022 && install -d $(DSTROOT)/usr/share/headerdoc/testsuite/parser_tests - umask 022 && install -d $(DSTROOT)/usr/share/headerdoc/testsuite/resolvelinks - umask 022 && install -d $(DSTROOT)/usr/share/headerdoc/testsuite/resolvelinks/sourcefiles - umask 022 && install -d $(DSTROOT)/usr/share/headerdoc/testsuite/resolvelinks/tests - umask 022 && install -d $(DSTROOT)/usr/share/headerdoc/testsuite/c_preprocessor_tests - install -c -m 444 testsuite/parser_tests/*.test $(DSTROOT)/usr/share/headerdoc/testsuite/parser_tests + umask 022 && install -d $(DSTROOT)$(DEVELOPER_DIR)/usr/share/headerdoc/testsuite + umask 022 && install -d $(DSTROOT)$(DEVELOPER_DIR)/usr/share/headerdoc/testsuite/parser_tests + umask 022 && install -d $(DSTROOT)$(DEVELOPER_DIR)/usr/share/headerdoc/testsuite/resolvelinks + umask 022 && install -d $(DSTROOT)$(DEVELOPER_DIR)/usr/share/headerdoc/testsuite/resolvelinks/sourcefiles + umask 022 && install -d $(DSTROOT)$(DEVELOPER_DIR)/usr/share/headerdoc/testsuite/resolvelinks/tests + umask 022 && install -d $(DSTROOT)$(DEVELOPER_DIR)/usr/share/headerdoc/testsuite/c_preprocessor_tests + install -c -m 444 testsuite/parser_tests/*.test $(DSTROOT)$(DEVELOPER_DIR)/usr/share/headerdoc/testsuite/parser_tests + + install -c -m 755 testsuite/version $(DSTROOT)$(DEVELOPER_DIR)/usr/share/headerdoc/testsuite # Install resolvelinks test tools - install -c -m 755 testsuite/resolvelinks/update.sh $(DSTROOT)/usr/share/headerdoc/testsuite/resolvelinks - install -c -m 755 testsuite/resolvelinks/runtests.sh $(DSTROOT)/usr/share/headerdoc/testsuite/resolvelinks + install -c -m 755 testsuite/resolvelinks/update.sh $(DSTROOT)$(DEVELOPER_DIR)/usr/share/headerdoc/testsuite/resolvelinks + install -c -m 755 testsuite/resolvelinks/runtests.sh $(DSTROOT)$(DEVELOPER_DIR)/usr/share/headerdoc/testsuite/resolvelinks # Make resolvelinks test source directories - find testsuite/resolvelinks/sourcefiles -type d -and \! -path '*/CVS/*' -and \! -path '*/CVS' -exec install -m 755 -d -c {} $(DSTROOT)/usr/share/headerdoc/{} \; + find testsuite/resolvelinks/sourcefiles -type d -and \! -path '*/CVS/*' -and \! -path '*/CVS' -exec install -m 755 -d -c {} $(DSTROOT)$(DEVELOPER_DIR)/usr/share/headerdoc/{} \; # Copy resolvelinks test sources - find testsuite/resolvelinks/sourcefiles \! -type d -and \! -path '*/CVS/*' -and \! -path '*/CVS' -exec install -m 444 -c {} $(DSTROOT)/usr/share/headerdoc/{} \; + find testsuite/resolvelinks/sourcefiles \! -type d -and \! -path '*/CVS/*' -and \! -path '*/CVS' -exec install -m 444 -c {} $(DSTROOT)$(DEVELOPER_DIR)/usr/share/headerdoc/{} \; # Make resolvelinks test expected result directories - find testsuite/resolvelinks/tests -type d \! -path '*/CVS/*' -and \! -path '*/CVS' -exec install -m 755 -d -c {} $(DSTROOT)/usr/share/headerdoc/{} \; + find testsuite/resolvelinks/tests -type d \! -path '*/CVS/*' -and \! -path '*/CVS' -exec install -m 755 -d -c {} $(DSTROOT)$(DEVELOPER_DIR)/usr/share/headerdoc/{} \; # Copy resolvelinks test expected results - find testsuite/resolvelinks/tests \! -type d -and \! -path '*/CVS/*' -and \! -path '*/CVS' -exec install -m 444 -c {} $(DSTROOT)/usr/share/headerdoc/{} \; + find testsuite/resolvelinks/tests \! -type d -and \! -path '*/CVS/*' -and \! -path '*/CVS' -exec install -m 444 -c {} $(DSTROOT)$(DEVELOPER_DIR)/usr/share/headerdoc/{} \; - install -c -m 444 testsuite/c_preprocessor_tests/*.test $(DSTROOT)/usr/share/headerdoc/testsuite/c_preprocessor_tests + install -c -m 444 testsuite/c_preprocessor_tests/*.test $(DSTROOT)$(DEVELOPER_DIR)/usr/share/headerdoc/testsuite/c_preprocessor_tests - # Install copies everywhere else - if [ -f "/usr/local/versioner/perl/versions" ] ; then \ - ./installmulti.sh "$(DSTROOT)"; \ - fi + ## # Install copies everywhere else + ## if [ -f "/usr/local/versioner/perl/versions" ] ; then \ + ## ./installmulti.sh "$(DSTROOT)"; \ + ## fi apidoc: ./generateAPIDocs.sh diff --git a/Modules/HeaderDoc/APIOwner.pm b/Modules/HeaderDoc/APIOwner.pm index 79b59b3..278ba72 100644 --- a/Modules/HeaderDoc/APIOwner.pm +++ b/Modules/HeaderDoc/APIOwner.pm @@ -3,7 +3,7 @@ # Class name: APIOwner # Synopsis: Abstract superclass for Header and OO structures # -# Last Updated: $Date: 2011/05/18 12:09:34 $ +# Last Updated: $Date: 2014/02/25 14:46:13 $ # # Method additions by SKoT McDonald Aug 2001 # @@ -74,6 +74,11 @@ # Contains an array of names of functions to "also include" in # the documentation for this class/pseudoclass. Mainly intended # for applying class-like behavior to procedural languages. +# @var APPLEREFUSED +# A reference to a hash containing API references that have been +# emitted already in the context of this API owner. This is +# needed so that it can be reset if a class is re-emitted (after +# category folding, for example). # @var CATEGORIES # An array of # {@link //apple_ref/perl/cl/HeaderDoc::ObjCCategory ObjCCategory} @@ -208,7 +213,6 @@ BEGIN { } use HeaderDoc::HeaderElement; use HeaderDoc::Group; -use HeaderDoc::DBLookup; use HeaderDoc::Utilities qw(findRelativePath safeName getAPINameAndDisc printArray printHash resolveLink sanitize dereferenceUIDObject validTag objName byLinkage byAccessControl objGroup linkageAndObjName byMethodType html_fixup_links xml_fixup_links calcDepth); use HeaderDoc::BlockParse qw(blockParseOutside); use File::Basename; @@ -225,7 +229,7 @@ use vars qw(@ISA); # In the git repository, contains the number of seconds since # January 1, 1970. # */ -$HeaderDoc::APIOwner::VERSION = '$Revision: 1305745774 $'; +$HeaderDoc::APIOwner::VERSION = '$Revision: 1393368373 $'; my $addToDebug = 0; @@ -1461,7 +1465,7 @@ sub tocStringSubForClasses } elsif ($HeaderDoc::use_iframes) { $tocString .= "$entrypreface$name
\n"; } else { - $tocString .= "$entrypreface$name
\n"; + $tocString .= "$entrypreface$name
\n"; } } else { } @@ -3484,8 +3488,10 @@ sub createTOCFile { # @abstract # Generates the content HTML file (right-side frame). # @discussion -# In "class as composite" mode, this function writes -# all of the right-side frames into a single file. +# In "class as composite" mode, this function does not +# get called. Instead, {@link writeHeaderElementsToCompositePage} +# is used. +# # Otherwise, this function just writes the introduction # for the header or class itself, and the other # right-side content is written later by a call to @@ -3818,12 +3824,58 @@ sub writeFunctionListToStdOut { return; } +# /*! +# @abstract +# Recursively ensures that the {@link apirefSetup} method has been called +# on everything that might get emitted later. +# */ +sub setupAPIReferences { + + my $self = shift; + + my @functions = $self->functions(); + my @methods = $self->methods(); + my @constants = $self->constants(); + my @typedefs = $self->typedefs(); + my @structs = $self->structs(); + my @vars = $self->vars(); + my @local_vars = (); + if ($self->can("variables")) { @local_vars = $self->variables(); } + my @enums = $self->enums(); + my @pDefines = $self->pDefines(); + my @classes = $self->classes(); + my @categories = $self->categories(); + my @protocols = $self->protocols(); + my @properties = $self->props(); + + # pre-process everything to make sure we don't have any unregistered + # api refs. + my $prevignore = $HeaderDoc::ignore_apiuid_errors; + $HeaderDoc::ignore_apiuid_errors = 1; + + my $junk = ""; + if (@functions) { foreach my $obj (@functions) { $junk = $obj->apirefSetup();}} + if (@methods) { foreach my $obj (@methods) { $junk = $obj->apirefSetup();}} + if (@constants) { foreach my $obj (@constants) { $junk = $obj->apirefSetup();}} + if (@typedefs) { foreach my $obj (@typedefs) { $junk = $obj->apirefSetup();}} + if (@structs) { foreach my $obj (@structs) { $junk = $obj->apirefSetup();}} + if (@local_vars) { foreach my $obj (@local_vars) { $junk = $obj->apirefSetup();}} + if (@vars) { foreach my $obj (@vars) { $junk = $obj->apirefSetup();}} + if (@enums) { foreach my $obj (@enums) { $junk = $obj->apirefSetup();}} + if (@pDefines) { foreach my $obj (@pDefines) { $junk = $obj->apirefSetup();}} + if (@classes) { foreach my $obj (@classes) { $junk = $obj->apirefSetup(); $junk = $obj->docNavigatorComment(); $obj->setupAPIReferences(); }} + if (@categories) { foreach my $obj (@categories) { $junk = $obj->apirefSetup(); $junk = $obj->docNavigatorComment(); $obj->setupAPIReferences(); }} + if (@protocols) { foreach my $obj (@protocols) { $junk = $obj->apirefSetup(); $junk = $obj->docNavigatorComment(); $obj->setupAPIReferences(); }} + if (@properties) { foreach my $obj (@properties) { $junk = $obj->apirefSetup();}} + $HeaderDoc::ignore_apiuid_errors = $prevignore; +} + # /*! # @abstract # Writes the right-side content. # @discussion # In "class as composite" mode, this function's -# purpose is handled by {@link createContentFile}, +# purpose is handled by {@link writeHeaderElementsToCompositePage}, # so it does not get called. # # Otherwise, this function writes all of the @@ -3853,11 +3905,7 @@ sub writeHeaderElements { unless (mkdir ("$rootOutputDir", 0777)) {die ("Can't create output folder $rootOutputDir. \n$!");}; } - # pre-process everything to make sure we don't have any unregistered - # api refs. my $junk = ""; - my $prevignore = $HeaderDoc::ignore_apiuid_errors; - $HeaderDoc::ignore_apiuid_errors = 1; my @functions = $self->functions(); my @methods = $self->methods(); my @constants = $self->constants(); @@ -3879,18 +3927,6 @@ sub writeHeaderElements { # } # } - if (@functions) { foreach my $obj (@functions) { $junk = $obj->apirefSetup();}} - if (@methods) { foreach my $obj (@methods) { $junk = $obj->apirefSetup();}} - if (@constants) { foreach my $obj (@constants) { $junk = $obj->apirefSetup();}} - if (@typedefs) { foreach my $obj (@typedefs) { $junk = $obj->apirefSetup();}} - if (@structs) { foreach my $obj (@structs) { $junk = $obj->apirefSetup();}} - if (@local_vars) { foreach my $obj (@local_vars) { $junk = $obj->apirefSetup();}} - if (@vars) { foreach my $obj (@vars) { $junk = $obj->apirefSetup();}} - if (@enums) { foreach my $obj (@enums) { $junk = $obj->apirefSetup();}} - if (@pDefines) { foreach my $obj (@pDefines) { $junk = $obj->apirefSetup();}} - if (@classes) { foreach my $obj (@classes) { $junk = $obj->apirefSetup();}} - if (@properties) { foreach my $obj (@properties) { $junk = $obj->apirefSetup();}} - $HeaderDoc::ignore_apiuid_errors = $prevignore; if (!$HeaderDoc::ClassAsComposite) { @@ -4203,8 +4239,8 @@ sub writeHeaderElementsToXMLPage { # All API in a single XML page # @abstract # Writes output to the composite page. # @discussion -# In "class as composite" mode, this function is not called. -# The function {@link createContentFile} handles this instead. +# In "class as composite" mode, this function supersedes +# the function {@link createContentFile}. # @param self # The APIOwner object. # */ @@ -4218,10 +4254,18 @@ sub writeHeaderElementsToCompositePage { # All API in a single HTML page -- for # $compositePageString = $self->stripAppleRefs($compositePageString); my $outputFile = $rootOutputDir.$pathSeparator.$compositePageName; +# print STDERR "OUTFILE: $outputFile\n"; + if (! -e $rootOutputDir) { unless (mkdir ("$rootOutputDir", 0777)) {die ("Can't create output folder $rootOutputDir. $!");}; } + +# print STDERR "PRE: $compositePageString\n"; + my $processed_string = html_fixup_links($self, $compositePageString); + +# print STDERR "DUMP: $processed_string\n"; + $self->_createHTMLOutputFile($outputFile, $processed_string, "$name", 1); } @@ -4249,8 +4293,9 @@ sub writeProtocols { $obj->outputDir("$protocolsRootDir$pathSeparator$protocolName"); $obj->createFramesetFile(); $obj->createContentFile() if (!$HeaderDoc::ClassAsComposite); + $obj->writeHeaderElementsToCompositePage(); $obj->createTOCFile(); - $obj->writeHeaderElements(); + $obj->writeHeaderElements(); } } @@ -4278,6 +4323,7 @@ sub writeCategories { $obj->outputDir("$categoriesRootDir$pathSeparator$categoryName"); $obj->createFramesetFile(); $obj->createContentFile() if (!$HeaderDoc::ClassAsComposite); + $obj->writeHeaderElementsToCompositePage(); $obj->createTOCFile(); $obj->writeHeaderElements(); } @@ -4627,6 +4673,33 @@ sub _getFunctionXMLDetailString { return $contentString; } +# /*! +# @abstract +# Returns the XML content string for classes in this class or header. +# @param self +# The APIOwner object. +# @discussion +# Called by {@link _getXMLPageString}. +# */ +sub _getEmbeddedClassXMLDetailString { + my $self = shift; + my $classObjsRef = shift; + my @classObjs = @{$classObjsRef}; + my $contentString = ""; + + my @tempobjs = (); + if (!$self->unsorted()) { + @tempobjs = sort objName @classObjs; + } else { + @tempobjs = @classObjs; + } + foreach my $obj (@tempobjs) { + # print STDERR "outputting class ".$obj->name."."; + my $documentationBlock = $obj->XMLdocumentationBlock(); + $contentString .= $documentationBlock; + } + return $contentString; +} # /*! # @abstract @@ -5689,8 +5762,8 @@ sub _createXMLOutputFile { $doctype = "framework"; } - # print OUTFILE "\n"; - print OUTFILE "\n"; + # print OUTFILE "\n"; + print OUTFILE "\n"; # print OUTFILE "
"; # print OUTFILE "$heading\n"; @@ -5758,8 +5831,14 @@ sub _createHTMLOutputFile { if ($HeaderDoc::use_iframes || $HeaderDoc::newTOC == 5) { if (!$HeaderDoc::suppressDefaultStyles) { + print OUTFILE $self->styleSheet(1); print OUTFILE "\n"; + + + if ($HeaderDoc::newTOC == 5) { + print OUTFILE "\n"; + } } if (!$HeaderDoc::suppressDefaultJavaScript) { + if ($HeaderDoc::newTOC == 5) { + print OUTFILE "\n"; + } + if ($newTOC && $newTOC != 5) { # if (!$HeaderDoc::use_iframes) { print OUTFILE "\n"; } print OUTFILE "\n"; @@ -6633,6 +6765,10 @@ sub processComment # @@@ FIXME DAG my $cppAccessControlState = "protected:"; + if ($sublang eq "IDL") { + $cppAccessControlState = "public:"; # IDLs have no notion of protection, typically. + } + my $fieldsref = \@fields; my $filename = $self->filename; @@ -7247,7 +7383,7 @@ sub groupDoc() my $desc = $group->discussion(); if ($xml) { $string .= "\n"; - $string .= "$groupname\n"; + $string .= "".$self->textToXML($groupname)."\n"; if ($abs =~ /\S/) { $string .= "".$self->htmlToXML($abs).""; } @@ -7579,5 +7715,55 @@ sub fixupTypeRequests $self->{PDEFINES} = \@newobjs; } + +# /*! +# @abstract +# Marks an API reference ID as having been emitted already. +# @param self +# The API owner object. +# @param uid +# The user ID to query or set. +# @param used +# Normally, you would pass 1 when setting. If you just +# want to query the value, do not pass this argument. +# */ +sub appleRefUsed +{ + my $self = shift; + my $uid = shift; + + my %map = (); + + if ($self->{APPLEREFUSED}) { + %map = %{$self->{APPLEREFUSED}}; + } + + my $retval = $map{$uid}; + + if (@_) { + # print STDERR "SETTING USED FOR $uid ON $self\n"; + $map{$uid} = 1; + $self->{APPLEREFUSED} = \%map; + } + + return $retval; +} + +# /*! +# @abstract +# Clears the API reference hash used by {@link appleRefUsed}. +# @discussion +# This is called when an API owner object needs to be +# emitted again (e.g. when a category's methods are folded +# into a class in another header). +# */ +sub resetAppleRefUsed +{ + my $self = shift; + + # print STDERR "RESETTING USED ON $self\n"; + delete $self->{APPLEREFUSED}; +} + 1; diff --git a/Modules/HeaderDoc/AvailHelper.pm b/Modules/HeaderDoc/AvailHelper.pm index 4831726..ee2e9ea 100644 --- a/Modules/HeaderDoc/AvailHelper.pm +++ b/Modules/HeaderDoc/AvailHelper.pm @@ -3,7 +3,7 @@ # Class name: AvailHelper # Synopsis: Helper code for availability # -# Last Updated: $Date: 2011/02/18 19:02:57 $ +# Last Updated: $Date: 2014/02/14 17:55:29 $ # # Copyright (c) 2006 Apple Computer, Inc. All rights reserved. # @@ -59,7 +59,6 @@ BEGIN { } } use HeaderDoc::HeaderElement; -use HeaderDoc::DBLookup; use HeaderDoc::Utilities qw(findRelativePath safeName printArray printHash sanitize); use File::Basename; use Cwd; @@ -75,7 +74,7 @@ use vars qw(@ISA); # In the git repository, contains the number of seconds since # January 1, 1970. # */ -$HeaderDoc::AvailHelper::VERSION = '$Revision: 1298084577 $'; +$HeaderDoc::AvailHelper::VERSION = '$Revision: 1392429329 $'; # Inheritance # @ISA = qw(HeaderDoc::HeaderElement); diff --git a/Modules/HeaderDoc/Availability.list b/Modules/HeaderDoc/Availability.list index c030867..be62ded 100644 --- a/Modules/HeaderDoc/Availability.list +++ b/Modules/HeaderDoc/Availability.list @@ -49,6 +49,17 @@ AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_ AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_7 Introduced in Mac OS X v10.5, but later deprecated in Mac OS X v10.7. AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_7 Introduced in Mac OS X v10.6, but later deprecated in Mac OS X v10.7. DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER Deprecated in Mac OS X v10.7. +AVAILABLE_MAC_OS_X_VERSION_10_8_AND_LATER Introduced in Mac OS X v10.8. +AVAILABLE_MAC_OS_X_VERSION_10_8_AND_LATER_BUT_DEPRECATED Introduced in Mac OS X v10.8, and deprecated in Mac OS X v10.8. +AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_8 Introduced in Mac OS X v10.0, but later deprecated in Mac OS X v10.8. +AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_8 Introduced in Mac OS X v10.1, but later deprecated in Mac OS X v10.8. +AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_8 Introduced in Mac OS X v10.2, but later deprecated in Mac OS X v10.8. +AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_8 Introduced in Mac OS X v10.3, but later deprecated in Mac OS X v10.8. +AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_8 Introduced in Mac OS X v10.4, but later deprecated in Mac OS X v10.8. +AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_8 Introduced in Mac OS X v10.5, but later deprecated in Mac OS X v10.8. +AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_8 Introduced in Mac OS X v10.6, but later deprecated in Mac OS X v10.8. +AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_8 Introduced in Mac OS X v10.7, but later deprecated in Mac OS X v10.8. +DEPRECATED_IN_MAC_OS_X_VERSION_10_8_AND_LATER Deprecated in Mac OS X v10.8. __BEGIN_DECLS __END_DECLS __OSX_AVAILABLE_BUT_DEPRECATED Magic 1 diff --git a/Modules/HeaderDoc/BlockParse.pm b/Modules/HeaderDoc/BlockParse.pm index b04b432..789a21a 100644 --- a/Modules/HeaderDoc/BlockParse.pm +++ b/Modules/HeaderDoc/BlockParse.pm @@ -3,7 +3,7 @@ # Module name: BlockParse # Synopsis: Block parser code # -# Last Updated: $Date: 2011/05/19 13:01:25 $ +# Last Updated: $Date: 2014/03/05 14:20:14 $ # # Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved. # @@ -72,6 +72,12 @@ # */ package HeaderDoc::BlockParse; +# /*! @abstract +# Tells the block parser to include the function body +# in the parse tree. +# */ +$HeaderDoc::includeFunctionContents = 0; + BEGIN { foreach (qw(Mac::Files)) { $MOD_AVAIL{$_} = eval "use $_; 1"; @@ -85,13 +91,17 @@ foreach (qw(Mac::Files Mac::MoreFiles)) { eval "use $_"; } + +# /*! @abstract Stores whether Objective-C protocol methods are optional or required. */ +$HeaderDoc::OptionalOrRequired = ""; + # $HeaderDoc::disable_parms = 0; @ISA = qw(Exporter); -@EXPORT = qw(blockParse nspaces blockParseOutside getAndClearCPPHash cpp_remove buildCommentFromFields bracematching peekmatch cpp_add_cl); +@EXPORT = qw(blockParse nspaces blockParseOutside getAndClearCPPHash cpp_remove buildCommentFromFields bracematching peekmatch cpp_add_cl pbs); @EXPORT_OK = qr(blockParseReturnState); # Used by Python parser. -use HeaderDoc::Utilities qw(findRelativePath safeName printArray printHash parseTokens isKeyword warnHDComment classTypeFromFieldAndBPinfo casecmp addAvailabilityMacro printFields objectForUID peek); +use HeaderDoc::Utilities qw(findRelativePath safeName printArray printHash parseTokens isKeyword warnHDComment classTypeFromFieldAndBPinfo casecmp addAvailabilityMacro printFields objectForUID peek isStandardAvailability); use HeaderDoc::HashObject; @@ -112,7 +122,7 @@ use File::Basename qw(basename); # In the git repository, contains the number of seconds since # January 1, 1970. # */ -$HeaderDoc::BlockParse::VERSION = '$Revision: 1305835285 $'; +$HeaderDoc::BlockParse::VERSION = '$Revision: 1394058014 $'; ################ Portability ################################### my $isMacOS; @@ -159,8 +169,12 @@ my %CPP_HASH = (); # */ my %CPP_ARG_HASH = (); +# 0, 1, or 2. my $cppDebugDefault = 0; my $cppDebug = 0; + +my $cppAddDebug = 0; + my $cppDebugFromToken = ""; my $nestedcommentwarn = 0; my $warnAllMultipleDefinitions = 1; @@ -353,6 +367,9 @@ sub bracematching ($tos eq "\@protocol") && do { return "\@end"; }; + (($lang eq "applescript") && $tos =~ /(if|repeat|try|tell)/) && do { + return "end"; + }; (($lang eq "ruby") && $tos =~ /(for|while|if|until|begin)/) && do { return "end"; }; @@ -571,6 +588,10 @@ sub bracematching # character. (The value of inComment (in the # parserState object) goes to 0 before that code, so # without this, it would end up at the start of the next parameter.) +# @var asConcat +# In AppleScript parsing, set to 1 when a vertical pipe operator (|) is +# encountered to protect an identifier. Set to 0 when the next vertical +# pipe operator is encountered. # # @vargroup Parameter parsing # @@ -616,6 +637,28 @@ sub bracematching # to insert the parser state because it is one of the access control tokens (e.g. # public/private) or because it isn't really being inserted into the tree. # +# @var pushParserStateAfterToken +# Normally 0. Set to 1 if the parser state should be pushed onto the stack +# after this token. +# +# @var pushParserStateAfterWordToken +# Normally 0. Set to 1 if the parser state should be pushed onto the stack +# after the next word token. May also be set to 2 if the parser state +# should be pushed at the word token after the next word token. +# +# @var pushParserStateAtBrace +# Normally 0. Set to 1 if the parser state should be pushed onto the stack +# after the next opening brace. +# +# @var occPushParserStateOnWordTokenAfterNext +# Normally 0. The name of this variable is slightly misleading. When used, +# the variable is initially set to 2. On the next word token (and only a word +# token), this variable is decremented to 1. +# +# At this point, matching behavior changes, and the parser state is pushed +# at the first token that is either a word token, an at sign (\@), a +# minus sign (-), or a plus sign (+). +# # @vargroup Tree management # # @var treeTop @@ -639,6 +682,11 @@ sub bracematching # @var treePopOnNewLine # This indicates that the current position in the parse tree should be popped from # the treeStack stack after the next newline character. +# @var trailingHide +# Indicates that this is a token that follows a state change to a new state in which +# the seenBraces flag was previously set, and that this token should be treated as +# though seenBraces were still set. This flag is only supported in bits of code after +# where it is first set (in the right closing brace code). # # @vargroup Parser stacks # @@ -748,7 +796,7 @@ sub blockParse my $treeDebug = 0; my $ilcDebug = 0; my $regexpDebug = 0; # 0, 1, 2 - my $parserStackDebug = 0 || $HeaderDoc::fileDebug; + my $parserStackDebug = 0 || $HeaderDoc::fileDebug; # 0, 1, 2 my $braceDebug = 0 || $HeaderDoc::fileDebug; my $hangDebug = 0; my $offsetDebug = 0; @@ -764,8 +812,11 @@ sub blockParse my $parserStateInsertDebug = 0; my $rubyDebug = 0; my $asDebug = 0; + my $reMarkDebug = 0; - $cppDebug = $cppDebugDefault || $HeaderDoc::fileDebug; + if ($asDebug && (!$HeaderDoc::AppleScriptDebug)) { $HeaderDoc::AppleScriptDebug = 1; } + + $cppDebug = $cppDebugDefault ? $cppDebugDefault : $HeaderDoc::fileDebug; # State variables (part 1 of 3) # my $typestring = ""; @@ -893,7 +944,7 @@ sub blockParse # that don't begin with parenthesis or brace. # my $inBrackets = 0; # square brackets ([]). my $inPType = 0; # in pascal types. - my $inRegexp = 0; # in perl regexp. + my $inRegexp = 0; # in regexp. my $leavingRegexp = 0; # inRegexp just went to zero, but don't process # this symbol differently in case it's a brace # or parenthesis. @@ -911,10 +962,10 @@ sub blockParse # This prevents the end-of-comment character # itself from being added.... - my $regexppattern = ""; # optional characters at start of regexp - my $singleregexppattern = ""; # members of regexppattern that take only - # one argument instead of two. - my $regexpcharpattern = ""; # legal chars to start a regexp. + #### my $regexppattern = ""; # optional characters at start of regexp + #### my $singleregexppattern = ""; # members of regexppattern that take only + #### # one argument instead of two. + #### my $regexpcharpattern = ""; # legal chars to start a regexp. my @regexpStack = (); # stack of RE tokens (since some can nest). # Get the parse tokens from Utilities.pm. @@ -935,6 +986,13 @@ sub blockParse my $requiredregexp = $parseTokens{requiredregexp}; my $moduleregexp = $parseTokens{moduleregexp}; + my $regexppattern = $parseTokens{regexppattern}; + my $singleregexppattern = $parseTokens{singleregexppattern}; + my $regexpfirstcharpattern = $parseTokens{regexpfirstcharpattern}; + my $regexpcharpattern = $parseTokens{regexpcharpattern}; + my $regexpAllowedAfter = $parseTokens{regexpAllowedAfter}; + my $TCLregexpcommand = $parseTokens{TCLregexpcommand}; + # print STDERR "SOCONSTRUCTOR: \"$parseTokens{soconstructor}\"\n"; if ($argparse && $lang eq "applescript") { @@ -960,12 +1018,12 @@ sub blockParse # Set up regexp patterns for perl, variable for perl or shell. if ($lang eq "perl" || $lang eq "shell" || $lang eq "tcl") { if ($lang eq "perl") { - # $regexpcharpattern = '\\{|\\#\\(|\\/|\\\'|\\"|\\<|\\[|\\`'; - # "}" vi bug workaround for previous line - $regexpcharpattern = "[[|{#(/'\"<`]"; - # "}" vi bug workaround for previous line - $regexppattern = "qq|qr|qx|qw|q|m|s|tr|y"; - $singleregexppattern = "qq|qr|qx|qw|q|m"; + #### # $regexpcharpattern = '\\{|\\#\\(|\\/|\\\'|\\"|\\<|\\[|\\`'; + #### # "}" vi bug workaround for previous line + #### $regexpcharpattern = "[[|{#(/'\"<`]"; + #### # "}" vi bug workaround for previous line + #### $regexppattern = "qq|qr|qx|qw|q|m|s|tr|y"; + #### $singleregexppattern = "qq|qr|qx|qw|q|m"; } } @@ -1054,6 +1112,7 @@ sub blockParse # my $classtype = ""; # my $inClass = 0; + my $asConcat = ""; my $pushParserStateAfterToken = 0; my $pushParserStateAfterWordToken = 0; my $pushParserStateAtBrace = 0; @@ -1110,7 +1169,9 @@ sub blockParse print STDERR "LINE[$inputCounter] : $line\n" if ($offsetDebug); # The tokenizer - if ($lang eq "perl" || $lang eq "shell") { + if ($lang eq "perl") { + @parts = split(/(->|=>|\&\&|\|\||"|'|\#|\{|\}|\(|\)|\s|;;|;|::|\\|\<\<|\W)/, $line); + } elsif ($lang eq "shell") { @parts = split(/("|'|\#|\{|\}|\(|\)|\s|;;|;|::|\\|\<\<|\W)/, $line); } elsif ($lang eq "tcl") { @parts = split(/("|'|\#|\{|\}|\(|\)|\s|;|\\|::|\/\*|\*\/|\W)/, $line); @@ -1156,7 +1217,7 @@ sub blockParse if ($localDebug || $cppDebug || $spaceDebug || $cppDebugFromToken) { foreach my $partlist (@parts) { print STDERR "PARTLIST: \"$partlist\"\n"; - if ($partlist eq $cppDebugFromToken) { + if ($partlist eq $cppDebugFromToken && length($cppDebugFromToken)) { $cppDebug = 1; $parseDebug = 1; $macroDebug = 1; } } @@ -1257,10 +1318,10 @@ sub blockParse $noCPPThisToken = 1; } } - if ($inCPPSpecial && $part =~ /(ifdef|ifndef)/) { + if ($inCPPSpecial && $part =~ /^(ifdef|ifndef)$/) { print STDERR "CPPSpecial: ifdef/ifndef\n" if ($cppDebug); $parserState->{NEXTTOKENNOCPP} = 2; - } elsif ($inCPPSpecial && $part =~ /if/) { + } elsif ($inCPPSpecial && $part =~ /^if$/) { print STDERR "CPPSpecial: if\n" if ($cppDebug); $parserState->{NEXTTOKENNOCPP} = 1; } @@ -1577,7 +1638,12 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST my $hideTokenAndMaybeContents = 0; my $bshandled = 0; my $setIsAvailable = 0; + my $trailingHide = 0; $treeSkip = 0; + my $reMark = ""; + + print "PARSER STATE COUNT: ".scalar(@parserStack)."\n" if ($parserStackDebug > 1); + $parserState->print() if ($parserStackDebug > 1); print STDERR "INMACROLINE: ".$parserState->{inMacroLine}."\n" if ($localDebug || $parseDebug || $parmDebug); if ($part) { $leavingRegexp = 0; } # Reset to 0 at the top of the loop. @@ -1595,6 +1661,10 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST print STDERR "MYPART: \"$part\"\n" if ($localDebug || $spaceDebug); + if ($braceDebug) { + print STDERR "TOBS: \"".peek(\@braceStack)."\"\n"; + } + # print STDERR "pushedfuncbrace: ".$parserState->{pushedfuncbrace}."\n"; $forcenobreak = 0; @@ -1635,9 +1705,10 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST next; } print STDERR "PART IS \"$part\"\n" if ($localDebug || $parserStackDebug || $parseDebug || $liteDebug || $spaceDebug || $tokenDebug); + print STDERR "SPS: ".scalar(@parserStack)." BSC: ".(scalar(@braceStack))." IBSC: ".$parserState->{initbsCount}."\n" if ($parserStackDebug); print STDERR "QUOTED: ".$parserState->isQuoted($lang, $sublang)."\n" if ($localDebug || $parserStackDebug || $parseDebug || $liteDebug || $spaceDebug); print STDERR "CURLINE IS \"$curline\"\n" if ($localDebug || $hangDebug || $liteDebug); - print STDERR "RETURNTYPE IS \"$parserState->{returntype}\"\n" if ($localDebug || $hangDebug || $liteDebug); + # print STDERR "RETURNTYPE IS \"$parserState->{returntype}\"\n" if ($localDebug || $hangDebug || $liteDebug); print STDERR "INOP: ".$parserState->{inOperator}."\n" if ($operatorDebug); if (!length($nextpart)) { @@ -1660,7 +1731,7 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST # if ($part !~ /(\s|<)/) print STDERR "OCCParse Case 2\n" if ($liteDebug); - if (($part =~ /(\-|\+|\w|\@)/ || ($part eq "/*" && $nextpart eq "!")) && !$parserState->{inComment} && !$parserState->{inInlineComment}) { + if (($part =~ /(#|\-|\+|\w|\@)/ || ($part eq "/*" && $nextpart eq "!")) && !$parserState->{inComment} && !$parserState->{inInlineComment}) { # die("PART: $part NP: $nextpart\n"); print STDERR "OCCParse Case 2a\n" if ($liteDebug); print STDERR "Last tree node set to $treeCur [1]\n" if ($parserStateInsertDebug); @@ -1714,11 +1785,14 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST print STDERR "PART: posstypes: $parserState->{posstypes}\n"; print STDERR "PART: seenBraces: $parserState->{seenBraces}\n"; print STDERR "SEENIF: ".$parserState->{seenIf}." INIF: ".$parserState->{INIF}."\n"; + } elsif ($parserStateInsertDebug) { + print STDERR "PART: seenBraces: $parserState->{seenBraces}\n"; } if ($parseDebug || $regexpDebug) { print STDERR "PART: inRegexp: $inRegexp inRegexpCharClass: $inRegexpCharClass\n"; print STDERR "PART: inRegexpTrailer: $inRegexpTrailer inRegexpFirstPart: $inRegexpFirstPart\n"; print STDERR "PART: leavingRegexp: $leavingRegexp regexpNoInterpolate: $regexpNoInterpolate\n"; + print STDERR "PART: inTCLRegExpCommand: ".$parserState->{inTCLRegExpCommand}." afterNL: ".$parserState->{afterNL}."\n"; } if ($parseDebug) { print STDERR "PART: seenTilde: $parserState->{seenTilde}\n"; @@ -1786,6 +1860,9 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST } $treeCur = $treeCur->addSibling($part, $hidden); + if ($HeaderDoc::includeFunctionContents && $reMark) { + $treeCur->{RE_STATE} = $reMark; + } $treeCur->isAvailabilityMacro(1); # print STDERR "SET IS AVAILABLE[2] FOR PART $part\n"; @@ -1813,13 +1890,15 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST print "IC: $parserState->{inClass} TOK: $part\n" if ($parseDebug || $classDebug); - my $externCDebug = 0; + my $externCDebug = 0; + my $iskw = isKeyword($part, $keywordhashref, $case_sensitive); + + if ($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces}) { # Handle the GCC "__attribute__" extension outside the context of # the parser because it isn't part of the language and massively # breaks the syntax. # Same for asm - my $iskw = isKeyword($part, $keywordhashref, $case_sensitive); if (($iskw == 8) && !$parserState->{attributeState} && !$parserState->{parsedParamParse} && !$parserState->{inBrackets} && @@ -1846,6 +1925,9 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST # Add __attribute__ as the next token. $treeCur = $treeCur->addSibling($part, 0); + if ($HeaderDoc::includeFunctionContents && $reMark) { + $treeCur->{RE_STATE} = $reMark; + } push(@treeStack, $treeCur); # Nest all contents one level lower. @@ -1870,6 +1952,9 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST $parserState->{attributeState} = -1; } $treeCur = $treeCur->addSibling($part, 0); + if ($HeaderDoc::includeFunctionContents && $reMark) { + $treeCur->{RE_STATE} = $reMark; + } $part = $nextpart; next; } elsif ($parserState->{attributeState} < 0) { @@ -1884,6 +1969,9 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST print STDERR "GCC attribute close paren, count=".(0-$parserState->{attributeState})."\n" if ($localDebug || $gccAttributeDebug); } $treeCur = $treeCur->addSibling($part, 0); + if ($HeaderDoc::includeFunctionContents && $reMark) { + $treeCur->{RE_STATE} = $reMark; + } if (!$parserState->{attributeState}) { print STDERR "GCC attribute: done collecting.\n" if ($localDebug || $gccAttributeDebug); @@ -1930,6 +2018,8 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST } } + } + # Here be the parser. Abandon all hope, ye who enter here. $treepart = ""; @@ -1955,8 +2045,8 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST print STDERR "parserState pushed onto stack[PROTOCOL]\n" if ($parserStackDebug); $parserState->{inProtocol} = -1; - $parserState->{lastTreeNode} = $treeCur; print STDERR "Last tree node set to $treeCur [2]\n" if ($parserStateInsertDebug); + $parserState->{lastTreeNode} = $treeCur; $curline = ""; $parserState->{storeDec} = $declaration; $parserState->{freezereturn} = 1; @@ -2100,8 +2190,7 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST } else { $parserState->{implementsClass} = ""; } - } elsif ($parserState->isLeftBrace($part, $lang, $parseTokens{lbrace}, $parseTokens{lbraceunconditionalre}, $parseTokens{lbraceconditionalre}, - $parseTokens{classisbrace}, $parseTokens{functionisbrace}, $case_sensitive, scalar(@braceStack)) || $part eq ";") { + } elsif ($parserState->isLeftBrace($part, $lang, \%parseTokens, $case_sensitive, scalar(@braceStack)) || $part eq ";") { # $part eq "{" print STDERR "INCLASS BRCSEMI\n" if ($parseDebug || $classDebug); @@ -2214,23 +2303,29 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST $parserState->dbprint() if ($regexpDebug == 2); print STDERR "LASTNSPART: $lastnspart\n" if ($regexpDebug == 2); - print STDERR " - (($inRegexp || $parserState->{lastsymbol} eq \"~\" || - ((!$inRegexp) && - ($parserState->{lastsymbol} =~ /[=,(]/ || - ($parserState->{lastsymbol} eq \"\" && $lastnspart eq \"\" && peek(\"".peek(\@braceStack)."\") eq \"(\") - ) && $part =~ /\// && !$parserState->{inTemplate} && - length($regexpcharpattern) && - !($inRegexp || $inRegexpTrailer || - $parserState->{inString} || $parserState->{inComment} || - $parserState->{inInlineComment} || $parserState->{inChar}) - ) - ) && - (length($regexpcharpattern) && - $part =~ /^($regexpcharpattern)$/ && - (!$inRegexpCharClass) && - (!scalar(@regexpStack) || $part eq peekmatch(\@regexpStack, $lang, $fullpath, $inputCounter)) - ) + print STDERR "\n + (($inRegexp &&\n + (length($regexpcharpattern) &&\n + $part =~ /^($regexpcharpattern)$/ &&\n + (!$inRegexpCharClass) &&\n + (!scalar(\@regexpStack) || $part eq peekmatch(\\\@regexpStack, $lang, $fullpath, $inputCounter))\n + )\n + ) || (\n + (!$inRegexp) &&\n + ($parserState->{lastsymbol} =~ /$regexpAllowedAfter/ ||\n + $parserState->{inTCLRegExpCommand} ||\n + ($parserState->{lastsymbol} eq \"\" && $lastnspart eq \"(\" && peek(\\\@braceStack) eq \"(\")\n + ) && $part =~ /\// && !$parserState->{inTemplate} &&\n + length($regexpfirstcharpattern) &&\n + (!($inRegexp || $inRegexpTrailer ||\n + $parserState->{inString} || $parserState->{inComment} ||\n + $parserState->{inInlineComment} || $parserState->{inChar})) &&\n + (!$parserState->isRubyOpenQuote($part) || $parserState->isRubyCloseQuote($part)) &&\n + (length($regexpfirstcharpattern) &&\n + $part =~ /^($regexpfirstcharpattern)$/ &&\n + (!$inRegexpCharClass) &&\n + (!scalar(\@regexpStack) || $part eq peekmatch(\\\@regexpStack, $lang, $fullpath, $inputCounter))\n + )\n \n" if ($regexpDebug == 2); if ($HeaderDoc::parseIfElse && (!$parserState->{inMacro} && !$parserState->{inMacroLine} && !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}))) { @@ -2303,52 +2398,117 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST $part eq "::" && !$parserState->{classNameConcat} && !$parserState->{variableNameConcat} && - !$parserState->{seenBraces}) { + ($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces})) { print STDERR "Perl CONCAT -> 1\n" if ($liteDebug); $parserState->{variableNameConcat} = 2; }; + + if ($part =~ /[\n\r]/) { + # 2 until first non-space token. + $parserState->{afterNL} = 2; + + if ($lang eq "tcl") { + if ($parserState->{inTCLRegExpCommand}) { + $parserState->{inTCLRegExpCommand} = 0; + } + } + } elsif ($parserState->{afterNL} == 1) { + # 0 after first non-space token. + $parserState->{afterNL} = 0; + } elsif ($parserState->{afterNL} == 2 && $part =~ /\S/) { + # 1 during first non-space token. + $parserState->{afterNL} = 1; + } + + SWITCH: { # Blank declaration handlers (mostly for misuse of # OSMetaClassDeclareReservedUsed and similar) - (($lang eq "applescript") && !$argparse && ($part =~ /(of|in)/) && + (($lang eq "applescript") && !$argparse && ($part eq "|") && !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do { + print STDERR "APPLESCRIPT CONCAT: CASE AS_00a\n" if ($liteDebug); + if ($asConcat) { + $part = $asConcat . $part; + $asConcat = ""; + # Fall through. + } else { + $asConcat = $part; + $part = ""; + last SWITCH; + } + }; + + (($lang eq "applescript") && !$argparse && ($asConcat) && + !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || + $parserState->{inChar})) && do { + print STDERR "APPLESCRIPT CONCAT: CASE AS_00b\n" if ($liteDebug); + $asConcat .= $part; + $part = ""; + last SWITCH; + }; + + (($lang eq "applescript") && !$argparse && ($part =~ /^(of|in)$/) && + !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || + $parserState->{inChar})) && do { + print STDERR "APPLESCRIPT OF/IN: CASE AS_00A\n" if ($liteDebug); print STDERR "IN APPLESCRIPT OF/IN: SET TO $part\n" if ($asDebug); $parserState->{inOfIn} = 1; $parserState->{OfIn} = $part; last SWITCH; }; - (($lang eq "applescript") && $parserState->{inOfIn} && ($part =~ /\w/)) && do { + (($lang eq "applescript") && + !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || + $parserState->{inChar}) && + $parserState->{inOfIn} && ($part =~ /\w/)) && do { + print STDERR "APPLESCRIPT OF/IN: CASE AS_00B\n" if ($liteDebug); print STDERR "IN APPLESCRIPT OF/IN: ADDING $part\n" if ($asDebug); $parserState->{OfIn} .= " ".$part; $parserState->{inOfIn} = 0; last SWITCH; }; - (($lang eq "applescript") && !$argparse && $labelregexp && ($part =~ /$labelregexp/) && ($parserState->{startOfDec} != 1)) && do { + (($lang eq "applescript") && + !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || + $parserState->{inChar}) && + !$argparse && $labelregexp && ($part =~ /$labelregexp/) && ($parserState->{startOfDec} != 1)) && do { + print STDERR "APPLESCRIPT LABEL: CASE AS_00C\n" if ($liteDebug); print STDERR "IN APPLESCRIPT LABEL: SET TO $part SOD=".$parserState->{startOfDec}."\n" if ($asDebug); $parserState->{inLabel} = 1; $parserState->{ASlabel} = $part; last SWITCH; }; - (($lang eq "applescript") && $labelregexp && $parserState->{inLabel} && ($part =~ /\w/)) && do { + (($lang eq "applescript") && + !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || + $parserState->{inChar}) && + $labelregexp && $parserState->{inLabel} && ($part =~ /\w/)) && do { + print STDERR "APPLESCRIPT LABEL: CASE AS_00D\n" if ($liteDebug); print STDERR "IN APPLESCRIPT LABEL: ADDING $part\n" if ($asDebug); $parserState->{ASlabel} .= " ".$part; $parserState->{inLabel} = 0; last SWITCH; }; - (($lang eq "applescript") && ($part eq "given")) && do { + (($lang eq "applescript") && + !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || + $parserState->{inChar}) && + ($part eq "given")) && do { + print STDERR "APPLESCRIPT GIVEN: CASE AS_00E\n" if ($liteDebug); print STDERR "IN APPLESCRIPT GIVEN ($part)\n" if ($asDebug); $parserState->{inGiven} = 1; $parserState->{inLabel} = 0; last SWITCH; }; - (($lang eq "applescript") && $parserState->{inGiven} && ($part !~ /[\r\n]/)) && do { + + (($lang eq "applescript") && $parserState->{inGiven} && + !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || + $parserState->{inChar}) && + ($part !~ /[\r\n]/)) && do { + print STDERR "APPLESCRIPT GIVEN: CASE AS_00F\n" if ($liteDebug); print STDERR "IN APPLESCRIPT GIVEN\n" if ($asDebug); if ($part eq ",") { print STDERR "IN APPLESCRIPT GIVEN COMMA\n" if ($asDebug); @@ -2363,17 +2523,20 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST }; # (($lang eq "applescript") && $argparse && ($part eq ":")) && do { + # print STDERR "APPLESCRIPT OF/IN: CASE AS_00G\n" if ($liteDebug); # print STDERR "IN APPLESCRIPT GIVEN: IGNORING COLON\n" if ($asDebug); # $treepart = ""; # last SWITCH; # }; (($iskw == 9) && ($parserState->{afterSemi} || $parserState->{firstpastnl})) && do { + print STDERR "ISKEYWORD == 9: CASE KW_0A\n" if ($liteDebug); $parserState->{inCase}++; print STDERR "inCase -> ".$parserState->{inCase}."\n" if ($parseDebug || $localDebug || $braceDebug); }; (($iskw == 10) && ($parserState->{afterSemi} == 2)) && do { # && ($parserState->{afterSemi} >= 2)) && do { + print STDERR "ISKEYWORD == 10: CASE KW_0B\n" if ($liteDebug); # print "AFTERSEMI: ".$parserState->{afterSemi}."\n" if ($parseDebug || $localDebug || $braceDebug); $parserState->{inCase}--; print STDERR "inCase -> ".$parserState->{inCase}."\n" if ($parseDebug || $localDebug || $braceDebug); @@ -2385,6 +2548,20 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST $part = ""; last SWITCH; }; + + (length($TCLregexpcommand) && ($part =~ /^$TCLregexpcommand$/) && + ($parserState->{lastsymbol} eq ";" || $parserState->{afterNL} || + $lasttoken eq "[" + ) && + (!($inRegexp || $inRegexpTrailer || $parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}))) && do { + print STDERR "TCL REGEXP: CASE 01A\n" if ($liteDebug); + $parserState->{inTCLRegExpCommand} = 1; + + # print STDERR "LS: $parserState->{lastsymbol} ANL: $parserState->{afterNL} LT: $lasttoken\n"; + + # Fall through + }; + (($lang eq "perl" || $lang eq "shell") && $part eq "<<" && !$parserState->{attributeState} && !$parserState->{parsedParamParse} && !$parserState->{inBrackets} && @@ -2401,6 +2578,7 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST !$parserState->{classNameFound} && !$parserState->{inMacro} && !$parserState->{inMacroLine}) && do { + print STDERR "PERL OR SHELL MULTI-LINE STRING: CASE 01B\n" if ($liteDebug); $parserState->{inString} = 13; $parserState->{endOfString} = ""; @@ -2411,16 +2589,22 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST last SWITCH; }; (($lang eq "perl" || $lang eq "shell") && ($parserState->{inString} == 13) && ($parserState->{endOfString} eq "") && $part =~ /\S/) && do { + print STDERR "PERL OR SHELL MULTI-LINE STRING: CASE 01C\n" if ($liteDebug); $parserState->{endOfString} = $part; last SWITCH; }; (($lang eq "perl" || $lang eq "shell") && ($parserState->{inString} == 13) && ($part =~ /[\n\r]/)) && do { + print STDERR "PERL OR SHELL MULTI-LINE STRING: CASE 01D\n" if ($liteDebug); $parserState->{firstpastnl} = 1; last SWITCH; }; (($lang eq "perl" || $lang eq "shell") && ($parserState->{inString} == 13) && ($part eq $parserState->{endOfString}) && $parserState->{firstpastnl}) && do { - $treeCur->addSibling($part, 0); $treeSkip = 1; + print STDERR "PERL OR SHELL MULTI-LINE STRING: CASE 01E\n" if ($liteDebug); + my $tempCur = $treeCur->addSibling($part, 0); $treeSkip = 1; + if ($HeaderDoc::includeFunctionContents && $reMark) { + $tempCur->{RE_STATE} = $reMark; + } $treeCur = pop(@treeStack) || $treeTop; $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); $treeCur = $treeCur->lastSibling(); @@ -2431,11 +2615,13 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST }; (($lang eq "perl" || $lang eq "shell") && ($parserState->{inString} == 13) && $part =~ /\S/ && $parserState->{firstpastnl}) && do { + print STDERR "PERL OR SHELL MULTI-LINE STRING: CASE 01F\n" if ($liteDebug); $parserState->{firstpastnl} = 0; last SWITCH; }; (($lang eq "perl" || $lang eq "shell") && ($parserState->{inString} == 13)) && do { + print STDERR "PERL OR SHELL MULTI-LINE STRING: CASE 01G\n" if ($liteDebug); last SWITCH; }; @@ -2521,6 +2707,7 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST last SWITCH; }; ($parserState->{inMacro} == 1 && ($part ne $parseTokens{soc}) && ($part ne $parseTokens{eoc}) && $part =~ /\s/) && do { + print STDERR "INMACRO SPACE: CASE 04A\n" if ($liteDebug); $treepart = $part; $part = ""; last SWITCH; }; @@ -2586,7 +2773,7 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST if ($part =~ /[\{\(]/o) { push(@braceStack, $part); push(@parsedParamParseStack, $parserState->{parsedParamParse}); - print STDERR "PUSHED $part ONTO BRACESTACK\n" if ($macroDebug || $braceDebug); + print STDERR "PUSHED $part ONTO BRACESTACK [1]\n" if ($macroDebug || $braceDebug); } elsif ($part =~ /[\}\)]/o) { if ($part ne peekmatch(\@braceStack, $lang, $fullpath, $inputCounter)) { if ($parserState->{macroNoTrunc} == 1) { @@ -2596,7 +2783,7 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST } my $temp = pop(@braceStack); $parserState->{parsedParamParse} = pop(@parsedParamParseStack); - print STDERR "POPPED $temp FROM BRACESTACK\n" if ($macroDebug || $braceDebug); + print STDERR "POPPED $temp FROM BRACESTACK [1]\n" if ($macroDebug || $braceDebug); } if ($part =~ /\S/o) { @@ -2627,6 +2814,7 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST # Fall through. }; (length($parseTokens{constname}) && $part eq $parseTokens{constname} && !($inRegexp || $inRegexpTrailer || $parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && (!(scalar(@braceStack) - $parserState->{initbsCount}))) && do { + print STDERR "CONST: CASE 06B\n" if ($liteDebug); $parserState->{constKeywordFound} = 1; print STDERR "DETECTED CONSTANT KEYWORD\n" if ($localDebug || $parseDebug); @@ -2635,7 +2823,7 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST # print STDERR "IRE: $inRegexp IRT: $inRegexpTrailer IS: $parserState->{inString} ICo $parserState->{inComment} ILC: $parserState->{inInlineComment} ICh $parserState->{inChar}\n"; # print STDERR "IRE: $inRegexp IRT: $inRegexpTrailer IS: $parserState->{inString} ICo $parserState->{inComment} ILC: $parserState->{inInlineComment} ICh $parserState->{inChar}\n"; - (length($regexppattern) && $parserState->{lastsymbol} ne "\$" && $part =~ /^($regexppattern)$/ && !($inRegexp || $inRegexpTrailer || $parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do { + (length($regexppattern) && $part ne $parseTokens{soc} && $part ne $parseTokens{eoc} && $part ne $parseTokens{ilc} && $part ne $parseTokens{ilc_b} && $parserState->{lastsymbol} ne "\$" && $part =~ /^($regexppattern)$/ && !($inRegexp || $inRegexpTrailer || $parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do { print STDERR "REGEXP PATTERN: CASE 07\n" if ($liteDebug); my $match = $1; print STDERR "REGEXP WITH PREFIX\n" if ($regexpDebug); @@ -2653,29 +2841,41 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST if ($part eq "tr") { $regexpNoInterpolate = 1; } # if ($part =~ /tr/) { $regexpNoInterpolate = 1; } } + $reMark = "RE_PREFIX"; + if ($reMarkDebug) { print STDERR "REMARK: $reMark\n"; } $inRegexpFirstPart = 2; last SWITCH; }; # end regexppattern - (($inRegexp || $parserState->{lastsymbol} eq "~" || - ((!$inRegexp) && - ($parserState->{lastsymbol} =~ /[=,(]/ || - ($parserState->{lastsymbol} eq "" && $lastnspart eq "(" && peek(\@braceStack) eq "(") - ) && $part =~ /\// && !$parserState->{inTemplate} && - length($regexpcharpattern) && - !($inRegexp || $inRegexpTrailer || - $parserState->{inString} || $parserState->{inComment} || - $parserState->{inInlineComment} || $parserState->{inChar}) - ) - ) && - (length($regexpcharpattern) && - $part =~ /^($regexpcharpattern)$/ && - (!$inRegexpCharClass) && - (!scalar(@regexpStack) || $part eq peekmatch(\@regexpStack, $lang, $fullpath, $inputCounter)) - ) + (($inRegexp && + (length($regexpcharpattern) && + $part =~ /^($regexpcharpattern)$/ && + (!$inRegexpCharClass) && + (!scalar(@regexpStack) || $part eq peekmatch(\@regexpStack, $lang, $fullpath, $inputCounter)) + ) + ) || ( + (!$inRegexp) && $part ne $parseTokens{soc} && $part ne $parseTokens{eoc} && $part ne $parseTokens{ilc} && $part ne $parseTokens{ilc_b} && + ($parserState->{lastsymbol} =~ /$regexpAllowedAfter/ || + ($parseTokens{regexpAllowedAtStartOfLine} && $parserState->{afterNL}) || + $parserState->{inTCLRegExpCommand} || + ($parserState->{lastsymbol} eq "" && $lastnspart eq "(" && peek(\@braceStack) eq "(") + ) && + length($regexpfirstcharpattern) && + $part =~ /$regexpfirstcharpattern/ && !$parserState->{inTemplate} && + (!($inRegexp || $inRegexpTrailer || + $parserState->{inString} || $parserState->{inComment} || + $parserState->{inInlineComment} || $parserState->{inChar})) && + (!$parserState->isRubyOpenQuote($part) || $parserState->isRubyCloseQuote($part)) && + (!$inRegexpCharClass) && + (!scalar(@regexpStack) || $part eq peekmatch(\@regexpStack, $lang, $fullpath, $inputCounter)) + ) ) && do { print STDERR "REGEXP CHARACTER: CASE 08\n" if ($liteDebug); print STDERR "REGEXP?\n" if ($regexpDebug); + if ($parserState->{inTCLRegExpCommand}) { + $parserState->{inTCLRegExpCommand} = 0; + } + # if ($lasttoken eq "\\") if ($parserState->isQuoted($lang, $sublang) || ((!$inRegexp) && $lasttoken eq "\$")) { @@ -2692,12 +2892,18 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST $inRegexp = 2; print STDERR "IRFP -> 1\n" if ($regexpDebug); $inRegexpFirstPart = 1; + $reMark = "RE_START"; + if ($reMarkDebug) { print STDERR "REMARK: $reMark\n"; } } elsif ($inRegexpFirstPart != 2) { print STDERR "IRFP -> 0\n" if ($regexpDebug); $inRegexpFirstPart = 0; + $reMark = "RE_PARTSEP"; + if ($reMarkDebug) { print STDERR "REMARK: $reMark\n"; } } else { print STDERR "IRFP -> 1\n" if ($regexpDebug); $inRegexpFirstPart = 1; + $reMark = "RE_START"; + if ($reMarkDebug) { print STDERR "REMARK: $reMark\n"; } } $lasttoken = $part; @@ -2721,7 +2927,11 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST print STDERR "PUSHING $part ONTO REGEXPSTACK [1]\n" if ($localDebug || $parseDebug || $regexpDebug); push(@regexpStack, $part); $inRegexp--; - if (!$inRegexp) { $leavingRegexp = 1; } + if (!$inRegexp) { + $leavingRegexp = 1; + $reMark = "RE_END"; + if ($reMarkDebug) { print STDERR "REMARK: $reMark\n"; } + } print STDERR "INREGEXP -> $inRegexp [4]\n" if ($regexpDebug); } else { my $match = peekmatch(\@regexpStack, $lang, $fullpath, $inputCounter); @@ -2730,14 +2940,22 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST if (!scalar(@regexpStack) && ($match eq $part)) { $inRegexp--; - if (!$inRegexp) { $leavingRegexp = 1; } + if (!$inRegexp) { + $leavingRegexp = 1; + $reMark = "RE_END"; + if ($reMarkDebug) { print STDERR "REMARK: $reMark\n"; } + } print STDERR "INREGEXP -> $inRegexp [5]\n" if ($regexpDebug); if ($inRegexp == 2 && ($tos eq "/" || $tos eq "|")) { # we don't double the slash or vertical bar in the # middle of a s/foo/bar/g style # expression. $inRegexp--; - if (!$inRegexp) { $leavingRegexp = 1; } + if (!$inRegexp) { + $leavingRegexp = 1; + $reMark = "RE_END"; + if ($reMarkDebug) { print STDERR "REMARK: $reMark\n"; } + } print STDERR "INREGEXP -> $inRegexp [6]\n" if ($regexpDebug); } if ($inRegexp) { @@ -2812,8 +3030,13 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST # Pascal and PHP) (($part eq $parseTokens{sofunction} || $part eq $parseTokens{soprocedure} || $part eq $parseTokens{soconstructor}) && + (($lang ne "applescript") || $parserState->appleScriptFunctionLegalHere(\@braceStack)) && !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !(scalar(@braceStack)-$parserState->{initbsCount}) && !$parserState->{seenBraces}) && do { + + # print STDERR "(($part eq $parseTokens{sofunction} || $part eq $parseTokens{soprocedure} || $part eq $parseTokens{soconstructor}) &&". + # "!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})\n"; + # print STDERR "AFTERNL: ".$parserState->{afterNL}."\n"; print STDERR "SOFUNC: CASE 10\n" if ($liteDebug); if ($part eq $parseTokens{soconstructor}) { $parserState->{isConstructor} = 1; @@ -2850,6 +3073,9 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST if ($parseTokens{parmswithcurlybraces}) { $parserState->{pendingBracedParameters} = 1; } + if ($parseTokens{functionisapiowner}) { + $pushParserStateAtBrace = 1; + } last SWITCH; }; @@ -2896,6 +3122,13 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST (!($parseTokens{classisbrace} && $parserState->{sodclass} eq "class" && (!$parserState->{inRubyClass}))) && (!($parseTokens{functionisbrace} && $parserState->{pushedfuncbrace} == 1)) && ($parserState->isQuoted($lang, $sublang) || (!$parserState->{newlineIsSemi}))) && do { + + my $precursor = $parserState->clearLeftBracePrecursor(); + if ($precursor) { + push(@braceStack, $precursor); + print STDERR "Pushing $precursor onto the brace stack [clearLeftBracePrecursor]\n" if ($HeaderDoc::AppleScriptDebug || $braceDebug || $parseDebug); + } + if ($lang eq "shell") { if ($part eq ";;") { $parserState->{afterSemi} = 2; @@ -2927,7 +3160,7 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST $treepart = $part; if ($inRegexp) { warn "$fullpath:$inputCounter: warning: multi-line regular expression\n"; - print "DECTODATE: $declaration".$line."\n"; + print STDERR "DECTODATE: $declaration".$line."\n"; } print STDERR "NLCR\n" if ($tsDebug || $treeDebug || $localDebug); # print "LASTCHAR: $lastchar\n"; @@ -2941,7 +3174,13 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST $postPossNL = 2; } elsif ($treePopOnNewLine && $prev_inInlineComment) { # print STDERR "TPONL: $treePopOnNewLine\n"; - print STDERR "Keeping parsed parameter $parsedParam because we're leaving a single-line comment.\n" if ($parmDebug || $cppDebug || $localDebug); + if ($parserState->{inMacroLine}) { + print STDERR "skipped pushing CPP directive $parsedParam into parsedParamList [0]\n" if ($parmDebug || $cppDebug || $localDebug); + $parserState->{inMacroLine} = 0; + $parsedParam = ""; + } else { + print STDERR "Keeping parsed parameter $parsedParam because we're leaving a single-line comment.\n" if ($parmDebug || $cppDebug || $localDebug); + } } else { if ($parserState->{inMacroLine}) { print STDERR "skipped pushing CPP directive $parsedParam into parsedParamList [1]\n" if ($parmDebug || $cppDebug || $localDebug); @@ -2981,13 +3220,16 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST # pop once for //, possibly again for macro $treePopOnNewLine = 0 - $treePopOnNewLine; $treeCur = $treeCur->addSibling($treepart, 0); + if ($HeaderDoc::includeFunctionContents && $reMark) { + $treeCur->{RE_STATE} = $reMark; + } bless($treeCur, "HeaderDoc::ParseTree"); # push(@treeStack, $treeCur); $treeSkip = 1; $treeCur = pop(@treeStack); if (!$treeCur) { $treeCur = $treeTop; - warn "$fullpath:$inputCounter: warning: Attempted to pop off top of tree\n"; + warn "$fullpath:$inputCounter: warning: Attempted to pop off top of tree"; } $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); $treeCur = $treeCur->lastSibling(); @@ -2998,13 +3240,16 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST if ($treePopOnNewLine == 1 || ($treePopOnNewLine && !$parserState->isQuoted($lang, $sublang))) { # $parserState->{lastsymbol} ne "\\" $treeCur = $treeCur->addSibling($treepart, 0); + if ($HeaderDoc::includeFunctionContents && $reMark) { + $treeCur->{RE_STATE} = $reMark; + } bless($treeCur, "HeaderDoc::ParseTree"); # push(@treeStack, $treeCur); $treeSkip = 1; $treeCur = pop(@treeStack); if (!$treeCur) { $treeCur = $treeTop; - warn "$fullpath:$inputCounter: warning: Attempted to pop off top of tree\n"; + warn "$fullpath:$inputCounter: warning: Attempted to pop off top of tree"; } $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); $treeCur = $treeCur->lastSibling(); @@ -3022,7 +3267,7 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST # C++ template handlers - ($part eq $parseTokens{sotemplate} && (($lang eq "perl" && $parserState->{lastsymbol} eq "=" && !$inRegexp) || ($lang ne "perl" && (!$parserState->{seenBraces}) && (!$parserState->{inMacroLine}) && (!$parserState->{inMacro}) && (!$parserState->{INIF}))) && ($parserState->{inOperator} != 1)) && do { + ($part eq $parseTokens{sotemplate} && (($lang eq "perl" && $parserState->{lastsymbol} eq "=" && !$inRegexp) || ($lang ne "perl" && ($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces}) && (!$parserState->{inMacroLine}) && (!$parserState->{inMacro}) && (!$parserState->{INIF}))) && ($parserState->{inOperator} != 1)) && do { print STDERR "C++ TEMPLATE: CASE 14\n" if ($liteDebug); if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) { if ($HeaderDoc::hideIDLAttributes && $lang eq "C" && $sublang eq "IDL") { $hideTokenAndMaybeContents = 3; } @@ -3037,11 +3282,13 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST $parserState->{onlyComments} = 0; push(@parsedParamParseStack, $parserState->{parsedParamParse}); push(@braceStack, $part); pbs(@braceStack); - print STDERR "PUSHED $part ONTO BRACESTACK\n" if ($macroDebug || $braceDebug); + print STDERR "PUSHED $part ONTO BRACESTACK [2]\n" if ($macroDebug || $braceDebug); print STDERR "LINE: $line\n" if ($regexpDebug && $braceDebug); - if (!$parserState->{seenBraces}) { # TREEDONE + if ($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces}) { # TREEDONE $treeNest = 1; - if (!$parserState->{hollow}) { $sethollow = 1; } # IDL can have this at the start of declaration. + if (!$parserState->{seenBraces}) { + if (!$parserState->{hollow}) { $sethollow = 1; } # IDL can have this at the start of declaration. + } if ($treeDebug) { print STDERR "TS TREENEST -> 1 [8]\n"; } # push(@treeStack, $treeCur); # $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1; @@ -3051,7 +3298,7 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST } last SWITCH; }; - ($part eq $parseTokens{eotemplate} && (($lang eq "perl" && $parserState->{inTemplate} && !$inRegexp) || ($lang ne "perl" && (!$parserState->{seenBraces}) && (!$parserState->{inMacroLine}) && (!$parserState->{inMacro}) && (!$parserState->{INIF}))) && ($parserState->{inOperator} != 1)) && do { + ($part eq $parseTokens{eotemplate} && (($lang eq "perl" && $parserState->{inTemplate} && !$inRegexp) || ($lang ne "perl" && ($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces}) && (!$parserState->{inMacroLine}) && (!$parserState->{inMacro}) && (!$parserState->{INIF}))) && ($parserState->{inOperator} != 1)) && do { print STDERR "C++ TEMPLATE END: CASE 15\n" if ($liteDebug); if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && (!(scalar(@braceStack)-$parserState->{initbsCount}) || $parserState->{inTemplate})) { if ($parserState->{inTemplate}) { @@ -3065,13 +3312,20 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST } my $top = pop(@braceStack); $parserState->{parsedParamParse} = pop(@parsedParamParseStack); - print STDERR "POPPED $top FROM BRACESTACK\n" if ($macroDebug || $braceDebug); - if (!$parserState->{seenBraces}) { # TREEDONE - $treeCur->addSibling($part, 0); $treeSkip = 1; + print STDERR "POPPED $top FROM BRACESTACK [2]\n" if ($macroDebug || $braceDebug); + if ($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces}) { # TREEDONE + my $tempCur = $treeCur->addSibling($part, 0); $treeSkip = 1; + if ($HeaderDoc::includeFunctionContents && $reMark) { + $tempCur->{RE_STATE} = $reMark; + } $treeCur = pop(@treeStack) || $treeTop; - $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); + if (!$parserState->{seenBraces}) { # TREEDONE + $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); + } $treeCur = $treeCur->lastSibling(); - $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); + if (!$parserState->{seenBraces}) { # TREEDONE + $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); + } print STDERR "TSPOP [2]: now $treeCur\n" if ($tsDebug || $treeDebug); bless($treeCur, "HeaderDoc::ParseTree"); } @@ -3081,6 +3335,7 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST # set this off. if ($lang eq "perl") { push(@braceStack, $top); + print STDERR "PUSHED $top ONTO BRACESTACK [2A]\n" if ($macroDebug || $braceDebug); } else { warn("$fullpath:$inputCounter: warning: Template (angle) brackets do not match.\nWe may have a problem.\n"); } @@ -3089,6 +3344,7 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST last SWITCH; }; ($ruby && ($part eq "<") && ($parserState->{sodclass} eq "class")) && do { + print STDERR "RUBY LEFT ANGLE BRACE: CASE 15A\n" if ($liteDebug); if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && (!(scalar(@braceStack)-$parserState->{initbsCount}))) { $parserState->{waitingForExceptions} = 1; } @@ -3201,10 +3457,14 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST } }; (length($requiredregexp) && $part =~ /$requiredregexp/) && do { + print STDERR "REQUIRED REGEXP: CASE 17A\n" if ($liteDebug); print STDERR "REQUIRED REGEXP MATCH: \"$part\"\n" if ($localDebug || $parseDebug); $hollowskip = 1; print STDERR "hollowskip -> 1 (requiredregexp)\n" if ($parserStateInsertDebug); + $HeaderDoc::OptionalOrRequired = $part; + $parserState->{optionalOrRequired} = $part; + last SWITCH; }; @@ -3275,7 +3535,7 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST next SWITCH; } } - if (!$parserState->{seenBraces} && !$parserState->{occmethod}) { # TREEDONE + if (($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces}) && !$parserState->{occmethod}) { # TREEDONE # $treeCur->addSibling($part, 0); $treeSkip = 1; $treeNest = 1; if ($treeDebug) { print STDERR "TS TREENEST -> 1 [9]\n"; } @@ -3338,7 +3598,7 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST # if (($lasttoken !~ /\\$/o) && ($curstring !~ /\\$/o)) if (!$parserState->isQuoted($lang, $sublang)) { if (!$parserState->{inString}) { - if (!$parserState->{seenBraces}) { # TREEDONE + if ($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces}) { # TREEDONE $treeNest = 1; if ($treeDebug) { print STDERR "TS TREENEST -> 1 [10]\n"; } # push(@treeStack, $treeCur); @@ -3346,8 +3606,11 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST # bless($treeCur, "HeaderDoc::ParseTree"); } } else { - if (!$parserState->{seenBraces}) { # TREEDONE - $treeCur->addSibling($part, 0); $treeSkip = 1; + if ($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces}) { # TREEDONE + my $tempCur = $treeCur->addSibling($part, 0); $treeSkip = 1; + if ($HeaderDoc::includeFunctionContents && $reMark) { + $tempCur->{RE_STATE} = $reMark; + } $treeCur = pop(@treeStack) || $treeTop; $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); $treeCur = $treeCur->lastSibling(); @@ -3377,7 +3640,10 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST $fall_through = 1; } elsif (!$parserState->isQuoted($lang, $sublang)) { if ($inRegexp && $inRegexpFirstPart == 1) { + print STDERR "inRegexpCharClass -> 3\n" if ($regexpDebug); $inRegexpCharClass = 3; + $reMark = "RE_CCSTART"; + if ($reMarkDebug) { print STDERR "REMARK: $reMark\n"; } } print STDERR "lbracket\n" if ($localDebug); @@ -3388,8 +3654,8 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST } push(@parsedParamParseStack, $parserState->{parsedParamParse}); push(@braceStack, $part); pbs(@braceStack); - print STDERR "PUSHED $part ONTO BRACESTACK\n" if ($macroDebug || $braceDebug); - if (!$parserState->{seenBraces}) { # TREEDONE + print STDERR "PUSHED $part ONTO BRACESTACK [3]\n" if ($macroDebug || $braceDebug); + if ($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces}) { # TREEDONE $treeNest = 1; if ($treeDebug) { print STDERR "TS TREENEST -> 1 [11]\n"; } # push(@treeStack, $treeCur); @@ -3460,9 +3726,12 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST } my $top = pop(@braceStack); $parserState->{parsedParamParse} = pop(@parsedParamParseStack); - print STDERR "POPPED $top FROM BRACESTACK\n" if ($macroDebug || $braceDebug); - if (!$parserState->{seenBraces}) { # TREEDONE - $treeCur->addSibling($part, 0); $treeSkip = 1; + print STDERR "POPPED $top FROM BRACESTACK [3]\n" if ($macroDebug || $braceDebug); + if ($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces}) { # TREEDONE + my $tempCur = $treeCur->addSibling($part, 0); $treeSkip = 1; + if ($HeaderDoc::includeFunctionContents && $reMark) { + $tempCur->{RE_STATE} = $reMark; + } $treeCur = pop(@treeStack) || $treeTop; $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); $treeCur = $treeCur->lastSibling(); @@ -3484,6 +3753,8 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST if ($inRegexpCharClass != 4) { print STDERR "Leaving character class.\n" if ($localDebug || $parseDebug || $regexpDebug); $inRegexpCharClass = 0; + $reMark = "RE_CCEND"; + if ($reMarkDebug) { print STDERR "REMARK: $reMark\n"; } } } $lastchar = $part; @@ -3505,7 +3776,7 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST last SWITCH; } }; - ($part eq "'") && do { + ($part eq "'" && $lang ne "applescript") && do { print STDERR "SINGLE QUOTE: CASE 24\n" if ($liteDebug); print STDERR "squo\n" if ($localDebug); @@ -3515,7 +3786,7 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST $parserState->{onlyComments} = 0; print STDERR "[h]onlyComments -> 0\n" if ($macroDebug); if (!$parserState->{inChar}) { - if (!$parserState->{seenBraces}) { # TREEDONE + if ($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces}) { # TREEDONE $treeNest = 1; if ($treeDebug) { print STDERR "TS TREENEST -> 1 [12]\n"; } # push(@treeStack, $treeCur); @@ -3523,8 +3794,11 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST # bless($treeCur, "HeaderDoc::ParseTree"); } } else { - if (!$parserState->{seenBraces}) { # TREEDONE - $treeCur->addSibling($part, 0); $treeSkip = 1; + if ($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces}) { # TREEDONE + my $tempCur = $treeCur->addSibling($part, 0); $treeSkip = 1; + if ($HeaderDoc::includeFunctionContents && $reMark) { + $tempCur->{RE_STATE} = $reMark; + } $treeCur = pop(@treeStack) || $treeTop; $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); $treeCur = $treeCur->lastSibling(); @@ -3557,7 +3831,7 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST $parserState->{inInlineComment} = 4; print STDERR "inInlineComment -> 1\n" if ($ilcDebug); $curline = spacefix($curline, $part, $lastchar, $parseTokens{soc}, $parseTokens{eoc}, $parseTokens{ilc}, $parseTokens{ilc_b}); - if (!$parserState->{seenBraces}) { # TREEDONE + if ($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces}) { # TREEDONE $treeNest = 1; if ($treeDebug) { print STDERR "TS TREENEST -> 1 [13]\n"; } @@ -3603,7 +3877,7 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{inString})) { $parserState->{inComment} = 4; $curline = spacefix($curline, $part, $lastchar); - if (!$parserState->{seenBraces}) { + if ($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces}) { $treeNest = 1; if ($treeDebug) { print STDERR "TS TREENEST -> 1 [14]\n"; } # print STDERR "TSPUSH\n" if ($tsDebug || $treeDebug); @@ -3635,12 +3909,19 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST $parserState->{leavingComment} = 1; $curline = spacefix($curline, $part, $lastchar); $ppSkipOneToken = 1; - if (!$parserState->{seenBraces}) { - $treeCur->addSibling($part, 0); $treeSkip = 1; + if ($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces}) { + my $tempCur = $treeCur->addSibling($part, 0); $treeSkip = 1; + if ($HeaderDoc::includeFunctionContents && $reMark) { + $tempCur->{RE_STATE} = $reMark; + } $treeCur = pop(@treeStack) || $treeTop; - $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); + if (!$parserState->{seenBraces}) { + $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); + } $treeCur = $treeCur->lastSibling(); - $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); + if (!$parserState->{seenBraces}) { + $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); + } print STDERR "TSPOP [6]: now $treeCur\n" if ($tsDebug || $treeDebug); bless($treeCur, "HeaderDoc::ParseTree"); } @@ -3791,8 +4072,8 @@ if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POST } push(@parsedParamParseStack, $oldParsedParamParse); push(@braceStack, $part); pbs(@braceStack); - print STDERR "PUSHED $part ONTO BRACESTACK\n" if ($macroDebug || $braceDebug); - if (!$parserState->{seenBraces}) { # TREEDONE + print STDERR "PUSHED $part ONTO BRACESTACK [4]\n" if ($macroDebug || $braceDebug); + if ($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces}) { # TREEDONE $treeNest = 1; if ($treeDebug) { print STDERR "TS TREENEST -> 1 [15]\n"; } # push(@treeStack, $treeCur); @@ -3875,8 +4156,9 @@ print STDERR "SCARYCASE\n" if ($localDebug); print STDERR "OUTGOING CURLINE: \"$curline\"\n" if ($localDebug); last SWITCH; }; - ((($part eq ")" && (!$parserState->{inCase})) || (casecmp($part, $parseTokens{rbrace}, $case_sensitive) && ($parserState->{pendingBracedParameters} == 2)))) && do { + ((($part eq ")" && (!$parserState->{inCase})) || ($parserState->isRightBrace($part, $lang, \%parseTokens, $case_sensitive) && ($parserState->{pendingBracedParameters} == 2)))) && do { print STDERR "CLOSE PAREN: CASE 29\n" if ($liteDebug); + # print STDERR "TOBS: \"".peek(\@braceStack)."\"\n"; print STDERR "TOP OF RE STACK IS: \"".peek(\@regexpStack)."\"\n" if ($localDebug || $parseDebug); if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && ($regexpNoInterpolate || ($inRegexpFirstPart != 1)) && (peek(\@regexpStack) ne "("))) { print STDERR "PAST FIRST CHECK\n" if ($localDebug || $parseDebug); @@ -3913,22 +4195,43 @@ print STDERR "SCARYCASE\n" if ($localDebug); print STDERR "rparen\n" if ($localDebug); - my $test = pop(@braceStack); pbs(@braceStack); - $parserState->{parsedParamParse} = pop(@parsedParamParseStack); - print STDERR "POPPED $test FROM BRACESTACK\n" if ($macroDebug || $braceDebug); - if (!$parserState->{seenBraces}) { # TREEDONE - $treeCur->addSibling($part, 0); $treeSkip = 1; + my $test = ""; + my $parenRegexp = 0; + # If the first node in the regexp stack is + # an open parenthesis, it isn't on the + # brace stack, so don't pop it off. + if ($inRegexp && ($regexpStack[0] eq "(")) { + $parenRegexp = 0; + } + if (!$parenRegexp) { + $test = pop(@braceStack); pbs(@braceStack); + $parserState->{parsedParamParse} = pop(@parsedParamParseStack); + print STDERR "POPPED $test FROM BRACESTACK [4]\n" if ($macroDebug || $braceDebug); + } + + print STDERR "RPAREN SEENBRACES: ".$parserState->{seenBraces}."\n" if ($localDebug || $parserStateInsertDebug); + if ($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces}) { # TREEDONE + my $tempCur = $treeCur->addSibling($part, 0); $treeSkip = 1; + if ($HeaderDoc::includeFunctionContents && $reMark) { + $tempCur->{RE_STATE} = $reMark; + } $treeCur = pop(@treeStack) || $treeTop; - $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); + if (!$parserState->{seenBraces}) { + $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); + } $treeCur = $treeCur->lastSibling(); - $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); + if (!$parserState->{seenBraces}) { + $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); + } print STDERR "TSPOP [6a]: now $treeCur\n" if ($tsDebug || $treeDebug); bless($treeCur, "HeaderDoc::ParseTree"); } - if (!($test eq $opentoken)) { - warn("$fullpath:$inputCounter: warning: Parentheses do not match.\nWe may have a problem.\n"); - warn("Declaration to date: $declaration$curline\n"); - # cluck("backtrace follows\n"); + if (!$parenRegexp) { + if (!($test eq $opentoken)) { + warn("$fullpath:$inputCounter: warning: Parentheses do not match.\nWe may have a problem.\n"); + warn("Declaration to date: $declaration$curline\n"); + # cluck("backtrace follows\n"); + } } $curline = spacefix($curline, $part, $lastchar); $parserState->{lastsymbol} = ""; @@ -3957,8 +4260,7 @@ print STDERR "SCARYCASE\n" if ($localDebug); } } }; - (($lang ne "perl" || !($parserState->{inTemplate} || $inRegexp || $leavingRegexp)) && $parserState->isLeftBrace($part, $lang, $parseTokens{lbrace}, $parseTokens{lbraceunconditionalre}, $parseTokens{lbraceconditionalre}, - $parseTokens{classisbrace}, $parseTokens{functionisbrace}, $case_sensitive, scalar(@braceStack))) && do { + (($lang ne "perl" || !($parserState->{inTemplate} || $inRegexp || $leavingRegexp)) && $parserState->isLeftBrace($part, $lang, \%parseTokens, $case_sensitive, scalar(@braceStack))) && do { my $brctoken = $part; print STDERR "IRC ".$parserState->{inRubyClass}."\n" if ($rubyDebug || $parseDebug); @@ -3973,7 +4275,11 @@ print STDERR "SCARYCASE\n" if ($localDebug); my $oldParsedParamParse = $parserState->{parsedParamParse}; print STDERR "LEFT BRACE: CASE 30\n" if ($liteDebug); - if ($parserState->{onlyComments} && !$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inChar} && !$inRegexp && !scalar(@parserStack) && !$parserState->{INIF} && !$tempInIf) { + if ($lang eq "applescript" && $pushParserStateAtBrace) { + $pushParserStateAtBrace = 0; + $pushParserStateAfterToken = 1; + } + if ($parserState->{onlyComments} && !$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inChar} && !$inRegexp && !scalar(@parserStack) && !$parserState->{INIF} && !$tempInIf && ($lang ne "applescript")) { print STDERR "BAILING NOW\n" if ($externCDebug); $continue_no_return = 1; print STDERR "CONTINUE -> 0 [NORETURN]\n" if ($parseDebug || $cppDebug || $macroDebug || $localDebug || $continueDebug); @@ -3984,7 +4290,7 @@ print STDERR "SCARYCASE\n" if ($localDebug); print STDERR "PUSHING \"$parsedParam\" onto parsed parameters list ()\n" if ($parseDebug || $asDebug); $parsedParam = ""; } - if ($parserState->{onlyComments} && !$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inChar} && !$inRegexp && scalar(@parserStack)) { + if ($parserState->{onlyComments} && !$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inChar} && !$inRegexp && scalar(@parserStack) && $lang ne "applescript") { # Somebody put in a brace in the middle of # a class or else we're seeing ObjC private # class bits. Either way, throw away the @@ -4001,6 +4307,10 @@ print STDERR "SCARYCASE\n" if ($localDebug); print STDERR "bracePending -> 0 [brace]\n" if ($localDebug); $parserState->{onlyComments} = 0; print STDERR "[k]onlyComments -> 0\n" if ($macroDebug); + + push(@{$parserState->{parsedParamStateAtBrace}}, $parserState->{parsedParamParse}); + push(@{$parserState->{parsedParamAtBrace}}, $parsedParam); + $parsedParam = ""; if (scalar(@{$parserState->{parsedParamList}})) { foreach my $node (@{$parserState->{parsedParamList}}) { $node =~ s/^\s*//so; @@ -4046,8 +4356,8 @@ print STDERR "SCARYCASE\n" if ($localDebug); push(@parsedParamParseStack, $oldParsedParamParse); push(@braceStack, $brctoken); pbs(@braceStack); - print STDERR "PUSHED $brctoken ONTO BRACESTACK\n" if ($macroDebug || $braceDebug); - if (!$parserState->{seenBraces}) { # TREEDONE + print STDERR "PUSHED $brctoken ONTO BRACESTACK [5]\n" if ($macroDebug || $braceDebug); + if ($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces}) { # TREEDONE $treeNest = 1; if ($treeDebug) { print STDERR "TS TREENEST -> 1 [16]\n"; } print STDERR "TN -> 1\n" if ($localDebug); @@ -4078,9 +4388,10 @@ print STDERR "SCARYCASE\n" if ($localDebug); } last SWITCH; }; - (casecmp($part, $parseTokens{rbrace}, $case_sensitive) && ($parserState->{pendingBracedParameters} != 2) && ($lang ne "perl" || !($parserState->{inTemplate} || $inRegexp || $leavingRegexp))) && do { + (($parserState->isRightBrace($part, $lang, \%parseTokens, $case_sensitive) || $parserState->{inrbraceargument}) && ($parserState->{pendingBracedParameters} != 2) && ($lang ne "perl" || !($parserState->{inTemplate} || $inRegexp || $leavingRegexp))) && do { # {Treat } within <> as ordinary character in Perl. print STDERR "RIGHT BRACE: CASE 31\n" if ($liteDebug); + print STDERR "INBRACEARGUMENT: ".$parserState->{inrbraceargument}."\n" if ($parserStateInsertDebug); if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $inRegexp)) { my $oldOC = $parserState->{onlyComments}; @@ -4090,13 +4401,29 @@ print STDERR "SCARYCASE\n" if ($localDebug); print STDERR "[l]onlyComments -> 0\n" if ($macroDebug); if ($ruby) { $parserState->{followingrubyrbrace} = 1; } + if (($parseTokens{rbracetakesargument}) && (!$parserState->{inrbraceargument})) { + $parserState->{inrbraceargument} = 1; + # $treePopOnNewLine = 1; + # $parserState->{newlineIsSemi} = 1; + } elsif ($parserState->{inrbraceargument} && $part =~ /\w/) { + $parserState->{inrbraceargument}--; + if ($parserState->{seenBraces}) { $trailingHide = 1; } + } - my $bsCount = scalar(@braceStack); + if ($parserState->{inrbraceargument}) { + print STDERR "Waiting for rbrace argument\n" if ($asDebug || $parserStackDebug || $parseDebug || $braceDebug); + } else { + print STDERR "INRBRACEARGUMENT: ".$parserState->{inrbraceargument}."\n" if ($asDebug || $parserStackDebug || $parseDebug || $braceDebug); + + my $bsCount = scalar(@braceStack); - print STDERR "SPS: ".scalar(@parserStack)." BSC: ".$bsCount." IBSC: ".$parserState->{initbsCount}."\n" if ($rubyDebug || $parseDebug); - if (scalar(@parserStack) && !($bsCount - $parserState->{initbsCount})) { + print STDERR "SPS: ".scalar(@parserStack)." BSC: ".$bsCount." IBSC: ".$parserState->{initbsCount}."\n" if ($rubyDebug || $parseDebug); + if (scalar(@parserStack) && !($bsCount - $parserState->{initbsCount})) { print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug); - if ($parserState->{noInsert} || $oldOC) { + if ($parserState->{inrbraceargument}) { + print STDERR "parserState insertion skipped[RBRACE, INARG]\n" if ($parserStackDebug || $parserStateInsertDebug); + # $parserState->{newlineIsSemi} = 1; # @@@ THIS ISN'T RIGHT. + } elsif ($parserState->{noInsert} || $oldOC) { print STDERR "parserState insertion skipped[RBRACE]\n" if ($parserStackDebug || $parserStateInsertDebug); } elsif ($parserState->{hollow}) { print STDERR "inserted parser state into tree [RBRACE]\n" if ($parserStateInsertDebug); @@ -4127,7 +4454,7 @@ print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug); $part = ""; print STDERR "INMODULE -> 3\n" if ($localDebug || $moduleDebug); $parserState->{INMODULE} = 3; - print STDERR "CONTINUE -> 0 [1a]\n" if ($parseDebug || $cppDebug || $macroDebug || $localDebug || $continueDebug); + print STDERR "CONTINUE -> 0 [1aMODULE]\n" if ($parseDebug || $cppDebug || $macroDebug || $localDebug || $continueDebug); $parserState->{noInsert} = 0; $continue = 0; # print STDERR "AT END: REALPS IS ".$parserState->{REALPS}."\n" if ($parserStackDebug || $localDebug); @@ -4136,13 +4463,18 @@ print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug); # print STDERR "HERE\n"; - if ($lang eq "php" || ($lang eq "C" && $sublang eq "IDL") || ($lang eq "java" && $sublang eq "java") || $ruby || ($lang eq "tcl")) { + if ($lang eq "php" || ($lang eq "C" && $sublang eq "IDL") || ($lang eq "java" && $sublang eq "java") || $ruby || ($lang eq "tcl") || ($lang eq "applescript")) { # print STDERR "PHP OUT OF BRACES?: ".scalar(@braceStack)."\n"; if (scalar(@braceStack) == 1) { # PHP, IDL, Ruby, TCL, and Java classes end at # the brace. - print STDERR "CONTINUE -> 0 [1a]\n" if ($parseDebug || $cppDebug || $macroDebug || $localDebug || $continueDebug); + print STDERR "CONTINUE -> 0 [1aOutOfBraces]\n" if ($parseDebug || $cppDebug || $macroDebug || $localDebug || $continueDebug); $continue = 0; + } elsif ($lang eq "applescript" && (scalar(@braceStack)-$parserState->{initbsCount}) == 1) { + # AppleScript allows nested classes and does not have a semicolon to + # indicate the point at which we should stop parsing a class. + print STDERR "Terminating nested class at newline.\n" if ($localDebug || $parseDebug || $asDebug); # @@@ + $parserState->{declarationEndsAtNewLine} = 1; } } if ($parserState->{noInsert} && scalar(@parserStack)) { @@ -4157,12 +4489,12 @@ print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug); $parserState->{initbsCount} = scalar(@braceStack) - 1; } # $parserState->{onlyComments} = 1; - } else { + } else { print STDERR "NO CHANGE IN PARSER STATE STACK (nPARSERSTACK = ".scalar(@parserStack).", $bsCount != $parserState->{initbsCount})\n" if ($parseDebug || $parserStackDebug); - } + } - print STDERR "Ruby stopcheck: ".scalar(@braceStack)." - ".$parserState->{initbsCount}."\n" if ($rubyDebug || $parseDebug); - if ((scalar(@braceStack)-$parserState->{initbsCount}) == 1) { + print STDERR "Ruby stopcheck: ".scalar(@braceStack)." - ".$parserState->{initbsCount}."\n" if ($rubyDebug || $parseDebug); + if ((scalar(@braceStack)-$parserState->{initbsCount}) == 1) { # stop parameter parsing if ($ruby) { print STDERR "Ruby stopearly: ".scalar(@braceStack)." - ".$parserState->{initbsCount}."\n" if ($rubyDebug || $parseDebug);; @@ -4185,14 +4517,15 @@ print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug); # } else { # print STDERR "checkpoint SC: ".$parserState->{sodclass}."\n"; # } - } else { + } else { # start parameter parsing after this token # grabbing end names for typedefs. - $parserState->{parsedParamParse} = 4; + $parserState->{parsedParamParse} = pop(@{$parserState->{parsedParamStateAtBrace}}); # 4; + $parsedParam = pop(@{$parserState->{parsedParamAtBrace}}); print STDERR "parsedParamParse -> $parserState->{parsedParamParse}"."[rbrace2]\n" if ($parmDebug); - } + } - if (scalar(@{$parserState->{parsedParamList}})) { + if (scalar(@{$parserState->{parsedParamList}})) { foreach my $node (@{$parserState->{parsedParamList}}) { $node =~ s/^\s*//so; $node =~ s/\s*$//so; @@ -4202,13 +4535,13 @@ print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug); } @{$parserState->{parsedParamList}} = (); print STDERR "parsedParamList pushed [3]\n" if ($parmDebug); - } + } - print STDERR "rbrace\n" if ($localDebug); + print STDERR "rbrace\n" if ($localDebug); - my $test = pop(@braceStack); pbs(@braceStack); - my $temp = pop(@parsedParamParseStack); - if ($temp) { + my $test = pop(@braceStack); pbs(@braceStack); + my $temp = pop(@parsedParamParseStack); + if ($temp) { if ($temp == 1) { $temp = 2; } elsif ($temp == 3) { $temp = 4; } @@ -4216,35 +4549,44 @@ print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug); warn("Changing PPP from ".$parserState->{parsedParamParse}." to $temp\n"); } $parserState->{parsedParamParse} = $temp; - } - print STDERR "POPPED $test FROM BRACESTACK\n" if ($macroDebug || $braceDebug); - if (!$parserState->{seenBraces}) { # TREEDONE - $treeCur->addSibling($part, 0); $treeSkip = 1; + } + print STDERR "POPPED $test FROM BRACESTACK [5]\n" if ($macroDebug || $braceDebug); + if (($HeaderDoc::includeFunctionContents || !($parserState->{seenBraces} || $trailingHide)) && (!$parserState->{inrbraceargument})) { # TREEDONE + warn("TSPOP FOR NOT SEEN BRACES\n") if ($parserStateInsertDebug || $treeDebug); + my $tempCur = $treeCur->addSibling($part, 0); $treeSkip = 1; + if ($HeaderDoc::includeFunctionContents && $reMark) { + $tempCur->{RE_STATE} = $reMark; + } $treeCur = pop(@treeStack) || $treeTop; - $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); + if (!($parserState->{seenBraces} || $trailingHide)) { + $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); + } $treeCur = $treeCur->lastSibling(); - $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); + if (!($parserState->{seenBraces} || $trailingHide)) { + $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); + } print STDERR "TSPOP [7]: now $treeCur\n" if ($tsDebug || $treeDebug); bless($treeCur, "HeaderDoc::ParseTree"); - } - if (!($test eq "$parseTokens{lbrace}") && (!length($parseTokens{structname}) || (!($test eq $parseTokens{structname}) && $parseTokens{structisbrace}))) { + } + if (!($test eq "$parseTokens{lbrace}") && (!length($parseTokens{structname}) || (!($test eq $parseTokens{structname}) && $parseTokens{structisbrace}))) { warn("$fullpath:$inputCounter: warning: Braces do not match (top of brace stack\nis \"$test\").We may have a problem.\n"); warn("Declaration to date: $declaration$curline\n"); - } - $curline = spacefix($curline, $part, $lastchar); - $parserState->{lastsymbol} = ""; - $lastchar = $part; + } + $curline = spacefix($curline, $part, $lastchar); + $parserState->{lastsymbol} = ""; + $lastchar = $part; - $parserState->{startOfDec} = 0; - print STDERR "startOfDec -> 0 [6]\n" if ($localDebug); - if ($curline !~ /\S/o) { + $parserState->{startOfDec} = 0; + print STDERR "startOfDec -> 0 [6]\n" if ($localDebug); + if ($curline !~ /\S/o) { # This is the first symbol on the line. # adjust immediately $prespace -= 4; print STDERR "PS: $prespace immediate\n" if ($localDebug); - } else { + } else { $prespaceadjust -= 4; print STDERR "PSA: $prespaceadjust\n" if ($localDebug); + } } } last SWITCH; @@ -4304,8 +4646,11 @@ print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug); $parserState->{seenBraces} = 1; my $temp = pop(@braceStack); $parserState->{parsedParamParse} = pop(@parsedParamParseStack); - print STDERR "POPPED $temp FROM BRACESTACK\n" if ($macroDebug || $braceDebug); - $treeCur->addSibling($part, 0); $treeSkip = 1; + print STDERR "POPPED $temp FROM BRACESTACK [6]\n" if ($macroDebug || $braceDebug); + my $tempCur = $treeCur->addSibling($part, 0); $treeSkip = 1; + if ($HeaderDoc::includeFunctionContents && $reMark) { + $tempCur->{RE_STATE} = $reMark; + } $treeCur = pop(@treeStack) || $treeTop; $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); $treeCur = $treeCur->lastSibling(); @@ -4378,11 +4723,13 @@ print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug); $parserState->{pendingBracedParameters} = 1; } + print STDERR "INCLASSCHECK AFTERNL: ".$parserState->{afterNL}."\n" if ($parseDebug); + my $localclasstype = $1; if ($part =~ /^\@/) { $part =~ s/^\@//s; } - if (!(scalar(@braceStack)-$parserState->{initbsCount})) { - if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) { - print STDERR "ITISACLASS\n" if ($localDebug); + if ((($lang eq "applescript") && $parserState->{afterNL}) || (($lang ne "applescript") && !(scalar(@braceStack)-$parserState->{initbsCount}))) { + if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || ($parserState->{inChar} && $lang ne "applescript"))) { + print STDERR "ITISACLASS\n" if ($localDebug || $classDebug); if (!length($parserState->{sodclass}) && !$parserState->{inTypedef}) { print STDERR "GOOD.\n" if ($localDebug); $parserState->{inClass} = 1; @@ -4424,7 +4771,7 @@ print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug); print STDERR "CLASS ($localclasstype) IS A BRACE.\n" if ($localDebug); push(@parsedParamParseStack, $parserState->{parsedParamParse}); push(@braceStack, $localclasstype); pbs(@braceStack); - print STDERR "PUSHED $localclasstype ONTO BRACESTACK\n" if ($macroDebug || $braceDebug); + print STDERR "PUSHED $localclasstype ONTO BRACESTACK [6]\n" if ($macroDebug || $braceDebug); $treeNest = 1; if ($treeDebug) { print STDERR "TS TREENEST -> 1 [17]\n"; } # } else { @@ -4457,6 +4804,12 @@ print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug); # $macrore = macroRegexpFromList($parseTokens{macronames}); $macrore_pound = macroRegexpFromList($parseTokens{macronames}, 1); $macrore_nopound = macroRegexpFromList($parseTokens{macronames}, 2); + $regexppattern = $parseTokens{regexppattern}; + $singleregexppattern = $parseTokens{singleregexppattern}; + $regexpfirstcharpattern = $parseTokens{regexpfirstcharpattern}; + $regexpcharpattern = $parseTokens{regexpcharpattern}; + $regexpAllowedAfter = $parseTokens{regexpAllowedAfter}; + $TCLregexpcommand = $parseTokens{TCLregexpcommand}; print STDERR "ARP: $accessregexp\n" if ($localDebug); @@ -4466,6 +4819,8 @@ print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug); $HeaderDoc::lang = $lang; $HeaderDoc::sublang = $sublang; + # print STDERR "ELSE CASE: $lang $sublang\n"; + # ($parseTokens{sotemplate}, $parseTokens{eotemplate}, $parseTokens{operator}, $parseTokens{soc}, $parseTokens{eoc}, $parseTokens{ilc}, $parseTokens{ilc_b}, $parseTokens{sofunction}, # $parseTokens{soprocedure}, $parseTokens{sopreproc}, $parseTokens{lbrace}, $parseTokens{rbrace}, $parseTokens{unionname}, $parseTokens{structname}, # $parseTokens{enumname}, @@ -4486,11 +4841,19 @@ print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug); # $macrore = macroRegexpFromList($parseTokens{macronames}); $macrore_pound = macroRegexpFromList($parseTokens{macronames}, 1); $macrore_nopound = macroRegexpFromList($parseTokens{macronames}, 2); + $regexppattern = $parseTokens{regexppattern}; + $singleregexppattern = $parseTokens{singleregexppattern}; + $regexpfirstcharpattern = $parseTokens{regexpfirstcharpattern}; + $regexpcharpattern = $parseTokens{regexpcharpattern}; + $regexpAllowedAfter = $parseTokens{regexpAllowedAfter}; + $TCLregexpcommand = $parseTokens{TCLregexpcommand}; print STDERR "ARP: $accessregexp\n" if ($localDebug); last SWITCH; } + } else { + print STDERR "STR: ".$parserState->{inString}." COM: ".$parserState->{inComment}." ILC: ".$parserState->{inInlineComment}." CHAR: ".$parserState->{inChar}." LANG: ".$lang."\n"; } } }; @@ -4538,8 +4901,8 @@ print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug); push(@parsedParamParseStack, $parserState->{parsedParamParse}); push(@braceStack, $part); pbs(@braceStack); - print STDERR "PUSHED $part ONTO BRACESTACK\n" if ($macroDebug || $braceDebug); - if (!$parserState->{seenBraces}) { # TREEDONE + print STDERR "PUSHED $part ONTO BRACESTACK [7]\n" if ($macroDebug || $braceDebug); + if ($HeaderDoc::includeFunctionContents || !($parserState->{seenBraces} || $trailingHide)) { # TREEDONE $treeNest = 1; if ($treeDebug) { print STDERR "TS TREENEST -> 1 [18]\n"; } # push(@treeStack, $treeCur); @@ -4566,7 +4929,7 @@ print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug); print STDERR "simpleTypedef -> 2\n" if ($localDebug); $parserState->{simpleTypedef} = 2; } - # if (!$parserState->{seenBraces}) { # TREEDONE + # if ($HeaderDoc::includeFunctionContents || !$parserState->{seenBraces}) { # TREEDONE # $treePopTwo++; # $treeNest = 1; # push(@treeStack, $treeCur); @@ -4655,6 +5018,7 @@ print STDERR "sodname cleared ($parseTokens{typedefname})\n" if ($sodDebug); # Punctuation handlers ($part =~ /;/o || ($parserState->{newlineIsSemi} && (!$parserState->isQuoted($lang, $sublang)) && $part =~ /[\n\r]/)) && do { + # semicolon handler. print STDERR "SEMICOLON: CASE 39\n" if ($liteDebug); if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) { if ($lang eq "shell") { @@ -4664,6 +5028,9 @@ print STDERR "sodname cleared ($parseTokens{typedefname})\n" if ($sodDebug); $parserState->{afterSemi} = 1; } } + if ($parserState->{inTCLRegExpCommand}) { + $parserState->{inTCLRegExpCommand} = 0; + } print STDERR "NOT IN STRING, CHAR, COMMENT, etc.\n" if ($localDebug); if ($parserState->{parsedParamParse}) { print STDERR "PPP IS $parserState->{parsedParamParse}.\n" if ($localDebug); @@ -4704,6 +5071,7 @@ print STDERR "sodname cleared ($parseTokens{typedefname})\n" if ($sodDebug); my $bsCount = scalar(@braceStack)-$parserState->{initbsCount}; print STDERR "INHERE BSC $bsCount\n" if ($rubyDebug || $parseDebug); + # print STDERR "KRC: ".$parserState->{kr_c_function}."\n"; if (!$bsCount && !$parserState->{kr_c_function}) { if ($parserState->{startOfDec} == 2 && !$pascal) { @@ -4722,6 +5090,9 @@ print STDERR "sodname cleared ($parseTokens{typedefname})\n" if ($sodDebug); if (!$bsCount) { print STDERR "HERE BSC: $bsCount\n" if ($rubyDebug || $parseDebug); $treeCur = $treeCur->addSibling($part); $treepart = " "; # $treeSkip = 1; + if ($HeaderDoc::includeFunctionContents && $reMark) { + $treeCur->{RE_STATE} = $reMark; + } if (0) { $treeCur = pop(@treeStack) || $treeTop; $treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}}, $lang, $sublang); @@ -4857,6 +5228,7 @@ if (0) { }; # end if }; # end do ($part =~ /[*^]/) && do { + print STDERR "PUNCTUATION: CASE 41A\n" if ($liteDebug); if ($part =~ /[*]/) { $parserState->{curvarstars} .= $part; } if ($lastnspart eq "(" && # ")" !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && @@ -5143,7 +5515,7 @@ if (0) { # Note: don't check tempInIf here. We want the open brace included because # the close brace is included. - if ($parserState->{seenBraces} && ($parserState->{INIF} != 1)) { + if (($parserState->{seenBraces} || $trailingHide) && !$HeaderDoc::includeFunctionContents && ($parserState->{INIF} != 1)) { # print STDERR "SEENBRACES. TP: $treepart PT: $part\n"; if ($treepart) { print STDERR "ADDED \"$treepart\" to function contents\n" if ($functionContentsDebug); @@ -5153,7 +5525,7 @@ if (0) { $parserState->{functionContents} .= $part; } # print STDERR "SEENBRACES. FC: ".$parserState->{functionContents}."\n"; - } elsif ($parserState->{seenBraces}) { + } elsif (($parserState->{seenBraces} || $trailingHide) && !$HeaderDoc::includeFunctionContents) { print STDERR "NOT ADDING \"$part\" to function contents (INIF: ".$parserState->{INIF}." TEMPINIF: $tempInIf\n" if ($functionContentsDebug); } else { print STDERR "NOT ADDING \"$part\" to function contents (!seenBraces)\n" if ($functionContentsDebug); @@ -5190,7 +5562,7 @@ if (0) { print STDERR "TN: $treeNest TS: $treeSkip nTS: ".scalar(@treeStack)."\n" if ($tsDebug || $parserStateInsertDebug); print STDERR "sethollow: $sethollow\n" if ($parserStateInsertDebug); if (!$treeSkip) { - if (!$parserState->{seenBraces}) { # TREEDONE + if ($HeaderDoc::includeFunctionContents || !($parserState->{seenBraces} || $trailingHide)) { # TREEDONE if ($treeNest != 2) { # If we really want to skip and nest, set treeNest to 2. if (length($treepart)) { @@ -5199,6 +5571,9 @@ if (0) { # print STDERR "SHORT\n"; } else { $treeCur = $treeCur->addSibling($treepart, $hide); + if ($HeaderDoc::includeFunctionContents && $reMark) { + $treeCur->{RE_STATE} = $reMark; + } } $treepart = ""; } else { @@ -5207,6 +5582,9 @@ if (0) { # print STDERR "SHORT\n"; } else { $treeCur = $treeCur->addSibling($part, $hide); + if ($HeaderDoc::includeFunctionContents && $reMark) { + $treeCur->{RE_STATE} = $reMark; + } } } bless($treeCur, "HeaderDoc::ParseTree"); @@ -5264,6 +5642,8 @@ if (0) { print STDERR "REPLACING RETURNTYPE[3]: NOW \"$parserState->{returntype}\".\n" if ($retDebug); } + print STDERR "AT MIDPOINT, TREECUR IS $treeCur (".$treeCur->token().")\n" if ($localDebug || $parserStateInsertDebug); + # From here down is... magic. This is where we figure out how # to handle parsed parameters, K&R C types, and in general, # determine whether we've received a complete declaration or not. @@ -5294,7 +5674,7 @@ if (0) { } $ppSkipOneToken = 0; print STDERR "MIDPOINT CL: $curline\nDEC:$declaration\nSCR: \"$scratch\"\n" if ($localDebug); - if (!$parserState->{seenBraces}) { + if ($HeaderDoc::includeFunctionContents || !($parserState->{seenBraces} || $trailingHide)) { # Add to current line (but don't put inline function/macro # declarations in. @@ -5401,9 +5781,9 @@ if (0) { print STDERR "CURLINE IS \"$curline\".\n" if ($localDebug); my $bsCount = scalar(@braceStack); - print STDERR "ENDTEST: $bsCount \"$parserState->{lastsymbol}\"\n" if ($localDebug); - print STDERR "KRC: $parserState->{kr_c_function} SB: $parserState->{seenBraces}\n" if ($localDebug); - print STDERR "DEANL: ".$parserState->{declarationEndsAtNewLine}." PART: \"$treepart\"\n" if ($parseDebug || $asDebug); + print STDERR "ENDTEST: $bsCount \"$parserState->{lastsymbol}\"\n" if ($localDebug || $continueDebug); + print STDERR "KRC: $parserState->{kr_c_function} SB: $parserState->{seenBraces}\n" if ($localDebug || $continueDebug); + print STDERR "DEANL: ".$parserState->{declarationEndsAtNewLine}." PART: \"$treepart\"\n" if ($parseDebug || $asDebug || $continueDebug); if (!($bsCount - $parserState->{initbsCount}) && ($parserState->{lastsymbol} =~ /;\s*$/o || ($parserState->{declarationEndsAtNewLine} && $partIsNL))) { if ($parserState->{declarationEndsAtNewLine} && $partIsNL) { print STDERR "CREATING NEW PARSER STATE NOW.\n" if ($parseDebug || $asDebug); @@ -5411,7 +5791,7 @@ if (0) { } # print STDERR "DPA\n"; if ((!$parserState->{kr_c_function} || $parserState->{seenBraces}) && !$parserState->{inMacro}) { - print STDERR "DPB\n" if ($parserStateInsertDebug); + print STDERR "DPB\n" if ($parserStateInsertDebug || $continueDebug); if (!scalar(@parserStack)) { $continue = 0; print STDERR "CONTINUE -> 0 [3]\n" if ($parseDebug || $cppDebug || $macroDebug || $localDebug || $continueDebug); @@ -5454,12 +5834,12 @@ if (0) { } # print STDERR "BSCOUNT: $bsCount IBS: $parserState->{initbsCount}\n"; - if (!($bsCount - $parserState->{initbsCount}) && $parserState->{seenBraces} && ($parserState->{sodclass} eq "function" || $parserState->{inOperator}) && + if (!($bsCount - $parserState->{initbsCount}) && ($parserState->{seenBraces} || $trailingHide) && ($parserState->{sodclass} eq "function" || $parserState->{inOperator}) && ($nextpart ne ";")) { # Function declarations end at the close curly brace. # No ';' necessary (though we'll eat it if it's there. - if ($parserState->{treePopTwo} || $ruby) { + if ($parserState->{treePopTwo} || $ruby || $parseTokens{functionisbrace}) { # Fix nesting. # print STDERR "LASTTREENODE -> $treeCur (".$treeCur->token().")\n"; while ($parserState->{treePopTwo}--) { @@ -5470,11 +5850,14 @@ if (0) { print STDERR "TSPOP [13]: now $treeCur\n" if ($tsDebug || $treeDebug); bless($treeCur, "HeaderDoc::ParseTree"); } - if ($ruby) { + if ($ruby || $parseTokens{functionisbrace}) { $treeCur = $treeCur->addSibling("", 0); } else { $treeCur = $treeCur->addSibling(";", 0); } + if ($HeaderDoc::includeFunctionContents && $reMark) { + $treeCur->{RE_STATE} = $reMark; + } print STDERR "parser state lastTreeNode reset [treePopTwo]\n" if ($parserStateInsertDebug); print STDERR "Last tree node set to $treeCur [8]\n" if ($parserStateInsertDebug); $parserState->{lastTreeNode} = $treeCur; @@ -5485,6 +5868,8 @@ if (0) { if (!scalar(@parserStack) && !$parserState->{INIF} && !$tempInIf) { $continue = 0; print STDERR "CONTINUE -> 0 [4]\n" if ($parseDebug || $cppDebug || $macroDebug || $localDebug || $continueDebug); + } elsif ($parserState->{inrbraceargument}) { + print STDERR "parserState insertion skipped[inrbraceargument]\n" if ($parserStackDebug); } elsif (!$parserState->{onlyComments} && !$parserState->{INIF} && !$tempInIf) { # Process entry here if ($parserState->{noInsert}) { @@ -5493,7 +5878,7 @@ if (0) { my $treeRef = $parserState->{hollow}; print STDERR "inserted parser state into tree [rbrace]\nEOD: $treeCur\n" if ($parserStateInsertDebug); - print STDERR "Last tree node set to $treeCur [9]\n" if ($parserStateInsertDebug); + print STDERR "Last tree node set to $treeCur [9] (token: \"".$treeCur->token()."\")\n" if ($parserStateInsertDebug); $parserState->{lastTreeNode} = $treeCur; $treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}}); $treeRef->parserState($parserState); @@ -5578,9 +5963,33 @@ if (0) { print STDERR "OOGABOOGA\n" if ($parserStackDebug); if ($pushParserStateAfterToken == 1) { + if ($parserState->{inClass}) { configureAccessControlStateForClass($parserState); } print STDERR "parserState pushed onto stack[token]\n" if ($parserStackDebug); print STDERR "Last tree node set to $treeCur [11]\n" if ($parserStateInsertDebug); $parserState->{lastTreeNode} = $treeCur; + if ($lang eq "applescript") { + # AppleScript needs a little help because functions can contain other things. + if (!$parserState->{lastDisplayNode}) { + $parserState->{lastDisplayNode} = $treeCur; + } + if (!$treeTop->{lastDisplayNode}) { + $treeTop->{lastDisplayNode} = $treeCur; + } + if (!$parserState->{lastDisplayNode}) { + $parserState->{lastDisplayNode} = $treeCur; + } + if (!$treeTop->{lastDisplayNode}) { + $treeTop->{lastDisplayNode} = $treeCur; + } + + # print STDERR "CUR: $treeCur\n"; + # print STDERR "FOR PS: $parserState\n"; + # $treeCur->dbprint(); + # print STDERR "TOP:\n"; + # $treeTop->dbprint(); + # print STDERR "SET TN: $treeTop\n"; + # print STDERR "TTLDN: ".$treeTop->{lastDisplayNode}."\n"; + } $curline = ""; $parserState->{storeDec} = $declaration; $parserState->{freezereturn} = 1; @@ -5596,6 +6005,8 @@ if (0) { if ($part =~ /\w/) { print STDERR "parserState pushed onto stack[word]\n" if ($parserStackDebug); print STDERR "Last tree node set to $treeCur [12]\n" if ($parserStateInsertDebug); + + if ($parserState->{inClass}) { configureAccessControlStateForClass($parserState); } $parserState->{lastTreeNode} = $treeCur; $curline = ""; $parserState->{storeDec} = $declaration; @@ -5617,12 +6028,14 @@ if (0) { # if (casecmp($part, $parseTokens{lbrace}, $case_sensitive)) - print STDERR "check: ".$parserState->isLeftBrace($part, $lang, $parseTokens{lbrace}, $parseTokens{lbraceunconditionalre}, $parseTokens{lbraceconditionalre}, $parseTokens{classisbrace}, $parseTokens{functionisbrace}, $case_sensitive, scalar(@braceStack))."\n" if ($rubyDebug || $parseDebug); + print STDERR "check: ".$parserState->isLeftBrace($part, $lang, \%parseTokens, $case_sensitive, scalar(@braceStack))."\n" if ($rubyDebug || $parseDebug || $HeaderDoc::AppleScriptDebug); - if ($parserState->isLeftBrace($part, $lang, $parseTokens{lbrace}, $parseTokens{lbraceunconditionalre}, $parseTokens{lbraceconditionalre}, - $parseTokens{classisbrace}, $parseTokens{functionisbrace}, $case_sensitive, scalar(@braceStack))) { + if ($parserState->isLeftBrace($part, $lang, \%parseTokens, $case_sensitive, scalar(@braceStack))) { if ($part =~ /[\n\r]/) { $parserState->{inRubyClass} = 2; } $parserState->{ISFORWARDDECLARATION} = 0; + + if ($parserState->{inClass}) { configureAccessControlStateForClass($parserState); } + print STDERR "parserState pushed onto stack[brace]\n" if ($parserStackDebug); # if ($pushParserStateAtBrace == 2) { # print STDERR "NOINSERT parserState: $parserState\n" if ($parserStackDebug); @@ -5661,7 +6074,7 @@ if (0) { if ($tok =~ /\S/) { print STDERR "parserState: PS IS $parserState\n" if ($parserStackDebug); print STDERR "parserState: NOT WHITESPACE : ".$parserState->{hollow}." -> $treeCur\n" if ($parserStackDebug); - if (!casecmp($tok, $parseTokens{rbrace}, $case_sensitive) && $part !~ /\)/) { + if (!$parserState->isRightBrace($tok, $lang, \%parseTokens, $case_sensitive) && $part !~ /\)/) { # $parserState->{hollow} = $treeCur; $parserState->setHollowWithLineNumbers($treeCur, $fileoffset, $inputCounter); # $HeaderDoc::curParserState = $parserState; @@ -5683,7 +6096,7 @@ if (0) { if ($tok =~ /\S/) { print STDERR "parserState: PS IS $parserState\n" if ($parserStackDebug); print STDERR "parserState: NOT WHITESPACE : ".$parserState->{hollow}." -> $treeCur\n" if ($parserStackDebug); - if (!casecmp($tok, $parseTokens{rbrace}, $case_sensitive) && $part !~ /\)/) { + if (!$parserState->isRightBrace($tok, $lang, \%parseTokens, $case_sensitive) && $part !~ /\)/) { $parserState->setHollowWithLineNumbers($treeCur, $fileoffset, $inputCounter); # $HeaderDoc::curParserState = $parserState; print STDERR "parserState: WILL INSERT STATE $parserState (HOLLOW-AUTO-2) AT TOKEN \"$part\"/\"".$treeCur->token()."\"\n" if ($parserStackDebug); @@ -5921,6 +6334,7 @@ sub blockParseReturnState my $nameObjDumpDebug = 0; # $forcedebug = 1; + if ($forcedebug) { $parserState->dbprint(); } if ($forcedebug) { $treeTop->dbprint(); } $forcedebug = $forcedebug || $HeaderDoc::fileDebug; @@ -5996,6 +6410,10 @@ if ($forcedebug) { print STDERR "FD\n"; } $parserState->{classtype} = "class"; print "SETTING sodtype TO $sodtype\n" if ($forcedebug); } + if ($lang eq "applescript" && $parserState->{sodclass} eq "class") { + $sodclass = "script"; + $parserState->{sodclass} = "script"; + } # AppleScript supports multi-word names, but does not support # types. @@ -6531,7 +6949,7 @@ print STDERR "SN: \"$sodname\"\nST: \"$sodtype\"\nSC: \"$sodclass\"\n" if ($loca print STDERR "TYPELIST WAS \"$typelist\"\n" if ($localDebug);; # warn("left blockParse (macro)\n"); -# print STDERR "NumPPs: ".scalar(@parsedParamList)."\n"; +print STDERR "NumPPs: ".scalar(@parsedParamList)."\n" if ($localDebug); # $treeTop->printTree(); @@ -6798,7 +7216,12 @@ print STDERR "TL: \"$typelist\".\n" if ($localDebug || $listDebug); print STDERR "PT: \"$posstypes\"\n" if ($localDebug || $listDebug); print STDERR "SN: \"$sodname\"\nST: \"$sodtype\"\nSC: \"$sodclass\"\n" if ($localDebug || $sodDebug); - $availability = mergeComplexAvailability($availability, $parserState->{availabilityNodesArray}); + if ($typelist !~ /\#define/) { + # Availability is meaningless for a macro, and worse, macros can be used to define new + # availability macros, which would cause this to just plain misbehave. + + $availability = mergeComplexAvailability($availability, $parserState->{availabilityNodesArray}); + } print STDERR "SUBPARSE: $subparse NAME: $namelist TTIC: ".$treeTop->{INPUTCOUNTER}." TTBO: ".$treeTop->{BLOCKOFFSET}."\n" if ($subparseDebug); @@ -6894,9 +7317,30 @@ print STDERR "SN: \"$sodname\"\nST: \"$sodtype\"\nSC: \"$sodclass\"\n" if ($loca } + # print STDERR "SODCLASS: $sodclass SODNAME: $sodname SODTYPE: $sodtype LANG: $sublang\n"; + my $memberOfClass = ""; + my $origsodname = $sodname; if ($sodclass eq "function" && $parserState->{isConstructor} && $lang eq "tcl") { $memberOfClass = $sodname; + print STDERR "MEMBER OF CLASS: $memberOfClass\n" if ($localDebug || $forcedebug); + } elsif ($sublang eq "javascript" && $sodclass eq "variable" && $sodname =~ s/^(\w+(?:\.\w+)*)\s*\.\s*prototype\s*\.\s*//s) { + my $headerobj = $HeaderDoc::headerObject; + my $possible_class = $1; + my $temp = $headerobj->findClass($possible_class); + + print STDERR "Checking for class \"$possible_class\"\n" if ($localDebug || $forcedebug); + + # Don't throw away the class part unless we've actually seen this class. + if ($temp) { + $memberOfClass = $possible_class; + print STDERR "MEMBER OF CLASS: $memberOfClass\n" if ($localDebug || $forcedebug); + changeAllMatching(\@nameObjects, "NAME", "$origsodname", "NAME", "$sodname", 0); + changeAllMatching(\@nameObjects, "TYPE", "variable", "TYPE", "function", 0); + changeAllMatching(\@nameObjects, "TYPE", "variable", "POSSTYPES", "function constant variable", 0); + } else { + $sodname = $origsodname; + } } elsif ($sodclass eq "function" && $sodtype =~ /(\w+)\s*::\s*$/) { $memberOfClass = $1; print STDERR "MEMBER OF CLASS: $memberOfClass\n" if ($localDebug || $forcedebug); @@ -6916,6 +7360,14 @@ print STDERR "SN: \"$sodname\"\nST: \"$sodtype\"\nSC: \"$sodclass\"\n" if ($loca changeAllMatching(\@nameObjects, "TYPE", "constant", "POSSTYPES", "constant variable", 0); changeAllMatching(\@nameObjects, "TYPE", "variable", "POSSTYPES", "constant variable", 0); + if ($sublang eq "javascript" && $sodclass eq "function") { + $posstypes = "function method class"; + changeAll(\@nameObjects, "POSSTYPES", $posstypes, 0); # may be no-op. + } elsif ($lang eq "applescript" && $sodclass eq "function") { + $posstypes = "function method ".$parserState->{classtype}; + changeAll(\@nameObjects, "POSSTYPES", $posstypes, 0); # may be no-op. + } + # print STDERR "ATEND PS $parserState HAS ARGS: ".$parserState->{cppMacroHasArgs}."\n"; # We're outta here. @@ -7243,18 +7695,18 @@ sub defParmParse if ($token =~ /[\(\[]/o) { print STDERR "open paren/bracket - $token\n" if ($localDebug); push(@braceStack, $token); - print STDERR "PUSHED $token ONTO BRACESTACK\n" if ($braceDebug); + print STDERR "PUSHED $token ONTO BRACESTACK [8]\n" if ($braceDebug); } elsif ($token =~ /\)/o) { print STDERR "close paren\n" if ($localDebug); my $top = pop(@braceStack); - print STDERR "POPPED $top FROM BRACESTACK\n" if ($braceDebug); + print STDERR "POPPED $top FROM BRACESTACK [7]\n" if ($braceDebug); if ($top !~ /\(/o) { warn("$fullpath:$inputCounter: warning: Parentheses do not match (macro).\nWe may have a problem.\n"); } } elsif ($token =~ /\]/o) { print STDERR "close bracket\n" if ($localDebug); my $top = pop(@braceStack); - print STDERR "POPPED $top FROM BRACESTACK\n" if ($braceDebug); + print STDERR "POPPED $top FROM BRACESTACK [8]\n" if ($braceDebug); if ($top !~ /\[/o) { warn("$fullpath:$inputCounter: warning: Braces do not match (macro).\nWe may have a problem.\n"); } @@ -7314,6 +7766,8 @@ sub ignore } return $def; } + my $isa = isStandardAvailability($part); + if ($isa) { return $isa; } if ($ignorelist{$part}) { print STDERR "IGNORING $part\n" if ($localDebug); @@ -8811,6 +9265,18 @@ print STDERR "NC: $newcount\n" if ($localDebug); warn("NL: \"$namelist\"\n"); warn("PT: \"$posstypes\"\n"); } + } elsif ($HeaderDoc::ignore_apiowner_names == 2 && length($outername) && !$curObj->isBlock) { + if ($localDebug || $nameDebug) { + print STDERR "CURNAME CHANGED FROM $curname -> $outername\n"; + print STDERR "CURNAME_EXTENDED CHANGED FROM $curname_extended -> $outername\n"; + } + $curname = $outername; + $curname_extended = $outername; + } + if ($localDebug || $nameDebug) { + print STDERR "CURNAME: $curname\n"; + print STDERR "OUTERNAME: $outername\n"; + print STDERR "IGNORE: ".$HeaderDoc::ignore_apiowner_names."\n"; } if ($outername eq "") { @@ -9044,11 +9510,12 @@ print STDERR "NC: $newcount\n" if ($localDebug); # $curname_inserted = 1; my $newcurObj; my $typestring = $curtype; + my $ncdeclaration = $parseTree->textTreeNC($lang, $sublang, 1); ($newcurObj, $classType, $varIsConstant) = objForType( $curObj, $parseTokens{typedefname}, $typestring, - $posstypes, $outertype, $curtype, $classType, $classKeyword, $declaration, + $posstypes, $outertype, $curtype, $classType, $classKeyword, $ncdeclaration, \@fields, $functionGroup, $varIsConstant, $blockmode, $inClass, $inInterface, $inTypedef, $inStruct, $fullpath, $inputCounter, $blockOffset, $lang, $sublang, 0, $functionContents, - $apiOwner, $subparseInputCounter, $subparseBlockOffset, $extendsClass, $implementsClass, 1); + $apiOwner, $subparseInputCounter, $subparseBlockOffset, $extendsClass, $implementsClass, 1, \%parseTokens); if ($mustLockDiscussion) { $curObj->prepareDiscussionForTemporary(); } @@ -9498,12 +9965,13 @@ print STDERR "setting curtype to UNKNOWN\n" if ($localDebug); print STDERR "BAILFAST[1]: AT END IC: $inputCounter\n" if ($HeaderDoc::inputCounterDebug); last; } + my $ncdeclaration = $parseTree->textTreeNC($lang, $sublang, 1); ($extra, $classType, $varIsConstant) = objForType( $curObj, $parseTokens{typedefname}, $typestring, - $posstypes, $outertype, $curtype, $classType, $classKeyword, $declaration, + $posstypes, $outertype, $curtype, $classType, $classKeyword, $ncdeclaration, \@fields, $functionGroup, $varIsConstant, $blockmode, $inClass, $inInterface, $inTypedef, $inStruct, $fullpath, $inputCounter, $blockOffset, $lang, $sublang, $outerLocalDebug, $functionContents, $apiOwner, $subparseInputCounter, $subparseBlockOffset, - $extendsClass, $implementsClass, 0); + $extendsClass, $implementsClass, 0, \%parseTokens); print "EXTRA ON RETURN IS $extra\n" if ($nameDebug || $nameObjDebug); } @@ -10037,8 +10505,13 @@ print STDERR "setting curtype to UNKNOWN\n" if ($localDebug); # print STDERR "ITD: $inTypedef\n"; print STDERR "B8X blockmode=$blockmode ts=$typestring\n" if ($localDebug || $hangDebug); my $typedefname = $parseTokens{typedefname}; + my $classregexp = $parseTokens{classregexp}; + my $moduleregexp = $parseTokens{moduleregexp}; - if (($typestring =~ /^(class|\@class|\@interface|\@implementation|\@protocol|interface|module|namespace|package)/ || $inClass) && !$inTypedef) { + # if (($typestring =~ /^(class|\@class|\@interface|\@implementation|\@protocol|interface|module|namespace|package)/ || $inClass) && !$inTypedef) + if (((length($classregexp) && $typestring =~ /$classregexp/) || + (length($moduleregexp) && $typestring =~ /$moduleregexp/) || $inClass) && + !$inTypedef) { print STDERR "ITSACLASS! ($extra->name)\n" if ($localDebug); $extra->declaration($declaration); $extra->declarationInHTML($declaration); @@ -10047,7 +10520,8 @@ print STDERR "setting curtype to UNKNOWN\n" if ($localDebug); # my $localDebug = 1; print STDERR "ADDING \"".$extra->name."\" TO CLASSES/PROTOCOLS/*\n" if ($localDebug); print STDERR "RAWDEC: $declaration\n" if ($localDebug); - $classType = classTypeFromFieldAndBPinfo($classKeyword, $typestring." ".$posstypes, $declaration, $fullpath, $inputCounter+$blockOffset, $sublang); + my $ncdeclaration = $parseTree->textTreeNC($lang, $sublang, 1); + $classType = classTypeFromFieldAndBPinfo($classKeyword, $typestring." ".$posstypes, $ncdeclaration, $fullpath, $inputCounter+$blockOffset, $sublang); # print STDERR "CLASSTYPE: $classType\n"; if ($classType eq "intf") { push (@classObjects, $extra); @@ -10446,20 +10920,31 @@ sub objForType my $extendsClass = shift; # IN my $implementsClass = shift; # IN my $alwaysProcessComment = shift; # IN + my $parseTokensRef = shift; # IN my $parserState = shift; # IN my $extra = undef; # OUT my $localDebug = 0; + my %parseTokens = %{$parseTokensRef}; + my $filename = basename($fullpath); print STDERR "FOR DECLARATION $declaration\n" if ($localDebug); # printFields($fieldref); + my $classregexp = $parseTokens{classregexp}; + my $moduleregexp = $parseTokens{moduleregexp}; + # print STDERR "CHECK: $classregexp\n"; + # print STDERR "CO: $curObj HASPC: ".$curObj->{HASPROCESSEDCOMMENT}." CURTYPE: $curtype\n"; + # print "TYPESTRING \"$typestring\" OUTERTYPE: \"$outertype\"\n"; + if ($typestring eq $outertype || !$HeaderDoc::outerNamesOnly) { - if (($typestring =~ /^(class|\@class|\@interface|\@implementation|\@protocol|interface|module|namespace|package)/ || $inClass) && !$inTypedef && !$inStruct) { + # $typestring =~ /^(class|\@class|\@interface|\@implementation|\@protocol|interface|module|namespace|package)/ + if (((length($classregexp) && $typestring =~ /$classregexp/) || + (length($moduleregexp) && $typestring =~ /$moduleregexp/) || $inClass) && !$inTypedef && !$inStruct) { print STDERR "blockParse returned class\n" if ($localDebug); print STDERR "RAWDEC: $declaration\n" if ($localDebug && $outerLocalDebug); $classType = classTypeFromFieldAndBPinfo($classKeyword, $typestring." ".$posstypes, $declaration, $fullpath, $inputCounter+$blockOffset, $sublang); @@ -10560,7 +11045,7 @@ sub objForType # $headerObject->addToClasses($extra); # } - } elsif (($typestring =~ /^$typedefname/ && length($typedefname)) || $typestring =~ /^(class|\@class|\@interface|\@implementation|\@protocol)/) { + } elsif (($typestring =~ /^$typedefname/ && length($typedefname)) || ($typestring =~ /$classregexp/ && length($classregexp))) { print STDERR "blockParse returned $typedefname\n" if ($localDebug); if ($localDebug) { foreach my $field (@{$fieldref}) { @@ -10910,7 +11395,7 @@ sub cpp_add($$) $string =~ s/^\/\*.*?\*\///s; - # print STDERR "IN cpp_add: ADDING \"$string\"\n"; + print STDERR "IN cpp_add: ADDING \"$string\"\n" if ($cppDebug || $cppAddDebug); return cpp_add_string($string, $dropdeclaration); } @@ -10932,8 +11417,8 @@ sub cpp_add_string($$) my $slstring = $string; $slstring =~ s/\\\n/ /sg; - print STDERR "cpp_add: STRING WAS $string\n" if ($cppDebug || $localDebug || $cppDebugFromToken); - print STDERR "SLSTRING: $slstring\n" if ($localDebug || $cppDebug); + print STDERR "cpp_add: STRING WAS $string\n" if ($cppDebug || $localDebug || $cppDebugFromToken || $cppAddDebug); + print STDERR "SLSTRING: $slstring\n" if ($localDebug || $cppDebug || $cppAddDebug); # if ($slstring =~ s/^\s*#define\s+(\w+)\(//s) { if ($dropdeclaration && $slstring =~ s/^\s*#define\s+(\w+)(\s|$)//s) { @@ -11141,9 +11626,9 @@ sub cpp_preprocess my $count = 0; if ($HeaderDoc::enable_cpp > 0) { -# print STDERR "CPP ENABLE\n"; +print STDERR "CPP ENABLE\n" if ($cppDebug > 1); foreach my $hashhashref (@HeaderDoc::cppHashList) { -# print STDERR "HASHREFCHECK\n"; +print STDERR "HASHREFCHECK\n" if ($cppDebug > 1); my $hashref = $hashhashref->{HASHREF}; print STDERR "HASHREF: $hashref\n" if ($cppDebug); if (!$hashref) { @@ -11178,6 +11663,8 @@ sub cpp_preprocess print STDERR "HASARGS: $hasargs\n" if ($cppDebug); return ($altpart, $hasargs, $CPP_ARG_HASH{$part}); } + } else { + print STDERR "C preprocessing is disabled.\n" if ($cppDebug); } # If we got here, either CPP is disabled or we didn't find anything. @@ -11727,6 +12214,35 @@ sub cppHashMerge return ($hashret, $arghashret, $root, $curhashobj); } +# /*! +# @abstract +# Configures the access control state and optional/required +# state for methods and variables within a class based on +# the current language and class type. +# */ +sub configureAccessControlStateForClass +{ + my $parserState = shift; + + my $lang = $parserState->{lang}; + + if ($lang eq "php") { + $HeaderDoc::AccessControlState = "public"; + } elsif ($lang eq "java") { + $HeaderDoc::AccessControlState = "package-private"; + } elsif ($lang eq "C") { + if ($parserState->{classIsObjC} || ($parserState->{sublang} eq "IDL" && $HeaderDoc::idl_language eq "occ")) { + $HeaderDoc::AccessControlState = "private"; + if ($parserState->{inProtocol}) { + $HeaderDoc::OptionalOrRequired = "\@required"; # The default in Objective C + } + } elsif ($parserState->{sublang} eq "IDL" && ($HeaderDoc::idl_language eq "idl" || $HeaderDoc::idl_language eq "javascript" || $HeaderDoc::idl_language eq "js")) { + $HeaderDoc::AccessControlState = "public"; + } else { + $HeaderDoc::AccessControlState = "protected"; + } + } +} 1; diff --git a/Modules/HeaderDoc/Header.pm b/Modules/HeaderDoc/Header.pm index 502da14..e5493b8 100644 --- a/Modules/HeaderDoc/Header.pm +++ b/Modules/HeaderDoc/Header.pm @@ -3,7 +3,7 @@ # Class name: Header # Synopsis: Holds header-wide comments parsed by headerDoc # -# Last Updated: $Date: 2011/02/18 19:02:58 $ +# Last Updated: $Date: 2011/05/26 15:50:22 $ # # Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved. # @@ -84,7 +84,7 @@ use vars qw($VERSION @ISA); # In the git repository, contains the number of seconds since # January 1, 1970. # */ -$HeaderDoc::Header::VERSION = '$Revision: 1298084578 $'; +$HeaderDoc::Header::VERSION = '$Revision: 1306450222 $'; # Inheritance @ISA = qw( HeaderDoc::APIOwner ); @@ -480,6 +480,8 @@ sub writeHeaderElementsToCompositePage { my @categoryObjs = $self->categories(); $self->SUPER::writeHeaderElementsToCompositePage(); + return; + if ($self->classes()) { foreach my $obj (@classObjs) { $obj->writeHeaderElementsToCompositePage(); diff --git a/Modules/HeaderDoc/HeaderElement.pm b/Modules/HeaderDoc/HeaderElement.pm index 36f6aa6..8db6ccd 100644 --- a/Modules/HeaderDoc/HeaderElement.pm +++ b/Modules/HeaderDoc/HeaderElement.pm @@ -3,7 +3,7 @@ # Class name: HeaderElement # Synopsis: Root class for Function, Typedef, Constant, etc. -- used by HeaderDoc. # -# Last Updated: $Date: 2011/05/18 14:09:25 $ +# Last Updated: $Date: 2014/03/06 11:05:55 $ # # Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved. # @@ -157,6 +157,8 @@ # @var FIRSTCONSTNAME # The first constant name within an enumeration. Used as the name of # an anonymous enumeration if no name is specified in the comment. +# @var FORCENAME +# The contents of an \@name tag, which overrides any name obtained in any other way. # @var FULLPATH # The filename containing this declaration (with leading parts left intact). # @var FUNCORMETHOD @@ -255,7 +257,7 @@ # destroying this object to allow those references to be destroyed. # @var NAMESPACE # Contains a text string representing the namespace for this class. -# See {@link namespace}. +# See {@link //apple_ref/perl/instm/HeaderDoc::HeaderElement/namespace//() namespace}. # @var NOREGISTERUID # Set to 1 when an object's UID has been unregistered to prevent it from being # registered again. See {@link noRegisterUID}. @@ -328,7 +330,8 @@ # @var USESTDOUT # Set to 1 if the -P (pipe) flag is passed to HeaderDoc, else 0. # @var VALUE -# The value of a constant/variable. See {@link value}. +# The value of a constant/variable. +# See {@link //apple_ref/perl/instm/HeaderDoc::HeaderElement/value//() value}. # @var VARIABLES # An array of variables enclosed in a normal (usually function) object. These are # {@link //apple_ref/perl/cl/HeaderDoc::MinorAPIElement MinorAPIElement} objects. @@ -337,6 +340,21 @@ # {@link //apple_ref/perl/cl/HeaderDoc::Var Var} objects. # @var XMLTHROWS # A copy of the value in THROWS with XML formatting. +# @var AS_CLASS_SELF +# A CPPClass object cloned from the current function object that holds +# any scripts that are nested within the function. See +# {@link cloneAppleScriptFunctionContents} and {@link processAppleScriptFunctionContents} +# for more information. +# @var AS_FUNC_SELF +# The Function object that the current class object was cloned from. See +# {@link cloneAppleScriptFunctionContents} and {@link processAppleScriptFunctionContents} +# for more information. +# @var ASCONTENTSPROCESSED +# Set to 1 after the {@link processAppleScriptFunctionContents} method runs. +# for more information. +# @var PARSEDPSEUDOCLASSNAME +# The name of the directory where the contents from any classes within the {@link AS_CLASS_SELF} +# container are written. # */ package HeaderDoc::HeaderElement; @@ -353,6 +371,16 @@ use Encode qw(encode decode); use Devel::Peek; +my $isMacOS; +my $pathSeparator; +if ($^O =~ /MacOS/io) { + $pathSeparator = ":"; + $isMacOS = 1; +} else { + $pathSeparator = "/"; + $isMacOS = 0; +} + # /*! # @abstract # The revision control revision number for this module. @@ -360,7 +388,7 @@ use Devel::Peek; # In the git repository, contains the number of seconds since # January 1, 1970. # */ -$HeaderDoc::HeaderElement::VERSION = '$Revision: 1305752965 $'; +$HeaderDoc::HeaderElement::VERSION = '$Revision: 1394132755 $'; # /*! # @abstract @@ -1113,7 +1141,7 @@ sub name { my($class) = ref($self) || $self; - print STDERR "$class\n" if ($localDebug); + print STDERR "IN NAME: $class\n" if ($localDebug); if (@_) { my $name = shift; @@ -1128,7 +1156,7 @@ sub name { print STDERR "NAMESET: $self -> $name\n" if ($localDebug); - if (!($class eq "HeaderDoc::Header") && ($oldname && length($oldname))) { + if (!($class eq "HeaderDoc::Header") && ($oldname && length($oldname)) && !length($self->{FORCENAME})) { # Don't warn for headers, as they always change if you add # text after @header. Also, don't warn if the new name # contains the entire old name, to avoid warnings for @@ -1155,7 +1183,9 @@ sub name { } elsif (($class eq "HeaderDoc::CPPClass" || $class =~ /^HeaderDoc::ObjC/o) && $name =~ /:/o) { warn("$fullpath:$linenum: warning: Class name contains colon, which is probably not what you want.\n"); } - } + } elsif (length($self->{FORCENAME})) { + $name = $self->{FORCENAME}; + } $name =~ s/\n$//sgo; $name =~ s/\s$//sgo; @@ -1596,6 +1626,8 @@ sub getAttributes foreach my $key (sort strcasecmp keys %attlist) { my $value = $attlist{$key}; if ($xml) { + $key = $self->htmlToXML($key); + $value = $self->htmlToXML($value); $retval .= "$key$value\n"; } else { $maybe = 0; @@ -2504,7 +2536,7 @@ sub throws { # @param self # The current object. # @discussion -# The value is set with {@link throws}. +# The value is set with {@link //apple_ref/perl/instm/HeaderDoc::HeaderElement/throws//() throws}. # */ sub XMLthrows { my $self = shift; @@ -3894,7 +3926,7 @@ sub keywords "try" => 1, "volatile" => 1, "while" => 1); - my %tclKeywords = ( ); # @@@ FIXME DAG @@@ + my %tclKeywords = ( "method" => 1, "constructor" => 1, "proc" => 1, "attribute" => 1 ); # Consider adding "regexp" command? # @@@ ADD "class" and fix bugs. my %perlKeywords = ( "sub" => 1, "my" => 8, "next" => 1, "last" => 1, "package" => 1 ); my %shellKeywords = ( "sub" => 1, "alias" => 1, @@ -4235,6 +4267,7 @@ sub declarationInHTML { # */ sub parseTree { my $self = shift; + my $localDebug = 0; if (@_) { my $parsetree = shift; @@ -4242,6 +4275,18 @@ sub parseTree { $self->addParseTree($parsetree); } $self->{PARSETREE} = $parsetree; + + my $class = ref($self) || $self; + if ($self->lang eq "applescript" && $class eq "HeaderDoc::Function") { + if (!$self->{AS_CLASS_SELF}) { + $self->cloneAppleScriptFunctionContents(); + } + if ($localDebug) { + print STDERR "ADDING PARSE TREE FOR $self\n"; + bless($parsetree, "HeaderDoc::ParseTree"); + ${$parsetree}->dbprint(); + } + } } return $self->{PARSETREE}; } @@ -4978,6 +5023,7 @@ sub styleSheet if ($stdstyles) { # Most stuff is 10 pt. + $css .= "body {border: 0px; margin: 0px;}"; $css .= "div {font-size: 10pt; text-decoration: none; font-family: lucida grande, geneva, helvetica, arial, sans-serif; color: #000000;}"; $css .= "td {font-size: 10pt; text-decoration: none; font-family: lucida grande, geneva, helvetica, arial, sans-serif; color: #000000;}"; @@ -5147,6 +5193,20 @@ sub documentationBlock if ($self->isInternal() && !$HeaderDoc::document_internal) { return ""; } + my @embeddedClasses = (); + my $class_self = undef; + if ($self->lang eq "applescript" && $class eq "HeaderDoc::Function") { + if (!$self->{ASCONTENTSPROCESSED}) { + $class_self = $self->processAppleScriptFunctionContents(); + if ($class_self) { + my @classes = $class_self->classes(); + foreach my $obj (@classes) { + push(@embeddedClasses, $obj); + } + } + } + } + # print STDERR "GOTHERE\n"; # Only use this style for API Owners. @@ -5341,6 +5401,10 @@ sub documentationBlock if ($self->can("accessControl")) { $accessControl = $self->accessControl(); } + my $optionalOrRequired = ""; + if ($self->parserState && ($apioclass =~ /HeaderDoc::ObjCProtocol/)) { + $optionalOrRequired = $self->parserState->{optionalOrRequired}; + } my $includeAccess = 0; if ($accessControl ne "") { $includeAccess = 1; } if ($self->can("isProperty") && $self->isProperty()) { $includeAccess = 0; } @@ -5354,6 +5418,8 @@ sub documentationBlock my $declend = $self->headerDocMark("declaration", "end"); if ($includeAccess) { $contentString .= "
$accessControl\n
$declaration
\n"; + } elsif (length $optionalOrRequired) { + $contentString .= "
$optionalOrRequired\n
$declaration
\n"; } else { $contentString .= "
$declstart$declaration$declend
\n"; } @@ -5504,6 +5570,48 @@ sub documentationBlock $contentString .= "\n"; } } + if (@embeddedClasses) { + $showDiscussionHeading = 1; + $contentString .= "
Embedded Classes
\n"; + $contentString .= "
\n"; + $contentString .= "
\n"; + # $contentString .= "\n"; + # $contentString .= "\n"; + foreach my $element (@embeddedClasses) { + my $cName = $element->name(); + + # print STDERR "EMBEDDED CLASS: $cName\n"; + + my $cDesc = $element->discussion(); + # my $uid = "//$apiUIDPrefix/c/econst/$cName"; + # registerUID($uid); + my $uid = $element->apiuid(); # "econst"); + + my $safeName = $cName; + $safeName = &safeName(filename => $cName); + + my $url = $class_self->{PARSEDPSEUDOCLASSNAME}.$pathSeparator."Classes".$pathSeparator.$safeName.$pathSeparator."index.html"; + + my $target = "doc"; + my $classAsComposite = $HeaderDoc::ClassAsComposite; + # if ($class eq "HeaderDoc::Header") { $classAsComposite = 0; } + + if ($composite && !$classAsComposite) { $classAsComposite = 1; $target = "_top"; } + if ($element->isAPIOwner()) { + $target = "_top"; + $classAsComposite = 0; + } + + if ($HeaderDoc::use_iframes) { + $target = "_top"; + } + + # $contentString .= "\n"; + $contentString .= "
$cName
$cDesc
\n"; + } + # $contentString .= "
NameDescription
$cName$cDesc
\n
\n"; + $contentString .= "\n\n"; + } if (@constants) { $showDiscussionHeading = 1; $contentString .= "
Constants
\n"; @@ -5519,9 +5627,9 @@ sub documentationBlock my $uid = $element->apiuid(); # "econst"); # $contentString .= "$cName$cDesc\n"; - if (!$HeaderDoc::appleRefUsed{$uid} && !$HeaderDoc::ignore_apiuid_errors) { + if (!$apio->appleRefUsed($uid) && !$HeaderDoc::ignore_apiuid_errors) { # print STDERR "MARKING APIREF $uid used\n"; - $HeaderDoc::appleRefUsed{$uid} = 1; + $apio->appleRefUsed($uid, 1); $contentString .= "
$cName
$cDesc
\n"; } else { $contentString .= "
$cName
$cDesc
\n"; @@ -5671,11 +5779,12 @@ sub documentationBlock # $contentString .= "$cName$cDesc\n"; - if (!$HeaderDoc::appleRefUsed{$uid} && !$HeaderDoc::ignore_apiuid_errors) { - # print STDERR "MARKING APIREF $uid used\n"; - $HeaderDoc::appleRefUsed{$uid} = 1; + if (!$apio->appleRefUsed($uid) && !$HeaderDoc::ignore_apiuid_errors) { + # cluck("MARKING APIREF $uid used\n"); + $apio->appleRefUsed($uid, 1); $contentString .= "
$cName
$cDesc
\n"; } else { + # cluck("Reused Apple Ref $uid\n"); $contentString .= "
$cName
$cDesc
\n"; } } @@ -6288,6 +6397,37 @@ sub XMLdocumentationBlock { my $fielduidtag = ""; my $extra = ""; + my $accessControl = ""; + if ($self->can("accessControl")) { + $accessControl = $self->accessControl(); + } + if ($accessControl =~ /\S/) { + $accessControl = " accessControl=\"$accessControl\""; + } else { + $accessControl = ""; + } + + my $optionalOrRequired = ""; + if ($self->parserState && ($apioclass =~ /HeaderDoc::ObjCProtocol/)) { + $optionalOrRequired = $self->parserState->{optionalOrRequired}; + if (length $optionalOrRequired) { + $optionalOrRequired = " optionalOrRequired=\"$optionalOrRequired\""; + } + } + + my @embeddedClasses = (); + my $class_self = undef; + if ($self->lang eq "applescript" && $class eq "HeaderDoc::Function") { + if (!$self->{ASCONTENTSPROCESSED}) { + $class_self = $self->processAppleScriptFunctionContents(); + # $class_self->dbprint(); + my @classes = $class_self->classes(); + foreach my $obj (@classes) { + push(@embeddedClasses, $obj); + } + } + } + $langstring = $self->apiRefLanguage($sublang); # if ($sublang eq "cpp") { @@ -6424,6 +6564,7 @@ sub XMLdocumentationBlock { # my $methodType = $self->getMethodType($declarationRaw); my $methodType = $self->getMethodType(); $uid = $self->apiuid($methodType); + $extra = " type=\"$methodType\""; $isAPIOwner = 0; last SWITCH; }; @@ -6494,7 +6635,11 @@ sub XMLdocumentationBlock { } else { $definetype = "value"; } - $defineinfo = " definetype=\"$definetype\" "; + $defineinfo = "definetype=\"$definetype\" "; + + if ($self->parseOnly()) { + $defineinfo .= "parseOnly=\"true\" "; + } $isAPIOwner = 0; last SWITCH; }; @@ -6563,13 +6708,17 @@ sub XMLdocumentationBlock { }; } + my $indexgroup = $self->indexgroup(); + my $throws = $self->XMLthrows(); - $compositePageString .= "<$type id=\"$uid\" $defineinfo"."lang=\"$langstring\"$extra>"; # e.g. ""; + $compositePageString .= "<$type id=\"$uid\" $defineinfo"."lang=\"$langstring\"$extra$accessControl$optionalOrRequired>"; # e.g. ""; if (length($name)) { $compositePageString .= "$name\n"; } + if ($indexgroup =~ /\S/) { $compositePageString .= "".textToXML($indexgroup).""; } + if (length($abstract)) { $compositePageString .= "$abstract\n"; } @@ -6587,6 +6736,9 @@ sub XMLdocumentationBlock { $value = $self->value(); if (length($value) && ($value ne "UNKNOWN")) { + # Always XML in this function, so do this every time. + $value = $self->textToXML($value); + $compositePageString .= "$value\n"; } } @@ -6720,9 +6872,9 @@ sub XMLdocumentationBlock { if (length($fielduidtag)) { my $fielduid = $field->apiuid($fielduidtag); $fielduidstring = " id=\"$fielduid\""; - if (!$HeaderDoc::appleRefUsed{$uid} && !$HeaderDoc::ignore_apiuid_errors) { + if (!$apio->appleRefUsed($uid) && !$HeaderDoc::ignore_apiuid_errors) { # print STDERR "MARKING APIREF $uid used\n"; - $HeaderDoc::appleRefUsed{$uid} = 1; + $apio->appleRefUsed($uid, 1); } else { # already used or a "junk" run to obtain # uids for another purpose. Drop the @@ -6748,7 +6900,14 @@ sub XMLdocumentationBlock { } $compositePageString .= "\n"; } - + if (@embeddedClasses) { + $contentString = $class_self->_getEmbeddedClassXMLDetailString(\@embeddedClasses); + if (length($contentString)) { + $compositePageString .= "\n"; + $compositePageString .= $contentString; + $compositePageString .= "\n"; + } + } if (@local_variables) { $compositePageString .= "\n"; foreach my $field (@local_variables) { @@ -6768,9 +6927,9 @@ sub XMLdocumentationBlock { if (length($fielduidtag)) { my $fielduid = $field->apiuid($fielduidtag); $fielduidstring = " id=\"$fielduid\""; - if (!$HeaderDoc::appleRefUsed{$uid} && !$HeaderDoc::ignore_apiuid_errors) { + if (!$apio->appleRefUsed($uid) && !$HeaderDoc::ignore_apiuid_errors) { # print STDERR "MARKING APIREF $uid used\n"; - $HeaderDoc::appleRefUsed{$uid} = 1; + $apio->appleRefUsed($uid, 1); } else { # already used or a "junk" run to obtain # uids for another purpose. Drop the @@ -7610,7 +7769,7 @@ sub processComment $top_level_field = validTag($fieldname, 1); if ($top_level_field && $seen_top_level_field && ($fieldname !~ /const(ant)?/) && - ($fieldname !~ /var/) && (!$self->isBlock() || $fieldname ne "define")) { + ($fieldname !~ /var/) && (!$self->isBlock() || $fieldname ne "define") && $fieldname ne "name") { # We've seen more than one top level field. $field =~ s/^(\w+)(\s)//s; @@ -7647,6 +7806,21 @@ sub processComment } elsif ($top_level_field && $seen_top_level_field && ($fieldname eq "var")) { $top_level_field = 0; } + + # Fix for another common mistake: people using @field for a class + # member variable instead of @var or @const. + if ($class =~ /HeaderDoc\:\:Var/ && !$isProperty) { + if (!$seen_top_level_field && $fieldname eq "field") { + if ($sublang !~ /^occ/o) { + warn "Field \@$fieldname found in \@var declaration.\nYou probably meant \@var instead.\n" if (!$HeaderDoc::running_test); + $field =~ s/^(\w+)(\s)//s; + my $spc = $2; + + $field = "var$spc$field"; + $top_level_field = 1; + } + } + } } # warn("FN: \"$fieldname\"\n"); # print STDERR "TLF: $top_level_field, FN: \"$fieldname\"\n"; @@ -7828,7 +8002,7 @@ field); }; ($class =~ /HeaderDoc\:\:PDefine/ && $self->isBlock() && $field =~ s/^hidesingletons(\s+)/$1/sio) && do {$self->{HIDESINGLETONS} = 1; last SWITCH;}; - ($class =~ /HeaderDoc\:\:PDefine/ && $field =~ s/^hidecontents(\s+)/$1/sio) && do {$self->hideContents(1); last SWITCH;}; + (($class =~ /HeaderDoc\:\:PDefine/ || $class =~ /HeaderDoc\:\:Function/ || $class =~ /HeaderDoc\:\:Method/) && $field =~ s/^hidecontents(\s+)/$1/sio) && do {$self->hideContents(1); last SWITCH;}; (($class =~ /HeaderDoc\:\:Function/ || $class =~ /HeaderDoc\:\:Method/) && $field =~ s/^(function|method)group\s+//sio) && do {$self->group($field); last SWITCH;}; @@ -8075,6 +8249,7 @@ field); print STDERR "TLF: $field\n" if ($localDebug); my $pattern = ""; + if ($class =~ /HeaderDoc\:\:PDefine/ && $field =~ s/^(availabilitymacro)(\s+|$)/$2/sio) { $self->isAvailabilityMacro(1); $keepname = 1; @@ -8114,6 +8289,7 @@ field); my ($name, $abstract_or_disc, $namedisc) = getAPINameAndDisc($field, $self->lang(), $pattern); print STDERR "FIELD: $field\nNAME: $name AOD: $abstract_or_disc ND: $namedisc" if ($localDebug); + if ($fieldname eq "name") {$self->{FORCENAME} = $name; print STDERR "FORCED NAME TO \"$name\"\n"}; print STDERR "KEEPNAME: $keepname\n" if ($localDebug); @@ -8398,6 +8574,25 @@ sub declaredIn return ""; } + # print STDERR "DI: $self APIO: $apio\n"; + + if ($apio->{AS_FUNC_SELF}) { + my $func_apio_ref = $apio->{AS_FUNC_SELF}; + if (!$func_apio_ref) { + die("Bad AS_FUNC_SELF for $apio (".$apio->name().")\n"); + } + my $func_apio = ${$func_apio_ref}; + bless($func_apio, "HeaderDoc::HeaderElement"); + bless($func_apio, $func_apio->class()); + + # print STDERR "CLASS IN FUNC\n"; + my $name = $func_apio->name(); + my $apiref = $func_apio->apiuid(); + my $jumpTarget = $apiref; + + return "$name"; + } + if ($self->isAPIOwner()) { if ($class =~ /HeaderDoc::Header/) { # warn $self->name.": Header\n"; @@ -9301,4 +9496,151 @@ sub prepareDiscussionForTemporary $self->{DISCUSSION_SET} = undef; } +# /*! +# @abstract +# Clones a function object for use as an API owner for any +# enclosing scripts. +# */ +sub cloneAppleScriptFunctionContents +{ + my $self = shift; + + my $localDebug = 0; + + if ($localDebug) { + print STDERR "Cloning $self for AppleScript function body parsing.\n"; + $self->dbprint(); + } + + my $class_self = HeaderDoc::CPPClass->new(); + $self->{AS_CLASS_SELF} = \$class_self; + $class_self->{AS_FUNC_SELF} = \$self; + + my $orig_ptref = $self->{PARSETREE}; + bless($orig_ptref, "HeaderDoc::ParseTree"); + my $parseTree = ${$orig_ptref}; + + $parseTree = $parseTree->ASFunctionBodyStart(); + + my $tree = $parseTree->clone(); + $tree->parserState($self->{PARSERSTATE}); + + # Don't copy the name here, because it hasn't been set yet, but copy + # the parse tree, because otherwise it gets stomped. + $class_self->{PARSETREE} = \$tree; + $class_self->{PARSERSTATE} = $self->{PARSERSTATE}; + $class_self->{SUBLANG} = $self->{SUBLANG}; + $class_self->{APIOWNER} = $self->{APIOWNER}; + $class_self->{FILENAME} = $self->{FILENAME}; + $class_self->{FULLPATH} = $self->{FULLPATH}; + $class_self->{OUTPUTFORMAT} = $self->{OUTPUTFORMAT}; + + print STDERR "NAME: ".$class_self->name()."\n" if ($localDebug); + print STDERR "RAWNAME: ".$class_self->rawname()."\n" if ($localDebug); + print STDERR "TREE: $tree\n" if ($localDebug); + + $tree->apiOwner($class_self); +} + +# /*! +# @abstract +# Processes the cloned function/class object previously +# created by the {@link cloneAppleScriptFunctionContents} +# method. +# */ +sub processAppleScriptFunctionContents +{ + my $self = shift; + my $localDebug = 0; + + print STDERR "IN processAppleScriptFunctionContents\n" if ($localDebug); + $self->dbprint() if ($localDebug); + + # Grab the class object that contains the parsed contents of the function body. + my $class_self_ref = $self->{AS_CLASS_SELF}; + if (!$class_self_ref) { + die("Missing AS_CLASS_SELF for $self (".$self->name().")\n"); + } + my $class_self = ${$class_self_ref}; + bless($class_self, "HeaderDoc::HeaderElement"); + bless($class_self, $class_self->class()); + + # Copy the name and other info, now that it is known. + $class_self->{NAME} = $self->{NAME}; + $class_self->{RAWNAME} = $self->{RAWNAME}; + $class_self->{FORCENAME} = $self->{FORCENAME}; + $class_self->{NAMEREFS} = $self->{NAMEREFS}; + $class_self->{LANG} = $self->{LANG}; + $class_self->{OUTPUTFORMAT} = $self->{OUTPUTFORMAT}; + + # Determine the output mode. + my $xml_output = 0; + my $apiOwner = $self->apiOwner(); + if ($apiOwner->outputformat() eq "hdxml") { $xml_output = 1; } + + my $apioclass = ref($apiOwner) || $apiOwner; + + if ($apioclass =~ /HeaderDoc::Header/) { + $class_self->{HEADEROBJECT} = $apiOwner; + } else { + $class_self->{HEADEROBJECT} = $apiOwner->{HEADEROBJECT}; + } + + + print STDERR "OF: ".$apiOwner->outputformat()."\n" if ($localDebug); + + # Obtain the parse tree. + my $ptref = $class_self->{PARSETREE}; + bless($ptref, "HeaderDoc::ParseTree"); + my $parseTree = ${$ptref}; + + # Process the embedded tags and write out the contents. + $parseTree->processEmbeddedTags($xml_output, $class_self); + + # print STDERR "PROCESSED ".$class_self->name()."\n"; + my @has_classes = $class_self->classes(); + # print STDERR "WRITING ".scalar(@has_classes)." CLASSES\n"; + if (!scalar(@has_classes)) { + return undef; + } + + # Compute the name of the directory where the contents should be written (in HTML mode) + if (!$xml_output) { + my $className = $class_self->name(); + # for now, always shorten long names since some files may be moved to a Mac for browsing + if (1 || $isMacOS) {$className = &safeName(filename => $className);}; + $className = "parsedFunctionContents_$className"; + + # my $classesDir = $self->apiOwner()->classesDir(); + + # if (!$HeaderDoc::running_test) { + # if (! -e $classesDir) { + # unless (mkdir ("$classesDir", 0777)) {die ("Can't create output folder $classesDir. \n$!");}; + # } + # } + + my $classRootDir = $self->apiOwner()->{OUTPUTDIR}; + $class_self->outputDir("$classRootDir$pathSeparator$className"); + $class_self->{PARSEDPSEUDOCLASSNAME} = $className; + } + + # Write the output (in HTML mode) + if (!$xml_output) { + if ($class_self->classes()) { + print STDERR "CLASSES\n" if ($localDebug); + if (!$HeaderDoc::running_test) { + $class_self->writeHeaderElements(); + } + } else { + print STDERR "NO CLASSES\n" if ($localDebug); + } + } + $self->{ASCONTENTSPROCESSED} = 1; + + $parseTree->dbprint() if ($localDebug); + + return $class_self; +} + + 1; diff --git a/Modules/HeaderDoc/LineRange.pm b/Modules/HeaderDoc/LineRange.pm index 216deb7..82bfdc4 100644 --- a/Modules/HeaderDoc/LineRange.pm +++ b/Modules/HeaderDoc/LineRange.pm @@ -3,7 +3,7 @@ # Class name: LineRange # Synopsis: Helper code for availability (line ranges) # -# Last Updated: $Date: 2011/02/18 19:02:58 $ +# Last Updated: $Date: 2014/02/14 17:55:29 $ # # Copyright (c) 2006 Apple Computer, Inc. All rights reserved. # @@ -63,7 +63,6 @@ BEGIN { } } use HeaderDoc::HeaderElement; -use HeaderDoc::DBLookup; use HeaderDoc::Utilities qw(findRelativePath safeName printArray printHash sanitize); use File::Basename; use Cwd; @@ -79,7 +78,7 @@ use vars qw($VERSION @ISA); # In the git repository, contains the number of seconds since # January 1, 1970. # */ -$HeaderDoc::LineRange::VERSION = '$Revision: 1298084578 $'; +$HeaderDoc::LineRange::VERSION = '$Revision: 1392429329 $'; # Inheritance # @ISA = qw(HeaderDoc::HeaderElement); diff --git a/Modules/HeaderDoc/MinorAPIElement.pm b/Modules/HeaderDoc/MinorAPIElement.pm index 829fb90..d8d3df9 100644 --- a/Modules/HeaderDoc/MinorAPIElement.pm +++ b/Modules/HeaderDoc/MinorAPIElement.pm @@ -3,7 +3,7 @@ # Class name: MinorAPIElement # Synopsis: Class for parameters and members of structs, etc. # -# Last Updated: $Date: 2011/04/29 19:46:01 $ +# Last Updated: $Date: 2011/05/26 14:13:20 $ # # Copyright (c) 1999-2008 Apple Computer, Inc. All rights reserved. # @@ -79,7 +79,7 @@ package HeaderDoc::MinorAPIElement; -use HeaderDoc::Utilities qw(findRelativePath safeName printArray printHash); +use HeaderDoc::Utilities qw(findRelativePath safeName printArray printHash registerUID); use HeaderDoc::HeaderElement; use Carp qw(cluck); @@ -95,7 +95,7 @@ use vars qw($VERSION @ISA); # In the git repository, contains the number of seconds since # January 1, 1970. # */ -$HeaderDoc::MinorAPIElement::VERSION = '$Revision: 1304131561 $'; +$HeaderDoc::MinorAPIElement::VERSION = '$Revision: 1306444400 $'; # /*! @@ -373,10 +373,11 @@ sub group # @param self # This MinorAPIElement object. # @discussion -# For special declarations (Perl instance variables), +# For special declarations (Perl instance variables, +# function-local variables, and so on), # returns a synthesized declaration from -# {@link AUTODECLARATION}. Otherwise, hands off the -# request to the superclass, +# {@link //apple_ref/perl/data/HeaderDoc::MinorAPIElement/AUTODECLARATION AUTODECLARATION}. +# Otherwise, hands off the request to the superclass, # {@link //apple_ref/perl/cl/HeaderDoc::HeaderElement HeaderElement}. # */ sub declaration @@ -392,10 +393,11 @@ sub declaration # @param self # This MinorAPIElement object. # @discussion -# For special declarations (Perl instance variables), +# For special declarations (Perl instance variables, +# function-local variables, and so on), # returns a synthesized declaration from -# {@link AUTODECLARATION}. Otherwise, hands off the -# request to the superclass, +# {@link //apple_ref/perl/data/HeaderDoc::MinorAPIElement/AUTODECLARATION AUTODECLARATION}. +# Otherwise, hands off the request to the superclass, # {@link //apple_ref/perl/cl/HeaderDoc::HeaderElement HeaderElement}. # */ sub declarationInHTML @@ -407,17 +409,19 @@ sub declarationInHTML # /*! # @abstract -# Gets/sets the {@link AUTODECLARATION} flag. +# Gets/sets the +# {@link //apple_ref/perl/data/HeaderDoc::MinorAPIElement/AUTODECLARATION AUTODECLARATION} +# value. # @param self # This MinorAPIElement object. # @param AUTODECLARATION # The new value to set. # @discussion -# For special declarations (Perl instance variables), -# returns a synthesized declaration from -# {@link AUTODECLARATION}. Otherwise, hands off the -# request to the superclass, -# {@link //apple_ref/perl/cl/HeaderDoc::HeaderElement HeaderElement}. +# For special declarations (Perl instance variables, +# function-local variables, and so on), declaration functions +# return a synthesized declaration based on the +# {@link //apple_ref/doc/functionparam/HeaderDoc::MinorAPIElement/autodeclaration/AUTODECLARATION AUTODECLARATION} +# parameter. This function supports that. # */ sub autodeclaration { @@ -487,10 +491,19 @@ sub apiuid $fieldtype = "enumconstant"; } elsif ($apioclass eq "HeaderDoc::Function") { $fieldtype = "functionparam"; + if ($self->autodeclaration()) { + $fieldtype = "functionvar"; + } } elsif ($apioclass eq "HeaderDoc::Method") { $fieldtype = "methodparam"; + if ($self->autodeclaration()) { + $fieldtype = "methodvar"; + } } elsif ($apioclass eq "HeaderDoc::PDefine") { $fieldtype = "defineparam"; + if ($self->autodeclaration()) { + $fieldtype = "definevar"; + } $include_class = 0; } elsif ($apioclass eq "HeaderDoc::Struct") { $fieldtype = "structfield"; @@ -516,6 +529,8 @@ sub apiuid $self->{APIUID} = $uid; + registerUID($uid, $self->rawname(), $self); + return $uid; } } diff --git a/Modules/HeaderDoc/ParseTree.pm b/Modules/HeaderDoc/ParseTree.pm index 170c898..ac11b91 100644 --- a/Modules/HeaderDoc/ParseTree.pm +++ b/Modules/HeaderDoc/ParseTree.pm @@ -2,7 +2,7 @@ # # Class name: ParseTree # Synopsis: Used by headerdoc2html to hold parse trees -# Last Updated: $Date: 2011/05/03 14:50:47 $ +# Last Updated: $Date: 2014/03/06 11:20:09 $ # # Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved. # @@ -64,6 +64,14 @@ # The first child (descendant) node of this node. # @var PARENT # The parent node in the parse tree. +# @var lastDisplayNode +# The last node in the parse tree rooted at this node that +# should be displayed. Used only in AppleScript, to hide +# content nested inside functions while still parsing them +# fully. This is used for functions that are not inside +# scripts. For functions that are inside a script statement, +# the lastDisplayNode in the parser state object +# is used instead. # # @vargroup File information # @var FILENAME @@ -121,6 +129,22 @@ # @var ISAVAILABILITYMACRO # Indicates that this node is an availability macro. This # is used for wrapping content in both HTML and XML. +# @var RE_STATE +# Indicates that this node is part of a regular expression. +# This value contains one of the following values: +# +# RE_PREFIX (the optional "command" letters before +# the expression) +# +# RE_START (the opening slash or other delimiter) +# +# RE_PARTSEP (the intermediate delimiter or delimiters) +# +# RE_END (the trailing slash or other delimiter). +# +# Note that the trailing flags are not tagged in any special way +# because you can trivially distinguish the parse tree node that +# contains them by inspecting the node after RE_END. # # @vargroup Caches # @@ -140,7 +164,7 @@ package HeaderDoc::ParseTree; use strict; use vars qw($VERSION @ISA); -use HeaderDoc::Utilities qw(isKeyword parseTokens stringToFields casecmp emptyHDok complexAvailabilityToArray printHash validTag); +use HeaderDoc::Utilities qw(isKeyword parseTokens stringToFields doxyTagFilter casecmp emptyHDok complexAvailabilityToArray printHash validTag); use HeaderDoc::BlockParse qw(blockParse nspaces); use Carp qw(cluck); @@ -153,13 +177,15 @@ use Carp qw(cluck); # In the git repository, contains the number of seconds since # January 1, 1970. # */ -$HeaderDoc::ParseTree::VERSION = '$Revision: 1304459447 $'; +$HeaderDoc::ParseTree::VERSION = '$Revision: 1394133609 $'; ################ General Constants ################################### my $debugging = 0; my $apioDebug = 0; +# 0 = normal; 1 = debug; 2 = debug + backtraces my $treeDebug = 0; + my %defaults = ( # TOKEN => undef, # NEXT => undef, @@ -324,6 +350,7 @@ sub addSibling # print STDERR "addSibling $self\n"; print STDERR "addSibling $self \"$name\" HIDDEN: $hide\n" if ($treeDebug || $localDebug); + if ($treeDebug == 2) { cluck("backtrace"); } # Always hide siblings of descendants of elements that the parser # tells us to hide. Also spaces if they are the immediate successor @@ -389,6 +416,7 @@ sub addChild # print STDERR "addChild\n"; print STDERR "addChild to $self \"$name\"\n" if ($treeDebug); + if ($treeDebug == 2) { cluck("backtrace"); } # If the parser wants a node hidden, any children of such a node # should be hidden, as should any siblings of those children or their @@ -907,7 +935,9 @@ sub slowprev() my $self = shift; my $parent = $self->parent; + if (!$parent) { return undef; } my $fc = $parent->firstchild; + if ($self == $fc) { return undef; } while ($fc && $fc->next && ($fc->next != $self)) { $fc = $fc->next; } return $fc; } @@ -972,12 +1002,15 @@ sub processEmbeddedTags my $localDebug = 0; # if ($apio->isAPIOwner()) { $localDebug = 1; } - print STDERR "PET: $apio\n" if ($localDebug); + print STDERR "IN PET\n" if ($localDebug); + print STDERR "API IS $apio\n" if ($localDebug); print STDERR $apio->name()."\n" if ($localDebug); print STDERR "APIOLIST IS $apiolist\n" if ($localDebug);; - # for my $tempapio (@{$apiolist}) { - # print STDERR "RETURNED APIOLIST INCLUDES $tempapio\n"; - # } + if ($localDebug && $apiolist) { + for my $tempapio (@{$apiolist}) { + print STDERR "RETURNED APIOLIST INCLUDES $tempapio (".($tempapio->rawname()).")\n"; + } + } ### Make the APIO owner list unique. ### @@ -1056,11 +1089,18 @@ sub processEmbeddedTags my $hashtreecur = undef; my $hashtreeroot = undef; + print STDERR "BEFORE APIOprocessEmbeddedTagsRec for $apio (".$apio->name().")\n" if ($localDebug > 1); + print STDERR "PS: $parserState\n" if ($localDebug > 1); + cluck("bt\n") if ($localDebug > 1); + $self->dbprint() if ($localDebug > 1); + # $self->printTree() if ($localDebug > 1); + + $self->APIOprocessEmbeddedTagsRec($apiOwner, $case_sensitive, \%parseTokens, $lastnode, 0, 1, $enable_javadoc_comments, $xmlmode, $apio->lang(), $apio->sublang(), $hashtreecur, $hashtreeroot); } else { print STDERR "calling processEmbeddedTagsRec for $apio (".$apio->name().") for parse tree $self.\n" if ($localDebug); $self->processEmbeddedTagsRec($xmlmode, $eoDeclaration, \%parseTokens, $case_sensitive, $keywordhashref, $lastDeclaration, $curDeclaration, $pendingHDcomment, - $apio, $apiolist, $sodec, $lastnode, $enable_javadoc_comments); + $apio, $apiolist, $sodec, $lastnode, $enable_javadoc_comments, undef); } print STDERR "PETDONE\n" if ($localDebug); @@ -1395,7 +1435,7 @@ sub APIOprocessEmbeddedTagsRec($$$$$$$$) print STDERR "NNTOKEN: $nntoken\n" if ($localDebug); if ((($lang ne "tcl" && ($ntoken eq "!" || ($enable_javadoc_comments && $ntoken eq "*" && $nntoken !~ /^\*/))) || ($lang eq "tcl" && ($ntoken eq "/*" && $nntoken eq "!" && $firstchild->next()->next()->next()))) && - !$self->hidden()) { + ($lang eq "applescript" || (!$self->hidden()))) { print STDERR "NODECHECK: $self\n" if ($localDebug); # HDCOMMENT $self->dbprint() if ($localDebug); @@ -1454,7 +1494,7 @@ sub APIOprocessEmbeddedTagsRec($$$$$$$$) # @@@ DAG CHECK ME # $string =~ s/^\s*\*\s*//mg; - my $fieldref = stringToFields($string, $self->fullpath, $self->linenum, $xmlmode, $lang, $sublang); + my $fieldref = stringToFields(doxyTagFilter($string), $self->fullpath, $self->linenum, $xmlmode, $lang, $sublang); # print STDERR "APIOLIST AT INSERT IS $apiolist\n" if ($localDebug); # foreach my $owner (@{$apiolist}) { # print STDERR "X POSSOWNER of $self: $owner\n" if ($localDebug); @@ -1470,7 +1510,9 @@ sub APIOprocessEmbeddedTagsRec($$$$$$$$) # nested deeper than this is bogus (unless we hit a curly brace). print STDERR "skipochildren -> 1 [1]" if ($localDebug); $skipchildren = 1; - $next = $next->skipcurly($parseTokens{lbrace}, $ncurly); # nextTokenNoComments($parseTokens{soc}, $parseTokens{ilc}, $parseTokens{ilc_b}, 0, $enable_javadoc_comments); + if ($next) { + $next = $next->skipcurly($parseTokens{lbrace}, $ncurly); # nextTokenNoComments($parseTokens{soc}, $parseTokens{ilc}, $parseTokens{ilc_b}, 0, $enable_javadoc_comments); + } if ($localDebug) { print STDERR "NEXT IS $next ("; if ($next) {print STDERR $next->token(); } @@ -1508,7 +1550,7 @@ sub APIOprocessEmbeddedTagsRec($$$$$$$$) } # @@@ DAG CHECKME LEADING STARS # $string =~ s/^\s*\*\s*//mg; - my $fieldref = stringToFields($string, $self->fullpath, $self->linenum, $xmlmode, $lang, $sublang); + my $fieldref = stringToFields(doxyTagFilter($string), $self->fullpath, $self->linenum, $xmlmode, $lang, $sublang); # foreach my $owner (@{$apiolist}) { print STDERR "POSSOWNER of $self: $apiOwner\n" if ($localDebug); if ($apiOwner && $apiOwner->isAPIOwner()) { @@ -1620,6 +1662,7 @@ sub processEmbeddedTagsRec my $sodec = shift; my $lastTreeNode = shift; my $enable_javadoc_comments = shift; + my $ASterminator = shift; my %parseTokens = %{$parseTokensRef}; @@ -1645,7 +1688,7 @@ print STDERR "PETREC\n" if ($localDebug); print STDERR "PENDING COMMENT: $pendingHDcomment\n" if ($localDebug); print STDERR "LAST DECLARATION: $lastDeclaration\n" if ($localDebug); - if (!$self) { return ($eoDeclaration, $pendingHDcomment, $continue); } + if (!$self) { return ($eoDeclaration, $pendingHDcomment, $continue, $ASterminator); } my $apioclass = ref($apio) || $apio; if ($apioclass =~ /HeaderDoc::PDefine/) { @@ -1660,6 +1703,14 @@ print STDERR "LAST DECLARATION: $lastDeclaration\n" if ($localDebug); } } + if ($apio->lang() eq "applescript") { + if (!$ASterminator) { + if ($self->token eq "(") { + $ASterminator = $self; + } + } + } + if ($self == $lastTreeNode) { print STDERR "CONTINUE -> 0\n" if ($localDebug); $continue = 0; @@ -1711,13 +1762,14 @@ print STDERR "LAST DECLARATION: $lastDeclaration\n" if ($localDebug); } if ($string =~ /^\s*\!/o) { $string =~ s/^\s*\!//so; - my $tagstring =~ s/^\s*\@//so; + my $tagstring = $string; + $tagstring =~ s/^\s*\@//so; print STDERR "EOD $eoDeclaration NT $ntoken STR $string\n" if ($localDebug);; if ((($eoDeclaration && $lastDeclaration =~ /[a-zA-Z]/) || !$ntoken || $ntoken =~ /[)}]/o || casecmp($ntoken, $parseTokens{rbrace}, $case_sensitive)) && - ($string !~ /^\s*\@/o || !validTag($tagstring, 1))) { + ($string !~ /^\s*\@/o || !validTag($tagstring, 0))) { if (!$inBlockDefine) { $string =~ s/\@abstract/ /sg; @@ -1778,11 +1830,14 @@ print STDERR "LAST DECLARATION: $lastDeclaration\n" if ($localDebug); } } $string =~ s/^\s*//so; - my $tagstring =~ s/^\s*\@//so; - if ($string =~ /^\s*\@/o && validTag($tagstring, 1)) { # $string =~ /^\s*\@/o + my $tagstring = $string; + $tagstring =~ s/^\s*\@//so; + # warn("STR: $string TAGSTR: $tagstring\n"); + # warn(validTag("", 0)." != ".validTag($tagstring, 0)); + if ($string =~ /^\s*\@/o && validTag($tagstring, 0)) { # $string =~ /^\s*\@/o print STDERR "COMMENTSTRING: $string\n" if ($localDebug); - my $fieldref = stringToFields($string, $fullpath, $linenum, $xmlmode, $apio->lang(), $apio->sublang()); + my $fieldref = stringToFields(doxyTagFilter($string), $fullpath, $linenum, $xmlmode, $apio->lang(), $apio->sublang()); # print STDERR "APIO: $apio\n"; foreach my $owner (@{$apiolist}) { my $copy = $fieldref; @@ -1814,12 +1869,15 @@ print STDERR "LAST DECLARATION: $lastDeclaration\n" if ($localDebug); } if (!$HeaderDoc::dumb_as_dirt) { # Drop this comment from the output. - if ($xmlmode) { + if ($xmlmode || ($apio->lang() eq "applescript")) { # We were doing this for HTML when we needed to # be able to reparse the tree after copying # it to a cloned data type. This is no longer # needed, and the old method (above) is slightly # faster. + # + # However, we still have to use this approach + # for AppleScript, for that reason. $self->hidden(1); $skipchildren = 1; } else { $self->{TOKEN} = ""; @@ -1851,7 +1909,7 @@ print STDERR "LAST DECLARATION: $lastDeclaration\n" if ($localDebug); my $fullpath = $apio->fullpath(); my $linenum = $apio->linenum(); - my $fieldref = stringToFields($string, $fullpath, $linenum, $xmlmode, $apio->lang(), $apio->sublang()); + my $fieldref = stringToFields(doxyTagFilter($string), $fullpath, $linenum, $xmlmode, $apio->lang(), $apio->sublang()); print STDERR "COMMENTSTRING: $string\n" if ($localDebug); print STDERR "OWNERSTART\n" if ($localDebug); foreach my $owner (@{$apiolist}) { @@ -1894,13 +1952,15 @@ print STDERR "LAST DECLARATION: $lastDeclaration\n" if ($localDebug); if ($firstchild && !$skipchildren) { my $nestallowed = commentsNestedIn($token, $parseTokens{soc}, $parseTokens{eoc}, $parseTokens{ilc}, $parseTokens{ilc_b}, $parseTokens{lbrace}, $case_sensitive); if ($nestallowed == 1) { - my $newcontinue; - ($eoDeclaration, $pendingHDcomment, $newcontinue) = $firstchild->processEmbeddedTagsRec($xmlmode, $eoDeclaration, $parseTokensRef, $case_sensitive, $keywordhashref, "", "", "", $apio, $apiolist, $sodec, $lastTreeNode, $enable_javadoc_comments); + my $newcontinue; my $newASterminator; + ($eoDeclaration, $pendingHDcomment, $newcontinue, $newASterminator) = $firstchild->processEmbeddedTagsRec($xmlmode, $eoDeclaration, $parseTokensRef, $case_sensitive, $keywordhashref, "", "", "", $apio, $apiolist, $sodec, $lastTreeNode, $enable_javadoc_comments, $ASterminator); if ($continue) { $continue = $newcontinue; } + if (!$ASterminator) { $ASterminator = $newASterminator; } } else { - my $newcontinue; - ($eoDeclaration, $pendingHDcomment, $newcontinue) = $firstchild->processEmbeddedTagsRec($xmlmode, $eoDeclaration, $parseTokensRef, $case_sensitive, $keywordhashref, "", "$curDeclaration", "", $apio, $apiolist, $sodec, $lastTreeNode, $enable_javadoc_comments); + my $newcontinue; my $newASterminator; + ($eoDeclaration, $pendingHDcomment, $newcontinue, $newASterminator) = $firstchild->processEmbeddedTagsRec($xmlmode, $eoDeclaration, $parseTokensRef, $case_sensitive, $keywordhashref, "", "$curDeclaration", "", $apio, $apiolist, $sodec, $lastTreeNode, $enable_javadoc_comments, $ASterminator); if ($continue) { $continue = $newcontinue; } + if (!$ASterminator) { $ASterminator = $newASterminator; } } $curDeclaration .= textTree($firstchild); } elsif ($firstchild && !$skipchildren) { @@ -1953,7 +2013,7 @@ print STDERR "LAST DECLARATION: $lastDeclaration\n" if ($localDebug); my $fullpath = $apio->fullpath(); my $linenum = $apio->linenum(); - my $fieldref = stringToFields($string, $fullpath, $linenum, $xmlmode, $apio->lang(), $apio->sublang()); + my $fieldref = stringToFields(doxyTagFilter($string), $fullpath, $linenum, $xmlmode, $apio->lang(), $apio->sublang()); print STDERR "COMMENTSTRING: $string\n" if ($localDebug); foreach my $owner (@{$apiolist}) { my $copy = $fieldref; @@ -1977,15 +2037,19 @@ print STDERR "LAST DECLARATION: $lastDeclaration\n" if ($localDebug); } } # $sodec = $oldsodec; + if ($ASterminator == $self) { + $continue = 0; + } + if ($next && $continue) { - ($eoDeclaration, $pendingHDcomment, $continue) = $next->processEmbeddedTagsRec($xmlmode, $eoDeclaration, $parseTokensRef, $case_sensitive, $keywordhashref, $lastDeclaration, $curDeclaration, $pendingHDcomment, $apio, $apiolist, $sodec, $lastTreeNode, $enable_javadoc_comments); + ($eoDeclaration, $pendingHDcomment, $continue) = $next->processEmbeddedTagsRec($xmlmode, $eoDeclaration, $parseTokensRef, $case_sensitive, $keywordhashref, $lastDeclaration, $curDeclaration, $pendingHDcomment, $apio, $apiolist, $sodec, $lastTreeNode, $enable_javadoc_comments, $ASterminator); } - return ($eoDeclaration, $pendingHDcomment, $continue); + return ($eoDeclaration, $pendingHDcomment, $continue, $ASterminator); } # THIS CODE USED TO PROCESS COMMENTS WHENEVER IT IS TIME. - # my $fieldref = stringToFields($string, $fullpath, $linenum, $xmlmode, $lang, $sublang); + # my $fieldref = stringToFields(doxyTagFilter($string), $fullpath, $linenum, $xmlmode, $lang, $sublang); # $apio->processComment($fieldref, 1, $self, $parseTokens{soc}, $parseTokens{ilc}, $parseTokens{ilc_b}, $self, $hashtreecur, $hashtreeroot); # $apio->{APIREFSETUPDONE} = 0; @@ -2069,6 +2133,10 @@ sub printTree { # */ sub textTree { my $self = shift; + my $nohidden = 0; + if (@_) { + $nohidden = shift; + } my $parserState = $self->parserState(); my $lastnode = undef; @@ -2081,7 +2149,7 @@ sub textTree { print STDERR "TEXTTREE: LASTNODE: $lastnode\n" if ($localDebug); if ($lastnode && $localDebug) { print STDERR "LASTNODE TEXT: \"".$lastnode->token()."\"\n"; } - my ($string, $continue) = $self->textTreeSub(0, "", "", "", $lastnode); + my ($string, $continue) = $self->textTreeSub(0, $nohidden, "", "", "", $lastnode); return $string; } @@ -2108,9 +2176,14 @@ sub textTreeNC { # $requiredregexp, $propname, $objcdynamicname, $objcsynthesizename, $moduleregexp, $definename, # $functionisbrace, $classisbrace, $parseTokens{lbraceconditionalre}, $parseTokens{lbraceunconditionalre}, $assignmentwithcolon, # $labelregexp, $parmswithcurlybraces, $superclasseswithcurlybraces, $parseTokens{soc}) = parseTokens($lang, $sublang); + + my $nohidden = 0; + if (@_) { + $nohidden = shift; + } my %parseTokens = %{parseTokens($lang, $sublang)}; - my ($string, $continue) = $self->textTreeSub(1, $parseTokens{soc}, $parseTokens{ilc}, $parseTokens{ilc_b}); + my ($string, $continue) = $self->textTreeSub(1, $nohidden, $parseTokens{soc}, $parseTokens{ilc}, $parseTokens{ilc_b}); return $string; } @@ -2122,6 +2195,8 @@ sub textTreeNC { # The top of the tree/subtree to dump. # @param nc # Set to 1 if comments should be dropped, else 0. +# @param nh +# Set to 1 if hidden tokens should be dropped, else 0. # @param soc # The start-of-comment token for the current programming language. # Obtained by a call to @@ -2142,6 +2217,7 @@ sub textTreeSub { my $self = shift; my $nc = shift; + my $nh = shift; my $soc = shift; my $ilc = shift; my $ilc_b = shift; @@ -2172,6 +2248,11 @@ sub textTreeSub $skip = 1; } } + if ($nh) { + if ($self->hidden()) { + $skip = 1; + } + } if (!$skip) { $string .= $token; @@ -2181,7 +2262,7 @@ sub textTreeSub if ($self->{FIRSTCHILD}) { my $node = $self->{FIRSTCHILD}; bless($node, "HeaderDoc::ParseTree"); - my ($newstring, $newcontinue) = $node->textTreeSub($nc, $soc, $ilc, $ilc_b, $lastnode); + my ($newstring, $newcontinue) = $node->textTreeSub($nc, $nh, $soc, $ilc, $ilc_b, $lastnode); if ($continue) { $continue = $newcontinue; } $string .= $newstring; } @@ -2192,7 +2273,7 @@ sub textTreeSub if ($self->{NEXT}) { my $node = $self->{NEXT}; bless($node, "HeaderDoc::ParseTree"); - my ($newstring, $newcontinue) = $node->textTreeSub($nc, $soc, $ilc, $ilc_b, $lastnode); + my ($newstring, $newcontinue) = $node->textTreeSub($nc, $nh, $soc, $ilc, $ilc_b, $lastnode); $continue = $newcontinue; $string .= $newstring; } @@ -2283,9 +2364,14 @@ sub xmlTree { # $typedefname, $varname, $constname, $structisbrace, $parseTokens{macronames}); my $lastnode = undef; + my $lastDisplayNode = undef; my $parserState = $self->parserState(); if ($parserState) { $lastnode = $parserState->{lastTreeNode}; + $lastDisplayNode = $parserState->{lastDisplayNode}; + } + if ((!$lastDisplayNode) && $self->{lastDisplayNode}) { + $lastDisplayNode = $self->{lastDisplayNode}; } # my ($sotemplate, $eotemplate, $operator, $parseTokens{soc}, $parseTokens{eoc}, $parseTokens{ilc}, $parseTokens{ilc_b}, $sofunction, @@ -2308,9 +2394,10 @@ sub xmlTree { xmlmode => 1, newlen => 0, breakable => 0, inMacro => 0, inEnum => 0, seenEquals => 0, lastKeyword => "", lastnstoken => "", lastTreeNode => $lastnode, lastTokenType => "", spaceSinceLastToken => 0, inAttribute => 0, inRaises => 0, inTypeOf => 0, - drop_pdefine_contents => $drop_pdefine_contents, ASinName => 0); + drop_pdefine_contents => $drop_pdefine_contents, ASinName => 0, afteradvisoryspace => 0, + lastDisplayNode => $lastDisplayNode); - my ($retvalref, $junka, $junkb, $junkc, $junkd, $junke, $lastTokenType, $spaceSinceLastToken) = $self->colorTreeSub($ctstate); + my ($retvalref, $junka, $junkb, $junkc, $junkd, $junke, $lastTokenType, $spaceSinceLastToken, $junk_afteradvisoryspace) = $self->colorTreeSub($ctstate); my $retval = ${$retvalref}; # my $retval = ""; @@ -2396,10 +2483,16 @@ sub htmlTree { # colorizer goes here my $lastnode = undef; + my $lastDisplayNode = undef; my $parserState = $self->parserState(); if ($parserState) { $lastnode = $parserState->{lastTreeNode}; + $lastDisplayNode = $parserState->{lastDisplayNode}; } + if ((!$lastDisplayNode) && $self->{lastDisplayNode}) { + $lastDisplayNode = $self->{lastDisplayNode}; + } + # print STDERR "TN: $self LTN: $lastnode LDN: $lastDisplayNode\n"; # if ($lang eq "shell") { # $keep_whitespace = 1; @@ -2431,9 +2524,10 @@ sub htmlTree { xmlmode => 0, newlen => 0, breakable => 0, inMacro => 0, inEnum => 0, seenEquals => 0, lastKeyword => "", lastnstoken => "", lastTreeNode => $lastnode, lastTokenType => "", spaceSinceLastToken => 0, inAttribute => 0, inRaises => 0, inTypeOf => 0, - drop_pdefine_contents => $drop_pdefine_contents, ASinName => 0); + drop_pdefine_contents => $drop_pdefine_contents, ASinName => 0, afteradvisoryspace => 0, + lastDisplayNode => $lastDisplayNode); - my ($retvalref, $junka, $junkb, $junkc, $junkd, $junke, $lastTokenType, $spaceSinceLastToken) = $self->colorTreeSub($ctstate); + my ($retvalref, $junka, $junkb, $junkc, $junkd, $junke, $lastTokenType, $spaceSinceLastToken, $junk_afteradvisoryspace) = $self->colorTreeSub($ctstate); my $retval = ${$retvalref}; # my $retval = ""; @@ -2787,6 +2881,21 @@ sub isMacro return 0; } +# /*! +# @abstract Prints the contents of a colorTreeSub state object. +# */ +sub dumpCTState +{ + my $ctstateref = shift; + my %ctstate = %{$ctstateref}; + + print STDERR "DUMPING CTSTATE:\n\n"; + foreach my $key (keys %ctstate) { + print " $key => ".$ctstate{$key}."\n"; + } + print "\n\n"; +} + # /*! # @abstract # Returns an HTML or XML representation of a parse tree/subtree. @@ -2963,12 +3072,56 @@ sub colorTreeSub my $self = shift; my $ctstateref = shift; -# print STDERR "IN COLORTREESUB\n"; + my $localDebug = 0; + my $psDebug = 0; + my $treeDebug = 0; + my $dropDebug = 0; + my $tokenDebug = 0; + my $codePathDebug = 0; + my $rubyDebug = 0; + my $tokenPrintDebug = 0; + my $advisorySpaceDebug = 0; my $continue = 1; my %ctstate = %{$ctstateref}; - if ($self == $ctstate{lastTreeNode}) { $continue = 0; } + my $token = $self->{TOKEN}; + my $ntoken = $self->nextpeek(); + + my $tokenname = $token; + if ($token eq "\n") { $tokenname = "[NEWLINE]"; } + elsif ($token eq "\r") { $tokenname = "[CARRIAGE RETURN]"; } + elsif (!length($token)) { $tokenname = "[EMPTY STRING]"; } + else { $tokenname = "\"".$tokenname."\""; } + + my $ntokenname = $ntoken; + if ($ntoken eq "\n") { $ntokenname = "[NEWLINE]"; } + elsif ($ntoken eq "\r") { $ntokenname = "[CARRIAGE RETURN]"; } + elsif (!length($ntoken)) { $ntokenname = "[EMPTY STRING]"; } + else { $ntokenname = "\"".$ntokenname."\""; } + + my $lastnstokenname = $ctstate{lastnstoken}; + if ($ctstate{lastnstoken} eq "\n") { $lastnstokenname = "[NEWLINE]"; } + elsif ($ctstate{lastnstoken} eq "\r") { $lastnstokenname = "[CARRIAGE RETURN]"; } + elsif (!length($ctstate{lastnstoken})) { $lastnstokenname = "[EMPTY STRING]"; } + else { $lastnstokenname = "\"".$lastnstokenname."\""; } + + print STDERR "***** TOKEN: ".$tokenname." *****\n" if ($codePathDebug || $localDebug || $tokenDebug || $tokenPrintDebug); + + + + + +# print STDERR "IN COLORTREESUB\n"; + + if ($self == $ctstate{lastTreeNode}) { + print STDERR "Node is last node in tree. Ending after this node.\n" if ($localDebug || $codePathDebug); + $continue = 0; + } + + dumpCTState(\%ctstate) if ($localDebug); + + print STDERR "NEWLEN: ".$ctstate{newlen}."\n" if ($localDebug); my %parseTokens = %{$ctstate{parseTokensRef}}; my %macroList = %{$parseTokens{macronames}}; @@ -2985,13 +3138,6 @@ sub colorTreeSub # This cache slows things down now that it works.... # if ($self->{CTSUB}) { return (\$self->{CTSTRING}, $self->{CTSUB}); } - my $localDebug = 0; - my $psDebug = 0; - my $treeDebug = 0; - my $dropDebug = 0; - my $tokenDebug = 0; - my $codePathDebug = 0; - my $rubyDebug = 0; my $keep_all_newlines = 0; @@ -3018,11 +3164,11 @@ sub colorTreeSub my $nextprespace = ""; my $string = ""; my $tailstring = ""; - my $token = $self->{TOKEN}; my $escapetoken = ""; my ($case_sensitive, $keywordhashref) = $ctstate{apio}->keywords(); my $tokennl = 0; if ($token =~ /^[\r\n]/o) { $tokennl = 1; } + if (($token eq "\t" || $token =~ /^ +$/) && (!$ctstate{keep_whitespace})) { $token = " "; } if ($ctstate{inQuote} == 3) { $keep_all_newlines = 1; @@ -3032,6 +3178,21 @@ sub colorTreeSub $ctstate{prespace} = ""; $nextprespace = ""; } + + if (length($token) && (!$tokennl)) { + if ($ctstate{afteradvisoryspace}) { + # Remove a single space if we're after a newline that + # got converted into a space + print STDERR "OLD AASTOKEN: \"$token\"\n" if ($localDebug || $advisorySpaceDebug || $codePathDebug); + $token =~ s/^ //; + $ctstate{afteradvisoryspace} = 0; + print STDERR "AASTOKEN NOW: \"$token\"\n" if ($localDebug || $advisorySpaceDebug || $codePathDebug); + print STDERR "AAS -> 0\n" if ($localDebug || $advisorySpaceDebug || $codePathDebug); + } + } + + print "keep_all_newlines: $keep_all_newlines\n" if ($localDebug); + my $tokenIsKeyword = isKeyword($token, $keywordhashref, $case_sensitive); print STDERR "TIK: $tokenIsKeyword\n" if ($localDebug); @@ -3043,7 +3204,6 @@ print STDERR "TIK: $tokenIsKeyword\n" if ($localDebug); print STDERR "IQ is ".$ctstate{inQuote}."\n" if ($rubyDebug || $colorDebug); my $ctoken = $self->childpeeknc($parseTokens{soc}, $parseTokens{ilc}, $parseTokens{ilc_b}); - my $ntoken = $self->nextpeek(); my $ntokennc = $self->nextpeeknc($parseTokens{soc}, $parseTokens{ilc}, $parseTokens{ilc_b}); my $nntokennc = $self->nextnextpeeknc($parseTokens{soc}, $parseTokens{ilc}, $parseTokens{ilc_b}); my $tokenType = undef; @@ -3073,21 +3233,7 @@ print STDERR "TIK: $tokenIsKeyword\n" if ($localDebug); $ctstate{tokenAccum} = ""; } - if ($treeDebug || $localDebug || $codePathDebug) { - my $tokenname = $token; - if ($token eq "\n") { $tokenname = "[NEWLINE]"; } - elsif ($token eq "\r") { $tokenname = "[CARRIAGE RETURN]"; } - - my $ntokenname = $ntoken; - if ($ntoken eq "\n") { $ntokenname = "[NEWLINE]"; } - elsif ($ntoken eq "\r") { $ntokenname = "[CARRIAGE RETURN]"; } - - my $lastnstokenname = $ctstate{lastnstoken}; - if ($ctstate{lastnstoken} eq "\n") { $lastnstokenname = "[NEWLINE]"; } - elsif ($ctstate{lastnstoken} eq "\r") { $lastnstokenname = "[CARRIAGE RETURN]"; } - - print STDERR "TOKEN: $tokenname NTOKEN: $ntokenname LASTNSTOKEN: $lastnstokenname IC: ".$ctstate{inComment}."\n" if ($treeDebug || $localDebug || $codePathDebug); - } + print STDERR "TOKEN: $tokenname NTOKEN: $ntokenname LASTNSTOKEN: $lastnstokenname IC: ".$ctstate{inComment}."\n" if ($treeDebug || $localDebug || $codePathDebug); print STDERR "OCC: ".$ctstate{inObjCMethod}."\n" if ($colorDebug || $localDebug); print STDERR "HIDDEN: $hidden\n" if ($localDebug); @@ -3163,7 +3309,7 @@ print STDERR "inQuote: ".$ctstate{inQuote}."\noldInQuote: $oldInQuote\ninComment print STDERR "oldInMacro: $oldInMacro\noldInComment: $oldInComment\n" if ($localDebug); # print STDERR "TOKEN: $token\n" if ($localDebug); - print STDERR "TOKEN: $token ASINNAME: ".$ctstate{ASinName}."\n" if ($localDebug); + print STDERR "TOKEN: $tokenname ASINNAME: ".$ctstate{ASinName}."\n" if ($localDebug); if ($ctstate{inEnum}) { # If we see this, anything nested below here is clearly not a union. @@ -3280,9 +3426,14 @@ print STDERR "oldInMacro: $oldInMacro\noldInComment: $oldInComment\n" if ($local $leavingComment = 1; $ctstate{inComment} = 0; } elsif ($tokennl && ($ntoken !~ /^[\r\n]/o || $ctstate{keep_whitespace} || $keep_all_newlines)) { + my $ignored_newline = 1; + + print STDERR " TOKENNL (KW: ".$ctstate{keep_whitespace}.", KAN: $keep_all_newlines)\n" if ($localDebug || $codePathDebug); + if ($ctstate{ASinName}) { $ctstate{ASinName} = 0; print STDERR "ASinName -> 0 [4]\n" if ($localDebug); + $ignored_newline = 0; } if ($ctstate{inComment} == 2) { print STDERR " EOL INCOMMENT: END ILCOMMENT [1]\n" if ($localDebug || $codePathDebug); @@ -3297,21 +3448,27 @@ print STDERR "oldInMacro: $oldInMacro\noldInComment: $oldInComment\n" if ($local $mustbreak = 1; # $token = ""; $drop = 1; + $ignored_newline = 0; } elsif ($ctstate{inMacro} || $keep_all_newlines) { print STDERR " EOL INMACRO\n" if ($localDebug || $codePathDebug); $mustbreak = 1; $ctstate{newlen} = 0; + $ignored_newline = 0; } elsif ($ctstate{inComment}) { print STDERR " EOL INCOMMENT\n" if ($localDebug || $codePathDebug); $mustbreak = 1; $ctstate{newlen} = 0; # $token = ""; $drop = 1; + $ignored_newline = 0; + } + + if (!$ignored_newline) { + $ctstate{breakable} = 0; + $nextbreakable = 0; + # $nextprespace = nspaces(4 * $ctstate{depth}); + $ctstate{newlen} = 0; } - $ctstate{breakable} = 0; - $nextbreakable = 0; - # $nextprespace = nspaces(4 * $ctstate{depth}); - $ctstate{newlen} = 0; # } elsif ($ntoken =~ /^[\r\n]/o) { # print STDERR " NEXT TOKEN IS NLCR\n" if ($localDebug || $codePathDebug); # $ctstate{breakable} = 0; @@ -3472,6 +3629,7 @@ print STDERR "oldInMacro: $oldInMacro\noldInComment: $oldInComment\n" if ($local $tokenType = "function"; } elsif ($token eq ":" && $ctoken) { # Don't indent Objective-C method parts so far. + print STDERR " COLON AND CTOKEN\n" if ($localDebug || $codePathDebug); $ctstate{depth} = $ctstate{depth} - 1; # We'll change it back before the next token. } elsif ($ntokennc eq "(" && !$ctstate{seenEquals} && !$ctstate{inAttribute} && !$ctstate{inRaises} && !$ctstate{inTypeOf}) { # Upcoming parenthesis handling @@ -3526,17 +3684,22 @@ print STDERR "oldInMacro: $oldInMacro\noldInComment: $oldInComment\n" if ($local $nextbreakable = 3; } } elsif (($ctstate{lang} eq "python") && ($token eq "\"\"\"")) { + print STDERR " IRQ STARTEND\n" if ($localDebug || $codePathDebug); if ($ctstate{inQuote}) { $ctstate{inQuote} = 0; } else { $ctstate{inQuote} = 3; } } elsif ($ruby && ($token eq "%{" || $token eq "%Q{")) { + print STDERR " IRQ START[1]\n" if ($localDebug || $codePathDebug); $ctstate{inQuote} = 3; $ctstate{inRubyQuote} = 1; } elsif ($ruby && ($token eq "%/")) { + print STDERR " IRQ PERCENTSLASH\n" if ($localDebug || $codePathDebug); $ctstate{inQuote} = 3; $ctstate{inRubyQuote} = 1; } elsif ($ruby && ($token eq "<<")) { + print STDERR " IRQ START[2]\n" if ($localDebug || $codePathDebug); $ctstate{inQuote} = 3; $ctstate{inRubyQuote} = 2; # quote coloring starts after next token. print STDERR "IRQ -> 2\n" if ($rubyDebug || $colorDebug); } elsif ($ruby && ($ctstate{inRubyQuote} == 2)) { + print STDERR " IRQ\n" if ($localDebug || $codePathDebug); $ctstate{inRubyQuote} = 1; print STDERR "IRQ 2 -> 1\n" if ($rubyDebug || $colorDebug); } elsif ($token =~ /^\"/o && !$ctstate{inRubyQuote}) { @@ -3593,11 +3756,13 @@ print STDERR "oldInMacro: $oldInMacro\noldInComment: $oldInComment\n" if ($local } } } elsif ($ctstate{prespace} ne "" && ($token =~ /^\)/o || casecmp($token, $parseTokens{rbrace}, $case_sensitive))) { + print " CPAREN OR RBRACE\n" if ($codePathDebug); print STDERR "PS: ".length($ctstate{prespace})." -> " if ($psDebug); if (!$ctstate{keep_whitespace}) { $ctstate{prespace} = nspaces(4 * ($ctstate{depth}-1)); } print STDERR length($ctstate{prespace})."\n" if ($psDebug); $mustbreak = 2; } elsif (casecmp($token, $parseTokens{rbrace}, $case_sensitive)) { + print " RBRACE\n" if ($codePathDebug); if (!$ctstate{keep_whitespace}) { $ctstate{prespace} = nspaces(4 * ($ctstate{depth}-1)); } print STDERR length($ctstate{prespace})."\n" if ($psDebug); $mustbreak = 2; @@ -3713,11 +3878,15 @@ print STDERR "NB: $nextbreakable\n" if ($localDebug); print STDERR "TESTTYPE: $tokenType\n" if ($localDebug); if ($ctstate{inObjCMethod}) { + print STDERR "OCC METHOD OVERRIDE: " if ($localDebug); $nextbreakable = 0; $ctstate{breakable} = 0; $mustbreak = 0; if ($ntoken eq ":" && $tokenType eq "function") { $ctstate{breakable} = 1; + print STDERR "BREAKABLE\n" if ($localDebug); + } else { + print STDERR "NOT BREAKABLE\n" if ($localDebug); } } @@ -3725,7 +3894,7 @@ print STDERR "TESTTYPE: $tokenType\n" if ($localDebug); print STDERR "PASREC VAR\n" if ($localDebug); $tokenType = "var"; } - else { print STDERR "TYPE: ".$ctstate{type}." TT: ".$ctstate{tokenType}."\n" if ($localDebug); } + else { print STDERR "TYPE: ".$ctstate{type}." TT: ".$tokenType."\n" if ($localDebug); } print STDERR "IM: ".$ctstate{inMacro}."\n" if ($localDebug); if (!$ctstate{inComment} && $token =~ /^\s/o && !$tokennl && ($mustbreak || !$ctstate{newlen}) && (!$ctstate{keep_whitespace})) { @@ -3741,6 +3910,8 @@ print STDERR "TESTTYPE: $tokenType\n" if ($localDebug); print STDERR "dropping newline\n" if ($localDebug); $drop = 1; $string .= " "; + $ctstate{afteradvisoryspace} = 1; + print STDERR "AAS -> 1 [drop]\n" if ($localDebug || $advisorySpaceDebug || $codePathDebug); } else { $mustbreak = 1; } @@ -3886,6 +4057,7 @@ print STDERR "TESTTYPE: $tokenType\n" if ($localDebug); my $newstring = ""; my $node = $self->{FIRSTCHILD}; my $newstringref = undef; + if ($node && $continue) { if ($nospaceafter == 1) { $nospaceafter = 0; } print STDERR "BEGIN CHILDREN\n" if ($localDebug || $colorDebug || $treeDebug); @@ -3893,11 +4065,17 @@ print STDERR "TESTTYPE: $tokenType\n" if ($localDebug); my $childctstate = newCTState(\%ctstate, depth => $ctstate{depth} + 1, breakable => $nextbreakable); - ($newstringref, $ctstate{newlen}, $nextbreakable, $ctstate{prespace}, $ctstate{lastnstoken}, $continue, $ctstate{lastTokenType}, $ctstate{spaceSinceLastToken}) = $node->colorTreeSub($childctstate); + ($newstringref, $ctstate{newlen}, $nextbreakable, $ctstate{prespace}, $ctstate{lastnstoken}, $continue, $ctstate{lastTokenType}, $ctstate{spaceSinceLastToken}, $ctstate{afteradvisoryspace}) = $node->colorTreeSub($childctstate); $newstring = ${$newstringref}; print STDERR "END CHILDREN\n" if ($localDebug || $colorDebug || $treeDebug); } + + if ($self == $ctstate{lastDisplayNode} ) { + print STDERR "Node is last node in tree (LDN/AS). Ending after this node.\n" if ($localDebug || $codePathDebug); + $continue = 0; + } + $string .= $newstring; $newstring = ""; print STDERR "SET STRING TO $string\n" if ($localDebug); @@ -3953,8 +4131,9 @@ print STDERR "TESTTYPE: $tokenType\n" if ($localDebug); } print STDERR "CONTINUING TO NODE \"".$node->token."\".\n" if ($localDebug); if ($node) { - my $nextctstate = newCTState(\%ctstate, breakable => $nextbreakable); - ($newstringref, $ctstate{newlen}, $nextbreakable, $ctstate{prespace}, $ctstate{lastnstoken}, $continue, $ctstate{lastTokenType}, $ctstate{spaceSinceLastToken}) = $node->colorTreeSub($nextctstate); + my $nextctstate = newCTState(\%ctstate, breakable => $nextbreakable, + afteradvisoryspace => $ctstate{afteradvisoryspace}); + ($newstringref, $ctstate{newlen}, $nextbreakable, $ctstate{prespace}, $ctstate{lastnstoken}, $continue, $ctstate{lastTokenType}, $ctstate{spaceSinceLastToken}, $ctstate{afteradvisoryspace}) = $node->colorTreeSub($nextctstate); $newstring = ${$newstringref}; } } @@ -3963,7 +4142,7 @@ print STDERR "TESTTYPE: $tokenType\n" if ($localDebug); # $self->{CTSTRING} = $string; # $self->{CTSUB} = ($ctstate{newlen}, $nextbreakable, $ctstate{prespace}, $ctstate{lastnstoken}); - return (\$string, $ctstate{newlen}, $nextbreakable, $ctstate{prespace}, $ctstate{lastnstoken}, $continue, $ctstate{lastTokenType}, $ctstate{spaceSinceLastToken}); + return (\$string, $ctstate{newlen}, $nextbreakable, $ctstate{prespace}, $ctstate{lastnstoken}, $continue, $ctstate{lastTokenType}, $ctstate{spaceSinceLastToken}, $ctstate{afteradvisoryspace}); } # /*! @@ -4064,11 +4243,13 @@ sub dbprintrec } my $HYPHEN = "-"; my $psString = ""; + my $reStateString = ""; + if ($self->{RE_STATE}) { $reStateString = " ".$self->{RE_STATE}; } if ($self->parserState()) { $HYPHEN = "*"; - $psString = " (TOKENID: ".$self.", PSID: ".$self->parserState().")"; + $psString = " (TOKENID: ".$self.", PSID: ".$self->parserState().$reStateString.")"; } else { - $psString = " (TOKENID: ".$self.")"; + $psString = " (TOKENID: ".$self.$reStateString.")"; } if ($depth) { print STDERR "+-$HYPHEN-"; @@ -4091,7 +4272,7 @@ sub dbprintrec if ($self == $lastnode) { my $deb = ""; - if ($localDebug) { $deb = $lastnode; } + if ($localDebug || 1) { $deb = $lastnode; } print STDERR "-=-=-=-=-=-=- EODEC $deb-=-=-=-=-=-=-\n"; } @@ -4654,4 +4835,519 @@ sub isAvailabilityMacro return 0; } +# /*! +# @abstract +# Partially translates Perl code into C +# */ +sub translateTree { + my $self = shift; + my %state = (); + + $self->translateTreeRec(\%state); +} + +# /*! +# @abstract +# Returns the parse tree node containing the +# next non-space token at the current level. +# @param self +# The initial parse tree node. +# */ +sub nextNSToken +{ + my $self = shift; + my $next = $self->{NEXT}; + while ($next && $next->{TOKEN} !~ /\S/s) { + $next = $next->{NEXT}; + } + return $next; +} + +# /*! @abstract +# Does the real work of translating a Perl script (partially) +# to C. +# @param self +# The tree to translate. +# @param self +# A translation state object (initially empty). +# */ +sub translateTreeRec { + my $self = shift; + my $stateref = shift; + my %state = %{$stateref}; + my $localDebug = 0; + + my $enteringComment = 0; + my $enteringString = 0; + my $enteringSingle = 0; + my $leavingHDComment = 0; + + print STDERR "TOK: ".$self->{TOKEN}."\n" if ($localDebug); + + if ((!$state{seenCode}) && $self->{TOKEN} && $self->{TOKEN} =~ /\S/s && $self->{TOKEN} ne "if" && $self->{TOKEN} ne "#" && $self->{TOKEN} ne "{" && $self->{TOKEN} ne "}") { + print STDERR "SEENCODE -> 1\n" if ($localDebug); + $state{seenCode} = 1; + $state{insertIfBeforeNode} = $self; + } + print STDERR "CHECK: INSTRING: ".$state{inString}." INCOMMENT: ".$state{inComment}." INREGEXP: ".$state{inRegExp}." INSINGLE: ".$state{inSingle}."\n" if ($localDebug); + if (!($state{inString} || $state{inComment} || $state{inRegExp} || $state{inSingle})) { + # Don't mess with the guts of these things, for the most part. + print STDERR "FIXUP OKAY\n" if ($localDebug); + + if ($self->{TOKEN} eq "\"") { + $state{inString} = 1; + $enteringString = 1; + } elsif ($self->{TOKEN} eq "'") { + $state{inSingle} = 1; + $enteringSingle = 1; + } elsif ($self->{TOKEN} eq "#") { + print STDERR "ILC\n" if ($localDebug); + $state{inComment} = 1; + $enteringComment = 1; + $state{socNode} = $self; + if ($state{inHDComment}) { + $self->{TOKEN} = " "; + } else { + $self->{TOKEN} = "//"; + } + if ($self->{FIRSTCHILD}->textTree() =~ /\*\//) { + $leavingHDComment = 1; + } + } elsif ($self->{TOKEN} eq "\$") { # Merge with next token. + my $next = $self->{NEXT}; + if ($next) { + $self->{TOKEN} = ""; + $self->{NEXT}->{TOKEN} = "\$".$self->{NEXT}->{TOKEN}; + } + } elsif ($self->{TOKEN} eq ":") { + if ($self->{NEXT} && $self->{NEXT}->{TOKEN} eq ":") { + $self->{TOKEN} = "_"; + $self->{NEXT}->{TOKEN} = "_"; + } + } elsif ($self->{TOKEN} eq "elsif") { + $self->{TOKEN} = "else if"; + } elsif ($self->{TOKEN} eq "STDERR") { + $self->{TOKEN} = "stderr"; + } elsif ($self->{TOKEN} eq "STDOUT") { + $self->{TOKEN} = "stdout"; + } elsif ($self->{TOKEN} eq "STDIN") { + $self->{TOKEN} = "stdin"; + } elsif ($self->{TOKEN} eq "<" && $self->{FIRSTCHILD} && + $self->{FIRSTCHILD}->{NEXT} && + $self->{FIRSTCHILD}->{NEXT}->{TOKEN} =~ /^[a-zA-Z]+$/ && + $self->{FIRSTCHILD}->{NEXT}->{NEXT} && + $self->{FIRSTCHILD}->{NEXT}->{NEXT}->{TOKEN} eq ">") { + # print STDERR "FC: ".$self->{FIRSTCHILD}->{TOKEN}." NC ".$self->{FIRSTCHILD}->{NEXT}->{TOKEN}."\n"; + print STDERR "Read from file.\n" if ($localDebug); + $self->{TOKEN} = "stringFromFP("; + $self->{FIRSTCHILD}->{NEXT}->{NEXT}->{TOKEN} = ")"; + } elsif ($self->{TOKEN} eq "print" || $self->{TOKEN} eq "warn") { + my $nextnstoken = $self->nextNSToken(); + if ($self->{TOKEN} eq "print") { + my $ns = $self->nextNSToken(); + if ($ns && ($ns->{TOKEN} eq "\"" || $ns->{TOKEN} eq "\$")) { + $self->{TOKEN} = "printf"; + } else { + $self->{TOKEN} = "fprintf"; + if ($ns->{TOKEN} eq "STDERR") { + $ns->{TOKEN} = "stderr"; + } elsif ($ns->{TOKEN} eq "STDOUT") { + $ns->{TOKEN} = "stdout"; + } + $ns->{TOKEN} .= ","; + } + } + if ($nextnstoken->{TOKEN} ne "(") { + $self->{TOKEN} .= "("; + $state{addParenAtSemi} = 1; + $self->{NEXT} = $nextnstoken; + } + } elsif ($self->{TOKEN} eq "split") { + $self->{TOKEN} = "regexpSplit"; + $state{inSplit} = 1; + print STDERR "inSplit -> 1\n" if ($localDebug); + } elsif ($self->{TOKEN} eq "(" && $state{inSplit}) { + $state{inSplit} = 2; + print STDERR "inSplit -> 1\n" if ($localDebug); + } elsif ($self->{TOKEN} eq "->") { + print STDERR "->" if ($localDebug); + my $pos = $self->{NEXT}; + while ($pos && $pos->{TOKEN} !~ /\S/s) { + $pos = $pos->{NEXT}; + } + if ($pos && $pos->{TOKEN} eq "{") { + my $posb = $pos->{FIRSTCHILD}; + while ($posb && $posb->{TOKEN} ne "}") { + $posb = $posb->{NEXT}; + } + if ($pos && $posb) { + $pos->{TOKEN} = ""; + $posb->{TOKEN} = ""; + } + } + } elsif ($self->{TOKEN} eq "eq" || $self->{TOKEN} eq "ne") { + my $prev = $self->slowprev(); + while ($prev && ($prev->token !~ /\S/s)) { + $prev = $prev->slowprev(); + } + while ($prev && $prev->{TOKEN} !~ /\&/ && $prev->{TOKEN} !~/\|/) { + print STDERR "PREV: $prev\n" if ($localDebug); + print STDERR "TOK: ".$prev->{TOKEN}."\n" if ($localDebug); + $prev = $prev->slowprev(); + } + # }) + + # If we run off the beginning of the chain, we hit an open parenthesis, + # so we know we can always insert after the first (always-empty) + # child. + + my $addspace = ""; + if (!$prev) { + $prev = $self->parent()->firstchild(); + } else { + # Add a space after || or && + $addspace = " "; + } + + my $next = $self->{NEXT}; + while ($next && ($next->token !~ /\S/s)) { + $next = $next->{NEXT}; + } + print STDERR "NEXT IS \"".$next->{TOKEN}."\"\n" if ($localDebug); + while ($next && $next->{NEXT} && $next->{NEXT}->{TOKEN} !~ /\&/ && $next->{NEXT}->{TOKEN} !~ /\|/ && + $next->{NEXT}->{TOKEN} !~ /\)/) { + $next = $next->{NEXT}; + print STDERR "INLOOP NEXT IS ".$next->{TOKEN}."\n" if ($localDebug); + } + if ($prev && $next) { + my $newnode = HeaderDoc::ParseTree->new(); + if ($self->{TOKEN} eq "eq") { + $newnode->{TOKEN} = $addspace."!strcmp("; + } else { + $newnode->{TOKEN} = $addspace."strcmp("; + } + $newnode->{NEXT} = $prev->{NEXT}; + $prev->{NEXT} = $newnode; + + if ($next->{TOKEN} eq "\$") { + $next->{TOKEN} = ""; + $next->{NEXT}->{TOKEN} = "\$".$next->{NEXT}->{TOKEN}; + $next = $next->{NEXT}; + } + + $newnode = HeaderDoc::ParseTree->new(); + $newnode->{TOKEN} = ")"; + $newnode->{NEXT} = $next->{NEXT}; + $next->{NEXT} = $newnode; + + $self->{TOKEN} = ","; + $prev = $self->slowprev(); + while ($prev && ($prev->{TOKEN} =~ /\s/s)) { + $prev->{TOKEN} = ""; + $prev = $prev->slowprev(); + } + } else { + warn("Could not fix \"eq\" because previous/next token not found (PREV: $prev NEXT: $next).\n"); + } + } elsif ($state{seenCode} && ($self->{TOKEN} eq ";" || $self->{TOKEN} eq "{")) { + $state{seenCode} = 0; + if ($state{addParenAtSemi}) { + $state{addParenAtSemi} = 0; + $self->{TOKEN} = ")".$self->{TOKEN}; + } + print STDERR "SEENCODE -> 0\n" if ($localDebug); + if ($state{captureIf}) { + my $lastcapture = $self->slowprev(); + + my $beforenode = $state{insertIfBeforeNode}; + my $prev = $beforenode->slowprev(); + if (!$prev) { + my $newnode = HeaderDoc::ParseTree->new(); + $newnode->{TOKEN} = $beforenode->{TOKEN}; + $newnode->{NEXT} = $beforenode->{NEXT}; + $beforenode->{NEXT} = $newnode; + $beforenode->{TOKEN} = ""; + $prev = $beforenode; + $beforenode = $newnode; + } + + my $trailingspace = $self->slowprev(); + if (!$trailingspace) { + $trailingspace = $self->parent(); + } + while ($trailingspace && + ((!$trailingspace->{TOKEN}) || + ($trailingspace->{TOKEN} =~ /\s/s))) { + + # print STDERR "TS: $trailingspace\n" if ($localDebug); + # print STDERR "PARENT: ".$trailingspace->parent()."\n" if ($localDebug); + + $trailingspace->{TOKEN} = ""; + my $temp = $trailingspace->slowprev(); + if ($temp) { $trailingspace = $temp; } + else { $trailingspace = $trailingspace->parent(); } + } + + my $copiedDataNode = HeaderDoc::ParseTree->new(); + $copiedDataNode->{NEXT} = $prev->{NEXT}; + $prev->{NEXT} = $copiedDataNode; + + $copiedDataNode->{TOKEN} = $state{capturedText}." "; + print STDERR "ACCUM: ".$state{capturedText}."\n" if ($localDebug); + + $state{captureIf} = 0; + print STDERR "captureIf -> 0\n" if ($localDebug); + } + } elsif ($self->{TOKEN} eq "if" && $state{seenCode}) { + $state{capturedText} = ""; + $state{captureIf} = 1; + print STDERR "captureIf -> 1\n" if ($localDebug); + } + } elsif ($state{inComment} == 1 && ($self->{TOKEN} eq "/*!" || $self->{TOKEN} eq "/**")) { + $state{socNode}->{TOKEN} = " "; + $state{inHDComment} = 1; + } elsif ($state{inComment} && $self->{TOKEN} =~ /\S/) { + $state{inComment} = 2; + } + + print STDERR "RE_STATE: ".$self->{RE_STATE}."\n" if ($localDebug); + if ($self->{RE_STATE} eq "RE_PREFIX") { + print STDERR "Regexp prefix found.\n" if ($localDebug); + if ($self->{TOKEN} eq "s") { + $state{inRegExp} = 3; + $state{rePrefix} = $self->{TOKEN}; + $self->{TOKEN} = ""; + } elsif ($self->{TOKEN} eq "tr") { + $state{inRegExp} = 4; + $state{rePrefix} = $self->{TOKEN}; + $self->{TOKEN} = ""; + } elsif ($self->{TOKEN} eq "m") { + $self->{TOKEN} = ""; + print STDERR "Dropping prefix because 'm' is equivalent to no prefix.\n" if ($localDebug); + } else { + print STDERR "Unsupported prefix. Ignoring this expression.\n" if ($localDebug); + $state{inRegExp} = -1; # No 'tr' support yet. + } + } elsif ($self->{RE_STATE} eq "RE_PARTSEP") { + if ($self->{NEXT}->{RE_STATE} eq "RE_PARTSEP") { + $self->{NEXT}->{TOKEN} = ""; + $self->{NEXT}->{RE_STATE} = ""; + } + $self->{TOKEN} = "\", \""; + } elsif ($self->{RE_STATE} eq "RE_START" && ((!$state{inRegExp}) || $state{inRegExp} == 3 || $state{inRegExp} == 4)) { + print STDERR "Regexp start found. INSPLIT: ".$state{inSplit}."\n" if ($localDebug); + $state{regexpName} = $state{prevTokenNode}->{TOKEN}; + + print STDERR "PTN: ".$state{prevTokenNode}." (".$state{prevTokenNode}->{TOKEN}.") REGEXPNAME: ".$state{regexpName}."\n" if ($localDebug); + + if ($state{inSplit}) { + $self->{TOKEN} = "\""; + $state{inRegExp} = 2; + } elsif ($state{regexpName} =~ /^\$[0-9A-Za-z_]+$/) { + if (!$state{inRegExp}) { + $state{inRegExp} = 1; + $state{prevTokenNode}->{TOKEN} = "regexpMatch(".$state{regexpName}.", "; + } elsif ($state{inRegExp} == 3) { + $state{prevTokenNode}->{TOKEN} = "regexpReplace(".$state{regexpName}.", \@\@\@DEST\@\@\@, "; + } elsif ($state{inRegExp} == 4) { + $state{prevTokenNode}->{TOKEN} = "regexptr(".$state{regexpName}.", \@\@\@DEST\@\@\@, "; + } + my $pos = $state{prevTokenNode}->{NEXT}; + print STDERR "Deleting the =~ .\n" if ($localDebug); + while ($pos && !$pos->{RE_STATE}) { + print STDERR "Deleting \"".$pos->{TOKEN}."\" ($pos)\n" if ($localDebug); + # Nuke the "=~" + if ($pos->{TOKEN} eq "!") { + $state{prevTokenNode}->{TOKEN} = "!".$state{prevTokenNode}->{TOKEN}; + } + $pos->{TOKEN} = ""; + $pos = $pos->{NEXT} + } + if ($state{rePrefix} eq "s") { + $self->{TOKEN} = "\""; + # } elsif ($state{rePrefix} eq "tr") { + # $self->{TOKEN} = "\"["; + } else { + $self->{TOKEN} = "\""; + } + } else { + $state{inRegExp} = -1; + } + } elsif ($self->{RE_STATE} eq "RE_END") { + print STDERR "End of regexp found.\n" if ($localDebug); + + # Defaults. + my $multiline = 0; + my $insensitive = 0; + my $global = 0; + my $complement = 0; + my $delete = 0; + my $nondestructive = 0; + my $squash = 0; + + my $next = $self->{NEXT}; + if ($next && $next->{TOKEN} =~ /^[siogmcdr]*$/) { + my $re_trailer = $next->{TOKEN}; + if ($re_trailer =~ /s/) { + $multiline = 0; # for 's' + $squash = 1; # for 'tr' + } elsif ($re_trailer =~ /m/) { + $multiline = 1; + } + if ($re_trailer =~ /g/) { + $global = 1; + } + if ($re_trailer =~ /i/) { + $insensitive = 1; + } + if ($re_trailer =~ /c/) { + $complement = 1; + } + if ($re_trailer =~ /d/) { + $delete = 1; + } + if ($re_trailer =~ /r/) { + $nondestructive = 1; + } + $next->{TOKEN} = ""; + } + if ($state{inRegExp} == 1) { + $self->{TOKEN} = "\", $multiline, $insensitive, NULL)"; + } elsif ($state{inRegExp} == 2) { + # Leave parentheses open. + $self->{TOKEN} = "\""; + + my $next = $self->nextNSToken(); + print STDERR "THISNEXT: ".$next->{TOKEN}."\n" if ($localDebug); + if (!$next) { + die("Malformed split\n"); + } + # $next should be the comma after the regular expression. + + $next = $next->nextNSToken(); + if ($next->{TOKEN} eq "\$") { + $next->{TOKEN} = ""; + $next->{NEXT}->{TOKEN} = "\$".$next->{NEXT}->{TOKEN}; + $next = $next->{NEXT}; + } + # $next should be the data to split. + + my $argNode = HeaderDoc::ParseTree->new(); + $argNode->{NEXT} = $next->{NEXT}; + $next->{NEXT} = $argNode; + $argNode->{TOKEN} = ", $multiline, $insensitive"; + + my $afternext = $argNode->nextNSToken(); + print STDERR "AN: ".$afternext->{TOKEN}."\n" if ($localDebug); + if (!$afternext || ($afternext->{TOKEN} ne ",")) { + $argNode->{TOKEN} .= ", 0"; + } + } elsif ($state{inRegExp} == 3) { + if ($state{rePrefix} eq "s") { + $self->{TOKEN} = "\", $multiline, $insensitive, $global)"; + # } elsif ($state{rePrefix} eq "tr") { + # $self->{TOKEN} = "]\""; + } else { + die("Unknown RE prefix \"".$state{rePrefix}."\" [1]\n"); + } + } elsif ($state{inRegExp} == 4) { + if ($state{rePrefix} eq "tr") { + # Allowed: "s", but not "m", not "i", not "g" + $self->{TOKEN} = "\", $squash, $complement, $delete)"; + + if ($nondestructive) { + $state{prevTokenNode}->{TOKEN} = "regexptr(".$state{regexpName}.", NULL, "; + } + } else { + die("Unknown RE prefix \"".$state{rePrefix}."\" [2]\n"); + } + } + $state{inRegExp} = 0; + $state{rePrefix} = ""; + } elsif ($state{inRegExp}) { + $self->{TOKEN} =~ s/\\/\\\\/g; + } + + if ($state{inComment} && $self->{TOKEN} =~ /[\n\r]/) { + print STDERR "Leaving comment.\n" if ($localDebug); + $state{inComment} = 0; + } + + print STDERR "Checking token.\n" if ($localDebug); + if ($self->{TOKEN} =~ /^\$[a-zA-Z0-9_]+$/) { + print STDERR "setting PTN\n" if ($localDebug); + $state{prevTokenNode} = $self; + } + + if ($state{captureIf}) { + print STDERR "APPEND ".$self->{TOKEN}."\n" if ($localDebug); + $state{capturedText} .= $self->{TOKEN}; + $self->{TOKEN} = ""; + } + + my $resetSplit = 0; + if ($state{inSplit} == 2) { + $resetSplit = 1; + $state{inSplit} = 3; + } + + if ($self->{FIRSTCHILD}) { + print STDERR "Processing children.\n" if ($localDebug); + my $tempstateref = $self->{FIRSTCHILD}->translateTreeRec(\%state); + my %tempstate = %{$tempstateref}; + if ($state{inComment} && $tempstate{inHDComment}) { + $state{inHDComment} = 1; + } + if ($state{captureIf}) { + $state{capturedText} = $tempstate{capturedText}; + } + $state{seenCode} = $tempstate{seenCode}; + $state{prevTokenNode} = $tempstate{prevtoken}; + } + if ($resetSplit) { $state{inSplit} = 0; print STDERR "inSplit -> 0\n" if ($localDebug) }; + if ($enteringComment) { $state{inComment} = 0; $state{seenCode} = 0; } + if ($enteringString) { $state{inString} = 0; } + if ($enteringSingle) { $state{inSingle} = 0; } + if ($leavingHDComment) { $state{inHDComment} = 0; $state{seenCode} = 0; } + if ($self->{NEXT}) { + print STDERR "Processing next.\n" if ($localDebug); + $stateref = $self->{NEXT}->translateTreeRec(\%state); + %state = %{$stateref}; + } + print STDERR "Returning.\n" if ($localDebug); + return \%state; +} + +# /*! +# @abstract Returns the first token inside the body of an AppleScript +# function. +# */ +sub ASFunctionBodyStart +{ + my $self = shift; + + my $localDebug = 0; + + while ($self && + ($self->token() ne "\n") && + ($self->token() ne "\r") && + ($self->token() ne "(")) { + print STDERR "SKIPPING ".$self->token()." (LOOP 1)\n" if ($localDebug); + $self = $self->next(); + } + while ($self && + ($self->token() eq "\n") || + ($self->token() eq "\r") || + ($self->token() eq "(")) { + print STDERR "SKIPPING ".$self->token()." (LOOP 2)\n" if ($localDebug); + $self = $self->next(); + } + + print STDERR "RETURNING TREE.\n" if ($localDebug); + $self->dbprint() if ($localDebug); + + return $self; +} + + 1; diff --git a/Modules/HeaderDoc/ParserState.pm b/Modules/HeaderDoc/ParserState.pm index 3c427c9..4470e89 100644 --- a/Modules/HeaderDoc/ParserState.pm +++ b/Modules/HeaderDoc/ParserState.pm @@ -2,7 +2,7 @@ # # Class name: ParserState # Synopsis: Used by headerDoc2HTML.pl to hold parser state -# Last Updated: $Date: 2011/05/10 17:36:18 $ +# Last Updated: $Date: 2014/03/05 14:20:15 $ # # Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved. # @@ -490,6 +490,17 @@ # Set to the actual of or in token # encountered when parsing AppleScript. The word token after it is # appended to this variable (delimited by a space). +# @var ASINELSE +# Set to 1 at an "else" statement. If the next word token is "if", +# we don't treat it as opening a new brace. +# @var ASLBRACEPRECURSOR +# In an if or tell statement, stores +# the if or tell token. Used to determine +# whether to treat the following newline as a brace. +# @var ASLBRACEPRECURSORTAG +# In an if or tell statement, stores +# the then or to token. Used to determine +# whether to treat the following newline as a brace. # @var inUnion # Set to 1 when the union keyword is encountered. Remains high # until the end of this declaration. @@ -661,6 +672,25 @@ # do not precede the function body with any other # opening brace. # +# @var afterNL +# A nondestructive variant of {@link firstpastnl} that is available to +# any programming language (and currently used in TCL). +# Set to 2 after a newline, 1 during the first non-space +# token, 0 after. Also set to 2 initially. +# +# @var inrbraceargument +# Some languages take an additional argument for their equivalent of +# a right brace. For example, in AppleScript, a tell +# block ends with end tell. In effect, end +# terminates the block, but the next token does not start the next +# block. +# +# If {@link //apple_ref/doc/functionvar/HeaderDoc::Utilities/parseTokens/rbracetakesargument rbracetakesargument} +# is set in the object returned by a call to +# {@link //apple_ref/perl/instm/HeaderDoc::Utilities/parseTokens//() parseTokens}, +# then that trailing tell is included in the +# trailer for the block. +# # @vargroup Parameter, attribute, asm, and availability parsing # # @var parsedParamParse @@ -727,6 +757,12 @@ # is complete. # # +# @var parsedParamAtBrace +# Any in-progress parsed parameters when we enter a brace. +# +# @var parsedParamStateAtBrace +# The state of parameter parsing when we enter a brace. +# # @vargroup Token variables # # @var lastsymbol @@ -799,8 +835,16 @@ # The contents of a function (or, when parsing a switch # statement, the contents of the struct body). # +# @var lastDisplayNode +# The last node in the parse tree rooted at this node that +# should be displayed. Used only in AppleScript, to hide +# content nested inside functions while still parsing them +# fully. Unlike lastTreeNode, this node's children +# should be included in the output. +# # @var lastTreeNode # The last node in the parse tree rooted at this node. +# This node is marked with EODEC in parse tree dumps. # # For example, the lastTreeNode value for # a class declaration would point to the closing brace @@ -850,6 +894,10 @@ # Set on parser state objects that represent declarations # within classes so that it does not get processed twice. # +# @var optionalOrRequired +# Either \@optional or \@required, depending on the current +# state of the parser. +# # @vargroup Parsing actual code # @var seenIf # If $HeaderDoc::parseIfElse is 1, this @@ -1060,6 +1108,11 @@ # of a function sets this to 1, an if statement # inside that function increases it to 2, and so on). # +# @var lastNLWasQuoted +# In Python, set to 1 if the last newline was preceded +# by a backslash, else unset. Used to determine +# whether to care about the leading whitespace count. +# # @var pushParserStateOnBrace # Set to 1 when a keyword is encountered that should # cause the parser state to be pushed the next time the @@ -1144,6 +1197,15 @@ # Reset to 0 after the first non-space token. Used in case/esac # parsing. # +# @vargroup TCL-specific variables +# +# @var inTCLRegExpCommand +# In TCL, set to 1 when a command is encountered that takes an +# unquoted (non-string) regular expression as an argument. +# +# Set to 0 upon entering the regular expression or when a +# newline or carriage return is encountered. +# # @vargroup Legacy junk variables # # @var simpleTDcontents @@ -1169,7 +1231,7 @@ use Carp qw(cluck); # In the git repository, contains the number of seconds since # January 1, 1970. # */ -$HeaderDoc::ParserState::VERSION = '$Revision: 1305074178 $'; +$HeaderDoc::ParserState::VERSION = '$Revision: 1394058015 $'; ################ General Constants ################################### my $debugging = 0; @@ -1301,6 +1363,8 @@ my %defaults = ( # to a variable. backslashcount => 0, + afterNL => 2, + functionReturnsCallback => 0 ); @@ -1347,6 +1411,10 @@ sub new { $self->{treeStack} = \@tempb; } + if (length $HeaderDoc::OptionalOrRequired) { + $self->{optionalOrRequired} = $HeaderDoc::OptionalOrRequired; + } + # Now grab any key => value pairs passed in foreach my $key (keys(%attributeHash)) { @@ -1368,11 +1436,15 @@ sub _initialize { my @arr1 = (); my @arr2 = (); my @arr3 = (); + my @arr4 = (); + my @arr5 = (); $self->{parsedParamList} = \@arr1; # currently active parsed parameter list. $self->{pplStack} = \@arr2; # stack of parsed parameter lists. Used to handle # fields and parameters in nested callbacks/structs. $self->{freezeStack} = \@arr3; # copy of pplStack when frozen. + $self->{parsedParamAtBrace} = \@arr4; # Any in-progress parsed parameters when we enter a brace. + $self->{parsedParamStateAtBrace} = \@arr5; # The state of parameter parsing when we enter a brace. my %orighash = %{$self}; @@ -1548,7 +1620,7 @@ sub rollback my %clonehash = %{$clone}; if ($localDebug) { - print STDERR "BEGIN PARSER STATE:\n"; + print STDERR "BEGIN PARSER STATE ($self):\n"; foreach my $key (keys(%clonehash)) { if ($self->{$key} ne $clone->{$key}) { print STDERR "$key: ".$self->{$key}." != ".$clone->{$key}."\n"; @@ -1579,7 +1651,7 @@ sub rollbackSet my $clone = HeaderDoc::ParserState->new(); my %selfhash = %{$self}; - # print STDERR "BEGIN PARSER STATE:\n"; + # print STDERR "BEGIN PARSER STATE ($self):\n"; foreach my $key (keys(%selfhash)) { # print STDERR "$key => $self->{$key}\n"; $clone->{$key} = $self->{$key}; @@ -1600,7 +1672,7 @@ sub print my $self = shift; my %selfhash = %{$self}; - print STDERR "BEGIN PARSER STATE:\n"; + print STDERR "BEGIN PARSER STATE ($self):\n"; foreach my $key (keys(%selfhash)) { print STDERR "$key => $self->{$key}\n"; } @@ -1746,6 +1818,28 @@ sub isRubyCloseQuote return 0; } +# /*! +# @abstract Enables some extra debugging for AppleScript. +# */ +$HeaderDoc::AppleScriptDebug = 0; + +# /*! +# @abstract Clears the left brace precursor token. +# @result Returns whether to treat the newline as a brace. +# */ +sub clearLeftBracePrecursor +{ + my $self = shift; + + my $retval = $self->{ASLBRACEPRECURSOR}; + + $self->{ASLBRACEPRECURSOR} = ""; + $self->{ASLBRACEPRECURSORTAG} = ""; + print STDERR "Cleared ASLBRACEPRECURSOR\n" if ($HeaderDoc::AppleScriptDebug); + + return $retval; +} + # /*! # @abstract # Returns whether or not this token should be @@ -1756,73 +1850,270 @@ sub isRubyCloseQuote # The token to check. # @param lang # The programming language. -# @param lbrace +# @param parseTokensRef +# A parse token hash obtained from a call to {@link parseTokens}. +# @param case_sensitive +# Set to 1 for most languages. Set to 0 if the +# language uses case-insensitive token matching +# (e.g. Pascal). +# @param curBraceCount +# The current brace count. This is used to prevent +# nesting of braces in languages that don't work that way. +# @var lbrace # The primary left brace character. -# @param lbraceunconditionalre +# @var lbraceunconditionalre # A regular expression containing other patterns that # are always considered left braces. Currently used # for for/if in Python and Ruby, and tell in AppleScript. -# @param lbraceconditionalre +# @var lbraceconditionalre # In Ruby/Python, a set of tokens that are treated as # left braces unless they are immediately after a # right brace. Basically, this handles # begin/while/until when used at the end of a line # in Ruby/Python. -# @param classisbrace +# +# In AppleScript, this handles tokens that are treated as +# braces only if they are at the beginning of a line. +# @var lbraceprecursorre +# In AppleScript, this handles "then" after an "if" +# on the same line or "to" after a "tell" on the +# same line. +# @var classisbrace # Set to 1 if a class declaration is treated as an # open brace. (This is not used for ObjC clases; # they are special.) -# @param functionisbrace +# @var functionisbrace # Set to 1 if a function declaration is treated as an # open brace. -# @param case_sensitive -# Set to 1 for most languages. Set to 0 if the -# language uses case-insensitive token matching -# (e.g. Pascal). -# @param curBraceCount -# The current brace count. This is used to prevent -# nesting of braces in languages that don't work that way. # */ sub isLeftBrace { my $self = shift; my $part = shift; my $lang = shift; - my $lbrace = shift; - my $lbraceunconditionalre = shift; - my $lbraceconditionalre = shift; - my $classisbrace = shift; - my $functionisbrace = shift; + my $parseTokensRef = shift; my $case_sensitive = shift; my $curBraceCount = shift; + my $localDebug = 0; + + my %parseTokens = (); + + my $lbrace; + my $lbracepreventerre; + my $lbraceunconditionalre; + my $lbraceconditionalre; + my $lbraceprecursorre; + my $classisbrace; + my $functionisbrace; + my $lbraceprecursor; + + print STDERR "IN LEFT BRACE CHECK\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); + + # Backwards compatibility hack. + if (@_) { + warn("The calling pattern for isLeftBrace has changed. Please update your code.\n"); + + $lbrace = $parseTokensRef; + $parseTokensRef = undef; + $lbraceunconditionalre = $case_sensitive; + $lbraceconditionalre = $curBraceCount; + $classisbrace = shift; + $classisbrace = shift; + $case_sensitive = shift; + $curBraceCount = shift; + $lbraceprecursor = ""; + $lbraceprecursorre = ""; + $lbracepreventerre = ""; + } else { + # New-style calling: use the value as a reference. + %parseTokens = %{$parseTokensRef}; + + $lbrace = $parseTokens{lbrace}; + $lbraceunconditionalre = $parseTokens{lbraceunconditionalre}; + $lbraceconditionalre = $parseTokens{lbraceconditionalre}; + $lbracepreventerre = $parseTokens{lbracepreventerre}; + $lbraceprecursorre = $parseTokens{lbraceprecursorre}; + $classisbrace = $parseTokens{classisbrace}; + $functionisbrace = $parseTokens{functionisbrace}; + $lbraceprecursor = $parseTokens{lbraceprecursor}; + } + # print STDERR "\$self: $self \$part: $part \$lbrace: $lbrace \$lbraceunconditionalre: $lbraceunconditionalre \$lbraceconditionalre: $lbraceconditionalre \$classisbrace: $classisbrace \$functionisbrace: $functionisbrace \$case_sensitive: $case_sensitive\n"; if ($lang eq "perl" && $self->{inTemplate}) { return 0; } - if (($lang eq "ruby" || $lang eq "python") && (($curBraceCount - $self->{initbsCount}) > 1)) { - # print STDERR "CBC: $curBraceCount INIT: ".$self->{initbsCount}."\n"; - return 0; + if ($lang ne "applescript") { + if ($classisbrace && (($curBraceCount - $self->{initbsCount}) > 1)) { + print STDERR "CBC: $curBraceCount INIT: ".$self->{initbsCount}."\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); + return 0; + } } if (casecmp($part, $lbrace, $case_sensitive)) { + print STDERR "BARE LBRACE\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); if ($self->{pendingBracedParameters}) { return 0; } return 1; } - if ($lbraceunconditionalre && ($part =~ /$lbraceunconditionalre/)) { return 1; } - if ($lbraceconditionalre && (!$self->{followingrubyrbrace}) && ($part =~ /$lbraceconditionalre/)) { return 1; } + print STDERR "IN LEFT BRACE CHECK 2\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); + + print STDERR "INRBR: ".$self->{inrbraceargument}."\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); + + if ($lbraceunconditionalre && ($part =~ /$lbraceunconditionalre/)) { + print STDERR "UNCONDITIONALRE MATCH\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); + return 1; + } + + if ($lbracepreventerre && ($part =~ /$lbracepreventerre/)) { + print STDERR "ASINELSE -> 1\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); + $self->{ASINELSE} = 1; + } elsif ($self->{ASINELSE} && $part =~ /\w/) { + print STDERR "ASINELSE -> 0\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); + $self->{ASINELSE} = 0; + if ($part eq "if") { + print STDERR "IGNORING IF\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); + return 0; + } + } + + if ($lang eq "applescript" && !($self->{inString} || $self->{inComment} || $self->{inInlineComment} || $self->{inLabel} || $self->{inrbraceargument})) { + print STDERR "ASPART: \"$part\" PC: ".$self->{ASLBRACEPRECURSOR}." PCTAG: ".$self->{ASLBRACEPRECURSORTAG}."\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); + + # After an if/then or a tell/to, if we see a non-space, non-comment token, + # then it is a simple-style "if" or "tell" statement. Clear the precursor data + # so that a subsequent call to {@link clearLeftBracePrecursor} will return + # an empty string. + if (($self->{ASLBRACEPRECURSORTAG}) && $part =~ /\S/) { + print STDERR "Cleared ASLBRACEPRECURSOR (simple statement)\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); + $self->{ASLBRACEPRECURSOR} = ""; + $self->{ASLBRACEPRECURSORTAG} = ""; + } + + # If we see the "if" or "tell" token, store it away, but be prepared to reverse + # that decision later, if it's right after a newline and turns into a conditional + # regex match. + my $oldprecursor = $self->{ASLBRACEPRECURSOR}; + if ($lbraceprecursor && $part =~ /$lbraceprecursor/) { + $self->{ASLBRACEPRECURSOR} = $part; + print STDERR "Set ASLBRACEPRECURSOR to \"$part\"\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); + } + + # If we see the "then" or "to" token, store it away. + if ($lbraceprecursorre && $part =~ /$lbraceprecursorre/) { + print STDERR "AS conditional lbrace: \"$part\"\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); + if ($part eq "then" && $self->{ASLBRACEPRECURSOR} eq "if") { + print STDERR "IF THEN\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); + $self->{ASLBRACEPRECURSORTAG} = $part; + } + if ($part eq "to" && $self->{ASLBRACEPRECURSOR} eq "tell") { + print STDERR "TELL TO\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); + $self->{ASLBRACEPRECURSORTAG} = $part; + } + print STDERR "Nope.\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); + return 0; + } elsif ($self->{afterNL} && $lbraceconditionalre && $part =~ /$lbraceconditionalre/) { + print STDERR "CONDITIONALRE MATCH\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); + $self->{ASLBRACEPRECURSOR} = $oldprecursor; + return 1; + } + } elsif ($lang eq "applescript" && ($self->{inString} || $self->{inComment} || $self->{inInlineComment} || $self->{inLabel} || $self->{inrbraceargument})) { + print STDERR "RETURNING 0 BECAUSE IN RBRACE ARGUMENT (".$self->{inrbraceargument}.")\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); + return 0; + } else { + if ($lbraceconditionalre && (!$self->{followingrubyrbrace}) && ($part =~ /$lbraceconditionalre/)) { return 1; } + } if (!$self->{newlineIsSemi}) { if ($classisbrace && $self->{sodclass} eq "class" && ($self->{inRubyClass} != 2) && $part =~ /[\n\r]/) { + print STDERR "Class is a brace. Returning 1 at newline.\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); + return 1; + } + if ($functionisbrace && $self->{pushedfuncbrace} == 1 && $part =~ /[\n\r]/) { + print STDERR "Function is a brace. Returning 1 at newline.\n" if ($localDebug || $HeaderDoc::AppleScriptDebug); return 1; } - if ($functionisbrace && $self->{pushedfuncbrace} == 1 && $part =~ /[\n\r]/) { return 1; } } return 0; } +# /*! +# @abstract +# Returns whether or not this token should be +# treated as a right brace. +# @param self +# This object. +# @param part +# The token to check. +# @param lang +# The programming language. +# @param parseTokensRef +# A parse token hash obtained from a call to {@link parseTokens}. +# @param case_sensitive +# Set to 1 for most languages. Set to 0 if the +# language uses case-insensitive token matching +# (e.g. Pascal). +# @var rbrace +# The primary left brace character. +# @var rbraceconditionalre +# In AppleScript, this handles "end". +# */ +sub isRightBrace +{ + my $self = shift; + + my $part = shift; + my $lang = shift; + my $parseTokensRef = shift; + my $case_sensitive = shift; + + my %parseTokens = %{$parseTokensRef}; + + my $localDebug = 0; + + if ($lang eq "applescript") { + print STDERR "Checking token \"$part\" for rbrace\n" if ($HeaderDoc::AppleScriptDebug || $localDebug); + + print STDERR "afterNL: ".$self->{afterNL}."\n" if ($HeaderDoc::AppleScriptDebug || $localDebug); + + my $rbraceconditionalre = $parseTokens{rbraceconditionalre}; + if ($self->{afterNL} && $rbraceconditionalre && $part =~ /$rbraceconditionalre/) { + print STDERR "Yes.\n" if ($HeaderDoc::AppleScriptDebug || $localDebug); + return 1; + } else { + print STDERR "No.\n" if ($HeaderDoc::AppleScriptDebug || $localDebug); + return 0; + } + } + print STDERR "Checking token \"$part\" for non-AppleScript rbrace\n" if ($HeaderDoc::AppleScriptDebug || $localDebug); + + my $retval = casecmp($part, $parseTokens{rbrace}, $case_sensitive); + + print STDERR ($retval ? "Yes\n" : "No\n") if ($HeaderDoc::AppleScriptDebug || $localDebug); + + return $retval; +} + +# /*! +# @abstract Returns whether an AppleScript on/to should be treated as a handler or just a normal token. +# */ +sub appleScriptFunctionLegalHere +{ + my $self = shift; + my $braceStackRef = shift; + + my @braceStack = @{$braceStackRef}; + + # It's only a handler if it is the first on a line. + if (!$self->{afterNL}) { return 0; } + + # It isn't legal inside other stuff, e.g. a try block. + if (scalar(@braceStack)-$self->{initbsCount}) { return 0; } + + return 1; +} + # /*! # @abstract # Pushes a token onto the brace stack. @@ -1867,6 +2158,63 @@ sub peekBrace return $temp; } +# /*! +# @abstract +# Looks at the top token on the brace stack and +# returns the closing token that would match it. +# @param self +# This object. +# @discussion +# This is currently only used for the Python +# parser. Eventually, the main parser should +# be modified to share this stack instead of +# using a local variable. +# */ +sub braceCount +{ + my $self = shift; + return scalar(@{$self->{braceStack}}); +} + +# /*! +# @abstract +# Returns whether the current line is a Python continuation line. +# @discussion +# In Python, if you are inside a string, a multiline string, +# a parenthesized expression, an array, etc., subsequent lines +# are treated as part of the current line implicitly. Those +# subsequent lines are called continuation lines. +# +# A continuation line also occurs explicitly when the previous +# line ends with a backslash. +# */ +sub isContinuationLine +{ + my $self = shift; + my $localDebug = 0; + + if ($self->braceCount()) { + print STDERR "In isContinuationLine: brace count is ".$self->braceCount()."\n" if ($localDebug); + if ($localDebug > 1) { + print STDERR "begin stack dump\n"; + foreach my $item (@{$self->{braceStack}}) { + print STDERR "ITEM: $item\n"; + } + print STDERR "end stack dump\n"; + } + + return 1; + } + if ($self->{lastNLWasQuoted}) { + print STDERR "In isContinuationLine: lastNLWasQuoted.\n" if ($localDebug); + return 1; + } + + print STDERR "In isContinuationLine: returning 0.\n" if ($localDebug); + + return 0; +} + # /*! # @abstract # Looks at the top token on the brace stack and diff --git a/Modules/HeaderDoc/PerfEngine.pm b/Modules/HeaderDoc/PerfEngine.pm index 68e0f5d..a1262ad 100644 --- a/Modules/HeaderDoc/PerfEngine.pm +++ b/Modules/HeaderDoc/PerfEngine.pm @@ -3,7 +3,7 @@ # Class name: PerfEngine # Synopsis: Performance Testing Engine # -# Last Updated: $Date: 2011/02/18 19:02:59 $ +# Last Updated: $Date: 2011/07/07 15:15:10 $ # # Copyright (c) 2005 Apple Computer, Inc. All rights reserved. # @@ -81,7 +81,6 @@ use HeaderDoc::PerfPoint; use File::Basename; use strict; use vars qw($VERSION @ISA); -use POSIX qw(strftime); use Carp; @@ -92,7 +91,7 @@ use Carp; # In the git repository, contains the number of seconds since # January 1, 1970. # */ -$HeaderDoc::PerfEngine::VERSION = '$Revision: 1298084579 $'; +$HeaderDoc::PerfEngine::VERSION = '$Revision: 1310076910 $'; my $perfDebug = 0; diff --git a/Modules/HeaderDoc/PerfPoint.pm b/Modules/HeaderDoc/PerfPoint.pm index aeca80c..653232b 100644 --- a/Modules/HeaderDoc/PerfPoint.pm +++ b/Modules/HeaderDoc/PerfPoint.pm @@ -3,7 +3,7 @@ # Class name: PerfPoint # Synopsis: Test Point Object for Performance Testing Engine # -# Last Updated: $Date: 2011/02/18 19:02:59 $ +# Last Updated: $Date: 2011/07/07 15:15:10 $ # # Copyright (c) 2005 Apple Computer, Inc. All rights reserved. # @@ -69,7 +69,6 @@ use HeaderDoc::Utilities qw(findRelativePath safeName printArray printHash unreg use File::Basename; use strict; use vars qw($VERSION @ISA); -use POSIX qw(strftime); use Time::HiRes qw( usleep ualarm gettimeofday tv_interval ); use Carp; @@ -81,7 +80,7 @@ use Carp; # In the git repository, contains the number of seconds since # January 1, 1970. # */ -$HeaderDoc::PerfPoint::VERSION = '$Revision: 1298084579 $'; +$HeaderDoc::PerfPoint::VERSION = '$Revision: 1310076910 $'; my $perfDebug = 1; diff --git a/Modules/HeaderDoc/PythonParse.pm b/Modules/HeaderDoc/PythonParse.pm index b978f03..6b2ed9e 100644 --- a/Modules/HeaderDoc/PythonParse.pm +++ b/Modules/HeaderDoc/PythonParse.pm @@ -3,7 +3,7 @@ # Module name: BlockParse # Synopsis: Block parser code # -# Last Updated: $Date: 2011/02/18 19:02:59 $ +# Last Updated: $Date: 2012/02/28 15:37:59 $ # # Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved. # @@ -88,7 +88,7 @@ use File::Basename qw(basename); # In the git repository, contains the number of seconds since # January 1, 1970. # */ -$HeaderDoc::PythonParse::VERSION = '$Revision: 1298084579 $'; +$HeaderDoc::PythonParse::VERSION = '$Revision: 1330472279 $'; ################ Portability ################################### my $isMacOS; @@ -307,7 +307,14 @@ sub pythonParse my $parseDebug = 0; my $liteDebug = 0; my $parmDebug = 0; + my $nameDebug = 0; + my $stateDebug = 0; + my $spaceDebug = 0; + my $stackDebug = 0; my $inputCounterDebug = 0; + + my $anyDebug = ($parseDebug || $liteDebug || $parmDebug || $nameDebug || $stateDebug || $spaceDebug || + $stackDebug || $inputCounterDebug); # print STDERR "Test\n"; my $treeTop = HeaderDoc::ParseTree->new(); @@ -359,6 +366,13 @@ sub pythonParse my $part = ""; foreach my $nextpart (@parts) { REDO: + if ($stackDebug) { + print STDERR "BEGIN STACK DUMP\n"; + foreach my $token (@{$parserState->{braceStack}}) { + print "ITEM: $token\n"; + } + print STDERR "END STACK DUMP\n"; + } if (!length($part)) { # print STDERR "SKIP TO \"$nextpart\"\n"; @@ -372,34 +386,66 @@ sub pythonParse my $treepart = $part; if ($part =~ /\s/ && $part !~ /[\r\n]/) { - print STDERR "WSATTOP\n" if ($parseDebug); + print STDERR "WSATTOP\n" if ($parseDebug || $spaceDebug); if ($parserState->{lastpart} =~ /[\n\r]/ || $parserState->{lastpart} eq "") { + if (!$parserState->isContinuationLine()) { # print STDERR "CMP ".pylength($part)." TO ".$parserState->{leadspace}."\n"; if ($parserState->{leadspace} == -1) { if ($nextpart !~ /[\n\r]/) { $parserState->{leadspace} = pylength($part); $parserState->{setleading} = 1; - print STDERR "leadspace -> ".$parserState->{leadspace}."\n" if ($parseDebug); + print STDERR "SETLEADING -> 1[1]\n" if ($parseDebug || $stateDebug); + print STDERR "leadspace -> ".$parserState->{leadspace}."\n" if ($parseDebug || $stateDebug || $spaceDebug); $treepart = ""; + } else { + print STDERR "Ignoring leading space for blank line.\n" if ($spaceDebug); } + } else { + print STDERR "Not setting leading space because it is already set (".$parserState->{leadspace}.").\n" if ($spaceDebug); } if ((!$parserState->{seenToken}) && (!$parserState->{seenLeading})) { $parserState->{seenLeading} = pylength($part); } + } else { + print STDERR "Ignoring leading whitespace for continuation line.\n" if ($parseDebug || $spaceDebug); + print STDERR "LEADSPACE: ".$parserState->{leadspace}."\n" if ($spaceDebug); + } + } else { + print STDERR "Not setting leading whitespace because this is not the first whitespace\n"."on the line (lastpart is ".$parserState->{lastpart}.").\n" if ($spaceDebug); } } elsif ($part =~ /[\r\n]/) { print STDERR "NLATTOP\n" if ($parseDebug); $parserState->{seenLeading} = 0; + if ($parserState->{seenToken}) { + $parserState->{setleading} = 0; + print STDERR "SETLEADING -> 0\n" if ($parseDebug || $stateDebug); + } $parserState->{seenToken} = 0; - $parserState->{setleading} = 0; } else { print STDERR "TEXTATTOP\n" if ($parseDebug); + if ($parserState->{leadspace} == -1) { + $parserState->{leadspace} = 0; # pylength($part); + $parserState->{setleading} = 1; + print STDERR "SETLEADING -> 1[1]\n" if ($parseDebug || $stateDebug); + print STDERR "leadspace -> ".$parserState->{leadspace}."\n" if ($parseDebug || $stateDebug); + } + if (!$parserState->{seenLeading}) { $parserState->{seenLeading} = 0; }; - print STDERR "CMP: ".$parserState->{seenLeading}." TO ".$parserState->{leadspace}."\n" if ($parseDebug); - if ((!$parserState->{setleading}) && ($parserState->{seenLeading} <= $parserState->{parentLeading})) { - if ((!$parserState->{seenToken}) && (!$parserState->{onlyComments})) { $parserState->{endgame} = 3; } - } elsif ((!$parserState->{setleading}) && ($parserState->{seenLeading} <= $parserState->{leadspace})) { - if ((!$parserState->{seenToken}) && (!$parserState->{onlyComments})) { $parserState->{endgame} = 2; } + print STDERR "CMP: ".$parserState->{seenLeading}." TO ".$parserState->{leadspace}."\n" if ($parseDebug || $spaceDebug); + if ((!$parserState->isContinuationLine()) && (!$parserState->{setleading}) && ($parserState->{seenLeading} <= $parserState->{parentLeading}) && (!$parserState->{onlyComments})) { + if (!$parserState->{seenToken}) { + $parserState->{endgame} = 3; + print STDERR "ENDGAME -> 3[TAT-LTPARENTLEAD]\n" if ($parseDebug || $stateDebug); + } else { + print STDERR "ENDGAME NOT SET (ST: ".$parserState->{seenToken}.", OC: ".$parserState->{onlyComments}.") [TAT-LTPARENTLEAD]\n" if ($parseDebug); + } + } elsif ((!$parserState->isContinuationLine()) && (!$parserState->{setleading}) && ($parserState->{seenLeading} <= $parserState->{leadspace}) && (!$parserState->{onlyComments})) { + if (!$parserState->{seenToken}) { + $parserState->{endgame} = 2; + print STDERR "ENDGAME -> 2[TAT-LTLEAD]\n" if ($parseDebug || $stateDebug); + } else { + print STDERR "ENDGAME NOT SET (ST: ".$parserState->{seenToken}.", OC: ".$parserState->{onlyComments}.") [TAT-LTPARENTLEAD]\n" if ($parseDebug); + } } elsif (!$parserState->{seenToken}) { if ($parserState->{leadspace}) { my $temp = ' ' x $parserState->{leadspace}; @@ -410,20 +456,24 @@ sub pythonParse if (($parserState->{leadspace} == -1) && (!$parserState->{seenLeading})) { $parserState->{leadspace} = 0; $parserState->{setleading} = 1; - print STDERR "leadspace -> ".$parserState->{leadspace}."\n" if ($parseDebug); + print STDERR "SETLEADING -> 1[2]\n" if ($parseDebug || $stateDebug); + print STDERR "leadspace -> ".$parserState->{leadspace}."\n" if ($parseDebug || $stateDebug); } $parserState->{seenToken} = 1; } print STDERR "POSTCMP: ".$parserState->{seenLeading}." TO ".$parserState->{leadspace}."\n" if ($parseDebug); - SWITCH: { - ($parserState->{endgame} == 1) && do { + if (($parserState->{endgame} != 2) && ($parserState->{endgame} != 3)) { + SWITCH: { + ($parserState->{endgame} == 1 && $part =~ /\S/) && do { if ($parserState->{onlyComments}) { print STDERR "Only comments, so not setting endgame\n" if ($parseDebug); $parserState->{endgame} = 0; + print STDERR "ENDGAME -> 0[ONLYCOMMENTS]\n" if ($parseDebug || $stateDebug); } else { $parserState->{endgame} = 2; + print STDERR "ENDGAME -> 2[WAS1]\n" if ($parseDebug || $stateDebug); $parserState->{popAfter} = 1; last SWITCH; } @@ -450,11 +500,17 @@ sub pythonParse }; ($part =~ /[\n\r]/) && do { print STDERR "newline\n" if ($parseDebug); - if (!$parserState->isQuoted($lang, $sublang)) { + if ($parserState->isQuoted($lang, $sublang)) { + $parserState->{lastNLWasQuoted} = 1; + print STDERR "lastNLWasQuoted -> 1\n" if ($spaceDebug || $stateDebug); + } else { print STDERR "MAYBE ENDGAME: AC IS ".$parserState->{autoContinue}."\n" if ($parseDebug); + $parserState->{lastNLWasQuoted} = 0; + print STDERR "lastNLWasQuoted -> 0\n" if ($spaceDebug || $stateDebug); if ((!$parserState->{autoContinue}) && (!$parserState->{onlyComments})) { print STDERR "ENDGAME\n" if ($parseDebug); $parserState->{endgame} = 1; + print STDERR "ENDGAME -> 1[NEWLINE]\n" if ($parseDebug || $stateDebug); } } last SWITCH; @@ -581,7 +637,8 @@ sub pythonParse $parserState->{classtype} = "class"; $parserState->{namepending} = 1; $parserState->{bracePending} = 1; - $parserState->pushBrace($part); + # $parserState->pushBrace($part); + $parserState->{autoContinue}++; $parserState->{pushParserStateOnBrace} = 1; } last SWITCH; @@ -592,17 +649,18 @@ sub pythonParse $parserState->{sodclass} = "function"; $parserState->{namepending} = 1; $parserState->{bracePending} = 1; - $parserState->pushBrace($part); + # $parserState->pushBrace($part); + $parserState->{autoContinue}++; } last SWITCH; }; { - print STDERR "NP: ".$parserState->{namepending}." PART \"$part\"\n" if ($parseDebug); + print STDERR "NP: ".$parserState->{namepending}." PART \"$part\"\n" if ($parseDebug || $nameDebug); if (($parserState->{namepending}) && ((!($parserState->{inString} || $parserState->{inComment} || $parserState->{inChar} || $parserState->{inInlineComment})) && ($part =~ /\w/))) { - print STDERR "NAME CHANGED TO $part\n" if ($parseDebug); + print STDERR "NAME CHANGED TO $part\n" if ($parseDebug || $nameDebug); $parserState->{sodname} = $part; $parserState->{namepending} = 0; if (!$parserState->{sodclass}) { @@ -611,6 +669,7 @@ sub pythonParse } print STDERR "default\n" if ($parseDebug); }; + } } if ($parserState->{parsedParamParse} == 1) { @@ -634,28 +693,28 @@ sub pythonParse if ($parserState->{onlyComments}) { $parserState->{setHollowAfter} = 1; # $parserState->setHollowWithLineNumbers($treeCur, $fileoffset, $inputCounter); - print STDERR "ONLYCOMMENTS -> 0\n" if ($parseDebug); + print STDERR "ONLYCOMMENTS -> 0\n" if ($parseDebug || $stateDebug); $parserState->{onlyComments} = 0; } } - if ($parserState->{valuepending} == 1) { - # Skip the "=" part. - $parserState->{valuepending} = 2; - $parserState->{preEqualsSymbol} = $parserState->{sodname}; - } elsif ($parserState->{valuepending} == 2) { - $parserState->{value} .= $part; - } + if (($parserState->{endgame} != 2) && ($parserState->{endgame} != 3)) { + if ($parserState->{valuepending} == 1) { + # Skip the "=" part. + $parserState->{valuepending} = 2; + $parserState->{preEqualsSymbol} = $parserState->{sodname}; + } elsif ($parserState->{valuepending} == 2) { + $parserState->{value} .= $part; + } - if ($part ne "\"") { - $parserState->{justLeftStringToken} = 0; - $parserState->{endOfTripleQuote} = 0; - } - if ($part ne "\\" && $part =~ /\S/) { - $parserState->resetBackslash(); - } + if ($part ne "\"") { + $parserState->{justLeftStringToken} = 0; + $parserState->{endOfTripleQuote} = 0; + } + if ($part ne "\\" && $part =~ /\S/) { + $parserState->resetBackslash(); + } - if (($parserState->{endgame} != 2) && ($parserState->{endgame} != 3)) { if ($treepart ne "") { print STDERR "ADDED PART AS SIBLING OF $treeCur: " if ($parseDebug); $treeCur = $treeCur->addSibling($treepart, $parserState->{seenBraces}); @@ -691,19 +750,22 @@ sub pythonParse my $leading = $parserState->{seenLeading}; my $parentLeading = $parserState->{leadspace}; - print STDERR "NEW PARSER STATE (PPSOB)\n" if ($parseDebug); + print STDERR "NEW PARSER STATE (PPSOB)\n" if ($parseDebug || $stateDebug); $parserState = HeaderDoc::ParserState->new( "FULLPATH" => $fullpath, "lang" => $lang, "sublang" => $sublang ); # $parserState->setHollowWithLineNumbers($treeCur, $fileoffset, $inputCounter); $parserState->{lang} = $lang; $parserState->{inputCounter} = $inputCounter; $parserState->{initbsCount} = 0; # included for consistency.... $parserState->{parentLeading} = $parentLeading || 0; - - if ($leading ne "" && $leading != -1) { - print STDERR "SETTING LEAD SPACE TO \"$leading\"\n" if ($parseDebug); - $parserState->{seenLeading} = $leading; - $parserState->{leadspace} = $leading; - } + $parserState->{leadspace} = -1; + print STDERR "PARENTLEADING -> ".$parserState->{parentLeading}."\n" if ($parseDebug || $stateDebug); + + # In the brace case, we haven't gotten the leading space yet. + # if ($leading ne "" && $leading != -1) { + # print STDERR "SETTING LEAD SPACE TO \"$leading\"\n" if ($parseDebug); + # $parserState->{seenLeading} = $leading; + # $parserState->{leadspace} = $leading; + # } } if ($parserState->{setHollowAfter}) { @@ -712,9 +774,9 @@ sub pythonParse print STDERR "SET HOLLOW TO $treeCur\n" if ($parseDebug); } - if ($parserState->{endgame}) { - # The part has to be reprocessed with the new parser - # state, so don't skip it. + if ($parserState->{endgame} == 2 || $parserState->{endgame} == 3) { + # Either the part has to be reprocessed with the new parser + # state (so redo it) or it's time to quit entirely. if (!scalar(@parserStack)) { $continue = 0; @@ -724,7 +786,7 @@ sub pythonParse } elsif (!$parserState->{onlyComments}) { # @@@ FIXME? @@@ my $treeRef = $parserState->{hollow}; - print STDERR "NEW PARSER STATE (ENDGAME)\n" if ($parseDebug); + print STDERR "NEW PARSER STATE (ENDGAME)\n" if ($parseDebug || $stateDebug); my $leading = $parserState->{seenLeading}; @@ -765,7 +827,7 @@ sub pythonParse $parserState->{parentLeading} = $parentLeading } } - if ($parseDebug) { print STDERR "REDO\n"; } + if ($anyDebug) { print STDERR "REDO\n"; } goto REDO; } else { # This part has been handled. Move on to the @@ -791,6 +853,8 @@ sub pythonParse # $retDebug = 1; + print STDERR "LEAVING PARSER\n" if ($parseDebug || $stateDebug); + return HeaderDoc::BlockParse::blockParseReturnState($parserState, $treeTop, $argparse, $declaration, $inPrivateParamTypes, $publicDeclaration, $lastACS, $retDebug, $fileoffset, 0, $parseTokens{definename}, $inputCounter, $lang, $sublang); } diff --git a/Modules/HeaderDoc/Test.pm b/Modules/HeaderDoc/Test.pm index fc1ceee..20ac07e 100644 --- a/Modules/HeaderDoc/Test.pm +++ b/Modules/HeaderDoc/Test.pm @@ -3,7 +3,7 @@ # Class name: Test # Synopsis: Test Harness # -# Last Updated: $Date: 2011/05/19 13:01:25 $ +# Last Updated: $Date: 2014/02/26 11:18:59 $ # # Copyright (c) 2008 Apple Computer, Inc. All rights reserved. # @@ -143,7 +143,6 @@ use File::Basename; use strict; use vars qw($VERSION @ISA); use Cwd; -use POSIX qw(strftime mktime localtime); use Carp qw(cluck); use HeaderDoc::Utilities qw(processTopLevel); use HeaderDoc::BlockParse qw(blockParseOutside blockParse getAndClearCPPHash); @@ -161,7 +160,7 @@ if ($HeaderDoc::FreezeThaw_available) { # In the git repository, contains the number of seconds since # January 1, 1970. # */ -$HeaderDoc::Test::VERSION = '$Revision: 1305835285 $'; +$HeaderDoc::Test::VERSION = '$Revision: 1393442339 $'; # /*! # @abstract @@ -330,12 +329,19 @@ sub runtest_sub { $HeaderDoc::enableParanoidWarnings = 0; $HeaderDoc::outerNamesOnly = 0; $HeaderDoc::AccessControlState = ""; + + $HeaderDoc::OptionalOrRequired = ""; + $HeaderDoc::idl_language = "idl"; %HeaderDoc::availability_defs = (); %HeaderDoc::availability_has_args = (); # warn "MP: ".$HeaderDoc::modulesPath."Availability.list\n"; - getAvailabilityMacros($HeaderDoc::modulesPath."Availability.list", 1); + if ( -f $HeaderDoc::modulesPath."../../Availability.list") { + getAvailabilityMacros($HeaderDoc::modulesPath."../../Availability.list", 1); + } else { + getAvailabilityMacros($HeaderDoc::modulesPath."Availability.list", 1); + } my $basefilename = basename($self->{FILENAME}); my $coretestfail = 0; @@ -368,6 +374,7 @@ sub runtest_sub { $HeaderDoc::lang = $self->{LANG}; $HeaderDoc::sublang = $self->{SUBLANG}; + my $apiOwner = HeaderDoc::Header->new("LANG" => $self->{LANG}, "SUBLANG" => $self->{SUBLANG}); $apiOwner->apiOwner($apiOwner); my $headerObject = $apiOwner; @@ -557,6 +564,9 @@ print STDERR "ITEM NOW $item\n" if ($localDebug); my $objcAccessControlState = "private:"; # the default in Objective C my $functionGroup = "default_function_group"; + if ($HeaderDoc::sublang eq "IDL") { + $cppAccessControlState = "public:"; # IDLs have no notion of protection, typically. + } my @codeLines = split(/\n/, $self->{CODE}); map(s/$/\n/gm, @codeLines); @@ -608,7 +618,7 @@ print STDERR "ITEM NOW $item\n" if ($localDebug); $results .= "-=: BLOCKPARSE PARSER STATE KEYS :=-\n"; my @pskeys = sort keys %{$parserState}; foreach my $key (@pskeys) { - if ($key !~ /(pplStack|hollow|lastTreeNode|freezeStack|parsedParamList|braceStack|treeStack|endOfTripleQuoteToken|rollbackState|availabilityNodesArray)/) { + if ($key !~ /(pplStack|hollow|lastDisplayNode|lastTreeNode|freezeStack|parsedParamList|braceStack|treeStack|endOfTripleQuoteToken|rollbackState|availabilityNodesArray|parsedParamAtBrace|parsedParamStateAtBrace)/) { $results .= "\$parserState->{$key} => ".$parserState->{$key}."\n"; } else { my $temp = $parserState->{$key}; @@ -756,6 +766,9 @@ print STDERR "ITEM NOW $item\n" if ($localDebug); } } + $headerObject->fixupTypeRequests(); + $headerObject->setupAPIReferences(); + $results .= "-=: FOUND MATCH :=-\n"; $results .= $foundMatch."\n"; $results .= "-=: NAMED OBJECTS :=-\n"; @@ -899,6 +912,46 @@ sub writeToFile { close(WRITEFILE); } +# /*! +# @abstract +# Writes tests to a property list file. Currently +# disabled. +# */ +sub writeToPlist { + my $self = shift; + my $filename = shift; + + # print "SELF: $self\n"; + + eval { + require Data::Plist::XMLWriter; + }; + +return; # for now. + + if ($@) { + warn("Not writing property lists because you do not have Data::Plist.\nTo install it, type:\n sudo cpan YAML\n sudo cpan Data::Plist::XMLWriter\n"); + return; + } + + $filename =~ s/\.test$/\.plist/g; + + # my $plist = Data::Plist->new($self); + + my $writer = Data::Plist::XMLWriter->new; + + my %selfhash = %{$self}; + # foreach my $key (keys %selfhash) { + # print STDERR "DATA $key -> ".$selfhash{$key}."\n"; + # } + + my $str = $writer->write(\%selfhash); + open(WRITEFILE, ">$filename") or die("Could not write file \"$filename\"\n"); + print WRITEFILE $str; + close(WRITEFILE); + +} + # sub dbprint_expanded # { # print STDERR "NOT IMPLEMENTED.\n"; @@ -1073,7 +1126,7 @@ sub showresults_sub print WRITEFILE $got_parts{$key}; close(WRITEFILE); - system("/usr/bin/diff -u /tmp/headerdoc-diff-expected /tmp/headerdoc-diff-got"); + system("/usr/bin/diff -u -U 15 /tmp/headerdoc-diff-expected /tmp/headerdoc-diff-got"); unlink("/tmp/headerdoc-diff-expected"); unlink("/tmp/headerdoc-diff-got"); @@ -1512,6 +1565,11 @@ sub dumpObjNames foreach my $copyobj (@newtrees) { push(@parseTrees, $copyobj); } + ($newret, @newtrees) = $self->dumpEmbeddedClasses($obj, $nest + 1); + $retstring .= $newret; + foreach my $copyobj (@newtrees) { + push(@parseTrees, $copyobj); + } } } if (@methods) { @@ -1614,6 +1672,7 @@ sub dumpObjNames } } } else { + my @objects = $obj->parsedParameters(); if (@objects) { $retstring .= $indent."PARSED PARAMETERS:\n"; @@ -1662,11 +1721,66 @@ sub dumpObjNames } } } + + my ($newret, @newtrees) = $self->dumpEmbeddedClasses($obj, $nest + 1); + $retstring .= $newret; + foreach my $copyobj (@newtrees) { + push(@parseTrees, $copyobj); + } } return ($retstring, @parseTrees); } + +# /*! +# @abstract Dumps information about AppleScript scripts embedded +# within handlers. +# */ +sub dumpEmbeddedClasses +{ + my $self = shift; + my $obj = shift; + my $nest = shift; + + my $class = ref($obj) || $obj; + + my $retstring = ""; + my @parseTrees = (); + my @embeddedClasses = (); + + if ($self->{LANG} eq "applescript" && $class eq "HeaderDoc::Function") { + my $class_self = undef; + if (!$obj->{ASCONTENTSPROCESSED}) { + $class_self = $obj->processAppleScriptFunctionContents(); + } else { + my $class_self_ref = $obj->{AS_CLASS_SELF}; + if ($class_self_ref) { + $class_self = ${$class_self_ref}; + bless($class_self, "HeaderDoc::HeaderElement"); + bless($class_self, $class_self->class()); + } + } + if ($class_self) { + my @tempClasses = $class_self->classes(); + foreach my $obj (@tempClasses) { + push(@embeddedClasses, $obj); + } + } + } + + if (@embeddedClasses) { + foreach my $obj (@embeddedClasses) { + my ($newret, @newtrees) = $self->dumpObjNames($obj, $nest + 1); + $retstring .= $newret; + foreach my $copyobj (@newtrees) { + push(@parseTrees, $copyobj); + } + } + } + return ($retstring, @parseTrees); +} + # /*! # @abstract # Returns whether this Test object supports the diff --git a/Modules/HeaderDoc/TypeHelper.pm b/Modules/HeaderDoc/TypeHelper.pm index e85deab..c0722a9 100644 --- a/Modules/HeaderDoc/TypeHelper.pm +++ b/Modules/HeaderDoc/TypeHelper.pm @@ -3,7 +3,7 @@ # Class name: TypeHelper # Synopsis: Helper code for block parser data type returns # -# Last Updated: $Date: 2011/02/18 19:02:59 $ +# Last Updated: $Date: 2014/02/14 17:55:29 $ # # Copyright (c) 2006 Apple Computer, Inc. All rights reserved. # @@ -100,7 +100,6 @@ BEGIN { } } use HeaderDoc::HeaderElement; -use HeaderDoc::DBLookup; use HeaderDoc::Utilities qw(findRelativePath safeName printArray printHash sanitize); use File::Basename; use Cwd; @@ -116,7 +115,7 @@ use vars qw($VERSION @ISA); # In the git repository, contains the number of seconds since # January 1, 1970. # */ -$HeaderDoc::TypeHelper::VERSION = '$Revision: 1298084579 $'; +$HeaderDoc::TypeHelper::VERSION = '$Revision: 1392429329 $'; # Inheritance # @ISA = qw(HeaderDoc::HeaderElement); diff --git a/Modules/HeaderDoc/Utilities.pm b/Modules/HeaderDoc/Utilities.pm index b0fe355..0a913e0 100644 --- a/Modules/HeaderDoc/Utilities.pm +++ b/Modules/HeaderDoc/Utilities.pm @@ -2,7 +2,7 @@ # Utilities.pm # # Common subroutines -# Last Updated: $Date: 2011/05/17 14:51:53 $ +# Last Updated: $Date: 2014/02/26 10:58:03 $ # # Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved. # @@ -50,6 +50,8 @@ package HeaderDoc::Utilities; use strict; use vars qw(@ISA @EXPORT $VERSION); use Carp qw(cluck); +use IPC::Open2; +use IO::Handle; # use HeaderDoc::MacroFilter qw(filterFileString); use Cwd; @@ -73,12 +75,12 @@ my $depth = 0; # In the git repository, contains the number of seconds since # January 1, 1970. # */ -$HeaderDoc::Utilities::VERSION = '$Revision: 1305669113 $'; +$HeaderDoc::Utilities::VERSION = '$Revision: 1393441083 $'; @ISA = qw(Exporter); @EXPORT = qw(findRelativePath safeName safeNameNoCollide linesFromFile makeAbsolutePath printHash printArray fileNameFromPath folderPathForFile updateHashFromConfigFiles getHashFromConfigFile getVarNameAndDisc - getAPINameAndDisc + getAPINameAndDisc doxyTagFilter registerUID resolveLink parseTokens isKeyword html2xhtml resolveLinks stringToFields sanitize warnHDComment classTypeFromFieldAndBPinfo casecmp unregisterUID @@ -92,7 +94,7 @@ $HeaderDoc::Utilities::VERSION = '$Revision: 1305669113 $'; byMethodType getLangAndSubLangFromFilename splitOnPara peek dumpCaches getDefaultEncoding stripLeading fixXHTMLAttributes html_fixup_links xml_fixup_links - calcDepth); + calcDepth isStandardAvailability); my %uid_list_by_uid = (); my %uid_list = (); @@ -755,6 +757,11 @@ sub linesFromFile { # @param arrayref # A reference to an array containing the candidate API references # to check. +# @result +# Returns the array ($value, $bogus) containing the +# best value and a flag to indicate whether the conflict is +# solely caused by a function parameter or local variable +# that is local to a different function. # */ sub chooseBestAPIRef { @@ -764,12 +771,15 @@ sub chooseBestAPIRef my $localDebug = 0; + my $bogus = 0; + if ($fromObj) { my $headerName = ""; my $className = ""; my $targetLang = $fromObj->lang(); my $targetSubLang = $fromObj->sublang(); my $apiOwner = $fromObj->apiOwner(); + my $name = $fromObj->apiuidname(); if ($fromObj->isAPIOwner()) { my $class = ref($fromObj) || $fromObj; @@ -798,7 +808,62 @@ sub chooseBestAPIRef $headerName =~ s/\s//sgo; $headerName =~ s/<.*?>//sgo; - # First, look for the one in the current class. + my @newarr = (); + # First, look for the one in the current function or declaration. + foreach my $ref (@arr) { + if ($ref =~ /^\/\/([^\/]+)\/([^\/]+)\/([^\/]+)\/([^\/]+)\/([^\/]+)\/([^\/]+)(\/|$)/) { + my $apple_ref_part = $1; + my $language_part = $2; + my $reftype_part = $3; + my $class_part = $4; + my $owning_symbol_part = $5; + my $symbol_part = $6; + + print STDERR "POINT A: REF: $ref reftype_part: $reftype_part\n" if ($localDebug); + + if ($reftype_part =~ /(functionparam|methodparam|defineparam|enumconstant|functionvar|methodvar|definevar|structfield|typedeffield)/) { + if (($class_part eq $className) && ($owning_symbol_part eq $name)) { + print STDERR "CLASSMATCH OWNERMATCH (($class_part eq $className) && ($owning_symbol_part eq $name))\n" if ($localDebug); + + return ($ref, $bogus); + } + } else { + push(@newarr, $ref); + } + } elsif ($ref =~ /^\/\/([^\/]+)\/([^\/]+)\/([^\/]+)\/([^\/]+)\/([^\/]+)(\/|$)/) { + my $apple_ref_part = $1; + my $language_part = $2; + my $reftype_part = $3; + my $owning_symbol_part = $4; + my $symbol_part = $5; + + print STDERR "POINT B: REF: $ref reftype_part: $reftype_part\n" if ($localDebug); + + if ($reftype_part =~ /(functionparam|methodparam|defineparam|enumconstant|functionvar|methodvar|definevar|structfield|typedeffield)/) { + if (($owning_symbol_part eq $name) && ($className eq "")) { + print STDERR "OWNERMATCH ($owning_symbol_part eq $name)\n" if ($localDebug); + return ($ref, $bogus); + } + } else { + push(@newarr, $ref); + } + } else { + push(@newarr, $ref); + } + } + + @arr = @newarr; + + if ($localDebug) { + print STDERR "BOGOSITY CHECK: scalar(\@newarr) is ".scalar(@newarr)."\n"; + foreach my $item (@newarr) { + print STDERR "BOGOSITY CHECK: $item\n"; + } + } + + if (scalar(@newarr) == 1) { $bogus = 1; } + + # Next, look for the one in the current class. foreach my $ref (@arr) { print STDERR "PASS 1. CHECKING REF: $ref\n" if ($localDebug); if ($ref =~ /^\/\/([^\/]+)\/([^\/]+)\/([^\/]+)\/([^\/]+)\/([^\/]+)(\/|$)/) { @@ -812,7 +877,7 @@ sub chooseBestAPIRef print STDERR "CLASS PART: $class_part TARGET: $className\n" if ($localDebug); if ($language_part eq $targetLang || $language_part eq $targetSubLang) { - if ($class_part eq $className) { return $ref; } + if ($class_part eq $className) { return ($ref, $bogus); } } } } @@ -831,7 +896,7 @@ sub chooseBestAPIRef print STDERR "HEADER PART: $class_part TARGET: $headerName\n" if ($localDebug); if ($language_part eq $targetLang || $language_part eq $targetSubLang) { - if ($class_part eq $headerName) { return $ref; } + if ($class_part eq $headerName) { return ($ref, $bogus); } } } } @@ -857,7 +922,7 @@ sub chooseBestAPIRef if ($toObj->filename() eq $fromObj->filename()) { - return $ref; + return ($ref, $bogus); } } elsif (!$toObj) { warn("No object found for UID $ref\n"); @@ -865,7 +930,7 @@ sub chooseBestAPIRef } } - return $arr[0]; + return ($arr[0], $bogus); } # /*! @@ -905,10 +970,14 @@ sub resolveLink $ret = $uid; if ($uid_conflict{$symbol}) { my @candidates = @{$uid_candidates{$symbol}}; - $uid = chooseBestAPIRef($fromObj, $uid_candidates{$symbol}); + my $conflict_is_bogus; + ($uid, $conflict_is_bogus) = chooseBestAPIRef($fromObj, $uid_candidates{$symbol}); $ret = $uid; # foreach my $x (@candidates) { print STDERR "CANDIDATE $x\n"; } - warn "$fullpath:0: warning: multiple matches found for symbol \"$symbol\"!!! Only the nearest matching symbol will be $linkedword. Replace the symbol with a specific api ref tag (e.g. apple_ref) in header file to fix this conflict.\n\nCandidates are:\n\t".join("\n\t", @candidates)."\n\nDefault is:\n\t$uid\n"; + + if (!$conflict_is_bogus) { + warn "$fullpath:0: warning: multiple matches found for symbol \"$symbol\"!!! Only the nearest matching symbol will be $linkedword. Replace the symbol with a specific api ref tag (e.g. apple_ref) in header file to fix this conflict.\n\nCandidates are:\n\t".join("\n\t", @candidates)."\n\nDefault is:\n\t$uid\n"; + } } } if ($ret eq "") { @@ -947,6 +1016,8 @@ sub registerUID($$$) my $object = shift; my $localDebug = 0; + cluck("registerUID: $name\n") if ($localDebug); + if ($HeaderDoc::ignore_apiuid_errors == 2) { return; } if ($object->noRegisterUID()) { return; } @@ -1274,6 +1345,9 @@ sub printHash { # Set to 1 if a class declaration is treated as an # open brace. (This is not used for ObjC clases; # they are special.) +# @var functionisapiowner +# Set to 1 if a function can usefully contain classes and other +# API elements. # @var structisbrace # Set to 1 if a struct declaration is treated as an # open brace. @@ -1330,6 +1404,45 @@ sub printHash { # #define macros to be parsed from the code. This is # only used for code parsing, NOT for interpreting # the actual #define macros themselves! +# @var regexpfirstcharpattern +# A regular expression that matches any symbol that is a +# legal start token for a regular expression. In Perl, +# there are a lot of these. In Ruby and JavaScript, only +# slash (/) is allowed. In Tcl, only a left curly brace +# is allowed (because other regular expressions are just +# strings). +# @var regexpcharpattern +# A regular expression containing a list of tokens that +# are special in regular expressions. In general, only +# start tokens are listed, with the exception of the close +# curly brace. This should probably be the same for every +# language that supports regular expressions. +# @var regexppattern +# A list of special Perl commands that are immediately +# followed by a regular expression (e.g. tr). +# @var singleregexppattern +# A list of special Perl commands that are immediately +# followed by a one-part regular expression (e.g. qq). +# This is a strict subset of {@link regexppattern}. +# @var regexpAllowedAfter +# A list of symbols that a regular expression can +# follow. This prevents other uses of certain common +# symbol (e.g. /) from incorrectly triggering the start +# of regular expression parsing. +# @var regexpAllowedAtStartOfLine +# Set to 1 in languages where regular expressions are +# first-class objects (Ruby) and thus can legally appear +# as the first symbol on a line in addition to places that +# can be detected based on the previous symbol. +# @var TCLregexpcommand +# Set to "regexp" in Tcl. This is a regular expression +# that matches a list of commands in scripting languages +# that can take an unquoted (non-string) regular expression. +# @var rbracetakesargument +# Normally zero. Set to 1 if a right brace marker +# (e.g. end) is followed by another token +# (e.g. tell) that tells what type of block +# it closes. # */ sub parseTokens { @@ -1429,7 +1542,7 @@ sub parseTokens # curly braces in TCL. $parseTokens{parmswithcurlybraces} = 1; $parseTokens{superclasseswithcurlybraces} = 1; - $parseTokens{classregexp} = "^(Class)\$"; + $parseTokens{classregexp} = "^(class)\$"; $parseTokens{varname} = "attribute"; } if ($lang eq "shell" && $sublang eq "csh") { @@ -1440,6 +1553,30 @@ sub parseTokens } $parseTokens{constname} = ""; $parseTokens{structisbrace} = 0; + + if ($lang eq "perl") { + $parseTokens{regexpAllowedAfter} = '(\~|\(|\=|\,)'; + + $parseTokens{regexpcharpattern} = "[[|{}#(/'\"<`]"; + # "}" vi bug workaround for previous line + + # If it appears not after a ~, tr, etc., only allow slash. + $parseTokens{regexpfirstcharpattern} = "[/]"; + # "}" vi bug workaround for previous line + + $parseTokens{regexppattern} = "qq|qr|qx|qw|q|m|s|tr|y"; + $parseTokens{singleregexppattern} = "qq|qr|qx|qw|q|m"; + + } elsif ($lang eq "tcl") { + # Syntax: regexp [-foo [-bar ..]] {expression goes here} ... + $parseTokens{TCLregexpcommand} = "regexp"; + + $parseTokens{regexpfirstcharpattern} = "[{]"; + # "}" vi bug workaround for previous line + + $parseTokens{regexpcharpattern} = "[[|{}#(/'\"<`]"; + # "}" vi bug workaround for previous line + } } elsif ($lang eq "pascal") { print STDERR "Language is Pascal.\n" if ($langDebug); $parseTokens{sotemplate} = ""; @@ -1508,6 +1645,15 @@ sub parseTokens $parseTokens{structisbrace} = 0; $parseTokens{functionisbrace} = 1; $parseTokens{classisbrace} = 1; + + $parseTokens{regexpAllowedAfter} = '(\~|\(|\=|\,|if|elsif|while|unless|until|when)'; + $parseTokens{regexpAllowedAtStartOfLine} = 1; + + $parseTokens{regexpfirstcharpattern} = "[/]"; + # "}" vi bug workaround for previous line + $parseTokens{regexpcharpattern} = "[[|{}#(/'\"<`]"; + # "}" vi bug workaround for previous line + } elsif ($lang eq "applescript") { # Applescript $parseTokens{classregexp} = "^(script)\$"; @@ -1522,15 +1668,29 @@ sub parseTokens $parseTokens{ilc} = "--"; $parseTokens{ilc_b} = "#"; # $parseTokens{lbrace} = "{"; - $parseTokens{lbraceunconditionalre} = "^(tell)"; - $parseTokens{rbrace} = "end"; + + # These always start a block ending in "end" + # $parseTokens{lbraceunconditionalre} = "^(repeat|try)\$"; + + # These might, if they aren't followed by the corresponding simple token. + $parseTokens{lbraceprecursor} = "^(if|tell)\$"; + $parseTokens{lbraceprecursorre} = "^(then|to)\$"; + # If this is followed by an "if", ignore the "if". + $parseTokens{lbracepreventerre} = "^(else)\$"; + # These do if they're after a newline. + $parseTokens{lbraceconditionalre} = "^(considering|ignoring|repeat|tell|try|using|with)\$"; + + # $parseTokens{rbrace} = "end"; + $parseTokens{rbraceconditionalre} = "^(end)\$"; + $parseTokens{rbracetakesargument} = 1; $parseTokens{varname} = "property"; # $parseTokens{constname} = "const"; $parseTokens{structisbrace} = 0; + $parseTokens{functionisapiowner} = 1; $parseTokens{functionisbrace} = 1; $parseTokens{classisbrace} = 1; $parseTokens{assignmentwithcolon} = 1; - $parseTokens{labelregexp} = "^(about|above|against|apart from|around|aside from|at|below|beneath|beside|between|by|for|from|instead of|into|on|onto|out of|over|since|thru|through|under)"; + $parseTokens{labelregexp} = "^(about|above|against|apart from|around|aside from|at|below|beneath|beside|between|by|for|from|instead of|into|on|onto|out of|over|since|thru|through|under)\$"; $parseTokens{sofunction} = "on"; @@ -1588,6 +1748,15 @@ sub parseTokens $parseTokens{accessregexp} = "^(public|private|protected)\$"; $parseTokens{ilc_b} = "#"; } + if ($lang eq "java" && $sublang eq "javascript") { + $parseTokens{regexpAllowedAfter} = '(\(|\=|\,)'; + + $parseTokens{regexpcharpattern} = "[[|{}#(/'\"<`]"; + # "}" vi bug workaround for previous line + $parseTokens{regexpfirstcharpattern} = '[/]'; + # "}" vi bug workaround for previous line + + } $parseTokens{soc} = "/*"; $parseTokens{eoc} = "*/"; @@ -1695,9 +1864,9 @@ sub isKeyword } -use FileHandle; -use IPC::Open2; -use Fcntl; +# use FileHandle; +# use IPC::Open2; +# use Fcntl; # /*! @group XML Helpers # @abstract @@ -1946,6 +2115,10 @@ sub resolveLinks($$$) if ( ! -x $resolverpath) { $resolverpath = "/sw/bin/resolveLinks"; } + if ( ! -x $resolverpath) { + $resolverpath = $HeaderDoc::modulesPath."../../../../bin/resolveLinks"; + # print "RP: $resolverpath\n"; + } if ( ! -x $resolverpath) { $resolverpath = $HeaderDoc::modulesPath."bin/resolveLinks"; warn("You are probably using an old resolveLinks.\n"); @@ -2077,7 +2250,7 @@ sub validTag ($field =~ s/^meta(\s+|$)//sio) && do { return $include_second_tier; }; ($field =~ s/^method(\s+|$)//sio) && do { return $include_first_tier; }; ($field =~ s/^methodgroup(\s+|$)//sio) && do { return $include_first_tier; }; - ($field =~ s/^name(\s+|$)//sio) && do { return $include_second_tier; }; + ($field =~ s/^name(\s+|$)//sio) && do { return $include_first_tier; }; ($field =~ s/^namespace(\s+|$)//sio) && do { return $include_second_tier; }; ($field =~ s/^note(\s+|$)//sio) && do { return -$include_second_tier; }; ($field =~ s/^noParse(\s+|$)//sio) && do { return $include_second_tier; }; @@ -2133,6 +2306,8 @@ sub replaceTag($$$) my $iter = shift; my $xml_mode = shift; + my $localDebug = 0; + my @fields = @{$fieldsref}; my $tag = $fields[$iter]; @@ -2146,29 +2321,25 @@ sub replaceTag($$$) } my $xmlkey = ""; - my $htmlkey = ""; - my $cssindentclass = ""; my $title = ""; my $body = ""; my $text; my $rest; - my $done; + my $more_after; # If true, there's more content after this. if ($tag =~ s/^warning(\s|$)//si) { $tag =~ s/^\s*//sg; - ($text, $rest, $done) = splitOnPara($tag); + ($text, $rest, $more_after) = splitOnPara($tag); - $xmlkey = "hd_warning"; - $htmlkey = "WARNING:"; - $cssindentclass = "warning_indent"; + $xmlkey = "hd_warning_internal"; + $body = $text; } elsif ($tag =~ s/^important(\s|$)//si) { $tag =~ s/^\s*//sg; - ($text, $rest, $done) = splitOnPara($tag); + ($text, $rest, $more_after) = splitOnPara($tag); - $xmlkey = "hd_important"; - $htmlkey = "Important:"; - $cssindentclass = "important_indent"; + $xmlkey = "hd_important_internal"; + $body = $text; } elsif ($tag =~ s/^note(\s|$)//si) { my $notitle = 0; if ($1 =~ /[\n\r]/ || $tag =~ /^\s*[\n\r]+/) { @@ -2176,7 +2347,7 @@ sub replaceTag($$$) } $tag =~ s/^\s*//sg; - ($text, $rest, $done) = splitOnPara($tag); + ($text, $rest, $more_after) = splitOnPara($tag); if ($notitle) { $body = $text; @@ -2188,9 +2359,7 @@ sub replaceTag($$$) if ($title !~ /\S/) { $title = "Note"; } - $xmlkey = "hd_note"; - $htmlkey = "Note:"; - $cssindentclass = "note_indent"; + $xmlkey = "hd_note_internal"; } else { warn "Could not replace unknown tag \"$tag\"\n"; return ($fieldsref, 0, ""); @@ -2199,42 +2368,42 @@ sub replaceTag($$$) # Now that we have this in $tag, wipe it from the array. $fields[$iter] = ""; - # print STDERR "XMLKEY: $xmlkey\n"; - # print STDERR "HTMLKEY: $htmlkey\n"; - # print STDERR "CSSINDENTCLASS: $cssindentclass\n"; - # print STDERR "TEXT: $text\n"; - # print STDERR "TITLE: $title\n"; - # print STDERR "BODY: $body\n"; - my $append = ""; my $tail = ""; - if ($title) { - if ($xml_mode) { - $append = "<$xmlkey>$title

".$body; - $tail = "

\n$rest"; - } else { - $append = "

$title:

".$body; - $tail = "

\n$rest"; - } - } else { - if ($xml_mode) { - $append = "<$xmlkey>

".$text; - $tail = "

\n$rest"; - } else { - $append = "

$htmlkey

".$text; - $tail = "

\n$rest"; - } + + $append = "<$xmlkey>$title

".$body; + $tail = "

\n$rest"; + + if ($localDebug) { + print STDERR "CONVERSION:\n"; + print STDERR " XMLKEY: $xmlkey\n"; + # print STDERR " HTMLKEY: $htmlkey\n"; + # print STDERR " CSSINDENTCLASS: $cssindentclass\n"; + print STDERR " TEXT: $text\n"; + print STDERR " TITLE: $title\n"; + print STDERR " BODY: $body\n"; + + print STDERR "APPEND: $append\n"; + print STDERR "TAIL: $tail\n"; + print STDERR "ITER: $iter\n"; } - if ($done) { + if ($more_after) { # We got a paragraph break. Append the closing bits immediately. + + print STDERR "DONE. ADDING $tail TO APPEND\n" if ($localDebug); + $append .= $tail; } else { # No paragraph break. Figure out where to append the closing tags. if ($iter == $#fields) { # This is the last part. Append it immediately. $append .= $tail; + + print STDERR "LASTFIELD. ADDING $tail TO APPEND\n" if ($localDebug); } else { + my $origiter = $iter; + $iter++; while (1) { my $nextfield = $fields[$iter]; @@ -2253,17 +2422,26 @@ sub replaceTag($$$) if ($iter > $#fields) { last; } # Break at the one after the last field. } - # print STDERR "Adding $tail before node ".$fields[$iter]."\n"; + print STDERR "Adding $tail before node ".$fields[$iter]."\n" if ($localDebug); $iter--; - # print STDERR "IN NODE: ".$fields[$iter]."\n"; + if ($iter == $origiter) { + # Immediately encountered a tag that can't be part of the + # note/important/warning box. Append the close tag immediately. + $append .= $tail; + } else { + print STDERR "IN NODE $iter: ".$fields[$iter]."\n" if ($localDebug); + + ($text, $rest, $more_after) = splitOnPara($fields[$iter]); - ($text, $rest, $done) = splitOnPara($fields[$iter]); + print STDERR "TEXT: $text\nREST: $rest\nDONE: $more_after\n" if ($localDebug); - # print STDERR "TEXT: $text\nREST: $rest\nDONE: $done\n"; + $fields[$iter] = $text.$tail.$rest; - $fields[$iter] = $text.$tail.$rest; + print STDERR "MODIFYING FIELD WITH $tail\n" if ($localDebug); + print STDERR "NOW: ".$fields[$iter]."\n" if ($localDebug); + } } } @@ -2849,6 +3027,7 @@ sub classTypeFromFieldAndBPinfo ($classBPtype =~ /typedef/) && do { return "C"; }; ($classBPtype =~ /struct/) && do { return "C"; }; ($classBPtype =~ /class/) && do { return $sublang; }; + ($classBPtype =~ /script/) && do { return $sublang; }; ($classBPtype =~ /interface/) && do { return $sublang; }; ($classBPtype =~ /implementation/) && do { return $sublang; }; ($classBPtype =~ /module/) && do { return $sublang; }; @@ -2980,11 +3159,12 @@ sub complexAvailabilityTokenToOSAndVersion($) my $os = ""; if ($string =~ s/^__IPHONE_//) { - $os = "iPhone OS"; + $os = "iOS"; } elsif ($string =~ s/^__MAC_//) { $os = "Mac OS X"; } else { warn "Unknown OS in availability string \"$string\". Giving up.\n"; + # cluck("bt\n"); return ""; } @@ -3383,9 +3563,9 @@ sub filterHeaderDocTagContents "ul" => 1, "var" => 1, - "hd_warning" => 1, # Used for @warning. - "hd_important" => 1, # Used for @important - "hd_note" => 1 # Used for @note + "hd_warning_internal" => 1, # Used for @warning. + "hd_important_internal" => 1, # Used for @important + "hd_note_internal" => 1 # Used for @note ); my %discouraged_tags = ( @@ -3500,6 +3680,9 @@ sub filterHeaderDocTagContents } elsif ($tagname eq "!--") { # Likewise. $tagcontents .= $close.$htmltag; + } elsif ($tagname eq "note_title") { + # Likewise. + $tagcontents .= $close.$htmltag; } elsif ($recommended_tags{lc($tagname)} || $custom_tags{lc($tagname)}) { print STDERR "Recommented tag $tagname\n" if ($filterTagsDebug); $attributes = fixXHTMLAttributes($attributes); @@ -4614,14 +4797,15 @@ sub getLineArrays { } # print "LINKLINE: $line\n"; # if ($lang eq "java" || $HeaderDoc::parse_javadoc) { - $line =~ s/\@ref\s+(\w+)\s*(\(\))?/\@link $1\@\/link<\/code>/sgio; - $line =~ s/\{\s*\@linkdoc\s+(.*?)\}/\@link $1\@\/link<\/i>/sgio; - $line =~ s/\{\s*\@linkplain\s+(.*?)\}/\@link $1\@\/link/sgio; - $line =~ s/\{\s*\@link\s+(.*?)\}/\@link $1\@\/link<\/code>/sgio; - $line =~ s/\{\s*\@docroot\s*\}/\\\@\\\@docroot/sgio; - # if ($line =~ /value/o) { warn "line was: $line\n"; } - $line =~ s/\{\@value\}/\@value/sgio; - $line =~ s/\{\@inheritDoc\}/\@inheritDoc/sgio; + ### $line =~ s/\@ref\s+(\w+)\s*(\(\))?/\@link $1\@\/link<\/code>/sgio; + ### $line =~ s/\{\s*\@linkdoc\s+(.*?)\}/\@link $1\@\/link<\/i>/sgio; + ### $line =~ s/\{\s*\@linkplain\s+(.*?)\}/\@link $1\@\/link/sgio; + ### $line =~ s/\{\s*\@link\s+(.*?)\}/\@link $1\@\/link<\/code>/sgio; + ### $line =~ s/\{\s*\@docroot\s*\}/\\\@\\\@docroot/sgio; + ### # if ($line =~ /value/o) { warn "line was: $line\n"; } + ### $line =~ s/\{\@value\}/\@value/sgio; + ### $line =~ s/\{\@inheritDoc\}/\@inheritDoc/sgio; + $line = doxyTagFilter($line); # if ($line =~ /value/o) { warn "line now: $line\n"; } # } $line =~ s/([^\\])\@docroot/$1\\\@\\\@docroot/sgi; @@ -4657,14 +4841,15 @@ sub getLineArrays { $line =~ s/^[ \t]*#//s; } # print "LINKLINE2: $line\n"; - $line =~ s/\{\s*\@linkdoc\s+(.*?)\}/\@link $1\@\/link<\/i>/sgio; - $line =~ s/\{\s*\@linkplain\s+(.*?)\}/\@link $1\@\/link/sgio; - $line =~ s/\{\s*\@link\s+(.*?)\}/\@link $1\@\/link<\/code>/sgio; - # $line =~ s/\{\s*\@docroot\s*\}/\\\@\\\@docroot/sgio; - # if ($line =~ /value/so) { warn "line was: $line\n"; } - $line =~ s/\{\@value\}/\@value/sgio; - $line =~ s/\{\@inheritDoc\}/\@inheritDoc/sgio; - $line =~ s/\{\s*\@docroot\s*\}/\\\@\\\@docroot/sgo; + ### $line =~ s/\{\s*\@linkdoc\s+(.*?)\}/\@link $1\@\/link<\/i>/sgio; + ### $line =~ s/\{\s*\@linkplain\s+(.*?)\}/\@link $1\@\/link/sgio; + ### $line =~ s/\{\s*\@link\s+(.*?)\}/\@link $1\@\/link<\/code>/sgio; + ### # $line =~ s/\{\s*\@docroot\s*\}/\\\@\\\@docroot/sgio; + ### # if ($line =~ /value/so) { warn "line was: $line\n"; } + ### $line =~ s/\{\@value\}/\@value/sgio; + ### $line =~ s/\{\@inheritDoc\}/\@inheritDoc/sgio; + ### $line =~ s/\{\s*\@docroot\s*\}/\\\@\\\@docroot/sgo; + $line = doxyTagFilter($line); my %lineentry = (); $lineentry{INTEXTBLOCK} = $in_textblock; @@ -4925,6 +5110,38 @@ sub getAvailabilityMacros } } +# /*! +# @abstract Returns whether the availability macro is one of the +# standard OS-version-based macros. +# */ +sub isStandardAvailability +{ + my $token = shift; + + # e.g. AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_8 + # becomes "Introduced in Mac OS X v10.7, but later deprecated in Mac OS X v10.8." + if ($token =~ /AVAILABLE_MAC_OS_X_VERSION_(\d+)_(\d+)_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_(\d+)_(\d+)/) { + my ($majorintro, $minorintro, $majordep, $minordep) = ($1, $2, $3, $4); + return "Introduced in Mac OS X v$majorintro.$minorintro, but later deprecated in Mac OS X v$majordep.$minordep." + } + + # e.g. AVAILABLE_MAC_OS_X_VERSION_10_8_AND_LATER + # becomes "Introduced in Mac OS X v10.8." + if ($token =~ /AVAILABLE_MAC_OS_X_VERSION_(\d+)_(\d+)_AND_LATER/) { + my ($major, $minor) = ($1, $2); + return "Introduced in Mac OS X v$major.$minor."; + } + + # e.g. DEPRECATED_IN_MAC_OS_X_VERSION_10_8_AND_LATER + # becomes "Deprecated in Mac OS X v10.8." + if ($token =~ /DEPRECATED_IN_MAC_OS_X_VERSION_(\d+)_(\d+)_AND_LATER/) { + my ($major, $minor) = ($1, $2); + return "Deprecated in Mac OS X v$major.$minor."; + } + + return ""; +} + # /*! @group Debugging Functions */ # /*! @@ -5438,15 +5655,43 @@ sub fixup_links my $element = ""; my $movespace = ""; my $in_link = 0; + + my $in_warning_et_al = ""; + foreach my $nextelt (@elements) { if ($first) { $first = 0; $element = $nextelt; next; } + # print "ELEMENT: $element\n"; # print "NEXTELT: $nextelt\n"; + if ($nextelt =~ /^\/hd_link>/s) { $element =~ s/(\s*)$//s; $movespace = $1; } - if ($element =~ /^hd_link posstarget=\"(.*?)\">/o) { + if ($element =~ /^hd_warning_internal>/o) { + $in_warning_et_al .= "<".$element; + + } elsif ($element =~ s/^\/hd_warning_internal>//o) { + $ret .= warningFixup($self, "WARNING:", "warning_indent", $mode, $in_warning_et_al); + $in_warning_et_al = ""; + + } elsif ($element =~ /^hd_important_internal>/o) { + $in_warning_et_al .= "<".$element; + + } elsif ($element =~ s/^\/hd_important_internal>//o) { + $ret .= warningFixup($self, "Important:", "important_indent", $mode, $in_warning_et_al); + $in_warning_et_al = ""; + + } elsif ($element =~ /^hd_note_internal>/o) { + $in_warning_et_al .= "<".$element; + + } elsif ($element =~ s/^\/hd_note_internal>//o) { + $ret .= warningFixup($self, "Note:", "note_indent", $mode, $in_warning_et_al); + $in_warning_et_al = ""; + + } elsif ($in_warning_et_al) { + $in_warning_et_al .= "<".$element; + } elsif ($element =~ /^hd_link posstarget=\"(.*?)\">/o) { $in_link = 1; # print STDERR "found.\n"; my $oldtarget = $1; @@ -5486,8 +5731,7 @@ sub fixup_links # $ret .= "\n"; # } } - } else { - if ($element =~ s/^\/hd_link>//o) { + } elsif ($element =~ s/^\/hd_link>//o) { $in_link = 0; # print "LEAVING LINK\n"; if ($nextelt =~ /^\s*[.,?!]/) { @@ -5499,17 +5743,82 @@ sub fixup_links $ret .= "$movespace"; } $ret .= $element; - } else { + } else { $ret .= "<$element"; - } } $element = $nextelt; } $ret =~ s/^//s; + + my $xmlkey = $1; + + $xmlkey =~ s/_internal$//s; + + $contents =~ s/^\s*(.*?)<\/note_title>//s; + + my $title = $1; + my $append = ""; + my $tail = ""; + + print STDERR " HTMLKEY: $htmlkey\n" if ($localDebug); + print STDERR " CSSCLASS: $cssindentclass\n" if ($localDebug); + print STDERR " XMLKEY: $xmlkey\n" if ($localDebug); + print STDERR " TITLE: $title\n" if ($localDebug); + print STDERR " CONTENTS: $contents\n" if ($localDebug); + + if ($title) { + if ($xml_mode) { + $append = "<$xmlkey>$title"; + $tail = "\n"; + } else { + $append = "

$title:

"; + $tail = "
\n"; + } + } else { + if ($xml_mode) { + $append = "<$xmlkey>"; + $tail = "\n"; + } else { + $append = "

$htmlkey

"; + $tail = "
\n"; + } + } + + my $updatedcontents = fixup_links($self, $contents, $xml_mode); + + print STDERR "CONTENTS: $contents\n" if ($localDebug); + print STDERR "UPDATED CONTENTS: $updatedcontents\n" if ($localDebug); + + return $append.$updatedcontents.$tail; +} + # /*! # @abstract # Converts \@link tags in a string into @@ -5576,6 +5885,26 @@ sub calcDepth return $depth; } +# /*! @abstract +# Performs conversion of certain Doxygen and JavaDoc tags. +# */ +sub doxyTagFilter +{ + my $line = shift; + + $line =~ s/\@ref\s+(\w+)\s*(\(\))?/\@link $1\@\/link<\/code>/sgio; + $line =~ s/\{\s*\@linkdoc\s+(.*?)\}/\@link $1\@\/link<\/i>/sgio; + $line =~ s/\{\s*\@linkplain\s+(.*?)\}/\@link $1\@\/link/sgio; + $line =~ s/\{\s*\@link\s+(.*?)\}/\@link $1\@\/link<\/code>/sgio; + # $line =~ s/\{\s*\@docroot\s*\}/\\\@\\\@docroot/sgio; + # if ($line =~ /value/so) { warn "line was: $line\n"; } + $line =~ s/\{\@value\}/\@value/sgio; + $line =~ s/\{\@inheritDoc\}/\@inheritDoc/sgio; + $line =~ s/\{\s*\@docroot\s*\}/\\\@\\\@docroot/sgo; + + return $line; +} + 1; diff --git a/apicoverage.sh b/apicoverage.sh index cc6dff5..21e0783 100755 --- a/apicoverage.sh +++ b/apicoverage.sh @@ -8,7 +8,7 @@ EXITSTATUS=0 echo "Checking function coverage:" echo -for i in headerDoc2HTML.pl gatherHeaderDoc.pl headerwalk.pl headerdoc_tp/tp_webkit_tools/filtermacros.pl Modules/HeaderDoc/*.pm ; do +for i in headerDoc2HTML.pl gatherHeaderDoc.pl headerwalk.pl perl2c.pl headerdoc_tp/tp_webkit_tools/filtermacros.pl Modules/HeaderDoc/*.pm ; do if [ -f "$i" ] ; then COMMENTS="$(grep -B 1 '^[ ]*sub[ ]' "$i" | grep -v '^[ ]*sub[ ]' | grep -v '^--' | grep -c '[ ]*#[^#]*\*\/')" SUBS="$(grep -c '^[ ]*sub[ ]' "$i")"; @@ -139,7 +139,7 @@ scanforallmissingkeys() ALLKEYS_SCRIPT="$ALLKEYS_SCRIPT "' }' ALLKEYS_SCRIPT="$ALLKEYS_SCRIPT "'}' - for i in headerDoc2HTML.pl gatherHeaderDoc.pl headerwalk.pl Modules/HeaderDoc/*.pm ; do + for i in headerDoc2HTML.pl gatherHeaderDoc.pl headerwalk.pl perl2c.pl Modules/HeaderDoc/*.pm ; do KEYS="$KEYS $(cat "$i" | grep -v '^[[:space:]]*\#' | perl -e "$ALLKEYS_SCRIPT")" done @@ -181,7 +181,7 @@ scanforallmissingkeys() DOCKEYS_SCRIPT="$DOCKEYS_SCRIPT "' }' DOCKEYS_SCRIPT="$DOCKEYS_SCRIPT "'}' - for i in headerDoc2HTML.pl gatherHeaderDoc.pl headerwalk.pl Modules/HeaderDoc/*.pm ; do + for i in headerDoc2HTML.pl gatherHeaderDoc.pl headerwalk.pl perl2c.pl Modules/HeaderDoc/*.pm ; do DOCUMENTED_KEYS="$DOCUMENTED_KEYS $(cat "$i" | perl -e "$DOCKEYS_SCRIPT")" done @@ -242,7 +242,7 @@ scanformissingglobals() CODE="$CODE"' }' DATA="$( - for i in headerDoc2HTML.pl gatherHeaderDoc.pl headerwalk.pl Modules/HeaderDoc/*.pm ; do + for i in headerDoc2HTML.pl gatherHeaderDoc.pl headerwalk.pl perl2c.pl Modules/HeaderDoc/*.pm ; do sed 's/#.*$//' "$i" | grep -v '^[[:space:]]*use' | grep -v '^[[:space:]]*require' | perl -e "$CODE" | grep '^HeaderDoc::' done | sort -u diff --git a/com.apple.headerdoc.exampletocteplate.html b/com.apple.headerdoc.exampletocteplate.html new file mode 100644 index 0000000..a92f80a --- /dev/null +++ b/com.apple.headerdoc.exampletocteplate.html @@ -0,0 +1,87 @@ + + + + API Reference: $$framework@@ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+
+ +

+
$$frameworkdiscussion@@
+
+
+
+

Headers

+ + $$headerlist cols=3 order=down atts=border="0" cellpadding="1" cellspacing="0" width="420"@@ +

Functions

+ $$functionlist cols=3 order=down atts=border="0" cellpadding="1" cellspacing="0" width="420"@@ +
+ + + + + + + + + + + +
+
+ $$copyright@@ +
+
+
+ + + + + + + + + + + diff --git a/gatherHeaderDoc.pl b/gatherHeaderDoc.pl index 5c2f737..1072206 100755 --- a/gatherHeaderDoc.pl +++ b/gatherHeaderDoc.pl @@ -4,7 +4,7 @@ # Synopsis: Finds all HeaderDoc generated docs in an input # folder and creates a top-level HTML page to them # -# Last Updated: $Date: 2011/03/18 14:20:22 $ +# Last Updated: $Date: 2012/10/11 16:16:46 $ # # Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved. # @@ -27,7 +27,7 @@ # # @APPLE_LICENSE_HEADER_END@ # -# $Revision: 1300483222 $ +# $Revision: 1349997406 $ ###################################################################### # /*! @@ -56,6 +56,10 @@ # */ my $uninstalledModulesPath; # /*! @abstract +# Path to the Perl modules in the developer tools package. +# */ +my $devtoolsModulesPath; +# /*! @abstract # Indicates that an internal link resolution tool was found. # */ my $has_resolver; @@ -91,6 +95,7 @@ BEGIN $isMacOS = 0; } $uninstalledModulesPath = "$FindBin::Bin"."$pathSeparator"."Modules"; + $devtoolsModulesPath = "$FindBin::Bin"."$pathSeparator".".."."$pathSeparator"."share"."$pathSeparator"."headerdoc"."$pathSeparator"."Modules"; $HeaderDoc::use_styles = 0; } @@ -102,6 +107,7 @@ BEGIN use File::Copy; # use Carp qw(cluck); use lib $uninstalledModulesPath; +use lib $devtoolsModulesPath; use POSIX; # /*! @abstract @@ -266,9 +272,11 @@ BEGIN $usersPreferencesPath = $homeDir.$pathSeparator."Library".$pathSeparator."Preferences"; $systemPreferencesPath = "/Library/Preferences"; } +my $usrPreferencesPath = "/usr/share/headerdoc/conf"; +my $devtoolsPreferencesPath = "$FindBin::Bin"."$pathSeparator".".."."$pathSeparator"."share"."$pathSeparator"."headerdoc"."$pathSeparator"."conf"; my $CWD = getcwd(); -my @configFiles = ($systemPreferencesPath.$pathSeparator.$preferencesConfigFileName, $usersPreferencesPath.$pathSeparator.$preferencesConfigFileName, $Bin.$pathSeparator.$localConfigFileName, $CWD.$pathSeparator.$localConfigFileName); +my @configFiles = ($devtoolsPreferencesPath.$pathSeparator.$preferencesConfigFileName, $systemPreferencesPath.$pathSeparator.$preferencesConfigFileName, $usersPreferencesPath.$pathSeparator.$preferencesConfigFileName, $Bin.$pathSeparator.$localConfigFileName, $CWD.$pathSeparator.$localConfigFileName); # ($Bin.$pathSeparator.$localConfigFileName, $usersPreferencesPath.$pathSeparator.$preferencesConfigFileName); @@ -314,6 +322,18 @@ BEGIN my $externalAPIUIDPrefixes = ""; my %usedInTemplate = (); +# /*! +# @abstract +# Controls whether to add the [Top] link above the TOC +# when in frame-style or iframe-style TOC mode. +# @discussion +# This value is set based on the addTopLink +# line in the configuration file, or 1 by default. +# */ +$HeaderDoc::addTopLink = 1; +if (defined $config{"addTopLink"}) { + $HeaderDoc::addTopLink = $config{"addTopLink"}; +} if (defined $config{"dateFormat"}) { $HeaderDoc::datefmt = $config{"dateFormat"}; if ($HeaderDoc::datefmt !~ /\S/) { @@ -455,21 +475,37 @@ BEGIN if (defined $config{"stripDotH"}) { $stripDotH = $config{"stripDotH"}; } + + +# /*! +# @abstract +# The background color for the built-in (default) template. +# */ +$GHD::bgcolor = "#ffffff"; + +my $TOCTemplateFile = "HEADERDOC_DEFAULT_INTERNAL_TEMPLATE"; if (defined $config{"TOCTemplateFile"}) { - my $TOCTemplateFile = $config{"TOCTemplateFile"}; + $TOCTemplateFile = $config{"TOCTemplateFile"}; +} + +my $oldRecSep = $/; +undef $/; # read in files as strings - my $oldRecSep = $/; - undef $/; # read in files as strings +my @filelist = split(/\s/, $TOCTemplateFile); +foreach my $file (@filelist) { + my %used = (); - my @filelist = split(/\s/, $TOCTemplateFile); - foreach my $file (@filelist) { - my %used = (); + my $TOCTemplate = ""; + my $found = 0; + my $foundpath = ""; + if ($file eq "HEADERDOC_DEFAULT_INTERNAL_TEMPLATE") { + $found = 1; + $foundpath = "n/a"; + $TOCTemplate = default_template(); + } else { print STDERR "Searching for $file\n"; - my @templateFiles = ($systemPreferencesPath.$pathSeparator.$file, $usersPreferencesPath.$pathSeparator.$file, $Bin.$pathSeparator.$file, $file); - my $TOCTemplate = ""; - my $found = 0; - my $foundpath = ""; + my @templateFiles = ($devtoolsPreferencesPath.$pathSeparator.$file, $usrPreferencesPath.$pathSeparator.$file, $systemPreferencesPath.$pathSeparator.$file, $usersPreferencesPath.$pathSeparator.$file, $Bin.$pathSeparator.$file, $file); foreach my $filename (@templateFiles) { if (open(TOCFILE, "<$filename")) { @@ -484,52 +520,52 @@ BEGIN } else { print STDERR "Found at $foundpath\n"; } - push(@TOCTemplateList, $TOCTemplate); - push(@TOCNames, basename($file)); + } + push(@TOCTemplateList, $TOCTemplate); + push(@TOCNames, basename($file)); - if ($TOCTemplate =~ /\$\$\s*typelist/) { - $gather_types = 1; - $used{type} = 1; - } - if ($TOCTemplate =~ /\$\$\s*proplist/) { - $gather_properties = 1; - $used{prop} = 1; - } - if ($TOCTemplate =~ /\$\$\s*datalist/) { - $gather_globals_and_constants = 1; - $used{data} = 1; - } - if ($TOCTemplate =~ /\$\$\s*functionlist/) { - $gather_functions = 1; - $used{function} = 1; - } - if ($TOCTemplate =~ /\$\$\s*manpagelist/) { - $gather_man_pages = 1; - $used{manpage} = 1; - } + if ($TOCTemplate =~ /\$\$\s*typelist/) { + $gather_types = 1; + $used{type} = 1; + } + if ($TOCTemplate =~ /\$\$\s*proplist/) { + $gather_properties = 1; + $used{prop} = 1; + } + if ($TOCTemplate =~ /\$\$\s*datalist/) { + $gather_globals_and_constants = 1; + $used{data} = 1; + } + if ($TOCTemplate =~ /\$\$\s*functionlist/) { + $gather_functions = 1; + $used{function} = 1; + } + if ($TOCTemplate =~ /\$\$\s*manpagelist/) { + $gather_man_pages = 1; + $used{manpage} = 1; + } - if ($TOCTemplate =~ /\$\$\s*headerlist/) { - $used{header} = 1; - } - if ($TOCTemplate =~ /\$\$\s*macrolist/) { - $used{macro} = 1; - } - if ($TOCTemplate =~ /\$\$\s*protocollist/) { - $used{protocol} = 1; - } - if ($TOCTemplate =~ /\$\$\s*categorylist/) { - $used{category} = 1; - } - if ($TOCTemplate =~ /\$\$\s*classlist/) { - $used{class} = 1; - } - if ($TOCTemplate =~ /\$\$\s*comintlist/) { - $used{comint} = 1; - } - $usedInTemplate{$TOCTemplate} = \%used; + if ($TOCTemplate =~ /\$\$\s*headerlist/) { + $used{header} = 1; + } + if ($TOCTemplate =~ /\$\$\s*macrolist/) { + $used{macro} = 1; + } + if ($TOCTemplate =~ /\$\$\s*protocollist/) { + $used{protocol} = 1; + } + if ($TOCTemplate =~ /\$\$\s*categorylist/) { + $used{category} = 1; + } + if ($TOCTemplate =~ /\$\$\s*classlist/) { + $used{class} = 1; + } + if ($TOCTemplate =~ /\$\$\s*comintlist/) { + $used{comint} = 1; } - $/ = $oldRecSep; + $usedInTemplate{$TOCTemplate} = \%used; } +$/ = $oldRecSep; my $useBreadcrumbs = 0; @@ -575,18 +611,6 @@ BEGIN unless (@inputFiles) { print STDERR "No valid input files specified. \n\n"; exit(-1)}; -# /*! -# @abstract -# The background color for the built-in (default) template. -# */ -$GHD::bgcolor = "#ffffff"; - -if (!scalar(@TOCTemplateList)) { - my $TOCTemplate = default_template(); - push(@TOCTemplateList, $TOCTemplate); - push(@TOCNames, "masterTOC.html") -} - # print STDERR "GatherFunc: $gather_functions\n"; # print STDERR "TT: $TOCTemplate\n"; @@ -671,7 +695,7 @@ sub getFiles { my $frameworkabstract = ""; my $frameworkdiscussion = ""; -my $oldRecSep = $/; +$oldRecSep = $/; undef $/; # read in files as strings my $localDebug = 0; @@ -1006,6 +1030,10 @@ sub getFiles { print STDERR "Header Path: $frameworkpath\n"; print STDERR "Related: $frameworkrelated\n"; } + } elsif ($tmpType eq "abstract") { + print STDERR "Ignored abstract\n" if ($localDebug); + } elsif ($tmpType eq "discussion") { + print STDERR "Ignored discussion\n" if ($localDebug); } elsif ($tmpType eq "inheritedContent") { print STDERR "Inherited content: ".$docRef->name()."\n" if ($localDebug); } elsif ($tmpType eq "econst") { @@ -1290,7 +1318,11 @@ sub printMasterTOC { my $templatefilename = $TOCNames[$template_number]; my $templatename = $templatefilename; - print STDERR "Writing output file for template \"$templatename\"\n"; + if ($templatename eq "HEADERDOC_DEFAULT_INTERNAL_TEMPLATE") { + print STDERR "Writing output file using default internal template.\n"; + } else { + print STDERR "Writing output file for template \"$templatename\"\n"; + } if ($localDebug) { print STDERR "Contains header list: ".($used{header} ? 1 : 0)."\n"; print STDERR "Contains type list: ".($used{type} ? 1 : 0)."\n"; @@ -2218,36 +2250,40 @@ sub addTopLinkToFramesetTOCs { $HeaderDoc::newTOC = $newTOC; my $relPathToMasterTOC = &findRelativePath($tocFile, $masterTOC); + my $breadcrumb_added = 0; if ($fileString =~ /.*/s) { my $breadcrumb = ""; + $breadcrumb_added = 1; if ($newTOC) { # In a class, so the heading is already there. # $breadcrumb .= HeaderDoc::APIOwner->tocSeparator("Other Reference", $newTOC); - $breadcrumb .= HeaderDoc::APIOwner->tocEntry("$relPathToMasterTOC", "$framework", "$linktarget"); + $breadcrumb .= HeaderDoc::APIOwner->tocEntry("$relPathToMasterTOC", "$framework", "_top"); } else { # In a class, so the heading is already there. # $breadcrumb .= "

Other Reference


\n"; - $breadcrumb .= "      $framework
\n"; + $breadcrumb .= "      $framework
\n"; } $fileString =~ s/.*/$breadcrumb/s; } elsif ($fileString =~ /.*/s) { my $breadcrumb = ""; + $breadcrumb_added = 1; if ($newTOC) { $breadcrumb .= HeaderDoc::APIOwner->tocSeparator("Other Reference", $newTOC); - $breadcrumb .= HeaderDoc::APIOwner->tocEntry("$relPathToMasterTOC", "$framework", "$linktarget"); + $breadcrumb .= HeaderDoc::APIOwner->tocEntry("$relPathToMasterTOC", "$framework", "_top"); } else { $breadcrumb .= "

Other Reference


\n"; - $breadcrumb .= "      $framework
\n"; + $breadcrumb .= "      $framework
\n"; } $fileString =~ s/.*/$breadcrumb/s; - } elsif (!$useBreadcrumbs) { + } + if ((($HeaderDoc::addTopLink && !$newTOC) || (!$breadcrumb_added)) && (!$useBreadcrumbs)) { if ($fileString !~ /$uniqueMarker/) { # we haven't been here before my $relPathToMasterTOC = &findRelativePath($tocFile, $masterTOC); - my $topLink = "\n[Top]
\n"; + my $topLink = "\n[Top]
\n"; $fileString =~ s/(]*>)/$1$topLink/i; } diff --git a/generateAPIDocs.sh b/generateAPIDocs.sh index 8129f22..041c280 100755 --- a/generateAPIDocs.sh +++ b/generateAPIDocs.sh @@ -9,9 +9,9 @@ fi rm -rf Documentation/hdapi ./headerDoc2HTML.pl -H -O -j -Q -n -p -o Documentation/hdapi Documentation/HeaderDoc.hdoc if [ -d headerdoc_tp ] ; then - ./headerDoc2HTML.pl -H -O -j -Q -n -p -o Documentation/hdapi headerwalk.pl headerDoc2HTML.pl gatherHeaderDoc.pl headerdoc_tp/*.pl headerdoc_tp/tp_webkit_tools/filtermacros.pl Modules/HeaderDoc/*.pm xmlman/*.c xmlman/*.h + ./headerDoc2HTML.pl -H -O -j -Q -n -p -o Documentation/hdapi headerwalk.pl headerDoc2HTML.pl gatherHeaderDoc.pl perl2c.pl headerdoc_tp/*.pl headerdoc_tp/tp_webkit_tools/filtermacros.pl Modules/HeaderDoc/*.pm xmlman/*.c xmlman/*.h else - ./headerDoc2HTML.pl -H -O -j -Q -n -p -o Documentation/hdapi headerwalk.pl headerDoc2HTML.pl gatherHeaderDoc.pl Modules/HeaderDoc/*.pm xmlman/*.c xmlman/*.h + ./headerDoc2HTML.pl -H -O -j -Q -n -p -o Documentation/hdapi headerwalk.pl headerDoc2HTML.pl gatherHeaderDoc.pl perl2c.pl Modules/HeaderDoc/*.pm xmlman/*.c xmlman/*.h fi ./gatherHeaderDoc.pl -N Documentation/hdapi index.html diff --git a/headerDoc2HTML.config b/headerDoc2HTML.config index a88d524..2209846 100644 --- a/headerDoc2HTML.config +++ b/headerDoc2HTML.config @@ -1,68 +1,43 @@ # Configuration file for HeaderDoc -# $Revision: 1.7 $ +# $Revision: 1.26 $ ########################################################### - -# These options set various parameters used in content generation. copyrightOwner => -defaultFrameName => index.html -masterTOCName => masterTOC.html - -# This controls the unique ID prefix used at the start of API references. -# Use this to control the API UID of generated refs. If you need to -# support linking to documents with multiple API UID prefixes, define -# the externalAPIUIDPrefixes variable with a space-separaed list of -# valid prefixes. -apiUIDPrefix => apple_ref - -# This is a legacy way of ignoring junk at the start of a line. -# The current preferred mechanism is to define it out of existence -# with C preprocessor macros. -ignorePrefixes => - -# To include information at the top or bottom of every page, -# either include a string in htmlHeader/htmlFooter or a filename -# in htmlHeaderFile or htmlFooterFile -htmlHeader => -htmlHeaderFile => -htmlFooter => -htmlFooterFile => - -# Tells HeaderDoc to suppress the default