From b4f9575af5ffe62fc25ba7db4eea4de3a3630add Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 8 Jan 2008 10:43:10 -0800 Subject: [PATCH] Initial Revision --- .gitignore | 4 + COPYING | 339 +++ README | 251 ++ Rakefile | 96 + bin/ohcount | 202 ++ ext/ohcount_native/.gitignore | 5 + ext/ohcount_native/common.c | 6 + ext/ohcount_native/common.h | 68 + ext/ohcount_native/compiled_state.c | 89 + ext/ohcount_native/compiled_state.h | 21 + ext/ohcount_native/escape_helper.rb | 32 + ext/ohcount_native/extconf.rb | 15 + ext/ohcount_native/generator.rb | 133 ++ ext/ohcount_native/glots/c_monoglot.rb | 77 + .../glots/clearsilver_template_polyglot.rb | 23 + ext/ohcount_native/glots/d_monoglot.rb | 58 + ext/ohcount_native/glots/html_polyglot.rb | 24 + .../glots/html_with_php_polyglot.rb | 23 + ext/ohcount_native/glots/jsp_polyglot.rb | 23 + .../glots/line_comment_monoglot.rb | 21 + ext/ohcount_native/glots/monoglot.rb | 91 + ext/ohcount_native/glots/polyglot.rb | 60 + ext/ohcount_native/glots/python_monoglot.rb | 35 + ext/ohcount_native/glots/rhtml_polyglot.rb | 23 + ext/ohcount_native/glots/xml_monoglot.rb | 26 + ext/ohcount_native/language_breakdown.c | 77 + ext/ohcount_native/language_breakdown.h | 23 + ext/ohcount_native/parser.c | 569 +++++ ext/ohcount_native/parser.h | 33 + ext/ohcount_native/polyglot.c | 44 + ext/ohcount_native/polyglot.h | 19 + ext/ohcount_native/polyglots.c | 1023 ++++++++ ext/ohcount_native/polyglots.h | 14 + ext/ohcount_native/ruby_binding.c | 167 ++ ext/ohcount_native/state.c | 42 + ext/ohcount_native/state.h | 33 + ext/ohcount_native/state.rb | 36 + ext/ohcount_native/transition.h | 39 + ext/ohcount_native/transition.rb | 107 + lib/ohcount.rb | 18 + lib/ohcount/detector.rb | 259 +++ lib/ohcount/diff.rb | 112 + lib/ohcount/language_breakdown.rb | 15 + lib/ohcount/parser.rb | 48 + lib/ohcount/scratch_dir.rb | 50 + lib/ohcount/simple_file_context.rb | 68 + lib/ohcount/sloc_info.rb | 80 + test/.gitignore | 1 + test/detect_files/bourne_again_script | 136 ++ test/detect_files/clearsilver_template1.cs | 6 + test/detect_files/core.lisp | 2 + test/detect_files/cs1.cs | 55 + test/detect_files/d_script | 1 + test/detect_files/findup | 215 ++ test/detect_files/foo.c | 4 + test/detect_files/foo.d | 4 + test/detect_files/foo.rb | 4 + test/detect_files/foo_matlab.m | 3 + test/detect_files/foo_objective_c.h | 3 + test/detect_files/foo_objective_c.m | 2 + test/detect_files/foo_upper_case.C | 4 + test/detect_files/foo_upper_case.RB | 4 + test/detect_files/py_script | 1457 ++++++++++++ test/detect_files/renrot | 13 + test/detect_files/ruby_script | 3 + test/detect_files/t1.m | 32 + test/detect_files/t2.m | 40 + test/detect_files/upper_case_php | 2 + test/expected_dir/ada1.ada/ada/blanks | 1 + test/expected_dir/ada1.ada/ada/code | 12 + test/expected_dir/ada1.ada/ada/comment | 1 + test/expected_dir/ada1.adb/ada/blanks | 1 + test/expected_dir/ada1.adb/ada/code | 12 + test/expected_dir/ada1.adb/ada/comment | 1 + .../assembler1.asm/assembler/blanks | 1 + .../assembler1.asm/assembler/code | 54 + .../assembler1.asm/assembler/comment | 12 + .../assembler2.S/assembler/blanks | 1 + test/expected_dir/assembler2.S/assembler/code | 2 + .../assembler2.S/assembler/comment | 3 + test/expected_dir/awk1.awk/awk/blanks | 1 + test/expected_dir/awk1.awk/awk/code | 45 + test/expected_dir/awk1.awk/awk/comment | 3 + test/expected_dir/bat1.bat/bat/blanks | 1 + test/expected_dir/bat1.bat/bat/code | 1 + test/expected_dir/bat1.bat/bat/comment | 3 + test/expected_dir/boo1.boo/boo/blanks | 1 + test/expected_dir/boo1.boo/boo/code | 20 + test/expected_dir/boo1.boo/boo/comment | 15 + test/expected_dir/c1.c/cncpp/blanks | 1 + test/expected_dir/c1.c/cncpp/code | 36 + test/expected_dir/c1.c/cncpp/comment | 30 + .../classic_basic1.classic_basic/basic/code | 17 + .../basic/comment | 2 + .../clearsilver/blanks | 1 + .../clearsilver_template1.cs/clearsilver/code | 1 + .../clearsilver/comment | 1 + .../clearsilver_template1.cs/html/blanks | 1 + .../clearsilver_template1.cs/html/code | 4 + .../clearsilver_template1.cs/html/comment | 0 test/expected_dir/cobol1.cbl/cobol/blank | 4 + test/expected_dir/cobol1.cbl/cobol/code | 13 + test/expected_dir/cobol1.cbl/cobol/comment | 7 + test/expected_dir/cs1.cs/csharp/blanks | 1 + test/expected_dir/cs1.cs/csharp/code | 41 + test/expected_dir/cs1.cs/csharp/comment | 8 + test/expected_dir/css1.css/css/blanks | 1 + test/expected_dir/css1.css/css/code | 3 + test/expected_dir/css1.css/css/comment | 0 test/expected_dir/d1.d/dmd/blanks | 1 + test/expected_dir/d1.d/dmd/code | 9 + test/expected_dir/d1.d/dmd/comment | 12 + test/expected_dir/dylan1.dylan/dylan/blanks | 1 + test/expected_dir/dylan1.dylan/dylan/code | 12 + test/expected_dir/dylan1.dylan/dylan/comment | 3 + test/expected_dir/el1.el/emacslisp/blanks | 1 + test/expected_dir/el1.el/emacslisp/code | 10 + test/expected_dir/el1.el/emacslisp/comment | 11 + test/expected_dir/erl1.erl/erlang/blanks | 1 + test/expected_dir/erl1.erl/erlang/code | 161 ++ test/expected_dir/erl1.erl/erlang/comment | 14 + test/expected_dir/frx1.frx/visualbasic/blanks | 1 + test/expected_dir/frx1.frx/visualbasic/code | 1729 ++++++++++++++ .../expected_dir/frx1.frx/visualbasic/comment | 203 ++ .../expected_dir/groovy1.groovy/groovy/blanks | 1 + test/expected_dir/groovy1.groovy/groovy/code | 4 + .../groovy1.groovy/groovy/comment | 5 + test/expected_dir/html1.html/css/blanks | 1 + test/expected_dir/html1.html/css/code | 3 + test/expected_dir/html1.html/css/comment | 0 test/expected_dir/html1.html/html/blanks | 1 + test/expected_dir/html1.html/html/code | 18 + test/expected_dir/html1.html/html/comment | 3 + .../expected_dir/html1.html/javascript/blanks | 1 + test/expected_dir/html1.html/javascript/code | 13 + .../html1.html/javascript/comment | 1 + test/expected_dir/java1.java/java/blanks | 1 + test/expected_dir/java1.java/java/code | 27 + test/expected_dir/java1.java/java/comment | 6 + test/expected_dir/java2.java/java/blanks | 1 + test/expected_dir/java2.java/java/code | 0 test/expected_dir/java2.java/java/comment | 2 + test/expected_dir/js1.js/javascript/code | 1446 ++++++++++++ test/expected_dir/js1.js/javascript/comment | 46 + test/expected_dir/js2.js/javascript/code | 6 + test/expected_dir/js2.js/javascript/comment | 7 + test/expected_dir/jsp1.jsp/html/code | 8 + test/expected_dir/jsp1.jsp/java/blanks | 1 + test/expected_dir/jsp1.jsp/java/code | 2 + test/expected_dir/jsp1.jsp/java/comment | 4 + test/expected_dir/lsp1.lsp/lisp/blanks | 1 + test/expected_dir/lsp1.lsp/lisp/code | 46 + test/expected_dir/lsp1.lsp/lisp/comment | 36 + test/expected_dir/lua1.lua/lua/blanks | 1 + test/expected_dir/lua1.lua/lua/code | 100 + test/expected_dir/lua1.lua/lua/comment | 9 + test/expected_dir/matlab1.m/matlab/blanks | 1 + test/expected_dir/matlab1.m/matlab/code | 29 + test/expected_dir/matlab1.m/matlab/comment | 16 + test/expected_dir/pascal1.pas/pascal/blanks | 1 + test/expected_dir/pascal1.pas/pascal/code | 90 + test/expected_dir/pascal1.pas/pascal/comment | 13 + test/expected_dir/pascal2.pp/pascal/blanks | 1 + test/expected_dir/pascal2.pp/pascal/code | 90 + test/expected_dir/pascal2.pp/pascal/comment | 13 + test/expected_dir/perl.cgi/perl/blanks | 1 + test/expected_dir/perl.cgi/perl/code | 47 + test/expected_dir/perl.cgi/perl/comment | 5 + test/expected_dir/perl1.pl/perl/blanks | 1 + test/expected_dir/perl1.pl/perl/code | 45 + test/expected_dir/perl1.pl/perl/comment | 15 + test/expected_dir/php1.php/css/code | 3 + test/expected_dir/php1.php/css/comment | 1 + test/expected_dir/php1.php/html/blanks | 1 + test/expected_dir/php1.php/html/code | 21 + test/expected_dir/php1.php/javascript/code | 1 + test/expected_dir/php1.php/javascript/comment | 1 + test/expected_dir/php1.php/php/code | 20 + test/expected_dir/php1.php/php/comment | 2 + test/expected_dir/py1.py/python/blanks | 1 + test/expected_dir/py1.py/python/code | 20 + test/expected_dir/py1.py/python/comment | 15 + test/expected_dir/rexx1.rex/rexx/blanks | 1 + test/expected_dir/rexx1.rex/rexx/code | 231 ++ test/expected_dir/rexx1.rex/rexx/comment | 41 + test/expected_dir/rhtml1.rhtml/html/blanks | 1 + test/expected_dir/rhtml1.rhtml/html/code | 10 + test/expected_dir/rhtml1.rhtml/html/comment | 3 + test/expected_dir/rhtml1.rhtml/ruby/code | 9 + test/expected_dir/rhtml1.rhtml/ruby/comment | 1 + test/expected_dir/ruby1.rb/ruby/blanks | 1 + test/expected_dir/ruby1.rb/ruby/code | 17 + test/expected_dir/ruby1.rb/ruby/comment | 3 + test/expected_dir/sh1.sh/shell/blanks | 1 + test/expected_dir/sh1.sh/shell/code | 2 + test/expected_dir/sh1.sh/shell/comment | 2 + test/expected_dir/sql1.sql/sql/blanks | 1 + test/expected_dir/sql1.sql/sql/code | 4 + test/expected_dir/sql1.sql/sql/comment | 22 + test/expected_dir/tcl1.tcl/tcl/blanks | 1 + test/expected_dir/tcl1.tcl/tcl/code | 19 + test/expected_dir/tcl1.tcl/tcl/comment | 12 + test/expected_dir/xml1.xml/xml/blanks | 1 + test/expected_dir/xml1.xml/xml/code | 7 + test/expected_dir/xml1.xml/xml/comment | 5 + test/parser_test.rb | 12 + test/src_dir/ada1.ada | 18 + test/src_dir/ada1.adb | 18 + test/src_dir/assembler1.asm | 68 + test/src_dir/assembler2.S | 7 + test/src_dir/awk1.awk | 53 + test/src_dir/bat1.bat | 6 + test/src_dir/boo1.boo | 44 + test/src_dir/c1.c | 70 + test/src_dir/classic_basic1.classic_basic | 19 + test/src_dir/clearsilver_template1.cs | 6 + test/src_dir/cobol1.cbl | 24 + test/src_dir/cs1.cs | 55 + test/src_dir/css1.css | 3 + test/src_dir/d1.d | 26 + test/src_dir/diff1_new.html | 11 + test/src_dir/diff1_old.html | 11 + test/src_dir/diff2_new.c | 7 + test/src_dir/diff2_old.c | 7 + test/src_dir/diff3_new.xml | 3 + test/src_dir/diff3_old.xml | 3 + test/src_dir/dylan1.dylan | 17 + test/src_dir/el1.el | 22 + test/src_dir/erl1.erl | 189 ++ test/src_dir/frx1.frx | 2068 +++++++++++++++++ test/src_dir/groovy1.groovy | 9 + test/src_dir/html1.html | 38 + test/src_dir/java1.java | 48 + test/src_dir/java2.java | 3 + test/src_dir/js1.js | 1781 ++++++++++++++ test/src_dir/js2.js | 13 + test/src_dir/js3.js | 2 + test/src_dir/jsp1.jsp | 14 + test/src_dir/lsp1.lsp | 133 ++ test/src_dir/lua1.lua | 121 + test/src_dir/matlab1.m | 54 + test/src_dir/pascal1.pas | 112 + test/src_dir/pascal2.pp | 112 + test/src_dir/perl.cgi | 66 + test/src_dir/perl1.pl | 72 + test/src_dir/php1.php | 58 + test/src_dir/py1.py | 44 + test/src_dir/rexx1.rex | 311 +++ test/src_dir/rhtml1.rhtml | 25 + test/src_dir/ruby1.rb | 22 + test/src_dir/sh1.sh | 5 + test/src_dir/sql1.sql | 30 + test/src_dir/tcl1.tcl | 35 + test/src_dir/vb1.vb | 16 + test/src_dir/vbs1.vbs | 14 + test/src_dir/xml1.xml | 14 + test/test_helper.rb | 102 + test/unit/ada_test.rb | 16 + test/unit/assembler_test.rb | 16 + test/unit/awk_test.rb | 18 + test/unit/bat_test.rb | 12 + test/unit/boo_test.rb | 17 + test/unit/c_test.rb | 25 + test/unit/clearsilver_template_test.rb | 14 + test/unit/clearsilver_test.rb | 10 + test/unit/csharp_test.rb | 13 + test/unit/css_test.rb | 12 + test/unit/d_test.rb | 37 + test/unit/detector_test.rb | 50 + test/unit/diff_test.rb | 43 + test/unit/dylan_test.rb | 13 + test/unit/emacs_lisp.rb | 15 + test/unit/erlang_test.rb | 13 + test/unit/groovy_test.rb | 13 + test/unit/html_test.rb | 25 + test/unit/java_test.rb | 16 + test/unit/javascript_test.rb | 16 + test/unit/jsp_test.rb | 19 + test/unit/lisp_test.rb | 13 + test/unit/lua_test.rb | 13 + test/unit/matlab_test.rb | 34 + test/unit/pascal_test.rb | 13 + test/unit/perl_test.rb | 16 + test/unit/php_test.rb | 12 + test/unit/python_test.rb | 17 + test/unit/rexx_test.rb | 13 + test/unit/rhtml_test.rb | 14 + test/unit/ruby_test.rb | 13 + test/unit/shell_test.rb | 12 + test/unit/sql_test.rb | 24 + test/unit/tcl_test.rb | 12 + test/unit/visual_basic_test.rb | 12 + test/unit/xml_test.rb | 12 + 293 files changed, 18458 insertions(+) create mode 100644 .gitignore create mode 100644 COPYING create mode 100644 README create mode 100644 Rakefile create mode 100755 bin/ohcount create mode 100644 ext/ohcount_native/.gitignore create mode 100644 ext/ohcount_native/common.c create mode 100644 ext/ohcount_native/common.h create mode 100644 ext/ohcount_native/compiled_state.c create mode 100644 ext/ohcount_native/compiled_state.h create mode 100644 ext/ohcount_native/escape_helper.rb create mode 100644 ext/ohcount_native/extconf.rb create mode 100644 ext/ohcount_native/generator.rb create mode 100644 ext/ohcount_native/glots/c_monoglot.rb create mode 100644 ext/ohcount_native/glots/clearsilver_template_polyglot.rb create mode 100644 ext/ohcount_native/glots/d_monoglot.rb create mode 100644 ext/ohcount_native/glots/html_polyglot.rb create mode 100644 ext/ohcount_native/glots/html_with_php_polyglot.rb create mode 100644 ext/ohcount_native/glots/jsp_polyglot.rb create mode 100644 ext/ohcount_native/glots/line_comment_monoglot.rb create mode 100644 ext/ohcount_native/glots/monoglot.rb create mode 100644 ext/ohcount_native/glots/polyglot.rb create mode 100644 ext/ohcount_native/glots/python_monoglot.rb create mode 100644 ext/ohcount_native/glots/rhtml_polyglot.rb create mode 100644 ext/ohcount_native/glots/xml_monoglot.rb create mode 100644 ext/ohcount_native/language_breakdown.c create mode 100644 ext/ohcount_native/language_breakdown.h create mode 100644 ext/ohcount_native/parser.c create mode 100644 ext/ohcount_native/parser.h create mode 100644 ext/ohcount_native/polyglot.c create mode 100644 ext/ohcount_native/polyglot.h create mode 100644 ext/ohcount_native/polyglots.c create mode 100644 ext/ohcount_native/polyglots.h create mode 100644 ext/ohcount_native/ruby_binding.c create mode 100644 ext/ohcount_native/state.c create mode 100644 ext/ohcount_native/state.h create mode 100644 ext/ohcount_native/state.rb create mode 100644 ext/ohcount_native/transition.h create mode 100644 ext/ohcount_native/transition.rb create mode 100644 lib/ohcount.rb create mode 100644 lib/ohcount/detector.rb create mode 100644 lib/ohcount/diff.rb create mode 100644 lib/ohcount/language_breakdown.rb create mode 100644 lib/ohcount/parser.rb create mode 100644 lib/ohcount/scratch_dir.rb create mode 100644 lib/ohcount/simple_file_context.rb create mode 100644 lib/ohcount/sloc_info.rb create mode 100644 test/.gitignore create mode 100755 test/detect_files/bourne_again_script create mode 100644 test/detect_files/clearsilver_template1.cs create mode 100644 test/detect_files/core.lisp create mode 100644 test/detect_files/cs1.cs create mode 100755 test/detect_files/d_script create mode 100755 test/detect_files/findup create mode 100644 test/detect_files/foo.c create mode 100644 test/detect_files/foo.d create mode 100644 test/detect_files/foo.rb create mode 100644 test/detect_files/foo_matlab.m create mode 100644 test/detect_files/foo_objective_c.h create mode 100644 test/detect_files/foo_objective_c.m create mode 100644 test/detect_files/foo_upper_case.C create mode 100644 test/detect_files/foo_upper_case.RB create mode 100755 test/detect_files/py_script create mode 100755 test/detect_files/renrot create mode 100755 test/detect_files/ruby_script create mode 100644 test/detect_files/t1.m create mode 100644 test/detect_files/t2.m create mode 100644 test/detect_files/upper_case_php create mode 100644 test/expected_dir/ada1.ada/ada/blanks create mode 100644 test/expected_dir/ada1.ada/ada/code create mode 100644 test/expected_dir/ada1.ada/ada/comment create mode 100644 test/expected_dir/ada1.adb/ada/blanks create mode 100644 test/expected_dir/ada1.adb/ada/code create mode 100644 test/expected_dir/ada1.adb/ada/comment create mode 100644 test/expected_dir/assembler1.asm/assembler/blanks create mode 100644 test/expected_dir/assembler1.asm/assembler/code create mode 100644 test/expected_dir/assembler1.asm/assembler/comment create mode 100644 test/expected_dir/assembler2.S/assembler/blanks create mode 100644 test/expected_dir/assembler2.S/assembler/code create mode 100644 test/expected_dir/assembler2.S/assembler/comment create mode 100644 test/expected_dir/awk1.awk/awk/blanks create mode 100644 test/expected_dir/awk1.awk/awk/code create mode 100644 test/expected_dir/awk1.awk/awk/comment create mode 100644 test/expected_dir/bat1.bat/bat/blanks create mode 100644 test/expected_dir/bat1.bat/bat/code create mode 100644 test/expected_dir/bat1.bat/bat/comment create mode 100644 test/expected_dir/boo1.boo/boo/blanks create mode 100644 test/expected_dir/boo1.boo/boo/code create mode 100644 test/expected_dir/boo1.boo/boo/comment create mode 100644 test/expected_dir/c1.c/cncpp/blanks create mode 100644 test/expected_dir/c1.c/cncpp/code create mode 100644 test/expected_dir/c1.c/cncpp/comment create mode 100644 test/expected_dir/classic_basic1.classic_basic/basic/code create mode 100644 test/expected_dir/classic_basic1.classic_basic/basic/comment create mode 100644 test/expected_dir/clearsilver_template1.cs/clearsilver/blanks create mode 100644 test/expected_dir/clearsilver_template1.cs/clearsilver/code create mode 100644 test/expected_dir/clearsilver_template1.cs/clearsilver/comment create mode 100644 test/expected_dir/clearsilver_template1.cs/html/blanks create mode 100644 test/expected_dir/clearsilver_template1.cs/html/code create mode 100644 test/expected_dir/clearsilver_template1.cs/html/comment create mode 100644 test/expected_dir/cobol1.cbl/cobol/blank create mode 100644 test/expected_dir/cobol1.cbl/cobol/code create mode 100644 test/expected_dir/cobol1.cbl/cobol/comment create mode 100644 test/expected_dir/cs1.cs/csharp/blanks create mode 100644 test/expected_dir/cs1.cs/csharp/code create mode 100644 test/expected_dir/cs1.cs/csharp/comment create mode 100644 test/expected_dir/css1.css/css/blanks create mode 100644 test/expected_dir/css1.css/css/code create mode 100644 test/expected_dir/css1.css/css/comment create mode 100644 test/expected_dir/d1.d/dmd/blanks create mode 100644 test/expected_dir/d1.d/dmd/code create mode 100644 test/expected_dir/d1.d/dmd/comment create mode 100644 test/expected_dir/dylan1.dylan/dylan/blanks create mode 100644 test/expected_dir/dylan1.dylan/dylan/code create mode 100644 test/expected_dir/dylan1.dylan/dylan/comment create mode 100644 test/expected_dir/el1.el/emacslisp/blanks create mode 100644 test/expected_dir/el1.el/emacslisp/code create mode 100644 test/expected_dir/el1.el/emacslisp/comment create mode 100644 test/expected_dir/erl1.erl/erlang/blanks create mode 100644 test/expected_dir/erl1.erl/erlang/code create mode 100644 test/expected_dir/erl1.erl/erlang/comment create mode 100644 test/expected_dir/frx1.frx/visualbasic/blanks create mode 100644 test/expected_dir/frx1.frx/visualbasic/code create mode 100644 test/expected_dir/frx1.frx/visualbasic/comment create mode 100644 test/expected_dir/groovy1.groovy/groovy/blanks create mode 100644 test/expected_dir/groovy1.groovy/groovy/code create mode 100644 test/expected_dir/groovy1.groovy/groovy/comment create mode 100644 test/expected_dir/html1.html/css/blanks create mode 100644 test/expected_dir/html1.html/css/code create mode 100644 test/expected_dir/html1.html/css/comment create mode 100644 test/expected_dir/html1.html/html/blanks create mode 100644 test/expected_dir/html1.html/html/code create mode 100644 test/expected_dir/html1.html/html/comment create mode 100644 test/expected_dir/html1.html/javascript/blanks create mode 100644 test/expected_dir/html1.html/javascript/code create mode 100644 test/expected_dir/html1.html/javascript/comment create mode 100644 test/expected_dir/java1.java/java/blanks create mode 100644 test/expected_dir/java1.java/java/code create mode 100644 test/expected_dir/java1.java/java/comment create mode 100644 test/expected_dir/java2.java/java/blanks create mode 100644 test/expected_dir/java2.java/java/code create mode 100644 test/expected_dir/java2.java/java/comment create mode 100644 test/expected_dir/js1.js/javascript/code create mode 100644 test/expected_dir/js1.js/javascript/comment create mode 100644 test/expected_dir/js2.js/javascript/code create mode 100644 test/expected_dir/js2.js/javascript/comment create mode 100644 test/expected_dir/jsp1.jsp/html/code create mode 100644 test/expected_dir/jsp1.jsp/java/blanks create mode 100644 test/expected_dir/jsp1.jsp/java/code create mode 100644 test/expected_dir/jsp1.jsp/java/comment create mode 100644 test/expected_dir/lsp1.lsp/lisp/blanks create mode 100644 test/expected_dir/lsp1.lsp/lisp/code create mode 100644 test/expected_dir/lsp1.lsp/lisp/comment create mode 100644 test/expected_dir/lua1.lua/lua/blanks create mode 100644 test/expected_dir/lua1.lua/lua/code create mode 100644 test/expected_dir/lua1.lua/lua/comment create mode 100644 test/expected_dir/matlab1.m/matlab/blanks create mode 100644 test/expected_dir/matlab1.m/matlab/code create mode 100644 test/expected_dir/matlab1.m/matlab/comment create mode 100644 test/expected_dir/pascal1.pas/pascal/blanks create mode 100644 test/expected_dir/pascal1.pas/pascal/code create mode 100644 test/expected_dir/pascal1.pas/pascal/comment create mode 100644 test/expected_dir/pascal2.pp/pascal/blanks create mode 100644 test/expected_dir/pascal2.pp/pascal/code create mode 100644 test/expected_dir/pascal2.pp/pascal/comment create mode 100644 test/expected_dir/perl.cgi/perl/blanks create mode 100644 test/expected_dir/perl.cgi/perl/code create mode 100644 test/expected_dir/perl.cgi/perl/comment create mode 100644 test/expected_dir/perl1.pl/perl/blanks create mode 100644 test/expected_dir/perl1.pl/perl/code create mode 100644 test/expected_dir/perl1.pl/perl/comment create mode 100644 test/expected_dir/php1.php/css/code create mode 100644 test/expected_dir/php1.php/css/comment create mode 100644 test/expected_dir/php1.php/html/blanks create mode 100644 test/expected_dir/php1.php/html/code create mode 100644 test/expected_dir/php1.php/javascript/code create mode 100644 test/expected_dir/php1.php/javascript/comment create mode 100644 test/expected_dir/php1.php/php/code create mode 100644 test/expected_dir/php1.php/php/comment create mode 100644 test/expected_dir/py1.py/python/blanks create mode 100644 test/expected_dir/py1.py/python/code create mode 100644 test/expected_dir/py1.py/python/comment create mode 100644 test/expected_dir/rexx1.rex/rexx/blanks create mode 100644 test/expected_dir/rexx1.rex/rexx/code create mode 100644 test/expected_dir/rexx1.rex/rexx/comment create mode 100644 test/expected_dir/rhtml1.rhtml/html/blanks create mode 100644 test/expected_dir/rhtml1.rhtml/html/code create mode 100644 test/expected_dir/rhtml1.rhtml/html/comment create mode 100644 test/expected_dir/rhtml1.rhtml/ruby/code create mode 100644 test/expected_dir/rhtml1.rhtml/ruby/comment create mode 100644 test/expected_dir/ruby1.rb/ruby/blanks create mode 100644 test/expected_dir/ruby1.rb/ruby/code create mode 100644 test/expected_dir/ruby1.rb/ruby/comment create mode 100644 test/expected_dir/sh1.sh/shell/blanks create mode 100644 test/expected_dir/sh1.sh/shell/code create mode 100644 test/expected_dir/sh1.sh/shell/comment create mode 100644 test/expected_dir/sql1.sql/sql/blanks create mode 100644 test/expected_dir/sql1.sql/sql/code create mode 100644 test/expected_dir/sql1.sql/sql/comment create mode 100644 test/expected_dir/tcl1.tcl/tcl/blanks create mode 100644 test/expected_dir/tcl1.tcl/tcl/code create mode 100644 test/expected_dir/tcl1.tcl/tcl/comment create mode 100644 test/expected_dir/xml1.xml/xml/blanks create mode 100644 test/expected_dir/xml1.xml/xml/code create mode 100644 test/expected_dir/xml1.xml/xml/comment create mode 100644 test/parser_test.rb create mode 100644 test/src_dir/ada1.ada create mode 100644 test/src_dir/ada1.adb create mode 100644 test/src_dir/assembler1.asm create mode 100644 test/src_dir/assembler2.S create mode 100644 test/src_dir/awk1.awk create mode 100644 test/src_dir/bat1.bat create mode 100644 test/src_dir/boo1.boo create mode 100644 test/src_dir/c1.c create mode 100644 test/src_dir/classic_basic1.classic_basic create mode 100644 test/src_dir/clearsilver_template1.cs create mode 100644 test/src_dir/cobol1.cbl create mode 100644 test/src_dir/cs1.cs create mode 100644 test/src_dir/css1.css create mode 100644 test/src_dir/d1.d create mode 100644 test/src_dir/diff1_new.html create mode 100644 test/src_dir/diff1_old.html create mode 100644 test/src_dir/diff2_new.c create mode 100644 test/src_dir/diff2_old.c create mode 100644 test/src_dir/diff3_new.xml create mode 100644 test/src_dir/diff3_old.xml create mode 100644 test/src_dir/dylan1.dylan create mode 100644 test/src_dir/el1.el create mode 100644 test/src_dir/erl1.erl create mode 100644 test/src_dir/frx1.frx create mode 100644 test/src_dir/groovy1.groovy create mode 100644 test/src_dir/html1.html create mode 100644 test/src_dir/java1.java create mode 100644 test/src_dir/java2.java create mode 100644 test/src_dir/js1.js create mode 100644 test/src_dir/js2.js create mode 100644 test/src_dir/js3.js create mode 100644 test/src_dir/jsp1.jsp create mode 100644 test/src_dir/lsp1.lsp create mode 100644 test/src_dir/lua1.lua create mode 100644 test/src_dir/matlab1.m create mode 100644 test/src_dir/pascal1.pas create mode 100644 test/src_dir/pascal2.pp create mode 100755 test/src_dir/perl.cgi create mode 100644 test/src_dir/perl1.pl create mode 100644 test/src_dir/php1.php create mode 100644 test/src_dir/py1.py create mode 100644 test/src_dir/rexx1.rex create mode 100644 test/src_dir/rhtml1.rhtml create mode 100644 test/src_dir/ruby1.rb create mode 100644 test/src_dir/sh1.sh create mode 100644 test/src_dir/sql1.sql create mode 100644 test/src_dir/tcl1.tcl create mode 100644 test/src_dir/vb1.vb create mode 100644 test/src_dir/vbs1.vbs create mode 100644 test/src_dir/xml1.xml create mode 100644 test/test_helper.rb create mode 100644 test/unit/ada_test.rb create mode 100644 test/unit/assembler_test.rb create mode 100644 test/unit/awk_test.rb create mode 100644 test/unit/bat_test.rb create mode 100644 test/unit/boo_test.rb create mode 100644 test/unit/c_test.rb create mode 100644 test/unit/clearsilver_template_test.rb create mode 100644 test/unit/clearsilver_test.rb create mode 100644 test/unit/csharp_test.rb create mode 100644 test/unit/css_test.rb create mode 100644 test/unit/d_test.rb create mode 100644 test/unit/detector_test.rb create mode 100644 test/unit/diff_test.rb create mode 100644 test/unit/dylan_test.rb create mode 100644 test/unit/emacs_lisp.rb create mode 100644 test/unit/erlang_test.rb create mode 100644 test/unit/groovy_test.rb create mode 100644 test/unit/html_test.rb create mode 100644 test/unit/java_test.rb create mode 100644 test/unit/javascript_test.rb create mode 100644 test/unit/jsp_test.rb create mode 100644 test/unit/lisp_test.rb create mode 100644 test/unit/lua_test.rb create mode 100644 test/unit/matlab_test.rb create mode 100644 test/unit/pascal_test.rb create mode 100644 test/unit/perl_test.rb create mode 100644 test/unit/php_test.rb create mode 100644 test/unit/python_test.rb create mode 100644 test/unit/rexx_test.rb create mode 100644 test/unit/rhtml_test.rb create mode 100644 test/unit/ruby_test.rb create mode 100644 test/unit/shell_test.rb create mode 100644 test/unit/sql_test.rb create mode 100644 test/unit/tcl_test.rb create mode 100644 test/unit/visual_basic_test.rb create mode 100644 test/unit/xml_test.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6081130 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +pkg +doc +lib/i686* +lib/x86* diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/README b/README new file mode 100644 index 0000000..54a485e --- /dev/null +++ b/README @@ -0,0 +1,251 @@ += Ohcount + +The Ohloh source code line counter + +Copyright (C) 2006-2008 Ohloh Corporation + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License Version 2 as +published by the Free Software Foundation. + +Ohcount is specifically licensed under GPL v2.0, and no later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +== Overview + +Ohcount is a library for counting lines of source code. +It was originally developed at Ohloh, and is used to generate +the reports at www.ohloh.net. + +Ohcount supports multiple languages within a single file: for example, +a complex HTML document might include regions of both CSS and JavaScript. + +Ohcount has two main components: a detector which determines the primary +language family used by a particular source file, and a parser which +provides a line-by-line breakdown of the contents of a source file. + +Ohcount provides a command line script that allows you to count individual +files or whole directory trees. It also allows you to find source code +files by language family, or to create a detailed annotation of an +individual source file. + +Ohcount includes a Ruby binding which allows you to directly access its +language detection features from a Ruby application. + +== System Requirements + +Ohcount is supported on Mac OS X 10.4 and Ubuntu 6.06 LTS. Other Linux +environments should also work, but your mileage may vary. + +Ohcount does not support Windows. + +Ohcount targets Ruby 1.8.6. The build script targets Rake 0.7.3. You will +also require a C compiler to build the native extensions. + +Ohcount requires the pcre library (http:///www.pcre.org). + +== Download + +The source code for ohcount is available as a tarball: + + http://labs.ohloh.net/download/ohcount-1.0.0.tgz + +You can also download the source code as a Git repository: + + git clone http://git.ohloh.net/ohcount.git + +== Installation + +Ohcount is packaged as a RubyGem. To build and install the gem (you will need +root priveleges for the install): + + $ rake install + +To uninstall the RubyGem: + + $ gem uninstall ohcount + +If you do not want to install the gem, you can simply build and run it like this: + + $ rake + $ bin/ohcount + +== First Steps + +To measure the lines of code, simply pass filenames or directory names +to the +ohcount+ script: + + $ ohcount helloworld.c + +Directories will be probed recursively. If you do not pass any parameters, +the current directory tree will be counted. + +You can use the ohcount +detect+ option to simply determine the language +family of each source file. The files will not be parsed or counted. +For example, to find all of the ruby files in the current directory tree: + + $ ohcount --detect | grep ^ruby + +The +annotate+ option presents a line-by-line accounting +of the languages used in a source code file. For example: + + $ ohcount --annotate ./test/src_dir/php1.php + +== Loading ohcount from Ruby + +If you have installed ohcount as a gem, you can load it like this: + + require 'rubygems' + require 'ohcount' + +If you have not installed the gem, you'll have to make sure that +ohcount is on your ruby load path and then require: + + require 'ohcount' + +The bin/ohcount script shows examples of calling the ohcount +libraries from Ruby. + +== How to Add a New Language to Ohcount + +There are two steps required to add a new language to ohcount. First, you +must update the detector to identify files that use the new language. Then, +you must create a state machine capable of parsing that language. + +For all changes to ohcount, you must provide unit tests if you want to submit +your new code to Ohloh. + +==== Modifying the Detector + +The Detector primarily uses filename extensions to identify languages. +An hash named EXTENSION_MAP is defined in lib/ohcount/detector.rb to map +extensions to their assosicated parsers. + +If your filename extension is unique, you are in luck and can simply add +a new item to the hash which connects your filename extension to your language. + +If your extension potentially conflicts with other file types in other languages, +then you will need to provide a Ruby method which can make a determination which +parser applies. A small Ruby trick is at play in the EXTENSION_MAP: if your extension +maps to a string, that string is assumed to be the name of a parser. If your +extension maps to a Ruby symbol, that symbol is assumed to be the name of a +Ruby method which will return the name of a parser. + +Many source files do not have an extension. The Ohcount::Detector method +disambiguate_nil+ +is responsible for determining the parser for these files. This determination is +delegated to the +file+ command line tool. + +==== Testing the Detector + +The directory test/detect_files contains test files for the detector. +These files are not used in testing the parser; they are strictly for detection. + +To manually test an addition to the detector, rebuild ohcount and run it against +your test file: + + rake + bin/ohcount --detect test/detect_files/my_file.ext + +If the detector is working, you should see the name of your new language: + + my_language test/detect_files/my_file.ext + +To add the new detector abilities to the standard unit test suite, edit +test/unit/detector_test.rb and add a test for your language. + +==== Monoglots and Polyglots + +The source code parser is written in C. However, you will not write any C code to add +a new language. The C code is generated by another bit of code called a Monoglot or +Polygot, written in Ruby. + +At build time, the script ext/ohcount_native/generator.rb will be run. +This script loads all of the Monoglot and Polyglot files found in +ext/ohcount_native/glots. +These glots are used to generate the C file polyglots.c, which will define +all of the languages parsed by ohcount. Do not edit polyglots.c directly. + +The parser for a single language is generated by a Monoglot. Most common source +code languages can be parsed by a Monoglot. + +However, if your language's file format mashes together spans of code from several +different languages, you will need to create a Monoglot for each individual language, +and then a Polyglot to handle the transitions from one language to another. For example, +Ohcount::HTMLPolyglot handles transitions from the simple HTML Mongolot to the inline +CSS or Javascript Monglots and back. + +==== Creating a New Monoglot + +You may not need to create a fully custom Monoglot. If your language has a simple syntax, +you may be able to use Ohcount::CMonoglot. This is a flexible Monoglot that can generate +parsers for most C-like languages. In fact, most of the parsers in ohcount are examples +of Ohcount::CMonoglot, and you can see examples in +generator.rb+. + +If you do need to create a custom Monoglot, you must create a new Ruby class that +derives from Ohcount::Monoglot, and save it in ext/ohcount_native/glots. + +Whether you create custom Monoglot or use a CMonoglot, you need to update +ext/ohcount_native/generator.rb. You must initialize an instance of your +glot and add it to the +polyglots+ array. + +A Monoglot is simply an array of states and an array of transitions between those +states. When creating your own Monoglot, you can define as many states and transitions +as you require. The parser will be initialized in the first state listed. + +As the source code is scanned, tokens which match those defined in the transitions +will cause the parser will advance to a new state. Each state is associated with +either code, comments, or blanks, so as the state machine advances through the source code, +the source code will be categorized accordingly. + +==== Testing the Parser + +The directory test/src_dir contains source files used in parser tests. You can +add your own test files here. + +To manually test your parser, rebuild ohcount and run it against your test file: + + rake + bin/ohcount --annotate test/src_dir/my_file.ext + +The +annotate+ option will emit your test file to the console, and each line will be +labeled as code, comment, or blank. + +To add the new parser to the standard unit test suite, you must create some additional +files which describe your expected test results. This is a little bit cumbersome: + +1. First, create a new directory in test/expected_dir with + the same name as your test source code file. For example, + test/expected_dir/my_file.ext/. + +2. Within this directory, create directories for each language used in the test source code + file. For example, test/expected_dir/my_file.ext/my_language/. + +3. In this language subdirectory, create three files called +code+, +comment+, and +blanks+. + The +code+ file should contain all of the lines from my_file.ext which are code lines. + The +comment+ file should contain all comment lines. + The +blanks+ file is a bit different: it should contain a single line with an integer + which is the count of blank lines in the original file. + +There are numerous examples in the test directories to help you out. + +To run your tests, you can simply run + + rake + +which runs all unit tests by default. + +== Contact Ohloh + +For more information visit the Ohloh website: + http://labs.ohloh.net + +You can reach Ohloh via email at: + info@ohloh.net diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..e0eebce --- /dev/null +++ b/Rakefile @@ -0,0 +1,96 @@ +require 'rake' +require 'rake/clean' +require 'rake/gempackagetask' +require 'rake/rdoctask' +require 'rake/testtask' +require 'rbconfig' +include Config + +NAME = 'ohcount' +VERS = '1.0.0' + +EXT_DIR = "ext/ohcount_native" +EXT_DL = "#{EXT_DIR}/ohcount_native.#{CONFIG['DLEXT']}" +ARCH_DIR = "lib/#{::Config::CONFIG['arch']}" +ARCH_DL = "#{ARCH_DIR}/ohcount_native.#{CONFIG['DLEXT']}" + +CLEAN.include FileList["#{EXT_DIR}/*.{so,bundle,#{CONFIG['DLEXT']}}"], + FileList["#{EXT_DIR}/*.o"], + FileList["#{EXT_DIR}/Makefile"] + +RDOC_OPTS = ['--quiet', '--title', 'Ohcount Reference', '--main', 'README', '--inline-source'] + +PKG_FILES = %w(README Rakefile lib/ohcount.rb) + + Dir.glob("ext/ohcount_native/*.{h,c,rb}") + + Dir.glob("ext/ohcount_native/glots/*.rb") + + Dir.glob("lib/ohcount/*.rb") + + Dir.glob("bin/*") + +SPEC = + Gem::Specification.new do |s| + s.name = NAME + s.version = VERS + s.platform = Gem::Platform::RUBY + s.has_rdoc = true + s.rdoc_options += RDOC_OPTS + s.summary = "The Ohloh source code line counter" + s.description = s.summary + s.author = "Ohloh Corporation" + s.email = "info@ohloh.net" + s.homepage = "http://www.ohloh.net" + s.files = PKG_FILES + s.require_paths = ["lib", ARCH_DIR] + s.extensions << 'ext/ohcount_native/extconf.rb' + s.bindir = 'bin' + s.executables = ['ohcount'] + end + +Rake::GemPackageTask.new(SPEC) do |p| + p.need_tar = true + p.gem_spec = SPEC +end + +task :install => :package do + `sudo gem install pkg/#{NAME}-#{VERS}` +end + +file ARCH_DL => EXT_DL do + mkdir_p ARCH_DIR + cp EXT_DL, ARCH_DIR +end + +file EXT_DL => FileList["#{EXT_DIR}/Makefile", "#{EXT_DIR}/*.{c,h,rb}"] do + cd EXT_DIR do + sh 'make' + end +end + +file "#{EXT_DIR}/Makefile" => "#{EXT_DIR}/extconf.rb" do + cd EXT_DIR do + if ENV['DEBUG'] + ruby 'extconf.rb', 'debug' + else + ruby 'extconf.rb' + end + end +end + +file "#{EXT_DIR}/polyglots.c" => FileList["#{EXT_DIR}/*.rb", "#{EXT_DIR}/glots/*.rb"] do + cd EXT_DIR do + ruby 'generator.rb' + end +end + +Rake::RDocTask.new do |rdoc| + rdoc.rdoc_dir = 'doc' + rdoc.options += RDOC_OPTS + rdoc.rdoc_files.add ['README' ,'COPYING', 'lib/**/*.rb', 'ext/**/*.rb'] +end + +Rake::TestTask.new :ohcount_unit_tests => ARCH_DL do |t| + puts File.dirname(__FILE__) + '/test/unit/*_test.rb' + t.test_files = FileList[File.dirname(__FILE__) + '/test/unit/*_test.rb'] + t.verbose = true +end + +task :default => :ohcount_unit_tests diff --git a/bin/ohcount b/bin/ohcount new file mode 100755 index 0000000..189da9c --- /dev/null +++ b/bin/ohcount @@ -0,0 +1,202 @@ +#!/usr/bin/env ruby +begin + # First assume we are installed as a gem + require 'rubygems' + require 'ohcount' +rescue LoadError + # Failing that, try to load our files from the source tree + $: << "#{File.dirname(__FILE__)}/../lib" + require 'ohcount' +end + +class OhcountCommandLine + attr_accessor :paths + + def initialize(args=[]) + args = args.clone # Because shift is destructive + set_option(args.shift) while args.first =~ /^-/ + self.paths = args + end + + def paths + @paths || [] + end + + def paths=(p) + @paths=p + @files = nil # If we change the search paths, clear the cache filenames + end + + def files + return @files if @files + + @files = `find #{(self.paths.any? ? self.paths : ['.']).join(' ')} \! -path "*/.*" -type f -print`.split + exit 1 unless @files.any? + @files + end + + def annotate + files.each do |file| + sfc = Ohcount::SimpleFileContext.new(file, files) + polyglot = Ohcount::Detector.detect(sfc) + if polyglot + Ohcount::parse(sfc.contents, polyglot) do |language, semantic, line| + puts "#{language}\t#{semantic}\t#{line}" + end + end + end + end + + # Find all source code files + def detect + files.each do |file| + sfc = Ohcount::SimpleFileContext.new(file, files) + polyglot = Ohcount::Detector.detect(sfc) + puts "#{polyglot}\t#{file}" if polyglot + end + end + + def help + puts < 0, :comment => 0, :blank => 0} + counts[language_name][semantic] += 1 + languages_found << language_name unless languages_found.include?(language_name) + end + end + + # Keep a running total of the number of files that include a specific language + languages_found.each { |l| counts[l][:files] = (counts[l][:files] || 0) + 1 } + + # Keep a running total of the number of files that include any language + any_language_file_count += 1 if languages_found.any? + + progress += 1 + if (progress % 100 == 0) + STDOUT.write('.') + STDOUT.flush + end + end + + puts + puts "Ohloh Line Count Summary".center(76) + puts + + puts "Language Files Code Comment Comment % Blank Total" + puts "-------------- ----- --------- --------- --------- --------- ---------" + + counts.keys.sort{ |a,b| counts[b][:code] <=> counts[a][:code] }.each do |key| + write_summary_row(key, counts[key][:files], counts[key][:code], counts[key][:comment], counts[key][:blank]) + end + + puts "-------------- ----- --------- --------- --------- --------- ---------" + write_summary_row('Total', any_language_file_count, + counts.values.inject(0) { |sum, v| sum + v[:code] }, + counts.values.inject(0) { |sum, v| sum + v[:comment] }, + counts.values.inject(0) { |sum, v| sum + v[:blank] }) + end + + def write_summary_row(name, file_count, code, comment, blank) + printf("%-14s", name) + printf(" %6d", file_count) + printf(" %10d", code) + printf(" %10d", comment) + if comment+code > 0 + printf(" %9.1f%%", comment.to_f / (comment+code).to_f * 100.0) + end + printf(" %10d", blank) + printf(" %10d\n", code+comment+blank) + end + + def subcommand=(s) + if @subcommand + STDERR.puts "Error: Multiple commands specified." + exit 1 + else + @subcommand=s + end + end + + def subcommand + @subcommand + end + + def set_option(option) + case option + when '-s', '--summary' + self.subcommand = :summary + when '-d', '--detect' + self.subcommand = :detect + when '-a', '--annotate' + self.subcommand = :annotate + when '-?', '-h', '--help' + self.subcommand = :help + else + STDERR.puts "Type 'ohcount -?' for usage." + exit 1 + end + end + + def run! + self.subcommand ||= :summary + if self.respond_to?(self.subcommand) + self.send(self.subcommand) + else + STDERR.puts "Type 'ohcount -?' for usage." + exit 1 + end + end +end + +OhcountCommandLine.new(ARGV).run! diff --git a/ext/ohcount_native/.gitignore b/ext/ohcount_native/.gitignore new file mode 100644 index 0000000..0c6e877 --- /dev/null +++ b/ext/ohcount_native/.gitignore @@ -0,0 +1,5 @@ +*.o +Makefile +*.log +*.so +*.bundle diff --git a/ext/ohcount_native/common.c b/ext/ohcount_native/common.c new file mode 100644 index 0000000..e9ea10b --- /dev/null +++ b/ext/ohcount_native/common.c @@ -0,0 +1,6 @@ +#include "common.h" + +void die(char *err, int exit_code) { + fprintf(stderr, err); + exit(exit_code); +} diff --git a/ext/ohcount_native/common.h b/ext/ohcount_native/common.h new file mode 100644 index 0000000..6697b75 --- /dev/null +++ b/ext/ohcount_native/common.h @@ -0,0 +1,68 @@ +/* + * common.h + * Ohcount + * + * Created by Jason Allen on 6/23/06. + * Copyright 2006 Ohloh. All rights reserved. + * + */ +#ifndef __common_h__ +#define __common_h__ + +/******************************************* + Limits +*******************************************/ +// The Parser's CompiledState Stack +#define MAX_CS_STACK 20 +// Parser's Maximum number of LanguageBreakdowns it can return +#define MAX_LANGUAGE_BREAKDOWN_SIZE 8 +// How large can a CompiledState's regex term be? +#define MAX_REGEX 200 +// CompiledState's number of transitions +#define MAX_TRANSITIONS 10 +// The longest a language name can be +#define MAX_LANGUAGE_NAME 20 + +/******************************************* + Common Headers +*******************************************/ +#include +#include +#include +#include +#include "transition.h" +#include "state.h" +#include "compiled_state.h" +#include "polyglot.h" +#include "polyglots.h" +#include "language_breakdown.h" +#include "parser.h" + +/******************************************* + Error Handling +*******************************************/ +void die(char *err, int exit_code); + +enum EXIT_CODES { + ERR_PCRE_OUT_OF_MEMORY = 15, + ERR_PCRE_GENERIC, + ERR_UNKNOWN_SEMANTIC +}; + + +/******************************************* + Logging +*******************************************/ + +#ifdef NDEBUG +#define log(e, arg) ((void)0) +#define log0(e) ((void)0) +#define log2(e, arg1, arg2) ((void)0) +#else +#define log(e, arg) (fprintf(stderr, e, arg)) +#define log0(e) (fprintf(stderr, e)) +#define log2(e, arg1, arg2) (fprintf(stderr, e, arg1, arg2)) +#endif + + +#endif /* common_h */ diff --git a/ext/ohcount_native/compiled_state.c b/ext/ohcount_native/compiled_state.c new file mode 100644 index 0000000..4f50efc --- /dev/null +++ b/ext/ohcount_native/compiled_state.c @@ -0,0 +1,89 @@ +/* + * compiled_state.c + * Ohcount + * + * Created by Jason Allen on 6/23/06. + * Copyright 2006 Ohloh. All rights reserved. + * + */ + +#include "common.h" + + +Transition *compiled_state_get_transition(CompiledState *compiled_state, int nth_transition) { + return compiled_state->transition_map[nth_transition]; +} + +/* + * compiled_state_initialize + * + * a 'compiled_state' helps the parser walk the DFA faster by precomputing the regular expression + * for each state. Basically any transition __from__ a state is added to the regex term. We also + * ensure the "\n" transition (to force end-of-line processing). + * + */ +void compiled_state_initialize(CompiledState *compiled_state, State *state, Transition *transitions[]) { + compiled_state->state = state; + + Transition **pp_t_cur = transitions; + Transition **pp_t_map = compiled_state->transition_map; + char *regex_cur = compiled_state->regex; + bool seen_newline = false; + + for (; (*pp_t_cur) != NULL; pp_t_cur++) { + Transition *t_cur = *pp_t_cur; + if (t_cur->from_state == state) { + + // hey! this is us! add this transition to our regex + *regex_cur++ = '('; + if (!seen_newline) { + seen_newline = *t_cur->regex == '\n'; + } + char *regex_src = t_cur->regex; + while ((*regex_cur++ = *regex_src++)) {} + regex_cur--; // dont want the nil! + *regex_cur++ = ')'; + *regex_cur++ = '|'; + + // add this transition to our map + (*pp_t_map) = t_cur; + pp_t_map++; + } + } + + // add newline (only if it's not already there...) + if (!seen_newline) { + *regex_cur++ = '('; + *regex_cur++ = '\n'; + *regex_cur++ = ')'; + *regex_cur++ = '|'; // just to stay similar to loop pattern + (*pp_t_map) = NULL; // make sure we are pointing to a NULL transition + } + + // terminate the string + *--regex_cur = 0; + + // some sanity checks +#ifndef NDEBUG + int transition_count = pp_t_map - compiled_state->transition_map; + if (transition_count >= MAX_TRANSITIONS) { + log("[ohcount] - ASSERT FAILED: transition_count > MAX (%d)\n", transition_count); + } +#endif + + const char *error; + int erroffset; + compiled_state->pcre = pcre_compile(compiled_state->regex, /* the pattern */ + 0, /* default options */ + &error, /* for error message */ + &erroffset, /* for error offset */ + NULL); /* use default character tables */ + + const char *errptr; + /* since we're likely going to reuse this often, go ahead and study it */ + /* we dont care about errors - it will return NULL which is fine */ + compiled_state->pcre_extra = pcre_study(compiled_state->pcre, /* result of pcre_compile() */ + 0, /* no options exist */ + &errptr); /* set to NULL or points to a message */ +} + diff --git a/ext/ohcount_native/compiled_state.h b/ext/ohcount_native/compiled_state.h new file mode 100644 index 0000000..3b52de0 --- /dev/null +++ b/ext/ohcount_native/compiled_state.h @@ -0,0 +1,21 @@ +/* + * compiled_state.h + * Ohcount + * + * Created by Jason Allen on 6/23/06. + * Copyright 2006 Ohloh. All rights reserved. + * + */ + +typedef struct { + State *state; + char regex[MAX_REGEX]; + pcre *pcre; + pcre_extra *pcre_extra; + Transition *transition_map[MAX_TRANSITIONS]; +} CompiledState; + + +Transition *compiled_state_get_transition(CompiledState *compiled_state, int transition_index); +void compiled_state_initialize(CompiledState *compiled_state, State *state, Transition *transitions[]); + diff --git a/ext/ohcount_native/escape_helper.rb b/ext/ohcount_native/escape_helper.rb new file mode 100644 index 0000000..feb0755 --- /dev/null +++ b/ext/ohcount_native/escape_helper.rb @@ -0,0 +1,32 @@ +module EscapeHelper + # From Ruby, we are generating C code which will call pcre. + # + # This means that characters that are significant to the C parser or the pcre regular + # expression parser must be escaped multiple times, once for each layer of code that + # must evaluate it. + # + # For instance, suppose you want to represent a literal backslash in a regular expression. + # That means we must pass TWO backslashes (\\) to pcre. + # The two backslashes will be stored in a C string constant -- and to express two backslashes + # in a C string constant, we must use FOUR backslashes (\\\\). + # It gets even better. To express these four backslashes in Ruby, we must use a literal string + # that has EIGHT backslashes! + # + # This helper method exists to wade through all of this mess, adding the correct number of + # backslashes to many types of special characters. + # + # Some examples: + # + # e('/*') -> /\\\* # * must be escaped because it has meaning to regular expression parser + # e('"') -> \\\" # " must be escaped because it has meaning to the C string parser + # e('\\') -> \\\\\\\\ # \ must be multiply escaped because it has meaning to both C and regex + # + # If you really want to pass a regular expression operator to pcre (for instance, you want . to be + # the wildcard operator, not a literal period), then you should NOT use this helper, and you'll have to + # sort out your escaping on your own. + # + # Someday we'll move this whole product over to Regel and get rid of all this craziness. + def e(string) + string.gsub(/\\/,'\\\\' * 4).gsub(/([\+\-\?\.\*\(\)\[\]])/, '\\\\' * 2 + '\1').gsub('"', '\\\\"') + end +end diff --git a/ext/ohcount_native/extconf.rb b/ext/ohcount_native/extconf.rb new file mode 100644 index 0000000..7bf3015 --- /dev/null +++ b/ext/ohcount_native/extconf.rb @@ -0,0 +1,15 @@ +# A ruby script to generate the C Makefile. +require 'mkmf' + +dir_config('ohcount_native') +have_library('pcre','pcre_compile') + +# FLAGS: enable logging (or not) +if $*.include?("debug") + puts "BUILD_TYPE: DEBUG" +else + puts "BUILD_TYPE: RELEASE" + $CFLAGS = "#{$CFLAGS} -g -O2 -Wall -DNDEBUG" +end + +create_makefile('ohcount_native') diff --git a/ext/ohcount_native/generator.rb b/ext/ohcount_native/generator.rb new file mode 100644 index 0000000..3d8ff73 --- /dev/null +++ b/ext/ohcount_native/generator.rb @@ -0,0 +1,133 @@ +require 'state' +require 'transition' +require 'escape_helper' + +# So that monoglot and polyglot source files can easily require eachother +$LOAD_PATH << File.join(File.dirname(__FILE__), 'glots') + +# Load all monoglots and polyglots +Dir.glob(File.join(File.dirname(__FILE__), 'glots/*.rb')).each {|f| require f } + +module Ohcount + class Generator + include EscapeHelper + + # The code generator that produces the 'polyglots.c' source file, which contains + # definitions for all the language states and transitions. + def generate + + # Defines all of the monoglots and polyglots known to the parser. + ada = CMonoglot.new("ada", '--', nil, true, false) + assembler = CMonoglot.new("assembler", [';', '!', '//'], [e('/*'), e('*/')], false, false) + awk = CMonoglot.new("awk", '#', nil, true, false, {:no_escape_dquote => true}) + bat = LineCommentMonoglot.new("bat", '^\\\\s*(?i)REM(?-i)') + boo = PythonMonoglot.new("boo") + clearsilver = CMonoglot.new("clearsilver", '#', nil, true, true) + cncpp = CMonoglot.new("cncpp", '//', [e('/*'), e('*/')], true, false) + csharp = CMonoglot.new("csharp", '//', [e('/*'), e('*/')], true, false) + css = CMonoglot.new("css", nil, [e('/*'), e('*/')], false, false) + dylan = CMonoglot.new("dylan", '//', nil, true, false) + erlang = CMonoglot.new("erlang", '%%', nil, true, true) + java = CMonoglot.new("java", '//', [e('/*'), e('*/')], true, false) + javascript = CMonoglot.new("javascript", '//', [e('/*'), e('*/')], true, true) + emacslisp = LineCommentMonoglot.new("emacslisp", ";") + lisp = LineCommentMonoglot.new("lisp", ";") + lua = CMonoglot.new("lua", '--', nil, true, true) + matlab = CMonoglot.new("matlab", '#|%', ['{%', '%}'], false,true) + objective_c = CMonoglot.new("objective_c", '//', [e('/*'), e('*/')], true, false) + pascal = CMonoglot.new("pascal", '//', ['{','}'], true, false) + perl = CMonoglot.new("perl", '#', nil, true, true) + phplanguage = CMonoglot.new("php", '//', [e('/*'), e('*/')], true, true, {:polyglot_name => 'phplanguage'}) + python = PythonMonoglot.new("python") + ruby = CMonoglot.new("ruby", '#', nil, true, true) + rexx = CMonoglot.new("rexx", nil, [e('/*'), e('*/')], true, true) + scheme = LineCommentMonoglot.new("scheme", ";") + shell = CMonoglot.new("shell", '#', nil, false, false) + sql = CMonoglot.new("sql", ['--','//'], [['{','}'], [e('/*'), e('*/')]], true, true) + tcl = CMonoglot.new("tcl", '#', nil, true, false) + visualbasic = CMonoglot.new("visualbasic", '\'', nil, true, false) + xml = XmlMonoglot.new("xml") + html = HtmlPolyglot.new("html", javascript, css) + php = HtmlWithPhpPolyglot.new("php", html, phplanguage) + rhtml = RhtmlPolyglot.new("rhtml", html, ruby) + jsp = JspPolyglot.new("jsp", html, java) + groovy = CMonoglot.new("groovy", '//', [e('/*'), e('*/')], true, false) + clearsilver_template = ClearsilverTemplate.new("clearsilver_template", html, clearsilver) + dmd = DMonoglot.new('dmd') + + polyglots = [ + ada , + assembler , + awk , + bat , + boo , + clearsilver , + cncpp , + csharp , + css , + dylan , + erlang , + groovy , + java , + javascript , + emacslisp , + lisp , + lua , + matlab, + objective_c, + pascal , + perl , + phplanguage , + python , + ruby , + rexx , + scheme , + shell , + sql , + tcl , + visualbasic , + xml , + dmd , + + # poly + html, + php, + rhtml, + jsp, + clearsilver_template + ] + File.open("polyglots.c", "w") do |io| + + # spit out the preamble to our source code + io.puts <:no_escape_dquote => true. + # + def initialize(language, line_comment, block_comment, double_quote = true, single_quote = false, options = {}) + @name = options[:polyglot_name] || language + + # spit out states + @states = [ + State.new(language, :code, :code), + State.new(language, :dquote_string, :code), + State.new(language, :squote_string, :code), + State.new(language, :line_comment, :comment), + State.new(language, :block_comment, :comment) + ] + + @transitions = [] + if line_comment + [ line_comment ].flatten.each_with_index do |line_comment_token, index| + @transitions << Transition.new(language, line_comment_token, :code, :line_comment, :to, false, index) + end + @transitions << Transition.new(language, '\n', :line_comment, :return, :from, false) + end + + if block_comment && !block_comment.empty? + block_comment = [ block_comment ] unless block_comment[0].is_a?(Array) + block_comment.each_with_index do |block_comment_delimiters, index| + @transitions << Transition.new(language, block_comment_delimiters[0], :code, :block_comment, :to, false, index) + @transitions << Transition.new(language, block_comment_delimiters[1], :block_comment, :return, :from, false, index) + end + end + + if single_quote + @transitions << Transition.new(language, "'", :code, :squote_string, :to, false) + @transitions << Transition.new(language, e('\\\\'), :squote_string, :squote_string, :from, true, "ESC_SLASH") + @transitions << Transition.new(language, e("\\'"), :squote_string, :squote_string, :from, true, "ESC") + @transitions << Transition.new(language, "'", :squote_string, :return, :from, false) + end + + if double_quote + @transitions << Transition.new(language, e('"'), :code, :dquote_string, :to, false) + unless options[:no_escape_dquote] + @transitions << Transition.new(language, e('\\\\'), :dquote_string, :dquote_string, :to, true, "ESC_SLASH") + @transitions << Transition.new(language, e('\\"'), :dquote_string, :dquote_string, :to, true, "ESC") + end + @transitions << Transition.new(language, e('"'), :dquote_string, :return, :from, false) + end + end + + end +end diff --git a/ext/ohcount_native/glots/clearsilver_template_polyglot.rb b/ext/ohcount_native/glots/clearsilver_template_polyglot.rb new file mode 100644 index 0000000..385d8f9 --- /dev/null +++ b/ext/ohcount_native/glots/clearsilver_template_polyglot.rb @@ -0,0 +1,23 @@ +require 'polyglot' + +module Ohcount + class ClearsilverTemplate < Polyglot + + def initialize(name, html, clearsilver) + @name = name + + @states = html.all_states + clearsilver.states + @extra_states = [] + + @transitions = html.all_transitions + clearsilver.transitions + @extra_transitions = [] + + # stitch phplanguage + @extra_transitions << StitchTransition.new(e(""), :clearsilver_code, :return, :to, false, name) + end + end +end diff --git a/ext/ohcount_native/glots/d_monoglot.rb b/ext/ohcount_native/glots/d_monoglot.rb new file mode 100644 index 0000000..6fa7cb7 --- /dev/null +++ b/ext/ohcount_native/glots/d_monoglot.rb @@ -0,0 +1,58 @@ +require 'monoglot' + +module Ohcount + # D is very similar to C, but not quite. + # It allows ` as a string delimiter. + # It allows nested block comments using /+ +/. + class DMonoglot < Monoglot + + def initialize(language) + @name = language + + # spit out states + @states = [ + State.new(language, :code, :code), + State.new(language, :dquote_string, :code), + State.new(language, :squote_string, :code), + State.new(language, :backtick_string, :code), + State.new(language, :line_comment, :comment), + State.new(language, :block_comment, :comment), + State.new(language, :nested_comment, :comment) + ] + + @transitions = [] + + # line comments + @transitions << Transition.new(language, '//', :code, :line_comment, :to, false) + @transitions << Transition.new(language, '\n', :line_comment, :return, :from, false) + + # C-like block comments + @transitions << Transition.new(language, e('/*'), :code, :block_comment, :to, false) + @transitions << Transition.new(language, e('/*'), :nested_comment, :block_comment, :to, false) + @transitions << Transition.new(language, e('*/'), :block_comment, :return, :from, false) + + # Nested block comments + @transitions << Transition.new(language, e('/+'), :code, :nested_comment, :to, false) + @transitions << Transition.new(language, e('/+'), :nested_comment, :nested_comment, :to, false) + @transitions << Transition.new(language, e('+/'), :nested_comment, :return, :from, false) + + # single_quote + @transitions << Transition.new(language, "'", :code, :squote_string, :to, false) + @transitions << Transition.new(language, e("\\\\"), :squote_string, :squote_string, :from, true, "ESC_SLASH") + @transitions << Transition.new(language, e("\\'"), :squote_string, :squote_string, :from, true, "ESC") + @transitions << Transition.new(language, "'", :squote_string, :return, :from, false) + + # backtick + @transitions << Transition.new(language, "`", :code, :backtick_string, :to, false) + @transitions << Transition.new(language, e("\\\\"), :backtick_string, :backtick_string, :from, true, "ESC_SLASH") + @transitions << Transition.new(language, e("\\`"), :backtick_string, :backtick_string, :from, true, "ESC") + @transitions << Transition.new(language, "`", :backtick_string, :return, :from, false) + + # double_quote + @transitions << Transition.new(language, e('"'), :code, :dquote_string, :to, false) + @transitions << Transition.new(language, e('\\\\'), :dquote_string, :dquote_string, :to, true, "ESC_SLASH") + @transitions << Transition.new(language, e('\\"'), :dquote_string, :dquote_string, :to, true, "ESC") + @transitions << Transition.new(language, e('"'), :dquote_string, :return, :from, false) + end + end +end diff --git a/ext/ohcount_native/glots/html_polyglot.rb b/ext/ohcount_native/glots/html_polyglot.rb new file mode 100644 index 0000000..ff8a625 --- /dev/null +++ b/ext/ohcount_native/glots/html_polyglot.rb @@ -0,0 +1,24 @@ +require 'polyglot' + +module Ohcount + class HtmlPolyglot < Polyglot + + def initialize(name, javascript, css) + html = XmlMonoglot.new("html") + + @name = name + + @states = javascript.states + css.states + @extra_states = html.states + + @transitions = javascript.transitions + css.transitions + @extra_transitions = html.transitions + + # stitch css + @extra_transitions << StitchTransition.new("<(?i)style(?-i)[^>]*(?i)css(?-i)[^>]*>", :html_markup, :css_code, :from, false, name) + @extra_transitions << StitchTransition.new("", :css_code, :return, :to, false, name) + @extra_transitions << StitchTransition.new("<(?i)script(?-i)\\\\ [^>]*(?i)javascript(?-i)[^>]*>", :html_markup, :javascript_code, :from, false, name) + @extra_transitions << StitchTransition.new("", :javascript_code, :return, :to, false, name) + end + end +end diff --git a/ext/ohcount_native/glots/html_with_php_polyglot.rb b/ext/ohcount_native/glots/html_with_php_polyglot.rb new file mode 100644 index 0000000..8013050 --- /dev/null +++ b/ext/ohcount_native/glots/html_with_php_polyglot.rb @@ -0,0 +1,23 @@ +require 'polyglot' + +module Ohcount + class HtmlWithPhpPolyglot < Polyglot + + def initialize(name, html, phplanguage) + @name = name + + @states = html.all_states + phplanguage.states + @extra_states = [] + + @transitions = html.all_transitions + phplanguage.transitions + @extra_transitions = [] + + # stitch phplanguage + @extra_transitions << StitchTransition.new(e(""), :php_code, :return, :from, false, name) + end + end +end diff --git a/ext/ohcount_native/glots/jsp_polyglot.rb b/ext/ohcount_native/glots/jsp_polyglot.rb new file mode 100644 index 0000000..fdff77e --- /dev/null +++ b/ext/ohcount_native/glots/jsp_polyglot.rb @@ -0,0 +1,23 @@ +require 'polyglot' + +module Ohcount + class JspPolyglot < Polyglot + + def initialize(name, html, java) + @name = name + + @states = html.all_states + java.states + @extra_states = [] + + @transitions = html.all_transitions + java.transitions + @extra_transitions = [] + + # stitch phplanguage + @extra_transitions << StitchTransition.new("<%", :html_markup, :java_code, :from, false, name) + @extra_transitions << StitchTransition.new("<%", :html_comment, :java_code, :from, false, name) + @extra_transitions << StitchTransition.new("<%", :html_squote, :java_code, :from, false, name) + @extra_transitions << StitchTransition.new("<%", :html_dquote, :java_code, :from, false, name) + @extra_transitions << StitchTransition.new("%>", :java_code, :return, :to, false, name) + end + end +end diff --git a/ext/ohcount_native/glots/line_comment_monoglot.rb b/ext/ohcount_native/glots/line_comment_monoglot.rb new file mode 100644 index 0000000..4b20bdc --- /dev/null +++ b/ext/ohcount_native/glots/line_comment_monoglot.rb @@ -0,0 +1,21 @@ +require 'monoglot' + +module Ohcount + class LineCommentMonoglot < Monoglot + + def initialize(language, line_comment_tokens) + @name = language + + @states = [ + State.new(language, :code, :code), + State.new(language, :comment, :comment) + ] + + @transitions = [] + [ line_comment_tokens ].flatten.each_with_index do |token, index| + @transitions << Transition.new(language, token, :code, :comment, :to, false, index.to_s) + end + @transitions << Transition.new(language, '\n', :comment, :return, :from, false) + end + end +end diff --git a/ext/ohcount_native/glots/monoglot.rb b/ext/ohcount_native/glots/monoglot.rb new file mode 100644 index 0000000..9be5e6a --- /dev/null +++ b/ext/ohcount_native/glots/monoglot.rb @@ -0,0 +1,91 @@ +require 'escape_helper' + +module Ohcount + # A Monoglot is a compile-time code generator. + # It generates C source code which defines the states and transitions + # required for a single language parser. + # + # To create a parser which spans multiple languages, use a Polyglot. + class Monoglot + include EscapeHelper + + # The name must be unique + attr_reader :name + + # A collection of State objects representing possible states + attr_reader :states + + # The Transition objects defining transitions between states + attr_reader :transitions + + def initialize(name, states = [], transitions = []) + @name = name + @states = states + @transitions = transitions + end + + # Emit the generated C code for the state machine definition. + def print(io) + Monoglot::print_banner(io, name) + print_states(io) + print_transitions(io) + print_polyglot_def(io) + end + + def self.print_banner(io, name) + io.puts "" + io.puts "/*****************************************************************************" + left = (80 - name.size)/2 + io.write " "*left + io.puts name + io.puts "*****************************************************************************/" + end + + def definition + "#{ @name.upcase }_POLYGLOT" + end + protected + + def print_states(io) + #define each + io.puts "/* States */" + @states.each do |s| + s.print(io) + end + + # now define the collection + io.write "State *#{ name.upcase }_STATES[] = { " + @states.each do |s| + io.write "&#{ s.definition }, " + end + io.write "NULL };\n" + end + + def print_transitions(io) + io.puts "/* Transitions */" + # print each transition + @transitions.each do |t| + t.print(io) + end + + #aggregate the transitions + io.write "Transition *#{ name.upcase }_TRANSITIONS[] = {" + @transitions.each do |t| + io.write " &#{ t.definition }," + end + io.write " NULL};\n" + end + + def print_polyglot_def(io) + io.puts <", :ruby_code, :return, :to, false, name) + end + end +end diff --git a/ext/ohcount_native/glots/xml_monoglot.rb b/ext/ohcount_native/glots/xml_monoglot.rb new file mode 100644 index 0000000..15cdab9 --- /dev/null +++ b/ext/ohcount_native/glots/xml_monoglot.rb @@ -0,0 +1,26 @@ +require 'monoglot' + +module Ohcount + class XmlMonoglot < Monoglot + def initialize(language) + @name = language + @states = [ + State.new(language, :markup, :code), + State.new(language, :squote, :code), + State.new(language, :dquote, :code), + State.new(language, :cdata, :code), + State.new(language, :comment, :comment) + ] + @transitions = [ + Transition.new(language, "'", :markup, :squote, :from, false), + Transition.new(language, "'", :squote, :return, :to, false), + Transition.new(language, '\"', :markup, :dquote, :from, false), + Transition.new(language, '\"', :dquote, :return, :to, false), + Transition.new(language, '', :cdata, :return, :to, false), + Transition.new(language, '', :comment, :return, :from, false) + ] + end + end +end diff --git a/ext/ohcount_native/language_breakdown.c b/ext/ohcount_native/language_breakdown.c new file mode 100644 index 0000000..e6ec924 --- /dev/null +++ b/ext/ohcount_native/language_breakdown.c @@ -0,0 +1,77 @@ +/* + * language_breakdown.c + * Ohcount + * + * Created by Jason Allen on 6/26/06. + * Copyright 2006 Ohloh. All rights reserved. + * + */ + +#include "common.h" + +/* + * language_breakdown_initialize + * + * sets up the blank buffers... + * + */ +void language_breakdown_initialize(LanguageBreakdown *lb, char *name, int buffer_size) { + strcpy(lb->name, name); + lb->code = lb->code_cur = malloc(buffer_size); + lb->code[0] = 0; + lb->comment = lb->comment_cur = malloc(buffer_size); + lb->comment[0] = 0; + lb->blank_count = 0; +} + +/* + * language_breakdown_free + * + * frees the buffers allocated by a language_breakdown + * + */ +void language_breakdown_free(LanguageBreakdown *lb) { +#ifndef NDEBUG + if (lb->code == NULL || lb->comment == NULL) { + log0("freeing language_breakdown twice!"); + } +#endif + free(lb->code); + free(lb->comment); + lb->code = NULL; + lb->comment = NULL; +} + + +char * first_non_blank(char *from, char *to) { + while (from < to && (*from == ' ' || *from == '\t')) { + from++; + } + return from; +} + +/* + * language_breakdown_copy_code + * + * copies the passed in string (via delimiters) to the code buffer + * + */ +void language_breakdown_copy_code(LanguageBreakdown *lb, char *from, char *to) { + from = first_non_blank(from, to); + strncpy(lb->code_cur, from, to - from); + lb->code_cur += to - from; + *lb->code_cur = 0; +} + +/* + * language_breakdown_copy_comment + * + * copies the passed in string (via delimiters) to the comment buffer + * + */ +void language_breakdown_copy_comment(LanguageBreakdown *lb, char *from, char *to) { + from = first_non_blank(from, to); + strncpy(lb->comment_cur, from, to - from); + lb->comment_cur += to - from; + *lb->comment_cur = 0; +} diff --git a/ext/ohcount_native/language_breakdown.h b/ext/ohcount_native/language_breakdown.h new file mode 100644 index 0000000..23acc86 --- /dev/null +++ b/ext/ohcount_native/language_breakdown.h @@ -0,0 +1,23 @@ +/* + * language_breakdown.h + * Ohcount + * + * Created by Jason Allen on 6/26/06. + * Copyright 2006 Ohloh. All rights reserved. + * + */ + +typedef struct { + char name[MAX_LANGUAGE_NAME]; + char *code; + char *code_cur; + char *comment; + char *comment_cur; + int blank_count; +} LanguageBreakdown; + +void language_breakdown_initialize(LanguageBreakdown *lb, char *name, int buffer_size); +void language_breakdown_copy_code(LanguageBreakdown *lb, char *from, char *to); +void language_breakdown_copy_comment(LanguageBreakdown *lb, char *from, char *to); + +void language_breakdown_free(LanguageBreakdown *lb); diff --git a/ext/ohcount_native/parser.c b/ext/ohcount_native/parser.c new file mode 100644 index 0000000..1738ec0 --- /dev/null +++ b/ext/ohcount_native/parser.c @@ -0,0 +1,569 @@ +/* + * parser.c + * Ohcount + * + * Created by Jason Allen on 6/23/06. + * Copyright 2006 Ohloh. All rights reserved. + * + */ + +/* #include - for memory debugging */ +#include "ruby.h" +#include "common.h" + + +/***************************************************************************** + ParseContext +*****************************************************************************/ + +/* + * ParseContext holds all the state required to parse a buffer + * + * This is where we keep state of an ongoing parse. It's not in the header file because + * it's not meant to be shared with anyone else... strictly internal! + */ +typedef struct { + // the buffer we're parsing + char *parse_buffer; + + // the length of the entire buffer + int parse_buffer_len; + + // the current cursor we're processing + char *parse_cur; + + // the length of the buffer left to parse + int parse_left_len; + + // where the current line started (just past the last newline) + char *parse_line_start; + + // where there current state should start attribution from + char *attribute_from; + + // the index of the current line (just for debugging) + int cur_line_index; + + // the state stack + CompiledState *cs_stack[MAX_CS_STACK]; + int cs_stack_index; + + // the state we're attributing this current line to (NULL means we haven't attributed it yet!) + State *line_attributed_state; + + // language_breakdowns + LanguageBreakdown language_breakdowns[MAX_LANGUAGE_BREAKDOWN_SIZE]; + int language_breakdown_count; + +} ParseContext; + +/* + * parse_context_find_or_create_language_breakdown + * + * Will return a valid language_breakdown pointer for a given language name. + */ +LanguageBreakdown *parse_context_find_or_create_language_breakdown(ParseContext *parse_context, char *name) { + int i_lb; + + // iterate to find + for (i_lb = 0; i_lb < parse_context->language_breakdown_count; i_lb++) { + if (strcmp(parse_context->language_breakdowns[i_lb].name, name) == 0) { + return &parse_context->language_breakdowns[i_lb]; + } + } + + // doesn't exist, create new onw + log("[ohcount] creating language_breakdown: '%s'\n", name); +#ifndef NDEBUG + if (parse_context->language_breakdown_count >= MAX_LANGUAGE_BREAKDOWN_SIZE) { + log("[ohcount] - ASSERT FAILED: parse_context->language_breakdown_count too big (%d)\n", parse_context->language_breakdown_count); + } +#endif + language_breakdown_initialize(&parse_context->language_breakdowns[parse_context->language_breakdown_count], name, parse_context->parse_buffer_len + 5); /* just in case we pad with newline or something */ + log("[ohcount] done creating language_breakdown: '%s'\n", name); + return &parse_context->language_breakdowns[parse_context->language_breakdown_count++]; +} + +/* + * parse_yield_line + * + * yeilds the just-processed line back up to an optional Ruby block, + * along with its language and semantic information. + */ +void parse_yield_line(ParseContext *parse_context, char *up_to, State *state) { + VALUE ary; + if (rb_block_given_p()) { + ary = rb_ary_new2(2); + rb_ary_store(ary, 0, ID2SYM(rb_intern(state->language))); + rb_ary_store(ary, 2, rb_str_new(parse_context->parse_line_start, up_to - parse_context->parse_line_start)); + + switch (state->semantic) { + case semantic_code: + rb_ary_store(ary, 1, ID2SYM(rb_intern("code"))); + break; + case semantic_comment: + rb_ary_store(ary, 1, ID2SYM(rb_intern("comment"))); + break; + case semantic_blank: + case semantic_null: + rb_ary_store(ary, 1, ID2SYM(rb_intern("blank"))); + break; + default: + break; + } + rb_yield(ary); + } +} + +/* + * parse_context_process_line + * + * will 'consume' the current line (parse_context->parse_line_start to 'up_to'). + * code and comments are copied, blanks are simply tallied up. + */ +void parse_context_process_line(ParseContext *parse_context, char *up_to, State *state) { + parse_yield_line(parse_context, up_to, state); + + LanguageBreakdown *lb = parse_context_find_or_create_language_breakdown(parse_context,state->language); + switch (state->semantic) { + case semantic_code: + language_breakdown_copy_code(lb, parse_context->parse_line_start, up_to); + break; + case semantic_comment: + language_breakdown_copy_comment(lb, parse_context->parse_line_start, up_to); + break; + case semantic_null: + case semantic_blank: + log("[ohcount] blankline at line %d\n", parse_context->cur_line_index); + lb->blank_count++; + break; + default: + die("Unknown semantic", ERR_UNKNOWN_SEMANTIC); + } +} + +/* + * parse_context_current_cs + * + * accessor for the top of the CompiledState stack + */ +CompiledState *parse_context_current_cs(ParseContext *parse_context) { +#ifndef NDEBUG + if (parse_context->cs_stack_index < 0 || parse_context->cs_stack_index >= MAX_CS_STACK) { + log("[ohcount] - ASSERT FAILED: parse_context->cs_stack_index out of bounds (%d)\n", parse_context->cs_stack_index); + } +#endif + if (parse_context->cs_stack_index == 0) { + return NULL; + } + return parse_context->cs_stack[parse_context->cs_stack_index - 1]; +} + +/* + * parse_context_current_state + * + * accessor for state represented by the top of the CompiledState stack + */ +State *parse_context_current_state(ParseContext *parse_context) { + CompiledState *cs = parse_context_current_cs(parse_context); + if (cs == NULL) { + return NULL; + } + return cs->state; +} + +/* + * parse_context_last_attributed_semantic + * + * accessor that returns the current line's attributed semantic (null if none was attributed + * yet). + */ +enum Semantic parse_context_last_attributed_semantic(ParseContext *parse_context) { + if (parse_context->line_attributed_state == NULL) { + return semantic_null; + } + return parse_context->line_attributed_state->semantic; +} + +/* + * parse_context_current_pcre + * + * returns the pcre (compiled regular expression) for the current state + */ +pcre *parse_context_current_pcre(ParseContext *parse_context) { + return parse_context_current_cs(parse_context)->pcre; +} + +/* + * parse_context_current_pcre_extra + * + * returns the pcre_extra (compiled regular expression additional hints) for the current state + */ +pcre_extra *parse_context_current_pcre_extra(ParseContext *parse_context) { + return parse_context_current_cs(parse_context)->pcre_extra; +} + +/* + * parse_context_attribute + * + * Determines whether the chunk of code seen up to 'at' should be attributed to the + * current state or not. The rules are pretty simple: + * - semantic_null < semantic_blank < semantic_comment < semantic_code + * - comment and code don't count if there are only blanks characters + * + * if we ate a newline then we also do some postprocessing -- mostly copy the current + * line to the appropriate buffer. + * + */ +void parse_context_attribute(ParseContext *parse_context, char *at, bool process_line) { + enum Semantic last_semantic = parse_context_last_attributed_semantic(parse_context); + State *state = parse_context_current_state(parse_context); + bool trumped = state_trumps_language(state, parse_context->line_attributed_state); + + log0("[ohcount] - __ATTRIBUTION__\n"); +#ifndef NDEBUG + char temp_buf[20]; + int max_chars = (at - parse_context->attribute_from); + if (max_chars > 19) { + max_chars = 19; + } + strncpy(temp_buf, parse_context->attribute_from, max_chars); + temp_buf[max_chars] = 0; + if (state) { + log2("[ohcount] - state[%s] eating '%s'\n", state->name, temp_buf); + } else { + log("[ohcount] - NULL state eating '%s'\n", temp_buf); + } + State *last_state = parse_context->line_attributed_state; + if (last_state) { + log("[ohcount] - last_attirbuted_state: '%s'\n", last_state->name); + } +#endif + + + + // shortcut -- if we've already found code, nothing else could really make a difference -- just bail + if (last_semantic != semantic_code || trumped) { + + // main code to attribute the chunk of code + log2("[ohcount] - attributing(at[%d], attribute_from[%d]\n", at, parse_context->attribute_from); + if (at > parse_context->attribute_from) { + + // if we're attributing to blank, we dont care what's in the string + if (state->semantic == semantic_blank && last_semantic == semantic_null) { + parse_context->line_attributed_state = state; + log2("[ohcount] - line %d now being assigned state '%s'\n", parse_context->cur_line_index, state->name); + } else { + + // we need to see some non-blank characters before we can acredit a comment or code + char *cur = parse_context->attribute_from; + bool saw_non_blank = false; + while (cur < at) { + if (*cur > 32) { /* ascii chars below 32 are non-printing */ + log2("attributing character 0x%x %c\n", (int)*cur, *cur); + saw_non_blank = true; + cur = at; + } + cur++; + } + if (saw_non_blank) { + if (trumped || ( + (last_semantic == semantic_blank || last_semantic == semantic_null) && + (state->semantic == semantic_code || state->semantic == semantic_comment) )) { + parse_context->line_attributed_state = state; + log2("[ohcount] - line %d now being assigned state '%s'\n", parse_context->cur_line_index, state->name); + } else if (last_semantic == semantic_comment && state->semantic == semantic_code) { + parse_context->line_attributed_state = state; + log2("[ohcount] - line %d now being assigned state '%s'\n", parse_context->cur_line_index, state->name); + } + } + } + } + } + + // copy line to appropriate buffer, if appropriate + if (process_line) { + + State *attributed_state = parse_context->line_attributed_state; + State temp_state; + + if (attributed_state == NULL) { + // if the line is totally blank, we haven't attributed it to anything yet + // instead, we'll invent a temporary state (same language.name as previous state on stack, but semantic blank) + temp_state.language = parse_context_current_state(parse_context)->language; + temp_state.name = parse_context_current_state(parse_context)->name; + temp_state.semantic = semantic_blank; + attributed_state = &temp_state; + log("[ohcount] - eating_newline. line_attributed_state=[MADE UP! semantic blank, language->%s\n", attributed_state->language); + } else { + log("[ohcount] - eating_newline. line_attributed_state=%s\n", attributed_state->name); + } + + parse_context_process_line(parse_context, at, attributed_state); + parse_context->parse_line_start = at; + parse_context->attribute_from = at; + parse_context->line_attributed_state = NULL; + parse_context->cur_line_index++; + } + +} + + +/* + * parse_context_transit + * + * performs transition to new state (by pushing or popping the compiled_state stack) + * + */ +void parse_context_transit(ParseContext *parse_context, CompiledState *cs, char *at) { + // push (or pop) + if (cs == NULL) { +#ifndef NDEBUG + if (parse_context->cs_stack_index <= 0) { + log("[ohcount] - ASSERT FAILED: cs_stack_index underflow (%d)\n", parse_context->cs_stack_index); + } +#endif + parse_context->cs_stack[--parse_context->cs_stack_index] = cs; + } else { +#ifndef NDEBUG + if (parse_context->cs_stack_index + 1 >= MAX_CS_STACK) { + log("[ohcount] - ASSERT FAILED: cs_stack_index overflow (%d)\n", parse_context->cs_stack_index); + } +#endif + parse_context->cs_stack[parse_context->cs_stack_index++] = cs; + } + parse_context->attribute_from = at; + +} + +/* + * parse_context_initialize + * + * Initialized a parse_context to be ready to start parsing. + * + */ +void parse_context_initialize(ParseContext *parse_context, char *buffer, int buffer_len, CompiledState *initial_cs_state) { + parse_context->parse_buffer = buffer; + parse_context->parse_buffer_len = buffer_len; + parse_context->parse_cur = buffer; + parse_context->attribute_from = buffer; + parse_context->parse_left_len = buffer_len; + parse_context->parse_line_start = buffer; + parse_context->cur_line_index = 1; // editors are 1-based...debugging is easier + + parse_context->cs_stack_index = 0; + parse_context->line_attributed_state = NULL; + parse_context->language_breakdown_count = 0; + + parse_context_attribute(parse_context, buffer, false); + parse_context_transit(parse_context, initial_cs_state, buffer); +} + + +/* + * parse_context_get_transition + * + * returns the "nth" transition from the current parse_context. + * + */ +Transition *parse_context_get_transition(ParseContext *parse_context, int transition_index) { + CompiledState *compiled_state = parse_context_current_cs(parse_context); + return compiled_state_get_transition(compiled_state, transition_index); +} + + + +/***************************************************************************** + ParseResult +*****************************************************************************/ + +/* + * parse_result_initialize + * + * initializes a parse_result from the parse_context + * + */ +void parse_result_initialize(ParseResult *pr, ParseContext *parse_context) { + int i_lb; + for (i_lb = 0; i_lb < parse_context->language_breakdown_count; i_lb++) { + pr->language_breakdowns[i_lb] = parse_context->language_breakdowns[i_lb]; + } + pr->language_breakdown_count = parse_context->language_breakdown_count; +} + +/* + * parse_result_free + * + * Deallocates the memory held by a ParseResult. + * + */ +void parse_result_free(ParseResult *parse_result) { + int i_lb; + for (i_lb = 0; i_lb < parse_result->language_breakdown_count; i_lb++) { + language_breakdown_free(&parse_result->language_breakdowns[i_lb]); + } +} + + +/***************************************************************************** + Parser +*****************************************************************************/ + +/* + * parser_print_match + * + * As a debugging tool, we print out the exact matched string. + * + */ +void parser_print_match(ParseContext *parse_context, int *ovector, int result) { + char match[10]; + pcre_copy_substring(parse_context->parse_cur, ovector, result, result - 1, match, 10); + if (match[0] == '\n') { + log2("[ohcount] state '%s' matched [%s]\n", parse_context_current_state(parse_context)->name, "\\n"); + } else { + log2("[ohcount] state '%s' matched [%s]\n", parse_context_current_state(parse_context)->name, match); + } +} + +/* + * parser_ate_newline + * + * returns true if the pcre result ate a newline + * + */ +bool parser_ate_newline(ParseContext *parse_context, int *ovector) { + char *c = parse_context->parse_cur + ovector[0]; + char *c_last = parse_context->parse_cur + ovector[1]; + while (c < c_last) { + if (*c++ == '\n') { + return true; + } + } + return false; +} + + +/* + * parser_parse + * + * The main parsing algorith consists of doing a DFA walk on the source code. + * We start in the initial state of the language and then maintain a stack of + * states. Transitions are triggered as regular expression matches (as defined + * by each state). At every transition we account for the code seen. We keep + * track for each line what semantic we've seen so far. Semantics trump each + * other in the following order: null < blank < comment < code. As soon as we + * see any code, we pretty much ignore other semantics until the newline. We + * do, however, keep parsing since we need to maintain the states properly - + * in other words, jumping to the newline might make us forget to jump out + * of a string state, or something. + * + */ +void parser_parse(ParseResult *pr, char *buffer, int buffer_len, Polyglot *polyglot) { +#ifndef NDEBUG +/* to help debug, export MALLOC_TRACE to output file */ +/* mtrace(); */ +#endif + + // make sure we have compiled states + polyglot_compile_states(polyglot); + + // setup the parse context + ParseContext parse_context; + parse_context_initialize(&parse_context, buffer, buffer_len, &polyglot->compiled_states[0]); + + // MAIN_PARSE_LOOP + int ovector[30]; + int result; + while ((result = pcre_exec(parse_context_current_pcre(&parse_context), NULL, parse_context.parse_cur, parse_context.parse_left_len, 0, 0, ovector, 30)) >= 0) { + +#ifndef NDEBUG + log("[ohcount] pcre result: %d\n", result); + parser_print_match(&parse_context, ovector, result); +#endif + + // crappy hack work around to solve surprisingly complex bug + // its all about the last line - how to avoid attributing twice or not at all + // The complexity comes about because sometimes we actually account for it + // "automatically" - like when the file ends with a newline. However, when it doesn't + // + + + // transition if possible (there might not be one if its a newline!) + Transition *t = parse_context_get_transition(&parse_context, result - 2); // -1 for pcre_exec storing the entire match first, -1 to be zero-based (pcre is 1-based, kinda) + + if (t && t->fake_transition) { + // fake transition -- just ignore it! + log0("- fake transition, still in current state"); + } else { + CompiledState *target_cs = NULL; + if (t && t->to_state) { + // find the target compiled_state + for (target_cs = polyglot->compiled_states; target_cs->state != t->to_state; target_cs++) {} + } + + // source or target: who eats the matched string itself? + int at = (t == NULL || t->token_eater == FromEatsToken) ? ovector[1] : ovector[0]; + + // attribute the code/text/blanks we've seen so far + bool ate_newline = parser_ate_newline(&parse_context, ovector); + parse_context_attribute(&parse_context, parse_context.parse_cur + at, ate_newline); + + // and transit to our new state (note: we usually won't have a transition if we hit a newline) + // set the 'at' at the proper place, depending on TokenEater + at = (t != NULL && (t->token_eater == ToEatsToken)) ? ovector[0] : ovector[1]; + if (t && !t->fake_transition) { + log("[ohcount] - transition at %d\n", parse_context.parse_cur + at); + parse_context_transit(&parse_context, target_cs, parse_context.parse_cur + at); + } + +#ifndef NDEBUG + if (ate_newline) { + log2("[ohcount] -- starting line %d in state %s\n", parse_context.cur_line_index, parse_context_current_state(&parse_context)->name); + } +#endif + } + // move forward + int jump_chars = (ovector[0] > ovector[1]) ? ovector[0] : ovector[1]; + parse_context.parse_left_len -= jump_chars ; + parse_context.parse_cur += jump_chars; + } + + switch (result) { + case PCRE_ERROR_NOMATCH: + // attribute what we (might have) eaten so far... + if (parse_context.parse_cur[parse_context.parse_left_len - 1] != '\n') { + parse_context_attribute(&parse_context, parse_context.parse_cur + parse_context.parse_left_len, true); + } + break; + case PCRE_ERROR_NOMEMORY: + die("PCRE_ERROR_NOMEMORY", ERR_PCRE_OUT_OF_MEMORY); + break; + default: + die("PCRE ERROR", ERR_PCRE_GENERIC); + break; + } + + /* setup the parse result */ + parse_result_initialize(pr, &parse_context); + +#ifndef NDEBUG +/* muntrace(); */ +#endif +} + + +/* + * parser_test + * + * internal testing code + */ +void parser_test() { + char buffer[] = "\"str//i\\\"ng\""; + ParseResult pr; + int len = strlen(buffer); + parser_parse(&pr, buffer, len, POLYGLOTS[0]); + printf("parsing this buffer:\n%s\n=============\n", buffer); + printf("__code_start__\n%s\n__code_end__\n", pr.language_breakdowns[0].code); + printf("__comment_start__\n%s\n__comment_end__\n", pr.language_breakdowns[0].comment); + printf("blanks[%d]\n", pr.language_breakdowns[0].blank_count); +} diff --git a/ext/ohcount_native/parser.h b/ext/ohcount_native/parser.h new file mode 100644 index 0000000..16a3f45 --- /dev/null +++ b/ext/ohcount_native/parser.h @@ -0,0 +1,33 @@ +/* + * parser.h + * Ohcount + * + * Created by Jason Allen on 6/23/06. + * Copyright 2006 Ohloh. All rights reserved. + * + */ + + +/* + * ParseResult + * + * Calling parser_parse fills out one of these babies. Each language ('html', 'css'...) is + * represented in its own language_breakdown. + * + */ +typedef struct { + LanguageBreakdown language_breakdowns[MAX_LANGUAGE_BREAKDOWN_SIZE]; + int language_breakdown_count; +} ParseResult; + + +/* + * Fills out the ParseResult with the result of parsing the buffer with the specific Language + */ +void parse_result_free(ParseResult *parse_result); + +/* + * frees the memory held by the ParseResult + */ +void parser_parse(ParseResult *pr, char *buffer, int buffer_len, Polyglot *polyglot); + diff --git a/ext/ohcount_native/polyglot.c b/ext/ohcount_native/polyglot.c new file mode 100644 index 0000000..ff51414 --- /dev/null +++ b/ext/ohcount_native/polyglot.c @@ -0,0 +1,44 @@ +/* + * polyglot.c + * Ohcount + * + * Created by Jason Allen on 6/23/06. + * Copyright 2006 Ohloh. All rights reserved. + * + */ +#include "common.h" + + +/* + * polyglot_state_count + * + * Returns the number of states a polyglot contains + * + */ +int polyglot_state_count(Polyglot *polyglot) { + int count = 0; + for ( ; polyglot->states[count] != NULL; count++) {} + return count; +} + +/* + * polyglot_compile_states + * + * creates an associated CompiledState for every State + * contained in a polyglot. CompiledStates are used by + * the parser to avoid doing expensive lookups and avoid + * redundant processing. + * + */ +void polyglot_compile_states(Polyglot *polyglot) { + if (polyglot->compiled_states == NULL) { + // compile them! + int state_count = polyglot_state_count(polyglot); + polyglot->compiled_states = malloc(sizeof(CompiledState) * state_count); + polyglot->compiled_state_count = state_count; + int i = 0; + for (; i < state_count; i++) { + compiled_state_initialize(&polyglot->compiled_states[i], polyglot->states[i], polyglot->transitions); + } + } +} diff --git a/ext/ohcount_native/polyglot.h b/ext/ohcount_native/polyglot.h new file mode 100644 index 0000000..ce865ab --- /dev/null +++ b/ext/ohcount_native/polyglot.h @@ -0,0 +1,19 @@ +/* + * polyglot.h + * Ohcount + * + * Created by Jason Allen on 6/23/06. + * Copyright 2006 Ohloh. All rights reserved. + * + */ + +typedef struct { + char *name; + State **states; + Transition **transitions; + CompiledState *compiled_states; + int compiled_state_count; +} Polyglot; + +int polyglot_state_count(Polyglot *polyglot); +void polyglot_compile_states(Polyglot *polyglot); diff --git a/ext/ohcount_native/polyglots.c b/ext/ohcount_native/polyglots.c new file mode 100644 index 0000000..1e501ef --- /dev/null +++ b/ext/ohcount_native/polyglots.c @@ -0,0 +1,1023 @@ +/* + * polyglots.c + * Ohcount + * + * GENERATED FILE **DO NOT EDIT** + * + */ + +#define __polyglots_c__ +#include "common.h" + +#define RETURN (State *)NULL + +/***************************************************************************** + ada +*****************************************************************************/ +/* States */ +State ADA_CODE = { "ADA_CODE", "ada", semantic_code }; +State ADA_DQUOTE_STRING = { "ADA_DQUOTE_STRING", "ada", semantic_code }; +State ADA_SQUOTE_STRING = { "ADA_SQUOTE_STRING", "ada", semantic_code }; +State ADA_LINE_COMMENT = { "ADA_LINE_COMMENT", "ada", semantic_comment }; +State ADA_BLOCK_COMMENT = { "ADA_BLOCK_COMMENT", "ada", semantic_comment }; +State *ADA_STATES[] = { &ADA_CODE, &ADA_DQUOTE_STRING, &ADA_SQUOTE_STRING, &ADA_LINE_COMMENT, &ADA_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition ADA_CODE__LINE_COMMENT_0 = { "--", &ADA_CODE, &ADA_LINE_COMMENT, ToEatsToken, false }; +Transition ADA_LINE_COMMENT__RETURN = { "\n", &ADA_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition ADA_CODE__DQUOTE_STRING = { "\"", &ADA_CODE, &ADA_DQUOTE_STRING, ToEatsToken, false }; +Transition ADA_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &ADA_DQUOTE_STRING, &ADA_DQUOTE_STRING, ToEatsToken, true }; +Transition ADA_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &ADA_DQUOTE_STRING, &ADA_DQUOTE_STRING, ToEatsToken, true }; +Transition ADA_DQUOTE_STRING__RETURN = { "\"", &ADA_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *ADA_TRANSITIONS[] = { &ADA_CODE__LINE_COMMENT_0, &ADA_LINE_COMMENT__RETURN, &ADA_CODE__DQUOTE_STRING, &ADA_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &ADA_DQUOTE_STRING__DQUOTE_STRING_ESC, &ADA_DQUOTE_STRING__RETURN, NULL}; +Polyglot ADA_POLYGLOT = { + "ada", + ADA_STATES, + ADA_TRANSITIONS, + NULL +}; + +/***************************************************************************** + assembler +*****************************************************************************/ +/* States */ +State ASSEMBLER_CODE = { "ASSEMBLER_CODE", "assembler", semantic_code }; +State ASSEMBLER_DQUOTE_STRING = { "ASSEMBLER_DQUOTE_STRING", "assembler", semantic_code }; +State ASSEMBLER_SQUOTE_STRING = { "ASSEMBLER_SQUOTE_STRING", "assembler", semantic_code }; +State ASSEMBLER_LINE_COMMENT = { "ASSEMBLER_LINE_COMMENT", "assembler", semantic_comment }; +State ASSEMBLER_BLOCK_COMMENT = { "ASSEMBLER_BLOCK_COMMENT", "assembler", semantic_comment }; +State *ASSEMBLER_STATES[] = { &ASSEMBLER_CODE, &ASSEMBLER_DQUOTE_STRING, &ASSEMBLER_SQUOTE_STRING, &ASSEMBLER_LINE_COMMENT, &ASSEMBLER_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition ASSEMBLER_CODE__LINE_COMMENT_0 = { ";", &ASSEMBLER_CODE, &ASSEMBLER_LINE_COMMENT, ToEatsToken, false }; +Transition ASSEMBLER_CODE__LINE_COMMENT_1 = { "!", &ASSEMBLER_CODE, &ASSEMBLER_LINE_COMMENT, ToEatsToken, false }; +Transition ASSEMBLER_CODE__LINE_COMMENT_2 = { "//", &ASSEMBLER_CODE, &ASSEMBLER_LINE_COMMENT, ToEatsToken, false }; +Transition ASSEMBLER_LINE_COMMENT__RETURN = { "\n", &ASSEMBLER_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition ASSEMBLER_CODE__BLOCK_COMMENT_0 = { "/\\*", &ASSEMBLER_CODE, &ASSEMBLER_BLOCK_COMMENT, ToEatsToken, false }; +Transition ASSEMBLER_BLOCK_COMMENT__RETURN_0 = { "\\*/", &ASSEMBLER_BLOCK_COMMENT, RETURN, FromEatsToken, false }; +Transition *ASSEMBLER_TRANSITIONS[] = { &ASSEMBLER_CODE__LINE_COMMENT_0, &ASSEMBLER_CODE__LINE_COMMENT_1, &ASSEMBLER_CODE__LINE_COMMENT_2, &ASSEMBLER_LINE_COMMENT__RETURN, &ASSEMBLER_CODE__BLOCK_COMMENT_0, &ASSEMBLER_BLOCK_COMMENT__RETURN_0, NULL}; +Polyglot ASSEMBLER_POLYGLOT = { + "assembler", + ASSEMBLER_STATES, + ASSEMBLER_TRANSITIONS, + NULL +}; + +/***************************************************************************** + awk +*****************************************************************************/ +/* States */ +State AWK_CODE = { "AWK_CODE", "awk", semantic_code }; +State AWK_DQUOTE_STRING = { "AWK_DQUOTE_STRING", "awk", semantic_code }; +State AWK_SQUOTE_STRING = { "AWK_SQUOTE_STRING", "awk", semantic_code }; +State AWK_LINE_COMMENT = { "AWK_LINE_COMMENT", "awk", semantic_comment }; +State AWK_BLOCK_COMMENT = { "AWK_BLOCK_COMMENT", "awk", semantic_comment }; +State *AWK_STATES[] = { &AWK_CODE, &AWK_DQUOTE_STRING, &AWK_SQUOTE_STRING, &AWK_LINE_COMMENT, &AWK_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition AWK_CODE__LINE_COMMENT_0 = { "#", &AWK_CODE, &AWK_LINE_COMMENT, ToEatsToken, false }; +Transition AWK_LINE_COMMENT__RETURN = { "\n", &AWK_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition AWK_CODE__DQUOTE_STRING = { "\"", &AWK_CODE, &AWK_DQUOTE_STRING, ToEatsToken, false }; +Transition AWK_DQUOTE_STRING__RETURN = { "\"", &AWK_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *AWK_TRANSITIONS[] = { &AWK_CODE__LINE_COMMENT_0, &AWK_LINE_COMMENT__RETURN, &AWK_CODE__DQUOTE_STRING, &AWK_DQUOTE_STRING__RETURN, NULL}; +Polyglot AWK_POLYGLOT = { + "awk", + AWK_STATES, + AWK_TRANSITIONS, + NULL +}; + +/***************************************************************************** + bat +*****************************************************************************/ +/* States */ +State BAT_CODE = { "BAT_CODE", "bat", semantic_code }; +State BAT_COMMENT = { "BAT_COMMENT", "bat", semantic_comment }; +State *BAT_STATES[] = { &BAT_CODE, &BAT_COMMENT, NULL }; +/* Transitions */ +Transition BAT_CODE__COMMENT_0 = { "^\\s*(?i)REM(?-i)", &BAT_CODE, &BAT_COMMENT, ToEatsToken, false }; +Transition BAT_COMMENT__RETURN = { "\n", &BAT_COMMENT, RETURN, FromEatsToken, false }; +Transition *BAT_TRANSITIONS[] = { &BAT_CODE__COMMENT_0, &BAT_COMMENT__RETURN, NULL}; +Polyglot BAT_POLYGLOT = { + "bat", + BAT_STATES, + BAT_TRANSITIONS, + NULL +}; + +/***************************************************************************** + boo +*****************************************************************************/ +/* States */ +State BOO_CODE = { "BOO_CODE", "boo", semantic_code }; +State BOO_MULTI_LINE_SQUOTE = { "BOO_MULTI_LINE_SQUOTE", "boo", semantic_code }; +State BOO_MULTI_LINE_DQUOTE = { "BOO_MULTI_LINE_DQUOTE", "boo", semantic_code }; +State BOO_RAW_DQUOTE = { "BOO_RAW_DQUOTE", "boo", semantic_code }; +State BOO_SQUOTE = { "BOO_SQUOTE", "boo", semantic_code }; +State BOO_DQUOTE = { "BOO_DQUOTE", "boo", semantic_code }; +State BOO_LINE_COMMENT = { "BOO_LINE_COMMENT", "boo", semantic_comment }; +State *BOO_STATES[] = { &BOO_CODE, &BOO_MULTI_LINE_SQUOTE, &BOO_MULTI_LINE_DQUOTE, &BOO_RAW_DQUOTE, &BOO_SQUOTE, &BOO_DQUOTE, &BOO_LINE_COMMENT, NULL }; +/* Transitions */ +Transition BOO_CODE__MULTI_LINE_SQUOTE = { "'''", &BOO_CODE, &BOO_MULTI_LINE_SQUOTE, FromEatsToken, false }; +Transition BOO_MULTI_LINE_SQUOTE__RETURN = { "'''", &BOO_MULTI_LINE_SQUOTE, RETURN, FromEatsToken, false }; +Transition BOO_CODE__MULTI_LINE_DQUOTE = { "\"\"\"", &BOO_CODE, &BOO_MULTI_LINE_DQUOTE, FromEatsToken, false }; +Transition BOO_MULTI_LINE_DQUOTE__RETURN = { "\"\"\"", &BOO_MULTI_LINE_DQUOTE, RETURN, FromEatsToken, false }; +Transition BOO_CODE__RAW_DQUOTE = { "r\"", &BOO_CODE, &BOO_RAW_DQUOTE, FromEatsToken, false }; +Transition BOO_RAW_DQUOTE__RETURN = { "\"", &BOO_RAW_DQUOTE, RETURN, FromEatsToken, false }; +Transition BOO_CODE__SQUOTE = { "'", &BOO_CODE, &BOO_SQUOTE, FromEatsToken, false }; +Transition BOO_SQUOTE__RETURN_ESC = { "\\\\'", &BOO_SQUOTE, RETURN, FromEatsToken, true }; +Transition BOO_SQUOTE__RETURN = { "'", &BOO_SQUOTE, RETURN, ToEatsToken, false }; +Transition BOO_CODE__DQUOTE = { "\"", &BOO_CODE, &BOO_DQUOTE, ToEatsToken, false }; +Transition BOO_DQUOTE__RETURN_ESC = { "\\\\\"", &BOO_DQUOTE, RETURN, FromEatsToken, true }; +Transition BOO_DQUOTE__RETURN = { "\"", &BOO_DQUOTE, RETURN, ToEatsToken, false }; +Transition BOO_CODE__LINE_COMMENT = { "#", &BOO_CODE, &BOO_LINE_COMMENT, ToEatsToken, false }; +Transition BOO_LINE_COMMENT__RETURN = { "\n", &BOO_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition *BOO_TRANSITIONS[] = { &BOO_CODE__MULTI_LINE_SQUOTE, &BOO_MULTI_LINE_SQUOTE__RETURN, &BOO_CODE__MULTI_LINE_DQUOTE, &BOO_MULTI_LINE_DQUOTE__RETURN, &BOO_CODE__RAW_DQUOTE, &BOO_RAW_DQUOTE__RETURN, &BOO_CODE__SQUOTE, &BOO_SQUOTE__RETURN_ESC, &BOO_SQUOTE__RETURN, &BOO_CODE__DQUOTE, &BOO_DQUOTE__RETURN_ESC, &BOO_DQUOTE__RETURN, &BOO_CODE__LINE_COMMENT, &BOO_LINE_COMMENT__RETURN, NULL}; +Polyglot BOO_POLYGLOT = { + "boo", + BOO_STATES, + BOO_TRANSITIONS, + NULL +}; + +/***************************************************************************** + clearsilver +*****************************************************************************/ +/* States */ +State CLEARSILVER_CODE = { "CLEARSILVER_CODE", "clearsilver", semantic_code }; +State CLEARSILVER_DQUOTE_STRING = { "CLEARSILVER_DQUOTE_STRING", "clearsilver", semantic_code }; +State CLEARSILVER_SQUOTE_STRING = { "CLEARSILVER_SQUOTE_STRING", "clearsilver", semantic_code }; +State CLEARSILVER_LINE_COMMENT = { "CLEARSILVER_LINE_COMMENT", "clearsilver", semantic_comment }; +State CLEARSILVER_BLOCK_COMMENT = { "CLEARSILVER_BLOCK_COMMENT", "clearsilver", semantic_comment }; +State *CLEARSILVER_STATES[] = { &CLEARSILVER_CODE, &CLEARSILVER_DQUOTE_STRING, &CLEARSILVER_SQUOTE_STRING, &CLEARSILVER_LINE_COMMENT, &CLEARSILVER_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition CLEARSILVER_CODE__LINE_COMMENT_0 = { "#", &CLEARSILVER_CODE, &CLEARSILVER_LINE_COMMENT, ToEatsToken, false }; +Transition CLEARSILVER_LINE_COMMENT__RETURN = { "\n", &CLEARSILVER_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition CLEARSILVER_CODE__SQUOTE_STRING = { "'", &CLEARSILVER_CODE, &CLEARSILVER_SQUOTE_STRING, ToEatsToken, false }; +Transition CLEARSILVER_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &CLEARSILVER_SQUOTE_STRING, &CLEARSILVER_SQUOTE_STRING, FromEatsToken, true }; +Transition CLEARSILVER_SQUOTE_STRING__SQUOTE_STRING_ESC = { "\\\\'", &CLEARSILVER_SQUOTE_STRING, &CLEARSILVER_SQUOTE_STRING, FromEatsToken, true }; +Transition CLEARSILVER_SQUOTE_STRING__RETURN = { "'", &CLEARSILVER_SQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition CLEARSILVER_CODE__DQUOTE_STRING = { "\"", &CLEARSILVER_CODE, &CLEARSILVER_DQUOTE_STRING, ToEatsToken, false }; +Transition CLEARSILVER_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &CLEARSILVER_DQUOTE_STRING, &CLEARSILVER_DQUOTE_STRING, ToEatsToken, true }; +Transition CLEARSILVER_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &CLEARSILVER_DQUOTE_STRING, &CLEARSILVER_DQUOTE_STRING, ToEatsToken, true }; +Transition CLEARSILVER_DQUOTE_STRING__RETURN = { "\"", &CLEARSILVER_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *CLEARSILVER_TRANSITIONS[] = { &CLEARSILVER_CODE__LINE_COMMENT_0, &CLEARSILVER_LINE_COMMENT__RETURN, &CLEARSILVER_CODE__SQUOTE_STRING, &CLEARSILVER_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH, &CLEARSILVER_SQUOTE_STRING__SQUOTE_STRING_ESC, &CLEARSILVER_SQUOTE_STRING__RETURN, &CLEARSILVER_CODE__DQUOTE_STRING, &CLEARSILVER_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &CLEARSILVER_DQUOTE_STRING__DQUOTE_STRING_ESC, &CLEARSILVER_DQUOTE_STRING__RETURN, NULL}; +Polyglot CLEARSILVER_POLYGLOT = { + "clearsilver", + CLEARSILVER_STATES, + CLEARSILVER_TRANSITIONS, + NULL +}; + +/***************************************************************************** + cncpp +*****************************************************************************/ +/* States */ +State CNCPP_CODE = { "CNCPP_CODE", "cncpp", semantic_code }; +State CNCPP_DQUOTE_STRING = { "CNCPP_DQUOTE_STRING", "cncpp", semantic_code }; +State CNCPP_SQUOTE_STRING = { "CNCPP_SQUOTE_STRING", "cncpp", semantic_code }; +State CNCPP_LINE_COMMENT = { "CNCPP_LINE_COMMENT", "cncpp", semantic_comment }; +State CNCPP_BLOCK_COMMENT = { "CNCPP_BLOCK_COMMENT", "cncpp", semantic_comment }; +State *CNCPP_STATES[] = { &CNCPP_CODE, &CNCPP_DQUOTE_STRING, &CNCPP_SQUOTE_STRING, &CNCPP_LINE_COMMENT, &CNCPP_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition CNCPP_CODE__LINE_COMMENT_0 = { "//", &CNCPP_CODE, &CNCPP_LINE_COMMENT, ToEatsToken, false }; +Transition CNCPP_LINE_COMMENT__RETURN = { "\n", &CNCPP_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition CNCPP_CODE__BLOCK_COMMENT_0 = { "/\\*", &CNCPP_CODE, &CNCPP_BLOCK_COMMENT, ToEatsToken, false }; +Transition CNCPP_BLOCK_COMMENT__RETURN_0 = { "\\*/", &CNCPP_BLOCK_COMMENT, RETURN, FromEatsToken, false }; +Transition CNCPP_CODE__DQUOTE_STRING = { "\"", &CNCPP_CODE, &CNCPP_DQUOTE_STRING, ToEatsToken, false }; +Transition CNCPP_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &CNCPP_DQUOTE_STRING, &CNCPP_DQUOTE_STRING, ToEatsToken, true }; +Transition CNCPP_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &CNCPP_DQUOTE_STRING, &CNCPP_DQUOTE_STRING, ToEatsToken, true }; +Transition CNCPP_DQUOTE_STRING__RETURN = { "\"", &CNCPP_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *CNCPP_TRANSITIONS[] = { &CNCPP_CODE__LINE_COMMENT_0, &CNCPP_LINE_COMMENT__RETURN, &CNCPP_CODE__BLOCK_COMMENT_0, &CNCPP_BLOCK_COMMENT__RETURN_0, &CNCPP_CODE__DQUOTE_STRING, &CNCPP_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &CNCPP_DQUOTE_STRING__DQUOTE_STRING_ESC, &CNCPP_DQUOTE_STRING__RETURN, NULL}; +Polyglot CNCPP_POLYGLOT = { + "cncpp", + CNCPP_STATES, + CNCPP_TRANSITIONS, + NULL +}; + +/***************************************************************************** + csharp +*****************************************************************************/ +/* States */ +State CSHARP_CODE = { "CSHARP_CODE", "csharp", semantic_code }; +State CSHARP_DQUOTE_STRING = { "CSHARP_DQUOTE_STRING", "csharp", semantic_code }; +State CSHARP_SQUOTE_STRING = { "CSHARP_SQUOTE_STRING", "csharp", semantic_code }; +State CSHARP_LINE_COMMENT = { "CSHARP_LINE_COMMENT", "csharp", semantic_comment }; +State CSHARP_BLOCK_COMMENT = { "CSHARP_BLOCK_COMMENT", "csharp", semantic_comment }; +State *CSHARP_STATES[] = { &CSHARP_CODE, &CSHARP_DQUOTE_STRING, &CSHARP_SQUOTE_STRING, &CSHARP_LINE_COMMENT, &CSHARP_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition CSHARP_CODE__LINE_COMMENT_0 = { "//", &CSHARP_CODE, &CSHARP_LINE_COMMENT, ToEatsToken, false }; +Transition CSHARP_LINE_COMMENT__RETURN = { "\n", &CSHARP_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition CSHARP_CODE__BLOCK_COMMENT_0 = { "/\\*", &CSHARP_CODE, &CSHARP_BLOCK_COMMENT, ToEatsToken, false }; +Transition CSHARP_BLOCK_COMMENT__RETURN_0 = { "\\*/", &CSHARP_BLOCK_COMMENT, RETURN, FromEatsToken, false }; +Transition CSHARP_CODE__DQUOTE_STRING = { "\"", &CSHARP_CODE, &CSHARP_DQUOTE_STRING, ToEatsToken, false }; +Transition CSHARP_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &CSHARP_DQUOTE_STRING, &CSHARP_DQUOTE_STRING, ToEatsToken, true }; +Transition CSHARP_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &CSHARP_DQUOTE_STRING, &CSHARP_DQUOTE_STRING, ToEatsToken, true }; +Transition CSHARP_DQUOTE_STRING__RETURN = { "\"", &CSHARP_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *CSHARP_TRANSITIONS[] = { &CSHARP_CODE__LINE_COMMENT_0, &CSHARP_LINE_COMMENT__RETURN, &CSHARP_CODE__BLOCK_COMMENT_0, &CSHARP_BLOCK_COMMENT__RETURN_0, &CSHARP_CODE__DQUOTE_STRING, &CSHARP_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &CSHARP_DQUOTE_STRING__DQUOTE_STRING_ESC, &CSHARP_DQUOTE_STRING__RETURN, NULL}; +Polyglot CSHARP_POLYGLOT = { + "csharp", + CSHARP_STATES, + CSHARP_TRANSITIONS, + NULL +}; + +/***************************************************************************** + css +*****************************************************************************/ +/* States */ +State CSS_CODE = { "CSS_CODE", "css", semantic_code }; +State CSS_DQUOTE_STRING = { "CSS_DQUOTE_STRING", "css", semantic_code }; +State CSS_SQUOTE_STRING = { "CSS_SQUOTE_STRING", "css", semantic_code }; +State CSS_LINE_COMMENT = { "CSS_LINE_COMMENT", "css", semantic_comment }; +State CSS_BLOCK_COMMENT = { "CSS_BLOCK_COMMENT", "css", semantic_comment }; +State *CSS_STATES[] = { &CSS_CODE, &CSS_DQUOTE_STRING, &CSS_SQUOTE_STRING, &CSS_LINE_COMMENT, &CSS_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition CSS_CODE__BLOCK_COMMENT_0 = { "/\\*", &CSS_CODE, &CSS_BLOCK_COMMENT, ToEatsToken, false }; +Transition CSS_BLOCK_COMMENT__RETURN_0 = { "\\*/", &CSS_BLOCK_COMMENT, RETURN, FromEatsToken, false }; +Transition *CSS_TRANSITIONS[] = { &CSS_CODE__BLOCK_COMMENT_0, &CSS_BLOCK_COMMENT__RETURN_0, NULL}; +Polyglot CSS_POLYGLOT = { + "css", + CSS_STATES, + CSS_TRANSITIONS, + NULL +}; + +/***************************************************************************** + dylan +*****************************************************************************/ +/* States */ +State DYLAN_CODE = { "DYLAN_CODE", "dylan", semantic_code }; +State DYLAN_DQUOTE_STRING = { "DYLAN_DQUOTE_STRING", "dylan", semantic_code }; +State DYLAN_SQUOTE_STRING = { "DYLAN_SQUOTE_STRING", "dylan", semantic_code }; +State DYLAN_LINE_COMMENT = { "DYLAN_LINE_COMMENT", "dylan", semantic_comment }; +State DYLAN_BLOCK_COMMENT = { "DYLAN_BLOCK_COMMENT", "dylan", semantic_comment }; +State *DYLAN_STATES[] = { &DYLAN_CODE, &DYLAN_DQUOTE_STRING, &DYLAN_SQUOTE_STRING, &DYLAN_LINE_COMMENT, &DYLAN_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition DYLAN_CODE__LINE_COMMENT_0 = { "//", &DYLAN_CODE, &DYLAN_LINE_COMMENT, ToEatsToken, false }; +Transition DYLAN_LINE_COMMENT__RETURN = { "\n", &DYLAN_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition DYLAN_CODE__DQUOTE_STRING = { "\"", &DYLAN_CODE, &DYLAN_DQUOTE_STRING, ToEatsToken, false }; +Transition DYLAN_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &DYLAN_DQUOTE_STRING, &DYLAN_DQUOTE_STRING, ToEatsToken, true }; +Transition DYLAN_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &DYLAN_DQUOTE_STRING, &DYLAN_DQUOTE_STRING, ToEatsToken, true }; +Transition DYLAN_DQUOTE_STRING__RETURN = { "\"", &DYLAN_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *DYLAN_TRANSITIONS[] = { &DYLAN_CODE__LINE_COMMENT_0, &DYLAN_LINE_COMMENT__RETURN, &DYLAN_CODE__DQUOTE_STRING, &DYLAN_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &DYLAN_DQUOTE_STRING__DQUOTE_STRING_ESC, &DYLAN_DQUOTE_STRING__RETURN, NULL}; +Polyglot DYLAN_POLYGLOT = { + "dylan", + DYLAN_STATES, + DYLAN_TRANSITIONS, + NULL +}; + +/***************************************************************************** + erlang +*****************************************************************************/ +/* States */ +State ERLANG_CODE = { "ERLANG_CODE", "erlang", semantic_code }; +State ERLANG_DQUOTE_STRING = { "ERLANG_DQUOTE_STRING", "erlang", semantic_code }; +State ERLANG_SQUOTE_STRING = { "ERLANG_SQUOTE_STRING", "erlang", semantic_code }; +State ERLANG_LINE_COMMENT = { "ERLANG_LINE_COMMENT", "erlang", semantic_comment }; +State ERLANG_BLOCK_COMMENT = { "ERLANG_BLOCK_COMMENT", "erlang", semantic_comment }; +State *ERLANG_STATES[] = { &ERLANG_CODE, &ERLANG_DQUOTE_STRING, &ERLANG_SQUOTE_STRING, &ERLANG_LINE_COMMENT, &ERLANG_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition ERLANG_CODE__LINE_COMMENT_0 = { "%%", &ERLANG_CODE, &ERLANG_LINE_COMMENT, ToEatsToken, false }; +Transition ERLANG_LINE_COMMENT__RETURN = { "\n", &ERLANG_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition ERLANG_CODE__SQUOTE_STRING = { "'", &ERLANG_CODE, &ERLANG_SQUOTE_STRING, ToEatsToken, false }; +Transition ERLANG_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &ERLANG_SQUOTE_STRING, &ERLANG_SQUOTE_STRING, FromEatsToken, true }; +Transition ERLANG_SQUOTE_STRING__SQUOTE_STRING_ESC = { "\\\\'", &ERLANG_SQUOTE_STRING, &ERLANG_SQUOTE_STRING, FromEatsToken, true }; +Transition ERLANG_SQUOTE_STRING__RETURN = { "'", &ERLANG_SQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition ERLANG_CODE__DQUOTE_STRING = { "\"", &ERLANG_CODE, &ERLANG_DQUOTE_STRING, ToEatsToken, false }; +Transition ERLANG_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &ERLANG_DQUOTE_STRING, &ERLANG_DQUOTE_STRING, ToEatsToken, true }; +Transition ERLANG_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &ERLANG_DQUOTE_STRING, &ERLANG_DQUOTE_STRING, ToEatsToken, true }; +Transition ERLANG_DQUOTE_STRING__RETURN = { "\"", &ERLANG_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *ERLANG_TRANSITIONS[] = { &ERLANG_CODE__LINE_COMMENT_0, &ERLANG_LINE_COMMENT__RETURN, &ERLANG_CODE__SQUOTE_STRING, &ERLANG_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH, &ERLANG_SQUOTE_STRING__SQUOTE_STRING_ESC, &ERLANG_SQUOTE_STRING__RETURN, &ERLANG_CODE__DQUOTE_STRING, &ERLANG_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &ERLANG_DQUOTE_STRING__DQUOTE_STRING_ESC, &ERLANG_DQUOTE_STRING__RETURN, NULL}; +Polyglot ERLANG_POLYGLOT = { + "erlang", + ERLANG_STATES, + ERLANG_TRANSITIONS, + NULL +}; + +/***************************************************************************** + groovy +*****************************************************************************/ +/* States */ +State GROOVY_CODE = { "GROOVY_CODE", "groovy", semantic_code }; +State GROOVY_DQUOTE_STRING = { "GROOVY_DQUOTE_STRING", "groovy", semantic_code }; +State GROOVY_SQUOTE_STRING = { "GROOVY_SQUOTE_STRING", "groovy", semantic_code }; +State GROOVY_LINE_COMMENT = { "GROOVY_LINE_COMMENT", "groovy", semantic_comment }; +State GROOVY_BLOCK_COMMENT = { "GROOVY_BLOCK_COMMENT", "groovy", semantic_comment }; +State *GROOVY_STATES[] = { &GROOVY_CODE, &GROOVY_DQUOTE_STRING, &GROOVY_SQUOTE_STRING, &GROOVY_LINE_COMMENT, &GROOVY_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition GROOVY_CODE__LINE_COMMENT_0 = { "//", &GROOVY_CODE, &GROOVY_LINE_COMMENT, ToEatsToken, false }; +Transition GROOVY_LINE_COMMENT__RETURN = { "\n", &GROOVY_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition GROOVY_CODE__BLOCK_COMMENT_0 = { "/\\*", &GROOVY_CODE, &GROOVY_BLOCK_COMMENT, ToEatsToken, false }; +Transition GROOVY_BLOCK_COMMENT__RETURN_0 = { "\\*/", &GROOVY_BLOCK_COMMENT, RETURN, FromEatsToken, false }; +Transition GROOVY_CODE__DQUOTE_STRING = { "\"", &GROOVY_CODE, &GROOVY_DQUOTE_STRING, ToEatsToken, false }; +Transition GROOVY_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &GROOVY_DQUOTE_STRING, &GROOVY_DQUOTE_STRING, ToEatsToken, true }; +Transition GROOVY_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &GROOVY_DQUOTE_STRING, &GROOVY_DQUOTE_STRING, ToEatsToken, true }; +Transition GROOVY_DQUOTE_STRING__RETURN = { "\"", &GROOVY_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *GROOVY_TRANSITIONS[] = { &GROOVY_CODE__LINE_COMMENT_0, &GROOVY_LINE_COMMENT__RETURN, &GROOVY_CODE__BLOCK_COMMENT_0, &GROOVY_BLOCK_COMMENT__RETURN_0, &GROOVY_CODE__DQUOTE_STRING, &GROOVY_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &GROOVY_DQUOTE_STRING__DQUOTE_STRING_ESC, &GROOVY_DQUOTE_STRING__RETURN, NULL}; +Polyglot GROOVY_POLYGLOT = { + "groovy", + GROOVY_STATES, + GROOVY_TRANSITIONS, + NULL +}; + +/***************************************************************************** + java +*****************************************************************************/ +/* States */ +State JAVA_CODE = { "JAVA_CODE", "java", semantic_code }; +State JAVA_DQUOTE_STRING = { "JAVA_DQUOTE_STRING", "java", semantic_code }; +State JAVA_SQUOTE_STRING = { "JAVA_SQUOTE_STRING", "java", semantic_code }; +State JAVA_LINE_COMMENT = { "JAVA_LINE_COMMENT", "java", semantic_comment }; +State JAVA_BLOCK_COMMENT = { "JAVA_BLOCK_COMMENT", "java", semantic_comment }; +State *JAVA_STATES[] = { &JAVA_CODE, &JAVA_DQUOTE_STRING, &JAVA_SQUOTE_STRING, &JAVA_LINE_COMMENT, &JAVA_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition JAVA_CODE__LINE_COMMENT_0 = { "//", &JAVA_CODE, &JAVA_LINE_COMMENT, ToEatsToken, false }; +Transition JAVA_LINE_COMMENT__RETURN = { "\n", &JAVA_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition JAVA_CODE__BLOCK_COMMENT_0 = { "/\\*", &JAVA_CODE, &JAVA_BLOCK_COMMENT, ToEatsToken, false }; +Transition JAVA_BLOCK_COMMENT__RETURN_0 = { "\\*/", &JAVA_BLOCK_COMMENT, RETURN, FromEatsToken, false }; +Transition JAVA_CODE__DQUOTE_STRING = { "\"", &JAVA_CODE, &JAVA_DQUOTE_STRING, ToEatsToken, false }; +Transition JAVA_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &JAVA_DQUOTE_STRING, &JAVA_DQUOTE_STRING, ToEatsToken, true }; +Transition JAVA_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &JAVA_DQUOTE_STRING, &JAVA_DQUOTE_STRING, ToEatsToken, true }; +Transition JAVA_DQUOTE_STRING__RETURN = { "\"", &JAVA_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *JAVA_TRANSITIONS[] = { &JAVA_CODE__LINE_COMMENT_0, &JAVA_LINE_COMMENT__RETURN, &JAVA_CODE__BLOCK_COMMENT_0, &JAVA_BLOCK_COMMENT__RETURN_0, &JAVA_CODE__DQUOTE_STRING, &JAVA_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &JAVA_DQUOTE_STRING__DQUOTE_STRING_ESC, &JAVA_DQUOTE_STRING__RETURN, NULL}; +Polyglot JAVA_POLYGLOT = { + "java", + JAVA_STATES, + JAVA_TRANSITIONS, + NULL +}; + +/***************************************************************************** + javascript +*****************************************************************************/ +/* States */ +State JAVASCRIPT_CODE = { "JAVASCRIPT_CODE", "javascript", semantic_code }; +State JAVASCRIPT_DQUOTE_STRING = { "JAVASCRIPT_DQUOTE_STRING", "javascript", semantic_code }; +State JAVASCRIPT_SQUOTE_STRING = { "JAVASCRIPT_SQUOTE_STRING", "javascript", semantic_code }; +State JAVASCRIPT_LINE_COMMENT = { "JAVASCRIPT_LINE_COMMENT", "javascript", semantic_comment }; +State JAVASCRIPT_BLOCK_COMMENT = { "JAVASCRIPT_BLOCK_COMMENT", "javascript", semantic_comment }; +State *JAVASCRIPT_STATES[] = { &JAVASCRIPT_CODE, &JAVASCRIPT_DQUOTE_STRING, &JAVASCRIPT_SQUOTE_STRING, &JAVASCRIPT_LINE_COMMENT, &JAVASCRIPT_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition JAVASCRIPT_CODE__LINE_COMMENT_0 = { "//", &JAVASCRIPT_CODE, &JAVASCRIPT_LINE_COMMENT, ToEatsToken, false }; +Transition JAVASCRIPT_LINE_COMMENT__RETURN = { "\n", &JAVASCRIPT_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition JAVASCRIPT_CODE__BLOCK_COMMENT_0 = { "/\\*", &JAVASCRIPT_CODE, &JAVASCRIPT_BLOCK_COMMENT, ToEatsToken, false }; +Transition JAVASCRIPT_BLOCK_COMMENT__RETURN_0 = { "\\*/", &JAVASCRIPT_BLOCK_COMMENT, RETURN, FromEatsToken, false }; +Transition JAVASCRIPT_CODE__SQUOTE_STRING = { "'", &JAVASCRIPT_CODE, &JAVASCRIPT_SQUOTE_STRING, ToEatsToken, false }; +Transition JAVASCRIPT_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &JAVASCRIPT_SQUOTE_STRING, &JAVASCRIPT_SQUOTE_STRING, FromEatsToken, true }; +Transition JAVASCRIPT_SQUOTE_STRING__SQUOTE_STRING_ESC = { "\\\\'", &JAVASCRIPT_SQUOTE_STRING, &JAVASCRIPT_SQUOTE_STRING, FromEatsToken, true }; +Transition JAVASCRIPT_SQUOTE_STRING__RETURN = { "'", &JAVASCRIPT_SQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition JAVASCRIPT_CODE__DQUOTE_STRING = { "\"", &JAVASCRIPT_CODE, &JAVASCRIPT_DQUOTE_STRING, ToEatsToken, false }; +Transition JAVASCRIPT_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &JAVASCRIPT_DQUOTE_STRING, &JAVASCRIPT_DQUOTE_STRING, ToEatsToken, true }; +Transition JAVASCRIPT_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &JAVASCRIPT_DQUOTE_STRING, &JAVASCRIPT_DQUOTE_STRING, ToEatsToken, true }; +Transition JAVASCRIPT_DQUOTE_STRING__RETURN = { "\"", &JAVASCRIPT_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *JAVASCRIPT_TRANSITIONS[] = { &JAVASCRIPT_CODE__LINE_COMMENT_0, &JAVASCRIPT_LINE_COMMENT__RETURN, &JAVASCRIPT_CODE__BLOCK_COMMENT_0, &JAVASCRIPT_BLOCK_COMMENT__RETURN_0, &JAVASCRIPT_CODE__SQUOTE_STRING, &JAVASCRIPT_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH, &JAVASCRIPT_SQUOTE_STRING__SQUOTE_STRING_ESC, &JAVASCRIPT_SQUOTE_STRING__RETURN, &JAVASCRIPT_CODE__DQUOTE_STRING, &JAVASCRIPT_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &JAVASCRIPT_DQUOTE_STRING__DQUOTE_STRING_ESC, &JAVASCRIPT_DQUOTE_STRING__RETURN, NULL}; +Polyglot JAVASCRIPT_POLYGLOT = { + "javascript", + JAVASCRIPT_STATES, + JAVASCRIPT_TRANSITIONS, + NULL +}; + +/***************************************************************************** + emacslisp +*****************************************************************************/ +/* States */ +State EMACSLISP_CODE = { "EMACSLISP_CODE", "emacslisp", semantic_code }; +State EMACSLISP_COMMENT = { "EMACSLISP_COMMENT", "emacslisp", semantic_comment }; +State *EMACSLISP_STATES[] = { &EMACSLISP_CODE, &EMACSLISP_COMMENT, NULL }; +/* Transitions */ +Transition EMACSLISP_CODE__COMMENT_0 = { ";", &EMACSLISP_CODE, &EMACSLISP_COMMENT, ToEatsToken, false }; +Transition EMACSLISP_COMMENT__RETURN = { "\n", &EMACSLISP_COMMENT, RETURN, FromEatsToken, false }; +Transition *EMACSLISP_TRANSITIONS[] = { &EMACSLISP_CODE__COMMENT_0, &EMACSLISP_COMMENT__RETURN, NULL}; +Polyglot EMACSLISP_POLYGLOT = { + "emacslisp", + EMACSLISP_STATES, + EMACSLISP_TRANSITIONS, + NULL +}; + +/***************************************************************************** + lisp +*****************************************************************************/ +/* States */ +State LISP_CODE = { "LISP_CODE", "lisp", semantic_code }; +State LISP_COMMENT = { "LISP_COMMENT", "lisp", semantic_comment }; +State *LISP_STATES[] = { &LISP_CODE, &LISP_COMMENT, NULL }; +/* Transitions */ +Transition LISP_CODE__COMMENT_0 = { ";", &LISP_CODE, &LISP_COMMENT, ToEatsToken, false }; +Transition LISP_COMMENT__RETURN = { "\n", &LISP_COMMENT, RETURN, FromEatsToken, false }; +Transition *LISP_TRANSITIONS[] = { &LISP_CODE__COMMENT_0, &LISP_COMMENT__RETURN, NULL}; +Polyglot LISP_POLYGLOT = { + "lisp", + LISP_STATES, + LISP_TRANSITIONS, + NULL +}; + +/***************************************************************************** + lua +*****************************************************************************/ +/* States */ +State LUA_CODE = { "LUA_CODE", "lua", semantic_code }; +State LUA_DQUOTE_STRING = { "LUA_DQUOTE_STRING", "lua", semantic_code }; +State LUA_SQUOTE_STRING = { "LUA_SQUOTE_STRING", "lua", semantic_code }; +State LUA_LINE_COMMENT = { "LUA_LINE_COMMENT", "lua", semantic_comment }; +State LUA_BLOCK_COMMENT = { "LUA_BLOCK_COMMENT", "lua", semantic_comment }; +State *LUA_STATES[] = { &LUA_CODE, &LUA_DQUOTE_STRING, &LUA_SQUOTE_STRING, &LUA_LINE_COMMENT, &LUA_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition LUA_CODE__LINE_COMMENT_0 = { "--", &LUA_CODE, &LUA_LINE_COMMENT, ToEatsToken, false }; +Transition LUA_LINE_COMMENT__RETURN = { "\n", &LUA_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition LUA_CODE__SQUOTE_STRING = { "'", &LUA_CODE, &LUA_SQUOTE_STRING, ToEatsToken, false }; +Transition LUA_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &LUA_SQUOTE_STRING, &LUA_SQUOTE_STRING, FromEatsToken, true }; +Transition LUA_SQUOTE_STRING__SQUOTE_STRING_ESC = { "\\\\'", &LUA_SQUOTE_STRING, &LUA_SQUOTE_STRING, FromEatsToken, true }; +Transition LUA_SQUOTE_STRING__RETURN = { "'", &LUA_SQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition LUA_CODE__DQUOTE_STRING = { "\"", &LUA_CODE, &LUA_DQUOTE_STRING, ToEatsToken, false }; +Transition LUA_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &LUA_DQUOTE_STRING, &LUA_DQUOTE_STRING, ToEatsToken, true }; +Transition LUA_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &LUA_DQUOTE_STRING, &LUA_DQUOTE_STRING, ToEatsToken, true }; +Transition LUA_DQUOTE_STRING__RETURN = { "\"", &LUA_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *LUA_TRANSITIONS[] = { &LUA_CODE__LINE_COMMENT_0, &LUA_LINE_COMMENT__RETURN, &LUA_CODE__SQUOTE_STRING, &LUA_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH, &LUA_SQUOTE_STRING__SQUOTE_STRING_ESC, &LUA_SQUOTE_STRING__RETURN, &LUA_CODE__DQUOTE_STRING, &LUA_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &LUA_DQUOTE_STRING__DQUOTE_STRING_ESC, &LUA_DQUOTE_STRING__RETURN, NULL}; +Polyglot LUA_POLYGLOT = { + "lua", + LUA_STATES, + LUA_TRANSITIONS, + NULL +}; + +/***************************************************************************** + matlab +*****************************************************************************/ +/* States */ +State MATLAB_CODE = { "MATLAB_CODE", "matlab", semantic_code }; +State MATLAB_DQUOTE_STRING = { "MATLAB_DQUOTE_STRING", "matlab", semantic_code }; +State MATLAB_SQUOTE_STRING = { "MATLAB_SQUOTE_STRING", "matlab", semantic_code }; +State MATLAB_LINE_COMMENT = { "MATLAB_LINE_COMMENT", "matlab", semantic_comment }; +State MATLAB_BLOCK_COMMENT = { "MATLAB_BLOCK_COMMENT", "matlab", semantic_comment }; +State *MATLAB_STATES[] = { &MATLAB_CODE, &MATLAB_DQUOTE_STRING, &MATLAB_SQUOTE_STRING, &MATLAB_LINE_COMMENT, &MATLAB_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition MATLAB_CODE__LINE_COMMENT_0 = { "#|%", &MATLAB_CODE, &MATLAB_LINE_COMMENT, ToEatsToken, false }; +Transition MATLAB_LINE_COMMENT__RETURN = { "\n", &MATLAB_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition MATLAB_CODE__BLOCK_COMMENT_0 = { "{%", &MATLAB_CODE, &MATLAB_BLOCK_COMMENT, ToEatsToken, false }; +Transition MATLAB_BLOCK_COMMENT__RETURN_0 = { "%}", &MATLAB_BLOCK_COMMENT, RETURN, FromEatsToken, false }; +Transition MATLAB_CODE__SQUOTE_STRING = { "'", &MATLAB_CODE, &MATLAB_SQUOTE_STRING, ToEatsToken, false }; +Transition MATLAB_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &MATLAB_SQUOTE_STRING, &MATLAB_SQUOTE_STRING, FromEatsToken, true }; +Transition MATLAB_SQUOTE_STRING__SQUOTE_STRING_ESC = { "\\\\'", &MATLAB_SQUOTE_STRING, &MATLAB_SQUOTE_STRING, FromEatsToken, true }; +Transition MATLAB_SQUOTE_STRING__RETURN = { "'", &MATLAB_SQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *MATLAB_TRANSITIONS[] = { &MATLAB_CODE__LINE_COMMENT_0, &MATLAB_LINE_COMMENT__RETURN, &MATLAB_CODE__BLOCK_COMMENT_0, &MATLAB_BLOCK_COMMENT__RETURN_0, &MATLAB_CODE__SQUOTE_STRING, &MATLAB_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH, &MATLAB_SQUOTE_STRING__SQUOTE_STRING_ESC, &MATLAB_SQUOTE_STRING__RETURN, NULL}; +Polyglot MATLAB_POLYGLOT = { + "matlab", + MATLAB_STATES, + MATLAB_TRANSITIONS, + NULL +}; + +/***************************************************************************** + objective_c +*****************************************************************************/ +/* States */ +State OBJECTIVE_C_CODE = { "OBJECTIVE_C_CODE", "objective_c", semantic_code }; +State OBJECTIVE_C_DQUOTE_STRING = { "OBJECTIVE_C_DQUOTE_STRING", "objective_c", semantic_code }; +State OBJECTIVE_C_SQUOTE_STRING = { "OBJECTIVE_C_SQUOTE_STRING", "objective_c", semantic_code }; +State OBJECTIVE_C_LINE_COMMENT = { "OBJECTIVE_C_LINE_COMMENT", "objective_c", semantic_comment }; +State OBJECTIVE_C_BLOCK_COMMENT = { "OBJECTIVE_C_BLOCK_COMMENT", "objective_c", semantic_comment }; +State *OBJECTIVE_C_STATES[] = { &OBJECTIVE_C_CODE, &OBJECTIVE_C_DQUOTE_STRING, &OBJECTIVE_C_SQUOTE_STRING, &OBJECTIVE_C_LINE_COMMENT, &OBJECTIVE_C_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition OBJECTIVE_C_CODE__LINE_COMMENT_0 = { "//", &OBJECTIVE_C_CODE, &OBJECTIVE_C_LINE_COMMENT, ToEatsToken, false }; +Transition OBJECTIVE_C_LINE_COMMENT__RETURN = { "\n", &OBJECTIVE_C_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition OBJECTIVE_C_CODE__BLOCK_COMMENT_0 = { "/\\*", &OBJECTIVE_C_CODE, &OBJECTIVE_C_BLOCK_COMMENT, ToEatsToken, false }; +Transition OBJECTIVE_C_BLOCK_COMMENT__RETURN_0 = { "\\*/", &OBJECTIVE_C_BLOCK_COMMENT, RETURN, FromEatsToken, false }; +Transition OBJECTIVE_C_CODE__DQUOTE_STRING = { "\"", &OBJECTIVE_C_CODE, &OBJECTIVE_C_DQUOTE_STRING, ToEatsToken, false }; +Transition OBJECTIVE_C_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &OBJECTIVE_C_DQUOTE_STRING, &OBJECTIVE_C_DQUOTE_STRING, ToEatsToken, true }; +Transition OBJECTIVE_C_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &OBJECTIVE_C_DQUOTE_STRING, &OBJECTIVE_C_DQUOTE_STRING, ToEatsToken, true }; +Transition OBJECTIVE_C_DQUOTE_STRING__RETURN = { "\"", &OBJECTIVE_C_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *OBJECTIVE_C_TRANSITIONS[] = { &OBJECTIVE_C_CODE__LINE_COMMENT_0, &OBJECTIVE_C_LINE_COMMENT__RETURN, &OBJECTIVE_C_CODE__BLOCK_COMMENT_0, &OBJECTIVE_C_BLOCK_COMMENT__RETURN_0, &OBJECTIVE_C_CODE__DQUOTE_STRING, &OBJECTIVE_C_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &OBJECTIVE_C_DQUOTE_STRING__DQUOTE_STRING_ESC, &OBJECTIVE_C_DQUOTE_STRING__RETURN, NULL}; +Polyglot OBJECTIVE_C_POLYGLOT = { + "objective_c", + OBJECTIVE_C_STATES, + OBJECTIVE_C_TRANSITIONS, + NULL +}; + +/***************************************************************************** + pascal +*****************************************************************************/ +/* States */ +State PASCAL_CODE = { "PASCAL_CODE", "pascal", semantic_code }; +State PASCAL_DQUOTE_STRING = { "PASCAL_DQUOTE_STRING", "pascal", semantic_code }; +State PASCAL_SQUOTE_STRING = { "PASCAL_SQUOTE_STRING", "pascal", semantic_code }; +State PASCAL_LINE_COMMENT = { "PASCAL_LINE_COMMENT", "pascal", semantic_comment }; +State PASCAL_BLOCK_COMMENT = { "PASCAL_BLOCK_COMMENT", "pascal", semantic_comment }; +State *PASCAL_STATES[] = { &PASCAL_CODE, &PASCAL_DQUOTE_STRING, &PASCAL_SQUOTE_STRING, &PASCAL_LINE_COMMENT, &PASCAL_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition PASCAL_CODE__LINE_COMMENT_0 = { "//", &PASCAL_CODE, &PASCAL_LINE_COMMENT, ToEatsToken, false }; +Transition PASCAL_LINE_COMMENT__RETURN = { "\n", &PASCAL_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition PASCAL_CODE__BLOCK_COMMENT_0 = { "{", &PASCAL_CODE, &PASCAL_BLOCK_COMMENT, ToEatsToken, false }; +Transition PASCAL_BLOCK_COMMENT__RETURN_0 = { "}", &PASCAL_BLOCK_COMMENT, RETURN, FromEatsToken, false }; +Transition PASCAL_CODE__DQUOTE_STRING = { "\"", &PASCAL_CODE, &PASCAL_DQUOTE_STRING, ToEatsToken, false }; +Transition PASCAL_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &PASCAL_DQUOTE_STRING, &PASCAL_DQUOTE_STRING, ToEatsToken, true }; +Transition PASCAL_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &PASCAL_DQUOTE_STRING, &PASCAL_DQUOTE_STRING, ToEatsToken, true }; +Transition PASCAL_DQUOTE_STRING__RETURN = { "\"", &PASCAL_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *PASCAL_TRANSITIONS[] = { &PASCAL_CODE__LINE_COMMENT_0, &PASCAL_LINE_COMMENT__RETURN, &PASCAL_CODE__BLOCK_COMMENT_0, &PASCAL_BLOCK_COMMENT__RETURN_0, &PASCAL_CODE__DQUOTE_STRING, &PASCAL_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &PASCAL_DQUOTE_STRING__DQUOTE_STRING_ESC, &PASCAL_DQUOTE_STRING__RETURN, NULL}; +Polyglot PASCAL_POLYGLOT = { + "pascal", + PASCAL_STATES, + PASCAL_TRANSITIONS, + NULL +}; + +/***************************************************************************** + perl +*****************************************************************************/ +/* States */ +State PERL_CODE = { "PERL_CODE", "perl", semantic_code }; +State PERL_DQUOTE_STRING = { "PERL_DQUOTE_STRING", "perl", semantic_code }; +State PERL_SQUOTE_STRING = { "PERL_SQUOTE_STRING", "perl", semantic_code }; +State PERL_LINE_COMMENT = { "PERL_LINE_COMMENT", "perl", semantic_comment }; +State PERL_BLOCK_COMMENT = { "PERL_BLOCK_COMMENT", "perl", semantic_comment }; +State *PERL_STATES[] = { &PERL_CODE, &PERL_DQUOTE_STRING, &PERL_SQUOTE_STRING, &PERL_LINE_COMMENT, &PERL_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition PERL_CODE__LINE_COMMENT_0 = { "#", &PERL_CODE, &PERL_LINE_COMMENT, ToEatsToken, false }; +Transition PERL_LINE_COMMENT__RETURN = { "\n", &PERL_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition PERL_CODE__SQUOTE_STRING = { "'", &PERL_CODE, &PERL_SQUOTE_STRING, ToEatsToken, false }; +Transition PERL_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &PERL_SQUOTE_STRING, &PERL_SQUOTE_STRING, FromEatsToken, true }; +Transition PERL_SQUOTE_STRING__SQUOTE_STRING_ESC = { "\\\\'", &PERL_SQUOTE_STRING, &PERL_SQUOTE_STRING, FromEatsToken, true }; +Transition PERL_SQUOTE_STRING__RETURN = { "'", &PERL_SQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition PERL_CODE__DQUOTE_STRING = { "\"", &PERL_CODE, &PERL_DQUOTE_STRING, ToEatsToken, false }; +Transition PERL_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &PERL_DQUOTE_STRING, &PERL_DQUOTE_STRING, ToEatsToken, true }; +Transition PERL_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &PERL_DQUOTE_STRING, &PERL_DQUOTE_STRING, ToEatsToken, true }; +Transition PERL_DQUOTE_STRING__RETURN = { "\"", &PERL_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *PERL_TRANSITIONS[] = { &PERL_CODE__LINE_COMMENT_0, &PERL_LINE_COMMENT__RETURN, &PERL_CODE__SQUOTE_STRING, &PERL_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH, &PERL_SQUOTE_STRING__SQUOTE_STRING_ESC, &PERL_SQUOTE_STRING__RETURN, &PERL_CODE__DQUOTE_STRING, &PERL_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &PERL_DQUOTE_STRING__DQUOTE_STRING_ESC, &PERL_DQUOTE_STRING__RETURN, NULL}; +Polyglot PERL_POLYGLOT = { + "perl", + PERL_STATES, + PERL_TRANSITIONS, + NULL +}; + +/***************************************************************************** + phplanguage +*****************************************************************************/ +/* States */ +State PHP_CODE = { "PHP_CODE", "php", semantic_code }; +State PHP_DQUOTE_STRING = { "PHP_DQUOTE_STRING", "php", semantic_code }; +State PHP_SQUOTE_STRING = { "PHP_SQUOTE_STRING", "php", semantic_code }; +State PHP_LINE_COMMENT = { "PHP_LINE_COMMENT", "php", semantic_comment }; +State PHP_BLOCK_COMMENT = { "PHP_BLOCK_COMMENT", "php", semantic_comment }; +State *PHPLANGUAGE_STATES[] = { &PHP_CODE, &PHP_DQUOTE_STRING, &PHP_SQUOTE_STRING, &PHP_LINE_COMMENT, &PHP_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition PHP_CODE__LINE_COMMENT_0 = { "//", &PHP_CODE, &PHP_LINE_COMMENT, ToEatsToken, false }; +Transition PHP_LINE_COMMENT__RETURN = { "\n", &PHP_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition PHP_CODE__BLOCK_COMMENT_0 = { "/\\*", &PHP_CODE, &PHP_BLOCK_COMMENT, ToEatsToken, false }; +Transition PHP_BLOCK_COMMENT__RETURN_0 = { "\\*/", &PHP_BLOCK_COMMENT, RETURN, FromEatsToken, false }; +Transition PHP_CODE__SQUOTE_STRING = { "'", &PHP_CODE, &PHP_SQUOTE_STRING, ToEatsToken, false }; +Transition PHP_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &PHP_SQUOTE_STRING, &PHP_SQUOTE_STRING, FromEatsToken, true }; +Transition PHP_SQUOTE_STRING__SQUOTE_STRING_ESC = { "\\\\'", &PHP_SQUOTE_STRING, &PHP_SQUOTE_STRING, FromEatsToken, true }; +Transition PHP_SQUOTE_STRING__RETURN = { "'", &PHP_SQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition PHP_CODE__DQUOTE_STRING = { "\"", &PHP_CODE, &PHP_DQUOTE_STRING, ToEatsToken, false }; +Transition PHP_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &PHP_DQUOTE_STRING, &PHP_DQUOTE_STRING, ToEatsToken, true }; +Transition PHP_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &PHP_DQUOTE_STRING, &PHP_DQUOTE_STRING, ToEatsToken, true }; +Transition PHP_DQUOTE_STRING__RETURN = { "\"", &PHP_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *PHPLANGUAGE_TRANSITIONS[] = { &PHP_CODE__LINE_COMMENT_0, &PHP_LINE_COMMENT__RETURN, &PHP_CODE__BLOCK_COMMENT_0, &PHP_BLOCK_COMMENT__RETURN_0, &PHP_CODE__SQUOTE_STRING, &PHP_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH, &PHP_SQUOTE_STRING__SQUOTE_STRING_ESC, &PHP_SQUOTE_STRING__RETURN, &PHP_CODE__DQUOTE_STRING, &PHP_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &PHP_DQUOTE_STRING__DQUOTE_STRING_ESC, &PHP_DQUOTE_STRING__RETURN, NULL}; +Polyglot PHPLANGUAGE_POLYGLOT = { + "phplanguage", + PHPLANGUAGE_STATES, + PHPLANGUAGE_TRANSITIONS, + NULL +}; + +/***************************************************************************** + python +*****************************************************************************/ +/* States */ +State PYTHON_CODE = { "PYTHON_CODE", "python", semantic_code }; +State PYTHON_MULTI_LINE_SQUOTE = { "PYTHON_MULTI_LINE_SQUOTE", "python", semantic_code }; +State PYTHON_MULTI_LINE_DQUOTE = { "PYTHON_MULTI_LINE_DQUOTE", "python", semantic_code }; +State PYTHON_RAW_DQUOTE = { "PYTHON_RAW_DQUOTE", "python", semantic_code }; +State PYTHON_SQUOTE = { "PYTHON_SQUOTE", "python", semantic_code }; +State PYTHON_DQUOTE = { "PYTHON_DQUOTE", "python", semantic_code }; +State PYTHON_LINE_COMMENT = { "PYTHON_LINE_COMMENT", "python", semantic_comment }; +State *PYTHON_STATES[] = { &PYTHON_CODE, &PYTHON_MULTI_LINE_SQUOTE, &PYTHON_MULTI_LINE_DQUOTE, &PYTHON_RAW_DQUOTE, &PYTHON_SQUOTE, &PYTHON_DQUOTE, &PYTHON_LINE_COMMENT, NULL }; +/* Transitions */ +Transition PYTHON_CODE__MULTI_LINE_SQUOTE = { "'''", &PYTHON_CODE, &PYTHON_MULTI_LINE_SQUOTE, FromEatsToken, false }; +Transition PYTHON_MULTI_LINE_SQUOTE__RETURN = { "'''", &PYTHON_MULTI_LINE_SQUOTE, RETURN, FromEatsToken, false }; +Transition PYTHON_CODE__MULTI_LINE_DQUOTE = { "\"\"\"", &PYTHON_CODE, &PYTHON_MULTI_LINE_DQUOTE, FromEatsToken, false }; +Transition PYTHON_MULTI_LINE_DQUOTE__RETURN = { "\"\"\"", &PYTHON_MULTI_LINE_DQUOTE, RETURN, FromEatsToken, false }; +Transition PYTHON_CODE__RAW_DQUOTE = { "r\"", &PYTHON_CODE, &PYTHON_RAW_DQUOTE, FromEatsToken, false }; +Transition PYTHON_RAW_DQUOTE__RETURN = { "\"", &PYTHON_RAW_DQUOTE, RETURN, FromEatsToken, false }; +Transition PYTHON_CODE__SQUOTE = { "'", &PYTHON_CODE, &PYTHON_SQUOTE, FromEatsToken, false }; +Transition PYTHON_SQUOTE__RETURN_ESC = { "\\\\'", &PYTHON_SQUOTE, RETURN, FromEatsToken, true }; +Transition PYTHON_SQUOTE__RETURN = { "'", &PYTHON_SQUOTE, RETURN, ToEatsToken, false }; +Transition PYTHON_CODE__DQUOTE = { "\"", &PYTHON_CODE, &PYTHON_DQUOTE, ToEatsToken, false }; +Transition PYTHON_DQUOTE__RETURN_ESC = { "\\\\\"", &PYTHON_DQUOTE, RETURN, FromEatsToken, true }; +Transition PYTHON_DQUOTE__RETURN = { "\"", &PYTHON_DQUOTE, RETURN, ToEatsToken, false }; +Transition PYTHON_CODE__LINE_COMMENT = { "#", &PYTHON_CODE, &PYTHON_LINE_COMMENT, ToEatsToken, false }; +Transition PYTHON_LINE_COMMENT__RETURN = { "\n", &PYTHON_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition *PYTHON_TRANSITIONS[] = { &PYTHON_CODE__MULTI_LINE_SQUOTE, &PYTHON_MULTI_LINE_SQUOTE__RETURN, &PYTHON_CODE__MULTI_LINE_DQUOTE, &PYTHON_MULTI_LINE_DQUOTE__RETURN, &PYTHON_CODE__RAW_DQUOTE, &PYTHON_RAW_DQUOTE__RETURN, &PYTHON_CODE__SQUOTE, &PYTHON_SQUOTE__RETURN_ESC, &PYTHON_SQUOTE__RETURN, &PYTHON_CODE__DQUOTE, &PYTHON_DQUOTE__RETURN_ESC, &PYTHON_DQUOTE__RETURN, &PYTHON_CODE__LINE_COMMENT, &PYTHON_LINE_COMMENT__RETURN, NULL}; +Polyglot PYTHON_POLYGLOT = { + "python", + PYTHON_STATES, + PYTHON_TRANSITIONS, + NULL +}; + +/***************************************************************************** + ruby +*****************************************************************************/ +/* States */ +State RUBY_CODE = { "RUBY_CODE", "ruby", semantic_code }; +State RUBY_DQUOTE_STRING = { "RUBY_DQUOTE_STRING", "ruby", semantic_code }; +State RUBY_SQUOTE_STRING = { "RUBY_SQUOTE_STRING", "ruby", semantic_code }; +State RUBY_LINE_COMMENT = { "RUBY_LINE_COMMENT", "ruby", semantic_comment }; +State RUBY_BLOCK_COMMENT = { "RUBY_BLOCK_COMMENT", "ruby", semantic_comment }; +State *RUBY_STATES[] = { &RUBY_CODE, &RUBY_DQUOTE_STRING, &RUBY_SQUOTE_STRING, &RUBY_LINE_COMMENT, &RUBY_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition RUBY_CODE__LINE_COMMENT_0 = { "#", &RUBY_CODE, &RUBY_LINE_COMMENT, ToEatsToken, false }; +Transition RUBY_LINE_COMMENT__RETURN = { "\n", &RUBY_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition RUBY_CODE__SQUOTE_STRING = { "'", &RUBY_CODE, &RUBY_SQUOTE_STRING, ToEatsToken, false }; +Transition RUBY_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &RUBY_SQUOTE_STRING, &RUBY_SQUOTE_STRING, FromEatsToken, true }; +Transition RUBY_SQUOTE_STRING__SQUOTE_STRING_ESC = { "\\\\'", &RUBY_SQUOTE_STRING, &RUBY_SQUOTE_STRING, FromEatsToken, true }; +Transition RUBY_SQUOTE_STRING__RETURN = { "'", &RUBY_SQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition RUBY_CODE__DQUOTE_STRING = { "\"", &RUBY_CODE, &RUBY_DQUOTE_STRING, ToEatsToken, false }; +Transition RUBY_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &RUBY_DQUOTE_STRING, &RUBY_DQUOTE_STRING, ToEatsToken, true }; +Transition RUBY_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &RUBY_DQUOTE_STRING, &RUBY_DQUOTE_STRING, ToEatsToken, true }; +Transition RUBY_DQUOTE_STRING__RETURN = { "\"", &RUBY_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *RUBY_TRANSITIONS[] = { &RUBY_CODE__LINE_COMMENT_0, &RUBY_LINE_COMMENT__RETURN, &RUBY_CODE__SQUOTE_STRING, &RUBY_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH, &RUBY_SQUOTE_STRING__SQUOTE_STRING_ESC, &RUBY_SQUOTE_STRING__RETURN, &RUBY_CODE__DQUOTE_STRING, &RUBY_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &RUBY_DQUOTE_STRING__DQUOTE_STRING_ESC, &RUBY_DQUOTE_STRING__RETURN, NULL}; +Polyglot RUBY_POLYGLOT = { + "ruby", + RUBY_STATES, + RUBY_TRANSITIONS, + NULL +}; + +/***************************************************************************** + rexx +*****************************************************************************/ +/* States */ +State REXX_CODE = { "REXX_CODE", "rexx", semantic_code }; +State REXX_DQUOTE_STRING = { "REXX_DQUOTE_STRING", "rexx", semantic_code }; +State REXX_SQUOTE_STRING = { "REXX_SQUOTE_STRING", "rexx", semantic_code }; +State REXX_LINE_COMMENT = { "REXX_LINE_COMMENT", "rexx", semantic_comment }; +State REXX_BLOCK_COMMENT = { "REXX_BLOCK_COMMENT", "rexx", semantic_comment }; +State *REXX_STATES[] = { &REXX_CODE, &REXX_DQUOTE_STRING, &REXX_SQUOTE_STRING, &REXX_LINE_COMMENT, &REXX_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition REXX_CODE__BLOCK_COMMENT_0 = { "/\\*", &REXX_CODE, &REXX_BLOCK_COMMENT, ToEatsToken, false }; +Transition REXX_BLOCK_COMMENT__RETURN_0 = { "\\*/", &REXX_BLOCK_COMMENT, RETURN, FromEatsToken, false }; +Transition REXX_CODE__SQUOTE_STRING = { "'", &REXX_CODE, &REXX_SQUOTE_STRING, ToEatsToken, false }; +Transition REXX_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &REXX_SQUOTE_STRING, &REXX_SQUOTE_STRING, FromEatsToken, true }; +Transition REXX_SQUOTE_STRING__SQUOTE_STRING_ESC = { "\\\\'", &REXX_SQUOTE_STRING, &REXX_SQUOTE_STRING, FromEatsToken, true }; +Transition REXX_SQUOTE_STRING__RETURN = { "'", &REXX_SQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition REXX_CODE__DQUOTE_STRING = { "\"", &REXX_CODE, &REXX_DQUOTE_STRING, ToEatsToken, false }; +Transition REXX_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &REXX_DQUOTE_STRING, &REXX_DQUOTE_STRING, ToEatsToken, true }; +Transition REXX_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &REXX_DQUOTE_STRING, &REXX_DQUOTE_STRING, ToEatsToken, true }; +Transition REXX_DQUOTE_STRING__RETURN = { "\"", &REXX_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *REXX_TRANSITIONS[] = { &REXX_CODE__BLOCK_COMMENT_0, &REXX_BLOCK_COMMENT__RETURN_0, &REXX_CODE__SQUOTE_STRING, &REXX_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH, &REXX_SQUOTE_STRING__SQUOTE_STRING_ESC, &REXX_SQUOTE_STRING__RETURN, &REXX_CODE__DQUOTE_STRING, &REXX_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &REXX_DQUOTE_STRING__DQUOTE_STRING_ESC, &REXX_DQUOTE_STRING__RETURN, NULL}; +Polyglot REXX_POLYGLOT = { + "rexx", + REXX_STATES, + REXX_TRANSITIONS, + NULL +}; + +/***************************************************************************** + scheme +*****************************************************************************/ +/* States */ +State SCHEME_CODE = { "SCHEME_CODE", "scheme", semantic_code }; +State SCHEME_COMMENT = { "SCHEME_COMMENT", "scheme", semantic_comment }; +State *SCHEME_STATES[] = { &SCHEME_CODE, &SCHEME_COMMENT, NULL }; +/* Transitions */ +Transition SCHEME_CODE__COMMENT_0 = { ";", &SCHEME_CODE, &SCHEME_COMMENT, ToEatsToken, false }; +Transition SCHEME_COMMENT__RETURN = { "\n", &SCHEME_COMMENT, RETURN, FromEatsToken, false }; +Transition *SCHEME_TRANSITIONS[] = { &SCHEME_CODE__COMMENT_0, &SCHEME_COMMENT__RETURN, NULL}; +Polyglot SCHEME_POLYGLOT = { + "scheme", + SCHEME_STATES, + SCHEME_TRANSITIONS, + NULL +}; + +/***************************************************************************** + shell +*****************************************************************************/ +/* States */ +State SHELL_CODE = { "SHELL_CODE", "shell", semantic_code }; +State SHELL_DQUOTE_STRING = { "SHELL_DQUOTE_STRING", "shell", semantic_code }; +State SHELL_SQUOTE_STRING = { "SHELL_SQUOTE_STRING", "shell", semantic_code }; +State SHELL_LINE_COMMENT = { "SHELL_LINE_COMMENT", "shell", semantic_comment }; +State SHELL_BLOCK_COMMENT = { "SHELL_BLOCK_COMMENT", "shell", semantic_comment }; +State *SHELL_STATES[] = { &SHELL_CODE, &SHELL_DQUOTE_STRING, &SHELL_SQUOTE_STRING, &SHELL_LINE_COMMENT, &SHELL_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition SHELL_CODE__LINE_COMMENT_0 = { "#", &SHELL_CODE, &SHELL_LINE_COMMENT, ToEatsToken, false }; +Transition SHELL_LINE_COMMENT__RETURN = { "\n", &SHELL_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition *SHELL_TRANSITIONS[] = { &SHELL_CODE__LINE_COMMENT_0, &SHELL_LINE_COMMENT__RETURN, NULL}; +Polyglot SHELL_POLYGLOT = { + "shell", + SHELL_STATES, + SHELL_TRANSITIONS, + NULL +}; + +/***************************************************************************** + sql +*****************************************************************************/ +/* States */ +State SQL_CODE = { "SQL_CODE", "sql", semantic_code }; +State SQL_DQUOTE_STRING = { "SQL_DQUOTE_STRING", "sql", semantic_code }; +State SQL_SQUOTE_STRING = { "SQL_SQUOTE_STRING", "sql", semantic_code }; +State SQL_LINE_COMMENT = { "SQL_LINE_COMMENT", "sql", semantic_comment }; +State SQL_BLOCK_COMMENT = { "SQL_BLOCK_COMMENT", "sql", semantic_comment }; +State *SQL_STATES[] = { &SQL_CODE, &SQL_DQUOTE_STRING, &SQL_SQUOTE_STRING, &SQL_LINE_COMMENT, &SQL_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition SQL_CODE__LINE_COMMENT_0 = { "--", &SQL_CODE, &SQL_LINE_COMMENT, ToEatsToken, false }; +Transition SQL_CODE__LINE_COMMENT_1 = { "//", &SQL_CODE, &SQL_LINE_COMMENT, ToEatsToken, false }; +Transition SQL_LINE_COMMENT__RETURN = { "\n", &SQL_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition SQL_CODE__BLOCK_COMMENT_0 = { "{", &SQL_CODE, &SQL_BLOCK_COMMENT, ToEatsToken, false }; +Transition SQL_BLOCK_COMMENT__RETURN_0 = { "}", &SQL_BLOCK_COMMENT, RETURN, FromEatsToken, false }; +Transition SQL_CODE__BLOCK_COMMENT_1 = { "/\\*", &SQL_CODE, &SQL_BLOCK_COMMENT, ToEatsToken, false }; +Transition SQL_BLOCK_COMMENT__RETURN_1 = { "\\*/", &SQL_BLOCK_COMMENT, RETURN, FromEatsToken, false }; +Transition SQL_CODE__SQUOTE_STRING = { "'", &SQL_CODE, &SQL_SQUOTE_STRING, ToEatsToken, false }; +Transition SQL_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &SQL_SQUOTE_STRING, &SQL_SQUOTE_STRING, FromEatsToken, true }; +Transition SQL_SQUOTE_STRING__SQUOTE_STRING_ESC = { "\\\\'", &SQL_SQUOTE_STRING, &SQL_SQUOTE_STRING, FromEatsToken, true }; +Transition SQL_SQUOTE_STRING__RETURN = { "'", &SQL_SQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition SQL_CODE__DQUOTE_STRING = { "\"", &SQL_CODE, &SQL_DQUOTE_STRING, ToEatsToken, false }; +Transition SQL_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &SQL_DQUOTE_STRING, &SQL_DQUOTE_STRING, ToEatsToken, true }; +Transition SQL_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &SQL_DQUOTE_STRING, &SQL_DQUOTE_STRING, ToEatsToken, true }; +Transition SQL_DQUOTE_STRING__RETURN = { "\"", &SQL_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *SQL_TRANSITIONS[] = { &SQL_CODE__LINE_COMMENT_0, &SQL_CODE__LINE_COMMENT_1, &SQL_LINE_COMMENT__RETURN, &SQL_CODE__BLOCK_COMMENT_0, &SQL_BLOCK_COMMENT__RETURN_0, &SQL_CODE__BLOCK_COMMENT_1, &SQL_BLOCK_COMMENT__RETURN_1, &SQL_CODE__SQUOTE_STRING, &SQL_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH, &SQL_SQUOTE_STRING__SQUOTE_STRING_ESC, &SQL_SQUOTE_STRING__RETURN, &SQL_CODE__DQUOTE_STRING, &SQL_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &SQL_DQUOTE_STRING__DQUOTE_STRING_ESC, &SQL_DQUOTE_STRING__RETURN, NULL}; +Polyglot SQL_POLYGLOT = { + "sql", + SQL_STATES, + SQL_TRANSITIONS, + NULL +}; + +/***************************************************************************** + tcl +*****************************************************************************/ +/* States */ +State TCL_CODE = { "TCL_CODE", "tcl", semantic_code }; +State TCL_DQUOTE_STRING = { "TCL_DQUOTE_STRING", "tcl", semantic_code }; +State TCL_SQUOTE_STRING = { "TCL_SQUOTE_STRING", "tcl", semantic_code }; +State TCL_LINE_COMMENT = { "TCL_LINE_COMMENT", "tcl", semantic_comment }; +State TCL_BLOCK_COMMENT = { "TCL_BLOCK_COMMENT", "tcl", semantic_comment }; +State *TCL_STATES[] = { &TCL_CODE, &TCL_DQUOTE_STRING, &TCL_SQUOTE_STRING, &TCL_LINE_COMMENT, &TCL_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition TCL_CODE__LINE_COMMENT_0 = { "#", &TCL_CODE, &TCL_LINE_COMMENT, ToEatsToken, false }; +Transition TCL_LINE_COMMENT__RETURN = { "\n", &TCL_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition TCL_CODE__DQUOTE_STRING = { "\"", &TCL_CODE, &TCL_DQUOTE_STRING, ToEatsToken, false }; +Transition TCL_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &TCL_DQUOTE_STRING, &TCL_DQUOTE_STRING, ToEatsToken, true }; +Transition TCL_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &TCL_DQUOTE_STRING, &TCL_DQUOTE_STRING, ToEatsToken, true }; +Transition TCL_DQUOTE_STRING__RETURN = { "\"", &TCL_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *TCL_TRANSITIONS[] = { &TCL_CODE__LINE_COMMENT_0, &TCL_LINE_COMMENT__RETURN, &TCL_CODE__DQUOTE_STRING, &TCL_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &TCL_DQUOTE_STRING__DQUOTE_STRING_ESC, &TCL_DQUOTE_STRING__RETURN, NULL}; +Polyglot TCL_POLYGLOT = { + "tcl", + TCL_STATES, + TCL_TRANSITIONS, + NULL +}; + +/***************************************************************************** + visualbasic +*****************************************************************************/ +/* States */ +State VISUALBASIC_CODE = { "VISUALBASIC_CODE", "visualbasic", semantic_code }; +State VISUALBASIC_DQUOTE_STRING = { "VISUALBASIC_DQUOTE_STRING", "visualbasic", semantic_code }; +State VISUALBASIC_SQUOTE_STRING = { "VISUALBASIC_SQUOTE_STRING", "visualbasic", semantic_code }; +State VISUALBASIC_LINE_COMMENT = { "VISUALBASIC_LINE_COMMENT", "visualbasic", semantic_comment }; +State VISUALBASIC_BLOCK_COMMENT = { "VISUALBASIC_BLOCK_COMMENT", "visualbasic", semantic_comment }; +State *VISUALBASIC_STATES[] = { &VISUALBASIC_CODE, &VISUALBASIC_DQUOTE_STRING, &VISUALBASIC_SQUOTE_STRING, &VISUALBASIC_LINE_COMMENT, &VISUALBASIC_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition VISUALBASIC_CODE__LINE_COMMENT_0 = { "'", &VISUALBASIC_CODE, &VISUALBASIC_LINE_COMMENT, ToEatsToken, false }; +Transition VISUALBASIC_LINE_COMMENT__RETURN = { "\n", &VISUALBASIC_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition VISUALBASIC_CODE__DQUOTE_STRING = { "\"", &VISUALBASIC_CODE, &VISUALBASIC_DQUOTE_STRING, ToEatsToken, false }; +Transition VISUALBASIC_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &VISUALBASIC_DQUOTE_STRING, &VISUALBASIC_DQUOTE_STRING, ToEatsToken, true }; +Transition VISUALBASIC_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &VISUALBASIC_DQUOTE_STRING, &VISUALBASIC_DQUOTE_STRING, ToEatsToken, true }; +Transition VISUALBASIC_DQUOTE_STRING__RETURN = { "\"", &VISUALBASIC_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *VISUALBASIC_TRANSITIONS[] = { &VISUALBASIC_CODE__LINE_COMMENT_0, &VISUALBASIC_LINE_COMMENT__RETURN, &VISUALBASIC_CODE__DQUOTE_STRING, &VISUALBASIC_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &VISUALBASIC_DQUOTE_STRING__DQUOTE_STRING_ESC, &VISUALBASIC_DQUOTE_STRING__RETURN, NULL}; +Polyglot VISUALBASIC_POLYGLOT = { + "visualbasic", + VISUALBASIC_STATES, + VISUALBASIC_TRANSITIONS, + NULL +}; + +/***************************************************************************** + xml +*****************************************************************************/ +/* States */ +State XML_MARKUP = { "XML_MARKUP", "xml", semantic_code }; +State XML_SQUOTE = { "XML_SQUOTE", "xml", semantic_code }; +State XML_DQUOTE = { "XML_DQUOTE", "xml", semantic_code }; +State XML_CDATA = { "XML_CDATA", "xml", semantic_code }; +State XML_COMMENT = { "XML_COMMENT", "xml", semantic_comment }; +State *XML_STATES[] = { &XML_MARKUP, &XML_SQUOTE, &XML_DQUOTE, &XML_CDATA, &XML_COMMENT, NULL }; +/* Transitions */ +Transition XML_MARKUP__SQUOTE = { "'", &XML_MARKUP, &XML_SQUOTE, FromEatsToken, false }; +Transition XML_SQUOTE__RETURN = { "'", &XML_SQUOTE, RETURN, ToEatsToken, false }; +Transition XML_MARKUP__DQUOTE = { "\"", &XML_MARKUP, &XML_DQUOTE, FromEatsToken, false }; +Transition XML_DQUOTE__RETURN = { "\"", &XML_DQUOTE, RETURN, ToEatsToken, false }; +Transition XML_MARKUP__CDATA = { "", &XML_CDATA, RETURN, ToEatsToken, false }; +Transition XML_MARKUP__COMMENT = { "", &XML_COMMENT, RETURN, FromEatsToken, false }; +Transition *XML_TRANSITIONS[] = { &XML_MARKUP__SQUOTE, &XML_SQUOTE__RETURN, &XML_MARKUP__DQUOTE, &XML_DQUOTE__RETURN, &XML_MARKUP__CDATA, &XML_CDATA__RETURN, &XML_MARKUP__COMMENT, &XML_COMMENT__RETURN, NULL}; +Polyglot XML_POLYGLOT = { + "xml", + XML_STATES, + XML_TRANSITIONS, + NULL +}; + +/***************************************************************************** + dmd +*****************************************************************************/ +/* States */ +State DMD_CODE = { "DMD_CODE", "dmd", semantic_code }; +State DMD_DQUOTE_STRING = { "DMD_DQUOTE_STRING", "dmd", semantic_code }; +State DMD_SQUOTE_STRING = { "DMD_SQUOTE_STRING", "dmd", semantic_code }; +State DMD_BACKTICK_STRING = { "DMD_BACKTICK_STRING", "dmd", semantic_code }; +State DMD_LINE_COMMENT = { "DMD_LINE_COMMENT", "dmd", semantic_comment }; +State DMD_BLOCK_COMMENT = { "DMD_BLOCK_COMMENT", "dmd", semantic_comment }; +State DMD_NESTED_COMMENT = { "DMD_NESTED_COMMENT", "dmd", semantic_comment }; +State *DMD_STATES[] = { &DMD_CODE, &DMD_DQUOTE_STRING, &DMD_SQUOTE_STRING, &DMD_BACKTICK_STRING, &DMD_LINE_COMMENT, &DMD_BLOCK_COMMENT, &DMD_NESTED_COMMENT, NULL }; +/* Transitions */ +Transition DMD_CODE__LINE_COMMENT = { "//", &DMD_CODE, &DMD_LINE_COMMENT, ToEatsToken, false }; +Transition DMD_LINE_COMMENT__RETURN = { "\n", &DMD_LINE_COMMENT, RETURN, FromEatsToken, false }; +Transition DMD_CODE__BLOCK_COMMENT = { "/\\*", &DMD_CODE, &DMD_BLOCK_COMMENT, ToEatsToken, false }; +Transition DMD_NESTED_COMMENT__BLOCK_COMMENT = { "/\\*", &DMD_NESTED_COMMENT, &DMD_BLOCK_COMMENT, ToEatsToken, false }; +Transition DMD_BLOCK_COMMENT__RETURN = { "\\*/", &DMD_BLOCK_COMMENT, RETURN, FromEatsToken, false }; +Transition DMD_CODE__NESTED_COMMENT = { "/\\+", &DMD_CODE, &DMD_NESTED_COMMENT, ToEatsToken, false }; +Transition DMD_NESTED_COMMENT__NESTED_COMMENT = { "/\\+", &DMD_NESTED_COMMENT, &DMD_NESTED_COMMENT, ToEatsToken, false }; +Transition DMD_NESTED_COMMENT__RETURN = { "\\+/", &DMD_NESTED_COMMENT, RETURN, FromEatsToken, false }; +Transition DMD_CODE__SQUOTE_STRING = { "'", &DMD_CODE, &DMD_SQUOTE_STRING, ToEatsToken, false }; +Transition DMD_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &DMD_SQUOTE_STRING, &DMD_SQUOTE_STRING, FromEatsToken, true }; +Transition DMD_SQUOTE_STRING__SQUOTE_STRING_ESC = { "\\\\'", &DMD_SQUOTE_STRING, &DMD_SQUOTE_STRING, FromEatsToken, true }; +Transition DMD_SQUOTE_STRING__RETURN = { "'", &DMD_SQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition DMD_CODE__BACKTICK_STRING = { "`", &DMD_CODE, &DMD_BACKTICK_STRING, ToEatsToken, false }; +Transition DMD_BACKTICK_STRING__BACKTICK_STRING_ESC_SLASH = { "\\\\\\\\", &DMD_BACKTICK_STRING, &DMD_BACKTICK_STRING, FromEatsToken, true }; +Transition DMD_BACKTICK_STRING__BACKTICK_STRING_ESC = { "\\\\`", &DMD_BACKTICK_STRING, &DMD_BACKTICK_STRING, FromEatsToken, true }; +Transition DMD_BACKTICK_STRING__RETURN = { "`", &DMD_BACKTICK_STRING, RETURN, FromEatsToken, false }; +Transition DMD_CODE__DQUOTE_STRING = { "\"", &DMD_CODE, &DMD_DQUOTE_STRING, ToEatsToken, false }; +Transition DMD_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH = { "\\\\\\\\", &DMD_DQUOTE_STRING, &DMD_DQUOTE_STRING, ToEatsToken, true }; +Transition DMD_DQUOTE_STRING__DQUOTE_STRING_ESC = { "\\\\\"", &DMD_DQUOTE_STRING, &DMD_DQUOTE_STRING, ToEatsToken, true }; +Transition DMD_DQUOTE_STRING__RETURN = { "\"", &DMD_DQUOTE_STRING, RETURN, FromEatsToken, false }; +Transition *DMD_TRANSITIONS[] = { &DMD_CODE__LINE_COMMENT, &DMD_LINE_COMMENT__RETURN, &DMD_CODE__BLOCK_COMMENT, &DMD_NESTED_COMMENT__BLOCK_COMMENT, &DMD_BLOCK_COMMENT__RETURN, &DMD_CODE__NESTED_COMMENT, &DMD_NESTED_COMMENT__NESTED_COMMENT, &DMD_NESTED_COMMENT__RETURN, &DMD_CODE__SQUOTE_STRING, &DMD_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH, &DMD_SQUOTE_STRING__SQUOTE_STRING_ESC, &DMD_SQUOTE_STRING__RETURN, &DMD_CODE__BACKTICK_STRING, &DMD_BACKTICK_STRING__BACKTICK_STRING_ESC_SLASH, &DMD_BACKTICK_STRING__BACKTICK_STRING_ESC, &DMD_BACKTICK_STRING__RETURN, &DMD_CODE__DQUOTE_STRING, &DMD_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &DMD_DQUOTE_STRING__DQUOTE_STRING_ESC, &DMD_DQUOTE_STRING__RETURN, NULL}; +Polyglot DMD_POLYGLOT = { + "dmd", + DMD_STATES, + DMD_TRANSITIONS, + NULL +}; + +/***************************************************************************** + html +*****************************************************************************/ +/* States */ +State HTML_MARKUP = { "HTML_MARKUP", "html", semantic_code }; +State HTML_SQUOTE = { "HTML_SQUOTE", "html", semantic_code }; +State HTML_DQUOTE = { "HTML_DQUOTE", "html", semantic_code }; +State HTML_CDATA = { "HTML_CDATA", "html", semantic_code }; +State HTML_COMMENT = { "HTML_COMMENT", "html", semantic_comment }; +State *HTML_STATES[] = { &HTML_MARKUP, &HTML_SQUOTE, &HTML_DQUOTE, &HTML_CDATA, &HTML_COMMENT, &JAVASCRIPT_CODE, &JAVASCRIPT_DQUOTE_STRING, &JAVASCRIPT_SQUOTE_STRING, &JAVASCRIPT_LINE_COMMENT, &JAVASCRIPT_BLOCK_COMMENT, &CSS_CODE, &CSS_DQUOTE_STRING, &CSS_SQUOTE_STRING, &CSS_LINE_COMMENT, &CSS_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition HTML_MARKUP__SQUOTE = { "'", &HTML_MARKUP, &HTML_SQUOTE, FromEatsToken, false }; +Transition HTML_SQUOTE__RETURN = { "'", &HTML_SQUOTE, RETURN, ToEatsToken, false }; +Transition HTML_MARKUP__DQUOTE = { "\"", &HTML_MARKUP, &HTML_DQUOTE, FromEatsToken, false }; +Transition HTML_DQUOTE__RETURN = { "\"", &HTML_DQUOTE, RETURN, ToEatsToken, false }; +Transition HTML_MARKUP__CDATA = { "", &HTML_CDATA, RETURN, ToEatsToken, false }; +Transition HTML_MARKUP__COMMENT = { "", &HTML_COMMENT, RETURN, FromEatsToken, false }; +Transition HTML_HTML_MARKUP__CSS_CODE = { "<(?i)style(?-i)[^>]*(?i)css(?-i)[^>]*>", &HTML_MARKUP, &CSS_CODE, FromEatsToken, false }; +Transition HTML_CSS_CODE__RETURN = { "", &CSS_CODE, RETURN, ToEatsToken, false }; +Transition HTML_HTML_MARKUP__JAVASCRIPT_CODE = { "<(?i)script(?-i)\\ [^>]*(?i)javascript(?-i)[^>]*>", &HTML_MARKUP, &JAVASCRIPT_CODE, FromEatsToken, false }; +Transition HTML_JAVASCRIPT_CODE__RETURN = { "", &JAVASCRIPT_CODE, RETURN, ToEatsToken, false }; +Transition *HTML_TRANSITIONS[] = { &HTML_MARKUP__SQUOTE, &HTML_SQUOTE__RETURN, &HTML_MARKUP__DQUOTE, &HTML_DQUOTE__RETURN, &HTML_MARKUP__CDATA, &HTML_CDATA__RETURN, &HTML_MARKUP__COMMENT, &HTML_COMMENT__RETURN, &HTML_HTML_MARKUP__CSS_CODE, &HTML_CSS_CODE__RETURN, &HTML_HTML_MARKUP__JAVASCRIPT_CODE, &HTML_JAVASCRIPT_CODE__RETURN, &JAVASCRIPT_CODE__LINE_COMMENT_0, &JAVASCRIPT_LINE_COMMENT__RETURN, &JAVASCRIPT_CODE__BLOCK_COMMENT_0, &JAVASCRIPT_BLOCK_COMMENT__RETURN_0, &JAVASCRIPT_CODE__SQUOTE_STRING, &JAVASCRIPT_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH, &JAVASCRIPT_SQUOTE_STRING__SQUOTE_STRING_ESC, &JAVASCRIPT_SQUOTE_STRING__RETURN, &JAVASCRIPT_CODE__DQUOTE_STRING, &JAVASCRIPT_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &JAVASCRIPT_DQUOTE_STRING__DQUOTE_STRING_ESC, &JAVASCRIPT_DQUOTE_STRING__RETURN, &CSS_CODE__BLOCK_COMMENT_0, &CSS_BLOCK_COMMENT__RETURN_0, NULL}; +Polyglot HTML_POLYGLOT = { + "html", + HTML_STATES, + HTML_TRANSITIONS, + NULL +}; + +/***************************************************************************** + php +*****************************************************************************/ +/* States */ +State *PHP_STATES[] = { &HTML_MARKUP, &HTML_SQUOTE, &HTML_DQUOTE, &HTML_CDATA, &HTML_COMMENT, &JAVASCRIPT_CODE, &JAVASCRIPT_DQUOTE_STRING, &JAVASCRIPT_SQUOTE_STRING, &JAVASCRIPT_LINE_COMMENT, &JAVASCRIPT_BLOCK_COMMENT, &CSS_CODE, &CSS_DQUOTE_STRING, &CSS_SQUOTE_STRING, &CSS_LINE_COMMENT, &CSS_BLOCK_COMMENT, &PHP_CODE, &PHP_DQUOTE_STRING, &PHP_SQUOTE_STRING, &PHP_LINE_COMMENT, &PHP_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition PHP_HTML_MARKUP__PHP_CODE = { "<\\?", &HTML_MARKUP, &PHP_CODE, ToEatsToken, false }; +Transition PHP_HTML_COMMENT__PHP_CODE = { "<\\?", &HTML_COMMENT, &PHP_CODE, ToEatsToken, false }; +Transition PHP_HTML_SQUOTE__PHP_CODE = { "<\\?", &HTML_SQUOTE, &PHP_CODE, ToEatsToken, false }; +Transition PHP_HTML_DQUOTE__PHP_CODE = { "<\\?", &HTML_DQUOTE, &PHP_CODE, ToEatsToken, false }; +Transition PHP_PHP_CODE__RETURN = { "\\?>", &PHP_CODE, RETURN, FromEatsToken, false }; +Transition *PHP_TRANSITIONS[] = { &PHP_HTML_MARKUP__PHP_CODE, &PHP_HTML_COMMENT__PHP_CODE, &PHP_HTML_SQUOTE__PHP_CODE, &PHP_HTML_DQUOTE__PHP_CODE, &PHP_PHP_CODE__RETURN, &HTML_MARKUP__SQUOTE, &HTML_SQUOTE__RETURN, &HTML_MARKUP__DQUOTE, &HTML_DQUOTE__RETURN, &HTML_MARKUP__CDATA, &HTML_CDATA__RETURN, &HTML_MARKUP__COMMENT, &HTML_COMMENT__RETURN, &HTML_HTML_MARKUP__CSS_CODE, &HTML_CSS_CODE__RETURN, &HTML_HTML_MARKUP__JAVASCRIPT_CODE, &HTML_JAVASCRIPT_CODE__RETURN, &JAVASCRIPT_CODE__LINE_COMMENT_0, &JAVASCRIPT_LINE_COMMENT__RETURN, &JAVASCRIPT_CODE__BLOCK_COMMENT_0, &JAVASCRIPT_BLOCK_COMMENT__RETURN_0, &JAVASCRIPT_CODE__SQUOTE_STRING, &JAVASCRIPT_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH, &JAVASCRIPT_SQUOTE_STRING__SQUOTE_STRING_ESC, &JAVASCRIPT_SQUOTE_STRING__RETURN, &JAVASCRIPT_CODE__DQUOTE_STRING, &JAVASCRIPT_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &JAVASCRIPT_DQUOTE_STRING__DQUOTE_STRING_ESC, &JAVASCRIPT_DQUOTE_STRING__RETURN, &CSS_CODE__BLOCK_COMMENT_0, &CSS_BLOCK_COMMENT__RETURN_0, &PHP_CODE__LINE_COMMENT_0, &PHP_LINE_COMMENT__RETURN, &PHP_CODE__BLOCK_COMMENT_0, &PHP_BLOCK_COMMENT__RETURN_0, &PHP_CODE__SQUOTE_STRING, &PHP_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH, &PHP_SQUOTE_STRING__SQUOTE_STRING_ESC, &PHP_SQUOTE_STRING__RETURN, &PHP_CODE__DQUOTE_STRING, &PHP_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &PHP_DQUOTE_STRING__DQUOTE_STRING_ESC, &PHP_DQUOTE_STRING__RETURN, NULL}; +Polyglot PHP_POLYGLOT = { + "php", + PHP_STATES, + PHP_TRANSITIONS, + NULL +}; + +/***************************************************************************** + rhtml +*****************************************************************************/ +/* States */ +State *RHTML_STATES[] = { &HTML_MARKUP, &HTML_SQUOTE, &HTML_DQUOTE, &HTML_CDATA, &HTML_COMMENT, &JAVASCRIPT_CODE, &JAVASCRIPT_DQUOTE_STRING, &JAVASCRIPT_SQUOTE_STRING, &JAVASCRIPT_LINE_COMMENT, &JAVASCRIPT_BLOCK_COMMENT, &CSS_CODE, &CSS_DQUOTE_STRING, &CSS_SQUOTE_STRING, &CSS_LINE_COMMENT, &CSS_BLOCK_COMMENT, &RUBY_CODE, &RUBY_DQUOTE_STRING, &RUBY_SQUOTE_STRING, &RUBY_LINE_COMMENT, &RUBY_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition RHTML_HTML_MARKUP__RUBY_CODE = { "<%", &HTML_MARKUP, &RUBY_CODE, FromEatsToken, false }; +Transition RHTML_HTML_COMMENT__RUBY_CODE = { "<%", &HTML_COMMENT, &RUBY_CODE, FromEatsToken, false }; +Transition RHTML_HTML_SQUOTE__RUBY_CODE = { "<%", &HTML_SQUOTE, &RUBY_CODE, FromEatsToken, false }; +Transition RHTML_HTML_DQUOTE__RUBY_CODE = { "<%", &HTML_DQUOTE, &RUBY_CODE, FromEatsToken, false }; +Transition RHTML_RUBY_CODE__RETURN = { "%>", &RUBY_CODE, RETURN, ToEatsToken, false }; +Transition *RHTML_TRANSITIONS[] = { &RHTML_HTML_MARKUP__RUBY_CODE, &RHTML_HTML_COMMENT__RUBY_CODE, &RHTML_HTML_SQUOTE__RUBY_CODE, &RHTML_HTML_DQUOTE__RUBY_CODE, &RHTML_RUBY_CODE__RETURN, &HTML_MARKUP__SQUOTE, &HTML_SQUOTE__RETURN, &HTML_MARKUP__DQUOTE, &HTML_DQUOTE__RETURN, &HTML_MARKUP__CDATA, &HTML_CDATA__RETURN, &HTML_MARKUP__COMMENT, &HTML_COMMENT__RETURN, &HTML_HTML_MARKUP__CSS_CODE, &HTML_CSS_CODE__RETURN, &HTML_HTML_MARKUP__JAVASCRIPT_CODE, &HTML_JAVASCRIPT_CODE__RETURN, &JAVASCRIPT_CODE__LINE_COMMENT_0, &JAVASCRIPT_LINE_COMMENT__RETURN, &JAVASCRIPT_CODE__BLOCK_COMMENT_0, &JAVASCRIPT_BLOCK_COMMENT__RETURN_0, &JAVASCRIPT_CODE__SQUOTE_STRING, &JAVASCRIPT_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH, &JAVASCRIPT_SQUOTE_STRING__SQUOTE_STRING_ESC, &JAVASCRIPT_SQUOTE_STRING__RETURN, &JAVASCRIPT_CODE__DQUOTE_STRING, &JAVASCRIPT_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &JAVASCRIPT_DQUOTE_STRING__DQUOTE_STRING_ESC, &JAVASCRIPT_DQUOTE_STRING__RETURN, &CSS_CODE__BLOCK_COMMENT_0, &CSS_BLOCK_COMMENT__RETURN_0, &RUBY_CODE__LINE_COMMENT_0, &RUBY_LINE_COMMENT__RETURN, &RUBY_CODE__SQUOTE_STRING, &RUBY_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH, &RUBY_SQUOTE_STRING__SQUOTE_STRING_ESC, &RUBY_SQUOTE_STRING__RETURN, &RUBY_CODE__DQUOTE_STRING, &RUBY_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &RUBY_DQUOTE_STRING__DQUOTE_STRING_ESC, &RUBY_DQUOTE_STRING__RETURN, NULL}; +Polyglot RHTML_POLYGLOT = { + "rhtml", + RHTML_STATES, + RHTML_TRANSITIONS, + NULL +}; + +/***************************************************************************** + jsp +*****************************************************************************/ +/* States */ +State *JSP_STATES[] = { &HTML_MARKUP, &HTML_SQUOTE, &HTML_DQUOTE, &HTML_CDATA, &HTML_COMMENT, &JAVASCRIPT_CODE, &JAVASCRIPT_DQUOTE_STRING, &JAVASCRIPT_SQUOTE_STRING, &JAVASCRIPT_LINE_COMMENT, &JAVASCRIPT_BLOCK_COMMENT, &CSS_CODE, &CSS_DQUOTE_STRING, &CSS_SQUOTE_STRING, &CSS_LINE_COMMENT, &CSS_BLOCK_COMMENT, &JAVA_CODE, &JAVA_DQUOTE_STRING, &JAVA_SQUOTE_STRING, &JAVA_LINE_COMMENT, &JAVA_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition JSP_HTML_MARKUP__JAVA_CODE = { "<%", &HTML_MARKUP, &JAVA_CODE, FromEatsToken, false }; +Transition JSP_HTML_COMMENT__JAVA_CODE = { "<%", &HTML_COMMENT, &JAVA_CODE, FromEatsToken, false }; +Transition JSP_HTML_SQUOTE__JAVA_CODE = { "<%", &HTML_SQUOTE, &JAVA_CODE, FromEatsToken, false }; +Transition JSP_HTML_DQUOTE__JAVA_CODE = { "<%", &HTML_DQUOTE, &JAVA_CODE, FromEatsToken, false }; +Transition JSP_JAVA_CODE__RETURN = { "%>", &JAVA_CODE, RETURN, ToEatsToken, false }; +Transition *JSP_TRANSITIONS[] = { &JSP_HTML_MARKUP__JAVA_CODE, &JSP_HTML_COMMENT__JAVA_CODE, &JSP_HTML_SQUOTE__JAVA_CODE, &JSP_HTML_DQUOTE__JAVA_CODE, &JSP_JAVA_CODE__RETURN, &HTML_MARKUP__SQUOTE, &HTML_SQUOTE__RETURN, &HTML_MARKUP__DQUOTE, &HTML_DQUOTE__RETURN, &HTML_MARKUP__CDATA, &HTML_CDATA__RETURN, &HTML_MARKUP__COMMENT, &HTML_COMMENT__RETURN, &HTML_HTML_MARKUP__CSS_CODE, &HTML_CSS_CODE__RETURN, &HTML_HTML_MARKUP__JAVASCRIPT_CODE, &HTML_JAVASCRIPT_CODE__RETURN, &JAVASCRIPT_CODE__LINE_COMMENT_0, &JAVASCRIPT_LINE_COMMENT__RETURN, &JAVASCRIPT_CODE__BLOCK_COMMENT_0, &JAVASCRIPT_BLOCK_COMMENT__RETURN_0, &JAVASCRIPT_CODE__SQUOTE_STRING, &JAVASCRIPT_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH, &JAVASCRIPT_SQUOTE_STRING__SQUOTE_STRING_ESC, &JAVASCRIPT_SQUOTE_STRING__RETURN, &JAVASCRIPT_CODE__DQUOTE_STRING, &JAVASCRIPT_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &JAVASCRIPT_DQUOTE_STRING__DQUOTE_STRING_ESC, &JAVASCRIPT_DQUOTE_STRING__RETURN, &CSS_CODE__BLOCK_COMMENT_0, &CSS_BLOCK_COMMENT__RETURN_0, &JAVA_CODE__LINE_COMMENT_0, &JAVA_LINE_COMMENT__RETURN, &JAVA_CODE__BLOCK_COMMENT_0, &JAVA_BLOCK_COMMENT__RETURN_0, &JAVA_CODE__DQUOTE_STRING, &JAVA_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &JAVA_DQUOTE_STRING__DQUOTE_STRING_ESC, &JAVA_DQUOTE_STRING__RETURN, NULL}; +Polyglot JSP_POLYGLOT = { + "jsp", + JSP_STATES, + JSP_TRANSITIONS, + NULL +}; + +/***************************************************************************** + clearsilver_template +*****************************************************************************/ +/* States */ +State *CLEARSILVER_TEMPLATE_STATES[] = { &HTML_MARKUP, &HTML_SQUOTE, &HTML_DQUOTE, &HTML_CDATA, &HTML_COMMENT, &JAVASCRIPT_CODE, &JAVASCRIPT_DQUOTE_STRING, &JAVASCRIPT_SQUOTE_STRING, &JAVASCRIPT_LINE_COMMENT, &JAVASCRIPT_BLOCK_COMMENT, &CSS_CODE, &CSS_DQUOTE_STRING, &CSS_SQUOTE_STRING, &CSS_LINE_COMMENT, &CSS_BLOCK_COMMENT, &CLEARSILVER_CODE, &CLEARSILVER_DQUOTE_STRING, &CLEARSILVER_SQUOTE_STRING, &CLEARSILVER_LINE_COMMENT, &CLEARSILVER_BLOCK_COMMENT, NULL }; +/* Transitions */ +Transition CLEARSILVER_TEMPLATE_HTML_MARKUP__CLEARSILVER_CODE = { "<\\?cs", &HTML_MARKUP, &CLEARSILVER_CODE, FromEatsToken, false }; +Transition CLEARSILVER_TEMPLATE_HTML_COMMENT__CLEARSILVER_CODE = { "<\\?cs", &HTML_COMMENT, &CLEARSILVER_CODE, FromEatsToken, false }; +Transition CLEARSILVER_TEMPLATE_HTML_SQUOTE__CLEARSILVER_CODE = { "<\\?cs", &HTML_SQUOTE, &CLEARSILVER_CODE, FromEatsToken, false }; +Transition CLEARSILVER_TEMPLATE_HTML_DQUOTE__CLEARSILVER_CODE = { "<\\?cs", &HTML_DQUOTE, &CLEARSILVER_CODE, FromEatsToken, false }; +Transition CLEARSILVER_TEMPLATE_CLEARSILVER_CODE__RETURN = { "\\?>", &CLEARSILVER_CODE, RETURN, ToEatsToken, false }; +Transition *CLEARSILVER_TEMPLATE_TRANSITIONS[] = { &CLEARSILVER_TEMPLATE_HTML_MARKUP__CLEARSILVER_CODE, &CLEARSILVER_TEMPLATE_HTML_COMMENT__CLEARSILVER_CODE, &CLEARSILVER_TEMPLATE_HTML_SQUOTE__CLEARSILVER_CODE, &CLEARSILVER_TEMPLATE_HTML_DQUOTE__CLEARSILVER_CODE, &CLEARSILVER_TEMPLATE_CLEARSILVER_CODE__RETURN, &HTML_MARKUP__SQUOTE, &HTML_SQUOTE__RETURN, &HTML_MARKUP__DQUOTE, &HTML_DQUOTE__RETURN, &HTML_MARKUP__CDATA, &HTML_CDATA__RETURN, &HTML_MARKUP__COMMENT, &HTML_COMMENT__RETURN, &HTML_HTML_MARKUP__CSS_CODE, &HTML_CSS_CODE__RETURN, &HTML_HTML_MARKUP__JAVASCRIPT_CODE, &HTML_JAVASCRIPT_CODE__RETURN, &JAVASCRIPT_CODE__LINE_COMMENT_0, &JAVASCRIPT_LINE_COMMENT__RETURN, &JAVASCRIPT_CODE__BLOCK_COMMENT_0, &JAVASCRIPT_BLOCK_COMMENT__RETURN_0, &JAVASCRIPT_CODE__SQUOTE_STRING, &JAVASCRIPT_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH, &JAVASCRIPT_SQUOTE_STRING__SQUOTE_STRING_ESC, &JAVASCRIPT_SQUOTE_STRING__RETURN, &JAVASCRIPT_CODE__DQUOTE_STRING, &JAVASCRIPT_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &JAVASCRIPT_DQUOTE_STRING__DQUOTE_STRING_ESC, &JAVASCRIPT_DQUOTE_STRING__RETURN, &CSS_CODE__BLOCK_COMMENT_0, &CSS_BLOCK_COMMENT__RETURN_0, &CLEARSILVER_CODE__LINE_COMMENT_0, &CLEARSILVER_LINE_COMMENT__RETURN, &CLEARSILVER_CODE__SQUOTE_STRING, &CLEARSILVER_SQUOTE_STRING__SQUOTE_STRING_ESC_SLASH, &CLEARSILVER_SQUOTE_STRING__SQUOTE_STRING_ESC, &CLEARSILVER_SQUOTE_STRING__RETURN, &CLEARSILVER_CODE__DQUOTE_STRING, &CLEARSILVER_DQUOTE_STRING__DQUOTE_STRING_ESC_SLASH, &CLEARSILVER_DQUOTE_STRING__DQUOTE_STRING_ESC, &CLEARSILVER_DQUOTE_STRING__RETURN, NULL}; +Polyglot CLEARSILVER_TEMPLATE_POLYGLOT = { + "clearsilver_template", + CLEARSILVER_TEMPLATE_STATES, + CLEARSILVER_TEMPLATE_TRANSITIONS, + NULL +}; + + +/***************************************************************************** + POLYGLOTS +*****************************************************************************/ +Polyglot *POLYGLOTS[] = { + &ADA_POLYGLOT, + &ASSEMBLER_POLYGLOT, + &AWK_POLYGLOT, + &BAT_POLYGLOT, + &BOO_POLYGLOT, + &CLEARSILVER_POLYGLOT, + &CNCPP_POLYGLOT, + &CSHARP_POLYGLOT, + &CSS_POLYGLOT, + &DYLAN_POLYGLOT, + &ERLANG_POLYGLOT, + &GROOVY_POLYGLOT, + &JAVA_POLYGLOT, + &JAVASCRIPT_POLYGLOT, + &EMACSLISP_POLYGLOT, + &LISP_POLYGLOT, + &LUA_POLYGLOT, + &MATLAB_POLYGLOT, + &OBJECTIVE_C_POLYGLOT, + &PASCAL_POLYGLOT, + &PERL_POLYGLOT, + &PHPLANGUAGE_POLYGLOT, + &PYTHON_POLYGLOT, + &RUBY_POLYGLOT, + &REXX_POLYGLOT, + &SCHEME_POLYGLOT, + &SHELL_POLYGLOT, + &SQL_POLYGLOT, + &TCL_POLYGLOT, + &VISUALBASIC_POLYGLOT, + &XML_POLYGLOT, + &DMD_POLYGLOT, + &HTML_POLYGLOT, + &PHP_POLYGLOT, + &RHTML_POLYGLOT, + &JSP_POLYGLOT, + &CLEARSILVER_TEMPLATE_POLYGLOT, + NULL +}; diff --git a/ext/ohcount_native/polyglots.h b/ext/ohcount_native/polyglots.h new file mode 100644 index 0000000..27abb5d --- /dev/null +++ b/ext/ohcount_native/polyglots.h @@ -0,0 +1,14 @@ +/* + * polyglots.h + * Ohcount + * + * Created by Jason Allen on 6/23/06. + * Copyright 2006 Ohloh. All rights reserved. + * + */ + +#ifndef __polyglots_c__ + +extern Polyglot *POLYGLOTS[]; + +#endif diff --git a/ext/ohcount_native/ruby_binding.c b/ext/ohcount_native/ruby_binding.c new file mode 100644 index 0000000..aa51bbb --- /dev/null +++ b/ext/ohcount_native/ruby_binding.c @@ -0,0 +1,167 @@ +#include "ruby.h" +#include "common.h" + +static VALUE rb_module_ohcount; +static VALUE rb_class_language_breakdown; + + +/***************************************************************************** + LanguageBreakdown +*****************************************************************************/ + +static void _language_breakdown_free(LanguageBreakdown *language_breakdown) { + language_breakdown_free(language_breakdown); + free(language_breakdown); +} + +static VALUE _language_breakdown_allocate(VALUE klass) { + int _my_language_id; + int _my_buffer_size; + _my_language_id = 0; + _my_buffer_size = 100; + LanguageBreakdown *language_breakdown = (LanguageBreakdown *) malloc(sizeof(LanguageBreakdown)); + language_breakdown_initialize(language_breakdown, "", _my_buffer_size); + + /* bs initializers */ + strcpy(language_breakdown->name, ""); + strcpy(language_breakdown->code, ""); + strcpy(language_breakdown->comment, ""); + return Data_Wrap_Struct(klass, 0, _language_breakdown_free, language_breakdown); +} + +static VALUE _language_breakdown_initialize(VALUE self, VALUE name, VALUE code, VALUE comment, VALUE blanks) { + /* validation */ + Check_Type(name, T_STRING); + Check_Type(code, T_STRING); + Check_Type(comment, T_STRING); + Check_Type(blanks, T_FIXNUM); + + LanguageBreakdown *lb; + Data_Get_Struct (self, LanguageBreakdown, lb); + + /* name */ + strncpy(lb->name, rb_string_value_ptr(&name), MAX_LANGUAGE_NAME); + + /* code */ + if (lb->code != NULL) { + free(lb->code); + } + lb->code = (char*)malloc(RSTRING(code)->len); + strcpy(lb->code, rb_string_value_ptr(&code)); + + /* comment */ + if (lb->comment != NULL) { + free(lb->comment); + } + lb->comment = (char*)malloc(RSTRING(comment)->len); + strcpy(lb->comment, rb_string_value_ptr(&comment)); + + /* blanks */ + lb->blank_count = NUM2INT(blanks); + + return self; +} + +static VALUE _language_breakdown_name(VALUE self) { + LanguageBreakdown *lb; + Data_Get_Struct (self, LanguageBreakdown, lb); + return rb_str_new2(lb->name); +} + +static VALUE _language_breakdown_code(VALUE self) { + LanguageBreakdown *lb; + Data_Get_Struct (self, LanguageBreakdown, lb); + return rb_str_new2(lb->code); +} + +static VALUE _language_breakdown_comment(VALUE self) { + LanguageBreakdown *lb; + Data_Get_Struct (self, LanguageBreakdown, lb); + return rb_str_new2(lb->comment); +} + +static VALUE _language_breakdown_blanks(VALUE self) { + LanguageBreakdown *lb; + Data_Get_Struct (self, LanguageBreakdown, lb); + return INT2NUM(lb->blank_count); +} + + +/***************************************************************************** + Ohcount (Module) +*****************************************************************************/ +static VALUE _ohcount_parse(VALUE self, VALUE buffer, VALUE polyglot_name_value) { + + // find the polyglot to parse with + char *polyglot_name = RSTRING(polyglot_name_value)->ptr; + int i_polyglot; + for (i_polyglot = 0; POLYGLOTS[i_polyglot] != NULL; i_polyglot++) { + if (strcmp(POLYGLOTS[i_polyglot]->name, polyglot_name) == 0) { + Polyglot *polyglot = POLYGLOTS[i_polyglot]; + + ParseResult pr; + parser_parse(&pr, RSTRING(buffer)->ptr, RSTRING(buffer)->len, polyglot); + + // create array we'll return all the language_breakdowns in + VALUE ary = rb_ary_new2(pr.language_breakdown_count); + + int i_pr; + for(i_pr = 0; i_pr < pr.language_breakdown_count; i_pr++) { + LanguageBreakdown *lb = (LanguageBreakdown *) malloc(sizeof(LanguageBreakdown)); + LanguageBreakdown *src_lb = &(pr.language_breakdowns[i_pr]); + strcpy(lb->name,src_lb->name); + lb->code = src_lb->code; + lb->comment = src_lb->comment; + lb->blank_count = src_lb->blank_count; + rb_ary_store(ary, i_pr, Data_Wrap_Struct(rb_class_language_breakdown, 0, _language_breakdown_free, lb)); + } + + return ary; + } + } + rb_raise(rb_eStandardError,"Polyglot name invalid"); + return Qnil; +} + + +static VALUE _ohcount_polyglots(VALUE self) { + + // how many are they? + int poly_count = 0; + Polyglot **p = POLYGLOTS; + while ((*p++) != NULL) { + poly_count++; + } + + // create the array + VALUE ary = rb_ary_new2(poly_count); + + // fill it in + int i_poly; + for (i_poly = 0; POLYGLOTS[i_poly] != NULL; i_poly++) { + VALUE poly_name = rb_str_new2(POLYGLOTS[i_poly]->name); + rb_ary_store(ary, i_poly, poly_name); + } + + return ary; +} + + +/***************************************************************************** + Initialize Ruby +*****************************************************************************/ +void Init_ohcount_native () { + rb_module_ohcount = rb_define_module("Ohcount"); + rb_define_module_function(rb_module_ohcount, "parse", _ohcount_parse, 2); + rb_define_module_function(rb_module_ohcount, "polyglots", _ohcount_polyglots, 0); + + // define language_breakdown + rb_class_language_breakdown = rb_define_class_under( rb_module_ohcount, "LanguageBreakdown", rb_cObject); + rb_define_alloc_func (rb_class_language_breakdown, _language_breakdown_allocate); + rb_define_method (rb_class_language_breakdown, "initialize", _language_breakdown_initialize, 4); + rb_define_method (rb_class_language_breakdown, "name", _language_breakdown_name, 0); + rb_define_method (rb_class_language_breakdown, "code", _language_breakdown_code, 0); + rb_define_method (rb_class_language_breakdown, "comment", _language_breakdown_comment, 0); + rb_define_method (rb_class_language_breakdown, "blanks", _language_breakdown_blanks, 0); +} + diff --git a/ext/ohcount_native/state.c b/ext/ohcount_native/state.c new file mode 100644 index 0000000..8bfe15d --- /dev/null +++ b/ext/ohcount_native/state.c @@ -0,0 +1,42 @@ +/* + * state.c + * Ohcount + * + * Created by Jason Allen on 6/22/06. + * Copyright 2006 Ohloh. All rights reserved. + * + */ +#include "common.h" + +/* + void state_initialize(State *state, char *name, enum Semantic semantic) { + state->name = name; + state->semantic = semantic; +} +*/ +/* + * test suite + * + * performs an overall test suite on State. + * + */ +void state_test(void) { + printf("passed state_test.\n"); +} + +bool state_trumps_language(State *the_state, State *other_state) { + if (the_state == NULL || + the_state->semantic == semantic_blank || + the_state->semantic == semantic_null || + other_state == NULL) { + return false; + } + // simple algorithm... html gets trumped by everything + bool trumped = (strcmp(other_state->language, "html") == 0 && strcmp(the_state->language, "html") != 0); +#ifndef NDEBUG + if (trumped) { + log2("[ohcount] - state %s trumped by %s\n", other_state->name, the_state->name); + } +#endif + return trumped; +} diff --git a/ext/ohcount_native/state.h b/ext/ohcount_native/state.h new file mode 100644 index 0000000..88466ef --- /dev/null +++ b/ext/ohcount_native/state.h @@ -0,0 +1,33 @@ +/* + * state.h + * Ohcount + * + * Created by Jason Allen on 6/22/06. + * Copyright 2006 Ohloh. All rights reserved. + * + */ + +#ifndef __state_h__ +#define __state_h__ + +// required +#include "transition.h" + +enum Semantic { + semantic_code, + semantic_comment, + semantic_blank, + semantic_null +}; + +typedef struct { + char *name; + char *language; + enum Semantic semantic; +} State; + +bool state_trumps_language(State *the_state, State *other_state); +void state_test(void); + + +#endif diff --git a/ext/ohcount_native/state.rb b/ext/ohcount_native/state.rb new file mode 100644 index 0000000..5cfbf0d --- /dev/null +++ b/ext/ohcount_native/state.rb @@ -0,0 +1,36 @@ +module Ohcount + # The source code parser is implemented as a state machine. + # + # Each state is associated with a particular language and semantic (:code, :comment, or :blank). + class State + # The state name -- any helpful mnemonic, but must be unique within this language. + attr_reader :name + + # When in this state, we are considered to be reading this language. + attr_reader :language + + # One of :code, :comment, or :blank. + attr_reader :semantic + + def initialize(language, name, semantic) + raise ArgumentError.new("unknown semantic '#{ semantic }'") unless [:code, :comment, :blank].include?(semantic) + + @language = language + @name = name.to_s.downcase + @semantic = semantic + end + + def full_name + "#{ language }_#{ name.to_s }".upcase + end + + def definition + full_name.upcase + end + + # Emit the state definition as C statements into the generated file. + def print(io) + io.puts %(State #{ definition } = { "#{ full_name }", "#{ @language }", semantic_#{ semantic.to_s } };) + end + end +end diff --git a/ext/ohcount_native/transition.h b/ext/ohcount_native/transition.h new file mode 100644 index 0000000..68d1741 --- /dev/null +++ b/ext/ohcount_native/transition.h @@ -0,0 +1,39 @@ +/* + * transition.h + * Ohcount + * + * Created by Jason Allen on 6/22/06. + * Copyright 2006 Ohloh. All rights reserved. + * + */ + +#ifndef __transition_h__ +#define __transition_h__ + +#include "state.h" + +enum TokenEater { + FromEatsToken, + ToEatsToken, + NeitherEatsToken +}; + +// structs +typedef struct { + + // the regular expression that triggers this transision + char *regex; + + // the states this transition maps + State *from_state; + State *to_state; + + // which state should get the matched token attributed to it? + enum TokenEater token_eater; + + // true if this transition should be ignored -- useful to preempt other matches + bool fake_transition; + +} Transition; + +#endif diff --git a/ext/ohcount_native/transition.rb b/ext/ohcount_native/transition.rb new file mode 100644 index 0000000..8e44320 --- /dev/null +++ b/ext/ohcount_native/transition.rb @@ -0,0 +1,107 @@ +module Ohcount + # Defines a transition between one parser State and another. + # + # A state transition is triggered when a regular expression or "token" match + # is found in the source code. + # + # The Transition class handles transitions between states in a single language. To + # define transitions between two different languages, use the StitchTransition class. + class Transition + # This transition defines state changes within this language only. + attr_reader :language + + # A regular expression which triggers the state transition when it is matched. + attr_reader :token + + # This transition can only be followed when we are in the 'from' state. + attr_reader :from + + # The state we will transition to when the token is matched. + attr_reader :to + + # One of :from, :to, or :neither. + # + # This determines which state 'owns' the text of the token. + # + # For instance, a double-quote character in the source code might trigger + # a transition from a code state to a string state. + # The who_eats value dictates whether the double-quote character itself + # should be considered part of the code or part of the string. + attr_reader :who_eats + + # Set to true if this transition should be ignored -- that is, continue + # on without changing state, and do not notify any listeners that a state + # transition occured. + # + # Why would we ever want this? + # One example use is handling escaped string chars in the CMonoglot. + # When we are in the string state, we want to ignore all escaped double-quotes (\") + # since these should not return us to the code state. We do this by swallowing the + # entire \" token with a fake transition and remaining in the string state. + # Without this fake transition, the \ would be considered an ordinary part of the + # string and the " would incorrectly return us to the code state. + attr_reader :fake + + # Each transition needs a unique name. The default name is generated + # by combining the language name with the names of the 'from' state and the 'to' state. + # In the case that this is not unique, you may provide an additional string here + # that will be appended to the generated name. + attr_reader :name_extension + + def initialize(language, token, from, to, who_eats, fake, name_extension = "") + @language = language + @token = token + @from = from.to_s + @to = to + @who_eats = who_eats + @fake = fake + @name_extension = name_extension.to_s.upcase + end + + def definition + "#{ language.upcase }_#{ from.to_s.upcase }__#{ to.to_s.upcase }#{ name_extension == "" ? "" : "_" + name_extension }".upcase + end + + def token_eater + case @who_eats + when :from + 'FromEatsToken' + when :to + 'ToEatsToken' + when :neither + 'NeitherEatsToken' + else + raise 'UnknownWhoEats' + end + end + + # Emit the transition as a C code definition in the generated source file. + def print(io) + full_from = from == :return ? "RETURN" : "&#{ language }_#{ from }".upcase + full_to = to == :return ? "RETURN" : "&#{ language }_#{ to }".upcase + io.puts %(Transition #{ definition } = { "#{ token }", #{ full_from }, #{ full_to }, #{ self.token_eater }, #{ fake } };) + end + end + + # Represents a transition from a state in one Monoglot to a state in another Monoglot. + class StitchTransition < Transition + def initialize(token, from, to, who_eats, fake, polyglot_name) + @token = token + @from = from.to_s + @to = to + @who_eats = who_eats + @fake = fake + @polyglot_name = polyglot_name + end + + def definition + "#{ @polyglot_name.upcase }_#{ @from.to_s.upcase }__#{ @to.to_s.upcase }" + end + + def print(io) + full_from = @from == :return ? "RETURN" : "&#{ @from }".upcase + full_to = @to == :return ? "RETURN" : "&#{ @to }".upcase + io.puts %(Transition #{ definition } = { "#{ @token }", #{ full_from }, #{ full_to }, #{ self.token_eater }, #{ @fake } };) + end + end +end diff --git a/lib/ohcount.rb b/lib/ohcount.rb new file mode 100644 index 0000000..e9fb716 --- /dev/null +++ b/lib/ohcount.rb @@ -0,0 +1,18 @@ +module Ohcount +end + +require 'rbconfig' + +begin + require 'ohcount_native' +rescue LoadError + require "#{Config::CONFIG['arch']}/ohcount_native" +end + +require "ohcount/detector" +require "ohcount/parser" +require "ohcount/language_breakdown" +require "ohcount/sloc_info" +require "ohcount/scratch_dir" +require "ohcount/diff" +require "ohcount/simple_file_context" diff --git a/lib/ohcount/detector.rb b/lib/ohcount/detector.rb new file mode 100644 index 0000000..72d5f6d --- /dev/null +++ b/lib/ohcount/detector.rb @@ -0,0 +1,259 @@ +# Determines the language family (Monoglot or Polyglot) used by a source file. +class Ohcount::Detector + + module ContainsM + # A performance hack -- once we've checked for the presence of *.m files, the result + # is stored here to avoid checking twice. + attr_accessor :contains_m + end + + # The primary entry point for the detector. + # Given a file context containing the file name, content, and an array of + # other filenames in the source tree, attempts to detect which + # language family (Monoglot or Polyglot) is in use for this file. + # + # Returns nil if the language is not recognized or if the file does not + # contain any code. + def self.detect(file_context) + # start with extension + polyglot = EXTENSION_MAP[File.extname(file_context.filename).downcase] + case polyglot + when String + # simplest case + return polyglot if polyglot.is_a?(String) + when Symbol + # extension is ambiguous - requires custom disambiguation + self.send(polyglot, file_context) + when NilClass + return disambiguate_nil(file_context) + else + raise RuntimeError.new("Unknown file detection type") + end + end + + # Based solely on the filename, makes a judgment whether a file is a binary format. + def self.binary_filename?(filename) + ignore = [ + ".svn", + ".jar", + ".tar", + ".gz", + ".tgz", + ".zip", + ".gif", + ".jpg", + ".jpeg", + ".bmp", + ".png", + ".tif", + ".tiff", + ".ogg", + ".aiff", + ".wav", + ".mp3", + ".au", + ".ra", + ".m4a", + ".pdf", + ".mpg", + ".mov", + ".qt", + ".avi" + ] + ignore.include?(File.extname(filename)) + end + + EXTENSION_MAP = { + '.ada' => "ada", + '.adb' => "ada", + '.asm' => "assembler", + '.awk' => "awk", + '.bas' => "visualbasic", + '.bat' => "bat", + '.boo' => "boo", + '.c' => "cncpp", + '.cc' => "cncpp", + '.cpp' => "cncpp", + '.css' => "css", + '.c++' => "cncpp", + '.cxx' => "cncpp", + '.el' => "emacslisp", + # '.cbl' => "cobol", + # '.cob' => "cobol", + '.cs' => :disambiguate_cs, + '.dylan'=> "dylan", + '.erl' => "erlang", + '.frx' => "visualbasic", + '.groovy'=> "groovy", + '.h' => :disambiguate_h_header, + '.hpp' => "cncpp", + '.hh' => "cncpp", + '.hrl' => "erlang", + '.htm' => "html", + '.html' => "html", + '.inc' => :disambiguate_inc, + '.java' => "java", + '.js' => "javascript", + '.jsp' => "jsp", + '.lua' => "lua", + '.lsp' => "lisp", + '.lisp' => "lisp", + '.m' => :matlab_or_objective_c, + '.mm' => "objective_c", + '.pas' => "pascal", + '.pp' => "pascal", + '.php' => "php", + '.php3' => "php", + '.php4' => "php", + '.php5' => "php", + '.pl' => "perl", + '.pm' => "perl", + '.perl' => "perl", + '.ph' => "perl", + '.py' => "python", + '.rhtml'=> "rhtml", + '.rb' => "ruby", + '.rex' => "rexx", + '.rexx' => "rexx", + '.s' => "assembler", + '.S' => "assembler", + '.sc' => "scheme", + '.scm' => "scheme", + '.sh' => "shell", + '.sql' => "sql", + '.tcl' => "tcl", + '.tpl' => "html", + '.vb' => "visualbasic", + '.vba' => "visualbasic", + '.vbs' => "visualbasic", + '.xml' => "xml", + '.d' => 'dmd', + '.di' => 'dmd' + } + + protected + + # Returns a count of lines in the buffer matching the given regular expression. + def self.lines_matching(buffer, re) + buffer.inject(0) { |total, line| line =~ re ? total+1 : total } + end + + # For *.m files, differentiates Matlab from Objective-C. + # + # This is done with a weighted heuristic that + # scans the *.m file contents for keywords, + # and also checks for the presence of matching *.h files. + def self.matlab_or_objective_c(file_context) + buffer = file_context.contents + + # if there are .h files in same directory, this probably isn't matlab + h_headers = 0.0 + h_headers = -0.5 if file_context.filenames.select { |a| a =~ /\.h$/ }.any? + + # if the contents contain 'function (' on a single line - very likely to be matlab + # if the contents contain lines starting with '%', its probably matlab comments + matlab_signatures = /(^\s*function\s*)|(^\s*%)/ + matlab_sig_score = 0.1 * lines_matching(buffer, matlab_signatures) + + # if the contents contains '//' or '/*', likely objective_c + objective_c_signatures = /(^\s*\/\/\s*)|(^\s*\/\*)|(^[+-])/ + obj_c_sig_score = -0.1 * lines_matching(buffer, objective_c_signatures) + + matlab = h_headers + matlab_sig_score + obj_c_sig_score + + matlab > 0 ? 'matlab' : 'objective_c' + end + + # For *.h files, differentiates C/C++ from Objective-C. + # + # This is done with a weighted heuristic that + # scans the *.h file contents for Objective-C keywords, + # and also checks for the presence of matching *.m files. + def self.disambiguate_h_header(file_context) + buffer = file_context.contents + + objective_c = 0 + + # could it be realistically be objective_c ? are there any .m files at all? + # Speed hack - remember our findings in case we get the same filenames over and over + unless defined?(file_context.filenames.contains_m) + file_context.filenames.extend(ContainsM) + file_context.filenames.contains_m = file_context.filenames.select { |a| a =~ /\.m$/ }.any? + end + return 'cncpp' unless file_context.filenames.contains_m + + # if the dir contains a matching *.m file, likely objective_c + if file_context.filename =~ /\.h$/ + m_counterpart = file_context.filename.gsub(/\.h$/, ".m") + return 'objective_c' if file_context.filenames.include?(m_counterpart) + end + + # ok - it just might be objective_c, let's check contents for objective_c signatures + objective_c_signatures = /(^\s*@interface)|(^\s*@end)/ + objective_c += lines_matching(buffer, objective_c_signatures) + + return objective_c > 1 ? 'objective_c' : 'cncpp' + end + + # Tests whether the provided buffer contains binary or text content. + # This is not fool-proof -- we basically just check for zero values + # in the early bytes of the buffer. If we find a zero, we know it + # is not (ascii) text. + def self.binary_buffer?(buffer) + 100.times do |i| + return true if buffer[i] == 0 + end + false + end + + # True if the provided buffer includes a '?php' directive + def self.php_instruction?(buffer) + buffer =~ /\?php/ + end + + # For *.inc files, checks for a PHP class. + def self.disambiguate_inc(file_context) + buffer = file_context.contents + return nil if binary_buffer?(buffer) + return 'php' if php_instruction?(buffer) + nil + end + + # For files with extention *.cs, differentiates C# from Clearsilver. + def self.disambiguate_cs(file_context) + buffer = file_context.contents + return 'clearsilver_template' if lines_matching(file_context.contents, /\<\?cs/) > 0 + return 'csharp' + end + + # Attempts to determine the Polyglot for files that do not have a + # filename extension. + # + # Relies on the bash +file+ command line tool as its primary method. + # + # There must be a file at file_context.file_location for +file+ + # to operate on. + # + def self.disambiguate_nil(file_context) + file_location = file_context.file_location + output = `file -b #{ file_location }` + case output + when /([\w\/]+) script text/, /script text executable for ([\w\/]+)/ + script = $1 + if script =~ /\/(\w*)$/ + script = $1 + end + known_languages = EXTENSION_MAP.values + return script.downcase if known_languages.include?(script.downcase) + when /([\w\-]*) shell script text/ + case $1 + when "Bourne-Again" + return "shell" + end + end + + # dang... no dice + nil + end + +end diff --git a/lib/ohcount/diff.rb b/lib/ohcount/diff.rb new file mode 100644 index 0000000..3880cb8 --- /dev/null +++ b/lib/ohcount/diff.rb @@ -0,0 +1,112 @@ +module Ohcount + + def self.diff_files(old_filename, new_filename) + langs = {} + ScratchDir.new do |old_dir| + ScratchDir.new do |new_dir| + old_buffer = File.new(old_filename).read + old_polyglot = Ohcount::Detector.detect(SimpleFileContext.new(old_filename)) + Ohcount::Parser.parse_to_dir(:dir => old_dir, + :buffer => old_buffer, + :polyglot => old_polyglot) + new_buffer = File.new(new_filename).read + new_polyglot = Ohcount::Detector.detect(SimpleFileContext.new(new_filename)) + Ohcount::Parser.parse_to_dir(:dir => new_dir, + :buffer => new_buffer, + :polyglot => new_polyglot) + langs = diff_sloc_dirs(old_dir, new_dir) + end + end + langs + end + + def self.blank_diffs(new_file, old_file) + # blanks are stored as a simple string + old_blanks = new_blanks = 0 + if old_file != "/dev/null" && FileTest.file?(old_file) + File.open(old_file) do |io| + old_blanks = io.read.to_i + end + end + if new_file != "/dev/null" && FileTest.file?(new_file) + File.open(new_file) do |io| + new_blanks = io.read.to_i + end + end + blanks_changed = new_blanks - old_blanks + blanks_added = blanks_changed > 0 ? blanks_changed : 0 + blanks_removed = blanks_changed < 0 ? -blanks_changed : 0 + [blanks_added, blanks_removed] + end + + + def self.get_langs(dir) + return {} if dir.nil? + langs = {} + Dir.foreach(dir) do |l| + next if [".", ".."].include?(l) + langs[l] ||= {} + Dir.foreach(dir + "/" + l) do |s| + next if [".", ".."].include?(s) + langs[l][s] = nil + end + end + langs + end + + def self.diff_sloc_dirs(old_dir, new_dir) + # figure out the superset of all languages and semantics we're dealing with (on old and new) + langs = {} + langs.merge!(get_langs(old_dir)) + langs.merge!(get_langs(new_dir)) + + # now go through each and tally up the added/removed + sloc_infos = [] + langs.each do |lang, semantics| + next if lang == "_file" # this is a special case... + sloc_info = SlocInfo.new(lang) + + semantics.each_key do |s| + old_file = old_dir ? File.join(old_dir, lang, s) : '/dev/null' + new_file = new_dir ? File.join(new_dir, lang, s) : '/dev/null' + if s == 'blanks' + sloc_info.blanks_added, sloc_info.blanks_removed = blank_diffs(new_file, old_file) + else + added_removed = diff_file(old_file, new_file) + case s + when 'code' + sloc_info.code_added, sloc_info.code_removed = added_removed + when 'comment' + sloc_info.comments_added, sloc_info.comments_removed = added_removed + else + raise RuntimeError.new("unknown semantic: #{ s }") + end + end + end + sloc_infos << sloc_info unless sloc_info.empty? + end + + # sort them -- nice thing to do + sloc_infos.sort do |a,b| + a.language <=> b.language + end + end + + def self.diff_file(old, new) + added = removed = 0 + + if FileTest.file?(old) == false + # original file doesn't exist -> return all new lines as added + added = `cat '#{ new }' | wc -l`.strip.to_i + elsif FileTest.file?(new) == false + # new file doesn't exist -> return all old lines as deleted + removed = `cat '#{ old }' | wc -l`.strip.to_i + else + cmd = "diff -d --normal --suppress-common-lines --new-file '#{old}' '#{new}' | grep '^>' | wc -l" + added = `#{cmd}`.to_i + cmd = "diff -d --normal --suppress-common-lines --new-file '#{old}' '#{new}' | grep '^<' | wc -l" + removed = `#{cmd}`.to_i + end + [added, removed] + end +end diff --git a/lib/ohcount/language_breakdown.rb b/lib/ohcount/language_breakdown.rb new file mode 100644 index 0000000..5ae3312 --- /dev/null +++ b/lib/ohcount/language_breakdown.rb @@ -0,0 +1,15 @@ +class Ohcount::LanguageBreakdown + + def ==(other) + return self.name == other.name && self.code == other.code && self.comment == other.comment && self.blanks == other.blanks + end + + def abbr(s, len=80) + s.size > len ? s[0..(len-3)] + "..." : s + end + + def inspect + return "<[#{ self.name }]-code(#{ abbr(self.code).gsub("\n", "\\n") })/comment(#{ abbr(self.comment) })/blanks:#{ self.blanks }>" + end + +end diff --git a/lib/ohcount/parser.rb b/lib/ohcount/parser.rb new file mode 100644 index 0000000..bc172da --- /dev/null +++ b/lib/ohcount/parser.rb @@ -0,0 +1,48 @@ +class Ohcount::Parser + # Parses a file, and store the results in files on disk. + # + # This method primarily exists for the benefit of the Ohloh analysis engine, + # which prefers to store interim results in files on disk. It is unlikely to be + # useful to the general public. + # + # A subdirectory is created for each language found in the target file. + # Within each language subdirectory, separate files are created for code, comments, and blanks. + # + # The 'code' file contains code lines, the 'comments' file contains comment lines, and the 'blanks' + # file contains a count of the number of blank lines in the file. + def self.parse_to_dir(args) + arg_keys = [ + :dir, # directory to parse to + :buffer, # buffer contents of the what we're parsing + :polyglot # the polyglot name of what we're parsing + ] + raise ArgumentError.new('Missing required args') unless (arg_keys - args.keys).empty? + + polyglot = args[:polyglot].to_s + dir = args[:dir] + buffer = args[:buffer].to_s + + language_breakdowns = Ohcount::parse(buffer, polyglot) + language_breakdowns.each do |lb| + lb_dest_dir = dir + "/" + lb.name + Dir.mkdir(lb_dest_dir) + if (lb.code) + File.open(lb_dest_dir + "/code", "w") do |io| + code = lb.code + io.write code + io.write "\n" unless (code.size == 0 || code[-1,1] == "\n") + end + end + if (lb.comment) + File.open(lb_dest_dir + "/comment", "w") do |io| + comment = lb.comment + io.write comment + io.write "\n" unless (comment.size == 0 || comment[-1,1] == "\n") + end + end + File.open(lb_dest_dir + "/blanks", "w") do |io| + io.write lb.blanks.to_s + end + end + end +end diff --git a/lib/ohcount/scratch_dir.rb b/lib/ohcount/scratch_dir.rb new file mode 100644 index 0000000..26daab7 --- /dev/null +++ b/lib/ohcount/scratch_dir.rb @@ -0,0 +1,50 @@ +require 'fileutils' +require 'tmpdir' + +# A utility class to manage the creation and automatic cleanup of temporary directories. +class ScratchDir + attr_reader :path + + # Creates a uniquely named directory in the system tmp directory. + # + # If a block is passed to the constructor, the path to the created directory + # will be yielded to the block. The directory will then be deleted + # when this block returns. + # + # Sample usage: + # + # ScratchDir.new do |path| + # # Do some work in the new directory + # File.new( path + '/foobaz', 'w' ) do + # # ... + # end + # end # Scratch directory is deleted here + # + def initialize + until @path + @path = File.join(Dir.tmpdir, Time.now.utc.strftime("ohloh_%Y%H%m%S#{rand(900) + 100}")) + begin + Dir.mkdir(@path) + rescue Errno::EEXIST + @path = nil + end + end + if block_given? + yield @path + FileUtils.rm_rf(@path) + end + end +end + +if $0 == __FILE__ + path = nil + ScratchDir.new do |d| + path = d + STDOUT.puts "Created scratch direcory #{d}" + File.open(File.join(d, "test"), "w") do |io| + io.write "test" + end + end + raise RuntimeError.new("Directory wasn't cleaned up") if FileTest.directory?(path) + STDOUT.puts "Test passed." +end diff --git a/lib/ohcount/simple_file_context.rb b/lib/ohcount/simple_file_context.rb new file mode 100644 index 0000000..73774a5 --- /dev/null +++ b/lib/ohcount/simple_file_context.rb @@ -0,0 +1,68 @@ +module Ohcount + + # The context provides an abstraction layer between ohcount and the + # file being analyzed. + # + # SimpleFileContext provides ohcount with the target filename and a means + # to access the contents of the file. + # + # In simple usage scenarios, the SimpleFileContext can simply point to an actual + # file on disk. In more complex scenarios, the context allows the + # file contents to be delivered to ohcount from a temp file or + # in-memory cache. + # + class SimpleFileContext + # The original name of the file to be analyzed. + # This name will be used when detecting the language. + attr_reader :filename + + # An array of names of other files in the source tree which + # may be helpful when disambiguating the language used by the target file. + # For instance, the presence of an Objective-C *.m file is a clue when + # determining the language used in a *.h header file. + # This array is optional, but language identification may be less accurate + # without it. + attr_reader :filenames + + # The location on disk where the file content can currently be found. + # This might not be the same as the original name of the file. + # For example, file content might be stored in temporary directory. + attr_reader :file_location + + # At a minimum, you must provide the filename. + # + # You may also optionally pass an array of names of other files in the source tree. + # This will assist when disambiguating the language used by the source file. + # If you do not include this array, language identification may be less accurate. + # + # The SimpleFileContext must provide access to the file content. You can do this + # by one of three means, which will be probed in the following order: + # + # 1. You may optionally pass the content of the source file as string +cached_contents+. + # + # 2. You may optionally provide +file_location+ as the name of a file on disk + # which contains the content of this source file. + # + # 3. If you do neither 1 nor 2, then +filename+ will be assumed to be an actual file on + # disk which can be read. + # + def initialize(filename, filenames = [], cached_contents = nil, file_location = nil) + @filename = filename + @filenames = filenames + @cached_contents = cached_contents + @file_location = file_location || filename + end + + # Returns the entire content of the target file as a single string. + def contents + return @cached_contents if @cached_contents + if @file_location + File.open(file_location) do |f| + @cached_contents = f.read + end + end + return @cached_contents + end + end + +end diff --git a/lib/ohcount/sloc_info.rb b/lib/ohcount/sloc_info.rb new file mode 100644 index 0000000..8cb8610 --- /dev/null +++ b/lib/ohcount/sloc_info.rb @@ -0,0 +1,80 @@ +# a DTO class to hold the sloc information +class Ohcount::SlocInfo + attr_reader :language + attr_accessor :code_added, :code_removed, :comments_added, :comments_removed, :blanks_added, :blanks_removed + + def initialize(language) + raise ArgumentError.new('language can not be nil') unless language + @language = language + @code_added = 0 + @code_removed = 0 + @comments_added = 0 + @comments_removed = 0 + @blanks_added = 0 + @blanks_removed = 0 + end + + def ==(b) + @language == b.language && + @code_added == b.code_added && + @code_removed == b.code_removed && + @comments_added == b.comments_added && + @comments_removed == b.comments_removed && + @blanks_added == b.blanks_added && + @blanks_removed == b.blanks_removed + end + + def empty? + if (@code_added == 0 && @code_removed == 0 && + @comments_added == 0 && @comments_removed == 0 && + @blanks_added == 0 && @blanks_removed == 0) + return true + end + return false + end + + @@lang_map = { + 'ada' => {:nice_name => 'Ada' , :category => 0}, + 'assembler' => {:nice_name => 'Assembler' , :category => 0}, + 'awk' => {:nice_name => 'AWK' , :category => 0}, + 'bat' => {:nice_name => 'DOS batch script' , :category => 0}, + 'boo' => {:nice_name => 'Boo' , :category => 0}, + 'cncpp' => {:nice_name => 'C/C++' , :category => 0}, + 'clearsilver' => {:nice_name => 'ClearSilver' , :category => 0}, + 'csharp' => {:nice_name => 'C#' , :category => 0}, + 'css' => {:nice_name => 'CSS' , :category => 1}, + 'dylan' => {:nice_name => 'Dylan' , :category => 0}, + 'emacslisp' => {:nice_name => 'Emacs Lisp' , :category => 0}, + 'erlang' => {:nice_name => 'Erlang' , :category => 0}, + 'groovy' => {:nice_name => 'Groovy' , :category => 0}, + 'html' => {:nice_name => 'HTML' , :category => 1}, + 'java' => {:nice_name => 'Java' , :category => 0}, + 'javascript' => {:nice_name => 'JavaScript' , :category => 0}, + 'lisp' => {:nice_name => 'Lisp' , :category => 0}, + 'lua' => {:nice_name => 'Lua' , :category => 0}, + 'matlab' => {:nice_name => 'Matlab' , :category => 0}, + 'objective_c' => {:nice_name => 'Objective C' , :category => 0}, + 'pascal' => {:nice_name => 'Pascal' , :category => 0}, + 'perl' => {:nice_name => 'Perl' , :category => 0}, + 'php' => {:nice_name => 'PHP' , :category => 0}, + 'python' => {:nice_name => 'Python' , :category => 0}, + 'rexx' => {:nice_name => 'rexx' , :category => 0}, + 'ruby' => {:nice_name => 'Ruby' , :category => 0}, + 'scheme' => {:nice_name => 'Scheme' , :category => 0}, + 'shell' => {:nice_name => 'shell script' , :category => 0}, + 'sql' => {:nice_name => 'SQL' , :category => 0}, + 'tcl' => {:nice_name => 'Tcl' , :category => 0}, + 'visualbasic' => {:nice_name => 'Visual Basic' , :category => 0}, + 'xml' => {:nice_name => 'XML' , :category => 1}, + 'dmd' => {:nice_name => 'D' , :category => 0} + } + + def language_nice_name + @@lang_map[self.language][:nice_name] + end + + def language_category + @@lang_map[self.language][:category] + end + +end diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000..bdb225c --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +scratch_dir diff --git a/test/detect_files/bourne_again_script b/test/detect_files/bourne_again_script new file mode 100755 index 0000000..aa04493 --- /dev/null +++ b/test/detect_files/bourne_again_script @@ -0,0 +1,136 @@ +#!/bin/bash + +# findbl - find bad symbolic links (dangling, malformed etc.) +# Copyright © 2000-2006 by Pádraig Brady . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details, +# which is available at www.gnu.org + + +# Notes: +# +# By default (-d) it reports dangling (stale) links. Note invalid +# pathnames are reported as stale by this script. +# +# To report redundant info in symbolic links, such as multiple +# consequtive ////'s or /./././ etc. you specify the -n option. +# Note that fixing this won't give you back any disk space as +# the link will take a disk block anyway, but malformed links +# like this could cause other programs problems. +# +# To report all absolute links in the specified path(s), use +# the -A option. This can help when you want to move a tree +# around in the filesystem. +# +# Likewise the -l option reports all relative links in the +# specified paths. +# +# The -s option reports suspect absolute links. I.E. absolute +# links to files in the same directory as the link or below. +# TODO: support finding suspect relative link also. For e.g.: +# /etc/file.lnk ->../etc/file (python and abspath may be needed?) +# +# Note if this output passed to xargs or rm etc. +# then filenames with spaces will cause problems +# +# Should insert list of filesystems that support links +# or specify -xdev or something +# +# auto tidying of messy links could use tr -s / to squeeze consequtive /'s +# and sed s//..///d to remove /../ + +script_dir=`dirname $0` #directory of this script +script_dir=`readlink -f "$script_dir"` #Make sure absolute path + +. $script_dir/supprt/fslver + +Usage() { + ProgName=`basename "$0"` + echo "find \"Bad\" symbolic Links. +Usage: $ProgName [-d] [-s] [-l] [-s] [-n] [[-r] [-f] paths(s) ...] + +These options are mutually exclusive (i.e. only the last one takes effect). +-d Dangling (or stale) links. This is the default mode +-s Suspect links (absolute links to paths within or below the link's directory) +-l all reLative links +-A all Absolute links +-n reduNdant info in links (/././. ///// /../ etc.) + +If no path(s) specified, then the current directory is assumed. + +e.g. find dangling links in "library directories": +findbl \`getffl\`" + exit +} + +mode="dangling" #default + +# Note must be careful with expressions (which are currently +# wrong I think), as the following are valid file/dir names: +# " ...", "..." etc. Hmm the symlinks program probably doesn't +# handle this correctly either? + +ASC_01=`printf "\001"` + +for arg +do + case "$arg" in + -d) + mode="dangling" ;; + -s) + mode="suspect" ;; + -A) + mode="absolute" + search_expr="${ASC_01}/" ;; + -l) + mode="relative" + search_expr="${ASC_01}[^/]+" ;; + -n) + mode="redundant" +search_expr="(${ASC_01}.*[/]{2,})" #finds 2 or more consequtive /'s +search_expr="$search_expr|([${ASC_01}/]\./)" # starting with ./ or /./ anywhere +search_expr="$search_expr|(${ASC_01}.*[^.]+/[.][.]/)" #finds x/../y +search_expr="$search_expr|(${ASC_01}/[.][.]/)" #finds /../y +search_expr="$search_expr|(${ASC_01}.*[.]{3,}/[.][.]/)" #finds .../../y etc +search_expr="$search_expr|(${ASC_01}.+/$)" ;; #finds ending with / + -h|--help|-help) + Usage ;; + -v|--version) + Version ;; + *) + argsToPassOn="$argsToPassOn '$arg'" ;; + esac +done + +. $script_dir/supprt/getfpf "$argsToPassOn" + +case "$mode" in +dangling) + find "$@" -type l -printf "$FPF\n" | + #perl -nle '-e || print' | #this is much faster than below + #/usr/share/dict/words is 45424 lines which is 0.12s for + #perl and 3.8s for shell while read! should be OK though? + #Note also this doesn't distinguish EPERM and ENOENT + while read file; do [ -e "$file" ] || echo $file; done | + tr '\n' '\0' | + xargs -r0 ls -lUd -- | + sed 's/.*[0-9]\{2\} \(.*\)/\1/' ;; #only leave link -> target +suspect) + find "$@" -type l -printf "$FPF ->\1%p\1%l\n" | + grep "${ASC_01}.*${ASC_01}/" | #get absolute links + sed -e "s¬${ASC_01}./¬${ASC_01}$PWD/¬g" | #change rel to abs paths + grep -E "${ASC_01}(.*)/[^/]+${ASC_01}\1" | #find suspect links + sed -e "s¬${ASC_01}.*${ASC_01}¬ ¬g" ;; #drop work column +absolute|relative|redundant) + find "$@" -type l -printf "$FPF ->\1%l\n" | + grep -E "$search_expr" | + tr '\1' ' ' ;; +esac diff --git a/test/detect_files/clearsilver_template1.cs b/test/detect_files/clearsilver_template1.cs new file mode 100644 index 0000000..53b3d0f --- /dev/null +++ b/test/detect_files/clearsilver_template1.cs @@ -0,0 +1,6 @@ + + +

+

+ + diff --git a/test/detect_files/core.lisp b/test/detect_files/core.lisp new file mode 100644 index 0000000..fd5e108 --- /dev/null +++ b/test/detect_files/core.lisp @@ -0,0 +1,2 @@ +;; This file is part of stumpwm. +(in-package :stumpwm) diff --git a/test/detect_files/cs1.cs b/test/detect_files/cs1.cs new file mode 100644 index 0000000..af2927e --- /dev/null +++ b/test/detect_files/cs1.cs @@ -0,0 +1,55 @@ +// The Delegate declaration which defines the signature of methods which can be invoked +public delegate void ScoreChangeEventHandler (int newScore, ref bool cancel); + +// Class which makes the event +public class Game { + // Note the use of the event keyword + public event ScoreChangeEventHandler ScoreChange; + + int score; + + // Score Property + public int Score { + get { + return score; + } + set { + if (score != value) { + bool cancel = false; + ScoreChange (value, ref cancel); + if (! cancel) + score = value; + } + } + } +} + +// Class which handles the event +public class Referee +{ + public Referee (Game game) { + // Monitor when a score changes in the game + game.ScoreChange += new ScoreChangeEventHandler (game_ScoreChange); + } + + // Notice how this method signature matches the ScoreChangeEventHandler's signature + private void game_ScoreChange (int newScore, ref bool cancel) { + if (newScore < 100) + System.Console.WriteLine ("Good Score"); + else { + cancel = true; + System.Console.WriteLine ("No Score can be that high!"); + } + } +} + +// Class to test it all +public class GameTest +{ + public static void Main () { + Game game = new Game (); + Referee referee = new Referee (game); + game.Score = 70; + game.Score = 110; + } +} diff --git a/test/detect_files/d_script b/test/detect_files/d_script new file mode 100755 index 0000000..507c8c2 --- /dev/null +++ b/test/detect_files/d_script @@ -0,0 +1 @@ +#!/usr/bin/dmd diff --git a/test/detect_files/findup b/test/detect_files/findup new file mode 100755 index 0000000..377882b --- /dev/null +++ b/test/detect_files/findup @@ -0,0 +1,215 @@ +#!/bin/bash + +# findup - find duplicate files +# Copyright © 2000-2006 by Pádraig Brady . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details, +# which is available at www.gnu.org + + +# Description +# +# will show duplicate files in the specified directories +# (and their subdirectories), in the format: +# +# 2 * 2048 file1 file2 +# 3 * 1024 file3 file4 file5 +# 2 * 1024 file6 file7 +# +# Where the number is the disk usage in bytes of each of the +# duplicate files on that line, and all duplicate files are +# shown on the same line. +# Output it ordered by largest disk usage first and +# then by the number of duplicate files. +# +# Caveats/Notes: +# I compared this to any equivalent utils I could find (as of Nov 2000) +# and it's (by far) the fastest, has the most functionality (thanks to +# find) and has no (known) bugs. In my opinion fdupes is the next best but +# is slower (even though written in C), and has a bug where hard links +# in different directories are reported as duplicates sometimes. +# +# This script requires uniq > V2.0.21 (part of GNU textutils|coreutils) +# undefined operation if any dir/file names contain \n or \\ +# sparse files are not treated differently. +# Don't specify params to find that affect output etc. (e.g -printf etc.) +# zero length files are ignored. +# symbolic links are ignored. +# path1 & path2 can be files &/or directories + +script_dir=`dirname $0` #directory of this script +script_dir=`readlink -f "$script_dir"` #Make sure absolute path + +. $script_dir/supprt/fslver + +Usage() { + ProgName=`basename "$0"` + echo "find dUPlicate files. +Usage: $ProgName [[-t [-m|-d]] [-r] [-f] paths(s) ...] + +If no path(s) specified then the currrent directory is assumed. + +When -m is specified any found duplicates will be merged (using hardlinks). +When -d is specified any found duplicates will be deleted (only 1 left). +When -t is specfied, only report what -m or -d would do. + +You can also pipe output to $script_dir/fstool/dupwaste to +get a total of the wastage due to duplicates. + +Examples: + +search for duplicates in current directory and below + findup or findup . +search for duplicates in all linux source directories and merge using hardlinks + findup -m /usr/src/linux* +same as above but don't look in subdirectories + findup -r . +search for duplicates in /usr/bin + findup /usr/bin +search in multiple directories but not their subdirectories + findup -r /usr/bin /bin /usr/sbin /sbin +search for duplicates in \$PATH + findup \`$script_dir/supprt/getffp\` +search system for duplicate files over 100K in size + findup / -size +100k +search only my files (that I own and are in my home dir) + findup ~ -user \`id -u\` +search system for duplicate files belonging to roger + findup / -user \`id -u roger\`" + exit +} + +for arg +do + case "$arg" in + -h|--help|-help) + Usage ;; + -v|--version) + Version ;; + --gui) + mode="gui" ;; + -m) + mode="merge" ;; + -d) + mode="del" ;; + -t) + t="t" ;; + *) + argsToPassOn="$argsToPassOn '$arg'" + esac +done +[ "$mode" = "merge" ] && argsToPassOn="$argsToPassOn -xdev" + +if [ ! -z "$mode" ]; then + forceFullPath="-f" + sep_mode="prepend" +else + sep_mode="none" +fi + +if [ "$mode" = "gui" ] || [ "$mode" = "merge" ] || [ "$mode" = "del" ]; then + merge_early="" #process hardlinks +else + merge_early="-u" #ignore hardlinks +fi + +. $script_dir/supprt/getfpf $forceFullPath "$argsToPassOn" + +check_uniq + +if [ `find . -maxdepth 0 -printf "%D" 2> /dev/null` = "D" ] +then + devFmt="\060" #0 +else + devFmt=%D #This is new and will help find more duplicate files +fi + #print name, inode & size. +find "$@" -size +0c -type f -printf "$FPF\0$devFmt\0%i\0%s\n" | +tr ' \t\0' '\0\1 ' | #remove spaces, tabs in file names +sort -k4,4nr -k2,2n -k3,3 $merge_early |#group [and merge] size,dev & inodes +if [ -z "$merge_early" ]; then + $script_dir/supprt/rmlint/merge_hardlinks +else + uniq -3 -D #pick just duplicate filesizes +fi | +sort -k2,2n -k3,3n | #NB sort inodes so md5sum does less seeking all over disk +cut -f1 -d' ' -s | #get filenames to work on +tr '\0\1\n' ' \t\0' |#reset any space & tabs etc and delimit names with \0 + +# The following optional block, md5sums a small sample of each file, +# which can help when there are many files of the same size, +# even more so if they are large. This usually adds a small amount of +# runtime, however it can save a large amount of time in certain situations. +if $script_dir/supprt/md5sum_approx; then + xargs -r0 $script_dir/supprt/md5sum_approx | + sort | #group duplicate files together + uniq --all-repeated -w32 | #pick just duplicates + cut -d' ' -f3- | #get filenames + sort | #sort by paths to try to minimise disk seeks + tr '\n' '\0' #delimit names with \0 +else + cat +fi | + +# This block selects duplicates using md5sum of whole file +xargs -r0 md5sum -- | #calculate md5sums for possible duplicates +sort | #group duplicate files together +uniq --all-repeated -w32 | #pick just duplicates + +# The following optional block, checks duplicates again using sha1 +# Note for data sets that don't totally fit in cache this will +# probably read duplicate files off the disk again. +cut -d' ' -f3- | #get filenames +sort | #sort by paths to try to minimise disk seeks +tr '\n' '\0' | #delimit names with \0 +xargs -r0 sha1sum -- | #to be sure to be sure +sort | #group duplicate files together +uniq --all-repeated=$sep_mode -w40 | #pick just duplicates + +if [ ! -z "$mode" ]; then + cut -d' ' -f3- | + if [ ! $mode = "gui" ]; then # external call to python as this is faster + if $script_dir/supprt/rmlint/fixdup.py < /dev/null; then + $script_dir/supprt/rmlint/fixdup.py $t$mode + elif $script_dir/supprt/rmlint/fixdup.sh < /dev/null; then + $script_dir/supprt/rmlint/fixdup.sh $t$mode + else + echo "Error, couldn't execute merge util" >&2 + exit 1 + fi + else + cat + fi +else +( +psum='no match' +line='' +declare -i counter +while read sum file; do #sum is delimited by first space + if [ "$sum" != "$psum" ]; then + if [ ! -z "$line" ]; then + echo "$counter * $line" + fi + counter=1 + line="`du -b "$file"`" + psum="$sum" + else + counter=counter+1 #Use bash arithmetic, not expr (for speed) + line="$line $file" + fi +done + +if [ ! -z "$line" ]; then + echo "$counter * $line" +fi +) | +sort -k3,3 -k1,1 -brn +fi diff --git a/test/detect_files/foo.c b/test/detect_files/foo.c new file mode 100644 index 0000000..5c2fd48 --- /dev/null +++ b/test/detect_files/foo.c @@ -0,0 +1,4 @@ +// c file +int function_a(void) { + int x; +} diff --git a/test/detect_files/foo.d b/test/detect_files/foo.d new file mode 100644 index 0000000..def8f1a --- /dev/null +++ b/test/detect_files/foo.d @@ -0,0 +1,4 @@ +// d file +int function_a(void) { + int x; +} diff --git a/test/detect_files/foo.rb b/test/detect_files/foo.rb new file mode 100644 index 0000000..22d51b4 --- /dev/null +++ b/test/detect_files/foo.rb @@ -0,0 +1,4 @@ +# a ruby script +File.open("blah") do |io| + a = io.read +end diff --git a/test/detect_files/foo_matlab.m b/test/detect_files/foo_matlab.m new file mode 100644 index 0000000..022fdb3 --- /dev/null +++ b/test/detect_files/foo_matlab.m @@ -0,0 +1,3 @@ +function foo = b +% a comment +end diff --git a/test/detect_files/foo_objective_c.h b/test/detect_files/foo_objective_c.h new file mode 100644 index 0000000..fba767d --- /dev/null +++ b/test/detect_files/foo_objective_c.h @@ -0,0 +1,3 @@ +@interface +@end + diff --git a/test/detect_files/foo_objective_c.m b/test/detect_files/foo_objective_c.m new file mode 100644 index 0000000..322c71b --- /dev/null +++ b/test/detect_files/foo_objective_c.m @@ -0,0 +1,2 @@ +// c_comment +i = 2; diff --git a/test/detect_files/foo_upper_case.C b/test/detect_files/foo_upper_case.C new file mode 100644 index 0000000..5c2fd48 --- /dev/null +++ b/test/detect_files/foo_upper_case.C @@ -0,0 +1,4 @@ +// c file +int function_a(void) { + int x; +} diff --git a/test/detect_files/foo_upper_case.RB b/test/detect_files/foo_upper_case.RB new file mode 100644 index 0000000..22d51b4 --- /dev/null +++ b/test/detect_files/foo_upper_case.RB @@ -0,0 +1,4 @@ +# a ruby script +File.open("blah") do |io| + a = io.read +end diff --git a/test/detect_files/py_script b/test/detect_files/py_script new file mode 100755 index 0000000..aabd365 --- /dev/null +++ b/test/detect_files/py_script @@ -0,0 +1,1457 @@ +#!/usr/bin/env python +# vim:fileencoding=utf8 +# Note both python and vim understand the above encoding declaration + +# Note using env above will cause the system to register +# the name (in ps etc.) as "python" rather than fslint-gui +# (because "python" is passed to exec by env). + +""" + FSlint - A utility to find File System lint. + Copyright © 2000-2006 by Pádraig Brady . + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details, + which is available at www.gnu.org +""" + +import gettext +import locale +import gtk +import gtk.glade + +import os, sys, time, stat + +# Maintain compatibility with Python 2.2 and below, +# while getting rid of warnings in newer pyGtks. +try: + True, False +except NameError: + True, False = 1, 0 + +time_commands=False #print sub commands timing on status line + +liblocation=os.path.dirname(os.path.abspath(sys.argv[0])) +locale_base=liblocation+'/po/locale' +try: + import fslint + if sys.argv[0][0] != '/': + #If relative probably debugging so don't use system files if possible + if not os.path.exists(liblocation+'/fslint'): + liblocation = fslint.liblocation + locale_base = None #sys default + else: + liblocation = fslint.liblocation + locale_base = None #sys default +except: + pass + +class i18n: + + def __init__(self): + #gtk2 only understands utf-8 so convert to unicode + #which will be automatically converted to utf-8 by pygtk + gettext.install("fslint", locale_base, unicode=1) + global N_ #translate string but not at point of definition + def N_(string): return string + td=gettext.bindtextdomain("fslint",locale_base) + gettext.textdomain("fslint") + #This call should be redundant + #(done correctly in gettext) for python 2.3 + try: + gtk.glade.bindtextdomain("fslint",td) #note sets codeset to utf-8 + except: + #if no glade.bindtextdomain then we'll do without + pass + + try: + locale.setlocale(locale.LC_ALL,'') + except: + #gtk will print warning for a duff locale + pass + #Note python 2.3 has the nicer locale.getpreferredencoding() + self.preferred_encoding=locale.nl_langinfo(locale.CODESET) + + class unicode_displayable(unicode): + """translate non displayable chars to an appropriate representation""" + translate_table=range(0x2400,0x2420) #control chars + def displayable(self,exclude): + if exclude: + curr_table=self.__class__.translate_table[:] #copy + for char in exclude: + try: + curr_table[ord(char)]=ord(char) + except: + pass #won't be converted anyway + else: + curr_table=self.__class__.translate_table + return self.translate(curr_table) + #Note in python 2.2 this will be a new style class as + #we are subclassing the builtin (immutable) unicode type. + #Therefore you can make a factory function with the following. + #I.E. you can do uc=self.unicode_displayable(uc) below + #(the __class__ is redundant in python 2.2 also). + #def __new__(cls,string): + # translated_string=unicode(string).translate(cls.translate_table) + # return unicode.__new__(cls, translated_string) + + #The following is used for display strings only + def utf8(self,orig,exclude=""): + """If orig is not a valid utf8 string, + then try to convert to utf8 using preferred encoding while + also replacing undisplayable or invalid characters. + Exclude contains control chars you don't want to translate.""" + import types + if type(orig) == types.UnicodeType: + uc=orig + else: + try: + uc=unicode(orig,"utf-8") + except: + try: + # Note I don't use "replace" here as that + # replaces multiple bytes with a FFFD in utf8 locales + # This is silly as then you know it's not utf8 so + # one should try each character. + uc=unicode(orig,self.preferred_encoding) + except: + uc=unicode(orig,"ascii","replace") + # Note I don't like the "replacement char" representation + # on fedora core 3 at least (bitstream-vera doesn't have it, + # and the nimbus fallback looks like a comma). + # It's even worse on redhat 9 where there is no + # representation at all. Note FreeSans does have a nice + # question mark representation, and dejavu also since 1.12. + # Alternatively I could: uc=unicode(orig,"latin-1") as that + # has a representation for each byte, but it's not general. + uc=self.__class__.unicode_displayable(uc).displayable(exclude) + return uc.encode("utf-8") + +I18N=i18n() #call first so everything is internationalized + +import getopt +def Usage(): + print _("Usage: %s [OPTION] [PATHS]") % os.path.split(sys.argv[0])[1] + print _(" --version display version") + print _(" --help display help") + +try: + lOpts, lArgs = getopt.getopt(sys.argv[1:], "", ["help","version"]) + + if len(lArgs) == 0: + lArgs = [os.getcwd()] + + if ("--help","") in lOpts: + Usage() + sys.exit(None) + + if ("--version","") in lOpts: + print "FSlint 2.19" + sys.exit(None) +except getopt.error, msg: + print msg + print + Usage() + sys.exit(2) + +def human_num(num, divisor=1, power=""): + num=float(num) + if divisor == 1: + return locale.format("%ld",int(num),1) + elif divisor == 1000: + powers=[" ","K","M","G","T","P"] + elif divisor == 1024: + powers=[" ","Ki","Mi","Gi","Ti","Pi"] + else: + raise ValueError, "Invalid divisor" + if not power: power=powers[0] + while num >= 1000: #4 digits + num /= divisor + power=powers[powers.index(power)+1] + human_num(num,divisor,power) + if power.strip(): + return "%6.1f%s" % (num,power) + else: + return "%4ld %s" % (num,power) + +class GladeWrapper: + """ + Superclass for glade based applications. Just derive from this + and your subclass should create methods whose names correspond to + the signal handlers defined in the glade file. Any other attributes + in your class will be safely ignored. + + This class will give you the ability to do: + subclass_instance.GtkWindow.method(...) + subclass_instance.widget_name... + """ + def __init__(self, Filename, WindowName): + #load glade file. + self.widgets = gtk.glade.XML(Filename, WindowName, gettext.textdomain()) + self.GtkWindow = getattr(self, WindowName) + + instance_attributes = {} + for attribute in dir(self.__class__): + instance_attributes[attribute] = getattr(self, attribute) + self.widgets.signal_autoconnect(instance_attributes) + + def __getattr__(self, attribute): #Called when no attribute in __dict__ + widget = self.widgets.get_widget(attribute) + if widget is None: + raise AttributeError("Widget [" + attribute + "] not found") + self.__dict__[attribute] = widget #add reference to cache + return widget + +# SubProcess Example: +# +# process = subProcess("your shell command") +# process.read() #timeout is optional +# handle(process.outdata, process.errdata) +# del(process) +import time, os, select, signal +class subProcess: + """Class representing a child process. It's like popen2.Popen3 + but there are three main differences. + 1. This makes the new child process group leader (using setpgrp()) + so that all children can be killed. + 2. The output function (read) is optionally non blocking returning in + specified timeout if nothing is read, or as close to specified + timeout as possible if data is read. + 3. The output from both stdout & stderr is read (into outdata and + errdata). Reading from multiple outputs while not deadlocking + is not trivial and is often done in a non robust manner.""" + + def __init__(self, cmd, bufsize=8192): + """The parameter 'cmd' is the shell command to execute in a + sub-process. If the 'bufsize' parameter is specified, it + specifies the size of the I/O buffers from the child process.""" + self.cleaned=False + self.BUFSIZ=bufsize + self.outr, self.outw = os.pipe() + self.errr, self.errw = os.pipe() + self.pid = os.fork() + if self.pid == 0: + self._child(cmd) + os.close(self.outw) #parent doesn't write so close + os.close(self.errw) + # Note we could use self.stdout=fdopen(self.outr) here + # to get a higher level file object like popen2.Popen3 uses. + # This would have the advantages of auto handling the BUFSIZ + # and closing the files when deleted. However it would mean + # that it would block waiting for a full BUFSIZ unless we explicitly + # set the files non blocking, and there would be extra uneeded + # overhead like EOL conversion. So I think it's handier to use os.read() + self.outdata = self.errdata = '' + self._outeof = self._erreof = 0 + + def _child(self, cmd): + # Note sh below doesn't setup a seperate group (job control) + # for non interactive shells (hmm maybe -m option does?) + os.setpgrp() #seperate group so we can kill it + os.dup2(self.outw,1) #stdout to write side of pipe + os.dup2(self.errw,2) #stderr to write side of pipe + #stdout & stderr connected to pipe, so close all other files + map(os.close,[self.outr,self.outw,self.errr,self.errw]) + try: + cmd = ['/bin/sh', '-c', cmd] + os.execvp(cmd[0], cmd) + finally: #exit child on error + os._exit(1) + + def read(self, timeout=None): + """return 0 when finished + else return 1 every timeout seconds + data will be in outdata and errdata""" + currtime=time.time() + while 1: + tocheck=[self.outr]*(not self._outeof)+ \ + [self.errr]*(not self._erreof) + ready = select.select(tocheck,[],[],timeout) + if len(ready[0]) == 0: #no data timeout + return 1 + else: + if self.outr in ready[0]: + outchunk = os.read(self.outr,self.BUFSIZ) + if outchunk == '': + self._outeof = 1 + self.outdata += outchunk + if self.errr in ready[0]: + errchunk = os.read(self.errr,self.BUFSIZ) + if errchunk == '': + self._erreof = 1 + self.errdata += errchunk + if self._outeof and self._erreof: + return 0 + elif timeout: + if (time.time()-currtime) > timeout: + return 1 #may be more data but time to go + + def kill(self): + os.kill(-self.pid, signal.SIGTERM) #kill whole group + + def cleanup(self): + """Wait for and return the exit status of the child process.""" + self.cleaned=True + os.close(self.outr) + os.close(self.errr) + pid, sts = os.waitpid(self.pid, 0) + if pid == self.pid: + self.sts = sts + return self.sts + + def __del__(self): + if not self.cleaned: + self.cleanup() + +# Determine what type of distro we're on. +class distroType: + def __init__(self): + self.rpm = self.deb = False + if os.path.exists("/etc/redhat-release"): + self.rpm = True + elif os.path.exists("/etc/debian_version"): + self.deb = True + else: + self.rpm = (os.system("rpm --version >/dev/null 2>&1") == 0) + if not self.rpm: + self.deb = (os.system("dpkg --version >/dev/null 2>&1") == 0) +dist_type=distroType() + +def human_space_left(where): + (device, total, used_b, avail, used_p, mount)=\ + os.popen("df -h %s | tail -1"%where).read().split() + return _("%s of %s is used leaving %sB available") % (used_p, mount, avail) + +class dlgUserInteraction(GladeWrapper): + """ + Note input buttons tuple text should not be translated + so that the stock buttons are used if possible. But the + translations should be available, so use N_ for input + buttons tuple text. Note the returned response is not + translated either. + """ + def init(self, app, message, buttons=('Ok',)): + for text in buttons: + try: + stock_text=getattr(gtk,"STOCK_"+text.upper()) + button = gtk.Button(stock=stock_text) + except: + button = gtk.Button(label=_(text)) + button.set_data("text", text) + button.connect("clicked", self.button_clicked) + self.GtkWindow.action_area.pack_start(button) + button.show() + button.set_flags(gtk.CAN_DEFAULT) + button.grab_default() #last button is default + self.app = app + self.lblmsg.set_text(message) + self.lblmsg.show() + if message.endswith(":"): + self.entry.show() + else: + self.entry.hide() + + def show(self): + self.response=None + self.GtkWindow.set_transient_for(self.app.GtkWindow)#center on main win + self.GtkWindow.show() + if self.GtkWindow.modal: + gtk.main() #synchronous call from parent + #else: not supported + + ################# + # Signal handlers + ################# + + def quit(self, *args): + self.GtkWindow.hide() + if self.GtkWindow.modal: + gtk.main_quit() + + def button_clicked(self, button): + self.input = self.entry.get_text() + self.response = button.get_data("text") + self.quit() + +class dlgPathSel(GladeWrapper): + + def init(self, app): + self.app = app + self.pwd = self.app.pwd + + def show(self, fileOps=0): + self.canceled=1 + self.fileOps = fileOps + self.GtkWindow.set_filename(self.pwd+'/') + if self.fileOps: + self.GtkWindow.show_fileop_buttons() + else: + self.GtkWindow.hide_fileop_buttons() + #self.GtkWindow.set_parent(self.app.GtkWindow)#error (on gtk-1.2.10-11?) + self.GtkWindow.set_transient_for(self.app.GtkWindow)#center on main win + self.GtkWindow.show() + if self.GtkWindow.modal: + gtk.main() #synchronous call from parent + #else: not supported + + ################# + # Signal handlers + ################# + + def quit(self, *args): + self.GtkWindow.hide() + if not self.canceled: + self.pwd = self.GtkWindow.history_pulldown.get_children()[0].get() + if self.GtkWindow.modal: + gtk.main_quit() + return True #Don't let window be destroyed + + def on_okdirs_clicked(self, *args): + if self.fileOps: #creating new item + file = self.GtkWindow.get_filename() + if os.path.exists(file): + if os.path.isfile(file): + msgbox=dlgUserInteraction(liblocation+"/fslint.glade", + "UserInteraction") + msgbox.init(self, + _("Do you want to overwrite?\n") + file, + (N_('Yes'), N_('No'))) + msgbox.show() + if msgbox.response != "Yes": + return + else: + msgbox=dlgUserInteraction(liblocation+"/fslint.glade", + "UserInteraction") + msgbox.init(self, _("You can't overwrite ") + file) + msgbox.show() + return + self.canceled=0 + self.quit() + +class fslint(GladeWrapper): + + class UserAbort(Exception): + pass + + def __init__(self, Filename, WindowName): + os.close(0) #don't hang if any sub cmd tries to read from stdin + self.pwd=os.path.realpath(os.curdir) + GladeWrapper.__init__(self, Filename, WindowName) + self.dlgPathSel = dlgPathSel(liblocation+"/fslint.glade", "PathSel") + self.dlgPathSel.init(self) + #Just need to keep this tuple in sync with tabs + (self.mode_up, self.mode_pkgs, self.mode_nl, self.mode_sn, + self.mode_tf, self.mode_bl, self.mode_id, self.mode_ed, + self.mode_ns, self.mode_rs) = range(10) + self.clists = { + self.mode_up:self.clist_dups, + self.mode_pkgs:self.clist_pkgs, + self.mode_nl:self.clist_nl, + self.mode_sn:self.clist_sn, + self.mode_tf:self.clist_tf, + self.mode_bl:self.clist_bl, + self.mode_id:self.clist_id, + self.mode_ed:self.clist_ed, + self.mode_ns:self.clist_ns, + self.mode_rs:self.clist_rs + } + self.mode_descs = { + self.mode_up:_("Files with the same content"), + self.mode_pkgs:_("Installed packages ordered by disk usage"), + self.mode_nl:_("Problematic filenames"), + self.mode_sn:_("Possibly conflicting commands or filenames"), + self.mode_tf:_("Possibly old temporary files"), + self.mode_bl:_("Problematic symbolic links"), + self.mode_id:_("Files with missing user IDs"), + self.mode_ed:_("Empty directories"), + self.mode_ns:_("Executables still containing debugging info"), + self.mode_rs:_("Whitespace at the end of lines in a text file") + } + for path in lArgs: + if os.path.exists(path): + self.addDirs(self.ok_dirs, os.path.abspath(path)) + else: + self.ShowErrors(_("Invalid path [") + path + "]") + for bad_dir in ['/lost+found','/dev','/proc','/sys','/tmp', + '/*.svn','/*CVS']: + self.addDirs(self.bad_dirs, bad_dir) + self.mode=0 + self.status.set_text(self.mode_descs[self.mode]) + self.bg_colour=self.vpanes.get_style().bg[gtk.STATE_NORMAL] + #make readonly GtkEntry and GtkTextView widgets obviously so, + #by making them the same colour as the surrounding panes + self.errors.modify_base(gtk.STATE_NORMAL,self.bg_colour) + self.status.modify_base(gtk.STATE_NORMAL,self.bg_colour) + self.pkg_info.modify_base(gtk.STATE_NORMAL,self.bg_colour) + #Other GUI stuff that ideally [lib]glade should support + self.clist_pkgs.set_column_visibility(2,0) + self.clist_ns.set_column_justification(2,gtk.JUSTIFY_RIGHT) + + def get_fslint(self, command, delim='\n'): + self.fslintproc = subProcess(command) + count=0 + while self.fslintproc.read(timeout=0.1): + self.status.set_text(_("searching")+"."*(count%10)) + count+=1 + while gtk.events_pending(): gtk.main_iteration(False) + if self.stopflag: + self.fslintproc.kill() + break + else: + self.fslintproc.outdata=self.fslintproc.outdata.split(delim)[:-1] + ret = (self.fslintproc.outdata, self.fslintproc.errdata) + del(self.fslintproc) + self.status.set_text(_("processing...")) + while gtk.events_pending(): gtk.main_iteration(False) + if self.stopflag: + raise self.UserAbort + else: + return ret + + def ShowErrors(self, lines): + if len(lines) == 0: + return + end=self.errors.get_buffer().get_end_iter() + self.errors.get_buffer().insert(end,I18N.utf8(lines,"\n")) + + def ClearErrors(self): + self.errors.get_buffer().set_text("") + + def buildFindParameters(self): + if self.mode == self.mode_sn: + if self.chk_sn_path.get_active(): + return "" + elif self.mode == self.mode_ns: + if self.chk_ns_path.get_active(): + return "" + elif self.mode == self.mode_pkgs: + return "" + + if self.ok_dirs.rows == 0: + #raise _("No search paths specified") #py 2.2.2 can't raise unicode + return _("No search paths specified") + + search_dirs = "" + for row in range(self.ok_dirs.rows): + search_dirs = search_dirs + \ + " '" + self.ok_dirs.get_row_data(row) + "'" + exclude_dirs="" + + for row in range(self.bad_dirs.rows): + if exclude_dirs == "": + exclude_dirs = '\(' + ' -path "' + else: + exclude_dirs += ' -o -path "' + exclude_dirs += self.bad_dirs.get_row_data(row) + '"' + if exclude_dirs != "": + exclude_dirs += ' \) -prune -o ' + + if not self.recurseDirs.get_active(): + recurseParam=" -r " + else: + recurseParam=" " + + self.findParams = search_dirs + " -f " + recurseParam + exclude_dirs + self.findParams += self.extra_find_params.get_text() + + return "" + + def addDirs(self, dirlist, dirs): + """Adds items to passed clist.""" + dirlist.append([I18N.utf8(dirs)]) + dirlist.set_row_data(dirlist.rows-1, dirs) + + def removeDirs(self, dirlist): + """Removes selected items from passed clist. + If no items selected then list is cleared.""" + paths_to_remove = dirlist.selection + if len(paths_to_remove) == 0: + dirlist.clear() + else: + paths_to_remove.sort() #selection order irrelevant/problematic + paths_to_remove.reverse() #so deleting works correctly + for row in paths_to_remove: + dirlist.remove(row) + + def clist_alloc_colour(self, clist, colour): + """cache colour allocation for clist + as colour will probably be used multiple times""" + cmap = clist.get_colormap() + cmap_cache=clist.get_data("cmap_cache") + if cmap_cache == None: + cmap_cache={'':None} + if not cmap_cache.has_key(colour): + cmap_cache[colour]=cmap.alloc_color(colour) + clist.set_data("cmap_cache",cmap_cache) + return cmap_cache[colour] + + def clist_append_path(self, clist, path, colour, *rest): + """append path to clist, handling utf8 and colour issues""" + colour = self.clist_alloc_colour(clist, colour) + utf8_path=I18N.utf8(path) + (dir,file)=os.path.split(utf8_path) + clist.append((file,dir)+rest) + row_data = clist.get_data("row_data") + row_data.append(path+'\n') #add '\n' so can write with writelines + if colour: + clist.set_foreground(clist.rows-1,colour) + + def clist_append_group_row(self, clist, cols): + """append header to clist""" + clist.append(cols) + row_data = clist.get_data("row_data") + row_data.append('#'+"\t".join(cols).rstrip()+'\n') + clist.set_background(clist.rows-1,self.bg_colour) + clist.set_selectable(clist.rows-1,0) + + def get_path_info(self, path): + """Returns path info appropriate for display, i.e. + (color, size, ondisk_size, username, groupname, mtime_ls_date)""" + + stat_val = os.lstat(path) + + date = time.ctime(stat_val[stat.ST_MTIME]) + month_time = date[4:16] + year = date[-5:] + timediff = time.time()-stat_val[stat.ST_MTIME] + if timediff > 15552000: #6months + date = month_time[0:6] + year + else: + date = month_time + + mode = stat_val[stat.ST_MODE] + if stat.S_ISREG(mode): + colour = '' #default + if mode & (stat.S_IXGRP|stat.S_IXUSR|stat.S_IXOTH): + colour = "#00C000" + elif stat.S_ISDIR(mode): + colour = "blue" + elif stat.S_ISLNK(mode): + colour = "cyan" + if not os.path.exists(path): + colour = "#C00000" + else: + colour = "tan" + + size=stat_val.st_blocks*512 + + return (colour, stat_val[stat.ST_SIZE], size, stat_val[stat.ST_UID], + stat_val[stat.ST_GID], date, stat_val[stat.ST_MTIME]) + + def whatRequires(self, packages, level=0): + if not packages: return + if level==0: self.checked_pkgs={} + for package in packages: + #print "\t"*level+package + self.checked_pkgs[package]='' + if dist_type.rpm: + cmd = r"rpm -e --test " + ' '.join(packages) + r" 2>&1 | " + cmd += r"sed -n 's/.*is needed by (installed) \(.*\)/\1/p' | " + cmd += r"LANG=C sort | uniq" + elif dist_type.deb: + cmd = r"dpkg --purge --dry-run " + ' '.join(packages) + r" 2>&1 | " + cmd += r"sed -n 's/ \(.*\) depends on.*/\1/p' | " + cmd += r"LANG=C sort | uniq" + else: + raise "unknown distro" + process = os.popen(cmd) + requires = process.read() + del(process) + new_packages = [p for p in requires.split() + if not self.checked_pkgs.has_key(p)] + self.whatRequires(new_packages, level+1) + if level==0: return self.checked_pkgs.keys() + + def findpkgs(self, clist_pkgs): + self.clist_pkgs_order=[False,False] #unordered, descending + self.clist_pkgs_user_input=False + self.pkg_info.get_buffer().set_text("") + if dist_type.deb: + #Package names unique on debian + cmd=r"dpkg-query -W --showformat='${Package}\t${Installed-Size}" + cmd+=r"\t${Status}\n' | LANG=C grep -F 'installed' | cut -f1,2" + elif dist_type.rpm: + #Must include version names to uniquefy on redhat + cmd=r"rpm -q -a --queryformat '%{N}-%{V}-%{R}.%{ARCH}\t%{SIZE}\n'" + else: + return ("", _("Sorry, FSlint does not support this functionality \ +on your system at present.")) + po, pe = self.get_fslint(cmd + " | LANG=C sort -k2,2rn") + pkg_tot = 0 + row = 0 + for pkg_info in po: + pkg_name, pkg_size= pkg_info.split() + pkg_size = int(pkg_size) + if dist_type.deb: + pkg_size = pkg_size*1024 + pkg_tot += pkg_size + clist_pkgs.append([pkg_name,human_num(pkg_size,1000).strip(), + "%010ld"%pkg_size]) + clist_pkgs.set_row_data(row, pkg_name) + row=row+1 + + return (str(row) + _(" packages, ") + + _("consuming %sB. ") % human_num(pkg_tot,1000).strip() + + _("Note %s.") % human_space_left('/'), pe) + #Note pkgs generally installed on root partition so report space left. + + def findrs(self, clist_rs): + po, pe = self.get_fslint("./findrs " + self.findParams) + row = 0 + for line in po: + colour,fsize,size,uid,gid,date,mtime = self.get_path_info(line) + self.clist_append_path(clist_rs, line, colour, str(fsize), date) + row=row+1 + + return (str(row) + _(" files"), pe) + + def findns(self, clist_ns): + cmd = "./findns " + if not self.chk_ns_path.get_active(): + cmd += self.findParams + po, pe = self.get_fslint(cmd) + + unstripped=[] + for line in po: + colour,fsize,size,uid,gid,date,mtime = self.get_path_info(line) + unstripped.append((fsize, line, date)) + unstripped.sort() + unstripped.reverse() + + row = 0 + for fsize, path, date in unstripped: + self.clist_append_path(clist_ns, path, '', human_num(fsize), date) + row += 1 + + return (str(row) + _(" unstripped binaries"), pe) + + def finded(self, clist_ed): + po, pe = self.get_fslint("./finded " + self.findParams) + row = 0 + for line in po: + colour,fsize,size,uid,gid,date,mtime = self.get_path_info(line) + self.clist_append_path(clist_ed, line, '', date) + row += 1 + + return (str(row) + _(" empty directories"), pe) + + def findid(self, clist_id): + po, pe = self.get_fslint("./findid " + self.findParams, '\0') + row = 0 + for record in po: + colour,fsize,size,uid,gid,date,mtime = self.get_path_info(record) + self.clist_append_path(clist_id, record, colour, + str(uid), str(gid), str(fsize), date) + row += 1 + + return (str(row) + _(" files"), pe) + + def findbl(self, clist_bl): + cmd = "./findbl " + self.findParams + if self.opt_bl_dangling.get_active(): + cmd += " -d" + elif self.opt_bl_suspect.get_active(): + cmd += " -s" + elif self.opt_bl_relative.get_active(): + cmd += " -l" + elif self.opt_bl_absolute.get_active(): + cmd += " -A" + elif self.opt_bl_redundant.get_active(): + cmd += " -n" + po, pe = self.get_fslint(cmd) + row = 0 + for line in po: + link, target = line.split(" -> ", 2) + self.clist_append_path(clist_bl, link, '', target) + row += 1 + + return (str(row) + _(" links"), pe) + + def findtf(self, clist_tf): + cmd = "./findtf " + self.findParams + cmd += " --age=" + str(int(self.spin_tf_core.get_value())) + if self.chk_tf_core.get_active(): + cmd += " -c" + po, pe = self.get_fslint(cmd) + row = 0 + byteWaste = 0 + for line in po: + colour,fsize,size,uid,gid,date,mtime = self.get_path_info(line) + self.clist_append_path(clist_tf, line, '', str(fsize), date) + byteWaste+=size + row += 1 + + return (human_num(byteWaste) + _(" bytes wasted in ") + + str(row) + _(" files"), pe) + + def findsn(self, clist_sn): + cmd = "./findsn " + if self.chk_sn_path.get_active(): + option = self.opt_sn_path.get_children()[0].get() + if option == _("Aliases"): + cmd += " -A" + elif option == _("Conflicting files"): + pass #default mode + else: + raise "glade GtkOptionMenu item not found" + else: + cmd += self.findParams + option = self.opt_sn_paths.get_children()[0].get() + if option == _("Aliases"): + cmd += " -A" + elif option == _("Same names"): + pass #default mode + elif option == _("Same names(ignore case)"): + cmd += " -C" + elif option == _("Case conflicts"): + cmd += " -c" + else: + raise "glade GtkOptionMenu item not found" + + po, pe = self.get_fslint(cmd,'\0') + po = po[1:] + row=0 + findsn_number=0 + findsn_groups=0 + for record in po: + if record == '': + self.clist_append_group_row(clist_sn, ['','','']) + findsn_groups += 1 + else: + colour,fsize,size,uid,gid,date,mtime=self.get_path_info(record) + self.clist_append_path(clist_sn, record, colour, str(fsize)) + clist_sn.set_row_data(clist_sn.rows-1,mtime) + findsn_number += 1 + row += 1 + if findsn_number: + findsn_groups += 1 #for stripped group head above + + return (str(findsn_number) + _(" files (in ") + str(findsn_groups) + + _(" groups)"), pe) + + def findnl(self, clist_nl): + if self.chk_findu8.get_active(): + po, pe = self.get_fslint("./findu8 " + self.findParams, '\0') + else: + sensitivity = ('1','2','3','p')[ + int(self.hscale_findnl_level.get_adjustment().value)-1] + po, pe = self.get_fslint("./findnl " + self.findParams + " -" + + sensitivity, '\0') + + row=0 + for record in po: + colour,fsize,size,uid,gid,date,mtime = self.get_path_info(record) + self.clist_append_path(clist_nl, record, colour) + row += 1 + + return (str(row) + _(" files"), pe) + + def findup(self, clist_dups): + po, pe = self.get_fslint("./findup " + self.findParams + " --gui") + + numdups = size = fsize = 0 + alldups = [] + inodes = {} + #inodes required to correctly report disk usage of + #duplicate files with seperate inode groups. + for line in po: + line = line.strip() + if line == '': #grouped == 1 + if len(inodes)>1: + alldups.append(((numdups-1)*size, numdups, fsize, dups)) + dups = [] + numdups = 0 + inodes = {} + else: + colour,fsize,size,uid,gid,date,mtime = self.get_path_info(line) + dups.append((line,date,mtime)) + inode = os.lstat(line)[stat.ST_INO] + if not inodes.has_key(inode): + inodes[inode] = True + numdups = numdups + 1 + else: + if len(inodes)>1: + alldups.append(((numdups-1)*size, numdups, fsize, dups)) + + alldups.sort() + alldups.reverse() + + byteWaste = 0 + numWaste = 0 + row=0 + for groupWaste, groupSize, FilesSize, files in alldups: + byteWaste += groupWaste + numWaste += groupSize - 1 + groupHeader = ["%d x %s" % (groupSize, human_num(FilesSize)), + "=> %s" % human_num(groupWaste), + _("bytes wasted")] + self.clist_append_group_row(clist_dups, groupHeader) + row += 1 + for file in files: + self.clist_append_path(clist_dups,file[0],'',file[1]) + clist_dups.set_row_data(row,file[2]) #mtime + row += 1 + + return (human_num(byteWaste) + _(" bytes wasted in ") + + str(numWaste) + _(" files (in ") + str(len(alldups)) + + _(" groups)"), pe) + + find_dispatch = (findup,findpkgs,findnl,findsn,findtf, + findbl,findid,finded,findns,findrs) #order NB + + def enable_stop(self): + self.find.hide() + self.stop.show() + self.stop.grab_focus() + self.stop.grab_add() #Just allow app to stop + + def disable_stop(self): + self.stop.grab_remove() + self.stop.hide() + self.find.show() + self.find.grab_focus() #as it already would have been in focus + + def check_user(self, question): + self.ClearErrors() + #remove as status from previous operation could be confusing + self.status.delete_text(0,-1) + clist = self.clists[self.mode] + if not clist.rows: + return False #Be consistent + #All actions buttons do nothing if no results + paths = clist.selection + if len(paths) == 0: + self.ShowErrors(_("None selected")) + return False + else: + msgbox = dlgUserInteraction(liblocation+"/fslint.glade", + "UserInteraction") + if len(paths) == 1: + question += _(" this item?\n") + else: + question += _(" these %d items?\n") % len(paths) + msgbox.init(self, question, (N_('Yes'), N_('No'))) + msgbox.show() + if msgbox.response != "Yes": + return False + return True + + ################# + # Signal handlers + ################# + + def on_fslint_destroy(self, event): + try: + self.fslintproc.kill() + del(self.fslintproc) + except: + pass #fslint wasn't searching + gtk.main_quit() + + def on_addOkDir_clicked(self, event): + self.dlgPathSel.show() + if not self.dlgPathSel.canceled: + path = self.dlgPathSel.GtkWindow.get_filename() + self.addDirs(self.ok_dirs, path) + + def on_addBadDir_clicked(self, event): + self.dlgPathSel.show() + if not self.dlgPathSel.canceled: + path = self.dlgPathSel.GtkWindow.get_filename() + self.addDirs(self.bad_dirs, path) + + def on_removeOkDir_clicked(self, event): + self.removeDirs(self.ok_dirs) + + def on_removeBadDir_clicked(self, event): + self.removeDirs(self.bad_dirs) + + def on_chk_sn_path_toggled(self, event): + if self.chk_sn_path.get_active(): + self.hbox_sn_paths.hide() + self.hbox_sn_path.show() + else: + self.hbox_sn_path.hide() + self.hbox_sn_paths.show() + + def on_chk_findu8_toggled(self, event): + if self.chk_findu8.get_active(): + self.hscale_findnl_level.hide() + self.lbl_findnl_sensitivity.hide() + else: + self.hscale_findnl_level.show() + self.lbl_findnl_sensitivity.show() + + def on_fslint_functions_switch_page(self, widget, dummy, pagenum): + self.ClearErrors() + self.mode=pagenum + self.status.set_text(self.mode_descs[self.mode]) + if self.mode == self.mode_up: + self.autoMerge.show() + else: + self.autoMerge.hide() + if self.mode == self.mode_ns or self.mode == self.mode_rs: #bl in future + self.autoClean.show() + else: + self.autoClean.hide() + + def on_selection_menu_button_press_event(self, widget, event): + if self.mode == self.mode_up or self.mode == self.mode_sn: + self.groups_menu.show() + else: + self.groups_menu.hide() + if event == None: #keyboard click + self.selection_menu_menu.popup(None,None,None,3,0) #at mouse pointer + elif type(widget) == gtk.Button or \ + (type(widget) == gtk.CList and event.button == 3): + self.selection_menu_menu.popup(None,None,None,event.button,0) + if type(widget) == gtk.Button: + widget.grab_focus() + return True #Don't fire click event + + def on_find_clicked(self, event): + + try: + self.ClearErrors() + errors="" + clist = self.clists[self.mode] + os.chdir(liblocation+"/fslint/") + errors = self.buildFindParameters() + if errors: + self.ShowErrors(errors) + return + self.status.delete_text(0,-1) + status="" + clist.clear() + #All GtkClist operations seem to be O(n), + #so doing the following for example will be O((n/2)*(n+1)) + # for row in range(clist.rows): + # path = clist.get_row_data(row) + #Therefore we use a python list to store row data. + clist.set_data("row_data",[]) + if self.mode == self.mode_pkgs: + self.pkg_info.get_buffer().set_text("") + self.enable_stop() + self.stopflag=0 + while gtk.events_pending(): gtk.main_iteration(False)#update GUI + clist.freeze() + tstart=time.time() + status, errors=self.__class__.find_dispatch[self.mode](self, clist) + tend=time.time() + if time_commands: + status += ". Found in %.3fs" % (tend-tstart) + except self.UserAbort: + status=_("User aborted") + except: + etype, emsg, etb = sys.exc_info() + errors=str(etype)+': '+str(emsg)+'\n' + clist.columns_autosize() + clist.thaw() + os.chdir(self.pwd) + self.ShowErrors(errors) + self.status.set_text(status) + self.disable_stop() + + def on_stop_clicked(self, event): + self.disable_stop() + self.stopflag=1 + + def on_stop_keypress(self, button, event): + #ingore capslock and numlock + state = event.state & ~(gtk.gdk.LOCK_MASK | gtk.gdk.MOD2_MASK) + ksyms=gtk.keysyms + abort_keys={ + int(gtk.gdk.CONTROL_MASK):[ksyms.c,ksyms.C], + 0 :[ksyms.space,ksyms.Escape,ksyms.Return] + } + try: + if event.keyval in abort_keys[state]: + self.on_stop_clicked(event) + except: + pass + return True + + def on_saveAs_clicked(self, event): + clist = self.clists[self.mode] + if clist.rows == 0: + return + self.dlgPathSel.show(1) + if not self.dlgPathSel.canceled: + self.ClearErrors() + fileSaveAs = self.dlgPathSel.GtkWindow.get_filename() + try: + fileSaveAs = open(fileSaveAs, 'w') + except: + etype, emsg, etb = sys.exc_info() + self.ShowErrors(str(emsg)+'\n') + return + rows_to_save = clist.selection + if self.mode == self.mode_pkgs: + for row in range(clist.rows): + if len(rows_to_save): + if row not in rows_to_save: continue + rowtext = '' + for col in (0,2): #ignore "human number" col + rowtext += clist.get_text(row,col) +'\t' + fileSaveAs.write(rowtext[:-1]+'\n') + else: + row_data=clist.get_data("row_data") + if len(rows_to_save): + for row in range(clist.rows): + if clist.get_selectable(row): + if row not in rows_to_save: continue + else: continue #don't save group headers + fileSaveAs.write(row_data[row]) + else: + fileSaveAs.writelines(row_data) + + def on_unselect_using_wildcard_activate(self, event): + self.select_using_wildcard(False) + def on_select_using_wildcard_activate(self, event): + self.select_using_wildcard(True) + def select_using_wildcard(self, select): + msgbox=dlgUserInteraction(liblocation+"/fslint.glade", + "UserInteraction") + msgbox.init(self, _("wildcard:"), (N_('Cancel'), N_('Ok'))) + msgbox.show() + if msgbox.response != "Ok": + return + wildcard=msgbox.input + if wildcard != "": + clist = self.clists[self.mode] + if clist.rows == 0: + return + select_func=select and clist.select_row or clist.unselect_row + import fnmatch + if self.mode == self.mode_pkgs: + for row in range(clist.rows): + pkgname = clist.get_text(row,0) + if fnmatch.fnmatch(pkgname,wildcard): + select_func(row, 0) + else: + row=0 + for path in clist.get_data("row_data"): + if fnmatch.fnmatch(path,wildcard): #trailing \n ignored + select_func(row, 0) + row+=1 + + def on_select_all_but_first_in_each_group_activate(self, event): + self.on_select_all_but_one_in_each_group_activate("first") + def on_select_all_but_newest_in_each_group_activate(self, event): + self.on_select_all_but_one_in_each_group_activate("newest") + def on_select_all_but_oldest_in_each_group_activate(self, event): + self.on_select_all_but_one_in_each_group_activate("oldest") + + def on_select_all_but_one_in_each_group_activate(self, which): + + def find_row_to_unselect(clist, row, which): + import operator + if which == "first": + if clist.get_selectable(row)==False: + return row+1 + else: + return row #for first row in clist_sn + elif which == "newest": + unselect_mtime=-1 + comp=operator.gt + elif which == "oldest": + unselect_mtime=2**32 + comp=operator.lt + if clist.get_selectable(row)==False: #not the case for first sn row + row=row+1 + while clist.get_selectable(row) == True and row < clist.rows: + mtime = clist.get_row_data(row) + if comp(mtime,unselect_mtime): + unselect_mtime = mtime + unselect_row=row + row=row+1 + return unselect_row + + clist = self.clists[self.mode] + clist.freeze() + clist.select_all() + for row in range(clist.rows): + if row==0 or clist.get_selectable(row)==False: #New group + unselect_row = find_row_to_unselect(clist, row, which) + clist.unselect_row(unselect_row, 0) + clist.thaw() + + def on_unselect_all_activate(self, event): + clist = self.clists[self.mode] + clist.unselect_all() + + def on_toggle_selection_activate(self, event): + clist = self.clists[self.mode] + clist.freeze() + selected = clist.selection + if len(selected) == 0: + clist.select_all() + elif len(selected) == clist.rows: + clist.unselect_all() + else: + clist.select_all() + for row in selected: + clist.unselect_row(row, 0) + clist.thaw() + + def on_selection_clicked(self, widget): + self.on_selection_menu_button_press_event(self.selection, None) + + def on_delSelected_clicked(self, event): + if self.mode == self.mode_pkgs: + if os.geteuid() != 0: + msgbox=dlgUserInteraction(liblocation+"/fslint.glade", + "UserInteraction") + msgbox.init( + self, + _("Sorry, you must be root to delete system packages.") + ) + msgbox.show() + return + if not self.check_user(_("Are you sure you want to delete")): + return + clist = self.clists[self.mode] + row_data = clist.get_data("row_data") + paths_to_remove = clist.selection + paths_to_remove.sort() #selection order irrelevant/problematic + paths_to_remove.reverse() #so deleting works correctly + numDeleted = 0 + if self.mode == self.mode_pkgs: + pkgs_selected = [] + for row in paths_to_remove: + package = clist.get_row_data(row) + pkgs_selected.append(package) + self.status.set_text(_("Calculating dependencies...")) + while gtk.events_pending(): gtk.main_iteration(False) + all_deps=self.whatRequires(pkgs_selected) + if len(all_deps) > len(pkgs_selected): + num_new_pkgs = 0 + for package in all_deps: + if package not in pkgs_selected: + num_new_pkgs += 1 + #Note clist.find_row_from_data() only compares pointers + for row in range(clist.rows): + if package == clist.get_row_data(row): + clist.select_row(row,0) + msgbox=dlgUserInteraction(liblocation+"/fslint.glade", + "UserInteraction") + msgbox.init( + self, + _("%d extra packages need to be deleted.\n") % num_new_pkgs + + _("Please review the updated selection.") + ) + msgbox.show() + #Note this is not ideal as it's difficult for users + #to get info on selected packages (Ctrl click twice). + #Should really have a seperate marked_for_deletion column. + self.status.set_text("") + return + + self.status.set_text(_("Removing packages...")) + while gtk.events_pending(): gtk.main_iteration(False) + if dist_type.rpm: + cmd="rpm -e " + elif dist_type.deb: + cmd="dpkg --purge " + cmd+=' '.join(pkgs_selected) + " >/dev/null 2>&1" + os.system(cmd) + + clist.freeze() + for row in paths_to_remove: + if self.mode != self.mode_pkgs: + try: + path=row_data[row][:-1] #strip trailing '\n' + if os.path.isdir(path): + os.rmdir(path) + else: + os.unlink(path) + except: + etype, emsg, etb = sys.exc_info() + self.ShowErrors(str(emsg)+'\n') + continue + row_data.pop(row) + clist.remove(row) + numDeleted += 1 + + #Remove any redundant grouping rows + rowver=clist.rows + rows_left = range(rowver) + rows_left.reverse() + for row in rows_left: + if clist.get_selectable(row) == False: + if (row == clist.rows-1) or (clist.get_selectable(row+1) == + False): + clist.remove(row) + if self.mode != self.mode_pkgs: + row_data.pop(row) + + clist.columns_autosize() + clist.thaw() + status = str(numDeleted) + _(" items deleted") + if self.mode == self.mode_pkgs: + status += ". " + human_space_left('/') + self.status.set_text(status) + + def on_clist_pkgs_click_column(self, clist, col): + self.clist_pkgs_order[col] = not self.clist_pkgs_order[col] + if self.clist_pkgs_order[col]: + clist.set_sort_type(gtk.SORT_ASCENDING) + else: + clist.set_sort_type(gtk.SORT_DESCENDING) + try: + #focus_row is not updated after ordering, so can't use + #last_selected=clist.get_row_data(clist.focus_row) + last_selected=self.clist_pkgs_last_selected + except: + last_selected=0 + if col==0: + clist.set_sort_column(0) + else: + clist.set_sort_column(2) + clist.sort() + #could instead just use our "row_data" and + #repopulate the gtkclist with something like: + #row_data = clist.get_data("row_data") + #row_data.sort(key = lambda x:x[col], + # reverse = not self.clist_pkgs_order[col]) + if last_selected: + #Warning! As of pygtk2-2.4.0 at least + #find_row_from_data only compares pointers, not strings! + last_selected_row=clist.find_row_from_data(last_selected) + clist.moveto(last_selected_row,0,0.5,0.0) + #clist.set_focus_row(last_selected_row) + else: + clist.moveto(0,0,0.0,0.0) + + + #Note the events and event ordering provided by the GtkClist + #make it very hard to provide robust and performant handlers + #for selected rows. These flags are an attempt to stop the + #function below from being called too frequently. + #Note most users will scoll the list with {Up,Down} rather + #than Ctrl+{Up,Down}, but at worst this will result in slow scrolling. + def on_clist_pkgs_button_press(self, list, event): + if event.button == 3: + self.on_selection_menu_button_press_event(list, event) + else: + self.clist_pkgs_user_input=True + def on_clist_pkgs_key_press(self, *args): + self.clist_pkgs_user_input=True + + def on_clist_pkgs_selection_changed(self, clist, *args): + self.pkg_info.get_buffer().set_text("") + if not self.clist_pkgs_user_input: + self.clist_pkgs_last_selected=False + return + self.clist_pkgs_user_input=False + if len(clist.selection) == 0: + return + pkg=clist.get_row_data(clist.selection[-1]) + self.clist_pkgs_last_selected=pkg #for ordering later + if dist_type.rpm: + cmd = "rpm -q --queryformat '%{DESCRIPTION}' " + elif dist_type.deb: + cmd = "dpkg-query -W --showformat='${Description}' " + cmd += pkg + pkg_process = subProcess(cmd) + pkg_process.read() + lines=pkg_process.outdata + self.pkg_info.get_buffer().set_text(I18N.utf8(lines,"\n")) + del(pkg_process) + + def on_autoMerge_clicked(self, event): + self.ClearErrors() + self.status.delete_text(0,-1) + clist = self.clists[self.mode] + if clist.rows < 3: + return + + question=_("Are you sure you want to merge ALL files?\n") + + paths_to_leave = clist.selection + if len(paths_to_leave): + question+=_("(Ignoring those selected)\n") + + msgbox = dlgUserInteraction(liblocation+"/fslint.glade", + "UserInteraction") + msgbox.init(self, question, (N_('Yes'), N_('No'))) + msgbox.show() + if msgbox.response != "Yes": + return + + newGroup = 0 + row_data=clist.get_data("row_data") + for row in range(clist.rows): + if row in paths_to_leave: + continue + if clist.get_selectable(row) == False: #new group + newGroup = 1 + else: + path = row_data[row][:-1] #strip '\n' + if newGroup: + keepfile = path + newGroup = 0 + else: + dupfile = path + try: + os.unlink(dupfile) + try: #Don't do this for autodelete + os.link(keepfile,dupfile) + except OSError, value: + if value.errno == 18: #EXDEV + os.symlink(os.path.realpath(keepfile),dupfile) + else: + raise + clist.set_background(row, self.bg_colour) + except OSError: + self.ShowErrors(str(sys.exc_value)+'\n') + + def on_autoClean_clicked(self, event): + if not self.check_user(_("Are you sure you want to clean")): + return + clist = self.clists[self.mode] + paths_to_clean = clist.selection + + numCleaned = 0 + totalSaved = 0 + row_data=clist.get_data("row_data") + for row in paths_to_clean: + try: + path_to_clean = row_data[row][:-1] #strip '\n' + startlen = os.stat(path_to_clean)[stat.ST_SIZE] + if self.mode == self.mode_ns: + stripProcess = subProcess("strip "+path_to_clean) + stripProcess.read() + errors = stripProcess.errdata + del(stripProcess) + if len(errors): + raise '', errors[:-1] + elif self.mode == self.mode_rs: + file_to_clean = open(path_to_clean,'r') + lines = open(path_to_clean,'r').readlines() + file_to_clean.close() + file_to_clean = open(path_to_clean,'w') + lines = map(lambda s: s.rstrip()+'\n', lines) + file_to_clean.writelines(lines) + file_to_clean.close() + clist.set_background(row, self.bg_colour) + clist.unselect_row(row,0) + totalSaved += startlen - os.stat(path_to_clean)[stat.ST_SIZE] + numCleaned += 1 + except: + etype, emsg, etb = sys.exc_info() + self.ShowErrors(str(emsg)+'\n') + status = str(numCleaned) + _(" items cleaned (") + \ + human_num(totalSaved) + _(" bytes saved)") + self.status.set_text(status) + +FSlint = fslint(liblocation+"/fslint.glade", "fslint") + +gtk.main () diff --git a/test/detect_files/renrot b/test/detect_files/renrot new file mode 100755 index 0000000..e91bc59 --- /dev/null +++ b/test/detect_files/renrot @@ -0,0 +1,13 @@ +#! perl -w +# +# $Id: renrot 299 2007-09-01 08:50:11Z zeus $ +# + +use strict; +use warnings; +use diagnostics; +require 5.006; +use Time::localtime; +use Time::Local; +use Image::ExifTool; +use Getopt::Long; diff --git a/test/detect_files/ruby_script b/test/detect_files/ruby_script new file mode 100755 index 0000000..6662450 --- /dev/null +++ b/test/detect_files/ruby_script @@ -0,0 +1,3 @@ +#!/usr/local/bin/ruby +require File.dirname(__FILE__) + '/../lib/slave/slave' +Slave.daemonize diff --git a/test/detect_files/t1.m b/test/detect_files/t1.m new file mode 100644 index 0000000..881bfe7 --- /dev/null +++ b/test/detect_files/t1.m @@ -0,0 +1,32 @@ +#include +#include "Test.h" + +@implementation Test : Object +{ + int x; +} + +- init: (int)n +{ + [super init]; + x = n; + return self; +} + ++ test: (int)n +{ + return [[self alloc] init: n]; +} + +- (int)x +{ + return x; +} + +@end + + +int main (int argc, char **argv) +{ + printf ("%d!\n", [[Test test: 17231] x]); +} diff --git a/test/detect_files/t2.m b/test/detect_files/t2.m new file mode 100644 index 0000000..b512b1b --- /dev/null +++ b/test/detect_files/t2.m @@ -0,0 +1,40 @@ +/* + + Copyright (C) 2002 Kris Gybels + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In addition, as a special exception, Kris Gybels + gives permission to link the code of this program with + the unRAR library (or with modified versions of unRAR that use the + same license as unRAR), and distribute linked combinations including + the two. You must obey the GNU General Public License in all + respects for all of the code used other than unRAR. If you modify + this file, you may extend this exception to your version of the + file, but you are not obligated to do so. If you do not wish to + do so, delete this exception statement from your version. + + --- + + $Id$ + + */ + +#import + +int main(int argc, const char *argv[]) +{ + return NSApplicationMain(argc, argv); +} diff --git a/test/detect_files/upper_case_php b/test/detect_files/upper_case_php new file mode 100644 index 0000000..acb6c35 --- /dev/null +++ b/test/detect_files/upper_case_php @@ -0,0 +1,2 @@ + diff --git a/test/expected_dir/ada1.ada/ada/blanks b/test/expected_dir/ada1.ada/ada/blanks new file mode 100644 index 0000000..7813681 --- /dev/null +++ b/test/expected_dir/ada1.ada/ada/blanks @@ -0,0 +1 @@ +5 \ No newline at end of file diff --git a/test/expected_dir/ada1.ada/ada/code b/test/expected_dir/ada1.ada/ada/code new file mode 100644 index 0000000..1dc1471 --- /dev/null +++ b/test/expected_dir/ada1.ada/ada/code @@ -0,0 +1,12 @@ +with Ada.Text_IO; use Ada.Text_IO; +procedure Get_Name is +Name : String (1..80); +Length : Integer; +begin +Put ("Enter your first name> "); +Get_Line (Name, Length); +New_Line; +Put ("Hello "); +Put (Name (1..Length)); +Put (", we hope that you enjoy learning Ada!"); +end Get_Name; diff --git a/test/expected_dir/ada1.ada/ada/comment b/test/expected_dir/ada1.ada/ada/comment new file mode 100644 index 0000000..3634d72 --- /dev/null +++ b/test/expected_dir/ada1.ada/ada/comment @@ -0,0 +1 @@ +-- no variables needed here :) diff --git a/test/expected_dir/ada1.adb/ada/blanks b/test/expected_dir/ada1.adb/ada/blanks new file mode 100644 index 0000000..7813681 --- /dev/null +++ b/test/expected_dir/ada1.adb/ada/blanks @@ -0,0 +1 @@ +5 \ No newline at end of file diff --git a/test/expected_dir/ada1.adb/ada/code b/test/expected_dir/ada1.adb/ada/code new file mode 100644 index 0000000..1dc1471 --- /dev/null +++ b/test/expected_dir/ada1.adb/ada/code @@ -0,0 +1,12 @@ +with Ada.Text_IO; use Ada.Text_IO; +procedure Get_Name is +Name : String (1..80); +Length : Integer; +begin +Put ("Enter your first name> "); +Get_Line (Name, Length); +New_Line; +Put ("Hello "); +Put (Name (1..Length)); +Put (", we hope that you enjoy learning Ada!"); +end Get_Name; diff --git a/test/expected_dir/ada1.adb/ada/comment b/test/expected_dir/ada1.adb/ada/comment new file mode 100644 index 0000000..3634d72 --- /dev/null +++ b/test/expected_dir/ada1.adb/ada/comment @@ -0,0 +1 @@ +-- no variables needed here :) diff --git a/test/expected_dir/assembler1.asm/assembler/blanks b/test/expected_dir/assembler1.asm/assembler/blanks new file mode 100644 index 0000000..d8263ee --- /dev/null +++ b/test/expected_dir/assembler1.asm/assembler/blanks @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/expected_dir/assembler1.asm/assembler/code b/test/expected_dir/assembler1.asm/assembler/code new file mode 100644 index 0000000..3ac6e84 --- /dev/null +++ b/test/expected_dir/assembler1.asm/assembler/code @@ -0,0 +1,54 @@ +BITS 32 +GLOBAL _gcdAsm +SECTION .text +_gcdAsm: +push ebp +mov ebp,esp +push ebx +push ecx +push edx +push edi +mov eax,[ebp + 8] ; eax = a (0 <= a <= 2^31 - 1) +mov ebx,[ebp + 12] ; ebx = b (0 <= b <= 2^31 - 1) +mov ecx,eax +or ecx,ebx +bsf ecx,ecx ; greatest common power of 2 of a and b +jnz notBoth0 +mov eax,1 ; if a = 0 and b = 0, return 1 +jmp done +notBoth0: +mov edi,ecx +test eax,eax +jnz aNot0 +mov eax,ebx ; if a = 0, return b +jmp done +aNot0: +test ebx,ebx +jz done ; if b = 0, return a +bsf ecx,eax ; "simplify" a as much as possible +shr eax,cl +bsf ecx,ebx ; "simplify" b as much as possible +shr ebx,cl +mainLoop: +mov ecx,ebx +sub ecx,eax ; b - a +sbb edx,edx ; edx = 0 if b >= a or -1 if a > b +and ecx,edx ; ecx = 0 if b >= a or b - a if a > b +add eax,ecx ; a-new = min(a,b) +sub ebx,ecx ; b-new = max(a,b) +sub ebx,eax ; the difference is >= 0 +bsf ecx,eax ; "simplify" as much as possible by 2 +shr eax,cl +bsf ecx,ebx ; "simplify" as much as possible by 2 +shr ebx,cl +jnz mainLoop ; keep looping until ebx = 0 +mov ecx,edi ; shift back with common power of 2 +shl eax,cl +done: +pop edi +pop edx +pop ecx +pop ebx +mov esp,ebp +pop ebp +ret ; eax = gcd(a,b) diff --git a/test/expected_dir/assembler1.asm/assembler/comment b/test/expected_dir/assembler1.asm/assembler/comment new file mode 100644 index 0000000..1ffc484 --- /dev/null +++ b/test/expected_dir/assembler1.asm/assembler/comment @@ -0,0 +1,12 @@ +; int gcdAsm(int a, int b) +; +; computes gcd(a,b) according to: +; 1. a even, b even: gcd(a,b) = 2 * gcd(a/2,b/2), +; and remember how often this happened +; 2. a even, b uneven: gcd(a,b) = gcd(a/2,b) +; 3. a uneven, b even: gcd(a,b) = gcd(a,b/2) +; 4. a uneven, b uneven: a>b ? a -= b : b -= a, +; i.e. gcd(a,b) = gcd(min(a,b),max(a,b) - min(a,b)) +; do 1., repeat 2. - 4. until a = 0 or b = 0 +; return (a + b) corrected by the remembered value from 1. +; by definition: gcd(a,0) = a, gcd(0,b) = b, gcd(0,0) = 1 ! diff --git a/test/expected_dir/assembler2.S/assembler/blanks b/test/expected_dir/assembler2.S/assembler/blanks new file mode 100644 index 0000000..d8263ee --- /dev/null +++ b/test/expected_dir/assembler2.S/assembler/blanks @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/expected_dir/assembler2.S/assembler/code b/test/expected_dir/assembler2.S/assembler/code new file mode 100644 index 0000000..92839c8 --- /dev/null +++ b/test/expected_dir/assembler2.S/assembler/code @@ -0,0 +1,2 @@ +#define FOO 43 // they even use whack-whack comments +mov eax, ecx diff --git a/test/expected_dir/assembler2.S/assembler/comment b/test/expected_dir/assembler2.S/assembler/comment new file mode 100644 index 0000000..f0e9c12 --- /dev/null +++ b/test/expected_dir/assembler2.S/assembler/comment @@ -0,0 +1,3 @@ +/******************************************************** +Made up assembler file, in the style of linux kernel +********************************************************/ diff --git a/test/expected_dir/awk1.awk/awk/blanks b/test/expected_dir/awk1.awk/awk/blanks new file mode 100644 index 0000000..7813681 --- /dev/null +++ b/test/expected_dir/awk1.awk/awk/blanks @@ -0,0 +1 @@ +5 \ No newline at end of file diff --git a/test/expected_dir/awk1.awk/awk/code b/test/expected_dir/awk1.awk/awk/code new file mode 100644 index 0000000..71a4dcb --- /dev/null +++ b/test/expected_dir/awk1.awk/awk/code @@ -0,0 +1,45 @@ +BEGIN { +FS = "\t" +dashes = sp45 = sprintf("%45s", " ") +gsub(/ /, "-", dashes) # to protect the payee +"date" | getline date # get today's date +split(date, d, " ") +date = d[2] " " d[3] ", " d[6] +initnum() # set up tables for number conversion +} +NF != 3 || $2 >= 1000000 { # illegal data +printf("\nline %d illegal:\n%s\n\nVOID\nVOID\n\n\n", NR, $0) +next # no check printed +} +{ printf("\n") # nothing on line 1 +printf("%s%s\n", sp45, $1) # number, indented 45 spaces +printf("%s%s\n", sp45, date) # date, indented 45 spaces +amt = sprintf("%.2f", $2) # formatted amount +printf("Pay to %45.45s $%s\n", $3 dashes, amt) # line 4 +printf("the sum of %s\n", numtowords(amt)) # line 5 +printf("\n\n\n") # lines 6, 7 and 8 +} +function numtowords(n, cents, dols) { # n has 2 decimal places +cents = substr(n, length(n)-1, 2) +dols = substr(n, 1, length(n)-3) +if (dols == 0) +return "zero dollars and " cents " cents exactly" +return intowords(dols) " dollars and " cents " cents exactly" +} +function intowords(n) { +n = int(n) +if (n >= 1000) +return intowords(n/1000) " thousand " intowords(n%1000) +if (n >= 100) +return intowords(n/100) " hundred " intowords(n%100) +if (n >= 20) +return tens[int(n/10)] " " intowords(n%10) +return nums[n] +} +function initnum() { +split("one two three four five six seven eight nine " \ +prchecks "ten eleven twelve thirteen fourteen fifteen " \ +prchecks "sixteen seventeen eighteen nineteen", nums, " ") +split("ten twenty thirty forty fifty sixty " \ +prchecks "seventy eighty ninety", tens, " ") +} diff --git a/test/expected_dir/awk1.awk/awk/comment b/test/expected_dir/awk1.awk/awk/comment new file mode 100644 index 0000000..362dc64 --- /dev/null +++ b/test/expected_dir/awk1.awk/awk/comment @@ -0,0 +1,3 @@ +# prchecks - print formatted checks +# input: number \t amount \t payee +# output: eight lines of text for preprinted check forms diff --git a/test/expected_dir/bat1.bat/bat/blanks b/test/expected_dir/bat1.bat/bat/blanks new file mode 100644 index 0000000..d8263ee --- /dev/null +++ b/test/expected_dir/bat1.bat/bat/blanks @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/expected_dir/bat1.bat/bat/code b/test/expected_dir/bat1.bat/bat/code new file mode 100644 index 0000000..36802a0 --- /dev/null +++ b/test/expected_dir/bat1.bat/bat/code @@ -0,0 +1 @@ +echo not a rem comment! diff --git a/test/expected_dir/bat1.bat/bat/comment b/test/expected_dir/bat1.bat/bat/comment new file mode 100644 index 0000000..49a153e --- /dev/null +++ b/test/expected_dir/bat1.bat/bat/comment @@ -0,0 +1,3 @@ +REM comment 1 +rem comment 2 +rEm comment 3 diff --git a/test/expected_dir/boo1.boo/boo/blanks b/test/expected_dir/boo1.boo/boo/blanks new file mode 100644 index 0000000..f11c82a --- /dev/null +++ b/test/expected_dir/boo1.boo/boo/blanks @@ -0,0 +1 @@ +9 \ No newline at end of file diff --git a/test/expected_dir/boo1.boo/boo/code b/test/expected_dir/boo1.boo/boo/code new file mode 100644 index 0000000..39890a5 --- /dev/null +++ b/test/expected_dir/boo1.boo/boo/code @@ -0,0 +1,20 @@ +"\" +# still in string +" +'\' +# still in string +' +import smtplib +smtpServer='smtp.yourdomain.com'; +fromAddr='xah@xahlee.org'; +toAddr='xah@xahlee.org'; +text='''Subject: newfound love +Hi friend, +long time no write, i have a new manifesto i +think it would be of interest for you to peruse. +... +''' +server = smtplib.SMTP(smtpServer) +server.set_debuglevel(1) +server.sendmail(fromAddr, toAddr, text) +server.quit() diff --git a/test/expected_dir/boo1.boo/boo/comment b/test/expected_dir/boo1.boo/boo/comment new file mode 100644 index 0000000..145f233 --- /dev/null +++ b/test/expected_dir/boo1.boo/boo/comment @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Python +# Suppose you want to spam your friend, and you have lots of +# friends. The solution is to write a program to do it. After a gander +# at python docs, one easily found the module for the job. +# see http://python.org/doc/2.3.4/lib/SMTP-example.html +# the code is a bit long with the command line, but the key lies at +# the bottom four lines. The gist is this: +####### test: strings - nonsense code follows +####### test done +# save this file as x.py and run it. +# it should send out the mail. +# the set_debuglevel() is nice because you see all the interactions +# with the smtp server. Useful when you want to see what's going on +# with a smtp server. diff --git a/test/expected_dir/c1.c/cncpp/blanks b/test/expected_dir/c1.c/cncpp/blanks new file mode 100644 index 0000000..bf0d87a --- /dev/null +++ b/test/expected_dir/c1.c/cncpp/blanks @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/test/expected_dir/c1.c/cncpp/code b/test/expected_dir/c1.c/cncpp/code new file mode 100644 index 0000000..b024045 --- /dev/null +++ b/test/expected_dir/c1.c/cncpp/code @@ -0,0 +1,36 @@ +#include /* MQ API header file */ +#define NUMBEROFSELECTORS 2 +const MQHCONN Hconn = MQHC_DEF_HCONN; +static void InquireGetAndPut(char *Message, +PMQHOBJ pHobj, +char *Object) +{ +MQLONG SelectorCount = NUMBEROFSELECTORS; +MQLONG IntAttrCount = NUMBEROFSELECTORS; +MQLONG CharAttrLength = 0; +MQCHAR *CharAttrs ; +MQLONG SelectorsTable[NUMBEROFSELECTORS]; +MQLONG IntAttrsTable[NUMBEROFSELECTORS]; +MQLONG CompCode; /* Completion code */ +MQLONG Reason; /* Qualifying reason */ +SelectorsTable[0] = MQIA_INHIBIT_GET; +SelectorsTable[1] = MQIA_INHIBIT_PUT; +MQINQ(Hconn, +*pHobj, +SelectorCount, +SelectorsTable, +IntAttrCount, +IntAttrsTable, +CharAttrLength, +CharAttrs, +&CompCode, +&Reason); +if (CompCode != MQCC_OK) +{ +sprintf(Message, MESSAGE_4_E, +ERROR_IN_MQINQ, CompCode, Reason); +SetMsg(Message); +} +else +{ +} /* end if CompCode */ diff --git a/test/expected_dir/c1.c/cncpp/comment b/test/expected_dir/c1.c/cncpp/comment new file mode 100644 index 0000000..e0faeb6 --- /dev/null +++ b/test/expected_dir/c1.c/cncpp/comment @@ -0,0 +1,30 @@ +// +/* Declare local variables */ +/* */ +/* Number of selectors */ +/* Number of int attrs */ +/* Length of char attribute buffer */ +/* Character attribute buffer */ +/* attribute selectors */ +/* integer attributes */ +/* */ +/* Open the queue. If successful, do the inquire */ +/* call. */ +/* */ +/* */ +/* Initialize the variables for the inquire */ +/* call: */ +/* - Set SelectorsTable to the attributes whose */ +/* status is */ +/* required */ +/* - All other variables are already set */ +/* */ +/* */ +/* Issue the inquire call */ +/* Test the output of the inquire call. If the */ +/* call failed, display an error message */ +/* showing the completion code and reason code,*/ +/* otherwise display the status of the */ +/* INHIBIT-GET and INHIBIT-PUT attributes */ +/* */ +/* Process the changes */ diff --git a/test/expected_dir/classic_basic1.classic_basic/basic/code b/test/expected_dir/classic_basic1.classic_basic/basic/code new file mode 100644 index 0000000..4ed7d0f --- /dev/null +++ b/test/expected_dir/classic_basic1.classic_basic/basic/code @@ -0,0 +1,17 @@ +10 INPUT "What is your name: "; U$ +20 PRINT "Hello "; U$ +40 INPUT "How many stars do you want: "; N +50 S$ = "" +60 FOR I = 1 TO N +70 S$ = S$ + "*" +80 NEXT I +90 PRINT S$ +110 INPUT "Do you want more stars? "; A$ +120 IF LEN(A$) = 0 THEN GOTO 110 +130 A$ = LEFT$(A$, 1) +140 IF (A$ = "Y") OR (A$ = "y") THEN GOTO 40 +150 PRINT "Goodbye "; +160 FOR I = 1 TO 200 +170 PRINT U$; " "; +180 NEXT I +190 PRINT diff --git a/test/expected_dir/classic_basic1.classic_basic/basic/comment b/test/expected_dir/classic_basic1.classic_basic/basic/comment new file mode 100644 index 0000000..9f42a86 --- /dev/null +++ b/test/expected_dir/classic_basic1.classic_basic/basic/comment @@ -0,0 +1,2 @@ +30 REM +100 REM diff --git a/test/expected_dir/clearsilver_template1.cs/clearsilver/blanks b/test/expected_dir/clearsilver_template1.cs/clearsilver/blanks new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/test/expected_dir/clearsilver_template1.cs/clearsilver/blanks @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/test/expected_dir/clearsilver_template1.cs/clearsilver/code b/test/expected_dir/clearsilver_template1.cs/clearsilver/code new file mode 100644 index 0000000..369aaed --- /dev/null +++ b/test/expected_dir/clearsilver_template1.cs/clearsilver/code @@ -0,0 +1 @@ +

diff --git a/test/expected_dir/clearsilver_template1.cs/clearsilver/comment b/test/expected_dir/clearsilver_template1.cs/clearsilver/comment new file mode 100644 index 0000000..387f33b --- /dev/null +++ b/test/expected_dir/clearsilver_template1.cs/clearsilver/comment @@ -0,0 +1 @@ +

diff --git a/test/expected_dir/clearsilver_template1.cs/html/blanks b/test/expected_dir/clearsilver_template1.cs/html/blanks new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/test/expected_dir/clearsilver_template1.cs/html/blanks @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/test/expected_dir/clearsilver_template1.cs/html/code b/test/expected_dir/clearsilver_template1.cs/html/code new file mode 100644 index 0000000..7879e1c --- /dev/null +++ b/test/expected_dir/clearsilver_template1.cs/html/code @@ -0,0 +1,4 @@ + + + + diff --git a/test/expected_dir/clearsilver_template1.cs/html/comment b/test/expected_dir/clearsilver_template1.cs/html/comment new file mode 100644 index 0000000..e69de29 diff --git a/test/expected_dir/cobol1.cbl/cobol/blank b/test/expected_dir/cobol1.cbl/cobol/blank new file mode 100644 index 0000000..d36ff3a --- /dev/null +++ b/test/expected_dir/cobol1.cbl/cobol/blank @@ -0,0 +1,4 @@ +000100 +000180 +000187 +000210 diff --git a/test/expected_dir/cobol1.cbl/cobol/code b/test/expected_dir/cobol1.cbl/cobol/code new file mode 100644 index 0000000..7be8d98 --- /dev/null +++ b/test/expected_dir/cobol1.cbl/cobol/code @@ -0,0 +1,13 @@ +000010 IDENTIFICATION DIVISION. +000020 PROGRAM-ID. LINE-NO-PROG. +000030 AUTHOR. TIM R P BROWN. +000110 ENVIRONMENT DIVISION. +000120 INPUT-OUTPUT SECTION. +000130 FILE-CONTROL. +000140 SELECT IN-FILE ASSIGN TO 'INPUT.TXT' +000150 ORGANIZATION IS LINE SEQUENTIAL. +000160 SELECT OUT-FILE ASSIGN TO 'OUTPUT.COB' +000170 ORGANIZATION IS LINE SEQUENTIAL. +000190 DATA DIVISION. +000200 FILE SECTION. +000220 FD IN-FILE. diff --git a/test/expected_dir/cobol1.cbl/cobol/comment b/test/expected_dir/cobol1.cbl/cobol/comment new file mode 100644 index 0000000..24658c2 --- /dev/null +++ b/test/expected_dir/cobol1.cbl/cobol/comment @@ -0,0 +1,7 @@ +000040**************************************************** +000050* Program to add line numbers to typed code * +000060* Allows for comment asterisk, solidus, or hyphen ,* +000070* moving it into position 7. * +000080* * +000090**************************************************** +000185***************************************************** diff --git a/test/expected_dir/cs1.cs/csharp/blanks b/test/expected_dir/cs1.cs/csharp/blanks new file mode 100644 index 0000000..62f9457 --- /dev/null +++ b/test/expected_dir/cs1.cs/csharp/blanks @@ -0,0 +1 @@ +6 \ No newline at end of file diff --git a/test/expected_dir/cs1.cs/csharp/code b/test/expected_dir/cs1.cs/csharp/code new file mode 100644 index 0000000..e99a696 --- /dev/null +++ b/test/expected_dir/cs1.cs/csharp/code @@ -0,0 +1,41 @@ +public delegate void ScoreChangeEventHandler (int newScore, ref bool cancel); +public class Game { +public event ScoreChangeEventHandler ScoreChange; +int score; +public int Score { +get { +return score; +} +set { +if (score != value) { +bool cancel = false; +ScoreChange (value, ref cancel); +if (! cancel) +score = value; +} +} +} +} +public class Referee +{ +public Referee (Game game) { +game.ScoreChange += new ScoreChangeEventHandler (game_ScoreChange); +} +private void game_ScoreChange (int newScore, ref bool cancel) { +if (newScore < 100) +System.Console.WriteLine ("Good Score"); +else { +cancel = true; +System.Console.WriteLine ("No Score can be that high!"); +} +} +} +public class GameTest +{ +public static void Main () { +Game game = new Game (); +Referee referee = new Referee (game); +game.Score = 70; +game.Score = 110; +} +} diff --git a/test/expected_dir/cs1.cs/csharp/comment b/test/expected_dir/cs1.cs/csharp/comment new file mode 100644 index 0000000..b0c67fb --- /dev/null +++ b/test/expected_dir/cs1.cs/csharp/comment @@ -0,0 +1,8 @@ +// The Delegate declaration which defines the signature of methods which can be invoked +// Class which makes the event +// Note the use of the event keyword +// Score Property +// Class which handles the event +// Monitor when a score changes in the game +// Notice how this method signature matches the ScoreChangeEventHandler's signature +// Class to test it all diff --git a/test/expected_dir/css1.css/css/blanks b/test/expected_dir/css1.css/css/blanks new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/test/expected_dir/css1.css/css/blanks @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/test/expected_dir/css1.css/css/code b/test/expected_dir/css1.css/css/code new file mode 100644 index 0000000..433f13a --- /dev/null +++ b/test/expected_dir/css1.css/css/code @@ -0,0 +1,3 @@ +.foo { +padding: 10px; +} diff --git a/test/expected_dir/css1.css/css/comment b/test/expected_dir/css1.css/css/comment new file mode 100644 index 0000000..e69de29 diff --git a/test/expected_dir/d1.d/dmd/blanks b/test/expected_dir/d1.d/dmd/blanks new file mode 100644 index 0000000..7813681 --- /dev/null +++ b/test/expected_dir/d1.d/dmd/blanks @@ -0,0 +1 @@ +5 \ No newline at end of file diff --git a/test/expected_dir/d1.d/dmd/code b/test/expected_dir/d1.d/dmd/code new file mode 100644 index 0000000..160cd23 --- /dev/null +++ b/test/expected_dir/d1.d/dmd/code @@ -0,0 +1,9 @@ +int main(char[][] args) +{ +int w_total; // a comment and code on the same line +this_line_is_code(); +this_line_is_also_code(); +x = `when inside a backtick string, /+ does not begin a nested comment`; +y = `when inside a backtick string, /* does not begin a nested comment`; +z = `when inside a backtick string, // does not begin a nested comment`; +} diff --git a/test/expected_dir/d1.d/dmd/comment b/test/expected_dir/d1.d/dmd/comment new file mode 100644 index 0000000..f5c5aad --- /dev/null +++ b/test/expected_dir/d1.d/dmd/comment @@ -0,0 +1,12 @@ +/* comment block */ +// single-line comment +/+ begin a nestable comment block +/* this comment is nested within another */ +this_code_is_commented_out(); ++/ +/* when inside a c-style block comment, /+ does not start a nested comment */ +// when inside a line comment, /+ does not start a nested comment +/+ when inside a nestable comment, /+ does begin a nested comment +now we close the inner comment +/ +This line is still part of the outer comment +now we close the outer comment +/ diff --git a/test/expected_dir/dylan1.dylan/dylan/blanks b/test/expected_dir/dylan1.dylan/dylan/blanks new file mode 100644 index 0000000..d8263ee --- /dev/null +++ b/test/expected_dir/dylan1.dylan/dylan/blanks @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/expected_dir/dylan1.dylan/dylan/code b/test/expected_dir/dylan1.dylan/dylan/code new file mode 100644 index 0000000..cbeac86 --- /dev/null +++ b/test/expected_dir/dylan1.dylan/dylan/code @@ -0,0 +1,12 @@ +define function describe-list(my-list :: , #key verbose?) => () +format(*standard-output*, "{a , size: %d", my-list.size); +if (verbose?) +format(*standard-output*, ", elements:"); +for (item in my-list) +format(*standard-output*, " %=", item); +end for; +end if; +format(*standard-output*, "}"); +end function; +describe-list(#(1, 2, 3, 4, 5, 6)); +describe-list(#(5, 7, 3), verbose?: #t); diff --git a/test/expected_dir/dylan1.dylan/dylan/comment b/test/expected_dir/dylan1.dylan/dylan/comment new file mode 100644 index 0000000..6687ac5 --- /dev/null +++ b/test/expected_dir/dylan1.dylan/dylan/comment @@ -0,0 +1,3 @@ +// random program i found +// prints "{a , size: 6}" +// prints "{a , size: 3, elements: 5 7 3}" diff --git a/test/expected_dir/el1.el/emacslisp/blanks b/test/expected_dir/el1.el/emacslisp/blanks new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/test/expected_dir/el1.el/emacslisp/blanks @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/test/expected_dir/el1.el/emacslisp/code b/test/expected_dir/el1.el/emacslisp/code new file mode 100644 index 0000000..967f65b --- /dev/null +++ b/test/expected_dir/el1.el/emacslisp/code @@ -0,0 +1,10 @@ +(if (string-equal "21" (substring (emacs-version) 10 12)) +(progn +(blink-cursor-mode 0) +(setq next-line-add-newlines t) +(auto-image-file-mode t) +(menu-bar-mode 1) +(tool-bar-mode nil) +(tooltip-mode nil) +(setq tooltip-delay 0.1) ; default is one second +)) diff --git a/test/expected_dir/el1.el/emacslisp/comment b/test/expected_dir/el1.el/emacslisp/comment new file mode 100644 index 0000000..59bffd7 --- /dev/null +++ b/test/expected_dir/el1.el/emacslisp/comment @@ -0,0 +1,11 @@ +;; Insert newline when you press `C-n' (next-line) +;; at the end of the buffer +;; Turn on image viewing +;; Turn on menu bar (this bar has text) +;; (Use numeric argument to turn on) +;; Turn off tool bar (this bar has icons) +;; (Use numeric argument to turn on) +;; Turn off tooltip mode for tool bar +;; (This mode causes icon explanations to pop up) +;; (Use numeric argument to turn on) +;; If tooltips turned on, make tips appear promptly diff --git a/test/expected_dir/erl1.erl/erlang/blanks b/test/expected_dir/erl1.erl/erlang/blanks new file mode 100644 index 0000000..da2d398 --- /dev/null +++ b/test/expected_dir/erl1.erl/erlang/blanks @@ -0,0 +1 @@ +14 \ No newline at end of file diff --git a/test/expected_dir/erl1.erl/erlang/code b/test/expected_dir/erl1.erl/erlang/code new file mode 100644 index 0000000..3057191 --- /dev/null +++ b/test/expected_dir/erl1.erl/erlang/code @@ -0,0 +1,161 @@ +-module(erl1). +-author('jason@ohloh.net'). +-vsn('$Revision: 1 $ '). +-export([import_file/1, +import_dir/1]). +-include("random.hrl"). +-include("more_random.hrl"). +import_file(File) -> +User = filename:rootname(filename:basename(File)), +Server = filename:basename(filename:dirname(File)), +case (jlib:nodeprep(User) /= error) andalso +(jlib:nameprep(Server) /= error) of +true -> +case file:read_file(File) of +{ok, Text} -> +case xml_stream:parse_element(Text) of +El when element(1, El) == xmlelement -> +case catch process_xdb(User, Server, El) of +{'EXIT', Reason} -> +?ERROR_MSG( +"Error while processing file \"~s\": ~p~n", +[File, Reason]), +{error, Reason}; +_ -> +ok +end; +{error, Reason} -> +?ERROR_MSG("Can't parse file \"~s\": ~p~n", +[File, Reason]), +{error, Reason} +end; +{error, Reason} -> +?ERROR_MSG("Can't read file \"~s\": ~p~n", [File, Reason]), +{error, Reason} +end; +false -> +?ERROR_MSG("Illegal user/server name in file \"~s\"~n", [File]), +{error, "illegal user/server"} +end. +import_dir(Dir) -> +{ok, Files} = file:list_dir(Dir), +MsgFiles = lists:filter( +fun(FN) -> +case string:len(FN) > 4 of +true -> +string:substr(FN, +string:len(FN) - 3) == ".xml"; +_ -> +false +end +end, Files), +lists:foldl( +fun(FN, A) -> +Res = import_file(filename:join([Dir, FN])), +case {A, Res} of +{ok, ok} -> ok; +{ok, _} -> {error, "see aoabberd log for details"}; +_ -> A +end +end, ok, MsgFiles). +process_xdb(User, Server, {xmlelement, Name, _Attrs, Els}) -> +case Name of +"xdb" -> +lists:foreach( +fun(El) -> +xdb_data(User, Server, El) +end, Els); +_ -> +ok +end. +xdb_data(User, Server, {xmlcdata, _CData}) -> +ok; +xdb_data(User, Server, {xmlelement, _Name, Attrs, _Els} = El) -> +From = jlib:make_jid(User, Server, ""), +LServer = jlib:nameprep(Server), +case xml:get_attr_s("xmlns", Attrs) of +?NS_AUTH -> +Password = xml:get_tag_cdata(El), +ejabberd_auth:set_password(User, Server, Password), +ok; +?NS_ROSTER -> +case lists:member(mod_roster_odbc, +gen_mod:loaded_modules(LServer)) of +true -> +catch mod_roster_odbc:set_items(User, Server, El); +false -> +catch mod_roster:set_items(User, Server, El) +end, +ok; +?NS_LAST -> +TimeStamp = xml:get_attr_s("last", Attrs), +Status = xml:get_tag_cdata(El), +case lists:member(mod_last_odbc, +gen_mod:loaded_modules(LServer)) of +true -> +catch mod_last_odbc:store_last_info( +User, +Server, +list_to_integer(TimeStamp), +Status); +false -> +catch mod_last:store_last_info( +User, +Server, +list_to_integer(TimeStamp), +Status) +end, +ok; +?NS_VCARD -> +case lists:member(mod_vcard_odbc, +gen_mod:loaded_modules(LServer)) of +true -> +catch mod_vcard_odbc:process_sm_iq( +From, +jlib:make_jid("", Server, ""), +#iq{type = set, xmlns = ?NS_VCARD, sub_el = El}); +false -> +catch mod_vcard:process_sm_iq( +From, +jlib:make_jid("", Server, ""), +#iq{type = set, xmlns = ?NS_VCARD, sub_el = El}) +end, +ok; +"jabber:x:offline" -> +process_offline(Server, From, El), +ok; +XMLNS -> +case xml:get_attr_s("j_private_flag", Attrs) of +"1" -> +catch mod_private:process_sm_iq( +From, +jlib:make_jid("", Server, ""), +#iq{type = set, xmlns = ?NS_PRIVATE, +sub_el = {xmlelement, "query", [], +[jlib:remove_attr( +"j_private_flag", +jlib:remove_attr("xdbns", El))]}}); +_ -> +?DEBUG("jd2ejd: Unknown namespace \"~s\"~n", [XMLNS]) +end, +ok +end. +process_offline(Server, To, {xmlelement, _, _, Els}) -> +LServer = jlib:nameprep(Server), +lists:foreach(fun({xmlelement, _, Attrs, _} = El) -> +FromS = xml:get_attr_s("from", Attrs), +From = case FromS of +"" -> +jlib:make_jid("", Server, ""); +_ -> +jlib:string_to_jid(FromS) +end, +case From of +error -> +ok; +_ -> +ejabberd_hooks:run(offline_message_hook, +LServer, +[From, To, El]) +end +end, Els). diff --git a/test/expected_dir/erl1.erl/erlang/comment b/test/expected_dir/erl1.erl/erlang/comment new file mode 100644 index 0000000..5a8848b --- /dev/null +++ b/test/expected_dir/erl1.erl/erlang/comment @@ -0,0 +1,14 @@ +%%%---------------------------------------------------------------------- +%%% File : erl1.erl +%%% Author : Jason Allen - kinda - just repurposing random code +%%% Purpose : Test out the erlang parsing +%%% Created : 1/17/2007 by Jason Allen +%%% Id : $Id: erl1.erl 1 2007-17-01 jason $ +%%%---------------------------------------------------------------------- +%% External exports +%%%---------------------------------------------------------------------- +%%% API +%%%---------------------------------------------------------------------- +%%%---------------------------------------------------------------------- +%%% Internal functions +%%%---------------------------------------------------------------------- diff --git a/test/expected_dir/frx1.frx/visualbasic/blanks b/test/expected_dir/frx1.frx/visualbasic/blanks new file mode 100644 index 0000000..d55f9f7 --- /dev/null +++ b/test/expected_dir/frx1.frx/visualbasic/blanks @@ -0,0 +1 @@ +136 \ No newline at end of file diff --git a/test/expected_dir/frx1.frx/visualbasic/code b/test/expected_dir/frx1.frx/visualbasic/code new file mode 100644 index 0000000..05dfafa --- /dev/null +++ b/test/expected_dir/frx1.frx/visualbasic/code @@ -0,0 +1,1729 @@ +VERSION 5.00 +Object = "{67397AA1-7FB1-11D0-B148-00A0C922E820}#6.0#0"; "MSADODC.OCX" +Object = "{BDC217C8-ED16-11CD-956C-0000C04E4C0A}#1.1#0"; "TABCTL32.OCX" +Object = "{CDE57A40-8B86-11D0-B3C6-00A0C90AEA82}#1.0#0"; "MSDATGRD.OCX" +Object = "{0ECD9B60-23AA-11D0-B351-00A0C9055D8E}#6.0#0"; "MSHFLXGD.OCX" +Object = "{831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0#0"; "MSCOMCTL.OCX" +Begin VB.Form frmMain +BorderStyle = 1 'Fixed Single +Caption = "DB2 Visual Basic Samples" +ClientHeight = 6555 +ClientLeft = 150 +ClientTop = 435 +ClientWidth = 10620 +LinkTopic = "Form1" +MaxButton = 0 'False +MinButton = 0 'False +ScaleHeight = 6555 +ScaleWidth = 10620 +StartUpPosition = 3 'Windows Default +Begin VB.CommandButton cmdSample +Caption = "Create Sample DB" +Height = 495 +Left = 8760 +TabIndex = 21 +TabStop = 0 'False +Top = 240 +Width = 1695 +End +Begin TabDlg.SSTab tabMain +Height = 6015 +Left = 0 +TabIndex = 6 +Top = 120 +Width = 8565 +_ExtentX = 15108 +_ExtentY = 10610 +_Version = 393216 +Tabs = 5 +TabsPerRow = 5 +TabHeight = 520 +TabCaption(0) = "Execute SQL" +TabPicture(0) = "Demo.frx":0000 +Tab(0).ControlEnabled= -1 'True +Tab(0).Control(0)= "flxRecords" +Tab(0).Control(0).Enabled= 0 'False +Tab(0).Control(1)= "txtSQL" +Tab(0).Control(1).Enabled= 0 'False +Tab(0).Control(2)= "frmAutoCommit" +Tab(0).Control(2).Enabled= 0 'False +Tab(0).Control(3)= "cmdCommit" +Tab(0).Control(3).Enabled= 0 'False +Tab(0).Control(4)= "cmdRollback" +Tab(0).Control(4).Enabled= 0 'False +Tab(0).Control(5)= "chkAutoCommit" +Tab(0).Control(5).Enabled= 0 'False +Tab(0).Control(6)= "DataGridSQL" +Tab(0).Control(6).Enabled= 0 'False +Tab(0).Control(7)= "frmSamples" +Tab(0).Control(7).Enabled= 0 'False +Tab(0).Control(8)= "frmExecuteSQL" +Tab(0).Control(8).Enabled= 0 'False +Tab(0).Control(9)= "cmdSQLConnection" +Tab(0).Control(9).Enabled= 0 'False +Tab(0).Control(10)= "cmdSQLRecordset" +Tab(0).Control(10).Enabled= 0 'False +Tab(0).Control(11)= "cmdSQLCommand" +Tab(0).Control(11).Enabled= 0 'False +Tab(0).Control(12)= "cmdSQLSamples(0)" +Tab(0).Control(12).Enabled= 0 'False +Tab(0).Control(13)= "cmdSQLSamples(1)" +Tab(0).Control(13).Enabled= 0 'False +Tab(0).Control(14)= "cmdSQLSamples(2)" +Tab(0).Control(14).Enabled= 0 'False +Tab(0).Control(15)= "cmdSQLSamples(3)" +Tab(0).Control(15).Enabled= 0 'False +Tab(0).ControlCount= 16 +TabCaption(1) = "Hierarchical Data" +TabPicture(1) = "Demo.frx":001C +Tab(1).ControlEnabled= 0 'False +Tab(1).Control(0)= "cmdHierarchy" +Tab(1).Control(1)= "hflxRecords" +Tab(1).Control(2)= "lblHierScript" +Tab(1).ControlCount= 3 +TabCaption(2) = "LOBs" +TabPicture(2) = "Demo.frx":0038 +Tab(2).ControlEnabled= 0 'False +Tab(2).Control(0)= "lblEmpno" +Tab(2).Control(1)= "lblLastname" +Tab(2).Control(2)= "lblFirstname" +Tab(2).Control(3)= "AdodcLob" +Tab(2).Control(4)= "cmdCLOB" +Tab(2).Control(5)= "cmdBLOB" +Tab(2).Control(6)= "cmdRefresh" +Tab(2).Control(7)= "txtEmpno" +Tab(2).Control(7).Enabled= 0 'False +Tab(2).Control(8)= "txtLastname" +Tab(2).Control(8).Enabled= 0 'False +Tab(2).Control(9)= "txtFirstname" +Tab(2).Control(9).Enabled= 0 'False +Tab(2).Control(10)= "txtClob" +Tab(2).Control(10).Enabled= 0 'False +Tab(2).Control(11)= "picBlob" +Tab(2).ControlCount= 12 +TabCaption(3) = "Store Procedures" +TabPicture(3) = "Demo.frx":0054 +Tab(3).ControlEnabled= 0 'False +Tab(3).Control(0)= "optStoredProcedures(11)" +Tab(3).Control(1)= "cmdShowSecondRS" +Tab(3).Control(2)= "DataGridSP" +Tab(3).Control(3)= "txtSPResult" +Tab(3).Control(4)= "cmdSPCall" +Tab(3).Control(5)= "optStoredProcedures(10)" +Tab(3).Control(6)= "optStoredProcedures(9)" +Tab(3).Control(7)= "optStoredProcedures(8)" +Tab(3).Control(8)= "optStoredProcedures(7)" +Tab(3).Control(9)= "optStoredProcedures(6)" +Tab(3).Control(10)= "optStoredProcedures(5)" +Tab(3).Control(11)= "optStoredProcedures(4)" +Tab(3).Control(12)= "optStoredProcedures(3)" +Tab(3).Control(13)= "optStoredProcedures(2)" +Tab(3).Control(14)= "optStoredProcedures(1)" +Tab(3).Control(15)= "optStoredProcedures(0)" +Tab(3).Control(16)= "frmStoredProcedures" +Tab(3).ControlCount= 17 +TabCaption(4) = "UDFs" +TabPicture(4) = "Demo.frx":0070 +Tab(4).ControlEnabled= 0 'False +Tab(4).Control(0)= "cmdUDFs(5)" +Tab(4).Control(1)= "cmdUDFs(4)" +Tab(4).Control(2)= "cmdUDFs(3)" +Tab(4).Control(3)= "cmdUDFs(2)" +Tab(4).Control(4)= "cmdUDFs(1)" +Tab(4).Control(5)= "cmdUDFs(0)" +Tab(4).Control(6)= "hflxGridUDF" +Tab(4).Control(7)= "txtUDF" +Tab(4).Control(7).Enabled= 0 'False +Tab(4).Control(8)= "Frame1" +Tab(4).ControlCount= 9 +Begin VB.CommandButton cmdSQLSamples +Caption = "Sample 4" +Enabled = 0 'False +Height = 375 +Index = 3 +Left = 7440 +TabIndex = 67 +Top = 2880 +Width = 855 +End +Begin VB.CommandButton cmdSQLSamples +Caption = "Sample 3" +Enabled = 0 'False +Height = 375 +Index = 2 +Left = 6600 +TabIndex = 66 +Top = 2880 +Width = 855 +End +Begin VB.CommandButton cmdSQLSamples +Caption = "Sample 2" +Enabled = 0 'False +Height = 375 +Index = 1 +Left = 7440 +TabIndex = 65 +Top = 2520 +Width = 855 +End +Begin VB.CommandButton cmdSQLSamples +Caption = "Sample 1" +Enabled = 0 'False +Height = 375 +Index = 0 +Left = 6600 +TabIndex = 64 +Top = 2520 +Width = 855 +End +Begin VB.CommandButton cmdUDFs +Caption = "TableUDF" +Enabled = 0 'False +Height = 495 +Index = 5 +Left = -68400 +TabIndex = 63 +Top = 3600 +Width = 1695 +End +Begin VB.CommandButton cmdUDFs +Caption = "SourcedColumnUDF" +Enabled = 0 'False +Height = 495 +Index = 4 +Left = -68400 +TabIndex = 62 +Top = 3000 +Width = 1695 +End +Begin VB.CommandButton cmdUDFs +Caption = "ScUDFReturningErr" +Enabled = 0 'False +Height = 495 +Index = 3 +Left = -68400 +TabIndex = 61 +Top = 2400 +Width = 1695 +End +Begin VB.CommandButton cmdUDFs +Caption = "ScratchpadScUDF" +Enabled = 0 'False +Height = 495 +Index = 2 +Left = -68400 +TabIndex = 60 +Top = 1800 +Width = 1695 +End +Begin VB.CommandButton cmdUDFs +Caption = "ClobScalarUDF" +Enabled = 0 'False +Height = 495 +Index = 1 +Left = -68400 +TabIndex = 59 +Top = 1200 +Width = 1695 +End +Begin VB.CommandButton cmdUDFs +Caption = "ScalarUDF" +Enabled = 0 'False +Height = 495 +Index = 0 +Left = -68400 +TabIndex = 58 +Top = 600 +Width = 1695 +End +Begin MSHierarchicalFlexGridLib.MSHFlexGrid hflxGridUDF +Height = 1575 +Left = -74880 +TabIndex = 57 +TabStop = 0 'False +Top = 4320 +Width = 6255 +_ExtentX = 11033 +_ExtentY = 2778 +_Version = 393216 +FixedCols = 0 +WordWrap = -1 'True +AllowUserResizing= 1 +_NumberOfBands = 1 +_Band(0).Cols = 2 +End +Begin VB.TextBox txtUDF +BeginProperty Font +Name = "Courier New" +Size = 9 +Charset = 0 +Weight = 400 +Underline = 0 'False +Italic = 0 'False +Strikethrough = 0 'False +EndProperty +Height = 3735 +Left = -74880 +Locked = -1 'True +MultiLine = -1 'True +ScrollBars = 2 'Vertical +TabIndex = 56 +TabStop = 0 'False +Top = 480 +Width = 6255 +End +Begin VB.Frame Frame1 +Caption = "Work with UDF:" +Height = 5535 +Left = -68520 +TabIndex = 55 +Top = 360 +Width = 1935 +End +Begin VB.OptionButton optStoredProcedures +Caption = "MAIN_EXAMPLE" +Enabled = 0 'False +Height = 495 +Index = 11 +Left = -69000 +TabIndex = 54 +Top = 1320 +Width = 1935 +End +Begin VB.CommandButton cmdShowSecondRS +Caption = "Show Next RS" +Height = 495 +Left = -68280 +TabIndex = 53 +Top = 2640 +Visible = 0 'False +Width = 1695 +End +Begin MSDataGridLib.DataGrid DataGridSP +Height = 3788 +Left = -74850 +TabIndex = 37 +Top = 2070 +Visible = 0 'False +Width = 6428 +_ExtentX = 11351 +_ExtentY = 6694 +_Version = 393216 +BorderStyle = 0 +Enabled = -1 'True +HeadLines = 1 +RowHeight = 15 +RowDividerStyle = 1 +AllowAddNew = -1 'True +AllowDelete = -1 'True +BeginProperty HeadFont {0BE35203-8F91-11CE-9DE3-00AA004BB851} +Name = "MS Sans Serif" +Size = 8.25 +Charset = 0 +Weight = 400 +Underline = 0 'False +Italic = 0 'False +Strikethrough = 0 'False +EndProperty +BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851} +Name = "MS Sans Serif" +Size = 8.25 +Charset = 0 +Weight = 400 +Underline = 0 'False +Italic = 0 'False +Strikethrough = 0 'False +EndProperty +ColumnCount = 2 +BeginProperty Column00 +DataField = "" +Caption = "" +BeginProperty DataFormat {6D835690-900B-11D0-9484-00A0C91110ED} +Type = 0 +Format = "" +HaveTrueFalseNull= 0 +FirstDayOfWeek = 0 +FirstWeekOfYear = 0 +LCID = 1033 +SubFormatType = 0 +EndProperty +EndProperty +BeginProperty Column01 +DataField = "" +Caption = "" +BeginProperty DataFormat {6D835690-900B-11D0-9484-00A0C91110ED} +Type = 0 +Format = "" +HaveTrueFalseNull= 0 +FirstDayOfWeek = 0 +FirstWeekOfYear = 0 +LCID = 1033 +SubFormatType = 0 +EndProperty +EndProperty +SplitCount = 1 +BeginProperty Split0 +BeginProperty Column00 +EndProperty +BeginProperty Column01 +EndProperty +EndProperty +End +Begin VB.TextBox txtSPResult +BeginProperty Font +Name = "Courier New" +Size = 9 +Charset = 0 +Weight = 400 +Underline = 0 'False +Italic = 0 'False +Strikethrough = 0 'False +EndProperty +Height = 3855 +Left = -74880 +MultiLine = -1 'True +TabIndex = 52 +Top = 2040 +Width = 6495 +End +Begin VB.CommandButton cmdSPCall +Caption = "Call" +Enabled = 0 'False +Height = 495 +Left = -68280 +TabIndex = 51 +Top = 2040 +Width = 1695 +End +Begin VB.OptionButton optStoredProcedures +Caption = "DBINFO_EXAMPLE" +Enabled = 0 'False +Height = 495 +Index = 10 +Left = -70920 +TabIndex = 50 +Top = 1320 +Width = 1935 +End +Begin VB.OptionButton optStoredProcedures +Caption = "DB2SQL_EXAMPLE" +Enabled = 0 'False +Height = 495 +Index = 9 +Left = -72840 +TabIndex = 49 +Top = 1320 +Width = 1935 +End +Begin VB.OptionButton optStoredProcedures +Caption = "CLOB_EXTRACT" +Enabled = 0 'False +Height = 495 +Index = 8 +Left = -74760 +TabIndex = 48 +Top = 1320 +Width = 1935 +End +Begin VB.OptionButton optStoredProcedures +Caption = "TWO_RESULT_SETS" +Enabled = 0 'False +Height = 495 +Index = 7 +Left = -69000 +TabIndex = 47 +Top = 960 +Width = 1935 +End +Begin VB.OptionButton optStoredProcedures +Caption = "ONE_RESULT_SET" +Enabled = 0 'False +Height = 495 +Index = 6 +Left = -70920 +TabIndex = 46 +Top = 960 +Width = 1935 +End +Begin VB.OptionButton optStoredProcedures +Caption = "DECIMAL_TYPE" +Enabled = 0 'False +Height = 495 +Index = 5 +Left = -72840 +TabIndex = 45 +Top = 960 +Width = 1935 +End +Begin VB.OptionButton optStoredProcedures +Caption = "ALL_DATA_TYPES" +Enabled = 0 'False +Height = 495 +Index = 4 +Left = -74760 +TabIndex = 44 +Top = 960 +Width = 1935 +End +Begin VB.OptionButton optStoredProcedures +Caption = "INOUT_PARAM" +Enabled = 0 'False +Height = 495 +Index = 3 +Left = -69000 +TabIndex = 43 +Top = 600 +Width = 1935 +End +Begin VB.OptionButton optStoredProcedures +Caption = "OUT_PARAM" +Enabled = 0 'False +Height = 495 +Index = 2 +Left = -70920 +TabIndex = 42 +Top = 600 +Width = 1935 +End +Begin VB.OptionButton optStoredProcedures +Caption = "IN_PARAMS" +Enabled = 0 'False +Height = 495 +Index = 1 +Left = -72840 +TabIndex = 41 +Top = 600 +Width = 1935 +End +Begin VB.OptionButton optStoredProcedures +Caption = "OUT_LANGUAGE" +Enabled = 0 'False +Height = 495 +Index = 0 +Left = -74760 +TabIndex = 40 +Top = 600 +Width = 1935 +End +Begin VB.Frame frmStoredProcedures +Caption = "Stored Procedure:" +Height = 1575 +Left = -74880 +TabIndex = 39 +Top = 360 +Width = 8295 +End +Begin VB.CommandButton cmdSQLCommand +Caption = "on Command" +Enabled = 0 'False +Height = 495 +Left = 6600 +TabIndex = 35 +Top = 1200 +Width = 1695 +End +Begin VB.CommandButton cmdSQLRecordset +Caption = "on Recordset" +Enabled = 0 'False +Height = 495 +Left = 6600 +TabIndex = 34 +Top = 1800 +Width = 1695 +End +Begin VB.CommandButton cmdSQLConnection +Caption = "on Connection" +Enabled = 0 'False +Height = 495 +Left = 6600 +TabIndex = 8 +Top = 600 +Width = 1695 +End +Begin VB.Frame frmExecuteSQL +Caption = "Execute SQL" +Height = 2055 +Left = 6480 +TabIndex = 32 +Top = 360 +Width = 1935 +End +Begin VB.Frame frmSamples +Height = 1095 +Left = 6480 +TabIndex = 38 +Top = 2280 +Width = 1935 +End +Begin MSDataGridLib.DataGrid DataGridSQL +Height = 3690 +Left = 150 +TabIndex = 36 +Top = 2190 +Width = 6200 +_ExtentX = 10927 +_ExtentY = 6509 +_Version = 393216 +BorderStyle = 0 +HeadLines = 1 +RowHeight = 15 +RowDividerStyle = 1 +AllowAddNew = -1 'True +AllowDelete = -1 'True +BeginProperty HeadFont {0BE35203-8F91-11CE-9DE3-00AA004BB851} +Name = "MS Sans Serif" +Size = 8.25 +Charset = 0 +Weight = 400 +Underline = 0 'False +Italic = 0 'False +Strikethrough = 0 'False +EndProperty +BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851} +Name = "MS Sans Serif" +Size = 8.25 +Charset = 0 +Weight = 400 +Underline = 0 'False +Italic = 0 'False +Strikethrough = 0 'False +EndProperty +ColumnCount = 2 +BeginProperty Column00 +DataField = "" +Caption = "" +BeginProperty DataFormat {6D835690-900B-11D0-9484-00A0C91110ED} +Type = 0 +Format = "" +HaveTrueFalseNull= 0 +FirstDayOfWeek = 0 +FirstWeekOfYear = 0 +LCID = 1033 +SubFormatType = 0 +EndProperty +EndProperty +BeginProperty Column01 +DataField = "" +Caption = "" +BeginProperty DataFormat {6D835690-900B-11D0-9484-00A0C91110ED} +Type = 0 +Format = "" +HaveTrueFalseNull= 0 +FirstDayOfWeek = 0 +FirstWeekOfYear = 0 +LCID = 1033 +SubFormatType = 0 +EndProperty +EndProperty +SplitCount = 1 +BeginProperty Split0 +BeginProperty Column00 +EndProperty +BeginProperty Column01 +EndProperty +EndProperty +End +Begin VB.CheckBox chkAutoCommit +Caption = " AutoCommit" +Enabled = 0 'False +Height = 255 +Left = 6840 +TabIndex = 31 +Top = 4320 +Value = 1 'Checked +Width = 1215 +End +Begin VB.CommandButton cmdRollback +Caption = "Rollback" +Enabled = 0 'False +Height = 495 +Left = 6600 +TabIndex = 10 +Top = 5280 +Width = 1695 +End +Begin VB.CommandButton cmdCommit +Caption = "Commit" +Enabled = 0 'False +Height = 495 +Left = 6600 +TabIndex = 9 +Top = 4680 +Width = 1695 +End +Begin VB.Frame frmAutoCommit +Height = 1575 +Left = 6480 +TabIndex = 33 +Top = 4320 +Width = 1935 +End +Begin VB.PictureBox picBlob +BackColor = &H80000005& +Height = 5405 +Left = -74870 +ScaleHeight = 5340 +ScaleWidth = 6420 +TabIndex = 30 +Top = 490 +Visible = 0 'False +Width = 6480 +End +Begin VB.TextBox txtClob +BeginProperty Font +Name = "Courier New" +Size = 8.25 +Charset = 0 +Weight = 400 +Underline = 0 'False +Italic = 0 'False +Strikethrough = 0 'False +EndProperty +Height = 5415 +Left = -74880 +Locked = -1 'True +MultiLine = -1 'True +ScrollBars = 3 'Both +TabIndex = 23 +TabStop = 0 'False +Top = 480 +Width = 6495 +End +Begin VB.TextBox txtFirstname +Appearance = 0 'Flat +BackColor = &H80000013& +Enabled = 0 'False +Height = 285 +Left = -68280 +Locked = -1 'True +TabIndex = 26 +TabStop = 0 'False +Top = 5040 +Width = 1695 +End +Begin VB.TextBox txtLastname +Appearance = 0 'Flat +BackColor = &H80000013& +Enabled = 0 'False +Height = 285 +Left = -68280 +Locked = -1 'True +TabIndex = 25 +TabStop = 0 'False +Top = 4440 +Width = 1695 +End +Begin VB.TextBox txtEmpno +Appearance = 0 'Flat +BackColor = &H80000013& +Enabled = 0 'False +Height = 285 +Left = -68280 +Locked = -1 'True +TabIndex = 24 +TabStop = 0 'False +Top = 3840 +Width = 1695 +End +Begin VB.CommandButton cmdRefresh +Caption = "Refresh Data" +Enabled = 0 'False +Height = 495 +Left = -68280 +TabIndex = 12 +Top = 480 +Width = 1695 +End +Begin VB.CommandButton cmdBLOB +Caption = "Show Picture" +Enabled = 0 'False +Height = 495 +Left = -68280 +TabIndex = 14 +Top = 1680 +Width = 1695 +End +Begin VB.CommandButton cmdCLOB +Caption = "Show Resume" +Enabled = 0 'False +Height = 495 +Left = -68280 +TabIndex = 13 +Top = 1080 +Width = 1695 +End +Begin VB.CommandButton cmdHierarchy +Caption = "Display" +Enabled = 0 'False +Height = 495 +Left = -68280 +TabIndex = 11 +Top = 480 +Width = 1695 +End +Begin VB.TextBox txtSQL +BeginProperty Font +Name = "Courier New" +Size = 9 +Charset = 0 +Weight = 400 +Underline = 0 'False +Italic = 0 'False +Strikethrough = 0 'False +EndProperty +Height = 1575 +Left = 120 +MultiLine = -1 'True +ScrollBars = 2 'Vertical +TabIndex = 7 +Top = 480 +Width = 6255 +End +Begin MSHierarchicalFlexGridLib.MSHFlexGrid hflxRecords +Height = 4815 +Left = -74880 +TabIndex = 17 +TabStop = 0 'False +Top = 1080 +Width = 8295 +_ExtentX = 14631 +_ExtentY = 8493 +_Version = 393216 +FixedCols = 0 +WordWrap = -1 'True +AllowUserResizing= 1 +_NumberOfBands = 1 +_Band(0).Cols = 2 +End +Begin MSHierarchicalFlexGridLib.MSHFlexGrid flxRecords +Height = 3735 +Left = 120 +TabIndex = 16 +TabStop = 0 'False +Top = 2160 +Width = 6255 +_ExtentX = 11033 +_ExtentY = 6588 +_Version = 393216 +FixedCols = 0 +WordWrap = -1 'True +AllowUserResizing= 1 +_NumberOfBands = 1 +_Band(0).Cols = 2 +End +Begin MSAdodcLib.Adodc AdodcLob +Height = 330 +Left = -68280 +Top = 5520 +Width = 1695 +_ExtentX = 2990 +_ExtentY = 582 +ConnectMode = 1 +CursorLocation = 3 +IsolationLevel = -1 +ConnectionTimeout= 15 +CommandTimeout = 30 +CursorType = 3 +LockType = 3 +CommandType = 8 +CursorOptions = 0 +CacheSize = 50 +MaxRecords = 0 +BOFAction = 0 +EOFAction = 0 +ConnectStringType= 1 +Appearance = 1 +BackColor = -2147483643 +ForeColor = -2147483640 +Orientation = 0 +Enabled = 0 +Connect = "" +OLEDBString = "" +OLEDBFile = "" +DataSourceName = "" +OtherAttributes = "" +UserName = "" +Password = "" +RecordSource = "" +Caption = "" +BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851} +Name = "MS Sans Serif" +Size = 8.25 +Charset = 0 +Weight = 400 +Underline = 0 'False +Italic = 0 'False +Strikethrough = 0 'False +EndProperty +_Version = 393216 +End +Begin VB.Label lblHierScript +Caption = $"Demo.frx":008C +ForeColor = &H80000011& +Height = 495 +Left = -74760 +TabIndex = 68 +Top = 540 +Width = 6135 +End +Begin VB.Label lblFirstname +Caption = "First Name:" +Height = 255 +Left = -68280 +TabIndex = 29 +Top = 4800 +Width = 1695 +End +Begin VB.Label lblLastname +Caption = "Last Name:" +Height = 255 +Left = -68280 +TabIndex = 28 +Top = 4200 +Width = 1695 +End +Begin VB.Label lblEmpno +Caption = "Employee No.:" +Height = 255 +Left = -68280 +TabIndex = 27 +Top = 3600 +Width = 1695 +End +End +Begin VB.CommandButton cmdVersionInfo +Caption = "Get Environment Info" +Enabled = 0 'False +Height = 495 +Left = 8760 +TabIndex = 3 +Top = 840 +Width = 1695 +End +Begin VB.CommandButton cmdConnectInfo +Caption = "Get Connection Info" +Enabled = 0 'False +Height = 495 +Left = 8760 +TabIndex = 4 +Top = 4200 +Width = 1695 +End +Begin VB.CommandButton cmdConnectDataShape +Caption = "Connect DataShape" +Height = 495 +Left = 8760 +TabIndex = 2 +Top = 3600 +Width = 1695 +End +Begin VB.CommandButton cmdConnectODBC +Caption = "Connect ODBC" +Height = 495 +Left = 8760 +TabIndex = 1 +Top = 3000 +Width = 1695 +End +Begin VB.CommandButton cmdDisconnect +Caption = "Disconnect" +Enabled = 0 'False +Height = 495 +Left = 8760 +TabIndex = 5 +Top = 4800 +Width = 1695 +End +Begin VB.CommandButton cmdConnectOLEDB +Caption = "Connect OLE DB" +Height = 495 +Left = 8760 +TabIndex = 0 +Top = 2400 +Width = 1695 +End +Begin VB.Frame frmConnection +Caption = "Connection:" +Height = 3255 +Left = 8640 +TabIndex = 18 +Top = 2160 +Width = 1935 +End +Begin VB.CommandButton cmdExit +Caption = "Exit" +Height = 495 +Left = 8760 +TabIndex = 15 +Top = 5520 +Width = 1695 +End +Begin VB.Frame fmExit +Height = 855 +Left = 8640 +TabIndex = 19 +Top = 5280 +Width = 1935 +End +Begin MSComctlLib.StatusBar sbrStatus +Align = 2 'Align Bottom +Height = 375 +Left = 0 +TabIndex = 20 +Top = 6180 +Width = 10620 +_ExtentX = 18733 +_ExtentY = 661 +_Version = 393216 +BeginProperty Panels {8E3867A5-8586-11D1-B16A-00C0F0283628} +NumPanels = 1 +BeginProperty Panel1 {8E3867AB-8586-11D1-B16A-00C0F0283628} +AutoSize = 1 +Object.Width = 18680 +EndProperty +EndProperty +BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851} +Name = "MS Sans Serif" +Size = 9.75 +Charset = 0 +Weight = 400 +Underline = 0 'False +Italic = 0 'False +Strikethrough = 0 'False +EndProperty +End +Begin VB.Frame frmEnvironment +Caption = "Environment:" +Height = 1455 +Left = 8640 +TabIndex = 22 +Top = 0 +Width = 1935 +End +End +Attribute VB_Name = "frmMain" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +Option Explicit +Private con As ADODB.Connection +Private rst As ADODB.Recordset +Private strMsgText As String +Private wShowInstructions As Integer +Private Sub cmdConnectOLEDB_Click() +Set con = ConnectOLEDB() +sbrStatus.Panels(1).Text = "Connect to sample database succeeded!" +EnableButtons +If wShowInstructions = vbYes Then +ShowConnectionInstruction +End If +cmdConnectOLEDB_Exit: +Exit Sub +cmdConnectOLEDB_Error: +sbrStatus.Panels(1).Text = "ERROR: " & Err.Description +If wShowInstructions = vbYes Then +MsgBox "Connect to sample database failed!" & vbCr & _ +Err.Description & vbCr & _ +"Please correct the problem and try again.", _ +vbOKOnly + vbCritical, "Instruction" +End If +Resume cmdConnectOLEDB_Exit +End Sub +Private Sub cmdConnectODBC_Click() +On Error GoTo cmdConnectODBC_Error +Set con = ConnectODBC() +sbrStatus.Panels(1).Text = "Connect to sample database succeeded!" +EnableButtons +If wShowInstructions = vbYes Then +ShowConnectionInstruction +End If +cmdConnectODBC_Exit: +Exit Sub +cmdConnectODBC_Error: +sbrStatus.Panels(1).Text = "ERROR: " & Err.Description +If wShowInstructions = vbYes Then +MsgBox "Connect to sample database failed!" & vbCr & _ +Err.Description & vbCr & _ +"Please correct the problem and try again.", _ +vbOKOnly + vbCritical, "Instruction" +End If +Resume cmdConnectODBC_Exit +End Sub +Private Sub cmdConnectDataShape_Click() +On Error GoTo cmdConnectDataShape_Error +Set con = ConnectDataShape() +con.Attributes = adXactCommitRetaining + adXactAbortRetaining +sbrStatus.Panels(1).Text = "Connect to sample database succeeded!" +EnableButtons +cmdHierarchy.Enabled = True +lblHierScript.ForeColor = vbButtonText +If wShowInstructions = vbYes Then +ShowConnectionInstruction +End If +cmdConnectDataShape_Exit: +Exit Sub +cmdConnectDataShape_Error: +sbrStatus.Panels(1).Text = "ERROR: " & Err.Description +If wShowInstructions = vbYes Then +MsgBox "Connect to sample database failed!" & vbCr & _ +Err.Description & vbCr & _ +"Please correct the problem and try again.", _ +vbOKOnly + vbCritical, "Instruction" +End If +Resume cmdConnectDataShape_Exit +End Sub +Private Sub EnableButtons() +Dim tmpButton As CommandButton +cmdConnectOLEDB.Enabled = False +cmdConnectODBC.Enabled = False +cmdConnectDataShape.Enabled = False +cmdHierarchy.Enabled = False +lblHierScript.ForeColor = vbGrayText +cmdSample.Enabled = False +cmdConnectInfo.Enabled = True +cmdVersionInfo.Enabled = True +cmdDisconnect.Enabled = True +cmdRefresh.Enabled = True +cmdSQLConnection.Enabled = True +cmdSQLRecordset.Enabled = True +cmdSQLCommand.Enabled = True +For Each tmpButton In cmdSQLSamples +tmpButton.Enabled = True +Next +cmdCommit.Enabled = False +cmdRollback.Enabled = False +chkAutoCommit.Enabled = True +CheckAvailableStoredProcedures +For Each tmpButton In cmdUDFs +tmpButton.Enabled = True +Next +End Sub +Private Sub ShowConnectionInstruction() +MsgBox "Connect to sample database succeeded!" & vbCr & _ +"You may choose a Tab for specific functional demonstration," & vbCr & _ +"or press one of the info buttons for more information.", _ +vbOKOnly, "Instruction" +End Sub +Private Sub cmdDisconnect_Click() +On Error GoTo cmdDisconnect_Error +Set rst = Nothing +Set DataGridSQL.DataSource = Nothing +Set hflxRecords.DataSource = Nothing +DataGridSQL.ClearFields +hflxRecords.Clear +picBlob.Visible = False +txtClob.Text = "" +txtEmpno.Text = "" +txtLastname.Text = "" +txtFirstname.Text = "" +AdodcLob.Caption = "" +chkAutoCommit.Value = 1 +DataGridSP.Visible = False +txtSPResult.Text = "" +txtUDF.Text = "" +hflxGridUDF.Clear +sbrStatus.Panels(1).Text = Disconnect(con) +Dim tmpButton As CommandButton +cmdConnectOLEDB.Enabled = True +cmdConnectODBC.Enabled = True +cmdConnectDataShape.Enabled = True +cmdSample.Enabled = True +cmdDisconnect.Enabled = False +cmdHierarchy.Enabled = False +lblHierScript.ForeColor = vbGrayText +cmdConnectInfo.Enabled = False +cmdVersionInfo.Enabled = False +cmdSQLConnection.Enabled = False +cmdSQLRecordset.Enabled = False +cmdSQLCommand.Enabled = False +For Each tmpButton In cmdSQLSamples +tmpButton.Enabled = False +Next +cmdCommit.Enabled = False +cmdRollback.Enabled = False +chkAutoCommit.Enabled = False +cmdRefresh.Enabled = False +cmdBLOB.Enabled = False +cmdCLOB.Enabled = False +AdodcLob.Enabled = False +cmdSPCall.Enabled = False +CheckAvailableStoredProcedures +For Each tmpButton In cmdUDFs +tmpButton.Enabled = False +Next +If wShowInstructions = vbYes Then +MsgBox "Sample Database is disconnected!" & vbCr & _ +"You may now choose one of the connections again.", _ +vbOKOnly, "Instruction" +End If +cmdDisconnect_Exit: +Set rst = Nothing +Set con = Nothing +Exit Sub +cmdDisconnect_Error: +sbrStatus.Panels(1).Text = "ERROR: " & Err.Description +If wShowInstructions = vbYes Then +MsgBox "Disconnect from sample database failed!" & vbCr & _ +Err.Description & vbCr & _ +"Please correct the problem and try again.", _ +vbOKOnly + vbCritical, "Instruction" +End If +Resume cmdDisconnect_Exit +End Sub +Private Sub cmdConnectInfo_Click() +sbrStatus.Panels(1).Text = "" +MsgBox ConnectInfo(con), vbOKOnly, "Connection Information" +End Sub +Private Sub cmdVersionInfo_Click() +sbrStatus.Panels(1).Text = "" +MsgBox VersionInfo(con), vbOKOnly, "Versions Information" +End Sub +Private Sub cmdExit_Click() +chkAutoCommit.Value = 1 +Set hflxRecords.DataSource = Nothing +Set DataGridSQL.DataSource = Nothing +Set rst = Nothing +Set con = Nothing +Unload Me +End Sub +Private Sub cmdSample_Click() +On Error GoTo cmdSample_Error +sbrStatus.Panels(1).Text = "Creating the sample database, please wait..." +CreateSample +sbrStatus.Panels(1).Text = "Create the sample database is done." +If wShowInstructions = vbYes Then +MsgBox "The sample database has been created!" & vbCr & _ +"You may now choose one of the connections.", _ +vbOKOnly, "Instruction" +End If +cmdSample_Exit: +Exit Sub +cmdSample_Error: +sbrStatus.Panels(1).Text = "ERROR: " & Err.Description +If wShowInstructions = vbYes Then +MsgBox "Create sample database failed!" & vbCr & _ +Err.Description & vbCr & _ +"Please correct the problem and try again.", _ +vbOKOnly + vbCritical, "Instruction" +End If +Resume cmdSample_Exit +End Sub +Private Sub cmdSQLConnection_Click() +On Error GoTo cmdSQLConnection_Error +DataGridSQL.ClearFields +Set rst = ExecuteSQLConnect(txtSQL, strMsgText, con) +Set DataGridSQL.DataSource = rst +sbrStatus.Panels(1).Text = strMsgText +cmdSQLConnection_Exit: +Exit Sub +cmdSQLConnection_Error: +sbrStatus.Panels(1).Text = "ERROR: " & Err.Description +Resume cmdSQLConnection_Exit +End Sub +Private Sub cmdSQLCommand_Click() +On Error GoTo cmdSQLCommand_Error +DataGridSQL.ClearFields +Set rst = ExecuteSQLCommand(txtSQL, strMsgText, con) +Set DataGridSQL.DataSource = rst +sbrStatus.Panels(1).Text = strMsgText +cmdSQLCommand_Exit: +Exit Sub +cmdSQLCommand_Error: +sbrStatus.Panels(1).Text = "ERROR: " & Err.Description +Resume cmdSQLCommand_Exit +End Sub +Private Sub cmdSQLRecordset_Click() +On Error GoTo cmdSQLRecordset_Error +DataGridSQL.ClearFields +Set rst = ExecuteSQLRecordset(txtSQL, strMsgText, con) +Set DataGridSQL.DataSource = rst +DataGridSQL.SetFocus +sbrStatus.Panels(1).Text = strMsgText +cmdSQLRecordset_Exit: +Exit Sub +cmdSQLRecordset_Error: +sbrStatus.Panels(1).Text = "ERROR: " & Err.Description +Resume cmdSQLRecordset_Exit +End Sub +Private Sub DataGridSQL_Error(ByVal DataError As Integer, Response As Integer) +If wShowInstructions = vbYes Then +MsgBox _ +"If errors keep happening," & vbCr & _ +"You may press [Disconnect] to clear errors.", _ +vbOKOnly, "Instruction" +End If +sbrStatus.Panels(1).Text = "Press [Disconnect] to clear continuous errors." +End Sub +Private Sub cmdSQLSamples_Click(Index As Integer) +Select Case Index +Case 0 +txtSQL.Text = "SELECT * FROM employee" +Case 1 +txtSQL.Text = "SELECT firstnme, job, hiredate" & vbCrLf & _ +"FROM employee" & vbCrLf & _ +"WHERE workdept = 'D11'" & vbCrLf & _ +"ORDER BY hiredate" +Case 2 +txtSQL.Text = "SELECT firstnme, job, salary + comm AS pay" & vbCrLf & _ +"FROM employee" & vbCrLf & _ +"WHERE (salary + comm) < 25000" & vbCrLf & _ +"ORDER BY pay DESC" +Case 3 +txtSQL.Text = "SELECT workdept," & vbCrLf & _ +" MAX(salary) AS maximum," & vbCrLf & _ +" MIN(salary) As minimum" & vbCrLf & _ +"FROM employee GROUP BY workdept ORDER BY workdept" +Case Else +End Select +End Sub +Private Sub cmdSQLSamples_GotFocus(Index As Integer) +Set DataGridSQL.DataSource = Nothing +sbrStatus.Panels(1).Text = "" +End Sub +Private Sub chkAutoCommit_Click() +On Error GoTo chkAutoCommit_Error +If chkAutoCommit.Value = 0 Then +AutoCommitOff con +cmdCommit.Enabled = True +cmdRollback.Enabled = True +sbrStatus.Panels(1).Text = "AutoCommit mode is OFF." +Else +strMsgText = "Commit all previous changes (if any)?" +If MsgBox(strMsgText, vbYesNo, "Turn Autocommit ON") = vbYes Then +Commit con +Else +Rollback con +End If +cmdCommit.Enabled = False +cmdRollback.Enabled = False +sbrStatus.Panels(1).Text = "AutoCommit mode is ON." +End If +chkAutoCommit_Exit: +RefreshDataGridSQL +Exit Sub +chkAutoCommit_Error: +sbrStatus.Panels(1).Text = "ERROR: " & Err.Description +Resume chkAutoCommit_Exit +End Sub +Private Sub cmdCommit_Click() +On Error GoTo cmdCommit_Error +If chkAutoCommit.Value = 0 Then +Commit con +AutoCommitOff con +End If +sbrStatus.Panels(1).Text = "Commit transactions succeeded." +cmdCommit_Exit: +RefreshDataGridSQL +Exit Sub +cmdCommit_Error: +sbrStatus.Panels(1).Text = "ERROR: " & Err.Description +Resume cmdCommit_Exit +End Sub +Private Sub cmdRollback_Click() +On Error GoTo cmdRollback_Error +If chkAutoCommit.Value = 0 Then +Rollback con +AutoCommitOff con +End If +sbrStatus.Panels(1).Text = "Rollback transactions succeeded." +cmdRollback_Exit: +RefreshDataGridSQL +Exit Sub +cmdRollback_Error: +sbrStatus.Panels(1).Text = "ERROR: " & Err.Description +Resume cmdRollback_Exit +End Sub +Private Sub RefreshDataGridSQL() +If Not DataGridSQL.DataSource Is Nothing Then +Set DataGridSQL.DataSource = Nothing +rst.Requery +Set DataGridSQL.DataSource = rst +End If +End Sub +Private Sub cmdHierarchy_Click() +hflxRecords.Clear +Set hflxRecords.DataSource = ExecuteHSQL(strMsgText, con) +sbrStatus.Panels(1).Text = strMsgText +End Sub +Private Sub cmdRefresh_Click() +On Error GoTo cmdRefresh_Error +GetLOB con, AdodcLob +AdodcLob.Refresh +txtClob.DataField = "RESUME" +Set txtClob.DataSource = AdodcLob +picBlob.DataField = "PICTURE" +Set picBlob.DataSource = AdodcLob +txtEmpno.DataField = "EMPNO" +Set txtEmpno.DataSource = AdodcLob +txtLastname.DataField = "LASTNAME" +Set txtLastname.DataSource = AdodcLob +txtFirstname.DataField = "FIRSTNME" +Set txtFirstname.DataSource = AdodcLob +cmdBLOB.Enabled = True +cmdCLOB.Enabled = True +AdodcLob.Enabled = True +cmdRefresh_Exit: +Exit Sub +cmdRefresh_Error: +sbrStatus.Panels(1).Text = "ERROR: " & Err.Description +AdodcLob.Enabled = False +cmdBLOB.Enabled = False +cmdCLOB.Enabled = False +Resume cmdRefresh_Exit +End Sub +Private Sub cmdBLOB_Click() +picBlob.Visible = True +End Sub +Private Sub cmdCLOB_Click() +picBlob.Visible = False +End Sub +Private Sub AdodcLob_MoveComplete(ByVal adReason As ADODB.EventReasonEnum, ByVal pError As ADODB.Error, adStatus As ADODB.EventStatusEnum, ByVal pRecordset As ADODB.Recordset) +AdodcLob.Caption = AdodcLob.Recordset.AbsolutePosition +End Sub +Private Sub CheckAvailableStoredProcedures() +Dim optStoredProcedure As Variant +Dim proToken As ADOX.Procedure +Dim pros As ADOX.Procedures +Set pros = GetProcedures(con) +For Each optStoredProcedure In optStoredProcedures +optStoredProcedure.Enabled = False +optStoredProcedure.Value = False +cmdShowSecondRS.Visible = False +cmdSPCall.Enabled = False +Next +For Each proToken In pros +Select Case proToken.Name +Case "OUT_LANGUAGE" +optStoredProcedures(0).Enabled = True +Case "IN_PARAMS" +optStoredProcedures(1).Enabled = True +Case "OUT_PARAM" +optStoredProcedures(2).Enabled = True +Case "INOUT_PARAM" +optStoredProcedures(3).Enabled = True +Case "ALL_DATA_TYPES" +optStoredProcedures(4).Enabled = True +Case "DECIMAL_TYPE" +optStoredProcedures(5).Enabled = True +Case "ONE_RESULT_SET" +optStoredProcedures(6).Enabled = True +Case "TWO_RESULT_SETS" +optStoredProcedures(7).Enabled = True +Case "CLOB_EXTRACT" +optStoredProcedures(8).Enabled = True +Case "DB2SQL_EXAMPLE" +optStoredProcedures(9).Enabled = True +Case "DBINFO_EXAMPLE" +optStoredProcedures(10).Enabled = True +Case "MAIN_EXAMPLE" +optStoredProcedures(11).Enabled = True +Case Else +End Select +Next proToken +For Each optStoredProcedure In optStoredProcedures +If optStoredProcedure.Enabled Then +cmdSPCall.Enabled = True +Exit For +End If +Next +Set pros = Nothing +Set proToken = Nothing +End Sub +Private Sub optStoredProcedures_Click(Index As Integer) +sbrStatus.Panels(1).Text = "" +txtSPResult.Text = "" +If DataGridSP.Visible Then +DataGridSP.Visible = False +Set DataGridSP.DataSource = Nothing +DataGridSP.ClearFields +cmdShowSecondRS.Visible = False +End If +cmdSPCall.SetFocus +End Sub +Private Sub cmdSPCall_Click() +Dim optStoredProcedure As Variant +Dim strParam As String +On Error GoTo cmdSPCall_Error +For Each optStoredProcedure In optStoredProcedures +If optStoredProcedure.Value = True Then +Exit For +End If +Next +If IsObject(optStoredProcedure) Then +sbrStatus.Panels(1).Text = "" +txtSPResult.Text = "" +DataGridSP.Visible = False +Else +sbrStatus.Panels(1).Text = "ERROR: No stored procedure selected." +Exit Sub +End If +Select Case optStoredProcedure.Caption +Case "OUT_LANGUAGE" +txtSPResult.Text = _ +"Stored procedures are implemented in LANGUAGE " & _ +CallSP_OUT_LANGUAGE(con) +Case "IN_PARAMS" +con.BeginTrans +CallInParameters +con.RollbackTrans +Case "OUT_PARAM" +txtSPResult.Text = _ +"Stored Procedure OUT_PARAM calculated median was " & _ +CallSP_OUT_PARAM(con) +Case "INOUT_PARAM" +CallInOutParameter +Case "ALL_DATA_TYPES" +CallAllDataTypes +Case "DECIMAL_TYPE" +txtSPResult.Text = _ +"Stored Procedure DECIMAL_TYPE returned value was " & _ +CallSP_DECIMAL_TYPE(con) +Case "CLOB_EXTRACT" +txtSPResult.Text = _ +"Resume section returned from calling CLOB_EXTRACT:" & _ +vbCrLf & vbCrLf & CallSP_CLOB_EXTRACT(con) +Case "ONE_RESULT_SET" +Set DataGridSP.DataSource = CallSP_ONE_RESULT_SET(con) +DataGridSP.Visible = True +Case "TWO_RESULT_SETS" +Set rst = CallSP_TWO_RESULT_SETS(con) +Set DataGridSP.DataSource = rst +DataGridSP.Visible = True +cmdShowSecondRS.Visible = True +cmdShowSecondRS.Enabled = True +cmdShowSecondRS.SetFocus +Case "DB2SQL_EXAMPLE" +strParam = "CLERK" +txtSPResult.Text = _ +"Stored Procedure DB2SQL_EXAMPLE returned value was " & _ +CallSP_DB2SQL_EXAMPLE(con, strParam) & _ +vbCrLf & "for the job of " & strParam & "." +Case "DBINFO_EXAMPLE" +CallDbInfo +Case "MAIN_EXAMPLE" +strParam = "DESIGNER" +txtSPResult.Text = _ +"Stored Procedure MAIN_EXAMPLE returned value was " & _ +CallSP_DB2SQL_EXAMPLE(con, strParam) & _ +vbCrLf & "for the job of " & strParam & "." +End Select +sbrStatus.Panels(1).Text = _ +"Stored Procedure " & optStoredProcedure.Caption & _ +" was called successfully." +cmdSPCall_Exit: +Exit Sub +cmdSPCall_Error: +sbrStatus.Panels(1).Text = "ERROR: " & Err.Description +Resume cmdSPCall_Exit +End Sub +Private Sub cmdShowSecondRS_Click() +Set DataGridSP.DataSource = rst.NextRecordset +cmdShowSecondRS.Enabled = False +cmdSPCall.SetFocus +End Sub +Private Sub CallInParameters() +Dim strSQL As String +strSQL = "SELECT SUM(salary) FROM employee WHERE workdept = 'E11'" +Set rst = ExecuteSQLCommand(strSQL, strMsgText, con) +txtSPResult.Text = "Before calling IN_PARAMS, " & vbCrLf & _ +"Sum of salaries for dept. E11 = " & _ +rst.Fields(0).Value & vbCrLf & vbCrLf +CallSP_IN_PARAMS con +txtSPResult.Text = txtSPResult.Text & _ +"SAMPLE Stored Procedure IN_PARAMS was called." & vbCrLf & vbCrLf +Set rst = ExecuteSQLCommand(strSQL, strMsgText, con) +txtSPResult.Text = txtSPResult.Text & _ +"After calling IN_PARAMS, " & vbCrLf & _ +"Sum of salaries for dept. E11 = " & _ +rst.Fields(0).Value & vbCrLf +Set rst = Nothing +strMsgText = "" +End Sub +Private Sub CallInOutParameter() +Dim dblMedian As Double +txtSPResult.Text = "Call OUT_PARAM to get the median." +dblMedian = CallSP_OUT_PARAM(con) +txtSPResult.Text = txtSPResult.Text & vbCrLf & _ +"Stored procedure returned successfully." & vbCrLf +txtSPResult.Text = txtSPResult.Text & vbCrLf & _ +"Call INOUT_PARAM with the result just got." +txtSPResult.Text = txtSPResult.Text & vbCrLf & _ +"New median returned from INOUT_PARAM = " & _ +CallSP_INOUT_PARAM(con, dblMedian) +End Sub +Private Sub CallAllDataTypes() +Dim pms As ADODB.Parameters +With txtSPResult +.Text = "Call ALL_DATA_TYPES to get all types of data." +Set pms = CallSP_ALL_DATA_TYPES(con) +.Text = .Text & vbCrLf & "Stored procedure returned successfully." +.Text = .Text & vbCrLf & _ +vbCrLf & "Value of SMALLINT = " & pms("SMALL").Value & _ +vbCrLf & "Value of INTEGER = " & pms("INTIN").Value & _ +vbCrLf & "Value of BIGINT = " & pms("BIGIN").Value & _ +vbCrLf & "Value of REAL = " & pms("REALIN").Value & _ +vbCrLf & "Value of DOUBLE = " & pms("DOUBLEIN").Value & _ +vbCrLf & "Value of CHAR(1) = " & pms("CHAROUT").Value & _ +vbCrLf & "Value of CHAR(15) = " & pms("CHARSOUT").Value & _ +vbCrLf & "Value of VARCHAR(12) = " & pms("VARCHAROUT").Value & _ +vbCrLf & "Value of DATE = " & pms("DATEOUT").Value & _ +vbCrLf & "Value of TIME = " & TimeValue(pms("TIMEOUT").Value) +End With +Set pms = Nothing +End Sub +Private Sub CallDbInfo() +Dim pms As ADODB.Parameters +Dim strJob As String +txtSPResult.Text = "CALL stored procedure named DBINFO_EXAMPLE." +strJob = "MANAGER" +Set pms = CallSP_DBINFO_EXAMPLE(con, strJob) +txtSPResult.Text = txtSPResult.Text & vbCrLf & _ +"Stored procedure returned successfully with SQLCODE = " & _ +pms("ERRORCODE").Value +txtSPResult.Text = txtSPResult.Text & vbCrLf & _ +"Average salary for job " & strJob & " = " & pms("SALARY").Value +txtSPResult.Text = txtSPResult.Text & vbCrLf & _ +"Database name from OUT parameter = " & Trim$(pms("DBNAME").Value) +txtSPResult.Text = txtSPResult.Text & vbCrLf & _ +"Database version from OUT parameter = " & pms("DBVERSION").Value +Set pms = Nothing +End Sub +Private Sub cmdUDFs_Click(Index As Integer) +On Error GoTo cmdUDFs_Error +sbrStatus.Panels(1).Text = "" +txtUDF.Text = "" +hflxGridUDF.ClearStructure +Select Case cmdUDFs(Index).Caption +Case "ScalarUDF" +hflxGridUDF.ColWidth(3) = 2000 +Set hflxGridUDF.DataSource = CallUDFScalarUDF(strMsgText, con) +Case "ClobScalarUDF" +Set hflxGridUDF.DataSource = CallUDFClobScalarUDF(strMsgText, con) +Case "ScratchpadScUDF" +Set hflxGridUDF.DataSource = CallUDFScratchpadScUDF(strMsgText, con) +Case "ScUDFReturningErr" +Set hflxGridUDF.DataSource = CallUDFScUDFReturningErr(strMsgText, con) +txtUDF.Text = strMsgText +Err.Raise vbObjectError, , "See display area for detail." +Case "SourcedColumnUDF" +Set hflxGridUDF.DataSource = CallUDFSourcedColUDF(strMsgText, con) +Case "TableUDF" +Set hflxGridUDF.DataSource = CallUDFTableUDF(strMsgText, con) +Case Else +End Select +txtUDF.Text = strMsgText +sbrStatus.Panels(1).Text = _ +"Calling UDF " & cmdUDFs(Index).Caption & " was done." +cmdUDFs_Exit: +Exit Sub +cmdUDFs_Error: +sbrStatus.Panels(1).Text = "ERROR: " & Err.Description +Resume cmdUDFs_Exit +End Sub +Private Sub Form_Load() +tabMain.Tab = 0 +wShowInstructions = vbYes +wShowInstructions = MsgBox("Would you like to have instructions?", _ +vbYesNo, "Welcome to the DB2 Visual Basic samples") +End Sub +Private Sub Form_Activate() +If wShowInstructions = vbYes Then +MsgBox _ +"Thank you for using instructions in this demonstration program!" & vbCr & vbCr & _ +"- Status messages are shown at the bottom of the working window;" & vbCr & _ +"- Buttons unavailable are being grayed out;" & vbCr & _ +"- SAMPLE database must be created if it doesn't exist;" & vbCr & _ +"- [Exit] button can be pressed at anytime to quit the program." & vbCr & vbCr & _ +"You may now choose one of the connections to begin the demonstraton.", _ +vbOKOnly, "Instruction" +End If +End Sub +Private Sub tabMain_Click(intPreviousTab As Integer) +Select Case tabMain.TabCaption(intPreviousTab) +Case "Execute SQL" +chkAutoCommit.Value = 1 +Set rst = Nothing +Set DataGridSQL.DataSource = Nothing +DataGridSQL.ClearFields +Case "Hierarchical Data" +Set hflxRecords.DataSource = Nothing +hflxRecords.Clear +Case "LOBs" +txtClob.Text = "" +txtEmpno.Text = "" +txtLastname.Text = "" +txtFirstname.Text = "" +AdodcLob.Caption = "" +AdodcLob.Enabled = False +cmdBLOB.Enabled = False +cmdCLOB.Enabled = False +picBlob.Visible = False +Case "Store Procedures" +Set rst = Nothing +Set DataGridSP.DataSource = Nothing +DataGridSP.Visible = False +DataGridSP.ClearFields +cmdShowSecondRS.Visible = False +txtSPResult.Text = "" +Case "UDFs" +txtUDF.Text = "" +hflxGridUDF.Clear +Case Else +End Select +sbrStatus.Panels(1).Text = "" +End Sub +Private Sub tabMain_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) +If wShowInstructions = vbYes Then +If con Is Nothing Then 'no connection established +MsgBox _ +"All funcitonal features require a valid connection.", _ +vbOKOnly + vbExclamation, "Instruction" +Else +Select Case tabMain.Caption +Case "Execute SQL" +MsgBox _ +"Please type a SQL statement into the text box, or," & vbCr & _ +"choose a preset one from the small Sample buttons, then," & vbCr & _ +"press one of the [Execute SQL] buttons to get the results." & vbCr & _ +"AutoCommit checkbox can be used to change the autocommit mode." & vbCr & vbCr & _ +"For more about the connection, command, and recordset objects," & vbCr & _ +"see the source code in the apExeSQL.bas module." & vbCr & vbCr & _ +"Note:" & vbCr & _ +"- The sample SQL statements can be edited." & vbCr & _ +"- Recordset results may be editable depending on the SQL statement issued.", _ +vbOKOnly, "Instruction" +Case "Hierarchical Data" +If InStr(con.Provider, "MSDataShape") Then +MsgBox _ +"Please press the [Display] button to display hierarchical result.", _ +vbOKOnly, "Instruction" +Else +MsgBox _ +"Hierarchical Data is only available for a" & vbCr & _ +"valid connection with DataShape.", _ +vbOKOnly + vbExclamation, "Instruction" +End If +Case "LOBs" +MsgBox _ +"After pressing the [Refresh Data] button;" & vbCr & _ +"Use arrow keys to manipulate results;" & vbCr & _ +"Press [Show Resume] button to display CLOBs;" & vbCr & _ +"Press [Show Picture] button to display BLOBs.", _ +vbOKOnly, "Instruction" +Case "Store Procedures" +MsgBox _ +"Choose an available stored procedure, then," & vbCr & _ +"press the [Call] button to get the results." & vbCr & vbCr & _ +"Note: To make them available, you first have to create and catalog" & vbCr & _ +"the stored procedures in the spserver stored procedure library.", _ +vbOKOnly, "Instruction" +Case "UDFs" +MsgBox _ +"Please choose one of the UDF buttons to show the usage.", _ +vbOKOnly, "Instruction" +Case Else +End Select +End If +End If +End Sub diff --git a/test/expected_dir/frx1.frx/visualbasic/comment b/test/expected_dir/frx1.frx/visualbasic/comment new file mode 100644 index 0000000..b1345c7 --- /dev/null +++ b/test/expected_dir/frx1.frx/visualbasic/comment @@ -0,0 +1,203 @@ +'--------------------------------------------------------------------------- +' +' Licensed Materials - Property of IBM +' Governed under the terms of the IBM Public License +' +' (C) COPYRIGHT International Business Machines Corp. 2002 +' All Rights Reserved. +' +' US Government Users Restricted Rights - Use, duplication or +' disclosure restricted by GSA ADP Schedule Contract with IBM Corp. +'--------------------------------------------------------------------------- +' +' SOURCE FILE NAME: Demo.frm +' +' SAMPLE: Visual Basic Demo with user interface for the sample modules +' +' MODULES USED: +' cli_Info.bas +' cliExeSQL.bas +' dbCommit.bas +' dbConn.bas +' dbInfo.bas +' dtHier.bas +' dtLob.bas +' spCall.bas +' udfUse.bas +' Util.bas +' +' For more information about samples, refer to the README file. +' +' For more information on the SQL language, refer to the SQL Reference. +' +' For the latest information on programming, compiling, and running DB2 +' applications, refer to the DB2 application development website at +' http://www.software.ibm.com/data/db2/udb/ad +'--------------------------------------------------------------------------- +'This procedure calls ConnectOLEDB() in the module dbConn to get +'a connection object. +'define the error handler +' On Error GoTo cmdConnectOLEDB_Error +'connect to database +'generate a message of success +'config status of the buttons +'show instructions +'generate an error message +'show instructions +'This procedure calls ConnectODBC() in the module dbConn to get +'a connection object. +'define the error handler +'connect to database +'generate a message of success +'config status of the buttons +'show instructions +'generate an error message +'show instructions +'This procedure calls ConnectDataShape() in the module dbConn to +'get a connection object. +'define the error handler +'connect to database +'generate a message of success +'config status of the buttons +'show instructions +'generate an error message +'show instructions +'This procedure enables buttons after a connection is created. +'This procedure shows the instruction message after creating a connection. +'This procedure calls Disconnect() in the module dbConn to close +'a connection object. +'define the error handler +'clear displays and release data sources +'disconnect from database +'configure status of the buttons +'show instructions +'generate an error message +'show instructions +'This procedure calls ConnectInfo in dbInfo to obtain information +'and displays the connection information on a message box. +'This procedure calls VersionInfo in apInfo to obtain information +'and displays the version information on a message box. +'This procedure close the main screen and quit the program. +'check if it is necessary to commit any changes +'release all the memory allocated +'exit +'This procedure calls CreateSample in Util to re-create the +'sample database. +'define the error handler +'create the sample database +'show instructions +'generate an error message +'show instructions +'This procedure calls ExecuteSQLConnect in apExeSQL to execute a +'SQL statement. +'define the error handler +'display results and/or message +'generate an error message and exit +'This procedure calls ExecuteSQLCommand in apExeSQL to execute a +'SQL statement. +'define the error handler +'display results and/or message +'generate an error message and exit +'This procedure calls ExecuteSQLRecordset in apExeSQL to execute a +'SQL statement. +'define the error handler +'display results and/or message +'generate an error message and exit +'This procedure displays instructions for exiting recursive errors while +'editing on the DataGird +'This procedure generates a sample SQL statement +'This procedure clears the results when choosing a predefined SQL +'statement sample +'This procedure toggles the autocommit mode on/off by calling +'procedures in the module dbCommit. +'define the error handler +'turn the autocommit mode OFF +'ask if the user wants to commit all the previous changes +'before turning the autocommit mode ON +'generate an error message and exit +'This procedure commits any previous changes by calling +'procedures in the module dbCommit. +'define the error handler +'commit the changes and start a new transaction +'generate an error message and exit +'This procedure rollbacks any previous changes by calling +'procedures in the module dbCommit. +'define the error handler +'rollback the changes and start a new transaction +'generate an error message and exit +'This is a helper procedure which refreshes the data displayed +'on the DataGridSQL. +'This procedure calls ExecuteHSQL() in the module dtHier to +'obtain a hierarchical recordset object. +'display in Grids +'display text information message +'This procedure calls GetLOB in dtLob to get an ADO Control for LOBs. +'define the error handler +'get an ADO Control for the LOBs +'set display objects +'enable buttons +'generate an error message and exit +'This procedure enables the display of employee pictures. +'This procedure enables the display of employee resumes. +'This is a helper procedure for Adodc caption display. +'This procedure checks and enables buttons for available stored +'procedures +'get information for all available procedures +'reset all selections +'enable buttons for available stored procedures +'enable Call button if any stored procedure available +'release objects +'This procedure clears the screen in switching the stored procedures +'This procedure calls various subroutines and subroutines in the +'module spCall to execute corresponding stored procedures and +'displays the results onto the screen. +'define the error handler +'check for the selected stored procedure by iteration +'clear the screen for result display +'call the corresponding selected stored procedure +'generate a message of success +'generate an error message and exit +'This procedure shows the second result set returned by calling +'the stored procedurd TWO_RESULT_SETS +'show next recordset +'This procedure calls CallSP_IN_PARAMS in the module spCall and +'compares information obtained from the same table before and +'after calling the stored procedure +'initialize variables +'get information before calling the stored procedure +'call the stored procedure +'get information after calling the stored procedure +'This procedure calls CallSP_INOUT_PARAM in the module spCall by +'using a parameter got form calling CallSP_OUT_PARAM and outputs +'a result message +'define variable +'get a parameter from OUT_PARAM +'call the stored procedure with the parameter +'This procedure calls CallSP_ALL_DATA_TYPES in the module spCall +'and displays the results +'initialize object and settings +'call the stored procedure +'output the results +'reset and release the object +'This procedure calls CallSP_DBINFO_EXAMPLE in the module spCall +'with a JOB as an IN parameter and displays the results obtained +'from the stored procedure containing information of the table and +'the database. +'define objects and variables +'call the stored procedure +'display the results +'This procedure calls various subroutines in the module udUse to +'execute corresponding user defined functions and displays the +'results onto the screen. +'define the error handler +'clear the screen for result display +'call the specific UDF procedure +'generate a message of success +'generate an error message and exit +'This procedure defines initial parameters. +'ask the user for displaying the instructions or not +'This procedure shows instructions at the begining of the program. +'This procedure maintains screen integrity for the Main Tabs. +'clear the the Tab screen before switching +'This procedure shows instructions for the Main Tabs. +'show instructions diff --git a/test/expected_dir/groovy1.groovy/groovy/blanks b/test/expected_dir/groovy1.groovy/groovy/blanks new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/test/expected_dir/groovy1.groovy/groovy/blanks @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/test/expected_dir/groovy1.groovy/groovy/code b/test/expected_dir/groovy1.groovy/groovy/code new file mode 100644 index 0000000..b881b63 --- /dev/null +++ b/test/expected_dir/groovy1.groovy/groovy/code @@ -0,0 +1,4 @@ +println "hello, world" +for (arg in this.args ) { +println "Argument:" + arg; +} diff --git a/test/expected_dir/groovy1.groovy/groovy/comment b/test/expected_dir/groovy1.groovy/groovy/comment new file mode 100644 index 0000000..a033d4b --- /dev/null +++ b/test/expected_dir/groovy1.groovy/groovy/comment @@ -0,0 +1,5 @@ +//hello.groovy +// this is a comment +/* a block comment, commenting out an alternative to above: +this.args.each{ arg -> println "hello, ${arg}"} +*/ diff --git a/test/expected_dir/html1.html/css/blanks b/test/expected_dir/html1.html/css/blanks new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/test/expected_dir/html1.html/css/blanks @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/test/expected_dir/html1.html/css/code b/test/expected_dir/html1.html/css/code new file mode 100644 index 0000000..014b64e --- /dev/null +++ b/test/expected_dir/html1.html/css/code @@ -0,0 +1,3 @@ +p { +color: #444 +} diff --git a/test/expected_dir/html1.html/css/comment b/test/expected_dir/html1.html/css/comment new file mode 100644 index 0000000..e69de29 diff --git a/test/expected_dir/html1.html/html/blanks b/test/expected_dir/html1.html/html/blanks new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/test/expected_dir/html1.html/html/blanks @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/test/expected_dir/html1.html/html/code b/test/expected_dir/html1.html/html/code new file mode 100644 index 0000000..b5eca21 --- /dev/null +++ b/test/expected_dir/html1.html/html/code @@ -0,0 +1,18 @@ + + + +foo + + + + +

+ +not in comment + +italic?]]> +

+ + diff --git a/test/expected_dir/html1.html/html/comment b/test/expected_dir/html1.html/html/comment new file mode 100644 index 0000000..30c82f6 --- /dev/null +++ b/test/expected_dir/html1.html/html/comment @@ -0,0 +1,3 @@ + diff --git a/test/expected_dir/html1.html/javascript/blanks b/test/expected_dir/html1.html/javascript/blanks new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/test/expected_dir/html1.html/javascript/blanks @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/test/expected_dir/html1.html/javascript/code b/test/expected_dir/html1.html/javascript/code new file mode 100644 index 0000000..69671f1 --- /dev/null +++ b/test/expected_dir/html1.html/javascript/code @@ -0,0 +1,13 @@ + diff --git a/test/expected_dir/html1.html/javascript/comment b/test/expected_dir/html1.html/javascript/comment new file mode 100644 index 0000000..ecd132d --- /dev/null +++ b/test/expected_dir/html1.html/javascript/comment @@ -0,0 +1 @@ +// javascript comment diff --git a/test/expected_dir/java1.java/java/blanks b/test/expected_dir/java1.java/java/blanks new file mode 100644 index 0000000..3f10ffe --- /dev/null +++ b/test/expected_dir/java1.java/java/blanks @@ -0,0 +1 @@ +15 \ No newline at end of file diff --git a/test/expected_dir/java1.java/java/code b/test/expected_dir/java1.java/java/code new file mode 100644 index 0000000..5966c9a --- /dev/null +++ b/test/expected_dir/java1.java/java/code @@ -0,0 +1,27 @@ +import java.applet.Applet; +import java.awt.Graphics; +public class SineApplet2 extends Applet { +public void paint(Graphics g) { +int i, j1, j2; +j1 = yvalue(0); +for (i = 0; i < size().width; i++) { +j2 = yvalue(i+1); +g.drawLine(i, j1 ,i+1, j2); +j1 = j2; +} +} +private int yvalue(int ivalue) { +double xmin = -10.0; +double xmax = 10.0; +double ymin = -1.0; +double ymax = 1.0; +double x, y; +int jvalue; +x = (ivalue * (xmax - xmin)/(size().width - 1)) + xmin; +y = Math.sin(x); +jvalue = (int) ((y - ymin)*(size().height - 1)/ +(ymax - ymin)); +jvalue = size().height - jvalue; +return jvalue; +} +} diff --git a/test/expected_dir/java1.java/java/comment b/test/expected_dir/java1.java/java/comment new file mode 100644 index 0000000..b628454 --- /dev/null +++ b/test/expected_dir/java1.java/java/comment @@ -0,0 +1,6 @@ +// Program 11.6: A nicer sine wave +// Given the xpoint we're given calculate the Cartesian equivalent +// Take the sine of that x +// Scale y into window coordinates +/* Switch jvalue from Cartesian coordinates +to computer graphics coordinates */ diff --git a/test/expected_dir/java2.java/java/blanks b/test/expected_dir/java2.java/java/blanks new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/test/expected_dir/java2.java/java/blanks @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/test/expected_dir/java2.java/java/code b/test/expected_dir/java2.java/java/code new file mode 100644 index 0000000..e69de29 diff --git a/test/expected_dir/java2.java/java/comment b/test/expected_dir/java2.java/java/comment new file mode 100644 index 0000000..b3e6072 --- /dev/null +++ b/test/expected_dir/java2.java/java/comment @@ -0,0 +1,2 @@ +/** +*/ diff --git a/test/expected_dir/js1.js/javascript/code b/test/expected_dir/js1.js/javascript/code new file mode 100644 index 0000000..134332a --- /dev/null +++ b/test/expected_dir/js1.js/javascript/code @@ -0,0 +1,1446 @@ +var Prototype = { +Version: '1.4.0', +ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)', +emptyFunction: function() {}, +K: function(x) {return x} +} +var Class = { +create: function() { +return function() { +this.initialize.apply(this, arguments); +} +} +} +var Abstract = new Object(); +Object.extend = function(destination, source) { +for (property in source) { +destination[property] = source[property]; +} +return destination; +} +Object.inspect = function(object) { +try { +if (object == undefined) return 'undefined'; +if (object == null) return 'null'; +return object.inspect ? object.inspect() : object.toString(); +} catch (e) { +if (e instanceof RangeError) return '...'; +throw e; +} +} +Function.prototype.bind = function() { +var __method = this, args = $A(arguments), object = args.shift(); +return function() { +return __method.apply(object, args.concat($A(arguments))); +} +} +Function.prototype.bindAsEventListener = function(object) { +var __method = this; +return function(event) { +return __method.call(object, event || window.event); +} +} +Object.extend(Number.prototype, { +toColorPart: function() { +var digits = this.toString(16); +if (this < 16) return '0' + digits; +return digits; +}, +succ: function() { +return this + 1; +}, +times: function(iterator) { +$R(0, this, true).each(iterator); +return this; +} +}); +var Try = { +these: function() { +var returnValue; +for (var i = 0; i < arguments.length; i++) { +var lambda = arguments[i]; +try { +returnValue = lambda(); +break; +} catch (e) {} +} +return returnValue; +} +} +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { +initialize: function(callback, frequency) { +this.callback = callback; +this.frequency = frequency; +this.currentlyExecuting = false; +this.registerCallback(); +}, +registerCallback: function() { +setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); +}, +onTimerEvent: function() { +if (!this.currentlyExecuting) { +try { +this.currentlyExecuting = true; +this.callback(); +} finally { +this.currentlyExecuting = false; +} +} +} +} +function $() { +var elements = new Array(); +for (var i = 0; i < arguments.length; i++) { +var element = arguments[i]; +if (typeof element == 'string') +element = document.getElementById(element); +if (arguments.length == 1) +return element; +elements.push(element); +} +return elements; +} +Object.extend(String.prototype, { +stripTags: function() { +return this.replace(/<\/?[^>]+>/gi, ''); +}, +stripScripts: function() { +return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); +}, +extractScripts: function() { +var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); +var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); +return (this.match(matchAll) || []).map(function(scriptTag) { +return (scriptTag.match(matchOne) || ['', ''])[1]; +}); +}, +evalScripts: function() { +return this.extractScripts().map(eval); +}, +escapeHTML: function() { +var div = document.createElement('div'); +var text = document.createTextNode(this); +div.appendChild(text); +return div.innerHTML; +}, +unescapeHTML: function() { +var div = document.createElement('div'); +div.innerHTML = this.stripTags(); +return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; +}, +toQueryParams: function() { +var pairs = this.match(/^\??(.*)$/)[1].split('&'); +return pairs.inject({}, function(params, pairString) { +var pair = pairString.split('='); +params[pair[0]] = pair[1]; +return params; +}); +}, +toArray: function() { +return this.split(''); +}, +camelize: function() { +var oStringList = this.split('-'); +if (oStringList.length == 1) return oStringList[0]; +var camelizedString = this.indexOf('-') == 0 +? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) +: oStringList[0]; +for (var i = 1, len = oStringList.length; i < len; i++) { +var s = oStringList[i]; +camelizedString += s.charAt(0).toUpperCase() + s.substring(1); +} +return camelizedString; +}, +inspect: function() { +return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; +} +}); +String.prototype.parseQuery = String.prototype.toQueryParams; +var $break = new Object(); +var $continue = new Object(); +var Enumerable = { +each: function(iterator) { +var index = 0; +try { +this._each(function(value) { +try { +iterator(value, index++); +} catch (e) { +if (e != $continue) throw e; +} +}); +} catch (e) { +if (e != $break) throw e; +} +}, +all: function(iterator) { +var result = true; +this.each(function(value, index) { +result = result && !!(iterator || Prototype.K)(value, index); +if (!result) throw $break; +}); +return result; +}, +any: function(iterator) { +var result = true; +this.each(function(value, index) { +if (result = !!(iterator || Prototype.K)(value, index)) +throw $break; +}); +return result; +}, +collect: function(iterator) { +var results = []; +this.each(function(value, index) { +results.push(iterator(value, index)); +}); +return results; +}, +detect: function (iterator) { +var result; +this.each(function(value, index) { +if (iterator(value, index)) { +result = value; +throw $break; +} +}); +return result; +}, +findAll: function(iterator) { +var results = []; +this.each(function(value, index) { +if (iterator(value, index)) +results.push(value); +}); +return results; +}, +grep: function(pattern, iterator) { +var results = []; +this.each(function(value, index) { +var stringValue = value.toString(); +if (stringValue.match(pattern)) +results.push((iterator || Prototype.K)(value, index)); +}) +return results; +}, +include: function(object) { +var found = false; +this.each(function(value) { +if (value == object) { +found = true; +throw $break; +} +}); +return found; +}, +inject: function(memo, iterator) { +this.each(function(value, index) { +memo = iterator(memo, value, index); +}); +return memo; +}, +invoke: function(method) { +var args = $A(arguments).slice(1); +return this.collect(function(value) { +return value[method].apply(value, args); +}); +}, +max: function(iterator) { +var result; +this.each(function(value, index) { +value = (iterator || Prototype.K)(value, index); +if (value >= (result || value)) +result = value; +}); +return result; +}, +min: function(iterator) { +var result; +this.each(function(value, index) { +value = (iterator || Prototype.K)(value, index); +if (value <= (result || value)) +result = value; +}); +return result; +}, +partition: function(iterator) { +var trues = [], falses = []; +this.each(function(value, index) { +((iterator || Prototype.K)(value, index) ? +trues : falses).push(value); +}); +return [trues, falses]; +}, +pluck: function(property) { +var results = []; +this.each(function(value, index) { +results.push(value[property]); +}); +return results; +}, +reject: function(iterator) { +var results = []; +this.each(function(value, index) { +if (!iterator(value, index)) +results.push(value); +}); +return results; +}, +sortBy: function(iterator) { +return this.collect(function(value, index) { +return {value: value, criteria: iterator(value, index)}; +}).sort(function(left, right) { +var a = left.criteria, b = right.criteria; +return a < b ? -1 : a > b ? 1 : 0; +}).pluck('value'); +}, +toArray: function() { +return this.collect(Prototype.K); +}, +zip: function() { +var iterator = Prototype.K, args = $A(arguments); +if (typeof args.last() == 'function') +iterator = args.pop(); +var collections = [this].concat(args).map($A); +return this.map(function(value, index) { +iterator(value = collections.pluck(index)); +return value; +}); +}, +inspect: function() { +return '#'; +} +} +Object.extend(Enumerable, { +map: Enumerable.collect, +find: Enumerable.detect, +select: Enumerable.findAll, +member: Enumerable.include, +entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { +if (!iterable) return []; +if (iterable.toArray) { +return iterable.toArray(); +} else { +var results = []; +for (var i = 0; i < iterable.length; i++) +results.push(iterable[i]); +return results; +} +} +Object.extend(Array.prototype, Enumerable); +Array.prototype._reverse = Array.prototype.reverse; +Object.extend(Array.prototype, { +_each: function(iterator) { +for (var i = 0; i < this.length; i++) +iterator(this[i]); +}, +clear: function() { +this.length = 0; +return this; +}, +first: function() { +return this[0]; +}, +last: function() { +return this[this.length - 1]; +}, +compact: function() { +return this.select(function(value) { +return value != undefined || value != null; +}); +}, +flatten: function() { +return this.inject([], function(array, value) { +return array.concat(value.constructor == Array ? +value.flatten() : [value]); +}); +}, +without: function() { +var values = $A(arguments); +return this.select(function(value) { +return !values.include(value); +}); +}, +indexOf: function(object) { +for (var i = 0; i < this.length; i++) +if (this[i] == object) return i; +return -1; +}, +reverse: function(inline) { +return (inline !== false ? this : this.toArray())._reverse(); +}, +shift: function() { +var result = this[0]; +for (var i = 0; i < this.length - 1; i++) +this[i] = this[i + 1]; +this.length--; +return result; +}, +inspect: function() { +return '[' + this.map(Object.inspect).join(', ') + ']'; +} +}); +var Hash = { +_each: function(iterator) { +for (key in this) { +var value = this[key]; +if (typeof value == 'function') continue; +var pair = [key, value]; +pair.key = key; +pair.value = value; +iterator(pair); +} +}, +keys: function() { +return this.pluck('key'); +}, +values: function() { +return this.pluck('value'); +}, +merge: function(hash) { +return $H(hash).inject($H(this), function(mergedHash, pair) { +mergedHash[pair.key] = pair.value; +return mergedHash; +}); +}, +toQueryString: function() { +return this.map(function(pair) { +return pair.map(encodeURIComponent).join('='); +}).join('&'); +}, +inspect: function() { +return '#'; +} +} +function $H(object) { +var hash = Object.extend({}, object || {}); +Object.extend(hash, Enumerable); +Object.extend(hash, Hash); +return hash; +} +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { +initialize: function(start, end, exclusive) { +this.start = start; +this.end = end; +this.exclusive = exclusive; +}, +_each: function(iterator) { +var value = this.start; +do { +iterator(value); +value = value.succ(); +} while (this.include(value)); +}, +include: function(value) { +if (value < this.start) +return false; +if (this.exclusive) +return value < this.end; +return value <= this.end; +} +}); +var $R = function(start, end, exclusive) { +return new ObjectRange(start, end, exclusive); +} +var Ajax = { +getTransport: function() { +return Try.these( +function() {return new ActiveXObject('Msxml2.XMLHTTP')}, +function() {return new ActiveXObject('Microsoft.XMLHTTP')}, +function() {return new XMLHttpRequest()} +) || false; +}, +activeRequestCount: 0 +} +Ajax.Responders = { +responders: [], +_each: function(iterator) { +this.responders._each(iterator); +}, +register: function(responderToAdd) { +if (!this.include(responderToAdd)) +this.responders.push(responderToAdd); +}, +unregister: function(responderToRemove) { +this.responders = this.responders.without(responderToRemove); +}, +dispatch: function(callback, request, transport, json) { +this.each(function(responder) { +if (responder[callback] && typeof responder[callback] == 'function') { +try { +responder[callback].apply(responder, [request, transport, json]); +} catch (e) {} +} +}); +} +}; +Object.extend(Ajax.Responders, Enumerable); +Ajax.Responders.register({ +onCreate: function() { +Ajax.activeRequestCount++; +}, +onComplete: function() { +Ajax.activeRequestCount--; +} +}); +Ajax.Base = function() {}; +Ajax.Base.prototype = { +setOptions: function(options) { +this.options = { +method: 'post', +asynchronous: true, +parameters: '' +} +Object.extend(this.options, options || {}); +}, +responseIsSuccess: function() { +return this.transport.status == undefined +|| this.transport.status == 0 +|| (this.transport.status >= 200 && this.transport.status < 300); +}, +responseIsFailure: function() { +return !this.responseIsSuccess(); +} +} +Ajax.Request = Class.create(); +Ajax.Request.Events = +['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { +initialize: function(url, options) { +this.transport = Ajax.getTransport(); +this.setOptions(options); +this.request(url); +}, +request: function(url) { +var parameters = this.options.parameters || ''; +if (parameters.length > 0) parameters += '&_='; +try { +this.url = url; +if (this.options.method == 'get' && parameters.length > 0) +this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; +Ajax.Responders.dispatch('onCreate', this, this.transport); +this.transport.open(this.options.method, this.url, +this.options.asynchronous); +if (this.options.asynchronous) { +this.transport.onreadystatechange = this.onStateChange.bind(this); +setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); +} +this.setRequestHeaders(); +var body = this.options.postBody ? this.options.postBody : parameters; +this.transport.send(this.options.method == 'post' ? body : null); +} catch (e) { +this.dispatchException(e); +} +}, +setRequestHeaders: function() { +var requestHeaders = +['X-Requested-With', 'XMLHttpRequest', +'X-Prototype-Version', Prototype.Version]; +if (this.options.method == 'post') { +requestHeaders.push('Content-type', +'application/x-www-form-urlencoded'); +if (this.transport.overrideMimeType) +requestHeaders.push('Connection', 'close'); +} +if (this.options.requestHeaders) +requestHeaders.push.apply(requestHeaders, this.options.requestHeaders); +for (var i = 0; i < requestHeaders.length; i += 2) +this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]); +}, +onStateChange: function() { +var readyState = this.transport.readyState; +if (readyState != 1) +this.respondToReadyState(this.transport.readyState); +}, +header: function(name) { +try { +return this.transport.getResponseHeader(name); +} catch (e) {} +}, +evalJSON: function() { +try { +return eval(this.header('X-JSON')); +} catch (e) {} +}, +evalResponse: function() { +try { +return eval(this.transport.responseText); +} catch (e) { +this.dispatchException(e); +} +}, +respondToReadyState: function(readyState) { +var event = Ajax.Request.Events[readyState]; +var transport = this.transport, json = this.evalJSON(); +if (event == 'Complete') { +try { +(this.options['on' + this.transport.status] +|| this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] +|| Prototype.emptyFunction)(transport, json); +} catch (e) { +this.dispatchException(e); +} +if ((this.header('Content-type') || '').match(/^text\/javascript/i)) +this.evalResponse(); +} +try { +(this.options['on' + event] || Prototype.emptyFunction)(transport, json); +Ajax.Responders.dispatch('on' + event, this, transport, json); +} catch (e) { +this.dispatchException(e); +} +if (event == 'Complete') +this.transport.onreadystatechange = Prototype.emptyFunction; +}, +dispatchException: function(exception) { +(this.options.onException || Prototype.emptyFunction)(this, exception); +Ajax.Responders.dispatch('onException', this, exception); +} +}); +Ajax.Updater = Class.create(); +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { +initialize: function(container, url, options) { +this.containers = { +success: container.success ? $(container.success) : $(container), +failure: container.failure ? $(container.failure) : +(container.success ? null : $(container)) +} +this.transport = Ajax.getTransport(); +this.setOptions(options); +var onComplete = this.options.onComplete || Prototype.emptyFunction; +this.options.onComplete = (function(transport, object) { +this.updateContent(); +onComplete(transport, object); +}).bind(this); +this.request(url); +}, +updateContent: function() { +var receiver = this.responseIsSuccess() ? +this.containers.success : this.containers.failure; +var response = this.transport.responseText; +if (!this.options.evalScripts) +response = response.stripScripts(); +if (receiver) { +if (this.options.insertion) { +new this.options.insertion(receiver, response); +} else { +Element.update(receiver, response); +} +} +if (this.responseIsSuccess()) { +if (this.onComplete) +setTimeout(this.onComplete.bind(this), 10); +} +} +}); +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { +initialize: function(container, url, options) { +this.setOptions(options); +this.onComplete = this.options.onComplete; +this.frequency = (this.options.frequency || 2); +this.decay = (this.options.decay || 1); +this.updater = {}; +this.container = container; +this.url = url; +this.start(); +}, +start: function() { +this.options.onComplete = this.updateComplete.bind(this); +this.onTimerEvent(); +}, +stop: function() { +this.updater.onComplete = undefined; +clearTimeout(this.timer); +(this.onComplete || Prototype.emptyFunction).apply(this, arguments); +}, +updateComplete: function(request) { +if (this.options.decay) { +this.decay = (request.responseText == this.lastText ? +this.decay * this.options.decay : 1); +this.lastText = request.responseText; +} +this.timer = setTimeout(this.onTimerEvent.bind(this), +this.decay * this.frequency * 1000); +}, +onTimerEvent: function() { +this.updater = new Ajax.Updater(this.container, this.url, this.options); +} +}); +document.getElementsByClassName = function(className, parentElement) { +var children = ($(parentElement) || document.body).getElementsByTagName('*'); +return $A(children).inject([], function(elements, child) { +if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) +elements.push(child); +return elements; +}); +} +if (!window.Element) { +var Element = new Object(); +} +Object.extend(Element, { +visible: function(element) { +return $(element).style.display != 'none'; +}, +toggle: function() { +for (var i = 0; i < arguments.length; i++) { +var element = $(arguments[i]); +Element[Element.visible(element) ? 'hide' : 'show'](element); +} +}, +hide: function() { +for (var i = 0; i < arguments.length; i++) { +var element = $(arguments[i]); +element.style.display = 'none'; +} +}, +show: function() { +for (var i = 0; i < arguments.length; i++) { +var element = $(arguments[i]); +element.style.display = ''; +} +}, +remove: function(element) { +element = $(element); +element.parentNode.removeChild(element); +}, +update: function(element, html) { +$(element).innerHTML = html.stripScripts(); +setTimeout(function() {html.evalScripts()}, 10); +}, +getHeight: function(element) { +element = $(element); +return element.offsetHeight; +}, +classNames: function(element) { +return new Element.ClassNames(element); +}, +hasClassName: function(element, className) { +if (!(element = $(element))) return; +return Element.classNames(element).include(className); +}, +addClassName: function(element, className) { +if (!(element = $(element))) return; +return Element.classNames(element).add(className); +}, +removeClassName: function(element, className) { +if (!(element = $(element))) return; +return Element.classNames(element).remove(className); +}, +cleanWhitespace: function(element) { +element = $(element); +for (var i = 0; i < element.childNodes.length; i++) { +var node = element.childNodes[i]; +if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) +Element.remove(node); +} +}, +empty: function(element) { +return $(element).innerHTML.match(/^\s*$/); +}, +scrollTo: function(element) { +element = $(element); +var x = element.x ? element.x : element.offsetLeft, +y = element.y ? element.y : element.offsetTop; +window.scrollTo(x, y); +}, +getStyle: function(element, style) { +element = $(element); +var value = element.style[style.camelize()]; +if (!value) { +if (document.defaultView && document.defaultView.getComputedStyle) { +var css = document.defaultView.getComputedStyle(element, null); +value = css ? css.getPropertyValue(style) : null; +} else if (element.currentStyle) { +value = element.currentStyle[style.camelize()]; +} +} +if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) +if (Element.getStyle(element, 'position') == 'static') value = 'auto'; +return value == 'auto' ? null : value; +}, +setStyle: function(element, style) { +element = $(element); +for (name in style) +element.style[name.camelize()] = style[name]; +}, +getDimensions: function(element) { +element = $(element); +if (Element.getStyle(element, 'display') != 'none') +return {width: element.offsetWidth, height: element.offsetHeight}; +var els = element.style; +var originalVisibility = els.visibility; +var originalPosition = els.position; +els.visibility = 'hidden'; +els.position = 'absolute'; +els.display = ''; +var originalWidth = element.clientWidth; +var originalHeight = element.clientHeight; +els.display = 'none'; +els.position = originalPosition; +els.visibility = originalVisibility; +return {width: originalWidth, height: originalHeight}; +}, +makePositioned: function(element) { +element = $(element); +var pos = Element.getStyle(element, 'position'); +if (pos == 'static' || !pos) { +element._madePositioned = true; +element.style.position = 'relative'; +if (window.opera) { +element.style.top = 0; +element.style.left = 0; +} +} +}, +undoPositioned: function(element) { +element = $(element); +if (element._madePositioned) { +element._madePositioned = undefined; +element.style.position = +element.style.top = +element.style.left = +element.style.bottom = +element.style.right = ''; +} +}, +makeClipping: function(element) { +element = $(element); +if (element._overflow) return; +element._overflow = element.style.overflow; +if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') +element.style.overflow = 'hidden'; +}, +undoClipping: function(element) { +element = $(element); +if (element._overflow) return; +element.style.overflow = element._overflow; +element._overflow = undefined; +} +}); +var Toggle = new Object(); +Toggle.display = Element.toggle; +Abstract.Insertion = function(adjacency) { +this.adjacency = adjacency; +} +Abstract.Insertion.prototype = { +initialize: function(element, content) { +this.element = $(element); +this.content = content.stripScripts(); +if (this.adjacency && this.element.insertAdjacentHTML) { +try { +this.element.insertAdjacentHTML(this.adjacency, this.content); +} catch (e) { +if (this.element.tagName.toLowerCase() == 'tbody') { +this.insertContent(this.contentFromAnonymousTable()); +} else { +throw e; +} +} +} else { +this.range = this.element.ownerDocument.createRange(); +if (this.initializeRange) this.initializeRange(); +this.insertContent([this.range.createContextualFragment(this.content)]); +} +setTimeout(function() {content.evalScripts()}, 10); +}, +contentFromAnonymousTable: function() { +var div = document.createElement('div'); +div.innerHTML = '' + this.content + '
'; +return $A(div.childNodes[0].childNodes[0].childNodes); +} +} +var Insertion = new Object(); +Insertion.Before = Class.create(); +Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { +initializeRange: function() { +this.range.setStartBefore(this.element); +}, +insertContent: function(fragments) { +fragments.each((function(fragment) { +this.element.parentNode.insertBefore(fragment, this.element); +}).bind(this)); +} +}); +Insertion.Top = Class.create(); +Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { +initializeRange: function() { +this.range.selectNodeContents(this.element); +this.range.collapse(true); +}, +insertContent: function(fragments) { +fragments.reverse(false).each((function(fragment) { +this.element.insertBefore(fragment, this.element.firstChild); +}).bind(this)); +} +}); +Insertion.Bottom = Class.create(); +Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { +initializeRange: function() { +this.range.selectNodeContents(this.element); +this.range.collapse(this.element); +}, +insertContent: function(fragments) { +fragments.each((function(fragment) { +this.element.appendChild(fragment); +}).bind(this)); +} +}); +Insertion.After = Class.create(); +Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { +initializeRange: function() { +this.range.setStartAfter(this.element); +}, +insertContent: function(fragments) { +fragments.each((function(fragment) { +this.element.parentNode.insertBefore(fragment, +this.element.nextSibling); +}).bind(this)); +} +}); +Element.ClassNames = Class.create(); +Element.ClassNames.prototype = { +initialize: function(element) { +this.element = $(element); +}, +_each: function(iterator) { +this.element.className.split(/\s+/).select(function(name) { +return name.length > 0; +})._each(iterator); +}, +set: function(className) { +this.element.className = className; +}, +add: function(classNameToAdd) { +if (this.include(classNameToAdd)) return; +this.set(this.toArray().concat(classNameToAdd).join(' ')); +}, +remove: function(classNameToRemove) { +if (!this.include(classNameToRemove)) return; +this.set(this.select(function(className) { +return className != classNameToRemove; +}).join(' ')); +}, +toString: function() { +return this.toArray().join(' '); +} +} +Object.extend(Element.ClassNames.prototype, Enumerable); +var Field = { +clear: function() { +for (var i = 0; i < arguments.length; i++) +$(arguments[i]).value = ''; +}, +focus: function(element) { +$(element).focus(); +}, +present: function() { +for (var i = 0; i < arguments.length; i++) +if ($(arguments[i]).value == '') return false; +return true; +}, +select: function(element) { +$(element).select(); +}, +activate: function(element) { +element = $(element); +element.focus(); +if (element.select) +element.select(); +} +} +var Form = { +serialize: function(form) { +var elements = Form.getElements($(form)); +var queryComponents = new Array(); +for (var i = 0; i < elements.length; i++) { +var queryComponent = Form.Element.serialize(elements[i]); +if (queryComponent) +queryComponents.push(queryComponent); +} +return queryComponents.join('&'); +}, +getElements: function(form) { +form = $(form); +var elements = new Array(); +for (tagName in Form.Element.Serializers) { +var tagElements = form.getElementsByTagName(tagName); +for (var j = 0; j < tagElements.length; j++) +elements.push(tagElements[j]); +} +return elements; +}, +getInputs: function(form, typeName, name) { +form = $(form); +var inputs = form.getElementsByTagName('input'); +if (!typeName && !name) +return inputs; +var matchingInputs = new Array(); +for (var i = 0; i < inputs.length; i++) { +var input = inputs[i]; +if ((typeName && input.type != typeName) || +(name && input.name != name)) +continue; +matchingInputs.push(input); +} +return matchingInputs; +}, +disable: function(form) { +var elements = Form.getElements(form); +for (var i = 0; i < elements.length; i++) { +var element = elements[i]; +element.blur(); +element.disabled = 'true'; +} +}, +enable: function(form) { +var elements = Form.getElements(form); +for (var i = 0; i < elements.length; i++) { +var element = elements[i]; +element.disabled = ''; +} +}, +findFirstElement: function(form) { +return Form.getElements(form).find(function(element) { +return element.type != 'hidden' && !element.disabled && +['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); +}); +}, +focusFirstElement: function(form) { +Field.activate(Form.findFirstElement(form)); +}, +reset: function(form) { +$(form).reset(); +} +} +Form.Element = { +serialize: function(element) { +element = $(element); +var method = element.tagName.toLowerCase(); +var parameter = Form.Element.Serializers[method](element); +if (parameter) { +var key = encodeURIComponent(parameter[0]); +if (key.length == 0) return; +if (parameter[1].constructor != Array) +parameter[1] = [parameter[1]]; +return parameter[1].map(function(value) { +return key + '=' + encodeURIComponent(value); +}).join('&'); +} +}, +getValue: function(element) { +element = $(element); +var method = element.tagName.toLowerCase(); +var parameter = Form.Element.Serializers[method](element); +if (parameter) +return parameter[1]; +} +} +Form.Element.Serializers = { +input: function(element) { +switch (element.type.toLowerCase()) { +case 'submit': +case 'hidden': +case 'password': +case 'text': +return Form.Element.Serializers.textarea(element); +case 'checkbox': +case 'radio': +return Form.Element.Serializers.inputSelector(element); +} +return false; +}, +inputSelector: function(element) { +if (element.checked) +return [element.name, element.value]; +}, +textarea: function(element) { +return [element.name, element.value]; +}, +select: function(element) { +return Form.Element.Serializers[element.type == 'select-one' ? +'selectOne' : 'selectMany'](element); +}, +selectOne: function(element) { +var value = '', opt, index = element.selectedIndex; +if (index >= 0) { +opt = element.options[index]; +value = opt.value; +if (!value && !('value' in opt)) +value = opt.text; +} +return [element.name, value]; +}, +selectMany: function(element) { +var value = new Array(); +for (var i = 0; i < element.length; i++) { +var opt = element.options[i]; +if (opt.selected) { +var optValue = opt.value; +if (!optValue && !('value' in opt)) +optValue = opt.text; +value.push(optValue); +} +} +return [element.name, value]; +} +} +var $F = Form.Element.getValue; +Abstract.TimedObserver = function() {} +Abstract.TimedObserver.prototype = { +initialize: function(element, frequency, callback) { +this.frequency = frequency; +this.element = $(element); +this.callback = callback; +this.lastValue = this.getValue(); +this.registerCallback(); +}, +registerCallback: function() { +setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); +}, +onTimerEvent: function() { +var value = this.getValue(); +if (this.lastValue != value) { +this.callback(this.element, value); +this.lastValue = value; +} +} +} +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { +getValue: function() { +return Form.Element.getValue(this.element); +} +}); +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { +getValue: function() { +return Form.serialize(this.element); +} +}); +Abstract.EventObserver = function() {} +Abstract.EventObserver.prototype = { +initialize: function(element, callback) { +this.element = $(element); +this.callback = callback; +this.lastValue = this.getValue(); +if (this.element.tagName.toLowerCase() == 'form') +this.registerFormCallbacks(); +else +this.registerCallback(this.element); +}, +onElementEvent: function() { +var value = this.getValue(); +if (this.lastValue != value) { +this.callback(this.element, value); +this.lastValue = value; +} +}, +registerFormCallbacks: function() { +var elements = Form.getElements(this.element); +for (var i = 0; i < elements.length; i++) +this.registerCallback(elements[i]); +}, +registerCallback: function(element) { +if (element.type) { +switch (element.type.toLowerCase()) { +case 'checkbox': +case 'radio': +Event.observe(element, 'click', this.onElementEvent.bind(this)); +break; +case 'password': +case 'text': +case 'textarea': +case 'select-one': +case 'select-multiple': +Event.observe(element, 'change', this.onElementEvent.bind(this)); +break; +} +} +} +} +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { +getValue: function() { +return Form.Element.getValue(this.element); +} +}); +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { +getValue: function() { +return Form.serialize(this.element); +} +}); +if (!window.Event) { +var Event = new Object(); +} +Object.extend(Event, { +KEY_BACKSPACE: 8, +KEY_TAB: 9, +KEY_RETURN: 13, +KEY_ESC: 27, +KEY_LEFT: 37, +KEY_UP: 38, +KEY_RIGHT: 39, +KEY_DOWN: 40, +KEY_DELETE: 46, +element: function(event) { +return event.target || event.srcElement; +}, +isLeftClick: function(event) { +return (((event.which) && (event.which == 1)) || +((event.button) && (event.button == 1))); +}, +pointerX: function(event) { +return event.pageX || (event.clientX + +(document.documentElement.scrollLeft || document.body.scrollLeft)); +}, +pointerY: function(event) { +return event.pageY || (event.clientY + +(document.documentElement.scrollTop || document.body.scrollTop)); +}, +stop: function(event) { +if (event.preventDefault) { +event.preventDefault(); +event.stopPropagation(); +} else { +event.returnValue = false; +event.cancelBubble = true; +} +}, +findElement: function(event, tagName) { +var element = Event.element(event); +while (element.parentNode && (!element.tagName || +(element.tagName.toUpperCase() != tagName.toUpperCase()))) +element = element.parentNode; +return element; +}, +observers: false, +_observeAndCache: function(element, name, observer, useCapture) { +if (!this.observers) this.observers = []; +if (element.addEventListener) { +this.observers.push([element, name, observer, useCapture]); +element.addEventListener(name, observer, useCapture); +} else if (element.attachEvent) { +this.observers.push([element, name, observer, useCapture]); +element.attachEvent('on' + name, observer); +} +}, +unloadCache: function() { +if (!Event.observers) return; +for (var i = 0; i < Event.observers.length; i++) { +Event.stopObserving.apply(this, Event.observers[i]); +Event.observers[i][0] = null; +} +Event.observers = false; +}, +observe: function(element, name, observer, useCapture) { +var element = $(element); +useCapture = useCapture || false; +if (name == 'keypress' && +(navigator.appVersion.match(/Konqueror|Safari|KHTML/) +|| element.attachEvent)) +name = 'keydown'; +this._observeAndCache(element, name, observer, useCapture); +}, +stopObserving: function(element, name, observer, useCapture) { +var element = $(element); +useCapture = useCapture || false; +if (name == 'keypress' && +(navigator.appVersion.match(/Konqueror|Safari|KHTML/) +|| element.detachEvent)) +name = 'keydown'; +if (element.removeEventListener) { +element.removeEventListener(name, observer, useCapture); +} else if (element.detachEvent) { +element.detachEvent('on' + name, observer); +} +} +}); +Event.observe(window, 'unload', Event.unloadCache, false); +var Position = { +includeScrollOffsets: false, +prepare: function() { +this.deltaX = window.pageXOffset +|| document.documentElement.scrollLeft +|| document.body.scrollLeft +|| 0; +this.deltaY = window.pageYOffset +|| document.documentElement.scrollTop +|| document.body.scrollTop +|| 0; +}, +realOffset: function(element) { +var valueT = 0, valueL = 0; +do { +valueT += element.scrollTop || 0; +valueL += element.scrollLeft || 0; +element = element.parentNode; +} while (element); +return [valueL, valueT]; +}, +cumulativeOffset: function(element) { +var valueT = 0, valueL = 0; +do { +valueT += element.offsetTop || 0; +valueL += element.offsetLeft || 0; +element = element.offsetParent; +} while (element); +return [valueL, valueT]; +}, +positionedOffset: function(element) { +var valueT = 0, valueL = 0; +do { +valueT += element.offsetTop || 0; +valueL += element.offsetLeft || 0; +element = element.offsetParent; +if (element) { +p = Element.getStyle(element, 'position'); +if (p == 'relative' || p == 'absolute') break; +} +} while (element); +return [valueL, valueT]; +}, +offsetParent: function(element) { +if (element.offsetParent) return element.offsetParent; +if (element == document.body) return element; +while ((element = element.parentNode) && element != document.body) +if (Element.getStyle(element, 'position') != 'static') +return element; +return document.body; +}, +within: function(element, x, y) { +if (this.includeScrollOffsets) +return this.withinIncludingScrolloffsets(element, x, y); +this.xcomp = x; +this.ycomp = y; +this.offset = this.cumulativeOffset(element); +return (y >= this.offset[1] && +y < this.offset[1] + element.offsetHeight && +x >= this.offset[0] && +x < this.offset[0] + element.offsetWidth); +}, +withinIncludingScrolloffsets: function(element, x, y) { +var offsetcache = this.realOffset(element); +this.xcomp = x + offsetcache[0] - this.deltaX; +this.ycomp = y + offsetcache[1] - this.deltaY; +this.offset = this.cumulativeOffset(element); +return (this.ycomp >= this.offset[1] && +this.ycomp < this.offset[1] + element.offsetHeight && +this.xcomp >= this.offset[0] && +this.xcomp < this.offset[0] + element.offsetWidth); +}, +overlap: function(mode, element) { +if (!mode) return 0; +if (mode == 'vertical') +return ((this.offset[1] + element.offsetHeight) - this.ycomp) / +element.offsetHeight; +if (mode == 'horizontal') +return ((this.offset[0] + element.offsetWidth) - this.xcomp) / +element.offsetWidth; +}, +clone: function(source, target) { +source = $(source); +target = $(target); +target.style.position = 'absolute'; +var offsets = this.cumulativeOffset(source); +target.style.top = offsets[1] + 'px'; +target.style.left = offsets[0] + 'px'; +target.style.width = source.offsetWidth + 'px'; +target.style.height = source.offsetHeight + 'px'; +}, +page: function(forElement) { +var valueT = 0, valueL = 0; +var element = forElement; +do { +valueT += element.offsetTop || 0; +valueL += element.offsetLeft || 0; +if (element.offsetParent==document.body) +if (Element.getStyle(element,'position')=='absolute') break; +} while (element = element.offsetParent); +element = forElement; +do { +valueT -= element.scrollTop || 0; +valueL -= element.scrollLeft || 0; +} while (element = element.parentNode); +return [valueL, valueT]; +}, +clone: function(source, target) { +var options = Object.extend({ +setLeft: true, +setTop: true, +setWidth: true, +setHeight: true, +offsetTop: 0, +offsetLeft: 0 +}, arguments[2] || {}) +source = $(source); +var p = Position.page(source); +target = $(target); +var delta = [0, 0]; +var parent = null; +if (Element.getStyle(target,'position') == 'absolute') { +parent = Position.offsetParent(target); +delta = Position.page(parent); +} +if (parent == document.body) { +delta[0] -= document.body.offsetLeft; +delta[1] -= document.body.offsetTop; +} +if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; +if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; +if(options.setWidth) target.style.width = source.offsetWidth + 'px'; +if(options.setHeight) target.style.height = source.offsetHeight + 'px'; +}, +absolutize: function(element) { +element = $(element); +if (element.style.position == 'absolute') return; +Position.prepare(); +var offsets = Position.positionedOffset(element); +var top = offsets[1]; +var left = offsets[0]; +var width = element.clientWidth; +var height = element.clientHeight; +element._originalLeft = left - parseFloat(element.style.left || 0); +element._originalTop = top - parseFloat(element.style.top || 0); +element._originalWidth = element.style.width; +element._originalHeight = element.style.height; +element.style.position = 'absolute'; +element.style.top = top + 'px';; +element.style.left = left + 'px';; +element.style.width = width + 'px';; +element.style.height = height + 'px';; +}, +relativize: function(element) { +element = $(element); +if (element.style.position == 'relative') return; +Position.prepare(); +element.style.position = 'relative'; +var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); +var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); +element.style.top = top + 'px'; +element.style.left = left + 'px'; +element.style.height = element._originalHeight; +element.style.width = element._originalWidth; +} +} +if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { +Position.cumulativeOffset = function(element) { +var valueT = 0, valueL = 0; +do { +valueT += element.offsetTop || 0; +valueL += element.offsetLeft || 0; +if (element.offsetParent == document.body) +if (Element.getStyle(element, 'position') == 'absolute') break; +element = element.offsetParent; +} while (element); +return [valueL, valueT]; +} +} diff --git a/test/expected_dir/js1.js/javascript/comment b/test/expected_dir/js1.js/javascript/comment new file mode 100644 index 0000000..71f7f83 --- /dev/null +++ b/test/expected_dir/js1.js/javascript/comment @@ -0,0 +1,46 @@ +/* Prototype JavaScript framework, version 1.4.0 +* (c) 2005 Sam Stephenson +* +* Prototype is freely distributable under the terms of an MIT-style license. +* For details, see the Prototype web site: http://prototype.conio.net/ +* +/*--------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------*/ +/* Force "Connection: close" for Mozilla browsers to work around +* a bug where XMLHttpReqeuest sends an incorrect Content-length +* header. See Mozilla Bugzilla #246651. +*/ +/* Avoid memory leak in MSIE: clean up the oncomplete event handler */ +/*--------------------------------------------------------------------------*/ +// removes whitespace-only text node children +// All *Width and *Height properties give 0 on elements with display none, +// so enable the element temporarily +// Opera returns the offset relative to the positioning context, when an +// element is position relative but top and left have not been defined +/*--------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------*/ +// find the first node with the given tagName, starting from the +// node the event was triggered on; traverses the DOM upwards +/* prevent memory leaks in IE */ +// set to true if needed, warning: firefox performance problems +// NOT neeeded for page scrolling, only if draggable contained in +// scrollable elements +// must be called before calling withinIncludingScrolloffset, every time the +// page is scrolled +// caches x/y coordinate pair to use with overlap +// within must be called directly before +// Safari fix +// find page position of source +// find coordinate system to use +// delta [0,0] will do fine with position: fixed elements, +// position:absolute needs offsetParent deltas +// correct by body offsets (fixes Safari) +// set position +// Safari returns margins on body which is incorrect if the child is absolutely +// positioned. For performance reasons, redefine Position.cumulativeOffset for +// KHTML/WebKit only. diff --git a/test/expected_dir/js2.js/javascript/code b/test/expected_dir/js2.js/javascript/code new file mode 100644 index 0000000..2b8e7c5 --- /dev/null +++ b/test/expected_dir/js2.js/javascript/code @@ -0,0 +1,6 @@ + diff --git a/test/expected_dir/js2.js/javascript/comment b/test/expected_dir/js2.js/javascript/comment new file mode 100644 index 0000000..636c0ba --- /dev/null +++ b/test/expected_dir/js2.js/javascript/comment @@ -0,0 +1,7 @@ +/* +Random Comments +Foo Foo Foo +*/ +// comment +// another comment +//Set delay before submenu disappears after mouse moves out of it (in milliseconds) diff --git a/test/expected_dir/jsp1.jsp/html/code b/test/expected_dir/jsp1.jsp/html/code new file mode 100644 index 0000000..c34bf15 --- /dev/null +++ b/test/expected_dir/jsp1.jsp/html/code @@ -0,0 +1,8 @@ + + +JSP page + + +%> + + diff --git a/test/expected_dir/jsp1.jsp/java/blanks b/test/expected_dir/jsp1.jsp/java/blanks new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/test/expected_dir/jsp1.jsp/java/blanks @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/test/expected_dir/jsp1.jsp/java/code b/test/expected_dir/jsp1.jsp/java/code new file mode 100644 index 0000000..e139ba9 --- /dev/null +++ b/test/expected_dir/jsp1.jsp/java/code @@ -0,0 +1,2 @@ +<%@ page language="java" %> +<% out.println("Hello World"); %> diff --git a/test/expected_dir/jsp1.jsp/java/comment b/test/expected_dir/jsp1.jsp/java/comment new file mode 100644 index 0000000..49d6ff4 --- /dev/null +++ b/test/expected_dir/jsp1.jsp/java/comment @@ -0,0 +1,4 @@ +<% // comment +/* +* more comment +*/ diff --git a/test/expected_dir/lsp1.lsp/lisp/blanks b/test/expected_dir/lsp1.lsp/lisp/blanks new file mode 100644 index 0000000..7003e7f --- /dev/null +++ b/test/expected_dir/lsp1.lsp/lisp/blanks @@ -0,0 +1 @@ +51 \ No newline at end of file diff --git a/test/expected_dir/lsp1.lsp/lisp/code b/test/expected_dir/lsp1.lsp/lisp/code new file mode 100644 index 0000000..b79eef4 --- /dev/null +++ b/test/expected_dir/lsp1.lsp/lisp/code @@ -0,0 +1,46 @@ +(DEFUN THROW-DIE () +(+ (RANDOM 6) 1) ;;; get a random number between 0 and 5 and then add 1 +) +(DEFUN THROW-DICE () +(LIST (THROW-DIE) (THROW-DIE)) ;;; create a list with two random numbers +) +(DEFUN BOXCARS-P (A B) +(AND (EQUAL '6 A) +(EQUAL '6 B) +) +) +(DEFUN SNAKE-EYES-P (A B) +(AND (EQUAL '1 A) +(EQUAL '1 B) +) +) +(DEFUN INSTANT-WIN-P (A B) +(OR (EQUAL '7 (+ A B)) +(EQUAL '11 (+ A B)) +) +) +(DEFUN INSTANT-LOSS-P (A B) +(OR (EQUAL '2 (+ A B)) +(EQUAL '3 (+ A B)) +(EQUAL '12 (+ A B)) +) +) +(DEFUN SAY-THROW (A B) +(COND ((BOXCARS-P A B) 'BOXCARS) ;;; make use of function BOXCARS_P +((SNAKE-EYES-P A B) 'SNAKE-EYES) ;;; make use of function SNAKE_EYES_P +) +) +(DEFUN CRAPS () +(LET THROW (THROW-DICE)) ;;; get initial roll of the dice +(COND ((INSTANT-WIN-P (FIRST THROW) (SECOND THROW)) +(LIST 'THROW (FIRST THROW) 'AND (SECOND THROW) '-- (+ (FIRST THROW) (SECOND THROW)) '-- 'YOU 'WIN)) +((INSTANT-LOSS-P (FIRST THROW) (SECOND THROW)) +(IF (EQUAL 'NIL (SAY-THROW (FIRST THROW) (SECOND THROW))) ;;; if Nil then LIST appropriate output +(LIST 'THROW (FIRST THROW) 'AND (SECOND THROW) '-- (+ (FIRST THROW) (SECOND THROW)) '-- 'YOU 'LOSE) +(LIST 'THROW (FIRST THROW) 'AND (SECOND THROW) '-- (SAY-THROW (FIRST THROW) (SECOND THROW)) +'-- 'YOU 'LOSE))) +(T (LIST 'THROW (FIRST THROW) 'AND (SECOND THROW) '-- 'YOUR 'POINT 'IS (+ (FIRST THROW) +(SECOND THROW)))) +) ;;; end COND +) ;;; end LET +) diff --git a/test/expected_dir/lsp1.lsp/lisp/comment b/test/expected_dir/lsp1.lsp/lisp/comment new file mode 100644 index 0000000..5c03aeb --- /dev/null +++ b/test/expected_dir/lsp1.lsp/lisp/comment @@ -0,0 +1,36 @@ +;;; CrapsSim.lsp +;;; The main purpose of this program was to implement a Craps game, using a language that we have just +;;; learned. Also, it was written in a functional style with almost no reliance on the assignment +;;; operation. Only one local variable called THROW was used. +;;; ====================================================================================================== ;;; +;;; ======================================= CRAPS SIMULATION ============================================= ;;; +;;; ====================================================================================================== ;;; +;;; ** This function takes no parameters as input and returns a random number between 1 and 6. ** +;;; ====================================================================================================== ;;; +;;; ** This function takes no parameters as input and returns a LIST with two numbers between 1 and 6. ** +;;; ====================================================================================================== ;;; +;;; ** This function takes two numbers as parameters for input and returns T or Nil. T is returned if both +;;; numbers are equal to 6. Nil is returned otherwise. ** +;;; ====================================================================================================== ;;; +;;; ** This function takes two numbers as parameters for input and returns T or Nil. T is returned if both +;;; numbers are equal to 1. Nil is returned otherwise. ** +;;; ====================================================================================================== ;;; +;;; ** This function takes two numbers as parameters for input and returns T or Nil. T is returned if the +;;; sum of both numbers is equal to a 7 or 11. Nil is returned otherwise. ** +;;; ====================================================================================================== ;;; +;;; ** This function takes two numbers as parameters for input and returns T or Nil. T is returned if the +;;; sum of both numbers is equal to a 2, 3 or 12. Nil is returned otherwise. ** +;;; ====================================================================================================== ;;; +;;; ** This function takes two numbers as parameters for input and returns a string. If function BOXCARS_P +;;; returns T, then the returned string equals BOXCARS. If function SNAKE_EYES_P returns T, then the +;;; returned string equals SNAKE_EYES. The string contains Nil otherwise. ** +;;; ====================================================================================================== ;;; +;;; ** This is the main function used to simulate the game of craps. Variable THROW contains a LIST of two +;;; numbers between 1 and 6. The numbers located in THROW, are used as parameters for the other functions. +;;; The several pieces used for output are listed together and then the LIST is returned from this +;;; function. +;;; if roll is a win, then LIST the appropriate output +;;; if roll is a loss, then check for BOXCARS or SNAKE-EYES +;;; else include the BOXCARS or SNAKE-EYES string in the output +;;; if roll is not instant win or loss then output sum of dice +;;; ======================================== END OF PROGRAM CRAPS ======================================== ;;; diff --git a/test/expected_dir/lua1.lua/lua/blanks b/test/expected_dir/lua1.lua/lua/blanks new file mode 100644 index 0000000..3cacc0b --- /dev/null +++ b/test/expected_dir/lua1.lua/lua/blanks @@ -0,0 +1 @@ +12 \ No newline at end of file diff --git a/test/expected_dir/lua1.lua/lua/code b/test/expected_dir/lua1.lua/lua/code new file mode 100644 index 0000000..32b5ead --- /dev/null +++ b/test/expected_dir/lua1.lua/lua/code @@ -0,0 +1,100 @@ +function q_create() +local q = {} +q.first = 0 +q.last = 0 +return q +end +function q_insert(q, s) +q[q.last] = s +q.last = q.last + 1 +end +function q_empty(q) +return q.first >= q.last +end +function q_remove(q) +if q_empty(q) then +return nil +end +local s = q[q.first] +q[q.first] = nil +q.first = q.first+1 +return s +end +function q_card(q) +return q.last - q.first +end +function q_length(q, f) +local l, i = 0, q.first +while i < q.last do +l = l + strlen(q[i]) +i = i + 1 +end +return l +end +function justify(q) +local blanks = MAX - q_length(q) +local skips = q_card(q) - 1 +local line = q_remove(q) +local quotient = floor(blanks/skips) +local reminder = blanks/skips - quotient +local error = 0 +while skips > 0 do +error = error + reminder +if error >= 0.5 then +error = error - 1 +line = line .. strrep(" ", quotient+1) +else +line = line .. strrep(" ", quotient) +end +line = line .. q_remove(q) +skips = skips - 1 +end +return line or "" +end +function catenate(q) +local line = q_remove(q) +while not q_empty(q) do +line = line .. " " .. q_remove(q) +end +return line or "" +end +DEFMAX = 72 +if not arg or getn(arg) < 1 then +MAX = DEFMAX +else +MAX = tonumber(arg[1]) +if not MAX or MAX < 0 then +MAX = DEFMAX +end +end +text = q_create() +line = read() +while line do +_, n = gsub(line, "(%S+)", function (s) q_insert(%text, s) end) +if n == 0 then +q_insert(text, "\n") +end +line = read() +end +line = q_create() +word = q_remove(text) +size = 0 +while word do +if word == "\n" then +if not q_empty(line) then +write(catenate(line), "\n\n") +else +write("\n") +end +size = 0 +elseif size + strlen(word) > MAX then +write(justify(line), "\n") +size = 0 +end +if word ~= "\n" then +q_insert(line, word) +size = size + strlen(word) + 1 +end +word = q_remove(text) +end +write(catenate(line), "\n") diff --git a/test/expected_dir/lua1.lua/lua/comment b/test/expected_dir/lua1.lua/lua/comment new file mode 100644 index 0000000..7f5dbe6 --- /dev/null +++ b/test/expected_dir/lua1.lua/lua/comment @@ -0,0 +1,9 @@ +-- random code from http://lua-users.org/wiki/TextJustification +-- easy queue implementation ------------------------------------------ +-- line creation routines ------------------------------------------ +-- justifies one line to fit into MAX columns +-- join all words with one space between them +-- main program ----------------------------------------------------- +-- tries to get MAX from command-line +-- collects all text from stdin +-- justify paragraphs diff --git a/test/expected_dir/matlab1.m/matlab/blanks b/test/expected_dir/matlab1.m/matlab/blanks new file mode 100644 index 0000000..f11c82a --- /dev/null +++ b/test/expected_dir/matlab1.m/matlab/blanks @@ -0,0 +1 @@ +9 \ No newline at end of file diff --git a/test/expected_dir/matlab1.m/matlab/code b/test/expected_dir/matlab1.m/matlab/code new file mode 100644 index 0000000..0c0b7d9 --- /dev/null +++ b/test/expected_dir/matlab1.m/matlab/code @@ -0,0 +1,29 @@ +r=0.3458; % intrinsic rate of increase--Butterflies at Jasper Ridge +K=846.017; % carrying capacity +theta=1; % nonlinearity in density dependence +sigma2=1.1151; % environmental variance +Nc=94; % starting population size +Nx=20; % quasi-extinction threshold +tmax=20; % time horizon +NumReps=50000; % number of replicate population trajectories +sigma=sqrt(sigma2); +randn('state',sum(100*clock)); % seed the random number generator +N=Nc*ones(1,NumReps); % all NumRep populations start at Nc +NumExtant=NumReps; % all populations are initially extant +Extant=[NumExtant]; % vector for number of extant pops. vs. time +for t=1:tmax, % For each future time, +N=N.*exp( r*( 1-(N/K).^theta )... % the theta logistic model ++ sigma*randn(1,NumExtant) ); % with random environmental effects. +for i=NumExtant:-1:1, % Then, looping over all extant populations, +if N(i)<=Nx, % if at or below quasi-extinction threshold, +N(i)=[]; % delete the population. +end; +end; +NumExtant=length(N); % Count remaining extant populations +Extant=[Extant NumExtant]; % and store the result. +end; +ProbExtinct=(NumReps-Extant)/NumReps; +plot([0:tmax],ProbExtinct) +xlabel('Years into the future'); +ylabel('Cumulative probability of quasi-extinction'); +axis([0 tmax 0 1]); diff --git a/test/expected_dir/matlab1.m/matlab/comment b/test/expected_dir/matlab1.m/matlab/comment new file mode 100644 index 0000000..e9dae13 --- /dev/null +++ b/test/expected_dir/matlab1.m/matlab/comment @@ -0,0 +1,16 @@ +% PROGRAM theta_logistic.m +% Calculates by simulation the probability that a population +% following the theta logistic model and starting at Nc will fall +% below the quasi-extinction threshold Nx at or before time tmax +% SIMULATION PARAMETERS +% for butterflies (Euphydryas editha bayensis) at Jasper Ridge (population C) +% SIMULATION CODE +% OUTPUT CODE +% ComputeS quasi-extinction probability as the fraction of replicate +% populations that have hit the threshold by each future time, +% and plotS quasi-extinction probability vs. time +% Integrate solution exactly % +% Options=[]; +% [T,true] = ode45(@logistic,[0,20],Nc,Options,r,K,theta); +% subplot(1,2,2) +% plot([1:tmax],P,'r.-',T,true,'g.-') diff --git a/test/expected_dir/pascal1.pas/pascal/blanks b/test/expected_dir/pascal1.pas/pascal/blanks new file mode 100644 index 0000000..f11c82a --- /dev/null +++ b/test/expected_dir/pascal1.pas/pascal/blanks @@ -0,0 +1 @@ +9 \ No newline at end of file diff --git a/test/expected_dir/pascal1.pas/pascal/code b/test/expected_dir/pascal1.pas/pascal/code new file mode 100644 index 0000000..263e32f --- /dev/null +++ b/test/expected_dir/pascal1.pas/pascal/code @@ -0,0 +1,90 @@ +unit pndefs; +interface +uses SysUtils; +function CreatePNFile(filename : string; Text : pChar) : Boolean; +function StripNewLines(aString: string): string; +procedure ConvertTypes(filename : string); +const strFileTypes : PChar = ('.txt'); +strOpenTypes : PChar = ('%2|Text files (*.txt)|*.txt|0|0|0|LOG files (*.log)|*.log|0|0|0|Executable Files (*.exe, *.com, *.dll)|*.exe;*.com;*.dll|0|0|0'); +sepChar = '|'; +verChar = '%'; +CurrFileVer = '2'; +implementation +function CreatePNFile(filename : string; Text : pChar) : Boolean; +var F : TextFile; +begin +AssignFile(F, filename); +Rewrite(F); +Write(F, Text); +CloseFile(F); +If IOResult <> 0 Then Result := False +Else Result := True; +end; +function StripNewLines(aString: string): string; +var i : longint; +begin +result := ''; +i := 1; +while i <= length(aString) do +begin +if aString[i] = #13 then result := result + ' ' else +if aString[i] <> #10 then result := result + aString[i]; +inc(i); +end; +end; +procedure ConvertTypes(filename : string); +var t : TextFile; +s : string; +ps : string; {part of string} +Part : integer; +ipos : integer; +OutStr : string; +const Desc = 1; +Files = 2; +Parser = 3; +Unix = 4; +begin +OutStr := VerChar + CurrFileVer; +if not fileexists(filename) then +begin +CreatePNFile(filename, strOpenTypes); +exit; +end; +Assignfile(t, FileName); +Reset(t); +repeat +Readln(t, s) +until (Length(s) > 0) or EOF(t); +CloseFile(t); +if s = '' then Exit; +part := Desc; +repeat +iPos := Pos(SepChar, s); +if (iPos = 0) and (Length(s) > 0) then +begin +ps := s; +s := ''; +end else +ps := Copy(s, 1, ipos - 1); +s := Copy(S, ipos + 1, Length(s)); +case part of +Desc : begin +OutStr := OutStr + SepChar + ps; +part := Files; +end; +Files : begin +OutStr := OutStr + SepChar + ps; +part := Parser; +end; +Parser : begin +OutStr := OutStr + SepChar + ps + SepChar + '0' + SepChar + '0'; +part := Desc; +end; +end; +until Length(s) < 1; +Assignfile(t, filename); +Rewrite(t); +Write(t, OutStr); +CloseFile(t); +end; +end. diff --git a/test/expected_dir/pascal1.pas/pascal/comment b/test/expected_dir/pascal1.pas/pascal/comment new file mode 100644 index 0000000..de8ff05 --- /dev/null +++ b/test/expected_dir/pascal1.pas/pascal/comment @@ -0,0 +1,13 @@ +{*************************************************************** +* +* Unit Name: pndefs +* Purpose : Various Definitions and functions... +* Author : Simon Steele +* Copyright: This Source Code is Copyright © 1998-2000 Echo +* Software and Simon Steele. Please read the license +* agreement at www.pnotepad.org/press/psidx.html. +**************************************************************} +{$I-} +{$I+} +// This assumes that it is being passed one of the old style type definition +// files. We'll set the status on the main form to indicate this as well... diff --git a/test/expected_dir/pascal2.pp/pascal/blanks b/test/expected_dir/pascal2.pp/pascal/blanks new file mode 100644 index 0000000..f11c82a --- /dev/null +++ b/test/expected_dir/pascal2.pp/pascal/blanks @@ -0,0 +1 @@ +9 \ No newline at end of file diff --git a/test/expected_dir/pascal2.pp/pascal/code b/test/expected_dir/pascal2.pp/pascal/code new file mode 100644 index 0000000..263e32f --- /dev/null +++ b/test/expected_dir/pascal2.pp/pascal/code @@ -0,0 +1,90 @@ +unit pndefs; +interface +uses SysUtils; +function CreatePNFile(filename : string; Text : pChar) : Boolean; +function StripNewLines(aString: string): string; +procedure ConvertTypes(filename : string); +const strFileTypes : PChar = ('.txt'); +strOpenTypes : PChar = ('%2|Text files (*.txt)|*.txt|0|0|0|LOG files (*.log)|*.log|0|0|0|Executable Files (*.exe, *.com, *.dll)|*.exe;*.com;*.dll|0|0|0'); +sepChar = '|'; +verChar = '%'; +CurrFileVer = '2'; +implementation +function CreatePNFile(filename : string; Text : pChar) : Boolean; +var F : TextFile; +begin +AssignFile(F, filename); +Rewrite(F); +Write(F, Text); +CloseFile(F); +If IOResult <> 0 Then Result := False +Else Result := True; +end; +function StripNewLines(aString: string): string; +var i : longint; +begin +result := ''; +i := 1; +while i <= length(aString) do +begin +if aString[i] = #13 then result := result + ' ' else +if aString[i] <> #10 then result := result + aString[i]; +inc(i); +end; +end; +procedure ConvertTypes(filename : string); +var t : TextFile; +s : string; +ps : string; {part of string} +Part : integer; +ipos : integer; +OutStr : string; +const Desc = 1; +Files = 2; +Parser = 3; +Unix = 4; +begin +OutStr := VerChar + CurrFileVer; +if not fileexists(filename) then +begin +CreatePNFile(filename, strOpenTypes); +exit; +end; +Assignfile(t, FileName); +Reset(t); +repeat +Readln(t, s) +until (Length(s) > 0) or EOF(t); +CloseFile(t); +if s = '' then Exit; +part := Desc; +repeat +iPos := Pos(SepChar, s); +if (iPos = 0) and (Length(s) > 0) then +begin +ps := s; +s := ''; +end else +ps := Copy(s, 1, ipos - 1); +s := Copy(S, ipos + 1, Length(s)); +case part of +Desc : begin +OutStr := OutStr + SepChar + ps; +part := Files; +end; +Files : begin +OutStr := OutStr + SepChar + ps; +part := Parser; +end; +Parser : begin +OutStr := OutStr + SepChar + ps + SepChar + '0' + SepChar + '0'; +part := Desc; +end; +end; +until Length(s) < 1; +Assignfile(t, filename); +Rewrite(t); +Write(t, OutStr); +CloseFile(t); +end; +end. diff --git a/test/expected_dir/pascal2.pp/pascal/comment b/test/expected_dir/pascal2.pp/pascal/comment new file mode 100644 index 0000000..de8ff05 --- /dev/null +++ b/test/expected_dir/pascal2.pp/pascal/comment @@ -0,0 +1,13 @@ +{*************************************************************** +* +* Unit Name: pndefs +* Purpose : Various Definitions and functions... +* Author : Simon Steele +* Copyright: This Source Code is Copyright © 1998-2000 Echo +* Software and Simon Steele. Please read the license +* agreement at www.pnotepad.org/press/psidx.html. +**************************************************************} +{$I-} +{$I+} +// This assumes that it is being passed one of the old style type definition +// files. We'll set the status on the main form to indicate this as well... diff --git a/test/expected_dir/perl.cgi/perl/blanks b/test/expected_dir/perl.cgi/perl/blanks new file mode 100644 index 0000000..da2d398 --- /dev/null +++ b/test/expected_dir/perl.cgi/perl/blanks @@ -0,0 +1 @@ +14 \ No newline at end of file diff --git a/test/expected_dir/perl.cgi/perl/code b/test/expected_dir/perl.cgi/perl/code new file mode 100644 index 0000000..4957a35 --- /dev/null +++ b/test/expected_dir/perl.cgi/perl/code @@ -0,0 +1,47 @@ +use strict; +use CGI qw/:standard/; +use CGI::Ajax; +use DBI; +my $dbh = do 'db.inc'; +my $query = q{ SELECT project.project_id, project.name, project.phase, prio.prio, +HEX((255 - prio.prio)) AS hex, begun, tags +FROM project JOIN prio +ON (project.project_id = prio.project_id) +WHERE completed < 1 +ORDER BY prio.prio DESC LIMIT 3}; +my $sth = $dbh->prepare($query); +$sth->execute(); +my $result = $dbh->selectall_arrayref($sth); +my $cgi = new CGI; +my $pjx = new CGI::Ajax( 'toStruck' => \&perl_func ); +print $pjx->build_html( $cgi, \&Show_HTML); +sub Show_HTML { +use CGI qw/:standard/; +my $html = < + + +This is the lastest source version + + + +

Carrot Queue

Priority List  |   +Add a listing  |  

Project listing

+HEAD +foreach my $row (@$result) { +$html .= ""; +$html .= "
" . @$row[1] . "

"; +} +$html .= ""; +return $html; +} +sub perl_func { +my $input=shift; +if ($input eq "ON") { +$input=""; +} else { +$input =""; +} +} diff --git a/test/expected_dir/perl.cgi/perl/comment b/test/expected_dir/perl.cgi/perl/comment new file mode 100644 index 0000000..8844721 --- /dev/null +++ b/test/expected_dir/perl.cgi/perl/comment @@ -0,0 +1,5 @@ +#!/usr/bin/perl -w +# ajaxCheckbox.pl - a script to test Ajax functionality +# --- database authenication +# you can append stuff to the HTML this way +# if onClick the change the style diff --git a/test/expected_dir/perl1.pl/perl/blanks b/test/expected_dir/perl1.pl/perl/blanks new file mode 100644 index 0000000..3cacc0b --- /dev/null +++ b/test/expected_dir/perl1.pl/perl/blanks @@ -0,0 +1 @@ +12 \ No newline at end of file diff --git a/test/expected_dir/perl1.pl/perl/code b/test/expected_dir/perl1.pl/perl/code new file mode 100644 index 0000000..768585f --- /dev/null +++ b/test/expected_dir/perl1.pl/perl/code @@ -0,0 +1,45 @@ +use Time::ParseDate; +use Time::CTime; +use LWP::Simple; +$dir="/usr/local/etc/httpd/htdocs/Dilbert"; +$location ="$dir/dilbert.gif"; +$_ = get("http://www.unitedmedia.com/comics/dilbert/index.html"); +s/^.*strip_left\.gif//s; +s/^.*?HREF=\"//s; +s/\">.*$//s; +$line = "http://www.unitedmedia.com" . $_; +# Back up yesterday's image: +# get the number +open (ID,"$dir/id"); +$id=; +close ID; +$id++; +$id=~s/\n$//; +`mv $location $dir/dilbert.$id.gif`; +# If you're using this on NT, you may want to replace 'mv' +# with 'move'. +open (ID,">$dir/id"); +print ID "$id"; +close ID; +# Now get the actual image +$_ = get($line); +open (FILE, ">$location"); +binmode FILE; # Important for NT +print FILE; +close FILE; +# Now I want to update the index.html file +open (FILE, "$dir/index.html"); +@index=; +close FILE; +$yesterday = parsedate('yesterday'); +$printdate = strftime('%a, %b %d', localtime($yesterday)); +open (FILE, ">$dir/index.html"); +for (@index) { +if (/INSERT HERE/) { +print FILE "$_"; +print FILE "$printdate\n"; +if (($id % 5) == 0) {print FILE "\n"} +} +else {print FILE "$_"}; +} # End for +close FILE; diff --git a/test/expected_dir/perl1.pl/perl/comment b/test/expected_dir/perl1.pl/perl/comment new file mode 100644 index 0000000..d9fab5e --- /dev/null +++ b/test/expected_dir/perl1.pl/perl/comment @@ -0,0 +1,15 @@ +#!/usr/bin/perl +# Conserve bandwidth - put a copy of Dilbert on your intranet. +# Run every morning with cron - after about 7am Eastern +######################################################## +# Where do you want the image put? +# $dir = "c:/httpd/htdocs/Dilbert"; +# These next 4 lines will change every time they change the +# page layout on the Dilbert site. Check back on my web site +# if things suddenly stop working +# Start with an index.html file containing ... +# +# +#
+# ... +# And whatever else you want on the page. diff --git a/test/expected_dir/php1.php/css/code b/test/expected_dir/php1.php/css/code new file mode 100644 index 0000000..b42db9a --- /dev/null +++ b/test/expected_dir/php1.php/css/code @@ -0,0 +1,3 @@ +h1 { +color: black; +} diff --git a/test/expected_dir/php1.php/css/comment b/test/expected_dir/php1.php/css/comment new file mode 100644 index 0000000..5912a96 --- /dev/null +++ b/test/expected_dir/php1.php/css/comment @@ -0,0 +1 @@ +/* css comment */ diff --git a/test/expected_dir/php1.php/html/blanks b/test/expected_dir/php1.php/html/blanks new file mode 100644 index 0000000..bf0d87a --- /dev/null +++ b/test/expected_dir/php1.php/html/blanks @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/test/expected_dir/php1.php/html/code b/test/expected_dir/php1.php/html/code new file mode 100644 index 0000000..9d65c2e --- /dev/null +++ b/test/expected_dir/php1.php/html/code @@ -0,0 +1,21 @@ + + + + + + + + + + + + +
FirstLastEmail +
+ + + + diff --git a/test/expected_dir/php1.php/javascript/code b/test/expected_dir/php1.php/javascript/code new file mode 100644 index 0000000..b14f5c0 --- /dev/null +++ b/test/expected_dir/php1.php/javascript/code @@ -0,0 +1 @@ +document.write("Hello World!") diff --git a/test/expected_dir/php1.php/javascript/comment b/test/expected_dir/php1.php/javascript/comment new file mode 100644 index 0000000..ecd132d --- /dev/null +++ b/test/expected_dir/php1.php/javascript/comment @@ -0,0 +1 @@ +// javascript comment diff --git a/test/expected_dir/php1.php/php/code b/test/expected_dir/php1.php/php/code new file mode 100644 index 0000000..4ea6122 --- /dev/null +++ b/test/expected_dir/php1.php/php/code @@ -0,0 +1,20 @@ + + + + + diff --git a/test/expected_dir/php1.php/php/comment b/test/expected_dir/php1.php/php/comment new file mode 100644 index 0000000..7fe642a --- /dev/null +++ b/test/expected_dir/php1.php/php/comment @@ -0,0 +1,2 @@ +// Spaghetti code starts....(slopping html code in) +// Spaghetti code is both a source of praise and complaints diff --git a/test/expected_dir/py1.py/python/blanks b/test/expected_dir/py1.py/python/blanks new file mode 100644 index 0000000..f11c82a --- /dev/null +++ b/test/expected_dir/py1.py/python/blanks @@ -0,0 +1 @@ +9 \ No newline at end of file diff --git a/test/expected_dir/py1.py/python/code b/test/expected_dir/py1.py/python/code new file mode 100644 index 0000000..39890a5 --- /dev/null +++ b/test/expected_dir/py1.py/python/code @@ -0,0 +1,20 @@ +"\" +# still in string +" +'\' +# still in string +' +import smtplib +smtpServer='smtp.yourdomain.com'; +fromAddr='xah@xahlee.org'; +toAddr='xah@xahlee.org'; +text='''Subject: newfound love +Hi friend, +long time no write, i have a new manifesto i +think it would be of interest for you to peruse. +... +''' +server = smtplib.SMTP(smtpServer) +server.set_debuglevel(1) +server.sendmail(fromAddr, toAddr, text) +server.quit() diff --git a/test/expected_dir/py1.py/python/comment b/test/expected_dir/py1.py/python/comment new file mode 100644 index 0000000..145f233 --- /dev/null +++ b/test/expected_dir/py1.py/python/comment @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Python +# Suppose you want to spam your friend, and you have lots of +# friends. The solution is to write a program to do it. After a gander +# at python docs, one easily found the module for the job. +# see http://python.org/doc/2.3.4/lib/SMTP-example.html +# the code is a bit long with the command line, but the key lies at +# the bottom four lines. The gist is this: +####### test: strings - nonsense code follows +####### test done +# save this file as x.py and run it. +# it should send out the mail. +# the set_debuglevel() is nice because you see all the interactions +# with the smtp server. Useful when you want to see what's going on +# with a smtp server. diff --git a/test/expected_dir/rexx1.rex/rexx/blanks b/test/expected_dir/rexx1.rex/rexx/blanks new file mode 100644 index 0000000..72f523f --- /dev/null +++ b/test/expected_dir/rexx1.rex/rexx/blanks @@ -0,0 +1 @@ +39 \ No newline at end of file diff --git a/test/expected_dir/rexx1.rex/rexx/code b/test/expected_dir/rexx1.rex/rexx/code new file mode 100644 index 0000000..1cc1366 --- /dev/null +++ b/test/expected_dir/rexx1.rex/rexx/code @@ -0,0 +1,231 @@ +*/ arg argline +address TSO /* REXXSKEL ver.19991109 */ +arg parms "((" opts +signal on syntax +signal on novalue +call TOOLKIT_INIT /* conventional start-up -*/ +rc = Trace(tv) +info = parms /* to enable parsing */ +if \sw.inispf then do +arg line +line = line "(( RESTARTED" /* tell the next invocation */ +"ISPSTART CMD("exec_name line")" /* Invoke ISPF if nec. */ +exit /* ...and restart it */ +end +call A_INIT /* -*/ +"NEWSTACK" +if \sw.0error_found then, +call C_TABLE_OPS /* -*/ +if \sw.0error_found then, +call D_PUMP_TBL /* -*/ +"DELSTACK" +if sw.restarted then do +rc = OutTrap("ll.") +exit 4 +end +exit /*@ FLTTBL */ +A_INIT: /*@ */ +if branch then call BRANCH +address TSO +call AA_KEYWDS /* -*/ +parse var info $tn$ . /* table-name required */ +if $tn$ = "" then do +helpmsg = "Tablename is required." +call HELP +end +parse value outdsn "FLATTBLS."$tn$ with, +outdsn . +xefef = "efef"x +if tblds = "" then do +call AB_FIND_LIBRARY /* -*/ +if tblds = "" then do +helpmsg = "Table" $tn$ "was not found in ISPTLIB. Please", +"restart specifying a library name as shown below." +call HELP /* ...and don't come back */ +end +end +else, +if Left(tblds,1) = "'" then tblds = Strip(tblds,,"'") +else tblds = Userid()"."tblds +return /*@ A_INIT */ +AA_KEYWDS: /*@ */ +if branch then call BRANCH +address TSO +tblds = KEYWD("IN") +outdsn = KEYWD("OUTPUT") +sortseq = KEYWD("SORT") +sw.0purge = SWITCH("DELETEBEHIND") +parse value KEYWD("ADD") "0" with bytes_to_add . +return /*@ AA_KEYWDS */ +AB_FIND_LIBRARY: /*@ */ +if branch then call BRANCH +address TSO +"NEWSTACK" +"LA ISPTLIB ((STACK LINE" +pull tliblist +"DELSTACK" +do Words(tliblist) /* each library */ +parse var tliblist tblds tliblist +if Sysdsn("'"tblds"("$tn$")'") = "OK" then return +end /* tliblist */ +tblds = "" +return /*@ AB_FIND_LIBRARY */ +C_TABLE_OPS: /*@ */ +if branch then call BRANCH +address ISPEXEC +call CA_OPEN_TBL /* -*/ +call CS_SPIN_TBL /* -*/ +call CZ_DROP_TBL /* -*/ +return /*@ C_TABLE_OPS */ +CA_OPEN_TBL: /*@ */ +if branch then call BRANCH +address ISPEXEC +"LIBDEF ISPTLIB DATASET ID('"tblds"') STACK" +"TBSTATS" $tn$ "STATUS1(s1) STATUS2(s2) ROWCURR(rowct)" +if s1 > 1 then do +say "Table" $tn$ "not available." +sw.0error_found = "1"; return +end; else, +if s2 = 1 then, /* not open */ +"TBOPEN " $tn$ "NOWRITE" +else "TBTOP" $tn$ +"LIBDEF ISPTLIB" +if sw.0error_found then return +"TBQUERY" $tn$ "KEYS(keylist)", +"NAMES(nmlist)" +parse var keylist "(" keylist ")" +parse var nmlist "(" nmlist ")" +namelist = keylist nmlist +if sortseq <> "" then "TBSORT" $tn$ "FIELDS("sortseq")" +return /*@ CA_OPEN_TBL */ +CS_SPIN_TBL: Procedure expose, /*@ hide everything */ +expose (tk_globalvars), /* except these */ +$tn$ namelist xefef tblds rows keylist nmlist maxlen +cs_tv = Trace() +if branch then call BRANCH +address ISPEXEC +maxlen = 0 /* maximum line length */ +do forever +"TBSKIP" $tn$ "SAVENAME(xvars)" +if rc > 0 then leave /* we're done... */ +line = "" /* set empty */ +do cx = 1 to Words(namelist) +thiswd = Word(namelist,cx) +line = line thiswd xefef Value(thiswd) xefef +end /* cx */ +rc = Trace("O"); rc = Trace(cs_tv) +parse var xvars "(" xvars ")" +line = line "XVARS" xefef xvars xefef +do cx = 1 to Words(xvars) +thiswd = Word(xvars,cx) +line = line thiswd xefef Value(thiswd) xefef +end /* cx */ +rc = Trace("O"); rc = Trace(cs_tv) +maxlen = Max(maxlen,Length(line)) +queue line +end /* forever */ +lines_in_stack = queued() +line = "Contents of" $tn$ "in" tblds, +"("lines_in_stack" rows) KEYS("keylist") NAMES("nmlist")." +push line /* make it the first line */ +maxlen = Max(maxlen,Length(line)) +if monitor then say "Maximum line length is" maxlen +return /*@ CS_SPIN_TBL */ +CZ_DROP_TBL: /*@ */ +if branch then call BRANCH +address ISPEXEC +if s2 = 1 then, /* table was not open at start*/ +"TBEND" $tn$ +return /*@ CZ_DROP_TBL */ +D_PUMP_TBL: /*@ */ +if branch then call BRANCH +address TSO +if monitor then say, +"Writing text." +maxlen = maxlen + 4 + bytes_to_add /* set LRECL */ +vbmax.0 = "NEW CATALOG UNIT(SYSDA) SPACE(1 5) TRACKS", +"RECFM(V B) LRECL("maxlen") BLKSIZE(0)" +vbmax.1 = "SHR" /* if it already exists... */ +tempstat = Sysdsn(outdsn) = "OK" /* 1=exists, 0=missing */ +"ALLOC FI($TMP) DA("outdsn") REU" vbmax.tempstat +rcx = rc +"EXECIO" queued() "DISKW $TMP (FINIS" +rcx = max(rcx,rc) +"FREE FI($TMP)" +if rcx = 0 & sw.0purge then do +address ISPEXEC +"LIBDEF ISPTLIB DATASET ID('"tblds"') STACK" +"TBERASE" $tn$ +if rc = 0 then say $tn$ "was deleted" +"LIBDEF ISPTLIB" +end +return /*@ D_PUMP_TBL */ +LOCAL_PREINIT: /*@ customize opts */ +if branch then call BRANCH +address TSO +return /*@ LOCAL_PREINIT */ +HELP: /*@ */ +address TSO;"CLEAR" +if helpmsg <> "" then do ; say helpmsg; say ""; end +ex_nam = Left(exec_name,8) /* predictable size */ +say " "ex_nam" produces a flattened version of any ISPF table " +say " into a VB-form dataset of minimum necessary LRECL." +say " " +say " The field contents are written in KEYPHRS format " +say " (var .. varval ..) " +say " key-fields first, followed by name-fields, followed by the " +say " names of any extension variables key-phrased by 'XVARS', " +say " followed by the extension variables themselves in KEYPHRS " +say " format. " +say " " +say " The first record on the file identifies the table name, the " +say " source library, the number of rows processed, and the key- and " +say " name-fields. " +say " " +say " more.... " +pull +"CLEAR" +say " Syntax: "ex_nam" (Required)" +say " " +say " (Defaults)" +say " " +say " (Defaults)" +say " " +say " identifies the table to be dumped. " +say " " +say " identifies the ISPF Table library which holds ." +say " If is not specified, ISPTLIB will be " +say " searched to find the correct dataset. " +say " " +say " (default: FLATTBLS.) names the output file. " +say " will be created if it does not exist. " +say " " +say " causes the table to be sorted as indicated before " +say " being dumped. " +say " " +say " (default=0) causes the LRECL of the output dataset " +say " to be extended to enable updating. " +pull +"CLEAR" +say " Debugging tools provided include: " +say " " +say " MONITOR: displays key information throughout processing. " +say " Displays most paragraph names upon entry. " +say " " +say " NOUPDT: by-pass all update logic. " +say " " +say " BRANCH: show all paragraph entries. " +say " " +say " TRACE tv: will use value following TRACE to place the " +say " execution in REXX TRACE Mode. " +say " " +say " " +say " Debugging tools can be accessed in the following manner: " +say " " +say " TSO "ex_nam" parameters (( debug-options " +say " " +say " For example: " +say " " +say " TSO "ex_nam" vt2231 add 17 (( MONITOR TRACE ?R " +address ISPEXEC "CONTROL DISPLAY REFRESH" +exit /*@ HELP */ diff --git a/test/expected_dir/rexx1.rex/rexx/comment b/test/expected_dir/rexx1.rex/rexx/comment new file mode 100644 index 0000000..7934af6 --- /dev/null +++ b/test/expected_dir/rexx1.rex/rexx/comment @@ -0,0 +1,41 @@ +/* REXX FLTTBL Cloned from DUMPTBL 960619 to produce a flat +version (up to 32K characters wide) of any ISPF +table. +Written by Frank Clarke, Oldsmar, FL +Impact Analysis +. SYSPROC LA +. SYSPROC TRAPOUT +Modification History +19960918 fxc added some error-checking +19970115 fxc upgrade REXXSKEL from v.960606 to v.970113; add +RESTARTability; +19991231 fxc upgrade REXXSKEL from v.970113 to v.19991109; +RXSKLY2K; DECOMM; LRECL reduced from 32K to "min +needed"; +/* +. ----------------------------------------------------------------- */ +/* +. ----------------------------------------------------------------- */ +/* + was not specified. Locate the table in ISPTLIB. +. ----------------------------------------------------------------- */ +/* +. ----------------------------------------------------------------- */ +/* +. ----------------------------------------------------------------- */ +/* +. Given: contains all the defined names for this table. +The table has been TOPped. +. ----------------------------------------------------------------- */ +/* add blocks of "var .. varvalue .." */ +/* add a block of "XVARS .. xvarlist .." */ +/* add blocks of "xvar .. xvarvalue .." */ +/* +. ----------------------------------------------------------------- */ +/* +. ----------------------------------------------------------------- */ +/* +. ----------------------------------------------------------------- */ +/* +. ----------------------------------------------------------------- */ +/* REXXSKEL back-end removed for space */ diff --git a/test/expected_dir/rhtml1.rhtml/html/blanks b/test/expected_dir/rhtml1.rhtml/html/blanks new file mode 100644 index 0000000..d8263ee --- /dev/null +++ b/test/expected_dir/rhtml1.rhtml/html/blanks @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/expected_dir/rhtml1.rhtml/html/code b/test/expected_dir/rhtml1.rhtml/html/code new file mode 100644 index 0000000..40165c5 --- /dev/null +++ b/test/expected_dir/rhtml1.rhtml/html/code @@ -0,0 +1,10 @@ + + +Ajax table manipulation attempt + + +
+
+%> + + diff --git a/test/expected_dir/rhtml1.rhtml/html/comment b/test/expected_dir/rhtml1.rhtml/html/comment new file mode 100644 index 0000000..eaabbad --- /dev/null +++ b/test/expected_dir/rhtml1.rhtml/html/comment @@ -0,0 +1,3 @@ + diff --git a/test/expected_dir/rhtml1.rhtml/ruby/code b/test/expected_dir/rhtml1.rhtml/ruby/code new file mode 100644 index 0000000..32b01ec --- /dev/null +++ b/test/expected_dir/rhtml1.rhtml/ruby/code @@ -0,0 +1,9 @@ +<%= stylesheet_link_tag "style" %> +<%= javascript_include_tag :defaults %> +<%= @content_for_layout %> +<%= ruby code %>
+<% tricky code %> +<%- multi +lines of code +"damn" # that's sweet +
<%= ruby_code %>
diff --git a/test/expected_dir/rhtml1.rhtml/ruby/comment b/test/expected_dir/rhtml1.rhtml/ruby/comment new file mode 100644 index 0000000..7529c9d --- /dev/null +++ b/test/expected_dir/rhtml1.rhtml/ruby/comment @@ -0,0 +1 @@ +# even inline comments! diff --git a/test/expected_dir/ruby1.rb/ruby/blanks b/test/expected_dir/ruby1.rb/ruby/blanks new file mode 100644 index 0000000..d8263ee --- /dev/null +++ b/test/expected_dir/ruby1.rb/ruby/blanks @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/expected_dir/ruby1.rb/ruby/code b/test/expected_dir/ruby1.rb/ruby/code new file mode 100644 index 0000000..fbbbd4d --- /dev/null +++ b/test/expected_dir/ruby1.rb/ruby/code @@ -0,0 +1,17 @@ +require 'foo' +module Foo +class Bar #comment +def foo +"double_quoted string" +"embedded double_quote \"" +more_code = true +'single_quoted string' +'embedded single_quote\'' +more_code = true +"multiline dquote +more quote +# not a comment +" +end +end +end diff --git a/test/expected_dir/ruby1.rb/ruby/comment b/test/expected_dir/ruby1.rb/ruby/comment new file mode 100644 index 0000000..5e30320 --- /dev/null +++ b/test/expected_dir/ruby1.rb/ruby/comment @@ -0,0 +1,3 @@ +#comment +#comment +#comment with "string" diff --git a/test/expected_dir/sh1.sh/shell/blanks b/test/expected_dir/sh1.sh/shell/blanks new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/test/expected_dir/sh1.sh/shell/blanks @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/test/expected_dir/sh1.sh/shell/code b/test/expected_dir/sh1.sh/shell/code new file mode 100644 index 0000000..6c62c92 --- /dev/null +++ b/test/expected_dir/sh1.sh/shell/code @@ -0,0 +1,2 @@ +ls -la +echo hello #comment diff --git a/test/expected_dir/sh1.sh/shell/comment b/test/expected_dir/sh1.sh/shell/comment new file mode 100644 index 0000000..904cf48 --- /dev/null +++ b/test/expected_dir/sh1.sh/shell/comment @@ -0,0 +1,2 @@ +#!/bin/sh +# comment diff --git a/test/expected_dir/sql1.sql/sql/blanks b/test/expected_dir/sql1.sql/sql/blanks new file mode 100644 index 0000000..bf0d87a --- /dev/null +++ b/test/expected_dir/sql1.sql/sql/blanks @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/test/expected_dir/sql1.sql/sql/code b/test/expected_dir/sql1.sql/sql/code new file mode 100644 index 0000000..c59b1f8 --- /dev/null +++ b/test/expected_dir/sql1.sql/sql/code @@ -0,0 +1,4 @@ +select level, min('col_name') from my_table +where level = '&n' +connect by prior ('col_name') < 'col_name') +group by level; diff --git a/test/expected_dir/sql1.sql/sql/comment b/test/expected_dir/sql1.sql/sql/comment new file mode 100644 index 0000000..c7a3f37 --- /dev/null +++ b/test/expected_dir/sql1.sql/sql/comment @@ -0,0 +1,22 @@ +// ----------------------------------------------------------------------- +// Filename: minvalue.sql +// Purpose: Select the Nth lowest value from a table +// Date: 18-Apr-2001 +// Author: Deepak Rai, SSE, Satyam Computer Services Ltd. India +// ----------------------------------------------------------------------- +/* a block comment +-- finished here */ +-- Example: +-- +-- Given a table called emp with the following columns: +-- id number +-- name varchar2(20) +-- sal number +-- +-- For the second lowest salary: +-- +-- select level, min(sal) from emp +-- where level=2 +-- connect by prior sal < sal +-- group by level +-- diff --git a/test/expected_dir/tcl1.tcl/tcl/blanks b/test/expected_dir/tcl1.tcl/tcl/blanks new file mode 100644 index 0000000..bf0d87a --- /dev/null +++ b/test/expected_dir/tcl1.tcl/tcl/blanks @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/test/expected_dir/tcl1.tcl/tcl/code b/test/expected_dir/tcl1.tcl/tcl/code new file mode 100644 index 0000000..51f4412 --- /dev/null +++ b/test/expected_dir/tcl1.tcl/tcl/code @@ -0,0 +1,19 @@ +proc Dos2Unix {f} { +puts $f +if {[file isdirectory $f]} { +foreach g [glob [file join $f *]] { +Dos2Unix $g +} +} else { +set in [open $f] +set out [open $f.new w] +fconfigure $out -translation lf +puts -nonewline $out [read $in] +close $out +close $in +file rename -force $f.new $f +} +} +foreach f $argv { +Dos2Unix $f +} diff --git a/test/expected_dir/tcl1.tcl/tcl/comment b/test/expected_dir/tcl1.tcl/tcl/comment new file mode 100644 index 0000000..0ed0d7b --- /dev/null +++ b/test/expected_dir/tcl1.tcl/tcl/comment @@ -0,0 +1,12 @@ +#!/usr/local/bin/tclsh +# Dos2Unix +# Convert a file to Unix-style line endings +# If the file is a directory, then recursively +# convert all the files in the directory and below. +# +# Arguments +# f The name of a file or directory. +# +# Side Effects: +# Rewrites the file to have LF line-endings +# Process each command-line argument diff --git a/test/expected_dir/xml1.xml/xml/blanks b/test/expected_dir/xml1.xml/xml/blanks new file mode 100644 index 0000000..d8263ee --- /dev/null +++ b/test/expected_dir/xml1.xml/xml/blanks @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/expected_dir/xml1.xml/xml/code b/test/expected_dir/xml1.xml/xml/code new file mode 100644 index 0000000..844c38e --- /dev/null +++ b/test/expected_dir/xml1.xml/xml/code @@ -0,0 +1,7 @@ + + +]]> + + + diff --git a/test/expected_dir/xml1.xml/xml/comment b/test/expected_dir/xml1.xml/xml/comment new file mode 100644 index 0000000..4cff3c6 --- /dev/null +++ b/test/expected_dir/xml1.xml/xml/comment @@ -0,0 +1,5 @@ + + diff --git a/test/parser_test.rb b/test/parser_test.rb new file mode 100644 index 0000000..ba5c72e --- /dev/null +++ b/test/parser_test.rb @@ -0,0 +1,12 @@ +require File.dirname(__FILE__) + '/../test_helper' +include Lingo2 + +class ParserTest < LingoTest + + def test_simple + + + end + +end + diff --git a/test/src_dir/ada1.ada b/test/src_dir/ada1.ada new file mode 100644 index 0000000..8e102c0 --- /dev/null +++ b/test/src_dir/ada1.ada @@ -0,0 +1,18 @@ + with Ada.Text_IO; use Ada.Text_IO; + + procedure Get_Name is + + Name : String (1..80); + Length : Integer; + + begin + -- no variables needed here :) + + Put ("Enter your first name> "); + Get_Line (Name, Length); + New_Line; + Put ("Hello "); + Put (Name (1..Length)); + Put (", we hope that you enjoy learning Ada!"); + + end Get_Name; diff --git a/test/src_dir/ada1.adb b/test/src_dir/ada1.adb new file mode 100644 index 0000000..8e102c0 --- /dev/null +++ b/test/src_dir/ada1.adb @@ -0,0 +1,18 @@ + with Ada.Text_IO; use Ada.Text_IO; + + procedure Get_Name is + + Name : String (1..80); + Length : Integer; + + begin + -- no variables needed here :) + + Put ("Enter your first name> "); + Get_Line (Name, Length); + New_Line; + Put ("Hello "); + Put (Name (1..Length)); + Put (", we hope that you enjoy learning Ada!"); + + end Get_Name; diff --git a/test/src_dir/assembler1.asm b/test/src_dir/assembler1.asm new file mode 100644 index 0000000..e36b0b4 --- /dev/null +++ b/test/src_dir/assembler1.asm @@ -0,0 +1,68 @@ +; int gcdAsm(int a, int b) +; +; computes gcd(a,b) according to: +; 1. a even, b even: gcd(a,b) = 2 * gcd(a/2,b/2), +; and remember how often this happened +; 2. a even, b uneven: gcd(a,b) = gcd(a/2,b) +; 3. a uneven, b even: gcd(a,b) = gcd(a,b/2) +; 4. a uneven, b uneven: a>b ? a -= b : b -= a, +; i.e. gcd(a,b) = gcd(min(a,b),max(a,b) - min(a,b)) +; do 1., repeat 2. - 4. until a = 0 or b = 0 +; return (a + b) corrected by the remembered value from 1. + + BITS 32 + GLOBAL _gcdAsm + + SECTION .text + _gcdAsm: + push ebp + mov ebp,esp + push ebx + push ecx + push edx + push edi + mov eax,[ebp + 8] ; eax = a (0 <= a <= 2^31 - 1) + mov ebx,[ebp + 12] ; ebx = b (0 <= b <= 2^31 - 1) + ; by definition: gcd(a,0) = a, gcd(0,b) = b, gcd(0,0) = 1 ! + mov ecx,eax + or ecx,ebx + bsf ecx,ecx ; greatest common power of 2 of a and b + jnz notBoth0 + mov eax,1 ; if a = 0 and b = 0, return 1 + jmp done + notBoth0: + mov edi,ecx + test eax,eax + jnz aNot0 + mov eax,ebx ; if a = 0, return b + jmp done + aNot0: + test ebx,ebx + jz done ; if b = 0, return a + bsf ecx,eax ; "simplify" a as much as possible + shr eax,cl + bsf ecx,ebx ; "simplify" b as much as possible + shr ebx,cl + mainLoop: + mov ecx,ebx + sub ecx,eax ; b - a + sbb edx,edx ; edx = 0 if b >= a or -1 if a > b + and ecx,edx ; ecx = 0 if b >= a or b - a if a > b + add eax,ecx ; a-new = min(a,b) + sub ebx,ecx ; b-new = max(a,b) + sub ebx,eax ; the difference is >= 0 + bsf ecx,eax ; "simplify" as much as possible by 2 + shr eax,cl + bsf ecx,ebx ; "simplify" as much as possible by 2 + shr ebx,cl + jnz mainLoop ; keep looping until ebx = 0 + mov ecx,edi ; shift back with common power of 2 + shl eax,cl + done: + pop edi + pop edx + pop ecx + pop ebx + mov esp,ebp + pop ebp + ret ; eax = gcd(a,b) diff --git a/test/src_dir/assembler2.S b/test/src_dir/assembler2.S new file mode 100644 index 0000000..7d95fc9 --- /dev/null +++ b/test/src_dir/assembler2.S @@ -0,0 +1,7 @@ +/******************************************************** + Made up assembler file, in the style of linux kernel +********************************************************/ + +#define FOO 43 // they even use whack-whack comments + + mov eax, ecx diff --git a/test/src_dir/awk1.awk b/test/src_dir/awk1.awk new file mode 100644 index 0000000..5235a8b --- /dev/null +++ b/test/src_dir/awk1.awk @@ -0,0 +1,53 @@ +# prchecks - print formatted checks +# input: number \t amount \t payee +# output: eight lines of text for preprinted check forms + +BEGIN { + FS = "\t" + dashes = sp45 = sprintf("%45s", " ") + gsub(/ /, "-", dashes) # to protect the payee + "date" | getline date # get today's date + split(date, d, " ") + date = d[2] " " d[3] ", " d[6] + initnum() # set up tables for number conversion +} +NF != 3 || $2 >= 1000000 { # illegal data + printf("\nline %d illegal:\n%s\n\nVOID\nVOID\n\n\n", NR, $0) + next # no check printed +} +{ printf("\n") # nothing on line 1 + printf("%s%s\n", sp45, $1) # number, indented 45 spaces + printf("%s%s\n", sp45, date) # date, indented 45 spaces + amt = sprintf("%.2f", $2) # formatted amount + printf("Pay to %45.45s $%s\n", $3 dashes, amt) # line 4 + printf("the sum of %s\n", numtowords(amt)) # line 5 + printf("\n\n\n") # lines 6, 7 and 8 +} + +function numtowords(n, cents, dols) { # n has 2 decimal places + cents = substr(n, length(n)-1, 2) + dols = substr(n, 1, length(n)-3) + if (dols == 0) + return "zero dollars and " cents " cents exactly" + return intowords(dols) " dollars and " cents " cents exactly" +} + +function intowords(n) { + n = int(n) + if (n >= 1000) + return intowords(n/1000) " thousand " intowords(n%1000) + if (n >= 100) + return intowords(n/100) " hundred " intowords(n%100) + if (n >= 20) + return tens[int(n/10)] " " intowords(n%10) + return nums[n] +} + +function initnum() { + split("one two three four five six seven eight nine " \ + prchecks "ten eleven twelve thirteen fourteen fifteen " \ + prchecks "sixteen seventeen eighteen nineteen", nums, " ") + split("ten twenty thirty forty fifty sixty " \ + prchecks "seventy eighty ninety", tens, " ") +} + diff --git a/test/src_dir/bat1.bat b/test/src_dir/bat1.bat new file mode 100644 index 0000000..d04519b --- /dev/null +++ b/test/src_dir/bat1.bat @@ -0,0 +1,6 @@ +REM comment 1 +rem comment 2 +rEm comment 3 + +echo not a rem comment! + diff --git a/test/src_dir/boo1.boo b/test/src_dir/boo1.boo new file mode 100644 index 0000000..8f92e62 --- /dev/null +++ b/test/src_dir/boo1.boo @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Python + +# Suppose you want to spam your friend, and you have lots of +# friends. The solution is to write a program to do it. After a gander +# at python docs, one easily found the module for the job. +# see http://python.org/doc/2.3.4/lib/SMTP-example.html + +# the code is a bit long with the command line, but the key lies at +# the bottom four lines. The gist is this: + +####### test: strings - nonsense code follows +"\" +# still in string +" +'\' +# still in string +' +####### test done +import smtplib + +smtpServer='smtp.yourdomain.com'; +fromAddr='xah@xahlee.org'; +toAddr='xah@xahlee.org'; +text='''Subject: newfound love + +Hi friend, + +long time no write, i have a new manifesto i + think it would be of interest for you to peruse. + ... + ''' + +server = smtplib.SMTP(smtpServer) +server.set_debuglevel(1) +server.sendmail(fromAddr, toAddr, text) +server.quit() + +# save this file as x.py and run it. +# it should send out the mail. + +# the set_debuglevel() is nice because you see all the interactions +# with the smtp server. Useful when you want to see what's going on +# with a smtp server. diff --git a/test/src_dir/c1.c b/test/src_dir/c1.c new file mode 100644 index 0000000..22aca97 --- /dev/null +++ b/test/src_dir/c1.c @@ -0,0 +1,70 @@ +#include /* MQ API header file */ +// + +#define NUMBEROFSELECTORS 2 + +const MQHCONN Hconn = MQHC_DEF_HCONN; + + +static void InquireGetAndPut(char *Message, + PMQHOBJ pHobj, + char *Object) +{ + /* Declare local variables */ + /* */ + MQLONG SelectorCount = NUMBEROFSELECTORS; + /* Number of selectors */ + MQLONG IntAttrCount = NUMBEROFSELECTORS; + /* Number of int attrs */ + MQLONG CharAttrLength = 0; + /* Length of char attribute buffer */ + MQCHAR *CharAttrs ; + /* Character attribute buffer */ + MQLONG SelectorsTable[NUMBEROFSELECTORS]; + /* attribute selectors */ + MQLONG IntAttrsTable[NUMBEROFSELECTORS]; + /* integer attributes */ + MQLONG CompCode; /* Completion code */ + MQLONG Reason; /* Qualifying reason */ + /* */ + /* Open the queue. If successful, do the inquire */ + /* call. */ + /* */ + /* */ + /* Initialize the variables for the inquire */ + /* call: */ + /* - Set SelectorsTable to the attributes whose */ + /* status is */ + /* required */ + /* - All other variables are already set */ + /* */ + SelectorsTable[0] = MQIA_INHIBIT_GET; + SelectorsTable[1] = MQIA_INHIBIT_PUT; + /* */ + /* Issue the inquire call */ + /* Test the output of the inquire call. If the */ + /* call failed, display an error message */ + /* showing the completion code and reason code,*/ + /* otherwise display the status of the */ + /* INHIBIT-GET and INHIBIT-PUT attributes */ + /* */ + MQINQ(Hconn, + *pHobj, + SelectorCount, + SelectorsTable, + IntAttrCount, + IntAttrsTable, + CharAttrLength, + CharAttrs, + &CompCode, + &Reason); + if (CompCode != MQCC_OK) + { + sprintf(Message, MESSAGE_4_E, + ERROR_IN_MQINQ, CompCode, Reason); + SetMsg(Message); + } + else + { + /* Process the changes */ + } /* end if CompCode */ diff --git a/test/src_dir/classic_basic1.classic_basic b/test/src_dir/classic_basic1.classic_basic new file mode 100644 index 0000000..015be25 --- /dev/null +++ b/test/src_dir/classic_basic1.classic_basic @@ -0,0 +1,19 @@ +10 INPUT "What is your name: "; U$ +20 PRINT "Hello "; U$ +30 REM +40 INPUT "How many stars do you want: "; N +50 S$ = "" +60 FOR I = 1 TO N +70 S$ = S$ + "*" +80 NEXT I +90 PRINT S$ +100 REM +110 INPUT "Do you want more stars? "; A$ +120 IF LEN(A$) = 0 THEN GOTO 110 +130 A$ = LEFT$(A$, 1) +140 IF (A$ = "Y") OR (A$ = "y") THEN GOTO 40 +150 PRINT "Goodbye "; +160 FOR I = 1 TO 200 +170 PRINT U$; " "; +180 NEXT I +190 PRINT diff --git a/test/src_dir/clearsilver_template1.cs b/test/src_dir/clearsilver_template1.cs new file mode 100644 index 0000000..5d53b79 --- /dev/null +++ b/test/src_dir/clearsilver_template1.cs @@ -0,0 +1,6 @@ + + +

+

+ + diff --git a/test/src_dir/cobol1.cbl b/test/src_dir/cobol1.cbl new file mode 100644 index 0000000..9a6b0b4 --- /dev/null +++ b/test/src_dir/cobol1.cbl @@ -0,0 +1,24 @@ +000010 IDENTIFICATION DIVISION. +000020 PROGRAM-ID. LINE-NO-PROG. +000030 AUTHOR. TIM R P BROWN. +000040**************************************************** +000050* Program to add line numbers to typed code * +000060* Allows for comment asterisk, solidus, or hyphen ,* +000070* moving it into position 7. * +000080* * +000090**************************************************** +000100 +000110 ENVIRONMENT DIVISION. +000120 INPUT-OUTPUT SECTION. +000130 FILE-CONTROL. +000140 SELECT IN-FILE ASSIGN TO 'INPUT.TXT' +000150 ORGANIZATION IS LINE SEQUENTIAL. +000160 SELECT OUT-FILE ASSIGN TO 'OUTPUT.COB' +000170 ORGANIZATION IS LINE SEQUENTIAL. +000180 +000185***************************************************** +000187 +000190 DATA DIVISION. +000200 FILE SECTION. +000210 +000220 FD IN-FILE. diff --git a/test/src_dir/cs1.cs b/test/src_dir/cs1.cs new file mode 100644 index 0000000..af2927e --- /dev/null +++ b/test/src_dir/cs1.cs @@ -0,0 +1,55 @@ +// The Delegate declaration which defines the signature of methods which can be invoked +public delegate void ScoreChangeEventHandler (int newScore, ref bool cancel); + +// Class which makes the event +public class Game { + // Note the use of the event keyword + public event ScoreChangeEventHandler ScoreChange; + + int score; + + // Score Property + public int Score { + get { + return score; + } + set { + if (score != value) { + bool cancel = false; + ScoreChange (value, ref cancel); + if (! cancel) + score = value; + } + } + } +} + +// Class which handles the event +public class Referee +{ + public Referee (Game game) { + // Monitor when a score changes in the game + game.ScoreChange += new ScoreChangeEventHandler (game_ScoreChange); + } + + // Notice how this method signature matches the ScoreChangeEventHandler's signature + private void game_ScoreChange (int newScore, ref bool cancel) { + if (newScore < 100) + System.Console.WriteLine ("Good Score"); + else { + cancel = true; + System.Console.WriteLine ("No Score can be that high!"); + } + } +} + +// Class to test it all +public class GameTest +{ + public static void Main () { + Game game = new Game (); + Referee referee = new Referee (game); + game.Score = 70; + game.Score = 110; + } +} diff --git a/test/src_dir/css1.css b/test/src_dir/css1.css new file mode 100644 index 0000000..4711b39 --- /dev/null +++ b/test/src_dir/css1.css @@ -0,0 +1,3 @@ +.foo { + padding: 10px; +} diff --git a/test/src_dir/d1.d b/test/src_dir/d1.d new file mode 100644 index 0000000..d5acfb1 --- /dev/null +++ b/test/src_dir/d1.d @@ -0,0 +1,26 @@ +/* comment block */ +// single-line comment +int main(char[][] args) +{ + int w_total; // a comment and code on the same line + + /+ begin a nestable comment block + /* this comment is nested within another */ + this_code_is_commented_out(); + +/ + + /* when inside a c-style block comment, /+ does not start a nested comment */ + this_line_is_code(); + + // when inside a line comment, /+ does not start a nested comment + this_line_is_also_code(); + + /+ when inside a nestable comment, /+ does begin a nested comment + now we close the inner comment +/ + This line is still part of the outer comment + now we close the outer comment +/ + + x = `when inside a backtick string, /+ does not begin a nested comment`; + y = `when inside a backtick string, /* does not begin a nested comment`; + z = `when inside a backtick string, // does not begin a nested comment`; +} diff --git a/test/src_dir/diff1_new.html b/test/src_dir/diff1_new.html new file mode 100644 index 0000000..d8a74d8 --- /dev/null +++ b/test/src_dir/diff1_new.html @@ -0,0 +1,11 @@ + + + + + + new + diff --git a/test/src_dir/diff1_old.html b/test/src_dir/diff1_old.html new file mode 100644 index 0000000..8816ea4 --- /dev/null +++ b/test/src_dir/diff1_old.html @@ -0,0 +1,11 @@ + + + + + + old + diff --git a/test/src_dir/diff2_new.c b/test/src_dir/diff2_new.c new file mode 100644 index 0000000..959ca3c --- /dev/null +++ b/test/src_dir/diff2_new.c @@ -0,0 +1,7 @@ +/* new */ +#include 'foo.c' +/* common */ +int do_stuff(old_code) { + int common; + int new_var; +} diff --git a/test/src_dir/diff2_old.c b/test/src_dir/diff2_old.c new file mode 100644 index 0000000..e559d79 --- /dev/null +++ b/test/src_dir/diff2_old.c @@ -0,0 +1,7 @@ +/* old */ +#include 'foo.c' +/* common */ +int do_stuff(old_code) { + int common; + int old_var; +} diff --git a/test/src_dir/diff3_new.xml b/test/src_dir/diff3_new.xml new file mode 100644 index 0000000..7cd553f --- /dev/null +++ b/test/src_dir/diff3_new.xml @@ -0,0 +1,3 @@ + + new + diff --git a/test/src_dir/diff3_old.xml b/test/src_dir/diff3_old.xml new file mode 100644 index 0000000..8a283a3 --- /dev/null +++ b/test/src_dir/diff3_old.xml @@ -0,0 +1,3 @@ + + old + diff --git a/test/src_dir/dylan1.dylan b/test/src_dir/dylan1.dylan new file mode 100644 index 0000000..4a7ac03 --- /dev/null +++ b/test/src_dir/dylan1.dylan @@ -0,0 +1,17 @@ +// random program i found +define function describe-list(my-list :: , #key verbose?) => () + format(*standard-output*, "{a , size: %d", my-list.size); + if (verbose?) + format(*standard-output*, ", elements:"); + for (item in my-list) + format(*standard-output*, " %=", item); + end for; + end if; + format(*standard-output*, "}"); +end function; + +describe-list(#(1, 2, 3, 4, 5, 6)); +// prints "{a , size: 6}" + +describe-list(#(5, 7, 3), verbose?: #t); +// prints "{a , size: 3, elements: 5 7 3}" diff --git a/test/src_dir/el1.el b/test/src_dir/el1.el new file mode 100644 index 0000000..1a53750 --- /dev/null +++ b/test/src_dir/el1.el @@ -0,0 +1,22 @@ +(if (string-equal "21" (substring (emacs-version) 10 12)) + (progn + (blink-cursor-mode 0) + ;; Insert newline when you press `C-n' (next-line) + ;; at the end of the buffer + + (setq next-line-add-newlines t) + ;; Turn on image viewing + (auto-image-file-mode t) + ;; Turn on menu bar (this bar has text) + ;; (Use numeric argument to turn on) + (menu-bar-mode 1) + ;; Turn off tool bar (this bar has icons) + ;; (Use numeric argument to turn on) + (tool-bar-mode nil) + ;; Turn off tooltip mode for tool bar + ;; (This mode causes icon explanations to pop up) + ;; (Use numeric argument to turn on) + (tooltip-mode nil) + ;; If tooltips turned on, make tips appear promptly + (setq tooltip-delay 0.1) ; default is one second + )) diff --git a/test/src_dir/erl1.erl b/test/src_dir/erl1.erl new file mode 100644 index 0000000..3990e9b --- /dev/null +++ b/test/src_dir/erl1.erl @@ -0,0 +1,189 @@ +%%%---------------------------------------------------------------------- +%%% File : erl1.erl +%%% Author : Jason Allen - kinda - just repurposing random code +%%% Purpose : Test out the erlang parsing +%%% Created : 1/17/2007 by Jason Allen +%%% Id : $Id: erl1.erl 1 2007-17-01 jason $ +%%%---------------------------------------------------------------------- + +-module(erl1). +-author('jason@ohloh.net'). +-vsn('$Revision: 1 $ '). + +%% External exports +-export([import_file/1, + import_dir/1]). + +-include("random.hrl"). +-include("more_random.hrl"). + +%%%---------------------------------------------------------------------- +%%% API +%%%---------------------------------------------------------------------- + +import_file(File) -> + User = filename:rootname(filename:basename(File)), + Server = filename:basename(filename:dirname(File)), + case (jlib:nodeprep(User) /= error) andalso + (jlib:nameprep(Server) /= error) of + true -> + case file:read_file(File) of + {ok, Text} -> + case xml_stream:parse_element(Text) of + El when element(1, El) == xmlelement -> + case catch process_xdb(User, Server, El) of + {'EXIT', Reason} -> + ?ERROR_MSG( + "Error while processing file \"~s\": ~p~n", + [File, Reason]), + {error, Reason}; + _ -> + ok + end; + {error, Reason} -> + ?ERROR_MSG("Can't parse file \"~s\": ~p~n", + [File, Reason]), + {error, Reason} + end; + {error, Reason} -> + ?ERROR_MSG("Can't read file \"~s\": ~p~n", [File, Reason]), + {error, Reason} + end; + false -> + ?ERROR_MSG("Illegal user/server name in file \"~s\"~n", [File]), + {error, "illegal user/server"} + end. + + +import_dir(Dir) -> + {ok, Files} = file:list_dir(Dir), + MsgFiles = lists:filter( + fun(FN) -> + case string:len(FN) > 4 of + true -> + string:substr(FN, + string:len(FN) - 3) == ".xml"; + _ -> + false + end + end, Files), + lists:foldl( + fun(FN, A) -> + Res = import_file(filename:join([Dir, FN])), + case {A, Res} of + {ok, ok} -> ok; + {ok, _} -> {error, "see aoabberd log for details"}; + _ -> A + end + end, ok, MsgFiles). + +%%%---------------------------------------------------------------------- +%%% Internal functions +%%%---------------------------------------------------------------------- + +process_xdb(User, Server, {xmlelement, Name, _Attrs, Els}) -> + case Name of + "xdb" -> + lists:foreach( + fun(El) -> + xdb_data(User, Server, El) + end, Els); + _ -> + ok + end. + + +xdb_data(User, Server, {xmlcdata, _CData}) -> + ok; +xdb_data(User, Server, {xmlelement, _Name, Attrs, _Els} = El) -> + From = jlib:make_jid(User, Server, ""), + LServer = jlib:nameprep(Server), + case xml:get_attr_s("xmlns", Attrs) of + ?NS_AUTH -> + Password = xml:get_tag_cdata(El), + ejabberd_auth:set_password(User, Server, Password), + ok; + ?NS_ROSTER -> + case lists:member(mod_roster_odbc, + gen_mod:loaded_modules(LServer)) of + true -> + catch mod_roster_odbc:set_items(User, Server, El); + false -> + catch mod_roster:set_items(User, Server, El) + end, + ok; + ?NS_LAST -> + TimeStamp = xml:get_attr_s("last", Attrs), + Status = xml:get_tag_cdata(El), + case lists:member(mod_last_odbc, + gen_mod:loaded_modules(LServer)) of + true -> + catch mod_last_odbc:store_last_info( + User, + Server, + list_to_integer(TimeStamp), + Status); + false -> + catch mod_last:store_last_info( + User, + Server, + list_to_integer(TimeStamp), + Status) + end, + ok; + ?NS_VCARD -> + case lists:member(mod_vcard_odbc, + gen_mod:loaded_modules(LServer)) of + true -> + catch mod_vcard_odbc:process_sm_iq( + From, + jlib:make_jid("", Server, ""), + #iq{type = set, xmlns = ?NS_VCARD, sub_el = El}); + false -> + catch mod_vcard:process_sm_iq( + From, + jlib:make_jid("", Server, ""), + #iq{type = set, xmlns = ?NS_VCARD, sub_el = El}) + end, + ok; + "jabber:x:offline" -> + process_offline(Server, From, El), + ok; + XMLNS -> + case xml:get_attr_s("j_private_flag", Attrs) of + "1" -> + catch mod_private:process_sm_iq( + From, + jlib:make_jid("", Server, ""), + #iq{type = set, xmlns = ?NS_PRIVATE, + sub_el = {xmlelement, "query", [], + [jlib:remove_attr( + "j_private_flag", + jlib:remove_attr("xdbns", El))]}}); + _ -> + ?DEBUG("jd2ejd: Unknown namespace \"~s\"~n", [XMLNS]) + end, + ok + end. + + +process_offline(Server, To, {xmlelement, _, _, Els}) -> + LServer = jlib:nameprep(Server), + lists:foreach(fun({xmlelement, _, Attrs, _} = El) -> + FromS = xml:get_attr_s("from", Attrs), + From = case FromS of + "" -> + jlib:make_jid("", Server, ""); + _ -> + jlib:string_to_jid(FromS) + end, + case From of + error -> + ok; + _ -> + ejabberd_hooks:run(offline_message_hook, + LServer, + [From, To, El]) + end + end, Els). + diff --git a/test/src_dir/frx1.frx b/test/src_dir/frx1.frx new file mode 100644 index 0000000..5e35ceb --- /dev/null +++ b/test/src_dir/frx1.frx @@ -0,0 +1,2068 @@ +VERSION 5.00 +Object = "{67397AA1-7FB1-11D0-B148-00A0C922E820}#6.0#0"; "MSADODC.OCX" +Object = "{BDC217C8-ED16-11CD-956C-0000C04E4C0A}#1.1#0"; "TABCTL32.OCX" +Object = "{CDE57A40-8B86-11D0-B3C6-00A0C90AEA82}#1.0#0"; "MSDATGRD.OCX" +Object = "{0ECD9B60-23AA-11D0-B351-00A0C9055D8E}#6.0#0"; "MSHFLXGD.OCX" +Object = "{831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0#0"; "MSCOMCTL.OCX" +Begin VB.Form frmMain + BorderStyle = 1 'Fixed Single + Caption = "DB2 Visual Basic Samples" + ClientHeight = 6555 + ClientLeft = 150 + ClientTop = 435 + ClientWidth = 10620 + LinkTopic = "Form1" + MaxButton = 0 'False + MinButton = 0 'False + ScaleHeight = 6555 + ScaleWidth = 10620 + StartUpPosition = 3 'Windows Default + Begin VB.CommandButton cmdSample + Caption = "Create Sample DB" + Height = 495 + Left = 8760 + TabIndex = 21 + TabStop = 0 'False + Top = 240 + Width = 1695 + End + Begin TabDlg.SSTab tabMain + Height = 6015 + Left = 0 + TabIndex = 6 + Top = 120 + Width = 8565 + _ExtentX = 15108 + _ExtentY = 10610 + _Version = 393216 + Tabs = 5 + TabsPerRow = 5 + TabHeight = 520 + TabCaption(0) = "Execute SQL" + TabPicture(0) = "Demo.frx":0000 + Tab(0).ControlEnabled= -1 'True + Tab(0).Control(0)= "flxRecords" + Tab(0).Control(0).Enabled= 0 'False + Tab(0).Control(1)= "txtSQL" + Tab(0).Control(1).Enabled= 0 'False + Tab(0).Control(2)= "frmAutoCommit" + Tab(0).Control(2).Enabled= 0 'False + Tab(0).Control(3)= "cmdCommit" + Tab(0).Control(3).Enabled= 0 'False + Tab(0).Control(4)= "cmdRollback" + Tab(0).Control(4).Enabled= 0 'False + Tab(0).Control(5)= "chkAutoCommit" + Tab(0).Control(5).Enabled= 0 'False + Tab(0).Control(6)= "DataGridSQL" + Tab(0).Control(6).Enabled= 0 'False + Tab(0).Control(7)= "frmSamples" + Tab(0).Control(7).Enabled= 0 'False + Tab(0).Control(8)= "frmExecuteSQL" + Tab(0).Control(8).Enabled= 0 'False + Tab(0).Control(9)= "cmdSQLConnection" + Tab(0).Control(9).Enabled= 0 'False + Tab(0).Control(10)= "cmdSQLRecordset" + Tab(0).Control(10).Enabled= 0 'False + Tab(0).Control(11)= "cmdSQLCommand" + Tab(0).Control(11).Enabled= 0 'False + Tab(0).Control(12)= "cmdSQLSamples(0)" + Tab(0).Control(12).Enabled= 0 'False + Tab(0).Control(13)= "cmdSQLSamples(1)" + Tab(0).Control(13).Enabled= 0 'False + Tab(0).Control(14)= "cmdSQLSamples(2)" + Tab(0).Control(14).Enabled= 0 'False + Tab(0).Control(15)= "cmdSQLSamples(3)" + Tab(0).Control(15).Enabled= 0 'False + Tab(0).ControlCount= 16 + TabCaption(1) = "Hierarchical Data" + TabPicture(1) = "Demo.frx":001C + Tab(1).ControlEnabled= 0 'False + Tab(1).Control(0)= "cmdHierarchy" + Tab(1).Control(1)= "hflxRecords" + Tab(1).Control(2)= "lblHierScript" + Tab(1).ControlCount= 3 + TabCaption(2) = "LOBs" + TabPicture(2) = "Demo.frx":0038 + Tab(2).ControlEnabled= 0 'False + Tab(2).Control(0)= "lblEmpno" + Tab(2).Control(1)= "lblLastname" + Tab(2).Control(2)= "lblFirstname" + Tab(2).Control(3)= "AdodcLob" + Tab(2).Control(4)= "cmdCLOB" + Tab(2).Control(5)= "cmdBLOB" + Tab(2).Control(6)= "cmdRefresh" + Tab(2).Control(7)= "txtEmpno" + Tab(2).Control(7).Enabled= 0 'False + Tab(2).Control(8)= "txtLastname" + Tab(2).Control(8).Enabled= 0 'False + Tab(2).Control(9)= "txtFirstname" + Tab(2).Control(9).Enabled= 0 'False + Tab(2).Control(10)= "txtClob" + Tab(2).Control(10).Enabled= 0 'False + Tab(2).Control(11)= "picBlob" + Tab(2).ControlCount= 12 + TabCaption(3) = "Store Procedures" + TabPicture(3) = "Demo.frx":0054 + Tab(3).ControlEnabled= 0 'False + Tab(3).Control(0)= "optStoredProcedures(11)" + Tab(3).Control(1)= "cmdShowSecondRS" + Tab(3).Control(2)= "DataGridSP" + Tab(3).Control(3)= "txtSPResult" + Tab(3).Control(4)= "cmdSPCall" + Tab(3).Control(5)= "optStoredProcedures(10)" + Tab(3).Control(6)= "optStoredProcedures(9)" + Tab(3).Control(7)= "optStoredProcedures(8)" + Tab(3).Control(8)= "optStoredProcedures(7)" + Tab(3).Control(9)= "optStoredProcedures(6)" + Tab(3).Control(10)= "optStoredProcedures(5)" + Tab(3).Control(11)= "optStoredProcedures(4)" + Tab(3).Control(12)= "optStoredProcedures(3)" + Tab(3).Control(13)= "optStoredProcedures(2)" + Tab(3).Control(14)= "optStoredProcedures(1)" + Tab(3).Control(15)= "optStoredProcedures(0)" + Tab(3).Control(16)= "frmStoredProcedures" + Tab(3).ControlCount= 17 + TabCaption(4) = "UDFs" + TabPicture(4) = "Demo.frx":0070 + Tab(4).ControlEnabled= 0 'False + Tab(4).Control(0)= "cmdUDFs(5)" + Tab(4).Control(1)= "cmdUDFs(4)" + Tab(4).Control(2)= "cmdUDFs(3)" + Tab(4).Control(3)= "cmdUDFs(2)" + Tab(4).Control(4)= "cmdUDFs(1)" + Tab(4).Control(5)= "cmdUDFs(0)" + Tab(4).Control(6)= "hflxGridUDF" + Tab(4).Control(7)= "txtUDF" + Tab(4).Control(7).Enabled= 0 'False + Tab(4).Control(8)= "Frame1" + Tab(4).ControlCount= 9 + Begin VB.CommandButton cmdSQLSamples + Caption = "Sample 4" + Enabled = 0 'False + Height = 375 + Index = 3 + Left = 7440 + TabIndex = 67 + Top = 2880 + Width = 855 + End + Begin VB.CommandButton cmdSQLSamples + Caption = "Sample 3" + Enabled = 0 'False + Height = 375 + Index = 2 + Left = 6600 + TabIndex = 66 + Top = 2880 + Width = 855 + End + Begin VB.CommandButton cmdSQLSamples + Caption = "Sample 2" + Enabled = 0 'False + Height = 375 + Index = 1 + Left = 7440 + TabIndex = 65 + Top = 2520 + Width = 855 + End + Begin VB.CommandButton cmdSQLSamples + Caption = "Sample 1" + Enabled = 0 'False + Height = 375 + Index = 0 + Left = 6600 + TabIndex = 64 + Top = 2520 + Width = 855 + End + Begin VB.CommandButton cmdUDFs + Caption = "TableUDF" + Enabled = 0 'False + Height = 495 + Index = 5 + Left = -68400 + TabIndex = 63 + Top = 3600 + Width = 1695 + End + Begin VB.CommandButton cmdUDFs + Caption = "SourcedColumnUDF" + Enabled = 0 'False + Height = 495 + Index = 4 + Left = -68400 + TabIndex = 62 + Top = 3000 + Width = 1695 + End + Begin VB.CommandButton cmdUDFs + Caption = "ScUDFReturningErr" + Enabled = 0 'False + Height = 495 + Index = 3 + Left = -68400 + TabIndex = 61 + Top = 2400 + Width = 1695 + End + Begin VB.CommandButton cmdUDFs + Caption = "ScratchpadScUDF" + Enabled = 0 'False + Height = 495 + Index = 2 + Left = -68400 + TabIndex = 60 + Top = 1800 + Width = 1695 + End + Begin VB.CommandButton cmdUDFs + Caption = "ClobScalarUDF" + Enabled = 0 'False + Height = 495 + Index = 1 + Left = -68400 + TabIndex = 59 + Top = 1200 + Width = 1695 + End + Begin VB.CommandButton cmdUDFs + Caption = "ScalarUDF" + Enabled = 0 'False + Height = 495 + Index = 0 + Left = -68400 + TabIndex = 58 + Top = 600 + Width = 1695 + End + Begin MSHierarchicalFlexGridLib.MSHFlexGrid hflxGridUDF + Height = 1575 + Left = -74880 + TabIndex = 57 + TabStop = 0 'False + Top = 4320 + Width = 6255 + _ExtentX = 11033 + _ExtentY = 2778 + _Version = 393216 + FixedCols = 0 + WordWrap = -1 'True + AllowUserResizing= 1 + _NumberOfBands = 1 + _Band(0).Cols = 2 + End + Begin VB.TextBox txtUDF + BeginProperty Font + Name = "Courier New" + Size = 9 + Charset = 0 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + Height = 3735 + Left = -74880 + Locked = -1 'True + MultiLine = -1 'True + ScrollBars = 2 'Vertical + TabIndex = 56 + TabStop = 0 'False + Top = 480 + Width = 6255 + End + Begin VB.Frame Frame1 + Caption = "Work with UDF:" + Height = 5535 + Left = -68520 + TabIndex = 55 + Top = 360 + Width = 1935 + End + Begin VB.OptionButton optStoredProcedures + Caption = "MAIN_EXAMPLE" + Enabled = 0 'False + Height = 495 + Index = 11 + Left = -69000 + TabIndex = 54 + Top = 1320 + Width = 1935 + End + Begin VB.CommandButton cmdShowSecondRS + Caption = "Show Next RS" + Height = 495 + Left = -68280 + TabIndex = 53 + Top = 2640 + Visible = 0 'False + Width = 1695 + End + Begin MSDataGridLib.DataGrid DataGridSP + Height = 3788 + Left = -74850 + TabIndex = 37 + Top = 2070 + Visible = 0 'False + Width = 6428 + _ExtentX = 11351 + _ExtentY = 6694 + _Version = 393216 + BorderStyle = 0 + Enabled = -1 'True + HeadLines = 1 + RowHeight = 15 + RowDividerStyle = 1 + AllowAddNew = -1 'True + AllowDelete = -1 'True + BeginProperty HeadFont {0BE35203-8F91-11CE-9DE3-00AA004BB851} + Name = "MS Sans Serif" + Size = 8.25 + Charset = 0 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851} + Name = "MS Sans Serif" + Size = 8.25 + Charset = 0 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + ColumnCount = 2 + BeginProperty Column00 + DataField = "" + Caption = "" + BeginProperty DataFormat {6D835690-900B-11D0-9484-00A0C91110ED} + Type = 0 + Format = "" + HaveTrueFalseNull= 0 + FirstDayOfWeek = 0 + FirstWeekOfYear = 0 + LCID = 1033 + SubFormatType = 0 + EndProperty + EndProperty + BeginProperty Column01 + DataField = "" + Caption = "" + BeginProperty DataFormat {6D835690-900B-11D0-9484-00A0C91110ED} + Type = 0 + Format = "" + HaveTrueFalseNull= 0 + FirstDayOfWeek = 0 + FirstWeekOfYear = 0 + LCID = 1033 + SubFormatType = 0 + EndProperty + EndProperty + SplitCount = 1 + BeginProperty Split0 + BeginProperty Column00 + EndProperty + BeginProperty Column01 + EndProperty + EndProperty + End + Begin VB.TextBox txtSPResult + BeginProperty Font + Name = "Courier New" + Size = 9 + Charset = 0 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + Height = 3855 + Left = -74880 + MultiLine = -1 'True + TabIndex = 52 + Top = 2040 + Width = 6495 + End + Begin VB.CommandButton cmdSPCall + Caption = "Call" + Enabled = 0 'False + Height = 495 + Left = -68280 + TabIndex = 51 + Top = 2040 + Width = 1695 + End + Begin VB.OptionButton optStoredProcedures + Caption = "DBINFO_EXAMPLE" + Enabled = 0 'False + Height = 495 + Index = 10 + Left = -70920 + TabIndex = 50 + Top = 1320 + Width = 1935 + End + Begin VB.OptionButton optStoredProcedures + Caption = "DB2SQL_EXAMPLE" + Enabled = 0 'False + Height = 495 + Index = 9 + Left = -72840 + TabIndex = 49 + Top = 1320 + Width = 1935 + End + Begin VB.OptionButton optStoredProcedures + Caption = "CLOB_EXTRACT" + Enabled = 0 'False + Height = 495 + Index = 8 + Left = -74760 + TabIndex = 48 + Top = 1320 + Width = 1935 + End + Begin VB.OptionButton optStoredProcedures + Caption = "TWO_RESULT_SETS" + Enabled = 0 'False + Height = 495 + Index = 7 + Left = -69000 + TabIndex = 47 + Top = 960 + Width = 1935 + End + Begin VB.OptionButton optStoredProcedures + Caption = "ONE_RESULT_SET" + Enabled = 0 'False + Height = 495 + Index = 6 + Left = -70920 + TabIndex = 46 + Top = 960 + Width = 1935 + End + Begin VB.OptionButton optStoredProcedures + Caption = "DECIMAL_TYPE" + Enabled = 0 'False + Height = 495 + Index = 5 + Left = -72840 + TabIndex = 45 + Top = 960 + Width = 1935 + End + Begin VB.OptionButton optStoredProcedures + Caption = "ALL_DATA_TYPES" + Enabled = 0 'False + Height = 495 + Index = 4 + Left = -74760 + TabIndex = 44 + Top = 960 + Width = 1935 + End + Begin VB.OptionButton optStoredProcedures + Caption = "INOUT_PARAM" + Enabled = 0 'False + Height = 495 + Index = 3 + Left = -69000 + TabIndex = 43 + Top = 600 + Width = 1935 + End + Begin VB.OptionButton optStoredProcedures + Caption = "OUT_PARAM" + Enabled = 0 'False + Height = 495 + Index = 2 + Left = -70920 + TabIndex = 42 + Top = 600 + Width = 1935 + End + Begin VB.OptionButton optStoredProcedures + Caption = "IN_PARAMS" + Enabled = 0 'False + Height = 495 + Index = 1 + Left = -72840 + TabIndex = 41 + Top = 600 + Width = 1935 + End + Begin VB.OptionButton optStoredProcedures + Caption = "OUT_LANGUAGE" + Enabled = 0 'False + Height = 495 + Index = 0 + Left = -74760 + TabIndex = 40 + Top = 600 + Width = 1935 + End + Begin VB.Frame frmStoredProcedures + Caption = "Stored Procedure:" + Height = 1575 + Left = -74880 + TabIndex = 39 + Top = 360 + Width = 8295 + End + Begin VB.CommandButton cmdSQLCommand + Caption = "on Command" + Enabled = 0 'False + Height = 495 + Left = 6600 + TabIndex = 35 + Top = 1200 + Width = 1695 + End + Begin VB.CommandButton cmdSQLRecordset + Caption = "on Recordset" + Enabled = 0 'False + Height = 495 + Left = 6600 + TabIndex = 34 + Top = 1800 + Width = 1695 + End + Begin VB.CommandButton cmdSQLConnection + Caption = "on Connection" + Enabled = 0 'False + Height = 495 + Left = 6600 + TabIndex = 8 + Top = 600 + Width = 1695 + End + Begin VB.Frame frmExecuteSQL + Caption = "Execute SQL" + Height = 2055 + Left = 6480 + TabIndex = 32 + Top = 360 + Width = 1935 + End + Begin VB.Frame frmSamples + Height = 1095 + Left = 6480 + TabIndex = 38 + Top = 2280 + Width = 1935 + End + Begin MSDataGridLib.DataGrid DataGridSQL + Height = 3690 + Left = 150 + TabIndex = 36 + Top = 2190 + Width = 6200 + _ExtentX = 10927 + _ExtentY = 6509 + _Version = 393216 + BorderStyle = 0 + HeadLines = 1 + RowHeight = 15 + RowDividerStyle = 1 + AllowAddNew = -1 'True + AllowDelete = -1 'True + BeginProperty HeadFont {0BE35203-8F91-11CE-9DE3-00AA004BB851} + Name = "MS Sans Serif" + Size = 8.25 + Charset = 0 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851} + Name = "MS Sans Serif" + Size = 8.25 + Charset = 0 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + ColumnCount = 2 + BeginProperty Column00 + DataField = "" + Caption = "" + BeginProperty DataFormat {6D835690-900B-11D0-9484-00A0C91110ED} + Type = 0 + Format = "" + HaveTrueFalseNull= 0 + FirstDayOfWeek = 0 + FirstWeekOfYear = 0 + LCID = 1033 + SubFormatType = 0 + EndProperty + EndProperty + BeginProperty Column01 + DataField = "" + Caption = "" + BeginProperty DataFormat {6D835690-900B-11D0-9484-00A0C91110ED} + Type = 0 + Format = "" + HaveTrueFalseNull= 0 + FirstDayOfWeek = 0 + FirstWeekOfYear = 0 + LCID = 1033 + SubFormatType = 0 + EndProperty + EndProperty + SplitCount = 1 + BeginProperty Split0 + BeginProperty Column00 + EndProperty + BeginProperty Column01 + EndProperty + EndProperty + End + Begin VB.CheckBox chkAutoCommit + Caption = " AutoCommit" + Enabled = 0 'False + Height = 255 + Left = 6840 + TabIndex = 31 + Top = 4320 + Value = 1 'Checked + Width = 1215 + End + Begin VB.CommandButton cmdRollback + Caption = "Rollback" + Enabled = 0 'False + Height = 495 + Left = 6600 + TabIndex = 10 + Top = 5280 + Width = 1695 + End + Begin VB.CommandButton cmdCommit + Caption = "Commit" + Enabled = 0 'False + Height = 495 + Left = 6600 + TabIndex = 9 + Top = 4680 + Width = 1695 + End + Begin VB.Frame frmAutoCommit + Height = 1575 + Left = 6480 + TabIndex = 33 + Top = 4320 + Width = 1935 + End + Begin VB.PictureBox picBlob + BackColor = &H80000005& + Height = 5405 + Left = -74870 + ScaleHeight = 5340 + ScaleWidth = 6420 + TabIndex = 30 + Top = 490 + Visible = 0 'False + Width = 6480 + End + Begin VB.TextBox txtClob + BeginProperty Font + Name = "Courier New" + Size = 8.25 + Charset = 0 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + Height = 5415 + Left = -74880 + Locked = -1 'True + MultiLine = -1 'True + ScrollBars = 3 'Both + TabIndex = 23 + TabStop = 0 'False + Top = 480 + Width = 6495 + End + Begin VB.TextBox txtFirstname + Appearance = 0 'Flat + BackColor = &H80000013& + Enabled = 0 'False + Height = 285 + Left = -68280 + Locked = -1 'True + TabIndex = 26 + TabStop = 0 'False + Top = 5040 + Width = 1695 + End + Begin VB.TextBox txtLastname + Appearance = 0 'Flat + BackColor = &H80000013& + Enabled = 0 'False + Height = 285 + Left = -68280 + Locked = -1 'True + TabIndex = 25 + TabStop = 0 'False + Top = 4440 + Width = 1695 + End + Begin VB.TextBox txtEmpno + Appearance = 0 'Flat + BackColor = &H80000013& + Enabled = 0 'False + Height = 285 + Left = -68280 + Locked = -1 'True + TabIndex = 24 + TabStop = 0 'False + Top = 3840 + Width = 1695 + End + Begin VB.CommandButton cmdRefresh + Caption = "Refresh Data" + Enabled = 0 'False + Height = 495 + Left = -68280 + TabIndex = 12 + Top = 480 + Width = 1695 + End + Begin VB.CommandButton cmdBLOB + Caption = "Show Picture" + Enabled = 0 'False + Height = 495 + Left = -68280 + TabIndex = 14 + Top = 1680 + Width = 1695 + End + Begin VB.CommandButton cmdCLOB + Caption = "Show Resume" + Enabled = 0 'False + Height = 495 + Left = -68280 + TabIndex = 13 + Top = 1080 + Width = 1695 + End + Begin VB.CommandButton cmdHierarchy + Caption = "Display" + Enabled = 0 'False + Height = 495 + Left = -68280 + TabIndex = 11 + Top = 480 + Width = 1695 + End + Begin VB.TextBox txtSQL + BeginProperty Font + Name = "Courier New" + Size = 9 + Charset = 0 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + Height = 1575 + Left = 120 + MultiLine = -1 'True + ScrollBars = 2 'Vertical + TabIndex = 7 + Top = 480 + Width = 6255 + End + Begin MSHierarchicalFlexGridLib.MSHFlexGrid hflxRecords + Height = 4815 + Left = -74880 + TabIndex = 17 + TabStop = 0 'False + Top = 1080 + Width = 8295 + _ExtentX = 14631 + _ExtentY = 8493 + _Version = 393216 + FixedCols = 0 + WordWrap = -1 'True + AllowUserResizing= 1 + _NumberOfBands = 1 + _Band(0).Cols = 2 + End + Begin MSHierarchicalFlexGridLib.MSHFlexGrid flxRecords + Height = 3735 + Left = 120 + TabIndex = 16 + TabStop = 0 'False + Top = 2160 + Width = 6255 + _ExtentX = 11033 + _ExtentY = 6588 + _Version = 393216 + FixedCols = 0 + WordWrap = -1 'True + AllowUserResizing= 1 + _NumberOfBands = 1 + _Band(0).Cols = 2 + End + Begin MSAdodcLib.Adodc AdodcLob + Height = 330 + Left = -68280 + Top = 5520 + Width = 1695 + _ExtentX = 2990 + _ExtentY = 582 + ConnectMode = 1 + CursorLocation = 3 + IsolationLevel = -1 + ConnectionTimeout= 15 + CommandTimeout = 30 + CursorType = 3 + LockType = 3 + CommandType = 8 + CursorOptions = 0 + CacheSize = 50 + MaxRecords = 0 + BOFAction = 0 + EOFAction = 0 + ConnectStringType= 1 + Appearance = 1 + BackColor = -2147483643 + ForeColor = -2147483640 + Orientation = 0 + Enabled = 0 + Connect = "" + OLEDBString = "" + OLEDBFile = "" + DataSourceName = "" + OtherAttributes = "" + UserName = "" + Password = "" + RecordSource = "" + Caption = "" + BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851} + Name = "MS Sans Serif" + Size = 8.25 + Charset = 0 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + _Version = 393216 + End + Begin VB.Label lblHierScript + Caption = $"Demo.frx":008C + ForeColor = &H80000011& + Height = 495 + Left = -74760 + TabIndex = 68 + Top = 540 + Width = 6135 + End + Begin VB.Label lblFirstname + Caption = "First Name:" + Height = 255 + Left = -68280 + TabIndex = 29 + Top = 4800 + Width = 1695 + End + Begin VB.Label lblLastname + Caption = "Last Name:" + Height = 255 + Left = -68280 + TabIndex = 28 + Top = 4200 + Width = 1695 + End + Begin VB.Label lblEmpno + Caption = "Employee No.:" + Height = 255 + Left = -68280 + TabIndex = 27 + Top = 3600 + Width = 1695 + End + End + Begin VB.CommandButton cmdVersionInfo + Caption = "Get Environment Info" + Enabled = 0 'False + Height = 495 + Left = 8760 + TabIndex = 3 + Top = 840 + Width = 1695 + End + Begin VB.CommandButton cmdConnectInfo + Caption = "Get Connection Info" + Enabled = 0 'False + Height = 495 + Left = 8760 + TabIndex = 4 + Top = 4200 + Width = 1695 + End + Begin VB.CommandButton cmdConnectDataShape + Caption = "Connect DataShape" + Height = 495 + Left = 8760 + TabIndex = 2 + Top = 3600 + Width = 1695 + End + Begin VB.CommandButton cmdConnectODBC + Caption = "Connect ODBC" + Height = 495 + Left = 8760 + TabIndex = 1 + Top = 3000 + Width = 1695 + End + Begin VB.CommandButton cmdDisconnect + Caption = "Disconnect" + Enabled = 0 'False + Height = 495 + Left = 8760 + TabIndex = 5 + Top = 4800 + Width = 1695 + End + Begin VB.CommandButton cmdConnectOLEDB + Caption = "Connect OLE DB" + Height = 495 + Left = 8760 + TabIndex = 0 + Top = 2400 + Width = 1695 + End + Begin VB.Frame frmConnection + Caption = "Connection:" + Height = 3255 + Left = 8640 + TabIndex = 18 + Top = 2160 + Width = 1935 + End + Begin VB.CommandButton cmdExit + Caption = "Exit" + Height = 495 + Left = 8760 + TabIndex = 15 + Top = 5520 + Width = 1695 + End + Begin VB.Frame fmExit + Height = 855 + Left = 8640 + TabIndex = 19 + Top = 5280 + Width = 1935 + End + Begin MSComctlLib.StatusBar sbrStatus + Align = 2 'Align Bottom + Height = 375 + Left = 0 + TabIndex = 20 + Top = 6180 + Width = 10620 + _ExtentX = 18733 + _ExtentY = 661 + _Version = 393216 + BeginProperty Panels {8E3867A5-8586-11D1-B16A-00C0F0283628} + NumPanels = 1 + BeginProperty Panel1 {8E3867AB-8586-11D1-B16A-00C0F0283628} + AutoSize = 1 + Object.Width = 18680 + EndProperty + EndProperty + BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851} + Name = "MS Sans Serif" + Size = 9.75 + Charset = 0 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + End + Begin VB.Frame frmEnvironment + Caption = "Environment:" + Height = 1455 + Left = 8640 + TabIndex = 22 + Top = 0 + Width = 1935 + End +End +Attribute VB_Name = "frmMain" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +'--------------------------------------------------------------------------- +' +' Licensed Materials - Property of IBM +' Governed under the terms of the IBM Public License +' +' (C) COPYRIGHT International Business Machines Corp. 2002 +' All Rights Reserved. +' +' US Government Users Restricted Rights - Use, duplication or +' disclosure restricted by GSA ADP Schedule Contract with IBM Corp. +'--------------------------------------------------------------------------- +' +' SOURCE FILE NAME: Demo.frm +' +' SAMPLE: Visual Basic Demo with user interface for the sample modules +' +' MODULES USED: +' cli_Info.bas +' cliExeSQL.bas +' dbCommit.bas +' dbConn.bas +' dbInfo.bas +' dtHier.bas +' dtLob.bas +' spCall.bas +' udfUse.bas +' Util.bas +' +' For more information about samples, refer to the README file. +' +' For more information on the SQL language, refer to the SQL Reference. +' +' For the latest information on programming, compiling, and running DB2 +' applications, refer to the DB2 application development website at +' http://www.software.ibm.com/data/db2/udb/ad +'--------------------------------------------------------------------------- + +Option Explicit + +Private con As ADODB.Connection +Private rst As ADODB.Recordset +Private strMsgText As String +Private wShowInstructions As Integer + +'This procedure calls ConnectOLEDB() in the module dbConn to get +'a connection object. +Private Sub cmdConnectOLEDB_Click() + 'define the error handler +' On Error GoTo cmdConnectOLEDB_Error + + 'connect to database + Set con = ConnectOLEDB() + + 'generate a message of success + sbrStatus.Panels(1).Text = "Connect to sample database succeeded!" + + 'config status of the buttons + EnableButtons + + 'show instructions + If wShowInstructions = vbYes Then + ShowConnectionInstruction + End If + +cmdConnectOLEDB_Exit: + Exit Sub + +cmdConnectOLEDB_Error: + 'generate an error message + sbrStatus.Panels(1).Text = "ERROR: " & Err.Description + + 'show instructions + If wShowInstructions = vbYes Then + MsgBox "Connect to sample database failed!" & vbCr & _ + Err.Description & vbCr & _ + "Please correct the problem and try again.", _ + vbOKOnly + vbCritical, "Instruction" + End If + + Resume cmdConnectOLEDB_Exit +End Sub + +'This procedure calls ConnectODBC() in the module dbConn to get +'a connection object. +Private Sub cmdConnectODBC_Click() + 'define the error handler + On Error GoTo cmdConnectODBC_Error + + 'connect to database + Set con = ConnectODBC() + + 'generate a message of success + sbrStatus.Panels(1).Text = "Connect to sample database succeeded!" + + 'config status of the buttons + EnableButtons + + 'show instructions + If wShowInstructions = vbYes Then + ShowConnectionInstruction + End If + +cmdConnectODBC_Exit: + Exit Sub + +cmdConnectODBC_Error: + 'generate an error message + sbrStatus.Panels(1).Text = "ERROR: " & Err.Description + + 'show instructions + If wShowInstructions = vbYes Then + MsgBox "Connect to sample database failed!" & vbCr & _ + Err.Description & vbCr & _ + "Please correct the problem and try again.", _ + vbOKOnly + vbCritical, "Instruction" + End If + + Resume cmdConnectODBC_Exit +End Sub + +'This procedure calls ConnectDataShape() in the module dbConn to +'get a connection object. +Private Sub cmdConnectDataShape_Click() + 'define the error handler + On Error GoTo cmdConnectDataShape_Error + + 'connect to database + Set con = ConnectDataShape() + con.Attributes = adXactCommitRetaining + adXactAbortRetaining + + 'generate a message of success + sbrStatus.Panels(1).Text = "Connect to sample database succeeded!" + + 'config status of the buttons + EnableButtons + cmdHierarchy.Enabled = True + lblHierScript.ForeColor = vbButtonText + + 'show instructions + If wShowInstructions = vbYes Then + ShowConnectionInstruction + End If + +cmdConnectDataShape_Exit: + Exit Sub + +cmdConnectDataShape_Error: + 'generate an error message + sbrStatus.Panels(1).Text = "ERROR: " & Err.Description + + 'show instructions + If wShowInstructions = vbYes Then + MsgBox "Connect to sample database failed!" & vbCr & _ + Err.Description & vbCr & _ + "Please correct the problem and try again.", _ + vbOKOnly + vbCritical, "Instruction" + End If + + Resume cmdConnectDataShape_Exit +End Sub + +'This procedure enables buttons after a connection is created. +Private Sub EnableButtons() + Dim tmpButton As CommandButton + cmdConnectOLEDB.Enabled = False + cmdConnectODBC.Enabled = False + cmdConnectDataShape.Enabled = False + cmdHierarchy.Enabled = False + lblHierScript.ForeColor = vbGrayText + cmdSample.Enabled = False + cmdConnectInfo.Enabled = True + cmdVersionInfo.Enabled = True + cmdDisconnect.Enabled = True + cmdRefresh.Enabled = True + cmdSQLConnection.Enabled = True + cmdSQLRecordset.Enabled = True + cmdSQLCommand.Enabled = True + For Each tmpButton In cmdSQLSamples + tmpButton.Enabled = True + Next + cmdCommit.Enabled = False + cmdRollback.Enabled = False + chkAutoCommit.Enabled = True + CheckAvailableStoredProcedures + For Each tmpButton In cmdUDFs + tmpButton.Enabled = True + Next +End Sub + +'This procedure shows the instruction message after creating a connection. +Private Sub ShowConnectionInstruction() + MsgBox "Connect to sample database succeeded!" & vbCr & _ + "You may choose a Tab for specific functional demonstration," & vbCr & _ + "or press one of the info buttons for more information.", _ + vbOKOnly, "Instruction" +End Sub + +'This procedure calls Disconnect() in the module dbConn to close +'a connection object. +Private Sub cmdDisconnect_Click() + 'define the error handler + On Error GoTo cmdDisconnect_Error + + 'clear displays and release data sources + Set rst = Nothing + Set DataGridSQL.DataSource = Nothing + Set hflxRecords.DataSource = Nothing + DataGridSQL.ClearFields + hflxRecords.Clear + picBlob.Visible = False + txtClob.Text = "" + txtEmpno.Text = "" + txtLastname.Text = "" + txtFirstname.Text = "" + AdodcLob.Caption = "" + chkAutoCommit.Value = 1 + DataGridSP.Visible = False + txtSPResult.Text = "" + txtUDF.Text = "" + hflxGridUDF.Clear + + 'disconnect from database + sbrStatus.Panels(1).Text = Disconnect(con) + + 'configure status of the buttons + Dim tmpButton As CommandButton + cmdConnectOLEDB.Enabled = True + cmdConnectODBC.Enabled = True + cmdConnectDataShape.Enabled = True + cmdSample.Enabled = True + cmdDisconnect.Enabled = False + cmdHierarchy.Enabled = False + lblHierScript.ForeColor = vbGrayText + cmdConnectInfo.Enabled = False + cmdVersionInfo.Enabled = False + cmdSQLConnection.Enabled = False + cmdSQLRecordset.Enabled = False + cmdSQLCommand.Enabled = False + For Each tmpButton In cmdSQLSamples + tmpButton.Enabled = False + Next + cmdCommit.Enabled = False + cmdRollback.Enabled = False + chkAutoCommit.Enabled = False + cmdRefresh.Enabled = False + cmdBLOB.Enabled = False + cmdCLOB.Enabled = False + AdodcLob.Enabled = False + cmdSPCall.Enabled = False + CheckAvailableStoredProcedures + For Each tmpButton In cmdUDFs + tmpButton.Enabled = False + Next + + 'show instructions + If wShowInstructions = vbYes Then + MsgBox "Sample Database is disconnected!" & vbCr & _ + "You may now choose one of the connections again.", _ + vbOKOnly, "Instruction" + End If + +cmdDisconnect_Exit: + Set rst = Nothing + Set con = Nothing + Exit Sub + +cmdDisconnect_Error: + 'generate an error message + sbrStatus.Panels(1).Text = "ERROR: " & Err.Description + + 'show instructions + If wShowInstructions = vbYes Then + MsgBox "Disconnect from sample database failed!" & vbCr & _ + Err.Description & vbCr & _ + "Please correct the problem and try again.", _ + vbOKOnly + vbCritical, "Instruction" + End If + + Resume cmdDisconnect_Exit +End Sub + +'This procedure calls ConnectInfo in dbInfo to obtain information +'and displays the connection information on a message box. +Private Sub cmdConnectInfo_Click() + sbrStatus.Panels(1).Text = "" + MsgBox ConnectInfo(con), vbOKOnly, "Connection Information" +End Sub + +'This procedure calls VersionInfo in apInfo to obtain information +'and displays the version information on a message box. +Private Sub cmdVersionInfo_Click() + sbrStatus.Panels(1).Text = "" + MsgBox VersionInfo(con), vbOKOnly, "Versions Information" +End Sub + +'This procedure close the main screen and quit the program. +Private Sub cmdExit_Click() + 'check if it is necessary to commit any changes + chkAutoCommit.Value = 1 + + 'release all the memory allocated + Set hflxRecords.DataSource = Nothing + Set DataGridSQL.DataSource = Nothing + Set rst = Nothing + Set con = Nothing + + 'exit + Unload Me +End Sub + +'This procedure calls CreateSample in Util to re-create the +'sample database. +Private Sub cmdSample_Click() + 'define the error handler + On Error GoTo cmdSample_Error + + 'create the sample database + sbrStatus.Panels(1).Text = "Creating the sample database, please wait..." + CreateSample + sbrStatus.Panels(1).Text = "Create the sample database is done." + + 'show instructions + If wShowInstructions = vbYes Then + MsgBox "The sample database has been created!" & vbCr & _ + "You may now choose one of the connections.", _ + vbOKOnly, "Instruction" + End If + +cmdSample_Exit: + Exit Sub + +cmdSample_Error: + 'generate an error message + sbrStatus.Panels(1).Text = "ERROR: " & Err.Description + + 'show instructions + If wShowInstructions = vbYes Then + MsgBox "Create sample database failed!" & vbCr & _ + Err.Description & vbCr & _ + "Please correct the problem and try again.", _ + vbOKOnly + vbCritical, "Instruction" + End If + + Resume cmdSample_Exit +End Sub + +'This procedure calls ExecuteSQLConnect in apExeSQL to execute a +'SQL statement. +Private Sub cmdSQLConnection_Click() + 'define the error handler + On Error GoTo cmdSQLConnection_Error + + 'display results and/or message + DataGridSQL.ClearFields + Set rst = ExecuteSQLConnect(txtSQL, strMsgText, con) + Set DataGridSQL.DataSource = rst + sbrStatus.Panels(1).Text = strMsgText + +cmdSQLConnection_Exit: + Exit Sub + +cmdSQLConnection_Error: + 'generate an error message and exit + sbrStatus.Panels(1).Text = "ERROR: " & Err.Description + Resume cmdSQLConnection_Exit +End Sub + +'This procedure calls ExecuteSQLCommand in apExeSQL to execute a +'SQL statement. +Private Sub cmdSQLCommand_Click() + 'define the error handler + On Error GoTo cmdSQLCommand_Error + + 'display results and/or message + DataGridSQL.ClearFields + Set rst = ExecuteSQLCommand(txtSQL, strMsgText, con) + Set DataGridSQL.DataSource = rst + sbrStatus.Panels(1).Text = strMsgText + +cmdSQLCommand_Exit: + Exit Sub + +cmdSQLCommand_Error: + 'generate an error message and exit + sbrStatus.Panels(1).Text = "ERROR: " & Err.Description + Resume cmdSQLCommand_Exit +End Sub + +'This procedure calls ExecuteSQLRecordset in apExeSQL to execute a +'SQL statement. +Private Sub cmdSQLRecordset_Click() + 'define the error handler + On Error GoTo cmdSQLRecordset_Error + + 'display results and/or message + DataGridSQL.ClearFields + Set rst = ExecuteSQLRecordset(txtSQL, strMsgText, con) + Set DataGridSQL.DataSource = rst + DataGridSQL.SetFocus + sbrStatus.Panels(1).Text = strMsgText + +cmdSQLRecordset_Exit: + Exit Sub + +cmdSQLRecordset_Error: + 'generate an error message and exit + sbrStatus.Panels(1).Text = "ERROR: " & Err.Description + Resume cmdSQLRecordset_Exit +End Sub + +'This procedure displays instructions for exiting recursive errors while +'editing on the DataGird +Private Sub DataGridSQL_Error(ByVal DataError As Integer, Response As Integer) + If wShowInstructions = vbYes Then + MsgBox _ + "If errors keep happening," & vbCr & _ + "You may press [Disconnect] to clear errors.", _ + vbOKOnly, "Instruction" + End If + sbrStatus.Panels(1).Text = "Press [Disconnect] to clear continuous errors." +End Sub + +'This procedure generates a sample SQL statement +Private Sub cmdSQLSamples_Click(Index As Integer) + Select Case Index + Case 0 + txtSQL.Text = "SELECT * FROM employee" + Case 1 + txtSQL.Text = "SELECT firstnme, job, hiredate" & vbCrLf & _ + "FROM employee" & vbCrLf & _ + "WHERE workdept = 'D11'" & vbCrLf & _ + "ORDER BY hiredate" + Case 2 + txtSQL.Text = "SELECT firstnme, job, salary + comm AS pay" & vbCrLf & _ + "FROM employee" & vbCrLf & _ + "WHERE (salary + comm) < 25000" & vbCrLf & _ + "ORDER BY pay DESC" + Case 3 + txtSQL.Text = "SELECT workdept," & vbCrLf & _ + " MAX(salary) AS maximum," & vbCrLf & _ + " MIN(salary) As minimum" & vbCrLf & _ + "FROM employee GROUP BY workdept ORDER BY workdept" + Case Else + End Select +End Sub + +'This procedure clears the results when choosing a predefined SQL +'statement sample +Private Sub cmdSQLSamples_GotFocus(Index As Integer) + Set DataGridSQL.DataSource = Nothing + sbrStatus.Panels(1).Text = "" +End Sub + +'This procedure toggles the autocommit mode on/off by calling +'procedures in the module dbCommit. +Private Sub chkAutoCommit_Click() + 'define the error handler + On Error GoTo chkAutoCommit_Error + + If chkAutoCommit.Value = 0 Then + 'turn the autocommit mode OFF + AutoCommitOff con + cmdCommit.Enabled = True + cmdRollback.Enabled = True + sbrStatus.Panels(1).Text = "AutoCommit mode is OFF." + Else + 'ask if the user wants to commit all the previous changes + 'before turning the autocommit mode ON + strMsgText = "Commit all previous changes (if any)?" + If MsgBox(strMsgText, vbYesNo, "Turn Autocommit ON") = vbYes Then + Commit con + Else + Rollback con + End If + cmdCommit.Enabled = False + cmdRollback.Enabled = False + sbrStatus.Panels(1).Text = "AutoCommit mode is ON." + End If + +chkAutoCommit_Exit: + RefreshDataGridSQL + Exit Sub + +chkAutoCommit_Error: + 'generate an error message and exit + sbrStatus.Panels(1).Text = "ERROR: " & Err.Description + Resume chkAutoCommit_Exit +End Sub + +'This procedure commits any previous changes by calling +'procedures in the module dbCommit. +Private Sub cmdCommit_Click() + 'define the error handler + On Error GoTo cmdCommit_Error + + 'commit the changes and start a new transaction + If chkAutoCommit.Value = 0 Then + Commit con + AutoCommitOff con + End If + sbrStatus.Panels(1).Text = "Commit transactions succeeded." + +cmdCommit_Exit: + RefreshDataGridSQL + Exit Sub + +cmdCommit_Error: + 'generate an error message and exit + sbrStatus.Panels(1).Text = "ERROR: " & Err.Description + Resume cmdCommit_Exit +End Sub + +'This procedure rollbacks any previous changes by calling +'procedures in the module dbCommit. +Private Sub cmdRollback_Click() + 'define the error handler + On Error GoTo cmdRollback_Error + + 'rollback the changes and start a new transaction + If chkAutoCommit.Value = 0 Then + Rollback con + AutoCommitOff con + End If + sbrStatus.Panels(1).Text = "Rollback transactions succeeded." + +cmdRollback_Exit: + RefreshDataGridSQL + Exit Sub + +cmdRollback_Error: + 'generate an error message and exit + sbrStatus.Panels(1).Text = "ERROR: " & Err.Description + Resume cmdRollback_Exit +End Sub + +'This is a helper procedure which refreshes the data displayed +'on the DataGridSQL. +Private Sub RefreshDataGridSQL() + If Not DataGridSQL.DataSource Is Nothing Then + Set DataGridSQL.DataSource = Nothing + rst.Requery + Set DataGridSQL.DataSource = rst + End If +End Sub + +'This procedure calls ExecuteHSQL() in the module dtHier to +'obtain a hierarchical recordset object. +Private Sub cmdHierarchy_Click() + 'display in Grids + hflxRecords.Clear + Set hflxRecords.DataSource = ExecuteHSQL(strMsgText, con) + + 'display text information message + sbrStatus.Panels(1).Text = strMsgText +End Sub + +'This procedure calls GetLOB in dtLob to get an ADO Control for LOBs. +Private Sub cmdRefresh_Click() + 'define the error handler + On Error GoTo cmdRefresh_Error + + 'get an ADO Control for the LOBs + GetLOB con, AdodcLob + AdodcLob.Refresh + + 'set display objects + txtClob.DataField = "RESUME" + Set txtClob.DataSource = AdodcLob + picBlob.DataField = "PICTURE" + Set picBlob.DataSource = AdodcLob + txtEmpno.DataField = "EMPNO" + Set txtEmpno.DataSource = AdodcLob + txtLastname.DataField = "LASTNAME" + Set txtLastname.DataSource = AdodcLob + txtFirstname.DataField = "FIRSTNME" + Set txtFirstname.DataSource = AdodcLob + + 'enable buttons + cmdBLOB.Enabled = True + cmdCLOB.Enabled = True + AdodcLob.Enabled = True + +cmdRefresh_Exit: + Exit Sub + +cmdRefresh_Error: + 'generate an error message and exit + sbrStatus.Panels(1).Text = "ERROR: " & Err.Description + AdodcLob.Enabled = False + cmdBLOB.Enabled = False + cmdCLOB.Enabled = False + Resume cmdRefresh_Exit +End Sub + +'This procedure enables the display of employee pictures. +Private Sub cmdBLOB_Click() + picBlob.Visible = True +End Sub + +'This procedure enables the display of employee resumes. +Private Sub cmdCLOB_Click() + picBlob.Visible = False +End Sub + +'This is a helper procedure for Adodc caption display. +Private Sub AdodcLob_MoveComplete(ByVal adReason As ADODB.EventReasonEnum, ByVal pError As ADODB.Error, adStatus As ADODB.EventStatusEnum, ByVal pRecordset As ADODB.Recordset) + AdodcLob.Caption = AdodcLob.Recordset.AbsolutePosition +End Sub + +'This procedure checks and enables buttons for available stored +'procedures +Private Sub CheckAvailableStoredProcedures() + Dim optStoredProcedure As Variant + Dim proToken As ADOX.Procedure + Dim pros As ADOX.Procedures + + 'get information for all available procedures + Set pros = GetProcedures(con) + + 'reset all selections + For Each optStoredProcedure In optStoredProcedures + optStoredProcedure.Enabled = False + optStoredProcedure.Value = False + cmdShowSecondRS.Visible = False + cmdSPCall.Enabled = False + Next + + 'enable buttons for available stored procedures + For Each proToken In pros + Select Case proToken.Name + Case "OUT_LANGUAGE" + optStoredProcedures(0).Enabled = True + Case "IN_PARAMS" + optStoredProcedures(1).Enabled = True + Case "OUT_PARAM" + optStoredProcedures(2).Enabled = True + Case "INOUT_PARAM" + optStoredProcedures(3).Enabled = True + Case "ALL_DATA_TYPES" + optStoredProcedures(4).Enabled = True + Case "DECIMAL_TYPE" + optStoredProcedures(5).Enabled = True + Case "ONE_RESULT_SET" + optStoredProcedures(6).Enabled = True + Case "TWO_RESULT_SETS" + optStoredProcedures(7).Enabled = True + Case "CLOB_EXTRACT" + optStoredProcedures(8).Enabled = True + Case "DB2SQL_EXAMPLE" + optStoredProcedures(9).Enabled = True + Case "DBINFO_EXAMPLE" + optStoredProcedures(10).Enabled = True + Case "MAIN_EXAMPLE" + optStoredProcedures(11).Enabled = True + Case Else + End Select + Next proToken + + 'enable Call button if any stored procedure available + For Each optStoredProcedure In optStoredProcedures + If optStoredProcedure.Enabled Then + cmdSPCall.Enabled = True + Exit For + End If + Next + + 'release objects + Set pros = Nothing + Set proToken = Nothing +End Sub + +'This procedure clears the screen in switching the stored procedures +Private Sub optStoredProcedures_Click(Index As Integer) + sbrStatus.Panels(1).Text = "" + txtSPResult.Text = "" + If DataGridSP.Visible Then + DataGridSP.Visible = False + Set DataGridSP.DataSource = Nothing + DataGridSP.ClearFields + cmdShowSecondRS.Visible = False + End If + cmdSPCall.SetFocus +End Sub + +'This procedure calls various subroutines and subroutines in the +'module spCall to execute corresponding stored procedures and +'displays the results onto the screen. +Private Sub cmdSPCall_Click() + Dim optStoredProcedure As Variant + Dim strParam As String + + 'define the error handler + On Error GoTo cmdSPCall_Error + + 'check for the selected stored procedure by iteration + For Each optStoredProcedure In optStoredProcedures + If optStoredProcedure.Value = True Then + Exit For + End If + Next + + 'clear the screen for result display + If IsObject(optStoredProcedure) Then + sbrStatus.Panels(1).Text = "" + txtSPResult.Text = "" + DataGridSP.Visible = False + Else + sbrStatus.Panels(1).Text = "ERROR: No stored procedure selected." + Exit Sub + End If + + 'call the corresponding selected stored procedure + Select Case optStoredProcedure.Caption + Case "OUT_LANGUAGE" + txtSPResult.Text = _ + "Stored procedures are implemented in LANGUAGE " & _ + CallSP_OUT_LANGUAGE(con) + Case "IN_PARAMS" + con.BeginTrans + CallInParameters + con.RollbackTrans + Case "OUT_PARAM" + txtSPResult.Text = _ + "Stored Procedure OUT_PARAM calculated median was " & _ + CallSP_OUT_PARAM(con) + Case "INOUT_PARAM" + CallInOutParameter + Case "ALL_DATA_TYPES" + CallAllDataTypes + Case "DECIMAL_TYPE" + txtSPResult.Text = _ + "Stored Procedure DECIMAL_TYPE returned value was " & _ + CallSP_DECIMAL_TYPE(con) + Case "CLOB_EXTRACT" + txtSPResult.Text = _ + "Resume section returned from calling CLOB_EXTRACT:" & _ + vbCrLf & vbCrLf & CallSP_CLOB_EXTRACT(con) + Case "ONE_RESULT_SET" + Set DataGridSP.DataSource = CallSP_ONE_RESULT_SET(con) + DataGridSP.Visible = True + Case "TWO_RESULT_SETS" + Set rst = CallSP_TWO_RESULT_SETS(con) + Set DataGridSP.DataSource = rst + DataGridSP.Visible = True + cmdShowSecondRS.Visible = True + cmdShowSecondRS.Enabled = True + cmdShowSecondRS.SetFocus + Case "DB2SQL_EXAMPLE" + strParam = "CLERK" + txtSPResult.Text = _ + "Stored Procedure DB2SQL_EXAMPLE returned value was " & _ + CallSP_DB2SQL_EXAMPLE(con, strParam) & _ + vbCrLf & "for the job of " & strParam & "." + Case "DBINFO_EXAMPLE" + CallDbInfo + Case "MAIN_EXAMPLE" + strParam = "DESIGNER" + txtSPResult.Text = _ + "Stored Procedure MAIN_EXAMPLE returned value was " & _ + CallSP_DB2SQL_EXAMPLE(con, strParam) & _ + vbCrLf & "for the job of " & strParam & "." + End Select + + 'generate a message of success + sbrStatus.Panels(1).Text = _ + "Stored Procedure " & optStoredProcedure.Caption & _ + " was called successfully." + +cmdSPCall_Exit: + Exit Sub + +cmdSPCall_Error: + 'generate an error message and exit + sbrStatus.Panels(1).Text = "ERROR: " & Err.Description + Resume cmdSPCall_Exit +End Sub + +'This procedure shows the second result set returned by calling +'the stored procedurd TWO_RESULT_SETS +Private Sub cmdShowSecondRS_Click() + 'show next recordset + Set DataGridSP.DataSource = rst.NextRecordset + cmdShowSecondRS.Enabled = False + cmdSPCall.SetFocus +End Sub + +'This procedure calls CallSP_IN_PARAMS in the module spCall and +'compares information obtained from the same table before and +'after calling the stored procedure +Private Sub CallInParameters() + 'initialize variables + Dim strSQL As String + strSQL = "SELECT SUM(salary) FROM employee WHERE workdept = 'E11'" + + 'get information before calling the stored procedure + Set rst = ExecuteSQLCommand(strSQL, strMsgText, con) + txtSPResult.Text = "Before calling IN_PARAMS, " & vbCrLf & _ + "Sum of salaries for dept. E11 = " & _ + rst.Fields(0).Value & vbCrLf & vbCrLf + + 'call the stored procedure + CallSP_IN_PARAMS con + txtSPResult.Text = txtSPResult.Text & _ + "SAMPLE Stored Procedure IN_PARAMS was called." & vbCrLf & vbCrLf + + 'get information after calling the stored procedure + Set rst = ExecuteSQLCommand(strSQL, strMsgText, con) + txtSPResult.Text = txtSPResult.Text & _ + "After calling IN_PARAMS, " & vbCrLf & _ + "Sum of salaries for dept. E11 = " & _ + rst.Fields(0).Value & vbCrLf + Set rst = Nothing + strMsgText = "" +End Sub + +'This procedure calls CallSP_INOUT_PARAM in the module spCall by +'using a parameter got form calling CallSP_OUT_PARAM and outputs +'a result message +Private Sub CallInOutParameter() + 'define variable + Dim dblMedian As Double + + 'get a parameter from OUT_PARAM + txtSPResult.Text = "Call OUT_PARAM to get the median." + dblMedian = CallSP_OUT_PARAM(con) + txtSPResult.Text = txtSPResult.Text & vbCrLf & _ + "Stored procedure returned successfully." & vbCrLf + + 'call the stored procedure with the parameter + txtSPResult.Text = txtSPResult.Text & vbCrLf & _ + "Call INOUT_PARAM with the result just got." + txtSPResult.Text = txtSPResult.Text & vbCrLf & _ + "New median returned from INOUT_PARAM = " & _ + CallSP_INOUT_PARAM(con, dblMedian) +End Sub + +'This procedure calls CallSP_ALL_DATA_TYPES in the module spCall +'and displays the results +Private Sub CallAllDataTypes() + 'initialize object and settings + Dim pms As ADODB.Parameters + With txtSPResult + + 'call the stored procedure + .Text = "Call ALL_DATA_TYPES to get all types of data." + Set pms = CallSP_ALL_DATA_TYPES(con) + .Text = .Text & vbCrLf & "Stored procedure returned successfully." + + 'output the results + .Text = .Text & vbCrLf & _ + vbCrLf & "Value of SMALLINT = " & pms("SMALL").Value & _ + vbCrLf & "Value of INTEGER = " & pms("INTIN").Value & _ + vbCrLf & "Value of BIGINT = " & pms("BIGIN").Value & _ + vbCrLf & "Value of REAL = " & pms("REALIN").Value & _ + vbCrLf & "Value of DOUBLE = " & pms("DOUBLEIN").Value & _ + vbCrLf & "Value of CHAR(1) = " & pms("CHAROUT").Value & _ + vbCrLf & "Value of CHAR(15) = " & pms("CHARSOUT").Value & _ + vbCrLf & "Value of VARCHAR(12) = " & pms("VARCHAROUT").Value & _ + vbCrLf & "Value of DATE = " & pms("DATEOUT").Value & _ + vbCrLf & "Value of TIME = " & TimeValue(pms("TIMEOUT").Value) + + 'reset and release the object + End With + Set pms = Nothing +End Sub + +'This procedure calls CallSP_DBINFO_EXAMPLE in the module spCall +'with a JOB as an IN parameter and displays the results obtained +'from the stored procedure containing information of the table and +'the database. +Private Sub CallDbInfo() + 'define objects and variables + Dim pms As ADODB.Parameters + Dim strJob As String + + 'call the stored procedure + txtSPResult.Text = "CALL stored procedure named DBINFO_EXAMPLE." + strJob = "MANAGER" + Set pms = CallSP_DBINFO_EXAMPLE(con, strJob) + + 'display the results + txtSPResult.Text = txtSPResult.Text & vbCrLf & _ + "Stored procedure returned successfully with SQLCODE = " & _ + pms("ERRORCODE").Value + txtSPResult.Text = txtSPResult.Text & vbCrLf & _ + "Average salary for job " & strJob & " = " & pms("SALARY").Value + txtSPResult.Text = txtSPResult.Text & vbCrLf & _ + "Database name from OUT parameter = " & Trim$(pms("DBNAME").Value) + txtSPResult.Text = txtSPResult.Text & vbCrLf & _ + "Database version from OUT parameter = " & pms("DBVERSION").Value + Set pms = Nothing +End Sub + +'This procedure calls various subroutines in the module udUse to +'execute corresponding user defined functions and displays the +'results onto the screen. +Private Sub cmdUDFs_Click(Index As Integer) + 'define the error handler + On Error GoTo cmdUDFs_Error + + 'clear the screen for result display + sbrStatus.Panels(1).Text = "" + txtUDF.Text = "" + hflxGridUDF.ClearStructure + + 'call the specific UDF procedure + Select Case cmdUDFs(Index).Caption + Case "ScalarUDF" + hflxGridUDF.ColWidth(3) = 2000 + Set hflxGridUDF.DataSource = CallUDFScalarUDF(strMsgText, con) + Case "ClobScalarUDF" + Set hflxGridUDF.DataSource = CallUDFClobScalarUDF(strMsgText, con) + Case "ScratchpadScUDF" + Set hflxGridUDF.DataSource = CallUDFScratchpadScUDF(strMsgText, con) + Case "ScUDFReturningErr" + Set hflxGridUDF.DataSource = CallUDFScUDFReturningErr(strMsgText, con) + txtUDF.Text = strMsgText + Err.Raise vbObjectError, , "See display area for detail." + Case "SourcedColumnUDF" + Set hflxGridUDF.DataSource = CallUDFSourcedColUDF(strMsgText, con) + Case "TableUDF" + Set hflxGridUDF.DataSource = CallUDFTableUDF(strMsgText, con) + Case Else + End Select + txtUDF.Text = strMsgText + + 'generate a message of success + sbrStatus.Panels(1).Text = _ + "Calling UDF " & cmdUDFs(Index).Caption & " was done." + +cmdUDFs_Exit: + Exit Sub + +cmdUDFs_Error: + 'generate an error message and exit + sbrStatus.Panels(1).Text = "ERROR: " & Err.Description + Resume cmdUDFs_Exit +End Sub + +'This procedure defines initial parameters. +Private Sub Form_Load() + tabMain.Tab = 0 + wShowInstructions = vbYes + + 'ask the user for displaying the instructions or not + wShowInstructions = MsgBox("Would you like to have instructions?", _ + vbYesNo, "Welcome to the DB2 Visual Basic samples") +End Sub + +'This procedure shows instructions at the begining of the program. +Private Sub Form_Activate() + If wShowInstructions = vbYes Then + MsgBox _ + "Thank you for using instructions in this demonstration program!" & vbCr & vbCr & _ + "- Status messages are shown at the bottom of the working window;" & vbCr & _ + "- Buttons unavailable are being grayed out;" & vbCr & _ + "- SAMPLE database must be created if it doesn't exist;" & vbCr & _ + "- [Exit] button can be pressed at anytime to quit the program." & vbCr & vbCr & _ + "You may now choose one of the connections to begin the demonstraton.", _ + vbOKOnly, "Instruction" + End If +End Sub + +'This procedure maintains screen integrity for the Main Tabs. +Private Sub tabMain_Click(intPreviousTab As Integer) + 'clear the the Tab screen before switching + Select Case tabMain.TabCaption(intPreviousTab) + Case "Execute SQL" + chkAutoCommit.Value = 1 + Set rst = Nothing + Set DataGridSQL.DataSource = Nothing + DataGridSQL.ClearFields + Case "Hierarchical Data" + Set hflxRecords.DataSource = Nothing + hflxRecords.Clear + Case "LOBs" + txtClob.Text = "" + txtEmpno.Text = "" + txtLastname.Text = "" + txtFirstname.Text = "" + AdodcLob.Caption = "" + AdodcLob.Enabled = False + cmdBLOB.Enabled = False + cmdCLOB.Enabled = False + picBlob.Visible = False + Case "Store Procedures" + Set rst = Nothing + Set DataGridSP.DataSource = Nothing + DataGridSP.Visible = False + DataGridSP.ClearFields + cmdShowSecondRS.Visible = False + txtSPResult.Text = "" + Case "UDFs" + txtUDF.Text = "" + hflxGridUDF.Clear + Case Else + End Select + sbrStatus.Panels(1).Text = "" +End Sub + +'This procedure shows instructions for the Main Tabs. +Private Sub tabMain_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) + 'show instructions + If wShowInstructions = vbYes Then + If con Is Nothing Then 'no connection established + MsgBox _ + "All funcitonal features require a valid connection.", _ + vbOKOnly + vbExclamation, "Instruction" + Else + Select Case tabMain.Caption + Case "Execute SQL" + MsgBox _ + "Please type a SQL statement into the text box, or," & vbCr & _ + "choose a preset one from the small Sample buttons, then," & vbCr & _ + "press one of the [Execute SQL] buttons to get the results." & vbCr & _ + "AutoCommit checkbox can be used to change the autocommit mode." & vbCr & vbCr & _ + "For more about the connection, command, and recordset objects," & vbCr & _ + "see the source code in the apExeSQL.bas module." & vbCr & vbCr & _ + "Note:" & vbCr & _ + "- The sample SQL statements can be edited." & vbCr & _ + "- Recordset results may be editable depending on the SQL statement issued.", _ + vbOKOnly, "Instruction" + Case "Hierarchical Data" + If InStr(con.Provider, "MSDataShape") Then + MsgBox _ + "Please press the [Display] button to display hierarchical result.", _ + vbOKOnly, "Instruction" + Else + MsgBox _ + "Hierarchical Data is only available for a" & vbCr & _ + "valid connection with DataShape.", _ + vbOKOnly + vbExclamation, "Instruction" + End If + Case "LOBs" + MsgBox _ + "After pressing the [Refresh Data] button;" & vbCr & _ + "Use arrow keys to manipulate results;" & vbCr & _ + "Press [Show Resume] button to display CLOBs;" & vbCr & _ + "Press [Show Picture] button to display BLOBs.", _ + vbOKOnly, "Instruction" + Case "Store Procedures" + MsgBox _ + "Choose an available stored procedure, then," & vbCr & _ + "press the [Call] button to get the results." & vbCr & vbCr & _ + "Note: To make them available, you first have to create and catalog" & vbCr & _ + "the stored procedures in the spserver stored procedure library.", _ + vbOKOnly, "Instruction" + Case "UDFs" + MsgBox _ + "Please choose one of the UDF buttons to show the usage.", _ + vbOKOnly, "Instruction" + Case Else + End Select + End If + End If +End Sub + + + + diff --git a/test/src_dir/groovy1.groovy b/test/src_dir/groovy1.groovy new file mode 100644 index 0000000..88fd2e0 --- /dev/null +++ b/test/src_dir/groovy1.groovy @@ -0,0 +1,9 @@ +//hello.groovy +println "hello, world" +for (arg in this.args ) { + println "Argument:" + arg; +} +// this is a comment +/* a block comment, commenting out an alternative to above: +this.args.each{ arg -> println "hello, ${arg}"} +*/ diff --git a/test/src_dir/html1.html b/test/src_dir/html1.html new file mode 100644 index 0000000..29e3f91 --- /dev/null +++ b/test/src_dir/html1.html @@ -0,0 +1,38 @@ + + + + foo + + + + +

+ + not in comment + + italic?]]> +

+ + + diff --git a/test/src_dir/java1.java b/test/src_dir/java1.java new file mode 100644 index 0000000..fa64172 --- /dev/null +++ b/test/src_dir/java1.java @@ -0,0 +1,48 @@ +// Program 11.6: A nicer sine wave +import java.applet.Applet; +import java.awt.Graphics; + +public class SineApplet2 extends Applet { + + public void paint(Graphics g) { + + int i, j1, j2; + + j1 = yvalue(0); + for (i = 0; i < size().width; i++) { + j2 = yvalue(i+1); + g.drawLine(i, j1 ,i+1, j2); + j1 = j2; + } + + } + + // Given the xpoint we're given calculate the Cartesian equivalent + private int yvalue(int ivalue) { + + double xmin = -10.0; + double xmax = 10.0; + double ymin = -1.0; + double ymax = 1.0; + double x, y; + int jvalue; + + x = (ivalue * (xmax - xmin)/(size().width - 1)) + xmin; + + // Take the sine of that x + y = Math.sin(x); + + // Scale y into window coordinates + jvalue = (int) ((y - ymin)*(size().height - 1)/ + (ymax - ymin)); + + /* Switch jvalue from Cartesian coordinates + to computer graphics coordinates */ + jvalue = size().height - jvalue; + + return jvalue; + + } + +} + diff --git a/test/src_dir/java2.java b/test/src_dir/java2.java new file mode 100644 index 0000000..361e930 --- /dev/null +++ b/test/src_dir/java2.java @@ -0,0 +1,3 @@ + /** + */ + diff --git a/test/src_dir/js1.js b/test/src_dir/js1.js new file mode 100644 index 0000000..f3ecd19 --- /dev/null +++ b/test/src_dir/js1.js @@ -0,0 +1,1781 @@ +/* Prototype JavaScript framework, version 1.4.0 + * (c) 2005 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://prototype.conio.net/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.4.0', + ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)', + + emptyFunction: function() {}, + K: function(x) {return x} +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (property in source) { + destination[property] = source[property]; + } + return destination; +} + +Object.inspect = function(object) { + try { + if (object == undefined) return 'undefined'; + if (object == null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } +} + +Function.prototype.bind = function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } +} + +Function.prototype.bindAsEventListener = function(object) { + var __method = this; + return function(event) { + return __method.call(object, event || window.event); + } +} + +Object.extend(Number.prototype, { + toColorPart: function() { + var digits = this.toString(16); + if (this < 16) return '0' + digits; + return digits; + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + } +}); + +var Try = { + these: function() { + var returnValue; + + for (var i = 0; i < arguments.length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) {} + } + + return returnValue; + } +} + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(); + } finally { + this.currentlyExecuting = false; + } + } + } +} + +/*--------------------------------------------------------------------------*/ + +function $() { + var elements = new Array(); + + for (var i = 0; i < arguments.length; i++) { + var element = arguments[i]; + if (typeof element == 'string') + element = document.getElementById(element); + + if (arguments.length == 1) + return element; + + elements.push(element); + } + + return elements; +} +Object.extend(String.prototype, { + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(eval); + }, + + escapeHTML: function() { + var div = document.createElement('div'); + var text = document.createTextNode(this); + div.appendChild(text); + return div.innerHTML; + }, + + unescapeHTML: function() { + var div = document.createElement('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; + }, + + toQueryParams: function() { + var pairs = this.match(/^\??(.*)$/)[1].split('&'); + return pairs.inject({}, function(params, pairString) { + var pair = pairString.split('='); + params[pair[0]] = pair[1]; + return params; + }); + }, + + toArray: function() { + return this.split(''); + }, + + camelize: function() { + var oStringList = this.split('-'); + if (oStringList.length == 1) return oStringList[0]; + + var camelizedString = this.indexOf('-') == 0 + ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) + : oStringList[0]; + + for (var i = 1, len = oStringList.length; i < len; i++) { + var s = oStringList[i]; + camelizedString += s.charAt(0).toUpperCase() + s.substring(1); + } + + return camelizedString; + }, + + inspect: function() { + return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; + } +}); + +String.prototype.parseQuery = String.prototype.toQueryParams; + +var $break = new Object(); +var $continue = new Object(); + +var Enumerable = { + each: function(iterator) { + var index = 0; + try { + this._each(function(value) { + try { + iterator(value, index++); + } catch (e) { + if (e != $continue) throw e; + } + }); + } catch (e) { + if (e != $break) throw e; + } + }, + + all: function(iterator) { + var result = true; + this.each(function(value, index) { + result = result && !!(iterator || Prototype.K)(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator) { + var result = true; + this.each(function(value, index) { + if (result = !!(iterator || Prototype.K)(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator) { + var results = []; + this.each(function(value, index) { + results.push(iterator(value, index)); + }); + return results; + }, + + detect: function (iterator) { + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator) { + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(pattern, iterator) { + var results = []; + this.each(function(value, index) { + var stringValue = value.toString(); + if (stringValue.match(pattern)) + results.push((iterator || Prototype.K)(value, index)); + }) + return results; + }, + + include: function(object) { + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inject: function(memo, iterator) { + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.collect(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (value >= (result || value)) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (value <= (result || value)) + result = value; + }); + return result; + }, + + partition: function(iterator) { + var trues = [], falses = []; + this.each(function(value, index) { + ((iterator || Prototype.K)(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value, index) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator) { + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator) { + return this.collect(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.collect(Prototype.K); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (typeof args.last() == 'function') + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + iterator(value = collections.pluck(index)); + return value; + }); + }, + + inspect: function() { + return '#'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0; i < iterable.length; i++) + results.push(iterable[i]); + return results; + } +} + +Object.extend(Array.prototype, Enumerable); + +Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0; i < this.length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != undefined || value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(value.constructor == Array ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + indexOf: function(object) { + for (var i = 0; i < this.length; i++) + if (this[i] == object) return i; + return -1; + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + shift: function() { + var result = this[0]; + for (var i = 0; i < this.length - 1; i++) + this[i] = this[i + 1]; + this.length--; + return result; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + } +}); +var Hash = { + _each: function(iterator) { + for (key in this) { + var value = this[key]; + if (typeof value == 'function') continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject($H(this), function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + toQueryString: function() { + return this.map(function(pair) { + return pair.map(encodeURIComponent).join('='); + }).join('&'); + }, + + inspect: function() { + return '#'; + } +} + +function $H(object) { + var hash = Object.extend({}, object || {}); + Object.extend(hash, Enumerable); + Object.extend(hash, Hash); + return hash; +} +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + do { + iterator(value); + value = value.succ(); + } while (this.include(value)); + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')}, + function() {return new XMLHttpRequest()} + ) || false; + }, + + activeRequestCount: 0 +} + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responderToAdd) { + if (!this.include(responderToAdd)) + this.responders.push(responderToAdd); + }, + + unregister: function(responderToRemove) { + this.responders = this.responders.without(responderToRemove); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (responder[callback] && typeof responder[callback] == 'function') { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) {} + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { + Ajax.activeRequestCount++; + }, + + onComplete: function() { + Ajax.activeRequestCount--; + } +}); + +Ajax.Base = function() {}; +Ajax.Base.prototype = { + setOptions: function(options) { + this.options = { + method: 'post', + asynchronous: true, + parameters: '' + } + Object.extend(this.options, options || {}); + }, + + responseIsSuccess: function() { + return this.transport.status == undefined + || this.transport.status == 0 + || (this.transport.status >= 200 && this.transport.status < 300); + }, + + responseIsFailure: function() { + return !this.responseIsSuccess(); + } +} + +Ajax.Request = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + initialize: function(url, options) { + this.transport = Ajax.getTransport(); + this.setOptions(options); + this.request(url); + }, + + request: function(url) { + var parameters = this.options.parameters || ''; + if (parameters.length > 0) parameters += '&_='; + + try { + this.url = url; + if (this.options.method == 'get' && parameters.length > 0) + this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; + + Ajax.Responders.dispatch('onCreate', this, this.transport); + + this.transport.open(this.options.method, this.url, + this.options.asynchronous); + + if (this.options.asynchronous) { + this.transport.onreadystatechange = this.onStateChange.bind(this); + setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); + } + + this.setRequestHeaders(); + + var body = this.options.postBody ? this.options.postBody : parameters; + this.transport.send(this.options.method == 'post' ? body : null); + + } catch (e) { + this.dispatchException(e); + } + }, + + setRequestHeaders: function() { + var requestHeaders = + ['X-Requested-With', 'XMLHttpRequest', + 'X-Prototype-Version', Prototype.Version]; + + if (this.options.method == 'post') { + requestHeaders.push('Content-type', + 'application/x-www-form-urlencoded'); + + /* Force "Connection: close" for Mozilla browsers to work around + * a bug where XMLHttpReqeuest sends an incorrect Content-length + * header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType) + requestHeaders.push('Connection', 'close'); + } + + if (this.options.requestHeaders) + requestHeaders.push.apply(requestHeaders, this.options.requestHeaders); + + for (var i = 0; i < requestHeaders.length; i += 2) + this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]); + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState != 1) + this.respondToReadyState(this.transport.readyState); + }, + + header: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) {} + }, + + evalJSON: function() { + try { + return eval(this.header('X-JSON')); + } catch (e) {} + }, + + evalResponse: function() { + try { + return eval(this.transport.responseText); + } catch (e) { + this.dispatchException(e); + } + }, + + respondToReadyState: function(readyState) { + var event = Ajax.Request.Events[readyState]; + var transport = this.transport, json = this.evalJSON(); + + if (event == 'Complete') { + try { + (this.options['on' + this.transport.status] + || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(transport, json); + } catch (e) { + this.dispatchException(e); + } + + if ((this.header('Content-type') || '').match(/^text\/javascript/i)) + this.evalResponse(); + } + + try { + (this.options['on' + event] || Prototype.emptyFunction)(transport, json); + Ajax.Responders.dispatch('on' + event, this, transport, json); + } catch (e) { + this.dispatchException(e); + } + + /* Avoid memory leak in MSIE: clean up the oncomplete event handler */ + if (event == 'Complete') + this.transport.onreadystatechange = Prototype.emptyFunction; + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Updater = Class.create(); + +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { + initialize: function(container, url, options) { + this.containers = { + success: container.success ? $(container.success) : $(container), + failure: container.failure ? $(container.failure) : + (container.success ? null : $(container)) + } + + this.transport = Ajax.getTransport(); + this.setOptions(options); + + var onComplete = this.options.onComplete || Prototype.emptyFunction; + this.options.onComplete = (function(transport, object) { + this.updateContent(); + onComplete(transport, object); + }).bind(this); + + this.request(url); + }, + + updateContent: function() { + var receiver = this.responseIsSuccess() ? + this.containers.success : this.containers.failure; + var response = this.transport.responseText; + + if (!this.options.evalScripts) + response = response.stripScripts(); + + if (receiver) { + if (this.options.insertion) { + new this.options.insertion(receiver, response); + } else { + Element.update(receiver, response); + } + } + + if (this.responseIsSuccess()) { + if (this.onComplete) + setTimeout(this.onComplete.bind(this), 10); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { + initialize: function(container, url, options) { + this.setOptions(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = {}; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(request) { + if (this.options.decay) { + this.decay = (request.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = request.responseText; + } + this.timer = setTimeout(this.onTimerEvent.bind(this), + this.decay * this.frequency * 1000); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +document.getElementsByClassName = function(className, parentElement) { + var children = ($(parentElement) || document.body).getElementsByTagName('*'); + return $A(children).inject([], function(elements, child) { + if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) + elements.push(child); + return elements; + }); +} + +/*--------------------------------------------------------------------------*/ + +if (!window.Element) { + var Element = new Object(); +} + +Object.extend(Element, { + visible: function(element) { + return $(element).style.display != 'none'; + }, + + toggle: function() { + for (var i = 0; i < arguments.length; i++) { + var element = $(arguments[i]); + Element[Element.visible(element) ? 'hide' : 'show'](element); + } + }, + + hide: function() { + for (var i = 0; i < arguments.length; i++) { + var element = $(arguments[i]); + element.style.display = 'none'; + } + }, + + show: function() { + for (var i = 0; i < arguments.length; i++) { + var element = $(arguments[i]); + element.style.display = ''; + } + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + }, + + update: function(element, html) { + $(element).innerHTML = html.stripScripts(); + setTimeout(function() {html.evalScripts()}, 10); + }, + + getHeight: function(element) { + element = $(element); + return element.offsetHeight; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + return Element.classNames(element).include(className); + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + return Element.classNames(element).add(className); + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + return Element.classNames(element).remove(className); + }, + + // removes whitespace-only text node children + cleanWhitespace: function(element) { + element = $(element); + for (var i = 0; i < element.childNodes.length; i++) { + var node = element.childNodes[i]; + if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) + Element.remove(node); + } + }, + + empty: function(element) { + return $(element).innerHTML.match(/^\s*$/); + }, + + scrollTo: function(element) { + element = $(element); + var x = element.x ? element.x : element.offsetLeft, + y = element.y ? element.y : element.offsetTop; + window.scrollTo(x, y); + }, + + getStyle: function(element, style) { + element = $(element); + var value = element.style[style.camelize()]; + if (!value) { + if (document.defaultView && document.defaultView.getComputedStyle) { + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css.getPropertyValue(style) : null; + } else if (element.currentStyle) { + value = element.currentStyle[style.camelize()]; + } + } + + if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) + if (Element.getStyle(element, 'position') == 'static') value = 'auto'; + + return value == 'auto' ? null : value; + }, + + setStyle: function(element, style) { + element = $(element); + for (name in style) + element.style[name.camelize()] = style[name]; + }, + + getDimensions: function(element) { + element = $(element); + if (Element.getStyle(element, 'display') != 'none') + return {width: element.offsetWidth, height: element.offsetHeight}; + + // All *Width and *Height properties give 0 on elements with display none, + // so enable the element temporarily + var els = element.style; + var originalVisibility = els.visibility; + var originalPosition = els.position; + els.visibility = 'hidden'; + els.position = 'absolute'; + els.display = ''; + var originalWidth = element.clientWidth; + var originalHeight = element.clientHeight; + els.display = 'none'; + els.position = originalPosition; + els.visibility = originalVisibility; + return {width: originalWidth, height: originalHeight}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + // Opera returns the offset relative to the positioning context, when an + // element is position relative but top and left have not been defined + if (window.opera) { + element.style.top = 0; + element.style.left = 0; + } + } + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return; + element._overflow = element.style.overflow; + if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') + element.style.overflow = 'hidden'; + }, + + undoClipping: function(element) { + element = $(element); + if (element._overflow) return; + element.style.overflow = element._overflow; + element._overflow = undefined; + } +}); + +var Toggle = new Object(); +Toggle.display = Element.toggle; + +/*--------------------------------------------------------------------------*/ + +Abstract.Insertion = function(adjacency) { + this.adjacency = adjacency; +} + +Abstract.Insertion.prototype = { + initialize: function(element, content) { + this.element = $(element); + this.content = content.stripScripts(); + + if (this.adjacency && this.element.insertAdjacentHTML) { + try { + this.element.insertAdjacentHTML(this.adjacency, this.content); + } catch (e) { + if (this.element.tagName.toLowerCase() == 'tbody') { + this.insertContent(this.contentFromAnonymousTable()); + } else { + throw e; + } + } + } else { + this.range = this.element.ownerDocument.createRange(); + if (this.initializeRange) this.initializeRange(); + this.insertContent([this.range.createContextualFragment(this.content)]); + } + + setTimeout(function() {content.evalScripts()}, 10); + }, + + contentFromAnonymousTable: function() { + var div = document.createElement('div'); + div.innerHTML = '' + this.content + '
'; + return $A(div.childNodes[0].childNodes[0].childNodes); + } +} + +var Insertion = new Object(); + +Insertion.Before = Class.create(); +Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { + initializeRange: function() { + this.range.setStartBefore(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, this.element); + }).bind(this)); + } +}); + +Insertion.Top = Class.create(); +Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(true); + }, + + insertContent: function(fragments) { + fragments.reverse(false).each((function(fragment) { + this.element.insertBefore(fragment, this.element.firstChild); + }).bind(this)); + } +}); + +Insertion.Bottom = Class.create(); +Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.appendChild(fragment); + }).bind(this)); + } +}); + +Insertion.After = Class.create(); +Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { + initializeRange: function() { + this.range.setStartAfter(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, + this.element.nextSibling); + }).bind(this)); + } +}); + +/*--------------------------------------------------------------------------*/ + +Element.ClassNames = Class.create(); +Element.ClassNames.prototype = { + initialize: function(element) { + this.element = $(element); + }, + + _each: function(iterator) { + this.element.className.split(/\s+/).select(function(name) { + return name.length > 0; + })._each(iterator); + }, + + set: function(className) { + this.element.className = className; + }, + + add: function(classNameToAdd) { + if (this.include(classNameToAdd)) return; + this.set(this.toArray().concat(classNameToAdd).join(' ')); + }, + + remove: function(classNameToRemove) { + if (!this.include(classNameToRemove)) return; + this.set(this.select(function(className) { + return className != classNameToRemove; + }).join(' ')); + }, + + toString: function() { + return this.toArray().join(' '); + } +} + +Object.extend(Element.ClassNames.prototype, Enumerable); +var Field = { + clear: function() { + for (var i = 0; i < arguments.length; i++) + $(arguments[i]).value = ''; + }, + + focus: function(element) { + $(element).focus(); + }, + + present: function() { + for (var i = 0; i < arguments.length; i++) + if ($(arguments[i]).value == '') return false; + return true; + }, + + select: function(element) { + $(element).select(); + }, + + activate: function(element) { + element = $(element); + element.focus(); + if (element.select) + element.select(); + } +} + +/*--------------------------------------------------------------------------*/ + +var Form = { + serialize: function(form) { + var elements = Form.getElements($(form)); + var queryComponents = new Array(); + + for (var i = 0; i < elements.length; i++) { + var queryComponent = Form.Element.serialize(elements[i]); + if (queryComponent) + queryComponents.push(queryComponent); + } + + return queryComponents.join('&'); + }, + + getElements: function(form) { + form = $(form); + var elements = new Array(); + + for (tagName in Form.Element.Serializers) { + var tagElements = form.getElementsByTagName(tagName); + for (var j = 0; j < tagElements.length; j++) + elements.push(tagElements[j]); + } + return elements; + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) + return inputs; + + var matchingInputs = new Array(); + for (var i = 0; i < inputs.length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || + (name && input.name != name)) + continue; + matchingInputs.push(input); + } + + return matchingInputs; + }, + + disable: function(form) { + var elements = Form.getElements(form); + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + element.blur(); + element.disabled = 'true'; + } + }, + + enable: function(form) { + var elements = Form.getElements(form); + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + element.disabled = ''; + } + }, + + findFirstElement: function(form) { + return Form.getElements(form).find(function(element) { + return element.type != 'hidden' && !element.disabled && + ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + Field.activate(Form.findFirstElement(form)); + }, + + reset: function(form) { + $(form).reset(); + } +} + +Form.Element = { + serialize: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + var parameter = Form.Element.Serializers[method](element); + + if (parameter) { + var key = encodeURIComponent(parameter[0]); + if (key.length == 0) return; + + if (parameter[1].constructor != Array) + parameter[1] = [parameter[1]]; + + return parameter[1].map(function(value) { + return key + '=' + encodeURIComponent(value); + }).join('&'); + } + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + var parameter = Form.Element.Serializers[method](element); + + if (parameter) + return parameter[1]; + } +} + +Form.Element.Serializers = { + input: function(element) { + switch (element.type.toLowerCase()) { + case 'submit': + case 'hidden': + case 'password': + case 'text': + return Form.Element.Serializers.textarea(element); + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element); + } + return false; + }, + + inputSelector: function(element) { + if (element.checked) + return [element.name, element.value]; + }, + + textarea: function(element) { + return [element.name, element.value]; + }, + + select: function(element) { + return Form.Element.Serializers[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + }, + + selectOne: function(element) { + var value = '', opt, index = element.selectedIndex; + if (index >= 0) { + opt = element.options[index]; + value = opt.value; + if (!value && !('value' in opt)) + value = opt.text; + } + return [element.name, value]; + }, + + selectMany: function(element) { + var value = new Array(); + for (var i = 0; i < element.length; i++) { + var opt = element.options[i]; + if (opt.selected) { + var optValue = opt.value; + if (!optValue && !('value' in opt)) + optValue = opt.text; + value.push(optValue); + } + } + return [element.name, value]; + } +} + +/*--------------------------------------------------------------------------*/ + +var $F = Form.Element.getValue; + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = function() {} +Abstract.TimedObserver.prototype = { + initialize: function(element, frequency, callback) { + this.frequency = frequency; + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + } +} + +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = function() {} +Abstract.EventObserver.prototype = { + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + var elements = Form.getElements(this.element); + for (var i = 0; i < elements.length; i++) + this.registerCallback(elements[i]); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + case 'password': + case 'text': + case 'textarea': + case 'select-one': + case 'select-multiple': + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +} + +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) { + var Event = new Object(); +} + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + + element: function(event) { + return event.target || event.srcElement; + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointerX: function(event) { + return event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)); + }, + + pointerY: function(event) { + return event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)); + }, + + stop: function(event) { + if (event.preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } else { + event.returnValue = false; + event.cancelBubble = true; + } + }, + + // find the first node with the given tagName, starting from the + // node the event was triggered on; traverses the DOM upwards + findElement: function(event, tagName) { + var element = Event.element(event); + while (element.parentNode && (!element.tagName || + (element.tagName.toUpperCase() != tagName.toUpperCase()))) + element = element.parentNode; + return element; + }, + + observers: false, + + _observeAndCache: function(element, name, observer, useCapture) { + if (!this.observers) this.observers = []; + if (element.addEventListener) { + this.observers.push([element, name, observer, useCapture]); + element.addEventListener(name, observer, useCapture); + } else if (element.attachEvent) { + this.observers.push([element, name, observer, useCapture]); + element.attachEvent('on' + name, observer); + } + }, + + unloadCache: function() { + if (!Event.observers) return; + for (var i = 0; i < Event.observers.length; i++) { + Event.stopObserving.apply(this, Event.observers[i]); + Event.observers[i][0] = null; + } + Event.observers = false; + }, + + observe: function(element, name, observer, useCapture) { + var element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (navigator.appVersion.match(/Konqueror|Safari|KHTML/) + || element.attachEvent)) + name = 'keydown'; + + this._observeAndCache(element, name, observer, useCapture); + }, + + stopObserving: function(element, name, observer, useCapture) { + var element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (navigator.appVersion.match(/Konqueror|Safari|KHTML/) + || element.detachEvent)) + name = 'keydown'; + + if (element.removeEventListener) { + element.removeEventListener(name, observer, useCapture); + } else if (element.detachEvent) { + element.detachEvent('on' + name, observer); + } + } +}); + +/* prevent memory leaks in IE */ +Event.observe(window, 'unload', Event.unloadCache, false); +var Position = { + // set to true if needed, warning: firefox performance problems + // NOT neeeded for page scrolling, only if draggable contained in + // scrollable elements + includeScrollOffsets: false, + + // must be called before calling withinIncludingScrolloffset, every time the + // page is scrolled + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + realOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return [valueL, valueT]; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return [valueL, valueT]; + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return [valueL, valueT]; + }, + + offsetParent: function(element) { + if (element.offsetParent) return element.offsetParent; + if (element == document.body) return element; + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return element; + + return document.body; + }, + + // caches x/y coordinate pair to use with overlap + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = this.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = this.realOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = this.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + // within must be called directly before + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + clone: function(source, target) { + source = $(source); + target = $(target); + target.style.position = 'absolute'; + var offsets = this.cumulativeOffset(source); + target.style.top = offsets[1] + 'px'; + target.style.left = offsets[0] + 'px'; + target.style.width = source.offsetWidth + 'px'; + target.style.height = source.offsetHeight + 'px'; + }, + + page: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent==document.body) + if (Element.getStyle(element,'position')=='absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } while (element = element.parentNode); + + return [valueL, valueT]; + }, + + clone: function(source, target) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || {}) + + // find page position of source + source = $(source); + var p = Position.page(source); + + // find coordinate system to use + target = $(target); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(target,'position') == 'absolute') { + parent = Position.offsetParent(target); + delta = Position.page(parent); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if(options.setWidth) target.style.width = source.offsetWidth + 'px'; + if(options.setHeight) target.style.height = source.offsetHeight + 'px'; + }, + + absolutize: function(element) { + element = $(element); + if (element.style.position == 'absolute') return; + Position.prepare(); + + var offsets = Position.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px';; + element.style.left = left + 'px';; + element.style.width = width + 'px';; + element.style.height = height + 'px';; + }, + + relativize: function(element) { + element = $(element); + if (element.style.position == 'relative') return; + Position.prepare(); + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + } +} + +// Safari returns margins on body which is incorrect if the child is absolutely +// positioned. For performance reasons, redefine Position.cumulativeOffset for +// KHTML/WebKit only. +if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { + Position.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return [valueL, valueT]; + } +} diff --git a/test/src_dir/js2.js b/test/src_dir/js2.js new file mode 100644 index 0000000..6859d6b --- /dev/null +++ b/test/src_dir/js2.js @@ -0,0 +1,13 @@ + diff --git a/test/src_dir/js3.js b/test/src_dir/js3.js new file mode 100644 index 0000000..81629ea --- /dev/null +++ b/test/src_dir/js3.js @@ -0,0 +1,2 @@ +return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; +// comment diff --git a/test/src_dir/jsp1.jsp b/test/src_dir/jsp1.jsp new file mode 100644 index 0000000..922fc70 --- /dev/null +++ b/test/src_dir/jsp1.jsp @@ -0,0 +1,14 @@ + + + JSP page + + + <%@ page language="java" %> + <% out.println("Hello World"); %> + <% // comment + /* + * more comment + */ + %> + + diff --git a/test/src_dir/lsp1.lsp b/test/src_dir/lsp1.lsp new file mode 100644 index 0000000..c93b0ae --- /dev/null +++ b/test/src_dir/lsp1.lsp @@ -0,0 +1,133 @@ +;;; CrapsSim.lsp + +;;; The main purpose of this program was to implement a Craps game, using a language that we have just +;;; learned. Also, it was written in a functional style with almost no reliance on the assignment +;;; operation. Only one local variable called THROW was used. + + +;;; ====================================================================================================== ;;; +;;; ======================================= CRAPS SIMULATION ============================================= ;;; +;;; ====================================================================================================== ;;; + + +;;; ** This function takes no parameters as input and returns a random number between 1 and 6. ** + +(DEFUN THROW-DIE () + (+ (RANDOM 6) 1) ;;; get a random number between 0 and 5 and then add 1 + ) + +;;; ====================================================================================================== ;;; + +;;; ** This function takes no parameters as input and returns a LIST with two numbers between 1 and 6. ** + + +(DEFUN THROW-DICE () + + (LIST (THROW-DIE) (THROW-DIE)) ;;; create a list with two random numbers + + ) + +;;; ====================================================================================================== ;;; + +;;; ** This function takes two numbers as parameters for input and returns T or Nil. T is returned if both +;;; numbers are equal to 6. Nil is returned otherwise. ** + +(DEFUN BOXCARS-P (A B) + (AND (EQUAL '6 A) + (EQUAL '6 B) + ) + + ) + +;;; ====================================================================================================== ;;; + +;;; ** This function takes two numbers as parameters for input and returns T or Nil. T is returned if both +;;; numbers are equal to 1. Nil is returned otherwise. ** + +(DEFUN SNAKE-EYES-P (A B) + (AND (EQUAL '1 A) + (EQUAL '1 B) + ) + + ) + +;;; ====================================================================================================== ;;; + +;;; ** This function takes two numbers as parameters for input and returns T or Nil. T is returned if the +;;; sum of both numbers is equal to a 7 or 11. Nil is returned otherwise. ** + +(DEFUN INSTANT-WIN-P (A B) + (OR (EQUAL '7 (+ A B)) + (EQUAL '11 (+ A B)) + ) + + ) + +;;; ====================================================================================================== ;;; + +;;; ** This function takes two numbers as parameters for input and returns T or Nil. T is returned if the +;;; sum of both numbers is equal to a 2, 3 or 12. Nil is returned otherwise. ** + +(DEFUN INSTANT-LOSS-P (A B) + (OR (EQUAL '2 (+ A B)) + (EQUAL '3 (+ A B)) + (EQUAL '12 (+ A B)) + ) + + ) + +;;; ====================================================================================================== ;;; + +;;; ** This function takes two numbers as parameters for input and returns a string. If function BOXCARS_P +;;; returns T, then the returned string equals BOXCARS. If function SNAKE_EYES_P returns T, then the +;;; returned string equals SNAKE_EYES. The string contains Nil otherwise. ** + +(DEFUN SAY-THROW (A B) + (COND ((BOXCARS-P A B) 'BOXCARS) ;;; make use of function BOXCARS_P + ((SNAKE-EYES-P A B) 'SNAKE-EYES) ;;; make use of function SNAKE_EYES_P + + ) + ) + +;;; ====================================================================================================== ;;; + +;;; ** This is the main function used to simulate the game of craps. Variable THROW contains a LIST of two +;;; numbers between 1 and 6. The numbers located in THROW, are used as parameters for the other functions. +;;; The several pieces used for output are listed together and then the LIST is returned from this +;;; function. + + +(DEFUN CRAPS () + (LET THROW (THROW-DICE)) ;;; get initial roll of the dice + + ;;; if roll is a win, then LIST the appropriate output + + (COND ((INSTANT-WIN-P (FIRST THROW) (SECOND THROW)) + (LIST 'THROW (FIRST THROW) 'AND (SECOND THROW) '-- (+ (FIRST THROW) (SECOND THROW)) '-- 'YOU 'WIN)) + + ;;; if roll is a loss, then check for BOXCARS or SNAKE-EYES + + ((INSTANT-LOSS-P (FIRST THROW) (SECOND THROW)) + + (IF (EQUAL 'NIL (SAY-THROW (FIRST THROW) (SECOND THROW))) ;;; if Nil then LIST appropriate output + + (LIST 'THROW (FIRST THROW) 'AND (SECOND THROW) '-- (+ (FIRST THROW) (SECOND THROW)) '-- 'YOU 'LOSE) + + ;;; else include the BOXCARS or SNAKE-EYES string in the output + + (LIST 'THROW (FIRST THROW) 'AND (SECOND THROW) '-- (SAY-THROW (FIRST THROW) (SECOND THROW)) + '-- 'YOU 'LOSE))) + + ;;; if roll is not instant win or loss then output sum of dice + + (T (LIST 'THROW (FIRST THROW) 'AND (SECOND THROW) '-- 'YOUR 'POINT 'IS (+ (FIRST THROW) + (SECOND THROW)))) + ) ;;; end COND + + ) ;;; end LET + + +) + + +;;; ======================================== END OF PROGRAM CRAPS ======================================== ;;; diff --git a/test/src_dir/lua1.lua b/test/src_dir/lua1.lua new file mode 100644 index 0000000..4f2e558 --- /dev/null +++ b/test/src_dir/lua1.lua @@ -0,0 +1,121 @@ +-- random code from http://lua-users.org/wiki/TextJustification +-- easy queue implementation ------------------------------------------ + +function q_create() + local q = {} + q.first = 0 + q.last = 0 + return q +end + +function q_insert(q, s) + q[q.last] = s + q.last = q.last + 1 +end + +function q_empty(q) + return q.first >= q.last +end + +function q_remove(q) + if q_empty(q) then + return nil + end + local s = q[q.first] + q[q.first] = nil + q.first = q.first+1 + return s +end + +function q_card(q) + return q.last - q.first +end + +function q_length(q, f) + local l, i = 0, q.first + while i < q.last do + l = l + strlen(q[i]) + i = i + 1 + end + return l +end + +-- line creation routines ------------------------------------------ + +-- justifies one line to fit into MAX columns +function justify(q) + local blanks = MAX - q_length(q) + local skips = q_card(q) - 1 + local line = q_remove(q) + local quotient = floor(blanks/skips) + local reminder = blanks/skips - quotient + local error = 0 + while skips > 0 do + error = error + reminder + if error >= 0.5 then + error = error - 1 + line = line .. strrep(" ", quotient+1) + else + line = line .. strrep(" ", quotient) + end + line = line .. q_remove(q) + skips = skips - 1 + end + return line or "" +end + +-- join all words with one space between them +function catenate(q) + local line = q_remove(q) + while not q_empty(q) do + line = line .. " " .. q_remove(q) + end + return line or "" +end + +-- main program ----------------------------------------------------- +DEFMAX = 72 +-- tries to get MAX from command-line +if not arg or getn(arg) < 1 then + MAX = DEFMAX +else + MAX = tonumber(arg[1]) + if not MAX or MAX < 0 then + MAX = DEFMAX + end +end + +-- collects all text from stdin +text = q_create() +line = read() +while line do + _, n = gsub(line, "(%S+)", function (s) q_insert(%text, s) end) + if n == 0 then + q_insert(text, "\n") + end + line = read() +end + +-- justify paragraphs +line = q_create() +word = q_remove(text) +size = 0 +while word do + if word == "\n" then + if not q_empty(line) then + write(catenate(line), "\n\n") + else + write("\n") + end + size = 0 + elseif size + strlen(word) > MAX then + write(justify(line), "\n") + size = 0 + end + if word ~= "\n" then + q_insert(line, word) + size = size + strlen(word) + 1 + end + word = q_remove(text) +end +write(catenate(line), "\n") diff --git a/test/src_dir/matlab1.m b/test/src_dir/matlab1.m new file mode 100644 index 0000000..dbb07b2 --- /dev/null +++ b/test/src_dir/matlab1.m @@ -0,0 +1,54 @@ +% PROGRAM theta_logistic.m +% Calculates by simulation the probability that a population +% following the theta logistic model and starting at Nc will fall +% below the quasi-extinction threshold Nx at or before time tmax + +% SIMULATION PARAMETERS +% for butterflies (Euphydryas editha bayensis) at Jasper Ridge (population C) + +r=0.3458; % intrinsic rate of increase--Butterflies at Jasper Ridge +K=846.017; % carrying capacity +theta=1; % nonlinearity in density dependence +sigma2=1.1151; % environmental variance +Nc=94; % starting population size +Nx=20; % quasi-extinction threshold +tmax=20; % time horizon +NumReps=50000; % number of replicate population trajectories + +% SIMULATION CODE + +sigma=sqrt(sigma2); +randn('state',sum(100*clock)); % seed the random number generator + +N=Nc*ones(1,NumReps); % all NumRep populations start at Nc +NumExtant=NumReps; % all populations are initially extant +Extant=[NumExtant]; % vector for number of extant pops. vs. time + +for t=1:tmax, % For each future time, + N=N.*exp( r*( 1-(N/K).^theta )... % the theta logistic model + + sigma*randn(1,NumExtant) ); % with random environmental effects. + for i=NumExtant:-1:1, % Then, looping over all extant populations, + if N(i)<=Nx, % if at or below quasi-extinction threshold, + N(i)=[]; % delete the population. + end; + end; + NumExtant=length(N); % Count remaining extant populations + Extant=[Extant NumExtant]; % and store the result. +end; + +% OUTPUT CODE +% ComputeS quasi-extinction probability as the fraction of replicate +% populations that have hit the threshold by each future time, +% and plotS quasi-extinction probability vs. time + +ProbExtinct=(NumReps-Extant)/NumReps; +plot([0:tmax],ProbExtinct) +xlabel('Years into the future'); +ylabel('Cumulative probability of quasi-extinction'); +axis([0 tmax 0 1]); + +% Integrate solution exactly % +% Options=[]; +% [T,true] = ode45(@logistic,[0,20],Nc,Options,r,K,theta); +% subplot(1,2,2) +% plot([1:tmax],P,'r.-',T,true,'g.-') diff --git a/test/src_dir/pascal1.pas b/test/src_dir/pascal1.pas new file mode 100644 index 0000000..a820b9a --- /dev/null +++ b/test/src_dir/pascal1.pas @@ -0,0 +1,112 @@ +{*************************************************************** + * + * Unit Name: pndefs + * Purpose : Various Definitions and functions... + * Author : Simon Steele + * Copyright: This Source Code is Copyright © 1998-2000 Echo + * Software and Simon Steele. Please read the license + * agreement at www.pnotepad.org/press/psidx.html. + **************************************************************} +unit pndefs; + +interface + +uses SysUtils; + +function CreatePNFile(filename : string; Text : pChar) : Boolean; +function StripNewLines(aString: string): string; +procedure ConvertTypes(filename : string); + +const strFileTypes : PChar = ('.txt'); + strOpenTypes : PChar = ('%2|Text files (*.txt)|*.txt|0|0|0|LOG files (*.log)|*.log|0|0|0|Executable Files (*.exe, *.com, *.dll)|*.exe;*.com;*.dll|0|0|0'); + sepChar = '|'; + verChar = '%'; + CurrFileVer = '2'; + +implementation + +function CreatePNFile(filename : string; Text : pChar) : Boolean; +var F : TextFile; +begin + {$I-} + AssignFile(F, filename); + Rewrite(F); + Write(F, Text); + CloseFile(F); + If IOResult <> 0 Then Result := False + Else Result := True; + {$I+} +end; + +function StripNewLines(aString: string): string; +var i : longint; +begin + result := ''; + i := 1; + while i <= length(aString) do + begin + if aString[i] = #13 then result := result + ' ' else + if aString[i] <> #10 then result := result + aString[i]; + inc(i); + end; +end; + +procedure ConvertTypes(filename : string); +var t : TextFile; + s : string; + ps : string; {part of string} + Part : integer; + ipos : integer; + OutStr : string; +const Desc = 1; + Files = 2; + Parser = 3; + Unix = 4; +begin + // This assumes that it is being passed one of the old style type definition + // files. We'll set the status on the main form to indicate this as well... + OutStr := VerChar + CurrFileVer; + if not fileexists(filename) then + begin + CreatePNFile(filename, strOpenTypes); + exit; + end; + Assignfile(t, FileName); + Reset(t); + repeat + Readln(t, s) + until (Length(s) > 0) or EOF(t); + CloseFile(t); + if s = '' then Exit; + part := Desc; + repeat + iPos := Pos(SepChar, s); + if (iPos = 0) and (Length(s) > 0) then + begin + ps := s; + s := ''; + end else + ps := Copy(s, 1, ipos - 1); + s := Copy(S, ipos + 1, Length(s)); + case part of + Desc : begin + OutStr := OutStr + SepChar + ps; + part := Files; + end; + Files : begin + OutStr := OutStr + SepChar + ps; + part := Parser; + end; + Parser : begin + OutStr := OutStr + SepChar + ps + SepChar + '0' + SepChar + '0'; + part := Desc; + end; + end; + until Length(s) < 1; + Assignfile(t, filename); + Rewrite(t); + Write(t, OutStr); + CloseFile(t); +end; + +end. diff --git a/test/src_dir/pascal2.pp b/test/src_dir/pascal2.pp new file mode 100644 index 0000000..a820b9a --- /dev/null +++ b/test/src_dir/pascal2.pp @@ -0,0 +1,112 @@ +{*************************************************************** + * + * Unit Name: pndefs + * Purpose : Various Definitions and functions... + * Author : Simon Steele + * Copyright: This Source Code is Copyright © 1998-2000 Echo + * Software and Simon Steele. Please read the license + * agreement at www.pnotepad.org/press/psidx.html. + **************************************************************} +unit pndefs; + +interface + +uses SysUtils; + +function CreatePNFile(filename : string; Text : pChar) : Boolean; +function StripNewLines(aString: string): string; +procedure ConvertTypes(filename : string); + +const strFileTypes : PChar = ('.txt'); + strOpenTypes : PChar = ('%2|Text files (*.txt)|*.txt|0|0|0|LOG files (*.log)|*.log|0|0|0|Executable Files (*.exe, *.com, *.dll)|*.exe;*.com;*.dll|0|0|0'); + sepChar = '|'; + verChar = '%'; + CurrFileVer = '2'; + +implementation + +function CreatePNFile(filename : string; Text : pChar) : Boolean; +var F : TextFile; +begin + {$I-} + AssignFile(F, filename); + Rewrite(F); + Write(F, Text); + CloseFile(F); + If IOResult <> 0 Then Result := False + Else Result := True; + {$I+} +end; + +function StripNewLines(aString: string): string; +var i : longint; +begin + result := ''; + i := 1; + while i <= length(aString) do + begin + if aString[i] = #13 then result := result + ' ' else + if aString[i] <> #10 then result := result + aString[i]; + inc(i); + end; +end; + +procedure ConvertTypes(filename : string); +var t : TextFile; + s : string; + ps : string; {part of string} + Part : integer; + ipos : integer; + OutStr : string; +const Desc = 1; + Files = 2; + Parser = 3; + Unix = 4; +begin + // This assumes that it is being passed one of the old style type definition + // files. We'll set the status on the main form to indicate this as well... + OutStr := VerChar + CurrFileVer; + if not fileexists(filename) then + begin + CreatePNFile(filename, strOpenTypes); + exit; + end; + Assignfile(t, FileName); + Reset(t); + repeat + Readln(t, s) + until (Length(s) > 0) or EOF(t); + CloseFile(t); + if s = '' then Exit; + part := Desc; + repeat + iPos := Pos(SepChar, s); + if (iPos = 0) and (Length(s) > 0) then + begin + ps := s; + s := ''; + end else + ps := Copy(s, 1, ipos - 1); + s := Copy(S, ipos + 1, Length(s)); + case part of + Desc : begin + OutStr := OutStr + SepChar + ps; + part := Files; + end; + Files : begin + OutStr := OutStr + SepChar + ps; + part := Parser; + end; + Parser : begin + OutStr := OutStr + SepChar + ps + SepChar + '0' + SepChar + '0'; + part := Desc; + end; + end; + until Length(s) < 1; + Assignfile(t, filename); + Rewrite(t); + Write(t, OutStr); + CloseFile(t); +end; + +end. diff --git a/test/src_dir/perl.cgi b/test/src_dir/perl.cgi new file mode 100755 index 0000000..1ac7811 --- /dev/null +++ b/test/src_dir/perl.cgi @@ -0,0 +1,66 @@ +#!/usr/bin/perl -w + +# ajaxCheckbox.pl - a script to test Ajax functionality + +use strict; +use CGI qw/:standard/; +use CGI::Ajax; +use DBI; + +# --- database authenication +my $dbh = do 'db.inc'; + +my $query = q{ SELECT project.project_id, project.name, project.phase, prio.prio, + HEX((255 - prio.prio)) AS hex, begun, tags + FROM project JOIN prio + ON (project.project_id = prio.project_id) + WHERE completed < 1 + ORDER BY prio.prio DESC LIMIT 3}; + +my $sth = $dbh->prepare($query); +$sth->execute(); +my $result = $dbh->selectall_arrayref($sth); + +my $cgi = new CGI; +my $pjx = new CGI::Ajax( 'toStruck' => \&perl_func ); +print $pjx->build_html( $cgi, \&Show_HTML); + +sub Show_HTML { + + use CGI qw/:standard/; + + my $html = < + + + This is the lastest source version + + + +

Carrot Queue

Priority List  |   + Add a listing  |  

Project listing

+HEAD + +foreach my $row (@$result) { + $html .= ""; + $html .= "
" . @$row[1] . "

"; +} + +# you can append stuff to the HTML this way +$html .= ""; + +return $html; +} + +sub perl_func { + my $input=shift; + + # if onClick the change the style + if ($input eq "ON") { + $input=""; + } else { + $input =""; + } +} diff --git a/test/src_dir/perl1.pl b/test/src_dir/perl1.pl new file mode 100644 index 0000000..3c806fa --- /dev/null +++ b/test/src_dir/perl1.pl @@ -0,0 +1,72 @@ +#!/usr/bin/perl +# Conserve bandwidth - put a copy of Dilbert on your intranet. +# Run every morning with cron - after about 7am Eastern +######################################################## +use Time::ParseDate; +use Time::CTime; +use LWP::Simple; + +# Where do you want the image put? +$dir="/usr/local/etc/httpd/htdocs/Dilbert"; +# $dir = "c:/httpd/htdocs/Dilbert"; +$location ="$dir/dilbert.gif"; + +$_ = get("http://www.unitedmedia.com/comics/dilbert/index.html"); + +# These next 4 lines will change every time they change the +# page layout on the Dilbert site. Check back on my web site +# if things suddenly stop working +s/^.*strip_left\.gif//s; +s/^.*?HREF=\"//s; +s/\">.*$//s; +$line = "http://www.unitedmedia.com" . $_; + +# Back up yesterday's image: +# get the number +open (ID,"$dir/id"); +$id=; +close ID; + +$id++; +$id=~s/\n$//; +`mv $location $dir/dilbert.$id.gif`; +# If you're using this on NT, you may want to replace 'mv' +# with 'move'. + +open (ID,">$dir/id"); +print ID "$id"; +close ID; + +# Now get the actual image +$_ = get($line); + +open (FILE, ">$location"); +binmode FILE; # Important for NT +print FILE; +close FILE; + +# Now I want to update the index.html file +open (FILE, "$dir/index.html"); +@index=; +close FILE; + +$yesterday = parsedate('yesterday'); +$printdate = strftime('%a, %b %d', localtime($yesterday)); + +open (FILE, ">$dir/index.html"); +for (@index) { +if (/INSERT HERE/) { + print FILE "$_"; + print FILE "$printdate\n"; + if (($id % 5) == 0) {print FILE "\n"} + } +else {print FILE "$_"}; + } # End for +close FILE; + +# Start with an index.html file containing ... +# +# +#
+# ... +# And whatever else you want on the page. diff --git a/test/src_dir/php1.php b/test/src_dir/php1.php new file mode 100644 index 0000000..7f033ab --- /dev/null +++ b/test/src_dir/php1.php @@ -0,0 +1,58 @@ + + + + + + + + + + + + +
FirstLastEmail +
+ + + + + + + + + + + + + diff --git a/test/src_dir/py1.py b/test/src_dir/py1.py new file mode 100644 index 0000000..8f92e62 --- /dev/null +++ b/test/src_dir/py1.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Python + +# Suppose you want to spam your friend, and you have lots of +# friends. The solution is to write a program to do it. After a gander +# at python docs, one easily found the module for the job. +# see http://python.org/doc/2.3.4/lib/SMTP-example.html + +# the code is a bit long with the command line, but the key lies at +# the bottom four lines. The gist is this: + +####### test: strings - nonsense code follows +"\" +# still in string +" +'\' +# still in string +' +####### test done +import smtplib + +smtpServer='smtp.yourdomain.com'; +fromAddr='xah@xahlee.org'; +toAddr='xah@xahlee.org'; +text='''Subject: newfound love + +Hi friend, + +long time no write, i have a new manifesto i + think it would be of interest for you to peruse. + ... + ''' + +server = smtplib.SMTP(smtpServer) +server.set_debuglevel(1) +server.sendmail(fromAddr, toAddr, text) +server.quit() + +# save this file as x.py and run it. +# it should send out the mail. + +# the set_debuglevel() is nice because you see all the interactions +# with the smtp server. Useful when you want to see what's going on +# with a smtp server. diff --git a/test/src_dir/rexx1.rex b/test/src_dir/rexx1.rex new file mode 100644 index 0000000..945e4f8 --- /dev/null +++ b/test/src_dir/rexx1.rex @@ -0,0 +1,311 @@ +/* REXX FLTTBL Cloned from DUMPTBL 960619 to produce a flat + version (up to 32K characters wide) of any ISPF + table. + + Written by Frank Clarke, Oldsmar, FL + + Impact Analysis +. SYSPROC LA +. SYSPROC TRAPOUT + + Modification History + 19960918 fxc added some error-checking + 19970115 fxc upgrade REXXSKEL from v.960606 to v.970113; add + RESTARTability; + 19991231 fxc upgrade REXXSKEL from v.970113 to v.19991109; + RXSKLY2K; DECOMM; LRECL reduced from 32K to "min + needed"; + +*/ arg argline +address TSO /* REXXSKEL ver.19991109 */ +arg parms "((" opts + +signal on syntax +signal on novalue + +call TOOLKIT_INIT /* conventional start-up -*/ +rc = Trace(tv) +info = parms /* to enable parsing */ + +if \sw.inispf then do + arg line + line = line "(( RESTARTED" /* tell the next invocation */ + "ISPSTART CMD("exec_name line")" /* Invoke ISPF if nec. */ + exit /* ...and restart it */ + end + +call A_INIT /* -*/ + +"NEWSTACK" + if \sw.0error_found then, +call C_TABLE_OPS /* -*/ + if \sw.0error_found then, +call D_PUMP_TBL /* -*/ + +"DELSTACK" + +if sw.restarted then do + rc = OutTrap("ll.") + exit 4 + end + +exit /*@ FLTTBL */ +/* +. ----------------------------------------------------------------- */ +A_INIT: /*@ */ + if branch then call BRANCH + address TSO + + call AA_KEYWDS /* -*/ + parse var info $tn$ . /* table-name required */ + if $tn$ = "" then do + helpmsg = "Tablename is required." + call HELP + end + + parse value outdsn "FLATTBLS."$tn$ with, + outdsn . + + xefef = "efef"x + if tblds = "" then do + call AB_FIND_LIBRARY /* -*/ + if tblds = "" then do + helpmsg = "Table" $tn$ "was not found in ISPTLIB. Please", + "restart specifying a library name as shown below." + call HELP /* ...and don't come back */ + end + end + else, + if Left(tblds,1) = "'" then tblds = Strip(tblds,,"'") + else tblds = Userid()"."tblds + +return /*@ A_INIT */ +/* +. ----------------------------------------------------------------- */ +AA_KEYWDS: /*@ */ + if branch then call BRANCH + address TSO + + tblds = KEYWD("IN") + outdsn = KEYWD("OUTPUT") + sortseq = KEYWD("SORT") + sw.0purge = SWITCH("DELETEBEHIND") + + parse value KEYWD("ADD") "0" with bytes_to_add . + +return /*@ AA_KEYWDS */ +/* + was not specified. Locate the table in ISPTLIB. +. ----------------------------------------------------------------- */ +AB_FIND_LIBRARY: /*@ */ + if branch then call BRANCH + address TSO + + "NEWSTACK" + "LA ISPTLIB ((STACK LINE" + pull tliblist + "DELSTACK" + + do Words(tliblist) /* each library */ + parse var tliblist tblds tliblist + if Sysdsn("'"tblds"("$tn$")'") = "OK" then return + end /* tliblist */ + tblds = "" + +return /*@ AB_FIND_LIBRARY */ +/* +. ----------------------------------------------------------------- */ +C_TABLE_OPS: /*@ */ + if branch then call BRANCH + address ISPEXEC + + call CA_OPEN_TBL /* -*/ + call CS_SPIN_TBL /* -*/ + call CZ_DROP_TBL /* -*/ + +return /*@ C_TABLE_OPS */ +/* +. ----------------------------------------------------------------- */ +CA_OPEN_TBL: /*@ */ + if branch then call BRANCH + address ISPEXEC + + "LIBDEF ISPTLIB DATASET ID('"tblds"') STACK" + "TBSTATS" $tn$ "STATUS1(s1) STATUS2(s2) ROWCURR(rowct)" + if s1 > 1 then do + say "Table" $tn$ "not available." + sw.0error_found = "1"; return + end; else, + if s2 = 1 then, /* not open */ + "TBOPEN " $tn$ "NOWRITE" + else "TBTOP" $tn$ + "LIBDEF ISPTLIB" + if sw.0error_found then return + "TBQUERY" $tn$ "KEYS(keylist)", + "NAMES(nmlist)" + parse var keylist "(" keylist ")" + parse var nmlist "(" nmlist ")" + namelist = keylist nmlist + + if sortseq <> "" then "TBSORT" $tn$ "FIELDS("sortseq")" + +return /*@ CA_OPEN_TBL */ +/* +. Given: contains all the defined names for this table. + The table has been TOPped. +. ----------------------------------------------------------------- */ +CS_SPIN_TBL: Procedure expose, /*@ hide everything */ + expose (tk_globalvars), /* except these */ + $tn$ namelist xefef tblds rows keylist nmlist maxlen + cs_tv = Trace() + if branch then call BRANCH + address ISPEXEC + + maxlen = 0 /* maximum line length */ + do forever + "TBSKIP" $tn$ "SAVENAME(xvars)" + if rc > 0 then leave /* we're done... */ + line = "" /* set empty */ + /* add blocks of "var .. varvalue .." */ + do cx = 1 to Words(namelist) + thiswd = Word(namelist,cx) + line = line thiswd xefef Value(thiswd) xefef + end /* cx */ + rc = Trace("O"); rc = Trace(cs_tv) + parse var xvars "(" xvars ")" + /* add a block of "XVARS .. xvarlist .." */ + line = line "XVARS" xefef xvars xefef + /* add blocks of "xvar .. xvarvalue .." */ + do cx = 1 to Words(xvars) + thiswd = Word(xvars,cx) + line = line thiswd xefef Value(thiswd) xefef + end /* cx */ + rc = Trace("O"); rc = Trace(cs_tv) + maxlen = Max(maxlen,Length(line)) + queue line + end /* forever */ + + lines_in_stack = queued() + line = "Contents of" $tn$ "in" tblds, + "("lines_in_stack" rows) KEYS("keylist") NAMES("nmlist")." + push line /* make it the first line */ + maxlen = Max(maxlen,Length(line)) + if monitor then say "Maximum line length is" maxlen + +return /*@ CS_SPIN_TBL */ +/* +. ----------------------------------------------------------------- */ +CZ_DROP_TBL: /*@ */ + if branch then call BRANCH + address ISPEXEC + + if s2 = 1 then, /* table was not open at start*/ + "TBEND" $tn$ + +return /*@ CZ_DROP_TBL */ +/* +. ----------------------------------------------------------------- */ +D_PUMP_TBL: /*@ */ + if branch then call BRANCH + address TSO + + if monitor then say, + "Writing text." + + maxlen = maxlen + 4 + bytes_to_add /* set LRECL */ + vbmax.0 = "NEW CATALOG UNIT(SYSDA) SPACE(1 5) TRACKS", + "RECFM(V B) LRECL("maxlen") BLKSIZE(0)" + vbmax.1 = "SHR" /* if it already exists... */ + + tempstat = Sysdsn(outdsn) = "OK" /* 1=exists, 0=missing */ + "ALLOC FI($TMP) DA("outdsn") REU" vbmax.tempstat + rcx = rc + "EXECIO" queued() "DISKW $TMP (FINIS" + rcx = max(rcx,rc) + "FREE FI($TMP)" + + if rcx = 0 & sw.0purge then do + address ISPEXEC + "LIBDEF ISPTLIB DATASET ID('"tblds"') STACK" + "TBERASE" $tn$ + if rc = 0 then say $tn$ "was deleted" + "LIBDEF ISPTLIB" + end + +return /*@ D_PUMP_TBL */ +/* +. ----------------------------------------------------------------- */ +LOCAL_PREINIT: /*@ customize opts */ + if branch then call BRANCH + address TSO + + +return /*@ LOCAL_PREINIT */ +/* +. ----------------------------------------------------------------- */ +HELP: /*@ */ +address TSO;"CLEAR" +if helpmsg <> "" then do ; say helpmsg; say ""; end +ex_nam = Left(exec_name,8) /* predictable size */ +say " "ex_nam" produces a flattened version of any ISPF table " +say " into a VB-form dataset of minimum necessary LRECL." +say " " +say " The field contents are written in KEYPHRS format " +say " (var .. varval ..) " +say " key-fields first, followed by name-fields, followed by the " +say " names of any extension variables key-phrased by 'XVARS', " +say " followed by the extension variables themselves in KEYPHRS " +say " format. " +say " " +say " The first record on the file identifies the table name, the " +say " source library, the number of rows processed, and the key- and " +say " name-fields. " +say " " +say " more.... " +pull +"CLEAR" +say " Syntax: "ex_nam" (Required)" +say " " +say " (Defaults)" +say " " +say " (Defaults)" +say " " +say " identifies the table to be dumped. " +say " " +say " identifies the ISPF Table library which holds ." +say " If is not specified, ISPTLIB will be " +say " searched to find the correct dataset. " +say " " +say " (default: FLATTBLS.) names the output file. " +say " will be created if it does not exist. " +say " " +say " causes the table to be sorted as indicated before " +say " being dumped. " +say " " +say " (default=0) causes the LRECL of the output dataset " +say " to be extended to enable updating. " +pull +"CLEAR" +say " Debugging tools provided include: " +say " " +say " MONITOR: displays key information throughout processing. " +say " Displays most paragraph names upon entry. " +say " " +say " NOUPDT: by-pass all update logic. " +say " " +say " BRANCH: show all paragraph entries. " +say " " +say " TRACE tv: will use value following TRACE to place the " +say " execution in REXX TRACE Mode. " +say " " +say " " +say " Debugging tools can be accessed in the following manner: " +say " " +say " TSO "ex_nam" parameters (( debug-options " +say " " +say " For example: " +say " " +say " TSO "ex_nam" vt2231 add 17 (( MONITOR TRACE ?R " +address ISPEXEC "CONTROL DISPLAY REFRESH" +exit /*@ HELP */ +/* REXXSKEL back-end removed for space */ diff --git a/test/src_dir/rhtml1.rhtml b/test/src_dir/rhtml1.rhtml new file mode 100644 index 0000000..52982f6 --- /dev/null +++ b/test/src_dir/rhtml1.rhtml @@ -0,0 +1,25 @@ + + + Ajax table manipulation attempt + <%= stylesheet_link_tag "style" %> + <%= javascript_include_tag :defaults %> + + + +
+ <%= @content_for_layout %> +
+ + <%= ruby code %>
+ + <%- multi + lines of code + # even inline comments! + "damn" # that's sweet + %> +
<%= ruby_code %>
+ + diff --git a/test/src_dir/ruby1.rb b/test/src_dir/ruby1.rb new file mode 100644 index 0000000..8ea7ab8 --- /dev/null +++ b/test/src_dir/ruby1.rb @@ -0,0 +1,22 @@ +require 'foo' + +#comment + #comment + #comment with "string" + +module Foo + class Bar #comment + def foo + "double_quoted string" + "embedded double_quote \"" + more_code = true + 'single_quoted string' + 'embedded single_quote\'' + more_code = true + "multiline dquote + more quote + # not a comment + " + end + end +end diff --git a/test/src_dir/sh1.sh b/test/src_dir/sh1.sh new file mode 100644 index 0000000..c016041 --- /dev/null +++ b/test/src_dir/sh1.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +ls -la +# comment +echo hello #comment diff --git a/test/src_dir/sql1.sql b/test/src_dir/sql1.sql new file mode 100644 index 0000000..fe300fe --- /dev/null +++ b/test/src_dir/sql1.sql @@ -0,0 +1,30 @@ +// ----------------------------------------------------------------------- +// Filename: minvalue.sql +// Purpose: Select the Nth lowest value from a table +// Date: 18-Apr-2001 +// Author: Deepak Rai, SSE, Satyam Computer Services Ltd. India +// ----------------------------------------------------------------------- + +select level, min('col_name') from my_table +where level = '&n' +connect by prior ('col_name') < 'col_name') +group by level; + +/* a block comment + -- finished here */ + +-- Example: +-- +-- Given a table called emp with the following columns: +-- id number +-- name varchar2(20) +-- sal number +-- +-- For the second lowest salary: +-- +-- select level, min(sal) from emp +-- where level=2 +-- connect by prior sal < sal +-- group by level +-- + diff --git a/test/src_dir/tcl1.tcl b/test/src_dir/tcl1.tcl new file mode 100644 index 0000000..445ad99 --- /dev/null +++ b/test/src_dir/tcl1.tcl @@ -0,0 +1,35 @@ +#!/usr/local/bin/tclsh + +# Dos2Unix +# Convert a file to Unix-style line endings +# If the file is a directory, then recursively +# convert all the files in the directory and below. +# +# Arguments +# f The name of a file or directory. +# +# Side Effects: +# Rewrites the file to have LF line-endings + +proc Dos2Unix {f} { + puts $f + if {[file isdirectory $f]} { + foreach g [glob [file join $f *]] { + Dos2Unix $g + } + } else { + set in [open $f] + set out [open $f.new w] + fconfigure $out -translation lf + puts -nonewline $out [read $in] + close $out + close $in + file rename -force $f.new $f + } +} + +# Process each command-line argument + +foreach f $argv { + Dos2Unix $f +} diff --git a/test/src_dir/vb1.vb b/test/src_dir/vb1.vb new file mode 100644 index 0000000..81c2bea --- /dev/null +++ b/test/src_dir/vb1.vb @@ -0,0 +1,16 @@ +class foo +' comment + +require File.dirname(__FILE__) + '/../test_helper' +include Lingo + +class ShellTest < LingoTest + def test_comment + p = Languages::Shell.parse(" #comment") + assert_equal({ 'shell' => { :comment => [" #comment"] } }, p.output_buffers) + end + + def test_comprehensive + verify_parse("sh1.sh") + end +end diff --git a/test/src_dir/vbs1.vbs b/test/src_dir/vbs1.vbs new file mode 100644 index 0000000..ec35b06 --- /dev/null +++ b/test/src_dir/vbs1.vbs @@ -0,0 +1,14 @@ + +require File.dirname(__FILE__) + '/../test_helper' +include Lingo + +class ShellTest < LingoTest + def test_comment + p = Languages::Shell.parse(" #comment") + assert_equal({ 'shell' => { :comment => [" #comment"] } }, p.output_buffers) + end + + def test_comprehensive + verify_parse("sh1.sh") + end +end diff --git a/test/src_dir/xml1.xml b/test/src_dir/xml1.xml new file mode 100644 index 0000000..c1c56cd --- /dev/null +++ b/test/src_dir/xml1.xml @@ -0,0 +1,14 @@ + + + + ]]> + + + + + + diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 0000000..b70699c --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,102 @@ +require 'test/unit' +require 'fileutils' +require 'find' + +TEST_DIR = File.dirname(__FILE__) +require TEST_DIR + '/../lib/ohcount' + +class LingoTest < Test::Unit::TestCase + + # For reasons unknown, the base class defines a default_test method to throw a failure. + # We override it with a no-op to prevent this 'helpful' feature. + def default_test + end + + def src_dir + TEST_DIR + "/src_dir" + end + + def scratch_dir + TEST_DIR + "/scratch_dir" + end + + def expected_dir + TEST_DIR + "/expected_dir" + end + + def verify_parse(src_filename, filenames = []) + # re-make the output directory + Dir.mkdir scratch_dir unless File.exists? scratch_dir + output_dir = scratch_dir + "/#{ File.basename(src_filename) }" + FileUtils.rm_r(output_dir) if FileTest.directory?(output_dir) + Dir.mkdir output_dir + + complete_src_filename = src_dir + "/#{ src_filename }" + sfc = Ohcount::SimpleFileContext.new(complete_src_filename, filenames) + polyglot = Ohcount::Detector.detect(sfc) + + # parse + buffer = File.new(complete_src_filename).read + Ohcount::Parser.parse_to_dir(:dir => output_dir, + :buffer => buffer, + :polyglot => polyglot) + + # now compare + answer_dir = expected_dir + "/#{ File.basename(src_filename) }" + compare_dir(answer_dir, output_dir) + + # just to be sure, lets compare the total number of lines from the source file and the processed breakdown + compare_line_count(complete_src_filename, output_dir) + end + + + def compare_dir(expected, actual) + # make sure entries are identical + expected_entries = expected.entries.collect { |e| e[expected.size..-1] } + actual_entries = actual.entries.collect { |a| a[actual.size..-1] } + assert_equal expected_entries, actual_entries + + Dir.foreach(expected) do |entry| + next if [".", "..", ".svn"].include?(entry) + case File.ftype(expected+ "/" + entry) + when 'file' + File.open(expected + "/" + entry) do |e| + File.open(actual + "/" + entry) do |a| + assert_equal e.read, a.read, "file #{actual + "/" + entry} differs from expected" + end + end + when 'directory' + compare_dir(expected + "/" + entry, actual + "/" + entry) + else + assert false, "weird ftype" + end + end + end + + + def compare_line_count(src_file, scratch_dir) + code_lines = comment_lines = blanks = 0 + + Find.find(scratch_dir) do |path| + if FileTest.file?(path) + `wc -l #{ path }` =~ /^\s*(\d*)\b/ + case File.basename(path) + when 'code' + code_lines += $1.to_i + when 'comment' + comment_lines += $1.to_i + when 'blanks' + blanks += File.new(path).read.to_i + end + end + end + + # src file lines + `wc -l #{ src_file }` =~ /^\s*(\d*)\b/ + src_file_lines = $1.to_i + + # compare + assert_equal src_file_lines, (code_lines + comment_lines + blanks), "wc -l of output (code, comment, blanks) doesn't match the 'wc -l' of original" + end +end + diff --git a/test/unit/ada_test.rb b/test/unit/ada_test.rb new file mode 100644 index 0000000..221053c --- /dev/null +++ b/test/unit/ada_test.rb @@ -0,0 +1,16 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class AdaTest < LingoTest + def test_comment + lb = [Ohcount::LanguageBreakdown.new("ada", "", "--comment", 0)] + assert_equal lb, Ohcount::parse(" --comment", "ada") + end + + def test_comprehensive + verify_parse("ada1.ada") + end + + def test_comprehensive_adb + verify_parse("ada1.adb") + end +end diff --git a/test/unit/assembler_test.rb b/test/unit/assembler_test.rb new file mode 100644 index 0000000..ea9796e --- /dev/null +++ b/test/unit/assembler_test.rb @@ -0,0 +1,16 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class AssemblerTest < LingoTest + def test_comment + lb = [Ohcount::LanguageBreakdown.new("assembler", "", "!comment\n;comment", 0)] + assert_equal lb, Ohcount::parse(" !comment\n ;comment", "assembler") + end + + def test_comprehensive + verify_parse("assembler1.asm") + end + + def test_comprehensive_2 + verify_parse("assembler2.S") + end +end diff --git a/test/unit/awk_test.rb b/test/unit/awk_test.rb new file mode 100644 index 0000000..3a11b46 --- /dev/null +++ b/test/unit/awk_test.rb @@ -0,0 +1,18 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class AwkTest < LingoTest + def test_comment + lb = [Ohcount::LanguageBreakdown.new("awk", "", "#comment", 0)] + assert_equal lb, Ohcount::parse(" #comment", "awk") + end + + def test_double_slash + lb = [Ohcount::LanguageBreakdown.new("awk", "\"\\\\\"\n", "#comment", 0)] + # awk doesn't recognize backslash escaping of double quote...weird + assert_equal lb, Ohcount::parse("\"\\\\\"\n#comment", "awk") + end + + def test_comprehensive + verify_parse("awk1.awk") + end +end diff --git a/test/unit/bat_test.rb b/test/unit/bat_test.rb new file mode 100644 index 0000000..4c992c9 --- /dev/null +++ b/test/unit/bat_test.rb @@ -0,0 +1,12 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class BatTest < LingoTest + def test_comment + lb = [Ohcount::LanguageBreakdown.new("bat", "", "REM comment", 0)] + assert_equal lb, Ohcount::parse(" REM comment", "bat") + end + + def test_comprehensive + verify_parse("bat1.bat") + end +end diff --git a/test/unit/boo_test.rb b/test/unit/boo_test.rb new file mode 100644 index 0000000..250f21f --- /dev/null +++ b/test/unit/boo_test.rb @@ -0,0 +1,17 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class BooTest < LingoTest + def test_comment + lb = [Ohcount::LanguageBreakdown.new("boo", "", "#comment", 0)] + assert_equal lb, Ohcount::parse(" #comment", "boo") + end + + def test_strings + lb = [Ohcount::LanguageBreakdown.new("boo", "'''abc\n#not a 'comment\n'''", "", 0)] + assert_equal lb, Ohcount::parse("'''abc\n#not a 'comment\n'''", "boo") + end + + def test_comprehensive + verify_parse("boo1.boo") + end +end diff --git a/test/unit/c_test.rb b/test/unit/c_test.rb new file mode 100644 index 0000000..37a6b28 --- /dev/null +++ b/test/unit/c_test.rb @@ -0,0 +1,25 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class CTest < LingoTest + + def test_comments + lb = [Ohcount::LanguageBreakdown.new("cncpp", "", "//comment", 0)] + assert_equal lb, Ohcount::parse(" //comment", "cncpp") + end + + def test_empty_comments + lb = [Ohcount::LanguageBreakdown.new("cncpp", "","//\n", 0)] + assert_equal lb, Ohcount::parse(" //\n", "cncpp") + end + + + def test_block_comment + lb = [Ohcount::LanguageBreakdown.new("cncpp", "","/*c*/", 0)] + assert_equal lb, Ohcount::parse("/*c*/", "cncpp") + end + + def test_comprehensive + verify_parse("c1.c") + end + +end diff --git a/test/unit/clearsilver_template_test.rb b/test/unit/clearsilver_template_test.rb new file mode 100644 index 0000000..bd0a13d --- /dev/null +++ b/test/unit/clearsilver_template_test.rb @@ -0,0 +1,14 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class ClearsilverTemplateTest < LingoTest + + def test_comment + html_lb = Ohcount::LanguageBreakdown.new("html", "", "", 0) + clearsilver_template_lb = Ohcount::LanguageBreakdown.new("clearsilver", "", "#comment\n", 0) + assert_equal [html_lb, clearsilver_template_lb], Ohcount::parse("", "clearsilver_template") + end + + def test_comprehensive + verify_parse("clearsilver_template1.cs") + end +end diff --git a/test/unit/clearsilver_test.rb b/test/unit/clearsilver_test.rb new file mode 100644 index 0000000..f2fa994 --- /dev/null +++ b/test/unit/clearsilver_test.rb @@ -0,0 +1,10 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class ClearsilverTest < LingoTest + + def test_comment + lb = [Ohcount::LanguageBreakdown.new("clearsilver", "", "#comment", 0)] + assert_equal lb, Ohcount::parse(" #comment", "clearsilver") + end + +end diff --git a/test/unit/csharp_test.rb b/test/unit/csharp_test.rb new file mode 100644 index 0000000..6987b4e --- /dev/null +++ b/test/unit/csharp_test.rb @@ -0,0 +1,13 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class CSharpTest < LingoTest + + def test_comment + lb = [Ohcount::LanguageBreakdown.new("csharp", "", "//comment", 0)] + assert_equal lb, Ohcount::parse(" //comment", "csharp") + end + + def test_comprehensive + verify_parse("cs1.cs") + end +end diff --git a/test/unit/css_test.rb b/test/unit/css_test.rb new file mode 100644 index 0000000..eb02957 --- /dev/null +++ b/test/unit/css_test.rb @@ -0,0 +1,12 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class CssTest < LingoTest + def test_comment + lb = [Ohcount::LanguageBreakdown.new("css", "", "/*comment*/", 0)] + assert_equal lb, Ohcount::parse(" /*comment*/", "css") + end + + def test_comprehensive + verify_parse("css1.css") + end +end diff --git a/test/unit/d_test.rb b/test/unit/d_test.rb new file mode 100644 index 0000000..553fa6b --- /dev/null +++ b/test/unit/d_test.rb @@ -0,0 +1,37 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class CTest < LingoTest + + def test_comments + lb = [Ohcount::LanguageBreakdown.new("dmd", "", "//comment", 0)] + assert_equal lb, Ohcount::parse(" //comment", "dmd") + end + + def test_empty_comments + lb = [Ohcount::LanguageBreakdown.new("dmd", "","//\n", 0)] + assert_equal lb, Ohcount::parse(" //\n", "dmd") + end + + def test_strings + lb = [Ohcount::LanguageBreakdown.new("dmd", "'/*' not a comment '*/'", "", 0)] + assert_equal lb, Ohcount::parse("'/*' not a comment '*/'", "dmd") + end + + def test_block_comment + lb = [Ohcount::LanguageBreakdown.new("dmd", "","/*d*/", 0)] + assert_equal lb, Ohcount::parse("/*d*/", "dmd") + + lb = [Ohcount::LanguageBreakdown.new("dmd", "","/+d+/", 0)] + assert_equal lb, Ohcount::parse("/+d+/", "dmd") + end + + def test_nested_block_comment + lb = [Ohcount::LanguageBreakdown.new("dmd", "","/+ /*d*/ not_code(); +/", 0)] + assert_equal lb, Ohcount::parse("/+ /*d*/ not_code(); +/", "dmd") + end + + def test_comprehensive + verify_parse("d1.d") + end + +end diff --git a/test/unit/detector_test.rb b/test/unit/detector_test.rb new file mode 100644 index 0000000..2452f8a --- /dev/null +++ b/test/unit/detector_test.rb @@ -0,0 +1,50 @@ +require File.dirname(__FILE__) + '/../test_helper' +include Ohcount + + +class DetectorTest < LingoTest + + + def do_detect(filename, filenames = []) + file_location = File.dirname(__FILE__) + "/../detect_files/" + filename + sfc = Ohcount::SimpleFileContext.new(filename, filenames, nil, file_location) + Ohcount::Detector.detect(sfc) + end + + def test_matlab_or_objective_c + assert_equal 'objective_c', do_detect("t1.m") + assert_equal 'objective_c', do_detect("t2.m") + end + + def test_detect_polyglot + assert_equal "cncpp", do_detect("foo.c") + assert_equal "ruby", do_detect("foo.rb") + assert_equal "matlab", do_detect("foo_matlab.m", ["foo_matlab.m", "bar.m", "README"]) + assert_equal "objective_c", do_detect("foo_objective_c.m", ["foo_objective_c.m", "bar.h", "README"]) + assert_equal "objective_c", do_detect("foo_objective_c.h", ["foo_objective_c.h, different_than_foo.m"]) + assert_equal "php", do_detect("upper_case_php") + assert_equal "lisp", do_detect("core.lisp") + assert_equal "dmd", do_detect("foo.d") + end + + def test_upper_case_extensions + assert_equal "cncpp", do_detect("foo_upper_case.C") + assert_equal "ruby", do_detect("foo_upper_case.RB") + end + + def test_no_extensions + assert_equal "python", do_detect("py_script", []) + assert_equal "ruby", do_detect("ruby_script", []) + assert_equal "shell", do_detect("bourne_again_script", []) + assert_equal "shell", do_detect("findup", []) + assert_equal "perl", do_detect("renrot", []) + assert_equal "dmd", do_detect("d_script", []) + end + + def test_csharp_or_clearsilver + assert_equal 'csharp', do_detect("cs1.cs") + assert_equal 'clearsilver_template', do_detect("clearsilver_template1.cs") + end + +end + diff --git a/test/unit/diff_test.rb b/test/unit/diff_test.rb new file mode 100644 index 0000000..f4593af --- /dev/null +++ b/test/unit/diff_test.rb @@ -0,0 +1,43 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class DiffTest < LingoTest + + def test_one + src_dir = File.dirname(__FILE__) + '/../src_dir/' + sloc_infos = Ohcount.diff_files(src_dir + 'diff1_old.html', src_dir + 'diff1_new.html') + + css = Ohcount::SlocInfo.new('css') + css.code_added = 1 + css.comments_added = 1 + + html = Ohcount::SlocInfo.new('html') + html.code_added, html.code_removed = [1,1] + + js = Ohcount::SlocInfo.new('javascript') + js.code_removed = 1 + js.comments_removed = 1 + + assert_equal [css, html, js], sloc_infos + end + + def test_two + src_dir = File.dirname(__FILE__) + '/../src_dir/' + sloc_infos = Ohcount.diff_files(src_dir + 'diff2_old.c', src_dir + 'diff2_new.c') + + c = Ohcount::SlocInfo.new('cncpp') + c.code_added, c.code_removed = [1,1] + c.comments_added, c.comments_removed = [1,1] + + assert_equal [c], sloc_infos + end + + def test_three + src_dir = File.dirname(__FILE__) + '/../src_dir/' + sloc_infos = Ohcount.diff_files(src_dir + 'diff3_old.xml', src_dir + 'diff3_new.xml') + + xml = Ohcount::SlocInfo.new('xml') + xml.code_added, xml.code_removed = [1,1] + + assert_equal [xml], sloc_infos + end +end diff --git a/test/unit/dylan_test.rb b/test/unit/dylan_test.rb new file mode 100644 index 0000000..534957d --- /dev/null +++ b/test/unit/dylan_test.rb @@ -0,0 +1,13 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class DylanTest < LingoTest + + def test_comment + lb = [Ohcount::LanguageBreakdown.new("dylan", "", "//comment", 0)] + assert_equal lb, Ohcount::parse(" //comment", "dylan") + end + + def test_comprehensive + verify_parse("dylan1.dylan") + end +end diff --git a/test/unit/emacs_lisp.rb b/test/unit/emacs_lisp.rb new file mode 100644 index 0000000..13d67b0 --- /dev/null +++ b/test/unit/emacs_lisp.rb @@ -0,0 +1,15 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class EmacsLispTest < LingoTest + + def test_comment + lb = [Ohcount::LanguageBreakdown.new("emacslisp", "", ";;comment", 0)] + assert_equal lb, Ohcount::parse(" ;;comment", "emacslisp") + end + + def test_comprehensive + verify_parse("el1.el") + end +end + + diff --git a/test/unit/erlang_test.rb b/test/unit/erlang_test.rb new file mode 100644 index 0000000..34184f7 --- /dev/null +++ b/test/unit/erlang_test.rb @@ -0,0 +1,13 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class ErlangTest < LingoTest + + def test_comment + lb = [Ohcount::LanguageBreakdown.new("erlang", "", "%%comment", 0)] + assert_equal lb, Ohcount::parse(" %%comment", "erlang") + end + + def test_comprehensive + verify_parse("erl1.erl") + end +end diff --git a/test/unit/groovy_test.rb b/test/unit/groovy_test.rb new file mode 100644 index 0000000..54eb6b6 --- /dev/null +++ b/test/unit/groovy_test.rb @@ -0,0 +1,13 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class GroovyTest < LingoTest + def test_comments + lb = [Ohcount::LanguageBreakdown.new("groovy", "", "//comment", 0)] + assert_equal lb, Ohcount::parse(" //comment", "groovy") + end + + def test_comprehensive + verify_parse("groovy1.groovy") + end + +end diff --git a/test/unit/html_test.rb b/test/unit/html_test.rb new file mode 100644 index 0000000..139b876 --- /dev/null +++ b/test/unit/html_test.rb @@ -0,0 +1,25 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class HtmlTest < LingoTest + + + def test_css +# html = " " +# html_lb = Ohcount::LanguageBreakdown.new("html", " ", "", 0) +# css_lb = Ohcount::LanguageBreakdown.new("css", "p {\n color: #444\n} \n", "", 0) +# parsed_lb = Ohcount::parse(html, "html") +# assert_equal 2, parsed_lb.size +# assert_equal html_lb, parsed_lb[0] +# assert_equal css_lb, parsed_lb[1] + end + + + def test_comment +# lb = [Ohcount::LanguageBreakdown.new("html", "", " ", 0)] +# assert_equal lb, Ohcount::parse(" ", "html") + end + + def test_comprehensive + verify_parse("html1.html") + end +end diff --git a/test/unit/java_test.rb b/test/unit/java_test.rb new file mode 100644 index 0000000..2ec2485 --- /dev/null +++ b/test/unit/java_test.rb @@ -0,0 +1,16 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class JavaTest < LingoTest + def test_comments + lb = [Ohcount::LanguageBreakdown.new("java", "", "//comment", 0)] + assert_equal lb, Ohcount::parse(" //comment", "java") + end + + def test_comprehensive + verify_parse("java1.java") + end + + def test_comprehensive_with_carriage_returns + verify_parse("java2.java") + end +end diff --git a/test/unit/javascript_test.rb b/test/unit/javascript_test.rb new file mode 100644 index 0000000..4e98b3f --- /dev/null +++ b/test/unit/javascript_test.rb @@ -0,0 +1,16 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class JavascriptTest < LingoTest + def test_comments + lb = [Ohcount::LanguageBreakdown.new("javascript", "", "//comment", 0)] + assert_equal lb, Ohcount::parse(" //comment", "javascript") + end + + def test_comprehensive + verify_parse("js1.js") + end + + def test_comp2 + verify_parse("js2.js") + end +end diff --git a/test/unit/jsp_test.rb b/test/unit/jsp_test.rb new file mode 100644 index 0000000..99e2c4c --- /dev/null +++ b/test/unit/jsp_test.rb @@ -0,0 +1,19 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class JspTest < LingoTest + def test_comment +# html_lb = Ohcount::LanguageBreakdown.new("html", "<%\n%>", "", 0) +# java_lb = Ohcount::LanguageBreakdown.new("java", "", " //comment\n", 0) +# assert_equal [html_lb, java_lb], Ohcount::parse("<%\n //comment\n%>", "jsp") + end + + def test_comment2 + html_lb = Ohcount::LanguageBreakdown.new("html", "%>", "", 0) + java_lb = Ohcount::LanguageBreakdown.new("java", "", "<% //comment\n", 0) + assert_equal [java_lb, html_lb], Ohcount::parse(" <% //comment\n%>", "jsp") + end + + def test_comprehensive + verify_parse("jsp1.jsp") + end +end diff --git a/test/unit/lisp_test.rb b/test/unit/lisp_test.rb new file mode 100644 index 0000000..4714b50 --- /dev/null +++ b/test/unit/lisp_test.rb @@ -0,0 +1,13 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class LispTest < LingoTest + + def test_comment + lb = [Ohcount::LanguageBreakdown.new("lisp", "", ";;; comment", 0)] + assert_equal lb, Ohcount::parse(" ;;; comment", "lisp") + end + + def test_comprehensive + verify_parse("lsp1.lsp") + end +end diff --git a/test/unit/lua_test.rb b/test/unit/lua_test.rb new file mode 100644 index 0000000..c78e477 --- /dev/null +++ b/test/unit/lua_test.rb @@ -0,0 +1,13 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class LuaTest < LingoTest + + def test_comment + lb = [Ohcount::LanguageBreakdown.new("lua", "", "-- comment", 0)] + assert_equal lb, Ohcount::parse(" -- comment", "lua") + end + + def test_comprehensive + verify_parse("lua1.lua") + end +end diff --git a/test/unit/matlab_test.rb b/test/unit/matlab_test.rb new file mode 100644 index 0000000..c41e858 --- /dev/null +++ b/test/unit/matlab_test.rb @@ -0,0 +1,34 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class MatlabTest < LingoTest + + def test_line_comment_1 + lb = [Ohcount::LanguageBreakdown.new("matlab", "", "%comment", 0)] + assert_equal lb, Ohcount::parse(" %comment", "matlab") + end + + def test_line_comment_2 + lb = [Ohcount::LanguageBreakdown.new("matlab", "", "%comment", 0)] + assert_equal lb, Ohcount::parse("%comment", "matlab") + end + + def test_octave_syntax_comment + lb = [Ohcount::LanguageBreakdown.new("matlab", "", "#comment", 0)] + assert_equal lb, Ohcount::parse(" #comment", "matlab") + end + + # matlab is slightly weird in that '%' starts a line comment + # while '{%' starts a block comment. To make sure we aren't + # misinterpreting '{%' as a line comment, the following test + # adds code after a single-line block comment. If it interprets the + # {% as a line comment (ie: just %) then it will ignore everything else + # after and attribute the line as comment + def test_false_line_comment + lb = [Ohcount::LanguageBreakdown.new("matlab", "{%block%} code", "", 0)] + assert_equal lb, Ohcount::parse(" {%block%} code", "matlab") + end + + def test_comprehensive + verify_parse("matlab1.m", 'matlab') + end +end diff --git a/test/unit/pascal_test.rb b/test/unit/pascal_test.rb new file mode 100644 index 0000000..74fec3a --- /dev/null +++ b/test/unit/pascal_test.rb @@ -0,0 +1,13 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class PascalTest < LingoTest + def test_comment + lb = [Ohcount::LanguageBreakdown.new("pascal", "", "//comment", 0)] + assert_equal lb, Ohcount::parse(" //comment", "pascal") + end + + def test_comprehensive + verify_parse("pascal1.pas") + verify_parse("pascal2.pp") + end +end diff --git a/test/unit/perl_test.rb b/test/unit/perl_test.rb new file mode 100644 index 0000000..fdb96d9 --- /dev/null +++ b/test/unit/perl_test.rb @@ -0,0 +1,16 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class PerlTest < LingoTest + def test_comments + lb = [Ohcount::LanguageBreakdown.new("perl", "", "#comment", 0)] + assert_equal lb, Ohcount::parse(" #comment", "perl") + end + + def test_perl_in_cgi + verify_parse("perl.cgi") + end + + def test_comprehensive + verify_parse("perl1.pl") + end +end diff --git a/test/unit/php_test.rb b/test/unit/php_test.rb new file mode 100644 index 0000000..ff18044 --- /dev/null +++ b/test/unit/php_test.rb @@ -0,0 +1,12 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class PhpTest < LingoTest + def test_comment + lb = [Ohcount::LanguageBreakdown.new("php", "", "//comment\n", 0)] + assert_equal lb, Ohcount::parse("", "php") + end + + def test_comprehensive + verify_parse("php1.php") + end +end diff --git a/test/unit/python_test.rb b/test/unit/python_test.rb new file mode 100644 index 0000000..31c4052 --- /dev/null +++ b/test/unit/python_test.rb @@ -0,0 +1,17 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class PythonTest < LingoTest + def test_comment + lb = [Ohcount::LanguageBreakdown.new("python", "", "#comment", 0)] + assert_equal lb, Ohcount::parse(" #comment", "python") + end + + def test_strings + lb = [Ohcount::LanguageBreakdown.new("python", "'''abc\n#not a 'comment\n'''", "", 0)] + assert_equal lb, Ohcount::parse("'''abc\n#not a 'comment\n'''", "python") + end + + def test_comprehensive + verify_parse("py1.py") + end +end diff --git a/test/unit/rexx_test.rb b/test/unit/rexx_test.rb new file mode 100644 index 0000000..1f98ef7 --- /dev/null +++ b/test/unit/rexx_test.rb @@ -0,0 +1,13 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class RexxTest < LingoTest + + def test_comment + lb = [Ohcount::LanguageBreakdown.new("rexx", "", "/*comment*/", 0)] + assert_equal lb, Ohcount::parse(" /*comment*/", "rexx") + end + + def test_comprehensive + verify_parse("rexx1.rex") + end +end diff --git a/test/unit/rhtml_test.rb b/test/unit/rhtml_test.rb new file mode 100644 index 0000000..1ed6522 --- /dev/null +++ b/test/unit/rhtml_test.rb @@ -0,0 +1,14 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class RhtmlTest < LingoTest + + def test_comment + html_lb = Ohcount::LanguageBreakdown.new("html", "<%\n%>", "", 0) + ruby_lb = Ohcount::LanguageBreakdown.new("ruby", "", "#comment\n", 0) + assert_equal [html_lb, ruby_lb], Ohcount::parse("<%\n #comment\n%>", "rhtml") + end + + def test_comprehensive + verify_parse("rhtml1.rhtml") + end +end diff --git a/test/unit/ruby_test.rb b/test/unit/ruby_test.rb new file mode 100644 index 0000000..6cd72af --- /dev/null +++ b/test/unit/ruby_test.rb @@ -0,0 +1,13 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class RubyTest < LingoTest + + def test_comment + lb = [Ohcount::LanguageBreakdown.new("ruby", "", "#comment", 0)] + assert_equal lb, Ohcount::parse(" #comment", "ruby") + end + + def test_comprehensive + verify_parse("ruby1.rb") + end +end diff --git a/test/unit/shell_test.rb b/test/unit/shell_test.rb new file mode 100644 index 0000000..32e17f6 --- /dev/null +++ b/test/unit/shell_test.rb @@ -0,0 +1,12 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class ShellTest < LingoTest + def test_comment + lb = [Ohcount::LanguageBreakdown.new("shell", "", "#comment", 0)] + assert_equal lb, Ohcount::parse(" #comment", "shell") + end + + def test_comprehensive + verify_parse("sh1.sh") + end +end diff --git a/test/unit/sql_test.rb b/test/unit/sql_test.rb new file mode 100644 index 0000000..4e8a5e3 --- /dev/null +++ b/test/unit/sql_test.rb @@ -0,0 +1,24 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class CTest < LingoTest + + def test_comments + lb = [Ohcount::LanguageBreakdown.new("sql", "", "--comment", 0)] + assert_equal lb, Ohcount::parse(" --comment", "sql") + end + + def test_empty_comments + lb = [Ohcount::LanguageBreakdown.new("sql", "","--\n", 0)] + assert_equal lb, Ohcount::parse(" --\n", "sql") + end + + def test_block_comment + lb = [Ohcount::LanguageBreakdown.new("sql", "","{sql}", 0)] + assert_equal lb, Ohcount::parse(" {sql}", "sql") + end + + def test_comprehensive + verify_parse("sql1.sql") + end + +end diff --git a/test/unit/tcl_test.rb b/test/unit/tcl_test.rb new file mode 100644 index 0000000..4c5aa1a --- /dev/null +++ b/test/unit/tcl_test.rb @@ -0,0 +1,12 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class TclTest < LingoTest + def test_comment + lb = [Ohcount::LanguageBreakdown.new("tcl", "", "#comment", 0)] + assert_equal lb, Ohcount::parse(" #comment", "tcl") + end + + def test_comprehensive + verify_parse("tcl1.tcl") + end +end diff --git a/test/unit/visual_basic_test.rb b/test/unit/visual_basic_test.rb new file mode 100644 index 0000000..cac466e --- /dev/null +++ b/test/unit/visual_basic_test.rb @@ -0,0 +1,12 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class VisualBasicTest < LingoTest + def test_comments + lb = [Ohcount::LanguageBreakdown.new("visualbasic", "", "'comment", 0)] + assert_equal lb, Ohcount::parse(" 'comment", "visualbasic") + end + + def test_comprehensive + verify_parse("frx1.frx") + end +end diff --git a/test/unit/xml_test.rb b/test/unit/xml_test.rb new file mode 100644 index 0000000..9448094 --- /dev/null +++ b/test/unit/xml_test.rb @@ -0,0 +1,12 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class XmlTest < LingoTest + def test_comment + lb = [Ohcount::LanguageBreakdown.new("xml", "", "", 0)] + assert_equal lb, Ohcount::parse(" ", "xml") + end + + def test_comprehensive + verify_parse("xml1.xml") + end +end -- 2.32.0.93.g670b81a890