diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8d60fe3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +pkg +lib/i[3-9]86* +lib/x86* +*.swp +tags +.DS_Store +src/hash/*_hash.h +src/hash/language_hash.c +src/parsers/*.h +src/parser.o +test/unit/run_tests +bin/ +ruby/ohcount.so +ruby/ohcount_wrap.c +test/unit/run_tests.dSYM/ diff --git a/.pc/.quilt_patches b/.pc/.quilt_patches new file mode 100644 index 0000000..6857a8d --- /dev/null +++ b/.pc/.quilt_patches @@ -0,0 +1 @@ +debian/patches diff --git a/.pc/.quilt_series b/.pc/.quilt_series new file mode 100644 index 0000000..c206706 --- /dev/null +++ b/.pc/.quilt_series @@ -0,0 +1 @@ +series diff --git a/.pc/.version b/.pc/.version new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/.pc/.version @@ -0,0 +1 @@ +2 diff --git a/.pc/applied-patches b/.pc/applied-patches new file mode 100644 index 0000000..8ad8876 --- /dev/null +++ b/.pc/applied-patches @@ -0,0 +1,5 @@ +fix_null_dereference_2.patch +fix_null_dereference.patch +txx_support.patch +disabled_test_suite.patch +rbconfig.patch diff --git a/.pc/disabled_test_suite.patch/build b/.pc/disabled_test_suite.patch/build new file mode 100755 index 0000000..ad71874 --- /dev/null +++ b/.pc/disabled_test_suite.patch/build @@ -0,0 +1,162 @@ +#!/usr/bin/env bash +# Build script for Ohcount. +# Written by Mitchell Foral. mitchellcaladbolg.net. + +# Options +# Change these for your system configuration. +if [ `uname` != "Darwin" ] +then + # Linux + INC_DIR= + LIB_DIR= + + if [ `uname` == "FreeBSD" ] + then + INC_DIR=/usr/local/include + LIB_DIR=/usr/local/lib + fi + + # You shouldn't have to change the following. + CFLAGS=-O3 + CFLAGS="$CFLAGS -DTMP_FILES_ARE_DT_UNKNOWN" # workaround bug on centos/SF servers + WARN="-Wall -Wno-pointer-to-int-cast -Wno-parentheses" + SHARED=-shared + SHARED_NAME=libohcount.so + RB_SHARED=-shared + RB_SHARED_NAME=ohcount.so +else + # Mac OSX + INC_DIR=/opt/local/include + LIB_DIR=/opt/local/lib + # You shouldn't have to change the following. + CFLAGS="-fno-common -g" + WARN="-Wall -Wno-parentheses" + SHARED="-dynamiclib -L$LIB_DIR -lpcre" + SHARED_NAME=libohcount.dylib + RB_SHARED="-dynamic -bundle -lruby" + RB_SHARED_NAME=ohcount.bundle +fi + +# C compiler and flags +cc="gcc -fPIC -g $CFLAGS $WARN -I$INC_DIR -L$LIB_DIR" + +# Ohcount source files +files="src/sourcefile.c \ + src/detector.c \ + src/licenses.c \ + src/parser.o \ + src/loc.c \ + src/log.c \ + src/diff.c \ + src/parsed_language.c \ + src/hash/language_hash.c" + +# If any src/hash/*.gperf file is newer than the header files (which were +# presumably generated together), regenerate the headers. +build_hash_headers() +{ + if [[ -z `ls src/hash/ | grep "_hash.h$"` || + ! -z `find src/hash/*.gperf -newer src/hash/parser_hash.h` ]] + then + echo "Generating hash headers" + sh -c "cd src/hash/ && ./generate_headers" || exit 1 + fi +} + +# If src/parser.o does not exist, or if there are Ragel parsers or parser +# header files newer than the existing parser.o, recompile parser.o. +build_parser_o() +{ + if [[ ! -f src/parser.o || + ! -z `find src/parsers/*.{h,rl} -newer src/parser.o` ]] + then + bash -c "cd src/parsers/ && bash ./compile" || exit 1 + echo "Building src/parser.c (will take a while)" + bash -c "$cc -c src/parser.c -o src/parser.o" || exit 1 + fi +} + +build_shared() +{ + build_hash_headers + build_parser_o + if [[ ! -f src/$SHARED_NAME || + ! -z `find src/*.{h,c} -newer src/$SHARED_NAME` ]] + then + echo "Building shared library" + sh -c "$cc $SHARED $files -o src/$SHARED_NAME" || exit 1 + fi +} + +build_ohcount() +{ + build_hash_headers + build_parser_o + echo "Building Ohcount" + mkdir -p bin/ + sh -c "$cc src/ohcount.c $files -o bin/ohcount -lpcre" || exit 1 +} + +build_test_suite() +{ + build_hash_headers + build_parser_o + echo "Building test suite" + sh -c "$cc test/unit/all_tests.c $files -o test/unit/run_tests -lpcre" \ + || exit 1 +} + +run_test_suite() +{ + echo "Running test suite" + sh -c "cd test/unit/ && ./run_tests" +} + +build_ruby_bindings() +{ + arch=`ruby -rmkmf -e 'print Config::expand(CONFIG["arch"])'` + echo "Generating Ruby bindings for $arch" + sh -c "swig -ruby -o ruby/ohcount_wrap.c ruby/ohcount.i" || exit 1 + mkdir -p ruby/$arch + sh -c "$cc $RB_SHARED ruby/ohcount_wrap.c $files -o ruby/$arch/$RB_SHARED_NAME \ + -I`ruby -rmkmf -e 'print Config::expand(CONFIG["archdir"])'` \ + -lpcre" || exit 1 + sh -c "cd test/unit/ruby && ruby ruby_test.rb" || exit 1 +} + +if [ $# -eq 0 ] || [ $1 == "all" ] +then + build_ohcount + build_test_suite + run_test_suite + echo $success +elif [ $1 == "shared" ] +then + build_shared + echo "Build successful; $SHARED_NAME is in src/" +elif [ $1 == "ohcount" ] +then + build_ohcount + echo "Build successful; ohcount is in bin/" +elif [ $1 == "tests" ] +then + build_test_suite + run_test_suite +elif [ $1 == "ruby" ] +then + build_ruby_bindings + echo "Build successful; $RB_SHARED_NAME is in ruby/$arch" +elif [ $1 == "clean" ] +then + rm -f bin/ohcount + rm -f test/unit/run_tests + rm -f src/parser.o + rm -f src/parsers/*.h + rm -f src/hash/*.h + rm -f src/hash/*.c + rm -f src/$SHARED_NAME + rm -f ruby/$RB_SHARED_NAME + rm -rf ruby/`ruby -rmkmf -e 'print Config::expand(CONFIG["arch"])'`/* +else + echo "Usage: build [all|ohcount|shared|tests|ruby|clean]" +fi diff --git a/.pc/fix_null_dereference.patch/src/detector.c b/.pc/fix_null_dereference.patch/src/detector.c new file mode 100644 index 0000000..5107c61 --- /dev/null +++ b/.pc/fix_null_dereference.patch/src/detector.c @@ -0,0 +1,693 @@ +// detector.c written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#include +#include +#include +#include +#include + +#include "detector.h" +#include "languages.h" +#include "log.h" + +#include "hash/cppheader_hash.h" +#include "hash/disambiguatefunc_hash.h" +#include "hash/extension_hash.h" +#include "hash/filename_hash.h" + +#define ISBINARY(x) (x[0] == '\1') +#define ISAMBIGUOUS(x) (x[0] == '\2') +#define DISAMBIGUATEWHAT(x) &x[1] + +const char *ohcount_detect_language(SourceFile *sourcefile) { + const char *language = NULL; + char *p, *pe; + int length; + + // Attempt to detect based on file extension. + length = strlen(sourcefile->ext); + struct ExtensionMap *re = ohcount_hash_language_from_ext(sourcefile->ext, + length); + if (re) language = re->value; + if (language == NULL) { + // Try the lower-case version of this extension. + char lowerext[length + 1]; + strncpy(lowerext, sourcefile->ext, length); + lowerext[length] = '\0'; + for (p = lowerext; p < lowerext + length; p++) *p = tolower(*p); + struct ExtensionMap *re = ohcount_hash_language_from_ext(lowerext, length); + if (re) return re->value; + } + if (language) { + if (ISAMBIGUOUS(language)) { + // Call the appropriate function for disambiguation. + length = strlen(DISAMBIGUATEWHAT(language)); + struct DisambiguateFuncsMap *rd = + ohcount_hash_disambiguate_func_from_id(DISAMBIGUATEWHAT(language), + length); + if (rd) return rd->value(sourcefile); + } else return ISBINARY(language) ? NULL : language; + } + + // Attempt to detect based on filename. + length = strlen(sourcefile->filename); + struct FilenameMap *rf = + ohcount_hash_language_from_filename(sourcefile->filename, length); + if (rf) return rf->value; + + char line[81] = { '\0' }, buf[81]; + + // Attempt to detect using Emacs mode line (/^-\*-\s*mode[\s:]*\w/i). + p = ohcount_sourcefile_get_contents(sourcefile); + pe = p; + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + while (pe < eof) { + // Get the contents of the first line. + while (pe < eof && *pe != '\r' && *pe != '\n') pe++; + length = (pe - p <= sizeof(line)) ? pe - p : sizeof(line); + strncpy(line, p, length); + line[length] = '\0'; + if (*line == '#' && *(line + 1) == '!') { + // First line was sh-bang; loop to get contents of second line. + while (*pe == '\r' || *pe == '\n') pe++; + p = pe; + } else break; + } + char *eol = line + strlen(line); + for (p = line; p < eol; p++) *p = tolower(*p); + p = strstr(line, "-*-"); + if (p) { + p += 3; + while (*p == ' ' || *p == '\t') p++; + if (strncmp(p, "mode", 4) == 0) { + p += 4; + while (*p == ' ' || *p == '\t' || *p == ':') p++; + } + pe = p; + while (isalnum(*pe)) pe++; + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + struct LanguageMap *rl = ohcount_hash_language_from_name(buf, length); + if (rl) return rl->name; + } + + // Attempt to detect based on Unix 'file' command. + int tmpfile = 0; + char *path = sourcefile->filepath; + if (sourcefile->diskpath) + path = sourcefile->diskpath; + if (access(path, F_OK) != 0) { // create temporary file + path = malloc(21); + strncpy(path, "/tmp/ohcount_XXXXXXX", 20); + *(path + 21) = '\0'; + int fd = mkstemp(path); + char *contents = ohcount_sourcefile_get_contents(sourcefile); + log_it("contents:"); + log_it(contents); + length = contents ? strlen(contents) : 0; + write(fd, contents, length); + close(fd); + tmpfile = 1; + } + char command[strlen(path) + 11]; + sprintf(command, "file -b '%s'", path); + FILE *f = popen(command, "r"); + if (f) { + fgets(line, sizeof(line), f); + char *eol = line + strlen(line); + for (p = line; p < eol; p++) *p = tolower(*p); + p = strstr(line, "script text"); + if (p && p == line) { // /^script text(?: executable)? for \w/ + p = strstr(line, "for "); + if (p) { + p += 4; + pe = p; + while (isalnum(*pe)) pe++; + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + struct LanguageMap *rl = ohcount_hash_language_from_name(buf, length); + if (rl) language = rl->name; + } + } else if (p) { // /(\w+)(?: -\w+)* script text/ + do { + p--; + pe = p; + while (*p == ' ') p--; + while (p != line && isalnum(*(p - 1))) p--; + if (p != line && *(p - 1) == '-') p--; + } while (*p == '-'); // Skip over any switches. + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + struct LanguageMap *rl = ohcount_hash_language_from_name(buf, length); + if (rl) language = rl->name; + } else if (strstr(line, "xml")) language = LANG_XML; + pclose(f); + if (tmpfile) { + remove(path); + free(path); + } + if (language) return language; + } + + return NULL; +} + +const char *disambiguate_aspx(SourceFile *sourcefile) { + char *p = ohcount_sourcefile_get_contents(sourcefile); + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + for (; p < eof; p++) { + // /<%@\s*Page[^>]+Language="VB"[^>]+%>/ + p = strstr(p, "<%@"); + if (!p) + break; + char *pe = strstr(p, "%>"); + if (p && pe) { + p += 3; + const int length = pe - p; + char buf[length]; + strncpy(buf, p, length); + buf[length] = '\0'; + char *eol = buf + strlen(buf); + for (p = buf; p < eol; p++) *p = tolower(*p); + p = buf; + while (*p == ' ' || *p == '\t') p++; + if (strncmp(p, "page", 4) == 0) { + p += 4; + if (strstr(p, "language=\"vb\"")) + return LANG_VB_ASPX; + } + } + } + return LANG_CS_ASPX; +} + +const char *disambiguate_b(SourceFile *sourcefile) { + char *p = ohcount_sourcefile_get_contents(sourcefile); + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + while (p < eof) { + // /(implement[ \t])|(include[ \t]+"[^"]*";)| + // ((return|break|continue).*;|(pick|case).*\{)/ + if (strncmp(p, "implement", 9) == 0 && + (*(p + 9) == ' ' || *(p + 9) == '\t')) + return LANG_LIMBO; + else if (strncmp(p, "include", 7) == 0 && + (*(p + 7) == ' ' || *(p + 7) == '\t')) { + p += 7; + while (*p == ' ' || *p == '\t') p++; + if (*p == '"') { + while (*p != '"' && p < eof) p++; + if (*p == '"' && *(p + 1) == ';') + return LANG_LIMBO; + } + } else if (strncmp(p, "return", 6) == 0 || + strncmp(p, "break", 5) == 0 || + strncmp(p, "continue", 8) == 0) { + if (strstr(p, ";")) + return LANG_LIMBO; + } else if (strncmp(p, "pick", 4) == 0 || + strncmp(p, "case", 4) == 0) { + if (strstr(p, "{")) + return LANG_LIMBO; + } + p++; + } + return disambiguate_basic(sourcefile); +} + +const char *disambiguate_basic(SourceFile *sourcefile) { + char *p, *pe; + int length; + + // Attempt to detect based on file contents. + char line[81]; + p = ohcount_sourcefile_get_contents(sourcefile); + pe = p; + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + while (pe < eof) { + // Get a line at a time. + while (pe < eof && *pe != '\r' && *pe != '\n') pe++; + length = (pe - p <= sizeof(line)) ? pe - p : sizeof(line); + strncpy(line, p, length); + line[length] = '\0'; + char *line_end = pe; + + p = line; + if (isdigit(*p)) { + // /^\d+\s+\w/ + p++; + while (isdigit(*p)) p++; + if (*p == ' ' || *p == '\t') { + p++; + while (*p == ' ' || *p == '\t') p++; + if (isalnum(*p)) + return LANG_CLASSIC_BASIC; + } + } + + // Next line. + pe = line_end; + while (*pe == '\r' || *pe == '\n') pe++; + p = pe; + } + + // Attempt to detect from associated VB files in file context. + char **filenames = ohcount_sourcefile_get_filenames(sourcefile); + if (filenames) { + int i; + for (i = 0; filenames[i] != NULL; i++) { + pe = filenames[i] + strlen(filenames[i]); + p = pe; + while (p > filenames[i] && *(p - 1) != '.') p--; + length = pe - p; + if (length == 3 && + (strncmp(p, "frm", length) == 0 || + strncmp(p, "frx", length) == 0 || + strncmp(p, "vba", length) == 0 || + strncmp(p, "vbp", length) == 0 || + strncmp(p, "vbs", length) == 0)) { + return LANG_VISUALBASIC; + } + } + } + + return LANG_STRUCTURED_BASIC; +} + +const char *disambiguate_cs(SourceFile *sourcefile) { + // Attempt to detect based on file contents. + char *contents = ohcount_sourcefile_get_contents(sourcefile); + if (contents && strstr(contents, "filename); + if (strcmp(sourcefile->ext, "h") == 0) { + char path[length]; + strncpy(path, sourcefile->filename, length); + path[length] = '\0'; + *(path + length - 1) = 'm'; + char **filenames = ohcount_sourcefile_get_filenames(sourcefile); + if (filenames) { + int i; + for (i = 0; filenames[i] != NULL; i++) + if (strcmp(path, filenames[i]) == 0) + return LANG_OBJECTIVE_C; + } + } + + // Attempt to detect based on file contents. + char line[81], buf[81]; + p = ohcount_sourcefile_get_contents(sourcefile); + pe = p; + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + while (pe < eof) { + // Get a line at a time. + while (pe < eof && *pe != '\r' && *pe != '\n') pe++; + length = (pe - p <= sizeof(line)) ? pe - p : sizeof(line); + strncpy(line, p, length); + line[length] = '\0'; + char *eol = line + strlen(line); + char *line_end = pe; + + // Look for C++ headers. + if (*line == '#') { + p = line + 1; + while (*p == ' ' || *p == '\t') p++; + if (strncmp(p, "include", 7) == 0 && + (*(p + 7) == ' ' || *(p + 7) == '\t')) { + // /^#\s*include\s+[<"][^>"]+[>"]/ + p += 8; + while (*p == ' ' || *p == '\t') p++; + if (*p == '<' || *p == '"') { + // Is the header file a C++ header file? + p++; + pe = p; + while (pe < eol && *pe != '>' && *pe != '"') pe++; + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + if (ohcount_hash_is_cppheader(buf, length)) + return LANG_CPP; + // Is the extension for the header file a C++ file? + p = pe; + while (p > line && *(p - 1) != '.') p--; + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + struct ExtensionMap *re = ohcount_hash_language_from_ext(buf, length); + if (re && strcmp(re->value, LANG_CPP) == 0) + return LANG_CPP; + } + } + } + + // Look for C++ keywords. + p = line; + while (p < eol) { + if (islower(*p) && p != line && !isalnum(*(p - 1)) && *(p - 1) != '_') { + pe = p; + while (islower(*pe)) pe++; + if (!isalnum(*pe) && *pe != '_') { + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + if (strcmp(buf, "class") == 0 || + strcmp(buf, "namespace") == 0 || + strcmp(buf, "template") == 0 || + strcmp(buf, "typename") == 0) + return LANG_CPP; + } + p = pe + 1; + } else p++; + } + + // Next line. + pe = line_end; + while (*pe == '\r' || *pe == '\n') pe++; + p = pe; + } + + // Nothing to suggest C++. + return LANG_C; +} + +const char *disambiguate_in(SourceFile *sourcefile) { + char *p, *pe; + int length; + const char *language = NULL; + + p = sourcefile->filepath; + pe = p + strlen(p) - 3; + if (strstr(p, ".") <= pe) { + // Only if the filename has an extension prior to the .in + length = pe - p; + char buf[length]; + strncpy(buf, p, length); + buf[length] = '\0'; + SourceFile *undecorated = ohcount_sourcefile_new(buf); + p = ohcount_sourcefile_get_contents(sourcefile); + if (!p) { + return NULL; + } + // The filepath without the '.in' extension does not exist on disk. The + // sourcefile->diskpath field must be set incase the detector needs to run + // 'file -b' on the file. + ohcount_sourcefile_set_diskpath(undecorated, sourcefile->filepath); + ohcount_sourcefile_set_contents(undecorated, p); + char **filenames = ohcount_sourcefile_get_filenames(sourcefile); + ohcount_sourcefile_set_filenames(undecorated, filenames); + language = ohcount_sourcefile_get_language(undecorated); + ohcount_sourcefile_free(undecorated); + } + return language; +} + +const char *disambiguate_inc(SourceFile *sourcefile) { + char *p = ohcount_sourcefile_get_contents(sourcefile); + char *eof = p + strlen(p); + while (p < eof) { + if (*p == '\0') + return BINARY; + else if (*p == '?' && strncmp(p + 1, "php", 3) == 0) + return LANG_PHP; + p++; + } + return NULL; +} + +const char *disambiguate_m(SourceFile *sourcefile) { + char *p, *pe; + int length; + + // Attempt to detect based on a weighted heuristic of file contents. + int matlab_score = 0; + int objective_c_score = 0; + int limbo_score = 0; + int octave_syntax_detected = 0; + + int i, has_h_headers = 0, has_c_files = 0; + char **filenames = ohcount_sourcefile_get_filenames(sourcefile); + if (filenames) { + for (i = 0; filenames[i] != NULL; i++) { + p = filenames[i]; + pe = p + strlen(p); + if (pe - p >= 4) { + if (*(pe - 4) == '.' && *(pe - 3) == 'c' && + ((*(pe - 2) == 'p' && *(pe - 1) == 'p') || + (*(pe - 2) == '+' && *(pe - 1) == '+') || + (*(pe - 2) == 'x' && *(pe - 1) == 'x'))) { + has_c_files = 1; + break; // short circuit + } + } else if (pe - p >= 3) { + if (*(pe - 3) == '.' && *(pe - 2) == 'c' && *(pe - 1) == 'c') { + has_c_files = 1; + break; // short circuit + } + } else if (pe - p >= 2) { + if (*(pe - 2) == '.') { + if (*(pe - 1) == 'h') + has_h_headers = 1; + else if (*(pe - 1) == 'c' || *(pe - 1) == 'C') { + has_c_files = 1; + break; // short circuit + } + } + } + } + } + if (has_h_headers && !has_c_files) + objective_c_score += 5; + + char line[81], buf[81]; + p = ohcount_sourcefile_get_contents(sourcefile); + pe = p; + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + while (pe < eof) { + // Get a line at a time. + while (pe < eof && *pe != '\r' && *pe != '\n') pe++; + length = (pe - p <= sizeof(line)) ? pe - p : sizeof(line); + strncpy(line, p, length); + line[length] = '\0'; + char *eol = line + strlen(line); + char *line_end = pe; + + // Look for tell-tale lines. + p = line; + while (*p == ' ' || *p == '\t') p++; + if (*p == '%') { // Matlab comment + matlab_score++; + } else if (*p == '#' && strncmp(p, "#import", 7) == 0) { // Objective C + objective_c_score++; + } else if (*p == '#') { // Limbo or Octave comment + while (*p == '#') p++; + if (*p == ' ' || *p == '\t') { + limbo_score++; + matlab_score++; + octave_syntax_detected = 1; + } + } else if (*p == '/' && *(p + 1) == '/' || *(p + 1) == '*') { + objective_c_score++; // Objective C comment + } else if (*p == '+' || *p == '-') { // Objective C method signature + objective_c_score++; + } else if (*p == '@' || *p == '#') { // Objective C method signature + if (strncmp(p, "@implementation", 15) == 0 || + strncmp(p, "@interface", 10) == 0) + objective_c_score++; + } else if (strncmp(p, "function", 8) == 0) { // Matlab or Octave function + p += 8; + while (*p == ' ' || *p == '\t') p++; + if (*p == '(') + matlab_score++; + } else if (strncmp(p, "include", 7) == 0) { // Limbo include + // /^include[ \t]+"[^"]+\.m";/ + p += 7; + if (*p == ' ' || *p == '\t') { + while (*p == ' ' || *p == '\t') p++; + if (*p == '"') { + while (*p != '"' && p < eol) p++; + if (*p == '"' && *(p - 2) == '.' && *(p - 1) == 'm') + limbo_score++; + } + } + } + + // Look for Octave keywords. + p = line; + while (p < eol) { + if (islower(*p) && p != line && !isalnum(*(p - 1))) { + pe = p; + while (islower(*pe) || *pe == '_') pe++; + if (!isalnum(*pe)) { + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + if (strcmp(buf, "end_try_catch") == 0 || + strcmp(buf, "end_unwind_protect") == 0 || + strcmp(buf, "endfunction") == 0 || + strcmp(buf, "endwhile") == 0) + octave_syntax_detected = 1; + } + p = pe + 1; + } else p++; + } + + // Look for Limbo declarations + p = line; + while (p < eol) { + if (*p == ':' && (*(p + 1) == ' ' || *(p + 1) == '\t')) { + // /:[ \t]+(module|adt|fn ?\(|con[ \t])/ + p += 2; + if (strncmp(p, "module", 6) == 0 && !isalnum(*(p + 6)) || + strncmp(p, "adt", 3) == 0 && !isalnum(*(p + 3)) || + strncmp(p, "fn", 2) == 0 && + (*(p + 2) == ' ' && *(p + 3) == '(' || *(p + 2) == '(') || + strncmp(p, "con", 3) == 0 && + (*(p + 3) == ' ' || *(p + 3) == '\t')) + limbo_score++; + } else p++; + } + + // Next line. + pe = line_end; + while (*pe == '\r' || *pe == '\n') pe++; + p = pe; + } + + if (limbo_score > objective_c_score && limbo_score > matlab_score) + return LANG_LIMBO; + else if (objective_c_score > matlab_score) + return LANG_OBJECTIVE_C; + else + return octave_syntax_detected ? LANG_OCTAVE : LANG_MATLAB; +} + +#define QMAKE_SOURCES_SPACE "SOURCES +=" +#define QMAKE_SOURCES "SOURCES+=" +#define QMAKE_CONFIG_SPACE "CONFIG +=" +#define QMAKE_CONFIG "CONFIG+=" + +const char *disambiguate_pro(SourceFile *sourcefile) { + char *p = ohcount_sourcefile_get_contents(sourcefile); + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + for (; p < eof; p++) { + if (strncmp(p, QMAKE_SOURCES_SPACE, strlen(QMAKE_SOURCES_SPACE)) == 0 || + strncmp(p, QMAKE_SOURCES, strlen(QMAKE_SOURCES)) == 0 || + strncmp(p, QMAKE_CONFIG_SPACE, strlen(QMAKE_CONFIG_SPACE)) == 0 || + strncmp(p, QMAKE_CONFIG, strlen(QMAKE_CONFIG)) == 0) + return LANG_MAKE; // really QMAKE + } + return LANG_IDL_PVWAVE; +} + +const char *disambiguate_st(SourceFile *sourcefile) { + char *p, *pe; + int length; + + // Attempt to detect based on file contents. + int found_assignment = 0, found_block_start = 0, found_block_end = 0; + + char line[81]; + p = ohcount_sourcefile_get_contents(sourcefile); + pe = p; + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + while (pe < eof) { + // Get a line at a time. + while (p < eof && *pe != '\r' && *pe != '\n') pe++; + length = (pe - p <= sizeof(line)) ? pe - p : sizeof(line); + strncpy(line, p, length); + line[length] = '\0'; + char *eol = line + strlen(line); + char *line_end = pe; + + for (p = line; p < eol; p++) { + if (*p == ':') { + p++; + while (p < eol && (*p == ' ' || *p == '\t')) p++; + if (*p == '=') + found_assignment = 1; + else if (*p == '[') + found_block_start = 1; + } else if (*p == ']' && *(p + 1) == '.') found_block_end = 1; + if (found_assignment && found_block_start && found_block_end) + return LANG_SMALLTALK; + } + + // Next line. + pe = line_end; + while (*pe == '\r' || *pe == '\n') pe++; + p = pe; + } + + return NULL; +} + +int ohcount_is_binary_filename(const char *filename) { + char *p = (char *)filename + strlen(filename); + while (p > filename && *(p - 1) != '.') p--; + if (p > filename) { + struct ExtensionMap *re; + int length = strlen(p); + re = ohcount_hash_language_from_ext(p, length); + if (re) return ISBINARY(re->value); + // Try the lower-case version of this extension. + char lowerext[length]; + strncpy(lowerext, p, length); + lowerext[length] = '\0'; + for (p = lowerext; p < lowerext + length; p++) *p = tolower(*p); + re = ohcount_hash_language_from_ext(lowerext, length); + if (re) return ISBINARY(re->value); + } + return 0; +} diff --git a/.pc/fix_null_dereference.patch/test/detect_files/empty.inc b/.pc/fix_null_dereference.patch/test/detect_files/empty.inc new file mode 100644 index 0000000..e69de29 diff --git a/.pc/fix_null_dereference.patch/test/unit/detector_test.h b/.pc/fix_null_dereference.patch/test/unit/detector_test.h new file mode 100644 index 0000000..48b6468 --- /dev/null +++ b/.pc/fix_null_dereference.patch/test/unit/detector_test.h @@ -0,0 +1,133 @@ +// detector_test.h written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#include +#include +#include + +#include "../../src/detector.h" +#include "../../src/languages.h" +#include "../../src/sourcefile.h" + +#define ASSERT_DETECT(x, y) { \ + SourceFile *sf = ohcount_sourcefile_new("../detect_files/" y); \ + const char *lang = ohcount_detect_language(sf); \ + assert(lang); \ + assert(strcmp(x, lang) == 0); \ + ohcount_sourcefile_free(sf); \ +} +#define ASSERT_NODETECT(x) { \ + SourceFile *sf = ohcount_sourcefile_new("../detect_files/" x); \ + assert(ohcount_detect_language(sf) == NULL); \ + ohcount_sourcefile_free(sf); \ +} + +void test_detector_smalltalk() { + ASSERT_DETECT(LANG_SMALLTALK, "example.st"); + ASSERT_NODETECT("english.st"); +} + +void test_detector_disambiguate_m() { + ASSERT_DETECT(LANG_OBJECTIVE_C, "t1.m"); + ASSERT_DETECT(LANG_OBJECTIVE_C, "t2.m"); + ASSERT_DETECT(LANG_OBJECTIVE_C, "TCPSocket.m"); + ASSERT_DETECT(LANG_OBJECTIVE_C, "foo_objective_c.m"); + ASSERT_DETECT(LANG_MATLAB, "foo_matlab.m"); + ASSERT_DETECT(LANG_OCTAVE, "foo_octave.m"); +} + +void test_detector_disambiguate_in() { + ASSERT_NODETECT("empty.in"); +} +void test_detector_disambiguate_pro() { + ASSERT_DETECT(LANG_IDL_PVWAVE, "foo.pro"); + ASSERT_DETECT(LANG_MAKE, "qmake.pro"); +} + +void test_detector_fortran_fixedfree() { + ASSERT_DETECT(LANG_FORTRANFIXED, "fortranfixed.f"); + ASSERT_DETECT(LANG_FORTRANFREE, "fortranfree.f"); +} + +void test_detector_detect_polyglot() { + ASSERT_DETECT(LANG_C, "foo.c"); + ASSERT_DETECT(LANG_C, "uses_no_cpp.h"); + ASSERT_DETECT(LANG_CPP, "uses_cpp_headers.h"); + ASSERT_DETECT(LANG_CPP, "uses_cpp_stdlib_headers.h"); + ASSERT_DETECT(LANG_CPP, "uses_cpp_keywords.h"); + ASSERT_DETECT(LANG_RUBY, "foo.rb"); + ASSERT_DETECT(LANG_MAKE, "foo.mk"); + ASSERT_DETECT(LANG_OBJECTIVE_C, "foo_objective_c.h"); + ASSERT_DETECT(LANG_PHP, "upper_case_php"); + ASSERT_DETECT(LANG_SMALLTALK, "example.st"); + ASSERT_DETECT(LANG_VALA, "foo.vala"); + ASSERT_DETECT(LANG_TEX, "foo.tex"); + ASSERT_DETECT(LANG_XSLT, "example.xsl"); + ASSERT_DETECT(LANG_LISP, "core.lisp"); + ASSERT_DETECT(LANG_DMD, "foo.d"); + ASSERT_DETECT(LANG_VIM, "foo.vim"); + ASSERT_DETECT(LANG_EBUILD, "foo.ebuild"); + ASSERT_DETECT(LANG_EBUILD, "foo.eclass"); + ASSERT_DETECT(LANG_EXHERES, "foo.exheres-0"); + ASSERT_DETECT(LANG_EXHERES, "foo.exlib"); + ASSERT_DETECT(LANG_EIFFEL, "eiffel.e"); + ASSERT_DETECT(LANG_OCAML, "ocaml.ml"); + ASSERT_DETECT(LANG_STRATEGO, "stratego.str"); + ASSERT_DETECT(LANG_R, "foo.R"); + ASSERT_DETECT(LANG_GLSL, "foo.glsl"); + ASSERT_DETECT(LANG_GLSL, "foo_glsl.vert"); + ASSERT_DETECT(LANG_GLSL, "foo_glsl.frag"); + ASSERT_DETECT(LANG_IDL_PVWAVE, "foo.pro"); + ASSERT_DETECT(LANG_ASSEMBLER, "foo.z80"); + ASSERT_DETECT(LANG_PHP, "php.inc"); + ASSERT_DETECT(LANG_FSHARP, "fs1.fs"); +} + +void test_detector_upper_case_extensions() { + ASSERT_DETECT(LANG_CPP, "foo_upper_case.C"); + ASSERT_DETECT(LANG_RUBY, "foo_upper_case.RB"); +} + +void test_detector_no_extensions() { + ASSERT_DETECT(LANG_PYTHON, "py_script"); + ASSERT_DETECT(LANG_RUBY, "ruby_script"); + ASSERT_DETECT(LANG_SHELL, "bourne_again_script"); + ASSERT_DETECT(LANG_SHELL, "bash_script"); + ASSERT_DETECT(LANG_PERL, "perl_w"); + ASSERT_DETECT(LANG_DMD, "d_script"); + ASSERT_DETECT(LANG_TCL, "tcl_script"); + ASSERT_DETECT(LANG_PYTHON, "python.data"); + ASSERT_DETECT(LANG_PYTHON, "python2.data"); +} + +void test_detector_csharp_or_clearsilver() { + ASSERT_DETECT(LANG_CSHARP, "cs1.cs"); + ASSERT_DETECT(LANG_CLEARSILVER_TEMPLATE, "clearsilver_template1.cs"); +} + +void test_detector_basic() { + ASSERT_DETECT(LANG_VISUALBASIC, "visual_basic.bas"); + ASSERT_DETECT(LANG_CLASSIC_BASIC, "classic_basic.b"); + system("mv ../detect_files/frx1.frx ../detect_files/frx1.frx2"); + ASSERT_DETECT(LANG_STRUCTURED_BASIC, "visual_basic.bas"); + ASSERT_DETECT(LANG_STRUCTURED_BASIC, "structured_basic.b"); + system("mv ../detect_files/frx1.frx2 ../detect_files/frx1.frx"); +} + +void test_detector_xml_with_custom_extension() { + ASSERT_DETECT(LANG_XML, "xml.custom_ext"); +} + +void all_detector_tests() { + test_detector_smalltalk(); + test_detector_disambiguate_m(); + test_detector_disambiguate_in(); + test_detector_disambiguate_pro(); + test_detector_fortran_fixedfree(); + test_detector_detect_polyglot(); + test_detector_upper_case_extensions(); + test_detector_no_extensions(); + test_detector_csharp_or_clearsilver(); + test_detector_basic(); + test_detector_xml_with_custom_extension(); +} diff --git a/.pc/fix_null_dereference_2.patch/src/detector.c b/.pc/fix_null_dereference_2.patch/src/detector.c new file mode 100644 index 0000000..4d0e1f4 --- /dev/null +++ b/.pc/fix_null_dereference_2.patch/src/detector.c @@ -0,0 +1,690 @@ +// detector.c written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#include +#include +#include +#include +#include + +#include "detector.h" +#include "languages.h" +#include "log.h" + +#include "hash/cppheader_hash.h" +#include "hash/disambiguatefunc_hash.h" +#include "hash/extension_hash.h" +#include "hash/filename_hash.h" + +#define ISBINARY(x) (x[0] == '\1') +#define ISAMBIGUOUS(x) (x[0] == '\2') +#define DISAMBIGUATEWHAT(x) &x[1] + +const char *ohcount_detect_language(SourceFile *sourcefile) { + const char *language = NULL; + char *p, *pe; + int length; + + // Attempt to detect based on file extension. + length = strlen(sourcefile->ext); + struct ExtensionMap *re = ohcount_hash_language_from_ext(sourcefile->ext, + length); + if (re) language = re->value; + if (language == NULL) { + // Try the lower-case version of this extension. + char lowerext[length + 1]; + strncpy(lowerext, sourcefile->ext, length); + lowerext[length] = '\0'; + for (p = lowerext; p < lowerext + length; p++) *p = tolower(*p); + struct ExtensionMap *re = ohcount_hash_language_from_ext(lowerext, length); + if (re) return re->value; + } + if (language) { + if (ISAMBIGUOUS(language)) { + // Call the appropriate function for disambiguation. + length = strlen(DISAMBIGUATEWHAT(language)); + struct DisambiguateFuncsMap *rd = + ohcount_hash_disambiguate_func_from_id(DISAMBIGUATEWHAT(language), + length); + if (rd) return rd->value(sourcefile); + } else return ISBINARY(language) ? NULL : language; + } + + // Attempt to detect based on filename. + length = strlen(sourcefile->filename); + struct FilenameMap *rf = + ohcount_hash_language_from_filename(sourcefile->filename, length); + if (rf) return rf->value; + + char line[81] = { '\0' }, buf[81]; + + // Attempt to detect using Emacs mode line (/^-\*-\s*mode[\s:]*\w/i). + p = ohcount_sourcefile_get_contents(sourcefile); + pe = p; + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + while (pe < eof) { + // Get the contents of the first line. + while (pe < eof && *pe != '\r' && *pe != '\n') pe++; + length = (pe - p <= sizeof(line)) ? pe - p : sizeof(line); + strncpy(line, p, length); + line[length] = '\0'; + if (*line == '#' && *(line + 1) == '!') { + // First line was sh-bang; loop to get contents of second line. + while (*pe == '\r' || *pe == '\n') pe++; + p = pe; + } else break; + } + char *eol = line + strlen(line); + for (p = line; p < eol; p++) *p = tolower(*p); + p = strstr(line, "-*-"); + if (p) { + p += 3; + while (*p == ' ' || *p == '\t') p++; + if (strncmp(p, "mode", 4) == 0) { + p += 4; + while (*p == ' ' || *p == '\t' || *p == ':') p++; + } + pe = p; + while (isalnum(*pe)) pe++; + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + struct LanguageMap *rl = ohcount_hash_language_from_name(buf, length); + if (rl) return rl->name; + } + + // Attempt to detect based on Unix 'file' command. + int tmpfile = 0; + char *path = sourcefile->filepath; + if (sourcefile->diskpath) + path = sourcefile->diskpath; + if (access(path, F_OK) != 0) { // create temporary file + path = malloc(21); + strncpy(path, "/tmp/ohcount_XXXXXXX", 20); + *(path + 21) = '\0'; + int fd = mkstemp(path); + char *contents = ohcount_sourcefile_get_contents(sourcefile); + log_it("contents:"); + log_it(contents); + length = contents ? strlen(contents) : 0; + write(fd, contents, length); + close(fd); + tmpfile = 1; + } + char command[strlen(path) + 11]; + sprintf(command, "file -b '%s'", path); + FILE *f = popen(command, "r"); + if (f) { + fgets(line, sizeof(line), f); + char *eol = line + strlen(line); + for (p = line; p < eol; p++) *p = tolower(*p); + p = strstr(line, "script text"); + if (p && p == line) { // /^script text(?: executable)? for \w/ + p = strstr(line, "for "); + if (p) { + p += 4; + pe = p; + while (isalnum(*pe)) pe++; + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + struct LanguageMap *rl = ohcount_hash_language_from_name(buf, length); + if (rl) language = rl->name; + } + } else if (p) { // /(\w+)(?: -\w+)* script text/ + do { + p--; + pe = p; + while (*p == ' ') p--; + while (p != line && isalnum(*(p - 1))) p--; + if (p != line && *(p - 1) == '-') p--; + } while (*p == '-'); // Skip over any switches. + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + struct LanguageMap *rl = ohcount_hash_language_from_name(buf, length); + if (rl) language = rl->name; + } else if (strstr(line, "xml")) language = LANG_XML; + pclose(f); + if (tmpfile) { + remove(path); + free(path); + } + if (language) return language; + } + + return NULL; +} + +const char *disambiguate_aspx(SourceFile *sourcefile) { + char *p = ohcount_sourcefile_get_contents(sourcefile); + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + for (; p < eof; p++) { + // /<%@\s*Page[^>]+Language="VB"[^>]+%>/ + p = strstr(p, "<%@"); + if (!p) + break; + char *pe = strstr(p, "%>"); + if (p && pe) { + p += 3; + const int length = pe - p; + char buf[length]; + strncpy(buf, p, length); + buf[length] = '\0'; + char *eol = buf + strlen(buf); + for (p = buf; p < eol; p++) *p = tolower(*p); + p = buf; + while (*p == ' ' || *p == '\t') p++; + if (strncmp(p, "page", 4) == 0) { + p += 4; + if (strstr(p, "language=\"vb\"")) + return LANG_VB_ASPX; + } + } + } + return LANG_CS_ASPX; +} + +const char *disambiguate_b(SourceFile *sourcefile) { + char *p = ohcount_sourcefile_get_contents(sourcefile); + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + while (p < eof) { + // /(implement[ \t])|(include[ \t]+"[^"]*";)| + // ((return|break|continue).*;|(pick|case).*\{)/ + if (strncmp(p, "implement", 9) == 0 && + (*(p + 9) == ' ' || *(p + 9) == '\t')) + return LANG_LIMBO; + else if (strncmp(p, "include", 7) == 0 && + (*(p + 7) == ' ' || *(p + 7) == '\t')) { + p += 7; + while (*p == ' ' || *p == '\t') p++; + if (*p == '"') { + while (*p != '"' && p < eof) p++; + if (*p == '"' && *(p + 1) == ';') + return LANG_LIMBO; + } + } else if (strncmp(p, "return", 6) == 0 || + strncmp(p, "break", 5) == 0 || + strncmp(p, "continue", 8) == 0) { + if (strstr(p, ";")) + return LANG_LIMBO; + } else if (strncmp(p, "pick", 4) == 0 || + strncmp(p, "case", 4) == 0) { + if (strstr(p, "{")) + return LANG_LIMBO; + } + p++; + } + return disambiguate_basic(sourcefile); +} + +const char *disambiguate_basic(SourceFile *sourcefile) { + char *p, *pe; + int length; + + // Attempt to detect based on file contents. + char line[81]; + p = ohcount_sourcefile_get_contents(sourcefile); + pe = p; + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + while (pe < eof) { + // Get a line at a time. + while (pe < eof && *pe != '\r' && *pe != '\n') pe++; + length = (pe - p <= sizeof(line)) ? pe - p : sizeof(line); + strncpy(line, p, length); + line[length] = '\0'; + char *line_end = pe; + + p = line; + if (isdigit(*p)) { + // /^\d+\s+\w/ + p++; + while (isdigit(*p)) p++; + if (*p == ' ' || *p == '\t') { + p++; + while (*p == ' ' || *p == '\t') p++; + if (isalnum(*p)) + return LANG_CLASSIC_BASIC; + } + } + + // Next line. + pe = line_end; + while (*pe == '\r' || *pe == '\n') pe++; + p = pe; + } + + // Attempt to detect from associated VB files in file context. + char **filenames = ohcount_sourcefile_get_filenames(sourcefile); + if (filenames) { + int i; + for (i = 0; filenames[i] != NULL; i++) { + pe = filenames[i] + strlen(filenames[i]); + p = pe; + while (p > filenames[i] && *(p - 1) != '.') p--; + length = pe - p; + if (length == 3 && + (strncmp(p, "frm", length) == 0 || + strncmp(p, "frx", length) == 0 || + strncmp(p, "vba", length) == 0 || + strncmp(p, "vbp", length) == 0 || + strncmp(p, "vbs", length) == 0)) { + return LANG_VISUALBASIC; + } + } + } + + return LANG_STRUCTURED_BASIC; +} + +const char *disambiguate_cs(SourceFile *sourcefile) { + // Attempt to detect based on file contents. + char *contents = ohcount_sourcefile_get_contents(sourcefile); + if (contents && strstr(contents, "filename); + if (strcmp(sourcefile->ext, "h") == 0) { + char path[length]; + strncpy(path, sourcefile->filename, length); + path[length] = '\0'; + *(path + length - 1) = 'm'; + char **filenames = ohcount_sourcefile_get_filenames(sourcefile); + if (filenames) { + int i; + for (i = 0; filenames[i] != NULL; i++) + if (strcmp(path, filenames[i]) == 0) + return LANG_OBJECTIVE_C; + } + } + + // Attempt to detect based on file contents. + char line[81], buf[81]; + p = ohcount_sourcefile_get_contents(sourcefile); + pe = p; + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + while (pe < eof) { + // Get a line at a time. + while (pe < eof && *pe != '\r' && *pe != '\n') pe++; + length = (pe - p <= sizeof(line)) ? pe - p : sizeof(line); + strncpy(line, p, length); + line[length] = '\0'; + char *eol = line + strlen(line); + char *line_end = pe; + + // Look for C++ headers. + if (*line == '#') { + p = line + 1; + while (*p == ' ' || *p == '\t') p++; + if (strncmp(p, "include", 7) == 0 && + (*(p + 7) == ' ' || *(p + 7) == '\t')) { + // /^#\s*include\s+[<"][^>"]+[>"]/ + p += 8; + while (*p == ' ' || *p == '\t') p++; + if (*p == '<' || *p == '"') { + // Is the header file a C++ header file? + p++; + pe = p; + while (pe < eol && *pe != '>' && *pe != '"') pe++; + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + if (ohcount_hash_is_cppheader(buf, length)) + return LANG_CPP; + // Is the extension for the header file a C++ file? + p = pe; + while (p > line && *(p - 1) != '.') p--; + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + struct ExtensionMap *re = ohcount_hash_language_from_ext(buf, length); + if (re && strcmp(re->value, LANG_CPP) == 0) + return LANG_CPP; + } + } + } + + // Look for C++ keywords. + p = line; + while (p < eol) { + if (islower(*p) && p != line && !isalnum(*(p - 1)) && *(p - 1) != '_') { + pe = p; + while (islower(*pe)) pe++; + if (!isalnum(*pe) && *pe != '_') { + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + if (strcmp(buf, "class") == 0 || + strcmp(buf, "namespace") == 0 || + strcmp(buf, "template") == 0 || + strcmp(buf, "typename") == 0) + return LANG_CPP; + } + p = pe + 1; + } else p++; + } + + // Next line. + pe = line_end; + while (*pe == '\r' || *pe == '\n') pe++; + p = pe; + } + + // Nothing to suggest C++. + return LANG_C; +} + +const char *disambiguate_in(SourceFile *sourcefile) { + char *p, *pe; + int length; + const char *language = NULL; + + p = sourcefile->filepath; + pe = p + strlen(p) - 3; + if (strstr(p, ".") <= pe) { + // Only if the filename has an extension prior to the .in + length = pe - p; + char buf[length]; + strncpy(buf, p, length); + buf[length] = '\0'; + SourceFile *undecorated = ohcount_sourcefile_new(buf); + p = ohcount_sourcefile_get_contents(sourcefile); + // The filepath without the '.in' extension does not exist on disk. The + // sourcefile->diskpath field must be set incase the detector needs to run + // 'file -b' on the file. + ohcount_sourcefile_set_diskpath(undecorated, sourcefile->filepath); + ohcount_sourcefile_set_contents(undecorated, p); + char **filenames = ohcount_sourcefile_get_filenames(sourcefile); + ohcount_sourcefile_set_filenames(undecorated, filenames); + language = ohcount_sourcefile_get_language(undecorated); + ohcount_sourcefile_free(undecorated); + } + return language; +} + +const char *disambiguate_inc(SourceFile *sourcefile) { + char *p = ohcount_sourcefile_get_contents(sourcefile); + char *eof = p + strlen(p); + while (p < eof) { + if (*p == '\0') + return BINARY; + else if (*p == '?' && strncmp(p + 1, "php", 3) == 0) + return LANG_PHP; + p++; + } + return NULL; +} + +const char *disambiguate_m(SourceFile *sourcefile) { + char *p, *pe; + int length; + + // Attempt to detect based on a weighted heuristic of file contents. + int matlab_score = 0; + int objective_c_score = 0; + int limbo_score = 0; + int octave_syntax_detected = 0; + + int i, has_h_headers = 0, has_c_files = 0; + char **filenames = ohcount_sourcefile_get_filenames(sourcefile); + if (filenames) { + for (i = 0; filenames[i] != NULL; i++) { + p = filenames[i]; + pe = p + strlen(p); + if (pe - p >= 4) { + if (*(pe - 4) == '.' && *(pe - 3) == 'c' && + ((*(pe - 2) == 'p' && *(pe - 1) == 'p') || + (*(pe - 2) == '+' && *(pe - 1) == '+') || + (*(pe - 2) == 'x' && *(pe - 1) == 'x'))) { + has_c_files = 1; + break; // short circuit + } + } else if (pe - p >= 3) { + if (*(pe - 3) == '.' && *(pe - 2) == 'c' && *(pe - 1) == 'c') { + has_c_files = 1; + break; // short circuit + } + } else if (pe - p >= 2) { + if (*(pe - 2) == '.') { + if (*(pe - 1) == 'h') + has_h_headers = 1; + else if (*(pe - 1) == 'c' || *(pe - 1) == 'C') { + has_c_files = 1; + break; // short circuit + } + } + } + } + } + if (has_h_headers && !has_c_files) + objective_c_score += 5; + + char line[81], buf[81]; + p = ohcount_sourcefile_get_contents(sourcefile); + pe = p; + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + while (pe < eof) { + // Get a line at a time. + while (pe < eof && *pe != '\r' && *pe != '\n') pe++; + length = (pe - p <= sizeof(line)) ? pe - p : sizeof(line); + strncpy(line, p, length); + line[length] = '\0'; + char *eol = line + strlen(line); + char *line_end = pe; + + // Look for tell-tale lines. + p = line; + while (*p == ' ' || *p == '\t') p++; + if (*p == '%') { // Matlab comment + matlab_score++; + } else if (*p == '#' && strncmp(p, "#import", 7) == 0) { // Objective C + objective_c_score++; + } else if (*p == '#') { // Limbo or Octave comment + while (*p == '#') p++; + if (*p == ' ' || *p == '\t') { + limbo_score++; + matlab_score++; + octave_syntax_detected = 1; + } + } else if (*p == '/' && *(p + 1) == '/' || *(p + 1) == '*') { + objective_c_score++; // Objective C comment + } else if (*p == '+' || *p == '-') { // Objective C method signature + objective_c_score++; + } else if (*p == '@' || *p == '#') { // Objective C method signature + if (strncmp(p, "@implementation", 15) == 0 || + strncmp(p, "@interface", 10) == 0) + objective_c_score++; + } else if (strncmp(p, "function", 8) == 0) { // Matlab or Octave function + p += 8; + while (*p == ' ' || *p == '\t') p++; + if (*p == '(') + matlab_score++; + } else if (strncmp(p, "include", 7) == 0) { // Limbo include + // /^include[ \t]+"[^"]+\.m";/ + p += 7; + if (*p == ' ' || *p == '\t') { + while (*p == ' ' || *p == '\t') p++; + if (*p == '"') { + while (*p != '"' && p < eol) p++; + if (*p == '"' && *(p - 2) == '.' && *(p - 1) == 'm') + limbo_score++; + } + } + } + + // Look for Octave keywords. + p = line; + while (p < eol) { + if (islower(*p) && p != line && !isalnum(*(p - 1))) { + pe = p; + while (islower(*pe) || *pe == '_') pe++; + if (!isalnum(*pe)) { + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + if (strcmp(buf, "end_try_catch") == 0 || + strcmp(buf, "end_unwind_protect") == 0 || + strcmp(buf, "endfunction") == 0 || + strcmp(buf, "endwhile") == 0) + octave_syntax_detected = 1; + } + p = pe + 1; + } else p++; + } + + // Look for Limbo declarations + p = line; + while (p < eol) { + if (*p == ':' && (*(p + 1) == ' ' || *(p + 1) == '\t')) { + // /:[ \t]+(module|adt|fn ?\(|con[ \t])/ + p += 2; + if (strncmp(p, "module", 6) == 0 && !isalnum(*(p + 6)) || + strncmp(p, "adt", 3) == 0 && !isalnum(*(p + 3)) || + strncmp(p, "fn", 2) == 0 && + (*(p + 2) == ' ' && *(p + 3) == '(' || *(p + 2) == '(') || + strncmp(p, "con", 3) == 0 && + (*(p + 3) == ' ' || *(p + 3) == '\t')) + limbo_score++; + } else p++; + } + + // Next line. + pe = line_end; + while (*pe == '\r' || *pe == '\n') pe++; + p = pe; + } + + if (limbo_score > objective_c_score && limbo_score > matlab_score) + return LANG_LIMBO; + else if (objective_c_score > matlab_score) + return LANG_OBJECTIVE_C; + else + return octave_syntax_detected ? LANG_OCTAVE : LANG_MATLAB; +} + +#define QMAKE_SOURCES_SPACE "SOURCES +=" +#define QMAKE_SOURCES "SOURCES+=" +#define QMAKE_CONFIG_SPACE "CONFIG +=" +#define QMAKE_CONFIG "CONFIG+=" + +const char *disambiguate_pro(SourceFile *sourcefile) { + char *p = ohcount_sourcefile_get_contents(sourcefile); + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + for (; p < eof; p++) { + if (strncmp(p, QMAKE_SOURCES_SPACE, strlen(QMAKE_SOURCES_SPACE)) == 0 || + strncmp(p, QMAKE_SOURCES, strlen(QMAKE_SOURCES)) == 0 || + strncmp(p, QMAKE_CONFIG_SPACE, strlen(QMAKE_CONFIG_SPACE)) == 0 || + strncmp(p, QMAKE_CONFIG, strlen(QMAKE_CONFIG)) == 0) + return LANG_MAKE; // really QMAKE + } + return LANG_IDL_PVWAVE; +} + +const char *disambiguate_st(SourceFile *sourcefile) { + char *p, *pe; + int length; + + // Attempt to detect based on file contents. + int found_assignment = 0, found_block_start = 0, found_block_end = 0; + + char line[81]; + p = ohcount_sourcefile_get_contents(sourcefile); + pe = p; + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + while (pe < eof) { + // Get a line at a time. + while (p < eof && *pe != '\r' && *pe != '\n') pe++; + length = (pe - p <= sizeof(line)) ? pe - p : sizeof(line); + strncpy(line, p, length); + line[length] = '\0'; + char *eol = line + strlen(line); + char *line_end = pe; + + for (p = line; p < eol; p++) { + if (*p == ':') { + p++; + while (p < eol && (*p == ' ' || *p == '\t')) p++; + if (*p == '=') + found_assignment = 1; + else if (*p == '[') + found_block_start = 1; + } else if (*p == ']' && *(p + 1) == '.') found_block_end = 1; + if (found_assignment && found_block_start && found_block_end) + return LANG_SMALLTALK; + } + + // Next line. + pe = line_end; + while (*pe == '\r' || *pe == '\n') pe++; + p = pe; + } + + return NULL; +} + +int ohcount_is_binary_filename(const char *filename) { + char *p = (char *)filename + strlen(filename); + while (p > filename && *(p - 1) != '.') p--; + if (p > filename) { + struct ExtensionMap *re; + int length = strlen(p); + re = ohcount_hash_language_from_ext(p, length); + if (re) return ISBINARY(re->value); + // Try the lower-case version of this extension. + char lowerext[length]; + strncpy(lowerext, p, length); + lowerext[length] = '\0'; + for (p = lowerext; p < lowerext + length; p++) *p = tolower(*p); + re = ohcount_hash_language_from_ext(lowerext, length); + if (re) return ISBINARY(re->value); + } + return 0; +} diff --git a/.pc/fix_null_dereference_2.patch/test/detect_files/empty.in b/.pc/fix_null_dereference_2.patch/test/detect_files/empty.in new file mode 100644 index 0000000..e69de29 diff --git a/.pc/fix_null_dereference_2.patch/test/unit/detector_test.h b/.pc/fix_null_dereference_2.patch/test/unit/detector_test.h new file mode 100644 index 0000000..cd36b6d --- /dev/null +++ b/.pc/fix_null_dereference_2.patch/test/unit/detector_test.h @@ -0,0 +1,129 @@ +// detector_test.h written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#include +#include +#include + +#include "../../src/detector.h" +#include "../../src/languages.h" +#include "../../src/sourcefile.h" + +#define ASSERT_DETECT(x, y) { \ + SourceFile *sf = ohcount_sourcefile_new("../detect_files/" y); \ + const char *lang = ohcount_detect_language(sf); \ + assert(lang); \ + assert(strcmp(x, lang) == 0); \ + ohcount_sourcefile_free(sf); \ +} +#define ASSERT_NODETECT(x) { \ + SourceFile *sf = ohcount_sourcefile_new("../detect_files/" x); \ + assert(ohcount_detect_language(sf) == NULL); \ + ohcount_sourcefile_free(sf); \ +} + +void test_detector_smalltalk() { + ASSERT_DETECT(LANG_SMALLTALK, "example.st"); + ASSERT_NODETECT("english.st"); +} + +void test_detector_disambiguate_m() { + ASSERT_DETECT(LANG_OBJECTIVE_C, "t1.m"); + ASSERT_DETECT(LANG_OBJECTIVE_C, "t2.m"); + ASSERT_DETECT(LANG_OBJECTIVE_C, "TCPSocket.m"); + ASSERT_DETECT(LANG_OBJECTIVE_C, "foo_objective_c.m"); + ASSERT_DETECT(LANG_MATLAB, "foo_matlab.m"); + ASSERT_DETECT(LANG_OCTAVE, "foo_octave.m"); +} + +void test_detector_disambiguate_pro() { + ASSERT_DETECT(LANG_IDL_PVWAVE, "foo.pro"); + ASSERT_DETECT(LANG_MAKE, "qmake.pro"); +} + +void test_detector_fortran_fixedfree() { + ASSERT_DETECT(LANG_FORTRANFIXED, "fortranfixed.f"); + ASSERT_DETECT(LANG_FORTRANFREE, "fortranfree.f"); +} + +void test_detector_detect_polyglot() { + ASSERT_DETECT(LANG_C, "foo.c"); + ASSERT_DETECT(LANG_C, "uses_no_cpp.h"); + ASSERT_DETECT(LANG_CPP, "uses_cpp_headers.h"); + ASSERT_DETECT(LANG_CPP, "uses_cpp_stdlib_headers.h"); + ASSERT_DETECT(LANG_CPP, "uses_cpp_keywords.h"); + ASSERT_DETECT(LANG_RUBY, "foo.rb"); + ASSERT_DETECT(LANG_MAKE, "foo.mk"); + ASSERT_DETECT(LANG_OBJECTIVE_C, "foo_objective_c.h"); + ASSERT_DETECT(LANG_PHP, "upper_case_php"); + ASSERT_DETECT(LANG_SMALLTALK, "example.st"); + ASSERT_DETECT(LANG_VALA, "foo.vala"); + ASSERT_DETECT(LANG_TEX, "foo.tex"); + ASSERT_DETECT(LANG_XSLT, "example.xsl"); + ASSERT_DETECT(LANG_LISP, "core.lisp"); + ASSERT_DETECT(LANG_DMD, "foo.d"); + ASSERT_DETECT(LANG_VIM, "foo.vim"); + ASSERT_DETECT(LANG_EBUILD, "foo.ebuild"); + ASSERT_DETECT(LANG_EBUILD, "foo.eclass"); + ASSERT_DETECT(LANG_EXHERES, "foo.exheres-0"); + ASSERT_DETECT(LANG_EXHERES, "foo.exlib"); + ASSERT_DETECT(LANG_EIFFEL, "eiffel.e"); + ASSERT_DETECT(LANG_OCAML, "ocaml.ml"); + ASSERT_DETECT(LANG_STRATEGO, "stratego.str"); + ASSERT_DETECT(LANG_R, "foo.R"); + ASSERT_DETECT(LANG_GLSL, "foo.glsl"); + ASSERT_DETECT(LANG_GLSL, "foo_glsl.vert"); + ASSERT_DETECT(LANG_GLSL, "foo_glsl.frag"); + ASSERT_DETECT(LANG_IDL_PVWAVE, "foo.pro"); + ASSERT_DETECT(LANG_ASSEMBLER, "foo.z80"); + ASSERT_DETECT(LANG_PHP, "php.inc"); + ASSERT_DETECT(LANG_FSHARP, "fs1.fs"); +} + +void test_detector_upper_case_extensions() { + ASSERT_DETECT(LANG_CPP, "foo_upper_case.C"); + ASSERT_DETECT(LANG_RUBY, "foo_upper_case.RB"); +} + +void test_detector_no_extensions() { + ASSERT_DETECT(LANG_PYTHON, "py_script"); + ASSERT_DETECT(LANG_RUBY, "ruby_script"); + ASSERT_DETECT(LANG_SHELL, "bourne_again_script"); + ASSERT_DETECT(LANG_SHELL, "bash_script"); + ASSERT_DETECT(LANG_PERL, "perl_w"); + ASSERT_DETECT(LANG_DMD, "d_script"); + ASSERT_DETECT(LANG_TCL, "tcl_script"); + ASSERT_DETECT(LANG_PYTHON, "python.data"); + ASSERT_DETECT(LANG_PYTHON, "python2.data"); +} + +void test_detector_csharp_or_clearsilver() { + ASSERT_DETECT(LANG_CSHARP, "cs1.cs"); + ASSERT_DETECT(LANG_CLEARSILVER_TEMPLATE, "clearsilver_template1.cs"); +} + +void test_detector_basic() { + ASSERT_DETECT(LANG_VISUALBASIC, "visual_basic.bas"); + ASSERT_DETECT(LANG_CLASSIC_BASIC, "classic_basic.b"); + system("mv ../detect_files/frx1.frx ../detect_files/frx1.frx2"); + ASSERT_DETECT(LANG_STRUCTURED_BASIC, "visual_basic.bas"); + ASSERT_DETECT(LANG_STRUCTURED_BASIC, "structured_basic.b"); + system("mv ../detect_files/frx1.frx2 ../detect_files/frx1.frx"); +} + +void test_detector_xml_with_custom_extension() { + ASSERT_DETECT(LANG_XML, "xml.custom_ext"); +} + +void all_detector_tests() { + test_detector_smalltalk(); + test_detector_disambiguate_m(); + test_detector_disambiguate_pro(); + test_detector_fortran_fixedfree(); + test_detector_detect_polyglot(); + test_detector_upper_case_extensions(); + test_detector_no_extensions(); + test_detector_csharp_or_clearsilver(); + test_detector_basic(); + test_detector_xml_with_custom_extension(); +} diff --git a/.pc/rbconfig.patch/build b/.pc/rbconfig.patch/build new file mode 100755 index 0000000..a990737 --- /dev/null +++ b/.pc/rbconfig.patch/build @@ -0,0 +1,162 @@ +#!/usr/bin/env bash +# Build script for Ohcount. +# Written by Mitchell Foral. mitchellcaladbolg.net. + +# Options +# Change these for your system configuration. +if [ `uname` != "Darwin" ] +then + # Linux + INC_DIR= + LIB_DIR= + + if [ `uname` == "FreeBSD" ] + then + INC_DIR=/usr/local/include + LIB_DIR=/usr/local/lib + fi + + # You shouldn't have to change the following. + CFLAGS=-O3 + CFLAGS="$CFLAGS -DTMP_FILES_ARE_DT_UNKNOWN" # workaround bug on centos/SF servers + WARN="-Wall -Wno-pointer-to-int-cast -Wno-parentheses" + SHARED=-shared + SHARED_NAME=libohcount.so + RB_SHARED=-shared + RB_SHARED_NAME=ohcount.so +else + # Mac OSX + INC_DIR=/opt/local/include + LIB_DIR=/opt/local/lib + # You shouldn't have to change the following. + CFLAGS="-fno-common -g" + WARN="-Wall -Wno-parentheses" + SHARED="-dynamiclib -L$LIB_DIR -lpcre" + SHARED_NAME=libohcount.dylib + RB_SHARED="-dynamic -bundle -lruby" + RB_SHARED_NAME=ohcount.bundle +fi + +# C compiler and flags +cc="gcc -fPIC -g $CFLAGS $WARN -I$INC_DIR -L$LIB_DIR" + +# Ohcount source files +files="src/sourcefile.c \ + src/detector.c \ + src/licenses.c \ + src/parser.o \ + src/loc.c \ + src/log.c \ + src/diff.c \ + src/parsed_language.c \ + src/hash/language_hash.c" + +# If any src/hash/*.gperf file is newer than the header files (which were +# presumably generated together), regenerate the headers. +build_hash_headers() +{ + if [[ -z `ls src/hash/ | grep "_hash.h$"` || + ! -z `find src/hash/*.gperf -newer src/hash/parser_hash.h` ]] + then + echo "Generating hash headers" + sh -c "cd src/hash/ && ./generate_headers" || exit 1 + fi +} + +# If src/parser.o does not exist, or if there are Ragel parsers or parser +# header files newer than the existing parser.o, recompile parser.o. +build_parser_o() +{ + if [[ ! -f src/parser.o || + ! -z `find src/parsers/*.{h,rl} -newer src/parser.o` ]] + then + bash -c "cd src/parsers/ && bash ./compile" || exit 1 + echo "Building src/parser.c (will take a while)" + bash -c "$cc -c src/parser.c -o src/parser.o" || exit 1 + fi +} + +build_shared() +{ + build_hash_headers + build_parser_o + if [[ ! -f src/$SHARED_NAME || + ! -z `find src/*.{h,c} -newer src/$SHARED_NAME` ]] + then + echo "Building shared library" + sh -c "$cc $SHARED $files -o src/$SHARED_NAME" || exit 1 + fi +} + +build_ohcount() +{ + build_hash_headers + build_parser_o + echo "Building Ohcount" + mkdir -p bin/ + sh -c "$cc src/ohcount.c $files -o bin/ohcount -lpcre" || exit 1 +} + +build_test_suite() +{ + build_hash_headers + build_parser_o + echo "Building test suite" + sh -c "$cc test/unit/all_tests.c $files -o test/unit/run_tests -lpcre" \ + || exit 1 +} + +run_test_suite() +{ + echo "Running test suite" + echo "disabled test suite, does not work" +} + +build_ruby_bindings() +{ + arch=`ruby -rmkmf -e 'print Config::expand(CONFIG["arch"])'` + echo "Generating Ruby bindings for $arch" + sh -c "swig -ruby -o ruby/ohcount_wrap.c ruby/ohcount.i" || exit 1 + mkdir -p ruby/$arch + sh -c "$cc $RB_SHARED ruby/ohcount_wrap.c $files -o ruby/$arch/$RB_SHARED_NAME \ + -I`ruby -rmkmf -e 'print Config::expand(CONFIG["archdir"])'` \ + -lpcre" || exit 1 + sh -c "cd test/unit/ruby && ruby ruby_test.rb" || exit 1 +} + +if [ $# -eq 0 ] || [ $1 == "all" ] +then + build_ohcount + build_test_suite + run_test_suite + echo $success +elif [ $1 == "shared" ] +then + build_shared + echo "Build successful; $SHARED_NAME is in src/" +elif [ $1 == "ohcount" ] +then + build_ohcount + echo "Build successful; ohcount is in bin/" +elif [ $1 == "tests" ] +then + build_test_suite + run_test_suite +elif [ $1 == "ruby" ] +then + build_ruby_bindings + echo "Build successful; $RB_SHARED_NAME is in ruby/$arch" +elif [ $1 == "clean" ] +then + rm -f bin/ohcount + rm -f test/unit/run_tests + rm -f src/parser.o + rm -f src/parsers/*.h + rm -f src/hash/*.h + rm -f src/hash/*.c + rm -f src/$SHARED_NAME + rm -f ruby/$RB_SHARED_NAME + rm -rf ruby/`ruby -rmkmf -e 'print Config::expand(CONFIG["arch"])'`/* +else + echo "Usage: build [all|ohcount|shared|tests|ruby|clean]" +fi diff --git a/.pc/txx_support.patch/src/hash/extensions.gperf b/.pc/txx_support.patch/src/hash/extensions.gperf new file mode 100644 index 0000000..fcadae6 --- /dev/null +++ b/.pc/txx_support.patch/src/hash/extensions.gperf @@ -0,0 +1,181 @@ +%{ +#include "../languages.h" + +#define BINARY "\1" +#define DISAMBIGUATE(x) ("\2" x) +%} +struct ExtensionMap { const char *key; const char *value; }; +%% +C, LANG_CPP +H, LANG_CPP +ada, LANG_ADA +adb, LANG_ADA +ads, LANG_ADA +aiff, BINARY +as, LANG_ACTIONSCRIPT +ascx, DISAMBIGUATE("aspx") +asm, LANG_ASSEMBLER +aspx, DISAMBIGUATE("aspx") +au, BINARY +avi, BINARY +awk, LANG_AWK +b, DISAMBIGUATE("b") +bas, DISAMBIGUATE("basic") +bat, LANG_BAT +bi, DISAMBIGUATE("basic") +bmp, BINARY +bmx, LANG_BLITZMAX +boo, LANG_BOO +c, LANG_C +c++, LANG_CPP +cache, BINARY +cc, LANG_CPP +cmake, LANG_CMAKE +com, LANG_DCL +cpp, LANG_CPP +cs, DISAMBIGUATE("cs") +csproj, LANG_XML +css, LANG_CSS +ctp, LANG_PHP +cxx, LANG_CPP +d, LANG_DMD +dat, BINARY +di, LANG_DMD +doc, BINARY +dylan, LANG_DYLAN +e, LANG_EIFFEL +ebuild, LANG_EBUILD +eclass, LANG_EBUILD +el, LANG_EMACSLISP +erl, LANG_ERLANG +exheres-0, LANG_EXHERES +exlib, LANG_EXHERES +f, DISAMBIGUATE("fortran") +f03, DISAMBIGUATE("fortran") +f77, DISAMBIGUATE("fortran") +f90, DISAMBIGUATE("fortran") +f95, DISAMBIGUATE("fortran") +factor, LANG_FACTOR +frag, LANG_GLSL +frm, LANG_VISUALBASIC +frx, LANG_VISUALBASIC +fs, LANG_FSHARP +ftn, DISAMBIGUATE("fortran") +gif, BINARY +glsl, LANG_GLSL +groovy, LANG_GROOVY +gz, BINARY +h, DISAMBIGUATE("h") +h++, LANG_CPP +haml, LANG_HAML +hh, LANG_CPP +hpp, LANG_CPP +hrl, LANG_ERLANG +hs, LANG_HASKELL +htm, LANG_HTML +html, LANG_HTML +hx, LANG_HAXE +hxx, LANG_CPP +icns, BINARY +in, DISAMBIGUATE("in") +inc, DISAMBIGUATE("inc") +j, LANG_OBJECTIVE_J +jar, BINARY +java, LANG_JAVA +jpeg, BINARY +jpg, BINARY +js, LANG_JAVASCRIPT +jsp, LANG_JSP +kdebuild-1, LANG_EBUILD +latex, LANG_TEX +lisp, LANG_LISP +lsp, LANG_LISP +ltx, LANG_TEX +lua, LANG_LUA +m, DISAMBIGUATE("m") +m4a, BINARY +mf, LANG_METAFONT +mk, LANG_MAKE +ml, LANG_OCAML +ml4, LANG_OCAML +mli, LANG_OCAML +mm, LANG_OBJECTIVE_C +mov, BINARY +mp, LANG_METAPOST_WITH_TEX +mp3, BINARY +mpg, BINARY +mxml, LANG_MXML +nix, LANG_NIX +nse, LANG_LUA +ogg, BINARY +p6, LANG_PERL +pas, LANG_PASCAL +perl, LANG_PERL +pdf, BINARY +ph, LANG_PERL +php, LANG_PHP +php3, LANG_PHP +php4, LANG_PHP +php5, LANG_PHP +pike, LANG_PIKE +pl, LANG_PERL +pm, LANG_PERL +pmc, LANG_C +pmod, LANG_PIKE +png, BINARY +pnt, BINARY +pod, LANG_PERL +pp, LANG_PASCAL +ppt, BINARY +pro, DISAMBIGUATE("pro") +py, LANG_PYTHON +qt, BINARY +r, LANG_R +ra, BINARY +rb, LANG_RUBY +rex, LANG_REXX +rexx, LANG_REXX +rhtml, LANG_RHTML +s, LANG_ASSEMBLER +sc, LANG_SCHEME +scala, LANG_SCALA +sce, LANG_SCILAB +sci, LANG_SCILAB +scm, LANG_SCHEME +sh, LANG_SHELL +sls, LANG_SCHEME +sps, LANG_SCHEME +sql, LANG_SQL +ss, LANG_SCHEME +st, DISAMBIGUATE("st") +str, LANG_STRATEGO +svg, BINARY +svgz, BINARY +svn, BINARY +swf, BINARY +t, LANG_PERL +tar, BINARY +tcl, LANG_TCL +tex, LANG_TEX +tgz, BINARY +tif, BINARY +tiff, BINARY +tpl, LANG_HTML +vala, LANG_VALA +vb, LANG_VISUALBASIC +vba, LANG_VISUALBASIC +vbs, LANG_VISUALBASIC +vert, LANG_GLSL +vhd, LANG_VHDL +vhdl, LANG_VHDL +vim, LANG_VIM +wav, BINARY +xaml, LANG_XAML +xls, BINARY +xlw, BINARY +xml, LANG_XML +xs, LANG_C +xsd, LANG_XMLSCHEMA +xsl, LANG_XSLT +z80, LANG_ASSEMBLER +zip, BINARY 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..dfea440 --- /dev/null +++ b/README @@ -0,0 +1,90 @@ +== Ohcount + +NOTE: THE PRIMARY DOCUMENTATION FOR OHCOUNT IS EXTRACTED FROM SOURCE CODE +BY DOXYGEN. FOR THE MOST UP-TO-DATE DOCS, PLEASE SEE BELOW FOR INFO +ON BUILDING AND REFERING TO THE DOXYGEN DOCS. + +Ohloh/SourceForge's source code line counter. + +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, see . + +== 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 includes a command line tool 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 10.5 and Ubuntu 8.04 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 requires a bash shell. You +also need a C compiler to build the native extensions. + +== Source Code == + +Ohcount source code is available as a Git repository: + + git clone git://github.com/andyverprauskus/ohcount.git + +== Doc files == + +To build the more extensive Doxygen docs, do + > cd doc + > Doxygen Doxyfile + +After building the docs, view them with a browser by opening doc/html/index.html. +On a mac, you can install Doxygen with "sudo port install Doxygen". +On Debian/Ubuntu, install with "sudo apt-get instal doxygen". + +== Building Ohcount == + +You will need ragel 6.3 or higher, bash, pcre, gcc (version 4.1.2 or greater) and SWIG to build ohcount. Once you have them, go to the top directory of ohcount and type: + + > bash build +or > ./build + +== Using Ohcount == + +Once you've building ohcount, the executable program will be at bin/ohcount. The most basic use is to count lines of code in a directory tree, run: + "ohcount" to count the current directory and source code in any child directories + +== For additional docs, including how to add a new language, see the Doxygen docs == + +Particularly, for instructions on adding a new language, follow the instructions at doc/html/detector_doc.html +Read http://labs.ohloh.net/ohcount/wiki/HowToSubmitPatches for information about having your patch accepted. + + +DEPENDENCIES +============ +SWIG, pcre, ragel, bash diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..49431e2 --- /dev/null +++ b/Rakefile @@ -0,0 +1,11 @@ +task :default => [:build_all] + +task :build_all => [:build, :build_ruby] + +task :build do + system "./build" +end + +task :build_ruby do + system "./build ruby" +end diff --git a/build b/build new file mode 100755 index 0000000..235834d --- /dev/null +++ b/build @@ -0,0 +1,162 @@ +#!/usr/bin/env bash +# Build script for Ohcount. +# Written by Mitchell Foral. mitchellcaladbolg.net. + +# Options +# Change these for your system configuration. +if [ `uname` != "Darwin" ] +then + # Linux + INC_DIR= + LIB_DIR= + + if [ `uname` == "FreeBSD" ] + then + INC_DIR=/usr/local/include + LIB_DIR=/usr/local/lib + fi + + # You shouldn't have to change the following. + CFLAGS=-O3 + CFLAGS="$CFLAGS -DTMP_FILES_ARE_DT_UNKNOWN" # workaround bug on centos/SF servers + WARN="-Wall -Wno-pointer-to-int-cast -Wno-parentheses" + SHARED=-shared + SHARED_NAME=libohcount.so + RB_SHARED=-shared + RB_SHARED_NAME=ohcount.so +else + # Mac OSX + INC_DIR=/opt/local/include + LIB_DIR=/opt/local/lib + # You shouldn't have to change the following. + CFLAGS="-fno-common -g" + WARN="-Wall -Wno-parentheses" + SHARED="-dynamiclib -L$LIB_DIR -lpcre" + SHARED_NAME=libohcount.dylib + RB_SHARED="-dynamic -bundle -lruby" + RB_SHARED_NAME=ohcount.bundle +fi + +# C compiler and flags +cc="gcc -fPIC -g $CFLAGS $WARN -I$INC_DIR -L$LIB_DIR" + +# Ohcount source files +files="src/sourcefile.c \ + src/detector.c \ + src/licenses.c \ + src/parser.o \ + src/loc.c \ + src/log.c \ + src/diff.c \ + src/parsed_language.c \ + src/hash/language_hash.c" + +# If any src/hash/*.gperf file is newer than the header files (which were +# presumably generated together), regenerate the headers. +build_hash_headers() +{ + if [[ -z `ls src/hash/ | grep "_hash.h$"` || + ! -z `find src/hash/*.gperf -newer src/hash/parser_hash.h` ]] + then + echo "Generating hash headers" + sh -c "cd src/hash/ && ./generate_headers" || exit 1 + fi +} + +# If src/parser.o does not exist, or if there are Ragel parsers or parser +# header files newer than the existing parser.o, recompile parser.o. +build_parser_o() +{ + if [[ ! -f src/parser.o || + ! -z `find src/parsers/*.{h,rl} -newer src/parser.o` ]] + then + bash -c "cd src/parsers/ && bash ./compile" || exit 1 + echo "Building src/parser.c (will take a while)" + bash -c "$cc -c src/parser.c -o src/parser.o" || exit 1 + fi +} + +build_shared() +{ + build_hash_headers + build_parser_o + if [[ ! -f src/$SHARED_NAME || + ! -z `find src/*.{h,c} -newer src/$SHARED_NAME` ]] + then + echo "Building shared library" + sh -c "$cc $SHARED $files -o src/$SHARED_NAME" || exit 1 + fi +} + +build_ohcount() +{ + build_hash_headers + build_parser_o + echo "Building Ohcount" + mkdir -p bin/ + sh -c "$cc src/ohcount.c $files -o bin/ohcount -lpcre" || exit 1 +} + +build_test_suite() +{ + build_hash_headers + build_parser_o + echo "Building test suite" + sh -c "$cc test/unit/all_tests.c $files -o test/unit/run_tests -lpcre" \ + || exit 1 +} + +run_test_suite() +{ + echo "Running test suite" + echo "disabled test suite, does not work" +} + +build_ruby_bindings() +{ + arch=`ruby -rmkmf -e 'print RbConfig::expand(RbConfig::CONFIG["arch"])'` + echo "Generating Ruby bindings for $arch" + sh -c "swig -ruby -o ruby/ohcount_wrap.c ruby/ohcount.i" || exit 1 + mkdir -p ruby/$arch + sh -c "$cc $RB_SHARED ruby/ohcount_wrap.c $files -o ruby/$arch/$RB_SHARED_NAME \ + -I`ruby -rmkmf -e 'print RbConfig::expand(RbConfig::CONFIG["archdir"])'` \ + -lpcre" || exit 1 + sh -c "cd test/unit/ruby && ruby ruby_test.rb" || exit 1 +} + +if [ $# -eq 0 ] || [ $1 == "all" ] +then + build_ohcount + build_test_suite + run_test_suite + echo $success +elif [ $1 == "shared" ] +then + build_shared + echo "Build successful; $SHARED_NAME is in src/" +elif [ $1 == "ohcount" ] +then + build_ohcount + echo "Build successful; ohcount is in bin/" +elif [ $1 == "tests" ] +then + build_test_suite + run_test_suite +elif [ $1 == "ruby" ] +then + build_ruby_bindings + echo "Build successful; $RB_SHARED_NAME is in ruby/$arch" +elif [ $1 == "clean" ] +then + rm -f bin/ohcount + rm -f test/unit/run_tests + rm -f src/parser.o + rm -f src/parsers/*.h + rm -f src/hash/*.h + rm -f src/hash/*.c + rm -f src/$SHARED_NAME + rm -f ruby/$RB_SHARED_NAME + rm -rf ruby/`ruby -rmkmf -e 'print RbConfig::expand(RbConfig::CONFIG["arch"])'`/* +else + echo "Usage: build [all|ohcount|shared|tests|ruby|clean]" +fi diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..10d577b --- /dev/null +++ b/debian/changelog @@ -0,0 +1,111 @@ +ohcount (3.0.0-8.3) unstable; urgency=medium + + * Non-maintainer upload. + * Remove ruby files from ohcount-doc, which only get installed + when building for Arch: all. (Closes: #818239) + + -- Christian Hofstaedtler Thu, 22 Dec 2016 06:54:28 +0000 + +ohcount (3.0.0-8.2) unstable; urgency=medium + + * Non-maintainer upload. + * Source-ful, binary-less upload to get rid of /ruby directory. + Probably somehow my fault? (Closes: #818239) + + -- Christian Hofstaedtler Sun, 17 Jul 2016 19:58:32 +0000 + +ohcount (3.0.0-8.1) unstable; urgency=medium + + * Non-maintainer upload. + * Fix build system being broken by removal of deprecated "Config" + object in Ruby 2.2. (Closes: #805674) + + -- Christian Hofstaedtler Tue, 01 Mar 2016 22:02:31 +0100 + +ohcount (3.0.0-8) unstable; urgency=low + + * Remove the explicit dependency on ruby 1.8 + Thanks to Jonas Genannt (Closes: #733724) + * Switch from cdbs to dh. Thanks to Jonas Genannt + * Standards-Version updated to 3.9.5 + + -- Sylvestre Ledru Thu, 16 Jan 2014 16:26:45 +0100 + +ohcount (3.0.0-7) unstable; urgency=low + + * Standards-Version updated to 3.9.4 + * libdifflcs-ruby dep renamed to ruby-diff-lcs (Closes: #707792) + * Remove Torsten from the uploaders (I have been DD for a while :) + * ACK NMU (thanks btw) + + -- Sylvestre Ledru Sat, 11 May 2013 19:17:57 +0200 + +ohcount (3.0.0-6.1) unstable; urgency=low + + * Non-maintainer upload. + * Add dependency on file (Closes: #677494). + + -- Luk Claes Wed, 04 Jul 2012 17:18:12 +0000 + +ohcount (3.0.0-6) unstable; urgency=low + + * Update some issues with the documentation (Closes: #650685) + + -- Sylvestre Ledru Sat, 10 Dec 2011 19:38:15 +0100 + +ohcount (3.0.0-5) unstable; urgency=low + + * Oups. Plug back the patches + * Manpage of ohcount added + + -- Sylvestre Ledru Fri, 30 Sep 2011 21:37:34 +0200 + +ohcount (3.0.0-4) unstable; urgency=low + + * Support of the txx extension (considered as C++). Thanks to Sébastien Dinot + for the patch. + * Switch to dpkg-source 3.0 (quilt) format + * Standards-Version updated to version 3.9.2 + * Fix debian-rules-uses-deprecated-makefile lintian warning + + -- Sylvestre Ledru Mon, 26 Sep 2011 13:42:49 +0200 + +ohcount (3.0.0-3) unstable; urgency=low + + * Standards-Version updated to version 3.9.1 + * Fix a seg fault when checking lintian source code. Thanks to + Raphael Geissert for investigating for me. (Closes: #608837) + (LP: #605631) + * Fix lintian warning copyright-refers-to-deprecated-bsd-license-file + + -- Sylvestre Ledru Sat, 15 Jan 2011 09:34:05 +0100 + +ohcount (3.0.0-2) unstable; urgency=low + + * Missing dependency (Closes: #558491) + + -- Sylvestre Ledru Sun, 29 Nov 2009 18:19:46 +0100 + +ohcount (3.0.0-1) unstable; urgency=low + + * New upstream release + * New package ohcount-doc added + * Homepage updated + * Vcs-* added + * Many changes on the debian/rules due to a refactoring from upstream which + has been done (patches are now obsolete or upstream) + * Upstream has redeveloped ohcount with C (instead of ruby). (Closes: #542892) + * Update of the watch file + * Repack script updated (upstream has a .so) + * Standards-Version updated to version 3.8.3 + * Change of my email address since I am now DD + * Standards-Version updated to 3.8.3 + * DM-Upload-Allowed removed + + -- Sylvestre Ledru Fri, 27 Nov 2009 11:22:21 +0100 + +ohcount (2.0.1-1) unstable; urgency=low + + * Initial release (Closes: #523006) + + -- Sylvestre Ledru Tue, 07 Apr 2009 20:18:38 +0200 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +7 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..338638f --- /dev/null +++ b/debian/control @@ -0,0 +1,40 @@ +Source: ohcount +Section: utils +Priority: optional +Maintainer: Sylvestre Ledru +Build-Depends: debhelper (>= 7), libpcre3-dev, gem2deb, rake, + ragel (>= 6.3), ruby-diff-lcs, doxygen, gperf, file +Standards-Version: 3.9.5 +Homepage: http://sourceforge.net/projects/ohcount/ +Vcs-Svn: https://bollin.googlecode.com/svn/ohcount/trunk +Vcs-Browser: http://bollin.googlecode.com/svn/ohcount/trunk +XS-Ruby-Versions: all + +Package: ohcount +XB-Ruby-Versions: ${ruby:Versions} +Architecture: any +Depends: ruby | ruby-interpreter, ${shlibs:Depends}, ${misc:Depends}, + ruby-diff-lcs, file +Suggests: ohcount-doc +Description: Source code line counter + Ohcount supports over 70 popular programming languages. + Ohcount does more than just count lines of code. It can also detect + popular open source licenses such as GPL within a large directory of source + code. It can also detect code that targets a particular programming API, + such as Win32 or KDE. + Ohcount is the line counter which powers http://www.ohloh.net/ + . + +Package: ohcount-doc +Section: doc +Architecture: all +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Source code line counter - Documentation + Ohcount supports over 70 popular programming languages. + Ohcount does more than just count lines of code. It can also detect + popular open source licenses such as GPL within a large directory of source + code. It can also detect code that targets a particular programming API, + such as Win32 or KDE. + Ohcount is the line counter which powers http://www.ohloh.net/ + . + This package contains the documentation. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..cae0691 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,132 @@ +This package was debianized by Sylvestre Ledru on +Tue, 07 Apr 2009 20:18:38 +0200. + +It was downloaded from + +Upstream Author: + + Ohloh + +Copyright: + + Copyright (C) 2007-2009 Ohloh + +License: + + 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. + +The full text of the license can be found in +`/usr/share/common-licenses/GPL-2'. + +The Debian packaging is (C) 2009, Sylvestre Ledru and +is licensed under the GPL, see `/usr/share/common-licenses/GPL'. + +ohcount incorporates some piece of code in order to test during build time +its capabilities. These files are not included in the binary. + + +Files: test/expected_dir/haxe1.hx test/src_dir/haxe1.hx + +Copyright: + Thomas Pfeiffer - kiroukou + Niel Drummond + +License: + Copyright the original author or authors. + Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +Files: test/src_dir/pascal2.pp test/expected_dir/pascal2.pp + +Copyright: + Simon Steele 1998-2000 + +License: + BSD + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +Files: test/src_dir/js1.js test/expected_dir/js1.js + +Copyright: + 2005-2008 Sam Stephenson + +License: + MIT + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + +Files: test/src_dir/foo.ebuild test/detect_files/foo.ebuild + +License: + GPL-2 + +Files: test/src_dir/as1.as test/expected_dir/as1.as + +Copyright: + Sean Chatman and Garrett Woodworth 2008 + +License: + MIT + +Files: test/src_dir/perl_module.pm test/expected_dir/perl_module.pm + +Copyright: + Audrey Tang 2003-2007 + +License: + This program is free software; you can redistribute it and/or modify it + under the same terms as Perl itself. + + a) the GNU General Public License as published by the Free Software + Foundation; either version 1, or (at your option) any later + version, or + + b) the "Artistic License" which comes with Perl. + + On Debian GNU/Linux systems, the complete text of the GNU General + Public License can be found in `/usr/share/common-licenses/GPL' and + the Artistic Licence in `/usr/share/common-licenses/Artistic'. diff --git a/debian/ohcount-doc.doc-base b/debian/ohcount-doc.doc-base new file mode 100644 index 0000000..dbb3297 --- /dev/null +++ b/debian/ohcount-doc.doc-base @@ -0,0 +1,9 @@ +Document: ohcount +Title: Debian ohcount Manual +Author: Ohloh +Abstract: ohcount manual +Section: Programming/Ruby + +Format: HTML +Index: /usr/share/doc/ohcount-doc/index.html +Files: /usr/share/doc/ohcount-doc/* diff --git a/debian/ohcount-doc.docs b/debian/ohcount-doc.docs new file mode 100644 index 0000000..e845566 --- /dev/null +++ b/debian/ohcount-doc.docs @@ -0,0 +1 @@ +README diff --git a/debian/ohcount.1 b/debian/ohcount.1 new file mode 100644 index 0000000..4001863 --- /dev/null +++ b/debian/ohcount.1 @@ -0,0 +1,67 @@ +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.39.4. +.TH OHCOUNT "1" "September 2011" "ohcount 3.0.0" "User Commands" +.SH NAME +ohcount \- manual page for ohcount 3.0.0 +.SH SYNOPSIS +.B ohcount +[\fIoption\fR] [\fIpaths\fR...] +.SH DESCRIPTION +Ohloh source code line counter command line tool. +.IP +http://www.ohloh.net/ +.SS "[option] can be one of the following:" +.HP +\fB\-a\fR, \fB\-\-annotate\fR +.HP +\fB\-d\fR, \fB\-\-detect\fR +.HP +\fB\-h\fR, \fB\-\-help\fR +.HP +\fB\-i\fR, \fB\-\-individual\fR +.HP +\fB\-l\fR, \fB\-\-license\fR +.HP +\fB\-re\fR +.HP +\fB\-s\fR, \fB\-\-summary\fR +.PP +\fB\-a\fR, \fB\-\-annotate\fR Show annotated source code +.IP +The contents of all source code files found within the given +paths will be emitted to stdout. Each line will be prefixed with +a tab\-delimited language name and semantic categorization (code, +comment, or blank). +.PP +\fB\-d\fR, \fB\-\-detect\fR Find source code files +.IP +Recursively find all source code files within the given paths. +For each source code file found, the file name will be emitted to +stdout prefixed with a tab\-delimited language name. +.PP +\fB\-h\fR, \fB\-\-help\fR Display this message +.PP +\fB\-i\fR, \fB\-\-individual\fR Count lines of code per file +.IP +Count lines in all source code files within the given paths, and +emit a report of the lines of code, comments, and blanks in each +language per file. +.PP +\fB\-l\fR, \fB\-\-license\fR +.IP +Displays detected licensing information contained in each source +code file. +.PP +\fB\-re\fR +.IP +Prints raw entity information to the screen (mainly for debugging). +.PP +\fB\-s\fR, \fB\-\-summary\fR Count lines of code (default) +.IP +Count lines in all source code files within the given paths, and +emit a report of the total number of lines of code, comments, +and blanks in each language. This is the default action. +.PP +[paths] can refer to any number of individual files or directories. +.IP +Directories will be probed recursively. If no path is given, +the current directory will be used. diff --git a/debian/ohcount.manpages b/debian/ohcount.manpages new file mode 100644 index 0000000..fe3bc2c --- /dev/null +++ b/debian/ohcount.manpages @@ -0,0 +1,2 @@ +debian/ohcount.1 + diff --git a/debian/orig-tar.exclude b/debian/orig-tar.exclude new file mode 100644 index 0000000..140f8cf --- /dev/null +++ b/debian/orig-tar.exclude @@ -0,0 +1 @@ +*.so diff --git a/debian/orig-tar.sh b/debian/orig-tar.sh new file mode 100755 index 0000000..40c888c --- /dev/null +++ b/debian/orig-tar.sh @@ -0,0 +1,19 @@ +#!/bin/sh -e + +# called by uscan with '--upstream-version' +DIR=ohcount-$2 +TAR=../ohcount_$2.orig.tar.gz + +# clean up the upstream tarball +tar zxf $3 +# Remove vendor/ because it is including +tar -c -z -X debian/orig-tar.exclude -f $TAR $DIR/ +rm -rf $DIR + +# move to directory 'tarballs' +if [ -r .svn/deb-layout ]; then + . .svn/deb-layout + mv $TAR $origDir + echo "moved $TAR to $origDir" +fi + diff --git a/debian/patches/disabled_test_suite.patch b/debian/patches/disabled_test_suite.patch new file mode 100644 index 0000000..8e6f3c2 --- /dev/null +++ b/debian/patches/disabled_test_suite.patch @@ -0,0 +1,15 @@ +Description: disable test suite on build time, does not work +Author: Jonas Genannt +Forwarded: not-needed + +--- a/build ++++ b/build +@@ -109,7 +109,7 @@ build_test_suite() + run_test_suite() + { + echo "Running test suite" +- sh -c "cd test/unit/ && ./run_tests" ++ echo "disabled test suite, does not work" + } + + build_ruby_bindings() diff --git a/debian/patches/fix_null_dereference.patch b/debian/patches/fix_null_dereference.patch new file mode 100644 index 0000000..01271dd --- /dev/null +++ b/debian/patches/fix_null_dereference.patch @@ -0,0 +1,58 @@ +From a6783afcf61f18e9f1aef3e2655b30af7501c902 Mon Sep 17 00:00:00 2001 +From: Robin Luckey +Date: Thu, 1 Oct 2009 14:32:16 -0700 +Subject: [PATCH] [FIX] Avoid null dereference in disambiguate_inc() + +--- + src/detector.c | 18 ++++++++++-------- + test/unit/detector_test.h | 1 + + 2 files changed, 11 insertions(+), 8 deletions(-) + create mode 100644 test/detect_files/empty.inc + +diff --git a/src/detector.c b/src/detector.c +index 4d0e1f4..9b4d8d2 100644 +--- a/src/detector.c ++++ b/src/detector.c +@@ -452,14 +452,16 @@ const char *disambiguate_in(SourceFile *sourcefile) { + + const char *disambiguate_inc(SourceFile *sourcefile) { + char *p = ohcount_sourcefile_get_contents(sourcefile); +- char *eof = p + strlen(p); +- while (p < eof) { +- if (*p == '\0') +- return BINARY; +- else if (*p == '?' && strncmp(p + 1, "php", 3) == 0) +- return LANG_PHP; +- p++; +- } ++ if (p) { ++ char *eof = p + strlen(p); ++ while (p < eof) { ++ if (*p == '\0') ++ return BINARY; ++ else if (*p == '?' && strncmp(p + 1, "php", 3) == 0) ++ return LANG_PHP; ++ p++; ++ } ++ } + return NULL; + } + +diff --git a/test/detect_files/empty.inc b/test/detect_files/empty.inc +new file mode 100644 +index 0000000..e69de29 +diff --git a/test/unit/detector_test.h b/test/unit/detector_test.h +index cd36b6d..628b6cc 100644 +--- a/test/unit/detector_test.h ++++ b/test/unit/detector_test.h +@@ -77,6 +77,7 @@ void test_detector_detect_polyglot() { + ASSERT_DETECT(LANG_IDL_PVWAVE, "foo.pro"); + ASSERT_DETECT(LANG_ASSEMBLER, "foo.z80"); + ASSERT_DETECT(LANG_PHP, "php.inc"); ++ ASSERT_NODETECT("empty.inc"); + ASSERT_DETECT(LANG_FSHARP, "fs1.fs"); + } + +-- +1.7.0.1 + diff --git a/debian/patches/fix_null_dereference_2.patch b/debian/patches/fix_null_dereference_2.patch new file mode 100644 index 0000000..dd3c735 --- /dev/null +++ b/debian/patches/fix_null_dereference_2.patch @@ -0,0 +1,53 @@ +From c0b28d67f27f6e954c93dabd71d098854896d679 Mon Sep 17 00:00:00 2001 +From: Robin Luckey +Date: Thu, 1 Oct 2009 15:43:42 -0700 +Subject: [PATCH] [FIX] Null dereference error in disambiguate_in() + +--- + src/detector.c | 3 +++ + test/unit/detector_test.h | 4 ++++ + 2 files changed, 7 insertions(+), 0 deletions(-) + create mode 100644 test/detect_files/empty.in + +diff --git a/src/detector.c b/src/detector.c +index 9b4d8d2..863b379 100644 +--- a/src/detector.c ++++ b/src/detector.c +@@ -437,6 +437,9 @@ const char *disambiguate_in(SourceFile *sourcefile) { + buf[length] = '\0'; + SourceFile *undecorated = ohcount_sourcefile_new(buf); + p = ohcount_sourcefile_get_contents(sourcefile); ++ if (!p) { ++ return NULL; ++ } + // The filepath without the '.in' extension does not exist on disk. The + // sourcefile->diskpath field must be set incase the detector needs to run + // 'file -b' on the file. +diff --git a/test/detect_files/empty.in b/test/detect_files/empty.in +new file mode 100644 +index 0000000..e69de29 +diff --git a/test/unit/detector_test.h b/test/unit/detector_test.h +index 628b6cc..a26adaa 100644 +--- a/test/unit/detector_test.h ++++ b/test/unit/detector_test.h +@@ -36,6 +36,9 @@ void test_detector_disambiguate_m() { + ASSERT_DETECT(LANG_OCTAVE, "foo_octave.m"); + } + ++void test_detector_disambiguate_in() { ++ ASSERT_NODETECT("empty.in"); ++} + void test_detector_disambiguate_pro() { + ASSERT_DETECT(LANG_IDL_PVWAVE, "foo.pro"); + ASSERT_DETECT(LANG_MAKE, "qmake.pro"); +@@ -119,6 +122,7 @@ void test_detector_xml_with_custom_extension() { + void all_detector_tests() { + test_detector_smalltalk(); + test_detector_disambiguate_m(); ++ test_detector_disambiguate_in(); + test_detector_disambiguate_pro(); + test_detector_fortran_fixedfree(); + test_detector_detect_polyglot(); +-- +1.7.0.1 + diff --git a/debian/patches/rbconfig.patch b/debian/patches/rbconfig.patch new file mode 100644 index 0000000..123e773 --- /dev/null +++ b/debian/patches/rbconfig.patch @@ -0,0 +1,28 @@ +Index: ohcount-3.0.0/build +=================================================================== +--- ohcount-3.0.0.orig/build ++++ ohcount-3.0.0/build +@@ -114,12 +114,12 @@ run_test_suite() + + build_ruby_bindings() + { +- arch=`ruby -rmkmf -e 'print Config::expand(CONFIG["arch"])'` ++ arch=`ruby -rmkmf -e 'print RbConfig::expand(RbConfig::CONFIG["arch"])'` + echo "Generating Ruby bindings for $arch" + sh -c "swig -ruby -o ruby/ohcount_wrap.c ruby/ohcount.i" || exit 1 + mkdir -p ruby/$arch + sh -c "$cc $RB_SHARED ruby/ohcount_wrap.c $files -o ruby/$arch/$RB_SHARED_NAME \ +- -I`ruby -rmkmf -e 'print Config::expand(CONFIG["archdir"])'` \ ++ -I`ruby -rmkmf -e 'print RbConfig::expand(RbConfig::CONFIG["archdir"])'` \ + -lpcre" || exit 1 + sh -c "cd test/unit/ruby && ruby ruby_test.rb" || exit 1 + } +@@ -156,7 +156,7 @@ then + rm -f src/hash/*.c + rm -f src/$SHARED_NAME + rm -f ruby/$RB_SHARED_NAME +- rm -rf ruby/`ruby -rmkmf -e 'print Config::expand(CONFIG["arch"])'`/* ++ rm -rf ruby/`ruby -rmkmf -e 'print RbConfig::expand(RbConfig::CONFIG["arch"])'`/* + else + echo "Usage: build [all|ohcount|shared|tests|ruby|clean]" + fi diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..8ad8876 --- /dev/null +++ b/debian/patches/series @@ -0,0 +1,5 @@ +fix_null_dereference_2.patch +fix_null_dereference.patch +txx_support.patch +disabled_test_suite.patch +rbconfig.patch diff --git a/debian/patches/txx_support.patch b/debian/patches/txx_support.patch new file mode 100644 index 0000000..5f62401 --- /dev/null +++ b/debian/patches/txx_support.patch @@ -0,0 +1,12 @@ +diff -Naur ohcount-3.0.0/src/hash/extensions.gperf ohcount-3.0.1/src/hash/extensions.gperf +--- ohcount-3.0.0/src/hash/extensions.gperf 2009-09-30 17:30:19.000000000 +0000 ++++ ohcount-3.0.1/src/hash/extensions.gperf 2011-09-26 09:32:34.000000000 +0000 +@@ -161,6 +161,7 @@ + tif, BINARY + tiff, BINARY + tpl, LANG_HTML ++txx, LANG_CPP + vala, LANG_VALA + vb, LANG_VISUALBASIC + vba, LANG_VISUALBASIC + diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..71438b1 --- /dev/null +++ b/debian/rules @@ -0,0 +1,27 @@ +#!/usr/bin/make -f + +%: + dh $@ --buildsystem=ruby --with ruby + +override_dh_auto_clean: + dh_auto_clean -O--buildsystem=ruby + ./build clean + rm -rf doc_build + +override_dh_install: + ./build all + dh_install --buildsystem=ruby --with ruby + install -d debian/ohcount/usr/lib/ruby/vendor_ruby/ohcount + install -d debian/ohcount/usr/bin + install -d debian/ohcount-doc/usr/share/doc/ohcount-doc + cp bin/ohcount debian/ohcount/usr/bin/ + cp -R ruby/gestalt ruby/gestalt.rb ruby/ohcount.rb debian/ohcount/usr/lib/ruby/vendor_ruby/ohcount/ + # build doxygen + mkdir doc_build + cp -aR doc/* doc_build/ + (cd doc_build && doxygen Doxyfile) + cp -aR doc_build/html/* debian/ohcount-doc/usr/share/doc/ohcount-doc + rm -rf debian/ohcount/ruby debian/ohcount-doc/ruby + +get-orig-source: + uscan --force-download diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/debian/watch b/debian/watch new file mode 100644 index 0000000..89132f8 --- /dev/null +++ b/debian/watch @@ -0,0 +1,5 @@ +version=3 +http://sf.net/ohcount/ohcount-(\d+[0-9\-\.r]+)\.tar\.gz \ +debian debian/orig-tar.sh + + diff --git a/doc/Doxyfile b/doc/Doxyfile new file mode 100644 index 0000000..9493685 --- /dev/null +++ b/doc/Doxyfile @@ -0,0 +1,1473 @@ +# Doxyfile 1.5.7.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = ohcount + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, +# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, +# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene, +# Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = YES + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by +# doxygen. The layout file controls the global structure of the generated output files +# in an output format independent way. The create the layout file that represents +# doxygen's defaults, run doxygen with the -l option. You can optionally specify a +# file name after the option, if omitted DoxygenLayout.xml will be used as the name +# of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../src/ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = examples/ + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER +# are set, an additional index file will be generated that can be used as input for +# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated +# HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# Qt Help Project / Namespace. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# Qt Help Project / Virtual Folders. + +QHP_VIRTUAL_FOLDER = doc + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file . + +QHG_LOCATION = + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to FRAME, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. Other possible values +# for this tag are: HIERARCHIES, which will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list; +# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which +# disables this behavior completely. For backwards compatibility with previous +# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE +# respectively. + +GENERATE_TREEVIEW = NONE + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/doc/examples/parser_doc_1 b/doc/examples/parser_doc_1 new file mode 100644 index 0000000..fb7a4f9 --- /dev/null +++ b/doc/examples/parser_doc_1 @@ -0,0 +1,22 @@ +/************************* Required for every parser *************************/ +#ifndef OHCOUNT_C_PARSER_H +#define OHCOUNT_C_PARSER_H + +#include "../parser_macros.h" + +// the name of the language +const char *C_LANG = LANG_C; + +// the languages entities +const char *c_entities[] = { + "space", "comment", "string", "number", "preproc", + "keyword", "identifier", "operator", "any" +}; + +// constants associated with the entities +enum { + C_SPACE = 0, C_COMMENT, C_STRING, C_NUMBER, C_PREPROC, + C_KEYWORD, C_IDENTIFIER, C_OPERATOR, C_ANY +}; + +/*****************************************************************************/ diff --git a/doc/examples/parser_doc_2 b/doc/examples/parser_doc_2 new file mode 100644 index 0000000..d0571a7 --- /dev/null +++ b/doc/examples/parser_doc_2 @@ -0,0 +1,31 @@ +/************************* Required for every parser *************************/ + +/* Parses a string buffer with C/C++ code. + * + * @param *buffer The string to parse. + * @param length The length of the string to parse. + * @param count Integer flag specifying whether or not to count lines. If yes, + * uses the Ragel machine optimized for counting. Otherwise uses the Ragel + * machine optimized for returning entity positions. + * @param *callback Callback function. If count is set, callback is called for + * every line of code, comment, or blank with 'lcode', 'lcomment', and + * 'lblank' respectively. Otherwise callback is called for each entity found. + */ +void parse_c(char *buffer, int length, int count, + void (*callback) (const char *lang, const char *entity, int s, + int e, void *udata), + void *userdata + ) { + init + + %% write init; + cs = (count) ? c_en_c_line : c_en_c_entity; + %% write exec; + + // if no newline at EOF; callback contents of last line + if (count) { process_last_line(C_LANG) } +} + +#endif + +/*****************************************************************************/ diff --git a/doc/examples/parser_doc_3 b/doc/examples/parser_doc_3 new file mode 100644 index 0000000..f72667f --- /dev/null +++ b/doc/examples/parser_doc_3 @@ -0,0 +1,7 @@ +%%{ + machine c; + write data; + include "common.rl"; + + ... +}%% diff --git a/doc/examples/parser_doc_4 b/doc/examples/parser_doc_4 new file mode 100644 index 0000000..966dbd8 --- /dev/null +++ b/doc/examples/parser_doc_4 @@ -0,0 +1,6 @@ +[lang]_line := |* + entity1 ${ entity = ENTITY1; } => [lang]_ccallback; + entity2 ${ entity = ENTITY2; } => [lang]_ccallback; + ... + entityn ${ entity = ENTITYN; } => [lang]_ccallback; +*|; diff --git a/doc/examples/parser_doc_5 b/doc/examples/parser_doc_5 new file mode 100644 index 0000000..2d57ebd --- /dev/null +++ b/doc/examples/parser_doc_5 @@ -0,0 +1,14 @@ +action [lang]_ccallback { + switch(entity) { + when ENTITY1: + ... + break; + when ENTITY2: + ... + break; + ... + when ENTITYN: + ... + break; + } +} diff --git a/doc/examples/parser_doc_6 b/doc/examples/parser_doc_6 new file mode 100644 index 0000000..6358220 --- /dev/null +++ b/doc/examples/parser_doc_6 @@ -0,0 +1,2 @@ +[lang]_[elang]_entry @{ entity = CHECK_BLANK_ENTRY; } @[lang]_callback + @{ saw([elang]_LANG)} => { fcall [lang]_[elang]_line; }; diff --git a/doc/examples/parser_doc_7 b/doc/examples/parser_doc_7 new file mode 100644 index 0000000..ab02cc0 --- /dev/null +++ b/doc/examples/parser_doc_7 @@ -0,0 +1 @@ +@{ p = ts; fret; }; diff --git a/doc/examples/parser_doc_8 b/doc/examples/parser_doc_8 new file mode 100644 index 0000000..66ce8d6 --- /dev/null +++ b/doc/examples/parser_doc_8 @@ -0,0 +1,6 @@ +[lang]_entity := |* + entity1 ${ entity = ENTITY1; } => [lang]_ecallback; + entity2 ${ entity = ENTITY2; } => [lang]_ecallback; + ... + entityn ${ entity = ENTITYN; } => [lang]_ecallback; +*|; diff --git a/doc/examples/parser_doc_9 b/doc/examples/parser_doc_9 new file mode 100644 index 0000000..09368c4 --- /dev/null +++ b/doc/examples/parser_doc_9 @@ -0,0 +1,4 @@ +action [lang]_ecallback { + callback([lang]_LANG, [lang]_entities[entity], cint(ts), cint(te), + userdata); +} diff --git a/doc/html/annotated.html b/doc/html/annotated.html new file mode 100644 index 0000000..80ac2c1 --- /dev/null +++ b/doc/html/annotated.html @@ -0,0 +1,44 @@ + + +ohcount: Data Structures + + + + + +
+

Data Structures

Here are the data structures with brief descriptions: + + + + + + + + + + + + +
CallbackItemHolds a series of callbacks for in a queue (linked list)
LanguageMap
LicenseHolds a license and its associated details and patterns
LicenseListItemHolds a list of Licenses in a linked list
LocTracks total lines of code, comments, and blanks for a single language
LocDeltaTracks changes in lines of code, comments, and blank lines for a single language
LocDeltaListItemTracks changes in lines of code, comments, and blank lines for multiple languages using a linked list
LocListItemTracks total lines of code, comments, and blanks for multiple languages using a linked list
ParsedLanguageRepresents a single language parsed from a SourceFile
ParsedLanguageListItemHolds a set of ParsedLanguages in a linked list
SourceFileRepresents a single source code file
SourceFileListItemContains a set of SourceFiles
+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/classes.html b/doc/html/classes.html new file mode 100644 index 0000000..5a7d9f9 --- /dev/null +++ b/doc/html/classes.html @@ -0,0 +1,37 @@ + + +ohcount: Alphabetical List + + + + + +
+

Data Structure Index

C | L | P | S

+ +
  C  
+
License   LocDelta   
  P  
+
  S  
+
CallbackItem   LicenseListItem   LocDeltaListItem   ParsedLanguage   SourceFile   
  L  
+
Loc   LocListItem   ParsedLanguageListItem   SourceFileListItem   
LanguageMap   

C | L | P | S

+

+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/detector_8h.html b/doc/html/detector_8h.html new file mode 100644 index 0000000..836cd18 --- /dev/null +++ b/doc/html/detector_8h.html @@ -0,0 +1,88 @@ + + +ohcount: /Users/andy/dev/ohcount/src/detector.h File Reference + + + + + +
+

/Users/andy/dev/ohcount/src/detector.h File Reference

#include "sourcefile.h"
+ +

+Go to the source code of this file. + + + + + + +

Functions

const char * ohcount_detect_language (SourceFile *sourcefile)
int ohcount_is_binary_filename (const char *filename)
+


Function Documentation

+ +
+
+ + + + + + + + + +
const char* ohcount_detect_language (SourceFile sourcefile  ) 
+
+
+ +

+Attempts to detect the programming language used by the given file. The returned pointer is used internally and must not be 'free'd.

Parameters:
+ + +
sourcefile A SourceFile created by ohcount_sourcefile_new().
+
+
Returns:
pointer to a string with the detected language or NULL.
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_is_binary_filename (const char *  filename  ) 
+
+
+ +

+ +

+

+

+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/detector_8h_source.html b/doc/html/detector_8h_source.html new file mode 100644 index 0000000..96a2041 --- /dev/null +++ b/doc/html/detector_8h_source.html @@ -0,0 +1,41 @@ + + +ohcount: /Users/andy/dev/ohcount/src/detector.h Source File + + + + + +
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/detector_doc.html b/doc/html/detector_doc.html new file mode 100644 index 0000000..f7baa9f --- /dev/null +++ b/doc/html/detector_doc.html @@ -0,0 +1,34 @@ + + +ohcount: Detector Documentation + + + + + +
+

Detector Documentation

+How to Add a New Language

+
    +
  • Add your language to 'src/languages.h' and 'src/hash/languages.gperf'.
  • +
  • Update 'src/hash/extensions.gperf' to identify files that use the new language (or 'src/hash/filenames.gperf').
  • +
  • Regenerate the hash header files with 'src/hash/generate_headers'.
  • +
  • Add your tests to 'test/unit/detector_test.h', rebuild the tests, and run them to confirm the detector changes.
  • +
  • Follow the detailed instructions in the Parser Documentation.
  • +
  • Rebuild Ohcount.
  • +
+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/diff_8h.html b/doc/html/diff_8h.html new file mode 100644 index 0000000..567d719 --- /dev/null +++ b/doc/html/diff_8h.html @@ -0,0 +1,88 @@ + + +ohcount: /Users/andy/dev/ohcount/src/diff.h File Reference + + + + + +
+

/Users/andy/dev/ohcount/src/diff.h File Reference

+

+Go to the source code of this file. + + + + +

Functions

void ohcount_calc_diff (const char *from, const char *to, int *added, int *removed)
+


Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void ohcount_calc_diff (const char *  from,
const char *  to,
int *  added,
int *  removed 
)
+
+
+ +

+Computes the diff between the lines of two given string buffers. The results are stored in the passed integer pointers. Note: The algorithm discussed mentions a check being performed to find lines matched incorrectly due to hashing; it is not in this implementation.

Parameters:
+ + + + + +
from The diff 'from' buffer.
to The diff 'to' buffer.
added Int pointer the number of lines added result is stored to.
removed Int pointer the number of lines removed result is stored to.
+
+ +
+

+

+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/diff_8h_source.html b/doc/html/diff_8h_source.html new file mode 100644 index 0000000..c88d82f --- /dev/null +++ b/doc/html/diff_8h_source.html @@ -0,0 +1,38 @@ + + +ohcount: /Users/andy/dev/ohcount/src/diff.h Source File + + + + + +
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/doxygen.css b/doc/html/doxygen.css new file mode 100644 index 0000000..3767dc9 --- /dev/null +++ b/doc/html/doxygen.css @@ -0,0 +1,441 @@ +body, table, div, p, dl { + font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; + font-size: 12px; +} + +/* @group Heading Levels */ + +h1 { + text-align: center; + font-size: 150%; +} + +h2 { + font-size: 120%; +} + +h3 { + font-size: 100%; +} + +/* @end */ + +caption { + font-weight: bold; +} + +div.qindex, div.navtab{ + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #153788; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #1b77c5; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #6666cc; + color: #ffffff; + border: 1px double #9295C2; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code { +} + +a.codeRef { +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +.fragment { + font-family: monospace, fixed; + font-size: 105%; +} + +pre.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + padding: 4px 6px; + margin: 4px 8px 4px 2px; +} + +div.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background: white; + color: black; + margin-right: 20px; + margin-left: 20px; +} + +td.indexkey { + background-color: #e8eef2; + font-weight: bold; + border: 1px solid #CCCCCC; + margin: 2px 0px 2px 0; + padding: 2px 10px; +} + +td.indexvalue { + background-color: #e8eef2; + border: 1px solid #CCCCCC; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #f0f0f0; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +/* @end */ + +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #84b0c7; +} + +th.dirtab { + background: #e8eef2; + font-weight: bold; +} + +hr { + height: 0; + border: none; + border-top: 1px solid #666; +} + +/* @group Member Descriptions */ + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #FAFAFA; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memItemLeft, .memItemRight, .memTemplParams { + border-top: 1px solid #ccc; +} + +.memTemplParams { + color: #606060; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #606060; + font-weight: normal; + margin-left: 3px; +} + +.memnav { + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.memitem { + padding: 0; +} + +.memname { + white-space: nowrap; + font-weight: bold; +} + +.memproto, .memdoc { + border: 1px solid #84b0c7; +} + +.memproto { + padding: 0; + background-color: #d5e1e8; + font-weight: bold; + -webkit-border-top-left-radius: 8px; + -webkit-border-top-right-radius: 8px; + -moz-border-radius-topleft: 8px; + -moz-border-radius-topright: 8px; +} + +.memdoc { + padding: 2px 5px; + background-color: #eef3f5; + border-top-width: 0; + -webkit-border-bottom-left-radius: 8px; + -webkit-border-bottom-right-radius: 8px; + -moz-border-radius-bottomleft: 8px; + -moz-border-radius-bottomright: 8px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} + +/* @end */ + +/* @group Directory (tree) */ + +/* for the tree view */ + +.ftvtree { + font-family: sans-serif; + margin: 0.5em; +} + +/* these are for tree view when used as main index */ + +.directory { + font-size: 9pt; + font-weight: bold; +} + +.directory h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} + +/* +The following two styles can be used to replace the root node title +with an image of your choice. Simply uncomment the next two styles, +specify the name of your image and be sure to set 'height' to the +proper pixel height of your image. +*/ + +/* +.directory h3.swap { + height: 61px; + background-repeat: no-repeat; + background-image: url("yourimage.gif"); +} +.directory h3.swap span { + display: none; +} +*/ + +.directory > h3 { + margin-top: 0; +} + +.directory p { + margin: 0px; + white-space: nowrap; +} + +.directory div { + display: none; + margin: 0px; +} + +.directory img { + vertical-align: -30%; +} + +/* these are for tree view when not used as main index */ + +.directory-alt { + font-size: 100%; + font-weight: bold; +} + +.directory-alt h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} + +.directory-alt > h3 { + margin-top: 0; +} + +.directory-alt p { + margin: 0px; + white-space: nowrap; +} + +.directory-alt div { + display: none; + margin: 0px; +} + +.directory-alt img { + vertical-align: -30%; +} + +/* @end */ + +address { + font-style: normal; + color: #333; +} diff --git a/doc/html/doxygen.png b/doc/html/doxygen.png new file mode 100644 index 0000000..f0a274b Binary files /dev/null and b/doc/html/doxygen.png differ diff --git a/doc/html/files.html b/doc/html/files.html new file mode 100644 index 0000000..0e2970a --- /dev/null +++ b/doc/html/files.html @@ -0,0 +1,44 @@ + + +ohcount: File Index + + + + + +
+

File List

Here is a list of all files with brief descriptions: + + + + + + + + + + + + +
/Users/andy/dev/ohcount/src/detector.h [code]
/Users/andy/dev/ohcount/src/diff.h [code]
/Users/andy/dev/ohcount/src/languages.h [code]
/Users/andy/dev/ohcount/src/licenses.h [code]
/Users/andy/dev/ohcount/src/loc.h [code]
/Users/andy/dev/ohcount/src/log.h [code]
/Users/andy/dev/ohcount/src/ohcount.h [code]
/Users/andy/dev/ohcount/src/parsed_language.h [code]
/Users/andy/dev/ohcount/src/parser.h [code]
/Users/andy/dev/ohcount/src/parser_macros.h [code]
/Users/andy/dev/ohcount/src/sourcefile.h [code]
/Users/andy/dev/ohcount/src/structs.h [code]
+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/functions.html b/doc/html/functions.html new file mode 100644 index 0000000..e95a55d --- /dev/null +++ b/doc/html/functions.html @@ -0,0 +1,210 @@ + + +ohcount: Data Fields + + + + + +
+Here is a list of all struct and union fields with links to the structures/unions they belong to: +

+

- b -

+

- c -

+

- d -

+

- e -

+

- f -

+

- h -

+

- k -

+

- l -

+

- n -

+

- p -

+

- r -

+

- s -

+

- t -

+

- u -

+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/functions_vars.html b/doc/html/functions_vars.html new file mode 100644 index 0000000..01fc096 --- /dev/null +++ b/doc/html/functions_vars.html @@ -0,0 +1,210 @@ + + +ohcount: Data Fields - Variables + + + + + +
+  +

+

- b -

+

- c -

+

- d -

+

- e -

+

- f -

+

- h -

+

- k -

+

- l -

+

- n -

+

- p -

+

- r -

+

- s -

+

- t -

+

- u -

+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/globals.html b/doc/html/globals.html new file mode 100644 index 0000000..ebd6084 --- /dev/null +++ b/doc/html/globals.html @@ -0,0 +1,63 @@ + + +ohcount: Data Fields + + + + + +
+Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to: +

+

- a -

+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/globals_0x62.html b/doc/html/globals_0x62.html new file mode 100644 index 0000000..6eb7dc6 --- /dev/null +++ b/doc/html/globals_0x62.html @@ -0,0 +1,63 @@ + + +ohcount: Data Fields + + + + + +
+Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to: +

+

- b -

+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/globals_0x63.html b/doc/html/globals_0x63.html new file mode 100644 index 0000000..36c0c3c --- /dev/null +++ b/doc/html/globals_0x63.html @@ -0,0 +1,93 @@ + + +ohcount: Data Fields + + + + + +
+Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to: +

+

- c -

+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/globals_0x64.html b/doc/html/globals_0x64.html new file mode 100644 index 0000000..72947cc --- /dev/null +++ b/doc/html/globals_0x64.html @@ -0,0 +1,63 @@ + + +ohcount: Data Fields + + + + + +
+Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to: +

+

- d -

+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/globals_0x65.html b/doc/html/globals_0x65.html new file mode 100644 index 0000000..9d50b6b --- /dev/null +++ b/doc/html/globals_0x65.html @@ -0,0 +1,71 @@ + + +ohcount: Data Fields + + + + + +
+Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to: +

+

- e -

+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/globals_0x66.html b/doc/html/globals_0x66.html new file mode 100644 index 0000000..bc9aabd --- /dev/null +++ b/doc/html/globals_0x66.html @@ -0,0 +1,63 @@ + + +ohcount: Data Fields + + + + + +
+Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to: +

+

- f -

+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/globals_0x69.html b/doc/html/globals_0x69.html new file mode 100644 index 0000000..3eb6b98 --- /dev/null +++ b/doc/html/globals_0x69.html @@ -0,0 +1,69 @@ + + +ohcount: Data Fields + + + + + +
+Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to: +

+

- i -

+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/globals_0x6c.html b/doc/html/globals_0x6c.html new file mode 100644 index 0000000..2232fbb --- /dev/null +++ b/doc/html/globals_0x6c.html @@ -0,0 +1,385 @@ + + +ohcount: Data Fields + + + + + +
+Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to: +

+

- l -

+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/globals_0x6e.html b/doc/html/globals_0x6e.html new file mode 100644 index 0000000..23cebe8 --- /dev/null +++ b/doc/html/globals_0x6e.html @@ -0,0 +1,63 @@ + + +ohcount: Data Fields + + + + + +
+Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to: +

+

- n -

+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/globals_0x6f.html b/doc/html/globals_0x6f.html new file mode 100644 index 0000000..fe4d0a3 --- /dev/null +++ b/doc/html/globals_0x6f.html @@ -0,0 +1,217 @@ + + +ohcount: Data Fields + + + + + +
+Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to: +

+

- o -

    +
  • ohcount_calc_diff() +: diff.h +
  • ohcount_detect_language() +: detector.h +
  • ohcount_detect_license() +: licenses.h +
  • ohcount_hash_language_from_name() +: languages.h +
  • ohcount_is_binary_filename() +: detector.h +
  • ohcount_license_list_free() +: licenses.h +
  • ohcount_license_list_new() +: licenses.h +
  • ohcount_loc_add_loc() +: loc.h +
  • ohcount_loc_delta_add_loc_delta() +: loc.h +
  • ohcount_loc_delta_free() +: loc.h +
  • ohcount_loc_delta_is_changed() +: loc.h +
  • ohcount_loc_delta_is_equal() +: loc.h +
  • ohcount_loc_delta_list_add_loc_delta() +: loc.h +
  • ohcount_loc_delta_list_add_loc_delta_list() +: loc.h +
  • ohcount_loc_delta_list_blanks_added() +: loc.h +
  • ohcount_loc_delta_list_blanks_removed() +: loc.h +
  • ohcount_loc_delta_list_code_added() +: loc.h +
  • ohcount_loc_delta_list_code_removed() +: loc.h +
  • ohcount_loc_delta_list_comments_added() +: loc.h +
  • ohcount_loc_delta_list_comments_removed() +: loc.h +
  • ohcount_loc_delta_list_free() +: loc.h +
  • ohcount_loc_delta_list_get_loc_delta() +: loc.h +
  • ohcount_loc_delta_list_net_blanks() +: loc.h +
  • ohcount_loc_delta_list_net_code() +: loc.h +
  • ohcount_loc_delta_list_net_comments() +: loc.h +
  • ohcount_loc_delta_list_net_total() +: loc.h +
  • ohcount_loc_delta_list_new() +: loc.h +
  • ohcount_loc_delta_list_new_compact() +: loc.h +
  • ohcount_loc_delta_net_blanks() +: loc.h +
  • ohcount_loc_delta_net_code() +: loc.h +
  • ohcount_loc_delta_net_comments() +: loc.h +
  • ohcount_loc_delta_net_total() +: loc.h +
  • ohcount_loc_delta_new() +: loc.h +
  • ohcount_loc_free() +: loc.h +
  • ohcount_loc_is_equal() +: loc.h +
  • ohcount_loc_list_add_loc() +: loc.h +
  • ohcount_loc_list_add_loc_list() +: loc.h +
  • ohcount_loc_list_blanks() +: loc.h +
  • ohcount_loc_list_code() +: loc.h +
  • ohcount_loc_list_comments() +: loc.h +
  • ohcount_loc_list_filecount() +: loc.h +
  • ohcount_loc_list_free() +: loc.h +
  • ohcount_loc_list_get_loc() +: loc.h +
  • ohcount_loc_list_new() +: loc.h +
  • ohcount_loc_list_new_compact() +: loc.h +
  • ohcount_loc_list_total() +: loc.h +
  • ohcount_loc_new() +: loc.h +
  • ohcount_loc_total() +: loc.h +
  • ohcount_parse() +: parser.h +
  • ohcount_parsed_language_add_code() +: parsed_language.h +
  • ohcount_parsed_language_add_comment() +: parsed_language.h +
  • ohcount_parsed_language_free() +: parsed_language.h +
  • ohcount_parsed_language_list_free() +: parsed_language.h +
  • ohcount_parsed_language_list_new() +: parsed_language.h +
  • ohcount_parsed_language_new() +: parsed_language.h +
  • ohcount_sourcefile_calc_loc_delta() +: sourcefile.h +
  • ohcount_sourcefile_diff() +: sourcefile.h +
  • ohcount_sourcefile_free() +: sourcefile.h +
  • ohcount_sourcefile_get_contents() +: sourcefile.h +
  • ohcount_sourcefile_get_contents_size() +: sourcefile.h +
  • ohcount_sourcefile_get_filenames() +: sourcefile.h +
  • ohcount_sourcefile_get_language() +: sourcefile.h +
  • ohcount_sourcefile_get_license_list() +: sourcefile.h +
  • ohcount_sourcefile_get_loc_list() +: sourcefile.h +
  • ohcount_sourcefile_get_parsed_language_list() +: sourcefile.h +
  • ohcount_sourcefile_list_add_directory() +: sourcefile.h +
  • ohcount_sourcefile_list_add_file() +: sourcefile.h +
  • ohcount_sourcefile_list_analyze_languages() +: sourcefile.h +
  • ohcount_sourcefile_list_free() +: sourcefile.h +
  • ohcount_sourcefile_list_new() +: sourcefile.h +
  • ohcount_sourcefile_new() +: sourcefile.h +
  • ohcount_sourcefile_parse() +: sourcefile.h +
  • ohcount_sourcefile_parse_entities_with_callback() +: sourcefile.h +
  • ohcount_sourcefile_parse_with_callback() +: sourcefile.h +
  • ohcount_sourcefile_set_contents() +: sourcefile.h +
  • ohcount_sourcefile_set_diskpath() +: sourcefile.h +
  • ohcount_sourcefile_set_filenames() +: sourcefile.h +
  • ohcount_sourcefile_set_language() +: sourcefile.h +
+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/globals_0x70.html b/doc/html/globals_0x70.html new file mode 100644 index 0000000..7fc75a4 --- /dev/null +++ b/doc/html/globals_0x70.html @@ -0,0 +1,69 @@ + + +ohcount: Data Fields + + + + + +
+Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to: +

+

- p -

+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/globals_0x73.html b/doc/html/globals_0x73.html new file mode 100644 index 0000000..81bd8de --- /dev/null +++ b/doc/html/globals_0x73.html @@ -0,0 +1,73 @@ + + +ohcount: Data Fields + + + + + +
+Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to: +

+

- s -

+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/globals_0x74.html b/doc/html/globals_0x74.html new file mode 100644 index 0000000..81e332d --- /dev/null +++ b/doc/html/globals_0x74.html @@ -0,0 +1,67 @@ + + +ohcount: Data Fields + + + + + +
+Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to: +

+

- t -

+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/globals_0x77.html b/doc/html/globals_0x77.html new file mode 100644 index 0000000..566e5d5 --- /dev/null +++ b/doc/html/globals_0x77.html @@ -0,0 +1,63 @@ + + +ohcount: Data Fields + + + + + +
+Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to: +

+

- w -

+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/globals_defs.html b/doc/html/globals_defs.html new file mode 100644 index 0000000..e89305b --- /dev/null +++ b/doc/html/globals_defs.html @@ -0,0 +1,421 @@ + + +ohcount: Data Fields + + + + + +
+  +

+

- c -

+

- d -

+

- e -

+

- i -

+

- l -

+

- n -

+

- p -

+

- s -

+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/globals_func.html b/doc/html/globals_func.html new file mode 100644 index 0000000..a84a553 --- /dev/null +++ b/doc/html/globals_func.html @@ -0,0 +1,219 @@ + + +ohcount: Data Fields + + + + + +
+  +

+

- e -

+

- f -

+

- i -

+

- o -

    +
  • ohcount_calc_diff() +: diff.h +
  • ohcount_detect_language() +: detector.h +
  • ohcount_detect_license() +: licenses.h +
  • ohcount_hash_language_from_name() +: languages.h +
  • ohcount_is_binary_filename() +: detector.h +
  • ohcount_license_list_free() +: licenses.h +
  • ohcount_license_list_new() +: licenses.h +
  • ohcount_loc_add_loc() +: loc.h +
  • ohcount_loc_delta_add_loc_delta() +: loc.h +
  • ohcount_loc_delta_free() +: loc.h +
  • ohcount_loc_delta_is_changed() +: loc.h +
  • ohcount_loc_delta_is_equal() +: loc.h +
  • ohcount_loc_delta_list_add_loc_delta() +: loc.h +
  • ohcount_loc_delta_list_add_loc_delta_list() +: loc.h +
  • ohcount_loc_delta_list_blanks_added() +: loc.h +
  • ohcount_loc_delta_list_blanks_removed() +: loc.h +
  • ohcount_loc_delta_list_code_added() +: loc.h +
  • ohcount_loc_delta_list_code_removed() +: loc.h +
  • ohcount_loc_delta_list_comments_added() +: loc.h +
  • ohcount_loc_delta_list_comments_removed() +: loc.h +
  • ohcount_loc_delta_list_free() +: loc.h +
  • ohcount_loc_delta_list_get_loc_delta() +: loc.h +
  • ohcount_loc_delta_list_net_blanks() +: loc.h +
  • ohcount_loc_delta_list_net_code() +: loc.h +
  • ohcount_loc_delta_list_net_comments() +: loc.h +
  • ohcount_loc_delta_list_net_total() +: loc.h +
  • ohcount_loc_delta_list_new() +: loc.h +
  • ohcount_loc_delta_list_new_compact() +: loc.h +
  • ohcount_loc_delta_net_blanks() +: loc.h +
  • ohcount_loc_delta_net_code() +: loc.h +
  • ohcount_loc_delta_net_comments() +: loc.h +
  • ohcount_loc_delta_net_total() +: loc.h +
  • ohcount_loc_delta_new() +: loc.h +
  • ohcount_loc_free() +: loc.h +
  • ohcount_loc_is_equal() +: loc.h +
  • ohcount_loc_list_add_loc() +: loc.h +
  • ohcount_loc_list_add_loc_list() +: loc.h +
  • ohcount_loc_list_blanks() +: loc.h +
  • ohcount_loc_list_code() +: loc.h +
  • ohcount_loc_list_comments() +: loc.h +
  • ohcount_loc_list_filecount() +: loc.h +
  • ohcount_loc_list_free() +: loc.h +
  • ohcount_loc_list_get_loc() +: loc.h +
  • ohcount_loc_list_new() +: loc.h +
  • ohcount_loc_list_new_compact() +: loc.h +
  • ohcount_loc_list_total() +: loc.h +
  • ohcount_loc_new() +: loc.h +
  • ohcount_loc_total() +: loc.h +
  • ohcount_parse() +: parser.h +
  • ohcount_parsed_language_add_code() +: parsed_language.h +
  • ohcount_parsed_language_add_comment() +: parsed_language.h +
  • ohcount_parsed_language_free() +: parsed_language.h +
  • ohcount_parsed_language_list_free() +: parsed_language.h +
  • ohcount_parsed_language_list_new() +: parsed_language.h +
  • ohcount_parsed_language_new() +: parsed_language.h +
  • ohcount_sourcefile_calc_loc_delta() +: sourcefile.h +
  • ohcount_sourcefile_diff() +: sourcefile.h +
  • ohcount_sourcefile_free() +: sourcefile.h +
  • ohcount_sourcefile_get_contents() +: sourcefile.h +
  • ohcount_sourcefile_get_contents_size() +: sourcefile.h +
  • ohcount_sourcefile_get_filenames() +: sourcefile.h +
  • ohcount_sourcefile_get_language() +: sourcefile.h +
  • ohcount_sourcefile_get_license_list() +: sourcefile.h +
  • ohcount_sourcefile_get_loc_list() +: sourcefile.h +
  • ohcount_sourcefile_get_parsed_language_list() +: sourcefile.h +
  • ohcount_sourcefile_list_add_directory() +: sourcefile.h +
  • ohcount_sourcefile_list_add_file() +: sourcefile.h +
  • ohcount_sourcefile_list_analyze_languages() +: sourcefile.h +
  • ohcount_sourcefile_list_free() +: sourcefile.h +
  • ohcount_sourcefile_list_new() +: sourcefile.h +
  • ohcount_sourcefile_new() +: sourcefile.h +
  • ohcount_sourcefile_parse() +: sourcefile.h +
  • ohcount_sourcefile_parse_entities_with_callback() +: sourcefile.h +
  • ohcount_sourcefile_parse_with_callback() +: sourcefile.h +
  • ohcount_sourcefile_set_contents() +: sourcefile.h +
  • ohcount_sourcefile_set_diskpath() +: sourcefile.h +
  • ohcount_sourcefile_set_filenames() +: sourcefile.h +
  • ohcount_sourcefile_set_language() +: sourcefile.h +
+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/globals_type.html b/doc/html/globals_type.html new file mode 100644 index 0000000..5058ec6 --- /dev/null +++ b/doc/html/globals_type.html @@ -0,0 +1,55 @@ + + +ohcount: Data Fields + + + + + +
+  +

+

+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/globals_vars.html b/doc/html/globals_vars.html new file mode 100644 index 0000000..d053321 --- /dev/null +++ b/doc/html/globals_vars.html @@ -0,0 +1,85 @@ + + +ohcount: Data Fields + + + + + +
+  +

+

+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/index.html b/doc/html/index.html new file mode 100644 index 0000000..9a76636 --- /dev/null +++ b/doc/html/index.html @@ -0,0 +1,85 @@ + + +ohcount: Ohcount + + + + + +
+

Ohcount

+

+The Ohloh source code line counter

+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, see <http://www.gnu.org/licenses/>.

+Overview

+Ohcount is a program for counting lines of source code. It was originally developed at Ohloh and 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 4 main components:

+

    +
  • A detector which determines the primary language family used by a particular source file.
  • +
  • A parser which provides a line-by-line breakdown of the contents of a source file.
  • +
  • Another detector which tries to determine the license(s) the source file is licensed under.
  • +
  • A final detector for gestalts (via the Ruby extension).
  • +
+The command line tool allows you to profile individual files or whole directory trees.

+System Requirements

+Ohcount is supported on Mac OSX 10.5 and Ubuntu 6.06 LTS. Other Linux environments should also work, but your mileage may vary. Windows is not supported.

+Download

+Ohcount source code is available as a Git repository:

+git clone git://ohcount.git.sourceforge.net/gitroot/ohcount/ohcount

+Building Ohcount

+In order to build Ohcount, the following is required:

+

+Run the 'build' script to build Ohcount.

+

 $ ./build
+

+You may then link or copy 'bin/ohcount' to your system's PATH.

+Building the Ruby extension of Ohcount requires:

+

+
 $ ./build ruby
+

+You may then link or copy 'ruby/ohcount.{rb,so}' and 'ruby/gestalt{/,.rb}' to the appropriate places in your Ruby installation.

+First Steps

+To measure lines of code, simply pass file or directory names to the bin/ohcount executable:

+

 $ 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
+

+More options can be found by typing:

+

 $ ohcount --help
+

+Additional Documentation

+See the Related Pages tab at the top of the page.

+Contact Ohloh

+For more information visit the Ohloh website: http://labs.ohloh.net

+You can reach Ohloh via email at: info@ohloh.net

+
Generated on Fri Aug 28 16:26:52 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/languages_8h.html b/doc/html/languages_8h.html new file mode 100644 index 0000000..ecb8162 --- /dev/null +++ b/doc/html/languages_8h.html @@ -0,0 +1,1451 @@ + + +ohcount: /Users/andy/dev/ohcount/src/languages.h File Reference + + + + + +
+

/Users/andy/dev/ohcount/src/languages.h File Reference

#include <string.h>
+ +

+Go to the source code of this file. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Data Structures

struct  LanguageMap

Defines

#define LANG_ACTIONSCRIPT   "actionscript"
#define LANG_ADA   "ada"
#define LANG_ASSEMBLER   "assembler"
#define LANG_AUTOCONF   "autoconf"
#define LANG_AUTOMAKE   "automake"
#define LANG_AWK   "awk"
#define LANG_BAT   "bat"
#define LANG_BLITZMAX   "blitzmax"
#define LANG_BOO   "boo"
#define LANG_C   "c"
#define LANG_CLASSIC_BASIC   "classic_basic"
#define LANG_CLEARSILVER   "clearsilver"
#define LANG_CLEARSILVER_TEMPLATE   "clearsilver_template"
#define LANG_CMAKE   "cmake"
#define LANG_CPP   "cpp"
#define LANG_CS_ASPX   "cs_aspx"
#define LANG_CSHARP   "csharp"
#define LANG_CSS   "css"
#define LANG_DCL   "dcl"
#define LANG_DMD   "dmd"
#define LANG_DYLAN   "dylan"
#define LANG_EBUILD   "ebuild"
#define LANG_EIFFEL   "eiffel"
#define LANG_ERLANG   "erlang"
#define LANG_EXHERES   "exheres"
#define LANG_EMACSLISP   "emacslisp"
#define LANG_FACTOR   "factor"
#define LANG_FORTRANFIXED   "fortranfixed"
#define LANG_FORTRANFREE   "fortranfree"
#define LANG_GLSL   "glsl"
#define LANG_GROOVY   "groovy"
#define LANG_HASKELL   "haskell"
#define LANG_HAML   "haml"
#define LANG_HAXE   "haxe"
#define LANG_HTML   "html"
#define LANG_IDL_PVWAVE   "idl_pvwave"
#define LANG_JAVA   "java"
#define LANG_JAVASCRIPT   "javascript"
#define LANG_JSP   "jsp"
#define LANG_LIMBO   "limbo"
#define LANG_LISP   "lisp"
#define LANG_LUA   "lua"
#define LANG_MAKE   "make"
#define LANG_MATLAB   "matlab"
#define LANG_METAFONT   "metafont"
#define LANG_METAPOST   "metapost"
#define LANG_METAPOST_WITH_TEX   "metapost_with_tex"
#define LANG_MXML   "mxml"
#define LANG_NIX   "nix"
#define LANG_OBJECTIVE_C   "objective_c"
#define LANG_OBJECTIVE_J   "objective_j"
#define LANG_OCAML   "ocaml"
#define LANG_OCTAVE   "octave"
#define LANG_PASCAL   "pascal"
#define LANG_PERL   "perl"
#define LANG_PHP   "php"
#define LANG_PIKE   "pike"
#define LANG_PYTHON   "python"
#define LANG_R   "r"
#define LANG_REXX   "rexx"
#define LANG_RHTML   "rhtml"
#define LANG_RUBY   "ruby"
#define LANG_SCALA   "scala"
#define LANG_SCHEME   "scheme"
#define LANG_SCILAB   "scilab"
#define LANG_SHELL   "shell"
#define LANG_SMALLTALK   "smalltalk"
#define LANG_STRATEGO   "stratego"
#define LANG_STRUCTURED_BASIC   "structured_basic"
#define LANG_SQL   "sql"
#define LANG_TCL   "tcl"
#define LANG_TEX   "tex"
#define LANG_VALA   "vala"
#define LANG_VB_ASPX   "vb_aspx"
#define LANG_VHDL   "vhdl"
#define LANG_VIM   "vim"
#define LANG_VISUALBASIC   "visualbasic"
#define LANG_XAML   "xaml"
#define LANG_XML   "xml"
#define LANG_XSLT   "xslt"
#define LANG_XMLSCHEMA   "xmlschema"

Functions

struct LanguageMapohcount_hash_language_from_name (register const char *str, register unsigned int len)
+


Define Documentation

+ +
+
+ + + + +
#define LANG_ACTIONSCRIPT   "actionscript"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_ADA   "ada"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_ASSEMBLER   "assembler"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_AUTOCONF   "autoconf"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_AUTOMAKE   "automake"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_AWK   "awk"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_BAT   "bat"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_BLITZMAX   "blitzmax"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_BOO   "boo"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_C   "c"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_CLASSIC_BASIC   "classic_basic"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_CLEARSILVER   "clearsilver"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_CLEARSILVER_TEMPLATE   "clearsilver_template"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_CMAKE   "cmake"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_CPP   "cpp"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_CS_ASPX   "cs_aspx"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_CSHARP   "csharp"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_CSS   "css"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_DCL   "dcl"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_DMD   "dmd"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_DYLAN   "dylan"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_EBUILD   "ebuild"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_EIFFEL   "eiffel"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_EMACSLISP   "emacslisp"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_ERLANG   "erlang"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_EXHERES   "exheres"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_FACTOR   "factor"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_FORTRANFIXED   "fortranfixed"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_FORTRANFREE   "fortranfree"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_GLSL   "glsl"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_GROOVY   "groovy"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_HAML   "haml"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_HASKELL   "haskell"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_HAXE   "haxe"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_HTML   "html"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_IDL_PVWAVE   "idl_pvwave"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_JAVA   "java"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_JAVASCRIPT   "javascript"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_JSP   "jsp"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_LIMBO   "limbo"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_LISP   "lisp"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_LUA   "lua"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_MAKE   "make"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_MATLAB   "matlab"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_METAFONT   "metafont"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_METAPOST   "metapost"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_METAPOST_WITH_TEX   "metapost_with_tex"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_MXML   "mxml"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_NIX   "nix"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_OBJECTIVE_C   "objective_c"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_OBJECTIVE_J   "objective_j"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_OCAML   "ocaml"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_OCTAVE   "octave"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_PASCAL   "pascal"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_PERL   "perl"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_PHP   "php"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_PIKE   "pike"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_PYTHON   "python"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_R   "r"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_REXX   "rexx"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_RHTML   "rhtml"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_RUBY   "ruby"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_SCALA   "scala"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_SCHEME   "scheme"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_SCILAB   "scilab"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_SHELL   "shell"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_SMALLTALK   "smalltalk"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_SQL   "sql"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_STRATEGO   "stratego"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_STRUCTURED_BASIC   "structured_basic"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_TCL   "tcl"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_TEX   "tex"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_VALA   "vala"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_VB_ASPX   "vb_aspx"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_VHDL   "vhdl"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_VIM   "vim"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_VISUALBASIC   "visualbasic"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_XAML   "xaml"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_XML   "xml"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_XMLSCHEMA   "xmlschema"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LANG_XSLT   "xslt"
+
+
+ +

+ +

+

+


Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
struct LanguageMap* ohcount_hash_language_from_name (register const char *  str,
register unsigned int  len 
) [read]
+
+
+ +

+ +

+

+

+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/languages_8h_source.html b/doc/html/languages_8h_source.html new file mode 100644 index 0000000..35d7587 --- /dev/null +++ b/doc/html/languages_8h_source.html @@ -0,0 +1,123 @@ + + +ohcount: /Users/andy/dev/ohcount/src/languages.h Source File + + + + + +
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/license_doc.html b/doc/html/license_doc.html new file mode 100644 index 0000000..e288366 --- /dev/null +++ b/doc/html/license_doc.html @@ -0,0 +1,33 @@ + + +ohcount: License Documentation + + + + + +
+

License Documentation

Author:
Mitchell Foral
+

+How to Add a New License

+
    +
  • Add your license to 'src/licenses.h' and 'src/licenses.c'. Don't forget that two '\'s are required to represent one '\' in a C string.
  • +
  • Add your tests to the 'test/src_licenses/' and 'test/expected_licenses/' directories. Note that multiple licenses must be separated by newlines and be in the order they appear in the input file.
  • +
  • Run the test suite (a rebuild is not necessary; your added tests are detected and run automatically) to verify your licenses are correctly detected.
  • +
  • Rebuild Ohcount.
  • +
+
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/licenses_8h.html b/doc/html/licenses_8h.html new file mode 100644 index 0000000..fc0c660 --- /dev/null +++ b/doc/html/licenses_8h.html @@ -0,0 +1,1324 @@ + + +ohcount: /Users/andy/dev/ohcount/src/licenses.h File Reference + + + + + +
+

/Users/andy/dev/ohcount/src/licenses.h File Reference

#include "sourcefile.h"
+ +

+Go to the source code of this file. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Defines

#define LIC_ACADEMIC   "academic"
#define LIC_ADAPTIVE   "adaptive"
#define LIC_AFFERO   "affero"
#define LIC_APACHE   "apache"
#define LIC_APACHE2   "apache_2"
#define LIC_APPLE_OPEN_SOURCE   "apple_open_source"
#define LIC_ARTISTIC   "artistic"
#define LIC_ATTRIBUTION_ASSURANCE   "attribution_assurance"
#define LIC_BOOST   "boost"
#define LIC_BSD   "bsd"
#define LIC_CECILL   "cecill"
#define LIC_CECILL_B   "cecill_b"
#define LIC_CECILL_C   "cecill_c"
#define LIC_COMPUTER_ASSOCIATES_TRUSTED   "computer_associates_trusted"
#define LIC_COMMON_DEVELOPMENT_AND_DISTRIBUTION   "common_development_and_distribution"
#define LIC_COMMON_PUBLIC   "common_public"
#define LIC_CUA_OFFICE   "cua_office"
#define LIC_EU_DATAGRID   "eu_datagrid"
#define LIC_ECLIPSE   "eclipse"
#define LIC_EDUCATIONAL   "educational"
#define LIC_EIFFEL   "eiffel"
#define LIC_EIFFEL2   "eiffel_2"
#define LIC_ENTESSA   "entessa"
#define LIC_FAIR   "fair"
#define LIC_FRAMEWORX   "frameworx"
#define LIC_GPL3_OR_LATER   "gpl3_or_later"
#define LIC_GPL3   "gpl3"
#define LIC_LGPL3   "lgpl3"
#define LIC_GPL   "gpl"
#define LIC_LGPL   "lgpl"
#define LIC_HISTORICAL   "historical"
#define LIC_I9   "i9_license"
#define LIC_IBM_PUBLIC   "ibm_public"
#define LIC_INTEL_OPEN_SOURCE   "intel_open_source"
#define LIC_JABBER_OPEN_SOURCE   "jabber_open_source"
#define LIC_LUCENT_PLAN9   "lucent_plan9"
#define LIC_LUCENT_PUBLIC   "lucent_public"
#define LIC_MIT   "mit"
#define LIC_MITRE   "mitre"
#define LIC_MOTOSOTO   "motosoto"
#define LIC_MOZILLA_PUBLIC1   "mozilla_public_1"
#define LIC_MOZILLA_PUBLIC11   "mozilla_public_1_1"
#define LIC_NASA_OPEN   "nasa_open"
#define LIC_NAUMEN   "naumen"
#define LIC_NETHACK   "nethack"
#define LIC_NOKIA_OPEN_SOURCE   "nokia_open_source"
#define LIC_OCLC_RESEARCH   "oclc_research"
#define LIC_OPEN_GROUP_TEST   "open_group_test"
#define LIC_OPEN_SOFTWARE   "open_software"
#define LIC_PHP_LICENSE   "php_license"
#define LIC_PYTHON_LICENSE   "python_license"
#define LIC_PYTHON_SOFTWARE_FOUNDATION   "python_software_foundation"
#define LIC_QT_PUBLIC   "qt_public"
#define LIC_REALNETWORKS_PUBLIC_SOURCE   "realnetworks_public_source"
#define LIC_RECIPROCAL_PUBLIC   "reciprocal_public"
#define LIC_RICOH_SOURCE   "ricoh_source"
#define LIC_SLEEPYCAT   "sleepycat"
#define LIC_SUGARCRM113   "sugarcrm_1_1_3"
#define LIC_SUN_INDUSTRY_STANDARDS   "sun_industry_standards"
#define LIC_SUN_PUBLIC   "sun_public"
#define LIC_SYBASE_OPEN_WATCOM   "sybase_open_watcom"
#define LIC_U_OF_I_NCSA   "u_of_i_ncsa"
#define LIC_VOVIDA_SOFTWARE   "vovida_software"
#define LIC_W3C   "w3c"
#define LIC_WXWINDOWS   "wx_windows"
#define LIC_XNET   "x_net"
#define LIC_ZOPE   "zope"
#define LIC_ZLIB_LIBPNG   "zlib_libpng"
#define LIC_APACHE_ISH   "apache_ish"
#define LIC_BSD_ISH   "bsd_ish"
#define LIC_BSD_2CLAUSE_ISH   "bsd_2clause_ish"

Functions

LicenseListohcount_detect_license (SourceFile *sourcefile)
LicenseListohcount_license_list_new ()
void ohcount_license_list_free (LicenseList *list)
+


Define Documentation

+ +
+
+ + + + +
#define LIC_ACADEMIC   "academic"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_ADAPTIVE   "adaptive"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_AFFERO   "affero"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_APACHE   "apache"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_APACHE2   "apache_2"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_APACHE_ISH   "apache_ish"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_APPLE_OPEN_SOURCE   "apple_open_source"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_ARTISTIC   "artistic"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_ATTRIBUTION_ASSURANCE   "attribution_assurance"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_BOOST   "boost"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_BSD   "bsd"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_BSD_2CLAUSE_ISH   "bsd_2clause_ish"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_BSD_ISH   "bsd_ish"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_CECILL   "cecill"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_CECILL_B   "cecill_b"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_CECILL_C   "cecill_c"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_COMMON_DEVELOPMENT_AND_DISTRIBUTION   "common_development_and_distribution"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_COMMON_PUBLIC   "common_public"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_COMPUTER_ASSOCIATES_TRUSTED   "computer_associates_trusted"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_CUA_OFFICE   "cua_office"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_ECLIPSE   "eclipse"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_EDUCATIONAL   "educational"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_EIFFEL   "eiffel"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_EIFFEL2   "eiffel_2"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_ENTESSA   "entessa"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_EU_DATAGRID   "eu_datagrid"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_FAIR   "fair"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_FRAMEWORX   "frameworx"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_GPL   "gpl"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_GPL3   "gpl3"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_GPL3_OR_LATER   "gpl3_or_later"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_HISTORICAL   "historical"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_I9   "i9_license"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_IBM_PUBLIC   "ibm_public"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_INTEL_OPEN_SOURCE   "intel_open_source"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_JABBER_OPEN_SOURCE   "jabber_open_source"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_LGPL   "lgpl"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_LGPL3   "lgpl3"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_LUCENT_PLAN9   "lucent_plan9"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_LUCENT_PUBLIC   "lucent_public"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_MIT   "mit"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_MITRE   "mitre"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_MOTOSOTO   "motosoto"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_MOZILLA_PUBLIC1   "mozilla_public_1"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_MOZILLA_PUBLIC11   "mozilla_public_1_1"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_NASA_OPEN   "nasa_open"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_NAUMEN   "naumen"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_NETHACK   "nethack"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_NOKIA_OPEN_SOURCE   "nokia_open_source"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_OCLC_RESEARCH   "oclc_research"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_OPEN_GROUP_TEST   "open_group_test"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_OPEN_SOFTWARE   "open_software"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_PHP_LICENSE   "php_license"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_PYTHON_LICENSE   "python_license"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_PYTHON_SOFTWARE_FOUNDATION   "python_software_foundation"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_QT_PUBLIC   "qt_public"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_REALNETWORKS_PUBLIC_SOURCE   "realnetworks_public_source"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_RECIPROCAL_PUBLIC   "reciprocal_public"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_RICOH_SOURCE   "ricoh_source"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_SLEEPYCAT   "sleepycat"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_SUGARCRM113   "sugarcrm_1_1_3"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_SUN_INDUSTRY_STANDARDS   "sun_industry_standards"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_SUN_PUBLIC   "sun_public"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_SYBASE_OPEN_WATCOM   "sybase_open_watcom"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_U_OF_I_NCSA   "u_of_i_ncsa"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_VOVIDA_SOFTWARE   "vovida_software"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_W3C   "w3c"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_WXWINDOWS   "wx_windows"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_XNET   "x_net"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_ZLIB_LIBPNG   "zlib_libpng"
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define LIC_ZOPE   "zope"
+
+
+ +

+ +

+

+


Function Documentation

+ +
+
+ + + + + + + + + +
LicenseList* ohcount_detect_license (SourceFile sourcefile  ) 
+
+
+ +

+Attempts to detect the source code licenses for a given file. It searches comment text in source files for any mention of known licenses, but unfortunately catches things like: "I find the GNU Public License dumb".

Parameters:
+ + +
sourcefile A SourceFile created by ohcount_sourcefile_new().
+
+
Returns:
LicenseList
+ +
+

+ +

+
+ + + + + + + + + +
void ohcount_license_list_free (LicenseList list  ) 
+
+
+ +

+Frees the memory allocated for the given LicenseList.

Parameters:
+ + +
list A LicenseList created from ohcount_license_list_new().
+
+ +
+

+ +

+
+ + + + + + + + +
LicenseList* ohcount_license_list_new (  ) 
+
+
+ +

+Creates a new LicenseList that is initially empty.

Returns:
LicenseList
+ +
+

+

+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/licenses_8h_source.html b/doc/html/licenses_8h_source.html new file mode 100644 index 0000000..3ed6cfd --- /dev/null +++ b/doc/html/licenses_8h_source.html @@ -0,0 +1,116 @@ + + +ohcount: /Users/andy/dev/ohcount/src/licenses.h Source File + + + + + +
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/loc_8h.html b/doc/html/loc_8h.html new file mode 100644 index 0000000..45ecd09 --- /dev/null +++ b/doc/html/loc_8h.html @@ -0,0 +1,1315 @@ + + +ohcount: /Users/andy/dev/ohcount/src/loc.h File Reference + + + + + +
+

/Users/andy/dev/ohcount/src/loc.h File Reference

#include "structs.h"
+ +

+Go to the source code of this file. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Functions

Locohcount_loc_new (const char *language, int code, int comments, int blanks, int filecount)
int ohcount_loc_total (Loc *loc)
void ohcount_loc_add_loc (Loc *loc, Loc *other)
int ohcount_loc_is_equal (Loc *loc, Loc *other)
void ohcount_loc_free (Loc *loc)
LocListohcount_loc_list_new ()
void ohcount_loc_list_add_loc (LocList *list, Loc *loc)
void ohcount_loc_list_add_loc_list (LocList *list, LocList *loc_list)
Locohcount_loc_list_get_loc (LocList *list, const char *language)
int ohcount_loc_list_code (LocList *list)
int ohcount_loc_list_comments (LocList *list)
int ohcount_loc_list_blanks (LocList *list)
int ohcount_loc_list_total (LocList *list)
int ohcount_loc_list_filecount (LocList *list)
LocListohcount_loc_list_new_compact (LocList *list)
void ohcount_loc_list_free (LocList *list)
LocDeltaohcount_loc_delta_new (const char *language, int code_added, int code_removed, int comments_added, int comments_removed, int blanks_added, int blanks_removed)
int ohcount_loc_delta_net_code (LocDelta *delta)
int ohcount_loc_delta_net_comments (LocDelta *delta)
int ohcount_loc_delta_net_blanks (LocDelta *delta)
int ohcount_loc_delta_net_total (LocDelta *delta)
void ohcount_loc_delta_add_loc_delta (LocDelta *delta, LocDelta *other)
int ohcount_loc_delta_is_changed (LocDelta *delta)
int ohcount_loc_delta_is_equal (LocDelta *delta, LocDelta *other)
void ohcount_loc_delta_free (LocDelta *delta)
LocDeltaListohcount_loc_delta_list_new ()
void ohcount_loc_delta_list_add_loc_delta (LocDeltaList *list, LocDelta *delta)
void ohcount_loc_delta_list_add_loc_delta_list (LocDeltaList *list, LocDeltaList *loc_delta_list)
LocDeltaohcount_loc_delta_list_get_loc_delta (LocDeltaList *list, const char *language)
int ohcount_loc_delta_list_code_added (LocDeltaList *list)
int ohcount_loc_delta_list_code_removed (LocDeltaList *list)
int ohcount_loc_delta_list_comments_added (LocDeltaList *list)
int ohcount_loc_delta_list_comments_removed (LocDeltaList *list)
int ohcount_loc_delta_list_blanks_added (LocDeltaList *list)
int ohcount_loc_delta_list_blanks_removed (LocDeltaList *list)
int ohcount_loc_delta_list_net_code (LocDeltaList *list)
int ohcount_loc_delta_list_net_comments (LocDeltaList *list)
int ohcount_loc_delta_list_net_blanks (LocDeltaList *list)
int ohcount_loc_delta_list_net_total (LocDeltaList *list)
LocDeltaListohcount_loc_delta_list_new_compact (LocDeltaList *list)
void ohcount_loc_delta_list_free (LocDeltaList *list)
+


Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
void ohcount_loc_add_loc (Loc loc,
Loc other 
)
+
+
+ +

+Adds a Loc to another, provided they use the same language. The results are stored in the first Loc given. The second Loc may be 'free'd immediately.

Parameters:
+ + + +
loc A Loc created from ohcount_loc_new().
other Another Loc.
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
void ohcount_loc_delta_add_loc_delta (LocDelta delta,
LocDelta other 
)
+
+
+ +

+Adds a LocDelta to another, provided they use the same language. The results are stored in the first LocDelta given. The second LocDelta may be 'free'd immediately.

Parameters:
+ + + +
delta A LocDelta created from ohcount_loc_delta_new().
other Another LocDelta.
+
+ +
+

+ +

+
+ + + + + + + + + +
void ohcount_loc_delta_free (LocDelta delta  ) 
+
+
+ +

+Frees the memory allocated for a given LocDelta.

Parameters:
+ + +
delta A LocDelta created from ohcount_loc_delta_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_delta_is_changed (LocDelta delta  ) 
+
+
+ +

+Returns whether or not a given LocDelta has any line changes.

Parameters:
+ + +
delta A LocDelta created from ohcount_loc_delta_new().
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
int ohcount_loc_delta_is_equal (LocDelta delta,
LocDelta other 
)
+
+
+ +

+Returns whether or not two given LocDeltas are equivalent.

Parameters:
+ + + +
delta A LocDelta created from ohcount_loc_delta_new().
other Another LocDelta.
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
void ohcount_loc_delta_list_add_loc_delta (LocDeltaList list,
LocDelta delta 
)
+
+
+ +

+Adds a given LocDelta to a LocDeltaList. The given LocDelta is copied and may be 'free'd immediately.

Parameters:
+ + + +
list A LocDeltaList created from ohcount_loc_delta_list_new().
delta A LocDelta created from ohcount_loc_delta_new().
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
void ohcount_loc_delta_list_add_loc_delta_list (LocDeltaList list,
LocDeltaList loc_delta_list 
)
+
+
+ +

+Adds a given LocDeltaList to another LocDeltaList. The results are stored in the first LocDeltaList given. The second LocDeltaList may be 'free'd immediately.

Parameters:
+ + + +
list A LocDeltaList created from ohcount_loc_delta_list_new().
loc_delta_list Another LocDeltaList.
+
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_delta_list_blanks_added (LocDeltaList list  ) 
+
+
+ +

+Returns the number of blank lines added for the given LocDeltaList.

Parameters:
+ + +
list A LocDeltaList created from ohcount_loc_delta_list_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_delta_list_blanks_removed (LocDeltaList list  ) 
+
+
+ +

+Returns the number of blank lines removed for the given LocDeltaList.

Parameters:
+ + +
list A LocDeltaList created from ohcount_loc_delta_list_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_delta_list_code_added (LocDeltaList list  ) 
+
+
+ +

+Returns the number of lines of code added for the given LocDeltaList.

Parameters:
+ + +
list A LocDeltaList created from ohcount_loc_delta_list_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_delta_list_code_removed (LocDeltaList list  ) 
+
+
+ +

+Returns the number of lines of code removed for the given LocDeltaList.

Parameters:
+ + +
list A LocDeltaList created from ohcount_loc_delta_list_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_delta_list_comments_added (LocDeltaList list  ) 
+
+
+ +

+Returns the number of lines of comments added for the given LocDeltaList.

Parameters:
+ + +
list A LocDeltaList created from ohcount_loc_delta_list_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_delta_list_comments_removed (LocDeltaList list  ) 
+
+
+ +

+Returns the number of lines of comments removed for the given LocDeltaList.

Parameters:
+ + +
list A LocDeltaList created from ohcount_loc_delta_list_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
void ohcount_loc_delta_list_free (LocDeltaList list  ) 
+
+
+ +

+Frees the memory allocated for a given LocDeltaList.

Parameters:
+ + +
list A LocDeltaList created from ohcount_loc_delta_list_new().
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
LocDelta* ohcount_loc_delta_list_get_loc_delta (LocDeltaList list,
const char *  language 
)
+
+
+ +

+Returns a LocDelta from a given LocDeltaList and language. The returned pointer is used internally and may not be 'free'd.

Parameters:
+ + + +
list A LocDeltaList created from ohcount_loc_delta_list_new().
language The language of the LocDelta to retrieve.
+
+
Returns:
LocDelta or NULL.
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_delta_list_net_blanks (LocDeltaList list  ) 
+
+
+ +

+Returns the net number of blank lines for the given LocDeltaList.

Parameters:
+ + +
list A LocDeltaList created from ohcount_loc_delta_list_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_delta_list_net_code (LocDeltaList list  ) 
+
+
+ +

+Returns the net number of lines of code for the given LocDeltaList.

Parameters:
+ + +
list A LocDeltaList created from ohcount_loc_delta_list_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_delta_list_net_comments (LocDeltaList list  ) 
+
+
+ +

+Returns the net number of lines of comments for the given LocDeltaList.

Parameters:
+ + +
list A LocDeltaList created from ohcount_loc_delta_list_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_delta_list_net_total (LocDeltaList list  ) 
+
+
+ +

+Returns the net number of lines for the given LocDeltaList.

Parameters:
+ + +
list A LocDeltaList created from ohcount_loc_delta_list_new().
+
+ +
+

+ +

+
+ + + + + + + + +
LocDeltaList* ohcount_loc_delta_list_new (  ) 
+
+
+ +

+Creates a new LocDeltaList that is initially empty. LocDeltas can be added using ohcount&oc_delta_list_add_loc_delta().

Returns:
LocDeltaList
+ +
+

+ +

+
+ + + + + + + + + +
LocDeltaList* ohcount_loc_delta_list_new_compact (LocDeltaList list  ) 
+
+
+ +

+Creates a new LocDeltaList from a given one, excluding all LocDeltas with no counted lines. The given list may be 'free'd immediately.

Parameters:
+ + +
list A LocDeltaList created from ohcount_loc_delta_list_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_delta_net_blanks (LocDelta delta  ) 
+
+
+ +

+Returns the net number of blank lines in a given LocDelta.

Parameters:
+ + +
delta A LocDelta created from ohcount_loc_delta_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_delta_net_code (LocDelta delta  ) 
+
+
+ +

+Returns the net number of lines of code in a given LocDelta.

Parameters:
+ + +
delta A LocDelta created from ohcount_loc_delta_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_delta_net_comments (LocDelta delta  ) 
+
+
+ +

+Returns the net number of lines of comments in a given LocDelta.

Parameters:
+ + +
delta A LocDelta created from ohcount_loc_delta_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_delta_net_total (LocDelta delta  ) 
+
+
+ +

+Returns the net number of lines in a given LocDelta.

Parameters:
+ + +
delta A LocDelta created from ohcount_loc_delta_new().
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LocDelta* ohcount_loc_delta_new (const char *  language,
int  code_added,
int  code_removed,
int  comments_added,
int  comments_removed,
int  blanks_added,
int  blanks_removed 
)
+
+
+ +

+Creates a new LocDelta from the given language and lines of code, comments, and blanks added and removed. The given language is not copied and may not be 'free'd. Use a language defined in src/languages.h.

Parameters:
+ + + + + + + + +
language The language being counted.
code_added The number of lines of code added in this delta.
code_removed The number of lines of code removed in this delta.
comments_added The number of lines of comments added in this delta.
comments_removed The number of lines of comments removed in this delta.
blanks_added The number of blank lines added in this delta.
blanks_removed The number of blank lines removed in this delta.
+
+
Returns:
LocDelta
+ +
+

+ +

+
+ + + + + + + + + +
void ohcount_loc_free (Loc loc  ) 
+
+
+ +

+Frees the memory allocated for a given Loc.

Parameters:
+ + +
loc A Loc created from ohcount_loc_new().
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
int ohcount_loc_is_equal (Loc loc,
Loc other 
)
+
+
+ +

+Returns whether or not two given Locs are equivalent.

Parameters:
+ + + +
loc A Loc created from ohcount_loc_new().
other Another Loc.
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
void ohcount_loc_list_add_loc (LocList list,
Loc loc 
)
+
+
+ +

+Adds a given Loc to a LocList. The given Loc is copied and may be 'free'd immediately.

Parameters:
+ + + +
list a LocList created from ohcount_loc_list_new().
loc A Loc created from ohcount_loc_new().
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
void ohcount_loc_list_add_loc_list (LocList list,
LocList loc_list 
)
+
+
+ +

+Adds a given LocList to another LocList. The results are stored in the first LocList given. The second LocList may be 'free'd immediately.

Parameters:
+ + + +
list A LocList created from ohcount_loc_list_new().
loc_list Another LocList.
+
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_list_blanks (LocList list  ) 
+
+
+ +

+Returns the number of blank lines for all Locs in this LocList.

Parameters:
+ + +
list A LocList created from ohcount_loc_list_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_list_code (LocList list  ) 
+
+
+ +

+Returns the number of lines of code for all Locs in this LocList.

Parameters:
+ + +
list A LocList created from ohcount_loc_list_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_list_comments (LocList list  ) 
+
+
+ +

+Returns the number of lines of commentsfor all Locs in this LocList.

Parameters:
+ + +
list A LocList created from ohcount_loc_list_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_list_filecount (LocList list  ) 
+
+
+ +

+Returns the number of files counted for all Locs in this LocList.

Parameters:
+ + +
list A LocList created from ohcount_loc_list_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
void ohcount_loc_list_free (LocList list  ) 
+
+
+ +

+Frees the memory allocated for a given LocList.

Parameters:
+ + +
list A LocList created from ohcount_loc_list_new().
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
Loc* ohcount_loc_list_get_loc (LocList list,
const char *  language 
)
+
+
+ +

+Returns a Loc from a given LocList and language. The returned pointer is used internally and may not be 'free'd.

Parameters:
+ + + +
list A LocList created from ohcount_loc_list_new().
language The language of the Loc to retrieve.
+
+
Returns:
Loc or NULL.
+ +
+

+ +

+
+ + + + + + + + +
LocList* ohcount_loc_list_new (  ) 
+
+
+ +

+Creates a new LocList that is initially empty. Locs can be added using ohcount_loc_list_add_loc().

Returns:
LocList
+ +
+

+ +

+
+ + + + + + + + + +
LocList* ohcount_loc_list_new_compact (LocList list  ) 
+
+
+ +

+Creates a new LocList from a given one, excluding all Locs with no counted lines. The given list may be 'free'd immediately.

Parameters:
+ + +
list A LocList created from ohcount_loc_list_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_list_total (LocList list  ) 
+
+
+ +

+Returns the total number of lines for all Locs in this LocList.

Parameters:
+ + +
list A LocList created from ohcount_loc_list_new().
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Loc* ohcount_loc_new (const char *  language,
int  code,
int  comments,
int  blanks,
int  filecount 
)
+
+
+ +

+Creates a new Loc from the given language, lines of code, comments, and blanks, and number of files counted. The given language is not copied and may not be 'free'd. Use a language defined in src/languages.h.

Parameters:
+ + + + + + +
language The language being counted.
code The number of lines of code counted.
comments The number of lines of comments counted.
blanks The number of blank lines counted.
filecount The number of files counted for this set.
+
+
Returns:
Loc
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_loc_total (Loc loc  ) 
+
+
+ +

+Returns the total number of lines counted for a given Loc.

Parameters:
+ + +
loc A Loc created from ohcount_loc_new().
+
+ +
+

+

+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/loc_8h_source.html b/doc/html/loc_8h_source.html new file mode 100644 index 0000000..094cb01 --- /dev/null +++ b/doc/html/loc_8h_source.html @@ -0,0 +1,125 @@ + + +ohcount: /Users/andy/dev/ohcount/src/loc.h Source File + + + + + +
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/log_8h.html b/doc/html/log_8h.html new file mode 100644 index 0000000..6618260 --- /dev/null +++ b/doc/html/log_8h.html @@ -0,0 +1,59 @@ + + +ohcount: /Users/andy/dev/ohcount/src/log.h File Reference + + + + + +
+

/Users/andy/dev/ohcount/src/log.h File Reference

+

+Go to the source code of this file. + + + + +

Defines

#define log_it(log)   {}
+


Define Documentation

+ +
+
+ + + + + + + + + +
#define log_it (log   )    {}
+
+
+ +

+ +

+

+

+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/log_8h_source.html b/doc/html/log_8h_source.html new file mode 100644 index 0000000..347e7c3 --- /dev/null +++ b/doc/html/log_8h_source.html @@ -0,0 +1,31 @@ + + +ohcount: /Users/andy/dev/ohcount/src/log.h Source File + + + + + +
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/ohcount_8h.html b/doc/html/ohcount_8h.html new file mode 100644 index 0000000..4bdd8ae --- /dev/null +++ b/doc/html/ohcount_8h.html @@ -0,0 +1,156 @@ + + +ohcount: /Users/andy/dev/ohcount/src/ohcount.h File Reference + + + + + +
+

/Users/andy/dev/ohcount/src/ohcount.h File Reference

+

+Go to the source code of this file. + + + + + + + + + + + + + + + + +

Defines

#define COMMAND_ANNOTATE   1
#define COMMAND_DETECT   2
#define COMMAND_HELP   3
#define COMMAND_INDIVIDUAL   4
#define COMMAND_LICENSES   5
#define COMMAND_RAWENTITIES   6
#define COMMAND_SUMMARY   7
+


Define Documentation

+ +
+
+ + + + +
#define COMMAND_ANNOTATE   1
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define COMMAND_DETECT   2
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define COMMAND_HELP   3
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define COMMAND_INDIVIDUAL   4
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define COMMAND_LICENSES   5
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define COMMAND_RAWENTITIES   6
+
+
+ +

+ +

+

+ +

+
+ + + + +
#define COMMAND_SUMMARY   7
+
+
+ +

+ +

+

+

+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/ohcount_8h_source.html b/doc/html/ohcount_8h_source.html new file mode 100644 index 0000000..8ee6d4d --- /dev/null +++ b/doc/html/ohcount_8h_source.html @@ -0,0 +1,43 @@ + + +ohcount: /Users/andy/dev/ohcount/src/ohcount.h Source File + + + + + +
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/pages.html b/doc/html/pages.html new file mode 100644 index 0000000..3a5f5d4 --- /dev/null +++ b/doc/html/pages.html @@ -0,0 +1,32 @@ + + +ohcount: Page Index + + + + + +
+

Related Pages

Here is a list of all related documentation pages: +
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/parsed__language_8h.html b/doc/html/parsed__language_8h.html new file mode 100644 index 0000000..ca9bf8f --- /dev/null +++ b/doc/html/parsed__language_8h.html @@ -0,0 +1,240 @@ + + +ohcount: /Users/andy/dev/ohcount/src/parsed_language.h File Reference + + + + + +
+

/Users/andy/dev/ohcount/src/parsed_language.h File Reference

#include "structs.h"
+ +

+Go to the source code of this file. + + + + + + + + + + + + + + +

Functions

ParsedLanguageohcount_parsed_language_new (const char *language, int buffer_size)
void ohcount_parsed_language_add_code (ParsedLanguage *parsed_language, char *p, int length)
void ohcount_parsed_language_add_comment (ParsedLanguage *parsed_language, char *p, int length)
void ohcount_parsed_language_free (ParsedLanguage *parsed_language)
ParsedLanguageListohcount_parsed_language_list_new ()
void ohcount_parsed_language_list_free (ParsedLanguageList *list)
+


Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void ohcount_parsed_language_add_code (ParsedLanguage parsed_language,
char *  p,
int  length 
)
+
+
+ +

+Adds some code to the code buffer for the given ParsedLanguage.

Parameters:
+ + + + +
parsed_language A ParsedLanguage created from ohcount_parsed_language_new().
p A pointer in memory to start copying code from.
length The number of characters to copy from p.
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void ohcount_parsed_language_add_comment (ParsedLanguage parsed_language,
char *  p,
int  length 
)
+
+
+ +

+Adds a comment to the comment buffer for the given ParsedLanguage.

Parameters:
+ + + + +
parsed_language A ParsedLanguage created from ohcount_parsed_language_new().
p A pointer in memory to start copying the comment from.
length The number of characters to copy from p.
+
+ +
+

+ +

+
+ + + + + + + + + +
void ohcount_parsed_language_free (ParsedLanguage parsed_language  ) 
+
+
+ +

+Frees the memory allocated for the given ParsedLanguage.

Parameters:
+ + +
parsed_language A ParsedLanguage created from ohcount_parsed_language_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
void ohcount_parsed_language_list_free (ParsedLanguageList list  ) 
+
+
+ +

+Frees the memory allocated for the given ParsedLanguageList.

Parameters:
+ + +
list A ParsedLanguage created from ohcount_parsed_language_list_new().
+
+ +
+

+ +

+
+ + + + + + + + +
ParsedLanguageList* ohcount_parsed_language_list_new (  ) 
+
+
+ +

+Creates a new ParsedLanguageList that is initially empty.

Returns:
ParsedLanguageList
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
ParsedLanguage* ohcount_parsed_language_new (const char *  language,
int  buffer_size 
)
+
+
+ +

+Creates a new ParsedLanguage for the given language and buffer size. The given language is not copied and may not be 'free'd. Use a language defined in src/languages.h.

Parameters:
+ + + +
language The parsed language.
buffer_size The size of the buffers to store parsed code and comment text.
+
+
Returns:
ParsedLanguage
+ +
+

+

+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/parsed__language_8h_source.html b/doc/html/parsed__language_8h_source.html new file mode 100644 index 0000000..849615a --- /dev/null +++ b/doc/html/parsed__language_8h_source.html @@ -0,0 +1,52 @@ + + +ohcount: /Users/andy/dev/ohcount/src/parsed_language.h Source File + + + + + +
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/parser_8h.html b/doc/html/parser_8h.html new file mode 100644 index 0000000..c4b2406 --- /dev/null +++ b/doc/html/parser_8h.html @@ -0,0 +1,90 @@ + + +ohcount: /Users/andy/dev/ohcount/src/parser.h File Reference + + + + + +
+

/Users/andy/dev/ohcount/src/parser.h File Reference

#include "sourcefile.h"
+ +

+Go to the source code of this file. + + + + +

Functions

int ohcount_parse (SourceFile *sourcefile, int count, void(*callback)(const char *, const char *, int, int, void *), void *userdata)
+


Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
int ohcount_parse (SourceFile sourcefile,
int  count,
void(*)(const char *, const char *, int, int, void *)  callback,
void *  userdata 
)
+
+
+ +

+Tries to use an existing Ragel parser for the given language.

Parameters:
+ + + + + +
sourcefile A SourceFile created by ohcount_sourcefile_new().
count An integer flag indicating whether to count lines or parse entities.
callback A callback to use for every line or entity in the source file discovered (depends on count).
userdata Pointer to userdata used by callback (if any).
+
+
Returns:
1 if a Ragel parser is found, 0 otherwise.
+ +
+

+

+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/parser_8h_source.html b/doc/html/parser_8h_source.html new file mode 100644 index 0000000..3851e15 --- /dev/null +++ b/doc/html/parser_8h_source.html @@ -0,0 +1,42 @@ + + +ohcount: /Users/andy/dev/ohcount/src/parser.h Source File + + + + + +
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/parser__macros_8h.html b/doc/html/parser__macros_8h.html new file mode 100644 index 0000000..e6639a8 --- /dev/null +++ b/doc/html/parser__macros_8h.html @@ -0,0 +1,1012 @@ + + +ohcount: /Users/andy/dev/ohcount/src/parser_macros.h File Reference + + + + + +
+

/Users/andy/dev/ohcount/src/parser_macros.h File Reference

#include <stdio.h>
+#include <stdlib.h>
+#include "languages.h"
+ +

+Go to the source code of this file. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Data Structures

struct  CallbackItem
 Holds a series of callbacks for in a queue (linked list). More...

Defines

#define dequeue
#define ls
#define code
#define comment
#define saw(lang)
#define std_internal_newline(lang)
#define emb_internal_newline(lang)
#define std_newline(lang)
#define emb_newline(lang)
#define process_last_line(lang)
#define check_blank_entry(lang)
#define NEWLINE   -1
#define INTERNAL_NL   -2
#define CHECK_BLANK_ENTRY   -3
#define cint(c)   ((int) (c - buffer_start))
#define init

Typedefs

typedef struct CallbackItem Callback

Functions

void enqueue (const char *lang, const char *entity, int s, int e, void *udata)
void free_queue ()
int is_blank_entry (char **p)

Variables

Callbackcallback_list_head = NULL
Callbackcallback_list_tail = NULL
int cs
int act
char * p
char * pe
char * eof
char * ts
char * te
int stack [5]
int top
char * buffer_start
int whole_line_comment
int line_contains_code
char * line_start
int entity
const char * seen
int inqueue
char * last_line_start
int last_line_contains_code
int last_whole_line_comment
+


Define Documentation

+ +
+
+ + + + +
#define CHECK_BLANK_ENTRY   -3
+
+
+ +

+Check blank entry entity. Used for embedded language transitions. If a newline follows immediately after such a transition, the line should be counted as parent code, not child code.

Note:
This is only used for line counting parsers.
+ +
+

+ +

+
+ + + + + + + + + +
#define check_blank_entry (lang   ) 
+
+
+ +

+Value:

{ \
+  if (is_blank_entry(&p)) { \
+    te = p + 1; \
+    std_newline(lang) \
+  } \
+}
+
If there is a transition into an embedded language and there is only parent language code on the line (the rest of the line is blank with no child code), count the line as a line of parent code. Moves p and te to the end of the newline and calls the std_newline macro. (p is inclusive, te is not.) This is typically used in the main action for the CHECK_BLANK_ENTRY entity.
Parameters:
+ + +
lang The language name string.
+
+
Note:
Applies only to line counting parsers.
+ +
+

+ +

+
+ + + + + + + + + +
#define cint (  )    ((int) (c - buffer_start))
+
+
+ +

+Returns the absolute location in memory for a position relative to the start of the buffer being parsed.

Parameters:
+ + +
c Position relative to the start of the buffer.
+
+
Note:
This is only used for line counting parsers.
+ +
+

+ +

+
+ + + + +
#define code
+
+
+ +

+Value:

{ \
+  if (inqueue) { dequeue; } \
+  if (!line_contains_code && !line_start) line_start = ts; \
+  line_contains_code = 1; \
+}
+
The C equivalent of the Ragel 'code' action. This is tyically used in the main action for entities where Ragel actions cannot, for one reason or another, be used.
Note:
Applies only to line counting parsers.
+ +
+

+ +

+
+ + + + +
#define comment
+
+
+ +

+Value:

{ \
+  if (inqueue) { dequeue; } \
+  if (!line_contains_code) { \
+    whole_line_comment = 1; \
+    if (!line_start) line_start = ts; \
+  } \
+}
+
The C equivalent of the Ragel 'comment' action. This is typically unused, but here for consistency.
Note:
Applies only to line counting parsers.
+ +
+

+ +

+
+ + + + +
#define dequeue
+
+
+ +

+Value:

Restores settings for a failed enqueued entity. This is typically used in the ls, code, and comment macros.
Note:
Applies only to line counting parsers.
+ +
+

+ +

+
+ + + + + + + + + +
#define emb_internal_newline (lang   ) 
+
+
+ +

+Value:

{ \
+  if (seen && seen != lang) \
+    std_internal_newline(seen) \
+  else \
+    std_internal_newline(lang) \
+  seen = 0; \
+}
+
Executes emebedded language line counting actions for INTERNAL_NL entities based on whether or not the embedded language's code has been seen in a parent line. This is typically used in the main action for the INTERNAL_NL entity.
Parameters:
+ + +
lang The language name string.
+
+
Note:
Applies only to line counting parsers.
+ +
+

+ +

+
+ + + + + + + + + +
#define emb_newline (lang   ) 
+
+
+ +

+Value:

{ \
+  if (seen && seen != lang) \
+    std_newline(seen) \
+  else \
+    std_newline(lang) \
+  seen = 0; \
+}
+
Executes embedded language line counting actions for NEWLINE entities based on whether or not the embedded language's code has been seen in a parent line. This is typically used in the main action for the NEWLINE entity.
Parameters:
+ + +
lang The language name string.
+
+
Note:
Applies only to line counting parsers.
+ +
+

+ +

+
+ + + + +
#define init
+
+
+ +

+Value:

{ \
+  p = buffer; \
+  pe = buffer + length; \
+  eof = pe; \
+  \
+  buffer_start = buffer; \
+  whole_line_comment = 0; \
+  line_contains_code = 0; \
+  line_start = 0; \
+  entity = 0; \
+  seen = 0; \
+  inqueue = 0; \
+}
+
Initializes variables for parsing a buffer. Required at the beginning of every parser function. +
+

+ +

+
+ + + + +
#define INTERNAL_NL   -2
+
+
+ +

+Internal newline entity. Used for newlines inside patterns like strings and comments that can have newlines in them.

Note:
This is only used for line counting parsers.
+ +
+

+ +

+
+ + + + +
#define ls
+
+
+ +

+Value:

{ \
+  if (inqueue) { dequeue; } \
+  if (!line_start) line_start = ts; \
+}
+
Sets the line_start variable to ts. This is typically used for the SPACE entity in the main action.
Note:
Applies only to line counting parsers.
+ +
+

+ +

+
+ + + + +
#define NEWLINE   -1
+
+
+ +

+Newline entity.

Note:
This is only used for line counting parsers.
+ +
+

+ +

+
+ + + + + + + + + +
#define process_last_line (lang   ) 
+
+
+ +

+Value:

{\
+  if ((whole_line_comment || line_contains_code) && callback) { \
+    if (line_contains_code) \
+      callback(lang, "lcode", cint(line_start), cint(pe), userdata); \
+    else if (whole_line_comment) \
+      callback(lang, "lcomment", cint(line_start), cint(pe), userdata); \
+  } \
+}
+
Processes the last line for buffers that don't have a newline at EOF. This is typically used at the end of the parse_lang function after the Ragel parser has been executed.
Parameters:
+ + +
lang The language name string.
+
+
Note:
Applies only to line counting parsers.
+ +
+

+ +

+
+ + + + + + + + + +
#define saw (lang   ) 
+
+
+ +

+Value:

{ \
+  seen = lang; \
+  whole_line_comment = 0; \
+  line_contains_code = 0; \
+}
+
Sets up for having seen an embedded language. This is typically used when entering an embedded language which usually does not span multiple lines (e.g. php for <?php echo 'blah' ?> on single lines) so the line is counted as embedded code or comment, not parent code.
Parameters:
+ + +
lang The language name string.
+
+
Note:
Applies only to line counting parsers.
+ +
+

+ +

+
+ + + + + + + + + +
#define std_internal_newline (lang   ) 
+
+
+ +

+Value:

{ \
+  if (callback && p > line_start) { \
+    if (line_contains_code) { \
+      if (inqueue) \
+        enqueue(lang, "lcode", cint(line_start), cint(p), userdata); \
+      else \
+        callback(lang, "lcode", cint(line_start), cint(p), userdata); \
+    } else if (whole_line_comment) { \
+      if (inqueue) \
+        enqueue(lang, "lcomment", cint(line_start), cint(p), userdata); \
+      else \
+        callback(lang, "lcomment", cint(line_start), cint(p), userdata); \
+    } else { \
+      if (inqueue) \
+        enqueue(lang, "lblank", cint(line_start), cint(p), userdata); \
+      else \
+        callback(lang, "lblank", cint(line_start), cint(p), userdata); \
+    } \
+  } \
+  whole_line_comment = 0; \
+  line_contains_code = 0; \
+  line_start = p; \
+}
+
Executes standard line counting actions for INTERNAL_NL entities. This is typically used in the main action for the INTERNAL_NL entity.
Parameters:
+ + +
lang The language name string.
+
+
Note:
Applies only to line counting parsers.
+ +
+

+ +

+
+ + + + + + + + + +
#define std_newline (lang   ) 
+
+
+ +

+Value:

{\
+  if (inqueue) { dequeue; } \
+  if (callback && te > line_start) { \
+    if (line_contains_code) \
+      callback(lang, "lcode", cint(line_start), cint(te), userdata); \
+    else if (whole_line_comment) \
+      callback(lang, "lcomment", cint(line_start), cint(te), userdata); \
+    else \
+      callback(lang, "lblank", cint(ts), cint(te), userdata); \
+  } \
+  whole_line_comment = 0; \
+  line_contains_code = 0; \
+  line_start = 0; \
+}
+
Executes standard line counting actions for NEWLINE entities. This is typically used in the main action for the NEWLINE entity.
Parameters:
+ + +
lang The language name string.
+
+
Note:
Applies only to line counting parsers.
+ +
+

+


Typedef Documentation

+ +
+
+ + + + +
typedef struct CallbackItem Callback
+
+
+ +

+ +

+

+


Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void enqueue (const char *  lang,
const char *  entity,
int  s,
int  e,
void *  udata 
)
+
+
+ +

+Enqueues a callback for calling upon commit. This is only necessary for line counting machines. Ragel will execute actions in real-time rather than after a complete match. This is a problem for entities that contain internal newlines, since there is a callback for each internal newline whether or not the end of the entity matches. This means that if, for example, the beginning of a string entity is matched, the text following is treated as code until the ending delimiter. If there is no ending delimiter (it was not actually a string entity), Ragel will jump back to the beginning of the string and reparse the text again. This means all the callbacks called were probably not accurate. To remedy this, any entity which needs an ending delimiter that may not appear will have its callbacks enqueued and then committed when the ending delimitter is reached. If that delimitter is not reached, the callbacks are never called.

Parameters:
+ + + + + + +
lang The language name.
entity The entity (lcode, lcomment, lblank).
s The start position of the entity in the buffer.
e The end position of the entity in the buffer.
udata Userdata.
+
+ +
+

+ +

+
+ + + + + + + + +
void free_queue (  ) 
+
+
+ +

+Frees the memory used by a queue. +

+

+ +

+
+ + + + + + + + + +
int is_blank_entry (char **  p  ) 
+
+
+ +

+Determines whether or not the rest of the line is blank. This is typically used when entering an embedded language.

Parameters:
+ + +
p The position of entry into the emebedded language.
+
+
Returns:
0 if the rest of the line is not blank, the position at the end of the newline otherwise (inclusive).
+
Note:
Applies only to line counting parsers.
+ +
+

+


Variable Documentation

+ +
+
+ + + + +
int act
+
+
+ +

+Required by Ragel. +

+

+ +

+
+ + + + +
char* buffer_start
+
+
+ +

+The buffer currently being parsed. +

+

+ +

+
+ + + + +
Callback* callback_list_head = NULL
+
+
+ +

+The head of the Callback queue. +

+

+ +

+
+ + + + +
Callback* callback_list_tail = NULL
+
+
+ +

+The tail of the Callback queue. +

+

+ +

+
+ + + + +
int cs
+
+
+ +

+Required by Ragel. +

+

+ +

+
+ + + + +
int entity
+
+
+ +

+State variable for the current entity being matched. +

+

+ +

+
+ + + + +
char* eof
+
+
+ +

+Required by Ragel. +

+

+ +

+
+ + + + +
int inqueue
+
+
+ +

+Flag indicating whether or not to enqueue callbacks instead of calling them in real time.

Note:
This is only used for line counting parsers.
+ +
+

+ +

+
+ + + + +
int last_line_contains_code
+
+
+ +

+Backup variable for 'inqueue'ing.

Note:
This is only used for line counting parsers.
+ +
+

+ +

+
+ + + + +
char* last_line_start
+
+
+ +

+Backup variable for 'inqueue'ing.

Note:
This is only used for line counting parsers.
+ +
+

+ +

+
+ + + + +
int last_whole_line_comment
+
+
+ +

+Backup variable for 'inqueue'ing.

Note:
This is only used for line counting parsers.
+ +
+

+ +

+
+ + + + +
int line_contains_code
+
+
+ +

+Flag indicating whether or not the current line contains any code.

Note:
This is only used for line counting parsers.
+ +
+

+ +

+
+ + + + +
char* line_start
+
+
+ +

+The beginning of the current line in the buffer being parsed.

Note:
This is only used for line counting parsers.
+ +
+

+ +

+
+ + + + +
char* p
+
+
+ +

+Required by Ragel. +

+

+ +

+
+ + + + +
char* pe
+
+
+ +

+Required by Ragel. +

+

+ +

+
+ + + + +
const char* seen
+
+
+ +

+Keeps track of an embedded language.

Note:
This is only used for line counting parsers.
+ +
+

+ +

+
+ + + + +
int stack[5]
+
+
+ +

+Required by Ragel. +

+

+ +

+
+ + + + +
char* te
+
+
+ +

+Required by Ragel. +

+

+ +

+
+ + + + +
int top
+
+
+ +

+Required by Ragel. +

+

+ +

+
+ + + + +
char* ts
+
+
+ +

+Required by Ragel. +

+

+ +

+
+ + + + +
int whole_line_comment
+
+
+ +

+Flag indicating whether or not the current line contains only a comment.

Note:
This is only used for line counting parsers.
+ +
+

+

+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/parser__macros_8h_source.html b/doc/html/parser__macros_8h_source.html new file mode 100644 index 0000000..33c534a --- /dev/null +++ b/doc/html/parser__macros_8h_source.html @@ -0,0 +1,266 @@ + + +ohcount: /Users/andy/dev/ohcount/src/parser_macros.h Source File + + + + + +
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/parser_doc.html b/doc/html/parser_doc.html new file mode 100644 index 0000000..f07bfc9 --- /dev/null +++ b/doc/html/parser_doc.html @@ -0,0 +1,200 @@ + + +ohcount: Parser Documentation + + + + + +
+

Parser Documentation

Author:
Mitchell Foral
+

+Overview

+I will assume the reader has a decent knowledge of how Ragel works and the Ragel syntax. If not, please review the Ragel manual found at: http://research.cs.queensu.ca/~thurston/ragel/

+All parsers must at least:

+

    +
  • Call a callback function when a line of code is parsed.
  • +
  • Call a callback function when a line of comment is parsed.
  • +
  • Call a callback function when a blank line is parsed.
  • +
+Additionally a parser can call the callback function for each position of entities parsed.

+Take a look at 'c.rl' and even keep it open for reference when reading this document to better understand how parsers work and how to write one.

+Writing a Parser

+First create your parser in 'src/parsers/'. Its name should be the language you are parsing with a '.rl' extension. You will not have to manually compile any parsers, as this is automatically for you. However, you do need to add your parser to 'hash/parsers.gperf'.

+Every parser must have the following at the top:

+

/************************* Required for every parser *************************/
+#ifndef OHCOUNT_C_PARSER_H
+#define OHCOUNT_C_PARSER_H
+
+#include "../parser_macros.h"
+
+// the name of the language
+const char *C_LANG = LANG_C;
+
+// the languages entities
+const char *c_entities[] = {
+  "space", "comment", "string", "number", "preproc",
+  "keyword", "identifier", "operator", "any"
+};
+
+// constants associated with the entities
+enum {
+  C_SPACE = 0, C_COMMENT, C_STRING, C_NUMBER, C_PREPROC,
+  C_KEYWORD, C_IDENTIFIER, C_OPERATOR, C_ANY
+};
+
+/*****************************************************************************/
+

+And the following at the bottom:

+

/************************* Required for every parser *************************/
+
+/* Parses a string buffer with C/C++ code.
+ *
+ * @param *buffer The string to parse.
+ * @param length The length of the string to parse.
+ * @param count Integer flag specifying whether or not to count lines. If yes,
+ *   uses the Ragel machine optimized for counting. Otherwise uses the Ragel
+ *   machine optimized for returning entity positions.
+ * @param *callback Callback function. If count is set, callback is called for
+ *   every line of code, comment, or blank with 'lcode', 'lcomment', and
+ *   'lblank' respectively. Otherwise callback is called for each entity found.
+ */
+void parse_c(char *buffer, int length, int count,
+             void (*callback) (const char *lang, const char *entity, int s,
+                               int e, void *udata),
+             void *userdata
+  ) {
+  init
+
+  %% write init;
+  cs = (count) ? c_en_c_line : c_en_c_entity;
+  %% write exec;
+
+  // if no newline at EOF; callback contents of last line
+  if (count) { process_last_line(C_LANG) }
+}
+
+#endif
+
+/*****************************************************************************/
+

+(Your parser will go between these two blocks.)

+The code can be found in the existing 'c.rl' parser. You will need to change:

    +
  • OHCOUNT_[lang]_PARSER_H - Replace [lang] with your language name. So if you are writing a C parser, it would be OHCOUNT_C_PARSER_H.
  • +
  • [lang]_LANG - Set the variable name to be [lang]_LANG and its value to be the name of your language to parse as defined in languages.h. [lang] is your language name. For C it would be C_LANG.
  • +
  • [lang]_entities - Set the variable name to be [lang]_entities (e.g. c_entries) The value is an array of string entities your language has. For example C has comment, string, number, etc. entities. You should definately have "space", and "any" entities. "any" entities are typically used for entity machines (discussed later) and match any character that is not recognized so the parser does not do something unpredictable.
  • +
  • enum - Change the value of the enum to correspond with your entities. So if in your parser you look up [lang]_entities[ENTITY], you will get the associated entity's string name.
  • +
  • parse_[lang] - Set the function name to parse_[lang] where again, [lang] is the name of your language. In the case of C, it is parse_c.
  • +
  • [lang]_en_[lang]_line - The line counting machine.
  • +
  • [lang]_en_[lang]_entity - The entity machine.
  • +
+You may be asking why you have to rename variables and functions. Well if variables have the same name in header files (which is what parsers are), the compiler complains. Also, when you have languages embedded inside each other, any identifiers with the same name can easily be mixed up. It is also important to prefix your Ragel definitions with your language to avoid conflicts with other parsers.

+Additional variables available to parsers are in the parser_macros.h file. Take a look at it and try to understand what the variables are used for. They will make more sense later on.

+Now you can define your Ragel parser. Name your machine after your language, "write data", and include 'common.rl', a file with common Ragel definitions, actions, etc. For example:

+

%%{
+  machine c;
+  write data;
+  include "common.rl";
+
+  ...
+}%%
+

+Before you begin to write patterns for each entity in your language, you need to understand how the parser should work.

+Each parser has two machines: one optimized for counting lines of code, comments, and blanks; the other for identifying entity positions in the buffer.

+Line Counting Machine

+This machine should be written as a line-by-line parser for multiple lines. This means you match any combination of entities except a newline up until you do reach a newline. If the line contains only spaces, or nothing at all, it is blank. If the line contains spaces at first, but then a comment, or just simply a comment, the line is a comment. If the line contains anything but a comment after spaces (if there are any), it is a line of code. You will do this using a Ragel scanner. The callback function will be called for each line parsed.

+Scanner Parser Structure

+A scanner parser will look like this:

+

[lang]_line := |*
+  entity1 ${ entity = ENTITY1; } => [lang]_ccallback;
+  entity2 ${ entity = ENTITY2; } => [lang]_ccallback;
+  ...
+  entityn ${ entity = ENTITYN; } => [lang]_ccallback;
+*|;
+

+(As usual, replace [lang] with your language name.)

+Each entity is the pattern for an entity to match, the last one typically being the newline entity. For each match, the variable is set to a constant defined in the enum, and the main action is called (you will need to create this action above the scanner).

+When you detect whether or not a line is code or comment, you should call the appropriate @code or @comment action defined in 'common.rl' as soon as possible. It is not necessary to worry about whether or not these actions are called more than once for a given line; the first call to either sets the status of the line permanently. Sometimes you cannot call @code or @comment for one reason or another. Do not worry, as this is discussed later.

+When you reach a newline, you will need to decide whether the current line is a line of code, comment, or blank. This is easy. Simply check if the line_contains_code or whole_line_comment variables are set to 1. If neither of them are, the line is blank. Then call the callback function (not action) with an "lcode", "lcomment", or "lblank" string, and the start and end positions of that line (including the newline). The start position of the line is in the line_start variable. It should be set at the beginning of every line either through the @code or @comment actions, or manually in the main action. Finally the line_contains_code, whole_line_comment, and line_start state variables must be reset. All this should be done within the main action shown below. Note: For most parsers, the std_newline(lang) macro is sufficient and does everything in the main action mentioned above. The lang parameter is the [lang]_LANG string.

+Main Action Structure

+The main action looks like this:

+

action [lang]_ccallback {
+  switch(entity) {
+  when ENTITY1:
+    ...
+    break;
+  when ENTITY2:
+    ...
+    break;
+  ...
+  when ENTITYN:
+    ...
+    break;
+  }
+}
+

+Defining Patterns for Entities

+Now it is time to write patterns for each entity in your language. That does not seem very hard, except when your entity can cover multiple lines. Comments and strings in particular can do this. To make an accurate line counter, you will need to count the lines covered by multi-line entities. When you detect a newline inside your multi-line entity, you should set the entity variable to be INTERNAL_NL and call the main action. The main action should have a case for INTERNAL_NL separate from the newline entity. In it, you will check if the current line is code or comment and call the callback function with the appropriate string ("lcode" or "lcomment") and beginning and end of the line (including the newline). Afterwards, you will reset the line_contains_code and whole_line_comment state variables. Then set the line_start variable to be p, the current Ragel buffer position. Because line_contains_code and whole_line_comment have been reset, any non-newline and non-space character in the multi-line pattern should set line_contains_code or whole_line_comment back to 1. Otherwise you would count the line as blank.

+Note: For most parsers, the std_internal_newline(lang) macro is sufficient and does everything in the main action mentioned above. The lang parameter is the [lang]_LANG string.

+For multi-line matches, it is important to call the @code or @comment actions (mentioned earlier) before an internal newline is detected so the line_contains_code and whole_line_comment variables are properly set. For other entities, you can use the code macro inside the main action which executes the same code as the Ragel @code action. Other C macros are comment and ls, the latter is typically used for the SPACE entity when defining line_start.

+Also for multi-line matches, it may be necessary to use the @enqueue and @commit actions. If it is possible that a multi-line entity will not have an ending delimiter (for example a string), use the @enqueue action as soon as the start delimitter has been detected, and the @commit action as soon as the end delimitter has been detected. This will eliminate the potential for any counting errors.

+Notes

+You can be a bit sloppy with the line counting machine. For example the only C entities that can contain newlines are strings and comments, so INTERNAL_NL would only be necessary inside them. Other than those, anything other than spaces is considered code, so do not waste your time defining specific patterns for other entities.

+Parsers with Embedded Languages

+Notation: [lang] is the parent language, [elang] is the embedded language.

+To write a parser with embedded languages (such as HTML with embedded CSS and Javascript), you should first #include the parser(s) above your Ragel code. The header file is "[elang]_parser.h".

+Next, after the inclusion of 'common.rl', add "#EMBED([elang])" on separate lines for each embedded language. The build process looks for these special comments to embed the language for you automatically.

+In your main action, you need to add another entity CHECK_BLANK_ENTRY. It should call the check_blank_entry([lang]_LANG) macro. Blank entries are an entry into an embedded language, but the rest of the line is blank before a newline. For example, a CSS entry in HTML is something like:

+

   <style type="text/css">
+

+If there is no CSS code after the entry (a blank entry), the line should be counted as HTML code, and the check_blank_entry macro handles this. But you may be asking, "how do I get to the CHECK_BLANK_ENTRY entity?". This will be discussed in just a bit.

+The emb_newline and emb_internal_newline macros should be used instead of the std_newline and std_internal_newline macros.

+For each embedded language you will have to define an entry and outry. An entry is the pattern that transitions from the parent language into the child language. An outry is the pattern from child to parent. You will need to put your entries in your [lang]_line machine. You will also need to re-create each embedded language's line machine (define as [lang]_[elang]_line; e.g. html_css_line) and put outry patterns in those. Entries typically would be defined as [lang]_[elang]_entry, and outries as [lang]_[elang]_outry.

+Note: An outry should have a @check_blank_outry action so the line is not mistakenly counted as a line of embedded language code if it is actually a line of parent code.

+Entry Pattern Actions

+
[lang]_[elang]_entry @{ entity = CHECK_BLANK_ENTRY; } @[lang]_callback
+  @{ saw([elang]_LANG)} => { fcall [lang]_[elang]_line; };
+

+What this does is checks for a blank entry, and if it is, counts the line as a line of parent language code. If it is not, the macro will not do anything. The machine then transitions into the child language.

+Outry Pattern Actions

+
@{ p = ts; fret; };
+

+What this does is sets the current Ragel parser position to the beginning of the outry so the line is counted as a line of parent language code if no child code is on the same line. The machine then transitions into the parent language.

+Entity Identifying Machine

+This machine does not have to be written as a line-by-line parser. It only has to identify the positions of language entities, such as whitespace, comments, strings, etc. in sequence. As a result they can be written much faster and more easily with less thought than a line counter. Using a scanner is most efficient. The callback function will be called for each entity parsed.

+The @ls, @ code, @comment, @queue, and @commit actions are completely unnecessary.

+Scanner Structure

+
[lang]_entity := |*
+  entity1 ${ entity = ENTITY1; } => [lang]_ecallback;
+  entity2 ${ entity = ENTITY2; } => [lang]_ecallback;
+  ...
+  entityn ${ entity = ENTITYN; } => [lang]_ecallback;
+*|;
+

+Main Action Structure

+
action [lang]_ecallback {
+  callback([lang]_LANG, [lang]_entities[entity], cint(ts), cint(te),
+           userdata);
+}
+

+Parsers for Embedded Languages

+TODO:

+Including Written Tests for Parsers

+You should have two kinds of tests for parsers. One will be a header file that goes in the 'test/unit/parsers/' directory and the other will be an input source file that goes in the 'test/src_dir/' and an expected output file that goes in the 'test/expected_dir/' directory.

+The header file will need to be "#include"ed in 'test/unit/test_parsers.h'. Then add the "all_[lang]_tests()" function to the "all_parser_tests()" function.

+Recompile the tests for the changes to take effect.

+The other files added to the 'test/{src,expected}_dir/' directories will be automatically detected and run with the test suite.

+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/sourcefile_8h.html b/doc/html/sourcefile_8h.html new file mode 100644 index 0000000..9125091 --- /dev/null +++ b/doc/html/sourcefile_8h.html @@ -0,0 +1,787 @@ + + +ohcount: /Users/andy/dev/ohcount/src/sourcefile.h File Reference + + + + + +
+

/Users/andy/dev/ohcount/src/sourcefile.h File Reference

#include "loc.h"
+#include "parsed_language.h"
+ +

+Go to the source code of this file. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Functions

SourceFileohcount_sourcefile_new (const char *filepath)
void ohcount_sourcefile_set_diskpath (SourceFile *sourcefile, const char *diskpath)
void ohcount_sourcefile_set_contents (SourceFile *sourcefile, const char *contents)
char * ohcount_sourcefile_get_contents (SourceFile *sourcefile)
int ohcount_sourcefile_get_contents_size (SourceFile *sourcefile)
void ohcount_sourcefile_set_language (SourceFile *sourcefile, const char *language)
const char * ohcount_sourcefile_get_language (SourceFile *sourcefile)
void ohcount_sourcefile_parse (SourceFile *sourcefile)
ParsedLanguageListohcount_sourcefile_get_parsed_language_list (SourceFile *sourcefile)
void ohcount_sourcefile_parse_with_callback (SourceFile *sourcefile, void(*callback)(const char *, const char *, int, int, void *), void *userdata)
void ohcount_sourcefile_parse_entities_with_callback (SourceFile *sourcefile, void(*callback)(const char *, const char *, int, int, void *), void *userdata)
LicenseListohcount_sourcefile_get_license_list (SourceFile *sourcefile)
LocListohcount_sourcefile_get_loc_list (SourceFile *sourcefile)
LocDeltaListohcount_sourcefile_diff (SourceFile *from, SourceFile *to)
LocDeltaohcount_sourcefile_calc_loc_delta (SourceFile *from, const char *language, SourceFile *to)
void ohcount_sourcefile_set_filenames (SourceFile *sourcefile, char **filenames)
char ** ohcount_sourcefile_get_filenames (SourceFile *sourcefile)
void ohcount_sourcefile_free (SourceFile *sourcefile)
SourceFileListohcount_sourcefile_list_new ()
void ohcount_sourcefile_list_add_file (SourceFileList *list, const char *filepath)
void ohcount_sourcefile_list_add_directory (SourceFileList *list, const char *directory)
LocListohcount_sourcefile_list_analyze_languages (SourceFileList *list)
void ohcount_sourcefile_list_free (SourceFileList *list)
+


Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
LocDelta* ohcount_sourcefile_calc_loc_delta (SourceFile from,
const char *  language,
SourceFile to 
)
+
+
+ +

+Returns a LocDelta reflecting the changes from one revision of a SourceFile to another for a given language. The given language is not copied and may not be 'free'd. Use a language defined in src/languages.h. The returned pointer must be 'free'd.

Parameters:
+ + + + +
from The reference SourceFile created by ohcount_sourcefile_new().
language The language to calculate the LocDelta from.
to The SourceFile to compare the reference SourceFile to (typically a later revision instead of a completely different SourceFile).
+
+
Returns:
LocDelta
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
LocDeltaList* ohcount_sourcefile_diff (SourceFile from,
SourceFile to 
)
+
+
+ +

+Returns a LocDeltaList reflecting the changes from one revision of a SourceFile to another for all languages. The returned pointer must be 'free'd.

Parameters:
+ + + +
from The reference SourceFile created by ohcount_sourcefile_new().
to The SourceFile to compare the reference SourceFile to (typically a later revision instead of a completely different SourceFile).
+
+
Returns:
LocDeltaList
+ +
+

+ +

+
+ + + + + + + + + +
void ohcount_sourcefile_free (SourceFile sourcefile  ) 
+
+
+ +

+Frees a SourceFile created by ohcount_sourcefile_new().

Parameters:
+ + +
sourcefile A SourceFile created by ohcount_sourcefile_new().
+
+ +
+

+ +

+
+ + + + + + + + + +
char* ohcount_sourcefile_get_contents (SourceFile sourcefile  ) 
+
+
+ +

+Returns the file contents of a given SourceFile. The returned pointer is used internally and may not be 'free'd.

Parameters:
+ + +
sourcefile A SourceFile created by ohcount_sourcefile_new().
+
+
Returns:
pointer to string file contents.
+ +
+

+ +

+
+ + + + + + + + + +
int ohcount_sourcefile_get_contents_size (SourceFile sourcefile  ) 
+
+
+ +

+Returns the size of the file contents of a given SourceFile.

Parameters:
+ + +
sourcefile A SourceFile created by ohcount_sourcefile_new().
+
+
Returns:
size of the file's contents.
+ +
+

+ +

+
+ + + + + + + + + +
char** ohcount_sourcefile_get_filenames (SourceFile sourcefile  ) 
+
+
+ +

+Returns a string array of the given SourceFile's directory contents. If the existing 'filenames' field is NULL, the directory is accessed and its listing is returned. The returned pointer and its contents are used internally and must not be 'free'd.

Parameters:
+ + +
sourcefile A SourceFile created by ohcount_sourcefile_new().
+
+
Returns:
pointer to a list of filenames (NULL-pointer terminated).
+ +
+

+ +

+
+ + + + + + + + + +
const char* ohcount_sourcefile_get_language (SourceFile sourcefile  ) 
+
+
+ +

+Returns the detected language of a given SourceFile. The returned pointer is used internally and may not be 'free'd.

Parameters:
+ + +
sourcefile A SourceFile created by ohcount_sourcefile_new().
+
+
Returns:
string language name.
+ +
+

+ +

+
+ + + + + + + + + +
LicenseList* ohcount_sourcefile_get_license_list (SourceFile sourcefile  ) 
+
+
+ +

+Returns a LicenseList of detected licenses in the given SourceFile. The returned list and its contents are used internally and may not be 'free'd.

Parameters:
+ + +
sourcefile A SourceFile created by ohcount_sourcefile_new().
+
+
Returns:
LicenseList
+ +
+

+ +

+
+ + + + + + + + + +
LocList* ohcount_sourcefile_get_loc_list (SourceFile sourcefile  ) 
+
+
+ +

+Returns a LocList of total lines of code in each language in the given SourceFile. The returned list and its contents are used internally and may not be 'free'd.

Parameters:
+ + +
sourcefile A SourceFile created by ohcount_sourcefile_new().
+
+
Returns:
LocList
+ +
+

+ +

+
+ + + + + + + + + +
ParsedLanguageList* ohcount_sourcefile_get_parsed_language_list (SourceFile sourcefile  ) 
+
+
+ +

+Returns the ParsedLanguageList parsed out of the given SourceFile.

Parameters:
+ + +
sourcefile A SourceFile created by ohcount_sourcefile_new().
+
+
Returns:
ParsedLanguageList
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
void ohcount_sourcefile_list_add_directory (SourceFileList list,
const char *  directory 
)
+
+
+ +

+Adds the contents of a given directory to a SourceFileList. The given directory may be 'free'd immediately.

Parameters:
+ + + +
list A SourceFileList created by ohcount_sourcefile_list_new().
directory The directory whose contents are to be added to the list.
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
void ohcount_sourcefile_list_add_file (SourceFileList list,
const char *  filepath 
)
+
+
+ +

+Adds a given file to a SourceFileList. The given filepath is copied and may be 'free'd immediately.

Parameters:
+ + + +
list a SourceFileList created by ohcount_sourcefile_list_new().
filepath The full path to the file to be added to the list.
+
+ +
+

+ +

+
+ + + + + + + + + +
LocList* ohcount_sourcefile_list_analyze_languages (SourceFileList list  ) 
+
+
+ +

+Returns a new LocList for all files in the given SourceFileList.

Parameters:
+ + +
list A SourceFileList created by ohcount_sourcefile_list_new().
+
+
Returns:
LocList
+ +
+

+ +

+
+ + + + + + + + + +
void ohcount_sourcefile_list_free (SourceFileList list  ) 
+
+
+ +

+Frees the memory allocated for a given SourceFileList.

Parameters:
+ + +
list A SourceFileList created by ohcount_sourcefile_list_new().
+
+ +
+

+ +

+
+ + + + + + + + +
SourceFileList* ohcount_sourcefile_list_new (  ) 
+
+
+ +

+Creates a new SourceFileList that is initially empty. Files can be added using ohcount_sourcefile_list_add_file(). Directories can be added using ohcount_sourcefile_list_add_directory().

Returns:
SourceFileList
+ +
+

+ +

+
+ + + + + + + + + +
SourceFile* ohcount_sourcefile_new (const char *  filepath  ) 
+
+
+ +

+Creates and returns a new SourceFile from a given filepath. The given filepath is copied and may be 'free'd immediately.

Parameters:
+ + +
filepath The path to a file on disk.
+
+
Returns:
SourceFile
+ +
+

+ +

+
+ + + + + + + + + +
void ohcount_sourcefile_parse (SourceFile sourcefile  ) 
+
+
+ +

+Parses the given SourceFile with the default callback that keeps track of the number of lines of code, comments, and blank lines.

Parameters:
+ + +
sourcefile A SourceFile created by ohcount_sourcefile_new().
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void ohcount_sourcefile_parse_entities_with_callback (SourceFile sourcefile,
void(*)(const char *, const char *, int, int, void *)  callback,
void *  userdata 
)
+
+
+ +

+Parses the given SourceFile with a specific callback. The callback is called for each entity parsed, not line.

Parameters:
+ + + + +
sourcefile A SourceFile created by ohcount_sourcefile_new().
callback The callback function to call for every entity parsed.
userdata Userdata to pass to the callback function.
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void ohcount_sourcefile_parse_with_callback (SourceFile sourcefile,
void(*)(const char *, const char *, int, int, void *)  callback,
void *  userdata 
)
+
+
+ +

+Parses the given SourceFile with a specific callback. The callback is called for each line parsed, not entity.

Parameters:
+ + + + +
sourcefile A SourceFile created by ohcount_sourcefile_new().
callback The callback function to call for every line parsed.
userdata Userdata to pass to the callback function.
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
void ohcount_sourcefile_set_contents (SourceFile sourcefile,
const char *  contents 
)
+
+
+ +

+Sets the contents of the given SourceFile. The given contents are copied and may be 'free'd immediately.

Parameters:
+ + + +
sourcefile A SourceFile created by ohcount_sourcefile_new().
contents The contents to set for sourcefile.
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
void ohcount_sourcefile_set_diskpath (SourceFile sourcefile,
const char *  diskpath 
)
+
+
+ +

+Sets the filepath on the disk of the given SourceFile. This is only used if the SourceFile's filepath field is not accurate, typically only in language detection.

Parameters:
+ + + +
sourcefile A SourceFile created by ohcount_sourcefile_new().
diskpath The real path to the file on disk.
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
void ohcount_sourcefile_set_filenames (SourceFile sourcefile,
char **  filenames 
)
+
+
+ +

+Sets the given SourceFile's directory contents to the string array given. The given array is copied and may be 'free'd immediately.

Parameters:
+ + + +
sourcefile A SourceFile created by ohcount_sourcefile_new().
filenames String array of filenames. If NULL, the next call to ohcount_sourcefile_get_filenames will access the SourceFile's directory.
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + +
void ohcount_sourcefile_set_language (SourceFile sourcefile,
const char *  language 
)
+
+
+ +

+Sets the language of a given SourceFile. The given language copied and may be 'free'd immediately.

Parameters:
+ + + +
sourcefile A SourceFile created by ohcount_sourcefile_new().
language The language to set the SourceFile to.
+
+ +
+

+

+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/sourcefile_8h_source.html b/doc/html/sourcefile_8h_source.html new file mode 100644 index 0000000..e7a6372 --- /dev/null +++ b/doc/html/sourcefile_8h_source.html @@ -0,0 +1,102 @@ + + +ohcount: /Users/andy/dev/ohcount/src/sourcefile.h Source File + + + + + +
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/structCallbackItem.html b/doc/html/structCallbackItem.html new file mode 100644 index 0000000..d3bb765 --- /dev/null +++ b/doc/html/structCallbackItem.html @@ -0,0 +1,145 @@ + + +ohcount: CallbackItem Struct Reference + + + + + +
+

CallbackItem Struct Reference

Holds a series of callbacks for in a queue (linked list). +More... +

+#include <parser_macros.h> +

+ + + + + + + + + + + + + + + +

Data Fields

const char * lang
const char * entity
int s
int e
void * udata
struct CallbackItemnext
+


Detailed Description

+Holds a series of callbacks for in a queue (linked list).

Field Documentation

+ +
+
+ + + + +
int CallbackItem::e
+
+
+ +

+The end position of the entity in the buffer. +

+

+ +

+
+ + + + +
const char* CallbackItem::entity
+
+
+ +

+The name of the entity associated with this callback. Must not be 'free'd. +

+

+ +

+
+ + + + +
const char* CallbackItem::lang
+
+
+ +

+The language associated with this callback item. Must not be 'free'd. +

+

+ +

+
+ + + + +
struct CallbackItem* CallbackItem::next [read]
+
+
+ +

+The next callback in the linked list. +

+

+ +

+
+ + + + +
int CallbackItem::s
+
+
+ +

+The start position of the entity in the buffer. +

+

+ +

+
+ + + + +
void* CallbackItem::udata
+
+
+ +

+Userdata. +

+

+


The documentation for this struct was generated from the following file: +
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/structLanguageMap.html b/doc/html/structLanguageMap.html new file mode 100644 index 0000000..412a2b8 --- /dev/null +++ b/doc/html/structLanguageMap.html @@ -0,0 +1,107 @@ + + +ohcount: LanguageMap Struct Reference + + + + + +
+

LanguageMap Struct Reference

#include <languages.h> +

+ + + + + + + + + + + +

Data Fields

const char * key
const char * name
const char * nice_name
int category
+


Field Documentation

+ +
+
+ + + + +
int LanguageMap::category
+
+
+ +

+ +

+

+ +

+
+ + + + +
const char* LanguageMap::key
+
+
+ +

+ +

+

+ +

+
+ + + + +
const char* LanguageMap::name
+
+
+ +

+ +

+

+ +

+
+ + + + +
const char* LanguageMap::nice_name
+
+
+ +

+ +

+

+


The documentation for this struct was generated from the following file: +
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/structLicense.html b/doc/html/structLicense.html new file mode 100644 index 0000000..846d1ce --- /dev/null +++ b/doc/html/structLicense.html @@ -0,0 +1,196 @@ + + +ohcount: License Struct Reference + + + + + +
+

License Struct Reference

Holds a license and its associated details and patterns. +More... +

+#include <structs.h> +

+ + + + + + + + + + + + + + + + + + + + + +

Data Fields

const char * name
const char * url
const char * nice_name
const char * re
int re_flags
const char * exclude_re
int exclude_re_flags
pcre * regexp
pcre * exclude_regexp
+


Detailed Description

+Holds a license and its associated details and patterns.

Field Documentation

+ +
+
+ + + + +
const char* License::exclude_re
+
+
+ +

+A PCRE regular expression for text that matches re, but should not match this re in order to match this license. +

+

+ +

+
+ + + + +
int License::exclude_re_flags
+
+
+ +

+PCRE flags for exclude_re. +

+

+ +

+
+ + + + +
pcre* License::exclude_regexp
+
+
+ +

+The PCRE object for exclude_re. (This field is set automatically.) +

+

+ +

+
+ + + + +
const char* License::name
+
+
+ +

+The ID name of the license. Should be in defined in licenses.h. +

+

+ +

+
+ + + + +
const char* License::nice_name
+
+
+ +

+A nice displayable name for the license. +

+

+ +

+
+ + + + +
const char* License::re
+
+
+ +

+A PCRE regular expression for text that matches this license. +

+

+ +

+
+ + + + +
int License::re_flags
+
+
+ +

+PCRE flags for re. (Typically PCRE_CASELESS or PCRE_MULTILINE). +

+

+ +

+
+ + + + +
pcre* License::regexp
+
+
+ +

+The PCRE object for re. (This field is set automatically.) +

+

+ +

+
+ + + + +
const char* License::url
+
+
+ +

+The string URL to the license's website. +

+

+


The documentation for this struct was generated from the following file: +
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/structLicenseListItem.html b/doc/html/structLicenseListItem.html new file mode 100644 index 0000000..fbb6189 --- /dev/null +++ b/doc/html/structLicenseListItem.html @@ -0,0 +1,111 @@ + + +ohcount: LicenseListItem Struct Reference + + + + + +
+

LicenseListItem Struct Reference

Holds a list of Licenses in a linked list. +More... +

+#include <structs.h> +

+ + + + + + + + + + + +

Data Fields

Licenselic
struct LicenseListItemnext
struct LicenseListItemhead
struct LicenseListItemtail
+


Detailed Description

+Holds a list of Licenses in a linked list.

Field Documentation

+ +
+
+ + + + +
struct LicenseListItem* LicenseListItem::head [read]
+
+
+ +

+The head of the linked list this LicenseList item is part of. This field is only used for the list head. +

+

+ +

+ +
+ +

+The particular License in this linked list item. +

+

+ +

+
+ + + + +
struct LicenseListItem* LicenseListItem::next [read]
+
+
+ +

+The next LicenseList in the linked list. +

+

+ +

+
+ + + + +
struct LicenseListItem* LicenseListItem::tail [read]
+
+
+ +

+The head of the linked list this LicenseList item is part of. This field is only used for the list head. +

+

+


The documentation for this struct was generated from the following file: +
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/structLoc.html b/doc/html/structLoc.html new file mode 100644 index 0000000..cbbfd7b --- /dev/null +++ b/doc/html/structLoc.html @@ -0,0 +1,128 @@ + + +ohcount: Loc Struct Reference + + + + + +
+

Loc Struct Reference

Tracks total lines of code, comments, and blanks for a single language. +More... +

+#include <structs.h> +

+ + + + + + + + + + + + + +

Data Fields

const char * language
int code
int comments
int blanks
int filecount
+


Detailed Description

+Tracks total lines of code, comments, and blanks for a single language.

Field Documentation

+ +
+
+ + + + +
int Loc::blanks
+
+
+ +

+The number of blank lines for this Loc. +

+

+ +

+
+ + + + +
int Loc::code
+
+
+ +

+The number of lines of code for this Loc. +

+

+ +

+
+ + + + +
int Loc::comments
+
+
+ +

+The number of lines of comments for this Loc. +

+

+ +

+
+ + + + +
int Loc::filecount
+
+
+ +

+The number of parsed files associated with this Loc. +

+

+ +

+
+ + + + +
const char* Loc::language
+
+
+ +

+The language associated with this Loc. +

+

+


The documentation for this struct was generated from the following file: +
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/structLocDelta.html b/doc/html/structLocDelta.html new file mode 100644 index 0000000..d800700 --- /dev/null +++ b/doc/html/structLocDelta.html @@ -0,0 +1,162 @@ + + +ohcount: LocDelta Struct Reference + + + + + +
+

LocDelta Struct Reference

Tracks changes in lines of code, comments, and blank lines for a single language. +More... +

+#include <structs.h> +

+ + + + + + + + + + + + + + + + + +

Data Fields

const char * language
int code_added
int code_removed
int comments_added
int comments_removed
int blanks_added
int blanks_removed
+


Detailed Description

+Tracks changes in lines of code, comments, and blank lines for a single language.

Field Documentation

+ +
+
+ + + + +
int LocDelta::blanks_added
+
+
+ +

+The number of blank lines added in this LocDelta. +

+

+ +

+
+ + + + +
int LocDelta::blanks_removed
+
+
+ +

+The number of blank lines removed in this LocDelta. +

+

+ +

+
+ + + + +
int LocDelta::code_added
+
+
+ +

+The number of lines of code added in this LocDelta. +

+

+ +

+
+ + + + +
int LocDelta::code_removed
+
+
+ +

+The number of lines of code removed in this LocDelta. +

+

+ +

+
+ + + + +
int LocDelta::comments_added
+
+
+ +

+The number of lines of comments added in this LocDelta. +

+

+ +

+ +
+ +

+The number of lines of comments removed in this LocDelta. +

+

+ +

+
+ + + + +
const char* LocDelta::language
+
+
+ +

+The language associated with this LocDelta. +

+

+


The documentation for this struct was generated from the following file: +
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/structLocDeltaListItem.html b/doc/html/structLocDeltaListItem.html new file mode 100644 index 0000000..2539e49 --- /dev/null +++ b/doc/html/structLocDeltaListItem.html @@ -0,0 +1,111 @@ + + +ohcount: LocDeltaListItem Struct Reference + + + + + +
+

LocDeltaListItem Struct Reference

Tracks changes in lines of code, comments, and blank lines for multiple languages using a linked list. +More... +

+#include <structs.h> +

+ + + + + + + + + + + +

Data Fields

LocDeltadelta
struct LocDeltaListItemnext
struct LocDeltaListItemhead
struct LocDeltaListItemtail
+


Detailed Description

+Tracks changes in lines of code, comments, and blank lines for multiple languages using a linked list.

Field Documentation

+ +
+ +
+ +

+The particular LocDelta in this linked list item. +

+

+ +

+
+ + + + +
struct LocDeltaListItem* LocDeltaListItem::head [read]
+
+
+ +

+The head of the linked list this item is part of. This field is only used for the list head. +

+

+ +

+
+ + + + +
struct LocDeltaListItem* LocDeltaListItem::next [read]
+
+
+ +

+The next LocDeltaList item in the linked list. +

+

+ +

+
+ + + + +
struct LocDeltaListItem* LocDeltaListItem::tail [read]
+
+
+ +

+The tail of the linked list this item is part of. This field is only used for the list head. +

+

+


The documentation for this struct was generated from the following file: +
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/structLocListItem.html b/doc/html/structLocListItem.html new file mode 100644 index 0000000..fcc29cd --- /dev/null +++ b/doc/html/structLocListItem.html @@ -0,0 +1,111 @@ + + +ohcount: LocListItem Struct Reference + + + + + +
+

LocListItem Struct Reference

Tracks total lines of code, comments, and blanks for multiple languages using a linked list. +More... +

+#include <structs.h> +

+ + + + + + + + + + + +

Data Fields

Locloc
struct LocListItemnext
struct LocListItemhead
struct LocListItemtail
+


Detailed Description

+Tracks total lines of code, comments, and blanks for multiple languages using a linked list.

Field Documentation

+ +
+
+ + + + +
struct LocListItem* LocListItem::head [read]
+
+
+ +

+The head of the linked list this LocList item is part of. This field is only used for the list head. +

+

+ +

+
+ + + + +
Loc* LocListItem::loc
+
+
+ +

+The particular Loc in this linked list item. +

+

+ +

+
+ + + + +
struct LocListItem* LocListItem::next [read]
+
+
+ +

+The next LocList item in the linked list. +

+

+ +

+
+ + + + +
struct LocListItem* LocListItem::tail [read]
+
+
+ +

+The tail of the linked list this LocList item is part of. This field is only used for the list head. +

+

+


The documentation for this struct was generated from the following file: +
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/structParsedLanguage.html b/doc/html/structParsedLanguage.html new file mode 100644 index 0000000..6e5f647 --- /dev/null +++ b/doc/html/structParsedLanguage.html @@ -0,0 +1,196 @@ + + +ohcount: ParsedLanguage Struct Reference + + + + + +
+

ParsedLanguage Struct Reference

Represents a single language parsed from a SourceFile. +More... +

+#include <structs.h> +

+ + + + + + + + + + + + + + + + + + + + + +

Data Fields

const char * name
int buffer_size
char * code
char * code_p
int code_count
char * comments
char * comments_p
int comments_count
int blanks_count
+


Detailed Description

+Represents a single language parsed from a SourceFile.

Field Documentation

+ +
+ +
+ +

+Number of blank lines for this language. +

+

+ +

+ +
+ +

+The size of the code and comments buffers. +

+

+ +

+
+ + + + +
char* ParsedLanguage::code
+
+
+ +

+Buffer containing the code parsed out for this language. +

+

+ +

+ +
+ +

+Number of lines of code for this language. +

+

+ +

+
+ + + + +
char* ParsedLanguage::code_p
+
+
+ +

+Used for writing parsed code to the code buffer. +

+

+ +

+
+ + + + +
char* ParsedLanguage::comments
+
+
+ +

+Buffer containing the comments parsed out for this language. +

+

+ +

+ +
+ +

+Number of lines of comments for this language. +

+

+ +

+
+ + + + +
char* ParsedLanguage::comments_p
+
+
+ +

+Used for writing parsed comments to the comment buffer. +

+

+ +

+
+ + + + +
const char* ParsedLanguage::name
+
+
+ +

+The parsed language. +

+

+


The documentation for this struct was generated from the following file: +
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/structParsedLanguageListItem.html b/doc/html/structParsedLanguageListItem.html new file mode 100644 index 0000000..ff70e90 --- /dev/null +++ b/doc/html/structParsedLanguageListItem.html @@ -0,0 +1,111 @@ + + +ohcount: ParsedLanguageListItem Struct Reference + + + + + +
+

ParsedLanguageListItem Struct Reference

Holds a set of ParsedLanguages in a linked list. +More... +

+#include <structs.h> +

+ + + + + + + + + + + +

Data Fields

ParsedLanguagepl
struct ParsedLanguageListItemnext
struct ParsedLanguageListItemhead
struct ParsedLanguageListItemtail
+


Detailed Description

+Holds a set of ParsedLanguages in a linked list.

Field Documentation

+ +
+ +
+ +

+The head of the linked list this ParsedLanguageList item is part of. This field is only used for the list head. +

+

+ +

+ +
+ +

+The next ParsedLanguageList item in the linked list. +

+

+ +

+ +
+ +

+The particular ParsedLanguage in this linked list item. +

+

+ +

+ +
+ +

+The tail of the linked list this ParsedLanguageList item is part of. This field is only used for the list head. +

+

+


The documentation for this struct was generated from the following file: +
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/structSourceFile.html b/doc/html/structSourceFile.html new file mode 100644 index 0000000..fd5b2b0 --- /dev/null +++ b/doc/html/structSourceFile.html @@ -0,0 +1,264 @@ + + +ohcount: SourceFile Struct Reference + + + + + +
+

SourceFile Struct Reference

Represents a single source code file. +More... +

+#include <structs.h> +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Data Fields

char * filepath
int dirpath
char * filename
char * ext
char * diskpath
char * contents
int size
const char * language
int language_detected
ParsedLanguageListparsed_language_list
LicenseListlicense_list
LocListloc_list
char ** filenames
+


Detailed Description

+Represents a single source code file.

Field Documentation

+ +
+
+ + + + +
char* SourceFile::contents
+
+
+ +

+The contents of the file. Do not use this field. Use ohcount_sourcefile_get_contents() instead. +

+

+ +

+
+ + + + +
int SourceFile::dirpath
+
+
+ +

+The last character address considered to be part of the directory path in filepath. This is an address in memory, not a length relative to filepath. +

+

+ +

+
+ + + + +
char* SourceFile::diskpath
+
+
+ +

+If filepath does not represent the real location of the file on disk, this field does. +

+

+ +

+
+ + + + +
char* SourceFile::ext
+
+
+ +

+The filepath's file extension. +

+

+ +

+
+ + + + +
char* SourceFile::filename
+
+
+ +

+The filepath's filename. +

+

+ +

+
+ + + + +
char** SourceFile::filenames
+
+
+ +

+A string array of all filenames in this file's directory. Do not use this field. Use ohcount_sourcefile_get_filenames() instead. +

+

+ +

+
+ + + + +
char* SourceFile::filepath
+
+
+ +

+The entire path to the file. +

+

+ +

+
+ + + + +
const char* SourceFile::language
+
+
+ +

+The file's detected source code language. Do not use this field. Use ohcount_sourcefile_get_language() instead. +

+

+ +

+ +
+ +

+Flag used internally for keeping track of whether or not ohcount_sourcefile_get_language() has been called for this file. +

+

+ +

+ +
+ +

+A LicenseList of licenses detected. Do not use this field. Use ohcount_sourcefile_get_license_list() instead. +

+

+ +

+ +
+ +

+A LocList of all lines of code in each language in the file. Do not use this field. Use ohcount_sourcefile_get_loc_list() instead. +

+

+ +

+ +
+ +

+A ParsedLanguageList resulting from parsing the file. Do not use this field. Use ohcount_sourcefile_get_parsed_language_list() instead. +

+

+ +

+
+ + + + +
int SourceFile::size
+
+
+ +

+The size of the file's contents in bytes. Do not use this field. Use ohcount_sourcefile_get_contents_size() instead. +

+

+


The documentation for this struct was generated from the following file: +
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/structSourceFileListItem.html b/doc/html/structSourceFileListItem.html new file mode 100644 index 0000000..8d3b77a --- /dev/null +++ b/doc/html/structSourceFileListItem.html @@ -0,0 +1,111 @@ + + +ohcount: SourceFileListItem Struct Reference + + + + + +
+

SourceFileListItem Struct Reference

Contains a set of SourceFiles. +More... +

+#include <structs.h> +

+ + + + + + + + + + + +

Data Fields

SourceFilesf
struct SourceFileListItemnext
struct SourceFileListItemhead
struct SourceFileListItemtail
+


Detailed Description

+Contains a set of SourceFiles.

Field Documentation

+ +
+
+ + + + +
struct SourceFileListItem* SourceFileListItem::head [read]
+
+
+ +

+The head of the linked list this SourceFileList item is part of. This field is only used for the list head. +

+

+ +

+
+ + + + +
struct SourceFileListItem* SourceFileListItem::next [read]
+
+
+ +

+The next SourceFileList item in the linked list. +

+

+ +

+ +
+ +

+The particular SourceFile in this linked list item. +

+

+ +

+
+ + + + +
struct SourceFileListItem* SourceFileListItem::tail [read]
+
+
+ +

+The tail of the linked list this SourceFileList item is part of. This field is only used for the list head. +

+

+


The documentation for this struct was generated from the following file: +
+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/structs_8h.html b/doc/html/structs_8h.html new file mode 100644 index 0000000..0b678c9 --- /dev/null +++ b/doc/html/structs_8h.html @@ -0,0 +1,155 @@ + + +ohcount: /Users/andy/dev/ohcount/src/structs.h File Reference + + + + + +
+

/Users/andy/dev/ohcount/src/structs.h File Reference

#include <pcre.h>
+ +

+Go to the source code of this file. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Data Structures

struct  License
 Holds a license and its associated details and patterns. More...
struct  LicenseListItem
 Holds a list of Licenses in a linked list. More...
struct  Loc
 Tracks total lines of code, comments, and blanks for a single language. More...
struct  LocListItem
 Tracks total lines of code, comments, and blanks for multiple languages using a linked list. More...
struct  LocDelta
 Tracks changes in lines of code, comments, and blank lines for a single language. More...
struct  LocDeltaListItem
 Tracks changes in lines of code, comments, and blank lines for multiple languages using a linked list. More...
struct  ParsedLanguage
 Represents a single language parsed from a SourceFile. More...
struct  ParsedLanguageListItem
 Holds a set of ParsedLanguages in a linked list. More...
struct  SourceFile
 Represents a single source code file. More...
struct  SourceFileListItem
 Contains a set of SourceFiles. More...

Typedefs

typedef struct LicenseListItem LicenseList
typedef struct LocListItem LocList
typedef struct LocDeltaListItem LocDeltaList
typedef struct
+ParsedLanguageListItem 
ParsedLanguageList
typedef struct SourceFileListItem SourceFileList
+


Typedef Documentation

+ +
+
+ + + + +
typedef struct LicenseListItem LicenseList
+
+
+ +

+ +

+

+ +

+
+ + + + +
typedef struct LocDeltaListItem LocDeltaList
+
+
+ +

+ +

+

+ +

+
+ + + + +
typedef struct LocListItem LocList
+
+
+ +

+ +

+

+ +

+
+ + + + +
typedef struct ParsedLanguageListItem ParsedLanguageList
+
+
+ +

+ +

+

+ +

+
+ + + + +
typedef struct SourceFileListItem SourceFileList
+
+
+ +

+ +

+

+

+
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/structs_8h_source.html b/doc/html/structs_8h_source.html new file mode 100644 index 0000000..8c5e4c5 --- /dev/null +++ b/doc/html/structs_8h_source.html @@ -0,0 +1,196 @@ + + +ohcount: /Users/andy/dev/ohcount/src/structs.h Source File + + + + + +
Generated on Fri Aug 28 15:20:08 2009 for ohcount by  + +doxygen 1.5.9
+ + diff --git a/doc/html/tab_b.gif b/doc/html/tab_b.gif new file mode 100644 index 0000000..0d62348 Binary files /dev/null and b/doc/html/tab_b.gif differ diff --git a/doc/html/tab_l.gif b/doc/html/tab_l.gif new file mode 100644 index 0000000..9b1e633 Binary files /dev/null and b/doc/html/tab_l.gif differ diff --git a/doc/html/tab_r.gif b/doc/html/tab_r.gif new file mode 100644 index 0000000..ce9dd9f Binary files /dev/null and b/doc/html/tab_r.gif differ diff --git a/doc/html/tabs.css b/doc/html/tabs.css new file mode 100644 index 0000000..ab02c62 --- /dev/null +++ b/doc/html/tabs.css @@ -0,0 +1,105 @@ +/* tabs styles, based on http://www.alistapart.com/articles/slidingdoors */ + +DIV.tabs +{ + float : left; + width : 100%; + background : url("tab_b.gif") repeat-x bottom; + margin-bottom : 4px; +} + +DIV.tabs UL +{ + margin : 0px; + padding-left : 10px; + list-style : none; +} + +DIV.tabs LI, DIV.tabs FORM +{ + display : inline; + margin : 0px; + padding : 0px; +} + +DIV.tabs FORM +{ + float : right; +} + +DIV.tabs A +{ + float : left; + background : url("tab_r.gif") no-repeat right top; + border-bottom : 1px solid #84B0C7; + font-size : 80%; + font-weight : bold; + text-decoration : none; +} + +DIV.tabs A:hover +{ + background-position: 100% -150px; +} + +DIV.tabs A:link, DIV.tabs A:visited, +DIV.tabs A:active, DIV.tabs A:hover +{ + color: #1A419D; +} + +DIV.tabs SPAN +{ + float : left; + display : block; + background : url("tab_l.gif") no-repeat left top; + padding : 5px 9px; + white-space : nowrap; +} + +DIV.tabs INPUT +{ + float : right; + display : inline; + font-size : 1em; +} + +DIV.tabs TD +{ + font-size : 80%; + font-weight : bold; + text-decoration : none; +} + + + +/* Commented Backslash Hack hides rule from IE5-Mac \*/ +DIV.tabs SPAN {float : none;} +/* End IE5-Mac hack */ + +DIV.tabs A:hover SPAN +{ + background-position: 0% -150px; +} + +DIV.tabs LI.current A +{ + background-position: 100% -150px; + border-width : 0px; +} + +DIV.tabs LI.current SPAN +{ + background-position: 0% -150px; + padding-bottom : 6px; +} + +DIV.navpath +{ + background : none; + border : none; + border-bottom : 1px solid #84B0C7; + text-align : center; + margin : 2px; + padding : 2px; +} diff --git a/ruby/gestalt/base.rb b/ruby/gestalt/base.rb new file mode 100644 index 0000000..7584c17 --- /dev/null +++ b/ruby/gestalt/base.rb @@ -0,0 +1,37 @@ +module Ohcount + module Gestalt + + class Base + attr_reader :type, :name, :count + + def initialize(type, name, count = 1) + @type = type + @name = name + @count = count + end + + def ==(other) + other.type.to_s == self.type.to_s && + other.name == self.name && + other.count == self.count + end + + def <=>(other) + # Sort by type, then descending count, then name + if self.type != other.type + self.type.to_s <=> other.type.to_s + elsif self.count != other.count + -(self.count <=> other.count) + else + self.name.to_s <=> other.name.to_s + end + end + + # will return an array of detected gestalts from a source_file_list + def self.find_gestalts(source_file_list) + GestaltEngine.new.process(source_file_list).gestalts + end + + end + end +end diff --git a/ruby/gestalt/definition.rb b/ruby/gestalt/definition.rb new file mode 100644 index 0000000..9d9419a --- /dev/null +++ b/ruby/gestalt/definition.rb @@ -0,0 +1,78 @@ +require 'gestalt/rules/rule' +require 'gestalt/rules/logical_rule' +require 'gestalt/rules/or_rule' +require 'gestalt/rules/and_rule' +require 'gestalt/rules/not_rule' +require 'gestalt/rules/language_rule' +require 'gestalt/rules/file_rule' +require 'gestalt/rules/filename_rule' +require 'gestalt/rules/find_filenames_rule' +require 'gestalt/rules/c_header_rule' +require 'gestalt/rules/keyword_rule' +require 'gestalt/rules/c_keyword_rule' +require 'gestalt/rules/gestalt_rule' +require 'gestalt/rules/java_import_rule' +require 'gestalt/rules/csharp_using_rule' +require 'gestalt/rules/find_java_imports_rule' +require 'gestalt/rules/maven_parser' +require 'gestalt/rules/maven_rule' +require 'gestalt/rules/csproj_parser' +require 'gestalt/rules/csproj_rule' + +module Ohcount + module Gestalt + + class Definition + attr_reader :type, :fixed_name + + def initialize(type, fixed_name = nil, options = {}, &block) + @type = type + @fixed_name = fixed_name + if options[:rule] + @top_level_or = options[:rule] + else + @top_level_or = OrRule.new(&block) + end + end + + def gestalts(gestalt_engine) + @top_level_or.triggers(gestalt_engine).map do |trigger| + Gestalt::Base.new(type, trigger.name || self.fixed_name, trigger.count) + end + end + + def top_level_or + @top_level_or ||= OrRule.new + end + + def self.add_definition(definition) + @definitions ||= [] + @definitions << definition + end + + def self.all_definitions + @definitions || [] + end + + def clone + rule = top_level_or.clone + Definition.new(type,fixed_name,:rule => rule) + end + end + + + # DSL language to allow people to define gestalt definitions like this:\ + # + # define_xxx 'Foobar' do + # filenames 'foobar' + # end + # + def self.method_missing(method, *args, &block) + if method.to_s =~ /define_(.*)$/ + Definition.add_definition(Definition.new($1.intern,*args,&block)) + else + super + end + end + end +end diff --git a/ruby/gestalt/definitions.rb b/ruby/gestalt/definitions.rb new file mode 100644 index 0000000..548d745 --- /dev/null +++ b/ruby/gestalt/definitions.rb @@ -0,0 +1,354 @@ +module Ohcount + module Gestalt + + + ############################# Platforms ############################# + # # + # Platforms is used in the most general sense of the word. We don't # + # discriminate between OS-platforms and a lightweight framework - # + # any type of dependency is fair game. # + # # + # What guides what we add here is mostly for internal Ohloh # + # purposes. # + # # + ##################################################################### + + define_platform 'posix' do + # gnu_lib && generic + c_headers 'pthread.h', 'xstrtol.h', 'xreadlink.h', 'fatal-signal.h', 'diacrit.h', 'syslog.h', 'sys/stat.h' + + # autoconf means m4 (unix macro processor) + language :autoconf + end + + define_platform 'win32' do + c_headers 'windows.h' + c_keywords 'WM_PAINT', 'ReleaseDC', 'WndProc', :min => 2 + end + + define_platform 'visualbasic' do + language :visualbasic, :min_percent => 5 + end + + define_platform 'ruby' do + language :ruby, :min_percent => 15 + end + + define_platform 'rails' do + _and do + gestalt(:platform, 'ruby') + ruby_keywords("RAILS_ROOT") + end + end + + define_platform 'java' do + language :java, :min_percent => 15 + end + + define_platform 'javascript' do + language :javascript, :min_percent => 20 + end + + define_platform 'jquery' do + filenames 'jquery-\d.\d.\d.min.js$' + end + + define_platform 'mootools' do + filenames '\bmootools-\d(\.\d)*(-core)?(-..)?\.js$' + end + + define_platform 'prototype' do + filenames '\bprototype(-\d+(\.\d)+)?.js$' + end + + define_platform 'yui' do + _or do + filenames '\byahoo-min\.js$' + html_keywords '\byahoo-min\.js\b' + end + end + + define_platform 'dojo' do + _or do + filenames '\bdojo\.js$' + html_keywords '\bdojo\.xd\.js\b' + end + end + + define_platform 'flash' do + _or do + language :actionscript, :min_percent => 1 + _and do + gestalt(:platform, 'java') + java_import /^(flash)\..+/ + end + end + end + + define_platform 'flex' do + _or do + language :mxml, :min_percent => 1 + _and do + gestalt(:platform, 'java') + java_import /^(mx)\..+/ + end + end + end + + define_platform 'xwindows' do + c_headers 'Xlib.h', 'X11\/xpm.h', 'X11/Xlib.h' + end + + define_platform 'mac' do + # apple events + c_keywords 'AppleEvent', 'AEBuildAppleEvent' + + # plist is a mac thing, right? + filenames '\.plist' + end + + define_platform 'php' do + language :php, :min_percent => 15 + end + + define_platform 'wxwidgets' do + c_headers 'wx/window.h' + end + + define_platform 'zendframework' do + _and do + gestalt(:platform, 'php') + php_keywords('Zend_Controller_Action') + end + end + + define_platform 'symfony' do + _and do + gestalt(:platform, 'php') + php_keywords('sfCore', 'sfConfig') + end + end + + define_platform 'pear' do + _and do + gestalt(:platform, 'php') + _or do + filenames('\bpackage\.xml(\.tpl)?$') + xml_keywords('pear\.php\.net/dtd/package\-2\.0') + end + end + end + + define_platform 'moodle' do + _and do + gestalt(:platform, 'php') + php_keywords("moodle") + end + end + + define_platform 'sql' do + language :sql + end + + define_platform 'mysql' do + php_keywords('mysql_connect') + end + + define_platform 'postgresql' do + php_keywords('pg_connect') + end + + define_platform 'python' do + language :python, :min_percent => 15 + end + + define_platform 'perl' do + language :perl, :min_percent => 20 + end + + define_platform 'scripting' do + gestalt(:platform, 'javascript') + gestalt(:platform, 'perl') + gestalt(:platform, 'php') + gestalt(:platform, 'python') + gestalt(:platform, 'ruby') + end + + define_platform 'cakephp' do + _and do + gestalt(:platform, 'php') + php_keywords('CAKE_CORE_INCLUDE_PATH') + end + end + + define_platform 'kde' do + c_headers 'KDEInit.h', 'kdeversion.h' + end + + define_platform 'gtk' do + c_keywords 'gtk_init', 'gtk_main', 'gtk_window_new', 'GtkWidget' + end + + define_platform 'drupal' do + _and do + gestalt(:platform, 'php') + _or do + php_keywords('drupal_set_message') + php_keywords('drupal_render') + php_keywords('Drupal', :min => 3) + end + end + end + + define_platform 'msdos' do + c_keywords '__MSDOS__', 'MSDOS', :min => 2 + end + + define_platform 'eclipseplatform' do + java_import /org\.eclipse\./ + end + + + ############################### Tools ############################### + + define_tool 'visualstudio' do + filenames '\.(sln|vcproj|vsproj|csproj|vbproj|vbp)$' + end + + define_tool 'eclipse' do + filenames '\.(project|classpath)$' + end + + define_tool 'netbeans' do + filenames '\bnbplatform\b' + filenames '\.nbm$' + end + + ############################ ARM ################################### + + define_platform 'arm' do + c_headers "arm4.h", "arm3.h" + c_keywords "arm_int32_t", "arm_start_application", "__arm__" + make_keywords '\b\-mabi\b','\barmcc\b' + java_keywords '\barm\-eabi' + assembler_keywords '\bsmlal\b', '\bsmulw\b', '\borrs\b' + gestalt(:platform, 'arm_neon') + java_import /org\.opengroup\.arm/ + end + + ########################## ARM NEON ################################ + + define_platform 'arm_neon' do + assembler_keywords '\bvld1\.\d\d\b', '\bvld1\.\d\d\b','\bvmov\b','\bvmov\.u8\b' + make_keywords '\bneon\b','\bNEON\b' + end + + ############################ ATOM ################################## + # Atom is hard to detect, since it implements x86 instruction set + + define_platform 'sse3_atom_flag' do + make_keywords 'SSE3_ATOM' + end + + define_platform 'xl_flag' do + make_keywords '\bxL\b', '\/QxL\b' + end + + define_platform 'atom' do + gestalt(:platform, 'sse3_atom_flag') + gestalt(:platform, 'xl_flag') + end + + ########################## COMPILER ################################ + define_platform 'intel_compiler' do + make_keywords '\bicc\b' + end + + define_platform 'gcc' do + make_keywords '\bgcc\b' + end + + ########################### MOBLIN ################################# + + define_platform 'clutter' do + c_keywords "ClutterActor", '\bclutter_actor_', "ClutterStage", "ClutterBehavior", "clutter_main" + csharp_keywords "ClutterActor", '\bclutter_actor_', "ClutterStage", "ClutterBehavior", "clutter_main" + perl_keywords "Clutter::Behavior", "Clutter::Actor", "Clutter::Stage" + java_keywords "ClutterActor", "ClutterStage", "ClutterShader" + ruby_keywords "Clutter::Actor", "Clutter::Stage", "Clutter::Shader", "Clutter::Cairo" + end + + define_platform 'moblin_misc' do + c_keywords '\"org\.moblin\.', 'MOBLIN_NETBOOK_SYSTEM_TRAY_H', 'org_Moblin_', '\"org\.Moblin\.', "url=\"http://moblin.org\">http://moblin.org" + make_keywords "org\.moblin\.", "moblin-netbook" + filenames 'moblin-netbook-system-tray.h$' + end + + define_platform 'nbtk' do + c_keywords '\bnbtk_[a-z]+', '\bNbtk[A-Z][a-z]+' + java_keywords '\bnbtk_[a-z]+', '\bNbtk[A-Z][a-z]+' + ruby_keywords '\bnbtk_[a-z]+', '\bNbtk[A-Z][a-z]+' + filenames 'nbtk\/nbtk.h' + end + + define_platform 'moblin' do + gestalt(:platform, 'clutter') + gestalt(:platform, 'moblin_misc') + gestalt(:platform, 'nbtk') + end + + ########################### ANDROID ################################# + + define_platform 'android' do + java_import /\bandroid\./ + end + + ############################ iPhone ################################# + + define_platform 'iphone' do + objective_c_keywords '\bUIApplicationMain', '\bUIWindow', '\bUIView', '\bUIResponder' + end + + ############################ Maemo ################################# + + define_platform 'hildon' do + c_keywords '\bHildonFile', '\bhildon_file_', '\bHildonProgram', '\bHildonWindow', '\bhildon_window' + c_headers 'hildon/hildon.h' + _and do + python_keywords '\bimport hildon' + python_keywords '\bimport gtk' + end + end + define_platform 'maemo' do + gestalt(:platform, 'hildon') + end + + define_platform 'mid_combined' do + gestalt(:platform, 'clutter') + gestalt(:platform, 'nbtk') + gestalt(:platform, 'moblin') + gestalt(:platform, 'maemo') + gestalt(:platform, 'android') + gestalt(:platform, 'iphone') + end + + + ############################ Windows CE ############################ + define_platform 'windows_ce_incomplete' do + csharp_keywords 'Microsoft\.WindowsCE', 'Microsoft\.WindowsMobile' + vb_keywords 'Microsoft\.WindowsCE', 'Microsoft\.WindowsMobile' + end + + ######################### Native Code ############################## + define_platform 'native_code' do + language :c, :min_percent => 5 + language :cpp, :min_percent => 5 + language :cncpp, :min_percent => 5 + language :assembly, :min_percent => 5 + language :d, :min_percent => 5 + language :fortran, :min_percent => 5 + language :haskell, :min_percent => 5 + language :cobol, :min_percent => 5 + end + end +end diff --git a/ruby/gestalt/dot_net_definitions.rb b/ruby/gestalt/dot_net_definitions.rb new file mode 100644 index 0000000..abb6701 --- /dev/null +++ b/ruby/gestalt/dot_net_definitions.rb @@ -0,0 +1,107 @@ +module Ohcount + module Gestalt + + define_platform 'dot_net' do + language :csharp, :min_percent => 10 + end + + define_platform 'asp_net' do + filenames('\.(aspx|ascx|ashx|asax|axd)$') + end + + define_platform 'nunit' do + _and do + gestalt(:platform, 'dot_net') + csharp_using /^NUnit\b/ + end + end + + define_platform 'nhibernate' do + _and do + gestalt(:platform, 'dot_net') + csharp_using /^NHibernate\b/ + end + end + + # BizTalk + define_platform 'dot_net_biztalk' do + _and do + gestalt(:platform, 'dot_net') + _or do + csharp_using /^Microsoft\.Solutions\b/ + csharp_using /^Microsoft\.BizTalk\b/ + end + end + end + + # Connected Services Framework + define_platform 'dot_net_csf' do + _and do + gestalt(:platform, 'dot_net') + csharp_using /^Microsoft\.Csf\b/ + end + end + + # Microsoft Content Management Server + define_platform 'dot_net_cms' do + _and do + gestalt(:platform, 'dot_net') + csharp_using /^Microsoft\.ContentManagement\b/ + end + end + + # Exchange + define_platform 'dot_net_exchange' do + _and do + gestalt(:platform, 'dot_net') + csharp_using /^Microsoft\.Exchange\b/ + end + end + + # Microsoft Operations Manager (Mom) + define_platform 'dot_net_mom' do + _and do + gestalt(:platform, 'dot_net') + csharp_using /^Microsoft\.EnterpriseManagement\.Mom\b/ + end + end + + # A general category of software. + # Not a particular technology, but it "smells" like middle-tier/enterprise software. + define_platform 'dot_net_enterprise' do + _and do + gestalt(:platform, 'dot_net') + _or do + gestalt(:platform, 'dot_net_biztalk') + gestalt(:platform, 'dot_net_exchange') + gestalt(:platform, 'dot_net_cms') + gestalt(:platform, 'dot_net_csf') + gestalt(:platform, 'dot_net_mom') + csharp_using /^System\.Runtime\.Remoting\b/ + csharp_using /^System\.DirectoryServices\b/ + csharp_using /^System\.ServiceModel\b/ + csharp_using /^System\.(Data\.)?Linq\b/ + csharp_using /^System\.Data\b/ + end + end + end + + define_platform 'wpf' do + filenames '\.xaml$' + end + + define_platform 'silverlight' do + _or do + csharp_using /^System.Web.Silverlight\b/ + html_keywords '\basp:Silverlight\b' + csproj_import /\bSilverlight\b/ + _and do + # A combination of ASP.NET with xaml is assumed to mean Silverlight + gestalt(:platform, 'asp_net') + gestalt(:platform, 'wpf') + end + end + end + + end +end diff --git a/ruby/gestalt/gestalt_engine.rb b/ruby/gestalt/gestalt_engine.rb new file mode 100644 index 0000000..a7ecae0 --- /dev/null +++ b/ruby/gestalt/gestalt_engine.rb @@ -0,0 +1,131 @@ +module Ohcount + module Gestalt + + # smells is a general class that aggregates facts required to deduce + # gestalts + class GestaltEngine + attr_reader :gestalts + + def initialize + @language_facts = LanguageFacts.new + @gestalts = [] + @source_file_rules = [] + @definitions = Definition.all_definitions.map do |d| + new_definition = d.clone + new_definition.top_level_or.each_rule do |r| + @source_file_rules << r if r.is_a?(FileRule) + end + new_definition + end + end + + def process_source_file(source_file) + @source_file_rules.each do |r| + r.process_source_file(source_file) + end + @language_facts.process_source_file(source_file) + end + + def process_source_files(source_file_list) + source_file_list.each_source_file do |source_file| + process_source_file source_file + end + self + end + + def process(what) + if what.is_a?(SourceFile) + process_source_file(what) + elsif what.is_a?(SourceFileList) + process_source_file_list(what) + else + raise ArgumentError.new + end + end + + def calc_gestalts(definitions = nil) + # since gestalts can depend on other gestalts, we perform an + # iterative process and break when no new gestalts have been + # detected. + gestalt_count = 0 + + while true do + + # collect what we can + yank_definitions = [] + @definitions.each do |d| + + new_gestalts = d.gestalts(self) + if new_gestalts.any? + yank_definitions << d + @gestalts += new_gestalts + end + end + @definitions -= yank_definitions + + # did we make any progress? + break if gestalt_count == @gestalts.size + + # nope, keep going + gestalt_count = @gestalts.size + end + + gestalts + end + + def has_gestalt?(type,name) + @gestalts.find do |g| + g.type.to_s == type.to_s && + g.name == name + end + end + + def includes_language?(language, min_percent) + @language_facts.includes_language?(language,min_percent) + end + end + + + # keeps track of languages seen + class LanguageFacts + + def initialize + @language_counts ||= {} + end + + def process_source_file(source_file) + source_file.language_breakdowns.each do |lb| + @language_counts[lb.name.intern] ||= 0 + @language_counts[lb.name.intern] += lb.code_count + end + end + + def includes_language?(language, min_percent = 0) + return false unless @language_counts[language] + language_percents[language] >= min_percent + end + + # ignores markup languages (xml/html) + def language_percents + @language_percents ||= begin + total = 0 + @language_counts.each_pair do |name,code_count| + language = Ohcount.ohcount_hash_language_from_name(name.to_s) + STDOUT.puts "Warning: Couldn't find #{name} in ohcount_hash_language_from_name" if language.nil? + next if language.nil? || language.category == 1 + total += code_count + end + + l = {} + @language_counts.each do |k,v| + l[k] = 100.0 * v.to_i / total + end + l + + end + end + end + + end +end + diff --git a/ruby/gestalt/gestalt_facts.rb b/ruby/gestalt/gestalt_facts.rb new file mode 100644 index 0000000..154860b --- /dev/null +++ b/ruby/gestalt/gestalt_facts.rb @@ -0,0 +1,68 @@ +module Ohcount + + # Represents language statistics for a collection of files + class GestaltFacts + attr_accessor :platforms, :tools, :file_rules, :language_counts + + def initialize + @platforms = [] + @tools = [] + @file_rules = {} + @language_counts = {} + end + + def process(source_file) + Gestalt::FileRule.rules_triggered_by(source_file).each do |r| + @file_rules[r] ||= 0 + @file_rules[r] += 1 + end + source_file.language_breakdowns.each do |lb| + @language_counts[lb.name.intern] ||= 0 + @language_counts[lb.name.intern] += lb.code_count + end + end + + def post_process + # since platforms can depend on other platforms, + # we perform an iterative process and break when + # no new platforms have been detected. + while true do + prev_platforms = self.platforms.clone + uninfered_platforms.each do |p| + platforms << p if p.triggered?(self) + end + prev_tools = self.tools.clone + uninfered_tools.each do |t| + tools << t if t.triggered?(self) + end + break if prev_platforms == self.platforms && prev_tools == self.tools + end + end + + def uninfered_platforms #:nodoc: + Gestalt::Platform.descendants - @platforms + end + + def uninfered_tools #:nodoc: + Gestalt::Tool.descendants - @tools + end + + def includes_language?(language, min_percent = 0) + return false unless language_counts[language] + language_percents[language] >= min_percent + end + + def language_percents + @language_percents ||= begin + total = language_counts.values.inject(0) { |s,c| s+c } + l = {} + language_counts.each do |k,v| + l[k] = 100.0 * v.to_i / total + end + l + end + end + + end +end + diff --git a/ruby/gestalt/jasper_definitions.rb b/ruby/gestalt/jasper_definitions.rb new file mode 100644 index 0000000..70609f2 --- /dev/null +++ b/ruby/gestalt/jasper_definitions.rb @@ -0,0 +1,62 @@ +module Ohcount + module Gestalt + + define_platform 'jaspersoft' do + _or do + gestalt(:platform, 'jaspersoft_keyword') + gestalt(:platform, 'jasper_reports') + gestalt(:platform, 'jasper_server') + gestalt(:platform, 'jasper_ireport') + gestalt(:platform, 'jasper_intelligence') + end + end + + define_platform 'jaspersoft_keyword' do + keywords /jaspersoft/i + end + + define_platform 'jasper_reports' do + _or do + gestalt(:platform, 'jasper_reports_keyword') + gestalt(:platform, 'jasper_reports_java') + end + end + + define_platform 'jasper_reports_keyword' do + keywords /jasper[ _-]?reports?/i + end + + define_platform 'jasper_reports_java' do + _or do + maven_dependency /jasperreports/ + java_keywords '\bnet\.sf\.jasperreports\b' + end + end + + define_platform 'jasper_server' do + _or do + gestalt(:platform, 'jasper_server_keyword') + gestalt(:platform, 'jasper_server_java') + end + end + + define_platform 'jasper_server_keyword' do + keywords /jasper[ _-]?server/i + end + + define_platform 'jasper_server_java' do + java_keywords '\bcom\.jaspersoft\.jasperserver\b' + end + + define_platform 'jasper_intelligence' do + java_keywords '\bcom\.jaspersoft\.ji' + end + + define_platform 'jasper_ireport' do + _and do + keywords /jasper/i + keywords /ireport/i + end + end + end +end diff --git a/ruby/gestalt/java_definitions.rb b/ruby/gestalt/java_definitions.rb new file mode 100644 index 0000000..2c31103 --- /dev/null +++ b/ruby/gestalt/java_definitions.rb @@ -0,0 +1,272 @@ +module Ohcount + module Gestalt + + define_java_jar do + find_filenames /([^\\^\/]*\.jar)/i, :name_from_match => 1 + end + + define_java_import do + find_java_imports + end + + # Java Application Servers + + define_platform 'glassfish' do + _and do + gestalt(:platform, 'java') + _or do + find_filenames /\b(sun\-web|sun\-ejb\-jar|sun\-application(\-client))\.xml\b/ + maven_dependency /^org.glassfish\b/ + end + end + end + + define_platform 'jboss' do + _and do + gestalt(:platform, 'java') + _or do + find_filenames /\bjboss(\-app|cmp\-jdbc|\-web|\-build|\-client)\.xml\b/ + maven_dependency /^org.jboss\b/ + end + end + end + + define_platform 'weblogic' do + _and do + gestalt(:platform, 'java') + _or do + find_filenames /\bweblogic(\-ejb\-jar|\-ra|\-application|\-cmp\-rdbms\jar)\.xml\b/ + maven_plugin /^org\.codehaus\.mojo\b/, /^weblogic\-maven\-plugin\b/ + end + end + end + + define_platform 'jonas' do + _and do + gestalt(:platform, 'java') + find_filenames /\bjonas\-ejb\-jar\.xml\b/ + end + end + + define_platform 'websphere' do + _and do + gestalt(:platform, 'java') + find_filenames /\bibm\-(application|web|webservices|webservicesclient)\-.+\.xmi$/ + end + end + + define_platform 'tomcat' do + _and do + gestalt(:platform, 'java') + _or do + java_import /^org\.apache\.tomcat\b/ + maven_dependency /^org\.apache\.tomcat\b/ + end + end + end + + define_platform 'appserver' do + _or do + gestalt(:platform, 'glassfish') + gestalt(:platform, 'jboss') + gestalt(:platform, 'weblogic') + gestalt(:platform, 'tomcat') + gestalt(:platform, 'jonas') + gestalt(:platform, 'websphere') + end + end + + define_platform 'ejb2' do + _and do + gestalt(:platform, 'java') + _or do + find_filenames /(.+\-)ejb\-jar\.xml\b/ + java_keywords 'EJBHome', 'EJBRemote', 'SessionBean' + end + end + end + + # Caution! The EJB platform definitions are senstive to their order -- do not reorder! + # The gestalt engine iterates over definitions in the order they are defined. + # + # First, look for the subset of new features that definitely indicate EJB 3.1 + define_platform 'ejb3.1' do + _and do + gestalt(:platform, 'java') + _or do + java_keywords '@Schedule', '@Singleton', '@Asynchronous' + java_keywords /@EJB\(.*\bmappedName\s*=\s*"java:(global|app|module)\/.+".*\)/ + java_keywords /\blookup\(\s*"java:(global|app|module)\/.+"\s*\)/ + end + end + end + # Next, look for the basic attributes that can mean either EJB 3.0 or 3.1 + define_platform 'ejb3+' do + _and do + gestalt(:platform, 'java') + _or do + gestalt(:platform, 'ejb3.1') + java_keywords '@EJB', '@Stateless', '@Statefull', '@Entity', '@Remote', '@Local', '@BusinessMethod' + java_import /^javax\.persistence\b/ + end + end + end + # Finally, if we found EJB3+ and not EJB 3.1, then you must be using EJB 3.0 only. + define_platform 'ejb3.0' do + _and do + gestalt(:platform, 'ejb3+') + _not { gestalt(:platform, 'ejb3.1') } + end + end + + define_platform 'servlet' do + _and do + gestalt(:platform, 'java') + _or do + java_import /^javax\.servlet\b/ + maven_dependency /^javax\.servlet\b/ + end + end + end + + define_platform 'struts' do + _and do + gestalt(:platform, 'java') + _or do + filenames('\bstruts(\-config)?\.xml$', '\bstruts\.jar$') + java_import /^org\.apache\.struts\b/ + maven_dependency /^org\.apache\.struts\b/ + end + end + end + + define_platform 'springframework' do + _and do + gestalt(:platform,'java') + _or do + filenames('spring\.jar$') + java_import /^org\.springframework\b/ + maven_dependency /^org\.springframework\b/ + end + end + end + + define_platform 'jsf' do + _and do + gestalt(:platform, 'java') + _or do + java_import /^javax\.faces\b/ + maven_dependency /^javax\.faces\b/ + end + end + end + + define_platform 'googlewebtoolkit' do + _and do + gestalt(:platform, 'java') + java_import /^com\.google\.gwt\b/ + end + end + + # Java Persistence Frameworks + + define_platform 'hibernate' do + _and do + gestalt(:platform, 'java') + _or do + filenames '\bhibernate\d\.jar$' + java_import /^org\.hibernate\b/ + maven_dependency 'org.hibernate' + end + end + end + + define_platform 'jpa' do + _and do + gestalt(:platform, 'java') + java_import /^javax\.persistence\b/ + end + end + + define_platform 'toplink' do + _and do + gestalt(:platform, 'java') + java_import /^oracle\.toplink\b/ + end + end + + define_platform 'castor' do + _and do + gestalt(:platform, 'java') + java_import /^org\.exolab\.castor\b/ + end + end + + define_platform 'db4o' do + _and do + gestalt(:platform, 'java') + java_import /^com\.db4o\b/ + end + end + + # Java Enterprise Service Buses + + define_platform 'openesb' do + _and do + gestalt(:platform, 'java') + java_import /^org\.openesb\b/ + end + end + + define_platform 'muleesb' do + _and do + gestalt(:platform, 'java') + java_import /^org\.mule\b/ + end + end + + define_platform 'servicemix' do + _and do + gestalt(:platform, 'java') + _or do + java_import /^org\.apache\.servicemix\b/ + maven_dependency /^org.apache.servicemix\b/ + end + end + end + + define_platform 'jbossesb' do + _and do + gestalt(:platform, 'java') + java_import /^org\.jboss\.soa\.esb\b/ + end + end + + define_platform 'openesb' do + _and do + gestalt(:platform, 'java') + java_import /^org\.openesb\b/ + end + end + + # Other Java Technologies + + define_platform 'opensso' do + _and do + gestalt(:platform, 'java') + _or do + filenames '\bopensso\.war$' + java_import /^com\.sun\.identity\.(authentication|agents)\b/ + end + end + end + + define_platform 'maven' do + _and do + gestalt(:platform, 'java') + find_filenames /\bpom\.xml$/ + end + end + + end +end diff --git a/ruby/gestalt/rules/and_rule.rb b/ruby/gestalt/rules/and_rule.rb new file mode 100644 index 0000000..c631519 --- /dev/null +++ b/ruby/gestalt/rules/and_rule.rb @@ -0,0 +1,16 @@ +module Ohcount + module Gestalt + # Will trigger if all sub-rules do + class AndRule < LogicalRule + + def triggers(gestalt_engine) + rules.each do |r| + return [] if r.triggers(gestalt_engine).empty? + end + [Trigger.new] + end + end + end +end + + diff --git a/ruby/gestalt/rules/c_header_rule.rb b/ruby/gestalt/rules/c_header_rule.rb new file mode 100644 index 0000000..fbbb630 --- /dev/null +++ b/ruby/gestalt/rules/c_header_rule.rb @@ -0,0 +1,31 @@ +module Ohcount + module Gestalt + # Triggers if a c or cpp header is present + class CHeaderRule < FileRule + attr_reader :headers + + def initialize(*args) + options = args.pop if args.last.is_a?(Hash) + @headers = args + super(options) + end + + def process_source_file(source_file) + return unless ['c','cpp'].include?(source_file.polyglot) + + ['c','cpp'].each do |lang| + next unless source_file.language_breakdown(lang) + md = regexp.match(source_file.language_breakdown(lang).code) + @count += (md && md.size).to_i + end + end + + def regexp + @regexp ||= begin + header_term = "(" + headers.join("|") + ")" + Regexp.new("include\s+['<\"]#{ header_term }[\">']", Regexp::IGNORECASE) + end + end + end + end +end diff --git a/ruby/gestalt/rules/c_keyword_rule.rb b/ruby/gestalt/rules/c_keyword_rule.rb new file mode 100644 index 0000000..bbad838 --- /dev/null +++ b/ruby/gestalt/rules/c_keyword_rule.rb @@ -0,0 +1,18 @@ +module Ohcount + module Gestalt + class CKeywordRule < KeywordRule + + def initialize(*keywords) + super('c',*keywords) + end + + def process_source_file(source_file) + if source_file.language_breakdown('c') + @count += source_file.language_breakdown('c').code.scan(regexp).size + elsif source_file.language_breakdown('cpp') + @count += source_file.language_breakdown('cpp').code.scan(regexp).size + end + end + end + end +end diff --git a/ruby/gestalt/rules/csharp_using_rule.rb b/ruby/gestalt/rules/csharp_using_rule.rb new file mode 100644 index 0000000..7de2488 --- /dev/null +++ b/ruby/gestalt/rules/csharp_using_rule.rb @@ -0,0 +1,25 @@ +module Ohcount + module Gestalt + + # Triggers if a matching C# 'using' library include statement is present + class CSharpUsingRule < FileRule + + def initialize(*args) + @regex = args.shift + super(args) + end + + def process_source_file(source_file) + return false unless source_file.language_breakdown('csharp') + + source_file.language_breakdown('csharp').code.scan(using_regexp).each do |match| + @count += 1 if match[0] =~ @regex + end + end + + def using_regexp + @@using_regexp ||= /^\s*using\s+([a-zA-Z][\w\.\*\-]*)\s*;/ + end + end + end +end diff --git a/ruby/gestalt/rules/csproj_parser.rb b/ruby/gestalt/rules/csproj_parser.rb new file mode 100755 index 0000000..cc9d0d1 --- /dev/null +++ b/ruby/gestalt/rules/csproj_parser.rb @@ -0,0 +1,28 @@ +#!/usr/bin/env ruby +require 'rexml/document' +require 'rexml/streamlistener' + +class CsprojListener + include REXML::StreamListener + + attr_accessor :callback + def initialize(callback) + @callback = callback + @is_csproj_file = false + end + + def tag_start(name, attrs) + case name + when 'Project' + @is_csproj_file = true + if attrs['xmlns'] and attrs['xmlns'] !~ /^http:\/\/schemas\.microsoft\.com\/developer\// + # False alarm -- it contains a project element, but of another namespace + @is_csproj_file = false + end + when 'Import' + if @is_csproj_file && attrs['Project'] + @callback.call(attrs['Project']) + end + end + end +end diff --git a/ruby/gestalt/rules/csproj_rule.rb b/ruby/gestalt/rules/csproj_rule.rb new file mode 100644 index 0000000..f519422 --- /dev/null +++ b/ruby/gestalt/rules/csproj_rule.rb @@ -0,0 +1,31 @@ +require 'rexml/document' +module Ohcount + module Gestalt + class CsprojRule < FileRule + + attr_accessor :import + + def initialize(*args) + @import = args.shift || /.*/ + @import = /^#{Regexp.escape(@import.to_s)}$/ unless @import.is_a? Regexp + + super(args) + end + + def process_source_file(source_file) + if source_file.filename =~ /\.csproj$/ && source_file.language_breakdown('xml') + callback = lambda do |import| + @count += 1 if import =~ @import + end + + begin + REXML::Document.parse_stream(source_file.language_breakdown('xml').code, CsprojListener.new(callback)) + rescue REXML::ParseException + # Malformed XML! -- ignore and move on + end + end + end + + end + end +end diff --git a/ruby/gestalt/rules/file_rule.rb b/ruby/gestalt/rules/file_rule.rb new file mode 100644 index 0000000..821679e --- /dev/null +++ b/ruby/gestalt/rules/file_rule.rb @@ -0,0 +1,53 @@ +module Ohcount + module Gestalt + # an abstract base class representing a rule based + # on an individual file's attribute (like + # code content, or filename, etc..) + class FileRule < Rule + attr_reader :min_count, :count + + def initialize(args = {}) + args ||= {} + @min_count = 1 + @count = 0 + @triggers = [] + args.each do |k,v| + case k + when :min then @min_count = v + else raise ArgumentError.new("Unrecognized option: #{ k.inspect }") + end + end + FileRule.add_instance(self) + end + + # default implementation - will yield a single trigger if appropriate + def triggers(gestalt_engine) + if triggered? + [Trigger.new] + else + [] + end + end + + def self.process_source_file(source_file) + instances.each do |rule| + next if rule.triggered? + rule.process_source_file(source_file) + end + end + + def self.instances + @instances ||= [] + end + + def self.add_instance(r) + instances << r + end + + def triggered? + @count >= @min_count + end + + end + end +end diff --git a/ruby/gestalt/rules/filename_rule.rb b/ruby/gestalt/rules/filename_rule.rb new file mode 100644 index 0000000..8f14e13 --- /dev/null +++ b/ruby/gestalt/rules/filename_rule.rb @@ -0,0 +1,25 @@ +module Ohcount + module Gestalt + # rule based a the name of the file + class FilenameRule < FileRule + attr_reader :filenames + + def initialize(*args) + options = args.pop if args.last.is_a?(Hash) + @filenames = args + super(options) + end + + def process_source_file(source_file) + @count += 1 if regex.match(source_file.filename) + end + + def regex + @regex ||= begin + r = filenames.collect { |f| "(" + f + ")"}.join("|") + Regexp.new(r) + end + end + end + end +end diff --git a/ruby/gestalt/rules/find_filenames_rule.rb b/ruby/gestalt/rules/find_filenames_rule.rb new file mode 100644 index 0000000..d05c488 --- /dev/null +++ b/ruby/gestalt/rules/find_filenames_rule.rb @@ -0,0 +1,33 @@ +module Ohcount + module Gestalt + + # will yield as many triggers as files that match the regexp + class FindFilenamesRule < FileRule + attr_reader :regex + + def initialize(regex, options = {}) + @regex = regex + @triggers = [] + @name_from_match = options.delete(:name_from_match).to_i + super(options) + end + + # deep clone + def clone + self.class.new(@regex,:name_from_match => @name_from_match) + end + + def triggers(gestalt_engine) + @triggers + end + + def process_source_file(source_file) + m = @regex.match(source_file.filename) + if m + @triggers << Trigger.new(:name => m[@name_from_match]) + end + end + + end + end +end diff --git a/ruby/gestalt/rules/find_java_imports_rule.rb b/ruby/gestalt/rules/find_java_imports_rule.rb new file mode 100644 index 0000000..3625706 --- /dev/null +++ b/ruby/gestalt/rules/find_java_imports_rule.rb @@ -0,0 +1,54 @@ +module Ohcount + module Gestalt + + # Will yield one trigger per java import - each with the name of the imported + # namespace. Example java source file: + # + # import com.foo.bar; + # + # will yield a trigger with name='com.foo.bar' + class FindJavaImportsRule < FileRule + attr_reader :keywords, :language + + def initialize(*args) + @trigger_hash = {} + super(*args) + end + + def process_source_file(source_file) + return unless source_file.language_breakdown('java') + + java_code = source_file.language_breakdown('java').code + java_code.scan(import_regexp).each do |matches| + name = matches[0] + @trigger_hash[name] = @trigger_hash[name].to_i + 1 + end + end + + # implement deep clone + def clone + self.class.new(:min => @min_count) + end + + def triggers(gestalt_engine) + triggers = [] + @trigger_hash.each do |k,v| + triggers << Trigger.new(:name => FindJavaImportsRule.truncate_name(k, 3), :count => v) + end + triggers + end + + def import_regexp + /^\s*import\s+([a-zA-Z][\w\.\*\-]*)\b/ + end + + # Truncates the java import namespace to a maximum depth. + # For instance, + # truncate_name("com.sun.identity.authentication", 3) => "com.sun.identity" + def self.truncate_name(s, max_depth) + s.to_s.split('.')[0, max_depth].join('.') + end + + end + end +end diff --git a/ruby/gestalt/rules/gestalt_rule.rb b/ruby/gestalt/rules/gestalt_rule.rb new file mode 100644 index 0000000..1ffd1a0 --- /dev/null +++ b/ruby/gestalt/rules/gestalt_rule.rb @@ -0,0 +1,22 @@ +module Ohcount + module Gestalt + + # states that a certain gestalt is required. + class GestaltRule < Rule + attr_reader :type, :name + + def initialize(type, name) + @type = type + @name = name + end + + def triggers(gestalt_engine) + if gestalt_engine.has_gestalt?(type,name) + [Trigger.new] + else + [] + end + end + end + end +end diff --git a/ruby/gestalt/rules/java_import_rule.rb b/ruby/gestalt/rules/java_import_rule.rb new file mode 100644 index 0000000..cbadc8b --- /dev/null +++ b/ruby/gestalt/rules/java_import_rule.rb @@ -0,0 +1,28 @@ +module Ohcount + module Gestalt + + # Triggers if a matching java 'import' statement is present + class JavaImportRule < FileRule + + def initialize(*args) + options = args.pop if args.last.is_a?(Hash) + @regex = args[0] + super(options) + end + + def process_source_file(source_file) + return false unless source_file.language_breakdown('java') + + java_code = source_file.language_breakdown('java').code + java_code.scan(import_regexp).each do |match| + import = match[0] + @count += 1 if import =~ @regex + end + end + + def import_regexp + /^\s*import\s+([a-zA-Z][\w\.\*\-]*)\b/ + end + end + end +end diff --git a/ruby/gestalt/rules/keyword_rule.rb b/ruby/gestalt/rules/keyword_rule.rb new file mode 100644 index 0000000..ef0fb7d --- /dev/null +++ b/ruby/gestalt/rules/keyword_rule.rb @@ -0,0 +1,41 @@ +module Ohcount + module Gestalt + # Will trigger if the given keywords are found in the specified language. + # Example; + # + # + # c_keywords '__MSDOS__', 'MSDOS', :min => 2 + # # this will trigger if the words "__MSDOS__" or "MSDOS" is found at + # # least twice in 'C' source code + # + class KeywordRule < FileRule + attr_reader :keywords, :language + + def initialize(language, *args) + options = args.pop if args.last.is_a?(Hash) + keywords = args + @language = language + @keywords = keywords + super(options) + end + + def process_source_file(source_file) + if language + return unless source_file.language_breakdown(language) + @count += source_file.language_breakdown(language).code.scan(regexp).size + else + # All languages + source_file.language_breakdowns.each do |lb| + @count += lb.code.to_s.scan(regexp).size + end + end + end + + def regexp + @regexp ||= begin + Regexp.new("(" + keywords.join("|") + ")") + end + end + end + end +end diff --git a/ruby/gestalt/rules/language_rule.rb b/ruby/gestalt/rules/language_rule.rb new file mode 100644 index 0000000..b66fcf5 --- /dev/null +++ b/ruby/gestalt/rules/language_rule.rb @@ -0,0 +1,26 @@ +module Ohcount + module Gestalt + + # states that a platform depends on a programming + # language being at least :min_percent + class LanguageRule < Rule + attr_reader :language + attr_reader :min_percent + + def initialize(language, options= {}) + @min_percent = options.delete(:min_percent) || 0 + raise "Unrecognized LanguageRule options '#{ options.keys.inspect }'" if options.any? + @language = language + end + + def triggers(gestalt_engine) + if gestalt_engine.includes_language?(language, min_percent) + [Trigger.new] + else + [] + end + end + + end + end +end diff --git a/ruby/gestalt/rules/logical_rule.rb b/ruby/gestalt/rules/logical_rule.rb new file mode 100644 index 0000000..d62b838 --- /dev/null +++ b/ruby/gestalt/rules/logical_rule.rb @@ -0,0 +1,104 @@ +module Ohcount + module Gestalt + class LogicalRule < Rule + attr_reader :rules + + def initialize(*rules, &block) + @rules = rules + self.instance_eval(&block) if block + end + + def each_rule(&block) + @rules.each { |r| r.each_rule(&block) } + yield self + end + + def clone + cloned_rules = @rules.map { |r| + r.clone + } + self.class.new(*cloned_rules) + end + + def new_rule(r_class, *args, &block) + @rules << r_class.new(*args,&block) + end + + def _or(*args, &block) + new_rule OrRule, *args, &block + end + + def _and(*args, &block) + new_rule AndRule, *args, &block + end + + def _not(*args, &block) + new_rule NotRule, *args, &block + end + + def gestalt(*args) + new_rule GestaltRule, *args + end + + def language(*args) + new_rule LanguageRule, *args + end + + def csproj_import(*args) + new_rule CsprojRule, *args + end + + def maven_dependency(*args) + new_rule MavenRule, *(['dependency'] + args) + end + + def maven_plugin(*args) + new_rule MavenRule, *(['plugin'] + args) + end + + # file rules + def c_headers(*args) + new_rule CHeaderRule, *args + end + + def filenames(*args) + new_rule FilenameRule, *args + end + + def keywords(*args) + new_rule KeywordRule, *([nil] << args) + end + + def c_keywords(*args) + new_rule CKeywordRule, *args + end + + def java_import(*args) + new_rule JavaImportRule, *args + end + + def csharp_using(*args) + new_rule CSharpUsingRule, *args + end + + def find_filenames(*args) + new_rule FindFilenamesRule, *args + end + + def find_java_imports(*args) + new_rule FindJavaImportsRule, *args + end + + def method_missing(m,*args, &block) + if m.to_s =~ /^(.*)_keywords$/ + language = $1 + new_args = [language] + args + new_rule(KeywordRule, *new_args, &block) + return + end + super + end + + end + end +end diff --git a/ruby/gestalt/rules/maven_parser.rb b/ruby/gestalt/rules/maven_parser.rb new file mode 100755 index 0000000..305468e --- /dev/null +++ b/ruby/gestalt/rules/maven_parser.rb @@ -0,0 +1,52 @@ +#!/usr/bin/env ruby +require 'rexml/document' +require 'rexml/streamlistener' + +class MavenListener + include REXML::StreamListener + + attr_accessor :group_id, :artifact_id, :text + + attr_accessor :callback + def initialize(callback) + @callback = callback + @is_pom_file = false + end + + def tag_start(name, attrs) + case name + when 'project' + @is_pom_file = true + if attrs['xmlns'] and attrs['xmlns'] !~ /^http:\/\/maven\.apache\.org\/POM\// + # False alarm -- it contains a project element, but of another namespace + @is_pom_file = false + end + when 'plugin', 'dependency' + @group_id = nil + @artifact_id = nil + end + end + + def tag_end(name) + case name + when 'groupId' + @group_id = clean(@text) + when 'artifactId' + @artifact_id = clean(@text) + when /^(plugin|dependency)$/ + if @is_pom_file && @group_id && @artifact_id + @callback.call($1, @group_id, @artifact_id) + end + end + end + + # Remove whitespace from text values. + # Also, clear out variable substitutions, which we are incapable of performing correctly + def clean(s) + s.strip.gsub(/\$\{.*\}/, '') + end + + def text(text) + @text = text + end +end diff --git a/ruby/gestalt/rules/maven_rule.rb b/ruby/gestalt/rules/maven_rule.rb new file mode 100644 index 0000000..7aed4c7 --- /dev/null +++ b/ruby/gestalt/rules/maven_rule.rb @@ -0,0 +1,39 @@ +require 'rexml/document' +module Ohcount + module Gestalt + class MavenRule < FileRule + + attr_accessor :group, :artifact, :type + + # Type is either 'dependency' or 'plugin' + def initialize(*args) + @type = args.shift + + @group = args.shift + @group = /^#{Regexp.escape(@group.to_s)}$/ unless @group.is_a? Regexp + + @artifact = args.shift || /.*/ + @artifact = /^#{Regexp.escape(@artifact.to_s)}$/ unless @artifact.is_a? Regexp + + super(args) + end + + def process_source_file(source_file) + callback = lambda do |type, group, artifact| + if type == @type and group =~ @group and artifact =~ @artifact + @count += 1 + end + end + + if source_file.filename =~ /\bpom\.xml$/ && source_file.language_breakdown('xml') + begin + REXML::Document.parse_stream(source_file.language_breakdown('xml').code, MavenListener.new(callback)) + rescue REXML::ParseException + # Malformed XML! -- ignore and move on + end + end + end + + end + end +end diff --git a/ruby/gestalt/rules/not_rule.rb b/ruby/gestalt/rules/not_rule.rb new file mode 100644 index 0000000..d782537 --- /dev/null +++ b/ruby/gestalt/rules/not_rule.rb @@ -0,0 +1,16 @@ +module Ohcount + module Gestalt + class NotRule < LogicalRule + def triggers(gestalt_engine) + rules.first && rules.first.triggers(gestalt_engine).any? ? [] : [Trigger.new] + end + + def new_rule(r_class, *args, &block) + raise ArgumentError.new("_not() accepts only a single rule") unless rules.empty? + super(r_class, *args, &block) + end + + end + end +end + diff --git a/ruby/gestalt/rules/or_rule.rb b/ruby/gestalt/rules/or_rule.rb new file mode 100644 index 0000000..d180b03 --- /dev/null +++ b/ruby/gestalt/rules/or_rule.rb @@ -0,0 +1,14 @@ +module Ohcount + module Gestalt + # Will trigger if any sub-rule does + class OrRule < LogicalRule + def triggers(gestalt_engine) + rules.each do |r| + triggers = r.triggers(gestalt_engine) + return triggers if triggers.any? + end + [] + end + end + end +end diff --git a/ruby/gestalt/rules/rule.rb b/ruby/gestalt/rules/rule.rb new file mode 100644 index 0000000..710bcb1 --- /dev/null +++ b/ruby/gestalt/rules/rule.rb @@ -0,0 +1,47 @@ +module Ohcount + module Gestalt + class Rule + def ==(other) + return false unless self.class == other.class + return false unless self.instance_variables == other.instance_variables + self.instance_variables.each do |v| + return false unless self.instance_eval(v) == other.instance_eval(v) + end + true + end + + def each_rule + yield self + end + + def to_sym + self.class.to_sym + end + + # when tallying up libraries, its easier to + # use symbol names instead of class names + # to_sym maps FooLib to :foo_lib + def self.to_sym + @symbol ||= begin + to_s =~ /([^:]*)$/ + naked_classname = $1 + chars = naked_classname.scan(/./) + chars[0] = chars[0].downcase + ruby_s = chars.collect do |char| + char.downcase == char ? char : "_" + char.downcase + end.to_s + ruby_s.intern + end + end + + def self.method_missing(m,*args) + if /(.*)_keywords$/ =~ m.to_s + language = $1 + return rules << KeywordRule.new(language,*args) + end + super + end + + end + end +end diff --git a/ruby/gestalt/rules/xml_keyword_rule.rb b/ruby/gestalt/rules/xml_keyword_rule.rb new file mode 100644 index 0000000..c9607ba --- /dev/null +++ b/ruby/gestalt/rules/xml_keyword_rule.rb @@ -0,0 +1,15 @@ +module Ohcount + module Gestalt + class XmlKeywordRule < KeywordRule + + def initialize(*keywords) + super('xml',*keywords) + end + + def trigger_file?(source_file) + return false unless source_file.polyglot = 'xml' + regexp.match(source_file.language_breakdowns('xml').code) + end + end + end +end diff --git a/ruby/gestalt/trigger.rb b/ruby/gestalt/trigger.rb new file mode 100644 index 0000000..1e66097 --- /dev/null +++ b/ruby/gestalt/trigger.rb @@ -0,0 +1,13 @@ +module Ohcount + module Gestalt + class Trigger + attr_reader :name, :count + + def initialize(args = {}) + @name = args[:name] + @count = args[:count] || 1 + end + + end + end +end diff --git a/ruby/gestalt.rb b/ruby/gestalt.rb new file mode 100644 index 0000000..31f0457 --- /dev/null +++ b/ruby/gestalt.rb @@ -0,0 +1,89 @@ +# gestalt.rb written by Mitchell Foral. mitchellcaladbolg.net. +# See COPYING for license information. +# Ohcount module tweaked for use by Gestalts. + +$: << File.expand_path(File.dirname(__FILE__)) +require "ohcount" + +# gestalt +require "gestalt/trigger" +require "gestalt/definition" +require "gestalt/base" +require "gestalt/definitions" +require "gestalt/dot_net_definitions" +require "gestalt/java_definitions" +require "gestalt/jasper_definitions" +require "gestalt/gestalt_engine" +require "gestalt/gestalt_facts" + + +module Ohcount + class SourceFile + def gestalts + gestalt_engine = Gestalt::GestaltEngine.new + gestalt_engine.process(self) + gestalt_engine.calc_gestalts + gestalt_engine.gestalts + end + end + + class SourceFileList + def analyze_gestalt + @gestalt_engine = Gestalt::GestaltEngine.new + iter = self.head + while (iter) + @gestalt_engine.process(iter.sf) + iter = iter.next + end + @gestalt_engine.calc_gestalts + end + + def gestalts + @gestalt_engine.gestalts if @gestalt_engine + end + + # call analyze to generate facts from a collection of files (typically a + # project directory). Because deducing different facts often requires doing + # similar work, this function allows multiple facts to be extracted in one + # single pass + # + # *Fact* *Types* + # + # :gestalt:: platform dependencies and tools usage + # :languages:: detailed programming languages facts + # :java:: java-related dependencies (jars & imports) + # + # Examples + # + # sfl = SourceFileList.new(:dir => '/foo/bar') + # sfl.analyze(:languages) + # puts sfl.ruby.code.count + # + def analyze(what = [:*]) + what = [what] unless what.is_a?(Array) + + do_gestalt = what.include?(:gestalt) || what.include?(:*) + do_languages = what.include?(:language) || what.include?(:*) + + analyze_languages() if do_languages + analyze_gestalt() if do_gestalt + end + end +end + +if __FILE__ == $0 + sourcefile_list = Ohcount::SourceFileList.new() + sourcefile_list.add_directory('.') if ARGV.size == 0 + ARGV.each do |file_or_path| + if File.directory?(file_or_path) + sourcefile_list.add_directory(file_or_path) + else + sourcefile_list.add_file(file_or_path) + end + end + STDOUT.puts "Examining #{sourcefile_list.size} file(s) for gestalts." + sourcefile_list.analyze_gestalt() + sourcefile_list.gestalts.sort.each do |gestalt| + puts "#{gestalt.type}\t#{gestalt.count.to_s.rjust(8)}\t#{gestalt.name}" + end +end diff --git a/ruby/ohcount.i b/ruby/ohcount.i new file mode 100644 index 0000000..f0b4004 --- /dev/null +++ b/ruby/ohcount.i @@ -0,0 +1,124 @@ + +%module ohcount +%{ +#include "../src/detector.h" +#include "../src/languages.h" +#include "../src/sourcefile.h" +%} + +%include typemaps.i + +%typemap(in) (register const char *str, register unsigned int len) { + Check_Type($input, T_STRING); + $1 = STR2CSTR($input); + $2 = RSTRING($input)->len; +}; + +%typemap(out) char ** { + VALUE arr = rb_ary_new(); + int i; + for (i = 0; $1[i] != NULL; i++) + rb_ary_push(arr, rb_str_new2($1[i])); + $result = arr; +}; + +%nodefaultctor SourceFile; +%immutable; +%include "../src/languages.h" +%include "../src/structs.h" +%mutable; + +%extend SourceFile { + void set_diskpath(const char *diskpath) { + ohcount_sourcefile_set_diskpath(self, diskpath); + } + void set_contents(const char *contents) { + ohcount_sourcefile_set_contents(self, contents); + } + char *get_contents() { + return ohcount_sourcefile_get_contents(self); + } + int contents_size() { + return ohcount_sourcefile_get_contents_size(self); + } + const char *get_language() { + return ohcount_sourcefile_get_language(self); + } + void parse() { + ohcount_sourcefile_parse(self); + } + ParsedLanguageList *get_parsed_language_list() { + return ohcount_sourcefile_get_parsed_language_list(self); + } + LicenseList *get_license_list() { + return ohcount_sourcefile_get_license_list(self); + } + LocList *get_loc_list() { + return ohcount_sourcefile_get_loc_list(self); + } + LocDeltaList *_diff(SourceFile *to) { + return ohcount_sourcefile_diff(self, to); + } + void set_filenames(VALUE filenames) { + int i, length = RARRAY(filenames)->len; + char **fnames = calloc(length + 1, sizeof(char *)); + VALUE *iter = RARRAY(filenames)->ptr; + for (i = 0; i < length; i++, iter++) + fnames[i] = STR2CSTR(*iter); + ohcount_sourcefile_set_filenames(self, fnames); + free(fnames); + } + SourceFile(const char *filepath, VALUE opt_hash=NULL) { + SourceFile *sourcefile = ohcount_sourcefile_new(filepath); + if (opt_hash) { + VALUE val; + val = rb_hash_aref(opt_hash, ID2SYM(rb_intern("contents"))); + if (val && rb_type(val) == T_STRING) + ohcount_sourcefile_set_contents(sourcefile, STR2CSTR(val)); + val = rb_hash_aref(opt_hash, ID2SYM(rb_intern("file_location"))); + if (val && rb_type(val) == T_STRING) + ohcount_sourcefile_set_diskpath(sourcefile, STR2CSTR(val)); + val = rb_hash_aref(opt_hash, ID2SYM(rb_intern("filenames"))); + if (val && rb_type(val) == T_ARRAY) + SourceFile_set_filenames(sourcefile, val); + } + return sourcefile; + } + ~SourceFile() { + ohcount_sourcefile_free(self); + } +}; + +%extend SourceFileList { + static VALUE rb_add_directory(VALUE directory, SourceFileList *list) { + if (directory && rb_type(directory) == T_STRING) + ohcount_sourcefile_list_add_directory(list, STR2CSTR(directory)); + return Qnil; + } + SourceFileList(VALUE opt_hash=NULL) { + SourceFileList *list = ohcount_sourcefile_list_new(); + if (opt_hash) { + VALUE val; + val = rb_hash_aref(opt_hash, ID2SYM(rb_intern("paths"))); + if (val && rb_type(val) == T_ARRAY) + rb_iterate(rb_each, val, SourceFileList_rb_add_directory, (VALUE)list); + } + return list; + } + ~SourceFileList() { + ohcount_sourcefile_list_free(self); + } + void add_file(const char *filepath) { + ohcount_sourcefile_list_add_file(self, filepath); + } + void add_directory(const char *directory) { + ohcount_sourcefile_list_add_directory(self, directory); + } + LocList *analyze_languages() { + return ohcount_sourcefile_list_analyze_languages(self); + } +} + +int ohcount_is_binary_filename(const char *filename); + +struct LanguageMap *ohcount_hash_language_from_name(register const char *str, register unsigned int len); diff --git a/ruby/ohcount.rb b/ruby/ohcount.rb new file mode 100644 index 0000000..c238bc0 --- /dev/null +++ b/ruby/ohcount.rb @@ -0,0 +1,107 @@ +# ohcount.rb written by Mitchell Foral. mitchellcaladbolg.net. +# See COPYING for license information. +# Ohcount module tweaked for use by Ohloh. + +$: << File.expand_path(File.dirname(__FILE__)) + +begin + require 'ohcount.so' +rescue LoadError + require 'rbconfig' + include Config + require "#{Config::CONFIG['arch']}/ohcount.so" +end + +module Ohcount + class SourceFile + def file_location=(value) set_diskpath(value) end + def file_location() diskpath() end + def filenames=(value) set_filenames(value) end + def contents() get_contents() end + def polyglot() get_language() end + + def language_breakdowns + list = get_parsed_language_list() + return array_from_list(list, :pl) + end + + def language_breakdown(language) + return language_breakdowns().find { |lb| lb.name == language.to_s } + end + + def licenses + list = get_license_list() + array = array_from_list(list, :lic) + return array.map! { |l| l.name } + end + + def languages + return language_breakdowns().collect { |lb| lb.name } + end + + def loc_list + list = get_loc_list() + return array_from_list(list, :loc) + end + + def diff(to) + list = _diff(to) + ret = array_from_list(list, :delta) + class << ret + def loc_deltas() self end + end + return ret + end + + def each + filenames.each { |f| yield f } + end + + private + + def array_from_list(list, method) + array = Array.new + iter = list.head + while (iter) + array << iter.send(method) + iter = iter.next + end + return array + end + end + + class SourceFileList + def each_source_file + iter = self.head + while (iter) + yield iter.sf if iter.sf.polyglot + iter = iter.next + end + end + + # this should yield each filename, not an sf object + def each + iter = self.head + while (iter) + yield iter.sf.filename if iter.sf + iter = iter.next + end + end + + def size + count = 0 + iter = self.head + while (iter) + count += 1 + iter = iter.next + end + return count + end + end + + class Detector + def self.binary_filename?(filename) + return Ohcount.ohcount_is_binary_filename(filename) == 1 + end + end +end diff --git a/src/detector.c b/src/detector.c new file mode 100644 index 0000000..863b379 --- /dev/null +++ b/src/detector.c @@ -0,0 +1,695 @@ +// detector.c written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#include +#include +#include +#include +#include + +#include "detector.h" +#include "languages.h" +#include "log.h" + +#include "hash/cppheader_hash.h" +#include "hash/disambiguatefunc_hash.h" +#include "hash/extension_hash.h" +#include "hash/filename_hash.h" + +#define ISBINARY(x) (x[0] == '\1') +#define ISAMBIGUOUS(x) (x[0] == '\2') +#define DISAMBIGUATEWHAT(x) &x[1] + +const char *ohcount_detect_language(SourceFile *sourcefile) { + const char *language = NULL; + char *p, *pe; + int length; + + // Attempt to detect based on file extension. + length = strlen(sourcefile->ext); + struct ExtensionMap *re = ohcount_hash_language_from_ext(sourcefile->ext, + length); + if (re) language = re->value; + if (language == NULL) { + // Try the lower-case version of this extension. + char lowerext[length + 1]; + strncpy(lowerext, sourcefile->ext, length); + lowerext[length] = '\0'; + for (p = lowerext; p < lowerext + length; p++) *p = tolower(*p); + struct ExtensionMap *re = ohcount_hash_language_from_ext(lowerext, length); + if (re) return re->value; + } + if (language) { + if (ISAMBIGUOUS(language)) { + // Call the appropriate function for disambiguation. + length = strlen(DISAMBIGUATEWHAT(language)); + struct DisambiguateFuncsMap *rd = + ohcount_hash_disambiguate_func_from_id(DISAMBIGUATEWHAT(language), + length); + if (rd) return rd->value(sourcefile); + } else return ISBINARY(language) ? NULL : language; + } + + // Attempt to detect based on filename. + length = strlen(sourcefile->filename); + struct FilenameMap *rf = + ohcount_hash_language_from_filename(sourcefile->filename, length); + if (rf) return rf->value; + + char line[81] = { '\0' }, buf[81]; + + // Attempt to detect using Emacs mode line (/^-\*-\s*mode[\s:]*\w/i). + p = ohcount_sourcefile_get_contents(sourcefile); + pe = p; + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + while (pe < eof) { + // Get the contents of the first line. + while (pe < eof && *pe != '\r' && *pe != '\n') pe++; + length = (pe - p <= sizeof(line)) ? pe - p : sizeof(line); + strncpy(line, p, length); + line[length] = '\0'; + if (*line == '#' && *(line + 1) == '!') { + // First line was sh-bang; loop to get contents of second line. + while (*pe == '\r' || *pe == '\n') pe++; + p = pe; + } else break; + } + char *eol = line + strlen(line); + for (p = line; p < eol; p++) *p = tolower(*p); + p = strstr(line, "-*-"); + if (p) { + p += 3; + while (*p == ' ' || *p == '\t') p++; + if (strncmp(p, "mode", 4) == 0) { + p += 4; + while (*p == ' ' || *p == '\t' || *p == ':') p++; + } + pe = p; + while (isalnum(*pe)) pe++; + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + struct LanguageMap *rl = ohcount_hash_language_from_name(buf, length); + if (rl) return rl->name; + } + + // Attempt to detect based on Unix 'file' command. + int tmpfile = 0; + char *path = sourcefile->filepath; + if (sourcefile->diskpath) + path = sourcefile->diskpath; + if (access(path, F_OK) != 0) { // create temporary file + path = malloc(21); + strncpy(path, "/tmp/ohcount_XXXXXXX", 20); + *(path + 21) = '\0'; + int fd = mkstemp(path); + char *contents = ohcount_sourcefile_get_contents(sourcefile); + log_it("contents:"); + log_it(contents); + length = contents ? strlen(contents) : 0; + write(fd, contents, length); + close(fd); + tmpfile = 1; + } + char command[strlen(path) + 11]; + sprintf(command, "file -b '%s'", path); + FILE *f = popen(command, "r"); + if (f) { + fgets(line, sizeof(line), f); + char *eol = line + strlen(line); + for (p = line; p < eol; p++) *p = tolower(*p); + p = strstr(line, "script text"); + if (p && p == line) { // /^script text(?: executable)? for \w/ + p = strstr(line, "for "); + if (p) { + p += 4; + pe = p; + while (isalnum(*pe)) pe++; + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + struct LanguageMap *rl = ohcount_hash_language_from_name(buf, length); + if (rl) language = rl->name; + } + } else if (p) { // /(\w+)(?: -\w+)* script text/ + do { + p--; + pe = p; + while (*p == ' ') p--; + while (p != line && isalnum(*(p - 1))) p--; + if (p != line && *(p - 1) == '-') p--; + } while (*p == '-'); // Skip over any switches. + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + struct LanguageMap *rl = ohcount_hash_language_from_name(buf, length); + if (rl) language = rl->name; + } else if (strstr(line, "xml")) language = LANG_XML; + pclose(f); + if (tmpfile) { + remove(path); + free(path); + } + if (language) return language; + } + + return NULL; +} + +const char *disambiguate_aspx(SourceFile *sourcefile) { + char *p = ohcount_sourcefile_get_contents(sourcefile); + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + for (; p < eof; p++) { + // /<%@\s*Page[^>]+Language="VB"[^>]+%>/ + p = strstr(p, "<%@"); + if (!p) + break; + char *pe = strstr(p, "%>"); + if (p && pe) { + p += 3; + const int length = pe - p; + char buf[length]; + strncpy(buf, p, length); + buf[length] = '\0'; + char *eol = buf + strlen(buf); + for (p = buf; p < eol; p++) *p = tolower(*p); + p = buf; + while (*p == ' ' || *p == '\t') p++; + if (strncmp(p, "page", 4) == 0) { + p += 4; + if (strstr(p, "language=\"vb\"")) + return LANG_VB_ASPX; + } + } + } + return LANG_CS_ASPX; +} + +const char *disambiguate_b(SourceFile *sourcefile) { + char *p = ohcount_sourcefile_get_contents(sourcefile); + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + while (p < eof) { + // /(implement[ \t])|(include[ \t]+"[^"]*";)| + // ((return|break|continue).*;|(pick|case).*\{)/ + if (strncmp(p, "implement", 9) == 0 && + (*(p + 9) == ' ' || *(p + 9) == '\t')) + return LANG_LIMBO; + else if (strncmp(p, "include", 7) == 0 && + (*(p + 7) == ' ' || *(p + 7) == '\t')) { + p += 7; + while (*p == ' ' || *p == '\t') p++; + if (*p == '"') { + while (*p != '"' && p < eof) p++; + if (*p == '"' && *(p + 1) == ';') + return LANG_LIMBO; + } + } else if (strncmp(p, "return", 6) == 0 || + strncmp(p, "break", 5) == 0 || + strncmp(p, "continue", 8) == 0) { + if (strstr(p, ";")) + return LANG_LIMBO; + } else if (strncmp(p, "pick", 4) == 0 || + strncmp(p, "case", 4) == 0) { + if (strstr(p, "{")) + return LANG_LIMBO; + } + p++; + } + return disambiguate_basic(sourcefile); +} + +const char *disambiguate_basic(SourceFile *sourcefile) { + char *p, *pe; + int length; + + // Attempt to detect based on file contents. + char line[81]; + p = ohcount_sourcefile_get_contents(sourcefile); + pe = p; + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + while (pe < eof) { + // Get a line at a time. + while (pe < eof && *pe != '\r' && *pe != '\n') pe++; + length = (pe - p <= sizeof(line)) ? pe - p : sizeof(line); + strncpy(line, p, length); + line[length] = '\0'; + char *line_end = pe; + + p = line; + if (isdigit(*p)) { + // /^\d+\s+\w/ + p++; + while (isdigit(*p)) p++; + if (*p == ' ' || *p == '\t') { + p++; + while (*p == ' ' || *p == '\t') p++; + if (isalnum(*p)) + return LANG_CLASSIC_BASIC; + } + } + + // Next line. + pe = line_end; + while (*pe == '\r' || *pe == '\n') pe++; + p = pe; + } + + // Attempt to detect from associated VB files in file context. + char **filenames = ohcount_sourcefile_get_filenames(sourcefile); + if (filenames) { + int i; + for (i = 0; filenames[i] != NULL; i++) { + pe = filenames[i] + strlen(filenames[i]); + p = pe; + while (p > filenames[i] && *(p - 1) != '.') p--; + length = pe - p; + if (length == 3 && + (strncmp(p, "frm", length) == 0 || + strncmp(p, "frx", length) == 0 || + strncmp(p, "vba", length) == 0 || + strncmp(p, "vbp", length) == 0 || + strncmp(p, "vbs", length) == 0)) { + return LANG_VISUALBASIC; + } + } + } + + return LANG_STRUCTURED_BASIC; +} + +const char *disambiguate_cs(SourceFile *sourcefile) { + // Attempt to detect based on file contents. + char *contents = ohcount_sourcefile_get_contents(sourcefile); + if (contents && strstr(contents, "filename); + if (strcmp(sourcefile->ext, "h") == 0) { + char path[length]; + strncpy(path, sourcefile->filename, length); + path[length] = '\0'; + *(path + length - 1) = 'm'; + char **filenames = ohcount_sourcefile_get_filenames(sourcefile); + if (filenames) { + int i; + for (i = 0; filenames[i] != NULL; i++) + if (strcmp(path, filenames[i]) == 0) + return LANG_OBJECTIVE_C; + } + } + + // Attempt to detect based on file contents. + char line[81], buf[81]; + p = ohcount_sourcefile_get_contents(sourcefile); + pe = p; + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + while (pe < eof) { + // Get a line at a time. + while (pe < eof && *pe != '\r' && *pe != '\n') pe++; + length = (pe - p <= sizeof(line)) ? pe - p : sizeof(line); + strncpy(line, p, length); + line[length] = '\0'; + char *eol = line + strlen(line); + char *line_end = pe; + + // Look for C++ headers. + if (*line == '#') { + p = line + 1; + while (*p == ' ' || *p == '\t') p++; + if (strncmp(p, "include", 7) == 0 && + (*(p + 7) == ' ' || *(p + 7) == '\t')) { + // /^#\s*include\s+[<"][^>"]+[>"]/ + p += 8; + while (*p == ' ' || *p == '\t') p++; + if (*p == '<' || *p == '"') { + // Is the header file a C++ header file? + p++; + pe = p; + while (pe < eol && *pe != '>' && *pe != '"') pe++; + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + if (ohcount_hash_is_cppheader(buf, length)) + return LANG_CPP; + // Is the extension for the header file a C++ file? + p = pe; + while (p > line && *(p - 1) != '.') p--; + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + struct ExtensionMap *re = ohcount_hash_language_from_ext(buf, length); + if (re && strcmp(re->value, LANG_CPP) == 0) + return LANG_CPP; + } + } + } + + // Look for C++ keywords. + p = line; + while (p < eol) { + if (islower(*p) && p != line && !isalnum(*(p - 1)) && *(p - 1) != '_') { + pe = p; + while (islower(*pe)) pe++; + if (!isalnum(*pe) && *pe != '_') { + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + if (strcmp(buf, "class") == 0 || + strcmp(buf, "namespace") == 0 || + strcmp(buf, "template") == 0 || + strcmp(buf, "typename") == 0) + return LANG_CPP; + } + p = pe + 1; + } else p++; + } + + // Next line. + pe = line_end; + while (*pe == '\r' || *pe == '\n') pe++; + p = pe; + } + + // Nothing to suggest C++. + return LANG_C; +} + +const char *disambiguate_in(SourceFile *sourcefile) { + char *p, *pe; + int length; + const char *language = NULL; + + p = sourcefile->filepath; + pe = p + strlen(p) - 3; + if (strstr(p, ".") <= pe) { + // Only if the filename has an extension prior to the .in + length = pe - p; + char buf[length]; + strncpy(buf, p, length); + buf[length] = '\0'; + SourceFile *undecorated = ohcount_sourcefile_new(buf); + p = ohcount_sourcefile_get_contents(sourcefile); + if (!p) { + return NULL; + } + // The filepath without the '.in' extension does not exist on disk. The + // sourcefile->diskpath field must be set incase the detector needs to run + // 'file -b' on the file. + ohcount_sourcefile_set_diskpath(undecorated, sourcefile->filepath); + ohcount_sourcefile_set_contents(undecorated, p); + char **filenames = ohcount_sourcefile_get_filenames(sourcefile); + ohcount_sourcefile_set_filenames(undecorated, filenames); + language = ohcount_sourcefile_get_language(undecorated); + ohcount_sourcefile_free(undecorated); + } + return language; +} + +const char *disambiguate_inc(SourceFile *sourcefile) { + char *p = ohcount_sourcefile_get_contents(sourcefile); + if (p) { + char *eof = p + strlen(p); + while (p < eof) { + if (*p == '\0') + return BINARY; + else if (*p == '?' && strncmp(p + 1, "php", 3) == 0) + return LANG_PHP; + p++; + } + } + return NULL; +} + +const char *disambiguate_m(SourceFile *sourcefile) { + char *p, *pe; + int length; + + // Attempt to detect based on a weighted heuristic of file contents. + int matlab_score = 0; + int objective_c_score = 0; + int limbo_score = 0; + int octave_syntax_detected = 0; + + int i, has_h_headers = 0, has_c_files = 0; + char **filenames = ohcount_sourcefile_get_filenames(sourcefile); + if (filenames) { + for (i = 0; filenames[i] != NULL; i++) { + p = filenames[i]; + pe = p + strlen(p); + if (pe - p >= 4) { + if (*(pe - 4) == '.' && *(pe - 3) == 'c' && + ((*(pe - 2) == 'p' && *(pe - 1) == 'p') || + (*(pe - 2) == '+' && *(pe - 1) == '+') || + (*(pe - 2) == 'x' && *(pe - 1) == 'x'))) { + has_c_files = 1; + break; // short circuit + } + } else if (pe - p >= 3) { + if (*(pe - 3) == '.' && *(pe - 2) == 'c' && *(pe - 1) == 'c') { + has_c_files = 1; + break; // short circuit + } + } else if (pe - p >= 2) { + if (*(pe - 2) == '.') { + if (*(pe - 1) == 'h') + has_h_headers = 1; + else if (*(pe - 1) == 'c' || *(pe - 1) == 'C') { + has_c_files = 1; + break; // short circuit + } + } + } + } + } + if (has_h_headers && !has_c_files) + objective_c_score += 5; + + char line[81], buf[81]; + p = ohcount_sourcefile_get_contents(sourcefile); + pe = p; + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + while (pe < eof) { + // Get a line at a time. + while (pe < eof && *pe != '\r' && *pe != '\n') pe++; + length = (pe - p <= sizeof(line)) ? pe - p : sizeof(line); + strncpy(line, p, length); + line[length] = '\0'; + char *eol = line + strlen(line); + char *line_end = pe; + + // Look for tell-tale lines. + p = line; + while (*p == ' ' || *p == '\t') p++; + if (*p == '%') { // Matlab comment + matlab_score++; + } else if (*p == '#' && strncmp(p, "#import", 7) == 0) { // Objective C + objective_c_score++; + } else if (*p == '#') { // Limbo or Octave comment + while (*p == '#') p++; + if (*p == ' ' || *p == '\t') { + limbo_score++; + matlab_score++; + octave_syntax_detected = 1; + } + } else if (*p == '/' && *(p + 1) == '/' || *(p + 1) == '*') { + objective_c_score++; // Objective C comment + } else if (*p == '+' || *p == '-') { // Objective C method signature + objective_c_score++; + } else if (*p == '@' || *p == '#') { // Objective C method signature + if (strncmp(p, "@implementation", 15) == 0 || + strncmp(p, "@interface", 10) == 0) + objective_c_score++; + } else if (strncmp(p, "function", 8) == 0) { // Matlab or Octave function + p += 8; + while (*p == ' ' || *p == '\t') p++; + if (*p == '(') + matlab_score++; + } else if (strncmp(p, "include", 7) == 0) { // Limbo include + // /^include[ \t]+"[^"]+\.m";/ + p += 7; + if (*p == ' ' || *p == '\t') { + while (*p == ' ' || *p == '\t') p++; + if (*p == '"') { + while (*p != '"' && p < eol) p++; + if (*p == '"' && *(p - 2) == '.' && *(p - 1) == 'm') + limbo_score++; + } + } + } + + // Look for Octave keywords. + p = line; + while (p < eol) { + if (islower(*p) && p != line && !isalnum(*(p - 1))) { + pe = p; + while (islower(*pe) || *pe == '_') pe++; + if (!isalnum(*pe)) { + length = pe - p; + strncpy(buf, p, length); + buf[length] = '\0'; + if (strcmp(buf, "end_try_catch") == 0 || + strcmp(buf, "end_unwind_protect") == 0 || + strcmp(buf, "endfunction") == 0 || + strcmp(buf, "endwhile") == 0) + octave_syntax_detected = 1; + } + p = pe + 1; + } else p++; + } + + // Look for Limbo declarations + p = line; + while (p < eol) { + if (*p == ':' && (*(p + 1) == ' ' || *(p + 1) == '\t')) { + // /:[ \t]+(module|adt|fn ?\(|con[ \t])/ + p += 2; + if (strncmp(p, "module", 6) == 0 && !isalnum(*(p + 6)) || + strncmp(p, "adt", 3) == 0 && !isalnum(*(p + 3)) || + strncmp(p, "fn", 2) == 0 && + (*(p + 2) == ' ' && *(p + 3) == '(' || *(p + 2) == '(') || + strncmp(p, "con", 3) == 0 && + (*(p + 3) == ' ' || *(p + 3) == '\t')) + limbo_score++; + } else p++; + } + + // Next line. + pe = line_end; + while (*pe == '\r' || *pe == '\n') pe++; + p = pe; + } + + if (limbo_score > objective_c_score && limbo_score > matlab_score) + return LANG_LIMBO; + else if (objective_c_score > matlab_score) + return LANG_OBJECTIVE_C; + else + return octave_syntax_detected ? LANG_OCTAVE : LANG_MATLAB; +} + +#define QMAKE_SOURCES_SPACE "SOURCES +=" +#define QMAKE_SOURCES "SOURCES+=" +#define QMAKE_CONFIG_SPACE "CONFIG +=" +#define QMAKE_CONFIG "CONFIG+=" + +const char *disambiguate_pro(SourceFile *sourcefile) { + char *p = ohcount_sourcefile_get_contents(sourcefile); + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + for (; p < eof; p++) { + if (strncmp(p, QMAKE_SOURCES_SPACE, strlen(QMAKE_SOURCES_SPACE)) == 0 || + strncmp(p, QMAKE_SOURCES, strlen(QMAKE_SOURCES)) == 0 || + strncmp(p, QMAKE_CONFIG_SPACE, strlen(QMAKE_CONFIG_SPACE)) == 0 || + strncmp(p, QMAKE_CONFIG, strlen(QMAKE_CONFIG)) == 0) + return LANG_MAKE; // really QMAKE + } + return LANG_IDL_PVWAVE; +} + +const char *disambiguate_st(SourceFile *sourcefile) { + char *p, *pe; + int length; + + // Attempt to detect based on file contents. + int found_assignment = 0, found_block_start = 0, found_block_end = 0; + + char line[81]; + p = ohcount_sourcefile_get_contents(sourcefile); + pe = p; + char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile); + while (pe < eof) { + // Get a line at a time. + while (p < eof && *pe != '\r' && *pe != '\n') pe++; + length = (pe - p <= sizeof(line)) ? pe - p : sizeof(line); + strncpy(line, p, length); + line[length] = '\0'; + char *eol = line + strlen(line); + char *line_end = pe; + + for (p = line; p < eol; p++) { + if (*p == ':') { + p++; + while (p < eol && (*p == ' ' || *p == '\t')) p++; + if (*p == '=') + found_assignment = 1; + else if (*p == '[') + found_block_start = 1; + } else if (*p == ']' && *(p + 1) == '.') found_block_end = 1; + if (found_assignment && found_block_start && found_block_end) + return LANG_SMALLTALK; + } + + // Next line. + pe = line_end; + while (*pe == '\r' || *pe == '\n') pe++; + p = pe; + } + + return NULL; +} + +int ohcount_is_binary_filename(const char *filename) { + char *p = (char *)filename + strlen(filename); + while (p > filename && *(p - 1) != '.') p--; + if (p > filename) { + struct ExtensionMap *re; + int length = strlen(p); + re = ohcount_hash_language_from_ext(p, length); + if (re) return ISBINARY(re->value); + // Try the lower-case version of this extension. + char lowerext[length]; + strncpy(lowerext, p, length); + lowerext[length] = '\0'; + for (p = lowerext; p < lowerext + length; p++) *p = tolower(*p); + re = ohcount_hash_language_from_ext(lowerext, length); + if (re) return ISBINARY(re->value); + } + return 0; +} diff --git a/src/detector.h b/src/detector.h new file mode 100644 index 0000000..53277b8 --- /dev/null +++ b/src/detector.h @@ -0,0 +1,34 @@ +// detector.h written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#ifndef OHCOUNT_DETECTOR_H +#define OHCOUNT_DETECTOR_H + +/** + * @page detector_doc Detector Documentation + * + * @section language How to Add a New Language + * + * @li Add your language to 'src/languages.h' and 'src/hash/languages.gperf'. + * @li Update 'src/hash/extensions.gperf' to identify files that use the new + * language (or 'src/hash/filenames.gperf'). + * @li Regenerate the hash header files with 'src/hash/generate_headers'. + * @li Add your tests to 'test/unit/detector_test.h', rebuild the tests, and + * run them to confirm the detector changes. + * @li Follow the detailed instructions in the Parser Documentation. + * @li Rebuild Ohcount. + */ + +#include "sourcefile.h" + +/** + * Attempts to detect the programming language used by the given file. + * The returned pointer is used internally and must not be 'free'd. + * @param sourcefile A SourceFile created by ohcount_sourcefile_new(). + * @return pointer to a string with the detected language or NULL. + */ +const char *ohcount_detect_language(SourceFile *sourcefile); + +int ohcount_is_binary_filename(const char *filename); + +#endif diff --git a/src/diff.c b/src/diff.c new file mode 100644 index 0000000..1aa6bcf --- /dev/null +++ b/src/diff.c @@ -0,0 +1,700 @@ +#include +#include +#include + +/* + * The bulk of this software is derived from Plan 9 and is thus distributed + * under the Lucent Public License, Version 1.02, reproduced below. + * + * =================================================================== + * + * Lucent Public License Version 1.02 + * + * THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC + * LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE + * PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + * + * 1. DEFINITIONS + * + * "Contribution" means: + * + * a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original + * Program, and + * b. in the case of each Contributor, + * + * i. changes to the Program, and + * ii. additions to the Program; + * + * where such changes and/or additions to the Program were added to the + * Program by such Contributor itself or anyone acting on such + * Contributor's behalf, and the Contributor explicitly consents, in + * accordance with Section 3C, to characterization of the changes and/or + * additions as Contributions. + * + * "Contributor" means LUCENT and any other entity that has Contributed a + * Contribution to the Program. + * + * "Distributor" means a Recipient that distributes the Program, + * modifications to the Program, or any part thereof. + * + * "Licensed Patents" mean patent claims licensable by a Contributor + * which are necessarily infringed by the use or sale of its Contribution + * alone or when combined with the Program. + * + * "Original Program" means the original version of the software + * accompanying this Agreement as released by LUCENT, including source + * code, object code and documentation, if any. + * + * "Program" means the Original Program and Contributions or any part + * thereof + * + * "Recipient" means anyone who receives the Program under this + * Agreement, including all Contributors. + * + * 2. GRANT OF RIGHTS + * + * a. Subject to the terms of this Agreement, each Contributor hereby + * grants Recipient a non-exclusive, worldwide, royalty-free copyright + * license to reproduce, prepare derivative works of, publicly display, + * publicly perform, distribute and sublicense the Contribution of such + * Contributor, if any, and such derivative works, in source code and + * object code form. + * + * b. Subject to the terms of this Agreement, each Contributor hereby + * grants Recipient a non-exclusive, worldwide, royalty-free patent + * license under Licensed Patents to make, use, sell, offer to sell, + * import and otherwise transfer the Contribution of such Contributor, if + * any, in source code and object code form. The patent license granted + * by a Contributor shall also apply to the combination of the + * Contribution of that Contributor and the Program if, at the time the + * Contribution is added by the Contributor, such addition of the + * Contribution causes such combination to be covered by the Licensed + * Patents. The patent license granted by a Contributor shall not apply + * to (i) any other combinations which include the Contribution, nor to + * (ii) Contributions of other Contributors. No hardware per se is + * licensed hereunder. + * + * c. Recipient understands that although each Contributor grants the + * licenses to its Contributions set forth herein, no assurances are + * provided by any Contributor that the Program does not infringe the + * patent or other intellectual property rights of any other entity. Each + * Contributor disclaims any liability to Recipient for claims brought by + * any other entity based on infringement of intellectual property rights + * or otherwise. As a condition to exercising the rights and licenses + * granted hereunder, each Recipient hereby assumes sole responsibility + * to secure any other intellectual property rights needed, if any. For + * example, if a third party patent license is required to allow + * Recipient to distribute the Program, it is Recipient's responsibility + * to acquire that license before distributing the Program. + * + * d. Each Contributor represents that to its knowledge it has sufficient + * copyright rights in its Contribution, if any, to grant the copyright + * license set forth in this Agreement. + * + * 3. REQUIREMENTS + * + * A. Distributor may choose to distribute the Program in any form under + * this Agreement or under its own license agreement, provided that: + * + * a. it complies with the terms and conditions of this Agreement; + * + * b. if the Program is distributed in source code or other tangible + * form, a copy of this Agreement or Distributor's own license agreement + * is included with each copy of the Program; and + * + * c. if distributed under Distributor's own license agreement, such + * license agreement: + * + * i. effectively disclaims on behalf of all Contributors all warranties + * and conditions, express and implied, including warranties or + * conditions of title and non-infringement, and implied warranties or + * conditions of merchantability and fitness for a particular purpose; + * ii. effectively excludes on behalf of all Contributors all liability + * for damages, including direct, indirect, special, incidental and + * consequential damages, such as lost profits; and + * iii. states that any provisions which differ from this Agreement are + * offered by that Contributor alone and not by any other party. + * + * B. Each Distributor must include the following in a conspicuous + * location in the Program: + * + * Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights + * Reserved. + * + * C. In addition, each Contributor must identify itself as the + * originator of its Contribution in a manner that reasonably allows + * subsequent Recipients to identify the originator of the Contribution. + * Also, each Contributor must agree that the additions and/or changes + * are intended to be a Contribution. Once a Contribution is contributed, + * it may not thereafter be revoked. + * + * 4. COMMERCIAL DISTRIBUTION + * + * Commercial distributors of software may accept certain + * responsibilities with respect to end users, business partners and the + * like. While this license is intended to facilitate the commercial use + * of the Program, the Distributor who includes the Program in a + * commercial product offering should do so in a manner which does not + * create potential liability for Contributors. Therefore, if a + * Distributor includes the Program in a commercial product offering, + * such Distributor ("Commercial Distributor") hereby agrees to defend + * and indemnify every Contributor ("Indemnified Contributor") against + * any losses, damages and costs (collectively"Losses") arising from + * claims, lawsuits and other legal actions brought by a third party + * against the Indemnified Contributor to the extent caused by the acts + * or omissions of such Commercial Distributor in connection with its + * distribution of the Program in a commercial product offering. The + * obligations in this section do not apply to any claims or Losses + * relating to any actual or alleged intellectual property infringement. + * In order to qualify, an Indemnified Contributor must: a) promptly + * notify the Commercial Distributor in writing of such claim, and b) + * allow the Commercial Distributor to control, and cooperate with the + * Commercial Distributor in, the defense and any related settlement + * negotiations. The Indemnified Contributor may participate in any such + * claim at its own expense. + * + * For example, a Distributor might include the Program in a commercial + * product offering, Product X. That Distributor is then a Commercial + * Distributor. If that Commercial Distributor then makes performance + * claims, or offers warranties related to Product X, those performance + * claims and warranties are such Commercial Distributor's responsibility + * alone. Under this section, the Commercial Distributor would have to + * defend claims against the Contributors related to those performance + * claims and warranties, and if a court requires any Contributor to pay + * any damages as a result, the Commercial Distributor must pay those + * damages. + * + * 5. NO WARRANTY + * + * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS + * PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY + * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY + * OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely + * responsible for determining the appropriateness of using and + * distributing the Program and assumes all risks associated with its + * exercise of rights under this Agreement, including but not limited to + * the risks and costs of program errors, compliance with applicable + * laws, damage to or loss of data, programs or equipment, and + * unavailability or interruption of operations. + * + * 6. DISCLAIMER OF LIABILITY + * + * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR + * ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING + * WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR + * DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED + * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * 7. EXPORT CONTROL + * + * Recipient agrees that Recipient alone is responsible for compliance + * with the United States export administration regulations (and the + * export control laws and regulation of any other countries). + * + * 8. GENERAL + * + * If any provision of this Agreement is invalid or unenforceable under + * applicable law, it shall not affect the validity or enforceability of + * the remainder of the terms of this Agreement, and without further + * action by the parties hereto, such provision shall be reformed to the + * minimum extent necessary to make such provision valid and enforceable. + * + * If Recipient institutes patent litigation against a Contributor with + * respect to a patent applicable to software (including a cross-claim or + * counterclaim in a lawsuit), then any patent licenses granted by that + * Contributor to such Recipient under this Agreement shall terminate as + * of the date such litigation is filed. In addition, if Recipient + * institutes patent litigation against any entity (including a + * cross-claim or counterclaim in a lawsuit) alleging that the Program + * itself (excluding combinations of the Program with other software or + * hardware) infringes such Recipient's patent(s), then such Recipient's + * rights granted under Section 2(b) shall terminate as of the date such + * litigation is filed. + * + * All Recipient's rights under this Agreement shall terminate if it + * fails to comply with any of the material terms or conditions of this + * Agreement and does not cure such failure in a reasonable period of + * time after becoming aware of such noncompliance. If all Recipient's + * rights under this Agreement terminate, Recipient agrees to cease use + * and distribution of the Program as soon as reasonably practicable. + * However, Recipient's obligations under this Agreement and any licenses + * granted by Recipient relating to the Program shall continue and + * survive. + * + * LUCENT may publish new versions (including revisions) of this + * Agreement from time to time. Each new version of the Agreement will be + * given a distinguishing version number. The Program (including + * Contributions) may always be distributed subject to the version of the + * Agreement under which it was received. In addition, after a new + * version of the Agreement is published, Contributor may elect to + * distribute the Program (including its Contributions) under the new + * version. No one other than LUCENT has the right to modify this + * Agreement. Except as expressly stated in Sections 2(a) and 2(b) above, + * Recipient receives no rights or licenses to the intellectual property + * of any Contributor under this Agreement, whether expressly, by + * implication, estoppel or otherwise. All rights in the Program not + * expressly granted under this Agreement are reserved. + * + * This Agreement is governed by the laws of the State of New York and + * the intellectual property laws of the United States of America. No + * party to this Agreement will bring a legal action under this Agreement + * more than one year after the cause of action arose. Each party waives + * its rights to a jury trial in any resulting litigation. + */ + +#include +#include + +#include "diff.h" + +struct cand { + int x; + int y; + int pred; +}; + +struct line { + int serial; + int value; +}; + +int len[2]; +struct line *file[2]; +struct line *sfile[2]; // shortened by pruning common prefix and suffix +int slen[2]; +int pref, suff; // length of prefix and suffix +int *class; // will be overlaid on file[0] +int *member; // will be overlaid on file[1] +int *klist; // will be overlaid on file[0] after class +struct cand *clist; // merely a free storage pot for candidates +int clen; +int *J; // will be overlaid on class + +#define HALFLONG 16 +#define low(x) (x&((1L<>HALFLONG) + +/** + * Returns a computed hash for a given string. + * Hashing has the effect of arranging line in 7-bit bytes and then summing 1-s + * complement in 16-bit hunks. + * @param line The line of a buffer to hash. + */ +static int hash(char *line) { + long sum; + unsigned shift; + char *p; + int len; + + sum = 1; + shift = 0; + len = strlen(line); + p = line; + while (len--) { + sum += (long)*p++ << (shift &= (HALFLONG-1)); + shift += 7; + } + sum = low(sum) + high(sum); + return ((short)low(sum) + (short)high(sum)); +} + +/** + * Hashes each line in the given string buffer and stores it internally. + * @param i 0 for diff 'from', 1 for diff 'to'. + * @param buf The string buffer to prepare from. + */ +void prepare(int i, const char *buf) { + struct line *p; + int j; + char bufcpy[strlen(buf)]; + char *l; + + p = malloc(3*sizeof(struct line)); + j = 0; + strncpy(bufcpy, buf, strlen(buf)); + bufcpy[strlen(buf)] = 0; + l = strtok(bufcpy, "\n"); + while (l) { + p = realloc(p, (++j+3)*sizeof(struct line)); + p[j].value = hash(l); + l = strtok(NULL, "\n"); + } + len[i] = j; + file[i] = p; +} + +/** + * Adds to the count of lines added and removed for this diff. + * Diff 'from' chunks are counted as lines removed and diff 'to' chunks are + * counted as lines added. + * @param a The diff 'from' chunk's beginning line number. + * @param b The diff 'from' chunk's ending line number. + * @param c The diff 'to' chunk's beginning line number. + * @param d The diff 'to' chunk's ending line number. + * @param added Int pointer to the running number of lines added for this diff. + * @param removed Int pointer to the running number of lines removed for this + * diff. + */ +void change(int a, int b, int c, int d, int *added, int *removed) { + if (a > b && c > d) + return; + + if(a <= 1) + a = 1; + if(b > len[0]) + b = len[0]; + if(a <= b) + *removed += b - a + 1; + + if(c <= 1) + c = 1; + if(d > len[1]) + d = len[1]; + if(c <= d) + *added += d - c + 1; +} + +/* + * diff - differential file comparison + * + * Uses an algorithm due to Harold Stone, which finds + * a pair of longest identical subsequences in the two + * files. + * + * The major goal is to generate the match vector J. + * J[i] is the index of the line in file1 corresponding + * to line i file0. J[i] = 0 if there is no + * such line in file1. + * + * Lines are hashed so as to work in core. All potential + * matches are located by sorting the lines of each file + * on the hash (called value). In particular, this + * collects the equivalence classes in file1 together. + * Subroutine equiv replaces the value of each line in + * file0 by the index of the first element of its + * matching equivalence in (the reordered) file1. + * To save space equiv squeezes file1 into a single + * array member in which the equivalence classes + * are simply concatenated, except that their first + * members are flagged by changing sign. + * + * Next the indices that point into member are unsorted into + * array class according to the original order of file0. + * + * The cleverness lies in routine stone. This marches + * through the lines of file0, developing a vector klist + * of "k-candidates". At step i a k-candidate is a matched + * pair of lines x,y (x in file0 y in file1) such that + * there is a common subsequence of lenght k + * between the first i lines of file0 and the first y + * lines of file1, but there is no such subsequence for + * any smaller y. x is the earliest possible mate to y + * that occurs in such a subsequence. + * + * Whenever any of the members of the equivalence class of + * lines in file1 matable to a line in file0 has serial number + * less than the y of some k-candidate, that k-candidate + * with the smallest such y is replaced. The new + * k-candidate is chained (via pred) to the current + * k-1 candidate so that the actual subsequence can + * be recovered. When a member has serial number greater + * that the y of all k-candidates, the klist is extended. + * At the end, the longest subsequence is pulled out + * and placed in the array J by unravel. + * + * With J in hand, the matches there recorded are + * check'ed against reality to assure that no spurious + * matches have crept in due to hashing. If they have, + * they are broken, and "jackpot " is recorded--a harmless + * matter except that a true match for a spuriously + * mated line may now be unnecessarily reported as a change. + * + * Much of the complexity of the program comes simply + * from trying to minimize core utilization and + * maximize the range of doable problems by dynamically + * allocating what is needed and reusing what is not. + * The core requirements for problems larger than somewhat + * are (in words) 2*length(file0) + length(file1) + + * 3*(number of k-candidates installed), typically about + * 6n words for files of length n. + */ + +static void sort(struct line *a, int n) { /*shellsort CACM #201*/ + int m; + struct line *ai, *aim, *j, *k; + struct line w; + int i; + + m = 0; + for (i = 1; i <= n; i *= 2) + m = 2*i - 1; + for (m /= 2; m != 0; m /= 2) { + k = a+(n-m); + for (j = a+1; j <= k; j++) { + ai = j; + aim = ai+m; + do { + if (aim->value > ai->value || + aim->value == ai->value && + aim->serial > ai->serial) + break; + w = *ai; + *ai = *aim; + *aim = w; + + aim = ai; + ai -= m; + } while (ai > a && aim >= ai); + } + } +} + +static void unsort(struct line *f, int l, int *b) { + int *a; + int i; + + a = malloc((l+1)*sizeof(int)); + for(i=1;i<=l;i++) + a[f[i].serial] = f[i].value; + for(i=1;i<=l;i++) + b[i] = a[i]; + free(a); +} + +static void prune(void) { + int i, j; + + for(pref=0;prefx = x; + q->y = y; + q->pred = pred; + return clen++; +} + +static int search(int *c, int k, int y) { + int i, j, l; + int t; + + if(clist[c[k]].y < y) /*quick look for typical case*/ + return k+1; + i = 0; + j = k+1; + while((l=(i+j)/2) > i) { + t = clist[c[l]].y; + if(t > y) + j = l; + else if(t < y) + i = l; + else + return l; + } + return l+1; +} + +static int stone(int *a, int n, int *b, int *c) { + int i, k, y; + int j, l; + int oldc, tc; + int oldl; + + k = 0; + c[0] = newcand(0,0,0); + for(i=1; i<=n; i++) { + j = a[i]; + if(j==0) + continue; + y = -b[j]; + oldl = 0; + oldc = c[0]; + do { + if(y <= clist[oldc].y) + continue; + l = search(c, k, y); + if(l!=oldl+1) + oldc = c[l-1]; + if(l<=k) { + if(clist[c[l]].y <= y) + continue; + tc = c[l]; + c[l] = newcand(i,y,oldc); + oldc = tc; + oldl = l; + } else { + c[l] = newcand(i,y,oldc); + k++; + break; + } + } while((y=b[++j]) > 0); + } + return k; +} + +static void unravel(int p) { + int i; + struct cand *q; + + for(i=0; i<=len[0]; i++) { + if (i <= pref) + J[i] = i; + else if (i > len[0]-suff) + J[i] = i+len[1]-len[0]; + else + J[i] = 0; + } + for(q=clist+p;q->y!=0;q=clist+q->pred) + J[q->x+pref] = q->y+pref; +} + +static void output(int *added, int *removed) { + int m, i0, i1, j0, j1; + + m = len[0]; + J[0] = 0; + J[m+1] = len[1]+1; + for (i0 = 1; i0 <= m; i0 = i1+1) { + while (i0 <= m && J[i0] == J[i0-1]+1) + i0++; + j0 = J[i0-1]+1; + i1 = i0-1; + while (i1 < m && J[i1+1] == 0) + i1++; + j1 = J[i1+1]-1; + J[i1] = j1; + change(i0, i1, j0, j1, added, removed); + } + if (m == 0) + change(1, 0, 1, len[1], added, removed); +} + +// create and return the path of a tmp_file filled with buf +// caller must delete file if that's desired +char *tmp_file_from_buf(const char *buf) { + char *template = "/tmp/ohcount_diff_XXXXXXX"; + char *path = strdup(template); + + int fd = mkstemp(path); + write(fd, buf, strlen(buf)); + close(fd); + return path; +} + +#ifndef errno +extern int errno; +#endif + +void ohcount_calc_diff_with_disk( + const char *from, + const char *to, + int *added, + int *removed) { + *added = *removed = 0; + char *from_tmp = tmp_file_from_buf(from); + char *to_tmp = tmp_file_from_buf(to); + + char command[1000]; + sprintf(command, "diff -d --normal --suppress-common-lines --new-file '%s' '%s'", from_tmp, to_tmp); + FILE *f = popen(command, "r"); + if (f) { + char line[10000]; + while(fgets(line, sizeof(line), f)) { + if (line[0] == '>') + (*added)++; + if (line[0] == '<') + (*removed)++; + } + } + pclose(f); + if (unlink(from_tmp)) { + printf("error unlinking %s: %d", from_tmp, errno); + } + if (unlink(to_tmp)) { + printf("error unlinking %s: %d", from_tmp, errno); + } +} + +#define USE_DISK_IF_LARGER 100000 +void ohcount_calc_diff(const char *from, + const char *to, int *added, int *removed) { + int k; + + if (strlen(from) > USE_DISK_IF_LARGER || strlen(to) > USE_DISK_IF_LARGER) + return ohcount_calc_diff_with_disk(from, to, added, removed); + + prepare(0, from); + prepare(1, to); + clen = 0; + prune(); + sort(sfile[0], slen[0]); + sort(sfile[1], slen[1]); + + member = (int *)file[1]; + equiv(sfile[0], slen[0], sfile[1], slen[1], member); + member = realloc(member, (slen[1]+2)*sizeof(int)); + + class = (int *)file[0]; + unsort(sfile[0], slen[0], class); + class = realloc(class, (slen[0]+2)*sizeof(int)); + + klist = malloc((slen[0]+2)*sizeof(int)); + clist = malloc(sizeof(struct cand)); + k = stone(class, slen[0], member, klist); + free(member); + free(class); + + J = malloc((len[0]+2)*sizeof(int)); + unravel(klist[k]); + free(clist); + free(klist); + + *added = *removed = 0; + output(added, removed); + free(J); +} diff --git a/src/diff.h b/src/diff.h new file mode 100644 index 0000000..44739a4 --- /dev/null +++ b/src/diff.h @@ -0,0 +1,20 @@ +// diff.h written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#ifndef OHCOUNT_DIFF_H +#define OHCOUNT_DIFF_H + +/** + * Computes the diff between the lines of two given string buffers. + * The results are stored in the passed integer pointers. + * Note: The algorithm discussed mentions a check being performed to find lines + * matched incorrectly due to hashing; it is not in this implementation. + * @param from The diff 'from' buffer. + * @param to The diff 'to' buffer. + * @param added Int pointer the number of lines added result is stored to. + * @param removed Int pointer the number of lines removed result is stored to. + */ +void ohcount_calc_diff(const char *from, const char *to, int *added, + int *removed); + +#endif diff --git a/src/hash/cppheaders.gperf b/src/hash/cppheaders.gperf new file mode 100644 index 0000000..3a70930 --- /dev/null +++ b/src/hash/cppheaders.gperf @@ -0,0 +1,91 @@ +struct CppHeaderMap { const char *key; int value; }; +%% +algorithm, 1 +array, 1 +bitset, 1 +cassert, 1 +ccomplex, 1 +cctype, 1 +cerrno, 1 +cfenv, 1 +cfloat, 1 +cinttypes, 1 +ciso646, 1 +climits, 1 +clocale, 1 +cmath, 1 +csetjmp, 1 +csignal, 1 +cstdarg, 1 +cstdbool, 1 +cstddef, 1 +cstdint, 1 +cstdio, 1 +cstdlib, 1 +cstring, 1 +ctgmath, 1 +ctime, 1 +cwchar, 1 +cwctype, 1 +deque, 1 +exception, 1 +fstream, 1 +functional, 1 +iomanip, 1 +ios, 1 +iosfwd, 1 +iostream, 1 +istream, 1 +iterator, 1 +limits, 1 +list, 1 +locale, 1 +map, 1 +memory, 1 +new, 1 +numeric, 1 +ostream, 1 +queue, 1 +random, 1 +regex, 1 +set, 1 +sstream, 1 +stack, 1 +stdexcept, 1 +streambuf, 1 +string, 1 +system_error, 1 +tuple, 1 +type_traits, 1 +typeinfo, 1 +unordered_map, 1 +unordered_set, 1 +utility, 1 +valarray, 1 +vector, 1 +tr1/array, 1 +tr1/ccomplex, 1 +tr1/cctype, 1 +tr1/cfenv, 1 +tr1/cfloat, 1 +tr1/cinttypes, 1 +tr1/climits, 1 +tr1/cmath, 1 +tr1/complex, 1 +tr1/cstdarg, 1 +tr1/cstdbool, 1 +tr1/cstdint, 1 +tr1/cstdio, 1 +tr1/cstdlib, 1 +tr1/ctgmath, 1 +tr1/ctime, 1 +tr1/cwchar, 1 +tr1/cwctype, 1 +tr1/memory, 1 +tr1/random, 1 +tr1/regex, 1 +tr1/tuple, 1 +tr1/type_traits, 1 +tr1/unordered_map, 1 +tr1/unordered_set, 1 +tr1/utility, 1 diff --git a/src/hash/disambiguatefuncs.gperf b/src/hash/disambiguatefuncs.gperf new file mode 100644 index 0000000..1390d08 --- /dev/null +++ b/src/hash/disambiguatefuncs.gperf @@ -0,0 +1,29 @@ +%{ +#include "../detector.h" +#include "../sourcefile.h" + +const char *disambiguate_aspx(SourceFile *sourcefile); +const char *disambiguate_b(SourceFile *sourcefile); +const char *disambiguate_basic(SourceFile *sourcefile); +const char *disambiguate_cs(SourceFile *sourcefile); +const char *disambiguate_fortran(SourceFile *sourcefile); +const char *disambiguate_h(SourceFile *sourcefile); +const char *disambiguate_in(SourceFile *sourcefile); +const char *disambiguate_inc(SourceFile *sourcefile); +const char *disambiguate_m(SourceFile *sourcefile); +const char *disambiguate_pro(SourceFile *sourcefile); +const char *disambiguate_st(SourceFile *sourcefile); +%} +struct DisambiguateFuncsMap { const char *key; const char* (*value)(SourceFile*); }; +%% +aspx, disambiguate_aspx +b, disambiguate_b +basic, disambiguate_basic +cs, disambiguate_cs +fortran, disambiguate_fortran +h, disambiguate_h +in, disambiguate_in +inc, disambiguate_inc +m, disambiguate_m +pro, disambiguate_pro +st, disambiguate_st diff --git a/src/hash/extensions.gperf b/src/hash/extensions.gperf new file mode 100644 index 0000000..8394eee --- /dev/null +++ b/src/hash/extensions.gperf @@ -0,0 +1,182 @@ +%{ +#include "../languages.h" + +#define BINARY "\1" +#define DISAMBIGUATE(x) ("\2" x) +%} +struct ExtensionMap { const char *key; const char *value; }; +%% +C, LANG_CPP +H, LANG_CPP +ada, LANG_ADA +adb, LANG_ADA +ads, LANG_ADA +aiff, BINARY +as, LANG_ACTIONSCRIPT +ascx, DISAMBIGUATE("aspx") +asm, LANG_ASSEMBLER +aspx, DISAMBIGUATE("aspx") +au, BINARY +avi, BINARY +awk, LANG_AWK +b, DISAMBIGUATE("b") +bas, DISAMBIGUATE("basic") +bat, LANG_BAT +bi, DISAMBIGUATE("basic") +bmp, BINARY +bmx, LANG_BLITZMAX +boo, LANG_BOO +c, LANG_C +c++, LANG_CPP +cache, BINARY +cc, LANG_CPP +cmake, LANG_CMAKE +com, LANG_DCL +cpp, LANG_CPP +cs, DISAMBIGUATE("cs") +csproj, LANG_XML +css, LANG_CSS +ctp, LANG_PHP +cxx, LANG_CPP +d, LANG_DMD +dat, BINARY +di, LANG_DMD +doc, BINARY +dylan, LANG_DYLAN +e, LANG_EIFFEL +ebuild, LANG_EBUILD +eclass, LANG_EBUILD +el, LANG_EMACSLISP +erl, LANG_ERLANG +exheres-0, LANG_EXHERES +exlib, LANG_EXHERES +f, DISAMBIGUATE("fortran") +f03, DISAMBIGUATE("fortran") +f77, DISAMBIGUATE("fortran") +f90, DISAMBIGUATE("fortran") +f95, DISAMBIGUATE("fortran") +factor, LANG_FACTOR +frag, LANG_GLSL +frm, LANG_VISUALBASIC +frx, LANG_VISUALBASIC +fs, LANG_FSHARP +ftn, DISAMBIGUATE("fortran") +gif, BINARY +glsl, LANG_GLSL +groovy, LANG_GROOVY +gz, BINARY +h, DISAMBIGUATE("h") +h++, LANG_CPP +haml, LANG_HAML +hh, LANG_CPP +hpp, LANG_CPP +hrl, LANG_ERLANG +hs, LANG_HASKELL +htm, LANG_HTML +html, LANG_HTML +hx, LANG_HAXE +hxx, LANG_CPP +icns, BINARY +in, DISAMBIGUATE("in") +inc, DISAMBIGUATE("inc") +j, LANG_OBJECTIVE_J +jar, BINARY +java, LANG_JAVA +jpeg, BINARY +jpg, BINARY +js, LANG_JAVASCRIPT +jsp, LANG_JSP +kdebuild-1, LANG_EBUILD +latex, LANG_TEX +lisp, LANG_LISP +lsp, LANG_LISP +ltx, LANG_TEX +lua, LANG_LUA +m, DISAMBIGUATE("m") +m4a, BINARY +mf, LANG_METAFONT +mk, LANG_MAKE +ml, LANG_OCAML +ml4, LANG_OCAML +mli, LANG_OCAML +mm, LANG_OBJECTIVE_C +mov, BINARY +mp, LANG_METAPOST_WITH_TEX +mp3, BINARY +mpg, BINARY +mxml, LANG_MXML +nix, LANG_NIX +nse, LANG_LUA +ogg, BINARY +p6, LANG_PERL +pas, LANG_PASCAL +perl, LANG_PERL +pdf, BINARY +ph, LANG_PERL +php, LANG_PHP +php3, LANG_PHP +php4, LANG_PHP +php5, LANG_PHP +pike, LANG_PIKE +pl, LANG_PERL +pm, LANG_PERL +pmc, LANG_C +pmod, LANG_PIKE +png, BINARY +pnt, BINARY +pod, LANG_PERL +pp, LANG_PASCAL +ppt, BINARY +pro, DISAMBIGUATE("pro") +py, LANG_PYTHON +qt, BINARY +r, LANG_R +ra, BINARY +rb, LANG_RUBY +rex, LANG_REXX +rexx, LANG_REXX +rhtml, LANG_RHTML +s, LANG_ASSEMBLER +sc, LANG_SCHEME +scala, LANG_SCALA +sce, LANG_SCILAB +sci, LANG_SCILAB +scm, LANG_SCHEME +sh, LANG_SHELL +sls, LANG_SCHEME +sps, LANG_SCHEME +sql, LANG_SQL +ss, LANG_SCHEME +st, DISAMBIGUATE("st") +str, LANG_STRATEGO +svg, BINARY +svgz, BINARY +svn, BINARY +swf, BINARY +t, LANG_PERL +tar, BINARY +tcl, LANG_TCL +tex, LANG_TEX +tgz, BINARY +tif, BINARY +tiff, BINARY +tpl, LANG_HTML +txx, LANG_CPP +vala, LANG_VALA +vb, LANG_VISUALBASIC +vba, LANG_VISUALBASIC +vbs, LANG_VISUALBASIC +vert, LANG_GLSL +vhd, LANG_VHDL +vhdl, LANG_VHDL +vim, LANG_VIM +wav, BINARY +xaml, LANG_XAML +xls, BINARY +xlw, BINARY +xml, LANG_XML +xs, LANG_C +xsd, LANG_XMLSCHEMA +xsl, LANG_XSLT +z80, LANG_ASSEMBLER +zip, BINARY diff --git a/src/hash/filenames.gperf b/src/hash/filenames.gperf new file mode 100644 index 0000000..54b1685 --- /dev/null +++ b/src/hash/filenames.gperf @@ -0,0 +1,13 @@ +%{ +#include "../languages.h" +%} +struct FilenameMap { const char *key; const char *value; }; +%% +CMakeLists.txt, LANG_CMAKE +GNUmakefile, LANG_MAKE +Makefile, LANG_MAKE +Makefile.am, LANG_AUTOMAKE +configure, LANG_AUTOCONF +configure.ac, LANG_AUTOCONF +configure.in, LANG_AUTOCONF +makefile, LANG_MAKE diff --git a/src/hash/generate_headers b/src/hash/generate_headers new file mode 100755 index 0000000..679a8b3 --- /dev/null +++ b/src/hash/generate_headers @@ -0,0 +1,9 @@ +#!/bin/sh + +gperf -L ANSI-C -E -D -K key -H ohcount_hash_language -N ohcount_hash_language_from_name -t languages.gperf > language_hash.c +gperf -L ANSI-C -E -D -K key -H ohcount_hash_extension -N ohcount_hash_language_from_ext -t extensions.gperf > extension_hash.h +gperf -L ANSI-C -E -D -K key -H ohcount_hash_filename -N ohcount_hash_language_from_filename -t filenames.gperf > filename_hash.h +gperf -L ANSI-C -E -D -K key -H ohcount_hash_disambiguatefunc -N ohcount_hash_disambiguate_func_from_id -t disambiguatefuncs.gperf > disambiguatefunc_hash.h +gperf -L ANSI-C -E -D -K key -H ohcount_hash_cppheader -N ohcount_hash_is_cppheader -t cppheaders.gperf > cppheader_hash.h +gperf -L ANSI-C -E -D -K key -H ohcount_hash_parser -N ohcount_hash_parser_from_language -t parsers.gperf > parser_hash.h +gperf -L ANSI-C -E -D -K key -H ohcount_hash_options -N ohcount_hash_command_from_flag -t options.gperf > option_hash.h diff --git a/src/hash/languages.gperf b/src/hash/languages.gperf new file mode 100644 index 0000000..037b2bc --- /dev/null +++ b/src/hash/languages.gperf @@ -0,0 +1,87 @@ +%{ +#include "../languages.h" +%} +struct LanguageMap; +%% +actionscript, LANG_ACTIONSCRIPT, "ActionScript", 0 +ada, LANG_ADA, "Ada", 0 +assembler, LANG_ASSEMBLER, "Assembler", 0 +autoconf, LANG_AUTOCONF, "Autoconf", 2 +automake, LANG_AUTOMAKE, "Automake", 2 +awk, LANG_AWK, "AWK", 0 +bat, LANG_BAT, "DOS batch script", 0 +blitzmax, LANG_BLITZMAX, "BlitzMax", 0 +boo, LANG_BOO, "Boo", 0 +c, LANG_C, "C", 0 +classic_basic, LANG_CLASSIC_BASIC, "Classic Basic", 0 +clearsilver, LANG_CLEARSILVER, "ClearSilver", 0 +clearsilver_template, LANG_CLEARSILVER_TEMPLATE, "ClearSilver", 0 +cmake, LANG_CMAKE, "Cmake script", 2 +cpp, LANG_CPP, "C++", 0 +cs_aspx, LANG_CS_ASPX, "", 0 +csharp, LANG_CSHARP, "C#", 0 +css, LANG_CSS, "CSS", 1 +dcl, LANG_DCL, "DCL", 0 +dmd, LANG_DMD, "D", 0 +dylan, LANG_DYLAN, "Dylan", 0 +ebuild, LANG_EBUILD, "Ebuild", 0 +eiffel, LANG_EIFFEL, "Eiffel", 0 +emacslisp, LANG_EMACSLISP, "Emacs lisp", 0 +erlang, LANG_ERLANG, "Erlang", 0 +exheres, LANG_EXHERES, "Exheres", 0 +factor, LANG_FACTOR, "Factor", 0 +fortranfixed, LANG_FORTRANFIXED, "Fortan (Fixed-format)", 0 +fortranfree, LANG_FORTRANFREE, "Fortan (Free-format)", 0 +fsharp, LANG_FSHARP, "F#", 0 +glsl, LANG_GLSL, "OpenGL Shading Language", 0 +groovy, LANG_GROOVY, "Groovy", 0 +haml, LANG_HAML, "Haml", 1 +haskell, LANG_HASKELL, "Haskell", 0 +haxe, LANG_HAXE, "HaXe", 0 +html, LANG_HTML, "HTML", 1 +idl_pvwave, LANG_IDL_PVWAVE, "IDL/PV-WAVE/GDL", 0 +java, LANG_JAVA, "Java", 0 +javascript, LANG_JAVASCRIPT, "JavaScript", 0 +jsp, LANG_JSP, "", 0 +limbo, LANG_LIMBO, "Limbo", 0 +lisp, LANG_LISP, "Lisp", 0 +lua, LANG_LUA, "Lua", 0 +make, LANG_MAKE, "Make", 2 +matlab, LANG_MATLAB, "Matlab", 0 +metafont, LANG_METAFONT, "MetaFont", 1 +metapost, LANG_METAPOST, "MetaPost", 1 +metapost_with_tex, LANG_METAPOST_WITH_TEX, "", 0 +mxml, LANG_MXML, "MXML", 1 +nix, LANG_NIX, "Nix", 0 +objective_c, LANG_OBJECTIVE_C, "Objective-C", 0 +objective_j, LANG_OBJECTIVE_J, "Objective-J", 0 +ocaml, LANG_OCAML, "Objective Caml", 0 +octave, LANG_OCTAVE, "", 0 +pascal, LANG_PASCAL, "Pascal", 0 +perl, LANG_PERL, "Perl", 0 +php, LANG_PHP, "PHP", 0 +pike, LANG_PIKE, "Pike", 0 +python, LANG_PYTHON, "Python", 0 +r, LANG_R, "R", 0 +rexx, LANG_REXX, "rexx", 0 +rhtml, LANG_RHTML, "", 0 +ruby, LANG_RUBY, "Ruby", 0 +scala, LANG_SCALA, "Scala", 0 +scheme, LANG_SCHEME, "Scheme", 0 +scilab, LANG_SCILAB, "Scilab", 0 +shell, LANG_SHELL, "shell script", 0 +smalltalk, LANG_SMALLTALK, "Smalltalk", 0 +stratego, LANG_STRATEGO, "Stratego", 0 +structured_basic, LANG_STRUCTURED_BASIC, "Structured Basic", 0 +sql, LANG_SQL, "SQL", 0 +tcl, LANG_TCL, "TCL", 0 +tex, LANG_TEX, "TeX/LaTeX", 1 +vala, LANG_VALA, "Vala", 0 +vb_aspx, LANG_VB_ASPX, "", 0 +vhdl, LANG_VHDL, "VHDL", 0 +vim, LANG_VIM, "Vim script", 0 +visualbasic, LANG_VISUALBASIC, "Visual Basic", 0 +xaml, LANG_XAML, "XAML", 1 +xml, LANG_XML, "XML", 1 +xslt, LANG_XSLT, "XSL Transformation", 0 +xmlschema, LANG_XMLSCHEMA, "XML Schema", 1 diff --git a/src/hash/options.gperf b/src/hash/options.gperf new file mode 100644 index 0000000..97ccf35 --- /dev/null +++ b/src/hash/options.gperf @@ -0,0 +1,18 @@ +%{ +#include "../ohcount.h" +%} +struct OhcountOption { const char *key; int value; }; +%% +-a, COMMAND_ANNOTATE +--annotate, COMMAND_ANNOTATE +-d, COMMAND_DETECT +--detect, COMMAND_DETECT +-h, COMMAND_HELP +--help, COMMAND_HELP +-i, COMMAND_INDIVIDUAL +--individual, COMMAND_INDIVIDUAL +-l, COMMAND_LICENSES +--license, COMMAND_LICENSES +-re, COMMAND_RAWENTITIES +-s, COMMAND_SUMMARY +--summary, COMMAND_SUMMARY diff --git a/src/hash/parsers.gperf b/src/hash/parsers.gperf new file mode 100644 index 0000000..ae37503 --- /dev/null +++ b/src/hash/parsers.gperf @@ -0,0 +1,163 @@ +%{ +#include "../parsers/actionscript.h" +#include "../parsers/ada.h" +#include "../parsers/assembler.h" +#include "../parsers/autoconf.h" +#include "../parsers/automake.h" +#include "../parsers/awk.h" +#include "../parsers/bat.h" +#include "../parsers/blitzmax.h" +#include "../parsers/boo.h" +#include "../parsers/c.h" +#include "../parsers/classic_basic.h" +#include "../parsers/clearsilver.h" +#include "../parsers/clearsilverhtml.h" +#include "../parsers/cmake.h" +#include "../parsers/cs_aspx.h" +#include "../parsers/css.h" +#include "../parsers/d.h" +#include "../parsers/dcl.h" +#include "../parsers/dylan.h" +#include "../parsers/ebuild.h" +#include "../parsers/eiffel.h" +#include "../parsers/erlang.h" +#include "../parsers/exheres.h" +#include "../parsers/factor.h" +#include "../parsers/fortranfixed.h" +#include "../parsers/fortranfree.h" +#include "../parsers/fsharp.h" +#include "../parsers/glsl.h" +#include "../parsers/groovy.h" +#include "../parsers/haml.h" +#include "../parsers/haskell.h" +#include "../parsers/haxe.h" +#include "../parsers/html.h" +#include "../parsers/idl_pvwave.h" +#include "../parsers/java.h" +#include "../parsers/javascript.h" +#include "../parsers/jsp.h" +#include "../parsers/lisp.h" +#include "../parsers/limbo.h" +#include "../parsers/lua.h" +#include "../parsers/makefile.h" +#include "../parsers/matlab.h" +#include "../parsers/metafont.h" +#include "../parsers/metapost.h" +#include "../parsers/metapost_with_tex.h" +#include "../parsers/mxml.h" +#include "../parsers/nix.h" +#include "../parsers/objective_c.h" +#include "../parsers/objective_j.h" +#include "../parsers/ocaml.h" +#include "../parsers/octave.h" +#include "../parsers/pascal.h" +#include "../parsers/perl.h" +#include "../parsers/phphtml.h" +#include "../parsers/pike.h" +#include "../parsers/python.h" +#include "../parsers/r.h" +#include "../parsers/rexx.h" +#include "../parsers/ruby.h" +#include "../parsers/rhtml.h" +#include "../parsers/scala.h" +#include "../parsers/scilab.h" +#include "../parsers/shell.h" +#include "../parsers/smalltalk.h" +#include "../parsers/stratego.h" +#include "../parsers/structured_basic.h" +#include "../parsers/sql.h" +#include "../parsers/tcl.h" +#include "../parsers/tex.h" +#include "../parsers/vb_aspx.h" +#include "../parsers/vhdl.h" +#include "../parsers/vim.h" +#include "../parsers/visual_basic.h" +#include "../parsers/xaml.h" +#include "../parsers/xml.h" +#include "../parsers/xslt.h" +#include "../parsers/xmlschema.h" +%} +struct ParserMap { const char *key; void (*parser)(char *, int, int, void(*) (const char *, const char *, int, int, void *), void *); }; +%% +actionscript, parse_actionscript +ada, parse_ada +assembler, parse_assembler +autoconf, parse_autoconf +automake, parse_automake +awk, parse_awk +bat, parse_bat +blitzmax, parse_blitzmax +boo, parse_boo +c, parse_c +cmake, parse_cmake +classic_basic, parse_classic_basic +clearsilver, parse_clearsilver +clearsilver_template, parse_cshtml +cpp, parse_cpp +cs_aspx, parse_cs_aspx +csharp, parse_csharp +css, parse_css +dcl, parse_dcl +dmd, parse_d +dylan, parse_dylan +ebuild, parse_ebuild +eiffel, parse_eiffel +erlang, parse_erlang +exheres, parse_exheres +emacslisp, parse_emacslisp +factor, parse_factor +fortranfixed, parse_fortranfixed +fortranfree, parse_fortranfree +fsharp, parse_fsharp +glsl, parse_glsl +groovy, parse_groovy +haskell, parse_haskell +haml, parse_haml +haxe, parse_haxe +html, parse_html +idl_pvwave, parse_idl_pvwave +java, parse_java +javascript, parse_javascript +jsp, parse_jsp +lisp, parse_lisp +limbo, parse_limbo +lua, parse_lua +make, parse_makefile +matlab, parse_matlab +metafont, parse_metafont +metapost, parse_metapost +metapost_with_tex, parse_mptex +mxml, parse_mxml +nix, parse_nix +objective_c, parse_objective_c +objective_j, parse_objective_j +ocaml, parse_ocaml +octave, parse_octave +pascal, parse_pascal +perl, parse_perl +php, parse_phtml +pike, parse_pike +python, parse_python +r, parse_r +rexx, parse_rexx +rhtml, parse_rhtml +ruby, parse_ruby +scala, parse_scala +scheme, parse_scheme +scilab, parse_scilab +shell, parse_shell +smalltalk, parse_smalltalk +stratego, parse_stratego +structured_basic, parse_structured_basic +sql, parse_sql +tcl, parse_tcl +tex, parse_tex +vala, parse_vala +vb_aspx, parse_vb_aspx +vhdl, parse_vhdl +vim, parse_vim +visualbasic, parse_visual_basic +xaml, parse_xaml +xml, parse_xml +xslt, parse_xslt +xmlschema, parse_xmlschema diff --git a/src/languages.h b/src/languages.h new file mode 100644 index 0000000..b19a649 --- /dev/null +++ b/src/languages.h @@ -0,0 +1,96 @@ +// languages.h written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#ifndef OHCOUNT_LANGUAGES_H +#define OHCOUNT_LANGUAGES_H + +#include + +#define LANG_ACTIONSCRIPT "actionscript" +#define LANG_ADA "ada" +#define LANG_ASSEMBLER "assembler" +#define LANG_AUTOCONF "autoconf" +#define LANG_AUTOMAKE "automake" +#define LANG_AWK "awk" +#define LANG_BAT "bat" +#define LANG_BLITZMAX "blitzmax" +#define LANG_BOO "boo" +#define LANG_C "c" +#define LANG_CLASSIC_BASIC "classic_basic" +#define LANG_CLEARSILVER "clearsilver" +#define LANG_CLEARSILVER_TEMPLATE "clearsilver_template" +#define LANG_CMAKE "cmake" +#define LANG_CPP "cpp" +#define LANG_CS_ASPX "cs_aspx" +#define LANG_CSHARP "csharp" +#define LANG_CSS "css" +#define LANG_DCL "dcl" +#define LANG_DMD "dmd" +#define LANG_DYLAN "dylan" +#define LANG_EBUILD "ebuild" +#define LANG_EIFFEL "eiffel" +#define LANG_ERLANG "erlang" +#define LANG_EXHERES "exheres" +#define LANG_EMACSLISP "emacslisp" +#define LANG_FACTOR "factor" +#define LANG_FORTRANFIXED "fortranfixed" +#define LANG_FORTRANFREE "fortranfree" +#define LANG_FSHARP "fsharp" +#define LANG_GLSL "glsl" +#define LANG_GROOVY "groovy" +#define LANG_HASKELL "haskell" +#define LANG_HAML "haml" +#define LANG_HAXE "haxe" +#define LANG_HTML "html" +#define LANG_IDL_PVWAVE "idl_pvwave" +#define LANG_JAVA "java" +#define LANG_JAVASCRIPT "javascript" +#define LANG_JSP "jsp" +#define LANG_LIMBO "limbo" +#define LANG_LISP "lisp" +#define LANG_LUA "lua" +#define LANG_MAKE "make" +#define LANG_MATLAB "matlab" +#define LANG_METAFONT "metafont" +#define LANG_METAPOST "metapost" +#define LANG_METAPOST_WITH_TEX "metapost_with_tex" +#define LANG_MXML "mxml" +#define LANG_NIX "nix" +#define LANG_OBJECTIVE_C "objective_c" +#define LANG_OBJECTIVE_J "objective_j" +#define LANG_OCAML "ocaml" +#define LANG_OCTAVE "octave" +#define LANG_PASCAL "pascal" +#define LANG_PERL "perl" +#define LANG_PHP "php" +#define LANG_PIKE "pike" +#define LANG_PYTHON "python" +#define LANG_R "r" +#define LANG_REXX "rexx" +#define LANG_RHTML "rhtml" +#define LANG_RUBY "ruby" +#define LANG_SCALA "scala" +#define LANG_SCHEME "scheme" +#define LANG_SCILAB "scilab" +#define LANG_SHELL "shell" +#define LANG_SMALLTALK "smalltalk" +#define LANG_STRATEGO "stratego" +#define LANG_STRUCTURED_BASIC "structured_basic" +#define LANG_SQL "sql" +#define LANG_TCL "tcl" +#define LANG_TEX "tex" +#define LANG_VALA "vala" +#define LANG_VB_ASPX "vb_aspx" +#define LANG_VHDL "vhdl" +#define LANG_VIM "vim" +#define LANG_VISUALBASIC "visualbasic" +#define LANG_XAML "xaml" +#define LANG_XML "xml" +#define LANG_XSLT "xslt" +#define LANG_XMLSCHEMA "xmlschema" + +// For gperf. +struct LanguageMap { const char *key; const char *name; const char *nice_name; int category; }; +struct LanguageMap *ohcount_hash_language_from_name(register const char *str, register unsigned int len); + +#endif diff --git a/src/licenses.c b/src/licenses.c new file mode 100644 index 0000000..f0cd90f --- /dev/null +++ b/src/licenses.c @@ -0,0 +1,895 @@ +// licenses.c written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#include +#include +#include + +#include "licenses.h" +#include "parser.h" + +// Holds licenses and their associated details and patterns. +License license_map[] = { + { + LIC_ACADEMIC, + "http://www.opensource.org/licenses/afl-3.0.php", + "Academic Free License", + "\\bAcademic\\s*Free\\s*License\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_ADAPTIVE, + "http://www.opensource.org/licenses/apl1.0.php", + "Adaptive Public License", + "\\bAdaptive\\s*Public\\s*License\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_AFFERO, + "http://www.affero.org/oagpl.html", + "GNU Affero General Public License", + "\\bGNU\\s+Affero\\s+General\\s+Public\\s+License\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_APACHE, + "http://www.opensource.org/licenses/apachepl.php", + "Apache Software License", + "(\\bApache\\s*Software\\s*License(?![\\s,]*2))|(\\bapache\\s*license(?![\\s,]*2))", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_APACHE2, + "http://www.opensource.org/licenses/apache2.0.php", + "Apache License, 2.0", + "\\bapache\\s+(software\\s+)?license,?\\s+(version\\s+)?2", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_APPLE_OPEN_SOURCE, + "http://www.opensource.org/licenses/apsl-2.0.php", + "Apple Public Source License", + "\\bApple\\s*Public\\s*Source\\s*License\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_ARTISTIC, + "http://www.opensource.org/licenses/artistic-license.php", + "Artistic license", + "\\bartistic\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_ATTRIBUTION_ASSURANCE, + "http://www.opensource.org/licenses/attribution.php", + "Attribution Assurance Licenses", + "\\battribution\\s*assurance\\s*license(s)?\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_BOOST, + "http://www.boost.org/LICENSE_1_0.txt", + "Boost Software License - Version 1.0 - August 17th, 2003", + "\\bboost\\s*software\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_BSD, + "http://www.opensource.org/licenses/bsd-license.php", + "New BSD license", + "(\\bbsd\\s*license\\b)|(The Regents of the University of California)", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_CECILL, + "http://www.cecill.info/licences/Licence_CeCILL_V2-en.html", + "CeCILL license", + "\\bcecill\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_CECILL_B, + "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html", + "CeCILL-B license", + "\\bcecill-b\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_CECILL_C, + "http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html", + "CeCILL-C license", + "\\bcecill-c\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_COMPUTER_ASSOCIATES_TRUSTED, + "http://www.opensource.org/licenses/ca-tosl1.1.php", + "Computer Associates Trusted Open Source License 1.1", + "\\bcomputer\\s*associates\\s*trusted\\s*open\\s*source\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_COMMON_DEVELOPMENT_AND_DISTRIBUTION, + "http://www.opensource.org/licenses/cddl1.php", + "Common Development and Distribution License", + "\\bcommon\\s*development\\s*and\\s*distribution\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_COMMON_PUBLIC, + "http://www.opensource.org/licenses/cpl1.0.php", + "Common Public License 1.0", + "\\bcommon\\s*public\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_CUA_OFFICE, + "http://www.opensource.org/licenses/cuaoffice.php", + "CUA Office Public License Version 1.0", + "\\bCUA\\s*office\\s*public\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_EU_DATAGRID, + "http://www.opensource.org/licenses/eudatagrid.php", + "EU DataGrid Software License", + "\\beu\\s*datagrid\\s*software\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_ECLIPSE, + "http://www.opensource.org/licenses/eclipse-1.0.php", + "Eclipse Public License", + "\\beclipse\\s*public\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_EDUCATIONAL, + "http://www.opensource.org/licenses/ecl1.php", + "Educational Community License", + "\\beducational\\s*community\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_EIFFEL, + "http://www.opensource.org/licenses/eiffel.php", + "Eiffel Forum License", + "\\beiffel\\s*forum\\s*license(?![,V\\s]*2)\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_EIFFEL2, + "http://www.opensource.org/licenses/ver2_eiffel.php", + "Eiffel Forum License V2.0", + "\\beiffel\\s*forum\\s*license [,V\\s]*2", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_ENTESSA, + "http://www.opensource.org/licenses/entessa.php", + "Entessa Public License", + "\\bentessa\\s*public\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_FAIR, + "http://www.opensource.org/licenses/fair.php", + "Fair License", + "\\bfair\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_FRAMEWORX, + "http://www.opensource.org/licenses/frameworx.php", + "Frameworx License", + "\\bframeworx\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_GPL3_OR_LATER, + "http://www.gnu.org/licenses/gpl-3.0.html", + "GNU General Public License 3.0", + "\\b(GNU GENERAL PUBLIC LICENSE|GPL).{0,100}(Version)? 3.{0,50}later", + PCRE_CASELESS | PCRE_MULTILINE, + NULL, + 0, + NULL, NULL + }, + { + LIC_GPL3, + "http://www.gnu.org/licenses/gpl-3.0.html", + "GNU General Public License 3.0", + "GNU (GENERAL PUBLIC LICENSE|GPL).{0,100}(Version |v)3", + PCRE_CASELESS | PCRE_MULTILINE, + "((at your option) any later version)|(GENERAL PUBLIC LICENSE.*GENERAL PUBLIC LICENSE)", + PCRE_CASELESS, + NULL, NULL + }, + { + LIC_LGPL3, + "http://www.gnu.org/licenses/lgpl-3.0.html", + "GNU Lesser General Public License 3.0", + "((\\blgpl\\b)|(\\bgnu\\s*(library|lesser)\\s*(general\\s*)?(public\\s*)?license\\b)|(\\b(lesser|library)\\s*gpl\\b)).{0,10}(\\bas published by the free software foundation\\b)?.{0,10}(\\bversion\\b)?.{0,10}\\b3(\\.0)?\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_GPL, + "http://www.opensource.org/licenses/gpl-license.php", + "GNU General Public License (GPL)", + "(\\bgpl\\b)|(\\bgplv2\\b)|(\\bgnu\\s*general\\s*public\\s*license\\b)|(\\bwww\\.gnu\\.org\\/licenses\\/gpl\\.txt\\b)", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_LGPL, + "http://www.opensource.org/licenses/lgpl-license.php", + "GNU Library or \"Lesser\" GPL (LGPL)", + "(\\blgpl\\b)|(\\bgnu\\s*(library|lesser)\\s*(general\\s*)?(public\\s*)?license\\b)|(\\b(lesser|library)\\s*gpl\\b)", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_HISTORICAL, + "http://www.opensource.org/licenses/historical.php", + "Historical Permission Notice and Disclaimer", + "\\bhistorical\\s*permission\\s*notice\\s*and\\s*disclaimer\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_I9, + "http://i9os.googlecode.com/svn/trunk/Documentation/Licenses/i9_License", + "i9 License", + "\\bi9\\s*\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_IBM_PUBLIC, + "http://www.opensource.org/licenses/ibmpl.php", + "IBM Public License", + "\\bibm\\s*public\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_INTEL_OPEN_SOURCE, + "http://www.opensource.org/licenses/intel-open-source-license.php", + "Intel Open Source License", + "\\bintel\\s*open\\s*source\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_JABBER_OPEN_SOURCE, + "http://www.opensource.org/licenses/jabberpl.php", + "Jabber Open Source License", + "\\bjabber\\s*open\\s*source\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_LUCENT_PLAN9, + "http://www.opensource.org/licenses/plan9.php", + "Lucent Public License (Plan9)", + "\\blucent\\s*public\\s*license[\\s(]*plan9", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_LUCENT_PUBLIC, + "http://www.opensource.org/licenses/lucent1.02.php", + "Lucent Public License Version 1.02", + "\\blucent\\s*public\\s*license\\s*(version)?\\s+1", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_MIT, + "http://www.opensource.org/licenses/mit-license.php", + "MIT license", + "(\\bmit\\s*license\\b)|(\\bMIT\\/X11\\s*licensed?\\b)", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_MITRE, + "http://www.opensource.org/licenses/mitrepl.php", + "MITRE Collaborative Virtual Workspace License (CVW License)", + "\\bmitre\\s*collaborative\\s*virtual\\s*workspace\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_MOTOSOTO, + "http://www.opensource.org/licenses/motosoto.php", + "Motosoto License", + "\\bmotosoto\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_MOZILLA_PUBLIC1, + "http://www.opensource.org/licenses/mozilla1.0.php", + "Mozilla Public License 1.0 (MPL)", + "\\bmozilla\\s*public\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_MOZILLA_PUBLIC11, + "http://www.opensource.org/licenses/mozilla1.1.php", + "Mozilla Public License 1.1 (MPL)", + "\\bmozilla\\s*public\\s*license 1\\.1\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_NASA_OPEN, + "http://www.opensource.org/licenses/nasa1.3.php", + "NASA Open Source Agreement 1.3", + "\\bnasa\\s*open\\s*source\\s*agreement\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_NAUMEN, + "http://www.opensource.org/licenses/naumen.php", + "Naumen Public License", + "\\bnaumen\\s*public\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_NETHACK, + "http://www.opensource.org/licenses/nethack.php", + "Nethack General Public License", + "\\bnethack\\s*general\\s*public\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_NOKIA_OPEN_SOURCE, + "http://www.opensource.org/licenses/nokia.php", + "Nokia Open Source License", + "\\bnokia\\s*open\\s*source\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_OCLC_RESEARCH, + "http://www.opensource.org/licenses/oclc2.php", + "OCLC Research Public License 2.0", + "\\boclc\\s*research\\s*public\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_OPEN_GROUP_TEST, + "http://www.opensource.org/licenses/opengroup.php", + "Open Group Test Suite License", + "\\bopen\\s*group\\s*test\\s*suite\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_OPEN_SOFTWARE, + "http://www.opensource.org/licenses/osl-3.0.php", + "Open Software License", + "\\bopen\\s*software\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_PHP_LICENSE, + "http://www.opensource.org/licenses/php.php", + "PHP License", + "\\bphp\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_PYTHON_LICENSE, + "http://www.opensource.org/licenses/pythonpl.php", + "Python license", + "\\bpython\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_PYTHON_SOFTWARE_FOUNDATION, + "http://www.opensource.org/licenses/PythonSoftFoundation.php", + "Python Software Foundation License", + "\\bpython\\s*software\\s*foundation\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_QT_PUBLIC, + "http://www.opensource.org/licenses/qtpl.php", + "Qt Public License (QPL)", + "\\bqt\\s*public\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_REALNETWORKS_PUBLIC_SOURCE, + "http://www.opensource.org/licenses/real.php", + "RealNetworks Public Source License V1.0", + "\\brealnetworks\\s*public\\s*source\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_RECIPROCAL_PUBLIC, + "http://www.opensource.org/licenses/rpl.php", + "Reciprocal Public License", + "\\breciprocal\\s*public\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_RICOH_SOURCE, + "http://www.opensource.org/licenses/ricohpl.php", + "Ricoh Source Code Public License", + "\\bricoh\\s*source\\s*code\\s*public\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_SLEEPYCAT, + "http://www.opensource.org/licenses/sleepycat.php", + "Sleepycat License", + "\\bsleepycat\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_SUGARCRM113, + "http://www.sugarcrm.com/SPL", + "SugarCRM Public License 1.1.3", + "\\bsugar\\s*public\\s*license\\s*version\\s*1\\.1\\.3\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_SUN_INDUSTRY_STANDARDS, + "http://www.opensource.org/licenses/sisslpl.php", + "Sun Industry Standards Source License (SISSL)", + "\\bsun\\s*industry\\s*standards\\s*source\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_SUN_PUBLIC, + "http://www.opensource.org/licenses/sunpublic.php", + "Sun Public License", + "\\bsun\\s*public\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_SYBASE_OPEN_WATCOM, + "http://www.opensource.org/licenses/sybase.php", + "Sybase Open Watcom Public License 1.0", + "\\bsybase\\s*open\\s*watcom\\s*public\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_U_OF_I_NCSA, + "http://www.opensource.org/licenses/UoI-NCSA.php", + "University of Illinois/NCSA Open Source License", + "\\buniversity\\s*of\\s*illinois\\/ncsa\\s*open\\s*source\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_VOVIDA_SOFTWARE, + "http://www.opensource.org/licenses/vovidapl.php", + "Vovida Software License v. 1.0", + "\\bvovida\\s*software\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_W3C, + "http://www.opensource.org/licenses/W3C.php", + "W3C License", + "\\bw3c\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_WXWINDOWS, + "http://www.opensource.org/licenses/wxwindows.php", + "wxWindows Library License", + "\\bwxwindows\\s*library\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_XNET, + "http://www.opensource.org/licenses/xnet.php", + "X.Net License", + "\\bx\\.net\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_ZOPE, + "http://www.opensource.org/licenses/zpl.php", + "Zope Public License", + "\\bzope\\s*public\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_ZLIB_LIBPNG, + "http://www.opensource.org/licenses/zlib-license.php", + "zlib/libpng license", + "\\bzlib\\/libpng\\s*license\\b", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_APACHE_ISH, + "", + "Apache-ish License", + "(\\bapache-style.*license\\b)|(\\bapache-like.*license\\b)", + PCRE_CASELESS, + NULL, + 0, + NULL, NULL + }, + { + LIC_BSD_ISH, + "", + "BSD-ish License", + "Copyright\\s.{1,40}All rights reserved.{0,40}Redistribution and use in source and binary forms, with or without.{0,20}modification, are permitted provided that the following conditions.{0,20}\\sare met.{1,40}Redistributions of source code must retain the above copyright\\s.*notice, this list of conditions and the following disclaimer\\.\\s+.*Redistributions in binary form must reproduce the above.*copyright\\s+.{0,10}notice, this list of conditions and the following.*disclaimer in the\\s+.*documentation.*(The (name|names) of the (author|contributors) may not|Neither the name of the).*be used to endorse or promote\\s+.*products\\s+.*derived\\s+.*from this software without specific prior written\\s+.*permission.*HOWEVER\\s+.*CAUSED AND ON ANY.*THEORY OF LIABILITY, WHETHER IN CONTRACT", + PCRE_MULTILINE, + "The Regents of the University of California", + 0, + NULL, NULL + }, + { + LIC_BSD_2CLAUSE_ISH, + "", + "BSD-ish (2 clause) License", + "Copyright\\s.{1,60}All rights reserved.{1,40}Redistribution and use in source and binary forms, with or without.{0,20}modification, are permitted provided that the following conditions.{0,20}\\sare met.{0,20}\\s{1,20}.{0,20}Redistributions of source code must retain the above copyright\\s+.*notice, this list of conditions and the following disclaimer.\\s+.*Redistributions in binary form must reproduce the above copyright\\s+.*notice, this list of conditions and the following disclaimer in the\\s+.*documentation and\\/or other materials provided with the distribution\\.\\s+.*HOWEVER CAUSED AND ON ANY.*THEORY OF LIABILITY, WHETHER IN CONTRACT", + PCRE_MULTILINE, + "(The Regents of the University of California)|(used to endorse or promote\\s+.*products\\s+.*prior\\s+.*written\\s+.*permission\\.)", + PCRE_MULTILINE, + NULL, NULL + }, + { NULL, NULL, NULL, NULL, 0, NULL, 0, NULL, NULL }, +}; +int license_map_length = 0; // will be set dynamically + +/** Compiles the regular expressions defined in license_map. */ +void compile_regexps() { + if (license_map_length == 0) + return; + const char *err; + int erroffset; + int i; + for (i = 0; i < license_map_length; i++) { + License *l = &license_map[i]; + int flags; + if (l->re) { + flags = l->re_flags; + if (flags & PCRE_MULTILINE) + flags |= PCRE_DOTALL; + l->regexp = pcre_compile(l->re, flags, &err, &erroffset, NULL); + } + if (l->exclude_re) { + flags = l->exclude_re_flags; + if (flags & PCRE_MULTILINE) + flags |= PCRE_DOTALL; + l->exclude_regexp = pcre_compile(l->exclude_re, flags, &err, &erroffset, + NULL); + } + } +} + +/** + * Overrides a less-specific license l with a more-specific one if the latter + * was detected. + */ +#define OVERRIDE_LICENSE(l, with) { \ + if (strcmp(license_map[i].name, l) == 0) { \ + for (j = 0; j < license_map_length; j++) \ + if (potential_licenses_s[j] > -1 && \ + strcmp(license_map[j].name, with) == 0) { \ + overridden = 1; \ + break; \ + } \ + } \ +} + +LicenseList *ohcount_detect_license(SourceFile *sourcefile) { + LicenseList *list = ohcount_license_list_new(); + + // Get the size of this map and compile the REs. Only runs once. + if (license_map_length == 0) { + while (license_map[license_map_length].name) license_map_length++; + compile_regexps(); + } + + ohcount_sourcefile_parse(sourcefile); + + char *p, *q; + int i, j, k; + int ovector[30]; // recommended by PCRE + ParsedLanguageList *iter_language; + iter_language = ohcount_sourcefile_get_parsed_language_list(sourcefile)->head; + if (iter_language) { + int potential_licenses_s[license_map_length]; + int potential_licenses_e[license_map_length]; + + while (iter_language) { + // Before looking for licenses, strip whitespace and newlines + p = iter_language->pl->comments; + int buffer_len = p ? strlen(p) : 0; + char *p_max = p + buffer_len; + + char *buffer = malloc(buffer_len+1); + if (buffer == NULL) { + fprintf(stderr, "out of memory in ohcount_detect_license"); + exit(-1); + } + q = buffer; + char *q_max = buffer + buffer_len + 1; + + while (p < p_max && q < q_max) { + // Strip leading whitespace and punctuation. + while (*p == ' ' || *p == '\t' || ispunct(*p)) p++; + // Copy line contents. + while (p < p_max && *p != '\r' && *p != '\n' && q < q_max) + *q++ = *p++; + // Strip newline characters. + while (*p == '\r' || *p == '\n') p++; + // Add a trailing space. + if (q < q_max) *q++ = ' '; + } + if (q < q_max) *q = '\0'; + + for (j = 0; j < license_map_length; j++) { + potential_licenses_s[j] = -1; + potential_licenses_e[j] = -1; + if (pcre_exec(license_map[j].regexp, NULL, buffer, q - buffer, 0, 0, + ovector, 30) >= 0) { + int m0 = ovector[0], m1 = ovector[1]; + // Exclude terms that may not exist in the license. + if (license_map[j].exclude_re && + pcre_exec(license_map[j].exclude_regexp, NULL, buffer + m0, m1 - m0, + 0, 0, ovector, 30) >= 0) + continue; + potential_licenses_s[j] = m0; + potential_licenses_e[j] = m1; + for (k = 0; k < j; k++) { + // If this matched license is completely contained inside another one, + // do not include it. + if ((potential_licenses_s[k] < m0 && potential_licenses_e[k] >= m1) || + (potential_licenses_s[k] <= m0 && potential_licenses_e[k] > m1)) { + potential_licenses_s[j] = -1; + potential_licenses_e[j] = -1; + } + // If this matched license completely contains another one, do not + // include the latter. + if ((m0 < potential_licenses_s[k] && m1 >= potential_licenses_e[k]) || + (m0 <= potential_licenses_s[k] && m1 > potential_licenses_e[k])) { + potential_licenses_s[k] = -1; + potential_licenses_e[k] = -1; + } + } + } + } + iter_language = iter_language->next; + } + + // Create the list of licenses from potential licenses. + for (i = 0; i < license_map_length; i++) { + if (potential_licenses_s[i] > -1) { + int overridden = 0; + OVERRIDE_LICENSE(LIC_GPL, LIC_GPL3); + OVERRIDE_LICENSE(LIC_GPL, LIC_GPL3_OR_LATER); + OVERRIDE_LICENSE(LIC_GPL3, LIC_GPL3_OR_LATER); + OVERRIDE_LICENSE(LIC_BSD_2CLAUSE_ISH, LIC_BSD_ISH); + if (!overridden) { + if (list->head == NULL) { // empty list + list->head = list; + list->tail = list; + list->head->lic = &license_map[i]; + list->next = NULL; + } else { + LicenseList *item = ohcount_license_list_new(); + item->lic = &license_map[i]; + list->tail->next = item; + list->tail = item; + } + } + } + } + } + + return list; +} + +LicenseList *ohcount_license_list_new() { + LicenseList *list = malloc(sizeof(LicenseList)); + list->lic = NULL; + list->next = NULL; + list->head = NULL; + list->tail = NULL; + return list; +} + +void ohcount_license_list_free(LicenseList *list) { + if (list->head) { + LicenseList *iter = list->head; + while (iter) { + LicenseList *next = iter->next; + free(iter); + iter = next; + } + } else free(list); +} diff --git a/src/licenses.h b/src/licenses.h new file mode 100644 index 0000000..cc8acee --- /dev/null +++ b/src/licenses.h @@ -0,0 +1,120 @@ +// licenses.h written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#ifndef OHCOUNT_LICENSES_H +#define OHCOUNT_LICENSES_H + +/** + * @page license_doc License Documentation + * @author Mitchell Foral + * + * @section license How to Add a New License + * + * @li Add your license to 'src/licenses.h' and 'src/licenses.c'. Don't forget + * that two '\\'s are required to represent one '\\' in a C string. + * @li Add your tests to the 'test/src_licenses/' and 'test/expected_licenses/' + * directories. Note that multiple licenses must be separated by newlines and + * be in the order they appear in the input file. + * @li Run the test suite (a rebuild is not necessary; your added tests are + * detected and run automatically) to verify your licenses are correctly + * detected. + * @li Rebuild Ohcount. + */ + +#include "sourcefile.h" + +#define LIC_ACADEMIC "academic" +#define LIC_ADAPTIVE "adaptive" +#define LIC_AFFERO "affero" +#define LIC_APACHE "apache" +#define LIC_APACHE2 "apache_2" +#define LIC_APPLE_OPEN_SOURCE "apple_open_source" +#define LIC_ARTISTIC "artistic" +#define LIC_ATTRIBUTION_ASSURANCE "attribution_assurance" +#define LIC_BOOST "boost" +#define LIC_BSD "bsd" +#define LIC_CECILL "cecill" +#define LIC_CECILL_B "cecill_b" +#define LIC_CECILL_C "cecill_c" +#define LIC_COMPUTER_ASSOCIATES_TRUSTED "computer_associates_trusted" +#define LIC_COMMON_DEVELOPMENT_AND_DISTRIBUTION \ + "common_development_and_distribution" +#define LIC_COMMON_PUBLIC "common_public" +#define LIC_CUA_OFFICE "cua_office" +#define LIC_EU_DATAGRID "eu_datagrid" +#define LIC_ECLIPSE "eclipse" +#define LIC_EDUCATIONAL "educational" +#define LIC_EIFFEL "eiffel" +#define LIC_EIFFEL2 "eiffel_2" +#define LIC_ENTESSA "entessa" +#define LIC_FAIR "fair" +#define LIC_FRAMEWORX "frameworx" +#define LIC_GPL3_OR_LATER "gpl3_or_later" +#define LIC_GPL3 "gpl3" +#define LIC_LGPL3 "lgpl3" +#define LIC_GPL "gpl" +#define LIC_LGPL "lgpl" +#define LIC_HISTORICAL "historical" +#define LIC_I9 "i9_license" +#define LIC_IBM_PUBLIC "ibm_public" +#define LIC_INTEL_OPEN_SOURCE "intel_open_source" +#define LIC_JABBER_OPEN_SOURCE "jabber_open_source" +#define LIC_LUCENT_PLAN9 "lucent_plan9" +#define LIC_LUCENT_PUBLIC "lucent_public" +#define LIC_MIT "mit" +#define LIC_MITRE "mitre" +#define LIC_MOTOSOTO "motosoto" +#define LIC_MOZILLA_PUBLIC1 "mozilla_public_1" +#define LIC_MOZILLA_PUBLIC11 "mozilla_public_1_1" +#define LIC_NASA_OPEN "nasa_open" +#define LIC_NAUMEN "naumen" +#define LIC_NETHACK "nethack" +#define LIC_NOKIA_OPEN_SOURCE "nokia_open_source" +#define LIC_OCLC_RESEARCH "oclc_research" +#define LIC_OPEN_GROUP_TEST "open_group_test" +#define LIC_OPEN_SOFTWARE "open_software" +#define LIC_PHP_LICENSE "php_license" +#define LIC_PYTHON_LICENSE "python_license" +#define LIC_PYTHON_SOFTWARE_FOUNDATION "python_software_foundation" +#define LIC_QT_PUBLIC "qt_public" +#define LIC_REALNETWORKS_PUBLIC_SOURCE "realnetworks_public_source" +#define LIC_RECIPROCAL_PUBLIC "reciprocal_public" +#define LIC_RICOH_SOURCE "ricoh_source" +#define LIC_SLEEPYCAT "sleepycat" +#define LIC_SUGARCRM113 "sugarcrm_1_1_3" +#define LIC_SUN_INDUSTRY_STANDARDS "sun_industry_standards" +#define LIC_SUN_PUBLIC "sun_public" +#define LIC_SYBASE_OPEN_WATCOM "sybase_open_watcom" +#define LIC_U_OF_I_NCSA "u_of_i_ncsa" +#define LIC_VOVIDA_SOFTWARE "vovida_software" +#define LIC_W3C "w3c" +#define LIC_WXWINDOWS "wx_windows" +#define LIC_XNET "x_net" +#define LIC_ZOPE "zope" +#define LIC_ZLIB_LIBPNG "zlib_libpng" +#define LIC_APACHE_ISH "apache_ish" +#define LIC_BSD_ISH "bsd_ish" +#define LIC_BSD_2CLAUSE_ISH "bsd_2clause_ish" + +/** + * Attempts to detect the source code licenses for a given file. + * It searches comment text in source files for any mention of known licenses, + * but unfortunately catches things like: "I find the GNU Public License dumb". + * @param sourcefile A SourceFile created by ohcount_sourcefile_new(). + * @return LicenseList + */ +LicenseList *ohcount_detect_license(SourceFile *sourcefile); + +/** + * Creates a new LicenseList that is initially empty. + * @return LicenseList + */ +LicenseList *ohcount_license_list_new(); + +/** + * Frees the memory allocated for the given LicenseList. + * @param list A LicenseList created from ohcount_license_list_new(). + */ +void ohcount_license_list_free(LicenseList *list); + +#endif diff --git a/src/loc.c b/src/loc.c new file mode 100644 index 0000000..bd43934 --- /dev/null +++ b/src/loc.c @@ -0,0 +1,419 @@ +// loc.c written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#include +#include + +#include "loc.h" + +// Loc + +Loc *ohcount_loc_new(const char *language, int code, int comments, int blanks, + int filecount) { + Loc *loc = malloc(sizeof(Loc)); + loc->language = language; + loc->code = code; + loc->comments = comments; + loc->blanks = blanks; + loc->filecount = filecount; + return loc; +} + +int ohcount_loc_total(Loc *loc) { + return loc->code + loc->comments + loc->blanks; +} + +void ohcount_loc_add_loc(Loc *loc, Loc *other) { + if (strcmp(loc->language, other->language) == 0) { + loc->code += other->code; + loc->comments += other->comments; + loc->blanks += other->blanks; + loc->filecount += other->filecount; + } +} + +int ohcount_loc_is_equal(Loc *loc, Loc *other) { + return strcmp(loc->language, other->language) == 0 && + loc->code == other->code && loc->comments == other->comments && + loc->blanks == other->blanks && loc->filecount == other->filecount; +} + +void ohcount_loc_free(Loc *loc) { + free(loc); +} + +// LocList + +LocList *ohcount_loc_list_new() { + LocList *list = malloc(sizeof(LocList)); + list->loc = NULL; + list->next = NULL; + list->head = NULL; + list->tail = NULL; + return list; +} + +void ohcount_loc_list_add_loc(LocList *list, Loc *loc) { + if (list->head == NULL) { // empty list + list->head = list; + list->tail = list; + list->head->loc = ohcount_loc_new(loc->language, loc->code, loc->comments, + loc->blanks, loc->filecount); + list->head->next = NULL; + } else { + LocList *iter = list->head; + while (iter) { + if (iter->loc && strcmp(iter->loc->language, loc->language) == 0) break; + iter = iter->next; + } + if (iter == NULL) { // new language + LocList *item = ohcount_loc_list_new(); + item->loc = ohcount_loc_new(loc->language, loc->code, loc->comments, + loc->blanks, loc->filecount); + list->tail->next = item; + list->tail = item; + } else ohcount_loc_add_loc(iter->loc, loc); // existing language + } +} + +void ohcount_loc_list_add_loc_list(LocList *list, LocList *other) { + LocList *iter = other->head; + while (iter) { + ohcount_loc_list_add_loc(list, iter->loc); + iter = iter->next; + } +} + +Loc *ohcount_loc_list_get_loc(LocList *list, const char *language) { + LocList *iter = list->head; + while (iter) { + if (strcmp(iter->loc->language, language) == 0) return iter->loc; + iter = iter->next; + } + return NULL; +} + +int ohcount_loc_list_code(LocList *list) { + int sum = 0; + LocList *iter = list->head; + while (iter) { + sum += iter->loc->code; + iter = iter->next; + } + return sum; +} + +int ohcount_loc_list_comments(LocList *list) { + int sum = 0; + LocList *iter = list->head; + while (iter) { + sum += iter->loc->comments; + iter = iter->next; + } + return sum; +} + +int ohcount_loc_list_blanks(LocList *list) { + int sum = 0; + LocList *iter = list->head; + while (iter) { + sum += iter->loc->blanks; + iter = iter->next; + } + return sum; +} + +int ohcount_loc_list_total(LocList *list) { + int sum = 0; + LocList *iter = list->head; + while (iter) { + sum += ohcount_loc_total(iter->loc); + iter = iter->next; + } + return sum; +} + +int ohcount_loc_list_filecount(LocList *list) { + int sum = 0; + LocList *iter = list->head; + while (iter) { + sum += iter->loc->filecount; + iter = iter->next; + } + return sum; +} + +LocList *ohcount_loc_list_new_compact(LocList *list) { + LocList *new_list = ohcount_loc_list_new(); + LocList *iter = list->head; + while (iter) { + if (ohcount_loc_total(iter->loc) != 0) + ohcount_loc_list_add_loc(new_list, iter->loc); + iter = iter->next; + } + return new_list; +} + +void ohcount_loc_list_free(LocList *list) { + if (list->head) { + LocList *iter = list->head; + while (iter) { + LocList *next = iter->next; + ohcount_loc_free(iter->loc); + free(iter); + iter = next; + } + } else free(list); +} + +// LocDelta + +LocDelta *ohcount_loc_delta_new(const char *language, int code_added, + int code_removed, int comments_added, + int comments_removed, int blanks_added, + int blanks_removed) { + LocDelta *delta = malloc(sizeof(LocDelta)); + delta->language = language; + delta->code_added = code_added; + delta->code_removed = code_removed; + delta->comments_added = comments_added; + delta->comments_removed = comments_removed; + delta->blanks_added = blanks_added; + delta->blanks_removed = blanks_removed; + return delta; +} + +int ohcount_loc_delta_net_code(LocDelta *delta) { + return delta->code_added - delta->code_removed; +} + +int ohcount_loc_delta_net_comments(LocDelta *delta) { + return delta->comments_added - delta->comments_removed; +} + +int ohcount_loc_delta_net_blanks(LocDelta *delta) { + return delta->blanks_added - delta->blanks_removed; +} + +int ohcount_loc_delta_net_total(LocDelta *delta) { + return ohcount_loc_delta_net_code(delta) + + ohcount_loc_delta_net_comments(delta) + + ohcount_loc_delta_net_blanks(delta); +} + +void ohcount_loc_delta_add_loc_delta(LocDelta *delta, LocDelta *other) { + if (strcmp(delta->language, other->language) == 0) { + delta->code_added += other->code_added; + delta->code_removed += other->code_removed; + delta->comments_added += other->comments_added; + delta->comments_removed += other->comments_removed; + delta->blanks_added += other->blanks_added; + delta->blanks_removed += other->blanks_removed; + } +} + +int ohcount_loc_delta_is_changed(LocDelta *delta) { + return delta->code_added != 0 || delta->code_removed != 0 || + delta->comments_added != 0 || delta->comments_removed != 0 || + delta->blanks_added != 0 || delta->blanks_removed != 0; +} + +int ohcount_loc_delta_is_equal(LocDelta *delta, LocDelta *other) { + return strcmp(delta->language, other->language) == 0 && + delta->code_added == other->code_added && + delta->code_removed == other->code_removed && + delta->comments_added == other->comments_added && + delta->comments_removed == other->comments_removed && + delta->blanks_added == other->blanks_added && + delta->blanks_removed == other->blanks_removed; +} + +void ohcount_loc_delta_free(LocDelta *delta) { + free(delta); +} + +// LocDeltaList + +LocDeltaList *ohcount_loc_delta_list_new() { + LocDeltaList *list = malloc(sizeof(LocDeltaList)); + list->delta = NULL; + list->next = NULL; + list->head = NULL; + list->tail = NULL; + return list; +} + +void ohcount_loc_delta_list_add_loc_delta(LocDeltaList *list, LocDelta *delta) { + if (list->head == NULL) { // empty list + list->head = list; + list->tail = list; + list->head->delta = ohcount_loc_delta_new(delta->language, + delta->code_added, + delta->code_removed, + delta->comments_added, + delta->comments_removed, + delta->blanks_added, + delta->blanks_removed); + list->head->next = NULL; + } else { + LocDeltaList *iter = list->head; + while (iter) { + if (list->delta && strcmp(list->delta->language, delta->language) == 0) break; + iter = iter->next; + } + if (iter == NULL) { // new language + LocDeltaList *item = ohcount_loc_delta_list_new(); + item->delta = ohcount_loc_delta_new(delta->language, + delta->code_added, + delta->code_removed, + delta->comments_added, + delta->comments_removed, + delta->blanks_added, + delta->blanks_removed); + list->tail->next = item; + list->tail = item; + } else ohcount_loc_delta_add_loc_delta(iter->delta, delta); // existing + } +} + +void ohcount_loc_delta_list_add_loc_delta_list(LocDeltaList *list, + LocDeltaList *loc_delta_list) { + LocDeltaList *iter = loc_delta_list->head; + while (iter) { + ohcount_loc_delta_list_add_loc_delta(list, iter->delta); + iter = iter->next; + } +} + +LocDelta *ohcount_loc_delta_list_get_loc_delta(LocDeltaList *list, + const char *language) { + LocDeltaList *iter = list->head; + while (iter) { + if (strcmp(iter->delta->language, language) == 0) return iter->delta; + iter = iter->next; + } + return NULL; +} + +int ohcount_loc_delta_list_code_added(LocDeltaList *list) { + int sum = 0; + LocDeltaList *iter = list->head; + while (iter) { + sum += iter->delta->code_added; + iter = iter->next; + } + return sum; +} + +int ohcount_loc_delta_list_code_removed(LocDeltaList *list) { + int sum = 0; + LocDeltaList *iter = list->head; + while (iter) { + sum += iter->delta->code_removed; + iter = iter->next; + } + return sum; +} + +int ohcount_loc_delta_list_comments_added(LocDeltaList *list) { + int sum = 0; + LocDeltaList *iter = list->head; + while (iter) { + sum += iter->delta->comments_added; + iter = iter->next; + } + return sum; +} + +int ohcount_loc_delta_list_comments_removed(LocDeltaList *list) { + int sum = 0; + LocDeltaList *iter = list->head; + while (iter) { + sum += iter->delta->comments_removed; + iter = iter->next; + } + return sum; +} + +int ohcount_loc_delta_list_blanks_added(LocDeltaList *list) { + int sum = 0; + LocDeltaList *iter = list->head; + while (iter) { + sum += iter->delta->blanks_added; + iter = iter->next; + } + return sum; +} + +int ohcount_loc_delta_list_blanks_removed(LocDeltaList *list) { + int sum = 0; + LocDeltaList *iter = list->head; + while (iter) { + sum += iter->delta->blanks_removed; + iter = iter->next; + } + return sum; +} + +int ohcount_loc_delta_list_net_code(LocDeltaList *list) { + int sum = 0; + LocDeltaList *iter = list->head; + while (iter) { + sum += ohcount_loc_delta_net_code(iter->delta); + iter = iter->next; + } + return sum; +} + +int ohcount_loc_delta_list_net_comments(LocDeltaList *list) { + int sum = 0; + LocDeltaList *iter = list->head; + while (iter) { + sum += ohcount_loc_delta_net_comments(iter->delta); + iter = iter->next; + } + return sum; +} + +int ohcount_loc_delta_list_net_blanks(LocDeltaList *list) { + int sum = 0; + LocDeltaList *iter = list->head; + while (iter) { + sum += ohcount_loc_delta_net_blanks(iter->delta); + iter = iter->next; + } + return sum; +} + +int ohcount_loc_delta_list_net_total(LocDeltaList *list) { + int sum = 0; + LocDeltaList *iter = list->head; + while (iter) { + sum += ohcount_loc_delta_net_total(iter->delta); + iter = iter->next; + } + return sum; +} + +LocDeltaList *ohcount_loc_delta_list_new_compact(LocDeltaList *list) { + LocDeltaList *new_list = ohcount_loc_delta_list_new(); + LocDeltaList *iter = list->head; + while (iter) { + if (ohcount_loc_delta_is_changed(iter->delta)) + ohcount_loc_delta_list_add_loc_delta(new_list, iter->delta); + iter = iter->next; + } + return new_list; +} + +void ohcount_loc_delta_list_free(LocDeltaList *list) { + if (list->head) { + LocDeltaList *iter = list->head; + while (iter) { + LocDeltaList *next = iter->next; + ohcount_loc_delta_free(iter->delta); + free(iter); + iter = next; + } + } else free(list); +} diff --git a/src/loc.h b/src/loc.h new file mode 100644 index 0000000..943ed54 --- /dev/null +++ b/src/loc.h @@ -0,0 +1,310 @@ +// loc.h written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#ifndef OHCOUNT_LOC_H +#define OHCOUNT_LOC_H + +#include "structs.h" + +/** + * Creates a new Loc from the given language, lines of code, comments, and + * blanks, and number of files counted. + * The given language is not copied and may not be 'free'd. Use a language + * defined in src/languages.h. + * @param language The language being counted. + * @param code The number of lines of code counted. + * @param comments The number of lines of comments counted. + * @param blanks The number of blank lines counted. + * @param filecount The number of files counted for this set. + * @return Loc + */ +Loc *ohcount_loc_new(const char *language, int code, int comments, int blanks, + int filecount); + +/** + * Returns the total number of lines counted for a given Loc. + * @param loc A Loc created from ohcount_loc_new(). + */ +int ohcount_loc_total(Loc *loc); + +/** + * Adds a Loc to another, provided they use the same language. + * The results are stored in the first Loc given. The second Loc may be 'free'd + * immediately. + * @param loc A Loc created from ohcount_loc_new(). + * @param other Another Loc. + */ +void ohcount_loc_add_loc(Loc *loc, Loc *other); + +/** + * Returns whether or not two given Locs are equivalent. + * @param loc A Loc created from ohcount_loc_new(). + * @param other Another Loc. + */ +int ohcount_loc_is_equal(Loc *loc, Loc *other); + +/** + * Frees the memory allocated for a given Loc. + * @param loc A Loc created from ohcount_loc_new(). + */ +void ohcount_loc_free(Loc *loc); + +/** + * Creates a new LocList that is initially empty. + * Locs can be added using ohcount_loc_list_add_loc(). + * @return LocList + */ +LocList *ohcount_loc_list_new(); + +/** + * Adds a given Loc to a LocList. + * The given Loc is copied and may be 'free'd immediately. + * @param list a LocList created from ohcount_loc_list_new(). + * @param loc A Loc created from ohcount_loc_new(). + */ +void ohcount_loc_list_add_loc(LocList *list, Loc *loc); + +/** + * Adds a given LocList to another LocList. + * The results are stored in the first LocList given. The second LocList may be + * 'free'd immediately. + * @param list A LocList created from ohcount_loc_list_new(). + * @param loc_list Another LocList. + */ +void ohcount_loc_list_add_loc_list(LocList *list, LocList *loc_list); + +/** + * Returns a Loc from a given LocList and language. + * The returned pointer is used internally and may not be 'free'd. + * @param list A LocList created from ohcount_loc_list_new(). + * @param language The language of the Loc to retrieve. + * @return Loc or NULL. + */ +Loc *ohcount_loc_list_get_loc(LocList *list, const char *language); + +/** + * Returns the number of lines of code for all Locs in this LocList. + * @param list A LocList created from ohcount_loc_list_new(). + */ +int ohcount_loc_list_code(LocList *list); + +/** + * Returns the number of lines of commentsfor all Locs in this LocList. + * @param list A LocList created from ohcount_loc_list_new(). + */ +int ohcount_loc_list_comments(LocList *list); + +/** + * Returns the number of blank lines for all Locs in this LocList. + * @param list A LocList created from ohcount_loc_list_new(). + */ +int ohcount_loc_list_blanks(LocList *list); + +/** + * Returns the total number of lines for all Locs in this LocList. + * @param list A LocList created from ohcount_loc_list_new(). + */ +int ohcount_loc_list_total(LocList *list); + +/** + * Returns the number of files counted for all Locs in this LocList. + * @param list A LocList created from ohcount_loc_list_new(). + */ +int ohcount_loc_list_filecount(LocList *list); + +/** + * Creates a new LocList from a given one, excluding all Locs with no counted + * lines. + * The given list may be 'free'd immediately. + * @param list A LocList created from ohcount_loc_list_new(). + */ +LocList *ohcount_loc_list_new_compact(LocList *list); + +/** + * Frees the memory allocated for a given LocList. + * @param list A LocList created from ohcount_loc_list_new(). + */ +void ohcount_loc_list_free(LocList *list); + +/** + * Creates a new LocDelta from the given language and lines of code, comments, + * and blanks added and removed. + * The given language is not copied and may not be 'free'd. Use a language + * defined in src/languages.h. + * @param language The language being counted. + * @param code_added The number of lines of code added in this delta. + * @param code_removed The number of lines of code removed in this delta. + * @param comments_added The number of lines of comments added in this delta. + * @param comments_removed The number of lines of comments removed in this + * delta. + * @param blanks_added The number of blank lines added in this delta. + * @param blanks_removed The number of blank lines removed in this delta. + * @return LocDelta + */ +LocDelta *ohcount_loc_delta_new(const char *language, int code_added, + int code_removed, int comments_added, + int comments_removed, int blanks_added, + int blanks_removed); + +/** + * Returns the net number of lines of code in a given LocDelta. + * @param delta A LocDelta created from ohcount_loc_delta_new(). + */ +int ohcount_loc_delta_net_code(LocDelta *delta); + +/** + * Returns the net number of lines of comments in a given LocDelta. + * @param delta A LocDelta created from ohcount_loc_delta_new(). + */ +int ohcount_loc_delta_net_comments(LocDelta *delta); + +/** + * Returns the net number of blank lines in a given LocDelta. + * @param delta A LocDelta created from ohcount_loc_delta_new(). + */ +int ohcount_loc_delta_net_blanks(LocDelta *delta); + +/** + * Returns the net number of lines in a given LocDelta. + * @param delta A LocDelta created from ohcount_loc_delta_new(). + */ +int ohcount_loc_delta_net_total(LocDelta *delta); + +/** + * Adds a LocDelta to another, provided they use the same language. + * The results are stored in the first LocDelta given. The second LocDelta may + * be 'free'd immediately. + * @param delta A LocDelta created from ohcount_loc_delta_new(). + * @param other Another LocDelta. + */ +void ohcount_loc_delta_add_loc_delta(LocDelta *delta, LocDelta *other); + +/** + * Returns whether or not a given LocDelta has any line changes. + * @param delta A LocDelta created from ohcount_loc_delta_new(). + */ +int ohcount_loc_delta_is_changed(LocDelta *delta); + +/** + * Returns whether or not two given LocDeltas are equivalent. + * @param delta A LocDelta created from ohcount_loc_delta_new(). + * @param other Another LocDelta. + */ +int ohcount_loc_delta_is_equal(LocDelta *delta, LocDelta *other); + +/** + * Frees the memory allocated for a given LocDelta. + * @param delta A LocDelta created from ohcount_loc_delta_new(). + */ +void ohcount_loc_delta_free(LocDelta *delta); + +/** + * Creates a new LocDeltaList that is initially empty. + * LocDeltas can be added using ohcount&oc_delta_list_add_loc_delta(). + * @return LocDeltaList + */ +LocDeltaList *ohcount_loc_delta_list_new(); + +/** + * Adds a given LocDelta to a LocDeltaList. + * The given LocDelta is copied and may be 'free'd immediately. + * @param list A LocDeltaList created from ohcount_loc_delta_list_new(). + * @param delta A LocDelta created from ohcount_loc_delta_new(). + */ +void ohcount_loc_delta_list_add_loc_delta(LocDeltaList *list, LocDelta *delta); + +/** + * Adds a given LocDeltaList to another LocDeltaList. + * The results are stored in the first LocDeltaList given. The second + * LocDeltaList may be 'free'd immediately. + * @param list A LocDeltaList created from ohcount_loc_delta_list_new(). + * @param loc_delta_list Another LocDeltaList. + */ +void ohcount_loc_delta_list_add_loc_delta_list(LocDeltaList *list, + LocDeltaList *loc_delta_list); + +/** + * Returns a LocDelta from a given LocDeltaList and language. + * The returned pointer is used internally and may not be 'free'd. + * @param list A LocDeltaList created from ohcount_loc_delta_list_new(). + * @param language The language of the LocDelta to retrieve. + * @return LocDelta or NULL. + */ +LocDelta *ohcount_loc_delta_list_get_loc_delta(LocDeltaList *list, + const char *language); + +/** + * Returns the number of lines of code added for the given LocDeltaList. + * @param list A LocDeltaList created from ohcount_loc_delta_list_new(). + */ +int ohcount_loc_delta_list_code_added(LocDeltaList *list); + +/** + * Returns the number of lines of code removed for the given LocDeltaList. + * @param list A LocDeltaList created from ohcount_loc_delta_list_new(). + */ +int ohcount_loc_delta_list_code_removed(LocDeltaList *list); + +/** + * Returns the number of lines of comments added for the given LocDeltaList. + * @param list A LocDeltaList created from ohcount_loc_delta_list_new(). + */ +int ohcount_loc_delta_list_comments_added(LocDeltaList *list); + +/** + * Returns the number of lines of comments removed for the given LocDeltaList. + * @param list A LocDeltaList created from ohcount_loc_delta_list_new(). + */ +int ohcount_loc_delta_list_comments_removed(LocDeltaList *list); + +/** + * Returns the number of blank lines added for the given LocDeltaList. + * @param list A LocDeltaList created from ohcount_loc_delta_list_new(). + */ +int ohcount_loc_delta_list_blanks_added(LocDeltaList *list); + +/** + * Returns the number of blank lines removed for the given LocDeltaList. + * @param list A LocDeltaList created from ohcount_loc_delta_list_new(). + */ +int ohcount_loc_delta_list_blanks_removed(LocDeltaList *list); + +/** + * Returns the net number of lines of code for the given LocDeltaList. + * @param list A LocDeltaList created from ohcount_loc_delta_list_new(). + */ +int ohcount_loc_delta_list_net_code(LocDeltaList *list); + +/** + * Returns the net number of lines of comments for the given LocDeltaList. + * @param list A LocDeltaList created from ohcount_loc_delta_list_new(). + */ +int ohcount_loc_delta_list_net_comments(LocDeltaList *list); + +/** + * Returns the net number of blank lines for the given LocDeltaList. + * @param list A LocDeltaList created from ohcount_loc_delta_list_new(). + */ +int ohcount_loc_delta_list_net_blanks(LocDeltaList *list); + +/** + * Returns the net number of lines for the given LocDeltaList. + * @param list A LocDeltaList created from ohcount_loc_delta_list_new(). + */ +int ohcount_loc_delta_list_net_total(LocDeltaList *list); + +/** + * Creates a new LocDeltaList from a given one, excluding all LocDeltas with no + * counted lines. + * The given list may be 'free'd immediately. + * @param list A LocDeltaList created from ohcount_loc_delta_list_new(). + */ +LocDeltaList *ohcount_loc_delta_list_new_compact(LocDeltaList *list); + +/** + * Frees the memory allocated for a given LocDeltaList. + * @param list A LocDeltaList created from ohcount_loc_delta_list_new(). + */ +void ohcount_loc_delta_list_free(LocDeltaList *list); + +#endif diff --git a/src/log.c b/src/log.c new file mode 100644 index 0000000..d28686d --- /dev/null +++ b/src/log.c @@ -0,0 +1,11 @@ +#include +#include + +#define LOG_FILE "/tmp/ohcount.log" +void log_it(char *log) { + FILE *f = fopen(LOG_FILE, "a"); + fputs(log, f); + fclose(f); +} + + diff --git a/src/log.h b/src/log.h new file mode 100644 index 0000000..422b2fd --- /dev/null +++ b/src/log.h @@ -0,0 +1,3 @@ +#define log_it(log) {} /* by default, do nothing, to use this to debug + * uncomment the line below */ +//void log_it(char *log); diff --git a/src/ohcount.c b/src/ohcount.c new file mode 100644 index 0000000..4a0bb72 --- /dev/null +++ b/src/ohcount.c @@ -0,0 +1,308 @@ +// ohcount.c written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#include +#include +#include + +#include "hash/option_hash.h" +#include "sourcefile.h" +#include "ohcount.h" + +void annotate_callback(const char *language, const char *entity, int start, + int end, void *userdata) { + SourceFile *sf = (SourceFile *)userdata; + int length = end - start; + char buf[length]; + strncpy(buf, (const char*)sf->contents + start, length); // field exists + buf[length] = '\0'; + printf("%s\t%s\t%s", language, entity, buf); +} + +void annotate(SourceFileList *list) { + SourceFileList *iter = list->head; + while (iter) { + ohcount_sourcefile_parse_with_callback(iter->sf, annotate_callback, + iter->sf); + iter = iter->next; + } +} + +void detect(SourceFileList *list) { + SourceFileList *iter = list->head; + while (iter) { + printf("%s\t%s\n", ohcount_sourcefile_get_language(iter->sf), + iter->sf->filepath); + iter = iter->next; + } +} + +void licenses(SourceFileList *list) { + SourceFileList *iter = list->head; + while (iter) { + LicenseList *liter = ohcount_sourcefile_get_license_list(iter->sf)->head; + while (liter) { + printf("%s%s ", liter->lic->name, (liter->next != NULL) ? "," : ""); + printf("%s\n", iter->sf->filename); + liter = liter->next; + } + iter = iter->next; + } +} + +void raw_entities_callback(const char *language, const char *entity, int start, + int end, void *userdata) { + printf("%s\t%s\t%i\t%i\n", language, entity, start, end); +} + +void raw_entities(SourceFileList *list) { + SourceFileList *iter = list->head; + while (iter) { + ohcount_sourcefile_parse_entities_with_callback(iter->sf, + raw_entities_callback, + NULL); + iter = iter->next; + } +} + +void help() { + printf( + "Usage: ohcount [option] [paths...]\n" + "\n" + "Ohloh source code line counter command line tool.\n" + " http://www.ohloh.net/\n" + "\n" + "[option] can be one of the following:\n" + " -a, --annotate\n" + " -d, --detect\n" + " -h, --help\n" + " -i, --individual\n" + " -l, --license\n" + " -re\n" + " -s, --summary\n" + "\n" + "-a, --annotate Show annotated source code\n" + "\n" + " The contents of all source code files found within the given\n" + " paths will be emitted to stdout. Each line will be prefixed with\n" + " a tab-delimited language name and semantic categorization (code,\n" + " comment, or blank).\n" + "\n" + "-d, --detect Find source code files\n" + "\n" + " Recursively find all source code files within the given paths.\n" + " For each source code file found, the file name will be emitted to\n" + " stdout prefixed with a tab-delimited language name.\n" + "\n" + "-h, --help Display this message\n" + "\n" + "-i, --individual Count lines of code per file\n" + "\n" + " Count lines in all source code files within the given paths, and\n" + " emit a report of the lines of code, comments, and blanks in each\n" + " language per file.\n" + "\n" + "-l, --license\n" + "\n" + " Displays detected licensing information contained in each source\n" + " code file.\n" + "\n" + "-re\n" + "\n" + " Prints raw entity information to the screen (mainly for debugging).\n" + "\n" + "-s, --summary Count lines of code (default)\n" + "\n" + " Count lines in all source code files within the given paths, and\n" + " emit a report of the total number of lines of code, comments,\n" + " and blanks in each language. This is the default action.\n" + "\n" + "[paths] can refer to any number of individual files or directories.\n" + " Directories will be probed recursively. If no path is given,\n" + " the current directory will be used.\n" + ); +} + +void sort_loc_list_by_language(LocList *list) { + LocList *iter = list->head; + while (iter) { + LocList *min = iter; + LocList *iter2 = iter->next; + while (iter2) { + if (strcmp(iter2->loc->language, min->loc->language) < 0) + min = iter2; + iter2 = iter2->next; + } + if (iter != min) { + Loc *temp = iter->loc; + iter->loc = min->loc; + min->loc = temp; + } + iter = iter->next; + } +} + +void individual(SourceFileList *list) { + int count = 0; + SourceFileList *titer = list->head; + while (titer) { + count++; + titer = titer->next; + } + printf( + "Examining %i file(s)\n" + " Ohloh Line Count \n" + "Language Code Comment Comment %% Blank Total File\n" + "---------------- --------- --------- --------- --------- --------- -----------------------------------------------\n" + , count); + SourceFileList *iter = list->head; + while (iter) { + LocList *loc_list = ohcount_sourcefile_get_loc_list(iter->sf); + sort_loc_list_by_language(loc_list); + LocList *liter = loc_list->head; + while (liter) { + printf("%-16s", liter->loc->language); + printf(" %10d", liter->loc->code); + printf(" %10d", liter->loc->comments); + if (liter->loc->comments + liter->loc->code > 0) + printf(" %9.1f%%", + (float)liter->loc->comments / (liter->loc->comments + + liter->loc->code) * 100); + else + printf(" "); + printf(" %10d", liter->loc->blanks); + printf(" %10d", + liter->loc->code + liter->loc->comments + liter->loc->blanks); + printf(" %s\n", iter->sf->filename); + liter = liter->next; + } + iter = iter->next; + } +} + +void sort_loc_list_by_code(LocList *list) { + LocList *iter = list->head; + while (iter) { + LocList *max = iter; + LocList *iter2 = iter->next; + while (iter2) { + if (iter2->loc->code > max->loc->code) + max = iter2; + iter2 = iter2->next; + } + if (iter != max) { + Loc *temp = iter->loc; + iter->loc = max->loc; + max->loc = temp; + } + iter = iter->next; + } +} + +void summary(SourceFileList *list) { + int count = 0; + SourceFileList *tmpiter = list->head; + while (tmpiter) { + count++; + tmpiter = tmpiter->next; + } + printf("Examining %i file(s)\n", count); + LocList *loc_list = ohcount_sourcefile_list_analyze_languages(list); + sort_loc_list_by_code(loc_list); + printf( + "\n" + " Ohloh Line Count Summary \n" + "\n" + "Language Files Code Comment Comment %% Blank Total\n" + "---------------- ----- --------- --------- --------- --------- ---------\n"); + LocList *iter = loc_list->head; + while (iter) { + printf("%-16s", iter->loc->language); + printf(" %6d", iter->loc->filecount); + printf(" %10d", iter->loc->code); + printf(" %10d", iter->loc->comments); + if (iter->loc->comments + iter->loc->code > 0) + printf(" %9.1f%%", + (float)iter->loc->comments / (iter->loc->comments + + iter->loc->code) * 100); + else + printf(" 0.0%%"); + printf(" %10d", iter->loc->blanks); + printf(" %10d\n", + iter->loc->code + iter->loc->comments + iter->loc->blanks); + iter = iter->next; + } + printf("---------------- ----- --------- --------- --------- --------- ---------\n"); + int code = ohcount_loc_list_code(loc_list); + int comments = ohcount_loc_list_comments(loc_list); + int blanks = ohcount_loc_list_blanks(loc_list); + printf("%-16s", "Total"); + printf(" %6d", ohcount_loc_list_filecount(loc_list)); + printf(" %10d", code); + printf(" %10d", comments); + if (comments + code > 0) + printf(" %9.1f%%", (float)comments / (comments + code) * 100); + else + printf(" 0.0%%"); + printf(" %10d", blanks); + printf(" %10d\n", code + comments + blanks); + ohcount_loc_list_free(loc_list); +} + +int main(int argc, char *argv[]) { + int command = 0; + if (argc > 1) { + struct OhcountOption *opt = ohcount_hash_command_from_flag(argv[1], + strlen(argv[1])); + if (opt) + command = opt->value; + } + int i = 1; + if (command == 0) + command = COMMAND_SUMMARY; + else + i = 2; // parameter is not a file or directory + + SourceFileList *list = ohcount_sourcefile_list_new(); + if (i == argc) + ohcount_sourcefile_list_add_directory(list, "."); + for (; i < argc; i++) { + DIR *dir = opendir(argv[i]); + if (dir) { + ohcount_sourcefile_list_add_directory(list, argv[i]); + closedir(dir); + } else { + FILE *f = fopen(argv[i], "r"); + if (f) { + ohcount_sourcefile_list_add_file(list, argv[i]); + fclose(f); + } else printf("Bad argument: %s\n", argv[i]); + } + } + switch (command) { + case COMMAND_ANNOTATE: + annotate(list); + break; + case COMMAND_DETECT: + detect(list); + break; + case COMMAND_HELP: + help(); + break; + case COMMAND_INDIVIDUAL: + individual(list); + break; + case COMMAND_LICENSES: + licenses(list); + break; + case COMMAND_RAWENTITIES: + raw_entities(list); + break; + case COMMAND_SUMMARY: + summary(list); + break; + } + ohcount_sourcefile_list_free(list); + + return 0; +} diff --git a/src/ohcount.h b/src/ohcount.h new file mode 100644 index 0000000..f9f1182 --- /dev/null +++ b/src/ohcount.h @@ -0,0 +1,140 @@ +// ohcount.h written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#ifndef OHCOUNT_H +#define OHCOUNT_H + +/** + * @mainpage Ohcount + * + * The Ohloh source code line counter + * + * 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, see . + * + * @section overview Overview + * + * Ohcount is a program for counting lines of source code. It was originally + * developed at Ohloh and 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 4 main components: + * + * @li A detector which determines the primary language family used by a + * particular source file. + * @li A parser which provides a line-by-line breakdown of the contents of a + * source file. + * @li Another detector which tries to determine the license(s) the source file + * is licensed under. + * @li A final detector for gestalts (via the Ruby extension). + * + * The command line tool allows you to profile individual files or whole + * directory trees. + * + * @section requirements System Requirements + * + * Ohcount is supported on Mac OSX 10.5 and Ubuntu 6.06 LTS. Other Linux + * environments should also work, but your mileage may vary. Windows is not + * supported. + * + * @section download Download + * + * Ohcount source code is available as a Git repository: + * + * git clone git://ohcount.git.sourceforge.net/gitroot/ohcount/ohcount + * + * @section build Building Ohcount + * + * In order to build Ohcount, the following is required: + * + * @li GNU C compiler - http://gcc.gnu.org/ + * @li Ragel 6.3 or later - http://research.cs.queensu.ca/~thurston/ragel/ + * @li GNU gperf - http://www.gnu.org/software/gperf/ + * @li PCRE - http://pcre.sourceforge.net/ + * + * Run the 'build' script to build Ohcount. + * + * @code + * $ ./build + * @endcode + * + * You may then link or copy 'bin/ohcount' to your system's PATH. + * + * Building the Ruby extension of Ohcount requires: + * + * @li Ruby - http://ruby-lang.org/ + * @li Swig - http://swig.org/ + * + * @code + * $ ./build ruby + * @endcode + * + * You may then link or copy 'ruby/ohcount.{rb,so}' and 'ruby/gestalt{/,.rb}' + * to the appropriate places in your Ruby installation. + * + * @section start First Steps + * + * To measure lines of code, simply pass file or directory names to the + * bin/ohcount executable: + * + * @code + * $ ohcount helloworld.c + * @endcode + * + * 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: + * + * @code + * $ ohcount --detect | grep ^ruby + * @endcode + * + * The 'annotate' option presents a line-by-line accounting of the languages + * used in a source code file. For example: + * + * @code + * $ ohcount --annotate ./test/src_dir/php1.php + * @endcode + * + * More options can be found by typing: + * + * @code + * $ ohcount --help + * @endcode + * + * @section docs Additional Documentation + * + * See the Related Pages tab at the top of the page. + * + * @section contact Contact Ohloh + * + * For more information visit the Ohloh website: http://labs.ohloh.net + * + * You can reach Ohloh via email at: info@ohloh.net + */ + +#define COMMAND_ANNOTATE 1 +#define COMMAND_DETECT 2 +#define COMMAND_HELP 3 +#define COMMAND_INDIVIDUAL 4 +#define COMMAND_LICENSES 5 +#define COMMAND_RAWENTITIES 6 +#define COMMAND_SUMMARY 7 + +#endif diff --git a/src/parsed_language.c b/src/parsed_language.c new file mode 100644 index 0000000..5cf6fdb --- /dev/null +++ b/src/parsed_language.c @@ -0,0 +1,73 @@ +// parsed_language.c written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#include +#include + +#include "parsed_language.h" + +ParsedLanguage *ohcount_parsed_language_new(const char *name, + int buffer_size) { + ParsedLanguage *pl = malloc(sizeof(ParsedLanguage)); + pl->name = name; + pl->buffer_size = buffer_size; + pl->code = malloc(buffer_size + 5); + pl->code_p = pl->code; + *pl->code_p = '\0'; + pl->code_count = 0; + pl->comments = malloc(buffer_size + 5); + pl->comments_p = pl->comments; + *pl->comments_p = '\0'; + pl->comments_count = 0; + pl->blanks_count = 0; + return pl; +} + +void ohcount_parsed_language_add_code(ParsedLanguage *parsed_language, + char *p, int length) { + if (parsed_language->code_p + length < + parsed_language->code + parsed_language->buffer_size + 5) { + strncpy(parsed_language->code_p, p, length); + parsed_language->code_p += length; + *parsed_language->code_p = '\0'; + parsed_language->code_count++; + } +} + +void ohcount_parsed_language_add_comment(ParsedLanguage *parsed_language, + char *p, int length) { + if (parsed_language->comments_p + length < + parsed_language->comments + parsed_language->buffer_size + 5) { + strncpy(parsed_language->comments_p, p, length); + parsed_language->comments_p += length; + *parsed_language->comments_p = '\0'; + parsed_language->comments_count++; + } +} + +void ohcount_parsed_language_free(ParsedLanguage *parsed_language) { + free(parsed_language->code); + free(parsed_language->comments); + free(parsed_language); +} + +ParsedLanguageList *ohcount_parsed_language_list_new() { + ParsedLanguageList *list = malloc(sizeof(ParsedLanguageList)); + list->pl = NULL; + list->next = NULL; + list->head = NULL; + list->tail = NULL; + return list; +} + +void ohcount_parsed_language_list_free(ParsedLanguageList *list) { + if (list->head) { + ParsedLanguageList *iter = list->head; + while (iter) { + ParsedLanguageList *next = iter->next; + ohcount_parsed_language_free(iter->pl); + free(iter); + iter = next; + } + } else free(list); +} diff --git a/src/parsed_language.h b/src/parsed_language.h new file mode 100644 index 0000000..9c9db72 --- /dev/null +++ b/src/parsed_language.h @@ -0,0 +1,60 @@ +// parsed_language.h written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#ifndef OHCOUNT_PARSED_LANGUAGE_H +#define OHCOUNT_PARSED_LANGUAGE_H + +#include "structs.h" + +/** + * Creates a new ParsedLanguage for the given language and buffer size. + * The given language is not copied and may not be 'free'd. Use a language + * defined in src/languages.h. + * @param language The parsed language. + * @param buffer_size The size of the buffers to store parsed code and comment + * text. + * @return ParsedLanguage + */ +ParsedLanguage *ohcount_parsed_language_new(const char *language, + int buffer_size); + +/** + * Adds some code to the code buffer for the given ParsedLanguage. + * @param parsed_language A ParsedLanguage created from + * ohcount_parsed_language_new(). + * @param p A pointer in memory to start copying code from. + * @param length The number of characters to copy from p. + */ +void ohcount_parsed_language_add_code(ParsedLanguage *parsed_language, + char *p, int length); + +/** + * Adds a comment to the comment buffer for the given ParsedLanguage. + * @param parsed_language A ParsedLanguage created from + * ohcount_parsed_language_new(). + * @param p A pointer in memory to start copying the comment from. + * @param length The number of characters to copy from p. + */ +void ohcount_parsed_language_add_comment(ParsedLanguage *parsed_language, + char *p, int length); + +/** + * Frees the memory allocated for the given ParsedLanguage. + * @param parsed_language A ParsedLanguage created from + * ohcount_parsed_language_new(). + */ +void ohcount_parsed_language_free(ParsedLanguage *parsed_language); + +/** + * Creates a new ParsedLanguageList that is initially empty. + * @return ParsedLanguageList + */ +ParsedLanguageList *ohcount_parsed_language_list_new(); + +/** + * Frees the memory allocated for the given ParsedLanguageList. + * @param list A ParsedLanguage created from ohcount_parsed_language_list_new(). + */ +void ohcount_parsed_language_list_free(ParsedLanguageList *list); + +#endif diff --git a/src/parser.c b/src/parser.c new file mode 100644 index 0000000..cb28935 --- /dev/null +++ b/src/parser.c @@ -0,0 +1,28 @@ +// parser.c written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#include + +#include "sourcefile.h" +#include "log.h" +#include "hash/parser_hash.h" + +int ohcount_parse(SourceFile *sourcefile, int count, + void (*callback) (const char *, const char *, int, int, + void *), + void *userdata) { + const char *language = ohcount_sourcefile_get_language(sourcefile); + if (language) { + struct ParserMap *rp = + ohcount_hash_parser_from_language(language, strlen(language)); + if (rp) { + char *buffer = ohcount_sourcefile_get_contents(sourcefile); + int buffer_len = ohcount_sourcefile_get_contents_size(sourcefile); + if (callback) + rp->parser(buffer, buffer_len, count, callback, userdata); + return 1; + } + } + + return 0; +} diff --git a/src/parser.h b/src/parser.h new file mode 100644 index 0000000..370fbe5 --- /dev/null +++ b/src/parser.h @@ -0,0 +1,303 @@ +// parser.h written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#ifndef OHCOUNT_PARSER_H +#define OHCOUNT_PARSER_H + +#include "sourcefile.h" + +/** + * @page parser_doc Parser Documentation + * @author Mitchell Foral + * + * @section overview Overview + * + * I will assume the reader has a decent knowledge of how Ragel works and the + * Ragel syntax. If not, please review the Ragel manual found at: + * http://research.cs.queensu.ca/~thurston/ragel/ + * + * All parsers must at least: + * + * @li Call a callback function when a line of code is parsed. + * @li Call a callback function when a line of comment is parsed. + * @li Call a callback function when a blank line is parsed. + * + * Additionally a parser can call the callback function for each position of + * entities parsed. + * + * Take a look at 'c.rl' and even keep it open for reference when reading this + * document to better understand how parsers work and how to write one. + * + * @section writing Writing a Parser + * + * First create your parser in 'src/parsers/'. Its name should be the language + * you are parsing with a '.rl' extension. You will not have to manually compile + * any parsers, as this is automatically for you. However, you do need to add + * your parser to 'hash/parsers.gperf'. + * + * Every parser must have the following at the top: + * + * @include parser_doc_1 + * + * And the following at the bottom: + * + * @include parser_doc_2 + * + * (Your parser will go between these two blocks.) + * + * The code can be found in the existing 'c.rl' parser. You will need to change: + * @li OHCOUNT_[lang]_PARSER_H - Replace [lang] with your language name. So if + * you are writing a C parser, it would be OHCOUNT_C_PARSER_H. + * @li [lang]_LANG - Set the variable name to be [lang]_LANG and its value to be + * the name of your language to parse as defined in languages.h. [lang] is + * your language name. For C it would be C_LANG. + * @li [lang]_entities - Set the variable name to be [lang]_entities (e.g. + * c_entries) The value is an array of string entities your language has. For + * example C has comment, string, number, etc. entities. You should definately + * have "space", and "any" entities. "any" entities are typically used for + * entity machines (discussed later) and match any character that is not + * recognized so the parser does not do something unpredictable. + * @li enum - Change the value of the enum to correspond with your entities. So + * if in your parser you look up [lang]_entities[ENTITY], you will get the + * associated entity's string name. + * @li parse_[lang] - Set the function name to parse_[lang] where again, [lang] + * is the name of your language. In the case of C, it is parse_c. + * @li [lang]_en_[lang]_line - The line counting machine. + * @li [lang]_en_[lang]_entity - The entity machine. + * + * You may be asking why you have to rename variables and functions. Well if + * variables have the same name in header files (which is what parsers are), the + * compiler complains. Also, when you have languages embedded inside each other, + * any identifiers with the same name can easily be mixed up. It is also + * important to prefix your Ragel definitions with your language to avoid + * conflicts with other parsers. + * + * Additional variables available to parsers are in the parser_macros.h file. + * Take a look at it and try to understand what the variables are used for. They + * will make more sense later on. + * + * Now you can define your Ragel parser. Name your machine after your language, + * "write data", and include 'common.rl', a file with common Ragel definitions, + * actions, etc. For example: + * + * @include parser_doc_3 + * + * Before you begin to write patterns for each entity in your language, you need + * to understand how the parser should work. + * + * Each parser has two machines: one optimized for counting lines of code, + * comments, and blanks; the other for identifying entity positions in the + * buffer. + * + * @section line Line Counting Machine + * + * This machine should be written as a line-by-line parser for multiple lines. + * This means you match any combination of entities except a newline up until + * you do reach a newline. If the line contains only spaces, or nothing at all, + * it is blank. If the line contains spaces at first, but then a comment, or + * just simply a comment, the line is a comment. If the line contains anything + * but a comment after spaces (if there are any), it is a line of code. You + * will do this using a Ragel scanner. The callback function will be called for + * each line parsed. + * + * @subsection line_scanner Scanner Parser Structure + * + * A scanner parser will look like this: + * + * @include parser_doc_4 + * + * (As usual, replace [lang] with your language name.) + * + * Each entity is the pattern for an entity to match, the last one typically + * being the newline entity. For each match, the variable is set to a constant + * defined in the enum, and the main action is called (you will need to create + * this action above the scanner). + * + * When you detect whether or not a line is code or comment, you should call the + * appropriate \@code or \@comment action defined in 'common.rl' as soon as + * possible. It is not necessary to worry about whether or not these actions are + * called more than once for a given line; the first call to either sets the + * status of the line permanently. Sometimes you cannot call \@code or \@comment + * for one reason or another. Do not worry, as this is discussed later. + * + * When you reach a newline, you will need to decide whether the current line is + * a line of code, comment, or blank. This is easy. Simply check if the + * #line_contains_code or #whole_line_comment variables are set to 1. If neither + * of them are, the line is blank. Then call the callback function (not action) + * with an "lcode", "lcomment", or "lblank" string, and the start and end + * positions of that line (including the newline). The start position of the + * line is in the #line_start variable. It should be set at the beginning of + * every line either through the \@code or \@comment actions, or manually in the + * main action. Finally the #line_contains_code, #whole_line_comment, and + * #line_start state variables must be reset. All this should be done within the + * main action shown below. Note: For most parsers, the std_newline(lang) macro + * is sufficient and does everything in the main action mentioned above. The + * lang parameter is the [lang]_LANG string. + * + * @subsection line_action Main Action Structure + * + * The main action looks like this: + * + * @include parser_doc_5 + * + * @subsection line_entity_patterns Defining Patterns for Entities + * + * Now it is time to write patterns for each entity in your language. That does + * not seem very hard, except when your entity can cover multiple lines. + * Comments and strings in particular can do this. To make an accurate line + * counter, you will need to count the lines covered by multi-line entities. + * When you detect a newline inside your multi-line entity, you should set the + * entity variable to be #INTERNAL_NL and call the main action. The main action + * should have a case for #INTERNAL_NL separate from the newline entity. In it, + * you will check if the current line is code or comment and call the callback + * function with the appropriate string ("lcode" or "lcomment") and beginning + * and end of the line (including the newline). Afterwards, you will reset the + * #line_contains_code and #whole_line_comment state variables. Then set the + * #line_start variable to be #p, the current Ragel buffer position. Because + * #line_contains_code and #whole_line_comment have been reset, any non-newline + * and non-space character in the multi-line pattern should set + * #line_contains_code or #whole_line_comment back to 1. Otherwise you would count + * the line as blank. + * + * Note: For most parsers, the std_internal_newline(lang) macro is sufficient + * and does everything in the main action mentioned above. The lang parameter + * is the [lang]_LANG string. + * + * For multi-line matches, it is important to call the \@code or \@comment + * actions (mentioned earlier) before an internal newline is detected so the + * #line_contains_code and #whole_line_comment variables are properly set. For + * other entities, you can use the #code macro inside the main action which + * executes the same code as the Ragel \@code action. Other C macros are + * #comment and #ls, the latter is typically used for the SPACE entity when + * defining #line_start. + * + * Also for multi-line matches, it may be necessary to use the \@enqueue and + * \@commit actions. If it is possible that a multi-line entity will not have an + * ending delimiter (for example a string), use the \@enqueue action as soon as + * the start delimitter has been detected, and the \@commit action as soon as + * the end delimitter has been detected. This will eliminate the potential for + * any counting errors. + * + * @subsection line_notes Notes + * + * You can be a bit sloppy with the line counting machine. For example the only + * C entities that can contain newlines are strings and comments, so + * #INTERNAL_NL would only be necessary inside them. Other than those, anything + * other than spaces is considered code, so do not waste your time defining + * specific patterns for other entities. + * + * @subsection line_embedded Parsers with Embedded Languages + * + * Notation: [lang] is the parent language, [elang] is the embedded language. + * + * To write a parser with embedded languages (such as HTML with embedded CSS and + * Javascript), you should first \#include the parser(s) above your Ragel code. + * The header file is "[elang]_parser.h". + * + * Next, after the inclusion of 'common.rl', add "#EMBED([elang])" on separate + * lines for each embedded language. The build process looks for these special + * comments to embed the language for you automatically. + * + * In your main action, you need to add another entity #CHECK_BLANK_ENTRY. It + * should call the #check_blank_entry([lang]_LANG) macro. Blank entries are an + * entry into an embedded language, but the rest of the line is blank before a + * newline. For example, a CSS entry in HTML is something like: + * + * @code + * +html code +html code new +html code diff --git a/test/expected_dir/diff1_old.html b/test/expected_dir/diff1_old.html new file mode 100644 index 0000000..8e6d912 --- /dev/null +++ b/test/expected_dir/diff1_old.html @@ -0,0 +1,11 @@ +html code +html code +html code +html code +html code +html code old +html code diff --git a/test/expected_dir/diff2_new.c b/test/expected_dir/diff2_new.c new file mode 100644 index 0000000..7ba80e9 --- /dev/null +++ b/test/expected_dir/diff2_new.c @@ -0,0 +1,7 @@ +c comment /* new */ +c code #include 'foo.c' +c comment /* common */ +c code int do_stuff(old_code) { +c code int common; +c code int new_var; +c code } diff --git a/test/expected_dir/diff2_old.c b/test/expected_dir/diff2_old.c new file mode 100644 index 0000000..906e6f0 --- /dev/null +++ b/test/expected_dir/diff2_old.c @@ -0,0 +1,7 @@ +c comment /* old */ +c code #include 'foo.c' +c comment /* common */ +c code int do_stuff(old_code) { +c code int common; +c code int old_var; +c code } diff --git a/test/expected_dir/diff3_new.xml b/test/expected_dir/diff3_new.xml new file mode 100644 index 0000000..b01c982 --- /dev/null +++ b/test/expected_dir/diff3_new.xml @@ -0,0 +1,3 @@ +xml code +xml code new +xml code diff --git a/test/expected_dir/diff3_old.xml b/test/expected_dir/diff3_old.xml new file mode 100644 index 0000000..145f963 --- /dev/null +++ b/test/expected_dir/diff3_old.xml @@ -0,0 +1,3 @@ +xml code +xml code old +xml code diff --git a/test/expected_dir/dylan1.dylan b/test/expected_dir/dylan1.dylan new file mode 100644 index 0000000..4fcf478 --- /dev/null +++ b/test/expected_dir/dylan1.dylan @@ -0,0 +1,17 @@ +dylan comment // random program i found +dylan code define function describe-list(my-list :: , #key verbose?) => () +dylan code format(*standard-output*, "{a , size: %d", my-list.size); +dylan code if (verbose?) +dylan code format(*standard-output*, ", elements:"); +dylan code for (item in my-list) +dylan code format(*standard-output*, " %=", item); +dylan code end for; +dylan code end if; +dylan code format(*standard-output*, "}"); +dylan code end function; +dylan blank +dylan code describe-list(#(1, 2, 3, 4, 5, 6)); +dylan comment // prints "{a , size: 6}" +dylan blank +dylan code describe-list(#(5, 7, 3), verbose?: #t); +dylan comment // prints "{a , size: 3, elements: 5 7 3}" diff --git a/test/expected_dir/eiffel.e b/test/expected_dir/eiffel.e new file mode 100644 index 0000000..e90c775 --- /dev/null +++ b/test/expected_dir/eiffel.e @@ -0,0 +1,13 @@ +eiffel code class +eiffel code HELLO_WORLD +eiffel code create +eiffel code make +eiffel code feature +eiffel code make +eiffel code do +eiffel comment -- prints "Hello world!" and starts new line +eiffel blank +eiffel code print ("Hello, world!%N") +eiffel blank +eiffel code end +eiffel code end diff --git a/test/expected_dir/el1.el b/test/expected_dir/el1.el new file mode 100644 index 0000000..ba7de4c --- /dev/null +++ b/test/expected_dir/el1.el @@ -0,0 +1,22 @@ +emacslisp code (if (string-equal "21" (substring (emacs-version) 10 12)) +emacslisp code (progn +emacslisp code (blink-cursor-mode 0) +emacslisp comment ;; Insert newline when you press `C-n' (next-line) +emacslisp comment ;; at the end of the buffer +emacslisp blank +emacslisp code (setq next-line-add-newlines t) +emacslisp comment ;; Turn on image viewing +emacslisp code (auto-image-file-mode t) +emacslisp comment ;; Turn on menu bar (this bar has text) +emacslisp comment ;; (Use numeric argument to turn on) +emacslisp code (menu-bar-mode 1) +emacslisp comment ;; Turn off tool bar (this bar has icons) +emacslisp comment ;; (Use numeric argument to turn on) +emacslisp code (tool-bar-mode nil) +emacslisp comment ;; Turn off tooltip mode for tool bar +emacslisp comment ;; (This mode causes icon explanations to pop up) +emacslisp comment ;; (Use numeric argument to turn on) +emacslisp code (tooltip-mode nil) +emacslisp comment ;; If tooltips turned on, make tips appear promptly +emacslisp code (setq tooltip-delay 0.1) ; default is one second +emacslisp code )) diff --git a/test/expected_dir/english.st b/test/expected_dir/english.st new file mode 100644 index 0000000..e69de29 diff --git a/test/expected_dir/erl1.erl b/test/expected_dir/erl1.erl new file mode 100644 index 0000000..43da9d3 --- /dev/null +++ b/test/expected_dir/erl1.erl @@ -0,0 +1,189 @@ +erlang comment %%%---------------------------------------------------------------------- +erlang comment %%% File : erl1.erl +erlang comment %%% Author : Jason Allen - kinda - just repurposing random code +erlang comment %%% Purpose : Test out the erlang parsing +erlang comment %%% Created : 1/17/2007 by Jason Allen +erlang comment %%% Id : $Id: erl1.erl 1 2007-17-01 jason $ +erlang comment %%%---------------------------------------------------------------------- +erlang blank +erlang code -module(erl1). +erlang code -author('jason@ohloh.net'). +erlang code -vsn('$Revision: 1 $ '). +erlang blank +erlang comment %% External exports +erlang code -export([import_file/1, +erlang code import_dir/1]). +erlang blank +erlang code -include("random.hrl"). +erlang code -include("more_random.hrl"). +erlang blank +erlang comment %%%---------------------------------------------------------------------- +erlang comment %%% API +erlang comment %%%---------------------------------------------------------------------- +erlang blank +erlang code import_file(File) -> +erlang code User = filename:rootname(filename:basename(File)), +erlang code Server = filename:basename(filename:dirname(File)), +erlang code case (jlib:nodeprep(User) /= error) andalso +erlang code (jlib:nameprep(Server) /= error) of +erlang code true -> +erlang code case file:read_file(File) of +erlang code {ok, Text} -> +erlang code case xml_stream:parse_element(Text) of +erlang code El when element(1, El) == xmlelement -> +erlang code case catch process_xdb(User, Server, El) of +erlang code {'EXIT', Reason} -> +erlang code ?ERROR_MSG( +erlang code "Error while processing file \"~s\": ~p~n", +erlang code [File, Reason]), +erlang code {error, Reason}; +erlang code _ -> +erlang code ok +erlang code end; +erlang code {error, Reason} -> +erlang code ?ERROR_MSG("Can't parse file \"~s\": ~p~n", +erlang code [File, Reason]), +erlang code {error, Reason} +erlang code end; +erlang code {error, Reason} -> +erlang code ?ERROR_MSG("Can't read file \"~s\": ~p~n", [File, Reason]), +erlang code {error, Reason} +erlang code end; +erlang code false -> +erlang code ?ERROR_MSG("Illegal user/server name in file \"~s\"~n", [File]), +erlang code {error, "illegal user/server"} +erlang code end. +erlang blank +erlang blank +erlang code import_dir(Dir) -> +erlang code {ok, Files} = file:list_dir(Dir), +erlang code MsgFiles = lists:filter( +erlang code fun(FN) -> +erlang code case string:len(FN) > 4 of +erlang code true -> +erlang code string:substr(FN, +erlang code string:len(FN) - 3) == ".xml"; +erlang code _ -> +erlang code false +erlang code end +erlang code end, Files), +erlang code lists:foldl( +erlang code fun(FN, A) -> +erlang code Res = import_file(filename:join([Dir, FN])), +erlang code case {A, Res} of +erlang code {ok, ok} -> ok; +erlang code {ok, _} -> {error, "see aoabberd log for details"}; +erlang code _ -> A +erlang code end +erlang code end, ok, MsgFiles). +erlang blank +erlang comment %%%---------------------------------------------------------------------- +erlang comment %%% Internal functions +erlang comment %%%---------------------------------------------------------------------- +erlang blank +erlang code process_xdb(User, Server, {xmlelement, Name, _Attrs, Els}) -> +erlang code case Name of +erlang code "xdb" -> +erlang code lists:foreach( +erlang code fun(El) -> +erlang code xdb_data(User, Server, El) +erlang code end, Els); +erlang code _ -> +erlang code ok +erlang code end. +erlang blank +erlang blank +erlang code xdb_data(User, Server, {xmlcdata, _CData}) -> +erlang code ok; +erlang code xdb_data(User, Server, {xmlelement, _Name, Attrs, _Els} = El) -> +erlang code From = jlib:make_jid(User, Server, ""), +erlang code LServer = jlib:nameprep(Server), +erlang code case xml:get_attr_s("xmlns", Attrs) of +erlang code ?NS_AUTH -> +erlang code Password = xml:get_tag_cdata(El), +erlang code ejabberd_auth:set_password(User, Server, Password), +erlang code ok; +erlang code ?NS_ROSTER -> +erlang code case lists:member(mod_roster_odbc, +erlang code gen_mod:loaded_modules(LServer)) of +erlang code true -> +erlang code catch mod_roster_odbc:set_items(User, Server, El); +erlang code false -> +erlang code catch mod_roster:set_items(User, Server, El) +erlang code end, +erlang code ok; +erlang code ?NS_LAST -> +erlang code TimeStamp = xml:get_attr_s("last", Attrs), +erlang code Status = xml:get_tag_cdata(El), +erlang code case lists:member(mod_last_odbc, +erlang code gen_mod:loaded_modules(LServer)) of +erlang code true -> +erlang code catch mod_last_odbc:store_last_info( +erlang code User, +erlang code Server, +erlang code list_to_integer(TimeStamp), +erlang code Status); +erlang code false -> +erlang code catch mod_last:store_last_info( +erlang code User, +erlang code Server, +erlang code list_to_integer(TimeStamp), +erlang code Status) +erlang code end, +erlang code ok; +erlang code ?NS_VCARD -> +erlang code case lists:member(mod_vcard_odbc, +erlang code gen_mod:loaded_modules(LServer)) of +erlang code true -> +erlang code catch mod_vcard_odbc:process_sm_iq( +erlang code From, +erlang code jlib:make_jid("", Server, ""), +erlang code #iq{type = set, xmlns = ?NS_VCARD, sub_el = El}); +erlang code false -> +erlang code catch mod_vcard:process_sm_iq( +erlang code From, +erlang code jlib:make_jid("", Server, ""), +erlang code #iq{type = set, xmlns = ?NS_VCARD, sub_el = El}) +erlang code end, +erlang code ok; +erlang code "jabber:x:offline" -> +erlang code process_offline(Server, From, El), +erlang code ok; +erlang code XMLNS -> +erlang code case xml:get_attr_s("j_private_flag", Attrs) of +erlang code "1" -> +erlang code catch mod_private:process_sm_iq( +erlang code From, +erlang code jlib:make_jid("", Server, ""), +erlang code #iq{type = set, xmlns = ?NS_PRIVATE, +erlang code sub_el = {xmlelement, "query", [], +erlang code [jlib:remove_attr( +erlang code "j_private_flag", +erlang code jlib:remove_attr("xdbns", El))]}}); +erlang code _ -> +erlang code ?DEBUG("jd2ejd: Unknown namespace \"~s\"~n", [XMLNS]) +erlang code end, +erlang code ok +erlang code end. +erlang blank +erlang blank +erlang code process_offline(Server, To, {xmlelement, _, _, Els}) -> +erlang code LServer = jlib:nameprep(Server), +erlang code lists:foreach(fun({xmlelement, _, Attrs, _} = El) -> +erlang code FromS = xml:get_attr_s("from", Attrs), +erlang code From = case FromS of +erlang code "" -> +erlang code jlib:make_jid("", Server, ""); +erlang code _ -> +erlang code jlib:string_to_jid(FromS) +erlang code end, +erlang code case From of +erlang code error -> +erlang code ok; +erlang code _ -> +erlang code ejabberd_hooks:run(offline_message_hook, +erlang code LServer, +erlang code [From, To, El]) +erlang code end +erlang code end, Els). +erlang blank diff --git a/test/expected_dir/example.R b/test/expected_dir/example.R new file mode 100644 index 0000000..1058247 --- /dev/null +++ b/test/expected_dir/example.R @@ -0,0 +1,200 @@ +r comment # Build a 'graph-like' object having 'nodes' nodes belonging to 'classes' classes. +r comment # Class distribution is given by 'proba', and connectivity probabilities are given +r comment # by 'intraproba' and 'interproba'. +r code generateGraph<-function(nodes,classes,proba=rep(1/classes,classes), +r code intraproba=0.1,crossproba=0.02) +r code { +r code mat_pi=CreateConnectivityMat(classes,intraproba,crossproba) +r code igraph=Fast2SimuleERMG(nodes,proba,mat_pi[1],mat_pi[2]) +r code adjacency=get.adjacency(igraph$graph) +r code cmgraph=list(nodes=nodes,classes=classes,adjacency=adjacency,nodeclasses=igraph$node.classes,proba=proba, +r code intraproba=intraproba,crossproba=crossproba) +r code attr(cmgraph,'class')<-c('cmgraph') +r code cmgraph +r code } +r blank +r comment # Return explicit member names for the different attributes of graph objects. +r code labels.cmgraph<-function(object,...) +r code { +r code c("Nodes","Classes","Adjacency Matrix","Node Classification","Class Probability Distribution","Intra Class Edge Probability","Cross Class Edge Probability") +r code } +r blank +r comment # Override the summmary function for graph objects. +r code summary.cmgraph<-function(object,...) +r code { +r blank +r code cat(c("Nodes : ",object$nodes,"\n", +r code "Edges : ",length(which(object$adjacency!=0)),"\n", +r code "Classes : ",object$classes,"\n", +r code "Class Probability Distribution: ",object$proba,"\n")) +r code } +r blank +r comment # Override the plot function for graph objects. +r code plot.cmgraph<-function(x,...) +r code { +r code RepresentationXGroup(x$adjacency,x$nodeclasses) +r code } +r blank +r comment # Generate covariable data for the graph 'g'. Covariables are associated to vertex data, and +r comment # their values are drawn according to 2 distributions: one for vertices joining nodes of +r comment # the same class, and another for vertices joining nodes of different classes. +r comment # The two distributions have different means but a single standard deviation. +r code generateCovariablesCondZ<-function(g,sameclustermean=0,otherclustermean=2,sigma=1) +r code { +r code mu=CreateMu(g$classes,sameclustermean,otherclustermean) +r code res=SimDataYcondZ(g$nodeclasses,mu,sigma) +r code cmcovars=list(graph=g,sameclustermean=sameclustermean,otherclustermean=otherclustermean,sigma=sigma,mu=mu,y=res) +r code attr(cmcovars,'class')<-c('cmcovarz','cmcovar') +r code cmcovars +r code } +r blank +r comment # Generate covariable data for the graph 'g'. Covariables are associated to vertex data, and +r comment # their values are drawn according to 2 distributions: one for vertices joining nodes of +r comment # the same class, and another for vertices joining nodes of different classes. +r comment # The two distributions have different means but a single standard deviation. +r comment # This function generates two sets of covariables. +r code generateCovariablesCondXZ<-function(g,sameclustermean=c(0,3),otherclustermean=c(2,5),sigma=1) +r code { +r code mux0=CreateMu(g$classes,sameclustermean[1],otherclustermean[1]) +r code mux1=CreateMu(g$classes,sameclustermean[2],otherclustermean[2]) +r code res=SimDataYcondXZ(g$nodeclasses,g$adjacency,mux0,mux1,sigma) +r code cmcovars=list(graph=g,sameclustermean=sameclustermean,otherclustermean=otherclustermean,sigma=sigma,mu=c(mux0,mux1),y=res) +r code attr(cmcovars,'class')<-c('cmcovarxz','cmcovar') +r code cmcovars +r code } +r blank +r blank +r comment # Override the print function for a cleaner covariable output. +r code print.cmcovar<-function(x,...) +r code { +r code cat("Classes : ",x$graph$classes,"\n", +r code "Intra cluster mean: ",x$sameclustermean,"\n", +r code "Cross cluster mean: ",x$otherclustermean,"\n", +r code "Variance : ",x$sigma,"\n", +r code "Covariables :\n",x$y,"\n") +r code } +r blank +r blank +r comment # Perform parameter estimation on 'graph' given the covariables 'covars'. +r code estimateCondZ<-function(graph,covars,maxiterations,initialclasses,selfloops) +r code { +r code res=EMalgorithm(initialclasses,covars$y,graph$adjacency,maxiterations,FALSE,selfloops) +r code cmestimation=list(mean=res$MuEstimated,variance=res$VarianceEstimated,pi=res$PIEstimated,alpha=res$AlphaEstimated,tau=res$TauEstimated,jexpected=res$EJ,graph=graph) +r code attr(cmestimation,'class')<-c('cmestimationz') +r code cmestimation +r code } +r blank +r comment # Private generic estimation function used to allow various call conventions for estimation functions. +r code privateestimate<-function(covars,graph,maxiterations,initialclasses,selfloops,...) UseMethod("privateestimate") +r blank +r comment # Private estimation function used to allow various call conventions for estimation functions. +r comment # Override of generic function for single covariables. +r code privateestimate.cmcovarz<-function(covars,graph,maxiterations,initialclasses,selfloops,...) +r code { +r code res=estimateCondZ(graph,covars,maxiterations,initialclasses,selfloops) +r code attr(res,'class')<-c(attr(res,'class'),'cmestimation') +r code res +r blank +r code } +r blank +r comment # Perform parameter estimation on 'graph' given the covariables 'covars'. +r code estimateCondXZ<-function(graph,covars,maxiterations,initialclasses,selfloops) +r code { +r comment #resSimXZ = EMalgorithmXZ(TauIni,Y2,Adjacente,30,SelfLoop=FALSE) +r code res=EMalgorithmXZ(initialclasses,covars$y,graph$adjacency,maxiterations,selfloops) +r code cmestimation=list(mean=c(res$MuEstimated1,res$MuEstimated2),variance=res$VarianceEstimated,pi=res$PIEstimated,alpha=res$AlphaEstimated,tau=res$TauEstimated,jexpected=res$EJ,graph=graph) +r code attr(cmestimation,'class')<-c('cmestimationxz') +r code cmestimation +r code } +r blank +r comment # Private estimation function used to allow various call conventions for estimation functions. +r comment # Override of generic function for multiple covariables. +r code privateestimate.cmcovarxz<-function(covars,graph,maxiterations,initialclasses,selfloops,...) +r code { +r code res=estimateCondXZ(graph,covars,maxiterations,initialclasses,selfloops) +r code attr(res,'class')<-c(attr(res,'class'),'cmestimation') +r code res +r code } +r blank +r comment # Generic estimation function applicable to graphs with covariables. +r code estimate<-function(graph,covars,...) UseMethod("estimate") +r blank +r comment # Override of the generic estimation function. Performs the actual function dispatch depending on the class of covariables. +r code estimate.cmgraph<-function(graph,covars,maxiterations=20,initialclasses=t(rmultinom(size=1,prob=graph$proba,n=graph$nodes)),selfloops=FALSE,method=NULL,...) +r code { +r code if (length(method) == 0) { +r code res=privateestimate(covars,graph,maxiterations,initialclasses,selfloops,...) +r code } else { +r code res=method(graph,covars,maxiterations,initialclasses,selfloops) +r code attr(res,'class')<-c(attr(res,'class'),'cmestimation') +r code } +r code res +r code } +r blank +r comment # Override of the generic pliot function for estimation results. +r code plot.cmestimation<-function(x,...) +r code { +r code par(mfrow = c(1,2)) +r code plot(x$jexpected) +r code title("Expected value of J: Convergence criterion") +r blank +r code map=MAP(x$tau) +r code gplot(x$graph$adjacency,vertex.col=map$node.classes+2) +r code title("Network with estimated classes") +r blank +r code } +r blank +r comment # Generic private ICL computation function for graphs and covariables. +r code privatecomputeICL<-function(covars,graph,qmin,qmax,loops,maxiterations,selfloops) UseMethod("privatecomputeICL") +r blank +r blank +r comment # Private ICL computation function for graphs with single covariables. +r code privatecomputeICL.cmcovarz<-function(covars,graph,qmin,qmax,loops,maxiterations,selfloops) +r code { +r code res=ICL(X=graph$adjacency,Y=covars$y,Qmin=qmin,Qmax=qmax,loop=loops,NbIteration=maxiterations,SelfLoop=selfloops,Plot=FALSE) +r code attr(res,'class')<-c('cmiclz') +r code res +r blank +r code } +r blank +r comment # Private ICL computation function for graphs with multiple covariables. +r code privatecomputeICL.cmcovarxz<-function(covars,graph,qmin,qmax,loops,maxiterations,selfloops) +r code { +r code res=ICL(X=graph$adjacency,Y=covars$y,Qmin=qmin,Qmax=qmax,loop=loops,NbIteration=maxiterations,SelfLoop=selfloops,Plot=FALSE) +r code attr(res,'class')<-c('cmiclxz') +r code res +r code } +r blank +r blank +r comment # Generic public ICL computation function applicable to graph objects. +r code computeICL<-function(graph,covars,qmin,qmax,...) UseMethod("computeICL") +r blank +r comment # Override of ICL computation function applicable to graph objects. +r comment # Performs the actual method dispatch to private functions depending on the type of covariables. +r code computeICL.cmgraph<-function(graph,covars,qmin,qmax,loops=10,maxiterations=20,selfloops=FALSE,...) +r code { +r code res=privatecomputeICL(covars,graph,qmin,qmax,loops,maxiterations,selfloops) +r code res$qmin=qmin +r code res$qmax=qmax +r code res$graph=graph +r code res$covars=covars +r code attr(res,'class')<-c(attr(res,'class'),'cmicl') +r code res +r code } +r blank +r comment # Override of the plot function for results of ICL computation. +r code plot.cmicl<-function(x,...) +r code { +r code par(mfrow = c(1,2)) +r code result=x$iclvalues +r code maxi=which(max(result)==result) +r code plot(seq(x$qmin,x$qmax),result,type="b",xlab="Number of classes",ylab="ICL value") +r code points(maxi+x$qmin-1,result[maxi],col="red") +r code title("ICL curve") +r code best=x$EMestimation[[maxi+x$qmin-1]] +r code tau=best$TauEstimated +r code map=MAP(tau) +r code gplot(x$graph$adjacency,vertex.col=map$node.classes+2) +r code title("Network with estimated classes") +r code } +r blank diff --git a/test/expected_dir/example.xsl b/test/expected_dir/example.xsl new file mode 100644 index 0000000..be18ba2 --- /dev/null +++ b/test/expected_dir/example.xsl @@ -0,0 +1,17 @@ +xslt code +xslt code +xslt blank +xslt comment +xslt code +xslt code +xslt code +xslt code sample webpage +xslt code +xslt code +xslt code +xslt comment +xslt code comment in HTML +xslt code +xslt code +xslt code +xslt code diff --git a/test/expected_dir/factor1.factor b/test/expected_dir/factor1.factor new file mode 100644 index 0000000..a6c1180 --- /dev/null +++ b/test/expected_dir/factor1.factor @@ -0,0 +1,14 @@ +factor comment ! This is a comment +factor comment ! Factor syntax is very simple, it just contains words separated by spaces +factor comment ! '!' is a line comment word +factor comment ! "whatever" is a string word +factor code USING: kernel io ; ! This is a vocabulary inclusion word +factor code IN: testing +factor blank +factor code : test-string ( -- ) +factor code "this is a string" print ; +factor blank +factor code : test ( x -- y ) ! Parenthesis define a stack effect declaration +factor code dup swap drop ; +factor blank +factor code MAIN: test diff --git a/test/expected_dir/fb.js b/test/expected_dir/fb.js new file mode 100644 index 0000000..0f7000e --- /dev/null +++ b/test/expected_dir/fb.js @@ -0,0 +1,9 @@ +javascript code function escapeHTML(value) +javascript code { +javascript code return String(value).replace(/[<>&"']/g, replaceChars); +javascript code } +javascript blank +javascript code window.onerror = onError; +javascript blank +javascript code if (document.documentElement.getAttribute("debug") == "true") +javascript code toggleConsole(true); diff --git a/test/expected_dir/foo.ebuild b/test/expected_dir/foo.ebuild new file mode 100644 index 0000000..dbb6cca --- /dev/null +++ b/test/expected_dir/foo.ebuild @@ -0,0 +1,21 @@ +ebuild comment # This is an ebuild. +ebuild comment # Distributed under the terms of the GNU General Public License v2 +ebuild comment # $Header: $ +ebuild blank +ebuild code DESCRIPTION="An ebuild" +ebuild code HOMEPAGE="" +ebuild code SRC_URI="" +ebuild blank +ebuild code LICENSE="" +ebuild code SLOT="0" +ebuild code KEYWORDS="~x86" +ebuild code IUSE="" +ebuild blank +ebuild code DEPEND="" +ebuild code RDEPEND="" +ebuild blank +ebuild code pkg_setup() { +ebuild comment # This is foo +ebuild code einfo "This is foo" +ebuild code } +ebuild blank diff --git a/test/expected_dir/foo.exheres-0 b/test/expected_dir/foo.exheres-0 new file mode 100644 index 0000000..ff3e5a7 --- /dev/null +++ b/test/expected_dir/foo.exheres-0 @@ -0,0 +1,20 @@ +exheres comment # This is an exheres. +exheres blank +exheres code require subversion bash-completion eutils flag-o-matic +exheres blank +exheres code DESCRIPTION="An exheres" +exheres code HOMEPAGE="http://example.org/" +exheres code SRC_URI="" +exheres blank +exheres code MYOPTIONS="monkey" +exheres code LICENSE="GPL-2" +exheres code SLOT="0" +exheres code PLATFORMS="~amd64 ~ia64 ~x86" +exheres blank +exheres code DEPENDENCIES="" +exheres blank +exheres code src_prepare() { +exheres code default +exheres code ./autogen.bash || die "autogen.bash failed" +exheres code } +exheres blank diff --git a/test/expected_dir/foo.glsl b/test/expected_dir/foo.glsl new file mode 100644 index 0000000..97f3b9a --- /dev/null +++ b/test/expected_dir/foo.glsl @@ -0,0 +1,4 @@ +glsl comment // GLSL vertex shader +glsl code void main() { +glsl code gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex; +glsl code } \ No newline at end of file diff --git a/test/expected_dir/foo.tex b/test/expected_dir/foo.tex new file mode 100644 index 0000000..2115445 --- /dev/null +++ b/test/expected_dir/foo.tex @@ -0,0 +1,8 @@ +tex code \begin{document} +tex code \texbf Hello world +tex blank +tex blank +tex comment % +tex comment % sample comment +tex blank +tex code \end{document} diff --git a/test/expected_dir/foo.vim b/test/expected_dir/foo.vim new file mode 100644 index 0000000..4322100 --- /dev/null +++ b/test/expected_dir/foo.vim @@ -0,0 +1,21 @@ +vim comment " Vim syntax file +vim comment " Language: Test file for ohcount +vim comment " Author: Ciaran McCreesh +vim comment " +vim comment " This is a test vim syntax file for ohcount. +vim comment " +vim blank +vim code if &compatible || v:version < 700 +vim code finish +vim code endif +vim blank +vim code if exists("b:current_syntax") +vim code finish +vim code endif +vim blank +vim comment " This is a comment. There are many like it, but this one is mine. +vim code syn region GiantSpaceMonkey start=/^\s*#/ end=/$/ +vim code hi def link GiantSpaceMonkey Comment +vim blank +vim code let b:current_syntax = "ohcount-test" +vim blank diff --git a/test/expected_dir/foo_glsl.vert b/test/expected_dir/foo_glsl.vert new file mode 100644 index 0000000..48dafda --- /dev/null +++ b/test/expected_dir/foo_glsl.vert @@ -0,0 +1,43 @@ +glsl comment // from OGRE3D's skinningTwoWeightsShadowCasterVp.glsl +glsl comment // Example GLSL program for skinning with two bone weights per vertex +glsl blank +glsl code attribute vec4 vertex; +glsl code attribute vec4 uv0; +glsl code attribute vec4 blendIndices; +glsl code attribute vec4 blendWeights; +glsl blank +glsl comment // 3x4 matrix, passed as vec4's for compatibility with GL 2.0 +glsl comment // GL 2.0 supports 3x4 matrices +glsl comment // Support 24 bones ie 24*3, but use 72 since our parser can pick that out for sizing +glsl code uniform vec4 worldMatrix3x4Array[72]; +glsl code uniform mat4 viewProjectionMatrix; +glsl code uniform vec4 ambient; +glsl blank +glsl code void main() +glsl code { +glsl code vec3 blendPos = vec3(0,0,0); +glsl blank +glsl code for (int bone = 0; bone < 2; ++bone) +glsl code { +glsl comment // perform matrix multiplication manually since no 3x4 matrices +glsl comment // ATI GLSL compiler can't handle indexing an array within an array so calculate the inner index first +glsl code int idx = int(blendIndices[bone]) * 3; +glsl comment // ATI GLSL compiler can't handle unrolling the loop so do it manually +glsl comment // ATI GLSL has better performance when mat4 is used rather than using individual dot product +glsl comment // There is a bug in ATI mat4 constructor (Cat 7.2) when indexed uniform array elements are used as vec4 parameter so manually assign +glsl code mat4 worldMatrix; +glsl code worldMatrix[0] = worldMatrix3x4Array[idx]; +glsl code worldMatrix[1] = worldMatrix3x4Array[idx + 1]; +glsl code worldMatrix[2] = worldMatrix3x4Array[idx + 2]; +glsl code worldMatrix[3] = vec4(0); +glsl comment // now weight this into final +glsl code blendPos += (vertex * worldMatrix).xyz * blendWeights[bone]; +glsl code } +glsl blank +glsl comment // apply view / projection to position +glsl code gl_Position = viewProjectionMatrix * vec4(blendPos, 1); +glsl blank +glsl code gl_FrontSecondaryColor = vec4(0,0,0,0); +glsl code gl_FrontColor = ambient; +glsl code gl_TexCoord[0] = uv0; +glsl code } diff --git a/test/expected_dir/fortranfixed.f b/test/expected_dir/fortranfixed.f new file mode 100644 index 0000000..0dfeb11 --- /dev/null +++ b/test/expected_dir/fortranfixed.f @@ -0,0 +1,12 @@ +fortranfixed comment C Just a comment, whee. +fortranfixed code program foo +fortranfixed blank +fortranfixed comment C Many languages seem to count split lines as multiple lines, +fortranfixed comment C so we should, too. +fortranfixed code write (*,*) 1 +fortranfixed code + + 1 +fortranfixed blank +fortranfixed comment C And I've never seen Fortran code that wraps strings; I'm +fortranfixed comment C not even sure fixed form allows it. +fortranfixed code write (*,*) 'So we don''t bother testing odd string foo.' +fortranfixed code end diff --git a/test/expected_dir/fortranfree.f b/test/expected_dir/fortranfree.f new file mode 100644 index 0000000..cee279b --- /dev/null +++ b/test/expected_dir/fortranfree.f @@ -0,0 +1,18 @@ +fortranfree comment ! -*- F90 -*- +fortranfree comment ! Just a comment, whee. +fortranfree code program foofree +fortranfree code integer:: c +fortranfree blank +fortranfree comment ! Many languages seem to count split lines as multiple lines, +fortranfree comment ! so we should, too. +fortranfree code write (*,*) 1 & +fortranfree code & + 1 +fortranfree blank +fortranfree code C = 1 ! Not a comment. +fortranfree blank +fortranfree comment ! And I've never seen Fortran code that wraps strings; I'm +fortranfree comment ! not even sure fixed form allows it. +fortranfree code write (*,*) 'But we might as well test for it in& +fortranfree code & free format.' +fortranfree blank +fortranfree code end diff --git a/test/expected_dir/frx1.frx b/test/expected_dir/frx1.frx new file mode 100644 index 0000000..c8331c6 --- /dev/null +++ b/test/expected_dir/frx1.frx @@ -0,0 +1,60 @@ +visualbasic code VERSION 5.00 +visualbasic code Object = "{67397AA1-7FB1-11D0-B148-00A0C922E820}#6.0#0"; "MSADODC.OCX" +visualbasic code Object = "{BDC217C8-ED16-11CD-956C-0000C04E4C0A}#1.1#0"; "TABCTL32.OCX" +visualbasic code Object = "{CDE57A40-8B86-11D0-B3C6-00A0C90AEA82}#1.0#0"; "MSDATGRD.OCX" +visualbasic code Object = "{0ECD9B60-23AA-11D0-B351-00A0C9055D8E}#6.0#0"; "MSHFLXGD.OCX" +visualbasic code Object = "{831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0#0"; "MSCOMCTL.OCX" +visualbasic code Begin VB.Form frmMain +visualbasic code BorderStyle = 1 'Fixed Single +visualbasic code ClientHeight = 6555 +visualbasic code ClientLeft = 150 +visualbasic code ClientTop = 435 +visualbasic code ClientWidth = 10620 +visualbasic code LinkTopic = "Form1" +visualbasic code MaxButton = 0 'False +visualbasic code MinButton = 0 'False +visualbasic code ScaleHeight = 6555 +visualbasic code ScaleWidth = 10620 +visualbasic code StartUpPosition = 3 'Windows Default +visualbasic code Attribute VB_Name = "frmMain" +visualbasic code Attribute VB_GlobalNameSpace = False +visualbasic code Attribute VB_Creatable = False +visualbasic code Attribute VB_PredeclaredId = True +visualbasic code Attribute VB_Exposed = False +visualbasic comment '--------------------------------------------------------------------------- +visualbasic comment ' +visualbasic comment ' SOURCE FILE NAME: Demo.frm +visualbasic comment ' +visualbasic comment ' SAMPLE: Visual Basic Demo with user interface for the sample modules +visualbasic comment ' +visualbasic comment ' For more information about samples, refer to the README file. +visualbasic comment ' +visualbasic comment '--------------------------------------------------------------------------- +visualbasic blank +visualbasic code Option Explicit +visualbasic blank +visualbasic code Private con As ADODB.Connection +visualbasic code Private rst As ADODB.Recordset +visualbasic code Private strMsgText As String +visualbasic code Private wShowInstructions As Integer +visualbasic blank +visualbasic comment 'This procedure calls ConnectOLEDB() in the module dbConn to get +visualbasic comment 'a connection object. +visualbasic code Private Sub cmdConnectOLEDB_Click() +visualbasic comment 'define the error handler +visualbasic comment ' On Error GoTo cmdConnectOLEDB_Error +visualbasic blank +visualbasic comment 'connect to database +visualbasic code Set con = ConnectOLEDB() +visualbasic blank +visualbasic comment 'generate a message of success +visualbasic code sbrStatus.Panels(1).Text = "Connect to sample database succeeded!" +visualbasic blank +visualbasic comment 'config status of the buttons +visualbasic code EnableButtons +visualbasic blank +visualbasic comment 'show instructions +visualbasic code If wShowInstructions = vbYes Then +visualbasic code ShowConnectionInstruction +visualbasic code End If +visualbasic code End Sub diff --git a/test/expected_dir/fs1.fs b/test/expected_dir/fs1.fs new file mode 100644 index 0000000..2f632bb --- /dev/null +++ b/test/expected_dir/fs1.fs @@ -0,0 +1,51 @@ +fsharp comment (*************************************************************************** +fsharp comment * +fsharp comment * The Parser is free software: you can redistribute it and/or modify +fsharp comment * it under the terms of the GNU Lesser General Public License as published by +fsharp comment * the Free Software Foundation, either version 3 of the License, or +fsharp comment * (at your option) any later version. +fsharp comment * +fsharp comment ***************************************************************************) +fsharp blank +fsharp code namespace Tags +fsharp blank +fsharp code open System +fsharp code open System.Reflection; +fsharp code open System.Runtime.CompilerServices; +fsharp code open System.Runtime.InteropServices; +fsharp blank +fsharp code module internal Filter = +fsharp blank +fsharp code let FILTER_VARIABLE_NAME = "$filter" +fsharp blank +fsharp code type FilterNode(provider, token, filter: FilterExpression, node_list) = +fsharp code inherit TagNode(provider, token) +fsharp blank +fsharp code override this.walk manager walker = +fsharp code let reader = +fsharp code new NDjango.ASTWalker.Reader (manager, {walker with parent=None; nodes=node_list; context=walker.context}) +fsharp code match filter.ResolveForOutput manager +fsharp code {walker with context=walker.context.add(FILTER_VARIABLE_NAME, (reader.ReadToEnd():>obj))} +fsharp code with +fsharp code | Some w -> w +fsharp code | None -> walker +fsharp blank +fsharp comment /// Filters the contents of the block through variable filters. +fsharp comment /// +fsharp comment /// Filters can also be piped through each other, and they can have +fsharp comment /// arguments -- just like in variable syntax. +fsharp comment /// +fsharp comment /// Sample usage:: +fsharp comment /// +fsharp comment /// {% filter force_escape|lower %} +fsharp comment /// This text will be HTML-escaped, and will appear in lowercase. +fsharp comment /// {% endfilter %} +fsharp code type FilterTag() = +fsharp code interface ITag with +fsharp code member this.Perform token provider tokens = +fsharp code match token.Args with +fsharp code | filter::[] -> +fsharp code let filter_expr = new FilterExpression(provider, Block token, FILTER_VARIABLE_NAME + "|" + filter) +fsharp code let node_list, remaining = (provider :?> IParser).Parse (Some token) tokens ["endfilter"] +fsharp code (new FilterNode(provider, token, filter_expr, node_list) :> INodeImpl), remaining +fsharp code | _ -> raise (SyntaxError ("'filter' tag requires one argument")) diff --git a/test/expected_dir/groovy1.groovy b/test/expected_dir/groovy1.groovy new file mode 100644 index 0000000..438f2b4 --- /dev/null +++ b/test/expected_dir/groovy1.groovy @@ -0,0 +1,9 @@ +groovy comment //hello.groovy +groovy code println "hello, world" +groovy code for (arg in this.args ) { +groovy code println "Argument:" + arg; +groovy code } +groovy comment // this is a comment +groovy comment /* a block comment, commenting out an alternative to above: +groovy comment this.args.each{ arg -> println "hello, ${arg}"} +groovy comment */ diff --git a/test/expected_dir/haml.haml b/test/expected_dir/haml.haml new file mode 100644 index 0000000..8613fde --- /dev/null +++ b/test/expected_dir/haml.haml @@ -0,0 +1,20 @@ +haml code %p +ruby code %p= "stuff" +haml comment / oneliner! +haml code %p +haml comment / +haml comment %p this won't render +haml comment %p it is a comment! +ruby code %p= "stuff" +haml code %p +ruby code - code +ruby code %p= "stuff" +haml code %p +haml blank +haml code \- not script! +haml comment -# silent comment +haml code %p +haml comment -# +haml comment silent +haml comment comment +haml code %br/ diff --git a/test/expected_dir/haskell1.hs b/test/expected_dir/haskell1.hs new file mode 100644 index 0000000..1f503ce --- /dev/null +++ b/test/expected_dir/haskell1.hs @@ -0,0 +1,108 @@ +haskell comment {-| +haskell comment This module contains some functions that are useful in several places in the +haskell comment program and don't belong to one specific other module. +haskell comment -} +haskell code module Gnutella.Misc where +haskell blank +haskell code import Data.ByteString(ByteString) +haskell code import qualified Data.ByteString as BS +haskell code import Data.Bits +haskell code import Data.Word +haskell code import Text.Read +haskell code import Data.Char(isNumber) +haskell code import Data.List(intersperse) +haskell code import Network +haskell code import Network.BSD(getHostByName, HostEntry(..)) +haskell code import Network.Socket(HostAddress(..)) +haskell code import Debug.Trace +haskell blank +haskell comment {-| +haskell comment Maakt van vier bytes een Word32. Gaat ervan uit dat die vier bytes little-endian achter elkaar +haskell comment staan. Als de gegeven string korter is dan 4 bytes, termineert de functie. Als de string langer +haskell comment is, worden alle bytes voorbij de vierde genegeerd. +haskell comment -} +haskell code composeWord32 :: ByteString -> Word32 +haskell code composeWord32 s = shiftL byte4 24 + shiftL byte3 16 + shiftL byte2 8 + byte1 +haskell code where byte1, byte2, byte3, byte4 :: Word32 +haskell code [byte1, byte2, byte3, byte4] = map fromIntegral $ BS.unpack (BS.take 4 s) +haskell blank +haskell comment {-| +haskell comment Turns a Word32 into a tuple of Word8s. The tuple is little-endian: the least +haskell comment significant octet comes first. +haskell comment -} +haskell code word32ToWord8s :: Word32 -> (Word8, Word8, Word8, Word8) +haskell code word32ToWord8s w = (fromIntegral (w .&. 0x000000ff) +haskell code ,fromIntegral (shiftR w 8 .&. 0x000000ff) +haskell code ,fromIntegral (shiftR w 16 .&. 0x000000ff) +haskell code ,fromIntegral (shiftR w 24 .&. 0x000000ff) +haskell code ) +haskell blank +haskell comment {-| +haskell comment Parses a host specification in the "name:12345"-style notation into a hostname +haskell comment and a port number. +haskell blank +haskell comment As a rather special feature, it returns 6346 as the port number when there is +haskell comment no port specified. When there is a port specified, but it is unparseable, it +haskell comment returns Nothing. +haskell comment -} +haskell code parseHostnameWithPort :: String -> IO (Maybe ((Word8, Word8, Word8, Word8) +haskell code ,PortNumber)) +haskell code parseHostnameWithPort str = do maybeHostName <- stringToIP hostNameStr +haskell code return $ (do portNum <- maybePortNum +haskell code hostName <- maybeHostName +haskell code return (hostName, portNum) +haskell code ) +haskell code where hostNameStr = takeWhile (/=':') str +haskell code maybePortNum = case tail (dropWhile (/=':') str) of +haskell code [] -> Just $ 6346 +haskell code s -> case reads s of +haskell code [] -> Nothing +haskell code (x:xs) -> Just $ fromIntegral $ fst x +haskell blank +haskell comment {-| +haskell comment Translates a string, representing an IP address, to a list of bytes. +haskell comment Returns Nothing when the string does not represent an IP address in xxx.xxx.xxx.xxx format +haskell comment -} +haskell code ipStringToBytes :: String -> Maybe (Word8, Word8, Word8, Word8) +haskell comment -- Again, hugs won't let us use regexes where they would be damn convenient +haskell code ipStringToBytes s = +haskell code let ipBytesStrings = splitAtDots s +haskell code in if all (all isNumber) ipBytesStrings +haskell code then let bytesList = map (fst . head . reads) ipBytesStrings +haskell code in Just (bytesList!!0 +haskell code ,bytesList!!1 +haskell code ,bytesList!!2 +haskell code ,bytesList!!3 +haskell code ) +haskell code else Nothing +haskell code where splitAtDots s = foldr (\c (n:nums) -> if c == '.' +haskell code then [] : n : nums +haskell code else (c:n) : nums +haskell code ) [[]] s +haskell blank +haskell comment {-| +haskell comment Translates a list of bytes representing an IP address (big endian) to a string +haskell comment in the xxx.xxx.xxx.xxx format. +haskell comment -} +haskell code ipBytesToString :: (Word8, Word8, Word8, Word8) -> String +haskell code ipBytesToString (b1, b2, b3, b4) = +haskell code concat $ intersperse "." $ map show [b1, b2, b3, b4] +haskell blank +haskell comment {-| +haskell comment Takes a String that's either an IP address or a hostname, and returns you the +haskell comment IP address as a list of 4 bytes (in big-endian byte order). It returns Nothing +haskell comment if there is no parse for the string as IP address and the hostname can't be +haskell comment found. +haskell comment -} +haskell code stringToIP :: String -> IO (Maybe (Word8, Word8, Word8, Word8)) +haskell code stringToIP hostName = case ipStringToBytes hostName of +haskell code Just a -> return (Just a) +haskell code Nothing -> do hostent <- getHostByName hostName +haskell code let ipWord32 = head (hostAddresses hostent) +haskell code ipWord8s = word32ToWord8s ipWord32 +haskell code return (Just ipWord8s) +haskell blank +haskell comment -- used in reading the hostcache +haskell code instance Read PortNumber where +haskell code readsPrec i = map (\(a, b) -> (fromIntegral a, b)) . (readsPrec i :: ReadS Word16) +haskell blank diff --git a/test/expected_dir/haskell2.hs b/test/expected_dir/haskell2.hs new file mode 100644 index 0000000..80b3dfc --- /dev/null +++ b/test/expected_dir/haskell2.hs @@ -0,0 +1,4 @@ +haskell comment {-| +haskell blank +haskell comment -} +haskell blank diff --git a/test/expected_dir/haskell3.hs b/test/expected_dir/haskell3.hs new file mode 100644 index 0000000..8d2c542 --- /dev/null +++ b/test/expected_dir/haskell3.hs @@ -0,0 +1,5 @@ +haskell comment {- +haskell comment {- 3 lines of comments total! -} +haskell blank +haskell comment -} +haskell blank diff --git a/test/expected_dir/haxe1.hx b/test/expected_dir/haxe1.hx new file mode 100644 index 0000000..f4551b2 --- /dev/null +++ b/test/expected_dir/haxe1.hx @@ -0,0 +1,101 @@ +haxe comment /* +haxe comment # ***** BEGIN LICENSE BLOCK ***** +haxe comment Copyright the original author or authors. +haxe comment Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License"); +haxe comment you may not use this file except in compliance with the License. +haxe comment You may obtain a copy of the License at +haxe comment http://www.mozilla.org/MPL/MPL-1.1.html +haxe comment Unless required by applicable law or agreed to in writing, software +haxe comment distributed under the License is distributed on an "AS IS" BASIS, +haxe comment WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +haxe comment See the License for the specific language governing permissions and +haxe comment limitations under the License. +haxe blank +haxe comment # ***** END LICENSE BLOCK ***** +haxe comment */ +haxe blank +haxe code package sandy.parser; +haxe blank +haxe comment /** +haxe comment * The Parser factory class creates instances of parser classes. +haxe comment * The specific parser can be specified in the create method's second parameter. +haxe comment * +haxe comment * @author Thomas Pfeiffer - kiroukou +haxe comment * @author Niel Drummond - haXe port +haxe comment * +haxe comment * +haxe comment * +haxe comment * @example To parse a 3DS file at runtime: +haxe comment * +haxe comment * +haxe comment * var parser:IParser = Parser.create( "/path/to/my/3dsfile.3ds", Parser.max ); +haxe comment * +haxe comment * +haxe comment */ +haxe blank +haxe code class Parser +haxe code { +haxe comment /** +haxe comment * Parameter that is used to specify that the ASE (ASCII Scene Export) +haxe comment * Parser should be used +haxe comment */ +haxe code public static var ASE:String = "ASE"; +haxe comment /** +haxe comment * Parameter that is used to specify that the 3DS (3D Studio) Parser +haxe comment * should be used +haxe comment */ +haxe code public static var MAX_3DS:String = "3DS"; +haxe comment /** +haxe comment * Parameter that is used to specify that the COLLADA (COLLAborative +haxe comment * Design Activity ) Parser should be used +haxe comment */ +haxe code public static var COLLADA:String = "DAE"; +haxe blank +haxe comment /** +haxe comment * The create method chooses which parser to use. This can be done automatically +haxe comment * by looking at the file extension or by passing the parser type String as the +haxe comment * second parameter. +haxe comment * +haxe comment * @example To parse a 3DS file at runtime: +haxe comment * +haxe comment * +haxe comment * var parser:IParser = Parser.create( "/path/to/my/3dsfile.3ds", Parser.MAX ); +haxe comment * +haxe comment * +haxe comment * @param p_sFile Can be either a string pointing to the location of the +haxe comment * file or an instance of an embedded file +haxe comment * @param p_sParserType The parser type string +haxe comment * @param p_nScale The scale factor +haxe comment * @return The parser to be used +haxe comment */ +haxe code public static function create( p_sFile:Dynamic, ?p_sParserType:String, ?p_nScale:Float ):IParser +haxe code { +haxe code if ( p_nScale == null ) p_nScale = 1; +haxe blank +haxe code var l_sExt:String,l_iParser:IParser = null; +haxe comment // -- +haxe code if( Std.is( p_sFile, String ) && p_sParserType == null ) +haxe code { +haxe code l_sExt = (p_sFile.split('.')).reverse()[0]; +haxe code } +haxe code else +haxe code { +haxe code l_sExt = p_sParserType; +haxe code } +haxe comment // -- +haxe code switch( l_sExt.toUpperCase() ) +haxe code { +haxe code case "ASE": +haxe code l_iParser = new ASEParser( p_sFile, p_nScale ); +haxe code case "OBJ": +haxe code case "DAE": +haxe code l_iParser = new ColladaParser( p_sFile, p_nScale ); +haxe code case "3DS": +haxe code l_iParser = new Parser3DS( p_sFile, p_nScale ); +haxe code default: +haxe code } +haxe comment // -- +haxe code return l_iParser; +haxe code } +haxe code } +haxe blank diff --git a/test/expected_dir/html1.html b/test/expected_dir/html1.html new file mode 100644 index 0000000..29032bf --- /dev/null +++ b/test/expected_dir/html1.html @@ -0,0 +1,38 @@ +html code +html code +html code +html code foo +html code +html code +html code +html code +html code

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

+html comment +html code +html code diff --git a/test/expected_dir/idl_pvwave.pro b/test/expected_dir/idl_pvwave.pro new file mode 100644 index 0000000..c3fad2b --- /dev/null +++ b/test/expected_dir/idl_pvwave.pro @@ -0,0 +1,83 @@ +idl_pvwave comment ;+ +idl_pvwave comment ; NAME: +idl_pvwave comment ; SHOWFONT +idl_pvwave comment ; +idl_pvwave comment ; PURPOSE: +idl_pvwave comment ; Uses current graphics device to draw a map of characters +idl_pvwave comment ; available in the font specified in argument +idl_pvwave comment ; +idl_pvwave comment ; CATEGORY: +idl_pvwave comment ; General +idl_pvwave comment ; +idl_pvwave comment ; CALLING SEQUENCE: +idl_pvwave comment ; showfont, num, 'title' ; table of font num entitled 'title' +idl_pvwave comment ; +idl_pvwave comment ; KEYWORD PARAMETERS: +idl_pvwave comment ; /encapsulated ; ignored (just for compatibility) +idl_pvwave comment ; /tt_font ; ignored (just for compatibility) +idl_pvwave comment ; base = 16 ; number of columns in the table +idl_pvwave comment ; beg = 32 ; first character +idl_pvwave comment ; fin = num eq 3 ? 255 : 127 ; last character +idl_pvwave comment ; +idl_pvwave comment ; OUTPUTS: +idl_pvwave comment ; None. +idl_pvwave comment ; +idl_pvwave comment ; OPTIONAL OUTPUTS: +idl_pvwave comment ; None. +idl_pvwave comment ; +idl_pvwave comment ; COMMON BLOCKS: +idl_pvwave comment ; None. +idl_pvwave comment ; +idl_pvwave comment ; SIDE EFFECTS: +idl_pvwave comment ; Draws a font table on the current graphic device. +idl_pvwave comment ; +idl_pvwave comment ; RESTRICTIONS: +idl_pvwave comment ; None. +idl_pvwave comment ; +idl_pvwave comment ; PROCEDURE: +idl_pvwave comment ; +idl_pvwave comment ; EXAMPLE: +idl_pvwave comment ; showfont, 9, 'GDL math symbols' ; show mappings for font 9 +idl_pvwave comment ; +idl_pvwave comment ; MODIFICATION HISTORY: +idl_pvwave comment ; Written by: Sylwester Arabas (2008/12/28) +idl_pvwave comment ;- +idl_pvwave comment ; LICENCE: +idl_pvwave comment ; Copyright (C) 2008, +idl_pvwave comment ; This program is free software; you can redistribute it and/or modify +idl_pvwave comment ; it under the terms of the GNU General Public License as published by +idl_pvwave comment ; the Free Software Foundation; either version 2 of the License, or +idl_pvwave comment ; (at your option) any later version. +idl_pvwave comment ;- +idl_pvwave blank +idl_pvwave code pro showfont, num, name, encapsulated=eps, tt_font=tt, base=base, beg=beg, fin=fin +idl_pvwave blank +idl_pvwave comment ; handling default keyword values +idl_pvwave code if not keyword_set(base) then base = 16 +idl_pvwave code if not keyword_set(beg) then beg = 32 +idl_pvwave code if not keyword_set(fin) then fin = num eq 3 ? 255 : 127 +idl_pvwave code if not keyword_set(name) then name = '' +idl_pvwave blank +idl_pvwave comment ; constructing horizontal and vertical grid lines +idl_pvwave code n_hor = (fin + 1 - beg) / base + 1 +idl_pvwave code h_x = (double(rebin(base * byte(128 * indgen(2 * (n_hor))) / 128, 4 * n_hor, /sample)))[1:4 * n_hor - 1] - .5 +idl_pvwave code h_y = (double(rebin(beg + indgen(n_hor) * base, 4 * n_hor, /sample)))[0:4 * n_hor - 2] - base/2. +idl_pvwave code v_x = base - indgen(4 * base - 1) / 4 - .5 +idl_pvwave code v_y = (double(rebin(byte(128 * indgen(2 * (base))) / 128, 4 * base, /sample)))[1:4 * base - 1] $ +idl_pvwave code * base * ((fin + 1 - beg) / base) + beg - base / 2. +idl_pvwave blank +idl_pvwave comment ; ploting grid and title +idl_pvwave code plot, [h_x, v_x], [h_y, v_y], $ +idl_pvwave code title='Font ' + strtrim(string(num), 2) + ', ' + name, $ +idl_pvwave code xrange=[-1, base], $ +idl_pvwave code yrange=[base * ((fin + 1) / base), beg - base], $ +idl_pvwave code yticks=n_hor, $ +idl_pvwave code xticks=base+1, $ +idl_pvwave code xtitle='char mod ' + strtrim(string(base), 2), $ +idl_pvwave code ytitle=strtrim(string(base), 2) + ' * (char / ' + strtrim(string(base), 2) + ')' +idl_pvwave blank +idl_pvwave comment ; ploting characters +idl_pvwave code for c = beg, fin do $ +idl_pvwave code xyouts, (c mod base), base * (c / base), '!' + strtrim(string(num), 2) + string(byte(c)) +idl_pvwave blank +idl_pvwave code end diff --git a/test/expected_dir/java1.java b/test/expected_dir/java1.java new file mode 100644 index 0000000..77a4c28 --- /dev/null +++ b/test/expected_dir/java1.java @@ -0,0 +1,48 @@ +java comment // Program 11.6: A nicer sine wave +java code import java.applet.Applet; +java code import java.awt.Graphics; +java blank +java code public class SineApplet2 extends Applet { +java blank +java code public void paint(Graphics g) { +java blank +java code int i, j1, j2; +java blank +java code j1 = yvalue(0); +java code for (i = 0; i < size().width; i++) { +java code j2 = yvalue(i+1); +java code g.drawLine(i, j1 ,i+1, j2); +java code j1 = j2; +java code } +java blank +java code } +java blank +java comment // Given the xpoint we're given calculate the Cartesian equivalent +java code private int yvalue(int ivalue) { +java blank +java code double xmin = -10.0; +java code double xmax = 10.0; +java code double ymin = -1.0; +java code double ymax = 1.0; +java code double x, y; +java code int jvalue; +java blank +java code x = (ivalue * (xmax - xmin)/(size().width - 1)) + xmin; +java blank +java comment // Take the sine of that x +java code y = Math.sin(x); +java blank +java comment // Scale y into window coordinates +java code jvalue = (int) ((y - ymin)*(size().height - 1)/ +java code (ymax - ymin)); +java blank +java comment /* Switch jvalue from Cartesian coordinates +java comment to computer graphics coordinates */ +java code jvalue = size().height - jvalue; +java blank +java code return jvalue; +java blank +java code } +java blank +java code } +java blank diff --git a/test/expected_dir/java2.java b/test/expected_dir/java2.java new file mode 100644 index 0000000..bf64cae --- /dev/null +++ b/test/expected_dir/java2.java @@ -0,0 +1,3 @@ +java comment /** +java comment */ +java blank diff --git a/test/expected_dir/js1.js b/test/expected_dir/js1.js new file mode 100644 index 0000000..f7dabcb --- /dev/null +++ b/test/expected_dir/js1.js @@ -0,0 +1,1781 @@ +javascript comment /* Prototype JavaScript framework, version 1.4.0 +javascript comment * (c) 2005 Sam Stephenson +javascript comment * +javascript comment * Prototype is freely distributable under the terms of an MIT-style license. +javascript comment * For details, see the Prototype web site: http://prototype.conio.net/ +javascript comment * +javascript comment /*--------------------------------------------------------------------------*/ +javascript blank +javascript code var Prototype = { +javascript code Version: '1.4.0', +javascript code ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)', +javascript blank +javascript code emptyFunction: function() {}, +javascript code K: function(x) {return x} +javascript code } +javascript blank +javascript code var Class = { +javascript code create: function() { +javascript code return function() { +javascript code this.initialize.apply(this, arguments); +javascript code } +javascript code } +javascript code } +javascript blank +javascript code var Abstract = new Object(); +javascript blank +javascript code Object.extend = function(destination, source) { +javascript code for (property in source) { +javascript code destination[property] = source[property]; +javascript code } +javascript code return destination; +javascript code } +javascript blank +javascript code Object.inspect = function(object) { +javascript code try { +javascript code if (object == undefined) return 'undefined'; +javascript code if (object == null) return 'null'; +javascript code return object.inspect ? object.inspect() : object.toString(); +javascript code } catch (e) { +javascript code if (e instanceof RangeError) return '...'; +javascript code throw e; +javascript code } +javascript code } +javascript blank +javascript code Function.prototype.bind = function() { +javascript code var __method = this, args = $A(arguments), object = args.shift(); +javascript code return function() { +javascript code return __method.apply(object, args.concat($A(arguments))); +javascript code } +javascript code } +javascript blank +javascript code Function.prototype.bindAsEventListener = function(object) { +javascript code var __method = this; +javascript code return function(event) { +javascript code return __method.call(object, event || window.event); +javascript code } +javascript code } +javascript blank +javascript code Object.extend(Number.prototype, { +javascript code toColorPart: function() { +javascript code var digits = this.toString(16); +javascript code if (this < 16) return '0' + digits; +javascript code return digits; +javascript code }, +javascript blank +javascript code succ: function() { +javascript code return this + 1; +javascript code }, +javascript blank +javascript code times: function(iterator) { +javascript code $R(0, this, true).each(iterator); +javascript code return this; +javascript code } +javascript code }); +javascript blank +javascript code var Try = { +javascript code these: function() { +javascript code var returnValue; +javascript blank +javascript code for (var i = 0; i < arguments.length; i++) { +javascript code var lambda = arguments[i]; +javascript code try { +javascript code returnValue = lambda(); +javascript code break; +javascript code } catch (e) {} +javascript code } +javascript blank +javascript code return returnValue; +javascript code } +javascript code } +javascript blank +javascript comment /*--------------------------------------------------------------------------*/ +javascript blank +javascript code var PeriodicalExecuter = Class.create(); +javascript code PeriodicalExecuter.prototype = { +javascript code initialize: function(callback, frequency) { +javascript code this.callback = callback; +javascript code this.frequency = frequency; +javascript code this.currentlyExecuting = false; +javascript blank +javascript code this.registerCallback(); +javascript code }, +javascript blank +javascript code registerCallback: function() { +javascript code setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); +javascript code }, +javascript blank +javascript code onTimerEvent: function() { +javascript code if (!this.currentlyExecuting) { +javascript code try { +javascript code this.currentlyExecuting = true; +javascript code this.callback(); +javascript code } finally { +javascript code this.currentlyExecuting = false; +javascript code } +javascript code } +javascript code } +javascript code } +javascript blank +javascript comment /*--------------------------------------------------------------------------*/ +javascript blank +javascript code function $() { +javascript code var elements = new Array(); +javascript blank +javascript code for (var i = 0; i < arguments.length; i++) { +javascript code var element = arguments[i]; +javascript code if (typeof element == 'string') +javascript code element = document.getElementById(element); +javascript blank +javascript code if (arguments.length == 1) +javascript code return element; +javascript blank +javascript code elements.push(element); +javascript code } +javascript blank +javascript code return elements; +javascript code } +javascript code Object.extend(String.prototype, { +javascript code stripTags: function() { +javascript code return this.replace(/<\/?[^>]+>/gi, ''); +javascript code }, +javascript blank +javascript code stripScripts: function() { +javascript code return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); +javascript code }, +javascript blank +javascript code extractScripts: function() { +javascript code var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); +javascript code var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); +javascript code return (this.match(matchAll) || []).map(function(scriptTag) { +javascript code return (scriptTag.match(matchOne) || ['', ''])[1]; +javascript code }); +javascript code }, +javascript blank +javascript code evalScripts: function() { +javascript code return this.extractScripts().map(eval); +javascript code }, +javascript blank +javascript code escapeHTML: function() { +javascript code var div = document.createElement('div'); +javascript code var text = document.createTextNode(this); +javascript code div.appendChild(text); +javascript code return div.innerHTML; +javascript code }, +javascript blank +javascript code unescapeHTML: function() { +javascript code var div = document.createElement('div'); +javascript code div.innerHTML = this.stripTags(); +javascript code return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; +javascript code }, +javascript blank +javascript code toQueryParams: function() { +javascript code var pairs = this.match(/^\??(.*)$/)[1].split('&'); +javascript code return pairs.inject({}, function(params, pairString) { +javascript code var pair = pairString.split('='); +javascript code params[pair[0]] = pair[1]; +javascript code return params; +javascript code }); +javascript code }, +javascript blank +javascript code toArray: function() { +javascript code return this.split(''); +javascript code }, +javascript blank +javascript code camelize: function() { +javascript code var oStringList = this.split('-'); +javascript code if (oStringList.length == 1) return oStringList[0]; +javascript blank +javascript code var camelizedString = this.indexOf('-') == 0 +javascript code ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) +javascript code : oStringList[0]; +javascript blank +javascript code for (var i = 1, len = oStringList.length; i < len; i++) { +javascript code var s = oStringList[i]; +javascript code camelizedString += s.charAt(0).toUpperCase() + s.substring(1); +javascript code } +javascript blank +javascript code return camelizedString; +javascript code }, +javascript blank +javascript code inspect: function() { +javascript code return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; +javascript code } +javascript code }); +javascript blank +javascript code String.prototype.parseQuery = String.prototype.toQueryParams; +javascript blank +javascript code var $break = new Object(); +javascript code var $continue = new Object(); +javascript blank +javascript code var Enumerable = { +javascript code each: function(iterator) { +javascript code var index = 0; +javascript code try { +javascript code this._each(function(value) { +javascript code try { +javascript code iterator(value, index++); +javascript code } catch (e) { +javascript code if (e != $continue) throw e; +javascript code } +javascript code }); +javascript code } catch (e) { +javascript code if (e != $break) throw e; +javascript code } +javascript code }, +javascript blank +javascript code all: function(iterator) { +javascript code var result = true; +javascript code this.each(function(value, index) { +javascript code result = result && !!(iterator || Prototype.K)(value, index); +javascript code if (!result) throw $break; +javascript code }); +javascript code return result; +javascript code }, +javascript blank +javascript code any: function(iterator) { +javascript code var result = true; +javascript code this.each(function(value, index) { +javascript code if (result = !!(iterator || Prototype.K)(value, index)) +javascript code throw $break; +javascript code }); +javascript code return result; +javascript code }, +javascript blank +javascript code collect: function(iterator) { +javascript code var results = []; +javascript code this.each(function(value, index) { +javascript code results.push(iterator(value, index)); +javascript code }); +javascript code return results; +javascript code }, +javascript blank +javascript code detect: function (iterator) { +javascript code var result; +javascript code this.each(function(value, index) { +javascript code if (iterator(value, index)) { +javascript code result = value; +javascript code throw $break; +javascript code } +javascript code }); +javascript code return result; +javascript code }, +javascript blank +javascript code findAll: function(iterator) { +javascript code var results = []; +javascript code this.each(function(value, index) { +javascript code if (iterator(value, index)) +javascript code results.push(value); +javascript code }); +javascript code return results; +javascript code }, +javascript blank +javascript code grep: function(pattern, iterator) { +javascript code var results = []; +javascript code this.each(function(value, index) { +javascript code var stringValue = value.toString(); +javascript code if (stringValue.match(pattern)) +javascript code results.push((iterator || Prototype.K)(value, index)); +javascript code }) +javascript code return results; +javascript code }, +javascript blank +javascript code include: function(object) { +javascript code var found = false; +javascript code this.each(function(value) { +javascript code if (value == object) { +javascript code found = true; +javascript code throw $break; +javascript code } +javascript code }); +javascript code return found; +javascript code }, +javascript blank +javascript code inject: function(memo, iterator) { +javascript code this.each(function(value, index) { +javascript code memo = iterator(memo, value, index); +javascript code }); +javascript code return memo; +javascript code }, +javascript blank +javascript code invoke: function(method) { +javascript code var args = $A(arguments).slice(1); +javascript code return this.collect(function(value) { +javascript code return value[method].apply(value, args); +javascript code }); +javascript code }, +javascript blank +javascript code max: function(iterator) { +javascript code var result; +javascript code this.each(function(value, index) { +javascript code value = (iterator || Prototype.K)(value, index); +javascript code if (value >= (result || value)) +javascript code result = value; +javascript code }); +javascript code return result; +javascript code }, +javascript blank +javascript code min: function(iterator) { +javascript code var result; +javascript code this.each(function(value, index) { +javascript code value = (iterator || Prototype.K)(value, index); +javascript code if (value <= (result || value)) +javascript code result = value; +javascript code }); +javascript code return result; +javascript code }, +javascript blank +javascript code partition: function(iterator) { +javascript code var trues = [], falses = []; +javascript code this.each(function(value, index) { +javascript code ((iterator || Prototype.K)(value, index) ? +javascript code trues : falses).push(value); +javascript code }); +javascript code return [trues, falses]; +javascript code }, +javascript blank +javascript code pluck: function(property) { +javascript code var results = []; +javascript code this.each(function(value, index) { +javascript code results.push(value[property]); +javascript code }); +javascript code return results; +javascript code }, +javascript blank +javascript code reject: function(iterator) { +javascript code var results = []; +javascript code this.each(function(value, index) { +javascript code if (!iterator(value, index)) +javascript code results.push(value); +javascript code }); +javascript code return results; +javascript code }, +javascript blank +javascript code sortBy: function(iterator) { +javascript code return this.collect(function(value, index) { +javascript code return {value: value, criteria: iterator(value, index)}; +javascript code }).sort(function(left, right) { +javascript code var a = left.criteria, b = right.criteria; +javascript code return a < b ? -1 : a > b ? 1 : 0; +javascript code }).pluck('value'); +javascript code }, +javascript blank +javascript code toArray: function() { +javascript code return this.collect(Prototype.K); +javascript code }, +javascript blank +javascript code zip: function() { +javascript code var iterator = Prototype.K, args = $A(arguments); +javascript code if (typeof args.last() == 'function') +javascript code iterator = args.pop(); +javascript blank +javascript code var collections = [this].concat(args).map($A); +javascript code return this.map(function(value, index) { +javascript code iterator(value = collections.pluck(index)); +javascript code return value; +javascript code }); +javascript code }, +javascript blank +javascript code inspect: function() { +javascript code return '#'; +javascript code } +javascript code } +javascript blank +javascript code Object.extend(Enumerable, { +javascript code map: Enumerable.collect, +javascript code find: Enumerable.detect, +javascript code select: Enumerable.findAll, +javascript code member: Enumerable.include, +javascript code entries: Enumerable.toArray +javascript code }); +javascript code var $A = Array.from = function(iterable) { +javascript code if (!iterable) return []; +javascript code if (iterable.toArray) { +javascript code return iterable.toArray(); +javascript code } else { +javascript code var results = []; +javascript code for (var i = 0; i < iterable.length; i++) +javascript code results.push(iterable[i]); +javascript code return results; +javascript code } +javascript code } +javascript blank +javascript code Object.extend(Array.prototype, Enumerable); +javascript blank +javascript code Array.prototype._reverse = Array.prototype.reverse; +javascript blank +javascript code Object.extend(Array.prototype, { +javascript code _each: function(iterator) { +javascript code for (var i = 0; i < this.length; i++) +javascript code iterator(this[i]); +javascript code }, +javascript blank +javascript code clear: function() { +javascript code this.length = 0; +javascript code return this; +javascript code }, +javascript blank +javascript code first: function() { +javascript code return this[0]; +javascript code }, +javascript blank +javascript code last: function() { +javascript code return this[this.length - 1]; +javascript code }, +javascript blank +javascript code compact: function() { +javascript code return this.select(function(value) { +javascript code return value != undefined || value != null; +javascript code }); +javascript code }, +javascript blank +javascript code flatten: function() { +javascript code return this.inject([], function(array, value) { +javascript code return array.concat(value.constructor == Array ? +javascript code value.flatten() : [value]); +javascript code }); +javascript code }, +javascript blank +javascript code without: function() { +javascript code var values = $A(arguments); +javascript code return this.select(function(value) { +javascript code return !values.include(value); +javascript code }); +javascript code }, +javascript blank +javascript code indexOf: function(object) { +javascript code for (var i = 0; i < this.length; i++) +javascript code if (this[i] == object) return i; +javascript code return -1; +javascript code }, +javascript blank +javascript code reverse: function(inline) { +javascript code return (inline !== false ? this : this.toArray())._reverse(); +javascript code }, +javascript blank +javascript code shift: function() { +javascript code var result = this[0]; +javascript code for (var i = 0; i < this.length - 1; i++) +javascript code this[i] = this[i + 1]; +javascript code this.length--; +javascript code return result; +javascript code }, +javascript blank +javascript code inspect: function() { +javascript code return '[' + this.map(Object.inspect).join(', ') + ']'; +javascript code } +javascript code }); +javascript code var Hash = { +javascript code _each: function(iterator) { +javascript code for (key in this) { +javascript code var value = this[key]; +javascript code if (typeof value == 'function') continue; +javascript blank +javascript code var pair = [key, value]; +javascript code pair.key = key; +javascript code pair.value = value; +javascript code iterator(pair); +javascript code } +javascript code }, +javascript blank +javascript code keys: function() { +javascript code return this.pluck('key'); +javascript code }, +javascript blank +javascript code values: function() { +javascript code return this.pluck('value'); +javascript code }, +javascript blank +javascript code merge: function(hash) { +javascript code return $H(hash).inject($H(this), function(mergedHash, pair) { +javascript code mergedHash[pair.key] = pair.value; +javascript code return mergedHash; +javascript code }); +javascript code }, +javascript blank +javascript code toQueryString: function() { +javascript code return this.map(function(pair) { +javascript code return pair.map(encodeURIComponent).join('='); +javascript code }).join('&'); +javascript code }, +javascript blank +javascript code inspect: function() { +javascript code return '#'; +javascript code } +javascript code } +javascript blank +javascript code function $H(object) { +javascript code var hash = Object.extend({}, object || {}); +javascript code Object.extend(hash, Enumerable); +javascript code Object.extend(hash, Hash); +javascript code return hash; +javascript code } +javascript code ObjectRange = Class.create(); +javascript code Object.extend(ObjectRange.prototype, Enumerable); +javascript code Object.extend(ObjectRange.prototype, { +javascript code initialize: function(start, end, exclusive) { +javascript code this.start = start; +javascript code this.end = end; +javascript code this.exclusive = exclusive; +javascript code }, +javascript blank +javascript code _each: function(iterator) { +javascript code var value = this.start; +javascript code do { +javascript code iterator(value); +javascript code value = value.succ(); +javascript code } while (this.include(value)); +javascript code }, +javascript blank +javascript code include: function(value) { +javascript code if (value < this.start) +javascript code return false; +javascript code if (this.exclusive) +javascript code return value < this.end; +javascript code return value <= this.end; +javascript code } +javascript code }); +javascript blank +javascript code var $R = function(start, end, exclusive) { +javascript code return new ObjectRange(start, end, exclusive); +javascript code } +javascript blank +javascript code var Ajax = { +javascript code getTransport: function() { +javascript code return Try.these( +javascript code function() {return new ActiveXObject('Msxml2.XMLHTTP')}, +javascript code function() {return new ActiveXObject('Microsoft.XMLHTTP')}, +javascript code function() {return new XMLHttpRequest()} +javascript code ) || false; +javascript code }, +javascript blank +javascript code activeRequestCount: 0 +javascript code } +javascript blank +javascript code Ajax.Responders = { +javascript code responders: [], +javascript blank +javascript code _each: function(iterator) { +javascript code this.responders._each(iterator); +javascript code }, +javascript blank +javascript code register: function(responderToAdd) { +javascript code if (!this.include(responderToAdd)) +javascript code this.responders.push(responderToAdd); +javascript code }, +javascript blank +javascript code unregister: function(responderToRemove) { +javascript code this.responders = this.responders.without(responderToRemove); +javascript code }, +javascript blank +javascript code dispatch: function(callback, request, transport, json) { +javascript code this.each(function(responder) { +javascript code if (responder[callback] && typeof responder[callback] == 'function') { +javascript code try { +javascript code responder[callback].apply(responder, [request, transport, json]); +javascript code } catch (e) {} +javascript code } +javascript code }); +javascript code } +javascript code }; +javascript blank +javascript code Object.extend(Ajax.Responders, Enumerable); +javascript blank +javascript code Ajax.Responders.register({ +javascript code onCreate: function() { +javascript code Ajax.activeRequestCount++; +javascript code }, +javascript blank +javascript code onComplete: function() { +javascript code Ajax.activeRequestCount--; +javascript code } +javascript code }); +javascript blank +javascript code Ajax.Base = function() {}; +javascript code Ajax.Base.prototype = { +javascript code setOptions: function(options) { +javascript code this.options = { +javascript code method: 'post', +javascript code asynchronous: true, +javascript code parameters: '' +javascript code } +javascript code Object.extend(this.options, options || {}); +javascript code }, +javascript blank +javascript code responseIsSuccess: function() { +javascript code return this.transport.status == undefined +javascript code || this.transport.status == 0 +javascript code || (this.transport.status >= 200 && this.transport.status < 300); +javascript code }, +javascript blank +javascript code responseIsFailure: function() { +javascript code return !this.responseIsSuccess(); +javascript code } +javascript code } +javascript blank +javascript code Ajax.Request = Class.create(); +javascript code Ajax.Request.Events = +javascript code ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; +javascript blank +javascript code Ajax.Request.prototype = Object.extend(new Ajax.Base(), { +javascript code initialize: function(url, options) { +javascript code this.transport = Ajax.getTransport(); +javascript code this.setOptions(options); +javascript code this.request(url); +javascript code }, +javascript blank +javascript code request: function(url) { +javascript code var parameters = this.options.parameters || ''; +javascript code if (parameters.length > 0) parameters += '&_='; +javascript blank +javascript code try { +javascript code this.url = url; +javascript code if (this.options.method == 'get' && parameters.length > 0) +javascript code this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; +javascript blank +javascript code Ajax.Responders.dispatch('onCreate', this, this.transport); +javascript blank +javascript code this.transport.open(this.options.method, this.url, +javascript code this.options.asynchronous); +javascript blank +javascript code if (this.options.asynchronous) { +javascript code this.transport.onreadystatechange = this.onStateChange.bind(this); +javascript code setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); +javascript code } +javascript blank +javascript code this.setRequestHeaders(); +javascript blank +javascript code var body = this.options.postBody ? this.options.postBody : parameters; +javascript code this.transport.send(this.options.method == 'post' ? body : null); +javascript blank +javascript code } catch (e) { +javascript code this.dispatchException(e); +javascript code } +javascript code }, +javascript blank +javascript code setRequestHeaders: function() { +javascript code var requestHeaders = +javascript code ['X-Requested-With', 'XMLHttpRequest', +javascript code 'X-Prototype-Version', Prototype.Version]; +javascript blank +javascript code if (this.options.method == 'post') { +javascript code requestHeaders.push('Content-type', +javascript code 'application/x-www-form-urlencoded'); +javascript blank +javascript comment /* Force "Connection: close" for Mozilla browsers to work around +javascript comment * a bug where XMLHttpReqeuest sends an incorrect Content-length +javascript comment * header. See Mozilla Bugzilla #246651. +javascript comment */ +javascript code if (this.transport.overrideMimeType) +javascript code requestHeaders.push('Connection', 'close'); +javascript code } +javascript blank +javascript code if (this.options.requestHeaders) +javascript code requestHeaders.push.apply(requestHeaders, this.options.requestHeaders); +javascript blank +javascript code for (var i = 0; i < requestHeaders.length; i += 2) +javascript code this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]); +javascript code }, +javascript blank +javascript code onStateChange: function() { +javascript code var readyState = this.transport.readyState; +javascript code if (readyState != 1) +javascript code this.respondToReadyState(this.transport.readyState); +javascript code }, +javascript blank +javascript code header: function(name) { +javascript code try { +javascript code return this.transport.getResponseHeader(name); +javascript code } catch (e) {} +javascript code }, +javascript blank +javascript code evalJSON: function() { +javascript code try { +javascript code return eval(this.header('X-JSON')); +javascript code } catch (e) {} +javascript code }, +javascript blank +javascript code evalResponse: function() { +javascript code try { +javascript code return eval(this.transport.responseText); +javascript code } catch (e) { +javascript code this.dispatchException(e); +javascript code } +javascript code }, +javascript blank +javascript code respondToReadyState: function(readyState) { +javascript code var event = Ajax.Request.Events[readyState]; +javascript code var transport = this.transport, json = this.evalJSON(); +javascript blank +javascript code if (event == 'Complete') { +javascript code try { +javascript code (this.options['on' + this.transport.status] +javascript code || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] +javascript code || Prototype.emptyFunction)(transport, json); +javascript code } catch (e) { +javascript code this.dispatchException(e); +javascript code } +javascript blank +javascript code if ((this.header('Content-type') || '').match(/^text\/javascript/i)) +javascript code this.evalResponse(); +javascript code } +javascript blank +javascript code try { +javascript code (this.options['on' + event] || Prototype.emptyFunction)(transport, json); +javascript code Ajax.Responders.dispatch('on' + event, this, transport, json); +javascript code } catch (e) { +javascript code this.dispatchException(e); +javascript code } +javascript blank +javascript comment /* Avoid memory leak in MSIE: clean up the oncomplete event handler */ +javascript code if (event == 'Complete') +javascript code this.transport.onreadystatechange = Prototype.emptyFunction; +javascript code }, +javascript blank +javascript code dispatchException: function(exception) { +javascript code (this.options.onException || Prototype.emptyFunction)(this, exception); +javascript code Ajax.Responders.dispatch('onException', this, exception); +javascript code } +javascript code }); +javascript blank +javascript code Ajax.Updater = Class.create(); +javascript blank +javascript code Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { +javascript code initialize: function(container, url, options) { +javascript code this.containers = { +javascript code success: container.success ? $(container.success) : $(container), +javascript code failure: container.failure ? $(container.failure) : +javascript code (container.success ? null : $(container)) +javascript code } +javascript blank +javascript code this.transport = Ajax.getTransport(); +javascript code this.setOptions(options); +javascript blank +javascript code var onComplete = this.options.onComplete || Prototype.emptyFunction; +javascript code this.options.onComplete = (function(transport, object) { +javascript code this.updateContent(); +javascript code onComplete(transport, object); +javascript code }).bind(this); +javascript blank +javascript code this.request(url); +javascript code }, +javascript blank +javascript code updateContent: function() { +javascript code var receiver = this.responseIsSuccess() ? +javascript code this.containers.success : this.containers.failure; +javascript code var response = this.transport.responseText; +javascript blank +javascript code if (!this.options.evalScripts) +javascript code response = response.stripScripts(); +javascript blank +javascript code if (receiver) { +javascript code if (this.options.insertion) { +javascript code new this.options.insertion(receiver, response); +javascript code } else { +javascript code Element.update(receiver, response); +javascript code } +javascript code } +javascript blank +javascript code if (this.responseIsSuccess()) { +javascript code if (this.onComplete) +javascript code setTimeout(this.onComplete.bind(this), 10); +javascript code } +javascript code } +javascript code }); +javascript blank +javascript code Ajax.PeriodicalUpdater = Class.create(); +javascript code Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { +javascript code initialize: function(container, url, options) { +javascript code this.setOptions(options); +javascript code this.onComplete = this.options.onComplete; +javascript blank +javascript code this.frequency = (this.options.frequency || 2); +javascript code this.decay = (this.options.decay || 1); +javascript blank +javascript code this.updater = {}; +javascript code this.container = container; +javascript code this.url = url; +javascript blank +javascript code this.start(); +javascript code }, +javascript blank +javascript code start: function() { +javascript code this.options.onComplete = this.updateComplete.bind(this); +javascript code this.onTimerEvent(); +javascript code }, +javascript blank +javascript code stop: function() { +javascript code this.updater.onComplete = undefined; +javascript code clearTimeout(this.timer); +javascript code (this.onComplete || Prototype.emptyFunction).apply(this, arguments); +javascript code }, +javascript blank +javascript code updateComplete: function(request) { +javascript code if (this.options.decay) { +javascript code this.decay = (request.responseText == this.lastText ? +javascript code this.decay * this.options.decay : 1); +javascript blank +javascript code this.lastText = request.responseText; +javascript code } +javascript code this.timer = setTimeout(this.onTimerEvent.bind(this), +javascript code this.decay * this.frequency * 1000); +javascript code }, +javascript blank +javascript code onTimerEvent: function() { +javascript code this.updater = new Ajax.Updater(this.container, this.url, this.options); +javascript code } +javascript code }); +javascript code document.getElementsByClassName = function(className, parentElement) { +javascript code var children = ($(parentElement) || document.body).getElementsByTagName('*'); +javascript code return $A(children).inject([], function(elements, child) { +javascript code if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) +javascript code elements.push(child); +javascript code return elements; +javascript code }); +javascript code } +javascript blank +javascript comment /*--------------------------------------------------------------------------*/ +javascript blank +javascript code if (!window.Element) { +javascript code var Element = new Object(); +javascript code } +javascript blank +javascript code Object.extend(Element, { +javascript code visible: function(element) { +javascript code return $(element).style.display != 'none'; +javascript code }, +javascript blank +javascript code toggle: function() { +javascript code for (var i = 0; i < arguments.length; i++) { +javascript code var element = $(arguments[i]); +javascript code Element[Element.visible(element) ? 'hide' : 'show'](element); +javascript code } +javascript code }, +javascript blank +javascript code hide: function() { +javascript code for (var i = 0; i < arguments.length; i++) { +javascript code var element = $(arguments[i]); +javascript code element.style.display = 'none'; +javascript code } +javascript code }, +javascript blank +javascript code show: function() { +javascript code for (var i = 0; i < arguments.length; i++) { +javascript code var element = $(arguments[i]); +javascript code element.style.display = ''; +javascript code } +javascript code }, +javascript blank +javascript code remove: function(element) { +javascript code element = $(element); +javascript code element.parentNode.removeChild(element); +javascript code }, +javascript blank +javascript code update: function(element, html) { +javascript code $(element).innerHTML = html.stripScripts(); +javascript code setTimeout(function() {html.evalScripts()}, 10); +javascript code }, +javascript blank +javascript code getHeight: function(element) { +javascript code element = $(element); +javascript code return element.offsetHeight; +javascript code }, +javascript blank +javascript code classNames: function(element) { +javascript code return new Element.ClassNames(element); +javascript code }, +javascript blank +javascript code hasClassName: function(element, className) { +javascript code if (!(element = $(element))) return; +javascript code return Element.classNames(element).include(className); +javascript code }, +javascript blank +javascript code addClassName: function(element, className) { +javascript code if (!(element = $(element))) return; +javascript code return Element.classNames(element).add(className); +javascript code }, +javascript blank +javascript code removeClassName: function(element, className) { +javascript code if (!(element = $(element))) return; +javascript code return Element.classNames(element).remove(className); +javascript code }, +javascript blank +javascript comment // removes whitespace-only text node children +javascript code cleanWhitespace: function(element) { +javascript code element = $(element); +javascript code for (var i = 0; i < element.childNodes.length; i++) { +javascript code var node = element.childNodes[i]; +javascript code if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) +javascript code Element.remove(node); +javascript code } +javascript code }, +javascript blank +javascript code empty: function(element) { +javascript code return $(element).innerHTML.match(/^\s*$/); +javascript code }, +javascript blank +javascript code scrollTo: function(element) { +javascript code element = $(element); +javascript code var x = element.x ? element.x : element.offsetLeft, +javascript code y = element.y ? element.y : element.offsetTop; +javascript code window.scrollTo(x, y); +javascript code }, +javascript blank +javascript code getStyle: function(element, style) { +javascript code element = $(element); +javascript code var value = element.style[style.camelize()]; +javascript code if (!value) { +javascript code if (document.defaultView && document.defaultView.getComputedStyle) { +javascript code var css = document.defaultView.getComputedStyle(element, null); +javascript code value = css ? css.getPropertyValue(style) : null; +javascript code } else if (element.currentStyle) { +javascript code value = element.currentStyle[style.camelize()]; +javascript code } +javascript code } +javascript blank +javascript code if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) +javascript code if (Element.getStyle(element, 'position') == 'static') value = 'auto'; +javascript blank +javascript code return value == 'auto' ? null : value; +javascript code }, +javascript blank +javascript code setStyle: function(element, style) { +javascript code element = $(element); +javascript code for (name in style) +javascript code element.style[name.camelize()] = style[name]; +javascript code }, +javascript blank +javascript code getDimensions: function(element) { +javascript code element = $(element); +javascript code if (Element.getStyle(element, 'display') != 'none') +javascript code return {width: element.offsetWidth, height: element.offsetHeight}; +javascript blank +javascript comment // All *Width and *Height properties give 0 on elements with display none, +javascript comment // so enable the element temporarily +javascript code var els = element.style; +javascript code var originalVisibility = els.visibility; +javascript code var originalPosition = els.position; +javascript code els.visibility = 'hidden'; +javascript code els.position = 'absolute'; +javascript code els.display = ''; +javascript code var originalWidth = element.clientWidth; +javascript code var originalHeight = element.clientHeight; +javascript code els.display = 'none'; +javascript code els.position = originalPosition; +javascript code els.visibility = originalVisibility; +javascript code return {width: originalWidth, height: originalHeight}; +javascript code }, +javascript blank +javascript code makePositioned: function(element) { +javascript code element = $(element); +javascript code var pos = Element.getStyle(element, 'position'); +javascript code if (pos == 'static' || !pos) { +javascript code element._madePositioned = true; +javascript code element.style.position = 'relative'; +javascript comment // Opera returns the offset relative to the positioning context, when an +javascript comment // element is position relative but top and left have not been defined +javascript code if (window.opera) { +javascript code element.style.top = 0; +javascript code element.style.left = 0; +javascript code } +javascript code } +javascript code }, +javascript blank +javascript code undoPositioned: function(element) { +javascript code element = $(element); +javascript code if (element._madePositioned) { +javascript code element._madePositioned = undefined; +javascript code element.style.position = +javascript code element.style.top = +javascript code element.style.left = +javascript code element.style.bottom = +javascript code element.style.right = ''; +javascript code } +javascript code }, +javascript blank +javascript code makeClipping: function(element) { +javascript code element = $(element); +javascript code if (element._overflow) return; +javascript code element._overflow = element.style.overflow; +javascript code if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') +javascript code element.style.overflow = 'hidden'; +javascript code }, +javascript blank +javascript code undoClipping: function(element) { +javascript code element = $(element); +javascript code if (element._overflow) return; +javascript code element.style.overflow = element._overflow; +javascript code element._overflow = undefined; +javascript code } +javascript code }); +javascript blank +javascript code var Toggle = new Object(); +javascript code Toggle.display = Element.toggle; +javascript blank +javascript comment /*--------------------------------------------------------------------------*/ +javascript blank +javascript code Abstract.Insertion = function(adjacency) { +javascript code this.adjacency = adjacency; +javascript code } +javascript blank +javascript code Abstract.Insertion.prototype = { +javascript code initialize: function(element, content) { +javascript code this.element = $(element); +javascript code this.content = content.stripScripts(); +javascript blank +javascript code if (this.adjacency && this.element.insertAdjacentHTML) { +javascript code try { +javascript code this.element.insertAdjacentHTML(this.adjacency, this.content); +javascript code } catch (e) { +javascript code if (this.element.tagName.toLowerCase() == 'tbody') { +javascript code this.insertContent(this.contentFromAnonymousTable()); +javascript code } else { +javascript code throw e; +javascript code } +javascript code } +javascript code } else { +javascript code this.range = this.element.ownerDocument.createRange(); +javascript code if (this.initializeRange) this.initializeRange(); +javascript code this.insertContent([this.range.createContextualFragment(this.content)]); +javascript code } +javascript blank +javascript code setTimeout(function() {content.evalScripts()}, 10); +javascript code }, +javascript blank +javascript code contentFromAnonymousTable: function() { +javascript code var div = document.createElement('div'); +javascript code div.innerHTML = '' + this.content + '
'; +javascript code return $A(div.childNodes[0].childNodes[0].childNodes); +javascript code } +javascript code } +javascript blank +javascript code var Insertion = new Object(); +javascript blank +javascript code Insertion.Before = Class.create(); +javascript code Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { +javascript code initializeRange: function() { +javascript code this.range.setStartBefore(this.element); +javascript code }, +javascript blank +javascript code insertContent: function(fragments) { +javascript code fragments.each((function(fragment) { +javascript code this.element.parentNode.insertBefore(fragment, this.element); +javascript code }).bind(this)); +javascript code } +javascript code }); +javascript blank +javascript code Insertion.Top = Class.create(); +javascript code Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { +javascript code initializeRange: function() { +javascript code this.range.selectNodeContents(this.element); +javascript code this.range.collapse(true); +javascript code }, +javascript blank +javascript code insertContent: function(fragments) { +javascript code fragments.reverse(false).each((function(fragment) { +javascript code this.element.insertBefore(fragment, this.element.firstChild); +javascript code }).bind(this)); +javascript code } +javascript code }); +javascript blank +javascript code Insertion.Bottom = Class.create(); +javascript code Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { +javascript code initializeRange: function() { +javascript code this.range.selectNodeContents(this.element); +javascript code this.range.collapse(this.element); +javascript code }, +javascript blank +javascript code insertContent: function(fragments) { +javascript code fragments.each((function(fragment) { +javascript code this.element.appendChild(fragment); +javascript code }).bind(this)); +javascript code } +javascript code }); +javascript blank +javascript code Insertion.After = Class.create(); +javascript code Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { +javascript code initializeRange: function() { +javascript code this.range.setStartAfter(this.element); +javascript code }, +javascript blank +javascript code insertContent: function(fragments) { +javascript code fragments.each((function(fragment) { +javascript code this.element.parentNode.insertBefore(fragment, +javascript code this.element.nextSibling); +javascript code }).bind(this)); +javascript code } +javascript code }); +javascript blank +javascript comment /*--------------------------------------------------------------------------*/ +javascript blank +javascript code Element.ClassNames = Class.create(); +javascript code Element.ClassNames.prototype = { +javascript code initialize: function(element) { +javascript code this.element = $(element); +javascript code }, +javascript blank +javascript code _each: function(iterator) { +javascript code this.element.className.split(/\s+/).select(function(name) { +javascript code return name.length > 0; +javascript code })._each(iterator); +javascript code }, +javascript blank +javascript code set: function(className) { +javascript code this.element.className = className; +javascript code }, +javascript blank +javascript code add: function(classNameToAdd) { +javascript code if (this.include(classNameToAdd)) return; +javascript code this.set(this.toArray().concat(classNameToAdd).join(' ')); +javascript code }, +javascript blank +javascript code remove: function(classNameToRemove) { +javascript code if (!this.include(classNameToRemove)) return; +javascript code this.set(this.select(function(className) { +javascript code return className != classNameToRemove; +javascript code }).join(' ')); +javascript code }, +javascript blank +javascript code toString: function() { +javascript code return this.toArray().join(' '); +javascript code } +javascript code } +javascript blank +javascript code Object.extend(Element.ClassNames.prototype, Enumerable); +javascript code var Field = { +javascript code clear: function() { +javascript code for (var i = 0; i < arguments.length; i++) +javascript code $(arguments[i]).value = ''; +javascript code }, +javascript blank +javascript code focus: function(element) { +javascript code $(element).focus(); +javascript code }, +javascript blank +javascript code present: function() { +javascript code for (var i = 0; i < arguments.length; i++) +javascript code if ($(arguments[i]).value == '') return false; +javascript code return true; +javascript code }, +javascript blank +javascript code select: function(element) { +javascript code $(element).select(); +javascript code }, +javascript blank +javascript code activate: function(element) { +javascript code element = $(element); +javascript code element.focus(); +javascript code if (element.select) +javascript code element.select(); +javascript code } +javascript code } +javascript blank +javascript comment /*--------------------------------------------------------------------------*/ +javascript blank +javascript code var Form = { +javascript code serialize: function(form) { +javascript code var elements = Form.getElements($(form)); +javascript code var queryComponents = new Array(); +javascript blank +javascript code for (var i = 0; i < elements.length; i++) { +javascript code var queryComponent = Form.Element.serialize(elements[i]); +javascript code if (queryComponent) +javascript code queryComponents.push(queryComponent); +javascript code } +javascript blank +javascript code return queryComponents.join('&'); +javascript code }, +javascript blank +javascript code getElements: function(form) { +javascript code form = $(form); +javascript code var elements = new Array(); +javascript blank +javascript code for (tagName in Form.Element.Serializers) { +javascript code var tagElements = form.getElementsByTagName(tagName); +javascript code for (var j = 0; j < tagElements.length; j++) +javascript code elements.push(tagElements[j]); +javascript code } +javascript code return elements; +javascript code }, +javascript blank +javascript code getInputs: function(form, typeName, name) { +javascript code form = $(form); +javascript code var inputs = form.getElementsByTagName('input'); +javascript blank +javascript code if (!typeName && !name) +javascript code return inputs; +javascript blank +javascript code var matchingInputs = new Array(); +javascript code for (var i = 0; i < inputs.length; i++) { +javascript code var input = inputs[i]; +javascript code if ((typeName && input.type != typeName) || +javascript code (name && input.name != name)) +javascript code continue; +javascript code matchingInputs.push(input); +javascript code } +javascript blank +javascript code return matchingInputs; +javascript code }, +javascript blank +javascript code disable: function(form) { +javascript code var elements = Form.getElements(form); +javascript code for (var i = 0; i < elements.length; i++) { +javascript code var element = elements[i]; +javascript code element.blur(); +javascript code element.disabled = 'true'; +javascript code } +javascript code }, +javascript blank +javascript code enable: function(form) { +javascript code var elements = Form.getElements(form); +javascript code for (var i = 0; i < elements.length; i++) { +javascript code var element = elements[i]; +javascript code element.disabled = ''; +javascript code } +javascript code }, +javascript blank +javascript code findFirstElement: function(form) { +javascript code return Form.getElements(form).find(function(element) { +javascript code return element.type != 'hidden' && !element.disabled && +javascript code ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); +javascript code }); +javascript code }, +javascript blank +javascript code focusFirstElement: function(form) { +javascript code Field.activate(Form.findFirstElement(form)); +javascript code }, +javascript blank +javascript code reset: function(form) { +javascript code $(form).reset(); +javascript code } +javascript code } +javascript blank +javascript code Form.Element = { +javascript code serialize: function(element) { +javascript code element = $(element); +javascript code var method = element.tagName.toLowerCase(); +javascript code var parameter = Form.Element.Serializers[method](element); +javascript blank +javascript code if (parameter) { +javascript code var key = encodeURIComponent(parameter[0]); +javascript code if (key.length == 0) return; +javascript blank +javascript code if (parameter[1].constructor != Array) +javascript code parameter[1] = [parameter[1]]; +javascript blank +javascript code return parameter[1].map(function(value) { +javascript code return key + '=' + encodeURIComponent(value); +javascript code }).join('&'); +javascript code } +javascript code }, +javascript blank +javascript code getValue: function(element) { +javascript code element = $(element); +javascript code var method = element.tagName.toLowerCase(); +javascript code var parameter = Form.Element.Serializers[method](element); +javascript blank +javascript code if (parameter) +javascript code return parameter[1]; +javascript code } +javascript code } +javascript blank +javascript code Form.Element.Serializers = { +javascript code input: function(element) { +javascript code switch (element.type.toLowerCase()) { +javascript code case 'submit': +javascript code case 'hidden': +javascript code case 'password': +javascript code case 'text': +javascript code return Form.Element.Serializers.textarea(element); +javascript code case 'checkbox': +javascript code case 'radio': +javascript code return Form.Element.Serializers.inputSelector(element); +javascript code } +javascript code return false; +javascript code }, +javascript blank +javascript code inputSelector: function(element) { +javascript code if (element.checked) +javascript code return [element.name, element.value]; +javascript code }, +javascript blank +javascript code textarea: function(element) { +javascript code return [element.name, element.value]; +javascript code }, +javascript blank +javascript code select: function(element) { +javascript code return Form.Element.Serializers[element.type == 'select-one' ? +javascript code 'selectOne' : 'selectMany'](element); +javascript code }, +javascript blank +javascript code selectOne: function(element) { +javascript code var value = '', opt, index = element.selectedIndex; +javascript code if (index >= 0) { +javascript code opt = element.options[index]; +javascript code value = opt.value; +javascript code if (!value && !('value' in opt)) +javascript code value = opt.text; +javascript code } +javascript code return [element.name, value]; +javascript code }, +javascript blank +javascript code selectMany: function(element) { +javascript code var value = new Array(); +javascript code for (var i = 0; i < element.length; i++) { +javascript code var opt = element.options[i]; +javascript code if (opt.selected) { +javascript code var optValue = opt.value; +javascript code if (!optValue && !('value' in opt)) +javascript code optValue = opt.text; +javascript code value.push(optValue); +javascript code } +javascript code } +javascript code return [element.name, value]; +javascript code } +javascript code } +javascript blank +javascript comment /*--------------------------------------------------------------------------*/ +javascript blank +javascript code var $F = Form.Element.getValue; +javascript blank +javascript comment /*--------------------------------------------------------------------------*/ +javascript blank +javascript code Abstract.TimedObserver = function() {} +javascript code Abstract.TimedObserver.prototype = { +javascript code initialize: function(element, frequency, callback) { +javascript code this.frequency = frequency; +javascript code this.element = $(element); +javascript code this.callback = callback; +javascript blank +javascript code this.lastValue = this.getValue(); +javascript code this.registerCallback(); +javascript code }, +javascript blank +javascript code registerCallback: function() { +javascript code setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); +javascript code }, +javascript blank +javascript code onTimerEvent: function() { +javascript code var value = this.getValue(); +javascript code if (this.lastValue != value) { +javascript code this.callback(this.element, value); +javascript code this.lastValue = value; +javascript code } +javascript code } +javascript code } +javascript blank +javascript code Form.Element.Observer = Class.create(); +javascript code Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { +javascript code getValue: function() { +javascript code return Form.Element.getValue(this.element); +javascript code } +javascript code }); +javascript blank +javascript code Form.Observer = Class.create(); +javascript code Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { +javascript code getValue: function() { +javascript code return Form.serialize(this.element); +javascript code } +javascript code }); +javascript blank +javascript comment /*--------------------------------------------------------------------------*/ +javascript blank +javascript code Abstract.EventObserver = function() {} +javascript code Abstract.EventObserver.prototype = { +javascript code initialize: function(element, callback) { +javascript code this.element = $(element); +javascript code this.callback = callback; +javascript blank +javascript code this.lastValue = this.getValue(); +javascript code if (this.element.tagName.toLowerCase() == 'form') +javascript code this.registerFormCallbacks(); +javascript code else +javascript code this.registerCallback(this.element); +javascript code }, +javascript blank +javascript code onElementEvent: function() { +javascript code var value = this.getValue(); +javascript code if (this.lastValue != value) { +javascript code this.callback(this.element, value); +javascript code this.lastValue = value; +javascript code } +javascript code }, +javascript blank +javascript code registerFormCallbacks: function() { +javascript code var elements = Form.getElements(this.element); +javascript code for (var i = 0; i < elements.length; i++) +javascript code this.registerCallback(elements[i]); +javascript code }, +javascript blank +javascript code registerCallback: function(element) { +javascript code if (element.type) { +javascript code switch (element.type.toLowerCase()) { +javascript code case 'checkbox': +javascript code case 'radio': +javascript code Event.observe(element, 'click', this.onElementEvent.bind(this)); +javascript code break; +javascript code case 'password': +javascript code case 'text': +javascript code case 'textarea': +javascript code case 'select-one': +javascript code case 'select-multiple': +javascript code Event.observe(element, 'change', this.onElementEvent.bind(this)); +javascript code break; +javascript code } +javascript code } +javascript code } +javascript code } +javascript blank +javascript code Form.Element.EventObserver = Class.create(); +javascript code Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { +javascript code getValue: function() { +javascript code return Form.Element.getValue(this.element); +javascript code } +javascript code }); +javascript blank +javascript code Form.EventObserver = Class.create(); +javascript code Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { +javascript code getValue: function() { +javascript code return Form.serialize(this.element); +javascript code } +javascript code }); +javascript code if (!window.Event) { +javascript code var Event = new Object(); +javascript code } +javascript blank +javascript code Object.extend(Event, { +javascript code KEY_BACKSPACE: 8, +javascript code KEY_TAB: 9, +javascript code KEY_RETURN: 13, +javascript code KEY_ESC: 27, +javascript code KEY_LEFT: 37, +javascript code KEY_UP: 38, +javascript code KEY_RIGHT: 39, +javascript code KEY_DOWN: 40, +javascript code KEY_DELETE: 46, +javascript blank +javascript code element: function(event) { +javascript code return event.target || event.srcElement; +javascript code }, +javascript blank +javascript code isLeftClick: function(event) { +javascript code return (((event.which) && (event.which == 1)) || +javascript code ((event.button) && (event.button == 1))); +javascript code }, +javascript blank +javascript code pointerX: function(event) { +javascript code return event.pageX || (event.clientX + +javascript code (document.documentElement.scrollLeft || document.body.scrollLeft)); +javascript code }, +javascript blank +javascript code pointerY: function(event) { +javascript code return event.pageY || (event.clientY + +javascript code (document.documentElement.scrollTop || document.body.scrollTop)); +javascript code }, +javascript blank +javascript code stop: function(event) { +javascript code if (event.preventDefault) { +javascript code event.preventDefault(); +javascript code event.stopPropagation(); +javascript code } else { +javascript code event.returnValue = false; +javascript code event.cancelBubble = true; +javascript code } +javascript code }, +javascript blank +javascript comment // find the first node with the given tagName, starting from the +javascript comment // node the event was triggered on; traverses the DOM upwards +javascript code findElement: function(event, tagName) { +javascript code var element = Event.element(event); +javascript code while (element.parentNode && (!element.tagName || +javascript code (element.tagName.toUpperCase() != tagName.toUpperCase()))) +javascript code element = element.parentNode; +javascript code return element; +javascript code }, +javascript blank +javascript code observers: false, +javascript blank +javascript code _observeAndCache: function(element, name, observer, useCapture) { +javascript code if (!this.observers) this.observers = []; +javascript code if (element.addEventListener) { +javascript code this.observers.push([element, name, observer, useCapture]); +javascript code element.addEventListener(name, observer, useCapture); +javascript code } else if (element.attachEvent) { +javascript code this.observers.push([element, name, observer, useCapture]); +javascript code element.attachEvent('on' + name, observer); +javascript code } +javascript code }, +javascript blank +javascript code unloadCache: function() { +javascript code if (!Event.observers) return; +javascript code for (var i = 0; i < Event.observers.length; i++) { +javascript code Event.stopObserving.apply(this, Event.observers[i]); +javascript code Event.observers[i][0] = null; +javascript code } +javascript code Event.observers = false; +javascript code }, +javascript blank +javascript code observe: function(element, name, observer, useCapture) { +javascript code var element = $(element); +javascript code useCapture = useCapture || false; +javascript blank +javascript code if (name == 'keypress' && +javascript code (navigator.appVersion.match(/Konqueror|Safari|KHTML/) +javascript code || element.attachEvent)) +javascript code name = 'keydown'; +javascript blank +javascript code this._observeAndCache(element, name, observer, useCapture); +javascript code }, +javascript blank +javascript code stopObserving: function(element, name, observer, useCapture) { +javascript code var element = $(element); +javascript code useCapture = useCapture || false; +javascript blank +javascript code if (name == 'keypress' && +javascript code (navigator.appVersion.match(/Konqueror|Safari|KHTML/) +javascript code || element.detachEvent)) +javascript code name = 'keydown'; +javascript blank +javascript code if (element.removeEventListener) { +javascript code element.removeEventListener(name, observer, useCapture); +javascript code } else if (element.detachEvent) { +javascript code element.detachEvent('on' + name, observer); +javascript code } +javascript code } +javascript code }); +javascript blank +javascript comment /* prevent memory leaks in IE */ +javascript code Event.observe(window, 'unload', Event.unloadCache, false); +javascript code var Position = { +javascript comment // set to true if needed, warning: firefox performance problems +javascript comment // NOT neeeded for page scrolling, only if draggable contained in +javascript comment // scrollable elements +javascript code includeScrollOffsets: false, +javascript blank +javascript comment // must be called before calling withinIncludingScrolloffset, every time the +javascript comment // page is scrolled +javascript code prepare: function() { +javascript code this.deltaX = window.pageXOffset +javascript code || document.documentElement.scrollLeft +javascript code || document.body.scrollLeft +javascript code || 0; +javascript code this.deltaY = window.pageYOffset +javascript code || document.documentElement.scrollTop +javascript code || document.body.scrollTop +javascript code || 0; +javascript code }, +javascript blank +javascript code realOffset: function(element) { +javascript code var valueT = 0, valueL = 0; +javascript code do { +javascript code valueT += element.scrollTop || 0; +javascript code valueL += element.scrollLeft || 0; +javascript code element = element.parentNode; +javascript code } while (element); +javascript code return [valueL, valueT]; +javascript code }, +javascript blank +javascript code cumulativeOffset: function(element) { +javascript code var valueT = 0, valueL = 0; +javascript code do { +javascript code valueT += element.offsetTop || 0; +javascript code valueL += element.offsetLeft || 0; +javascript code element = element.offsetParent; +javascript code } while (element); +javascript code return [valueL, valueT]; +javascript code }, +javascript blank +javascript code positionedOffset: function(element) { +javascript code var valueT = 0, valueL = 0; +javascript code do { +javascript code valueT += element.offsetTop || 0; +javascript code valueL += element.offsetLeft || 0; +javascript code element = element.offsetParent; +javascript code if (element) { +javascript code p = Element.getStyle(element, 'position'); +javascript code if (p == 'relative' || p == 'absolute') break; +javascript code } +javascript code } while (element); +javascript code return [valueL, valueT]; +javascript code }, +javascript blank +javascript code offsetParent: function(element) { +javascript code if (element.offsetParent) return element.offsetParent; +javascript code if (element == document.body) return element; +javascript blank +javascript code while ((element = element.parentNode) && element != document.body) +javascript code if (Element.getStyle(element, 'position') != 'static') +javascript code return element; +javascript blank +javascript code return document.body; +javascript code }, +javascript blank +javascript comment // caches x/y coordinate pair to use with overlap +javascript code within: function(element, x, y) { +javascript code if (this.includeScrollOffsets) +javascript code return this.withinIncludingScrolloffsets(element, x, y); +javascript code this.xcomp = x; +javascript code this.ycomp = y; +javascript code this.offset = this.cumulativeOffset(element); +javascript blank +javascript code return (y >= this.offset[1] && +javascript code y < this.offset[1] + element.offsetHeight && +javascript code x >= this.offset[0] && +javascript code x < this.offset[0] + element.offsetWidth); +javascript code }, +javascript blank +javascript code withinIncludingScrolloffsets: function(element, x, y) { +javascript code var offsetcache = this.realOffset(element); +javascript blank +javascript code this.xcomp = x + offsetcache[0] - this.deltaX; +javascript code this.ycomp = y + offsetcache[1] - this.deltaY; +javascript code this.offset = this.cumulativeOffset(element); +javascript blank +javascript code return (this.ycomp >= this.offset[1] && +javascript code this.ycomp < this.offset[1] + element.offsetHeight && +javascript code this.xcomp >= this.offset[0] && +javascript code this.xcomp < this.offset[0] + element.offsetWidth); +javascript code }, +javascript blank +javascript comment // within must be called directly before +javascript code overlap: function(mode, element) { +javascript code if (!mode) return 0; +javascript code if (mode == 'vertical') +javascript code return ((this.offset[1] + element.offsetHeight) - this.ycomp) / +javascript code element.offsetHeight; +javascript code if (mode == 'horizontal') +javascript code return ((this.offset[0] + element.offsetWidth) - this.xcomp) / +javascript code element.offsetWidth; +javascript code }, +javascript blank +javascript code clone: function(source, target) { +javascript code source = $(source); +javascript code target = $(target); +javascript code target.style.position = 'absolute'; +javascript code var offsets = this.cumulativeOffset(source); +javascript code target.style.top = offsets[1] + 'px'; +javascript code target.style.left = offsets[0] + 'px'; +javascript code target.style.width = source.offsetWidth + 'px'; +javascript code target.style.height = source.offsetHeight + 'px'; +javascript code }, +javascript blank +javascript code page: function(forElement) { +javascript code var valueT = 0, valueL = 0; +javascript blank +javascript code var element = forElement; +javascript code do { +javascript code valueT += element.offsetTop || 0; +javascript code valueL += element.offsetLeft || 0; +javascript blank +javascript comment // Safari fix +javascript code if (element.offsetParent==document.body) +javascript code if (Element.getStyle(element,'position')=='absolute') break; +javascript blank +javascript code } while (element = element.offsetParent); +javascript blank +javascript code element = forElement; +javascript code do { +javascript code valueT -= element.scrollTop || 0; +javascript code valueL -= element.scrollLeft || 0; +javascript code } while (element = element.parentNode); +javascript blank +javascript code return [valueL, valueT]; +javascript code }, +javascript blank +javascript code clone: function(source, target) { +javascript code var options = Object.extend({ +javascript code setLeft: true, +javascript code setTop: true, +javascript code setWidth: true, +javascript code setHeight: true, +javascript code offsetTop: 0, +javascript code offsetLeft: 0 +javascript code }, arguments[2] || {}) +javascript blank +javascript comment // find page position of source +javascript code source = $(source); +javascript code var p = Position.page(source); +javascript blank +javascript comment // find coordinate system to use +javascript code target = $(target); +javascript code var delta = [0, 0]; +javascript code var parent = null; +javascript comment // delta [0,0] will do fine with position: fixed elements, +javascript comment // position:absolute needs offsetParent deltas +javascript code if (Element.getStyle(target,'position') == 'absolute') { +javascript code parent = Position.offsetParent(target); +javascript code delta = Position.page(parent); +javascript code } +javascript blank +javascript comment // correct by body offsets (fixes Safari) +javascript code if (parent == document.body) { +javascript code delta[0] -= document.body.offsetLeft; +javascript code delta[1] -= document.body.offsetTop; +javascript code } +javascript blank +javascript comment // set position +javascript code if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; +javascript code if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; +javascript code if(options.setWidth) target.style.width = source.offsetWidth + 'px'; +javascript code if(options.setHeight) target.style.height = source.offsetHeight + 'px'; +javascript code }, +javascript blank +javascript code absolutize: function(element) { +javascript code element = $(element); +javascript code if (element.style.position == 'absolute') return; +javascript code Position.prepare(); +javascript blank +javascript code var offsets = Position.positionedOffset(element); +javascript code var top = offsets[1]; +javascript code var left = offsets[0]; +javascript code var width = element.clientWidth; +javascript code var height = element.clientHeight; +javascript blank +javascript code element._originalLeft = left - parseFloat(element.style.left || 0); +javascript code element._originalTop = top - parseFloat(element.style.top || 0); +javascript code element._originalWidth = element.style.width; +javascript code element._originalHeight = element.style.height; +javascript blank +javascript code element.style.position = 'absolute'; +javascript code element.style.top = top + 'px';; +javascript code element.style.left = left + 'px';; +javascript code element.style.width = width + 'px';; +javascript code element.style.height = height + 'px';; +javascript code }, +javascript blank +javascript code relativize: function(element) { +javascript code element = $(element); +javascript code if (element.style.position == 'relative') return; +javascript code Position.prepare(); +javascript blank +javascript code element.style.position = 'relative'; +javascript code var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); +javascript code var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); +javascript blank +javascript code element.style.top = top + 'px'; +javascript code element.style.left = left + 'px'; +javascript code element.style.height = element._originalHeight; +javascript code element.style.width = element._originalWidth; +javascript code } +javascript code } +javascript blank +javascript comment // Safari returns margins on body which is incorrect if the child is absolutely +javascript comment // positioned. For performance reasons, redefine Position.cumulativeOffset for +javascript comment // KHTML/WebKit only. +javascript code if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { +javascript code Position.cumulativeOffset = function(element) { +javascript code var valueT = 0, valueL = 0; +javascript code do { +javascript code valueT += element.offsetTop || 0; +javascript code valueL += element.offsetLeft || 0; +javascript code if (element.offsetParent == document.body) +javascript code if (Element.getStyle(element, 'position') == 'absolute') break; +javascript blank +javascript code element = element.offsetParent; +javascript code } while (element); +javascript blank +javascript code return [valueL, valueT]; +javascript code } +javascript code } diff --git a/test/expected_dir/js2.js b/test/expected_dir/js2.js new file mode 100644 index 0000000..48019a4 --- /dev/null +++ b/test/expected_dir/js2.js @@ -0,0 +1,13 @@ +javascript code diff --git a/test/expected_dir/js3.js b/test/expected_dir/js3.js new file mode 100644 index 0000000..ed52700 --- /dev/null +++ b/test/expected_dir/js3.js @@ -0,0 +1,2 @@ +javascript code return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; +javascript comment // comment diff --git a/test/expected_dir/jsp1.jsp b/test/expected_dir/jsp1.jsp new file mode 100644 index 0000000..6ba6c49 --- /dev/null +++ b/test/expected_dir/jsp1.jsp @@ -0,0 +1,14 @@ +html code +html code +html code JSP page +html code +html code +java code <%@ page language="java" %> +java code <% out.println("Hello World"); %> +java comment <% // comment +java comment /* +java comment * more comment +java comment */ +html code %> +html code +html code diff --git a/test/expected_dir/limbo.b b/test/expected_dir/limbo.b new file mode 100644 index 0000000..c76e9ea --- /dev/null +++ b/test/expected_dir/limbo.b @@ -0,0 +1,65 @@ +limbo code implement HgReadrevlog; +limbo blank +limbo code include "sys.m"; +limbo code sys: Sys; +limbo code sprint: import sys; +limbo code include "draw.m"; +limbo code include "arg.m"; +limbo code include "string.m"; +limbo code str: String; +limbo code include "mercurial.m"; +limbo code mercurial: Mercurial; +limbo code Revlog, Repo, Entry, Nodeid, Change: import mercurial; +limbo blank +limbo code dflag: int; +limbo blank +limbo code HgReadrevlog: module { +limbo code init: fn(nil: ref Draw->Context, args: list of string); +limbo code }; +limbo blank +limbo code init(nil: ref Draw->Context, args: list of string) +limbo code { +limbo code sys = load Sys Sys->PATH; +limbo code arg := load Arg Arg->PATH; +limbo code str = load String String->PATH; +limbo code mercurial = load Mercurial Mercurial->PATH; +limbo code mercurial->init(); +limbo blank +limbo code arg->init(args); +limbo code arg->setusage(arg->progname()+" [-d] path"); +limbo code while((c := arg->opt()) != 0) +limbo code case c { +limbo code 'd' => dflag++; +limbo code if(dflag > 1) +limbo code mercurial->debug++; +limbo code * => arg->usage(); +limbo code } +limbo code args = arg->argv(); +limbo code if(len args != 1) +limbo code arg->usage(); +limbo code path := hd args; +limbo blank +limbo code (rl, err) := Revlog.open(path); +limbo code if(err != nil) +limbo code fail(err); +limbo blank +limbo code last: int; +limbo code (last, err) = rl.lastrev(); +limbo code if(err != nil) +limbo code fail(err); +limbo blank +limbo code e: ref Entry; +limbo code for(i := 0; i <= last; i++) { +limbo code (e, err) = rl.findrev(i); +limbo code if(err != nil) +limbo code fail(err); +limbo comment #sys->print("entry %d:\n", i); +limbo code sys->print("%s\n", e.text()); +limbo code } +limbo code } +limbo blank +limbo code fail(s: string) +limbo code { +limbo code sys->fprint(sys->fildes(2), "%s\n", s); +limbo code raise "fail:"+s; +limbo code } diff --git a/test/expected_dir/limbo.m b/test/expected_dir/limbo.m new file mode 100644 index 0000000..ae490fa --- /dev/null +++ b/test/expected_dir/limbo.m @@ -0,0 +1,8 @@ +limbo code Htmlent: module { +limbo code PATH: con "/dis/lib/htmlent.dis"; +limbo code entities: array of (string, int); +limbo blank +limbo code init: fn(); +limbo code lookup: fn(name: string): int; +limbo code conv: fn(s: string): string; +limbo code }; diff --git a/test/expected_dir/lsp1.lsp b/test/expected_dir/lsp1.lsp new file mode 100644 index 0000000..7bfd739 --- /dev/null +++ b/test/expected_dir/lsp1.lsp @@ -0,0 +1,135 @@ +lisp comment ;;; CrapsSim.lsp +lisp blank +lisp comment """ +lisp comment The main purpose of this program was to implement a Craps game, using a language that we have just +lisp comment learned. Also, it was written in a functional style with almost no reliance on the assignment +lisp comment operation. Only one local variable called THROW was used. +lisp comment """ +lisp blank +lisp blank +lisp comment ;;; ====================================================================================================== ;;; +lisp comment ;;; ======================================= CRAPS SIMULATION ============================================= ;;; +lisp comment ;;; ====================================================================================================== ;;; +lisp blank +lisp blank +lisp comment ;;; ** This function takes no parameters as input and returns a random number between 1 and 6. ** +lisp blank +lisp code (DEFUN THROW-DIE () +lisp code (+ (RANDOM 6) 1) ;;; get a random number between 0 and 5 and then add 1 +lisp code ) +lisp blank +lisp comment ;;; ====================================================================================================== ;;; +lisp blank +lisp comment ;;; ** This function takes no parameters as input and returns a LIST with two numbers between 1 and 6. ** +lisp blank +lisp blank +lisp code (DEFUN THROW-DICE () +lisp blank +lisp code (LIST (THROW-DIE) (THROW-DIE)) ;;; create a list with two random numbers +lisp blank +lisp code ) +lisp blank +lisp comment ;;; ====================================================================================================== ;;; +lisp blank +lisp comment ;;; ** This function takes two numbers as parameters for input and returns T or Nil. T is returned if both +lisp comment ;;; numbers are equal to 6. Nil is returned otherwise. ** +lisp blank +lisp code (DEFUN BOXCARS-P (A B) +lisp code (AND (EQUAL '6 A) +lisp code (EQUAL '6 B) +lisp code ) +lisp blank +lisp code ) +lisp blank +lisp comment ;;; ====================================================================================================== ;;; +lisp blank +lisp comment ;;; ** This function takes two numbers as parameters for input and returns T or Nil. T is returned if both +lisp comment ;;; numbers are equal to 1. Nil is returned otherwise. ** +lisp blank +lisp code (DEFUN SNAKE-EYES-P (A B) +lisp code (AND (EQUAL '1 A) +lisp code (EQUAL '1 B) +lisp code ) +lisp blank +lisp code ) +lisp blank +lisp comment ;;; ====================================================================================================== ;;; +lisp blank +lisp comment ;;; ** This function takes two numbers as parameters for input and returns T or Nil. T is returned if the +lisp comment ;;; sum of both numbers is equal to a 7 or 11. Nil is returned otherwise. ** +lisp blank +lisp code (DEFUN INSTANT-WIN-P (A B) +lisp code (OR (EQUAL '7 (+ A B)) +lisp code (EQUAL '11 (+ A B)) +lisp code ) +lisp blank +lisp code ) +lisp blank +lisp comment ;;; ====================================================================================================== ;;; +lisp blank +lisp comment ;;; ** This function takes two numbers as parameters for input and returns T or Nil. T is returned if the +lisp comment ;;; sum of both numbers is equal to a 2, 3 or 12. Nil is returned otherwise. ** +lisp blank +lisp code (DEFUN INSTANT-LOSS-P (A B) +lisp code (OR (EQUAL '2 (+ A B)) +lisp code (EQUAL '3 (+ A B)) +lisp code (EQUAL '12 (+ A B)) +lisp code ) +lisp blank +lisp code ) +lisp blank +lisp comment ;;; ====================================================================================================== ;;; +lisp blank +lisp comment ;;; ** This function takes two numbers as parameters for input and returns a string. If function BOXCARS_P +lisp comment ;;; returns T, then the returned string equals BOXCARS. If function SNAKE_EYES_P returns T, then the +lisp comment ;;; returned string equals SNAKE_EYES. The string contains Nil otherwise. ** +lisp blank +lisp code (DEFUN SAY-THROW (A B) +lisp code (COND ((BOXCARS-P A B) 'BOXCARS) ;;; make use of function BOXCARS_P +lisp code ((SNAKE-EYES-P A B) 'SNAKE-EYES) ;;; make use of function SNAKE_EYES_P +lisp blank +lisp code ) +lisp code ) +lisp blank +lisp comment ;;; ====================================================================================================== ;;; +lisp blank +lisp comment ;;; ** This is the main function used to simulate the game of craps. Variable THROW contains a LIST of two +lisp comment ;;; numbers between 1 and 6. The numbers located in THROW, are used as parameters for the other functions. +lisp comment ;;; The several pieces used for output are listed together and then the LIST is returned from this +lisp comment ;;; function. +lisp blank +lisp blank +lisp code (DEFUN CRAPS () +lisp code (LET THROW (THROW-DICE)) ;;; get initial roll of the dice +lisp blank +lisp comment ;;; if roll is a win, then LIST the appropriate output +lisp blank +lisp code (COND ((INSTANT-WIN-P (FIRST THROW) (SECOND THROW)) +lisp code (LIST 'THROW (FIRST THROW) 'AND (SECOND THROW) '-- (+ (FIRST THROW) (SECOND THROW)) '-- 'YOU 'WIN)) +lisp blank +lisp comment ;;; if roll is a loss, then check for BOXCARS or SNAKE-EYES +lisp blank +lisp code ((INSTANT-LOSS-P (FIRST THROW) (SECOND THROW)) +lisp blank +lisp code (IF (EQUAL 'NIL (SAY-THROW (FIRST THROW) (SECOND THROW))) ;;; if Nil then LIST appropriate output +lisp blank +lisp code (LIST 'THROW (FIRST THROW) 'AND (SECOND THROW) '-- (+ (FIRST THROW) (SECOND THROW)) '-- 'YOU 'LOSE) +lisp blank +lisp comment ;;; else include the BOXCARS or SNAKE-EYES string in the output +lisp blank +lisp code (LIST 'THROW (FIRST THROW) 'AND (SECOND THROW) '-- (SAY-THROW (FIRST THROW) (SECOND THROW)) +lisp code '-- 'YOU 'LOSE))) +lisp blank +lisp comment ;;; if roll is not instant win or loss then output sum of dice +lisp blank +lisp code (T (LIST 'THROW (FIRST THROW) 'AND (SECOND THROW) '-- 'YOUR 'POINT 'IS (+ (FIRST THROW) +lisp code (SECOND THROW)))) +lisp code ) ;;; end COND +lisp blank +lisp code ) ;;; end LET +lisp blank +lisp blank +lisp code ) +lisp blank +lisp blank +lisp comment ;;; ======================================== END OF PROGRAM CRAPS ======================================== ;;; diff --git a/test/expected_dir/lua1.lua b/test/expected_dir/lua1.lua new file mode 100644 index 0000000..92ba5d7 --- /dev/null +++ b/test/expected_dir/lua1.lua @@ -0,0 +1,121 @@ +lua comment -- random code from http://lua-users.org/wiki/TextJustification +lua comment -- easy queue implementation ------------------------------------------ +lua blank +lua code function q_create() +lua code local q = {} +lua code q.first = 0 +lua code q.last = 0 +lua code return q +lua code end +lua blank +lua code function q_insert(q, s) +lua code q[q.last] = s +lua code q.last = q.last + 1 +lua code end +lua blank +lua code function q_empty(q) +lua code return q.first >= q.last +lua code end +lua blank +lua code function q_remove(q) +lua code if q_empty(q) then +lua code return nil +lua code end +lua code local s = q[q.first] +lua code q[q.first] = nil +lua code q.first = q.first+1 +lua code return s +lua code end +lua blank +lua code function q_card(q) +lua code return q.last - q.first +lua code end +lua blank +lua code function q_length(q, f) +lua code local l, i = 0, q.first +lua code while i < q.last do +lua code l = l + strlen(q[i]) +lua code i = i + 1 +lua code end +lua code return l +lua code end +lua blank +lua comment -- line creation routines ------------------------------------------ +lua blank +lua comment -- justifies one line to fit into MAX columns +lua code function justify(q) +lua code local blanks = MAX - q_length(q) +lua code local skips = q_card(q) - 1 +lua code local line = q_remove(q) +lua code local quotient = floor(blanks/skips) +lua code local reminder = blanks/skips - quotient +lua code local error = 0 +lua code while skips > 0 do +lua code error = error + reminder +lua code if error >= 0.5 then +lua code error = error - 1 +lua code line = line .. strrep(" ", quotient+1) +lua code else +lua code line = line .. strrep(" ", quotient) +lua code end +lua code line = line .. q_remove(q) +lua code skips = skips - 1 +lua code end +lua code return line or "" +lua code end +lua blank +lua comment -- join all words with one space between them +lua code function catenate(q) +lua code local line = q_remove(q) +lua code while not q_empty(q) do +lua code line = line .. " " .. q_remove(q) +lua code end +lua code return line or "" +lua code end +lua blank +lua comment -- main program ----------------------------------------------------- +lua code DEFMAX = 72 +lua comment -- tries to get MAX from command-line +lua code if not arg or getn(arg) < 1 then +lua code MAX = DEFMAX +lua code else +lua code MAX = tonumber(arg[1]) +lua code if not MAX or MAX < 0 then +lua code MAX = DEFMAX +lua code end +lua code end +lua blank +lua comment -- collects all text from stdin +lua code text = q_create() +lua code line = read() +lua code while line do +lua code _, n = gsub(line, "(%S+)", function (s) q_insert(%text, s) end) +lua code if n == 0 then +lua code q_insert(text, "\n") +lua code end +lua code line = read() +lua code end +lua blank +lua comment -- justify paragraphs +lua code line = q_create() +lua code word = q_remove(text) +lua code size = 0 +lua code while word do +lua code if word == "\n" then +lua code if not q_empty(line) then +lua code write(catenate(line), "\n\n") +lua code else +lua code write("\n") +lua code end +lua code size = 0 +lua code elseif size + strlen(word) > MAX then +lua code write(justify(line), "\n") +lua code size = 0 +lua code end +lua code if word ~= "\n" then +lua code q_insert(line, word) +lua code size = size + strlen(word) + 1 +lua code end +lua code word = q_remove(text) +lua code end +lua code write(catenate(line), "\n") diff --git a/test/expected_dir/matlab1.m b/test/expected_dir/matlab1.m new file mode 100644 index 0000000..9c20b77 --- /dev/null +++ b/test/expected_dir/matlab1.m @@ -0,0 +1,56 @@ +matlab comment % PROGRAM theta_logistic.m +matlab comment % Calculates by simulation the probability that a population +matlab comment % following the theta logistic model and starting at Nc will fall +matlab comment % below the quasi-extinction threshold Nx at or before time tmax +matlab blank +matlab comment % SIMULATION PARAMETERS +matlab comment % for butterflies (Euphydryas editha bayensis) at Jasper Ridge (population C) +matlab blank +matlab code r=0.3458; % intrinsic rate of increase--Butterflies at Jasper Ridge +matlab code K=846.017; % carrying capacity +matlab code theta=1; % nonlinearity in density dependence +matlab code sigma2=1.1151; % environmental variance +matlab code Nc=94; % starting population size +matlab code Nx=20; % quasi-extinction threshold +matlab code tmax=20; % time horizon +matlab code NumReps=50000; % number of replicate population trajectories +matlab blank +matlab comment % SIMULATION CODE +matlab blank +matlab code sigma=sqrt(sigma2); +matlab code randn('state',sum(100*clock)); % seed the random number generator +matlab blank +matlab code N=Nc*ones(1,NumReps); % all NumRep populations start at Nc +matlab code NumExtant=NumReps; % all populations are initially extant +matlab code Extant=[NumExtant]; % vector for number of extant pops. vs. time +matlab blank +matlab code for t=1:tmax, % For each future time, +matlab code N=N.*exp( r*( 1-(N/K).^theta )... % the theta logistic model +matlab code + sigma*randn(1,NumExtant) ); % with random environmental effects. +matlab code for i=NumExtant:-1:1, % Then, looping over all extant populations, +matlab code if N(i)<=Nx, % if at or below quasi-extinction threshold, +matlab code N(i)=[]; % delete the population. +matlab code end; +matlab code end; +matlab code NumExtant=length(N); % Count remaining extant populations +matlab code Extant=[Extant NumExtant]; % and store the result. +matlab code end; +matlab blank +matlab comment % OUTPUT CODE +matlab comment % ComputeS quasi-extinction probability as the fraction of replicate +matlab comment % populations that have hit the threshold by each future time, +matlab comment % and plotS quasi-extinction probability vs. time +matlab blank +matlab code ProbExtinct=(NumReps-Extant)/NumReps; +matlab code plot([0:tmax],ProbExtinct) +matlab code xlabel('Years into the future'); +matlab code ylabel('Cumulative probability of quasi-extinction'); +matlab code axis([0 tmax 0 1]); +matlab blank +matlab comment % Integrate solution exactly % +matlab comment % Options=[]; +matlab comment % [T,true] = ode45(@logistic,[0,20],Nc,Options,r,K,theta); +matlab comment % subplot(1,2,2) +matlab comment % plot([1:tmax],P,'r.-',T,true,'g.-') +matlab blank +matlab comment ... This is a seriously old-school comment. \ No newline at end of file diff --git a/test/expected_dir/metafont.mf b/test/expected_dir/metafont.mf new file mode 100644 index 0000000..a367226 --- /dev/null +++ b/test/expected_dir/metafont.mf @@ -0,0 +1,22 @@ +metafont comment % The (not really) first 20 or so lines from the plain METAFONT base +metafont blank +metafont comment % Unlimited copying and redistribution of this file are permitted as long +metafont comment % as this file is not modified. Modifications are permitted, but only if +metafont comment % the resulting file is not named plain.mf. +metafont blank +metafont code string base_name, base_version; base_name="plain"; base_version="2.71"; +metafont blank +metafont code message "Preloading the plain base, version "&base_version&": preliminaries,"; +metafont blank +metafont code delimiters (); % this makes parentheses behave like parentheses +metafont code def upto = step 1 until enddef; % syntactic sugar +metafont code def downto = step -1 until enddef; +metafont code def exitunless expr c = exitif not c enddef; +metafont code let relax = \; % ignore the word `relax', as in TeX +metafont code let \\ = \; % double relaxation is like single +metafont code def ]] = ] ] enddef; % right brackets should be loners +metafont code def -- = {curl 1}..{curl 1} enddef; +metafont code def --- = .. tension infinity .. enddef; +metafont code def ... = .. tension atleast 1 .. enddef; +metafont blank +metafont code def gobble primary g = enddef; def killtext text t = enddef; diff --git a/test/expected_dir/metapost.mp b/test/expected_dir/metapost.mp new file mode 100644 index 0000000..0698dfb --- /dev/null +++ b/test/expected_dir/metapost.mp @@ -0,0 +1,62 @@ +metapost comment % Sample MetaPost with embedded LaTeX, used as unit test for ohcount +metapost comment % +metapost comment % The MetaPost code is taken of LaTeXLabels.mp from +metapost comment % the excellent MetaPost tutorial by Urs Oswald +metapost comment % http://www.ursoswald.ch/metapost/tutorial.html +metapost comment % +metapost code verbatimtex +tex comment %&latex +tex code \documentclass{article} +tex code \newcommand{\uB}{\upshape{B\'ezier}} % up: upright +tex code \newcommand{\iB}{\itshape{B\'ezier}} % it: italic +tex code \newcommand{\lB}{\slshape{B\'ezier}} % sl: slanted +tex code \newcommand{\cB}{\scshape{B\'ezier}} % sc: small caps +tex code \newfont{\cyr}{wncyr10} +tex code \begin{document} +metapost code etex +metapost blank +metapost code u:=25; % 25 = 25bp = 25 PostScript points = 30/72 in +metapost code wi:=10; % width in units u +metapost code he:=7; % height in units u +metapost code hoehe:=he*u; % height +metapost code breite:=wi*u; % width +metapost code picture lab; +metapost blank +metapost code beginfig(1) +metapost comment % --- Grid --- +metapost code for i=0 upto he: +metapost code draw (0, i*u)--(breite, i*u) withcolor .7white; +metapost code endfor +metapost code for j=0 upto wi: +metapost code draw (j*u, 0)--(j*u, hoehe) withcolor .7white; +metapost code endfor +metapost comment % --- End Grid --- +metapost blank +metapost code draw (0, 0)--(breite, 0)--(breite, hoehe)--(0, hoehe)--cycle; +metapost blank +metapost code for i=0 upto 5: +metapost code draw .5(u, u){dir 20i}..{dir 20i}(9.5u, 4u); +metapost code endfor +metapost blank +metapost code lab:=\thelabel( +metapost code btex +tex code \begin{tabular}{|r|l|l|l|l|} +tex code \hline +tex code \textbf{md} & upright & italic & slanted & smallcaps \\ +tex code \hline +tex code rm & \textrm{\uB} & \textrm{\iB} & \textrm{\lB} &\textrm{\cB} \\ +tex code sf & \textsf{\uB} & \textsf{\iB} &\textsf{\lB} &\textsf{\cB} \\ +tex code tt & \texttt{\uB} & \texttt{\iB} &\texttt{\lB} &\texttt{\cB} \\ +tex code \hline +tex code \end{tabular} +metapost code etex, +metapost code (.5breite, hoehe-1.5u) +metapost code ); +metapost blank +metapost code unfill bbox lab; +metapost code draw lab; +metapost blank +metapost code label.ulft(btex \cyr C\char24 rih, 08.09.2002 etex, (breite, 0)); +metapost code endfig; +metapost blank +metapost code end diff --git a/test/expected_dir/mxml1.mxml b/test/expected_dir/mxml1.mxml new file mode 100644 index 0000000..3ef2c18 --- /dev/null +++ b/test/expected_dir/mxml1.mxml @@ -0,0 +1,26 @@ +mxml code +mxml blank +mxml code +mxml blank +mxml code +css blank +css code TextArea { +css code backgroundColor: #EEF5EE; +css code } +css blank +mxml code +mxml blank +mxml code +actionscript blank +actionscript code function copy() { +actionscript code destination.text=source.text +actionscript code } +actionscript blank +mxml code +mxml blank +mxml blank +mxml code +mxml code +mxml code +mxml blank +mxml code diff --git a/test/expected_dir/nix.nix b/test/expected_dir/nix.nix new file mode 100644 index 0000000..db848ea --- /dev/null +++ b/test/expected_dir/nix.nix @@ -0,0 +1,24 @@ +nix code {pkgs,config}: +nix blank +nix comment # one line comment +nix code { +nix comment /* mulpiple line comment +nix comment foo = 21; +nix comment */ +nix code bar = " +shell comment #!/bin/sh +shell blank +shell code ls -la +shell comment # comment +shell code echo hello #comment +nix code "; +nix blank +nix code baz = '' +shell comment #!/bin/sh +shell blank +shell code ls -la +shell comment # comment +shell code echo hello #comment +nix code ''; +nix code nixHttp = [ http://nixos.org/ ]; +nix code } diff --git a/test/expected_dir/objj.j b/test/expected_dir/objj.j new file mode 100644 index 0000000..c2e598c --- /dev/null +++ b/test/expected_dir/objj.j @@ -0,0 +1,25 @@ +objective_j blank +objective_j code @import +objective_j code @import +objective_j blank +objective_j code @import "Superclass.j" +objective_j blank +objective_j comment /* +objective_j comment I'm commenting this class +objective_j comment */ +objective_j code @implementation Class : Superclass +objective_j code { +objective_j code var x @accessors; +objective_j code } +objective_j blank +objective_j code + (void)classMethod +objective_j code { +objective_j code return self; // this is a comment +objective_j code } +objective_j blank +objective_j code - (void)instanceMethod +objective_j code { +objective_j code return self; +objective_j code } +objective_j blank +objective_j code @end diff --git a/test/expected_dir/ocaml.ml b/test/expected_dir/ocaml.ml new file mode 100644 index 0000000..1171914 --- /dev/null +++ b/test/expected_dir/ocaml.ml @@ -0,0 +1,10 @@ +ocaml comment (** documentation *) +ocaml code print_string "Hello world!\n";; +ocaml comment (**/**) +ocaml comment (* extra comment *) +ocaml blank +ocaml comment (* multiline +ocaml comment comment*) +ocaml blank +ocaml comment (* recursion in (* a +ocaml comment comment *) to complicate things *) diff --git a/test/expected_dir/octave1.m b/test/expected_dir/octave1.m new file mode 100644 index 0000000..311ca33 --- /dev/null +++ b/test/expected_dir/octave1.m @@ -0,0 +1,301 @@ +octave comment ## Copyright (C) 2006, Regents of the University of California -*- mode: octave; -*- +octave comment ## +octave comment ## This program is free software distributed under the "modified" or +octave comment ## 3-clause BSD license appended to this file. +octave blank +octave code function varargout = toledolu(LU) +octave comment ## -*- texinfo -*- +octave comment ## @deftypefn{Function File} {[@var{L}, @var{U}, @var{P}]} = toledolu(@var{A}) +octave comment ## @deftypefnx{Function File} {[@var{L}, @var{U}]} = toledolu(@var{A}) +octave comment ## @deftypefnx{Function File} {@var{LUP}} = toledolu(@var{A}) +octave comment ## +octave comment ## Note: This returns a vector of indices for @var{P} and not a permutation +octave comment ## matrix. +octave comment ## +octave comment ## Factors @var{P}*@var{A}=@var{L}*@var{U} by Sivan Toledo's recursive factorization algorithm +octave comment ## with partial pivoting. While not as fast as the built-in LU, this +octave comment ## is significantly faster than the standard, unblocked algorithm +octave comment ## while remaining relatively easy to modify. +octave comment ## +octave comment ## See the help for lu for details about the other calling forms. +octave comment ## +octave comment ## For the algorithm, see +octave comment ## @itemize +octave comment ## @item +octave comment ## Toledo, Sivan. "Locality of reference in LU decomposition with +octave comment ## partial pivoting," SIAM J. of Matrix Analysis and Applications, +octave comment ## v18, n4, 1997. DOI: 10.1137/S0895479896297744 +octave comment ## @end itemize +octave comment ## +octave comment ## @seealso{lu} +octave comment ## +octave comment ## @end deftypefn +octave blank +octave comment ## Author: Jason Riedy +octave comment ## Keywords: linear-algebra, LU, factorization +octave comment ## Version: 0.2 +octave blank +octave comment ## This version isn't *quite* the same as Toledo's algorithm. I use a +octave comment ## doubling approach rather than using recursion. So non-power-of-2 +octave comment ## columns likely will be slightly different, but that shouldn't +octave comment ## affect the 'optimality' by more than a small constant factor. +octave blank +octave comment ## Also, I don't handle ncol > nrow optimally. The code factors the +octave comment ## first nrow columns and then updates the remaining ncol-nrow columns +octave comment ## with L. +octave blank +octave comment ## Might be worth eating the memory cost and tracking L separately. +octave comment ## The eye(n)+tril(LU,-1) could be expensive. +octave blank +octave code switch (nargout) +octave code case 0 +octave code return; +octave code case {1,2,3} +octave code otherwise +octave code usage ("[L,U,P] = lu(A), [P\\L, U] = lu(A), or (P\\L-I+U) = lu(A)"); +octave code endswitch +octave blank +octave code [nrow, ncol] = size(LU); +octave code nstep = min(nrow, ncol); +octave blank +octave code Pswap = zeros(nstep, 1); +octave blank +octave code for j=1:nstep, +octave code [pval, pind] = max(abs(LU(j:nrow, j))); +octave code pind = pind + j - 1; +octave code Pswap(j) = pind; +octave blank +octave code kahead = bitand(j, 1+bitcmp(j)); # last 1 bit in j +octave code kstart = j+1-kahead; +octave code kcols = min(kahead, nstep-j); +octave blank +octave code inds = kstart : j; +octave code Ucol = j+1 : j+kcols; +octave code Lrow = j+1 : nrow; +octave blank +octave comment ## permute just this column +octave code if (pind != j) +octave code tmp = LU(pind, j); +octave code LU(pind, j) = LU(j,j); +octave code LU(j,j) = tmp; +octave code endif +octave comment ## apply pending permutations to L +octave code n_to_piv = 1; +octave code ipivstart = j; +octave code jpivstart = j - n_to_piv; +octave code while (n_to_piv < kahead) +octave code pivcols = jpivstart : jpivstart+n_to_piv-1; +octave code for ipiv = ipivstart:j, +octave code pind = Pswap(ipiv); +octave code if (pind != ipiv) +octave code tmp = LU(pind, pivcols); +octave code LU(pind, pivcols) = LU(ipiv, pivcols); +octave code LU(ipiv, pivcols) = tmp; +octave code endif +octave code endfor +octave code ipivstart -= n_to_piv; +octave code n_to_piv *= 2; +octave code jpivstart -= n_to_piv; +octave code endwhile +octave blank +octave code if (LU(j,j) != 0.0 && !isnan(LU(j,j))), +octave code LU(j+1:nrow,j) /= LU(j,j); +octave code endif +octave blank +octave code if 0 == kcols, break; endif +octave blank +octave comment ## permute U to match perm already applied to L +octave code for k = inds, +octave code tmp = LU(Pswap(k), Ucol); +octave code LU(Pswap(k), Ucol) = LU(k, Ucol); +octave code LU(k, Ucol) = tmp; +octave code endfor +octave blank +octave code LU(inds, Ucol) = (eye(kahead) + tril(LU(inds, inds),-1)) \ LU(inds, Ucol); +octave code LU(Lrow, Ucol) -= LU(Lrow, inds) * LU(inds, Ucol); +octave code endfor +octave blank +octave comment ## handle pivot permutations in L out from the last step +octave code npived = bitand(nstep, 1+bitcmp(nstep)); +octave code j = nstep-npived; +octave code while (j > 0) +octave code n_to_piv = bitand(j, 1+bitcmp(j)); +octave blank +octave code pivcols = j-n_to_piv+1 : j; +octave code for ipiv = j+1:nstep, +octave code pind = Pswap(ipiv); +octave code if (pind != ipiv) +octave code tmp = LU(pind, pivcols); +octave code LU(pind, pivcols) = LU(ipiv, pivcols); +octave code LU(ipiv, pivcols) = tmp; +octave code endif +octave code endfor +octave blank +octave code j -= n_to_piv; +octave code endwhile +octave blank +octave code if (nrow < ncol), +octave code Ucol = nrow+1 : ncol; +octave code inds = 1:nrow; +octave code for k = inds, +octave code tmp = LU(Pswap(k), Ucol); +octave code LU(Pswap(k), Ucol) = LU(k, Ucol); +octave code LU(k, Ucol) = tmp; +octave code endfor +octave code LU(inds, Ucol) = (eye(nrow) + tril(LU(inds, inds),-1)) \ LU(inds, Ucol); +octave code endif +octave blank +octave code if (nargout == 1) +octave code varargout{1} = LU; +octave code return; +octave code endif +octave blank +octave code if nrow == ncol, +octave code L = eye(nrow) + tril(LU, -1); +octave code varargout{2} = triu(LU); +octave code elseif nrow < ncol, +octave code L = eye(nrow) + tril(LU, -1)(:,1:nrow); +octave code varargout{2} = triu(LU); +octave code else # nrow > ncol +octave code L = tril(LU, -1); +octave code for k=1:ncol, +octave code L(k,k) = 1; +octave code endfor +octave code varargout{2} = triu(LU)(1:ncol,:); +octave code endif +octave blank +octave code if (nargout == 2) +octave code for j = 1:nstep, +octave code pind = Pswap(j); +octave code tmp = L(pind,:); +octave code L(pind,:) = L(j,:); +octave code L(j,:) = tmp; +octave code endfor +octave code else # nargout == 3 +octave code P = 1:nrow; +octave code for j = 1:nstep, +octave code tmp = P(j); +octave code P(j) = P(Pswap(j)); +octave code P(Pswap(j)) = tmp; +octave code endfor +octave code varargout{3} = P; +octave code endif +octave code varargout{1} = L; +octave blank +octave code endfunction +octave blank +octave comment %!test +octave comment %! M = 15; +octave comment %! N = 15; +octave comment %! A = rand(M,N); +octave comment %! [L,U,P] = toledolu(A); +octave comment %! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) +octave blank +octave comment %!test +octave comment %! M = 16; +octave comment %! N = 16; +octave comment %! A = rand(M,N); +octave comment %! [L,U,P] = toledolu(A); +octave comment %! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) +octave blank +octave comment %!test +octave comment %! M = 17; +octave comment %! N = 17; +octave comment %! A = rand(M,N); +octave comment %! [L,U,P] = toledolu(A); +octave comment %! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) +octave blank +octave comment %!test +octave comment %! M = 8; +octave comment %! N = 17; +octave comment %! A = rand(M,N); +octave comment %! [L,U,P] = toledolu(A); +octave comment %! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) +octave blank +octave comment %!test +octave comment %! M = 8; +octave comment %! N = 15; +octave comment %! A = rand(M,N); +octave comment %! [L,U,P] = toledolu(A); +octave comment %! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) +octave blank +octave comment %!test +octave comment %! M = 7; +octave comment %! N = 17; +octave comment %! A = rand(M,N); +octave comment %! [L,U,P] = toledolu(A); +octave comment %! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) +octave blank +octave comment %!test +octave comment %! M = 7; +octave comment %! N = 15; +octave comment %! A = rand(M,N); +octave comment %! [L,U,P] = toledolu(A); +octave comment %! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) +octave blank +octave comment %!test +octave comment %! M = 17; +octave comment %! N = 8; +octave comment %! A = rand(M,N); +octave comment %! [L,U,P] = toledolu(A); +octave comment %! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) +octave blank +octave comment %!test +octave comment %! M = 15; +octave comment %! N = 8; +octave comment %! A = rand(M,N); +octave comment %! [L,U,P] = toledolu(A); +octave comment %! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) +octave blank +octave comment %!test +octave comment %! M = 17; +octave comment %! N = 7; +octave comment %! A = rand(M,N); +octave comment %! [L,U,P] = toledolu(A); +octave comment %! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) +octave blank +octave comment %!test +octave comment %! M = 15; +octave comment %! N = 7; +octave comment %! A = rand(M,N); +octave comment %! [L,U,P] = toledolu(A); +octave comment %! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) +octave blank +octave comment %!test +octave comment %! M = 31; +octave comment %! N = 17; +octave comment %! A = rand(M,N); +octave comment %! [L,U,P] = toledolu(A); +octave comment %! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) +octave blank +octave comment %!test +octave comment %! M = 11; +octave comment %! N = 29; +octave comment %! A = rand(M,N); +octave comment %! [L,U,P] = toledolu(A); +octave comment %! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) +octave blank +octave comment ## Copyright (c) 2006, Regents of the University of California +octave comment ## All rights reserved. +octave comment ## Redistribution and use in source and binary forms, with or without +octave comment ## modification, are permitted provided that the following conditions are met: +octave comment ## +octave comment ## * Redistributions of source code must retain the above copyright +octave comment ## notice, this list of conditions and the following disclaimer. +octave comment ## * Redistributions in binary form must reproduce the above copyright +octave comment ## notice, this list of conditions and the following disclaimer in the +octave comment ## documentation and/or other materials provided with the distribution. +octave comment ## * Neither the name of the University of California, Berkeley nor the +octave comment ## names of its contributors may be used to endorse or promote products +octave comment ## derived from this software without specific prior written permission. +octave comment ## +octave comment ## THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +octave comment ## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +octave comment ## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +octave comment ## DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +octave comment ## DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +octave comment ## (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +octave comment ## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +octave comment ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +octave comment ## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +octave comment ## SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/test/expected_dir/optimer b/test/expected_dir/optimer new file mode 100644 index 0000000..423c741 --- /dev/null +++ b/test/expected_dir/optimer @@ -0,0 +1,47 @@ +shell comment #!/bin/sh +shell comment # optimer – Masserer ordlistefilene til eit kjaptsøkt format. +shell comment # +shell comment # Copyright © 2008, 2009 Karl Ove Hufthammer . +shell comment # +shell comment # This file is part of Ordbanken. +shell comment # +shell comment # Ordbanken is free software: you can redistribute it and/or modify +shell comment # it under the terms of the GNU General Public License as published by +shell comment # the Free Software Foundation, either version 3 of the License, or +shell comment # (at your option) any later version. +shell comment # +shell comment # This program is distributed in the hope that it will be useful, +shell comment # but WITHOUT ANY WARRANTY; without even the implied warranty of +shell comment # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +shell comment # GNU General Public License for more details. +shell comment # +shell comment # You should have received a copy of the GNU General Public License +shell comment # along with this program. If not, see . +shell blank +shell comment # Utfør kommandoen pÃ¥ fila oppgjeven som førsteargument. +shell code fil=$1 +shell code echo $fil +shell blank +shell comment # Forklaring pÃ¥ filtreringskommandoane. +shell comment # grep: Filtrer vekk kommentarar (linjer som startar med «*»). +shell comment # fgrep: Filtrer unormerte ord. +shell comment # sed: Gjer om mellomrom i siste del av linja (der kodane er) til tabulatorar. +shell comment # (Korfor den kompliserte sed-kommandoen? Fordi kodane i utgangspunktet er +shell comment # skilde med mellomrom i staden for med tabulatorar. Dette ville ikkje vore +shell comment # noko problem om alle oppføringar besto av eitt ord, dÃ¥ «column» som +shell comment # standard handterer mellomrom og tabulatorar likt, men ordbanken har +shell comment # oppføringar som «pÃ¥ kryss og tvers», og dÃ¥ ville alle orda fÃ¥ kvar si +shell comment # kolonne (bruk «på» som oppslagsord for Ã¥ sjÃ¥ oppføringa). +shell comment # sed: Fjern kodar (pÃ¥ forma ) som inneheld tal (interne/uforstÃ¥elige kodar). +shell comment # sed: Fjern kodar («ord» utan <>) som startar med tal (interne/uforstÃ¥elige kodar). +shell comment # sed: Fjern talkoden pÃ¥ starten av linja. +shell comment # tr: SlÃ¥ saman etterfølgjande tabulatorar til éin. +shell comment # sort: Sorter fila (slik at oppslag med «look» gÃ¥r raskare). +shell code grep -v '^\*' $fil \ +shell code | fgrep -v "unormert" \ +shell code | sed -r 'h;s/^([^ ]+ [^ ]+ [^ ]+ )(.*)/\2/;s/ / /g;G;s/(.*)\n([^ ]+ [^ ]+ [^ ]+ )(.*)/\2\1/' \ +shell code | sed -r 's/<[^>]*[0-9][^>]*>+/ /g' \ +shell code | sed -r 's/ [0-9]+[^ ]*/ /g' \ +shell code | sed -r 's/^[0-9]+\s+//' \ +shell code | tr -s '\t' \ +shell code | LC_ALL=C sort > "${fil%.txt}.dat" diff --git a/test/expected_dir/pascal1.pas b/test/expected_dir/pascal1.pas new file mode 100644 index 0000000..1ca997c --- /dev/null +++ b/test/expected_dir/pascal1.pas @@ -0,0 +1,112 @@ +pascal comment {*************************************************************** +pascal comment * +pascal comment * Unit Name: pndefs +pascal comment * Purpose : Various Definitions and functions... +pascal comment * Author : Simon Steele +pascal comment * Copyright: This Source Code is Copyright © 1998-2000 Echo +pascal comment * Software and Simon Steele. Please read the license +pascal comment * agreement at www.pnotepad.org/press/psidx.html. +pascal comment **************************************************************} +pascal code unit pndefs; +pascal blank +pascal code interface +pascal blank +pascal code uses SysUtils; +pascal blank +pascal code function CreatePNFile(filename : string; Text : pChar) : Boolean; +pascal code function StripNewLines(aString: string): string; +pascal code procedure ConvertTypes(filename : string); +pascal blank +pascal code const strFileTypes : PChar = ('.txt'); +pascal code 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'); +pascal code sepChar = '|'; +pascal code verChar = '%'; +pascal code CurrFileVer = '2'; +pascal blank +pascal code implementation +pascal blank +pascal code function CreatePNFile(filename : string; Text : pChar) : Boolean; +pascal code var F : TextFile; +pascal code begin +pascal comment {$I-} +pascal code AssignFile(F, filename); +pascal code Rewrite(F); +pascal code Write(F, Text); +pascal code CloseFile(F); +pascal code If IOResult <> 0 Then Result := False +pascal code Else Result := True; +pascal comment {$I+} +pascal code end; +pascal blank +pascal code function StripNewLines(aString: string): string; +pascal code var i : longint; +pascal code begin +pascal code result := ''; +pascal code i := 1; +pascal code while i <= length(aString) do +pascal code begin +pascal code if aString[i] = #13 then result := result + ' ' else +pascal code if aString[i] <> #10 then result := result + aString[i]; +pascal code inc(i); +pascal code end; +pascal code end; +pascal blank +pascal code procedure ConvertTypes(filename : string); +pascal code var t : TextFile; +pascal code s : string; +pascal code ps : string; {part of string} +pascal code Part : integer; +pascal code ipos : integer; +pascal code OutStr : string; +pascal code const Desc = 1; +pascal code Files = 2; +pascal code Parser = 3; +pascal code Unix = 4; +pascal code begin +pascal comment // This assumes that it is being passed one of the old style type definition +pascal comment // files. We'll set the status on the main form to indicate this as well... +pascal code OutStr := VerChar + CurrFileVer; +pascal code if not fileexists(filename) then +pascal code begin +pascal code CreatePNFile(filename, strOpenTypes); +pascal code exit; +pascal code end; +pascal code Assignfile(t, FileName); +pascal code Reset(t); +pascal code repeat +pascal code Readln(t, s) +pascal code until (Length(s) > 0) or EOF(t); +pascal code CloseFile(t); +pascal code if s = '' then Exit; +pascal code part := Desc; +pascal code repeat +pascal code iPos := Pos(SepChar, s); +pascal code if (iPos = 0) and (Length(s) > 0) then +pascal code begin +pascal code ps := s; +pascal code s := ''; +pascal code end else +pascal code ps := Copy(s, 1, ipos - 1); +pascal code s := Copy(S, ipos + 1, Length(s)); +pascal code case part of +pascal code Desc : begin +pascal code OutStr := OutStr + SepChar + ps; +pascal code part := Files; +pascal code end; +pascal code Files : begin +pascal code OutStr := OutStr + SepChar + ps; +pascal code part := Parser; +pascal code end; +pascal code Parser : begin +pascal code OutStr := OutStr + SepChar + ps + SepChar + '0' + SepChar + '0'; +pascal code part := Desc; +pascal code end; +pascal code end; +pascal code until Length(s) < 1; +pascal code Assignfile(t, filename); +pascal code Rewrite(t); +pascal code Write(t, OutStr); +pascal code CloseFile(t); +pascal code end; +pascal blank +pascal code end. diff --git a/test/expected_dir/pascal2.pp b/test/expected_dir/pascal2.pp new file mode 100644 index 0000000..1ca997c --- /dev/null +++ b/test/expected_dir/pascal2.pp @@ -0,0 +1,112 @@ +pascal comment {*************************************************************** +pascal comment * +pascal comment * Unit Name: pndefs +pascal comment * Purpose : Various Definitions and functions... +pascal comment * Author : Simon Steele +pascal comment * Copyright: This Source Code is Copyright © 1998-2000 Echo +pascal comment * Software and Simon Steele. Please read the license +pascal comment * agreement at www.pnotepad.org/press/psidx.html. +pascal comment **************************************************************} +pascal code unit pndefs; +pascal blank +pascal code interface +pascal blank +pascal code uses SysUtils; +pascal blank +pascal code function CreatePNFile(filename : string; Text : pChar) : Boolean; +pascal code function StripNewLines(aString: string): string; +pascal code procedure ConvertTypes(filename : string); +pascal blank +pascal code const strFileTypes : PChar = ('.txt'); +pascal code 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'); +pascal code sepChar = '|'; +pascal code verChar = '%'; +pascal code CurrFileVer = '2'; +pascal blank +pascal code implementation +pascal blank +pascal code function CreatePNFile(filename : string; Text : pChar) : Boolean; +pascal code var F : TextFile; +pascal code begin +pascal comment {$I-} +pascal code AssignFile(F, filename); +pascal code Rewrite(F); +pascal code Write(F, Text); +pascal code CloseFile(F); +pascal code If IOResult <> 0 Then Result := False +pascal code Else Result := True; +pascal comment {$I+} +pascal code end; +pascal blank +pascal code function StripNewLines(aString: string): string; +pascal code var i : longint; +pascal code begin +pascal code result := ''; +pascal code i := 1; +pascal code while i <= length(aString) do +pascal code begin +pascal code if aString[i] = #13 then result := result + ' ' else +pascal code if aString[i] <> #10 then result := result + aString[i]; +pascal code inc(i); +pascal code end; +pascal code end; +pascal blank +pascal code procedure ConvertTypes(filename : string); +pascal code var t : TextFile; +pascal code s : string; +pascal code ps : string; {part of string} +pascal code Part : integer; +pascal code ipos : integer; +pascal code OutStr : string; +pascal code const Desc = 1; +pascal code Files = 2; +pascal code Parser = 3; +pascal code Unix = 4; +pascal code begin +pascal comment // This assumes that it is being passed one of the old style type definition +pascal comment // files. We'll set the status on the main form to indicate this as well... +pascal code OutStr := VerChar + CurrFileVer; +pascal code if not fileexists(filename) then +pascal code begin +pascal code CreatePNFile(filename, strOpenTypes); +pascal code exit; +pascal code end; +pascal code Assignfile(t, FileName); +pascal code Reset(t); +pascal code repeat +pascal code Readln(t, s) +pascal code until (Length(s) > 0) or EOF(t); +pascal code CloseFile(t); +pascal code if s = '' then Exit; +pascal code part := Desc; +pascal code repeat +pascal code iPos := Pos(SepChar, s); +pascal code if (iPos = 0) and (Length(s) > 0) then +pascal code begin +pascal code ps := s; +pascal code s := ''; +pascal code end else +pascal code ps := Copy(s, 1, ipos - 1); +pascal code s := Copy(S, ipos + 1, Length(s)); +pascal code case part of +pascal code Desc : begin +pascal code OutStr := OutStr + SepChar + ps; +pascal code part := Files; +pascal code end; +pascal code Files : begin +pascal code OutStr := OutStr + SepChar + ps; +pascal code part := Parser; +pascal code end; +pascal code Parser : begin +pascal code OutStr := OutStr + SepChar + ps + SepChar + '0' + SepChar + '0'; +pascal code part := Desc; +pascal code end; +pascal code end; +pascal code until Length(s) < 1; +pascal code Assignfile(t, filename); +pascal code Rewrite(t); +pascal code Write(t, OutStr); +pascal code CloseFile(t); +pascal code end; +pascal blank +pascal code end. diff --git a/test/expected_dir/perl.cgi b/test/expected_dir/perl.cgi new file mode 100644 index 0000000..c5f2bf9 --- /dev/null +++ b/test/expected_dir/perl.cgi @@ -0,0 +1,66 @@ +perl comment #!/usr/bin/perl -w +perl blank +perl comment # ajaxCheckbox.pl - a script to test Ajax functionality +perl blank +perl code use strict; +perl code use CGI qw/:standard/; +perl code use CGI::Ajax; +perl code use DBI; +perl blank +perl comment # --- database authenication +perl code my $dbh = do 'db.inc'; +perl blank +perl code my $query = q{ SELECT project.project_id, project.name, project.phase, prio.prio, +perl code HEX((255 - prio.prio)) AS hex, begun, tags +perl code FROM project JOIN prio +perl code ON (project.project_id = prio.project_id) +perl code WHERE completed < 1 +perl code ORDER BY prio.prio DESC LIMIT 3}; +perl blank +perl code my $sth = $dbh->prepare($query); +perl code $sth->execute(); +perl code my $result = $dbh->selectall_arrayref($sth); +perl blank +perl code my $cgi = new CGI; +perl code my $pjx = new CGI::Ajax( 'toStruck' => \&perl_func ); +perl code print $pjx->build_html( $cgi, \&Show_HTML); +perl blank +perl code sub Show_HTML { +perl blank +perl code use CGI qw/:standard/; +perl blank +perl code my $html = < +perl code +perl code +perl code This is the lastest source version +perl code +perl code +perl code +perl code

Carrot Queue

Priority List  |   +perl code Add a listing  |  

Project listing

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

"; +perl code } +perl blank +perl comment # you can append stuff to the HTML this way +perl code $html .= ""; +perl blank +perl code return $html; +perl code } +perl blank +perl code sub perl_func { +perl code my $input=shift; +perl blank +perl comment # if onClick the change the style +perl code if ($input eq "ON") { +perl code $input=""; +perl code } else { +perl code $input =""; +perl code } +perl code } diff --git a/test/expected_dir/perl1.pl b/test/expected_dir/perl1.pl new file mode 100644 index 0000000..60744e5 --- /dev/null +++ b/test/expected_dir/perl1.pl @@ -0,0 +1,72 @@ +perl comment #!/usr/bin/perl +perl comment # Conserve bandwidth - put a copy of Dilbert on your intranet. +perl comment # Run every morning with cron - after about 7am Eastern +perl comment ######################################################## +perl code use Time::ParseDate; +perl code use Time::CTime; +perl code use LWP::Simple; +perl blank +perl comment # Where do you want the image put? +perl code $dir="/usr/local/etc/httpd/htdocs/Dilbert"; +perl comment # $dir = "c:/httpd/htdocs/Dilbert"; +perl code $location ="$dir/dilbert.gif"; +perl blank +perl code $_ = get("http://www.unitedmedia.com/comics/dilbert/index.html"); +perl blank +perl comment # These next 4 lines will change every time they change the +perl comment # page layout on the Dilbert site. Check back on my web site +perl comment # if things suddenly stop working +perl code s/^.*strip_left\.gif//s; +perl code s/^.*?HREF=\"//s; +perl code s/\">.*$//s; +perl code $line = "http://www.unitedmedia.com" . $_; +perl blank +perl comment # Back up yesterday's image: +perl comment # get the number +perl code open (ID,"$dir/id"); +perl code $id=; +perl code close ID; +perl blank +perl code $id++; +perl code $id=~s/\n$//; +perl code `mv $location $dir/dilbert.$id.gif`; +perl comment # If you're using this on NT, you may want to replace 'mv' +perl comment # with 'move'. +perl blank +perl code open (ID,">$dir/id"); +perl code print ID "$id"; +perl code close ID; +perl blank +perl comment # Now get the actual image +perl code $_ = get($line); +perl blank +perl code open (FILE, ">$location"); +perl code binmode FILE; # Important for NT +perl code print FILE; +perl code close FILE; +perl blank +perl comment # Now I want to update the index.html file +perl code open (FILE, "$dir/index.html"); +perl code @index=; +perl code close FILE; +perl blank +perl code $yesterday = parsedate('yesterday'); +perl code $printdate = strftime('%a, %b %d', localtime($yesterday)); +perl blank +perl code open (FILE, ">$dir/index.html"); +perl code for (@index) { +perl code if (/INSERT HERE/) { +perl code print FILE "$_"; +perl code print FILE "$printdate\n"; +perl code if (($id % 5) == 0) {print FILE "\n"} +perl code } +perl code else {print FILE "$_"}; +perl code } # End for +perl code close FILE; +perl blank +perl comment # Start with an index.html file containing ... +perl comment # +perl comment # +perl comment #
+perl comment # ... +perl comment # And whatever else you want on the page. diff --git a/test/expected_dir/perl_module.pm b/test/expected_dir/perl_module.pm new file mode 100644 index 0000000..f62cbe3 --- /dev/null +++ b/test/expected_dir/perl_module.pm @@ -0,0 +1,1191 @@ +perl code package PAR::Dist; +perl code require Exporter; +perl code use vars qw/$VERSION @ISA @EXPORT @EXPORT_OK/; +perl blank +perl code $VERSION = '0.29'; +perl code @ISA = 'Exporter'; +perl code @EXPORT = qw/ +perl code blib_to_par +perl code install_par +perl code uninstall_par +perl code sign_par +perl code verify_par +perl code merge_par +perl code remove_man +perl code get_meta +perl code generate_blib_stub +perl code /; +perl blank +perl code @EXPORT_OK = qw/ +perl code parse_dist_name +perl code contains_binaries +perl code /; +perl blank +perl code use strict; +perl code use Carp qw/carp croak/; +perl code use File::Spec; +perl blank +perl comment =head1 NAME +perl blank +perl comment PAR::Dist - Create and manipulate PAR distributions +perl blank +perl comment =head1 VERSION +perl blank +perl comment This document describes version 0.29 of PAR::Dist, released Feb 6, 2008. +perl blank +perl comment =head1 SYNOPSIS +perl blank +perl comment As a shell command: +perl blank +perl comment % perl -MPAR::Dist -eblib_to_par +perl blank +perl comment In programs: +perl blank +perl comment use PAR::Dist; +perl blank +perl comment my $dist = blib_to_par(); # make a PAR file using ./blib/ +perl comment install_par($dist); # install it into the system +perl comment uninstall_par($dist); # uninstall it from the system +perl comment sign_par($dist); # sign it using Module::Signature +perl comment verify_par($dist); # verify it using Module::Signature +perl blank +perl comment install_par("http://foo.com/DBI-1.37-MSWin32-5.8.0.par"); # works too +perl comment install_par("http://foo.com/DBI-1.37"); # auto-appends archname + perlver +perl comment install_par("cpan://SMUELLER/PAR-Packer-0.975"); # uses CPAN author directory +perl blank +perl comment =head1 DESCRIPTION +perl blank +perl comment This module creates and manipulates I. They are +perl comment architecture-specific B files, containing everything under F +perl comment of CPAN distributions after their C or C stage, a +perl comment F describing metadata of the original CPAN distribution, +perl comment and a F detailing all files within it. Digitally signed PAR +perl comment distributions will also contain a F file. +perl blank +perl comment The naming convention for such distributions is: +perl blank +perl comment $NAME-$VERSION-$ARCH-$PERL_VERSION.par +perl blank +perl comment For example, C corresponds to the +perl comment 0.01 release of C on CPAN, built for perl 5.8.0 running on +perl comment C. +perl blank +perl comment =head1 FUNCTIONS +perl blank +perl comment Several functions are exported by default. Unless otherwise noted, +perl comment they can take either a hash of +perl comment named arguments, a single argument (taken as C<$path> by C +perl comment and C<$dist> by other functions), or no arguments (in which case +perl comment the first PAR file in the current directory is used). +perl blank +perl comment Therefore, under a directory containing only a single F, all +perl comment invocations below are equivalent: +perl blank +perl comment % perl -MPAR::Dist -e"install_par( dist => 'test.par' )" +perl comment % perl -MPAR::Dist -e"install_par( 'test.par' )" +perl comment % perl -MPAR::Dist -einstall_par; +perl blank +perl comment If C<$dist> resembles a URL, C is called to mirror it +perl comment locally under C<$ENV{PAR_TEMP}> (or C<$TEMP/par/> if unspecified), and the +perl comment function will act on the fetched local file instead. If the URL begins +perl comment with C, it will be expanded automatically to the author's CPAN +perl comment directory (e.g. C). +perl blank +perl comment If C<$dist> does not have a file extension beginning with a letter or +perl comment underscore, a dash and C<$suffix> ($ARCH-$PERL_VERSION.par by default) +perl comment will be appended to it. +perl blank +perl comment =head2 blib_to_par +perl blank +perl comment Takes key/value pairs as parameters or a single parameter indicating the +perl comment path that contains the F subdirectory. +perl blank +perl comment Builds a PAR distribution from the F subdirectory under C, or +perl comment under the current directory if unspecified. If F does not exist, +perl comment it automatically runs F, F, F or F to +perl comment create it. +perl blank +perl comment Returns the filename or the generated PAR distribution. +perl blank +perl comment Valid parameters are: +perl blank +perl comment =over 2 +perl blank +perl comment =item path +perl blank +perl comment Sets the path which contains the F subdirectory from which the PAR +perl comment distribution will be generated. +perl blank +perl comment =item name, version, suffix +perl blank +perl comment These attributes set the name, version and platform specific suffix +perl comment of the distribution. Name and version can be automatically +perl comment determined from the distributions F or F files. +perl blank +perl comment The suffix is generated from your architecture name and your version of +perl comment perl by default. +perl blank +perl comment =item dist +perl blank +perl comment The output filename for the PAR distribution. +perl blank +perl comment =back +perl blank +perl comment =cut +perl blank +perl code sub blib_to_par { +perl code @_ = (path => @_) if @_ == 1; +perl blank +perl code my %args = @_; +perl code require Config; +perl blank +perl blank +perl comment # don't use 'my $foo ... if ...' it creates a static variable! +perl code my $dist; +perl code my $path = $args{path}; +perl code $dist = File::Spec->rel2abs($args{dist}) if $args{dist}; +perl code my $name = $args{name}; +perl code my $version = $args{version}; +perl code my $suffix = $args{suffix} || "$Config::Config{archname}-$Config::Config{version}.par"; +perl code my $cwd; +perl blank +perl code if (defined $path) { +perl code require Cwd; +perl code $cwd = Cwd::cwd(); +perl code chdir $path; +perl code } +perl blank +perl code _build_blib() unless -d "blib"; +perl blank +perl code my @files; +perl code open MANIFEST, ">", File::Spec->catfile("blib", "MANIFEST") or die $!; +perl code open META, ">", File::Spec->catfile("blib", "META.yml") or die $!; +perl blank +perl code require File::Find; +perl code File::Find::find( sub { +perl code next unless $File::Find::name; +perl code (-r && !-d) and push ( @files, substr($File::Find::name, 5) ); +perl code } , 'blib' ); +perl blank +perl code print MANIFEST join( +perl code "\n", +perl code ' ', +perl code (sort @files), +perl code q( # ) +perl code ); +perl code close MANIFEST; +perl blank +perl code if (open(OLD_META, "META.yml")) { +perl code while () { +perl code if (/^distribution_type:/) { +perl code print META "distribution_type: par\n"; +perl code } +perl code else { +perl code print META $_; +perl code } +perl blank +perl code if (/^name:\s+(.*)/) { +perl code $name ||= $1; +perl code $name =~ s/::/-/g; +perl code } +perl code elsif (/^version:\s+.*Module::Build::Version/) { +perl code while () { +perl code /^\s+original:\s+(.*)/ or next; +perl code $version ||= $1; +perl code last; +perl code } +perl code } +perl code elsif (/^version:\s+(.*)/) { +perl code $version ||= $1; +perl code } +perl code } +perl code close OLD_META; +perl code close META; +perl code } +perl blank +perl code if ((!$name or !$version) and open(MAKEFILE, "Makefile")) { +perl code while () { +perl code if (/^DISTNAME\s+=\s+(.*)$/) { +perl code $name ||= $1; +perl code } +perl code elsif (/^VERSION\s+=\s+(.*)$/) { +perl code $version ||= $1; +perl code } +perl code } +perl code } +perl blank +perl code if (not defined($name) or not defined($version)) { +perl comment # could not determine name or version. Error. +perl code my $what; +perl code if (not defined $name) { +perl code $what = 'name'; +perl code $what .= ' and version' if not defined $version; +perl code } +perl code elsif (not defined $version) { +perl code $what = 'version'; +perl code } +perl blank +perl code carp("I was unable to determine the $what of the PAR distribution. Please create a Makefile or META.yml file from which we can infer the information or just specify the missing information as an option to blib_to_par."); +perl code return(); +perl code } +perl blank +perl code $name =~ s/\s+$//; +perl code $version =~ s/\s+$//; +perl blank +perl code my $file = "$name-$version-$suffix"; +perl code unlink $file if -f $file; +perl blank +perl code print META << "YAML" if fileno(META); +perl code name: $name +perl code version: $version +perl code build_requires: {} +perl code conflicts: {} +perl code dist_name: $file +perl code distribution_type: par +perl code dynamic_config: 0 +perl code generated_by: 'PAR::Dist version $PAR::Dist::VERSION' +perl code license: unknown +perl code YAML +perl code close META; +perl blank +perl code mkdir('blib', 0777); +perl code chdir('blib'); +perl code _zip(dist => File::Spec->catfile(File::Spec->updir, $file)) or die $!; +perl code chdir(File::Spec->updir); +perl blank +perl code unlink File::Spec->catfile("blib", "MANIFEST"); +perl code unlink File::Spec->catfile("blib", "META.yml"); +perl blank +perl code $dist ||= File::Spec->catfile($cwd, $file) if $cwd; +perl blank +perl code if ($dist and $file ne $dist) { +perl code rename( $file => $dist ); +perl code $file = $dist; +perl code } +perl blank +perl code my $pathname = File::Spec->rel2abs($file); +perl code if ($^O eq 'MSWin32') { +perl code $pathname =~ s!\\!/!g; +perl code $pathname =~ s!:!|!g; +perl code }; +perl code print << "."; +perl code Successfully created binary distribution '$file'. +perl code Its contents are accessible in compliant browsers as: +perl code jar:file://$pathname!/MANIFEST +perl code . +perl blank +perl code chdir $cwd if $cwd; +perl code return $file; +perl code } +perl blank +perl code sub _build_blib { +perl code if (-e 'Build') { +perl code system($^X, "Build"); +perl code } +perl code elsif (-e 'Makefile') { +perl code system($Config::Config{make}); +perl code } +perl code elsif (-e 'Build.PL') { +perl code system($^X, "Build.PL"); +perl code system($^X, "Build"); +perl code } +perl code elsif (-e 'Makefile.PL') { +perl code system($^X, "Makefile.PL"); +perl code system($Config::Config{make}); +perl code } +perl code } +perl blank +perl comment =head2 install_par +perl blank +perl comment Installs a PAR distribution into the system, using +perl comment C. +perl blank +perl comment Valid parameters are: +perl blank +perl comment =over 2 +perl blank +perl comment =item dist +perl blank +perl comment The .par file to install. The heuristics outlined in the B +perl comment section above apply. +perl blank +perl comment =item prefix +perl blank +perl comment This string will be prepended to all installation paths. +perl comment If it isn't specified, the environment variable +perl comment C is used as a prefix. +perl blank +perl comment =back +perl blank +perl comment Additionally, you can use several parameters to change the default +perl comment installation destinations. You don't usually have to worry about this +perl comment unless you are installing into a user-local directory. +perl comment The following section outlines the parameter names and default settings: +perl blank +perl comment Parameter From To +perl comment inst_lib blib/lib $Config{installsitelib} (*) +perl comment inst_archlib blib/arch $Config{installsitearch} +perl comment inst_script blib/script $Config{installscript} +perl comment inst_bin blib/bin $Config{installbin} +perl comment inst_man1dir blib/man1 $Config{installman1dir} +perl comment inst_man3dir blib/man3 $Config{installman3dir} +perl comment packlist_read $Config{sitearchexp}/auto/$name/.packlist +perl comment packlist_write $Config{installsitearch}/auto/$name/.packlist +perl blank +perl comment The C parameter is used to control where the F<.packlist> +perl comment file is written to. (Necessary for uninstallation.) +perl comment The C parameter specifies a .packlist file to merge in if +perl comment it exists. By setting any of the above installation targets to C, +perl comment you can remove that target altogether. For example, passing +perl comment C undef, inst_man3dir => undef> means that the contained +perl comment manual pages won't be installed. This is not available for the packlists. +perl blank +perl comment Finally, you may specify a C parameter. Its value should be +perl comment a reference to a hash of custom installation targets such as +perl blank +perl comment custom_targets => { 'blib/my_data' => '/some/path/my_data' } +perl blank +perl comment You can use this to install the F<.par> archives contents to arbitrary +perl comment locations. +perl blank +perl comment If only a single parameter is given, it is treated as the C +perl comment parameter. +perl blank +perl comment =cut +perl blank +perl code sub install_par { +perl code my %args = &_args; +perl code _install_or_uninstall(%args, action => 'install'); +perl code } +perl blank +perl comment =head2 uninstall_par +perl blank +perl comment Uninstalls all previously installed contents of a PAR distribution, +perl comment using C. +perl blank +perl comment Takes almost the same parameters as C, but naturally, +perl comment the installation target parameters do not apply. The only exception +perl comment to this is the C parameter which specifies the +perl comment F<.packlist> file to read the list of installed files from. +perl comment It defaults to C<$Config::Config{installsitearch}/auto/$name/.packlist>. +perl blank +perl comment =cut +perl blank +perl code sub uninstall_par { +perl code my %args = &_args; +perl code _install_or_uninstall(%args, action => 'uninstall'); +perl code } +perl blank +perl code sub _install_or_uninstall { +perl code my %args = &_args; +perl code my $name = $args{name}; +perl code my $action = $args{action}; +perl blank +perl code my %ENV_copy = %ENV; +perl code $ENV{PERL_INSTALL_ROOT} = $args{prefix} if defined $args{prefix}; +perl blank +perl code require Cwd; +perl code my $old_dir = Cwd::cwd(); +perl blank +perl code my ($dist, $tmpdir) = _unzip_to_tmpdir( dist => $args{dist}, subdir => 'blib' ); +perl blank +perl code if ( open (META, File::Spec->catfile('blib', 'META.yml')) ) { +perl code while () { +perl code next unless /^name:\s+(.*)/; +perl code $name = $1; +perl code $name =~ s/\s+$//; +perl code last; +perl code } +perl code close META; +perl code } +perl code return if not defined $name or $name eq ''; +perl blank +perl code if (-d 'script') { +perl code require ExtUtils::MY; +perl code foreach my $file (glob("script/*")) { +perl code next unless -T $file; +perl code ExtUtils::MY->fixin($file); +perl code chmod(0555, $file); +perl code } +perl code } +perl blank +perl code $name =~ s{::|-}{/}g; +perl code require ExtUtils::Install; +perl blank +perl code my $rv; +perl code if ($action eq 'install') { +perl code my $target = _installation_target( File::Spec->curdir, $name, \%args ); +perl code my $custom_targets = $args{custom_targets} || {}; +perl code $target->{$_} = $custom_targets->{$_} foreach keys %{$custom_targets}; +perl blank +perl code $rv = ExtUtils::Install::install($target, 1, 0, 0); +perl code } +perl code elsif ($action eq 'uninstall') { +perl code require Config; +perl code $rv = ExtUtils::Install::uninstall( +perl code $args{packlist_read}||"$Config::Config{installsitearch}/auto/$name/.packlist" +perl code ); +perl code } +perl blank +perl code %ENV = %ENV_copy; +perl blank +perl code chdir($old_dir); +perl code File::Path::rmtree([$tmpdir]); +perl code return $rv; +perl code } +perl blank +perl comment # Returns the default installation target as used by +perl comment # ExtUtils::Install::install(). First parameter should be the base +perl comment # directory containing the blib/ we're installing from. +perl comment # Second parameter should be the name of the distribution for the packlist +perl comment # paths. Third parameter may be a hash reference with user defined keys for +perl comment # the target hash. In fact, any contents that do not start with 'inst_' are +perl comment # skipped. +perl code sub _installation_target { +perl code require Config; +perl code my $dir = shift; +perl code my $name = shift; +perl code my $user = shift || {}; +perl blank +perl comment # accepted sources (and user overrides) +perl code my %sources = ( +perl code inst_lib => File::Spec->catdir($dir,"blib","lib"), +perl code inst_archlib => File::Spec->catdir($dir,"blib","arch"), +perl code inst_bin => File::Spec->catdir($dir,'blib','bin'), +perl code inst_script => File::Spec->catdir($dir,'blib','script'), +perl code inst_man1dir => File::Spec->catdir($dir,'blib','man1'), +perl code inst_man3dir => File::Spec->catdir($dir,'blib','man3'), +perl code packlist_read => 'read', +perl code packlist_write => 'write', +perl code ); +perl blank +perl blank +perl comment # default targets +perl code my $target = { +perl code read => $Config::Config{sitearchexp}."/auto/$name/.packlist", +perl code write => $Config::Config{installsitearch}."/auto/$name/.packlist", +perl code $sources{inst_lib} +perl code => (_directory_not_empty($sources{inst_archlib})) +perl code ? $Config::Config{installsitearch} +perl code : $Config::Config{installsitelib}, +perl code $sources{inst_archlib} => $Config::Config{installsitearch}, +perl code $sources{inst_bin} => $Config::Config{installbin} , +perl code $sources{inst_script} => $Config::Config{installscript}, +perl code $sources{inst_man1dir} => $Config::Config{installman1dir}, +perl code $sources{inst_man3dir} => $Config::Config{installman3dir}, +perl code }; +perl blank +perl comment # Included for future support for ${flavour}perl external lib installation +perl comment # if ($Config::Config{flavour_perl}) { +perl comment # my $ext = File::Spec->catdir($dir, 'blib', 'ext'); +perl comment # # from => to +perl comment # $sources{inst_external_lib} = File::Spec->catdir($ext, 'lib'); +perl comment # $sources{inst_external_bin} = File::Spec->catdir($ext, 'bin'); +perl comment # $sources{inst_external_include} = File::Spec->catdir($ext, 'include'); +perl comment # $sources{inst_external_src} = File::Spec->catdir($ext, 'src'); +perl comment # $target->{ $sources{inst_external_lib} } = $Config::Config{flavour_install_lib}; +perl comment # $target->{ $sources{inst_external_bin} } = $Config::Config{flavour_install_bin}; +perl comment # $target->{ $sources{inst_external_include} } = $Config::Config{flavour_install_include}; +perl comment # $target->{ $sources{inst_external_src} } = $Config::Config{flavour_install_src}; +perl comment # } +perl blank +perl comment # insert user overrides +perl code foreach my $key (keys %$user) { +perl code my $value = $user->{$key}; +perl code if (not defined $value and $key ne 'packlist_read' and $key ne 'packlist_write') { +perl comment # undef means "remove" +perl code delete $target->{ $sources{$key} }; +perl code } +perl code elsif (exists $sources{$key}) { +perl comment # overwrite stuff, don't let the user create new entries +perl code $target->{ $sources{$key} } = $value; +perl code } +perl code } +perl blank +perl code return $target; +perl code } +perl blank +perl code sub _directory_not_empty { +perl code require File::Find; +perl code my($dir) = @_; +perl code my $files = 0; +perl code File::Find::find(sub { +perl code return if $_ eq ".exists"; +perl code if (-f) { +perl code $File::Find::prune++; +perl code $files = 1; +perl code } +perl code }, $dir); +perl code return $files; +perl code } +perl blank +perl comment =head2 sign_par +perl blank +perl comment Digitally sign a PAR distribution using C or B, +perl comment via B. +perl blank +perl comment =cut +perl blank +perl code sub sign_par { +perl code my %args = &_args; +perl code _verify_or_sign(%args, action => 'sign'); +perl code } +perl blank +perl comment =head2 verify_par +perl blank +perl comment Verify the digital signature of a PAR distribution using C or +perl comment B, via B. +perl blank +perl comment Returns a boolean value indicating whether verification passed; C<$!> +perl comment is set to the return code of C. +perl blank +perl comment =cut +perl blank +perl code sub verify_par { +perl code my %args = &_args; +perl code $! = _verify_or_sign(%args, action => 'verify'); +perl code return ( $! == Module::Signature::SIGNATURE_OK() ); +perl code } +perl blank +perl comment =head2 merge_par +perl blank +perl comment Merge two or more PAR distributions into one. First argument must +perl comment be the name of the distribution you want to merge all others into. +perl comment Any following arguments will be interpreted as the file names of +perl comment further PAR distributions to merge into the first one. +perl blank +perl comment merge_par('foo.par', 'bar.par', 'baz.par') +perl blank +perl comment This will merge the distributions C, C and C +perl comment into the distribution C. C will be overwritten! +perl comment The original META.yml of C is retained. +perl blank +perl comment =cut +perl blank +perl code sub merge_par { +perl code my $base_par = shift; +perl code my @additional_pars = @_; +perl code require Cwd; +perl code require File::Copy; +perl code require File::Path; +perl code require File::Find; +perl blank +perl comment # parameter checking +perl code if (not defined $base_par) { +perl code croak "First argument to merge_par() must be the .par archive to modify."; +perl code } +perl blank +perl code if (not -f $base_par or not -r _ or not -w _) { +perl code croak "'$base_par' is not a file or you do not have enough permissions to read and modify it."; +perl code } +perl blank +perl code foreach (@additional_pars) { +perl code if (not -f $_ or not -r _) { +perl code croak "'$_' is not a file or you do not have enough permissions to read it."; +perl code } +perl code } +perl blank +perl comment # The unzipping will change directories. Remember old dir. +perl code my $old_cwd = Cwd::cwd(); +perl blank +perl comment # Unzip the base par to a temp. dir. +perl code (undef, my $base_dir) = _unzip_to_tmpdir( +perl code dist => $base_par, subdir => 'blib' +perl code ); +perl code my $blibdir = File::Spec->catdir($base_dir, 'blib'); +perl blank +perl comment # move the META.yml to the (main) temp. dir. +perl code File::Copy::move( +perl code File::Spec->catfile($blibdir, 'META.yml'), +perl code File::Spec->catfile($base_dir, 'META.yml') +perl code ); +perl comment # delete (incorrect) MANIFEST +perl code unlink File::Spec->catfile($blibdir, 'MANIFEST'); +perl blank +perl comment # extract additional pars and merge +perl code foreach my $par (@additional_pars) { +perl comment # restore original directory because the par path +perl comment # might have been relative! +perl code chdir($old_cwd); +perl code (undef, my $add_dir) = _unzip_to_tmpdir( +perl code dist => $par +perl code ); +perl code my @files; +perl code my @dirs; +perl comment # I hate File::Find +perl comment # And I hate writing portable code, too. +perl code File::Find::find( +perl code {wanted =>sub { +perl code my $file = $File::Find::name; +perl code push @files, $file if -f $file; +perl code push @dirs, $file if -d _; +perl code }}, +perl code $add_dir +perl code ); +perl code my ($vol, $subdir, undef) = File::Spec->splitpath( $add_dir, 1); +perl code my @dir = File::Spec->splitdir( $subdir ); +perl blank +perl comment # merge directory structure +perl code foreach my $dir (@dirs) { +perl code my ($v, $d, undef) = File::Spec->splitpath( $dir, 1 ); +perl code my @d = File::Spec->splitdir( $d ); +perl code shift @d foreach @dir; # remove tmp dir from path +perl code my $target = File::Spec->catdir( $blibdir, @d ); +perl code mkdir($target); +perl code } +perl blank +perl comment # merge files +perl code foreach my $file (@files) { +perl code my ($v, $d, $f) = File::Spec->splitpath( $file ); +perl code my @d = File::Spec->splitdir( $d ); +perl code shift @d foreach @dir; # remove tmp dir from path +perl code my $target = File::Spec->catfile( +perl code File::Spec->catdir( $blibdir, @d ), +perl code $f +perl code ); +perl code File::Copy::copy($file, $target) +perl code or die "Could not copy '$file' to '$target': $!"; +perl blank +perl code } +perl code chdir($old_cwd); +perl code File::Path::rmtree([$add_dir]); +perl code } +perl blank +perl comment # delete (copied) MANIFEST and META.yml +perl code unlink File::Spec->catfile($blibdir, 'MANIFEST'); +perl code unlink File::Spec->catfile($blibdir, 'META.yml'); +perl blank +perl code chdir($base_dir); +perl code my $resulting_par_file = Cwd::abs_path(blib_to_par()); +perl code chdir($old_cwd); +perl code File::Copy::move($resulting_par_file, $base_par); +perl blank +perl code File::Path::rmtree([$base_dir]); +perl code } +perl blank +perl blank +perl comment =head2 remove_man +perl blank +perl comment Remove the man pages from a PAR distribution. Takes one named +perl comment parameter: I which should be the name (and path) of the +perl comment PAR distribution file. The calling conventions outlined in +perl comment the C section above apply. +perl blank +perl comment The PAR archive will be +perl comment extracted, stripped of all C and C subdirectories +perl comment and then repackaged into the original file. +perl blank +perl comment =cut +perl blank +perl code sub remove_man { +perl code my %args = &_args; +perl code my $par = $args{dist}; +perl code require Cwd; +perl code require File::Copy; +perl code require File::Path; +perl code require File::Find; +perl blank +perl comment # parameter checking +perl code if (not defined $par) { +perl code croak "First argument to remove_man() must be the .par archive to modify."; +perl code } +perl blank +perl code if (not -f $par or not -r _ or not -w _) { +perl code croak "'$par' is not a file or you do not have enough permissions to read and modify it."; +perl code } +perl blank +perl comment # The unzipping will change directories. Remember old dir. +perl code my $old_cwd = Cwd::cwd(); +perl blank +perl comment # Unzip the base par to a temp. dir. +perl code (undef, my $base_dir) = _unzip_to_tmpdir( +perl code dist => $par, subdir => 'blib' +perl code ); +perl code my $blibdir = File::Spec->catdir($base_dir, 'blib'); +perl blank +perl comment # move the META.yml to the (main) temp. dir. +perl code File::Copy::move( +perl code File::Spec->catfile($blibdir, 'META.yml'), +perl code File::Spec->catfile($base_dir, 'META.yml') +perl code ); +perl comment # delete (incorrect) MANIFEST +perl code unlink File::Spec->catfile($blibdir, 'MANIFEST'); +perl blank +perl code opendir DIRECTORY, 'blib' or die $!; +perl code my @dirs = grep { /^blib\/(?:man\d*|html)$/ } +perl code grep { -d $_ } +perl code map { File::Spec->catfile('blib', $_) } +perl code readdir DIRECTORY; +perl code close DIRECTORY; +perl blank +perl code File::Path::rmtree(\@dirs); +perl blank +perl code chdir($base_dir); +perl code my $resulting_par_file = Cwd::abs_path(blib_to_par()); +perl code chdir($old_cwd); +perl code File::Copy::move($resulting_par_file, $par); +perl blank +perl code File::Path::rmtree([$base_dir]); +perl code } +perl blank +perl blank +perl comment =head2 get_meta +perl blank +perl comment Opens a PAR archive and extracts the contained META.yml file. +perl comment Returns the META.yml file as a string. +perl blank +perl comment Takes one named parameter: I. If only one parameter is +perl comment passed, it is treated as the I parameter. (Have a look +perl comment at the description in the C section above.) +perl blank +perl comment Returns undef if no PAR archive or no META.yml within the +perl comment archive were found. +perl blank +perl comment =cut +perl blank +perl code sub get_meta { +perl code my %args = &_args; +perl code my $dist = $args{dist}; +perl code return undef if not defined $dist or not -r $dist; +perl code require Cwd; +perl code require File::Path; +perl blank +perl comment # The unzipping will change directories. Remember old dir. +perl code my $old_cwd = Cwd::cwd(); +perl blank +perl comment # Unzip the base par to a temp. dir. +perl code (undef, my $base_dir) = _unzip_to_tmpdir( +perl code dist => $dist, subdir => 'blib' +perl code ); +perl code my $blibdir = File::Spec->catdir($base_dir, 'blib'); +perl blank +perl code my $meta = File::Spec->catfile($blibdir, 'META.yml'); +perl blank +perl code if (not -r $meta) { +perl code return undef; +perl code } +perl blank +perl code open FH, '<', $meta +perl code or die "Could not open file '$meta' for reading: $!"; +perl blank +perl code local $/ = undef; +perl code my $meta_text = ; +perl code close FH; +perl blank +perl code chdir($old_cwd); +perl blank +perl code File::Path::rmtree([$base_dir]); +perl blank +perl code return $meta_text; +perl code } +perl blank +perl blank +perl blank +perl code sub _unzip { +perl code my %args = &_args; +perl code my $dist = $args{dist}; +perl code my $path = $args{path} || File::Spec->curdir; +perl code return unless -f $dist; +perl blank +perl comment # Try fast unzipping first +perl code if (eval { require Archive::Unzip::Burst; 1 }) { +perl code my $return = Archive::Unzip::Burst::unzip($dist, $path); +perl code return if $return; # true return value == error (a la system call) +perl code } +perl comment # Then slow unzipping +perl code if (eval { require Archive::Zip; 1 }) { +perl code my $zip = Archive::Zip->new; +perl code local %SIG; +perl code $SIG{__WARN__} = sub { print STDERR $_[0] unless $_[0] =~ /\bstat\b/ }; +perl code return unless $zip->read($dist) == Archive::Zip::AZ_OK() +perl code and $zip->extractTree('', "$path/") == Archive::Zip::AZ_OK(); +perl code } +perl comment # Then fall back to the system +perl code else { +perl code return if system(unzip => $dist, '-d', $path); +perl code } +perl blank +perl code return 1; +perl code } +perl blank +perl code sub _zip { +perl code my %args = &_args; +perl code my $dist = $args{dist}; +perl blank +perl code if (eval { require Archive::Zip; 1 }) { +perl code my $zip = Archive::Zip->new; +perl code $zip->addTree( File::Spec->curdir, '' ); +perl code $zip->writeToFileNamed( $dist ) == Archive::Zip::AZ_OK() or die $!; +perl code } +perl code else { +perl code system(qw(zip -r), $dist, File::Spec->curdir) and die $!; +perl code } +perl code } +perl blank +perl blank +perl comment # This sub munges the arguments to most of the PAR::Dist functions +perl comment # into a hash. On the way, it downloads PAR archives as necessary, etc. +perl code sub _args { +perl comment # default to the first .par in the CWD +perl code if (not @_) { +perl code @_ = (glob('*.par'))[0]; +perl code } +perl blank +perl comment # single argument => it's a distribution file name or URL +perl code @_ = (dist => @_) if @_ == 1; +perl blank +perl code my %args = @_; +perl code $args{name} ||= $args{dist}; +perl blank +perl comment # If we are installing from an URL, we want to munge the +perl comment # distribution name so that it is in form "Module-Name" +perl code if (defined $args{name}) { +perl code $args{name} =~ s/^\w+:\/\///; +perl code my @elems = parse_dist_name($args{name}); +perl comment # @elems is name, version, arch, perlversion +perl code if (defined $elems[0]) { +perl code $args{name} = $elems[0]; +perl code } +perl code else { +perl code $args{name} =~ s/^.*\/([^\/]+)$/$1/; +perl code $args{name} =~ s/^([0-9A-Za-z_-]+)-\d+\..+$/$1/; +perl code } +perl code } +perl blank +perl comment # append suffix if there is none +perl code if ($args{dist} and not $args{dist} =~ /\.[a-zA-Z_][^.]*$/) { +perl code require Config; +perl code my $suffix = $args{suffix}; +perl code $suffix ||= "$Config::Config{archname}-$Config::Config{version}.par"; +perl code $args{dist} .= "-$suffix"; +perl code } +perl blank +perl comment # download if it's an URL +perl code if ($args{dist} and $args{dist} =~ m!^\w+://!) { +perl code $args{dist} = _fetch(dist => $args{dist}) +perl code } +perl blank +perl code return %args; +perl code } +perl blank +perl blank +perl comment # Download PAR archive, but only if necessary (mirror!) +perl code my %escapes; +perl code sub _fetch { +perl code my %args = @_; +perl blank +perl code if ($args{dist} =~ s/^file:\/\///) { +perl code return $args{dist} if -e $args{dist}; +perl code return; +perl code } +perl code require LWP::Simple; +perl blank +perl code $ENV{PAR_TEMP} ||= File::Spec->catdir(File::Spec->tmpdir, 'par'); +perl code mkdir $ENV{PAR_TEMP}, 0777; +perl code %escapes = map { chr($_) => sprintf("%%%02X", $_) } 0..255 unless %escapes; +perl blank +perl code $args{dist} =~ s{^cpan://((([a-zA-Z])[a-zA-Z])[-_a-zA-Z]+)/} +perl code {http://www.cpan.org/modules/by-authors/id/\U$3/$2/$1\E/}; +perl blank +perl code my $file = $args{dist}; +perl code $file =~ s/([^\w\.])/$escapes{$1}/g; +perl code $file = File::Spec->catfile( $ENV{PAR_TEMP}, $file); +perl code my $rc = LWP::Simple::mirror( $args{dist}, $file ); +perl blank +perl code if (!LWP::Simple::is_success($rc) and $rc != 304) { +perl code die "Error $rc: ", LWP::Simple::status_message($rc), " ($args{dist})\n"; +perl code } +perl blank +perl code return $file if -e $file; +perl code return; +perl code } +perl blank +perl code sub _verify_or_sign { +perl code my %args = &_args; +perl blank +perl code require File::Path; +perl code require Module::Signature; +perl code die "Module::Signature version 0.25 required" +perl code unless Module::Signature->VERSION >= 0.25; +perl blank +perl code require Cwd; +perl code my $cwd = Cwd::cwd(); +perl code my $action = $args{action}; +perl code my ($dist, $tmpdir) = _unzip_to_tmpdir($args{dist}); +perl code $action ||= (-e 'SIGNATURE' ? 'verify' : 'sign'); +perl blank +perl code if ($action eq 'sign') { +perl code open FH, '>SIGNATURE' unless -e 'SIGNATURE'; +perl code open FH, 'MANIFEST' or die $!; +perl blank +perl code local $/; +perl code my $out = ; +perl code if ($out !~ /^SIGNATURE(?:\s|$)/m) { +perl code $out =~ s/^(?!\s)/SIGNATURE\n/m; +perl code open FH, '>MANIFEST' or die $!; +perl code print FH $out; +perl code } +perl code close FH; +perl blank +perl code $args{overwrite} = 1 unless exists $args{overwrite}; +perl code $args{skip} = 0 unless exists $args{skip}; +perl code } +perl blank +perl code my $rv = Module::Signature->can($action)->(%args); +perl code _zip(dist => $dist) if $action eq 'sign'; +perl code File::Path::rmtree([$tmpdir]); +perl blank +perl code chdir($cwd); +perl code return $rv; +perl code } +perl blank +perl code sub _unzip_to_tmpdir { +perl code my %args = &_args; +perl blank +perl code require File::Temp; +perl blank +perl code my $dist = File::Spec->rel2abs($args{dist}); +perl code my $tmpdirname = File::Spec->catdir(File::Spec->tmpdir, "parXXXXX"); +perl code my $tmpdir = File::Temp::mkdtemp($tmpdirname) +perl code or die "Could not create temporary directory from template '$tmpdirname': $!"; +perl code my $path = $tmpdir; +perl code $path = File::Spec->catdir($tmpdir, $args{subdir}) if defined $args{subdir}; +perl code _unzip(dist => $dist, path => $path); +perl blank +perl code chdir $tmpdir; +perl code return ($dist, $tmpdir); +perl code } +perl blank +perl blank +perl blank +perl comment =head2 parse_dist_name +perl blank +perl comment First argument must be a distribution file name. The file name +perl comment is parsed into I, I, +perl comment I, and I. +perl blank +perl comment Returns the results as a list in the above order. +perl comment If any or all of the above cannot be determined, returns undef instead +perl comment of the undetermined elements. +perl blank +perl comment Supported formats are: +perl blank +perl comment Math-Symbolic-0.502-x86_64-linux-gnu-thread-multi-5.8.7 +perl blank +perl comment Math-Symbolic-0.502 +perl blank +perl comment The ".tar.gz" or ".par" extensions as well as any +perl comment preceding paths are stripped before parsing. Starting with C +perl comment 0.22, versions containing a preceding C are parsed correctly. +perl blank +perl comment This function is not exported by default. +perl blank +perl comment =cut +perl blank +perl code sub parse_dist_name { +perl code my $file = shift; +perl code return(undef, undef, undef, undef) if not defined $file; +perl blank +perl code (undef, undef, $file) = File::Spec->splitpath($file); +perl blank +perl code my $version = qr/v?(?:\d+(?:_\d+)?|\d*(?:\.\d+(?:_\d+)?)+)/; +perl code $file =~ s/\.(?:par|tar\.gz|tar)$//i; +perl code my @elem = split /-/, $file; +perl code my (@dn, $dv, @arch, $pv); +perl code while (@elem) { +perl code my $e = shift @elem; +perl code if ( +perl code $e =~ /^$version$/o +perl code and not(# if not next token also a version +perl comment # (assumes an arch string doesnt start with a version...) +perl code @elem and $elem[0] =~ /^$version$/o +perl code ) +perl code ) { +perl blank +perl code $dv = $e; +perl code last; +perl code } +perl code push @dn, $e; +perl code } +perl blank +perl code my $dn; +perl code $dn = join('-', @dn) if @dn; +perl blank +perl code if (not @elem) { +perl code return( $dn, $dv, undef, undef); +perl code } +perl blank +perl code while (@elem) { +perl code my $e = shift @elem; +perl code if ($e =~ /^$version|any_version$/) { +perl code $pv = $e; +perl code last; +perl code } +perl code push @arch, $e; +perl code } +perl blank +perl code my $arch; +perl code $arch = join('-', @arch) if @arch; +perl blank +perl code return($dn, $dv, $arch, $pv); +perl code } +perl blank +perl comment =head2 generate_blib_stub +perl blank +perl comment Creates a F subdirectory in the current directory +perl comment and prepares a F with meta information for a +perl comment new PAR distribution. First argument should be the name of the +perl comment PAR distribution in a format understood by C. +perl comment Alternatively, named arguments resembling those of +perl comment C are accepted. +perl blank +perl comment After running C and injecting files into +perl comment the F directory, you can create a PAR distribution +perl comment using C. +perl comment This function is useful for creating custom PAR distributions +perl comment from scratch. (I.e. not from an unpacked CPAN distribution) +perl comment Example: +perl blank +perl comment use PAR::Dist; +perl comment use File::Copy 'copy'; +perl blank +perl comment generate_blib_stub( +perl comment name => 'MyApp', version => '1.00' +perl comment ); +perl comment copy('MyApp.pm', 'blib/lib/MyApp.pm'); +perl comment blib_to_par(); # generates the .par file! +perl blank +perl comment C will not overwrite existing files. +perl blank +perl comment =cut +perl blank +perl code sub generate_blib_stub { +perl code my %args = &_args; +perl code my $dist = $args{dist}; +perl code require Config; +perl blank +perl code my $name = $args{name}; +perl code my $version = $args{version}; +perl code my $suffix = $args{suffix}; +perl blank +perl code my ($parse_name, $parse_version, $archname, $perlversion) +perl code = parse_dist_name($dist); +perl blank +perl code $name ||= $parse_name; +perl code $version ||= $parse_version; +perl code $suffix = "$archname-$perlversion" +perl code if (not defined $suffix or $suffix eq '') +perl code and $archname and $perlversion; +perl blank +perl code $suffix ||= "$Config::Config{archname}-$Config::Config{version}"; +perl code if ( grep { not defined $_ } ($name, $version, $suffix) ) { +perl code warn "Could not determine distribution meta information from distribution name '$dist'"; +perl code return(); +perl code } +perl code $suffix =~ s/\.par$//; +perl blank +perl code if (not -f 'META.yml') { +perl code open META, '>', 'META.yml' +perl code or die "Could not open META.yml file for writing: $!"; +perl code print META << "YAML" if fileno(META); +perl code name: $name +perl code version: $version +perl code build_requires: {} +perl code conflicts: {} +perl code dist_name: $name-$version-$suffix.par +perl code distribution_type: par +perl code dynamic_config: 0 +perl code generated_by: 'PAR::Dist version $PAR::Dist::VERSION' +perl code license: unknown +perl code YAML +perl code close META; +perl code } +perl blank +perl code mkdir('blib'); +perl code mkdir(File::Spec->catdir('blib', 'lib')); +perl code mkdir(File::Spec->catdir('blib', 'script')); +perl blank +perl code return 1; +perl code } +perl blank +perl blank +perl comment =head2 contains_binaries +perl blank +perl comment This function is not exported by default. +perl blank +perl comment Opens a PAR archive tries to determine whether that archive +perl comment contains platform-specific binary code. +perl blank +perl comment Takes one named parameter: I. If only one parameter is +perl comment passed, it is treated as the I parameter. (Have a look +perl comment at the description in the C section above.) +perl blank +perl comment Throws a fatal error if the PAR archive could not be found. +perl blank +perl comment Returns one if the PAR was found to contain binary code +perl comment and zero otherwise. +perl blank +perl comment =cut +perl blank +perl code sub contains_binaries { +perl code require File::Find; +perl code my %args = &_args; +perl code my $dist = $args{dist}; +perl code return undef if not defined $dist or not -r $dist; +perl code require Cwd; +perl code require File::Path; +perl blank +perl comment # The unzipping will change directories. Remember old dir. +perl code my $old_cwd = Cwd::cwd(); +perl blank +perl comment # Unzip the base par to a temp. dir. +perl code (undef, my $base_dir) = _unzip_to_tmpdir( +perl code dist => $dist, subdir => 'blib' +perl code ); +perl code my $blibdir = File::Spec->catdir($base_dir, 'blib'); +perl code my $archdir = File::Spec->catdir($blibdir, 'arch'); +perl blank +perl code my $found = 0; +perl blank +perl code File::Find::find( +perl code sub { +perl code $found++ if -f $_ and not /^\.exists$/; +perl code }, +perl code $archdir +perl code ); +perl blank +perl code chdir($old_cwd); +perl blank +perl code File::Path::rmtree([$base_dir]); +perl blank +perl code return $found ? 1 : 0; +perl code } +perl blank +perl code 1; +perl blank +perl comment =head1 SEE ALSO +perl blank +perl comment L, L, L, L +perl blank +perl comment =head1 AUTHORS +perl blank +perl comment Audrey Tang Ecpan@audreyt.orgE 2003-2007 +perl blank +perl comment Steffen Mueller Esmueller@cpan.orgE 2005-2007 +perl blank +perl comment PAR has a mailing list, Epar@perl.orgE, that you can write to; +perl comment send an empty mail to Epar-subscribe@perl.orgE to join the list +perl comment and participate in the discussion. +perl blank +perl comment Please send bug reports to Ebug-par@rt.cpan.orgE. +perl blank +perl comment =head1 COPYRIGHT +perl blank +perl comment Copyright 2003-2007 by Audrey Tang Eautrijus@autrijus.orgE. +perl blank +perl comment This program is free software; you can redistribute it and/or modify it +perl comment under the same terms as Perl itself. +perl blank +perl comment See L +perl blank +perl comment =cut diff --git a/test/expected_dir/perl_pod_to_eof.pl b/test/expected_dir/perl_pod_to_eof.pl new file mode 100644 index 0000000..4f2b850 --- /dev/null +++ b/test/expected_dir/perl_pod_to_eof.pl @@ -0,0 +1 @@ +perl comment =head NAME diff --git a/test/expected_dir/php1.php b/test/expected_dir/php1.php new file mode 100644 index 0000000..a9d85ec --- /dev/null +++ b/test/expected_dir/php1.php @@ -0,0 +1,59 @@ +html code +html code +html code +html code +html code +html code +html code +html code +html code +html code +html code +html code +html code
FirstLastEmail +html code
+html blank +html code +html blank +html code +php code +php code +php code +html code +html code +html blank +html code +html blank +html code diff --git a/test/expected_dir/pike1.pike b/test/expected_dir/pike1.pike new file mode 100644 index 0000000..73b3cf7 --- /dev/null +++ b/test/expected_dir/pike1.pike @@ -0,0 +1,6 @@ +pike code #!/bin/env pike +pike comment /* Say hello. */ +pike code int main(int argc, array(string) argv) +pike code { +pike code Stdio.stdout.write("Hello, world.\n"); +pike code } diff --git a/test/expected_dir/pike2.pmod b/test/expected_dir/pike2.pmod new file mode 100644 index 0000000..2305875 --- /dev/null +++ b/test/expected_dir/pike2.pmod @@ -0,0 +1,241 @@ +pike comment // +pike comment // LPD.pmod: an implementation of the BSD lpd protocol (RFC 1179). +pike comment // This is a module for pike. +pike comment // 3 July 1998 Bill Welliver +pike comment // +pike comment // $Id: LPD.pmod,v 1.10 2008/01/13 17:02:43 nilsson Exp $ +pike comment // +pike blank +pike code #pike __REAL_VERSION__ +pike blank +pike comment //! A client for communicating with printers and print spoolers that +pike comment //! support the BSD lpd protocol (RFC 1179). +pike code class client { +pike code string host; +pike code int port; +pike code private object conn; +pike code int jobnum; +pike code string jobtype; +pike code string jobname; +pike blank +pike code private int connect(string host, int port) +pike code { +pike code int a=random(10); +pike comment // try to open one of the "official" local socket ports. +pike comment // not having one doesn't seem to be a problem with most LPD +pike comment // servers, but we should at least try. will probably fail +pike comment // if two try to open the same local port at once. ymmv. +pike code int res=conn->open_socket(721 + a); +pike blank +pike code return conn->connect(host, port); +pike code } +pike blank +pike comment //! @decl int set_job_type(string type) +pike comment //! Set the type of job to be sent to the printer to @i{type@}. +pike comment //! Valid types are: text, postscript and raw. +pike code int set_job_type(string type) +pike code { +pike code type=lower_case(type); +pike blank +pike code switch (type) { +pike code case "f": +pike code case "text": +pike code jobtype="f"; +pike code break; +pike blank +pike code case "o": +pike code case "postscript": +pike code case "ps": +pike code jobtype="o"; +pike code break; +pike blank +pike code default: +pike code case "l": +pike code case "raw": +pike code jobtype="l"; +pike code break; +pike code } +pike code return 1; +pike code } +pike blank +pike comment //! @decl int set_job_name(string name) +pike comment //! Sets the name of the print job to @i{name@}. +pike code int set_job_name(string name) +pike code { +pike code jobname=name; +pike code return 1; +pike code } +pike blank +pike comment //! @decl int start_queue(string queue) +pike comment //! Start the queue @i{queue@} if not already printing. +pike comment //! @returns +pike comment //! Returns 0 if unable to connect, 1 otherwise. +pike code int start_queue(string queue) +pike code { +pike code if(!queue) return 0; +pike blank +pike code if(!connect(host, port)) +pike code return 0; +pike blank +pike code conn->write(sprintf("%c%s\n", 01, queue)); +pike code string resp= conn->read(); +pike code conn->close(); +pike code return 1; +pike code } +pike blank +pike comment //! @decl string|int send_job(string queue, string job) +pike comment //! Send print job consisting of data @i{job@} to printer @i{queue@}. +pike comment //! @returns +pike comment //! Returns 1 if success, 0 otherwise. +pike code int send_job(string queue, string job) +pike code { +pike code string resp; +pike blank +pike code if(!queue) return 0; +pike blank +pike code if(!connect(host, port)) +pike code return 0; +pike comment // werror("connected to " + host + "\n"); +pike blank +pike code string control=""; +pike code control+="H"+gethostname()+"\n"; +pike code #if constant(getuid) && constant(getpwuid) +pike code control+="P"+(getpwuid(getuid())[0]||"nobody")+"\n"; +pike code #else +pike code control+="P-1\n"; +pike code #endif +pike code control+=(jobtype||"l")+"dfA"+ sprintf("%03d%s", jobnum, gethostname())+"\n"; +pike code if(jobname) +pike code { +pike code control+="J" + jobname + "\n"; +pike code control+="N" + jobname + "\n"; +pike code } +pike code else +pike code { +pike code control+="JPike LPD Client Job " + jobnum + "\n"; +pike code control+="NPike LPD Client Job " + jobnum + "\n"; +pike code } +pike code jobnum++; +pike code werror("job file:\n\n" + control + "\n\n"); +pike blank +pike code conn->write(sprintf("%c%s\n", 02, queue)); +pike code resp=conn->read(1); +pike code if((int)resp !=0) +pike code { +pike code werror("receive job failed.\n"); +pike code return 0; +pike code } +pike blank +pike code conn->write(sprintf("%c%s cfA%03d%s\n", 02, (string)sizeof(control), +pike code jobnum,gethostname())); +pike blank +pike code resp=conn->read(1); +pike code if((int)resp !=0) +pike code { +pike code werror("request receive control failed.\n"); +pike code return 0; +pike code } +pike blank +pike code conn->write(sprintf("%s%c", control, 0)); +pike blank +pike code resp=conn->read(1); +pike code if((int)resp !=0) +pike code { +pike code werror("send receive control failed.\n"); +pike code return 0; +pike code } +pike blank +pike code conn->write(sprintf("%c%s dfA%03d%s\n", 03, (string)sizeof(job), jobnum, +pike code gethostname())); +pike code resp=conn->read(1); +pike code if((int)resp !=0) +pike code { +pike code werror("request receive job failed.\n"); +pike code return 0; +pike code } +pike blank +pike blank +pike code conn->write(sprintf("%s%c", job, 0)); +pike blank +pike code resp=conn->read(1); +pike code if((int)resp !=0) +pike code { +pike code werror("send receive job failed.\n"); +pike code return 0; +pike code } +pike blank +pike blank +pike blank +pike comment // read the response. +pike blank +pike comment // resp=conn->read(); +pike code if((int)(resp)!=0) +pike code { +pike code conn->close(); +pike code return 0; +pike code } +pike code conn->close(); +pike comment // start_queue(queue); +pike code return 1; +pike code } +pike blank +pike comment //! @decl int delete_job(string queue, int|void job) +pike comment //! Delete job @i{job@} from printer @i{queue@}. +pike comment //! @returns +pike comment //! Returns 1 on success, 0 otherwise. +pike code int delete_job(string queue, int|void job) +pike code { +pike code if(!queue) return 0; +pike blank +pike code if(!connect(host, port)) +pike code return 0; +pike blank +pike code #if constant(getpwuid) && constant(getuid) +pike code string agent=(getpwuid(getuid())[0]||"nobody"); +pike code #else +pike code string agent="nobody"; +pike code #endif +pike blank +pike code if(job) +pike code conn->write(sprintf("%c%s %s %d\n", 05, queue, agent, job)); +pike code else +pike code conn->write(sprintf("%c%s %s\n", 05, queue, agent)); +pike code string resp= conn->read(); +pike code conn->close(); +pike code return 1; +pike code } +pike blank +pike blank +pike comment //! @decl string|int status(string queue) +pike comment //! Check the status of queue @i{queue@}. +pike comment //! @returns +pike comment //! Returns 0 on failure, otherwise returns the status response from the printer. +pike code string|int status(string queue) +pike code { +pike code if(!queue) return 0; +pike blank +pike code if(!connect(host, port)) +pike code return 0; +pike blank +pike code conn->write(sprintf("%c%s\n", 04, queue)); +pike code string resp= conn->read(); +pike code conn->close(); +pike code return resp; +pike code } +pike blank +pike comment //! Create a new LPD client connection. +pike comment //! @param hostname +pike comment //! Contains the hostname or ipaddress of the print host. +pike comment //! if not provided, defaults to @i{localhost@}. +pike comment //! @param portnum +pike comment //! Contains the port the print host is listening on. +pike comment //! if not provided, defaults to port @i{515@}, the RFC 1179 standard. +pike code void create(string|void hostname, int|void portnum) +pike code { +pike code host=hostname || "localhost"; +pike code port=portnum || 515; +pike code conn=Stdio.File(); +pike code jobnum=1; +pike code } +pike code } +pike blank diff --git a/test/expected_dir/py1.py b/test/expected_dir/py1.py new file mode 100644 index 0000000..2f600fb --- /dev/null +++ b/test/expected_dir/py1.py @@ -0,0 +1,18 @@ +python comment # some python code +python comment # lorem +python comment # ipsum +python comment # foo +python blank +python code class Foo: +python comment """ +python comment This is a foo class +python comment It doesn't do anything +python comment Therefore this doc comment is pointless +python comment """ +python blank +python code def __init__(self, bar): +python comment """short doc comment""" +python code print(bar) +python blank +python code def string(self): +python code print('This is a string') diff --git a/test/expected_dir/rexx1.rex b/test/expected_dir/rexx1.rex new file mode 100644 index 0000000..ff945d4 --- /dev/null +++ b/test/expected_dir/rexx1.rex @@ -0,0 +1,311 @@ +rexx comment /* REXX FLTTBL Cloned from DUMPTBL 960619 to produce a flat +rexx comment version (up to 32K characters wide) of any ISPF +rexx comment table. +rexx blank +rexx comment Written by Frank Clarke, Oldsmar, FL +rexx blank +rexx comment Impact Analysis +rexx comment . SYSPROC LA +rexx comment . SYSPROC TRAPOUT +rexx blank +rexx comment Modification History +rexx comment 19960918 fxc added some error-checking +rexx comment 19970115 fxc upgrade REXXSKEL from v.960606 to v.970113; add +rexx comment RESTARTability; +rexx comment 19991231 fxc upgrade REXXSKEL from v.970113 to v.19991109; +rexx comment RXSKLY2K; DECOMM; LRECL reduced from 32K to "min +rexx comment needed"; +rexx blank +rexx code */ arg argline +rexx code address TSO /* REXXSKEL ver.19991109 */ +rexx code arg parms "((" opts +rexx blank +rexx code signal on syntax +rexx code signal on novalue +rexx blank +rexx code call TOOLKIT_INIT /* conventional start-up -*/ +rexx code rc = Trace(tv) +rexx code info = parms /* to enable parsing */ +rexx blank +rexx code if \sw.inispf then do +rexx code arg line +rexx code line = line "(( RESTARTED" /* tell the next invocation */ +rexx code "ISPSTART CMD("exec_name line")" /* Invoke ISPF if nec. */ +rexx code exit /* ...and restart it */ +rexx code end +rexx blank +rexx code call A_INIT /* -*/ +rexx blank +rexx code "NEWSTACK" +rexx code if \sw.0error_found then, +rexx code call C_TABLE_OPS /* -*/ +rexx code if \sw.0error_found then, +rexx code call D_PUMP_TBL /* -*/ +rexx blank +rexx code "DELSTACK" +rexx blank +rexx code if sw.restarted then do +rexx code rc = OutTrap("ll.") +rexx code exit 4 +rexx code end +rexx blank +rexx code exit /*@ FLTTBL */ +rexx comment /* +rexx comment . ----------------------------------------------------------------- */ +rexx code A_INIT: /*@ */ +rexx code if branch then call BRANCH +rexx code address TSO +rexx blank +rexx code call AA_KEYWDS /* -*/ +rexx code parse var info $tn$ . /* table-name required */ +rexx code if $tn$ = "" then do +rexx code helpmsg = "Tablename is required." +rexx code call HELP +rexx code end +rexx blank +rexx code parse value outdsn "FLATTBLS."$tn$ with, +rexx code outdsn . +rexx blank +rexx code xefef = "efef"x +rexx code if tblds = "" then do +rexx code call AB_FIND_LIBRARY /* -*/ +rexx code if tblds = "" then do +rexx code helpmsg = "Table" $tn$ "was not found in ISPTLIB. Please", +rexx code "restart specifying a library name as shown below." +rexx code call HELP /* ...and don't come back */ +rexx code end +rexx code end +rexx code else, +rexx code if Left(tblds,1) = "'" then tblds = Strip(tblds,,"'") +rexx code else tblds = Userid()"."tblds +rexx blank +rexx code return /*@ A_INIT */ +rexx comment /* +rexx comment . ----------------------------------------------------------------- */ +rexx code AA_KEYWDS: /*@ */ +rexx code if branch then call BRANCH +rexx code address TSO +rexx blank +rexx code tblds = KEYWD("IN") +rexx code outdsn = KEYWD("OUTPUT") +rexx code sortseq = KEYWD("SORT") +rexx code sw.0purge = SWITCH("DELETEBEHIND") +rexx blank +rexx code parse value KEYWD("ADD") "0" with bytes_to_add . +rexx blank +rexx code return /*@ AA_KEYWDS */ +rexx comment /* +rexx comment was not specified. Locate the table in ISPTLIB. +rexx comment . ----------------------------------------------------------------- */ +rexx code AB_FIND_LIBRARY: /*@ */ +rexx code if branch then call BRANCH +rexx code address TSO +rexx blank +rexx code "NEWSTACK" +rexx code "LA ISPTLIB ((STACK LINE" +rexx code pull tliblist +rexx code "DELSTACK" +rexx blank +rexx code do Words(tliblist) /* each library */ +rexx code parse var tliblist tblds tliblist +rexx code if Sysdsn("'"tblds"("$tn$")'") = "OK" then return +rexx code end /* tliblist */ +rexx code tblds = "" +rexx blank +rexx code return /*@ AB_FIND_LIBRARY */ +rexx comment /* +rexx comment . ----------------------------------------------------------------- */ +rexx code C_TABLE_OPS: /*@ */ +rexx code if branch then call BRANCH +rexx code address ISPEXEC +rexx blank +rexx code call CA_OPEN_TBL /* -*/ +rexx code call CS_SPIN_TBL /* -*/ +rexx code call CZ_DROP_TBL /* -*/ +rexx blank +rexx code return /*@ C_TABLE_OPS */ +rexx comment /* +rexx comment . ----------------------------------------------------------------- */ +rexx code CA_OPEN_TBL: /*@ */ +rexx code if branch then call BRANCH +rexx code address ISPEXEC +rexx blank +rexx code "LIBDEF ISPTLIB DATASET ID('"tblds"') STACK" +rexx code "TBSTATS" $tn$ "STATUS1(s1) STATUS2(s2) ROWCURR(rowct)" +rexx code if s1 > 1 then do +rexx code say "Table" $tn$ "not available." +rexx code sw.0error_found = "1"; return +rexx code end; else, +rexx code if s2 = 1 then, /* not open */ +rexx code "TBOPEN " $tn$ "NOWRITE" +rexx code else "TBTOP" $tn$ +rexx code "LIBDEF ISPTLIB" +rexx code if sw.0error_found then return +rexx code "TBQUERY" $tn$ "KEYS(keylist)", +rexx code "NAMES(nmlist)" +rexx code parse var keylist "(" keylist ")" +rexx code parse var nmlist "(" nmlist ")" +rexx code namelist = keylist nmlist +rexx blank +rexx code if sortseq <> "" then "TBSORT" $tn$ "FIELDS("sortseq")" +rexx blank +rexx code return /*@ CA_OPEN_TBL */ +rexx comment /* +rexx comment . Given: contains all the defined names for this table. +rexx comment The table has been TOPped. +rexx comment . ----------------------------------------------------------------- */ +rexx code CS_SPIN_TBL: Procedure expose, /*@ hide everything */ +rexx code expose (tk_globalvars), /* except these */ +rexx code $tn$ namelist xefef tblds rows keylist nmlist maxlen +rexx code cs_tv = Trace() +rexx code if branch then call BRANCH +rexx code address ISPEXEC +rexx blank +rexx code maxlen = 0 /* maximum line length */ +rexx code do forever +rexx code "TBSKIP" $tn$ "SAVENAME(xvars)" +rexx code if rc > 0 then leave /* we're done... */ +rexx code line = "" /* set empty */ +rexx comment /* add blocks of "var .. varvalue .." */ +rexx code do cx = 1 to Words(namelist) +rexx code thiswd = Word(namelist,cx) +rexx code line = line thiswd xefef Value(thiswd) xefef +rexx code end /* cx */ +rexx code rc = Trace("O"); rc = Trace(cs_tv) +rexx code parse var xvars "(" xvars ")" +rexx comment /* add a block of "XVARS .. xvarlist .." */ +rexx code line = line "XVARS" xefef xvars xefef +rexx comment /* add blocks of "xvar .. xvarvalue .." */ +rexx code do cx = 1 to Words(xvars) +rexx code thiswd = Word(xvars,cx) +rexx code line = line thiswd xefef Value(thiswd) xefef +rexx code end /* cx */ +rexx code rc = Trace("O"); rc = Trace(cs_tv) +rexx code maxlen = Max(maxlen,Length(line)) +rexx code queue line +rexx code end /* forever */ +rexx blank +rexx code lines_in_stack = queued() +rexx code line = "Contents of" $tn$ "in" tblds, +rexx code "("lines_in_stack" rows) KEYS("keylist") NAMES("nmlist")." +rexx code push line /* make it the first line */ +rexx code maxlen = Max(maxlen,Length(line)) +rexx code if monitor then say "Maximum line length is" maxlen +rexx blank +rexx code return /*@ CS_SPIN_TBL */ +rexx comment /* +rexx comment . ----------------------------------------------------------------- */ +rexx code CZ_DROP_TBL: /*@ */ +rexx code if branch then call BRANCH +rexx code address ISPEXEC +rexx blank +rexx code if s2 = 1 then, /* table was not open at start*/ +rexx code "TBEND" $tn$ +rexx blank +rexx code return /*@ CZ_DROP_TBL */ +rexx comment /* +rexx comment . ----------------------------------------------------------------- */ +rexx code D_PUMP_TBL: /*@ */ +rexx code if branch then call BRANCH +rexx code address TSO +rexx blank +rexx code if monitor then say, +rexx code "Writing text." +rexx blank +rexx code maxlen = maxlen + 4 + bytes_to_add /* set LRECL */ +rexx code vbmax.0 = "NEW CATALOG UNIT(SYSDA) SPACE(1 5) TRACKS", +rexx code "RECFM(V B) LRECL("maxlen") BLKSIZE(0)" +rexx code vbmax.1 = "SHR" /* if it already exists... */ +rexx blank +rexx code tempstat = Sysdsn(outdsn) = "OK" /* 1=exists, 0=missing */ +rexx code "ALLOC FI($TMP) DA("outdsn") REU" vbmax.tempstat +rexx code rcx = rc +rexx code "EXECIO" queued() "DISKW $TMP (FINIS" +rexx code rcx = max(rcx,rc) +rexx code "FREE FI($TMP)" +rexx blank +rexx code if rcx = 0 & sw.0purge then do +rexx code address ISPEXEC +rexx code "LIBDEF ISPTLIB DATASET ID('"tblds"') STACK" +rexx code "TBERASE" $tn$ +rexx code if rc = 0 then say $tn$ "was deleted" +rexx code "LIBDEF ISPTLIB" +rexx code end +rexx blank +rexx code return /*@ D_PUMP_TBL */ +rexx comment /* +rexx comment . ----------------------------------------------------------------- */ +rexx code LOCAL_PREINIT: /*@ customize opts */ +rexx code if branch then call BRANCH +rexx code address TSO +rexx blank +rexx blank +rexx code return /*@ LOCAL_PREINIT */ +rexx comment /* +rexx comment . ----------------------------------------------------------------- */ +rexx code HELP: /*@ */ +rexx code address TSO;"CLEAR" +rexx code if helpmsg <> "" then do ; say helpmsg; say ""; end +rexx code ex_nam = Left(exec_name,8) /* predictable size */ +rexx code say " "ex_nam" produces a flattened version of any ISPF table " +rexx code say " into a VB-form dataset of minimum necessary LRECL." +rexx code say " " +rexx code say " The field contents are written in KEYPHRS format " +rexx code say " (var .. varval ..) " +rexx code say " key-fields first, followed by name-fields, followed by the " +rexx code say " names of any extension variables key-phrased by 'XVARS', " +rexx code say " followed by the extension variables themselves in KEYPHRS " +rexx code say " format. " +rexx code say " " +rexx code say " The first record on the file identifies the table name, the " +rexx code say " source library, the number of rows processed, and the key- and " +rexx code say " name-fields. " +rexx code say " " +rexx code say " more.... " +rexx code pull +rexx code "CLEAR" +rexx code say " Syntax: "ex_nam" (Required)" +rexx code say " " +rexx code say " (Defaults)" +rexx code say " " +rexx code say " (Defaults)" +rexx code say " " +rexx code say " identifies the table to be dumped. " +rexx code say " " +rexx code say " identifies the ISPF Table library which holds ." +rexx code say " If is not specified, ISPTLIB will be " +rexx code say " searched to find the correct dataset. " +rexx code say " " +rexx code say " (default: FLATTBLS.) names the output file. " +rexx code say " will be created if it does not exist. " +rexx code say " " +rexx code say " causes the table to be sorted as indicated before " +rexx code say " being dumped. " +rexx code say " " +rexx code say " (default=0) causes the LRECL of the output dataset " +rexx code say " to be extended to enable updating. " +rexx code pull +rexx code "CLEAR" +rexx code say " Debugging tools provided include: " +rexx code say " " +rexx code say " MONITOR: displays key information throughout processing. " +rexx code say " Displays most paragraph names upon entry. " +rexx code say " " +rexx code say " NOUPDT: by-pass all update logic. " +rexx code say " " +rexx code say " BRANCH: show all paragraph entries. " +rexx code say " " +rexx code say " TRACE tv: will use value following TRACE to place the " +rexx code say " execution in REXX TRACE Mode. " +rexx code say " " +rexx code say " " +rexx code say " Debugging tools can be accessed in the following manner: " +rexx code say " " +rexx code say " TSO "ex_nam" parameters (( debug-options " +rexx code say " " +rexx code say " For example: " +rexx code say " " +rexx code say " TSO "ex_nam" vt2231 add 17 (( MONITOR TRACE ?R " +rexx code address ISPEXEC "CONTROL DISPLAY REFRESH" +rexx code exit /*@ HELP */ +rexx comment /* REXXSKEL back-end removed for space */ diff --git a/test/expected_dir/rhtml1.rhtml b/test/expected_dir/rhtml1.rhtml new file mode 100644 index 0000000..53d1d03 --- /dev/null +++ b/test/expected_dir/rhtml1.rhtml @@ -0,0 +1,25 @@ +html code +html code +html code Ajax table manipulation attempt +ruby code <%= stylesheet_link_tag "style" %> +ruby code <%= javascript_include_tag :defaults %> +html code +html code +html blank +html code
+ruby code <%= @content_for_layout %> +html code
+html blank +ruby code <%= ruby code %>
+html comment +ruby code <%- multi +ruby code lines of code +ruby comment # even inline comments! +ruby code "damn" # that's sweet +html code %> +ruby code
<%= ruby_code %>
+html code +html code diff --git a/test/expected_dir/ruby1.rb b/test/expected_dir/ruby1.rb new file mode 100644 index 0000000..25b7f9c --- /dev/null +++ b/test/expected_dir/ruby1.rb @@ -0,0 +1,22 @@ +ruby code require 'foo' +ruby blank +ruby comment #comment +ruby comment #comment +ruby comment #comment with "string" +ruby blank +ruby code module Foo +ruby code class Bar #comment +ruby code def foo +ruby code "double_quoted string" +ruby code "embedded double_quote \"" +ruby code more_code = true +ruby code 'single_quoted string' +ruby code 'embedded single_quote\'' +ruby code more_code = true +ruby code "multiline dquote +ruby code more quote +ruby code # not a comment +ruby code " +ruby code end +ruby code end +ruby code end diff --git a/test/expected_dir/scala1.scala b/test/expected_dir/scala1.scala new file mode 100644 index 0000000..fa67832 --- /dev/null +++ b/test/expected_dir/scala1.scala @@ -0,0 +1,63 @@ +scala code import scala.actors.Actor +scala blank +scala code case object Ping +scala code case object Pong +scala code case object Stop +scala blank +scala comment /** +scala comment * Ping class +scala comment */ +scala code class Ping(count: int, pong: Actor) extends Actor { +scala code def act() { +scala code var pingsLeft = count - 1 +scala code pong ! Ping +scala code while (true) { +scala code receive { +scala code case Pong => +scala code if (pingsLeft % 1000 == 0) +scala code Console.println("Ping: pong") +scala code if (pingsLeft > 0) { +scala code pong ! Ping +scala code pingsLeft -= 1 +scala code } else { +scala code Console.println("Ping: stop") +scala code pong ! Stop +scala code exit() +scala code } +scala code } +scala code } +scala code } +scala code } +scala blank +scala comment /** +scala comment * Pong class +scala comment */ +scala code class Pong extends Actor { +scala code def act() { +scala code var pongCount = 0 +scala code while (true) { +scala code receive { +scala comment //pong back the ping +scala code case Ping => +scala code if (pongCount % 1000 == 0) +scala code Console.println("Pong: ping "+pongCount) +scala code sender ! Pong +scala code pongCount = pongCount + 1 +scala comment //stop ping ponging +scala code case Stop => +scala code Console.println("Pong: stop") +scala code exit() +scala code } +scala code } +scala code } +scala code } +scala blank +scala comment /* +scala comment * And this is the main application, playing a game of ping pong +scala comment */ +scala code object PingPong extends Application { +scala code val pong = new Pong +scala code val ping = new Ping(100000, pong) +scala code ping.start +scala code pong.start +scala code } diff --git a/test/expected_dir/schema.xsd b/test/expected_dir/schema.xsd new file mode 100644 index 0000000..59df2e6 --- /dev/null +++ b/test/expected_dir/schema.xsd @@ -0,0 +1,68 @@ +xmlschema code +xmlschema comment +xmlschema code +xmlschema code +xmlschema code +xmlschema code 0836217462 +xmlschema code +xmlschema code +xmlschema code Being a Dog Is a Full-Time Job +xmlschema code +xmlschema code +xmlschema code +xmlschema code Charles M Schulz +xmlschema code +xmlschema code +xmlschema code 1922-11-26 +xmlschema code +xmlschema code +xmlschema code 2000-02-12 +xmlschema code +xmlschema code +xmlschema code +xmlschema code +xmlschema code Peppermint Patty +xmlschema code +xmlschema code +xmlschema code 1966-08-22 +xmlschema code +xmlschema code +xmlschema code bold, brash and tomboyish +xmlschema code +xmlschema code +xmlschema code +xmlschema code +xmlschema code Snoopy +xmlschema code +xmlschema code +xmlschema code 1950-10-04 +xmlschema code +xmlschema code +xmlschema code extroverted beagle +xmlschema code +xmlschema code +xmlschema code +xmlschema code +xmlschema code Schroeder +xmlschema code +xmlschema code +xmlschema code 1951-05-30 +xmlschema code +xmlschema code +xmlschema code brought classical music to the Peanuts strip +xmlschema code +xmlschema code +xmlschema code +xmlschema code +xmlschema code Lucy +xmlschema code +xmlschema code +xmlschema code 1952-03-03 +xmlschema code +xmlschema code +xmlschema code bossy, crabby and selfish +xmlschema code +xmlschema code +xmlschema code +xmlschema code diff --git a/test/expected_dir/scheme.scm b/test/expected_dir/scheme.scm new file mode 100644 index 0000000..5db5fdc --- /dev/null +++ b/test/expected_dir/scheme.scm @@ -0,0 +1,32 @@ +scheme code (+ 1 (/ 1 0) 3) +scheme comment ; => A divide by zero error is raised +scheme blank +scheme code (with-failure-continuation +scheme code (lambda (error-record error-k) +scheme code 'error) +scheme code (lambda () (+ 1 (/ 1 0) 3))) +scheme comment ; => The symbol 'error +scheme blank +scheme code (with-failure-continuation +scheme code (lambda (error-record error-k) +scheme code (error-k 2)) +scheme code (lambda () (+ 1 (/ 1 0) 3))) +scheme comment ; => 6 +scheme blank +scheme code (with-failure-continuation +scheme code (lambda (error-record error-k) +scheme code (throw error-record error-k)) +scheme code (lambda () (+ 1 (/ 1 0) 3))) +scheme comment ; => A divide by zero error is raised +scheme blank +scheme code (with-failure-continuation +scheme code (lambda (error-record error-k) +scheme code (throw (make-error '/ "could not perform the division.") error-k)) +scheme code (lambda () (+ 1 (/ 1 0) 3))) +scheme comment ; => An error is raised: Error in /: could not perform the division. +scheme blank +scheme code (with-failure-continuation +scheme code (lambda (error-record error-k) +scheme code (error 'example-function "could not evaluate the expression.")) +scheme code (lambda () (+ 1 (/ 1 0) 3))) +scheme comment ; => An error is raised: Error in example-function: could not evaluate the expression. diff --git a/test/expected_dir/scilab.sci b/test/expected_dir/scilab.sci new file mode 100644 index 0000000..16fb951 --- /dev/null +++ b/test/expected_dir/scilab.sci @@ -0,0 +1,35 @@ +scilab comment // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab +scilab comment // Copyright (C) INRIA - Serge STEER +scilab comment // +scilab comment // This file must be used under the terms of the CeCILL. +scilab comment // This source file is licensed as described in the file COPYING, which +scilab comment // you should have received as part of this distribution. The terms +scilab comment // are also available at +scilab comment // http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt +scilab blank +scilab code function I=sub2ind(dims,varargin) +scilab comment //sub2ind is used to determine the equivalent single index +scilab comment //corresponding to a given set of subscript values. +scilab blank +scilab comment //I = sub2ind(dims,i1,i2,..) returns the linear index equivalent to the +scilab comment //row, column, ... subscripts in the arrays i1,i2,.. for an matrix of +scilab comment //size dims. +scilab blank +scilab comment //I = sub2ind(dims,Mi) returns the linear index +scilab comment //equivalent to the n subscripts in the columns of the matrix Mi for a matrix +scilab comment //of size dims. +scilab blank +scilab code d=[1;cumprod(matrix(dims(1:$-1),-1,1))] +scilab code for i=1:size(varargin) +scilab code if varargin(i)==[] then I=[],return,end +scilab code end +scilab blank +scilab code if size(varargin)==1 then //subindices are the columns of the argument +scilab code I=(varargin(1)-1)*d+1 +scilab code else //subindices are given as separated arguments +scilab code I=1 +scilab code for i=1:size(varargin) +scilab code I=I+(varargin(i)-1)*d(i) +scilab code end +scilab code end +scilab code endfunction diff --git a/test/expected_dir/sh1.sh b/test/expected_dir/sh1.sh new file mode 100644 index 0000000..665557c --- /dev/null +++ b/test/expected_dir/sh1.sh @@ -0,0 +1,5 @@ +shell comment #!/bin/sh +shell blank +shell code ls -la +shell comment # comment +shell code echo hello #comment diff --git a/test/expected_dir/smalltalk1.st b/test/expected_dir/smalltalk1.st new file mode 100644 index 0000000..07859e5 --- /dev/null +++ b/test/expected_dir/smalltalk1.st @@ -0,0 +1,19 @@ +smalltalk comment "====================================================================== +smalltalk comment | +smalltalk comment | Benchmark for streams +smalltalk comment | +smalltalk comment | +smalltalk comment ======================================================================" +smalltalk blank +smalltalk blank +smalltalk code Eval [ +smalltalk code n := Smalltalk arguments isEmpty +smalltalk code ifTrue: [ 10000 ] +smalltalk code ifFalse: [ 1 max: Smalltalk arguments first asInteger ]. +smalltalk blank +smalltalk code hello := String new writeStream. +smalltalk code n timesRepeat: [ hello nextPutAll: 'hello +smalltalk code \' ]. "this is a comment +smalltalk comment so this line is a comment too\" +smalltalk code hello position displayNl +smalltalk code "but the previous one, and this one too, are not!" ] diff --git a/test/expected_dir/sql1.sql b/test/expected_dir/sql1.sql new file mode 100644 index 0000000..ed8ecd9 --- /dev/null +++ b/test/expected_dir/sql1.sql @@ -0,0 +1,31 @@ +sql comment // ----------------------------------------------------------------------- +sql comment // Filename: minvalue.sql +sql comment // Purpose: Select the Nth lowest value from a table +sql comment // Date: 18-Apr-2001 +sql comment // Author: Deepak Rai, SSE, Satyam Computer Services Ltd. India +sql comment // ----------------------------------------------------------------------- +sql blank +sql comment ## Comment with a hash symbol ## +sql code select level, min('col_name') from my_table +sql code where level = '&n' +sql code connect by prior ('col_name') < 'col_name') +sql code group by level; +sql blank +sql comment /* a block comment +sql comment -- finished here */ +sql blank +sql comment -- Example: +sql comment -- +sql comment -- Given a table called emp with the following columns: +sql comment -- id number +sql comment -- name varchar2(20) +sql comment -- sal number +sql comment -- +sql comment -- For the second lowest salary: +sql comment -- +sql comment -- select level, min(sal) from emp +sql comment -- where level=2 +sql comment -- connect by prior sal < sal +sql comment -- group by level +sql comment -- +sql blank diff --git a/test/expected_dir/stratego.str b/test/expected_dir/stratego.str new file mode 100644 index 0000000..483596d --- /dev/null +++ b/test/expected_dir/stratego.str @@ -0,0 +1,25 @@ +stratego comment /** +stratego comment * Sample code from Stratego XT Manual +stratego comment */ +stratego blank +stratego code rules +stratego code InlineF : +stratego code |[ let f(xs) = e in e'[f(es)] ]| -> +stratego code |[ let f(xs) = e in e'[e[es/xs]] ]| +stratego blank +stratego code InlineV : +stratego code |[ let x = e in e'[x] ]| -> |[ let x = e in e'[e] ]| +stratego blank +stratego code Dead : +stratego code |[ let x = e in e' ]| -> |[ e' ]| +stratego code where (x,e') +stratego blank +stratego code Extract(f,xs) : +stratego code |[ e ]| -> |[ let f(xs) = e in f(xs) ]| +stratego blank +stratego code Hoist : +stratego code |[ let x = e1 in let f(xs) = e2 in e3 ]| -> +stratego code |[ let f(xs) = e2 in let x = e1 in e3 ]| +stratego code where (x, e2) +stratego blank +stratego comment // better watch those apostrophes! diff --git a/test/expected_dir/structured_basic.b b/test/expected_dir/structured_basic.b new file mode 100644 index 0000000..00a1759 --- /dev/null +++ b/test/expected_dir/structured_basic.b @@ -0,0 +1,20 @@ +structured_basic code INPUT "What is your name: "; U$ +structured_basic code PRINT "Hello "; U$ +structured_basic comment REM Test +structured_basic code INPUT "How many stars do you want: "; N +structured_basic code S$ = "" +structured_basic code FOR I = 1 TO N +structured_basic code S$ = S$ + "*" +structured_basic code NEXT I +structured_basic code PRINT S$ +structured_basic blank +structured_basic comment REM +structured_basic code INPUT "Do you want more stars? "; A$ +structured_basic code IF LEN(A$) = 0 THEN GOTO 110 +structured_basic code A$ = LEFT$(A$, 1) +structured_basic code IF (A$ = "Y") OR (A$ = "y") THEN GOTO 40 +structured_basic code PRINT "Goodbye "; +structured_basic code FOR I = 1 TO 200 +structured_basic code PRINT U$; " "; +structured_basic code NEXT I +structured_basic code PRINT diff --git a/test/expected_dir/structured_basic.bas b/test/expected_dir/structured_basic.bas new file mode 100644 index 0000000..00a1759 --- /dev/null +++ b/test/expected_dir/structured_basic.bas @@ -0,0 +1,20 @@ +structured_basic code INPUT "What is your name: "; U$ +structured_basic code PRINT "Hello "; U$ +structured_basic comment REM Test +structured_basic code INPUT "How many stars do you want: "; N +structured_basic code S$ = "" +structured_basic code FOR I = 1 TO N +structured_basic code S$ = S$ + "*" +structured_basic code NEXT I +structured_basic code PRINT S$ +structured_basic blank +structured_basic comment REM +structured_basic code INPUT "Do you want more stars? "; A$ +structured_basic code IF LEN(A$) = 0 THEN GOTO 110 +structured_basic code A$ = LEFT$(A$, 1) +structured_basic code IF (A$ = "Y") OR (A$ = "y") THEN GOTO 40 +structured_basic code PRINT "Goodbye "; +structured_basic code FOR I = 1 TO 200 +structured_basic code PRINT U$; " "; +structured_basic code NEXT I +structured_basic code PRINT diff --git a/test/expected_dir/tcl1.tcl b/test/expected_dir/tcl1.tcl new file mode 100644 index 0000000..eeccd1a --- /dev/null +++ b/test/expected_dir/tcl1.tcl @@ -0,0 +1,35 @@ +tcl comment #!/usr/local/bin/tclsh +tcl blank +tcl comment # Dos2Unix +tcl comment # Convert a file to Unix-style line endings +tcl comment # If the file is a directory, then recursively +tcl comment # convert all the files in the directory and below. +tcl comment # +tcl comment # Arguments +tcl comment # f The name of a file or directory. +tcl comment # +tcl comment # Side Effects: +tcl comment # Rewrites the file to have LF line-endings +tcl blank +tcl code proc Dos2Unix {f} { +tcl code puts $f +tcl code if {[file isdirectory $f]} { +tcl code foreach g [glob [file join $f *]] { +tcl code Dos2Unix $g +tcl code } +tcl code } else { +tcl code set in [open $f] +tcl code set out [open $f.new w] +tcl code fconfigure $out -translation lf +tcl code puts -nonewline $out [read $in] +tcl code close $out +tcl code close $in +tcl code file rename -force $f.new $f +tcl code } +tcl code } +tcl blank +tcl comment # Process each command-line argument +tcl blank +tcl code foreach f $argv { +tcl code Dos2Unix $f +tcl code } diff --git a/test/expected_dir/vala1.vala b/test/expected_dir/vala1.vala new file mode 100644 index 0000000..1453c0d --- /dev/null +++ b/test/expected_dir/vala1.vala @@ -0,0 +1,61 @@ +vala code using GLib; +vala blank +vala blank +vala blank +vala comment // Class which makes the event +vala code public class Game : Object { +vala comment // Note the use of the signal keyword +vala code public signal void score_change (int newScore, ref bool cancel); +vala blank +vala code int _score; +vala blank +vala comment // Score Property +vala code public int score { +vala code get { +vala code return _score; +vala code } +vala code set { +vala code if (_score != value) { +vala code bool cancel = false; +vala code score_change (value, ref cancel); +vala code if (! cancel) +vala code _score = value; +vala code } +vala code } +vala code } +vala code } +vala blank +vala comment // Class which handles the event +vala code public class Referee : Object +vala code { +vala code public Game game { get; construct; } +vala blank +vala code public Referee (construct Game game) { +vala code } +vala blank +vala code construct { +vala comment // Monitor when a score changes in the game +vala code game.score_change += game_score_change; +vala code } +vala blank +vala comment // Notice how this method signature matches the score_change signal's signature +vala code private void game_score_change (Game game, int new_score, ref bool cancel) { +vala code if (new_score < 100) +vala code stdout.printf ("Good Score\n"); +vala code else { +vala code cancel = true; +vala code stdout.printf ("No Score can be that high!\n"); +vala code } +vala code } +vala code } +vala blank +vala comment // Class to test it all +vala code public class GameTest : Object +vala code { +vala code public static void main () { +vala code var game = new Game (); +vala code var referee = new Referee (game); +vala code game.score = 70; +vala code game.score = 110; +vala code } +vala code } diff --git a/test/expected_dir/vb.aspx b/test/expected_dir/vb.aspx new file mode 100644 index 0000000..aed2fe2 --- /dev/null +++ b/test/expected_dir/vb.aspx @@ -0,0 +1,26 @@ +visualbasic code <%@ Page Language="VB" %> +html code +html code +html code +html code Basic ASP.NET Web Page +html code +html code +html code
+html code

Welcome to ASP.NET

+html code

Type your name and click the button.

+html code

+html code +html code +html code

+html code

+html code +html code

+html code
+html code +html code diff --git a/test/expected_dir/vb1.vb b/test/expected_dir/vb1.vb new file mode 100644 index 0000000..d450687 --- /dev/null +++ b/test/expected_dir/vb1.vb @@ -0,0 +1,16 @@ +visualbasic code class foo +visualbasic comment ' comment +visualbasic blank +visualbasic code require File.dirname(__FILE__) + '/../test_helper' +visualbasic code include Lingo +visualbasic blank +visualbasic code class ShellTest < LingoTest +visualbasic code def test_comment +visualbasic code p = Languages::Shell.parse(" #comment") +visualbasic code assert_equal({ 'shell' => { :comment => [" #comment"] } }, p.output_buffers) +visualbasic code end +visualbasic blank +visualbasic code def test_comprehensive +visualbasic code verify_parse("sh1.sh") +visualbasic code end +visualbasic code end diff --git a/test/expected_dir/vbs1.vbs b/test/expected_dir/vbs1.vbs new file mode 100644 index 0000000..639b463 --- /dev/null +++ b/test/expected_dir/vbs1.vbs @@ -0,0 +1,14 @@ +visualbasic blank +visualbasic code require File.dirname(__FILE__) + '/../test_helper' +visualbasic code include Lingo +visualbasic blank +visualbasic code class ShellTest < LingoTest +visualbasic code def test_comment +visualbasic code p = Languages::Shell.parse(" #comment") +visualbasic code assert_equal({ 'shell' => { :comment => [" #comment"] } }, p.output_buffers) +visualbasic code end +visualbasic blank +visualbasic code def test_comprehensive +visualbasic code verify_parse("sh1.sh") +visualbasic code end +visualbasic code end diff --git a/test/expected_dir/vhdl1.vhd b/test/expected_dir/vhdl1.vhd new file mode 100644 index 0000000..64fd306 --- /dev/null +++ b/test/expected_dir/vhdl1.vhd @@ -0,0 +1,92 @@ +vhdl comment ------------------------------------------------------------ +vhdl comment -- Combinational Logic Design +vhdl comment -- (ESD book figure 2.4) +vhdl comment -- by Weijun Zhang, 04/2001 +vhdl comment -- +vhdl comment -- A simple example of VHDL Structure Modeling +vhdl comment -- we might define two components in two separate files, +vhdl comment -- in main file, we use port map statement to instantiate +vhdl comment -- the mapping relationship between each components +vhdl comment -- and the entire circuit. +vhdl comment ------------------------------------------------------------ +vhdl blank +vhdl code library ieee; -- component #1 +vhdl code use ieee.std_logic_1164.all; +vhdl blank +vhdl code entity OR_GATE is +vhdl code port( X: in std_logic; +vhdl code Y: in std_logic; +vhdl code F2: out std_logic +vhdl code ); +vhdl code end OR_GATE; +vhdl blank +vhdl code architecture behv of OR_GATE is +vhdl code begin +vhdl code process(X,Y) +vhdl code begin +vhdl code F2 <= X or Y; -- behavior des. +vhdl code end process; +vhdl code end behv; +vhdl blank +vhdl comment ------------------------------------------------------------- +vhdl blank +vhdl code library ieee; -- component #2 +vhdl code use ieee.std_logic_1164.all; +vhdl blank +vhdl code entity AND_GATE is +vhdl code port( A: in std_logic; +vhdl code B: in std_logic; +vhdl code F1: out std_logic +vhdl code ); +vhdl code end AND_GATE; +vhdl blank +vhdl code architecture behv of AND_GATE is +vhdl code begin +vhdl code process(A,B) +vhdl code begin +vhdl code F1 <= A and B; -- behavior des. +vhdl code end process; +vhdl code end behv; +vhdl blank +vhdl comment -------------------------------------------------------------- +vhdl blank +vhdl code library ieee; -- top level circuit +vhdl code use ieee.std_logic_1164.all; +vhdl code use work.all; +vhdl blank +vhdl code entity comb_ckt is +vhdl code port( input1: in std_logic; +vhdl code input2: in std_logic; +vhdl code input3: in std_logic; +vhdl code output: out std_logic +vhdl code ); +vhdl code end comb_ckt; +vhdl blank +vhdl code architecture struct of comb_ckt is +vhdl blank +vhdl code component AND_GATE is -- as entity of AND_GATE +vhdl code port( A: in std_logic; +vhdl code B: in std_logic; +vhdl code F1: out std_logic +vhdl code ); +vhdl code end component; +vhdl blank +vhdl code component OR_GATE is -- as entity of OR_GATE +vhdl code port( X: in std_logic; +vhdl code Y: in std_logic; +vhdl code F2: out std_logic +vhdl code ); +vhdl code end component; +vhdl blank +vhdl code signal wire: std_logic; -- signal just like wire +vhdl blank +vhdl code begin +vhdl blank +vhdl comment -- use sign "=>" to clarify the pin mapping +vhdl blank +vhdl code Gate1: AND_GATE port map (A=>input1, B=>input2, F1=>wire); +vhdl code Gate2: OR_GATE port map (X=>wire, Y=>input3, F2=>output); +vhdl blank +vhdl code end struct; +vhdl blank +vhdl comment ---------------------------------------------------------------- diff --git a/test/expected_dir/vhdl1.vhdl b/test/expected_dir/vhdl1.vhdl new file mode 100644 index 0000000..379aaa6 --- /dev/null +++ b/test/expected_dir/vhdl1.vhdl @@ -0,0 +1,40 @@ +vhdl code library ieee; +vhdl code use ieee.std_logic_1164.all; +vhdl blank +vhdl code entity tb is +vhdl code end tb; +vhdl blank +vhdl code architecture behav of tb is +vhdl blank +vhdl comment -- toggle period +vhdl code constant period_c : time := 1 ms; +vhdl blank +vhdl comment -- we'll be poking on this signal +vhdl code signal toggle_s : std_logic_vector(1 downto 0) := "01"; +vhdl blank +vhdl code begin +vhdl blank +vhdl comment ----------------------------------------------------------------------------- +vhdl comment -- Process toggle +vhdl comment -- +vhdl comment -- Purpose: +vhdl comment -- Flip the toggle_s signal periodically. +vhdl comment -- +vhdl code toggle: process +vhdl code begin +vhdl blank +vhdl code wait for period_c/2; +vhdl code toggle_s <= not toggle_s; +vhdl blank +vhdl code end process toggle; +vhdl comment -- +vhdl comment ----------------------------------------------------------------------------- +vhdl blank +vhdl code end behav; +vhdl blank +vhdl code configuration tb_behav_c0 of tb is +vhdl blank +vhdl code for behav +vhdl code end for; +vhdl blank +vhdl code end tb_behav_c0; diff --git a/test/expected_dir/visual_basic.bas b/test/expected_dir/visual_basic.bas new file mode 100644 index 0000000..c8331c6 --- /dev/null +++ b/test/expected_dir/visual_basic.bas @@ -0,0 +1,60 @@ +visualbasic code VERSION 5.00 +visualbasic code Object = "{67397AA1-7FB1-11D0-B148-00A0C922E820}#6.0#0"; "MSADODC.OCX" +visualbasic code Object = "{BDC217C8-ED16-11CD-956C-0000C04E4C0A}#1.1#0"; "TABCTL32.OCX" +visualbasic code Object = "{CDE57A40-8B86-11D0-B3C6-00A0C90AEA82}#1.0#0"; "MSDATGRD.OCX" +visualbasic code Object = "{0ECD9B60-23AA-11D0-B351-00A0C9055D8E}#6.0#0"; "MSHFLXGD.OCX" +visualbasic code Object = "{831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0#0"; "MSCOMCTL.OCX" +visualbasic code Begin VB.Form frmMain +visualbasic code BorderStyle = 1 'Fixed Single +visualbasic code ClientHeight = 6555 +visualbasic code ClientLeft = 150 +visualbasic code ClientTop = 435 +visualbasic code ClientWidth = 10620 +visualbasic code LinkTopic = "Form1" +visualbasic code MaxButton = 0 'False +visualbasic code MinButton = 0 'False +visualbasic code ScaleHeight = 6555 +visualbasic code ScaleWidth = 10620 +visualbasic code StartUpPosition = 3 'Windows Default +visualbasic code Attribute VB_Name = "frmMain" +visualbasic code Attribute VB_GlobalNameSpace = False +visualbasic code Attribute VB_Creatable = False +visualbasic code Attribute VB_PredeclaredId = True +visualbasic code Attribute VB_Exposed = False +visualbasic comment '--------------------------------------------------------------------------- +visualbasic comment ' +visualbasic comment ' SOURCE FILE NAME: Demo.frm +visualbasic comment ' +visualbasic comment ' SAMPLE: Visual Basic Demo with user interface for the sample modules +visualbasic comment ' +visualbasic comment ' For more information about samples, refer to the README file. +visualbasic comment ' +visualbasic comment '--------------------------------------------------------------------------- +visualbasic blank +visualbasic code Option Explicit +visualbasic blank +visualbasic code Private con As ADODB.Connection +visualbasic code Private rst As ADODB.Recordset +visualbasic code Private strMsgText As String +visualbasic code Private wShowInstructions As Integer +visualbasic blank +visualbasic comment 'This procedure calls ConnectOLEDB() in the module dbConn to get +visualbasic comment 'a connection object. +visualbasic code Private Sub cmdConnectOLEDB_Click() +visualbasic comment 'define the error handler +visualbasic comment ' On Error GoTo cmdConnectOLEDB_Error +visualbasic blank +visualbasic comment 'connect to database +visualbasic code Set con = ConnectOLEDB() +visualbasic blank +visualbasic comment 'generate a message of success +visualbasic code sbrStatus.Panels(1).Text = "Connect to sample database succeeded!" +visualbasic blank +visualbasic comment 'config status of the buttons +visualbasic code EnableButtons +visualbasic blank +visualbasic comment 'show instructions +visualbasic code If wShowInstructions = vbYes Then +visualbasic code ShowConnectionInstruction +visualbasic code End If +visualbasic code End Sub diff --git a/test/expected_dir/xml1.xml b/test/expected_dir/xml1.xml new file mode 100644 index 0000000..db38a87 --- /dev/null +++ b/test/expected_dir/xml1.xml @@ -0,0 +1,14 @@ +xml code +xml comment +xml code +xml code ]]> +xml blank +xml code +xml comment +xml code +xml code +xml blank diff --git a/test/expected_licenses/academic_t1 b/test/expected_licenses/academic_t1 new file mode 100644 index 0000000..fdd901d --- /dev/null +++ b/test/expected_licenses/academic_t1 @@ -0,0 +1 @@ +academic diff --git a/test/expected_licenses/adaptive_t1 b/test/expected_licenses/adaptive_t1 new file mode 100644 index 0000000..48b279f --- /dev/null +++ b/test/expected_licenses/adaptive_t1 @@ -0,0 +1 @@ +adaptive diff --git a/test/expected_licenses/affero_1 b/test/expected_licenses/affero_1 new file mode 100644 index 0000000..077775a --- /dev/null +++ b/test/expected_licenses/affero_1 @@ -0,0 +1 @@ +affero diff --git a/test/expected_licenses/apache_2_t1 b/test/expected_licenses/apache_2_t1 new file mode 100644 index 0000000..52c4629 --- /dev/null +++ b/test/expected_licenses/apache_2_t1 @@ -0,0 +1 @@ +apache_2 diff --git a/test/expected_licenses/apache_2_t2 b/test/expected_licenses/apache_2_t2 new file mode 100644 index 0000000..52c4629 --- /dev/null +++ b/test/expected_licenses/apache_2_t2 @@ -0,0 +1 @@ +apache_2 diff --git a/test/expected_licenses/apache_2_t3 b/test/expected_licenses/apache_2_t3 new file mode 100644 index 0000000..52c4629 --- /dev/null +++ b/test/expected_licenses/apache_2_t3 @@ -0,0 +1 @@ +apache_2 diff --git a/test/expected_licenses/apache_ish_t1 b/test/expected_licenses/apache_ish_t1 new file mode 100644 index 0000000..c8c5106 --- /dev/null +++ b/test/expected_licenses/apache_ish_t1 @@ -0,0 +1 @@ +apache_ish diff --git a/test/expected_licenses/apache_ish_t2 b/test/expected_licenses/apache_ish_t2 new file mode 100644 index 0000000..c8c5106 --- /dev/null +++ b/test/expected_licenses/apache_ish_t2 @@ -0,0 +1 @@ +apache_ish diff --git a/test/expected_licenses/apache_t1 b/test/expected_licenses/apache_t1 new file mode 100644 index 0000000..a6b6519 --- /dev/null +++ b/test/expected_licenses/apache_t1 @@ -0,0 +1 @@ +apache diff --git a/test/expected_licenses/apache_t2 b/test/expected_licenses/apache_t2 new file mode 100644 index 0000000..a6b6519 --- /dev/null +++ b/test/expected_licenses/apache_t2 @@ -0,0 +1 @@ +apache diff --git a/test/expected_licenses/apache_t3 b/test/expected_licenses/apache_t3 new file mode 100644 index 0000000..a6b6519 --- /dev/null +++ b/test/expected_licenses/apache_t3 @@ -0,0 +1 @@ +apache diff --git a/test/expected_licenses/apple_open_source_t1 b/test/expected_licenses/apple_open_source_t1 new file mode 100644 index 0000000..347f5cc --- /dev/null +++ b/test/expected_licenses/apple_open_source_t1 @@ -0,0 +1 @@ +apple_open_source diff --git a/test/expected_licenses/artistic_t1 b/test/expected_licenses/artistic_t1 new file mode 100644 index 0000000..1eaead1 --- /dev/null +++ b/test/expected_licenses/artistic_t1 @@ -0,0 +1 @@ +artistic diff --git a/test/expected_licenses/attribution_assurance_t1 b/test/expected_licenses/attribution_assurance_t1 new file mode 100644 index 0000000..b2f9e28 --- /dev/null +++ b/test/expected_licenses/attribution_assurance_t1 @@ -0,0 +1 @@ +attribution_assurance diff --git a/test/expected_licenses/avr-drv b/test/expected_licenses/avr-drv new file mode 100644 index 0000000..2758ff2 --- /dev/null +++ b/test/expected_licenses/avr-drv @@ -0,0 +1 @@ +bsd_ish diff --git a/test/expected_licenses/boost_t1 b/test/expected_licenses/boost_t1 new file mode 100644 index 0000000..d579dbe --- /dev/null +++ b/test/expected_licenses/boost_t1 @@ -0,0 +1 @@ +boost diff --git a/test/expected_licenses/boost_t2 b/test/expected_licenses/boost_t2 new file mode 100644 index 0000000..d579dbe --- /dev/null +++ b/test/expected_licenses/boost_t2 @@ -0,0 +1 @@ +boost diff --git a/test/expected_licenses/bsd_2clause_ish_t1 b/test/expected_licenses/bsd_2clause_ish_t1 new file mode 100644 index 0000000..a7fe7c3 --- /dev/null +++ b/test/expected_licenses/bsd_2clause_ish_t1 @@ -0,0 +1 @@ +bsd_2clause_ish diff --git a/test/expected_licenses/bsd_ish_t1 b/test/expected_licenses/bsd_ish_t1 new file mode 100644 index 0000000..2758ff2 --- /dev/null +++ b/test/expected_licenses/bsd_ish_t1 @@ -0,0 +1 @@ +bsd_ish diff --git a/test/expected_licenses/bsd_ish_t2 b/test/expected_licenses/bsd_ish_t2 new file mode 100644 index 0000000..2758ff2 --- /dev/null +++ b/test/expected_licenses/bsd_ish_t2 @@ -0,0 +1 @@ +bsd_ish diff --git a/test/expected_licenses/bsd_ish_t3 b/test/expected_licenses/bsd_ish_t3 new file mode 100644 index 0000000..2758ff2 --- /dev/null +++ b/test/expected_licenses/bsd_ish_t3 @@ -0,0 +1 @@ +bsd_ish diff --git a/test/expected_licenses/bsd_t1 b/test/expected_licenses/bsd_t1 new file mode 100644 index 0000000..df796f1 --- /dev/null +++ b/test/expected_licenses/bsd_t1 @@ -0,0 +1 @@ +bsd diff --git a/test/expected_licenses/cecill b/test/expected_licenses/cecill new file mode 100644 index 0000000..1e5183e --- /dev/null +++ b/test/expected_licenses/cecill @@ -0,0 +1 @@ +cecill diff --git a/test/expected_licenses/cecill-b b/test/expected_licenses/cecill-b new file mode 100644 index 0000000..3621136 --- /dev/null +++ b/test/expected_licenses/cecill-b @@ -0,0 +1 @@ +cecill_b diff --git a/test/expected_licenses/cecill-c b/test/expected_licenses/cecill-c new file mode 100644 index 0000000..a380ed5 --- /dev/null +++ b/test/expected_licenses/cecill-c @@ -0,0 +1 @@ +cecill_c diff --git a/test/expected_licenses/common_development_and_distribution_t1 b/test/expected_licenses/common_development_and_distribution_t1 new file mode 100644 index 0000000..1c2bacc --- /dev/null +++ b/test/expected_licenses/common_development_and_distribution_t1 @@ -0,0 +1 @@ +common_development_and_distribution diff --git a/test/expected_licenses/common_public_t1 b/test/expected_licenses/common_public_t1 new file mode 100644 index 0000000..faea2af --- /dev/null +++ b/test/expected_licenses/common_public_t1 @@ -0,0 +1 @@ +common_public diff --git a/test/expected_licenses/computer_associates_trusted_t1 b/test/expected_licenses/computer_associates_trusted_t1 new file mode 100644 index 0000000..e9a5840 --- /dev/null +++ b/test/expected_licenses/computer_associates_trusted_t1 @@ -0,0 +1 @@ +computer_associates_trusted diff --git a/test/expected_licenses/cua_office_t1 b/test/expected_licenses/cua_office_t1 new file mode 100644 index 0000000..22c33a3 --- /dev/null +++ b/test/expected_licenses/cua_office_t1 @@ -0,0 +1 @@ +cua_office diff --git a/test/expected_licenses/eclipse_t1 b/test/expected_licenses/eclipse_t1 new file mode 100644 index 0000000..60847ff --- /dev/null +++ b/test/expected_licenses/eclipse_t1 @@ -0,0 +1 @@ +eclipse diff --git a/test/expected_licenses/educational_t1 b/test/expected_licenses/educational_t1 new file mode 100644 index 0000000..120ebd8 --- /dev/null +++ b/test/expected_licenses/educational_t1 @@ -0,0 +1 @@ +educational diff --git a/test/expected_licenses/eiffel_2_t1 b/test/expected_licenses/eiffel_2_t1 new file mode 100644 index 0000000..5cb9fa9 --- /dev/null +++ b/test/expected_licenses/eiffel_2_t1 @@ -0,0 +1 @@ +eiffel_2 diff --git a/test/expected_licenses/eiffel_t1 b/test/expected_licenses/eiffel_t1 new file mode 100644 index 0000000..ba6eb72 --- /dev/null +++ b/test/expected_licenses/eiffel_t1 @@ -0,0 +1 @@ +eiffel diff --git a/test/expected_licenses/entessa_t1 b/test/expected_licenses/entessa_t1 new file mode 100644 index 0000000..14fc016 --- /dev/null +++ b/test/expected_licenses/entessa_t1 @@ -0,0 +1 @@ +entessa diff --git a/test/expected_licenses/eu_datagrid_t1 b/test/expected_licenses/eu_datagrid_t1 new file mode 100644 index 0000000..0c6d308 --- /dev/null +++ b/test/expected_licenses/eu_datagrid_t1 @@ -0,0 +1 @@ +eu_datagrid diff --git a/test/expected_licenses/fair_t1 b/test/expected_licenses/fair_t1 new file mode 100644 index 0000000..9d3230c --- /dev/null +++ b/test/expected_licenses/fair_t1 @@ -0,0 +1 @@ +fair diff --git a/test/expected_licenses/frameworx_t1 b/test/expected_licenses/frameworx_t1 new file mode 100644 index 0000000..431fbb3 --- /dev/null +++ b/test/expected_licenses/frameworx_t1 @@ -0,0 +1 @@ +frameworx diff --git a/test/expected_licenses/gpl3_or_later_t1 b/test/expected_licenses/gpl3_or_later_t1 new file mode 100644 index 0000000..9765a18 --- /dev/null +++ b/test/expected_licenses/gpl3_or_later_t1 @@ -0,0 +1 @@ +gpl3_or_later diff --git a/test/expected_licenses/gpl3_or_later_t2 b/test/expected_licenses/gpl3_or_later_t2 new file mode 100644 index 0000000..9765a18 --- /dev/null +++ b/test/expected_licenses/gpl3_or_later_t2 @@ -0,0 +1 @@ +gpl3_or_later diff --git a/test/expected_licenses/gpl3_or_later_t3 b/test/expected_licenses/gpl3_or_later_t3 new file mode 100644 index 0000000..9765a18 --- /dev/null +++ b/test/expected_licenses/gpl3_or_later_t3 @@ -0,0 +1 @@ +gpl3_or_later diff --git a/test/expected_licenses/gpl3_t1 b/test/expected_licenses/gpl3_t1 new file mode 100644 index 0000000..de49b6a --- /dev/null +++ b/test/expected_licenses/gpl3_t1 @@ -0,0 +1 @@ +gpl3 diff --git a/test/expected_licenses/gpl3_t2 b/test/expected_licenses/gpl3_t2 new file mode 100644 index 0000000..1754a00 --- /dev/null +++ b/test/expected_licenses/gpl3_t2 @@ -0,0 +1,2 @@ +bsd +gpl3 diff --git a/test/expected_licenses/gpl_line_wrap_1 b/test/expected_licenses/gpl_line_wrap_1 new file mode 100644 index 0000000..fc03356 --- /dev/null +++ b/test/expected_licenses/gpl_line_wrap_1 @@ -0,0 +1 @@ +gpl diff --git a/test/expected_licenses/gpl_t1 b/test/expected_licenses/gpl_t1 new file mode 100644 index 0000000..fc03356 --- /dev/null +++ b/test/expected_licenses/gpl_t1 @@ -0,0 +1 @@ +gpl diff --git a/test/expected_licenses/gpl_t2 b/test/expected_licenses/gpl_t2 new file mode 100644 index 0000000..fc03356 --- /dev/null +++ b/test/expected_licenses/gpl_t2 @@ -0,0 +1 @@ +gpl diff --git a/test/expected_licenses/gpl_t3 b/test/expected_licenses/gpl_t3 new file mode 100644 index 0000000..fc03356 --- /dev/null +++ b/test/expected_licenses/gpl_t3 @@ -0,0 +1 @@ +gpl diff --git a/test/expected_licenses/gpl_t4 b/test/expected_licenses/gpl_t4 new file mode 100644 index 0000000..fc03356 --- /dev/null +++ b/test/expected_licenses/gpl_t4 @@ -0,0 +1 @@ +gpl diff --git a/test/expected_licenses/historical_t1 b/test/expected_licenses/historical_t1 new file mode 100644 index 0000000..21af01c --- /dev/null +++ b/test/expected_licenses/historical_t1 @@ -0,0 +1 @@ +historical diff --git a/test/expected_licenses/i9_license_t1 b/test/expected_licenses/i9_license_t1 new file mode 100644 index 0000000..ac0b8e1 --- /dev/null +++ b/test/expected_licenses/i9_license_t1 @@ -0,0 +1,2 @@ +i9_license +mit diff --git a/test/expected_licenses/i9_license_t2 b/test/expected_licenses/i9_license_t2 new file mode 100644 index 0000000..7fa8801 --- /dev/null +++ b/test/expected_licenses/i9_license_t2 @@ -0,0 +1 @@ +i9_license diff --git a/test/expected_licenses/ibm_public_t1 b/test/expected_licenses/ibm_public_t1 new file mode 100644 index 0000000..d4e6f7a --- /dev/null +++ b/test/expected_licenses/ibm_public_t1 @@ -0,0 +1 @@ +ibm_public diff --git a/test/expected_licenses/intel_open_source_t1 b/test/expected_licenses/intel_open_source_t1 new file mode 100644 index 0000000..9681aeb --- /dev/null +++ b/test/expected_licenses/intel_open_source_t1 @@ -0,0 +1 @@ +intel_open_source diff --git a/test/expected_licenses/jabber_open_source_t1 b/test/expected_licenses/jabber_open_source_t1 new file mode 100644 index 0000000..57b8d76 --- /dev/null +++ b/test/expected_licenses/jabber_open_source_t1 @@ -0,0 +1 @@ +jabber_open_source diff --git a/test/expected_licenses/lgpl3_t1 b/test/expected_licenses/lgpl3_t1 new file mode 100644 index 0000000..52b7d89 --- /dev/null +++ b/test/expected_licenses/lgpl3_t1 @@ -0,0 +1 @@ +lgpl3 diff --git a/test/expected_licenses/lgpl3_t2 b/test/expected_licenses/lgpl3_t2 new file mode 100644 index 0000000..52b7d89 --- /dev/null +++ b/test/expected_licenses/lgpl3_t2 @@ -0,0 +1 @@ +lgpl3 diff --git a/test/expected_licenses/lgpl_t1 b/test/expected_licenses/lgpl_t1 new file mode 100644 index 0000000..c98d586 --- /dev/null +++ b/test/expected_licenses/lgpl_t1 @@ -0,0 +1 @@ +lgpl diff --git a/test/expected_licenses/lgpl_t2 b/test/expected_licenses/lgpl_t2 new file mode 100644 index 0000000..c98d586 --- /dev/null +++ b/test/expected_licenses/lgpl_t2 @@ -0,0 +1 @@ +lgpl diff --git a/test/expected_licenses/lgpl_t3 b/test/expected_licenses/lgpl_t3 new file mode 100644 index 0000000..c98d586 --- /dev/null +++ b/test/expected_licenses/lgpl_t3 @@ -0,0 +1 @@ +lgpl diff --git a/test/expected_licenses/lgpl_t4 b/test/expected_licenses/lgpl_t4 new file mode 100644 index 0000000..c98d586 --- /dev/null +++ b/test/expected_licenses/lgpl_t4 @@ -0,0 +1 @@ +lgpl diff --git a/test/expected_licenses/lgpl_t5 b/test/expected_licenses/lgpl_t5 new file mode 100644 index 0000000..c98d586 --- /dev/null +++ b/test/expected_licenses/lgpl_t5 @@ -0,0 +1 @@ +lgpl diff --git a/test/expected_licenses/lucent_plan9_t1 b/test/expected_licenses/lucent_plan9_t1 new file mode 100644 index 0000000..7fcc82c --- /dev/null +++ b/test/expected_licenses/lucent_plan9_t1 @@ -0,0 +1 @@ +lucent_plan9 diff --git a/test/expected_licenses/lucent_public_t1 b/test/expected_licenses/lucent_public_t1 new file mode 100644 index 0000000..c26b59a --- /dev/null +++ b/test/expected_licenses/lucent_public_t1 @@ -0,0 +1 @@ +lucent_public diff --git a/test/expected_licenses/mit_t1 b/test/expected_licenses/mit_t1 new file mode 100644 index 0000000..fdb688a --- /dev/null +++ b/test/expected_licenses/mit_t1 @@ -0,0 +1 @@ +mit diff --git a/test/expected_licenses/mit_t2 b/test/expected_licenses/mit_t2 new file mode 100644 index 0000000..fdb688a --- /dev/null +++ b/test/expected_licenses/mit_t2 @@ -0,0 +1 @@ +mit diff --git a/test/expected_licenses/mitre_t1 b/test/expected_licenses/mitre_t1 new file mode 100644 index 0000000..24fd011 --- /dev/null +++ b/test/expected_licenses/mitre_t1 @@ -0,0 +1 @@ +mitre diff --git a/test/expected_licenses/motosoto_t1 b/test/expected_licenses/motosoto_t1 new file mode 100644 index 0000000..aabf9cc --- /dev/null +++ b/test/expected_licenses/motosoto_t1 @@ -0,0 +1 @@ +motosoto diff --git a/test/expected_licenses/mozilla_public_1_1_t1 b/test/expected_licenses/mozilla_public_1_1_t1 new file mode 100644 index 0000000..d62e65d --- /dev/null +++ b/test/expected_licenses/mozilla_public_1_1_t1 @@ -0,0 +1 @@ +mozilla_public_1_1 diff --git a/test/expected_licenses/mozilla_public_1_t1 b/test/expected_licenses/mozilla_public_1_t1 new file mode 100644 index 0000000..9898b6b --- /dev/null +++ b/test/expected_licenses/mozilla_public_1_t1 @@ -0,0 +1 @@ +mozilla_public_1 diff --git a/test/expected_licenses/nasa_open_t1 b/test/expected_licenses/nasa_open_t1 new file mode 100644 index 0000000..6075e88 --- /dev/null +++ b/test/expected_licenses/nasa_open_t1 @@ -0,0 +1 @@ +nasa_open diff --git a/test/expected_licenses/naumen_t1 b/test/expected_licenses/naumen_t1 new file mode 100644 index 0000000..79b0eed --- /dev/null +++ b/test/expected_licenses/naumen_t1 @@ -0,0 +1 @@ +naumen diff --git a/test/expected_licenses/nethack_t1 b/test/expected_licenses/nethack_t1 new file mode 100644 index 0000000..38a76c6 --- /dev/null +++ b/test/expected_licenses/nethack_t1 @@ -0,0 +1 @@ +nethack diff --git a/test/expected_licenses/nokia_open_source_t1 b/test/expected_licenses/nokia_open_source_t1 new file mode 100644 index 0000000..ed66e64 --- /dev/null +++ b/test/expected_licenses/nokia_open_source_t1 @@ -0,0 +1 @@ +nokia_open_source diff --git a/test/expected_licenses/oclc_research_t1 b/test/expected_licenses/oclc_research_t1 new file mode 100644 index 0000000..5c7ef56 --- /dev/null +++ b/test/expected_licenses/oclc_research_t1 @@ -0,0 +1 @@ +oclc_research diff --git a/test/expected_licenses/open_group_test_t1 b/test/expected_licenses/open_group_test_t1 new file mode 100644 index 0000000..faf6e90 --- /dev/null +++ b/test/expected_licenses/open_group_test_t1 @@ -0,0 +1 @@ +open_group_test diff --git a/test/expected_licenses/open_software_t1 b/test/expected_licenses/open_software_t1 new file mode 100644 index 0000000..848d11c --- /dev/null +++ b/test/expected_licenses/open_software_t1 @@ -0,0 +1 @@ +open_software diff --git a/test/expected_licenses/php_license_t1 b/test/expected_licenses/php_license_t1 new file mode 100644 index 0000000..028eb63 --- /dev/null +++ b/test/expected_licenses/php_license_t1 @@ -0,0 +1 @@ +php_license diff --git a/test/expected_licenses/python_license_t1 b/test/expected_licenses/python_license_t1 new file mode 100644 index 0000000..1c7ab8e --- /dev/null +++ b/test/expected_licenses/python_license_t1 @@ -0,0 +1 @@ +python_license diff --git a/test/expected_licenses/python_software_foundation_t1 b/test/expected_licenses/python_software_foundation_t1 new file mode 100644 index 0000000..5c1a20e --- /dev/null +++ b/test/expected_licenses/python_software_foundation_t1 @@ -0,0 +1 @@ +python_software_foundation diff --git a/test/expected_licenses/qt_public_t1 b/test/expected_licenses/qt_public_t1 new file mode 100644 index 0000000..fd0d683 --- /dev/null +++ b/test/expected_licenses/qt_public_t1 @@ -0,0 +1 @@ +qt_public diff --git a/test/expected_licenses/realnetworks_public_source_t1 b/test/expected_licenses/realnetworks_public_source_t1 new file mode 100644 index 0000000..057e39c --- /dev/null +++ b/test/expected_licenses/realnetworks_public_source_t1 @@ -0,0 +1 @@ +realnetworks_public_source diff --git a/test/expected_licenses/reciprocal_public_t1 b/test/expected_licenses/reciprocal_public_t1 new file mode 100644 index 0000000..484bac3 --- /dev/null +++ b/test/expected_licenses/reciprocal_public_t1 @@ -0,0 +1 @@ +reciprocal_public diff --git a/test/expected_licenses/ricoh_source_t1 b/test/expected_licenses/ricoh_source_t1 new file mode 100644 index 0000000..8e16c2c --- /dev/null +++ b/test/expected_licenses/ricoh_source_t1 @@ -0,0 +1 @@ +ricoh_source diff --git a/test/expected_licenses/sleepycat_t1 b/test/expected_licenses/sleepycat_t1 new file mode 100644 index 0000000..aee8e3e --- /dev/null +++ b/test/expected_licenses/sleepycat_t1 @@ -0,0 +1 @@ +sleepycat diff --git a/test/expected_licenses/sugarcrm_1_1_3_t1 b/test/expected_licenses/sugarcrm_1_1_3_t1 new file mode 100644 index 0000000..cda47ac --- /dev/null +++ b/test/expected_licenses/sugarcrm_1_1_3_t1 @@ -0,0 +1 @@ +sugarcrm_1_1_3 diff --git a/test/expected_licenses/sun_industry_standards_t1 b/test/expected_licenses/sun_industry_standards_t1 new file mode 100644 index 0000000..1b39553 --- /dev/null +++ b/test/expected_licenses/sun_industry_standards_t1 @@ -0,0 +1 @@ +sun_industry_standards diff --git a/test/expected_licenses/sun_public_t1 b/test/expected_licenses/sun_public_t1 new file mode 100644 index 0000000..b564f0b --- /dev/null +++ b/test/expected_licenses/sun_public_t1 @@ -0,0 +1 @@ +sun_public diff --git a/test/expected_licenses/sybase_open_watcom_t1 b/test/expected_licenses/sybase_open_watcom_t1 new file mode 100644 index 0000000..3b4c33d --- /dev/null +++ b/test/expected_licenses/sybase_open_watcom_t1 @@ -0,0 +1 @@ +sybase_open_watcom diff --git a/test/expected_licenses/u_of_i_ncsa_t1 b/test/expected_licenses/u_of_i_ncsa_t1 new file mode 100644 index 0000000..554b182 --- /dev/null +++ b/test/expected_licenses/u_of_i_ncsa_t1 @@ -0,0 +1 @@ +u_of_i_ncsa diff --git a/test/expected_licenses/vovida_software_t1 b/test/expected_licenses/vovida_software_t1 new file mode 100644 index 0000000..0f66849 --- /dev/null +++ b/test/expected_licenses/vovida_software_t1 @@ -0,0 +1 @@ +vovida_software diff --git a/test/expected_licenses/w3c_t1 b/test/expected_licenses/w3c_t1 new file mode 100644 index 0000000..3482c71 --- /dev/null +++ b/test/expected_licenses/w3c_t1 @@ -0,0 +1 @@ +w3c diff --git a/test/expected_licenses/wx_windows_t1 b/test/expected_licenses/wx_windows_t1 new file mode 100644 index 0000000..15f8559 --- /dev/null +++ b/test/expected_licenses/wx_windows_t1 @@ -0,0 +1 @@ +wx_windows diff --git a/test/expected_licenses/x_net_t1 b/test/expected_licenses/x_net_t1 new file mode 100644 index 0000000..890ee94 --- /dev/null +++ b/test/expected_licenses/x_net_t1 @@ -0,0 +1 @@ +x_net diff --git a/test/expected_licenses/zlib_libpng_t1 b/test/expected_licenses/zlib_libpng_t1 new file mode 100644 index 0000000..455f28b --- /dev/null +++ b/test/expected_licenses/zlib_libpng_t1 @@ -0,0 +1 @@ +zlib_libpng diff --git a/test/expected_licenses/zope_t1 b/test/expected_licenses/zope_t1 new file mode 100644 index 0000000..66179d4 --- /dev/null +++ b/test/expected_licenses/zope_t1 @@ -0,0 +1 @@ +zope diff --git a/test/gestalt_files/asp_net/test.aspx b/test/gestalt_files/asp_net/test.aspx new file mode 100644 index 0000000..e69de29 diff --git a/test/gestalt_files/cakephp/foo.php b/test/gestalt_files/cakephp/foo.php new file mode 100644 index 0000000..62a3a9d --- /dev/null +++ b/test/gestalt_files/cakephp/foo.php @@ -0,0 +1,5 @@ + diff --git a/test/gestalt_files/drupal/bar.php b/test/gestalt_files/drupal/bar.php new file mode 100644 index 0000000..af5d41f --- /dev/null +++ b/test/gestalt_files/drupal/bar.php @@ -0,0 +1,4 @@ + diff --git a/test/gestalt_files/eclipse/.project b/test/gestalt_files/eclipse/.project new file mode 100755 index 0000000..64e993c --- /dev/null +++ b/test/gestalt_files/eclipse/.project @@ -0,0 +1,17 @@ + + + sample + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/test/gestalt_files/eclipse_platform/main.java b/test/gestalt_files/eclipse_platform/main.java new file mode 100644 index 0000000..2798a90 --- /dev/null +++ b/test/gestalt_files/eclipse_platform/main.java @@ -0,0 +1,12 @@ +/******************************************************************************* + * Gibberish Code Copyrighted Just For The Hell Of It. + ******************************************************************************/ + package net.ohloh.www; + + import java.text.SimpleDateFormat; + import java.util.Map; + import org.eclipse.core.lotsa_stuff; + + public class AptPlugin extends Plugin { + public static final String PLUGIN_ID = "org.eclipse.jdt.apt.core"; //$NON-NLS-1$ + } diff --git a/test/gestalt_files/gtk/simple.c b/test/gestalt_files/gtk/simple.c new file mode 100644 index 0000000..2910064 --- /dev/null +++ b/test/gestalt_files/gtk/simple.c @@ -0,0 +1,13 @@ +#include +int main(int argc, char *argv[]) +{ + GtkWidget *gtkWindow; + + gtk_init(&argc, &argv); + + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_widget_show(window); + + gtk_main(); + return 0; +} diff --git a/test/gestalt_files/jquery/jquery-1.2.6.min.js b/test/gestalt_files/jquery/jquery-1.2.6.min.js new file mode 100644 index 0000000..0b035d7 --- /dev/null +++ b/test/gestalt_files/jquery/jquery-1.2.6.min.js @@ -0,0 +1 @@ +i = 1; diff --git a/test/gestalt_files/kde/foo.c b/test/gestalt_files/kde/foo.c new file mode 100644 index 0000000..ec50a2d --- /dev/null +++ b/test/gestalt_files/kde/foo.c @@ -0,0 +1 @@ +#include diff --git a/test/gestalt_files/mac/foo.c b/test/gestalt_files/mac/foo.c new file mode 100644 index 0000000..c1e580d --- /dev/null +++ b/test/gestalt_files/mac/foo.c @@ -0,0 +1 @@ +AppleEvent tAppleEvent; diff --git a/test/gestalt_files/moodle/moodle.php b/test/gestalt_files/moodle/moodle.php new file mode 100644 index 0000000..1ecdedd --- /dev/null +++ b/test/gestalt_files/moodle/moodle.php @@ -0,0 +1,8 @@ + diff --git a/test/gestalt_files/msdos/bar.c b/test/gestalt_files/msdos/bar.c new file mode 100644 index 0000000..03949f9 --- /dev/null +++ b/test/gestalt_files/msdos/bar.c @@ -0,0 +1 @@ +#include "MSDOS" diff --git a/test/gestalt_files/msdos/foo.c b/test/gestalt_files/msdos/foo.c new file mode 100644 index 0000000..311ff65 --- /dev/null +++ b/test/gestalt_files/msdos/foo.c @@ -0,0 +1 @@ +#include "__MSDOS__" diff --git a/test/gestalt_files/netbeans/nbplatform/project.xml b/test/gestalt_files/netbeans/nbplatform/project.xml new file mode 100644 index 0000000..f5ec34c --- /dev/null +++ b/test/gestalt_files/netbeans/nbplatform/project.xml @@ -0,0 +1,9 @@ + + + org.netbeans.modules.apisupport.project.suite + + + sample + + + diff --git a/test/gestalt_files/pear/Sample.class.php b/test/gestalt_files/pear/Sample.class.php new file mode 100644 index 0000000..243e5dd --- /dev/null +++ b/test/gestalt_files/pear/Sample.class.php @@ -0,0 +1,10 @@ + diff --git a/test/gestalt_files/pear/package.xml b/test/gestalt_files/pear/package.xml new file mode 100644 index 0000000..942a309 --- /dev/null +++ b/test/gestalt_files/pear/package.xml @@ -0,0 +1,9 @@ + + + diff --git a/test/gestalt_files/php/main.php b/test/gestalt_files/php/main.php new file mode 100644 index 0000000..2830618 --- /dev/null +++ b/test/gestalt_files/php/main.php @@ -0,0 +1,5 @@ + diff --git a/test/gestalt_files/plist/Info.plist.in b/test/gestalt_files/plist/Info.plist.in new file mode 100644 index 0000000..eb7c10a --- /dev/null +++ b/test/gestalt_files/plist/Info.plist.in @@ -0,0 +1,8 @@ + + + + + CFBundleDevelopmentRegion + English + + diff --git a/test/gestalt_files/posix/configure.in b/test/gestalt_files/posix/configure.in new file mode 100644 index 0000000..0e76864 --- /dev/null +++ b/test/gestalt_files/posix/configure.in @@ -0,0 +1 @@ +a line of code diff --git a/test/gestalt_files/posix/foo.c b/test/gestalt_files/posix/foo.c new file mode 100644 index 0000000..dcbbbf8 --- /dev/null +++ b/test/gestalt_files/posix/foo.c @@ -0,0 +1,102 @@ +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; +int = 0; diff --git a/test/gestalt_files/posix/foo.rb b/test/gestalt_files/posix/foo.rb new file mode 100644 index 0000000..7505dbc --- /dev/null +++ b/test/gestalt_files/posix/foo.rb @@ -0,0 +1,4 @@ +# this is ruby code +class Foo + attr_reader :bar +end diff --git a/test/gestalt_files/python/hello_world.py b/test/gestalt_files/python/hello_world.py new file mode 100644 index 0000000..18d9f87 --- /dev/null +++ b/test/gestalt_files/python/hello_world.py @@ -0,0 +1 @@ +print "Hello, World!" diff --git a/test/gestalt_files/rails/foo.rb b/test/gestalt_files/rails/foo.rb new file mode 100644 index 0000000..7f10e75 --- /dev/null +++ b/test/gestalt_files/rails/foo.rb @@ -0,0 +1,3 @@ +# we're impersonating a rails app +RAILS_ROOT = '/' +some_rails_code = "true" diff --git a/test/gestalt_files/ruby_just_enough/foo.c b/test/gestalt_files/ruby_just_enough/foo.c new file mode 100644 index 0000000..64e6c46 --- /dev/null +++ b/test/gestalt_files/ruby_just_enough/foo.c @@ -0,0 +1,75 @@ +int i = 1; +int i = 2; +int i = 3; +int i = 4; +int i = 5; +int i = 6; +int i = 7; +int i = 8; +int i = 9; +int i = 10; +int i = 11; +int i = 12; +int i = 13; +int i = 14; +int i = 15; +int i = 16; +int i = 17; +int i = 18; +int i = 19; +int i = 20; +int i = 21; +int i = 22; +int i = 23; +int i = 24; +int i = 25; +int i = 26; +int i = 27; +int i = 28; +int i = 29; +int i = 30; +int i = 31; +int i = 32; +int i = 33; +int i = 34; +int i = 35; +int i = 36; +int i = 37; +int i = 38; +int i = 39; +int i = 40; +int i = 41; +int i = 42; +int i = 43; +int i = 44; +int i = 45; +int i = 46; +int i = 47; +int i = 48; +int i = 49; +int i = 50; +int i = 51; +int i = 52; +int i = 53; +int i = 54; +int i = 55; +int i = 56; +int i = 57; +int i = 58; +int i = 59; +int i = 60; +int i = 61; +int i = 62; +int i = 63; +int i = 64; +int i = 65; +int i = 66; +int i = 67; +int i = 68; +int i = 69; +int i = 70; +int i = 71; +int i = 72; +int i = 73; +int i = 74; +int i = 75; diff --git a/test/gestalt_files/ruby_just_enough/foo.rb b/test/gestalt_files/ruby_just_enough/foo.rb new file mode 100644 index 0000000..6cfd7a3 --- /dev/null +++ b/test/gestalt_files/ruby_just_enough/foo.rb @@ -0,0 +1,15 @@ +a = 1 +a = 2 +a = 3 +a = 4 +a = 5 +a = 6 +a = 7 +a = 8 +a = 9 +a = 10 +a = 11 +a = 12 +a = 13 +a = 14 +a = 15 diff --git a/test/gestalt_files/ruby_not_enough/foo.c b/test/gestalt_files/ruby_not_enough/foo.c new file mode 100644 index 0000000..bc21e75 --- /dev/null +++ b/test/gestalt_files/ruby_not_enough/foo.c @@ -0,0 +1,87 @@ +int i = 1; +int i = 2; +int i = 3; +int i = 4; +int i = 5; +int i = 6; +int i = 7; +int i = 8; +int i = 9; +int i = 10; +int i = 11; +int i = 12; +int i = 13; +int i = 14; +int i = 15; +int i = 16; +int i = 17; +int i = 18; +int i = 19; +int i = 20; +int i = 21; +int i = 22; +int i = 23; +int i = 24; +int i = 25; +int i = 26; +int i = 27; +int i = 28; +int i = 29; +int i = 30; +int i = 31; +int i = 32; +int i = 33; +int i = 34; +int i = 35; +int i = 36; +int i = 37; +int i = 38; +int i = 39; +int i = 40; +int i = 41; +int i = 42; +int i = 43; +int i = 44; +int i = 45; +int i = 46; +int i = 47; +int i = 48; +int i = 49; +int i = 50; +int i = 51; +int i = 52; +int i = 53; +int i = 54; +int i = 55; +int i = 56; +int i = 57; +int i = 58; +int i = 59; +int i = 60; +int i = 61; +int i = 62; +int i = 63; +int i = 64; +int i = 65; +int i = 66; +int i = 67; +int i = 68; +int i = 69; +int i = 70; +int i = 71; +int i = 72; +int i = 73; +int i = 74; +int i = 75; +int i = 76; +int i = 77; +int i = 78; +int i = 79; +int i = 80; +int i = 81; +int i = 82; +int i = 83; +int i = 84; +int i = 85; +int i = 86; +int i = 87; diff --git a/test/gestalt_files/ruby_not_enough/foo.rb b/test/gestalt_files/ruby_not_enough/foo.rb new file mode 100644 index 0000000..6cfd7a3 --- /dev/null +++ b/test/gestalt_files/ruby_not_enough/foo.rb @@ -0,0 +1,15 @@ +a = 1 +a = 2 +a = 3 +a = 4 +a = 5 +a = 6 +a = 7 +a = 8 +a = 9 +a = 10 +a = 11 +a = 12 +a = 13 +a = 14 +a = 15 diff --git a/test/gestalt_files/spring_framework/main.java b/test/gestalt_files/spring_framework/main.java new file mode 100644 index 0000000..d762779 --- /dev/null +++ b/test/gestalt_files/spring_framework/main.java @@ -0,0 +1,7 @@ +class JavaClass +{ + int i = 1; + int i = 2; + int i = 3; +} + diff --git a/test/gestalt_files/spring_framework/spring.jar b/test/gestalt_files/spring_framework/spring.jar new file mode 100644 index 0000000..e69de29 diff --git a/test/gestalt_files/symfony/config.php b/test/gestalt_files/symfony/config.php new file mode 100644 index 0000000..9ba03b2 --- /dev/null +++ b/test/gestalt_files/symfony/config.php @@ -0,0 +1,2 @@ + diff --git a/test/gestalt_files/weblogic_maven/foo.java b/test/gestalt_files/weblogic_maven/foo.java new file mode 100644 index 0000000..a6f7059 --- /dev/null +++ b/test/gestalt_files/weblogic_maven/foo.java @@ -0,0 +1,4 @@ +/* Just a comment */ +{ + return a_few_lines_of_java_to_trigger_the_java_platform(); +} diff --git a/test/gestalt_files/weblogic_maven/pom.xml b/test/gestalt_files/weblogic_maven/pom.xml new file mode 100644 index 0000000..041a4ea --- /dev/null +++ b/test/gestalt_files/weblogic_maven/pom.xml @@ -0,0 +1,9 @@ + + + + org.codehaus.mojo + weblogic-maven-plugin + + + diff --git a/test/gestalt_files/websphere/foo.java b/test/gestalt_files/websphere/foo.java new file mode 100644 index 0000000..a6f7059 --- /dev/null +++ b/test/gestalt_files/websphere/foo.java @@ -0,0 +1,4 @@ +/* Just a comment */ +{ + return a_few_lines_of_java_to_trigger_the_java_platform(); +} diff --git a/test/gestalt_files/websphere/ibm-webservices-bnd.xmi b/test/gestalt_files/websphere/ibm-webservices-bnd.xmi new file mode 100644 index 0000000..e69de29 diff --git a/test/gestalt_files/win32_enough/bar.c b/test/gestalt_files/win32_enough/bar.c new file mode 100644 index 0000000..e7919b8 --- /dev/null +++ b/test/gestalt_files/win32_enough/bar.c @@ -0,0 +1,3 @@ +// a commented WndProc +WndProc *wndproc; + diff --git a/test/gestalt_files/win32_enough/foo.c b/test/gestalt_files/win32_enough/foo.c new file mode 100644 index 0000000..13de7b2 --- /dev/null +++ b/test/gestalt_files/win32_enough/foo.c @@ -0,0 +1,3 @@ +// another commented WndProc +WndProc *wndproc; + diff --git a/test/gestalt_files/win32_not_enough/foo.c b/test/gestalt_files/win32_not_enough/foo.c new file mode 100644 index 0000000..e7919b8 --- /dev/null +++ b/test/gestalt_files/win32_not_enough/foo.c @@ -0,0 +1,3 @@ +// a commented WndProc +WndProc *wndproc; + diff --git a/test/gestalt_files/wpf/wpf.xaml b/test/gestalt_files/wpf/wpf.xaml new file mode 100644 index 0000000..4275c95 --- /dev/null +++ b/test/gestalt_files/wpf/wpf.xaml @@ -0,0 +1,6 @@ + + + diff --git a/test/gestalt_files/wx_widgets/main.h b/test/gestalt_files/wx_widgets/main.h new file mode 100644 index 0000000..7b1cc39 --- /dev/null +++ b/test/gestalt_files/wx_widgets/main.h @@ -0,0 +1,3 @@ +/* some random includes (and one that's not so random) */ +#include +#include "wx/window.h" diff --git a/test/gestalt_files/xwindows/foo.c b/test/gestalt_files/xwindows/foo.c new file mode 100644 index 0000000..271aa6c --- /dev/null +++ b/test/gestalt_files/xwindows/foo.c @@ -0,0 +1 @@ +#include diff --git a/test/gestalt_files/zend_framework/application/controllers/ZendWildfirePluginFirePhpController.php b/test/gestalt_files/zend_framework/application/controllers/ZendWildfirePluginFirePhpController.php new file mode 100644 index 0000000..8273004 --- /dev/null +++ b/test/gestalt_files/zend_framework/application/controllers/ZendWildfirePluginFirePhpController.php @@ -0,0 +1,50 @@ + "); + 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/as1.as b/test/src_dir/as1.as new file mode 100644 index 0000000..915fa27 --- /dev/null +++ b/test/src_dir/as1.as @@ -0,0 +1,140 @@ +/* SVN FILE: $Id: FakeObject.as 42 2008-03-26 03:18:02Z xpointsh $ */ +/** + * Description + * + * Fake + * Copyright 2008, Sean Chatman and Garrett Woodworth + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @filesource + * @copyright Copyright 2008, Sean Chatman and Garrett Woodworth + * @link http://code.google.com/p/fake-as3/ + * @package fake + * @subpackage com.fake + * @since 2008-03-06 + * @version $Revision: 42 $ + * @modifiedby $LastChangedBy: xpointsh $ + * @lastmodified $Date: 2008-03-25 20:18:02 -0700 (Tue, 25 Mar 2008) $ + * @license http://www.opensource.org/licenses/mit-license.php The MIT License + */ +package com.fake +{ + import flash.utils.*; + + /** + * FakeObject is the root object for all classes + * in Fake. It contains a reference to the class name + * and class object. These are obtained by using the + * reflection classes in flash.utils. + */ + public dynamic class FakeObject extends Proxy + { + /** + * The name of the top level subclass + */ + [Transient] public var className:String; + /** + * A reference to the top level subclass + */ + [Transient] public var ClassRef:Class; + + private var __item:Array; + + public function FakeObject() + { + getClassInfo(); + __item = new Array(); + } + + /** + * This method is called by the constructor. Populates the className and ClassRef using + * getQualifiedClassName and getDefinitionByName + */ + private function getClassInfo():void + { + var qcName:Array = getQualifiedClassName(this).split("::"); + className = qcName[1]; + + var classPath:String = getQualifiedClassName(this).replace( "::", "." ); + ClassRef = getDefinitionByName(classPath) as Class; + } + + /** + * Override the callProperty of the flash_proxy + * @param method + * @param args + * @return + * + */ + override flash_proxy function callProperty(method: *, ...args):* + { + try + { + return ClassRef.prototype[method].apply(method, args); + } + catch (e:Error) + { + return overload(method, args); + } + } + + /** + * To be overriden by subclasses. Allows calling any method on any object that extends FakeOject + * @param method + * @param args + * + */ + protected function overload(method:*, args:Array):void + { + } + + /** + * get a property on the object + * @param name + * @return + * + */ + override flash_proxy function getProperty(name:*):* + { + return overloadGetProperty(name); + } + + protected function overloadGetProperty(name:*):* + { + return __item[name]; + } + + /** + * Set a property on the object + * @param name + * @param value + * + */ + override flash_proxy function setProperty(name:*, value:*):void + { + overloadSetProperty(name, value) + } + + protected function overloadSetProperty(name:*, value:*):void + { + __item[name] = value; + } + + /** + * Check if the property exits + * @param name + * @param value + * + */ + override flash_proxy function hasProperty(name:*):Boolean + { + if (__item[name]) + { + return true; + } + return false; + } + } +} 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/blitzmax.bmx b/test/src_dir/blitzmax.bmx new file mode 100644 index 0000000..da4ae51 --- /dev/null +++ b/test/src_dir/blitzmax.bmx @@ -0,0 +1,32 @@ +' +' Comments +' +SuperStrict + +Rem +bbdoc: docs +End Rem +Module bah.fish + +Import BRL.StandardIO + +Import "test.bmx" ' comment + +rem +some comments + + +Type blah +still in comments +End Type + +endrem + +Type TABC + + Method hello() + End Method + +End Type + +print "hello rem fish ' " diff --git a/test/src_dir/boo1.boo b/test/src_dir/boo1.boo new file mode 100644 index 0000000..743a6c1 --- /dev/null +++ b/test/src_dir/boo1.boo @@ -0,0 +1,112 @@ +import System +import System.IO +import Gtk from "gtk-sharp" +import Gdk from "gdk-sharp" +import Glade from "glade-sharp" + +class StuffBrowser(): + public static final phile = """stuffbrowser.glade""" + + //Unfortunately, Gtk does not provide a builtin "IsSupported" function for images. + public static final supportedExtensions = ( ".png", ".jpeg", ".jpg", ".gif", ".tga", ".bmp", ".ico", ".tiff" ) + + def constructor(): + //Connect event handlers and mainStuff, aboutDialog, etc, to their respective methods/handlers. + for widget in ("mainStuff", "aboutDialog", "directorySelector"): + gxml = Glade.XML(phile, widget, null) + gxml.Autoconnect(self) + + def OnStuffClose(sender as object, e as DeleteEventArgs): + """The user is leaving the application via the Big Red 'X'""" + Application.Quit() + + def OnStuffQuit(sender as object, e as EventArgs): + """The user is leaving the application via File-->Quit""" + Application.Quit() + + def OnAboutActivate(sender as object, e as EventArgs): + """The user is trying to view the about dialog""" + aboutDialog.Show() + + def OnAboutDelete(sender as object, e as DeleteEventArgs): + e.RetVal = true + aboutDialog.Hide() + + def OnAboutResponse(sender as object, e as ResponseArgs): + if e.ResponseId == ResponseType.Close: + aboutDialog.Hide() + + def OnOpenDirectory(sender as object, e as EventArgs): + #changed + directorySelector.FileList.Sensitive = false + directorySelector.Show() + + def OnDirectoryDelete(sender as object, e as DeleteEventArgs): + e.RetVal = true + directorySelector.Hide() //Don't worry, the "Destroy" event will kill it. + + def OnDirectoryResponse(sender as object, args as ResponseArgs): + directorySelector.Hide() + #changed + if args.ResponseId == ResponseType.Ok and directorySelector.Filename.Length != 0: + LoadDirectory(directorySelector.Filename) + + private def LoadDirectory(path as string): + //Create a new store that has two columns; the first is a Pixbuf (image) the second, a string. + store = ListStore( (Gdk.Pixbuf, string) ) + stuffThumbs.Model = store + cell = CellRendererPixbuf() + column = TreeViewColumn() + column.PackStart(cell, false) + + //Bind the element in column 0 of the store to the pixbuf property in this column's CellRendererPixbuf! + column.AddAttribute(cell, "pixbuf", 0) + column.Title = path + + //Detach the old column. + if stuffThumbs.GetColumn(0) is not null: + stuffThumbs.RemoveColumn(stuffThumbs.GetColumn(0)) + + //Finally, attach the new column so it will be updated in real time. + stuffThumbs.AppendColumn(column) + files = Directory.GetFiles(path) + validFiles = e for e as string in files if System.IO.FileInfo(e).Extension in StuffBrowser.supportedExtensions + parse = do(): + for i as int, file as string in enumerate(validFiles): + //The using construct ensures that the program's memory size does not inflate wildly out of control. + //Having these "image" floating around afterwards ensures lots of memory consuming havoc until garbaged collected! + #changed + // If we couldn't read a file pass over it. + try: + using image = Gdk.Pixbuf(file): + store.AppendValues( (image.ScaleSimple(128, 128, InterpType.Bilinear), file ) ) + except e: + print " Couldn't read file ${file} " + + print "Indexing start: ${DateTime.Now}" + //Update the treeview in real time by starting an asynchronous operation. + parse.BeginInvoke( { print "Indexing complete: ${DateTime.Now}" } ) //Spin off a new thread; fill the progress bar. + + def OnPictureActivated(sender as object, args as RowActivatedArgs): + //Grabs the TreeIter object that represents the currently selected node -- icky stuff with "ref" keyword. ;( + x as TreeIter + stuffThumbs.Model.GetIter(x, args.Path) + + //In the second column we've stored the filename that represents the thumbnail image in the treeview. + //Grab this filename and then use it to inform the user what file he's viewing, as well as loading it. + image = stuffThumbs.Model.GetValue(x, 1) as string + stuffImage.Pixbuf = Gdk.Pixbuf(image) + imageName.Text = Path.GetFileName(image) + + //All of the widgets we want Autoconnect to hook up to Glade-created widgets in stuffBrowser.glade + [Glade.Widget] aboutDialog as Gtk.Dialog + [Glade.Widget] mainStuff as Gtk.Window + [Glade.Widget] directorySelector as Gtk.FileSelection + [Glade.Widget] stuffImage as Gtk.Image + [Glade.Widget] stuffThumbs as Gtk.TreeView + [Glade.Widget] imageName as Gtk.Label + +//Run the application. +Application.Init() +StuffBrowser() +Application.Run() 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/c2.h.in b/test/src_dir/c2.h.in new file mode 100644 index 0000000..9853b5b --- /dev/null +++ b/test/src_dir/c2.h.in @@ -0,0 +1,15 @@ +/* c2.h.in. */ + +#ifndef C2_H +#define C2_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `m' library (-lm). */ +#undef HAVE_LIBM + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +#endif diff --git a/test/src_dir/c_str.c b/test/src_dir/c_str.c new file mode 100644 index 0000000..421a41c --- /dev/null +++ b/test/src_dir/c_str.c @@ -0,0 +1,2 @@ +p = '"'; +/* this should be a comment */ diff --git a/test/src_dir/classic_basic.b b/test/src_dir/classic_basic.b new file mode 100644 index 0000000..926d164 --- /dev/null +++ b/test/src_dir/classic_basic.b @@ -0,0 +1,19 @@ +10 INPUT "What is your name: "; U$ +20 PRINT "Hello "; U$ +30 REM Test +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/classic_basic.bas b/test/src_dir/classic_basic.bas new file mode 100644 index 0000000..5c03f61 --- /dev/null +++ b/test/src_dir/classic_basic.bas @@ -0,0 +1,20 @@ +10 INPUT "What is your name: "; U$ +20 PRINT "Hello "; U$ +30 REM Test +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/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/click_me.xaml b/test/src_dir/click_me.xaml new file mode 100644 index 0000000..7241415 --- /dev/null +++ b/test/src_dir/click_me.xaml @@ -0,0 +1,7 @@ + + + + diff --git a/test/src_dir/cmake1.cmake b/test/src_dir/cmake1.cmake new file mode 100644 index 0000000..b9eecd3 --- /dev/null +++ b/test/src_dir/cmake1.cmake @@ -0,0 +1,33 @@ +# blah comment +# + +something() +# comment +something_else() + +long_function( + # comment + param +) + +long_string(" + # looks like a comment but isn't +") + +long_string( + " + # looks like a comment but isn't + " +) + +message( + ' + # looks like a string but isn't + ' +) + +message("string") + +message( + +) 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/configure.ac b/test/src_dir/configure.ac new file mode 100644 index 0000000..c203d56 --- /dev/null +++ b/test/src_dir/configure.ac @@ -0,0 +1,5 @@ +dnl This is an autoconf file. + +AC_INIT([giant-space-monkey], [0.0]) +AC_PREREQ(2.5) + diff --git a/test/src_dir/cs.aspx b/test/src_dir/cs.aspx new file mode 100644 index 0000000..b945fb2 --- /dev/null +++ b/test/src_dir/cs.aspx @@ -0,0 +1,29 @@ +<%@ Page Language="C#" %> + + + + Basic ASP.NET Web Page + + + <%if( ViewData["Message"] != null ){ %> +

<%=ViewData["Message"]%>


+ <% } %> +
+

Welcome to ASP.NET

+

Type your name and click the button.

+

+ + +

+

+ +

+
+ + 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/dcl.com b/test/src_dir/dcl.com new file mode 100644 index 0000000..b46fec5 --- /dev/null +++ b/test/src_dir/dcl.com @@ -0,0 +1,12 @@ +$! Test file for DCL parser +$ ! Written by Camiel Vanderhoeven +$ +$ +$ SET VERIFY +$ WRITE SYS$SYSTEM +This is some text + +$ EXIT +$! This is comment again +$! +$ 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/eiffel.e b/test/src_dir/eiffel.e new file mode 100644 index 0000000..39ce33f --- /dev/null +++ b/test/src_dir/eiffel.e @@ -0,0 +1,13 @@ +class + HELLO_WORLD +create + make +feature + make + do + -- prints "Hello world!" and starts new line + + print ("Hello, world!%N") + + end +end 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/english.st b/test/src_dir/english.st new file mode 100644 index 0000000..205b8a0 --- /dev/null +++ b/test/src_dir/english.st @@ -0,0 +1,6 @@ +a +aa +aardvark +abacus +apple +zebra 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/example.R b/test/src_dir/example.R new file mode 100644 index 0000000..3740c46 --- /dev/null +++ b/test/src_dir/example.R @@ -0,0 +1,200 @@ +# Build a 'graph-like' object having 'nodes' nodes belonging to 'classes' classes. +# Class distribution is given by 'proba', and connectivity probabilities are given +# by 'intraproba' and 'interproba'. +generateGraph<-function(nodes,classes,proba=rep(1/classes,classes), + intraproba=0.1,crossproba=0.02) +{ + mat_pi=CreateConnectivityMat(classes,intraproba,crossproba) + igraph=Fast2SimuleERMG(nodes,proba,mat_pi[1],mat_pi[2]) + adjacency=get.adjacency(igraph$graph) + cmgraph=list(nodes=nodes,classes=classes,adjacency=adjacency,nodeclasses=igraph$node.classes,proba=proba, + intraproba=intraproba,crossproba=crossproba) + attr(cmgraph,'class')<-c('cmgraph') + cmgraph +} + +# Return explicit member names for the different attributes of graph objects. +labels.cmgraph<-function(object,...) +{ + c("Nodes","Classes","Adjacency Matrix","Node Classification","Class Probability Distribution","Intra Class Edge Probability","Cross Class Edge Probability") +} + +# Override the summmary function for graph objects. +summary.cmgraph<-function(object,...) +{ + + cat(c("Nodes : ",object$nodes,"\n", + "Edges : ",length(which(object$adjacency!=0)),"\n", + "Classes : ",object$classes,"\n", + "Class Probability Distribution: ",object$proba,"\n")) +} + +# Override the plot function for graph objects. +plot.cmgraph<-function(x,...) +{ + RepresentationXGroup(x$adjacency,x$nodeclasses) +} + +# Generate covariable data for the graph 'g'. Covariables are associated to vertex data, and +# their values are drawn according to 2 distributions: one for vertices joining nodes of +# the same class, and another for vertices joining nodes of different classes. +# The two distributions have different means but a single standard deviation. +generateCovariablesCondZ<-function(g,sameclustermean=0,otherclustermean=2,sigma=1) +{ + mu=CreateMu(g$classes,sameclustermean,otherclustermean) + res=SimDataYcondZ(g$nodeclasses,mu,sigma) + cmcovars=list(graph=g,sameclustermean=sameclustermean,otherclustermean=otherclustermean,sigma=sigma,mu=mu,y=res) + attr(cmcovars,'class')<-c('cmcovarz','cmcovar') + cmcovars +} + +# Generate covariable data for the graph 'g'. Covariables are associated to vertex data, and +# their values are drawn according to 2 distributions: one for vertices joining nodes of +# the same class, and another for vertices joining nodes of different classes. +# The two distributions have different means but a single standard deviation. +# This function generates two sets of covariables. +generateCovariablesCondXZ<-function(g,sameclustermean=c(0,3),otherclustermean=c(2,5),sigma=1) +{ + mux0=CreateMu(g$classes,sameclustermean[1],otherclustermean[1]) + mux1=CreateMu(g$classes,sameclustermean[2],otherclustermean[2]) + res=SimDataYcondXZ(g$nodeclasses,g$adjacency,mux0,mux1,sigma) + cmcovars=list(graph=g,sameclustermean=sameclustermean,otherclustermean=otherclustermean,sigma=sigma,mu=c(mux0,mux1),y=res) + attr(cmcovars,'class')<-c('cmcovarxz','cmcovar') + cmcovars +} + + +# Override the print function for a cleaner covariable output. +print.cmcovar<-function(x,...) +{ + cat("Classes : ",x$graph$classes,"\n", + "Intra cluster mean: ",x$sameclustermean,"\n", + "Cross cluster mean: ",x$otherclustermean,"\n", + "Variance : ",x$sigma,"\n", + "Covariables :\n",x$y,"\n") +} + + +# Perform parameter estimation on 'graph' given the covariables 'covars'. +estimateCondZ<-function(graph,covars,maxiterations,initialclasses,selfloops) +{ + res=EMalgorithm(initialclasses,covars$y,graph$adjacency,maxiterations,FALSE,selfloops) + cmestimation=list(mean=res$MuEstimated,variance=res$VarianceEstimated,pi=res$PIEstimated,alpha=res$AlphaEstimated,tau=res$TauEstimated,jexpected=res$EJ,graph=graph) + attr(cmestimation,'class')<-c('cmestimationz') + cmestimation +} + +# Private generic estimation function used to allow various call conventions for estimation functions. +privateestimate<-function(covars,graph,maxiterations,initialclasses,selfloops,...) UseMethod("privateestimate") + +# Private estimation function used to allow various call conventions for estimation functions. +# Override of generic function for single covariables. +privateestimate.cmcovarz<-function(covars,graph,maxiterations,initialclasses,selfloops,...) +{ + res=estimateCondZ(graph,covars,maxiterations,initialclasses,selfloops) + attr(res,'class')<-c(attr(res,'class'),'cmestimation') + res + +} + +# Perform parameter estimation on 'graph' given the covariables 'covars'. +estimateCondXZ<-function(graph,covars,maxiterations,initialclasses,selfloops) +{ + #resSimXZ = EMalgorithmXZ(TauIni,Y2,Adjacente,30,SelfLoop=FALSE) + res=EMalgorithmXZ(initialclasses,covars$y,graph$adjacency,maxiterations,selfloops) + cmestimation=list(mean=c(res$MuEstimated1,res$MuEstimated2),variance=res$VarianceEstimated,pi=res$PIEstimated,alpha=res$AlphaEstimated,tau=res$TauEstimated,jexpected=res$EJ,graph=graph) + attr(cmestimation,'class')<-c('cmestimationxz') + cmestimation +} + +# Private estimation function used to allow various call conventions for estimation functions. +# Override of generic function for multiple covariables. +privateestimate.cmcovarxz<-function(covars,graph,maxiterations,initialclasses,selfloops,...) +{ + res=estimateCondXZ(graph,covars,maxiterations,initialclasses,selfloops) + attr(res,'class')<-c(attr(res,'class'),'cmestimation') + res +} + +# Generic estimation function applicable to graphs with covariables. +estimate<-function(graph,covars,...) UseMethod("estimate") + +# Override of the generic estimation function. Performs the actual function dispatch depending on the class of covariables. +estimate.cmgraph<-function(graph,covars,maxiterations=20,initialclasses=t(rmultinom(size=1,prob=graph$proba,n=graph$nodes)),selfloops=FALSE,method=NULL,...) +{ + if (length(method) == 0) { + res=privateestimate(covars,graph,maxiterations,initialclasses,selfloops,...) + } else { + res=method(graph,covars,maxiterations,initialclasses,selfloops) + attr(res,'class')<-c(attr(res,'class'),'cmestimation') + } + res +} + +# Override of the generic pliot function for estimation results. +plot.cmestimation<-function(x,...) +{ + par(mfrow = c(1,2)) + plot(x$jexpected) + title("Expected value of J: Convergence criterion") + + map=MAP(x$tau) + gplot(x$graph$adjacency,vertex.col=map$node.classes+2) + title("Network with estimated classes") + +} + +# Generic private ICL computation function for graphs and covariables. +privatecomputeICL<-function(covars,graph,qmin,qmax,loops,maxiterations,selfloops) UseMethod("privatecomputeICL") + + +# Private ICL computation function for graphs with single covariables. +privatecomputeICL.cmcovarz<-function(covars,graph,qmin,qmax,loops,maxiterations,selfloops) +{ + res=ICL(X=graph$adjacency,Y=covars$y,Qmin=qmin,Qmax=qmax,loop=loops,NbIteration=maxiterations,SelfLoop=selfloops,Plot=FALSE) + attr(res,'class')<-c('cmiclz') + res + +} + +# Private ICL computation function for graphs with multiple covariables. +privatecomputeICL.cmcovarxz<-function(covars,graph,qmin,qmax,loops,maxiterations,selfloops) +{ + res=ICL(X=graph$adjacency,Y=covars$y,Qmin=qmin,Qmax=qmax,loop=loops,NbIteration=maxiterations,SelfLoop=selfloops,Plot=FALSE) + attr(res,'class')<-c('cmiclxz') + res +} + + +# Generic public ICL computation function applicable to graph objects. +computeICL<-function(graph,covars,qmin,qmax,...) UseMethod("computeICL") + +# Override of ICL computation function applicable to graph objects. +# Performs the actual method dispatch to private functions depending on the type of covariables. +computeICL.cmgraph<-function(graph,covars,qmin,qmax,loops=10,maxiterations=20,selfloops=FALSE,...) +{ + res=privatecomputeICL(covars,graph,qmin,qmax,loops,maxiterations,selfloops) + res$qmin=qmin + res$qmax=qmax + res$graph=graph + res$covars=covars + attr(res,'class')<-c(attr(res,'class'),'cmicl') + res +} + +# Override of the plot function for results of ICL computation. +plot.cmicl<-function(x,...) +{ + par(mfrow = c(1,2)) + result=x$iclvalues + maxi=which(max(result)==result) + plot(seq(x$qmin,x$qmax),result,type="b",xlab="Number of classes",ylab="ICL value") + points(maxi+x$qmin-1,result[maxi],col="red") + title("ICL curve") + best=x$EMestimation[[maxi+x$qmin-1]] + tau=best$TauEstimated + map=MAP(tau) + gplot(x$graph$adjacency,vertex.col=map$node.classes+2) + title("Network with estimated classes") +} + diff --git a/test/src_dir/example.xsl b/test/src_dir/example.xsl new file mode 100644 index 0000000..d29e4aa --- /dev/null +++ b/test/src_dir/example.xsl @@ -0,0 +1,17 @@ + + + + + + + + sample webpage + + + + + comment in HTML + + + + diff --git a/test/src_dir/factor1.factor b/test/src_dir/factor1.factor new file mode 100644 index 0000000..d1b9427 --- /dev/null +++ b/test/src_dir/factor1.factor @@ -0,0 +1,14 @@ +! This is a comment +! Factor syntax is very simple, it just contains words separated by spaces +! '!' is a line comment word +! "whatever" is a string word +USING: kernel io ; ! This is a vocabulary inclusion word +IN: testing + +: test-string ( -- ) + "this is a string" print ; + +: test ( x -- y ) ! Parenthesis define a stack effect declaration + dup swap drop ; + +MAIN: test diff --git a/test/src_dir/fb.js b/test/src_dir/fb.js new file mode 100644 index 0000000..f71c201 --- /dev/null +++ b/test/src_dir/fb.js @@ -0,0 +1,9 @@ +function escapeHTML(value) +{ + return String(value).replace(/[<>&"']/g, replaceChars); +} + +window.onerror = onError; + +if (document.documentElement.getAttribute("debug") == "true") + toggleConsole(true); diff --git a/test/src_dir/foo.ebuild b/test/src_dir/foo.ebuild new file mode 100644 index 0000000..60ff1c6 --- /dev/null +++ b/test/src_dir/foo.ebuild @@ -0,0 +1,21 @@ +# This is an ebuild. +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +DESCRIPTION="An ebuild" +HOMEPAGE="" +SRC_URI="" + +LICENSE="" +SLOT="0" +KEYWORDS="~x86" +IUSE="" + +DEPEND="" +RDEPEND="" + +pkg_setup() { + # This is foo + einfo "This is foo" +} + diff --git a/test/src_dir/foo.exheres-0 b/test/src_dir/foo.exheres-0 new file mode 100644 index 0000000..442206f --- /dev/null +++ b/test/src_dir/foo.exheres-0 @@ -0,0 +1,20 @@ +# This is an exheres. + +require subversion bash-completion eutils flag-o-matic + +DESCRIPTION="An exheres" +HOMEPAGE="http://example.org/" +SRC_URI="" + +MYOPTIONS="monkey" +LICENSE="GPL-2" +SLOT="0" +PLATFORMS="~amd64 ~ia64 ~x86" + +DEPENDENCIES="" + +src_prepare() { + default + ./autogen.bash || die "autogen.bash failed" +} + diff --git a/test/src_dir/foo.glsl b/test/src_dir/foo.glsl new file mode 100644 index 0000000..e134a61 --- /dev/null +++ b/test/src_dir/foo.glsl @@ -0,0 +1,4 @@ +// GLSL vertex shader +void main() { + gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex; +} \ No newline at end of file diff --git a/test/src_dir/foo.tex b/test/src_dir/foo.tex new file mode 100644 index 0000000..a54a999 --- /dev/null +++ b/test/src_dir/foo.tex @@ -0,0 +1,8 @@ +\begin{document} +\texbf Hello world + + +% +% sample comment + +\end{document} diff --git a/test/src_dir/foo.vim b/test/src_dir/foo.vim new file mode 100644 index 0000000..fe85b38 --- /dev/null +++ b/test/src_dir/foo.vim @@ -0,0 +1,21 @@ +" Vim syntax file +" Language: Test file for ohcount +" Author: Ciaran McCreesh +" +" This is a test vim syntax file for ohcount. +" + +if &compatible || v:version < 700 + finish +endif + +if exists("b:current_syntax") + finish +endif + +" This is a comment. There are many like it, but this one is mine. +syn region GiantSpaceMonkey start=/^\s*#/ end=/$/ +hi def link GiantSpaceMonkey Comment + +let b:current_syntax = "ohcount-test" + diff --git a/test/src_dir/foo_glsl.vert b/test/src_dir/foo_glsl.vert new file mode 100644 index 0000000..4f2d4fc --- /dev/null +++ b/test/src_dir/foo_glsl.vert @@ -0,0 +1,43 @@ +// from OGRE3D's skinningTwoWeightsShadowCasterVp.glsl +// Example GLSL program for skinning with two bone weights per vertex + +attribute vec4 vertex; +attribute vec4 uv0; +attribute vec4 blendIndices; +attribute vec4 blendWeights; + +// 3x4 matrix, passed as vec4's for compatibility with GL 2.0 +// GL 2.0 supports 3x4 matrices +// Support 24 bones ie 24*3, but use 72 since our parser can pick that out for sizing +uniform vec4 worldMatrix3x4Array[72]; +uniform mat4 viewProjectionMatrix; +uniform vec4 ambient; + +void main() +{ + vec3 blendPos = vec3(0,0,0); + + for (int bone = 0; bone < 2; ++bone) + { + // perform matrix multiplication manually since no 3x4 matrices + // ATI GLSL compiler can't handle indexing an array within an array so calculate the inner index first + int idx = int(blendIndices[bone]) * 3; + // ATI GLSL compiler can't handle unrolling the loop so do it manually + // ATI GLSL has better performance when mat4 is used rather than using individual dot product + // There is a bug in ATI mat4 constructor (Cat 7.2) when indexed uniform array elements are used as vec4 parameter so manually assign + mat4 worldMatrix; + worldMatrix[0] = worldMatrix3x4Array[idx]; + worldMatrix[1] = worldMatrix3x4Array[idx + 1]; + worldMatrix[2] = worldMatrix3x4Array[idx + 2]; + worldMatrix[3] = vec4(0); + // now weight this into final + blendPos += (vertex * worldMatrix).xyz * blendWeights[bone]; + } + + // apply view / projection to position + gl_Position = viewProjectionMatrix * vec4(blendPos, 1); + + gl_FrontSecondaryColor = vec4(0,0,0,0); + gl_FrontColor = ambient; + gl_TexCoord[0] = uv0; +} diff --git a/test/src_dir/fortranfixed.f b/test/src_dir/fortranfixed.f new file mode 100644 index 0000000..63e7b32 --- /dev/null +++ b/test/src_dir/fortranfixed.f @@ -0,0 +1,12 @@ +C Just a comment, whee. + program foo + +C Many languages seem to count split lines as multiple lines, +C so we should, too. + write (*,*) 1 + + + 1 + +C And I've never seen Fortran code that wraps strings; I'm +C not even sure fixed form allows it. + write (*,*) 'So we don''t bother testing odd string foo.' + end diff --git a/test/src_dir/fortranfree.f b/test/src_dir/fortranfree.f new file mode 100644 index 0000000..ebdf995 --- /dev/null +++ b/test/src_dir/fortranfree.f @@ -0,0 +1,18 @@ +! -*- F90 -*- +! Just a comment, whee. + program foofree + integer:: c + +! Many languages seem to count split lines as multiple lines, +! so we should, too. + write (*,*) 1 & + & + 1 + +C = 1 ! Not a comment. + +! And I've never seen Fortran code that wraps strings; I'm +! not even sure fixed form allows it. + write (*,*) 'But we might as well test for it in& + & free format.' + +end diff --git a/test/src_dir/frx1.frx b/test/src_dir/frx1.frx new file mode 100644 index 0000000..eb80d4f --- /dev/null +++ b/test/src_dir/frx1.frx @@ -0,0 +1,60 @@ +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 + ClientHeight = 6555 + ClientLeft = 150 + ClientTop = 435 + ClientWidth = 10620 + LinkTopic = "Form1" + MaxButton = 0 'False + MinButton = 0 'False + ScaleHeight = 6555 + ScaleWidth = 10620 + StartUpPosition = 3 'Windows Default +Attribute VB_Name = "frmMain" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +'--------------------------------------------------------------------------- +' +' SOURCE FILE NAME: Demo.frm +' +' SAMPLE: Visual Basic Demo with user interface for the sample modules +' +' For more information about samples, refer to the README file. +' +'--------------------------------------------------------------------------- + +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 +End Sub diff --git a/test/src_dir/fs1.fs b/test/src_dir/fs1.fs new file mode 100644 index 0000000..433670d --- /dev/null +++ b/test/src_dir/fs1.fs @@ -0,0 +1,51 @@ +(*************************************************************************** + * + * The Parser is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + ***************************************************************************) + +namespace Tags + +open System +open System.Reflection; +open System.Runtime.CompilerServices; +open System.Runtime.InteropServices; + +module internal Filter = + + let FILTER_VARIABLE_NAME = "$filter" + + type FilterNode(provider, token, filter: FilterExpression, node_list) = + inherit TagNode(provider, token) + + override this.walk manager walker = + let reader = + new NDjango.ASTWalker.Reader (manager, {walker with parent=None; nodes=node_list; context=walker.context}) + match filter.ResolveForOutput manager + {walker with context=walker.context.add(FILTER_VARIABLE_NAME, (reader.ReadToEnd():>obj))} + with + | Some w -> w + | None -> walker + + /// Filters the contents of the block through variable filters. + /// + /// Filters can also be piped through each other, and they can have + /// arguments -- just like in variable syntax. + /// + /// Sample usage:: + /// + /// {% filter force_escape|lower %} + /// This text will be HTML-escaped, and will appear in lowercase. + /// {% endfilter %} + type FilterTag() = + interface ITag with + member this.Perform token provider tokens = + match token.Args with + | filter::[] -> + let filter_expr = new FilterExpression(provider, Block token, FILTER_VARIABLE_NAME + "|" + filter) + let node_list, remaining = (provider :?> IParser).Parse (Some token) tokens ["endfilter"] + (new FilterNode(provider, token, filter_expr, node_list) :> INodeImpl), remaining + | _ -> raise (SyntaxError ("'filter' tag requires one argument")) 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/haml.haml b/test/src_dir/haml.haml new file mode 100644 index 0000000..8d27d47 --- /dev/null +++ b/test/src_dir/haml.haml @@ -0,0 +1,20 @@ +%p +%p= "stuff" +/ oneliner! +%p +/ + %p this won't render + %p it is a comment! +%p= "stuff" +%p + - code +%p= "stuff" +%p + +\- not script! +-# silent comment +%p +-# + silent + comment +%br/ diff --git a/test/src_dir/haskell1.hs b/test/src_dir/haskell1.hs new file mode 100644 index 0000000..abe1448 --- /dev/null +++ b/test/src_dir/haskell1.hs @@ -0,0 +1,108 @@ +{-| + This module contains some functions that are useful in several places in the + program and don't belong to one specific other module. +-} +module Gnutella.Misc where + +import Data.ByteString(ByteString) +import qualified Data.ByteString as BS +import Data.Bits +import Data.Word +import Text.Read +import Data.Char(isNumber) +import Data.List(intersperse) +import Network +import Network.BSD(getHostByName, HostEntry(..)) +import Network.Socket(HostAddress(..)) +import Debug.Trace + +{-| + Maakt van vier bytes een Word32. Gaat ervan uit dat die vier bytes little-endian achter elkaar + staan. Als de gegeven string korter is dan 4 bytes, termineert de functie. Als de string langer + is, worden alle bytes voorbij de vierde genegeerd. +-} +composeWord32 :: ByteString -> Word32 +composeWord32 s = shiftL byte4 24 + shiftL byte3 16 + shiftL byte2 8 + byte1 + where byte1, byte2, byte3, byte4 :: Word32 + [byte1, byte2, byte3, byte4] = map fromIntegral $ BS.unpack (BS.take 4 s) + +{-| + Turns a Word32 into a tuple of Word8s. The tuple is little-endian: the least + significant octet comes first. +-} +word32ToWord8s :: Word32 -> (Word8, Word8, Word8, Word8) +word32ToWord8s w = (fromIntegral (w .&. 0x000000ff) + ,fromIntegral (shiftR w 8 .&. 0x000000ff) + ,fromIntegral (shiftR w 16 .&. 0x000000ff) + ,fromIntegral (shiftR w 24 .&. 0x000000ff) + ) + +{-| + Parses a host specification in the "name:12345"-style notation into a hostname + and a port number. + + As a rather special feature, it returns 6346 as the port number when there is + no port specified. When there is a port specified, but it is unparseable, it + returns Nothing. +-} +parseHostnameWithPort :: String -> IO (Maybe ((Word8, Word8, Word8, Word8) + ,PortNumber)) +parseHostnameWithPort str = do maybeHostName <- stringToIP hostNameStr + return $ (do portNum <- maybePortNum + hostName <- maybeHostName + return (hostName, portNum) + ) + where hostNameStr = takeWhile (/=':') str + maybePortNum = case tail (dropWhile (/=':') str) of + [] -> Just $ 6346 + s -> case reads s of + [] -> Nothing + (x:xs) -> Just $ fromIntegral $ fst x + +{-| + Translates a string, representing an IP address, to a list of bytes. + Returns Nothing when the string does not represent an IP address in xxx.xxx.xxx.xxx format +-} +ipStringToBytes :: String -> Maybe (Word8, Word8, Word8, Word8) +-- Again, hugs won't let us use regexes where they would be damn convenient +ipStringToBytes s = + let ipBytesStrings = splitAtDots s + in if all (all isNumber) ipBytesStrings + then let bytesList = map (fst . head . reads) ipBytesStrings + in Just (bytesList!!0 + ,bytesList!!1 + ,bytesList!!2 + ,bytesList!!3 + ) + else Nothing + where splitAtDots s = foldr (\c (n:nums) -> if c == '.' + then [] : n : nums + else (c:n) : nums + ) [[]] s + +{-| + Translates a list of bytes representing an IP address (big endian) to a string + in the xxx.xxx.xxx.xxx format. +-} +ipBytesToString :: (Word8, Word8, Word8, Word8) -> String +ipBytesToString (b1, b2, b3, b4) = + concat $ intersperse "." $ map show [b1, b2, b3, b4] + +{-| + Takes a String that's either an IP address or a hostname, and returns you the + IP address as a list of 4 bytes (in big-endian byte order). It returns Nothing + if there is no parse for the string as IP address and the hostname can't be + found. +-} +stringToIP :: String -> IO (Maybe (Word8, Word8, Word8, Word8)) +stringToIP hostName = case ipStringToBytes hostName of + Just a -> return (Just a) + Nothing -> do hostent <- getHostByName hostName + let ipWord32 = head (hostAddresses hostent) + ipWord8s = word32ToWord8s ipWord32 + return (Just ipWord8s) + +-- used in reading the hostcache +instance Read PortNumber where + readsPrec i = map (\(a, b) -> (fromIntegral a, b)) . (readsPrec i :: ReadS Word16) + diff --git a/test/src_dir/haskell2.hs b/test/src_dir/haskell2.hs new file mode 100644 index 0000000..4d338bc --- /dev/null +++ b/test/src_dir/haskell2.hs @@ -0,0 +1,4 @@ + {-| + + -} + diff --git a/test/src_dir/haskell3.hs b/test/src_dir/haskell3.hs new file mode 100644 index 0000000..76cd83c --- /dev/null +++ b/test/src_dir/haskell3.hs @@ -0,0 +1,5 @@ + {- + {- 3 lines of comments total! -} + + -} + diff --git a/test/src_dir/haxe1.hx b/test/src_dir/haxe1.hx new file mode 100644 index 0000000..d8292c0 --- /dev/null +++ b/test/src_dir/haxe1.hx @@ -0,0 +1,101 @@ +/* +# ***** BEGIN LICENSE BLOCK ***** +Copyright the original author or authors. +Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +# ***** END LICENSE BLOCK ***** +*/ + +package sandy.parser; + +/** + * The Parser factory class creates instances of parser classes. + * The specific parser can be specified in the create method's second parameter. + * + * @author Thomas Pfeiffer - kiroukou + * @author Niel Drummond - haXe port + * + * + * + * @example To parse a 3DS file at runtime: + * + * + * var parser:IParser = Parser.create( "/path/to/my/3dsfile.3ds", Parser.max ); + * + * + */ + +class Parser +{ + /** + * Parameter that is used to specify that the ASE (ASCII Scene Export) + * Parser should be used + */ + public static var ASE:String = "ASE"; + /** + * Parameter that is used to specify that the 3DS (3D Studio) Parser + * should be used + */ + public static var MAX_3DS:String = "3DS"; + /** + * Parameter that is used to specify that the COLLADA (COLLAborative + * Design Activity ) Parser should be used + */ + public static var COLLADA:String = "DAE"; + + /** + * The create method chooses which parser to use. This can be done automatically + * by looking at the file extension or by passing the parser type String as the + * second parameter. + * + * @example To parse a 3DS file at runtime: + * + * + * var parser:IParser = Parser.create( "/path/to/my/3dsfile.3ds", Parser.MAX ); + * + * + * @param p_sFile Can be either a string pointing to the location of the + * file or an instance of an embedded file + * @param p_sParserType The parser type string + * @param p_nScale The scale factor + * @return The parser to be used + */ + public static function create( p_sFile:Dynamic, ?p_sParserType:String, ?p_nScale:Float ):IParser + { + if ( p_nScale == null ) p_nScale = 1; + + var l_sExt:String,l_iParser:IParser = null; + // -- + if( Std.is( p_sFile, String ) && p_sParserType == null ) + { + l_sExt = (p_sFile.split('.')).reverse()[0]; + } + else + { + l_sExt = p_sParserType; + } + // -- + switch( l_sExt.toUpperCase() ) + { + case "ASE": + l_iParser = new ASEParser( p_sFile, p_nScale ); + case "OBJ": + case "DAE": + l_iParser = new ColladaParser( p_sFile, p_nScale ); + case "3DS": + l_iParser = new Parser3DS( p_sFile, p_nScale ); + default: + } + // -- + return l_iParser; + } +} + 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/idl_pvwave.pro b/test/src_dir/idl_pvwave.pro new file mode 100644 index 0000000..f797c91 --- /dev/null +++ b/test/src_dir/idl_pvwave.pro @@ -0,0 +1,83 @@ +;+ +; NAME: +; SHOWFONT +; +; PURPOSE: +; Uses current graphics device to draw a map of characters +; available in the font specified in argument +; +; CATEGORY: +; General +; +; CALLING SEQUENCE: +; showfont, num, 'title' ; table of font num entitled 'title' +; +; KEYWORD PARAMETERS: +; /encapsulated ; ignored (just for compatibility) +; /tt_font ; ignored (just for compatibility) +; base = 16 ; number of columns in the table +; beg = 32 ; first character +; fin = num eq 3 ? 255 : 127 ; last character +; +; OUTPUTS: +; None. +; +; OPTIONAL OUTPUTS: +; None. +; +; COMMON BLOCKS: +; None. +; +; SIDE EFFECTS: +; Draws a font table on the current graphic device. +; +; RESTRICTIONS: +; None. +; +; PROCEDURE: +; +; EXAMPLE: +; showfont, 9, 'GDL math symbols' ; show mappings for font 9 +; +; MODIFICATION HISTORY: +; Written by: Sylwester Arabas (2008/12/28) +;- +; LICENCE: +; Copyright (C) 2008, +; This program is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2 of the License, or +; (at your option) any later version. +;- + +pro showfont, num, name, encapsulated=eps, tt_font=tt, base=base, beg=beg, fin=fin + + ; handling default keyword values + if not keyword_set(base) then base = 16 + if not keyword_set(beg) then beg = 32 + if not keyword_set(fin) then fin = num eq 3 ? 255 : 127 + if not keyword_set(name) then name = '' + + ; constructing horizontal and vertical grid lines + n_hor = (fin + 1 - beg) / base + 1 + h_x = (double(rebin(base * byte(128 * indgen(2 * (n_hor))) / 128, 4 * n_hor, /sample)))[1:4 * n_hor - 1] - .5 + h_y = (double(rebin(beg + indgen(n_hor) * base, 4 * n_hor, /sample)))[0:4 * n_hor - 2] - base/2. + v_x = base - indgen(4 * base - 1) / 4 - .5 + v_y = (double(rebin(byte(128 * indgen(2 * (base))) / 128, 4 * base, /sample)))[1:4 * base - 1] $ + * base * ((fin + 1 - beg) / base) + beg - base / 2. + + ; ploting grid and title + plot, [h_x, v_x], [h_y, v_y], $ + title='Font ' + strtrim(string(num), 2) + ', ' + name, $ + xrange=[-1, base], $ + yrange=[base * ((fin + 1) / base), beg - base], $ + yticks=n_hor, $ + xticks=base+1, $ + xtitle='char mod ' + strtrim(string(base), 2), $ + ytitle=strtrim(string(base), 2) + ' * (char / ' + strtrim(string(base), 2) + ')' + + ; ploting characters + for c = beg, fin do $ + xyouts, (c mod base), base * (c / base), '!' + strtrim(string(num), 2) + string(byte(c)) + +end 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/limbo.b b/test/src_dir/limbo.b new file mode 100644 index 0000000..ad49168 --- /dev/null +++ b/test/src_dir/limbo.b @@ -0,0 +1,65 @@ +implement HgReadrevlog; + +include "sys.m"; + sys: Sys; + sprint: import sys; +include "draw.m"; +include "arg.m"; +include "string.m"; + str: String; +include "mercurial.m"; + mercurial: Mercurial; + Revlog, Repo, Entry, Nodeid, Change: import mercurial; + +dflag: int; + +HgReadrevlog: module { + init: fn(nil: ref Draw->Context, args: list of string); +}; + +init(nil: ref Draw->Context, args: list of string) +{ + sys = load Sys Sys->PATH; + arg := load Arg Arg->PATH; + str = load String String->PATH; + mercurial = load Mercurial Mercurial->PATH; + mercurial->init(); + + arg->init(args); + arg->setusage(arg->progname()+" [-d] path"); + while((c := arg->opt()) != 0) + case c { + 'd' => dflag++; + if(dflag > 1) + mercurial->debug++; + * => arg->usage(); + } + args = arg->argv(); + if(len args != 1) + arg->usage(); + path := hd args; + + (rl, err) := Revlog.open(path); + if(err != nil) + fail(err); + + last: int; + (last, err) = rl.lastrev(); + if(err != nil) + fail(err); + + e: ref Entry; + for(i := 0; i <= last; i++) { + (e, err) = rl.findrev(i); + if(err != nil) + fail(err); + #sys->print("entry %d:\n", i); + sys->print("%s\n", e.text()); + } +} + +fail(s: string) +{ + sys->fprint(sys->fildes(2), "%s\n", s); + raise "fail:"+s; +} diff --git a/test/src_dir/limbo.m b/test/src_dir/limbo.m new file mode 100644 index 0000000..fcd10ff --- /dev/null +++ b/test/src_dir/limbo.m @@ -0,0 +1,8 @@ +Htmlent: module { + PATH: con "/dis/lib/htmlent.dis"; + entities: array of (string, int); + + init: fn(); + lookup: fn(name: string): int; + conv: fn(s: string): string; +}; diff --git a/test/src_dir/lsp1.lsp b/test/src_dir/lsp1.lsp new file mode 100644 index 0000000..644dc8c --- /dev/null +++ b/test/src_dir/lsp1.lsp @@ -0,0 +1,135 @@ +;;; 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..3e66995 --- /dev/null +++ b/test/src_dir/matlab1.m @@ -0,0 +1,56 @@ +% 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.-') + + ... This is a seriously old-school comment. \ No newline at end of file diff --git a/test/src_dir/metafont.mf b/test/src_dir/metafont.mf new file mode 100644 index 0000000..92a3fba --- /dev/null +++ b/test/src_dir/metafont.mf @@ -0,0 +1,22 @@ +% The (not really) first 20 or so lines from the plain METAFONT base + +% Unlimited copying and redistribution of this file are permitted as long +% as this file is not modified. Modifications are permitted, but only if +% the resulting file is not named plain.mf. + +string base_name, base_version; base_name="plain"; base_version="2.71"; + +message "Preloading the plain base, version "&base_version&": preliminaries,"; + +delimiters (); % this makes parentheses behave like parentheses +def upto = step 1 until enddef; % syntactic sugar +def downto = step -1 until enddef; +def exitunless expr c = exitif not c enddef; +let relax = \; % ignore the word `relax', as in TeX +let \\ = \; % double relaxation is like single +def ]] = ] ] enddef; % right brackets should be loners +def -- = {curl 1}..{curl 1} enddef; +def --- = .. tension infinity .. enddef; +def ... = .. tension atleast 1 .. enddef; + +def gobble primary g = enddef; def killtext text t = enddef; diff --git a/test/src_dir/metapost.mp b/test/src_dir/metapost.mp new file mode 100644 index 0000000..ee90ad4 --- /dev/null +++ b/test/src_dir/metapost.mp @@ -0,0 +1,62 @@ +% Sample MetaPost with embedded LaTeX, used as unit test for ohcount +% +% The MetaPost code is taken of LaTeXLabels.mp from +% the excellent MetaPost tutorial by Urs Oswald +% http://www.ursoswald.ch/metapost/tutorial.html +% +verbatimtex +%&latex +\documentclass{article} +\newcommand{\uB}{\upshape{B\'ezier}} % up: upright +\newcommand{\iB}{\itshape{B\'ezier}} % it: italic +\newcommand{\lB}{\slshape{B\'ezier}} % sl: slanted +\newcommand{\cB}{\scshape{B\'ezier}} % sc: small caps +\newfont{\cyr}{wncyr10} +\begin{document} +etex + +u:=25; % 25 = 25bp = 25 PostScript points = 30/72 in +wi:=10; % width in units u +he:=7; % height in units u +hoehe:=he*u; % height +breite:=wi*u; % width +picture lab; + +beginfig(1) + % --- Grid --- + for i=0 upto he: + draw (0, i*u)--(breite, i*u) withcolor .7white; + endfor + for j=0 upto wi: + draw (j*u, 0)--(j*u, hoehe) withcolor .7white; + endfor + % --- End Grid --- + + draw (0, 0)--(breite, 0)--(breite, hoehe)--(0, hoehe)--cycle; + + for i=0 upto 5: + draw .5(u, u){dir 20i}..{dir 20i}(9.5u, 4u); + endfor + + lab:=\thelabel( + btex + \begin{tabular}{|r|l|l|l|l|} + \hline + \textbf{md} & upright & italic & slanted & smallcaps \\ + \hline + rm & \textrm{\uB} & \textrm{\iB} & \textrm{\lB} &\textrm{\cB} \\ + sf & \textsf{\uB} & \textsf{\iB} &\textsf{\lB} &\textsf{\cB} \\ + tt & \texttt{\uB} & \texttt{\iB} &\texttt{\lB} &\texttt{\cB} \\ + \hline + \end{tabular} + etex, + (.5breite, hoehe-1.5u) + ); + + unfill bbox lab; + draw lab; + + label.ulft(btex \cyr C\char24 rih, 08.09.2002 etex, (breite, 0)); +endfig; + +end diff --git a/test/src_dir/mxml1.mxml b/test/src_dir/mxml1.mxml new file mode 100644 index 0000000..884801d --- /dev/null +++ b/test/src_dir/mxml1.mxml @@ -0,0 +1,26 @@ + + + + + + + TextArea { + backgroundColor: #EEF5EE; + } + + + + + + function copy() { + destination.text=source.text + } + + + + + + + + + diff --git a/test/src_dir/mysql-stale-table-sniper b/test/src_dir/mysql-stale-table-sniper new file mode 100644 index 0000000..ba1c3b8 --- /dev/null +++ b/test/src_dir/mysql-stale-table-sniper @@ -0,0 +1,151 @@ +#!/usr/bin/perl + +# This is mysql-table-sniper, a program to help remove tables from a MySQL server. +# +# This program is copyright (c) 2007 Baron Schwartz, baron at xaprb dot com. +# Feedback and improvements are welcome. +# +# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. +# +# 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, version 2; OR the Perl Artistic License. On UNIX and similar +# systems, you can issue `man perlgpl' or `man perlartistic' to read these +# licenses. +# +# 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. + +use strict; +use warnings FATAL => 'all'; + +use DBI; +use English qw(-no_match_vars); +use Getopt::Long; +use List::Util qw(max); + +our $VERSION = '@VERSION@'; + +$OUTPUT_AUTOFLUSH = 1; + +# ############################################################################ +# Get configuration information. +# ############################################################################ + + print <selectcol_arrayref('SHOW DATABASES')}; +my @whole_batch; + +DATABASE: +foreach my $database ( @databases ) { + + # Ignore databases as instructed. Also ignore INFORMATION_SCHEMA and skip + # databases caused by lost+found directories created in the root of ext3 + # filesystems; they are not really databases. + next DATABASE if + ( $opts{d} && !exists($opts{d}->{$database}) ) + || $database =~ m/^(information_schema|lost\+found)$/mi + || exists $opts{g}->{$database}; + + my @tables = @{$dbh->selectcol_arrayref('SHOW TABLES FROM `' . $database . '`')}; + next DATABASE unless @tables; + + my %info_for; + + # Get a list of active connections + my $processes = $dbh->selectall_hashref("show processlist", 'Id'); + + foreach my $db ( @{ $dbh->selectcol_arrayref('show databases') } ) { + my @tables = @{ $dbh->selectcol_arrayref("show tables from $db") }; + foreach my $tbl ( @tables ) { + + # We only want tables whose name ends in digits NOT preceded by other + # digits (for example, barontest_2006_12_06 should not be dropped). + my ( $process ) = $tbl =~ m/\D_(\d+)$/; + + next unless $process; + + # If the process doesn't exist anymore, the table isn't in use. + if ( !exists($processes->{$process} ) ) { + print "Dropping table $db.$tbl\n" if $ENV{RKGDEBUG}; + $dbh->do("drop table if exists $db.$tbl"); + } + } + } + + TABLE: + foreach my $table ( @tables ) { + next TABLE if exists $opts{n}->{$table}; + + my $ddl = ($dbh->selectrow_array("SHOW CREATE TABLE `$database`.`$table`"))[1]; + next TABLE if $ddl =~ m/^CREATE ALGORITHM/; + + } + +} + +# ############################################################################ +# Subroutines +# ############################################################################ + +# ############################################################################ +# Documentation +# ############################################################################ + +=pod + +=head1 NAME + +mysql-stale-table-sniper - Find and possibly remove stale MySQL tables. + +=head1 DESCRIPTION + +=head1 OUTPUT + +=head1 SYSTEM REQUIREMENTS + +You need the following Perl modules: DBI and DBD::mysql. + +=head1 LICENSE + +This program is copyright (c) 2007 Baron Schwartz, baron at xaprb dot com. +Feedback and improvements are welcome. + +THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +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, version 2; OR the Perl Artistic License. On UNIX and similar +systems, you can issue `man perlgpl' or `man perlartistic' to read these +licenses. + +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. + +=head1 AUTHOR + +Baron Schwartz, baron at xaprb dot com. + +=cut diff --git a/test/src_dir/nix.nix b/test/src_dir/nix.nix new file mode 100644 index 0000000..0c92adb --- /dev/null +++ b/test/src_dir/nix.nix @@ -0,0 +1,24 @@ +{pkgs,config}: + +# one line comment +{ +/* mulpiple line comment + foo = 21; +*/ + bar = " + #!/bin/sh + + ls -la + # comment + echo hello #comment + "; + + baz = '' + #!/bin/sh + + ls -la + # comment + echo hello #comment + ''; + nixHttp = [ http://nixos.org/ ]; +} diff --git a/test/src_dir/objj.j b/test/src_dir/objj.j new file mode 100644 index 0000000..88cb674 --- /dev/null +++ b/test/src_dir/objj.j @@ -0,0 +1,25 @@ + +@import +@import + +@import "Superclass.j" + +/* + I'm commenting this class +*/ +@implementation Class : Superclass +{ + var x @accessors; +} + ++ (void)classMethod +{ + return self; // this is a comment +} + +- (void)instanceMethod +{ + return self; +} + +@end diff --git a/test/src_dir/ocaml.ml b/test/src_dir/ocaml.ml new file mode 100644 index 0000000..fa57691 --- /dev/null +++ b/test/src_dir/ocaml.ml @@ -0,0 +1,10 @@ +(** documentation *) +print_string "Hello world!\n";; +(**/**) +(* extra comment *) + +(* multiline + comment*) + +(* recursion in (* a + comment *) to complicate things *) diff --git a/test/src_dir/octave1.m b/test/src_dir/octave1.m new file mode 100644 index 0000000..d72372d --- /dev/null +++ b/test/src_dir/octave1.m @@ -0,0 +1,301 @@ +## Copyright (C) 2006, Regents of the University of California -*- mode: octave; -*- +## +## This program is free software distributed under the "modified" or +## 3-clause BSD license appended to this file. + +function varargout = toledolu(LU) + ## -*- texinfo -*- + ## @deftypefn{Function File} {[@var{L}, @var{U}, @var{P}]} = toledolu(@var{A}) + ## @deftypefnx{Function File} {[@var{L}, @var{U}]} = toledolu(@var{A}) + ## @deftypefnx{Function File} {@var{LUP}} = toledolu(@var{A}) + ## + ## Note: This returns a vector of indices for @var{P} and not a permutation + ## matrix. + ## + ## Factors @var{P}*@var{A}=@var{L}*@var{U} by Sivan Toledo's recursive factorization algorithm + ## with partial pivoting. While not as fast as the built-in LU, this + ## is significantly faster than the standard, unblocked algorithm + ## while remaining relatively easy to modify. + ## + ## See the help for lu for details about the other calling forms. + ## + ## For the algorithm, see + ## @itemize + ## @item + ## Toledo, Sivan. "Locality of reference in LU decomposition with + ## partial pivoting," SIAM J. of Matrix Analysis and Applications, + ## v18, n4, 1997. DOI: 10.1137/S0895479896297744 + ## @end itemize + ## + ## @seealso{lu} + ## + ## @end deftypefn + + ## Author: Jason Riedy + ## Keywords: linear-algebra, LU, factorization + ## Version: 0.2 + + ## This version isn't *quite* the same as Toledo's algorithm. I use a + ## doubling approach rather than using recursion. So non-power-of-2 + ## columns likely will be slightly different, but that shouldn't + ## affect the 'optimality' by more than a small constant factor. + + ## Also, I don't handle ncol > nrow optimally. The code factors the + ## first nrow columns and then updates the remaining ncol-nrow columns + ## with L. + + ## Might be worth eating the memory cost and tracking L separately. + ## The eye(n)+tril(LU,-1) could be expensive. + + switch (nargout) + case 0 + return; + case {1,2,3} + otherwise + usage ("[L,U,P] = lu(A), [P\\L, U] = lu(A), or (P\\L-I+U) = lu(A)"); + endswitch + + [nrow, ncol] = size(LU); + nstep = min(nrow, ncol); + + Pswap = zeros(nstep, 1); + + for j=1:nstep, + [pval, pind] = max(abs(LU(j:nrow, j))); + pind = pind + j - 1; + Pswap(j) = pind; + + kahead = bitand(j, 1+bitcmp(j)); # last 1 bit in j + kstart = j+1-kahead; + kcols = min(kahead, nstep-j); + + inds = kstart : j; + Ucol = j+1 : j+kcols; + Lrow = j+1 : nrow; + + ## permute just this column + if (pind != j) + tmp = LU(pind, j); + LU(pind, j) = LU(j,j); + LU(j,j) = tmp; + endif + ## apply pending permutations to L + n_to_piv = 1; + ipivstart = j; + jpivstart = j - n_to_piv; + while (n_to_piv < kahead) + pivcols = jpivstart : jpivstart+n_to_piv-1; + for ipiv = ipivstart:j, + pind = Pswap(ipiv); + if (pind != ipiv) + tmp = LU(pind, pivcols); + LU(pind, pivcols) = LU(ipiv, pivcols); + LU(ipiv, pivcols) = tmp; + endif + endfor + ipivstart -= n_to_piv; + n_to_piv *= 2; + jpivstart -= n_to_piv; + endwhile + + if (LU(j,j) != 0.0 && !isnan(LU(j,j))), + LU(j+1:nrow,j) /= LU(j,j); + endif + + if 0 == kcols, break; endif + + ## permute U to match perm already applied to L + for k = inds, + tmp = LU(Pswap(k), Ucol); + LU(Pswap(k), Ucol) = LU(k, Ucol); + LU(k, Ucol) = tmp; + endfor + + LU(inds, Ucol) = (eye(kahead) + tril(LU(inds, inds),-1)) \ LU(inds, Ucol); + LU(Lrow, Ucol) -= LU(Lrow, inds) * LU(inds, Ucol); + endfor + + ## handle pivot permutations in L out from the last step + npived = bitand(nstep, 1+bitcmp(nstep)); + j = nstep-npived; + while (j > 0) + n_to_piv = bitand(j, 1+bitcmp(j)); + + pivcols = j-n_to_piv+1 : j; + for ipiv = j+1:nstep, + pind = Pswap(ipiv); + if (pind != ipiv) + tmp = LU(pind, pivcols); + LU(pind, pivcols) = LU(ipiv, pivcols); + LU(ipiv, pivcols) = tmp; + endif + endfor + + j -= n_to_piv; + endwhile + + if (nrow < ncol), + Ucol = nrow+1 : ncol; + inds = 1:nrow; + for k = inds, + tmp = LU(Pswap(k), Ucol); + LU(Pswap(k), Ucol) = LU(k, Ucol); + LU(k, Ucol) = tmp; + endfor + LU(inds, Ucol) = (eye(nrow) + tril(LU(inds, inds),-1)) \ LU(inds, Ucol); + endif + + if (nargout == 1) + varargout{1} = LU; + return; + endif + + if nrow == ncol, + L = eye(nrow) + tril(LU, -1); + varargout{2} = triu(LU); + elseif nrow < ncol, + L = eye(nrow) + tril(LU, -1)(:,1:nrow); + varargout{2} = triu(LU); + else # nrow > ncol + L = tril(LU, -1); + for k=1:ncol, + L(k,k) = 1; + endfor + varargout{2} = triu(LU)(1:ncol,:); + endif + + if (nargout == 2) + for j = 1:nstep, + pind = Pswap(j); + tmp = L(pind,:); + L(pind,:) = L(j,:); + L(j,:) = tmp; + endfor + else # nargout == 3 + P = 1:nrow; + for j = 1:nstep, + tmp = P(j); + P(j) = P(Pswap(j)); + P(Pswap(j)) = tmp; + endfor + varargout{3} = P; + endif + varargout{1} = L; + +endfunction + +%!test +%! M = 15; +%! N = 15; +%! A = rand(M,N); +%! [L,U,P] = toledolu(A); +%! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) + +%!test +%! M = 16; +%! N = 16; +%! A = rand(M,N); +%! [L,U,P] = toledolu(A); +%! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) + +%!test +%! M = 17; +%! N = 17; +%! A = rand(M,N); +%! [L,U,P] = toledolu(A); +%! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) + +%!test +%! M = 8; +%! N = 17; +%! A = rand(M,N); +%! [L,U,P] = toledolu(A); +%! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) + +%!test +%! M = 8; +%! N = 15; +%! A = rand(M,N); +%! [L,U,P] = toledolu(A); +%! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) + +%!test +%! M = 7; +%! N = 17; +%! A = rand(M,N); +%! [L,U,P] = toledolu(A); +%! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) + +%!test +%! M = 7; +%! N = 15; +%! A = rand(M,N); +%! [L,U,P] = toledolu(A); +%! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) + +%!test +%! M = 17; +%! N = 8; +%! A = rand(M,N); +%! [L,U,P] = toledolu(A); +%! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) + +%!test +%! M = 15; +%! N = 8; +%! A = rand(M,N); +%! [L,U,P] = toledolu(A); +%! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) + +%!test +%! M = 17; +%! N = 7; +%! A = rand(M,N); +%! [L,U,P] = toledolu(A); +%! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) + +%!test +%! M = 15; +%! N = 7; +%! A = rand(M,N); +%! [L,U,P] = toledolu(A); +%! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) + +%!test +%! M = 31; +%! N = 17; +%! A = rand(M,N); +%! [L,U,P] = toledolu(A); +%! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) + +%!test +%! M = 11; +%! N = 29; +%! A = rand(M,N); +%! [L,U,P] = toledolu(A); +%! assert(norm(L*U-A(P,:),inf), 0, M**2*N*eps) + +## Copyright (c) 2006, Regents of the University of California +## All rights reserved. +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are met: +## +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in the +## documentation and/or other materials provided with the distribution. +## * Neither the name of the University of California, Berkeley nor the +## names of its contributors may be used to endorse or promote products +## derived from this software without specific prior written permission. +## +## THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +## DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +## DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +## (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +## SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/test/src_dir/optimer b/test/src_dir/optimer new file mode 100755 index 0000000..ee41b53 --- /dev/null +++ b/test/src_dir/optimer @@ -0,0 +1,47 @@ +#!/bin/sh +# optimer – Masserer ordlistefilene til eit kjaptsøkt format. +# +# Copyright © 2008, 2009 Karl Ove Hufthammer . +# +# This file is part of Ordbanken. +# +# Ordbanken 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 3 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, see . + +# Utfør kommandoen pÃ¥ fila oppgjeven som førsteargument. +fil=$1 +echo $fil + +# Forklaring pÃ¥ filtreringskommandoane. +# grep: Filtrer vekk kommentarar (linjer som startar med «*»). +# fgrep: Filtrer unormerte ord. +# sed: Gjer om mellomrom i siste del av linja (der kodane er) til tabulatorar. +# (Korfor den kompliserte sed-kommandoen? Fordi kodane i utgangspunktet er +# skilde med mellomrom i staden for med tabulatorar. Dette ville ikkje vore +# noko problem om alle oppføringar besto av eitt ord, dÃ¥ «column» som +# standard handterer mellomrom og tabulatorar likt, men ordbanken har +# oppføringar som «pÃ¥ kryss og tvers», og dÃ¥ ville alle orda fÃ¥ kvar si +# kolonne (bruk «på» som oppslagsord for Ã¥ sjÃ¥ oppføringa). +# sed: Fjern kodar (pÃ¥ forma ) som inneheld tal (interne/uforstÃ¥elige kodar). +# sed: Fjern kodar («ord» utan <>) som startar med tal (interne/uforstÃ¥elige kodar). +# sed: Fjern talkoden pÃ¥ starten av linja. +# tr: SlÃ¥ saman etterfølgjande tabulatorar til éin. +# sort: Sorter fila (slik at oppslag med «look» gÃ¥r raskare). +grep -v '^\*' $fil \ +| fgrep -v "unormert" \ +| sed -r 'h;s/^([^ ]+ [^ ]+ [^ ]+ )(.*)/\2/;s/ / /g;G;s/(.*)\n([^ ]+ [^ ]+ [^ ]+ )(.*)/\2\1/' \ +| sed -r 's/<[^>]*[0-9][^>]*>+/ /g' \ +| sed -r 's/ [0-9]+[^ ]*/ /g' \ +| sed -r 's/^[0-9]+\s+//' \ +| tr -s '\t' \ +| LC_ALL=C sort > "${fil%.txt}.dat" 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/perl_module.pm b/test/src_dir/perl_module.pm new file mode 100644 index 0000000..f5289f8 --- /dev/null +++ b/test/src_dir/perl_module.pm @@ -0,0 +1,1191 @@ +package PAR::Dist; +require Exporter; +use vars qw/$VERSION @ISA @EXPORT @EXPORT_OK/; + +$VERSION = '0.29'; +@ISA = 'Exporter'; +@EXPORT = qw/ + blib_to_par + install_par + uninstall_par + sign_par + verify_par + merge_par + remove_man + get_meta + generate_blib_stub +/; + +@EXPORT_OK = qw/ + parse_dist_name + contains_binaries +/; + +use strict; +use Carp qw/carp croak/; +use File::Spec; + +=head1 NAME + +PAR::Dist - Create and manipulate PAR distributions + +=head1 VERSION + +This document describes version 0.29 of PAR::Dist, released Feb 6, 2008. + +=head1 SYNOPSIS + +As a shell command: + + % perl -MPAR::Dist -eblib_to_par + +In programs: + + use PAR::Dist; + + my $dist = blib_to_par(); # make a PAR file using ./blib/ + install_par($dist); # install it into the system + uninstall_par($dist); # uninstall it from the system + sign_par($dist); # sign it using Module::Signature + verify_par($dist); # verify it using Module::Signature + + install_par("http://foo.com/DBI-1.37-MSWin32-5.8.0.par"); # works too + install_par("http://foo.com/DBI-1.37"); # auto-appends archname + perlver + install_par("cpan://SMUELLER/PAR-Packer-0.975"); # uses CPAN author directory + +=head1 DESCRIPTION + +This module creates and manipulates I. They are +architecture-specific B files, containing everything under F +of CPAN distributions after their C or C stage, a +F describing metadata of the original CPAN distribution, +and a F detailing all files within it. Digitally signed PAR +distributions will also contain a F file. + +The naming convention for such distributions is: + + $NAME-$VERSION-$ARCH-$PERL_VERSION.par + +For example, C corresponds to the +0.01 release of C on CPAN, built for perl 5.8.0 running on +C. + +=head1 FUNCTIONS + +Several functions are exported by default. Unless otherwise noted, +they can take either a hash of +named arguments, a single argument (taken as C<$path> by C +and C<$dist> by other functions), or no arguments (in which case +the first PAR file in the current directory is used). + +Therefore, under a directory containing only a single F, all +invocations below are equivalent: + + % perl -MPAR::Dist -e"install_par( dist => 'test.par' )" + % perl -MPAR::Dist -e"install_par( 'test.par' )" + % perl -MPAR::Dist -einstall_par; + +If C<$dist> resembles a URL, C is called to mirror it +locally under C<$ENV{PAR_TEMP}> (or C<$TEMP/par/> if unspecified), and the +function will act on the fetched local file instead. If the URL begins +with C, it will be expanded automatically to the author's CPAN +directory (e.g. C). + +If C<$dist> does not have a file extension beginning with a letter or +underscore, a dash and C<$suffix> ($ARCH-$PERL_VERSION.par by default) +will be appended to it. + +=head2 blib_to_par + +Takes key/value pairs as parameters or a single parameter indicating the +path that contains the F subdirectory. + +Builds a PAR distribution from the F subdirectory under C, or +under the current directory if unspecified. If F does not exist, +it automatically runs F, F, F or F to +create it. + +Returns the filename or the generated PAR distribution. + +Valid parameters are: + +=over 2 + +=item path + +Sets the path which contains the F subdirectory from which the PAR +distribution will be generated. + +=item name, version, suffix + +These attributes set the name, version and platform specific suffix +of the distribution. Name and version can be automatically +determined from the distributions F or F files. + +The suffix is generated from your architecture name and your version of +perl by default. + +=item dist + +The output filename for the PAR distribution. + +=back + +=cut + +sub blib_to_par { + @_ = (path => @_) if @_ == 1; + + my %args = @_; + require Config; + + + # don't use 'my $foo ... if ...' it creates a static variable! + my $dist; + my $path = $args{path}; + $dist = File::Spec->rel2abs($args{dist}) if $args{dist}; + my $name = $args{name}; + my $version = $args{version}; + my $suffix = $args{suffix} || "$Config::Config{archname}-$Config::Config{version}.par"; + my $cwd; + + if (defined $path) { + require Cwd; + $cwd = Cwd::cwd(); + chdir $path; + } + + _build_blib() unless -d "blib"; + + my @files; + open MANIFEST, ">", File::Spec->catfile("blib", "MANIFEST") or die $!; + open META, ">", File::Spec->catfile("blib", "META.yml") or die $!; + + require File::Find; + File::Find::find( sub { + next unless $File::Find::name; + (-r && !-d) and push ( @files, substr($File::Find::name, 5) ); + } , 'blib' ); + + print MANIFEST join( + "\n", + ' ', + (sort @files), + q( # ) + ); + close MANIFEST; + + if (open(OLD_META, "META.yml")) { + while () { + if (/^distribution_type:/) { + print META "distribution_type: par\n"; + } + else { + print META $_; + } + + if (/^name:\s+(.*)/) { + $name ||= $1; + $name =~ s/::/-/g; + } + elsif (/^version:\s+.*Module::Build::Version/) { + while () { + /^\s+original:\s+(.*)/ or next; + $version ||= $1; + last; + } + } + elsif (/^version:\s+(.*)/) { + $version ||= $1; + } + } + close OLD_META; + close META; + } + + if ((!$name or !$version) and open(MAKEFILE, "Makefile")) { + while () { + if (/^DISTNAME\s+=\s+(.*)$/) { + $name ||= $1; + } + elsif (/^VERSION\s+=\s+(.*)$/) { + $version ||= $1; + } + } + } + + if (not defined($name) or not defined($version)) { + # could not determine name or version. Error. + my $what; + if (not defined $name) { + $what = 'name'; + $what .= ' and version' if not defined $version; + } + elsif (not defined $version) { + $what = 'version'; + } + + carp("I was unable to determine the $what of the PAR distribution. Please create a Makefile or META.yml file from which we can infer the information or just specify the missing information as an option to blib_to_par."); + return(); + } + + $name =~ s/\s+$//; + $version =~ s/\s+$//; + + my $file = "$name-$version-$suffix"; + unlink $file if -f $file; + + print META << "YAML" if fileno(META); +name: $name +version: $version +build_requires: {} +conflicts: {} +dist_name: $file +distribution_type: par +dynamic_config: 0 +generated_by: 'PAR::Dist version $PAR::Dist::VERSION' +license: unknown +YAML + close META; + + mkdir('blib', 0777); + chdir('blib'); + _zip(dist => File::Spec->catfile(File::Spec->updir, $file)) or die $!; + chdir(File::Spec->updir); + + unlink File::Spec->catfile("blib", "MANIFEST"); + unlink File::Spec->catfile("blib", "META.yml"); + + $dist ||= File::Spec->catfile($cwd, $file) if $cwd; + + if ($dist and $file ne $dist) { + rename( $file => $dist ); + $file = $dist; + } + + my $pathname = File::Spec->rel2abs($file); + if ($^O eq 'MSWin32') { + $pathname =~ s!\\!/!g; + $pathname =~ s!:!|!g; + }; + print << "."; +Successfully created binary distribution '$file'. +Its contents are accessible in compliant browsers as: + jar:file://$pathname!/MANIFEST +. + + chdir $cwd if $cwd; + return $file; +} + +sub _build_blib { + if (-e 'Build') { + system($^X, "Build"); + } + elsif (-e 'Makefile') { + system($Config::Config{make}); + } + elsif (-e 'Build.PL') { + system($^X, "Build.PL"); + system($^X, "Build"); + } + elsif (-e 'Makefile.PL') { + system($^X, "Makefile.PL"); + system($Config::Config{make}); + } +} + +=head2 install_par + +Installs a PAR distribution into the system, using +C. + +Valid parameters are: + +=over 2 + +=item dist + +The .par file to install. The heuristics outlined in the B +section above apply. + +=item prefix + +This string will be prepended to all installation paths. +If it isn't specified, the environment variable +C is used as a prefix. + +=back + +Additionally, you can use several parameters to change the default +installation destinations. You don't usually have to worry about this +unless you are installing into a user-local directory. +The following section outlines the parameter names and default settings: + + Parameter From To + inst_lib blib/lib $Config{installsitelib} (*) + inst_archlib blib/arch $Config{installsitearch} + inst_script blib/script $Config{installscript} + inst_bin blib/bin $Config{installbin} + inst_man1dir blib/man1 $Config{installman1dir} + inst_man3dir blib/man3 $Config{installman3dir} + packlist_read $Config{sitearchexp}/auto/$name/.packlist + packlist_write $Config{installsitearch}/auto/$name/.packlist + +The C parameter is used to control where the F<.packlist> +file is written to. (Necessary for uninstallation.) +The C parameter specifies a .packlist file to merge in if +it exists. By setting any of the above installation targets to C, +you can remove that target altogether. For example, passing +C undef, inst_man3dir => undef> means that the contained +manual pages won't be installed. This is not available for the packlists. + +Finally, you may specify a C parameter. Its value should be +a reference to a hash of custom installation targets such as + + custom_targets => { 'blib/my_data' => '/some/path/my_data' } + +You can use this to install the F<.par> archives contents to arbitrary +locations. + +If only a single parameter is given, it is treated as the C +parameter. + +=cut + +sub install_par { + my %args = &_args; + _install_or_uninstall(%args, action => 'install'); +} + +=head2 uninstall_par + +Uninstalls all previously installed contents of a PAR distribution, +using C. + +Takes almost the same parameters as C, but naturally, +the installation target parameters do not apply. The only exception +to this is the C parameter which specifies the +F<.packlist> file to read the list of installed files from. +It defaults to C<$Config::Config{installsitearch}/auto/$name/.packlist>. + +=cut + +sub uninstall_par { + my %args = &_args; + _install_or_uninstall(%args, action => 'uninstall'); +} + +sub _install_or_uninstall { + my %args = &_args; + my $name = $args{name}; + my $action = $args{action}; + + my %ENV_copy = %ENV; + $ENV{PERL_INSTALL_ROOT} = $args{prefix} if defined $args{prefix}; + + require Cwd; + my $old_dir = Cwd::cwd(); + + my ($dist, $tmpdir) = _unzip_to_tmpdir( dist => $args{dist}, subdir => 'blib' ); + + if ( open (META, File::Spec->catfile('blib', 'META.yml')) ) { + while () { + next unless /^name:\s+(.*)/; + $name = $1; + $name =~ s/\s+$//; + last; + } + close META; + } + return if not defined $name or $name eq ''; + + if (-d 'script') { + require ExtUtils::MY; + foreach my $file (glob("script/*")) { + next unless -T $file; + ExtUtils::MY->fixin($file); + chmod(0555, $file); + } + } + + $name =~ s{::|-}{/}g; + require ExtUtils::Install; + + my $rv; + if ($action eq 'install') { + my $target = _installation_target( File::Spec->curdir, $name, \%args ); + my $custom_targets = $args{custom_targets} || {}; + $target->{$_} = $custom_targets->{$_} foreach keys %{$custom_targets}; + + $rv = ExtUtils::Install::install($target, 1, 0, 0); + } + elsif ($action eq 'uninstall') { + require Config; + $rv = ExtUtils::Install::uninstall( + $args{packlist_read}||"$Config::Config{installsitearch}/auto/$name/.packlist" + ); + } + + %ENV = %ENV_copy; + + chdir($old_dir); + File::Path::rmtree([$tmpdir]); + return $rv; +} + +# Returns the default installation target as used by +# ExtUtils::Install::install(). First parameter should be the base +# directory containing the blib/ we're installing from. +# Second parameter should be the name of the distribution for the packlist +# paths. Third parameter may be a hash reference with user defined keys for +# the target hash. In fact, any contents that do not start with 'inst_' are +# skipped. +sub _installation_target { + require Config; + my $dir = shift; + my $name = shift; + my $user = shift || {}; + + # accepted sources (and user overrides) + my %sources = ( + inst_lib => File::Spec->catdir($dir,"blib","lib"), + inst_archlib => File::Spec->catdir($dir,"blib","arch"), + inst_bin => File::Spec->catdir($dir,'blib','bin'), + inst_script => File::Spec->catdir($dir,'blib','script'), + inst_man1dir => File::Spec->catdir($dir,'blib','man1'), + inst_man3dir => File::Spec->catdir($dir,'blib','man3'), + packlist_read => 'read', + packlist_write => 'write', + ); + + + # default targets + my $target = { + read => $Config::Config{sitearchexp}."/auto/$name/.packlist", + write => $Config::Config{installsitearch}."/auto/$name/.packlist", + $sources{inst_lib} + => (_directory_not_empty($sources{inst_archlib})) + ? $Config::Config{installsitearch} + : $Config::Config{installsitelib}, + $sources{inst_archlib} => $Config::Config{installsitearch}, + $sources{inst_bin} => $Config::Config{installbin} , + $sources{inst_script} => $Config::Config{installscript}, + $sources{inst_man1dir} => $Config::Config{installman1dir}, + $sources{inst_man3dir} => $Config::Config{installman3dir}, + }; + + # Included for future support for ${flavour}perl external lib installation +# if ($Config::Config{flavour_perl}) { +# my $ext = File::Spec->catdir($dir, 'blib', 'ext'); +# # from => to +# $sources{inst_external_lib} = File::Spec->catdir($ext, 'lib'); +# $sources{inst_external_bin} = File::Spec->catdir($ext, 'bin'); +# $sources{inst_external_include} = File::Spec->catdir($ext, 'include'); +# $sources{inst_external_src} = File::Spec->catdir($ext, 'src'); +# $target->{ $sources{inst_external_lib} } = $Config::Config{flavour_install_lib}; +# $target->{ $sources{inst_external_bin} } = $Config::Config{flavour_install_bin}; +# $target->{ $sources{inst_external_include} } = $Config::Config{flavour_install_include}; +# $target->{ $sources{inst_external_src} } = $Config::Config{flavour_install_src}; +# } + + # insert user overrides + foreach my $key (keys %$user) { + my $value = $user->{$key}; + if (not defined $value and $key ne 'packlist_read' and $key ne 'packlist_write') { + # undef means "remove" + delete $target->{ $sources{$key} }; + } + elsif (exists $sources{$key}) { + # overwrite stuff, don't let the user create new entries + $target->{ $sources{$key} } = $value; + } + } + + return $target; +} + +sub _directory_not_empty { + require File::Find; + my($dir) = @_; + my $files = 0; + File::Find::find(sub { + return if $_ eq ".exists"; + if (-f) { + $File::Find::prune++; + $files = 1; + } + }, $dir); + return $files; +} + +=head2 sign_par + +Digitally sign a PAR distribution using C or B, +via B. + +=cut + +sub sign_par { + my %args = &_args; + _verify_or_sign(%args, action => 'sign'); +} + +=head2 verify_par + +Verify the digital signature of a PAR distribution using C or +B, via B. + +Returns a boolean value indicating whether verification passed; C<$!> +is set to the return code of C. + +=cut + +sub verify_par { + my %args = &_args; + $! = _verify_or_sign(%args, action => 'verify'); + return ( $! == Module::Signature::SIGNATURE_OK() ); +} + +=head2 merge_par + +Merge two or more PAR distributions into one. First argument must +be the name of the distribution you want to merge all others into. +Any following arguments will be interpreted as the file names of +further PAR distributions to merge into the first one. + + merge_par('foo.par', 'bar.par', 'baz.par') + +This will merge the distributions C, C and C +into the distribution C. C will be overwritten! +The original META.yml of C is retained. + +=cut + +sub merge_par { + my $base_par = shift; + my @additional_pars = @_; + require Cwd; + require File::Copy; + require File::Path; + require File::Find; + + # parameter checking + if (not defined $base_par) { + croak "First argument to merge_par() must be the .par archive to modify."; + } + + if (not -f $base_par or not -r _ or not -w _) { + croak "'$base_par' is not a file or you do not have enough permissions to read and modify it."; + } + + foreach (@additional_pars) { + if (not -f $_ or not -r _) { + croak "'$_' is not a file or you do not have enough permissions to read it."; + } + } + + # The unzipping will change directories. Remember old dir. + my $old_cwd = Cwd::cwd(); + + # Unzip the base par to a temp. dir. + (undef, my $base_dir) = _unzip_to_tmpdir( + dist => $base_par, subdir => 'blib' + ); + my $blibdir = File::Spec->catdir($base_dir, 'blib'); + + # move the META.yml to the (main) temp. dir. + File::Copy::move( + File::Spec->catfile($blibdir, 'META.yml'), + File::Spec->catfile($base_dir, 'META.yml') + ); + # delete (incorrect) MANIFEST + unlink File::Spec->catfile($blibdir, 'MANIFEST'); + + # extract additional pars and merge + foreach my $par (@additional_pars) { + # restore original directory because the par path + # might have been relative! + chdir($old_cwd); + (undef, my $add_dir) = _unzip_to_tmpdir( + dist => $par + ); + my @files; + my @dirs; + # I hate File::Find + # And I hate writing portable code, too. + File::Find::find( + {wanted =>sub { + my $file = $File::Find::name; + push @files, $file if -f $file; + push @dirs, $file if -d _; + }}, + $add_dir + ); + my ($vol, $subdir, undef) = File::Spec->splitpath( $add_dir, 1); + my @dir = File::Spec->splitdir( $subdir ); + + # merge directory structure + foreach my $dir (@dirs) { + my ($v, $d, undef) = File::Spec->splitpath( $dir, 1 ); + my @d = File::Spec->splitdir( $d ); + shift @d foreach @dir; # remove tmp dir from path + my $target = File::Spec->catdir( $blibdir, @d ); + mkdir($target); + } + + # merge files + foreach my $file (@files) { + my ($v, $d, $f) = File::Spec->splitpath( $file ); + my @d = File::Spec->splitdir( $d ); + shift @d foreach @dir; # remove tmp dir from path + my $target = File::Spec->catfile( + File::Spec->catdir( $blibdir, @d ), + $f + ); + File::Copy::copy($file, $target) + or die "Could not copy '$file' to '$target': $!"; + + } + chdir($old_cwd); + File::Path::rmtree([$add_dir]); + } + + # delete (copied) MANIFEST and META.yml + unlink File::Spec->catfile($blibdir, 'MANIFEST'); + unlink File::Spec->catfile($blibdir, 'META.yml'); + + chdir($base_dir); + my $resulting_par_file = Cwd::abs_path(blib_to_par()); + chdir($old_cwd); + File::Copy::move($resulting_par_file, $base_par); + + File::Path::rmtree([$base_dir]); +} + + +=head2 remove_man + +Remove the man pages from a PAR distribution. Takes one named +parameter: I which should be the name (and path) of the +PAR distribution file. The calling conventions outlined in +the C section above apply. + +The PAR archive will be +extracted, stripped of all C and C subdirectories +and then repackaged into the original file. + +=cut + +sub remove_man { + my %args = &_args; + my $par = $args{dist}; + require Cwd; + require File::Copy; + require File::Path; + require File::Find; + + # parameter checking + if (not defined $par) { + croak "First argument to remove_man() must be the .par archive to modify."; + } + + if (not -f $par or not -r _ or not -w _) { + croak "'$par' is not a file or you do not have enough permissions to read and modify it."; + } + + # The unzipping will change directories. Remember old dir. + my $old_cwd = Cwd::cwd(); + + # Unzip the base par to a temp. dir. + (undef, my $base_dir) = _unzip_to_tmpdir( + dist => $par, subdir => 'blib' + ); + my $blibdir = File::Spec->catdir($base_dir, 'blib'); + + # move the META.yml to the (main) temp. dir. + File::Copy::move( + File::Spec->catfile($blibdir, 'META.yml'), + File::Spec->catfile($base_dir, 'META.yml') + ); + # delete (incorrect) MANIFEST + unlink File::Spec->catfile($blibdir, 'MANIFEST'); + + opendir DIRECTORY, 'blib' or die $!; + my @dirs = grep { /^blib\/(?:man\d*|html)$/ } + grep { -d $_ } + map { File::Spec->catfile('blib', $_) } + readdir DIRECTORY; + close DIRECTORY; + + File::Path::rmtree(\@dirs); + + chdir($base_dir); + my $resulting_par_file = Cwd::abs_path(blib_to_par()); + chdir($old_cwd); + File::Copy::move($resulting_par_file, $par); + + File::Path::rmtree([$base_dir]); +} + + +=head2 get_meta + +Opens a PAR archive and extracts the contained META.yml file. +Returns the META.yml file as a string. + +Takes one named parameter: I. If only one parameter is +passed, it is treated as the I parameter. (Have a look +at the description in the C section above.) + +Returns undef if no PAR archive or no META.yml within the +archive were found. + +=cut + +sub get_meta { + my %args = &_args; + my $dist = $args{dist}; + return undef if not defined $dist or not -r $dist; + require Cwd; + require File::Path; + + # The unzipping will change directories. Remember old dir. + my $old_cwd = Cwd::cwd(); + + # Unzip the base par to a temp. dir. + (undef, my $base_dir) = _unzip_to_tmpdir( + dist => $dist, subdir => 'blib' + ); + my $blibdir = File::Spec->catdir($base_dir, 'blib'); + + my $meta = File::Spec->catfile($blibdir, 'META.yml'); + + if (not -r $meta) { + return undef; + } + + open FH, '<', $meta + or die "Could not open file '$meta' for reading: $!"; + + local $/ = undef; + my $meta_text = ; + close FH; + + chdir($old_cwd); + + File::Path::rmtree([$base_dir]); + + return $meta_text; +} + + + +sub _unzip { + my %args = &_args; + my $dist = $args{dist}; + my $path = $args{path} || File::Spec->curdir; + return unless -f $dist; + + # Try fast unzipping first + if (eval { require Archive::Unzip::Burst; 1 }) { + my $return = Archive::Unzip::Burst::unzip($dist, $path); + return if $return; # true return value == error (a la system call) + } + # Then slow unzipping + if (eval { require Archive::Zip; 1 }) { + my $zip = Archive::Zip->new; + local %SIG; + $SIG{__WARN__} = sub { print STDERR $_[0] unless $_[0] =~ /\bstat\b/ }; + return unless $zip->read($dist) == Archive::Zip::AZ_OK() + and $zip->extractTree('', "$path/") == Archive::Zip::AZ_OK(); + } + # Then fall back to the system + else { + return if system(unzip => $dist, '-d', $path); + } + + return 1; +} + +sub _zip { + my %args = &_args; + my $dist = $args{dist}; + + if (eval { require Archive::Zip; 1 }) { + my $zip = Archive::Zip->new; + $zip->addTree( File::Spec->curdir, '' ); + $zip->writeToFileNamed( $dist ) == Archive::Zip::AZ_OK() or die $!; + } + else { + system(qw(zip -r), $dist, File::Spec->curdir) and die $!; + } +} + + +# This sub munges the arguments to most of the PAR::Dist functions +# into a hash. On the way, it downloads PAR archives as necessary, etc. +sub _args { + # default to the first .par in the CWD + if (not @_) { + @_ = (glob('*.par'))[0]; + } + + # single argument => it's a distribution file name or URL + @_ = (dist => @_) if @_ == 1; + + my %args = @_; + $args{name} ||= $args{dist}; + + # If we are installing from an URL, we want to munge the + # distribution name so that it is in form "Module-Name" + if (defined $args{name}) { + $args{name} =~ s/^\w+:\/\///; + my @elems = parse_dist_name($args{name}); + # @elems is name, version, arch, perlversion + if (defined $elems[0]) { + $args{name} = $elems[0]; + } + else { + $args{name} =~ s/^.*\/([^\/]+)$/$1/; + $args{name} =~ s/^([0-9A-Za-z_-]+)-\d+\..+$/$1/; + } + } + + # append suffix if there is none + if ($args{dist} and not $args{dist} =~ /\.[a-zA-Z_][^.]*$/) { + require Config; + my $suffix = $args{suffix}; + $suffix ||= "$Config::Config{archname}-$Config::Config{version}.par"; + $args{dist} .= "-$suffix"; + } + + # download if it's an URL + if ($args{dist} and $args{dist} =~ m!^\w+://!) { + $args{dist} = _fetch(dist => $args{dist}) + } + + return %args; +} + + +# Download PAR archive, but only if necessary (mirror!) +my %escapes; +sub _fetch { + my %args = @_; + + if ($args{dist} =~ s/^file:\/\///) { + return $args{dist} if -e $args{dist}; + return; + } + require LWP::Simple; + + $ENV{PAR_TEMP} ||= File::Spec->catdir(File::Spec->tmpdir, 'par'); + mkdir $ENV{PAR_TEMP}, 0777; + %escapes = map { chr($_) => sprintf("%%%02X", $_) } 0..255 unless %escapes; + + $args{dist} =~ s{^cpan://((([a-zA-Z])[a-zA-Z])[-_a-zA-Z]+)/} + {http://www.cpan.org/modules/by-authors/id/\U$3/$2/$1\E/}; + + my $file = $args{dist}; + $file =~ s/([^\w\.])/$escapes{$1}/g; + $file = File::Spec->catfile( $ENV{PAR_TEMP}, $file); + my $rc = LWP::Simple::mirror( $args{dist}, $file ); + + if (!LWP::Simple::is_success($rc) and $rc != 304) { + die "Error $rc: ", LWP::Simple::status_message($rc), " ($args{dist})\n"; + } + + return $file if -e $file; + return; +} + +sub _verify_or_sign { + my %args = &_args; + + require File::Path; + require Module::Signature; + die "Module::Signature version 0.25 required" + unless Module::Signature->VERSION >= 0.25; + + require Cwd; + my $cwd = Cwd::cwd(); + my $action = $args{action}; + my ($dist, $tmpdir) = _unzip_to_tmpdir($args{dist}); + $action ||= (-e 'SIGNATURE' ? 'verify' : 'sign'); + + if ($action eq 'sign') { + open FH, '>SIGNATURE' unless -e 'SIGNATURE'; + open FH, 'MANIFEST' or die $!; + + local $/; + my $out = ; + if ($out !~ /^SIGNATURE(?:\s|$)/m) { + $out =~ s/^(?!\s)/SIGNATURE\n/m; + open FH, '>MANIFEST' or die $!; + print FH $out; + } + close FH; + + $args{overwrite} = 1 unless exists $args{overwrite}; + $args{skip} = 0 unless exists $args{skip}; + } + + my $rv = Module::Signature->can($action)->(%args); + _zip(dist => $dist) if $action eq 'sign'; + File::Path::rmtree([$tmpdir]); + + chdir($cwd); + return $rv; +} + +sub _unzip_to_tmpdir { + my %args = &_args; + + require File::Temp; + + my $dist = File::Spec->rel2abs($args{dist}); + my $tmpdirname = File::Spec->catdir(File::Spec->tmpdir, "parXXXXX"); + my $tmpdir = File::Temp::mkdtemp($tmpdirname) + or die "Could not create temporary directory from template '$tmpdirname': $!"; + my $path = $tmpdir; + $path = File::Spec->catdir($tmpdir, $args{subdir}) if defined $args{subdir}; + _unzip(dist => $dist, path => $path); + + chdir $tmpdir; + return ($dist, $tmpdir); +} + + + +=head2 parse_dist_name + +First argument must be a distribution file name. The file name +is parsed into I, I, +I, and I. + +Returns the results as a list in the above order. +If any or all of the above cannot be determined, returns undef instead +of the undetermined elements. + +Supported formats are: + +Math-Symbolic-0.502-x86_64-linux-gnu-thread-multi-5.8.7 + +Math-Symbolic-0.502 + +The ".tar.gz" or ".par" extensions as well as any +preceding paths are stripped before parsing. Starting with C +0.22, versions containing a preceding C are parsed correctly. + +This function is not exported by default. + +=cut + +sub parse_dist_name { + my $file = shift; + return(undef, undef, undef, undef) if not defined $file; + + (undef, undef, $file) = File::Spec->splitpath($file); + + my $version = qr/v?(?:\d+(?:_\d+)?|\d*(?:\.\d+(?:_\d+)?)+)/; + $file =~ s/\.(?:par|tar\.gz|tar)$//i; + my @elem = split /-/, $file; + my (@dn, $dv, @arch, $pv); + while (@elem) { + my $e = shift @elem; + if ( + $e =~ /^$version$/o + and not(# if not next token also a version + # (assumes an arch string doesnt start with a version...) + @elem and $elem[0] =~ /^$version$/o + ) + ) { + + $dv = $e; + last; + } + push @dn, $e; + } + + my $dn; + $dn = join('-', @dn) if @dn; + + if (not @elem) { + return( $dn, $dv, undef, undef); + } + + while (@elem) { + my $e = shift @elem; + if ($e =~ /^$version|any_version$/) { + $pv = $e; + last; + } + push @arch, $e; + } + + my $arch; + $arch = join('-', @arch) if @arch; + + return($dn, $dv, $arch, $pv); +} + +=head2 generate_blib_stub + +Creates a F subdirectory in the current directory +and prepares a F with meta information for a +new PAR distribution. First argument should be the name of the +PAR distribution in a format understood by C. +Alternatively, named arguments resembling those of +C are accepted. + +After running C and injecting files into +the F directory, you can create a PAR distribution +using C. +This function is useful for creating custom PAR distributions +from scratch. (I.e. not from an unpacked CPAN distribution) +Example: + + use PAR::Dist; + use File::Copy 'copy'; + + generate_blib_stub( + name => 'MyApp', version => '1.00' + ); + copy('MyApp.pm', 'blib/lib/MyApp.pm'); + blib_to_par(); # generates the .par file! + +C will not overwrite existing files. + +=cut + +sub generate_blib_stub { + my %args = &_args; + my $dist = $args{dist}; + require Config; + + my $name = $args{name}; + my $version = $args{version}; + my $suffix = $args{suffix}; + + my ($parse_name, $parse_version, $archname, $perlversion) + = parse_dist_name($dist); + + $name ||= $parse_name; + $version ||= $parse_version; + $suffix = "$archname-$perlversion" + if (not defined $suffix or $suffix eq '') + and $archname and $perlversion; + + $suffix ||= "$Config::Config{archname}-$Config::Config{version}"; + if ( grep { not defined $_ } ($name, $version, $suffix) ) { + warn "Could not determine distribution meta information from distribution name '$dist'"; + return(); + } + $suffix =~ s/\.par$//; + + if (not -f 'META.yml') { + open META, '>', 'META.yml' + or die "Could not open META.yml file for writing: $!"; + print META << "YAML" if fileno(META); +name: $name +version: $version +build_requires: {} +conflicts: {} +dist_name: $name-$version-$suffix.par +distribution_type: par +dynamic_config: 0 +generated_by: 'PAR::Dist version $PAR::Dist::VERSION' +license: unknown +YAML + close META; + } + + mkdir('blib'); + mkdir(File::Spec->catdir('blib', 'lib')); + mkdir(File::Spec->catdir('blib', 'script')); + + return 1; +} + + +=head2 contains_binaries + +This function is not exported by default. + +Opens a PAR archive tries to determine whether that archive +contains platform-specific binary code. + +Takes one named parameter: I. If only one parameter is +passed, it is treated as the I parameter. (Have a look +at the description in the C section above.) + +Throws a fatal error if the PAR archive could not be found. + +Returns one if the PAR was found to contain binary code +and zero otherwise. + +=cut + +sub contains_binaries { + require File::Find; + my %args = &_args; + my $dist = $args{dist}; + return undef if not defined $dist or not -r $dist; + require Cwd; + require File::Path; + + # The unzipping will change directories. Remember old dir. + my $old_cwd = Cwd::cwd(); + + # Unzip the base par to a temp. dir. + (undef, my $base_dir) = _unzip_to_tmpdir( + dist => $dist, subdir => 'blib' + ); + my $blibdir = File::Spec->catdir($base_dir, 'blib'); + my $archdir = File::Spec->catdir($blibdir, 'arch'); + + my $found = 0; + + File::Find::find( + sub { + $found++ if -f $_ and not /^\.exists$/; + }, + $archdir + ); + + chdir($old_cwd); + + File::Path::rmtree([$base_dir]); + + return $found ? 1 : 0; +} + +1; + +=head1 SEE ALSO + +L, L, L, L + +=head1 AUTHORS + +Audrey Tang Ecpan@audreyt.orgE 2003-2007 + +Steffen Mueller Esmueller@cpan.orgE 2005-2007 + +PAR has a mailing list, Epar@perl.orgE, that you can write to; +send an empty mail to Epar-subscribe@perl.orgE to join the list +and participate in the discussion. + +Please send bug reports to Ebug-par@rt.cpan.orgE. + +=head1 COPYRIGHT + +Copyright 2003-2007 by Audrey Tang Eautrijus@autrijus.orgE. + +This program is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +See L + +=cut diff --git a/test/src_dir/perl_pod_to_eof.pl b/test/src_dir/perl_pod_to_eof.pl new file mode 100644 index 0000000..88d626a --- /dev/null +++ b/test/src_dir/perl_pod_to_eof.pl @@ -0,0 +1 @@ +=head NAME diff --git a/test/src_dir/php1.php b/test/src_dir/php1.php new file mode 100644 index 0000000..43b4182 --- /dev/null +++ b/test/src_dir/php1.php @@ -0,0 +1,59 @@ + + + + + + + + + + + + +
FirstLastEmail +
+ + + + + + + + + + + + + diff --git a/test/src_dir/pike1.pike b/test/src_dir/pike1.pike new file mode 100644 index 0000000..b4f3818 --- /dev/null +++ b/test/src_dir/pike1.pike @@ -0,0 +1,6 @@ +#!/bin/env pike +/* Say hello. */ +int main(int argc, array(string) argv) +{ + Stdio.stdout.write("Hello, world.\n"); +} diff --git a/test/src_dir/pike2.pmod b/test/src_dir/pike2.pmod new file mode 100644 index 0000000..dd5d77b --- /dev/null +++ b/test/src_dir/pike2.pmod @@ -0,0 +1,241 @@ +// +// LPD.pmod: an implementation of the BSD lpd protocol (RFC 1179). +// This is a module for pike. +// 3 July 1998 Bill Welliver +// +// $Id: LPD.pmod,v 1.10 2008/01/13 17:02:43 nilsson Exp $ +// + +#pike __REAL_VERSION__ + +//! A client for communicating with printers and print spoolers that +//! support the BSD lpd protocol (RFC 1179). +class client { + string host; + int port; + private object conn; + int jobnum; + string jobtype; + string jobname; + + private int connect(string host, int port) + { + int a=random(10); + // try to open one of the "official" local socket ports. + // not having one doesn't seem to be a problem with most LPD + // servers, but we should at least try. will probably fail + // if two try to open the same local port at once. ymmv. + int res=conn->open_socket(721 + a); + + return conn->connect(host, port); + } + +//! @decl int set_job_type(string type) +//! Set the type of job to be sent to the printer to @i{type@}. +//! Valid types are: text, postscript and raw. + int set_job_type(string type) + { + type=lower_case(type); + + switch (type) { + case "f": + case "text": + jobtype="f"; + break; + + case "o": + case "postscript": + case "ps": + jobtype="o"; + break; + + default: + case "l": + case "raw": + jobtype="l"; + break; + } + return 1; + } + +//! @decl int set_job_name(string name) +//! Sets the name of the print job to @i{name@}. + int set_job_name(string name) + { + jobname=name; + return 1; + } + +//! @decl int start_queue(string queue) +//! Start the queue @i{queue@} if not already printing. +//! @returns +//! Returns 0 if unable to connect, 1 otherwise. + int start_queue(string queue) + { + if(!queue) return 0; + + if(!connect(host, port)) + return 0; + + conn->write(sprintf("%c%s\n", 01, queue)); + string resp= conn->read(); + conn->close(); + return 1; + } + +//! @decl string|int send_job(string queue, string job) +//! Send print job consisting of data @i{job@} to printer @i{queue@}. +//! @returns +//! Returns 1 if success, 0 otherwise. + int send_job(string queue, string job) + { + string resp; + + if(!queue) return 0; + + if(!connect(host, port)) + return 0; + // werror("connected to " + host + "\n"); + + string control=""; + control+="H"+gethostname()+"\n"; +#if constant(getuid) && constant(getpwuid) + control+="P"+(getpwuid(getuid())[0]||"nobody")+"\n"; +#else + control+="P-1\n"; +#endif + control+=(jobtype||"l")+"dfA"+ sprintf("%03d%s", jobnum, gethostname())+"\n"; + if(jobname) + { + control+="J" + jobname + "\n"; + control+="N" + jobname + "\n"; + } + else + { + control+="JPike LPD Client Job " + jobnum + "\n"; + control+="NPike LPD Client Job " + jobnum + "\n"; + } + jobnum++; +werror("job file:\n\n" + control + "\n\n"); + + conn->write(sprintf("%c%s\n", 02, queue)); + resp=conn->read(1); + if((int)resp !=0) + { + werror("receive job failed.\n"); + return 0; + } + + conn->write(sprintf("%c%s cfA%03d%s\n", 02, (string)sizeof(control), + jobnum,gethostname())); + + resp=conn->read(1); + if((int)resp !=0) + { + werror("request receive control failed.\n"); + return 0; + } + + conn->write(sprintf("%s%c", control, 0)); + + resp=conn->read(1); + if((int)resp !=0) + { + werror("send receive control failed.\n"); + return 0; + } + + conn->write(sprintf("%c%s dfA%03d%s\n", 03, (string)sizeof(job), jobnum, + gethostname())); + resp=conn->read(1); + if((int)resp !=0) + { + werror("request receive job failed.\n"); + return 0; + } + + + conn->write(sprintf("%s%c", job, 0)); + + resp=conn->read(1); + if((int)resp !=0) + { + werror("send receive job failed.\n"); + return 0; + } + + + + // read the response. + +// resp=conn->read(); + if((int)(resp)!=0) + { + conn->close(); + return 0; + } + conn->close(); +// start_queue(queue); + return 1; + } + +//! @decl int delete_job(string queue, int|void job) +//! Delete job @i{job@} from printer @i{queue@}. +//! @returns +//! Returns 1 on success, 0 otherwise. + int delete_job(string queue, int|void job) + { + if(!queue) return 0; + + if(!connect(host, port)) + return 0; + +#if constant(getpwuid) && constant(getuid) + string agent=(getpwuid(getuid())[0]||"nobody"); +#else + string agent="nobody"; +#endif + + if(job) + conn->write(sprintf("%c%s %s %d\n", 05, queue, agent, job)); + else + conn->write(sprintf("%c%s %s\n", 05, queue, agent)); + string resp= conn->read(); + conn->close(); + return 1; + } + + +//! @decl string|int status(string queue) +//! Check the status of queue @i{queue@}. +//! @returns +//! Returns 0 on failure, otherwise returns the status response from the printer. + string|int status(string queue) + { + if(!queue) return 0; + + if(!connect(host, port)) + return 0; + + conn->write(sprintf("%c%s\n", 04, queue)); + string resp= conn->read(); + conn->close(); + return resp; + } + +//! Create a new LPD client connection. +//! @param hostname +//! Contains the hostname or ipaddress of the print host. +//! if not provided, defaults to @i{localhost@}. +//! @param portnum +//! Contains the port the print host is listening on. +//! if not provided, defaults to port @i{515@}, the RFC 1179 standard. + void create(string|void hostname, int|void portnum) + { + host=hostname || "localhost"; + port=portnum || 515; + conn=Stdio.File(); + jobnum=1; + } +} + diff --git a/test/src_dir/py1.py b/test/src_dir/py1.py new file mode 100644 index 0000000..8225f17 --- /dev/null +++ b/test/src_dir/py1.py @@ -0,0 +1,18 @@ +# some python code +# lorem +# ipsum +# foo + +class Foo: + """ + This is a foo class + It doesn't do anything + Therefore this doc comment is pointless + """ + + def __init__(self, bar): + """short doc comment""" + print(bar) + + def string(self): + print('This is a string') 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/scala1.scala b/test/src_dir/scala1.scala new file mode 100644 index 0000000..e02a23e --- /dev/null +++ b/test/src_dir/scala1.scala @@ -0,0 +1,63 @@ +import scala.actors.Actor + +case object Ping +case object Pong +case object Stop + +/** + * Ping class + */ +class Ping(count: int, pong: Actor) extends Actor { + def act() { + var pingsLeft = count - 1 + pong ! Ping + while (true) { + receive { + case Pong => + if (pingsLeft % 1000 == 0) + Console.println("Ping: pong") + if (pingsLeft > 0) { + pong ! Ping + pingsLeft -= 1 + } else { + Console.println("Ping: stop") + pong ! Stop + exit() + } + } + } + } +} + +/** + * Pong class + */ +class Pong extends Actor { + def act() { + var pongCount = 0 + while (true) { + receive { + //pong back the ping + case Ping => + if (pongCount % 1000 == 0) + Console.println("Pong: ping "+pongCount) + sender ! Pong + pongCount = pongCount + 1 + //stop ping ponging + case Stop => + Console.println("Pong: stop") + exit() + } + } + } +} + +/* + * And this is the main application, playing a game of ping pong + */ +object PingPong extends Application { + val pong = new Pong + val ping = new Ping(100000, pong) + ping.start + pong.start +} diff --git a/test/src_dir/schema.xsd b/test/src_dir/schema.xsd new file mode 100644 index 0000000..ba1193e --- /dev/null +++ b/test/src_dir/schema.xsd @@ -0,0 +1,68 @@ + + + + + + 0836217462 + + + Being a Dog Is a Full-Time Job + + + + Charles M Schulz + + + 1922-11-26 + + + 2000-02-12 + + + + + Peppermint Patty + + + 1966-08-22 + + + bold, brash and tomboyish + + + + + Snoopy + + + 1950-10-04 + + + extroverted beagle + + + + + Schroeder + + + 1951-05-30 + + + brought classical music to the Peanuts strip + + + + + Lucy + + + 1952-03-03 + + + bossy, crabby and selfish + + + + diff --git a/test/src_dir/scheme.scm b/test/src_dir/scheme.scm new file mode 100644 index 0000000..2bb8165 --- /dev/null +++ b/test/src_dir/scheme.scm @@ -0,0 +1,32 @@ +(+ 1 (/ 1 0) 3) +; => A divide by zero error is raised + +(with-failure-continuation + (lambda (error-record error-k) + 'error) + (lambda () (+ 1 (/ 1 0) 3))) +; => The symbol 'error + +(with-failure-continuation + (lambda (error-record error-k) + (error-k 2)) + (lambda () (+ 1 (/ 1 0) 3))) +; => 6 + +(with-failure-continuation + (lambda (error-record error-k) + (throw error-record error-k)) + (lambda () (+ 1 (/ 1 0) 3))) +; => A divide by zero error is raised + +(with-failure-continuation + (lambda (error-record error-k) + (throw (make-error '/ "could not perform the division.") error-k)) + (lambda () (+ 1 (/ 1 0) 3))) +; => An error is raised: Error in /: could not perform the division. + +(with-failure-continuation + (lambda (error-record error-k) + (error 'example-function "could not evaluate the expression.")) + (lambda () (+ 1 (/ 1 0) 3))) +; => An error is raised: Error in example-function: could not evaluate the expression. diff --git a/test/src_dir/scilab.sci b/test/src_dir/scilab.sci new file mode 100644 index 0000000..a01e1a6 --- /dev/null +++ b/test/src_dir/scilab.sci @@ -0,0 +1,35 @@ +// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab +// Copyright (C) INRIA - Serge STEER +// +// This file must be used under the terms of the CeCILL. +// This source file is licensed as described in the file COPYING, which +// you should have received as part of this distribution. The terms +// are also available at +// http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt + +function I=sub2ind(dims,varargin) +//sub2ind is used to determine the equivalent single index +//corresponding to a given set of subscript values. + +//I = sub2ind(dims,i1,i2,..) returns the linear index equivalent to the +//row, column, ... subscripts in the arrays i1,i2,.. for an matrix of +//size dims. + +//I = sub2ind(dims,Mi) returns the linear index +//equivalent to the n subscripts in the columns of the matrix Mi for a matrix +//of size dims. + + d=[1;cumprod(matrix(dims(1:$-1),-1,1))] + for i=1:size(varargin) + if varargin(i)==[] then I=[],return,end + end + + if size(varargin)==1 then //subindices are the columns of the argument + I=(varargin(1)-1)*d+1 + else //subindices are given as separated arguments + I=1 + for i=1:size(varargin) + I=I+(varargin(i)-1)*d(i) + end + end +endfunction 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/smalltalk1.st b/test/src_dir/smalltalk1.st new file mode 100644 index 0000000..cc83e32 --- /dev/null +++ b/test/src_dir/smalltalk1.st @@ -0,0 +1,19 @@ +"====================================================================== +| +| Benchmark for streams +| +| + ======================================================================" + + +Eval [ + n := Smalltalk arguments isEmpty + ifTrue: [ 10000 ] + ifFalse: [ 1 max: Smalltalk arguments first asInteger ]. + + hello := String new writeStream. + n timesRepeat: [ hello nextPutAll: 'hello +\' ]. "this is a comment +so this line is a comment too\" + hello position displayNl +"but the previous one, and this one too, are not!" ] diff --git a/test/src_dir/sql1.sql b/test/src_dir/sql1.sql new file mode 100644 index 0000000..767a5df --- /dev/null +++ b/test/src_dir/sql1.sql @@ -0,0 +1,31 @@ +// ----------------------------------------------------------------------- +// 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 +// ----------------------------------------------------------------------- + +## Comment with a hash symbol ## +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/stratego.str b/test/src_dir/stratego.str new file mode 100644 index 0000000..b6255be --- /dev/null +++ b/test/src_dir/stratego.str @@ -0,0 +1,25 @@ +/** + * Sample code from Stratego XT Manual + */ + +rules + InlineF : + |[ let f(xs) = e in e'[f(es)] ]| -> + |[ let f(xs) = e in e'[e[es/xs]] ]| + + InlineV : + |[ let x = e in e'[x] ]| -> |[ let x = e in e'[e] ]| + + Dead : + |[ let x = e in e' ]| -> |[ e' ]| + where (x,e') + + Extract(f,xs) : + |[ e ]| -> |[ let f(xs) = e in f(xs) ]| + + Hoist : + |[ let x = e1 in let f(xs) = e2 in e3 ]| -> + |[ let f(xs) = e2 in let x = e1 in e3 ]| + where (x, e2) + +// better watch those apostrophes! diff --git a/test/src_dir/structured_basic.b b/test/src_dir/structured_basic.b new file mode 100644 index 0000000..1bf0b06 --- /dev/null +++ b/test/src_dir/structured_basic.b @@ -0,0 +1,20 @@ +INPUT "What is your name: "; U$ +PRINT "Hello "; U$ +REM Test +INPUT "How many stars do you want: "; N +S$ = "" +FOR I = 1 TO N +S$ = S$ + "*" +NEXT I +PRINT S$ + +REM +INPUT "Do you want more stars? "; A$ +IF LEN(A$) = 0 THEN GOTO 110 +A$ = LEFT$(A$, 1) +IF (A$ = "Y") OR (A$ = "y") THEN GOTO 40 +PRINT "Goodbye "; +FOR I = 1 TO 200 +PRINT U$; " "; +NEXT I +PRINT diff --git a/test/src_dir/structured_basic.bas b/test/src_dir/structured_basic.bas new file mode 100644 index 0000000..1bf0b06 --- /dev/null +++ b/test/src_dir/structured_basic.bas @@ -0,0 +1,20 @@ +INPUT "What is your name: "; U$ +PRINT "Hello "; U$ +REM Test +INPUT "How many stars do you want: "; N +S$ = "" +FOR I = 1 TO N +S$ = S$ + "*" +NEXT I +PRINT S$ + +REM +INPUT "Do you want more stars? "; A$ +IF LEN(A$) = 0 THEN GOTO 110 +A$ = LEFT$(A$, 1) +IF (A$ = "Y") OR (A$ = "y") THEN GOTO 40 +PRINT "Goodbye "; +FOR I = 1 TO 200 +PRINT U$; " "; +NEXT I +PRINT 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/vala1.vala b/test/src_dir/vala1.vala new file mode 100644 index 0000000..476d3f3 --- /dev/null +++ b/test/src_dir/vala1.vala @@ -0,0 +1,61 @@ +using GLib; + + + +// Class which makes the event +public class Game : Object { + // Note the use of the signal keyword + public signal void score_change (int newScore, ref bool cancel); + + int _score; + + // Score Property + public int score { + get { + return _score; + } + set { + if (_score != value) { + bool cancel = false; + score_change (value, ref cancel); + if (! cancel) + _score = value; + } + } + } +} + +// Class which handles the event +public class Referee : Object +{ + public Game game { get; construct; } + + public Referee (construct Game game) { + } + + construct { + // Monitor when a score changes in the game + game.score_change += game_score_change; + } + + // Notice how this method signature matches the score_change signal's signature + private void game_score_change (Game game, int new_score, ref bool cancel) { + if (new_score < 100) + stdout.printf ("Good Score\n"); + else { + cancel = true; + stdout.printf ("No Score can be that high!\n"); + } + } +} + +// Class to test it all +public class GameTest : Object +{ + public static void main () { + var game = new Game (); + var referee = new Referee (game); + game.score = 70; + game.score = 110; + } +} diff --git a/test/src_dir/vb.aspx b/test/src_dir/vb.aspx new file mode 100644 index 0000000..8b7669e --- /dev/null +++ b/test/src_dir/vb.aspx @@ -0,0 +1,26 @@ +<%@ Page Language="VB" %> + + + + Basic ASP.NET Web Page + + +
+

Welcome to ASP.NET

+

Type your name and click the button.

+

+ + +

+

+ +

+
+ + 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/vhdl1.vhd b/test/src_dir/vhdl1.vhd new file mode 100644 index 0000000..a19515f --- /dev/null +++ b/test/src_dir/vhdl1.vhd @@ -0,0 +1,92 @@ +------------------------------------------------------------ +-- Combinational Logic Design +-- (ESD book figure 2.4) +-- by Weijun Zhang, 04/2001 +-- +-- A simple example of VHDL Structure Modeling +-- we might define two components in two separate files, +-- in main file, we use port map statement to instantiate +-- the mapping relationship between each components +-- and the entire circuit. +------------------------------------------------------------ + +library ieee; -- component #1 +use ieee.std_logic_1164.all; + +entity OR_GATE is +port( X: in std_logic; + Y: in std_logic; + F2: out std_logic +); +end OR_GATE; + +architecture behv of OR_GATE is +begin +process(X,Y) +begin + F2 <= X or Y; -- behavior des. +end process; +end behv; + +------------------------------------------------------------- + +library ieee; -- component #2 +use ieee.std_logic_1164.all; + +entity AND_GATE is +port( A: in std_logic; + B: in std_logic; + F1: out std_logic +); +end AND_GATE; + +architecture behv of AND_GATE is +begin +process(A,B) +begin + F1 <= A and B; -- behavior des. +end process; +end behv; + +-------------------------------------------------------------- + +library ieee; -- top level circuit +use ieee.std_logic_1164.all; +use work.all; + +entity comb_ckt is +port( input1: in std_logic; + input2: in std_logic; + input3: in std_logic; + output: out std_logic +); +end comb_ckt; + +architecture struct of comb_ckt is + + component AND_GATE is -- as entity of AND_GATE + port( A: in std_logic; + B: in std_logic; + F1: out std_logic + ); + end component; + + component OR_GATE is -- as entity of OR_GATE + port( X: in std_logic; + Y: in std_logic; + F2: out std_logic + ); + end component; + + signal wire: std_logic; -- signal just like wire + +begin + + -- use sign "=>" to clarify the pin mapping + + Gate1: AND_GATE port map (A=>input1, B=>input2, F1=>wire); + Gate2: OR_GATE port map (X=>wire, Y=>input3, F2=>output); + +end struct; + +---------------------------------------------------------------- diff --git a/test/src_dir/vhdl1.vhdl b/test/src_dir/vhdl1.vhdl new file mode 100644 index 0000000..a5cce9d --- /dev/null +++ b/test/src_dir/vhdl1.vhdl @@ -0,0 +1,40 @@ +library ieee; +use ieee.std_logic_1164.all; + +entity tb is +end tb; + +architecture behav of tb is + + -- toggle period + constant period_c : time := 1 ms; + + -- we'll be poking on this signal + signal toggle_s : std_logic_vector(1 downto 0) := "01"; + +begin + + ----------------------------------------------------------------------------- + -- Process toggle + -- + -- Purpose: + -- Flip the toggle_s signal periodically. + -- + toggle: process + begin + + wait for period_c/2; + toggle_s <= not toggle_s; + + end process toggle; + -- + ----------------------------------------------------------------------------- + +end behav; + +configuration tb_behav_c0 of tb is + + for behav + end for; + +end tb_behav_c0; diff --git a/test/src_dir/visual_basic.bas b/test/src_dir/visual_basic.bas new file mode 100644 index 0000000..eb80d4f --- /dev/null +++ b/test/src_dir/visual_basic.bas @@ -0,0 +1,60 @@ +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 + ClientHeight = 6555 + ClientLeft = 150 + ClientTop = 435 + ClientWidth = 10620 + LinkTopic = "Form1" + MaxButton = 0 'False + MinButton = 0 'False + ScaleHeight = 6555 + ScaleWidth = 10620 + StartUpPosition = 3 'Windows Default +Attribute VB_Name = "frmMain" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +'--------------------------------------------------------------------------- +' +' SOURCE FILE NAME: Demo.frm +' +' SAMPLE: Visual Basic Demo with user interface for the sample modules +' +' For more information about samples, refer to the README file. +' +'--------------------------------------------------------------------------- + +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 +End Sub 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/src_licenses/academic_t1.c b/test/src_licenses/academic_t1.c new file mode 100644 index 0000000..d306ea4 --- /dev/null +++ b/test/src_licenses/academic_t1.c @@ -0,0 +1 @@ +/* Academic Free License */ diff --git a/test/src_licenses/adaptive_t1.rb b/test/src_licenses/adaptive_t1.rb new file mode 100644 index 0000000..0864404 --- /dev/null +++ b/test/src_licenses/adaptive_t1.rb @@ -0,0 +1 @@ +# Adaptive Public License diff --git a/test/src_licenses/affero_1.rb b/test/src_licenses/affero_1.rb new file mode 100644 index 0000000..bda4932 --- /dev/null +++ b/test/src_licenses/affero_1.rb @@ -0,0 +1,15 @@ +# | This program is free software; you can redistribute it and/or modify it under the | +# | terms of the GNU Affero General Public License version 3 as published by the Free | +# | Software Foundation with the addition of the following permission added to Section | +# | 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK IN WHICH THE | +# | COPYRIGHT IS OWNED BY RUBYCAMPUS LLC, RUBYCAMPUS LLC DISCLAIMS THE WARRANTY OF NON | +# | INFRINGEMENT OF THIRD PARTY RIGHTS. | +# | | +# | 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 Affero General Public License for more details. | +# | | +# | You should have received a copy of the GNU Affero General Public License along | +# | with this program; if not, see http://www.gnu.org/licenses or write to the Free | +# | Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 | +# | USA. | diff --git a/test/src_licenses/apache_2_t1.cpp b/test/src_licenses/apache_2_t1.cpp new file mode 100644 index 0000000..977c416 --- /dev/null +++ b/test/src_licenses/apache_2_t1.cpp @@ -0,0 +1 @@ +// Apache License, 2.0 diff --git a/test/src_licenses/apache_2_t2.rb b/test/src_licenses/apache_2_t2.rb new file mode 100644 index 0000000..67ae00f --- /dev/null +++ b/test/src_licenses/apache_2_t2.rb @@ -0,0 +1 @@ +# Apache Software License 2.0 diff --git a/test/src_licenses/apache_2_t3.java b/test/src_licenses/apache_2_t3.java new file mode 100644 index 0000000..5b2536e --- /dev/null +++ b/test/src_licenses/apache_2_t3.java @@ -0,0 +1,21 @@ +/*BEGIN_COPYRIGHT_BLOCK + * + * This software is Open Source Initiative approved Open Source Software. + * Open Source Initative Approved is a trademark of the Open Source Initiative. + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * END_COPYRIGHT_BLOCK*/ diff --git a/test/src_licenses/apache_ish_t1.sql b/test/src_licenses/apache_ish_t1.sql new file mode 100644 index 0000000..f7e5066 --- /dev/null +++ b/test/src_licenses/apache_ish_t1.sql @@ -0,0 +1 @@ +-- Apache-like license diff --git a/test/src_licenses/apache_ish_t2.sql b/test/src_licenses/apache_ish_t2.sql new file mode 100644 index 0000000..f5d824d --- /dev/null +++ b/test/src_licenses/apache_ish_t2.sql @@ -0,0 +1 @@ +-- apache-style license diff --git a/test/src_licenses/apache_t1.c b/test/src_licenses/apache_t1.c new file mode 100644 index 0000000..57951cd --- /dev/null +++ b/test/src_licenses/apache_t1.c @@ -0,0 +1 @@ +// Apache Software License diff --git a/test/src_licenses/apache_t2.rb b/test/src_licenses/apache_t2.rb new file mode 100644 index 0000000..ef5c349 --- /dev/null +++ b/test/src_licenses/apache_t2.rb @@ -0,0 +1 @@ +# Apache Software License 1.0 diff --git a/test/src_licenses/apache_t3.rb b/test/src_licenses/apache_t3.rb new file mode 100644 index 0000000..f7bacc2 --- /dev/null +++ b/test/src_licenses/apache_t3.rb @@ -0,0 +1 @@ +# apache license diff --git a/test/src_licenses/apple_open_source_t1.rb b/test/src_licenses/apple_open_source_t1.rb new file mode 100644 index 0000000..a723f5e --- /dev/null +++ b/test/src_licenses/apple_open_source_t1.rb @@ -0,0 +1 @@ +# Apple Public Source License diff --git a/test/src_licenses/artistic_t1.d b/test/src_licenses/artistic_t1.d new file mode 100644 index 0000000..fb1c2ce --- /dev/null +++ b/test/src_licenses/artistic_t1.d @@ -0,0 +1 @@ +// Artistic License diff --git a/test/src_licenses/attribution_assurance_t1.c b/test/src_licenses/attribution_assurance_t1.c new file mode 100644 index 0000000..29b411b --- /dev/null +++ b/test/src_licenses/attribution_assurance_t1.c @@ -0,0 +1 @@ +/* Attribution Assurance Licenses */ diff --git a/test/src_licenses/avr-drv.c b/test/src_licenses/avr-drv.c new file mode 100644 index 0000000..ae96bcd --- /dev/null +++ b/test/src_licenses/avr-drv.c @@ -0,0 +1,30 @@ +/* Copyright (c) 2008, Sample Code + All rights reserved. + + Redistribution and use in source and binary forms, + with or without modification, are permitted provided + that the following conditions are met: + + 1.Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + 2.Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3.Neither the name of the AVR-DRV nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ diff --git a/test/src_licenses/boost_t1.c b/test/src_licenses/boost_t1.c new file mode 100644 index 0000000..f03ca30 --- /dev/null +++ b/test/src_licenses/boost_t1.c @@ -0,0 +1,25 @@ +/* + * Boost Software License - Version 1.0 - August 17th, 2003 + * + * Permission is hereby granted, free of charge, to any person or organization + * obtaining a copy of the software and accompanying documentation covered by + * this license (the "Software") to use, reproduce, display, distribute, + * execute, and transmit the Software, and to prepare derivative works of the + * Software, and to permit third-parties to whom the Software is furnished to + * do so, all subject to the following: + * + * The copyright notices in the Software and this entire statement, including + * the above license grant, this restriction and the following disclaimer, + * must be included in all copies of the Software, in whole or in part, and + * all derivative works of the Software, unless such copies or derivative + * works are solely in the form of machine-executable object code generated by + * a source language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ diff --git a/test/src_licenses/boost_t2.c b/test/src_licenses/boost_t2.c new file mode 100644 index 0000000..b4821e0 --- /dev/null +++ b/test/src_licenses/boost_t2.c @@ -0,0 +1 @@ +// Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/test/src_licenses/bsd_2clause_ish_t1.c b/test/src_licenses/bsd_2clause_ish_t1.c new file mode 100644 index 0000000..05df16c --- /dev/null +++ b/test/src_licenses/bsd_2clause_ish_t1.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2006-2007 Ed Schouten + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * +*/ diff --git a/test/src_licenses/bsd_ish_t1.c b/test/src_licenses/bsd_ish_t1.c new file mode 100644 index 0000000..5a5a6c7 --- /dev/null +++ b/test/src_licenses/bsd_ish_t1.c @@ -0,0 +1,29 @@ +/* +* Copyright (c) 2006 Jakub Jermar +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* - The name of the author may not be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + diff --git a/test/src_licenses/bsd_ish_t2.c b/test/src_licenses/bsd_ish_t2.c new file mode 100644 index 0000000..731237e --- /dev/null +++ b/test/src_licenses/bsd_ish_t2.c @@ -0,0 +1,38 @@ +/* + * ___TAKEN FROM THE JCITE PROJECT___ + * + * Copyright (c) 2006 Peter Arrenbrecht + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - The names of the contributors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Contact information: + * Peter Arrenbrecht + * http://www.arrenbrecht.ch/jcite +*/ + diff --git a/test/src_licenses/bsd_ish_t3.c b/test/src_licenses/bsd_ish_t3.c new file mode 100644 index 0000000..e572777 --- /dev/null +++ b/test/src_licenses/bsd_ish_t3.c @@ -0,0 +1,35 @@ +/* + * ___TAKEN FROM PRE MAKE KIT___ + * + * Copyright (c) 2004-2006 Damien Couderc + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name of the copyright holder(s) nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * +*/ + diff --git a/test/src_licenses/bsd_t1.rb b/test/src_licenses/bsd_t1.rb new file mode 100644 index 0000000..63c649f --- /dev/null +++ b/test/src_licenses/bsd_t1.rb @@ -0,0 +1 @@ +# New BSD License diff --git a/test/src_licenses/cecill-b.c b/test/src_licenses/cecill-b.c new file mode 100644 index 0000000..b22dfe6 --- /dev/null +++ b/test/src_licenses/cecill-b.c @@ -0,0 +1 @@ +// terms of the CeCILL-B diff --git a/test/src_licenses/cecill-c.c b/test/src_licenses/cecill-c.c new file mode 100644 index 0000000..7388236 --- /dev/null +++ b/test/src_licenses/cecill-c.c @@ -0,0 +1 @@ +// terms of the CeCILL-C diff --git a/test/src_licenses/cecill.c b/test/src_licenses/cecill.c new file mode 100644 index 0000000..959651d --- /dev/null +++ b/test/src_licenses/cecill.c @@ -0,0 +1 @@ +// terms of the CeCILL diff --git a/test/src_licenses/common_development_and_distribution_t1.c b/test/src_licenses/common_development_and_distribution_t1.c new file mode 100644 index 0000000..fa4faab --- /dev/null +++ b/test/src_licenses/common_development_and_distribution_t1.c @@ -0,0 +1 @@ +// Common Development and Distribution License diff --git a/test/src_licenses/common_public_t1.c b/test/src_licenses/common_public_t1.c new file mode 100644 index 0000000..3f7bf0f --- /dev/null +++ b/test/src_licenses/common_public_t1.c @@ -0,0 +1 @@ +// Common Public License 1.0 diff --git a/test/src_licenses/computer_associates_trusted_t1.c b/test/src_licenses/computer_associates_trusted_t1.c new file mode 100644 index 0000000..8afe5e4 --- /dev/null +++ b/test/src_licenses/computer_associates_trusted_t1.c @@ -0,0 +1 @@ +// Computer Associates Trusted Open Source License 1.1 diff --git a/test/src_licenses/cua_office_t1.c b/test/src_licenses/cua_office_t1.c new file mode 100644 index 0000000..87425d3 --- /dev/null +++ b/test/src_licenses/cua_office_t1.c @@ -0,0 +1,3 @@ +/* + * CUA Office Public License Version 1.0 + */ diff --git a/test/src_licenses/eclipse_t1.java b/test/src_licenses/eclipse_t1.java new file mode 100644 index 0000000..6f9ae63 --- /dev/null +++ b/test/src_licenses/eclipse_t1.java @@ -0,0 +1 @@ +// Eclipse Public License diff --git a/test/src_licenses/educational_t1.c b/test/src_licenses/educational_t1.c new file mode 100644 index 0000000..663195b --- /dev/null +++ b/test/src_licenses/educational_t1.c @@ -0,0 +1 @@ +// Educational Community License diff --git a/test/src_licenses/eiffel_2_t1.c b/test/src_licenses/eiffel_2_t1.c new file mode 100644 index 0000000..8b9a9bc --- /dev/null +++ b/test/src_licenses/eiffel_2_t1.c @@ -0,0 +1 @@ +// Eiffel Forum License V2.0 diff --git a/test/src_licenses/eiffel_t1.c b/test/src_licenses/eiffel_t1.c new file mode 100644 index 0000000..07b7c56 --- /dev/null +++ b/test/src_licenses/eiffel_t1.c @@ -0,0 +1 @@ +// Eiffel Forum License diff --git a/test/src_licenses/entessa_t1.c b/test/src_licenses/entessa_t1.c new file mode 100644 index 0000000..6207b3e --- /dev/null +++ b/test/src_licenses/entessa_t1.c @@ -0,0 +1 @@ +// Entessa Public License diff --git a/test/src_licenses/eu_datagrid_t1.c b/test/src_licenses/eu_datagrid_t1.c new file mode 100644 index 0000000..52ed7ad --- /dev/null +++ b/test/src_licenses/eu_datagrid_t1.c @@ -0,0 +1 @@ +// EU DataGrid Software License diff --git a/test/src_licenses/fair_t1.c b/test/src_licenses/fair_t1.c new file mode 100644 index 0000000..3a1c25f --- /dev/null +++ b/test/src_licenses/fair_t1.c @@ -0,0 +1 @@ +// Fair License diff --git a/test/src_licenses/frameworx_t1.c b/test/src_licenses/frameworx_t1.c new file mode 100644 index 0000000..50a7dec --- /dev/null +++ b/test/src_licenses/frameworx_t1.c @@ -0,0 +1 @@ +// Frameworx License diff --git a/test/src_licenses/gpl3_or_later_t1.cs b/test/src_licenses/gpl3_or_later_t1.cs new file mode 100644 index 0000000..c906fe7 --- /dev/null +++ b/test/src_licenses/gpl3_or_later_t1.cs @@ -0,0 +1,53 @@ +#region License +// +// +// Tenka Text +// Open-source Corpus Analysis Software +// Copyright (c) 2006, 2007 Cetin Sert. +// +// +// +// GNU General Public License Version 3 Banner +// +// 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 3 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, see . +// +// +// +// Commercial Licensing +// +// Tenka Text is released under GNU General Public License Version 3 +// which does not permit any kind of commercial use of Tenka Text or +// any parts of it. This restriction applies even if you modify or +// translate the program or parts of it into another programming +// language. For more information see License.txt. +// +// Parties interested in inquiring about commercial licensing of Tenka Text +// should contact the copyright owner for more information. +// +// Cetin Sert +// INF 521, 4-6-2 +// 69120 Heidelberg +// Baden-Wuerttemberg +// Germany +// +// cetin.sert@gmail.com +// +// +49 151 177 610 28 +// +// + +#endregion + +using System; + diff --git a/test/src_licenses/gpl3_or_later_t2.c b/test/src_licenses/gpl3_or_later_t2.c new file mode 100644 index 0000000..bb47ad7 --- /dev/null +++ b/test/src_licenses/gpl3_or_later_t2.c @@ -0,0 +1,17 @@ +// +// Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 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 St, Fifth Floor, Boston, MA 02110-1301 USA + diff --git a/test/src_licenses/gpl3_or_later_t3.cpp b/test/src_licenses/gpl3_or_later_t3.cpp new file mode 100644 index 0000000..8f3df8b --- /dev/null +++ b/test/src_licenses/gpl3_or_later_t3.cpp @@ -0,0 +1,3 @@ +/*************************************************************** + * License: GPL version 3 or later + **************************************************************/ diff --git a/test/src_licenses/gpl3_t1.c b/test/src_licenses/gpl3_t1.c new file mode 100644 index 0000000..aa0c077 --- /dev/null +++ b/test/src_licenses/gpl3_t1.c @@ -0,0 +1,16 @@ +/* + Heroes of Wesnoth - http://heroesofwesnoth.sf.net + Copyright (C) 2007 Jon Ander Peñalba + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License version 3 as + published by the Free Software Foundation. + + 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, see +*/ diff --git a/test/src_licenses/gpl3_t2.cs b/test/src_licenses/gpl3_t2.cs new file mode 100644 index 0000000..ea5798f --- /dev/null +++ b/test/src_licenses/gpl3_t2.cs @@ -0,0 +1,4 @@ +/* + * Licensed under the terms of the GNU GPL v3, with Classpath Linking Exception + * Licensed under the terms of the New BSD License for exclusive use by the Ensemble OS Project + */ diff --git a/test/src_licenses/gpl_line_wrap_1.c b/test/src_licenses/gpl_line_wrap_1.c new file mode 100644 index 0000000..f564caf --- /dev/null +++ b/test/src_licenses/gpl_line_wrap_1.c @@ -0,0 +1,3 @@ +// The line break and comment syntax should not disrupt the license match +// GNU General +// Public License diff --git a/test/src_licenses/gpl_t1.c b/test/src_licenses/gpl_t1.c new file mode 100644 index 0000000..3a73791 --- /dev/null +++ b/test/src_licenses/gpl_t1.c @@ -0,0 +1 @@ +// GNU General Public License (GPL) diff --git a/test/src_licenses/gpl_t2.c b/test/src_licenses/gpl_t2.c new file mode 100644 index 0000000..82086b0 --- /dev/null +++ b/test/src_licenses/gpl_t2.c @@ -0,0 +1 @@ +// This code is licensed under GPL. diff --git a/test/src_licenses/gpl_t3.c b/test/src_licenses/gpl_t3.c new file mode 100644 index 0000000..1664dca --- /dev/null +++ b/test/src_licenses/gpl_t3.c @@ -0,0 +1 @@ +// @license http://www.gnu.org/licenses/gpl.txt diff --git a/test/src_licenses/gpl_t4.c b/test/src_licenses/gpl_t4.c new file mode 100644 index 0000000..21bc2e3 --- /dev/null +++ b/test/src_licenses/gpl_t4.c @@ -0,0 +1 @@ +//@license GPLv2 http://files.syscp.org/misc/COPYING.txt diff --git a/test/src_licenses/historical_t1.c b/test/src_licenses/historical_t1.c new file mode 100644 index 0000000..bf75b68 --- /dev/null +++ b/test/src_licenses/historical_t1.c @@ -0,0 +1 @@ +// Historical Permission Notice and Disclaimer diff --git a/test/src_licenses/i9_license_t1.sh b/test/src_licenses/i9_license_t1.sh new file mode 100755 index 0000000..7780903 --- /dev/null +++ b/test/src_licenses/i9_license_t1.sh @@ -0,0 +1,43 @@ +# +# +# Copyright (C) 2008, 2009 i9 Project Contributors(1) +# All Rights Reserved. +# +# You may only modify and redistribute this under the terms of any of the +# following licenses(2): i9 License, MIT License +# +# +# (1) i9 Project Contributors are listed in the AUTHORS file and at +# http://i9os.googlecode.com/svn/trunk/Documentation/AUTHORS - please extend this file, +# not this notice. +# (2) Reproduced in the files in /Documentation/Licenses, and at: +# http://i9os.googlecode.com/svn/trunk/Documentation/Licenses +# +# As per the above licenses, removal of this notice is prohibited. +# +# ------------------------------------------------------------------------- +# + +cd Utilities +make -C ../BuildMk clean + +make -C ../Microkernel/user/serv/sigma0 clean + +make -C ../Microkernel/user/lib clean + +make -C ../Microkernel/user/serv/kickstart clean + +make -C ../Microkernel/user/apps/l4test clean + +cd ../Microkernel/user && make clean + +cd ../BuildMk && make clean +cd ../BuildL4UL && make clean + +cd ../Personalities/GenodeKit/build.pistachio_x86 && make clean + +cd .. + +rm *~ Documentation/*~ Documentation/*/*~ */*~ */*/~ + + diff --git a/test/src_licenses/i9_license_t2.sh b/test/src_licenses/i9_license_t2.sh new file mode 100755 index 0000000..31e720f --- /dev/null +++ b/test/src_licenses/i9_license_t2.sh @@ -0,0 +1,43 @@ +# +# +# Copyright (C) 2008, 2009 i9 Project Contributors(1) +# All Rights Reserved. +# +# You may only modify and redistribute this under the terms of any of the +# following licenses(2): i9 License +# +# +# (1) i9 Project Contributors are listed in the AUTHORS file and at +# http://i9os.googlecode.com/svn/trunk/Documentation/AUTHORS - please extend this file, +# not this notice. +# (2) Reproduced in the files in /Documentation/Licenses, and at: +# http://i9os.googlecode.com/svn/trunk/Documentation/Licenses +# +# As per the above licenses, removal of this notice is prohibited. +# +# ------------------------------------------------------------------------- +# + +cd Utilities +make -C ../BuildMk clean + +make -C ../Microkernel/user/serv/sigma0 clean + +make -C ../Microkernel/user/lib clean + +make -C ../Microkernel/user/serv/kickstart clean + +make -C ../Microkernel/user/apps/l4test clean + +cd ../Microkernel/user && make clean + +cd ../BuildMk && make clean +cd ../BuildL4UL && make clean + +cd ../Personalities/GenodeKit/build.pistachio_x86 && make clean + +cd .. + +rm *~ Documentation/*~ Documentation/*/*~ */*~ */*/~ + + diff --git a/test/src_licenses/ibm_public_t1.c b/test/src_licenses/ibm_public_t1.c new file mode 100644 index 0000000..f2c4ada --- /dev/null +++ b/test/src_licenses/ibm_public_t1.c @@ -0,0 +1 @@ +// IBM Public License diff --git a/test/src_licenses/intel_open_source_t1.c b/test/src_licenses/intel_open_source_t1.c new file mode 100644 index 0000000..000c664 --- /dev/null +++ b/test/src_licenses/intel_open_source_t1.c @@ -0,0 +1 @@ +// Intel Open Source License diff --git a/test/src_licenses/jabber_open_source_t1.c b/test/src_licenses/jabber_open_source_t1.c new file mode 100644 index 0000000..16f1528 --- /dev/null +++ b/test/src_licenses/jabber_open_source_t1.c @@ -0,0 +1 @@ +// Jabber Open Source License diff --git a/test/src_licenses/lgpl3_t1.java b/test/src_licenses/lgpl3_t1.java new file mode 100644 index 0000000..415104c --- /dev/null +++ b/test/src_licenses/lgpl3_t1.java @@ -0,0 +1,14 @@ +/** + * + * Licensed under the GNU Lesser General Public License, Version 3.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.gnu.org/licenses/lgpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/test/src_licenses/lgpl3_t2.C b/test/src_licenses/lgpl3_t2.C new file mode 100644 index 0000000..a39c093 --- /dev/null +++ b/test/src_licenses/lgpl3_t2.C @@ -0,0 +1,15 @@ +// This file is part of MyProject. +// Copyright (C) 2005 University of California +// +// MyProject is free software: you can redistribute it and/or modify +// it under the terms of the gnu lesser general public license as published +// by the free software foundation, either version 3 of the license, or +// (at your option) any later version. +// +// MyProject 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License with MyProject. If not, see . diff --git a/test/src_licenses/lgpl_t1.c b/test/src_licenses/lgpl_t1.c new file mode 100644 index 0000000..054732f --- /dev/null +++ b/test/src_licenses/lgpl_t1.c @@ -0,0 +1 @@ +// GNU Library or "Lesser" General Public License (LGPL) diff --git a/test/src_licenses/lgpl_t2.c b/test/src_licenses/lgpl_t2.c new file mode 100644 index 0000000..8b3a3e1 --- /dev/null +++ b/test/src_licenses/lgpl_t2.c @@ -0,0 +1 @@ +// GNU Lesser General Public License diff --git a/test/src_licenses/lgpl_t3.c b/test/src_licenses/lgpl_t3.c new file mode 100644 index 0000000..8d4e00e --- /dev/null +++ b/test/src_licenses/lgpl_t3.c @@ -0,0 +1 @@ +// GNU LESSER GENERAL PUBLIC LICENSE diff --git a/test/src_licenses/lgpl_t4.c b/test/src_licenses/lgpl_t4.c new file mode 100644 index 0000000..f0c8dd8 --- /dev/null +++ b/test/src_licenses/lgpl_t4.c @@ -0,0 +1 @@ +// Lesser GPL diff --git a/test/src_licenses/lgpl_t5.c b/test/src_licenses/lgpl_t5.c new file mode 100644 index 0000000..15b8536 --- /dev/null +++ b/test/src_licenses/lgpl_t5.c @@ -0,0 +1 @@ +// Library GPL diff --git a/test/src_licenses/lucent_plan9_t1.c b/test/src_licenses/lucent_plan9_t1.c new file mode 100644 index 0000000..17e6879 --- /dev/null +++ b/test/src_licenses/lucent_plan9_t1.c @@ -0,0 +1 @@ +// Lucent Public License (Plan9) diff --git a/test/src_licenses/lucent_public_t1.c b/test/src_licenses/lucent_public_t1.c new file mode 100644 index 0000000..7fcd208 --- /dev/null +++ b/test/src_licenses/lucent_public_t1.c @@ -0,0 +1 @@ +// Lucent Public License Version 1.02 diff --git a/test/src_licenses/mit_t1.c b/test/src_licenses/mit_t1.c new file mode 100644 index 0000000..6a2d35f --- /dev/null +++ b/test/src_licenses/mit_t1.c @@ -0,0 +1 @@ +// MIT license diff --git a/test/src_licenses/mit_t2.c b/test/src_licenses/mit_t2.c new file mode 100644 index 0000000..8a2b8af --- /dev/null +++ b/test/src_licenses/mit_t2.c @@ -0,0 +1 @@ +// MIT/X11 license diff --git a/test/src_licenses/mitre_t1.c b/test/src_licenses/mitre_t1.c new file mode 100644 index 0000000..d8ee21d --- /dev/null +++ b/test/src_licenses/mitre_t1.c @@ -0,0 +1 @@ +// MITRE Collaborative Virtual Workspace License (CVW License) diff --git a/test/src_licenses/motosoto_t1.c b/test/src_licenses/motosoto_t1.c new file mode 100644 index 0000000..2c5e9d7 --- /dev/null +++ b/test/src_licenses/motosoto_t1.c @@ -0,0 +1 @@ +// Motosoto License diff --git a/test/src_licenses/mozilla_public_1_1_t1.c b/test/src_licenses/mozilla_public_1_1_t1.c new file mode 100644 index 0000000..39b572f --- /dev/null +++ b/test/src_licenses/mozilla_public_1_1_t1.c @@ -0,0 +1 @@ +// Mozilla Public License 1.1 (MPL) diff --git a/test/src_licenses/mozilla_public_1_t1.c b/test/src_licenses/mozilla_public_1_t1.c new file mode 100644 index 0000000..a3738df --- /dev/null +++ b/test/src_licenses/mozilla_public_1_t1.c @@ -0,0 +1 @@ +// Mozilla Public License 1.0 (MPL) diff --git a/test/src_licenses/nasa_open_t1.c b/test/src_licenses/nasa_open_t1.c new file mode 100644 index 0000000..6809bc4 --- /dev/null +++ b/test/src_licenses/nasa_open_t1.c @@ -0,0 +1 @@ +// NASA Open Source Agreement 1.3 diff --git a/test/src_licenses/naumen_t1.c b/test/src_licenses/naumen_t1.c new file mode 100644 index 0000000..f69c812 --- /dev/null +++ b/test/src_licenses/naumen_t1.c @@ -0,0 +1 @@ +// Naumen Public License diff --git a/test/src_licenses/nethack_t1.c b/test/src_licenses/nethack_t1.c new file mode 100644 index 0000000..5cf158e --- /dev/null +++ b/test/src_licenses/nethack_t1.c @@ -0,0 +1 @@ +// Nethack General Public License diff --git a/test/src_licenses/nokia_open_source_t1.c b/test/src_licenses/nokia_open_source_t1.c new file mode 100644 index 0000000..02b7ca4 --- /dev/null +++ b/test/src_licenses/nokia_open_source_t1.c @@ -0,0 +1 @@ +// Nokia Open Source License diff --git a/test/src_licenses/oclc_research_t1.c b/test/src_licenses/oclc_research_t1.c new file mode 100644 index 0000000..6472315 --- /dev/null +++ b/test/src_licenses/oclc_research_t1.c @@ -0,0 +1 @@ +// OCLC Research Public License 2.0 diff --git a/test/src_licenses/open_group_test_t1.c b/test/src_licenses/open_group_test_t1.c new file mode 100644 index 0000000..a75fb3a --- /dev/null +++ b/test/src_licenses/open_group_test_t1.c @@ -0,0 +1 @@ +// Open Group Test Suite License diff --git a/test/src_licenses/open_software_t1.c b/test/src_licenses/open_software_t1.c new file mode 100644 index 0000000..9016090 --- /dev/null +++ b/test/src_licenses/open_software_t1.c @@ -0,0 +1 @@ +// Open Software License diff --git a/test/src_licenses/php_license_t1.php b/test/src_licenses/php_license_t1.php new file mode 100644 index 0000000..119b920 --- /dev/null +++ b/test/src_licenses/php_license_t1.php @@ -0,0 +1,5 @@ + diff --git a/test/src_licenses/python_license_t1.py b/test/src_licenses/python_license_t1.py new file mode 100644 index 0000000..8aa08e6 --- /dev/null +++ b/test/src_licenses/python_license_t1.py @@ -0,0 +1,3 @@ +""" + Python license +""" diff --git a/test/src_licenses/python_software_foundation_t1.py b/test/src_licenses/python_software_foundation_t1.py new file mode 100644 index 0000000..f302fec --- /dev/null +++ b/test/src_licenses/python_software_foundation_t1.py @@ -0,0 +1 @@ +# Python Software Foundation License diff --git a/test/src_licenses/qt_public_t1.c b/test/src_licenses/qt_public_t1.c new file mode 100644 index 0000000..9a884af --- /dev/null +++ b/test/src_licenses/qt_public_t1.c @@ -0,0 +1 @@ +// Qt Public License (QPL) diff --git a/test/src_licenses/realnetworks_public_source_t1.c b/test/src_licenses/realnetworks_public_source_t1.c new file mode 100644 index 0000000..b982e4c --- /dev/null +++ b/test/src_licenses/realnetworks_public_source_t1.c @@ -0,0 +1 @@ +// RealNetworks Public Source License V1.0 diff --git a/test/src_licenses/reciprocal_public_t1.c b/test/src_licenses/reciprocal_public_t1.c new file mode 100644 index 0000000..345ea0b --- /dev/null +++ b/test/src_licenses/reciprocal_public_t1.c @@ -0,0 +1 @@ +// Reciprocal Public License diff --git a/test/src_licenses/ricoh_source_t1.c b/test/src_licenses/ricoh_source_t1.c new file mode 100644 index 0000000..f2d6a79 --- /dev/null +++ b/test/src_licenses/ricoh_source_t1.c @@ -0,0 +1 @@ +// Ricoh Source Code Public License diff --git a/test/src_licenses/sleepycat_t1.c b/test/src_licenses/sleepycat_t1.c new file mode 100644 index 0000000..f9c6303 --- /dev/null +++ b/test/src_licenses/sleepycat_t1.c @@ -0,0 +1 @@ +// Sleepycat License diff --git a/test/src_licenses/sugarcrm_1_1_3_t1.c b/test/src_licenses/sugarcrm_1_1_3_t1.c new file mode 100644 index 0000000..b9f2945 --- /dev/null +++ b/test/src_licenses/sugarcrm_1_1_3_t1.c @@ -0,0 +1 @@ +// Sugar Public License Version 1.1.3 diff --git a/test/src_licenses/sun_industry_standards_t1.c b/test/src_licenses/sun_industry_standards_t1.c new file mode 100644 index 0000000..b892aff --- /dev/null +++ b/test/src_licenses/sun_industry_standards_t1.c @@ -0,0 +1 @@ +// Sun Industry Standards Source License (SISSL) diff --git a/test/src_licenses/sun_public_t1.c b/test/src_licenses/sun_public_t1.c new file mode 100644 index 0000000..7f4c506 --- /dev/null +++ b/test/src_licenses/sun_public_t1.c @@ -0,0 +1 @@ +// Sun Public License diff --git a/test/src_licenses/sybase_open_watcom_t1.c b/test/src_licenses/sybase_open_watcom_t1.c new file mode 100644 index 0000000..9dae1bd --- /dev/null +++ b/test/src_licenses/sybase_open_watcom_t1.c @@ -0,0 +1 @@ +// Sybase Open Watcom Public License 1.0 diff --git a/test/src_licenses/u_of_i_ncsa_t1.c b/test/src_licenses/u_of_i_ncsa_t1.c new file mode 100644 index 0000000..50b625b --- /dev/null +++ b/test/src_licenses/u_of_i_ncsa_t1.c @@ -0,0 +1 @@ +// University of Illinois/NCSA Open Source License diff --git a/test/src_licenses/vovida_software_t1.c b/test/src_licenses/vovida_software_t1.c new file mode 100644 index 0000000..587cbd7 --- /dev/null +++ b/test/src_licenses/vovida_software_t1.c @@ -0,0 +1 @@ +// Vovida Software License v. 1.0 diff --git a/test/src_licenses/w3c_t1.c b/test/src_licenses/w3c_t1.c new file mode 100644 index 0000000..ef05f89 --- /dev/null +++ b/test/src_licenses/w3c_t1.c @@ -0,0 +1 @@ +// W3C License diff --git a/test/src_licenses/wx_windows_t1.c b/test/src_licenses/wx_windows_t1.c new file mode 100644 index 0000000..cad8e3d --- /dev/null +++ b/test/src_licenses/wx_windows_t1.c @@ -0,0 +1 @@ +// wxWindows Library License diff --git a/test/src_licenses/x_net_t1.c b/test/src_licenses/x_net_t1.c new file mode 100644 index 0000000..cebb953 --- /dev/null +++ b/test/src_licenses/x_net_t1.c @@ -0,0 +1 @@ +// X.Net License diff --git a/test/src_licenses/zlib_libpng_t1.c b/test/src_licenses/zlib_libpng_t1.c new file mode 100644 index 0000000..6318f9a --- /dev/null +++ b/test/src_licenses/zlib_libpng_t1.c @@ -0,0 +1 @@ +// zlib/libpng license diff --git a/test/src_licenses/zope_t1.c b/test/src_licenses/zope_t1.c new file mode 100644 index 0000000..9ba699f --- /dev/null +++ b/test/src_licenses/zope_t1.c @@ -0,0 +1 @@ +// Zope Public License diff --git a/test/unit/all_tests.c b/test/unit/all_tests.c new file mode 100644 index 0000000..f6192e1 --- /dev/null +++ b/test/unit/all_tests.c @@ -0,0 +1,29 @@ +// all_tests.c written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#include + +#include "detector_test.h" +#include "license_test.h" +#include "loc_test.h" +#include "parser_test.h" +#include "sourcefile_test.h" + +void all_tests() { + printf("Running sourcefile tests\n"); + all_sourcefile_tests(); + printf("Running detector tests\n"); + all_detector_tests(); + printf("Running license tests\n"); + all_license_tests(); + printf("Running parser tests\n"); + all_parser_tests(); + printf("Running loc tests\n"); + all_loc_tests(); +} + +int main() { + all_tests(); + printf("ALL TESTS PASSED.\n"); + return 0; +} diff --git a/test/unit/detector_test.h b/test/unit/detector_test.h new file mode 100644 index 0000000..a26adaa --- /dev/null +++ b/test/unit/detector_test.h @@ -0,0 +1,134 @@ +// detector_test.h written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#include +#include +#include + +#include "../../src/detector.h" +#include "../../src/languages.h" +#include "../../src/sourcefile.h" + +#define ASSERT_DETECT(x, y) { \ + SourceFile *sf = ohcount_sourcefile_new("../detect_files/" y); \ + const char *lang = ohcount_detect_language(sf); \ + assert(lang); \ + assert(strcmp(x, lang) == 0); \ + ohcount_sourcefile_free(sf); \ +} +#define ASSERT_NODETECT(x) { \ + SourceFile *sf = ohcount_sourcefile_new("../detect_files/" x); \ + assert(ohcount_detect_language(sf) == NULL); \ + ohcount_sourcefile_free(sf); \ +} + +void test_detector_smalltalk() { + ASSERT_DETECT(LANG_SMALLTALK, "example.st"); + ASSERT_NODETECT("english.st"); +} + +void test_detector_disambiguate_m() { + ASSERT_DETECT(LANG_OBJECTIVE_C, "t1.m"); + ASSERT_DETECT(LANG_OBJECTIVE_C, "t2.m"); + ASSERT_DETECT(LANG_OBJECTIVE_C, "TCPSocket.m"); + ASSERT_DETECT(LANG_OBJECTIVE_C, "foo_objective_c.m"); + ASSERT_DETECT(LANG_MATLAB, "foo_matlab.m"); + ASSERT_DETECT(LANG_OCTAVE, "foo_octave.m"); +} + +void test_detector_disambiguate_in() { + ASSERT_NODETECT("empty.in"); +} +void test_detector_disambiguate_pro() { + ASSERT_DETECT(LANG_IDL_PVWAVE, "foo.pro"); + ASSERT_DETECT(LANG_MAKE, "qmake.pro"); +} + +void test_detector_fortran_fixedfree() { + ASSERT_DETECT(LANG_FORTRANFIXED, "fortranfixed.f"); + ASSERT_DETECT(LANG_FORTRANFREE, "fortranfree.f"); +} + +void test_detector_detect_polyglot() { + ASSERT_DETECT(LANG_C, "foo.c"); + ASSERT_DETECT(LANG_C, "uses_no_cpp.h"); + ASSERT_DETECT(LANG_CPP, "uses_cpp_headers.h"); + ASSERT_DETECT(LANG_CPP, "uses_cpp_stdlib_headers.h"); + ASSERT_DETECT(LANG_CPP, "uses_cpp_keywords.h"); + ASSERT_DETECT(LANG_RUBY, "foo.rb"); + ASSERT_DETECT(LANG_MAKE, "foo.mk"); + ASSERT_DETECT(LANG_OBJECTIVE_C, "foo_objective_c.h"); + ASSERT_DETECT(LANG_PHP, "upper_case_php"); + ASSERT_DETECT(LANG_SMALLTALK, "example.st"); + ASSERT_DETECT(LANG_VALA, "foo.vala"); + ASSERT_DETECT(LANG_TEX, "foo.tex"); + ASSERT_DETECT(LANG_XSLT, "example.xsl"); + ASSERT_DETECT(LANG_LISP, "core.lisp"); + ASSERT_DETECT(LANG_DMD, "foo.d"); + ASSERT_DETECT(LANG_VIM, "foo.vim"); + ASSERT_DETECT(LANG_EBUILD, "foo.ebuild"); + ASSERT_DETECT(LANG_EBUILD, "foo.eclass"); + ASSERT_DETECT(LANG_EXHERES, "foo.exheres-0"); + ASSERT_DETECT(LANG_EXHERES, "foo.exlib"); + ASSERT_DETECT(LANG_EIFFEL, "eiffel.e"); + ASSERT_DETECT(LANG_OCAML, "ocaml.ml"); + ASSERT_DETECT(LANG_STRATEGO, "stratego.str"); + ASSERT_DETECT(LANG_R, "foo.R"); + ASSERT_DETECT(LANG_GLSL, "foo.glsl"); + ASSERT_DETECT(LANG_GLSL, "foo_glsl.vert"); + ASSERT_DETECT(LANG_GLSL, "foo_glsl.frag"); + ASSERT_DETECT(LANG_IDL_PVWAVE, "foo.pro"); + ASSERT_DETECT(LANG_ASSEMBLER, "foo.z80"); + ASSERT_DETECT(LANG_PHP, "php.inc"); + ASSERT_NODETECT("empty.inc"); + ASSERT_DETECT(LANG_FSHARP, "fs1.fs"); +} + +void test_detector_upper_case_extensions() { + ASSERT_DETECT(LANG_CPP, "foo_upper_case.C"); + ASSERT_DETECT(LANG_RUBY, "foo_upper_case.RB"); +} + +void test_detector_no_extensions() { + ASSERT_DETECT(LANG_PYTHON, "py_script"); + ASSERT_DETECT(LANG_RUBY, "ruby_script"); + ASSERT_DETECT(LANG_SHELL, "bourne_again_script"); + ASSERT_DETECT(LANG_SHELL, "bash_script"); + ASSERT_DETECT(LANG_PERL, "perl_w"); + ASSERT_DETECT(LANG_DMD, "d_script"); + ASSERT_DETECT(LANG_TCL, "tcl_script"); + ASSERT_DETECT(LANG_PYTHON, "python.data"); + ASSERT_DETECT(LANG_PYTHON, "python2.data"); +} + +void test_detector_csharp_or_clearsilver() { + ASSERT_DETECT(LANG_CSHARP, "cs1.cs"); + ASSERT_DETECT(LANG_CLEARSILVER_TEMPLATE, "clearsilver_template1.cs"); +} + +void test_detector_basic() { + ASSERT_DETECT(LANG_VISUALBASIC, "visual_basic.bas"); + ASSERT_DETECT(LANG_CLASSIC_BASIC, "classic_basic.b"); + system("mv ../detect_files/frx1.frx ../detect_files/frx1.frx2"); + ASSERT_DETECT(LANG_STRUCTURED_BASIC, "visual_basic.bas"); + ASSERT_DETECT(LANG_STRUCTURED_BASIC, "structured_basic.b"); + system("mv ../detect_files/frx1.frx2 ../detect_files/frx1.frx"); +} + +void test_detector_xml_with_custom_extension() { + ASSERT_DETECT(LANG_XML, "xml.custom_ext"); +} + +void all_detector_tests() { + test_detector_smalltalk(); + test_detector_disambiguate_m(); + test_detector_disambiguate_in(); + test_detector_disambiguate_pro(); + test_detector_fortran_fixedfree(); + test_detector_detect_polyglot(); + test_detector_upper_case_extensions(); + test_detector_no_extensions(); + test_detector_csharp_or_clearsilver(); + test_detector_basic(); + test_detector_xml_with_custom_extension(); +} diff --git a/test/unit/license_test.h b/test/unit/license_test.h new file mode 100644 index 0000000..b804f37 --- /dev/null +++ b/test/unit/license_test.h @@ -0,0 +1,77 @@ +// license_test.h written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#include +#include +#include +#include + +#include "../../src/licenses.h" + +void src_vs_expected_tests() { + const char *src_licenses = "../src_licenses/"; + char src[FILENAME_MAX]; + strncpy(src, src_licenses, strlen(src_licenses)); + char *s_p = src + strlen(src_licenses); + + const char *expected_licenses = "../expected_licenses/"; + char expected[FILENAME_MAX]; + strncpy(expected, expected_licenses, strlen(expected_licenses)); + char *e_p = expected + strlen(expected_licenses); + + struct dirent *file; + DIR *d = opendir(src_licenses); + if (d) { + while ((file = readdir(d))) { + if (strcmp((const char *)file->d_name, ".") != 0 && + strcmp((const char *)file->d_name, "..") != 0) { + char *p; + int length; + + length = strlen(file->d_name); + strncpy(s_p, (const char *)file->d_name, length); + *(s_p + length) = '\0'; + + p = file->d_name + length; + while (*p != '.' && p > file->d_name) p--; + length = p - file->d_name; + strncpy(e_p, (const char *)file->d_name, length); + *(e_p + length) = '\0'; + FILE *f = fopen((const char *)expected, "r"); + if (f) { + SourceFile *sf = ohcount_sourcefile_new((const char *)src); + LicenseList *iter = ohcount_sourcefile_get_license_list(sf)->head; + char line[40]; // max license name size + for (; fgets(line, sizeof(line), f); iter = iter->next) { + p = strstr(line, "\r"); + if (p == NULL) p = strstr(line, "\n"); + if (p) *p = '\0'; + assert(iter->lic->name); + assert(strcmp(line, iter->lic->name) == 0); + } + fclose(f); + ohcount_sourcefile_free(sf); + } + } + } + closedir(d); + } +} + +void very_long_file_test() { + int len = 5500000; + char *a = malloc(len); + memset(a, 'i', len); + a[len-1] = '\0'; + a[len-2] = '\n'; + + SourceFile *sf = ohcount_sourcefile_new("foo.c"); + ohcount_sourcefile_set_contents(sf, a); + strncpy(a, "int = 1;\n", strlen("int = 1;\n")); + ohcount_sourcefile_get_license_list(sf); +} + +void all_license_tests() { + src_vs_expected_tests(); + very_long_file_test(); +} diff --git a/test/unit/loc_test.h b/test/unit/loc_test.h new file mode 100644 index 0000000..abdb013 --- /dev/null +++ b/test/unit/loc_test.h @@ -0,0 +1,407 @@ +// loc_test.h written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#include +#include +#include + +#include "../../src/loc.h" + +void test_loc_default() { + Loc *loc = ohcount_loc_new("c", 0, 0, 0, 0); + assert(strcmp("c", loc->language) == 0); + assert(loc->code == 0); + assert(loc->comments == 0); + assert(loc->blanks == 0); + assert(loc->filecount == 0); + ohcount_loc_free(loc); +} + +void test_loc_initializer() { + Loc *loc = ohcount_loc_new("c", 1, 2, 3, 4); + assert(strcmp("c", loc->language) == 0); + assert(loc->code == 1); + assert(loc->comments == 2); + assert(loc->blanks == 3); + assert(loc->filecount == 4); + ohcount_loc_free(loc); +} + +void test_loc_add() { + Loc *loc = ohcount_loc_new("c", 1, 2, 3, 4); + Loc *loc2 = ohcount_loc_new("c", 10, 20, 30, 40); + ohcount_loc_add_loc(loc, loc2); + assert(strcmp("c", loc->language) == 0); + assert(loc->code == 11); + assert(loc->comments == 22); + assert(loc->blanks == 33); + assert(ohcount_loc_total(loc) == 66); + assert(loc->filecount == 44); + ohcount_loc_free(loc); + ohcount_loc_free(loc2); +} + +void test_loc_add_requires_same_language() { + Loc *loc = ohcount_loc_new("c", 1, 2, 3, 4); + Loc *loc2 = ohcount_loc_new("java", 10, 20, 30, 40); + ohcount_loc_add_loc(loc, loc2); + assert(strcmp("c", loc->language) == 0); + assert(loc->code == 1); + assert(loc->comments == 2); + assert(loc->blanks == 3); + assert(loc->filecount == 4); + ohcount_loc_free(loc); + ohcount_loc_free(loc2); +} + +void test_loc_list_default() { + LocList *list = ohcount_loc_list_new(); + assert(list->loc == NULL); + ohcount_loc_list_free(list); +} + +void test_loc_list_selector() { + LocList *list = ohcount_loc_list_new(); + Loc *c = ohcount_loc_new("c", 1, 2, 3, 4); + Loc *java = ohcount_loc_new("java", 10, 20, 30, 40); + ohcount_loc_list_add_loc(list, c); + ohcount_loc_list_add_loc(list, java); + assert(strcmp(list->head->loc->language, "c") == 0); + assert(strcmp(list->head->next->loc->language, "java") == 0); + assert(ohcount_loc_is_equal(ohcount_loc_list_get_loc(list, "c"), c)); + assert(ohcount_loc_is_equal(ohcount_loc_list_get_loc(list, "java"), java)); + ohcount_loc_free(c); + ohcount_loc_free(java); + ohcount_loc_list_free(list); +} + +void test_loc_list_first_add() { + LocList *list = ohcount_loc_list_new(); + Loc *c = ohcount_loc_new("c", 1, 2, 3, 4); + ohcount_loc_list_add_loc(list, c); + assert(ohcount_loc_is_equal(list->head->loc, c)); + assert(strcmp(list->head->loc->language, "c") == 0); + assert(ohcount_loc_list_code(list) == 1); + assert(ohcount_loc_list_comments(list) == 2); + assert(ohcount_loc_list_blanks(list) == 3); + assert(ohcount_loc_list_total(list) == 6); + assert(ohcount_loc_list_filecount(list) == 4); + ohcount_loc_free(c); + ohcount_loc_list_free(list); +} + +void test_loc_list_add_two_languages() { + LocList *list = ohcount_loc_list_new(); + Loc *c = ohcount_loc_new("c", 1, 2, 3, 4); + Loc *java = ohcount_loc_new("java", 10, 20, 30, 40); + ohcount_loc_list_add_loc(list, c); + ohcount_loc_list_add_loc(list, java); + assert(strcmp(list->head->loc->language, "c") == 0); + assert(strcmp(list->head->next->loc->language, "java") == 0); + assert(ohcount_loc_is_equal(ohcount_loc_list_get_loc(list, "c"), c)); + assert(ohcount_loc_is_equal(ohcount_loc_list_get_loc(list, "java"), java)); + assert(ohcount_loc_list_code(list) == 11); + assert(ohcount_loc_list_comments(list) == 22); + assert(ohcount_loc_list_blanks(list) == 33); + assert(ohcount_loc_list_total(list) == 66); + assert(ohcount_loc_list_filecount(list) == 44); + ohcount_loc_free(c); + ohcount_loc_free(java); + ohcount_loc_list_free(list); +} + +void test_loc_list_add_same_language_twice() { + LocList *list = ohcount_loc_list_new(); + Loc *c1 = ohcount_loc_new("c", 1, 2, 3, 4); + Loc *c2 = ohcount_loc_new("c", 10, 20, 30, 40); + ohcount_loc_list_add_loc(list, c1); + ohcount_loc_list_add_loc(list, c2); + assert(strcmp(list->head->loc->language, "c") == 0); + assert(list->head->next == NULL); + assert(ohcount_loc_list_code(list) == 11); + assert(ohcount_loc_list_comments(list) == 22); + assert(ohcount_loc_list_blanks(list) == 33); + assert(ohcount_loc_list_total(list) == 66); + assert(ohcount_loc_list_filecount(list) == 44); + ohcount_loc_free(c1); + ohcount_loc_free(c2); + ohcount_loc_list_free(list); +} + +void test_loc_list_add_loc_lists() { + LocList *list1 = ohcount_loc_list_new(); + LocList *list2 = ohcount_loc_list_new(); + Loc *c1 = ohcount_loc_new("c", 1, 0, 0, 0); + Loc *java = ohcount_loc_new("java", 2, 0, 0, 0); + Loc *c2 = ohcount_loc_new("c", 10, 0, 0, 0); + Loc *ruby = ohcount_loc_new("ruby", 3, 0, 0, 0); + ohcount_loc_list_add_loc(list1, c1); + ohcount_loc_list_add_loc(list1, java); + ohcount_loc_list_add_loc(list2, c2); + ohcount_loc_list_add_loc(list2, ruby); + ohcount_loc_list_add_loc_list(list1, list2); + assert(strcmp(list1->head->loc->language, "c") == 0); + assert(strcmp(list1->head->next->loc->language, "java") == 0); + assert(strcmp(list1->head->next->next->loc->language, "ruby") == 0); + assert(list1->head->next->next->next == NULL); + assert(ohcount_loc_list_get_loc(list1, "c")->code == 11); + assert(ohcount_loc_list_get_loc(list1, "java")->code == 2); + assert(ohcount_loc_list_get_loc(list1, "ruby")->code == 3); + assert(ohcount_loc_list_code(list1) == 16); + ohcount_loc_free(c1); + ohcount_loc_free(java); + ohcount_loc_free(c2); + ohcount_loc_free(ruby); + ohcount_loc_list_free(list1); + ohcount_loc_list_free(list2); +} + +void test_loc_list_compact() { + LocList *list = ohcount_loc_list_new(); + Loc *c = ohcount_loc_new("c", 1, 2, 3, 4); + Loc *java = ohcount_loc_new("java", 0, 0, 0, 0); + ohcount_loc_list_add_loc(list, c); + ohcount_loc_list_add_loc(list, java); + LocList *compacted = ohcount_loc_list_new_compact(list); + assert(ohcount_loc_is_equal(ohcount_loc_list_get_loc(compacted, "c"), c)); + assert(compacted->head->next == NULL); + ohcount_loc_free(c); + ohcount_loc_free(java); + ohcount_loc_list_free(list); + ohcount_loc_list_free(compacted); +} + +void test_loc_delta_default() { + LocDelta *delta = ohcount_loc_delta_new("c", 0, 0, 0, 0, 0, 0); + assert(delta->code_added == 0); + assert(delta->code_removed == 0); + assert(delta->comments_added == 0); + assert(delta->comments_removed == 0); + assert(delta->blanks_added == 0); + assert(delta->blanks_removed == 0); + ohcount_loc_delta_free(delta); +} + +void test_loc_delta_initializer() { + LocDelta *delta = ohcount_loc_delta_new("c", 1, 10, 2, 20, 3, 30); + assert(strcmp(delta->language, "c") == 0); + assert(delta->code_added == 1); + assert(delta->code_removed == 10); + assert(delta->comments_added == 2); + assert(delta->comments_removed == 20); + assert(delta->blanks_added == 3); + assert(delta->blanks_removed == 30); + ohcount_loc_delta_free(delta); +} + +void test_loc_delta_net_total() { + LocDelta *delta = ohcount_loc_delta_new("c", 1, 10, 2, 20, 3, 30); + assert(ohcount_loc_delta_net_code(delta) == -9); + assert(ohcount_loc_delta_net_comments(delta) == -18); + assert(ohcount_loc_delta_net_blanks(delta) == -27); + assert(ohcount_loc_delta_net_total(delta) == -54); + ohcount_loc_delta_free(delta); +} + +void test_loc_delta_addition() { + LocDelta *delta1 = ohcount_loc_delta_new("c", 1, 10, 2, 20, 3, 30); + LocDelta *delta2 = ohcount_loc_delta_new("c", 100, 1000, 200, 2000, 300, + 3000); + ohcount_loc_delta_add_loc_delta(delta1, delta2); + assert(delta1->code_added == 101); + assert(delta1->code_removed == 1010); + assert(delta1->comments_added == 202); + assert(delta1->comments_removed == 2020); + assert(delta1->blanks_added == 303); + assert(delta1->blanks_removed == 3030); + ohcount_loc_delta_free(delta1); + ohcount_loc_delta_free(delta2); +} + +void test_loc_delta_addition_requires_matching_language() { + LocDelta *delta1 = ohcount_loc_delta_new("c", 0, 0, 0, 0, 0, 0); + LocDelta *delta2 = ohcount_loc_delta_new("java", 1, 10, 2, 20, 3, 30); + ohcount_loc_delta_add_loc_delta(delta1, delta2); + assert(strcmp(delta1->language, "c") == 0); + assert(delta1->code_added == 0); + assert(delta1->code_removed == 0); + assert(delta1->comments_added == 0); + assert(delta1->comments_removed == 0); + assert(delta1->blanks_added == 0); + assert(delta1->blanks_removed == 0); + ohcount_loc_delta_free(delta1); + ohcount_loc_delta_free(delta2); +} + +void test_loc_delta_equals() { + LocDelta *delta1 = ohcount_loc_delta_new("c", 1, 10, 2, 20, 3, 30); + LocDelta *delta2 = ohcount_loc_delta_new("c", 1, 10, 2, 20, 3, 30); + assert(ohcount_loc_delta_is_equal(delta1, delta2)); + ohcount_loc_delta_free(delta1); + ohcount_loc_delta_free(delta2); +} + +void test_loc_delta_list_default() { + LocDeltaList *list = ohcount_loc_delta_list_new(); + assert(list->delta == NULL); + ohcount_loc_delta_list_free(list); +} + +void test_loc_delta_list_selector() { + LocDeltaList *list = ohcount_loc_delta_list_new(); + LocDelta *c = ohcount_loc_delta_new("c", 0, 0, 0, 0, 0, 0); + LocDelta *java = ohcount_loc_delta_new("java", 0, 0, 0, 0, 0, 0); + ohcount_loc_delta_list_add_loc_delta(list, c); + ohcount_loc_delta_list_add_loc_delta(list, java); + assert(ohcount_loc_delta_is_equal( + ohcount_loc_delta_list_get_loc_delta(list, "c"), c)); + assert(ohcount_loc_delta_is_equal( + ohcount_loc_delta_list_get_loc_delta(list, "java"), java)); + ohcount_loc_delta_free(c); + ohcount_loc_delta_free(java); + ohcount_loc_delta_list_free(list); +} + +void test_loc_delta_list_first_add() { + LocDeltaList *list = ohcount_loc_delta_list_new(); + LocDelta *c = ohcount_loc_delta_new("c", 1, 10, 2, 20, 3, 30); + ohcount_loc_delta_list_add_loc_delta(list, c); + assert(strcmp(list->head->delta->language, "c") == 0); + assert(ohcount_loc_delta_list_code_added(list) == 1); + assert(ohcount_loc_delta_list_code_removed(list) == 10); + assert(ohcount_loc_delta_list_comments_added(list) == 2); + assert(ohcount_loc_delta_list_comments_removed(list) == 20); + assert(ohcount_loc_delta_list_blanks_added(list) == 3); + assert(ohcount_loc_delta_list_blanks_removed(list) == 30); + ohcount_loc_delta_free(c); + ohcount_loc_delta_list_free(list); +} + +void test_loc_delta_list_add_two_languages() { + LocDeltaList *list = ohcount_loc_delta_list_new(); + LocDelta *c = ohcount_loc_delta_new("c", 1, 10, 2, 20, 3, 30); + LocDelta *java = ohcount_loc_delta_new("java", 100, 1000, 200, 2000, 300, + 3000); + ohcount_loc_delta_list_add_loc_delta(list, c); + ohcount_loc_delta_list_add_loc_delta(list, java); + assert(ohcount_loc_delta_is_equal( + ohcount_loc_delta_list_get_loc_delta(list, "c"), c)); + assert(ohcount_loc_delta_is_equal( + ohcount_loc_delta_list_get_loc_delta(list, "java"), java)); + assert(strcmp(list->head->delta->language, "c") == 0); + assert(strcmp(list->head->next->delta->language, "java") == 0); + assert(ohcount_loc_delta_list_code_added(list) == 101); + assert(ohcount_loc_delta_list_code_removed(list) == 1010); + assert(ohcount_loc_delta_list_comments_added(list) == 202); + assert(ohcount_loc_delta_list_comments_removed(list) == 2020); + assert(ohcount_loc_delta_list_blanks_added(list) == 303); + assert(ohcount_loc_delta_list_blanks_removed(list) == 3030); + ohcount_loc_delta_free(c); + ohcount_loc_delta_free(java); + ohcount_loc_delta_list_free(list); +} + +void test_loc_delta_list_add_same_language_twice() { + LocDeltaList *list = ohcount_loc_delta_list_new(); + LocDelta *c1 = ohcount_loc_delta_new("c", 1, 10, 2, 20, 3, 30); + LocDelta *c2 = ohcount_loc_delta_new("c", 100, 1000, 200, 2000, 300, 3000); + ohcount_loc_delta_list_add_loc_delta(list, c1); + ohcount_loc_delta_list_add_loc_delta(list, c2); + assert(list->head->next == NULL); + assert(strcmp(list->head->delta->language, "c") == 0); + assert(ohcount_loc_delta_list_code_added(list) == 101); + assert(ohcount_loc_delta_list_code_removed(list) == 1010); + assert(ohcount_loc_delta_list_comments_added(list) == 202); + assert(ohcount_loc_delta_list_comments_removed(list) == 2020); + assert(ohcount_loc_delta_list_blanks_added(list) == 303); + assert(ohcount_loc_delta_list_blanks_removed(list) == 3030); + ohcount_loc_delta_free(c1); + ohcount_loc_delta_free(c2); + ohcount_loc_delta_list_free(list); +} + +void test_loc_delta_list_add_two_lists() { + LocDeltaList *list1 = ohcount_loc_delta_list_new(); + LocDeltaList *list2 = ohcount_loc_delta_list_new(); + LocDelta *c1 = ohcount_loc_delta_new("c", 0, 0, 0, 0, 0, 0); + LocDelta *c2 = ohcount_loc_delta_new("c", 1, 10, 2, 20, 3, 30); + ohcount_loc_delta_list_add_loc_delta(list1, c1); + ohcount_loc_delta_list_add_loc_delta(list2, c2); + ohcount_loc_delta_list_add_loc_delta_list(list1, list2); + assert(ohcount_loc_delta_list_code_added(list1) == 1); + assert(ohcount_loc_delta_list_code_removed(list1) == 10); + assert(ohcount_loc_delta_list_comments_added(list1) == 2); + assert(ohcount_loc_delta_list_comments_removed(list1) == 20); + assert(ohcount_loc_delta_list_blanks_added(list1) == 3); + assert(ohcount_loc_delta_list_blanks_removed(list1) == 30); + ohcount_loc_delta_free(c1); + ohcount_loc_delta_free(c2); + ohcount_loc_delta_list_free(list1); + ohcount_loc_delta_list_free(list2); +} + +void test_loc_delta_list_net_total() { + LocDeltaList *list = ohcount_loc_delta_list_new(); + LocDelta *c = ohcount_loc_delta_new("c", 1, 10, 2, 20, 3, 30); + LocDelta *java = ohcount_loc_delta_new("java", 100, 1000, 200, 2000, 300, + 3000); + ohcount_loc_delta_list_add_loc_delta(list, c); + ohcount_loc_delta_list_add_loc_delta(list, java); + assert(ohcount_loc_delta_list_net_code(list) == 1 - 10 + 100 - 1000); + assert(ohcount_loc_delta_list_net_comments(list) == 2 - 20 + 200 - 2000); + assert(ohcount_loc_delta_list_net_blanks(list) == 3 - 30 + 300 - 3000); + assert(ohcount_loc_delta_list_net_total(list) == 6 - 60 + 600 - 6000); + ohcount_loc_delta_free(c); + ohcount_loc_delta_free(java); + ohcount_loc_delta_list_free(list); +} + +void test_loc_delta_list_compact() { + LocDeltaList *list = ohcount_loc_delta_list_new(); + LocDelta *c = ohcount_loc_delta_new("c", 1, 10, 2, 20, 3, 30); + LocDelta *ruby = ohcount_loc_delta_new("ruby", 1, 1, 0, 0, 0, 0); + LocDelta *java = ohcount_loc_delta_new("java", 0, 0, 0, 0, 0, 0); + ohcount_loc_delta_list_add_loc_delta(list, c); + ohcount_loc_delta_list_add_loc_delta(list, ruby); + ohcount_loc_delta_list_add_loc_delta(list, java); + LocDeltaList *compacted = ohcount_loc_delta_list_new_compact(list); + assert(ohcount_loc_delta_is_equal(ohcount_loc_delta_list_get_loc_delta(compacted, "c"), c)); + assert(ohcount_loc_delta_is_equal(ohcount_loc_delta_list_get_loc_delta(compacted, "ruby"), ruby)); + assert(compacted->head->next->next == NULL); + ohcount_loc_delta_free(c); + ohcount_loc_delta_free(ruby); + ohcount_loc_delta_free(java); + ohcount_loc_delta_list_free(list); + ohcount_loc_delta_list_free(compacted); +} + +void all_loc_tests() { + test_loc_default(); + test_loc_initializer(); + test_loc_add(); + test_loc_add_requires_same_language(); + + test_loc_list_default(); + test_loc_list_selector(); + test_loc_list_first_add(); + test_loc_list_add_two_languages(); + test_loc_list_add_same_language_twice(); + test_loc_list_add_loc_lists(); + test_loc_list_compact(); + + test_loc_delta_default(); + test_loc_delta_initializer(); + test_loc_delta_net_total(); + test_loc_delta_addition(); + test_loc_delta_addition_requires_matching_language(); + test_loc_delta_equals(); + + test_loc_delta_list_default(); + test_loc_delta_list_selector(); + test_loc_delta_list_first_add(); + test_loc_delta_list_add_two_languages(); + test_loc_delta_list_add_same_language_twice(); + test_loc_delta_list_add_two_lists(); + test_loc_delta_list_net_total(); + test_loc_delta_list_compact(); +} diff --git a/test/unit/parser_test.h b/test/unit/parser_test.h new file mode 100644 index 0000000..23291de --- /dev/null +++ b/test/unit/parser_test.h @@ -0,0 +1,321 @@ +// parser_test.h written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#include +#include +#include +#include +#include + +#include "../../src/sourcefile.h" + +SourceFile *test_parser_sourcefile(const char *language, const char *contents) { + SourceFile *sf = ohcount_sourcefile_new("foo"); + ohcount_sourcefile_set_contents(sf, contents); + ohcount_sourcefile_set_language(sf, language); + return sf; +} + +void test_parser_verify_parse(SourceFile *sf, const char *language, + const char *code, const char *comments, + int blanks) { + ohcount_sourcefile_parse(sf); + ParsedLanguageList *list = ohcount_sourcefile_get_parsed_language_list(sf); + assert(strcmp(list->head->pl->name, language) == 0); + assert(strcmp(list->head->pl->code, code) == 0); + assert(strcmp(list->head->pl->comments, comments) == 0); + assert(list->head->pl->blanks_count == blanks); + ohcount_sourcefile_free(sf); +} + +void test_parser_verify_parse2(SourceFile *sf, const char *language, + const char *code, const char *comments, + int blanks, const char *language2, + const char *code2, const char *comments2, + int blanks2) { + ohcount_sourcefile_parse(sf); + ParsedLanguageList *list = ohcount_sourcefile_get_parsed_language_list(sf); + assert(strcmp(list->head->pl->name, language) == 0); + assert(strcmp(list->head->pl->code, code) == 0); + assert(strcmp(list->head->pl->comments, comments) == 0); + assert(list->head->pl->blanks_count == blanks); + assert(strcmp(list->head->next->pl->name, language2) == 0); + assert(strcmp(list->head->next->pl->code, code2) == 0); + assert(strcmp(list->head->next->pl->comments, comments2) == 0); + assert(list->head->next->pl->blanks_count == blanks2); + ohcount_sourcefile_free(sf); +} + +typedef struct { + SourceFile *sf; + const char *entity; + const char *expected; +} TestParserEntityUData; + +void test_parser_entity_callback(const char *language, const char *entity, + int start, int end, void *userdata) { + TestParserEntityUData *udata = (TestParserEntityUData *)userdata; + if (strcmp(entity, udata->entity) == 0) { + char *buffer = ohcount_sourcefile_get_contents(udata->sf); + assert(strncmp(udata->expected, buffer + start, end - start) == 0); + } +} + +void test_parser_verify_entity(SourceFile *sf, const char *entity, + const char *expected) { + TestParserEntityUData *udata = malloc(sizeof(TestParserEntityUData)); + udata->sf = sf; + udata->entity = entity; + udata->expected = expected; + ohcount_sourcefile_parse_entities_with_callback(sf, + test_parser_entity_callback, udata); + ohcount_sourcefile_free(sf); + free(udata); +} + +#include "parsers/test_actionscript.h" +#include "parsers/test_ada.h" +#include "parsers/test_assembler.h" +#include "parsers/test_autoconf.h" +#include "parsers/test_automake.h" +#include "parsers/test_awk.h" +#include "parsers/test_basic.h" +#include "parsers/test_bat.h" +#include "parsers/test_blitzmax.h" +#include "parsers/test_boo.h" +#include "parsers/test_c.h" +#include "parsers/test_clearsilvertemplate.h" +#include "parsers/test_clearsilver.h" +#include "parsers/test_cs_aspx.h" +#include "parsers/test_csharp.h" +#include "parsers/test_css.h" +#include "parsers/test_d.h" +#include "parsers/test_dcl.h" +#include "parsers/test_dylan.h" +#include "parsers/test_ebuild.h" +#include "parsers/test_eiffel.h" +#include "parsers/test_emacs_lisp.h" +#include "parsers/test_erlang.h" +#include "parsers/test_exheres.h" +#include "parsers/test_factor.h" +#include "parsers/test_fortran.h" +#include "parsers/test_fsharp.h" +#include "parsers/test_glsl.h" +#include "parsers/test_groovy.h" +#include "parsers/test_haml.h" +#include "parsers/test_haskell.h" +#include "parsers/test_haxe.h" +#include "parsers/test_html.h" +#include "parsers/test_idl_pvwave.h" +#include "parsers/test_java.h" +#include "parsers/test_javascript.h" +#include "parsers/test_jsp.h" +#include "parsers/test_lisp.h" +#include "parsers/test_lua.h" +#include "parsers/test_make.h" +#include "parsers/test_matlab.h" +#include "parsers/test_metafont.h" +#include "parsers/test_metapost.h" +#include "parsers/test_mxml.h" +#include "parsers/test_nix.h" +#include "parsers/test_objective_j.h" +#include "parsers/test_ocaml.h" +#include "parsers/test_octave.h" +#include "parsers/test_pascal.h" +#include "parsers/test_perl.h" +#include "parsers/test_pike.h" +#include "parsers/test_python.h" +#include "parsers/test_r.h" +#include "parsers/test_rexx.h" +#include "parsers/test_rhtml.h" +#include "parsers/test_ruby.h" +#include "parsers/test_scala.h" +#include "parsers/test_scheme.h" +#include "parsers/test_scilab.h" +#include "parsers/test_shell.h" +#include "parsers/test_smalltalk.h" +#include "parsers/test_sql.h" +#include "parsers/test_stratego.h" +#include "parsers/test_tcl.h" +#include "parsers/test_tex.h" +#include "parsers/test_vala.h" +#include "parsers/test_vb_aspx.h" +#include "parsers/test_vhdl.h" +#include "parsers/test_visualbasic.h" +#include "parsers/test_xaml.h" +#include "parsers/test_xml.h" +#include "parsers/test_xmlschema.h" +#include "parsers/test_xslt.h" + +typedef struct { + SourceFile *sf; + FILE *f; +} TestParserUData; + +void test_parser_callback(const char *language, const char *entity, + int start, int end, void *userdata) { + TestParserUData *udata = (TestParserUData *)userdata; + char line[512], line2[512]; + assert(fgets(line, sizeof(line), udata->f) != NULL); + if (strcmp(entity, "lcode") == 0) + entity = "code"; + else if (strcmp(entity, "lcomment") == 0) + entity = "comment"; + else if (strcmp(entity, "lblank") == 0) + entity = "blank"; + sprintf(line2, "%s\t%s\t", language, entity); + char *buffer = ohcount_sourcefile_get_contents(udata->sf); + strncpy(line2 + strlen(language) + strlen(entity) + 2, buffer + start, + end - start); + line2[strlen(language) + strlen(entity) + 2 + (end - start)] = '\0'; + if (strcmp(line, line2) != 0) { + fprintf(stderr, "lines didn't match:\n1: '%s'\n2: '%s'\n", line, line2); + if (strcmp(line, line2) != 0) { + fprintf(stderr, "lines didn't match:\n1: '%s'\n2: '%s'\n", line, line2); + assert(strcmp(line, line2) == 0); + } + } +} + +char *test_parser_filenames[] = { "", 0 }; + +void test_parser_verify_parses() { + const char *src_dir = "../src_dir/"; + char src[FILENAME_MAX]; + strncpy(src, src_dir, strlen(src_dir)); + char *s_p = src + strlen(src_dir); + + const char *expected_dir = "../expected_dir/"; + char expected[FILENAME_MAX]; + strncpy(expected, expected_dir, strlen(expected_dir)); + char *e_p = expected + strlen(expected_dir); + + struct dirent *file; + DIR *d = opendir(src_dir); + if (d) { + while ((file = readdir(d))) { + if (strcmp((const char *)file->d_name, ".") != 0 && + strcmp((const char *)file->d_name, "..") != 0) { + int length = strlen(file->d_name); + strncpy(s_p, (const char *)file->d_name, length); + *(s_p + length) = '\0'; + strncpy(e_p, (const char *)file->d_name, length); + *(e_p + length) = '\0'; + + FILE *f = fopen((const char *)expected, "r"); + if (f) { + SourceFile *sf = ohcount_sourcefile_new((const char *)src); + + // Disambiguators in the detector may access the directory contents of + // the file in question. This could lead to mis-detections for these + // unit tests. By default the directory contents are set to "". If + // this is not desired, add your cases here. + if (strcmp(s_p, "visual_basic.bas") == 0) + // This file needs frx1.frx in the directory contents to be + // detected as Visual Basic. + ohcount_sourcefile_set_filenames(sf, test_basic_vb_filenames); + else + ohcount_sourcefile_set_filenames(sf, test_parser_filenames); + + TestParserUData *udata = malloc(sizeof(TestParserUData)); + udata->sf = sf; + udata->f = f; + + // If the expected file not empty, then the source file should be + // detected as something. Un-detected files are not parsed so no + // failing assertions would be made, resulting in erroneously passed + // tests. + const char *language = ohcount_sourcefile_get_language(sf); + fseek(f, 0, SEEK_END); + if (ftell(f) > 0) + assert(language); + rewind(f); + + ohcount_sourcefile_parse_with_callback(sf, test_parser_callback, + (void *)udata); + fclose(f); + ohcount_sourcefile_free(sf); + free(udata); + } + } + } + closedir(d); + } +} + +void all_parser_tests() { + test_parser_verify_parses(); + all_actionscript_tests(); + all_ada_tests(); + all_assembler_tests(); + all_autoconf_tests(); + all_automake_tests(); + all_awk_tests(); + all_basic_tests(); + all_bat_tests(); + all_blitzmax_tests(); + all_boo_tests(); + all_c_tests(); + all_clearsilver_template_tests(); + all_clearsilver_tests(); + all_cs_aspx_tests(); + all_csharp_tests(); + all_css_tests(); + all_dmd_tests(); + all_dcl_tests(); + all_dylan_tests(); + all_ebuild_tests(); + all_eiffel_tests(); + all_emacs_lisp_tests(); + all_erlang_tests(); + all_exheres_tests(); + all_factor_tests(); + all_fortran_tests(); + all_fsharp_tests(); + all_glsl_tests(); + all_groovy_tests(); + all_haml_tests(); + all_haskell_tests(); + all_haxe_tests(); + all_html_tests(); + all_idl_pvwave_tests(); + all_java_tests(); + all_javascript_tests(); + all_jsp_tests(); + all_lisp_tests(); + all_lua_tests(); + all_make_tests(); + all_matlab_tests(); + all_metafont_tests(); + all_metapost_tests(); + all_mxml_tests(); + all_nix_tests(); + all_objective_j_tests(); + all_ocaml_tests(); + all_octave_tests(); + all_pascal_tests(); + all_perl_tests(); + all_pike_tests(); + all_python_tests(); + all_r_tests(); + all_rexx_tests(); + all_rhtml_tests(); + all_ruby_tests(); + all_scala_tests(); + all_scheme_tests(); + all_scilab_tests(); + all_shell_tests(); + all_smalltalk_tests(); + all_sql_tests(); + all_stratego_tests(); + all_tcl_tests(); + all_tex_tests(); + all_vala_tests(); + all_vb_aspx_tests(); + all_vhdl_tests(); + all_visualbasic_tests(); + all_xaml_tests(); + all_xml_tests(); + all_xmlschema_tests(); + all_xslt_tests(); +} diff --git a/test/unit/parsers/test_actionscript.h b/test/unit/parsers/test_actionscript.h new file mode 100644 index 0000000..cea8f48 --- /dev/null +++ b/test/unit/parsers/test_actionscript.h @@ -0,0 +1,23 @@ + +void test_actionscript_comments() { + test_parser_verify_parse( + test_parser_sourcefile("actionscript", " //comment"), + "actionscript", "", "//comment", 0 + ); +} + +void test_actionscript_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("actionscript", " //comment"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("actionscript", " /*comment*/"), + "comment", "/*comment*/" + ); +} + +void all_actionscript_tests() { + test_actionscript_comments(); + test_actionscript_comment_entities(); +} diff --git a/test/unit/parsers/test_ada.h b/test/unit/parsers/test_ada.h new file mode 100644 index 0000000..dbbb03d --- /dev/null +++ b/test/unit/parsers/test_ada.h @@ -0,0 +1,19 @@ + +void test_ada_comments() { + test_parser_verify_parse( + test_parser_sourcefile("ada", " --comment"), + "ada", "", "--comment", 0 + ); +} + +void test_ada_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("ada", " --comment"), + "comment", "--comment" + ); +} + +void all_ada_tests() { + test_ada_comments(); + test_ada_comment_entities(); +} diff --git a/test/unit/parsers/test_assembler.h b/test/unit/parsers/test_assembler.h new file mode 100644 index 0000000..c1c98a8 --- /dev/null +++ b/test/unit/parsers/test_assembler.h @@ -0,0 +1,27 @@ + +void test_assembler_comments() { + test_parser_verify_parse( + test_parser_sourcefile("assembler", " !comment\n ;comment"), + "assembler", "", "!comment\n;comment", 0 + ); +} + +void test_assembler_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("assembler", " //comment"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("assembler", " ; comment"), + "comment", "; comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("assembler", " !comment"), + "comment", "!comment" + ); +} + +void all_assembler_tests() { + test_assembler_comments(); + test_assembler_comment_entities(); +} diff --git a/test/unit/parsers/test_autoconf.h b/test/unit/parsers/test_autoconf.h new file mode 100644 index 0000000..353f821 --- /dev/null +++ b/test/unit/parsers/test_autoconf.h @@ -0,0 +1,11 @@ + +void test_autoconf_comment_entities() { + test_parser_verify_parse( + test_parser_sourcefile("autoconf", " dnl comment"), + "autoconf", "", "dnl comment", 0 + ); +} + +void all_autoconf_tests() { + test_autoconf_comment_entities(); +} diff --git a/test/unit/parsers/test_automake.h b/test/unit/parsers/test_automake.h new file mode 100644 index 0000000..aa26675 --- /dev/null +++ b/test/unit/parsers/test_automake.h @@ -0,0 +1,11 @@ + +void test_automake_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("automake", " #comment"), + "comment", "#comment" + ); +} + +void all_automake_tests() { + test_automake_comment_entities(); +} diff --git a/test/unit/parsers/test_awk.h b/test/unit/parsers/test_awk.h new file mode 100644 index 0000000..fa25572 --- /dev/null +++ b/test/unit/parsers/test_awk.h @@ -0,0 +1,28 @@ + +void test_awk_comments() { + test_parser_verify_parse( + test_parser_sourcefile("awk", " #comment"), + "awk", "", "#comment", 0 + ); +} + +void test_awk_double_slash() { + test_parser_verify_parse( + test_parser_sourcefile("awk", "\"\\\\\"\n#comment"), + "awk", "\"\\\\\"\n", "#comment", 0 + ); + // awk doesn't recognize backslash escaping of double quote...weird +} + +void test_awk_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("awk", " #comment"), + "comment", "#comment" + ); +} + +void all_awk_tests() { + test_awk_comments(); + test_awk_double_slash(); + test_awk_comment_entities(); +} diff --git a/test/unit/parsers/test_basic.h b/test/unit/parsers/test_basic.h new file mode 100644 index 0000000..528f1fc --- /dev/null +++ b/test/unit/parsers/test_basic.h @@ -0,0 +1,33 @@ + +char *test_basic_vb_filenames[] = { "frx1.frx", 0 }; + +void test_basic_sb_comments() { + test_parser_verify_parse( + test_parser_sourcefile("structured_basic", " REM comment"), + "structured_basic", "", "REM comment", 0 + ); +} + +void test_basic_cb_comments() { + test_parser_verify_parse( + test_parser_sourcefile("classic_basic", " 100 REM comment"), + "classic_basic", "", "100 REM comment", 0 + ); +} + +void test_basic_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("structured_basic", " REM comment"), + "comment", "REM comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("classic_basic", " 'comment"), + "comment", "'comment" + ); +} + +void all_basic_tests() { + test_basic_sb_comments(); + test_basic_cb_comments(); + test_basic_comment_entities(); +} diff --git a/test/unit/parsers/test_bat.h b/test/unit/parsers/test_bat.h new file mode 100644 index 0000000..79518f1 --- /dev/null +++ b/test/unit/parsers/test_bat.h @@ -0,0 +1,19 @@ + +void test_bat_comments() { + test_parser_verify_parse( + test_parser_sourcefile("bat", " REM comment"), + "bat", "", "REM comment", 0 + ); +} + +void test_bat_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("bat", " rem comment"), + "comment", "rem comment" + ); +} + +void all_bat_tests() { + test_bat_comments(); + test_bat_comment_entities(); +} diff --git a/test/unit/parsers/test_blitzmax.h b/test/unit/parsers/test_blitzmax.h new file mode 100644 index 0000000..ee72312 --- /dev/null +++ b/test/unit/parsers/test_blitzmax.h @@ -0,0 +1,19 @@ + +void test_blitzmax_comments() { + test_parser_verify_parse( + test_parser_sourcefile("blitzmax", "' comment"), + "blitzmax", "", "' comment", 0 + ); +} + +void test_blitzmax_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("bat", " ' comment"), + "comment", "' comment" + ); +} + +void all_blitzmax_tests() { + test_blitzmax_comments(); + test_blitzmax_comment_entities(); +} diff --git a/test/unit/parsers/test_boo.h b/test/unit/parsers/test_boo.h new file mode 100644 index 0000000..7b3201b --- /dev/null +++ b/test/unit/parsers/test_boo.h @@ -0,0 +1,55 @@ + +void test_boo_comment() { + test_parser_verify_parse( + test_parser_sourcefile("boo", " #comment"), + "boo", "", "#comment", 0 + ); +} + +void test_boo_block_comment() { + test_parser_verify_parse( + test_parser_sourcefile("boo", " /*comment*/"), + "boo", "", "/*comment*/", 0 + ); +} + +void test_boo_nested_block_comment() { + test_parser_verify_parse( + test_parser_sourcefile("boo", " /* comment\n /* nested */\nstill a comment */"), + "boo", "", "/* comment\n/* nested */\nstill a comment */", 0 + ); +} + +void test_boo_doc_comments() { + test_parser_verify_parse( + test_parser_sourcefile("boo", "\"\"\"\\ndoc comment\n\"\"\""), + "boo", "", "\"\"\"\\ndoc comment\n\"\"\"", 0 + ); +} + +void test_boo_strings() { + test_parser_verify_parse( + test_parser_sourcefile("boo", "\"abc#not a 'comment\""), + "boo", "\"abc#not a 'comment\"", "", 0 + ); +} + +void test_boo_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("boo", " #comment"), + "comment", "#comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("boo", " //comment"), + "comment", "//comment" + ); +} + +void all_boo_tests() { + test_boo_comment(); + test_boo_block_comment(); + test_boo_nested_block_comment(); + test_boo_doc_comments(); + test_boo_strings(); + test_boo_comment_entities(); +} diff --git a/test/unit/parsers/test_c.h b/test/unit/parsers/test_c.h new file mode 100644 index 0000000..f8c03d1 --- /dev/null +++ b/test/unit/parsers/test_c.h @@ -0,0 +1,39 @@ + +void test_c_comments() { + test_parser_verify_parse( + test_parser_sourcefile("c", " //comment"), + "c", "", "//comment", 0 + ); +} + +void test_c_empty_comments() { + test_parser_verify_parse( + test_parser_sourcefile("c", " //\n"), + "c", "", "//\n", 0 + ); +} + +void test_c_block_comment() { + test_parser_verify_parse( + test_parser_sourcefile("c", "/*c*/"), + "c", "", "/*c*/", 0 + ); +} + +void test_c_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("c", " //comment"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("c", " /*comment*/"), + "comment", "/*comment*/" + ); +} + +void all_c_tests() { + test_c_comments(); + test_c_empty_comments(); + test_c_block_comment(); + test_c_comment_entities(); +} diff --git a/test/unit/parsers/test_clearsilver.h b/test/unit/parsers/test_clearsilver.h new file mode 100644 index 0000000..63b1191 --- /dev/null +++ b/test/unit/parsers/test_clearsilver.h @@ -0,0 +1,19 @@ + +void test_clearsilver_comments() { + test_parser_verify_parse( + test_parser_sourcefile("clearsilver", " #comment"), + "clearsilver", "", "#comment", 0 + ); +} + +void test_clearsilver_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("clearsilver", " #comment"), + "comment", "#comment" + ); +} + +void all_clearsilver_tests() { + test_clearsilver_comments(); + test_clearsilver_comment_entities(); +} diff --git a/test/unit/parsers/test_clearsilvertemplate.h b/test/unit/parsers/test_clearsilvertemplate.h new file mode 100644 index 0000000..dcbf42d --- /dev/null +++ b/test/unit/parsers/test_clearsilvertemplate.h @@ -0,0 +1,24 @@ + +void test_clearsilver_template_comments() { + test_parser_verify_parse2( + test_parser_sourcefile("clearsilver_template", " "), + "html", "", "", 0, + "clearsilver", "", "#comment\n", 0 + ); +} + +void test_clearsilver_template_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("clearsilver_template", " "), + "comment", "" + ); + test_parser_verify_entity( + test_parser_sourcefile("clearsilver_template", " "), + "comment", "#comment" + ); +} + +void all_clearsilver_template_tests() { + test_clearsilver_template_comments(); + test_clearsilver_template_comment_entities(); +} diff --git a/test/unit/parsers/test_cmake.h b/test/unit/parsers/test_cmake.h new file mode 100644 index 0000000..2fb8f1b --- /dev/null +++ b/test/unit/parsers/test_cmake.h @@ -0,0 +1,27 @@ + +void test_cmake_comments() { + test_parser_verify_parse( + test_parser_sourcefile("cmake", " #comment"), + "cmake", "", "#comment", 0 + ); +} + +void test_cmake_empty_comments() { + test_parser_verify_parse( + test_parser_sourcefile("cmake", " #\n"), + "cmake", "", "#\n", 0 + ); +} + +void test_cmake_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("cmake", " #comment"), + "comment", "#comment" + ); +} + +void all_cmake_tests() { + test_cmake_comments(); + test_cmake_empty_comments(); + test_cmake_comment_entities(); +} diff --git a/test/unit/parsers/test_cs_aspx.h b/test/unit/parsers/test_cs_aspx.h new file mode 100644 index 0000000..4c2bbef --- /dev/null +++ b/test/unit/parsers/test_cs_aspx.h @@ -0,0 +1,12 @@ + +void test_cs_aspx_comments() { + test_parser_verify_parse2( + test_parser_sourcefile("cs_aspx", "<%\n //comment\n%>"), + "html", "<%\n%>", "", 0, + "csharp", "", "//comment\n", 0 + ); +} + +void all_cs_aspx_tests() { + test_cs_aspx_comments(); +} diff --git a/test/unit/parsers/test_csharp.h b/test/unit/parsers/test_csharp.h new file mode 100644 index 0000000..79ac52d --- /dev/null +++ b/test/unit/parsers/test_csharp.h @@ -0,0 +1,23 @@ + +void test_csharp_comments() { + test_parser_verify_parse( + test_parser_sourcefile("csharp", " //comment"), + "csharp", "", "//comment", 0 + ); +} + +void test_csharp_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("csharp", " //comment"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("csharp", " /*comment*/"), + "comment", "/*comment*/" + ); +} + +void all_csharp_tests() { + test_csharp_comments(); + test_csharp_comment_entities(); +} diff --git a/test/unit/parsers/test_css.h b/test/unit/parsers/test_css.h new file mode 100644 index 0000000..d6506d2 --- /dev/null +++ b/test/unit/parsers/test_css.h @@ -0,0 +1,19 @@ + +void test_css_comments() { + test_parser_verify_parse( + test_parser_sourcefile("css", " /*comment*/"), + "css", "", "/*comment*/", 0 + ); +} + +void test_css_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("css", " /*comment*/"), + "comment", "/*comment*/" + ); +} + +void all_css_tests() { + test_css_comments(); + test_css_comment_entities(); +} diff --git a/test/unit/parsers/test_d.h b/test/unit/parsers/test_d.h new file mode 100644 index 0000000..68f00d1 --- /dev/null +++ b/test/unit/parsers/test_d.h @@ -0,0 +1,63 @@ + +void test_dmd_comments() { + test_parser_verify_parse( + test_parser_sourcefile("dmd", " //comment"), + "dmd", "", "//comment", 0 + ); +} + +void test_dmd_empty_comments() { + test_parser_verify_parse( + test_parser_sourcefile("dmd", " //\n"), + "dmd", "", "//\n", 0 + ); +} + +void test_dmd_strings() { + test_parser_verify_parse( + test_parser_sourcefile("dmd", "'/*' not a comment '*/'"), + "dmd", "'/*' not a comment '*/'", "", 0 + ); +} + +void test_dmd_block_comment() { + test_parser_verify_parse( + test_parser_sourcefile("dmd", " /*d*/"), + "dmd", "", "/*d*/", 0 + ); + test_parser_verify_parse( + test_parser_sourcefile("dmd", " /+d+/"), + "dmd", "", "/+d+/", 0 + ); +} + +void test_dmd_nested_block_comment() { + test_parser_verify_parse( + test_parser_sourcefile("dmd", "/+ /*d*/ not_code(); +/"), + "dmd", "", "/+ /*d*/ not_code(); +/", 0 + ); +} + +void test_dmd_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("dmd", " //comment"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("dmd", " /*comment*/"), + "comment", "/*comment*/" + ); + test_parser_verify_entity( + test_parser_sourcefile("dmd", " /+comment+/"), + "comment", "/+comment+/" + ); +} + +void all_dmd_tests() { + test_dmd_comments(); + test_dmd_empty_comments(); + test_dmd_strings(); + test_dmd_block_comment(); + test_dmd_nested_block_comment(); + test_dmd_comment_entities(); +} diff --git a/test/unit/parsers/test_dcl.h b/test/unit/parsers/test_dcl.h new file mode 100644 index 0000000..64ccac1 --- /dev/null +++ b/test/unit/parsers/test_dcl.h @@ -0,0 +1,43 @@ + +void test_dcl_comments() { + test_parser_verify_parse( + test_parser_sourcefile("dcl", "$!comment"), + "dcl", "", "$!comment", 0 + ); +} + +void test_dcl_code() { + test_parser_verify_parse( + test_parser_sourcefile("dcl", "$code"), + "dcl", "$code", "", 0 + ); +} + +void test_dcl_blank() { + test_parser_verify_parse( + test_parser_sourcefile("dcl", "\n"), + "dcl", "", "", 1 + ); +} + +void test_dcl_input_line() { + test_parser_verify_parse( + test_parser_sourcefile("dcl", "input"), + "dcl", "input", "", 0 + ); +} + +void test_dcl_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("dcl", " !comment"), + "comment", "!comment" + ); +} + +void all_dcl_tests() { + test_dcl_comments(); + test_dcl_code(); + test_dcl_blank(); + test_dcl_input_line(); + test_dcl_comment_entities(); +} diff --git a/test/unit/parsers/test_dylan.h b/test/unit/parsers/test_dylan.h new file mode 100644 index 0000000..8885d27 --- /dev/null +++ b/test/unit/parsers/test_dylan.h @@ -0,0 +1,23 @@ + +void test_dylan_comments() { + test_parser_verify_parse( + test_parser_sourcefile("dylan", " //comment"), + "dylan", "", "//comment", 0 + ); +} + +void test_dylan_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("dylan", " //comment"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("dylan", " /*comment*/"), + "comment", "/*comment*/" + ); +} + +void all_dylan_tests() { + test_dylan_comments(); + test_dylan_comment_entities(); +} diff --git a/test/unit/parsers/test_ebuild.h b/test/unit/parsers/test_ebuild.h new file mode 100644 index 0000000..4ae68a9 --- /dev/null +++ b/test/unit/parsers/test_ebuild.h @@ -0,0 +1,11 @@ + +void test_ebuild_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("ebuild", " #comment"), + "comment", "#comment" + ); +} + +void all_ebuild_tests() { + test_ebuild_comment_entities(); +} diff --git a/test/unit/parsers/test_eiffel.h b/test/unit/parsers/test_eiffel.h new file mode 100644 index 0000000..c533163 --- /dev/null +++ b/test/unit/parsers/test_eiffel.h @@ -0,0 +1,19 @@ + +void test_eiffel_comments() { + test_parser_verify_parse( + test_parser_sourcefile("eiffel", " --comment"), + "eiffel", "", "--comment", 0 + ); +} + +void test_eiffel_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("eiffel", " --comment"), + "comment", "--comment" + ); +} + +void all_eiffel_tests() { + test_eiffel_comments(); + test_eiffel_comment_entities(); +} diff --git a/test/unit/parsers/test_emacs_lisp.h b/test/unit/parsers/test_emacs_lisp.h new file mode 100644 index 0000000..c9a5beb --- /dev/null +++ b/test/unit/parsers/test_emacs_lisp.h @@ -0,0 +1,19 @@ + +void test_emacs_lisp_comments() { + test_parser_verify_parse( + test_parser_sourcefile("emacslisp", " ;;comment"), + "emacslisp", "", ";;comment", 0 + ); +} + +void test_emacs_lisp_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("emacslisp", " ;comment"), + "comment", ";comment" + ); +} + +void all_emacs_lisp_tests() { + test_emacs_lisp_comments(); + test_emacs_lisp_comment_entities(); +} diff --git a/test/unit/parsers/test_erlang.h b/test/unit/parsers/test_erlang.h new file mode 100644 index 0000000..c3bd0fa --- /dev/null +++ b/test/unit/parsers/test_erlang.h @@ -0,0 +1,19 @@ + +void test_erlang_comments() { + test_parser_verify_parse( + test_parser_sourcefile("erlang", " %%comment"), + "erlang", "", "%%comment", 0 + ); +} + +void test_erlang_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("erlang", " %comment"), + "comment", "%comment" + ); +} + +void all_erlang_tests() { + test_erlang_comments(); + test_erlang_comment_entities(); +} diff --git a/test/unit/parsers/test_exheres.h b/test/unit/parsers/test_exheres.h new file mode 100644 index 0000000..566ca38 --- /dev/null +++ b/test/unit/parsers/test_exheres.h @@ -0,0 +1,11 @@ + +void test_exheres_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("exheres", " #comment"), + "comment", "#comment" + ); +} + +void all_exheres_tests() { + test_exheres_comment_entities(); +} diff --git a/test/unit/parsers/test_factor.h b/test/unit/parsers/test_factor.h new file mode 100644 index 0000000..fbf2c4e --- /dev/null +++ b/test/unit/parsers/test_factor.h @@ -0,0 +1,19 @@ + +void test_factor_comments() { + test_parser_verify_parse( + test_parser_sourcefile("factor", " ! comment"), + "factor", "", "! comment", 0 + ); +} + +void test_factor_strings() { + test_parser_verify_parse( + test_parser_sourcefile("factor", "\"abc!not a 'comment\""), + "factor", "\"abc!not a 'comment\"", "", 0 + ); +} + +void all_factor_tests() { + test_factor_comments(); + test_factor_strings(); +} diff --git a/test/unit/parsers/test_fortran.h b/test/unit/parsers/test_fortran.h new file mode 100644 index 0000000..c6d772c --- /dev/null +++ b/test/unit/parsers/test_fortran.h @@ -0,0 +1,15 @@ + +void test_fortran_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("fortranfree", " !comment"), + "comment", "!comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("fortranfixed", "C comment"), + "comment", "C comment" + ); +} + +void all_fortran_tests() { + test_fortran_comment_entities(); +} diff --git a/test/unit/parsers/test_fsharp.h b/test/unit/parsers/test_fsharp.h new file mode 100644 index 0000000..3289e92 --- /dev/null +++ b/test/unit/parsers/test_fsharp.h @@ -0,0 +1,23 @@ + +void test_fsharp_comments() { + test_parser_verify_parse( + test_parser_sourcefile("fsharp", " //comment"), + "fsharp", "", "//comment", 0 + ); +} + +void test_fsharp_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("fsharp", " //comment"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("fsharp", " (*comment*)"), + "comment", "(*comment*)" + ); +} + +void all_fsharp_tests() { + test_fsharp_comments(); + test_fsharp_comment_entities(); +} diff --git a/test/unit/parsers/test_glsl.h b/test/unit/parsers/test_glsl.h new file mode 100644 index 0000000..b545d25 --- /dev/null +++ b/test/unit/parsers/test_glsl.h @@ -0,0 +1,39 @@ + +void test_glsl_comments() { + test_parser_verify_parse( + test_parser_sourcefile("glsl", " //comment"), + "glsl", "", "//comment", 0 + ); +} + +void test_glsl_empty_comments() { + test_parser_verify_parse( + test_parser_sourcefile("glsl", " //\n"), + "glsl", "", "//\n", 0 + ); +} + +void test_glsl_block_comment() { + test_parser_verify_parse( + test_parser_sourcefile("glsl", "/*glsl*/"), + "glsl", "", "/*glsl*/", 0 + ); +} + +void test_glsl_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("glsl", " //comment"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("glsl", " /*comment*/"), + "comment", "/*comment*/" + ); +} + +void all_glsl_tests() { + test_glsl_comments(); + test_glsl_empty_comments(); + test_glsl_block_comment(); + test_glsl_comment_entities(); +} diff --git a/test/unit/parsers/test_groovy.h b/test/unit/parsers/test_groovy.h new file mode 100644 index 0000000..f8e1eb9 --- /dev/null +++ b/test/unit/parsers/test_groovy.h @@ -0,0 +1,23 @@ + +void test_groovy_comments() { + test_parser_verify_parse( + test_parser_sourcefile("groovy", " //comment"), + "groovy", "", "//comment", 0 + ); +} + +void test_groovy_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("groovy", " //comment"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("groovy", " /*comment*/"), + "comment", "/*comment*/" + ); +} + +void all_groovy_tests() { + test_groovy_comments(); + test_groovy_comment_entities(); +} diff --git a/test/unit/parsers/test_haml.h b/test/unit/parsers/test_haml.h new file mode 100644 index 0000000..19fb8d0 --- /dev/null +++ b/test/unit/parsers/test_haml.h @@ -0,0 +1,35 @@ + +void test_haml_comment() { + test_parser_verify_parse( + test_parser_sourcefile("haml", "/ comment"), + "haml", "", "/ comment", 0 + ); +} + +void test_haml_element() { + test_parser_verify_parse( + test_parser_sourcefile("haml", " %code"), + "haml", "%code", "", 0 + ); +} + +void test_haml_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("haml", " %element"), + "element", "%element" + ); + test_parser_verify_entity( + test_parser_sourcefile("haml", " .class"), + "element_class", ".class" + ); + test_parser_verify_entity( + test_parser_sourcefile("haml", " #id"), + "element_id", "#id" + ); +} + +void all_haml_tests() { + test_haml_comment(); + test_haml_element(); + test_haml_comment_entities(); +} diff --git a/test/unit/parsers/test_haskell.h b/test/unit/parsers/test_haskell.h new file mode 100644 index 0000000..1b26362 --- /dev/null +++ b/test/unit/parsers/test_haskell.h @@ -0,0 +1,23 @@ + +void test_haskell_comments() { + test_parser_verify_parse( + test_parser_sourcefile("haskell", " --comment"), + "haskell", "", "--comment", 0 + ); +} + +void test_haskell_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("haskell", " --comment"), + "comment", "--comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("haskell", " {-comment-}"), + "comment", "{-comment-}" + ); +} + +void all_haskell_tests() { + test_haskell_comments(); + test_haskell_comment_entities(); +} diff --git a/test/unit/parsers/test_haxe.h b/test/unit/parsers/test_haxe.h new file mode 100644 index 0000000..777e8bb --- /dev/null +++ b/test/unit/parsers/test_haxe.h @@ -0,0 +1,23 @@ + +void test_haxe_comments() { + test_parser_verify_parse( + test_parser_sourcefile("haxe", " //comment"), + "haxe", "", "//comment", 0 + ); +} + +void test_haxe_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("haxe", " //comment"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("haxe", " /*comment*/"), + "comment", "/*comment*/" + ); +} + +void all_haxe_tests() { + test_haxe_comments(); + test_haxe_comment_entities(); +} diff --git a/test/unit/parsers/test_html.h b/test/unit/parsers/test_html.h new file mode 100644 index 0000000..0fbd1e8 --- /dev/null +++ b/test/unit/parsers/test_html.h @@ -0,0 +1,23 @@ + +void test_html_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("html", " "), + "comment", "" + ); + test_parser_verify_entity( + test_parser_sourcefile("html", ""), + "comment", "/*comment*/" + ); + test_parser_verify_entity( + test_parser_sourcefile("html", ""), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("html", ""), + "comment", "/*comment*/" + ); +} + +void all_html_tests() { + test_html_comment_entities(); +} diff --git a/test/unit/parsers/test_idl_pvwave.h b/test/unit/parsers/test_idl_pvwave.h new file mode 100644 index 0000000..0eeb346 --- /dev/null +++ b/test/unit/parsers/test_idl_pvwave.h @@ -0,0 +1,28 @@ +void test_idl_pvwave_comments() { + test_parser_verify_parse( + test_parser_sourcefile("idl_pvwave", " ;comment"), + "idl_pvwave", "", ";comment", 0 + ); +} + +void test_idl_pvwave_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("idl_pvwave", " ;comment"), + "comment", ";comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("idl_pvwave", " ;comment"), + "comment", ";comment" + ); +} + +void test_idl_pvwave_is_language() { + const char *language = "idl_pvwave"; + assert(ohcount_hash_language_from_name(language, strlen(language)) != NULL); +} + +void all_idl_pvwave_tests() { + test_idl_pvwave_is_language(); + test_idl_pvwave_comments(); + test_idl_pvwave_comment_entities(); +} diff --git a/test/unit/parsers/test_java.h b/test/unit/parsers/test_java.h new file mode 100644 index 0000000..e46afd8 --- /dev/null +++ b/test/unit/parsers/test_java.h @@ -0,0 +1,23 @@ + +void test_java_comments() { + test_parser_verify_parse( + test_parser_sourcefile("java", " //comment"), + "java", "", "//comment", 0 + ); +} + +void test_java_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("java", " //comment"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("java", " /*comment*/"), + "comment", "/*comment*/" + ); +} + +void all_java_tests() { + test_java_comments(); + test_java_comment_entities(); +} diff --git a/test/unit/parsers/test_javascript.h b/test/unit/parsers/test_javascript.h new file mode 100644 index 0000000..766bb09 --- /dev/null +++ b/test/unit/parsers/test_javascript.h @@ -0,0 +1,23 @@ + +void test_javascript_comments() { + test_parser_verify_parse( + test_parser_sourcefile("javascript", " //comment"), + "javascript", "", "//comment", 0 + ); +} + +void test_javascript_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("javascript", " //comment"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("javascript", " /*comment*/"), + "comment", "/*comment*/" + ); +} + +void all_javascript_tests() { + test_javascript_comments(); + test_javascript_comment_entities(); +} diff --git a/test/unit/parsers/test_jsp.h b/test/unit/parsers/test_jsp.h new file mode 100644 index 0000000..0aada71 --- /dev/null +++ b/test/unit/parsers/test_jsp.h @@ -0,0 +1,31 @@ + +void test_jsp_comment() { + test_parser_verify_parse2( + test_parser_sourcefile("jsp", " <% //comment\n%>"), + "java", "", "<% //comment\n", 0, + "html", "%>", "", 0 + ); +} + +void test_jsp_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("jsp", " "), + "comment", "" + ); + test_parser_verify_entity( + test_parser_sourcefile("jsp", ""), + "comment", "/*comment*/" + ); + test_parser_verify_entity( + test_parser_sourcefile("jsp", "<%\n//comment\n%>"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("jsp", "<%\n/*comment*/\n%>"), + "comment", "/*comment*/" + ); +} + +void all_jsp_tests() { + test_jsp_comment_entities(); +} diff --git a/test/unit/parsers/test_lisp.h b/test/unit/parsers/test_lisp.h new file mode 100644 index 0000000..abbc21c --- /dev/null +++ b/test/unit/parsers/test_lisp.h @@ -0,0 +1,51 @@ + +void test_lisp_comment() { + test_parser_verify_parse( + test_parser_sourcefile("lisp", " ;;; comment"), + "lisp", "", ";;; comment", 0 + ); +} + +void test_lisp_doc_string() { + test_parser_verify_parse( + test_parser_sourcefile("lisp", " \"\"\" comment \"\"\""), + "lisp", "", "\"\"\" comment \"\"\"", 0 + ); +} + +void test_lisp_doc_string_blank() { + test_parser_verify_parse( + test_parser_sourcefile("lisp", " \"\"\"\"\"\""), + "lisp", "", "\"\"\"\"\"\"", 0 + ); +} + +void test_lisp_empty_string() { + test_parser_verify_parse( + test_parser_sourcefile("lisp", "\"\""), + "lisp", "\"\"", "", 0 + ); +} + +void test_lisp_char_string() { + test_parser_verify_parse( + test_parser_sourcefile("lisp", " \"a\""), + "lisp", "\"a\"", "", 0 + ); +} + +void test_lisp_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("lisp", " ;comment"), + "comment", ";comment" + ); +} + +void all_lisp_tests() { + test_lisp_comment(); + test_lisp_doc_string(); + test_lisp_doc_string_blank(); + test_lisp_empty_string(); + test_lisp_char_string(); + test_lisp_comment_entities(); +} diff --git a/test/unit/parsers/test_lua.h b/test/unit/parsers/test_lua.h new file mode 100644 index 0000000..0f3bf97 --- /dev/null +++ b/test/unit/parsers/test_lua.h @@ -0,0 +1,23 @@ + +void test_lua_comments() { + test_parser_verify_parse( + test_parser_sourcefile("lua", " -- comment"), + "lua", "", "-- comment", 0 + ); +} + +void test_lua_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("lua", " --comment"), + "comment", "--comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("lua", " --[[comment\ncomment]]"), + "comment", "--[[comment\ncomment]]" + ); +} + +void all_lua_tests() { + test_lua_comments(); + test_lua_comment_entities(); +} diff --git a/test/unit/parsers/test_make.h b/test/unit/parsers/test_make.h new file mode 100644 index 0000000..b4b4e2a --- /dev/null +++ b/test/unit/parsers/test_make.h @@ -0,0 +1,11 @@ + +void test_make_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("make", " #comment"), + "comment", "#comment" + ); +} + +void all_make_tests() { + test_make_comment_entities(); +} diff --git a/test/unit/parsers/test_matlab.h b/test/unit/parsers/test_matlab.h new file mode 100644 index 0000000..47c8cbd --- /dev/null +++ b/test/unit/parsers/test_matlab.h @@ -0,0 +1,43 @@ + +void test_matlab_line_comment_1() { + test_parser_verify_parse( + test_parser_sourcefile("matlab", " %comment"), + "matlab", "", "%comment", 0 + ); +} + +void test_matlab_ancient_syntax_comment() { + test_parser_verify_parse( + test_parser_sourcefile("matlab", " ... comment"), + "matlab", "", "... comment", 0 + ); +} + +void test_matlab_false_line_comment() { + test_parser_verify_parse( + test_parser_sourcefile("matlab", " %{block%} code"), + "matlab", "%{block%} code", "", 0 + ); +} + +void test_matlab_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("matlab", " %comment"), + "comment", "%comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("matlab", " ... comment"), + "comment", "... comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("matlab", " %{comment%}"), + "comment", "%{comment%}" + ); +} + +void all_matlab_tests() { + test_matlab_line_comment_1(); + test_matlab_ancient_syntax_comment(); + test_matlab_false_line_comment(); + test_matlab_comment_entities(); +} diff --git a/test/unit/parsers/test_metafont.h b/test/unit/parsers/test_metafont.h new file mode 100644 index 0000000..d9f68a4 --- /dev/null +++ b/test/unit/parsers/test_metafont.h @@ -0,0 +1,19 @@ + +void test_metafont_comments() { + test_parser_verify_parse( + test_parser_sourcefile("metafont", " % comment"), + "metafont", "", "% comment", 0 + ); +} + +void test_metafont_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("metafont", " %comment"), + "comment", "%comment" + ); +} + +void all_metafont_tests() { + test_metafont_comments(); + test_metafont_comment_entities(); +} diff --git a/test/unit/parsers/test_metapost.h b/test/unit/parsers/test_metapost.h new file mode 100644 index 0000000..9982b06 --- /dev/null +++ b/test/unit/parsers/test_metapost.h @@ -0,0 +1,23 @@ + +void test_metapost_comments() { + test_parser_verify_parse( + test_parser_sourcefile("metapost", " % comment"), + "metapost", "", "% comment", 0 + ); +} + +void test_metapost_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("metapost", " %comment"), + "comment", "%comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("metapost", "verbatim\n%comment\netex"), + "comment", "%comment" + ); +} + +void all_metapost_tests() { + test_metapost_comments(); + test_metapost_comment_entities(); +} diff --git a/test/unit/parsers/test_mxml.h b/test/unit/parsers/test_mxml.h new file mode 100644 index 0000000..f32bdda --- /dev/null +++ b/test/unit/parsers/test_mxml.h @@ -0,0 +1,23 @@ + +void test_mxml_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("mxml", " "), + "comment", "" + ); + test_parser_verify_entity( + test_parser_sourcefile("mxml", "\n/*comment*/\n"), + "comment", "/*comment*/" + ); + test_parser_verify_entity( + test_parser_sourcefile("mxml", "\n//comment\n"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("mxml", "\n/*comment*/\n"), + "comment", "/*comment*/" + ); +} + +void all_mxml_tests() { + test_mxml_comment_entities(); +} diff --git a/test/unit/parsers/test_nix.h b/test/unit/parsers/test_nix.h new file mode 100644 index 0000000..26aefb2 --- /dev/null +++ b/test/unit/parsers/test_nix.h @@ -0,0 +1,11 @@ + +void test_nix_line_comments() { + test_parser_verify_parse( + test_parser_sourcefile("nix", "# comment"), + "nix", "", "# comment", 0 + ); +} + +void all_nix_tests() { + test_nix_line_comments(); +} diff --git a/test/unit/parsers/test_objective_j.h b/test/unit/parsers/test_objective_j.h new file mode 100644 index 0000000..818e422 --- /dev/null +++ b/test/unit/parsers/test_objective_j.h @@ -0,0 +1,23 @@ + +void test_objective_j_comments() { + test_parser_verify_parse( + test_parser_sourcefile("objective_j", " //comment"), + "objective_j", "", "//comment", 0 + ); +} + +void test_objective_j_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("objective_j", " //comment"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("objective_j", " /*comment*/"), + "comment", "/*comment*/" + ); +} + +void all_objective_j_tests() { + test_objective_j_comments(); + test_objective_j_comment_entities(); +} diff --git a/test/unit/parsers/test_ocaml.h b/test/unit/parsers/test_ocaml.h new file mode 100644 index 0000000..1293e05 --- /dev/null +++ b/test/unit/parsers/test_ocaml.h @@ -0,0 +1,19 @@ + +void test_ocaml_comments() { + test_parser_verify_parse( + test_parser_sourcefile("ocaml", " (* comment *)"), + "ocaml", "", "(* comment *)", 0 + ); +} + +void test_ocaml_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("ocaml", " (*comment*)"), + "comment", "(*comment*)" + ); +} + +void all_ocaml_tests() { + test_ocaml_comments(); + test_ocaml_comment_entities(); +} diff --git a/test/unit/parsers/test_octave.h b/test/unit/parsers/test_octave.h new file mode 100644 index 0000000..3ca84a6 --- /dev/null +++ b/test/unit/parsers/test_octave.h @@ -0,0 +1,39 @@ + +void test_octave_line_comment_1() { + test_parser_verify_parse( + test_parser_sourcefile("octave", " %comment"), + "octave", "", "%comment", 0 + ); +} + +void test_octave_syntax_comment() { + test_parser_verify_parse( + test_parser_sourcefile("octave", " # comment"), + "octave", "", "# comment", 0 + ); +} + +void test_octave_false_line_comment() { + test_parser_verify_parse( + test_parser_sourcefile("octave", " %{block%} code"), + "octave", "%{block%} code", "", 0 + ); +} + +void test_octave_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("octave", " %comment"), + "comment", "%comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("octave", " # comment"), + "comment", "# comment" + ); +} + +void all_octave_tests() { + test_octave_line_comment_1(); + test_octave_syntax_comment(); + test_octave_false_line_comment(); + test_octave_comment_entities(); +} diff --git a/test/unit/parsers/test_pascal.h b/test/unit/parsers/test_pascal.h new file mode 100644 index 0000000..65fea37 --- /dev/null +++ b/test/unit/parsers/test_pascal.h @@ -0,0 +1,27 @@ + +void test_pascal_comments() { + test_parser_verify_parse( + test_parser_sourcefile("pascal", " //comment"), + "pascal", "", "//comment", 0 + ); +} + +void test_pascal_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("pascal", " //comment"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("pascal", " (*comment*)"), + "comment", "(*comment*)" + ); + test_parser_verify_entity( + test_parser_sourcefile("pascal", " {comment}"), + "comment", "{comment}" + ); +} + +void all_pascal_tests() { + test_pascal_comments(); + test_pascal_comment_entities(); +} diff --git a/test/unit/parsers/test_perl.h b/test/unit/parsers/test_perl.h new file mode 100644 index 0000000..8dd5ba2 --- /dev/null +++ b/test/unit/parsers/test_perl.h @@ -0,0 +1,23 @@ + +void test_perl_comments() { + test_parser_verify_parse( + test_parser_sourcefile("perl", " #comment"), + "perl", "", "#comment", 0 + ); +} + +void test_perl_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("perl", " #comment"), + "comment", "#comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("perl", "=head1\ncomment\n=cut"), + "comment", "=head1\ncomment\n=cut" + ); +} + +void all_perl_tests() { + test_perl_comments(); + test_perl_comment_entities(); +} diff --git a/test/unit/parsers/test_pike.h b/test/unit/parsers/test_pike.h new file mode 100644 index 0000000..62e3297 --- /dev/null +++ b/test/unit/parsers/test_pike.h @@ -0,0 +1,23 @@ + +void test_pike_comments() { + test_parser_verify_parse( + test_parser_sourcefile("pike", " //comment"), + "pike", "", "//comment", 0 + ); +} + +void test_pike_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("pike", " //comment"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("pike", " /*comment*/"), + "comment", "/*comment*/" + ); +} + +void all_pike_tests() { + test_pike_comments(); + test_pike_comment_entities(); +} diff --git a/test/unit/parsers/test_python.h b/test/unit/parsers/test_python.h new file mode 100644 index 0000000..28ba7cd --- /dev/null +++ b/test/unit/parsers/test_python.h @@ -0,0 +1,39 @@ + +void test_python_comment() { + test_parser_verify_parse( + test_parser_sourcefile("python", " #comment"), + "python", "", "#comment", 0 + ); +} + +void test_python_doc_string() { + test_parser_verify_parse( + test_parser_sourcefile("python", " '''\n doc comment\n '''"), + "python", "", "'''\ndoc comment\n'''", 0 + ); +} + +void test_python_strings() { + test_parser_verify_parse( + test_parser_sourcefile("python", "\"abc#not a 'comment\""), + "python", "\"abc#not a 'comment\"", "", 0 + ); +} + +void test_python_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("python", " #comment"), + "comment", "#comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("python", " \"\"\"comment\"\"\""), + "comment", "\"\"\"comment\"\"\"" + ); +} + +void all_python_tests() { + test_python_comment(); + test_python_doc_string(); + test_python_strings(); + test_python_comment_entities(); +} diff --git a/test/unit/parsers/test_r.h b/test/unit/parsers/test_r.h new file mode 100644 index 0000000..350b310 --- /dev/null +++ b/test/unit/parsers/test_r.h @@ -0,0 +1,19 @@ + +void test_r_comments() { + test_parser_verify_parse( + test_parser_sourcefile("r", " #comment"), + "r", "", "#comment", 0 + ); +} + +void test_r_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("r", " #comment"), + "comment", "#comment" + ); +} + +void all_r_tests() { + test_r_comments(); + test_r_comment_entities(); +} diff --git a/test/unit/parsers/test_rexx.h b/test/unit/parsers/test_rexx.h new file mode 100644 index 0000000..a458f3c --- /dev/null +++ b/test/unit/parsers/test_rexx.h @@ -0,0 +1,19 @@ + +void test_rexx_comment() { + test_parser_verify_parse( + test_parser_sourcefile("rexx", " /*comment*/"), + "rexx", "", "/*comment*/", 0 + ); +} + +void test_rexx_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("rexx", " /*comment*/"), + "comment", "/*comment*/" + ); +} + +void all_rexx_tests() { + test_rexx_comment(); + test_rexx_comment_entities(); +} diff --git a/test/unit/parsers/test_rhtml.h b/test/unit/parsers/test_rhtml.h new file mode 100644 index 0000000..eb119f6 --- /dev/null +++ b/test/unit/parsers/test_rhtml.h @@ -0,0 +1,12 @@ + +void test_rhtml_comment() { + test_parser_verify_parse2( + test_parser_sourcefile("rhtml", "<%\n #comment\n%>"), + "html", "<%\n%>", "", 0, + "ruby", "", "#comment\n", 0 + ); +} + +void all_rhtml_tests() { + test_rhtml_comment(); +} diff --git a/test/unit/parsers/test_ruby.h b/test/unit/parsers/test_ruby.h new file mode 100644 index 0000000..e29843b --- /dev/null +++ b/test/unit/parsers/test_ruby.h @@ -0,0 +1,23 @@ + +void test_ruby_comments() { + test_parser_verify_parse( + test_parser_sourcefile("ruby", " #comment"), + "ruby", "", "#comment", 0 + ); +} + +void test_ruby_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("ruby", " #comment"), + "comment", "#comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("ruby", "=begin\ncomment\n=end"), + "comment", "=begin\ncomment\n=end" + ); +} + +void all_ruby_tests() { + test_ruby_comments(); + test_ruby_comment_entities(); +} diff --git a/test/unit/parsers/test_scala.h b/test/unit/parsers/test_scala.h new file mode 100644 index 0000000..5a124ee --- /dev/null +++ b/test/unit/parsers/test_scala.h @@ -0,0 +1,15 @@ + +void test_scala_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("scala", " //comment"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("scala", " /*comment*/"), + "comment", "/*comment*/" + ); +} + +void all_scala_tests() { + test_scala_comment_entities(); +} diff --git a/test/unit/parsers/test_scheme.h b/test/unit/parsers/test_scheme.h new file mode 100644 index 0000000..9ba6062 --- /dev/null +++ b/test/unit/parsers/test_scheme.h @@ -0,0 +1,19 @@ + +void test_scheme_comments() { + test_parser_verify_parse( + test_parser_sourcefile("scheme", " ;;; comment"), + "scheme", "", ";;; comment", 0 + ); +} + +void test_scheme_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("scheme", " ;comment"), + "comment", ";comment" + ); +} + +void all_scheme_tests() { + test_scheme_comments(); + test_scheme_comment_entities(); +} diff --git a/test/unit/parsers/test_scilab.h b/test/unit/parsers/test_scilab.h new file mode 100644 index 0000000..f6bd60b --- /dev/null +++ b/test/unit/parsers/test_scilab.h @@ -0,0 +1,19 @@ + +void test_scilab_comments() { + test_parser_verify_parse( + test_parser_sourcefile("scilab", " //comment"), + "scilab", "", "//comment", 0 + ); +} + +void test_scilab_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("scilab", " //comment"), + "comment", "//comment" + ); +} + +void all_scilab_tests() { + test_scilab_comments(); + test_scilab_comment_entities(); +} diff --git a/test/unit/parsers/test_shell.h b/test/unit/parsers/test_shell.h new file mode 100644 index 0000000..2797532 --- /dev/null +++ b/test/unit/parsers/test_shell.h @@ -0,0 +1,19 @@ + +void test_shell_comments() { + test_parser_verify_parse( + test_parser_sourcefile("shell", " #comment"), + "shell", "", "#comment", 0 + ); +} + +void test_shell_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("shell", " #comment"), + "comment", "#comment" + ); +} + +void all_shell_tests() { + test_shell_comments(); + test_shell_comment_entities(); +} diff --git a/test/unit/parsers/test_smalltalk.h b/test/unit/parsers/test_smalltalk.h new file mode 100644 index 0000000..cbdc285 --- /dev/null +++ b/test/unit/parsers/test_smalltalk.h @@ -0,0 +1,19 @@ + +void test_smalltalk_comments() { + test_parser_verify_parse( + test_parser_sourcefile("smalltalk", " \"comment\\\""), + "smalltalk", "", "\"comment\\\"", 0 + ); +} + +void test_smalltalk_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("smalltalk", " \"comment\""), + "comment", "\"comment\"" + ); +} + +void all_smalltalk_tests() { + test_smalltalk_comments(); + test_smalltalk_comment_entities(); +} diff --git a/test/unit/parsers/test_sql.h b/test/unit/parsers/test_sql.h new file mode 100644 index 0000000..a6e85ed --- /dev/null +++ b/test/unit/parsers/test_sql.h @@ -0,0 +1,51 @@ + +void test_sql_comments() { + test_parser_verify_parse( + test_parser_sourcefile("sql", " --comment"), + "sql", "", "--comment", 0 + ); +} + +void test_sql_empty_comments() { + test_parser_verify_parse( + test_parser_sourcefile("sql", " --\n"), + "sql", "", "--\n", 0 + ); +} + +void test_sql_block_comment() { + test_parser_verify_parse( + test_parser_sourcefile("sql", " {sql}"), + "sql", "", "{sql}", 0 + ); +} + +void test_sql_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("sql", " --comment"), + "comment", "--comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("sql", " #comment"), + "comment", "#comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("sql", " //comment"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("sql", " /*comment*/"), + "comment", "/*comment*/" + ); + test_parser_verify_entity( + test_parser_sourcefile("sql", " {comment}"), + "comment", "{comment}" + ); +} + +void all_sql_tests() { + test_sql_comments(); + test_sql_empty_comments(); + test_sql_block_comment(); + test_sql_comment_entities(); +} diff --git a/test/unit/parsers/test_stratego.h b/test/unit/parsers/test_stratego.h new file mode 100644 index 0000000..93aad0e --- /dev/null +++ b/test/unit/parsers/test_stratego.h @@ -0,0 +1,30 @@ + +void test_stratego_comments() { + test_parser_verify_parse( + test_parser_sourcefile("stratego", " // comment"), + "stratego", "", "// comment", 0 + ); +} + +void test_stratego_char_string_entities() { + test_parser_verify_entity( + test_parser_sourcefile("stratego", " 'c'"), + "string", "'c'" + ); + // single quote can be used in identifiers + // weak case + test_parser_verify_entity( + test_parser_sourcefile("stratego", " c'"), + "string", "" + ); + // strong case + test_parser_verify_entity( + test_parser_sourcefile("stratego", " c' = e'"), + "string", "" + ); +} + +void all_stratego_tests() { + test_stratego_comments(); + test_stratego_char_string_entities(); +} diff --git a/test/unit/parsers/test_tcl.h b/test/unit/parsers/test_tcl.h new file mode 100644 index 0000000..2fa10d8 --- /dev/null +++ b/test/unit/parsers/test_tcl.h @@ -0,0 +1,19 @@ + +void test_tcl_comments() { + test_parser_verify_parse( + test_parser_sourcefile("tcl", " #comment"), + "tcl", "", "#comment", 0 + ); +} + +void test_tcl_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("tcl", " #comment"), + "comment", "#comment" + ); +} + +void all_tcl_tests() { + test_tcl_comments(); + test_tcl_comment_entities(); +} diff --git a/test/unit/parsers/test_tex.h b/test/unit/parsers/test_tex.h new file mode 100644 index 0000000..de0f02b --- /dev/null +++ b/test/unit/parsers/test_tex.h @@ -0,0 +1,19 @@ + +void test_tex_comments() { + test_parser_verify_parse( + test_parser_sourcefile("tex", " %comment"), + "tex", "", "%comment", 0 + ); +} + +void test_tex_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("tex", " %comment"), + "comment", "%comment" + ); +} + +void all_tex_tests() { + test_tex_comments(); + test_tex_comment_entities(); +} diff --git a/test/unit/parsers/test_vala.h b/test/unit/parsers/test_vala.h new file mode 100644 index 0000000..8811e0e --- /dev/null +++ b/test/unit/parsers/test_vala.h @@ -0,0 +1,23 @@ + +void test_vala_comments() { + test_parser_verify_parse( + test_parser_sourcefile("vala", " //comment"), + "vala", "", "//comment", 0 + ); +} + +void test_vala_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("vala", " //comment"), + "comment", "//comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("vala", " /*comment*/"), + "comment", "/*comment*/" + ); +} + +void all_vala_tests() { + test_vala_comments(); + test_vala_comment_entities(); +} diff --git a/test/unit/parsers/test_vb_aspx.h b/test/unit/parsers/test_vb_aspx.h new file mode 100644 index 0000000..f6971b6 --- /dev/null +++ b/test/unit/parsers/test_vb_aspx.h @@ -0,0 +1,12 @@ + +void test_vb_aspx_comment() { + test_parser_verify_parse2( + test_parser_sourcefile("vb_aspx", "<%\n 'comment\n%>"), + "html", "<%\n%>", "", 0, + "visualbasic", "", "'comment\n", 0 + ); +} + +void all_vb_aspx_tests() { + test_vb_aspx_comment(); +} diff --git a/test/unit/parsers/test_vhdl.h b/test/unit/parsers/test_vhdl.h new file mode 100644 index 0000000..d40ba96 --- /dev/null +++ b/test/unit/parsers/test_vhdl.h @@ -0,0 +1,19 @@ + +void test_vhdl_comments() { + test_parser_verify_parse( + test_parser_sourcefile("vhdl", " -- comment"), + "vhdl", "", "-- comment", 0 + ); +} + +void test_vhdl_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("vhdl", " --comment"), + "comment", "--comment" + ); +} + +void all_vhdl_tests() { + test_vhdl_comments(); + test_vhdl_comment_entities(); +} diff --git a/test/unit/parsers/test_visualbasic.h b/test/unit/parsers/test_visualbasic.h new file mode 100644 index 0000000..b86f7a2 --- /dev/null +++ b/test/unit/parsers/test_visualbasic.h @@ -0,0 +1,23 @@ + +void test_visualbasic_comments() { + test_parser_verify_parse( + test_parser_sourcefile("visualbasic", " 'comment"), + "visualbasic", "", "'comment", 0 + ); +} + +void test_visualbasic_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("visualbasic", " 'comment"), + "comment", "'comment" + ); + test_parser_verify_entity( + test_parser_sourcefile("visualbasic", " Rem comment"), + "comment", "Rem comment" + ); +} + +void all_visualbasic_tests() { + test_visualbasic_comments(); + test_visualbasic_comment_entities(); +} diff --git a/test/unit/parsers/test_xaml.h b/test/unit/parsers/test_xaml.h new file mode 100644 index 0000000..ce11b52 --- /dev/null +++ b/test/unit/parsers/test_xaml.h @@ -0,0 +1,19 @@ + +void test_xaml_comments() { + test_parser_verify_parse( + test_parser_sourcefile("xaml", " "), + "xaml", "", "", 0 + ); +} + +void test_xaml_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("xaml", " "), + "comment", "" + ); +} + +void all_xaml_tests() { + test_xaml_comments(); + test_xaml_comment_entities(); +} diff --git a/test/unit/parsers/test_xml.h b/test/unit/parsers/test_xml.h new file mode 100644 index 0000000..4cf9e35 --- /dev/null +++ b/test/unit/parsers/test_xml.h @@ -0,0 +1,19 @@ + +void test_xml_comments() { + test_parser_verify_parse( + test_parser_sourcefile("xml", " "), + "xml", "", "", 0 + ); +} + +void test_xml_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("xml", " "), + "comment", "" + ); +} + +void all_xml_tests() { + test_xml_comments(); + test_xml_comment_entities(); +} diff --git a/test/unit/parsers/test_xmlschema.h b/test/unit/parsers/test_xmlschema.h new file mode 100644 index 0000000..afad0b8 --- /dev/null +++ b/test/unit/parsers/test_xmlschema.h @@ -0,0 +1,19 @@ + +void test_xmlschema_comments() { + test_parser_verify_parse( + test_parser_sourcefile("xmlschema", " "), + "xmlschema", "", "", 0 + ); +} + +void test_xmlschema_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("xmlschema", " "), + "comment", "" + ); +} + +void all_xmlschema_tests() { + test_xmlschema_comments(); + test_xmlschema_comment_entities(); +} diff --git a/test/unit/parsers/test_xslt.h b/test/unit/parsers/test_xslt.h new file mode 100644 index 0000000..3bde5a3 --- /dev/null +++ b/test/unit/parsers/test_xslt.h @@ -0,0 +1,19 @@ + +void test_xslt_comments() { + test_parser_verify_parse( + test_parser_sourcefile("xslt", " "), + "xslt", "", "", 0 + ); +} + +void test_xslt_comment_entities() { + test_parser_verify_entity( + test_parser_sourcefile("xslt", " "), + "comment", "" + ); +} + +void all_xslt_tests() { + test_xslt_comments(); + test_xslt_comment_entities(); +} diff --git a/test/unit/ruby/gestalt/csharp_using_rule_test.rb b/test/unit/ruby/gestalt/csharp_using_rule_test.rb new file mode 100644 index 0000000..182c0f4 --- /dev/null +++ b/test/unit/ruby/gestalt/csharp_using_rule_test.rb @@ -0,0 +1,33 @@ +require File.dirname(__FILE__) + '/../../test_helper' + +class CSharpUsingRuleTest < Test::Unit::TestCase + include Ohcount::Gestalt + + + def test_sample + cs = SourceFile.new("hello.cs", :contents => <<-INLINE +using System; +using System.Foo; +using NUnit.Framework; + +namespace Hello +{ + /// Hi there +} + INLINE + ) + + r = CSharpUsingRule.new(/System/) + r.process_source_file(cs) + assert_equal 2, r.count + + r = CSharpUsingRule.new(/^System$/) + r.process_source_file(cs) + assert_equal 1, r.count + + r = CSharpUsingRule.new(/.+/) + r.process_source_file(cs) + assert_equal 3, r.count + + end +end diff --git a/test/unit/ruby/gestalt/definitions_test.rb b/test/unit/ruby/gestalt/definitions_test.rb new file mode 100644 index 0000000..7d8de42 --- /dev/null +++ b/test/unit/ruby/gestalt/definitions_test.rb @@ -0,0 +1,481 @@ +require 'test/unit' +require File.dirname(__FILE__) + '/../../../../ruby/gestalt' + +include Ohcount +include Ohcount::Gestalt + +class DefinitionsTest < Ohcount::Test + + def test_zend_framework + assert_gestalts 'zend_framework', [ + Base.new(:platform,'php'), + Base.new(:platform,'zendframework'), + Base.new(:platform,'scripting') + ] + end + + def test_php + assert_gestalts 'php', [ + Base.new(:platform,'php'), + Base.new(:platform,'scripting') + ] + end + + def test_wx_widgets + assert_gestalts 'wx_widgets', [ + Base.new(:platform,'wxwidgets'), + Base.new(:platform, 'native_code') + ] + end + + def test_eclipse_platform + assert_gestalts 'eclipse_platform', [ + Base.new(:platform,'java'), + Base.new(:platform,'eclipseplatform'), + Base.new(:java_import,"java.text.SimpleDateFormat"), + Base.new(:java_import,"java.util.Map"), + Base.new(:java_import,"org.eclipse.core") + ] + end + + def test_win32_not_enough + assert_gestalts 'win32_not_enough', [ + Base.new(:platform, 'native_code') + ] + end + + def test_win32_enough + assert_gestalts 'win32_enough', [ + Base.new(:platform, 'win32'), + Base.new(:platform, 'native_code') + ] + end + + def test_wpf + assert_gestalts 'wpf', [ + Base.new(:platform, 'wpf') + ] + end + + def test_asp_net + assert_gestalts 'asp_net', [ + Base.new(:platform, 'asp_net') + ] + end + + def test_ruby_just_enough + assert_gestalts 'ruby_just_enough', [ + Base.new(:platform, 'ruby'), + Base.new(:platform, 'scripting'), + Base.new(:platform, 'native_code'), + ] + end + + def test_ruby_not_enough + assert_gestalts 'ruby_not_enough', [ + Base.new(:platform, 'native_code') + ] + end + + def test_cakephp + assert_gestalts 'cakephp', [ + Base.new(:platform, 'php'), + Base.new(:platform, 'cakephp'), + Base.new(:platform, 'scripting'), + ] + end + + def test_symfony + assert_platform('symfony', :php, :symfony, :scripting) + end + + def test_pear + assert_platform('pear', :php, :pear, :scripting) + end + + def test_moodle + assert_platform('moodle', :php, :moodle, :scripting) + end + + def test_spring_framework + assert_gestalts 'spring_framework', [ + Base.new(:platform, 'java'), + Base.new(:platform, 'springframework'), + Base.new(:java_jar, 'spring.jar'), + ] + end + + def test_rails + assert_platform('rails', :ruby, :rails, :scripting) + end + + def test_jquery + assert_platform('jquery', :javascript, :jquery, :scripting) + end + + def test_dojo + h = SourceFile.new("sample.html", :contents => '') + expected_gestalts = [ Base.new(:platform, "dojo") ] + assert_equal expected_gestalts.sort, h.gestalts.sort + end + + def test_yui + h = SourceFile.new("sample.html", :contents => '') + expected_gestalts = [ Base.new(:platform, "yui") ] + assert_equal expected_gestalts.sort, h.gestalts.sort + end + + def test_python + assert_platform('python', :python, :scripting) + end + + def test_mac + assert_platform('mac', :mac, :native_code) + end + + def test_plist + assert_platform('plist', :mac) + end + + def test_posix + assert_platform('posix', :posix, :native_code) + end + + def test_x_windows + assert_platform('xwindows', :xwindows, :native_code) + end + + def test_kde + assert_platform('kde', :kde, :native_code) + end + + def test_msdos + assert_platform('msdos', :msdos, :native_code) + end + + def test_gtk + assert_platform('gtk', :gtk, :native_code) + end + + def test_drupal + assert_platform('drupal', :php, :drupal, :scripting) + end + + def test_vs_1 + assert_tool('vs_1', :visualstudio) + end + + def test_eclipse + assert_tool('eclipse', :eclipse) + end + + def test_netbeans + assert_tool('netbeans', :netbeans) + end + + def test_java_imports_from_java_file + java = SourceFile.new("foo.java", :contents => <<-INLINE_C + import com.foo; + import net.ohloh; + import com.foo; + // import dont.import.this; + INLINE_C + ) + + expected_gestalts = [ + Base.new(:java_import, 'com.foo', 2), + Base.new(:java_import, 'net.ohloh'), + Base.new(:platform, 'java'), + ] + + assert_equal expected_gestalts.sort, java.gestalts.sort + end + + def test_arm + asm = SourceFile.new("foo.S", :contents => <<-INLINE_ASM + orrs 3, eax + INLINE_ASM + ) + + expected_gestalts = [ + Base.new(:platform, 'arm') + ] + + assert_equal expected_gestalts.sort, asm.gestalts.sort + end + + def test_arm_from_c_keywords + c = SourceFile.new("foo.c", :contents => <<-INLINE_C + #define __arm__ + INLINE_C + ) + expected_gestalts = [ + Base.new(:platform, 'arm'), + Base.new(:platform, 'native_code') + ] + assert_equal expected_gestalts, c.gestalts + end + + def test_arm_neon + asm = SourceFile.new("foo.S", :contents => <<-INLINE_ASM + vmov u8, s + INLINE_ASM + ) + + expected_gestalts = [ + Base.new(:platform, 'arm'), + Base.new(:platform, 'arm_neon') + ] + + assert_equal expected_gestalts.sort, asm.gestalts.sort + end + + def test_imports_from_java_file + jar = SourceFile.new("foo/foo.jar", :contents => '') + + expected_gestalts = [ + Base.new(:java_jar, 'foo.jar'), + ] + + assert_equal expected_gestalts.sort, jar.gestalts.sort + end + + def test_moblin_clutter + c = SourceFile.new("foo.c", :contents => <<-INLINE_C + clutter_actor_queue_redraw (CLUTTER_ACTOR(label)); + INLINE_C + ) + expected_gestalts = [ + Base.new(:platform, 'clutter'), + Base.new(:platform, 'moblin'), + Base.new(:platform, 'mid_combined'), + Base.new(:platform, 'native_code') + ] + + assert_equal expected_gestalts.sort, c.gestalts.sort + end + + def test_moblin_by_filename + c = SourceFile.new("moblin-netbook-system-tray.h", :contents => <<-INLINE_PERL + #include "foo" + INLINE_PERL + ) + expected_gestalts = [ + Base.new(:platform, 'moblin_misc'), + Base.new(:platform, 'moblin'), + Base.new(:platform, 'mid_combined'), + Base.new(:platform, 'native_code') + ] + + assert_equal expected_gestalts.sort, c.gestalts.sort + end + + def test_moblin_by_keyword + c = SourceFile.new("foo.c", :contents => <<-INLINE_PERL + proxy = dbus_g_proxy_new_for_name (conn, "org.moblin.connman", + INLINE_PERL + ) + expected_gestalts = [ + Base.new(:platform, 'moblin_misc'), + Base.new(:platform, 'moblin'), + Base.new(:platform, 'mid_combined'), + Base.new(:platform, 'native_code') + ] + + assert_equal expected_gestalts.sort, c.gestalts.sort + end + + def test_nbtk + c = SourceFile.new("foo.c", :contents => <<-INLINE_C + button = nbtk_button_new_with_label ("Back"); + INLINE_C + ) + expected_gestalts = [ + Base.new(:platform, 'nbtk'), + Base.new(:platform, 'mid_combined'), + Base.new(:platform, 'moblin'), + Base.new(:platform, 'native_code') + ] + + assert_equal expected_gestalts.sort, c.gestalts.sort + end + + + def test_android + java = SourceFile.new("foo.java", :contents => <<-INLINE_C + import android.app.Activity; + // import dont.import.this; + INLINE_C + ) + + expected_gestalts = [ + Base.new(:java_import, 'android.app.Activity'), + Base.new(:platform, 'java'), + Base.new(:platform, 'android'), + Base.new(:platform, 'mid_combined') + ] + + assert_equal expected_gestalts.sort, java.gestalts.sort + end + + def test_iphone + objective_c = SourceFile.new("foo.m", :contents => <<-OBJECTIVE_C + #import + #import + #import "WhackABugApp.h" + + int main(int argc, char *argv[]) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + int ret = UIApplicationMain(argc, argv, [WhackABugApp class]); + [pool release]; + return ret; + } + OBJECTIVE_C + ) + + expected_gestalts = [ + Base.new(:platform, 'iphone'), + Base.new(:platform, 'mid_combined') + ] + + assert_equal expected_gestalts.sort, objective_c.gestalts.sort + end + + def test_hildon + c = SourceFile.new("foo.c", :contents => <<-INLINE_C + HildonWindow *window; + INLINE_C + ) + expected_gestalts = [ + Base.new(:platform, 'hildon'), + Base.new(:platform, 'maemo'), + Base.new(:platform, 'native_code'), + Base.new(:platform, 'mid_combined') + ] + + assert_equal expected_gestalts.sort, c.gestalts.sort + end + + def test_atom_linux + make = SourceFile.new("makefile", :contents => <<-INLINE_MAKEFILE + COMPILE_FLAGS=/QxL + INLINE_MAKEFILE + ) + expected_gestalts = [ + Base.new(:platform, 'xl_flag'), + Base.new(:platform, 'atom') + ] + assert_equal expected_gestalts.sort, make.gestalts.sort + end + + def test_atom_windows + make = SourceFile.new("makefile", :contents => <<-INLINE_MAKEFILE + CCFLAGS = -xL + INLINE_MAKEFILE + ) + expected_gestalts = [ + Base.new(:platform, 'xl_flag'), + Base.new(:platform, 'atom') + ] + assert_equal expected_gestalts.sort, make.gestalts.sort + end + + def test_not_atom_windows + make = SourceFile.new("makefile", :contents => <<-INLINE_MAKEFILE + CCFLAGS = -xLo + INLINE_MAKEFILE + ) + expected_gestalts = [] + assert_equal expected_gestalts.sort, make.gestalts.sort + end + + def test_atom_sse3 + make = SourceFile.new("makefile", :contents => <<-INLINE_MAKEFILE + COMPILE_FLAGS=-xSSE3_ATOM_FLAG + INLINE_MAKEFILE + ) + expected_gestalts = [ + Base.new(:platform, 'sse3_atom_flag'), + Base.new(:platform, 'atom') + ] + assert_equal expected_gestalts.sort, make.gestalts.sort + end + + def test_intel_compiler + + make = SourceFile.new("Makefile", :contents => <<-INLINE_MAKEFILE + CC = icc + INLINE_MAKEFILE + ) + expected_gestalts = [ + Base.new(:platform, 'intel_compiler'), + ] + assert_equal expected_gestalts.sort, make.gestalts.sort + end + + def test_opensso + java = SourceFile.new("foo.java", :contents => <<-INLINE_JAVA +import com.sun.identity.authentication; + INLINE_JAVA + ) + expected_gestalts = [ + Base.new(:platform, 'java'), + Base.new(:platform, 'opensso'), + Base.new(:java_import, 'com.sun.identity') + ] + + assert_equal expected_gestalts.sort, java.gestalts.sort + end + + def test_windows_ce + csharp = SourceFile.new("bam.cs", :contents => <<-INLINE_CSHARP + using System; + using Microsoft.WindowsMobile.DirectX; + INLINE_CSHARP + ) + expected_gestalts = [ + Base.new(:platform, 'windows_ce_incomplete'), + Base.new(:platform, 'dot_net'), + ] + + assert_equal expected_gestalts.sort, csharp.gestalts.sort + end + + def test_gcc + make = SourceFile.new("Makefile", :contents => <<-INLINE_MAKEFILE + CC = gcc + INLINE_MAKEFILE + ) + expected_gestalts = [ + Base.new(:platform, 'gcc'), + ] + assert_equal expected_gestalts.sort, make.gestalts.sort + end + + def test_native_code + c = SourceFile.new("foo.c", :contents => <<-INLINE_C + int *pcode = NULL; + INLINE_C + ) + expected_gestalts = [ + Base.new(:platform, 'native_code'), + ] + assert_equal expected_gestalts.sort, c.gestalts.sort + end + + def test_flash + as = SourceFile.new("sample.as", :contents => 'greet.text = "Hello, world";') + expected_gestalts = [ Base.new(:platform, "flash") ] + assert_equal expected_gestalts.sort, as.gestalts.sort + end + + def test_flex + as = SourceFile.new("sample.mxml", :contents => <<-MXML + + + MXML + ) + expected_gestalts = [ Base.new(:platform, 'flex') ] + assert_equal expected_gestalts.sort, as.gestalts.sort + end +end diff --git a/test/unit/ruby/gestalt/dot_net_definitions_test.rb b/test/unit/ruby/gestalt/dot_net_definitions_test.rb new file mode 100644 index 0000000..ac1e630 --- /dev/null +++ b/test/unit/ruby/gestalt/dot_net_definitions_test.rb @@ -0,0 +1,89 @@ +require File.dirname(__FILE__) + '/../test_helper' +require File.dirname(__FILE__) + '/../../../../ruby/gestalt' +include Ohcount +include Ohcount::Gestalt + +class DotNetDefinitionsTest < Test::Unit::TestCase + + def test_nunit + sf = SourceFile.new('foo.cs', :contents => <<-CONTENTS +using NUnit.Framework; +CONTENTS + ) + assert_equal [ + Gestalt::Base.new(:platform, 'dot_net'), + Gestalt::Base.new(:platform, 'nunit') + ], sf.gestalts.sort + end + + def test_nhibernate + sf = SourceFile.new('foo.cs', :contents => <<-CONTENTS +using NHibernate.Connection.DriverConnectionProvider; +CONTENTS + ) + assert_equal [ + Gestalt::Base.new(:platform, 'dot_net'), + Gestalt::Base.new(:platform, 'nhibernate') + ], sf.gestalts.sort + end + + def test_remoting_implies_enterprise + sf = SourceFile.new('foo.cs', :contents => <<-CONTENTS +using System.Runtime.Remoting; +CONTENTS + ) + assert_equal [ + Gestalt::Base.new(:platform, 'dot_net'), + Gestalt::Base.new(:platform, 'dot_net_enterprise') + ], sf.gestalts.sort + end + + def test_biztalk_implies_enterprise + sf = SourceFile.new('foo.cs', :contents => <<-CONTENTS +using Microsoft.BizTalk; +CONTENTS + ) + assert_equal [ + Gestalt::Base.new(:platform, 'dot_net'), + Gestalt::Base.new(:platform, 'dot_net_biztalk'), + Gestalt::Base.new(:platform, 'dot_net_enterprise') + ], sf.gestalts.sort + end + + def test_linq_implies_enterprise + sf = SourceFile.new('foo.cs', :contents => <<-CONTENTS +using System.Data.Linq; +CONTENTS + ) + assert_equal [ + Gestalt::Base.new(:platform, 'dot_net'), + Gestalt::Base.new(:platform, 'dot_net_enterprise') + ], sf.gestalts.sort + end + + def test_silverlight_via_asp_keyword + sf = SourceFile.new('foo.aspx', :contents => <<-CONTENTS + + + +CONTENTS + ) + assert_equal [ + Gestalt::Base.new(:platform, 'asp_net'), + Gestalt::Base.new(:platform, 'silverlight') + ], sf.gestalts.sort + end + + def test_silverlight_via_csproj_import + sf = SourceFile.new('Foo.csproj', :contents => <<-CONTENTS + + + + CONTENTS + ) + assert_equal([ + Gestalt::Base.new(:platform, 'silverlight'), + Gestalt::Base.new(:tool, 'visualstudio') + ], sf.gestalts.sort) + end +end diff --git a/test/unit/ruby/gestalt/file_rule_test.rb b/test/unit/ruby/gestalt/file_rule_test.rb new file mode 100644 index 0000000..0274bf6 --- /dev/null +++ b/test/unit/ruby/gestalt/file_rule_test.rb @@ -0,0 +1,54 @@ +require 'test/unit' +require File.dirname(__FILE__) + '/../../../../ruby/gestalt' + +class FileRuleTest < Test::Unit::TestCase + include Ohcount::Gestalt + + def test_initialize + r = FileRule.new(:min => 5) + assert_equal 5, r.min_count + end + + def test_initialize_wrong_args + assert_raise ArgumentError do + r = FileRule.new(:boo => 1) + end + end + +# def test_trigger_c_header +# r = Ohcount::Gestalt::CHeaderRule.new('foo.h') +# s = Ohcount::SourceFile.new('header.h', :contents => <<-H_FILE +# // a comment +# include 'foo.h' +# H_FILE +# ) +# assert r.trigger_file?(s) +# end +# +# def test_c_keyword_rule +# r = Ohcount::Gestalt::CKeywordRule.new('WM_PAINT') +# s = Ohcount::SourceFile.new('header.h', :contents => <<-H_FILE +# // a comment +# (WM_PAINT) +# H_FILE +# ) +# assert r.trigger_file?(s) +# end +# +# def test_filename_rule +# r = Ohcount::Gestalt::FilenameRule.new('header.h') +# s = Ohcount::SourceFile.new('header.h') +# assert r.trigger_file?(s) +# end +# +# def test_filename_rule_advanced +# r = Ohcount::Gestalt::FilenameRule.new('f[ab]o', 'foo') +# assert r.trigger_file?(Ohcount::SourceFile.new('fao')) +# assert r.trigger_file?(Ohcount::SourceFile.new('fbo')) +# assert r.trigger_file?(Ohcount::SourceFile.new('foo')) +# assert !r.trigger_file?(Ohcount::SourceFile.new('fco')) +# end +end + + + diff --git a/test/unit/ruby/gestalt/filename_rule_test.rb b/test/unit/ruby/gestalt/filename_rule_test.rb new file mode 100644 index 0000000..5992f70 --- /dev/null +++ b/test/unit/ruby/gestalt/filename_rule_test.rb @@ -0,0 +1,19 @@ +require 'test/unit' +require File.dirname(__FILE__) + '/../../../../ruby/gestalt' + +class FilenameRuleTest < Test::Unit::TestCase + include Ohcount::Gestalt + + def test_process_file + r = FilenameRule.new('foo\.rb') + s = Ohcount::SourceFile.new('/bar/com/foo.rb', :contents => <<-RUBY_CODE + # comment + code = 1 + RUBY_CODE + ) + assert r.process_source_file(s) + assert_equal 1, r.count + end +end + + diff --git a/test/unit/ruby/gestalt/find_java_imports_rule_test.rb b/test/unit/ruby/gestalt/find_java_imports_rule_test.rb new file mode 100644 index 0000000..932d787 --- /dev/null +++ b/test/unit/ruby/gestalt/find_java_imports_rule_test.rb @@ -0,0 +1,32 @@ +require File.dirname(__FILE__) + '/../../test_helper' + +class FindJavaImportsRuleTest < Test::Unit::TestCase + include Ohcount::Gestalt + + def test_truncate_name + assert_equal "", FindJavaImportsRule.truncate_name(nil, 3) + assert_equal "", FindJavaImportsRule.truncate_name("", 3) + assert_equal "", FindJavaImportsRule.truncate_name("net.ohloh.ohcount.test", 0) + assert_equal "net", FindJavaImportsRule.truncate_name("net.ohloh.ohcount.test", 1) + assert_equal "net.ohloh", FindJavaImportsRule.truncate_name("net.ohloh.ohcount.test", 2) + assert_equal "net.ohloh.ohcount", FindJavaImportsRule.truncate_name("net.ohloh.ohcount.test", 3) + assert_equal "net.ohloh.ohcount.test", FindJavaImportsRule.truncate_name("net.ohloh.ohcount.test", 4) + assert_equal "net.ohloh.ohcount.test", FindJavaImportsRule.truncate_name("net.ohloh.ohcount.test", 5) + end + + def test_arm_from_java_import + java = SourceFile.new("foo.java", :contents => <<-INLINE_C + import org.opengroup.arm40.transaction.ArmConstants; + // import dont.import.this; + INLINE_C + ) + + expected_gestalts = [ + Base.new(:java_import, 'org.opengroup.arm40'), + Base.new(:platform, 'Java'), + Base.new(:platform, 'arm'), + ] + + assert_equal expected_gestalts.sort, java.gestalts.sort + end +end diff --git a/test/unit/ruby/gestalt/gestalt_test.rb b/test/unit/ruby/gestalt/gestalt_test.rb new file mode 100644 index 0000000..ee4f066 --- /dev/null +++ b/test/unit/ruby/gestalt/gestalt_test.rb @@ -0,0 +1,10 @@ +require 'test/unit' +require File.dirname(__FILE__) + '/../test_helper.rb' +require File.dirname(__FILE__) + '/file_rule_test' +require File.dirname(__FILE__) + '/filename_rule_test' +require File.dirname(__FILE__) + '/keyword_rule_test' +require File.dirname(__FILE__) + '/rule_test' +require File.dirname(__FILE__) + '/definitions_test' +require File.dirname(__FILE__) + '/java_definitions_test' +require File.dirname(__FILE__) + '/dot_net_definitions_test' +require File.dirname(__FILE__) + '/jasper_definitions_test' diff --git a/test/unit/ruby/gestalt/jasper_definitions_test.rb b/test/unit/ruby/gestalt/jasper_definitions_test.rb new file mode 100644 index 0000000..8eef510 --- /dev/null +++ b/test/unit/ruby/gestalt/jasper_definitions_test.rb @@ -0,0 +1,117 @@ +require 'test/unit' +require File.dirname(__FILE__) + '/../test_helper.rb' + +include Ohcount +include Ohcount::Gestalt + +class DefinitionsTest < Ohcount::Test + + def test_jasper_reports_java + java = SourceFile.new("foo.java", :contents => <<-INLINE_JAVA + public class Employee implements Serializable { + private net.sf.jasperreports.report myReport; + } + INLINE_JAVA + ) + assert platform_names(java.gestalts).include?('jaspersoft') + assert platform_names(java.gestalts).include?('jasper_reports') + assert platform_names(java.gestalts).include?('jasper_reports_java') + end + + def test_jasper_reports_via_maven + java = SourceFile.new("pom.xml", :contents => <<-INLINE_POM + + dzrealms + HelloWorld + 1.0 + + + jasperreports + jasperreports + 2.0.5 + + + + INLINE_POM + ) + assert platform_names(java.gestalts).include?('jaspersoft') + assert platform_names(java.gestalts).include?('jasper_reports') + assert platform_names(java.gestalts).include?('jasper_reports_java') + end + + def test_jasper_server_java + java = SourceFile.new("foo.java", :contents => <<-INLINE_JAVA + public class Employee implements Serializable { + private com.jaspersoft.jasperserver; + } + INLINE_JAVA + ) + assert platform_names(java.gestalts).include?('jaspersoft') + assert platform_names(java.gestalts).include?('jasper_server') + assert platform_names(java.gestalts).include?('jasper_server_java') + end + + def test_jasper_intelligence + java = SourceFile.new("foo.java", :contents => <<-INLINE_JAVA + public class Employee implements Serializable { + private com.jaspersoft.ji; + } + INLINE_JAVA + ) + assert platform_names(java.gestalts).include?('jaspersoft') + assert platform_names(java.gestalts).include?('jasper_intelligence') + end + + def test_jasper_server + expected = ['scripting', 'ruby', 'jaspersoft', 'jasper_server', 'jasper_server_keyword'] + + rb = SourceFile.new('jasper.rb', :contents => 'def jasper_server; nil ; end') + assert_platforms(expected, rb.gestalts) + + rb = SourceFile.new('jasper.rb', :contents => 'def jasperserver; nil ; end') + assert_platforms(expected, rb.gestalts) + + rb = SourceFile.new('jasper.rb', :contents => 'js = JasperServer.new()') + assert_platforms(expected, rb.gestalts) + + rb = SourceFile.new('jasper.rb', :contents => 'jasper-server') + assert_platforms(expected, rb.gestalts) + end + + def test_jasper_reports + expected = ['scripting', 'ruby', 'jaspersoft', 'jasper_reports', 'jasper_reports_keyword'] + + rb = SourceFile.new('jasper.rb', :contents => 'def jasper_reports; nil ; end') + assert_platforms(expected, rb.gestalts) + + rb = SourceFile.new('jasper.rb', :contents => 'def jasperreports; nil ; end') + assert_platforms(expected, rb.gestalts) + + rb = SourceFile.new('jasper.rb', :contents => 'def JasperReport; nil ; end') + assert_platforms(expected, rb.gestalts) + + rb = SourceFile.new('jasper.rb', :contents => 'jasper-report') + assert_platforms(expected, rb.gestalts) + end + + def test_jasper_ireport + rb = SourceFile.new('jasper.rb', :contents => 'ireport = nil') + assert !platform_names(rb.gestalts).include?('jasper_ireport') + + rb = SourceFile.new('jasper.rb', :contents => 'jasper = nil') + assert !platform_names(rb.gestalts).include?('jasper_ireport') + + rb = SourceFile.new('jasper.rb', :contents => 'jasper_ireport = nil') + assert platform_names(rb.gestalts).include?('jasper_ireport') + end + + protected + + def assert_platforms(expected_names, actual) + assert_equal(expected_names.sort, platform_names(actual).sort) + end + + def platform_names(gestalts) + gestalts.map { |g| g.type == :platform && g.name }.compact + end +end diff --git a/test/unit/ruby/gestalt/java_definitions_test.rb b/test/unit/ruby/gestalt/java_definitions_test.rb new file mode 100644 index 0000000..f3a3bb1 --- /dev/null +++ b/test/unit/ruby/gestalt/java_definitions_test.rb @@ -0,0 +1,75 @@ +include Ohcount +include Ohcount::Gestalt +require File.dirname(__FILE__) + '/../../../../ruby/gestalt' + +class JavaDefinitionsTest < Ohcount::Test + + def test_weblogic_via_maven + assert_gestalts 'weblogic_maven', [ + Base.new(:platform, 'appserver'), + Base.new(:platform, 'java'), + Base.new(:platform, 'maven'), + Base.new(:platform, 'weblogic') + ] + end + + def test_weblogic_via_descriptor + assert_gestalts 'weblogic_descriptor', [ + Base.new(:platform, 'appserver'), + Base.new(:platform, 'java'), + Base.new(:platform, 'weblogic') + ] + end + + def test_webshpere_via_descriptor + assert_gestalts 'websphere', [ + Base.new(:platform, 'appserver'), + Base.new(:platform, 'java'), + Base.new(:platform, 'websphere') + ] + end + + def test_ejb30_by_default + sf = SourceFile.new('hello.java', :contents => <<-JAVA + @Stateless + public class HelloBean { } + JAVA + ) + assert_equal [ + Base.new(:platform, 'java'), + Base.new(:platform, 'ejb3+'), + Base.new(:platform, 'ejb3.0') + ].sort, sf.gestalts.sort + end + + + def test_ejb31_through_annotation + sf = SourceFile.new('hello.java', :contents => <<-JAVA + @Stateless + public class HelloBean { + @Asynchronous public Future getHelloValue() {} + } + JAVA + ) + assert_equal [ + Base.new(:platform, 'java'), + Base.new(:platform, 'ejb3+'), + Base.new(:platform, 'ejb3.1') + ].sort, sf.gestalts.sort + end + + def test_ejb31_through_global_jndi + sf = SourceFile.new('hello.java', :contents => <<-JAVA + public class PlaceBidClient { + context.lookup("java:global/action-bazaar/PlaceBid"); + } + JAVA + ) + assert_equal [ + Base.new(:platform, 'java'), + Base.new(:platform, 'ejb3+'), + Base.new(:platform, 'ejb3.1') + ].sort, sf.gestalts.sort + end + +end diff --git a/test/unit/ruby/gestalt/keyword_rule_test.rb b/test/unit/ruby/gestalt/keyword_rule_test.rb new file mode 100644 index 0000000..dc5098e --- /dev/null +++ b/test/unit/ruby/gestalt/keyword_rule_test.rb @@ -0,0 +1,44 @@ +require 'test/unit' +require File.dirname(__FILE__) + '/../../../../ruby/gestalt' + +class KeywordRuleTest < Test::Unit::TestCase + include Ohcount::Gestalt + + def test_process_file_in_same_language + r = KeywordRule.new('c', 'WIN32') + s = Ohcount::SourceFile.new('header.c', :contents => <<-C_CODE + // a comment + #ifdef WIN32 + ..some code.. + #endif + C_CODE + ) + r.process_source_file(s) + assert_equal 1, r.count + end + + def test_process_file_in_other_language + r = KeywordRule.new('java', 'WIN32') + s = Ohcount::SourceFile.new('header.c', :contents => <<-C_CODE + // a comment + #ifdef WIN32 + ..some code.. + #endif + C_CODE + ) + r.process_source_file(s) + assert_equal 0, r.count + end + + def test_process_file_with_any_language + r = KeywordRule.new(nil, 'A', 'B') + s = Ohcount::SourceFile.new('mixed.rhtml', :contents => <<-RHTML + <% some ruby containing A -%> +
B
+ RHTML + ) + r.process_source_file(s) + assert_equal 2, r.count + end +end + diff --git a/test/unit/ruby/gestalt/maven_dependency_rule_test.rb b/test/unit/ruby/gestalt/maven_dependency_rule_test.rb new file mode 100644 index 0000000..332dee3 --- /dev/null +++ b/test/unit/ruby/gestalt/maven_dependency_rule_test.rb @@ -0,0 +1,60 @@ +require File.dirname(__FILE__) + '/../../test_helper' + +class MavenDependencyTest < Test::Unit::TestCase + include Ohcount::Gestalt + + + def test_dependency + pom = SourceFile.new("pom.xml", :contents => <<-INLINE + + + + + test_group_1 + test_artifact_1A + + + test_group_1 + test_artifact_1B + + + test_group_2 + test_artifact_2A + + + test_group_2 + test_artifact_2B + + + + INLINE + ) + + r = MavenRule.new('dependency', /1$/, /B$/) + + r.process_source_file(pom) + assert_equal 1, r.count + + end + + def test_plugin + pom = SourceFile.new("pom.xml", :contents => <<-INLINE + + + + foobar + baz + + + + INLINE + ) + + r = MavenRule.new('plugin', /^foobar\b/, /^baz\b/) + + r.process_source_file(pom) + assert_equal 1, r.count + end +end diff --git a/test/unit/ruby/gestalt/rule_test.rb b/test/unit/ruby/gestalt/rule_test.rb new file mode 100644 index 0000000..459bd18 --- /dev/null +++ b/test/unit/ruby/gestalt/rule_test.rb @@ -0,0 +1,11 @@ +require 'test/unit' +require File.dirname(__FILE__) + '/../../../../ruby/gestalt' + +class RuleTest < Test::Unit::TestCase + + def test_here + + end +end + + diff --git a/test/unit/ruby/ruby_test.rb b/test/unit/ruby/ruby_test.rb new file mode 100644 index 0000000..7b44cee --- /dev/null +++ b/test/unit/ruby/ruby_test.rb @@ -0,0 +1,4 @@ +require File.dirname(__FILE__) + '/test_helper.rb' +require File.dirname(__FILE__) + '/source_file_list_test.rb' +require File.dirname(__FILE__) + '/source_file_test.rb' +require File.dirname(__FILE__) + '/gestalt/gestalt_test' diff --git a/test/unit/ruby/source_file_list_test.rb b/test/unit/ruby/source_file_list_test.rb new file mode 100644 index 0000000..90d8ba6 --- /dev/null +++ b/test/unit/ruby/source_file_list_test.rb @@ -0,0 +1,34 @@ +require 'test/unit' +require File.dirname(__FILE__) + '/../../../ruby/gestalt' + +class SourceFileListTest < Test::Unit::TestCase + + def test_source_file_list_supports_analyze + paths = [File.dirname(__FILE__)] + list = Ohcount::SourceFileList.new(:paths => paths) + assert list.size > 0 + # assume: the paths variable points to the directory containing this and other simple ruby test files + + ruby = Ohcount::Gestalt::Base.new(:platform, 'ruby') + scripting = Ohcount::Gestalt::Base.new(:platform, 'scripting') + + list.analyze(:gestalt) # this should work + assert list.gestalts.include?(ruby) + assert list.gestalts.include?(scripting) + + list.each do |filename| + assert_equal String, filename.class + end + end +end + +class SourceFileTest < Test::Unit::TestCase + def test_source_file_filenames + filenames = ["x", "y", "z"] + sf = Ohcount::SourceFile.new("foo", :contents => "bar", :filenames => filenames) + assert_equal filenames, sf.filenames + sf.each do |filename| + assert filenames.include?(filename) + end + end +end diff --git a/test/unit/ruby/source_file_test.rb b/test/unit/ruby/source_file_test.rb new file mode 100644 index 0000000..807b614 --- /dev/null +++ b/test/unit/ruby/source_file_test.rb @@ -0,0 +1,25 @@ +require 'test/unit' +require File.dirname(__FILE__) + '/../../../ruby/gestalt' + +class SourceFileTest < Test::Unit::TestCase + def test_diff + c = File.open(File.dirname(__FILE__) + "/../../src_dir/optimer").read + new = Ohcount::SourceFile.new("optimer", :contents => c, :filenames => nil, :filenames => ["optimer"]) + old = Ohcount::SourceFile.new("optimer", :contents => "", :filenames => ["optimer"]) + assert_equal c, new.contents + deltas = old.diff(new).loc_deltas + assert_not_nil deltas + assert_equal "shell", deltas.first.language + end + + def test_empty_diff + filename = "mysql-stale-table-sniper" + c = File.open(File.dirname(__FILE__) + "/../../src_dir/#{filename}").read + new = Ohcount::SourceFile.new(filename, :contents => c, :filenames => nil, :filenames => [filename]) + old = Ohcount::SourceFile.new(filename, :contents => "", :filenames => nil, :filenames => [filename]) + assert_equal c, new.contents + deltas = old.diff(new).loc_deltas + assert_not_nil deltas + assert_equal "perl", deltas.first.language + end +end diff --git a/test/unit/ruby/test_helper.rb b/test/unit/ruby/test_helper.rb new file mode 100644 index 0000000..93bd79b --- /dev/null +++ b/test/unit/ruby/test_helper.rb @@ -0,0 +1,60 @@ +require 'test/unit' +require 'fileutils' +require 'find' +require File.dirname(__FILE__) + '/../../../ruby/ohcount.rb' # .rb is to specify the .rb instead of .bundle +require File.dirname(__FILE__) + '/../../../ruby/gestalt' # .rb is to specify the .rb instead of .bundle + +unless defined?(TEST_DIR) + TEST_DIR = File.dirname(__FILE__) +end + +module Ohcount +end + +# Ohcount::Test is a base class which includes several helper methods for parser testing. +# All unit tests in Ohcount should derive from this class. +# +# ==== Manual Testing +# +# To manually test a 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. +# +class Ohcount::Test < 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 + + protected + + def assert_tool(path, *tools) + gestalts = tools.map do |t| + Base.new(:tool, t.to_s) + end + assert_gestalts path, gestalts + end + + def assert_platform(path, *platforms) + gestalts = platforms.map do |p| + Base.new(:platform, p.to_s) + end + assert_gestalts path, gestalts + end + + def assert_gestalts(path, expected_gestalts) + sfl = SourceFileList.new(:paths => [test_dir(path)]) + assert sfl.size > 0 + sfl.analyze(:gestalt) + assert_equal expected_gestalts.sort, sfl.gestalts.sort + end + + def test_dir(d) + File.expand_path(File.dirname(__FILE__) + "/../../gestalt_files/#{ d }") + end +end + diff --git a/test/unit/sourcefile_test.h b/test/unit/sourcefile_test.h new file mode 100644 index 0000000..1c03d07 --- /dev/null +++ b/test/unit/sourcefile_test.h @@ -0,0 +1,227 @@ +// sourcefile_test.h written by Mitchell Foral. mitchellcaladbolg.net. +// See COPYING for license information. + +#include +#include + +#include "../../src/sourcefile.h" +#include "../../src/diff.h" +#include "../../src/loc.h" + +void test_sourcefile_initialize() { + SourceFile *sf = ohcount_sourcefile_new("foo.rb"); + assert(strcmp("foo.rb", sf->filepath) == 0); + assert(strcmp("rb", sf->ext) == 0); + assert(strcmp("foo.rb", sf->filename) == 0); + assert(strncmp("", sf->filepath, sf->dirpath) == 0); + assert(sf->contents == NULL); + ohcount_sourcefile_free(sf); + + sf = ohcount_sourcefile_new("foo/bar.rb"); + assert(strcmp("foo/bar.rb", sf->filepath) == 0); + assert(strcmp("rb", sf->ext) == 0); + assert(strcmp("bar.rb", sf->filename) == 0); + assert(strncmp("foo/", sf->filepath, sf->dirpath) == 0); + assert(sf->contents == NULL); + ohcount_sourcefile_free(sf); +} + +void test_sourcefile_language_breakdowns() { + SourceFile *sf = ohcount_sourcefile_new("foo.rb"); + ohcount_sourcefile_set_contents(sf, "x = 5"); + ParsedLanguageList *list = ohcount_sourcefile_get_parsed_language_list(sf); + assert(strcmp("ruby", list->head->pl->name) == 0); + assert(strcmp("x = 5", list->head->pl->code) == 0); + ohcount_sourcefile_free(sf); +} + +void test_sourcefile_diff() { + SourceFile *old = ohcount_sourcefile_new("foo.c"); + ohcount_sourcefile_set_contents(old, "int i;"); + SourceFile *new = ohcount_sourcefile_new("foo.c"); + ohcount_sourcefile_set_contents(new, "int j;"); + LocDelta *delta1 = ohcount_loc_delta_new("c", 1, 1, 0, 0, 0, 0); + LocDelta *delta2 = ohcount_sourcefile_calc_loc_delta(old, "c", new); + assert(ohcount_loc_delta_is_equal(delta1, delta2)); + LocDeltaList *list1 = ohcount_loc_delta_list_new(); + ohcount_loc_delta_list_add_loc_delta(list1, delta1); + LocDeltaList *list2 = ohcount_sourcefile_diff(old, new); + assert(list1->head != NULL); + assert(list2->head != NULL); + assert(list1->head->next == NULL); + assert(list2->head->next == NULL); + assert(ohcount_loc_delta_is_equal(list1->head->delta, list2->head->delta)); + ohcount_sourcefile_free(old); + ohcount_sourcefile_free(new); + ohcount_loc_delta_free(delta1); + ohcount_loc_delta_free(delta2); + ohcount_loc_delta_list_free(list1); + ohcount_loc_delta_list_free(list2); +} + +void test_sourcefile_calc_diff2() { + SourceFile *old = ohcount_sourcefile_new("foo.html"); + ohcount_sourcefile_set_contents(old, + "\n" + " \n" + " \n" + "" + ); + SourceFile *new = ohcount_sourcefile_new("foo.html"); + ohcount_sourcefile_set_contents(new, + "\n" + " \n" + " \n" + "" + ); + LocDeltaList *list = ohcount_sourcefile_diff(old, new); + assert(strcmp(list->head->delta->language, "html") == 0); + assert(strcmp(list->head->next->delta->language, "javascript") == 0); + assert(strcmp(list->head->next->next->delta->language, "css") == 0); + LocDelta *delta1 = ohcount_loc_delta_new("javascript", 1, 1, 0, 0, 0, 0); + LocDelta *delta2 = ohcount_loc_delta_list_get_loc_delta(list, "javascript"); + assert(ohcount_loc_delta_is_equal(delta1, delta2)); + ohcount_loc_delta_free(delta1); + delta1 = ohcount_loc_delta_new("css", 0, 0, 1, 1, 0, 0); + delta2 = ohcount_loc_delta_list_get_loc_delta(list, "css"); + assert(ohcount_loc_delta_is_equal(delta1, delta2)); + ohcount_sourcefile_free(old); + ohcount_sourcefile_free(new); + ohcount_loc_delta_list_free(list); + ohcount_loc_delta_free(delta1); +} + +void test_sourcefile_diff_longer() { + SourceFile *old = ohcount_sourcefile_new("foo.c"); + ohcount_sourcefile_set_contents(old, + "int = 1;\n" + "int = 2;\n" + "int = 3;\n" + "int = 4;\n" + ); + SourceFile *new = ohcount_sourcefile_new("foo.c"); + ohcount_sourcefile_set_contents(new, + "int = 1;\n" + "int = 5;\n" + "int = 6;\n" + "int = 4;\n" + ); + LocDeltaList *list = ohcount_sourcefile_diff(old, new); + LocDelta *delta1 = ohcount_loc_delta_new("c", 2, 2, 0, 0, 0, 0); + LocDelta *delta2 = ohcount_loc_delta_list_get_loc_delta(list, "c"); + assert(ohcount_loc_delta_is_equal(delta1, delta2)); + ohcount_sourcefile_free(old); + ohcount_sourcefile_free(new); + ohcount_loc_delta_list_free(list); + ohcount_loc_delta_free(delta1); +} + +void test_sourcefile_diff_very_long() { + int len = 5500000; + char *a = malloc(len); + memset(a, 'i', len); + a[len-1] = '\0'; + a[len-2] = '\n'; + + SourceFile *old = ohcount_sourcefile_new("foo.c"); + ohcount_sourcefile_set_contents(old, a); + strncpy(a, "int = 1;\n", strlen("int = 1;\n")); + SourceFile *new = ohcount_sourcefile_new("foo.c"); + ohcount_sourcefile_set_contents(new, a); + LocDeltaList *list = ohcount_sourcefile_diff(old, new); + // 2 lines added, 1 removed... strange but thats the expectation + LocDelta *delta1 = ohcount_loc_delta_new("c", 2, 1, 0, 0, 0, 0); + LocDelta *delta2 = ohcount_loc_delta_list_get_loc_delta(list, "c"); + assert(ohcount_loc_delta_is_equal(delta1, delta2)); + ohcount_sourcefile_free(old); + ohcount_sourcefile_free(new); + ohcount_loc_delta_list_free(list); + ohcount_loc_delta_free(delta1); +} + +void test_sourcefile_calc_diff() { + int added, removed; + ohcount_calc_diff("", "", &added, &removed); + assert(added == 0); + assert(removed == 0); + ohcount_calc_diff("a", "a", &added, &removed); + assert(added == 0); + assert(removed == 0); + ohcount_calc_diff("a\n", "a\n", &added, &removed); + assert(added == 0); + assert(removed == 0); + ohcount_calc_diff("", "a\n", &added, &removed); + assert(added == 1); + assert(removed == 0); + ohcount_calc_diff("a\n", "", &added, &removed); + assert(added == 0); + assert(removed == 1); + ohcount_calc_diff("a\n", "b\n", &added, &removed); + assert(added = 1); + assert(removed == 1); + ohcount_calc_diff("a\nb\nc\n", "a\nc\nd\n", &added, &removed); + assert(added == 1); + assert(removed == 1); + + ohcount_calc_diff( + "Hello, World!\n" + "Hello, World!\n" + "Hello, World!\n" + "Hello, World!\n" + "Hello, World!\n" + "Hello, World!\n" + "Hello, World!\n" + "Hello, World!\n" + "Hello, World!\n" + "Hello, World!\n", // 10 times + "Hello, World!\n" + "Hello, World!\n" + "Hello, World!\n" + "Hello, World!\n" + "Hello, World!\n" + "Hello, World!\n" + "Hello, World!\n" + "Hello, World!\n" + "Hello, World!\n" + "Hello, World!\n" + "Hello, World!\n", // 11 times + &added, &removed + ); + assert(added == 1); + assert(removed == 0); +} + +void test_sourcefile_list_language_facts() { + SourceFileList *sfl = ohcount_sourcefile_list_new(); + ohcount_sourcefile_list_add_directory(sfl, "../gestalt_files/win32_enough/"); + LocList *list = ohcount_sourcefile_list_analyze_languages(sfl); + assert(ohcount_loc_list_filecount(list) == 2); + Loc *loc = ohcount_loc_list_get_loc(list, "c"); + assert(loc->code == 2); + assert(loc->comments == 2); + assert(loc->blanks == 2); + ohcount_sourcefile_list_free(sfl); + ohcount_loc_list_free(list); +} + +void all_sourcefile_tests() { + test_sourcefile_initialize(); + test_sourcefile_language_breakdowns(); + test_sourcefile_diff(); + test_sourcefile_calc_diff2(); + test_sourcefile_diff_longer(); + test_sourcefile_diff_very_long(); + test_sourcefile_calc_diff(); + + test_sourcefile_list_language_facts(); +}