From b6460f8ed6b249281ada099ca28bd8f1230b8892 Mon Sep 17 00:00:00 2001 From: John Gardner Date: Tue, 30 May 2017 18:02:03 +1000 Subject: [PATCH] Add recognition and classification of WebAssembly (#3650) --- .gitmodules | 3 + grammars.yml | 2 + lib/linguist/languages.yml | 15 ++ samples/Makefile/filenames/Makefile.wat | 248 ++++++++++++++++++ samples/WebAssembly/add.wat | 14 + samples/WebAssembly/fibonacci.wat | 41 +++ samples/WebAssembly/imported-min.wast | 48 ++++ samples/WebAssembly/local-cse.wast | 164 ++++++++++++ samples/WebAssembly/print.wat | 23 ++ ..._shrink-level=1_ignore-implicit-traps.wast | 81 ++++++ vendor/README.md | 1 + vendor/grammars/language-webassembly | 1 + .../licenses/grammar/language-webassembly.txt | 18 ++ 13 files changed, 659 insertions(+) create mode 100644 samples/Makefile/filenames/Makefile.wat create mode 100644 samples/WebAssembly/add.wat create mode 100644 samples/WebAssembly/fibonacci.wat create mode 100644 samples/WebAssembly/imported-min.wast create mode 100644 samples/WebAssembly/local-cse.wast create mode 100644 samples/WebAssembly/print.wat create mode 100644 samples/WebAssembly/remove-unused-brs_shrink-level=1_ignore-implicit-traps.wast create mode 160000 vendor/grammars/language-webassembly create mode 100644 vendor/licenses/grammar/language-webassembly.txt diff --git a/.gitmodules b/.gitmodules index 9081d758..2b129753 100644 --- a/.gitmodules +++ b/.gitmodules @@ -851,3 +851,6 @@ [submodule "vendor/grammars/language-closure-templates"] path = vendor/grammars/language-closure-templates url = https://github.com/mthadley/language-closure-templates +[submodule "vendor/grammars/language-webassembly"] + path = vendor/grammars/language-webassembly + url = https://github.com/Alhadis/language-webassembly diff --git a/grammars.yml b/grammars.yml index 417e920a..fdf08527 100755 --- a/grammars.yml +++ b/grammars.yml @@ -462,6 +462,8 @@ vendor/grammars/language-viml: vendor/grammars/language-wavefront: - source.wavefront.mtl - source.wavefront.obj +vendor/grammars/language-webassembly: +- source.webassembly vendor/grammars/language-xbase: - source.harbour vendor/grammars/language-xcompose: diff --git a/lib/linguist/languages.yml b/lib/linguist/languages.yml index a1a89808..c84dfe6c 100755 --- a/lib/linguist/languages.yml +++ b/lib/linguist/languages.yml @@ -2469,6 +2469,7 @@ Makefile: - Makefile.frag - Makefile.in - Makefile.inc + - Makefile.wat - makefile - makefile.sco - mkfile @@ -4693,6 +4694,20 @@ Web Ontology Language: tm_scope: text.xml ace_mode: xml language_id: 394 +WebAssembly: + type: programming + color: "#04133b" + extensions: + - ".wast" + - ".wat" + aliases: + - wast + - wasm + tm_scope: source.webassembly + ace_mode: lisp + codemirror_mode: commonlisp + codemirror_mime_type: text/x-common-lisp + language_id: 956556503 WebIDL: type: programming extensions: diff --git a/samples/Makefile/filenames/Makefile.wat b/samples/Makefile/filenames/Makefile.wat new file mode 100644 index 00000000..fa145527 --- /dev/null +++ b/samples/Makefile/filenames/Makefile.wat @@ -0,0 +1,248 @@ +# +# The FreeType Project LICENSE +# ---------------------------- +# +# Copyright 1996-1999 by +# David Turner, Robert Wilhelm, and Werner Lemberg +# +# +# +# Introduction +# ============ +# +# The FreeType Project is distributed in several archive packages; +# some of them may contain, in addition to the FreeType font engine, +# various tools and contributions which rely on, or relate to, the +# FreeType Project. +# +# This license applies to all files found in such packages, and +# which do not fall under their own explicit license. The license +# affects thus the FreeType font engine, the test programs, +# documentation and makefiles, at the very least. +# +# This license was inspired by the BSD, Artistic, and IJG +# (Independent JPEG Group) licenses, which all encourage inclusion +# and use of free software in commercial and freeware products +# alike. As a consequence, its main points are that: +# +# o We don't promise that this software works. However, we are be +# interested in any kind of bug reports. (`as is' distribution) +# +# o You can use this software for whatever you want, in parts or +# full form, without having to pay us. (`royalty-free' usage) +# +# o You may not pretend that you wrote this software. If you use +# it, or only parts of it, in a program, you must acknowledge +# somewhere in your documentation that you've used the FreeType +# code. (`credits') +# +# We specifically permit and encourage the inclusion of this +# software, with or without modifications, in commercial products, +# provided that all warranty or liability claims are assumed by the +# product vendor. +# +# +# Legal Terms +# =========== +# +# 0. Definitions +# -------------- +# +# Throughout this license, the terms `package', `FreeType Project', +# and `FreeType archive' refer to the set of files originally +# distributed by the authors (David Turner, Robert Wilhelm, and +# Werner Lemberg) as the `FreeType project', be they named as alpha, +# beta or final release. +# +# `You' refers to the licensee, or person using the project, where +# `using' is a generic term including compiling the project's source +# code as well as linking it to form a `program' or `executable'. +# This program is referred to as `a program using the FreeType +# engine'. +# +# This license applies to all files distributed in the original +# FreeType archive, including all source code, binaries and +# documentation, unless otherwise stated in the file in its +# original, unmodified form as distributed in the original archive. +# If you are unsure whether or not a particular file is covered by +# this license, you must contact us to verify this. +# +# The FreeType project is copyright (C) 1996-1999 by David Turner, +# Robert Wilhelm, and Werner Lemberg. All rights reserved except as +# specified below. +# +# 1. No Warranty +# -------------- +# +# THE FREETYPE ARCHIVE IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY +# KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO +# USE, OF THE FREETYPE PROJECT. +# +# As you have not signed this license, you are not required to +# accept it. However, as the FreeType project is copyrighted +# material, only this license, or another one contracted with the +# authors, grants you the right to use, distribute, and modify it. +# Therefore, by using, distributing, or modifying the FreeType +# project, you indicate that you understand and accept all the terms +# of this license. +# +# 2. Redistribution +# ----------------- +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# o Redistribution of source code must retain this license file +# (`licence.txt') unaltered; any additions, deletions or changes +# to the original files must be clearly indicated in +# accompanying documentation. The copyright notices of the +# unaltered, original files must be preserved in all copies of +# source files. +# +# o Redistribution in binary form must provide a disclaimer that +# states that the software is based in part of the work of the +# FreeType Team, in the distribution documentation. We also +# encourage you to put an URL to the FreeType web page in your +# documentation, though this isn't mandatory. +# +# These conditions apply to any software derived from or based on +# the FreeType code, not just the unmodified files. If you use our +# work, you must acknowledge us. However, no fee need be paid to +# us. +# +# 3. Advertising +# -------------- +# +# The names of FreeType's authors and contributors may not be used +# to endorse or promote products derived from this software without +# specific prior written permission. +# +# We suggest, but do not require, that you use one or more of the +# following phrases to refer to this software in your documentation +# or advertising materials: `FreeType Project', `FreeType Engine', +# `FreeType library', or `FreeType Distribution'. +# +# 4. Contacts +# ----------- +# +# There are two mailing lists related to FreeType: +# +# o freetype@freetype.org +# +# Discusses general use and applications of FreeType, as well as +# future and wanted additions to the library and distribution. +# If you are looking for support, start in this list if you +# haven't found anything to help you in the documentation. +# +# o devel@freetype.org +# +# Discusses bugs, as well as engine internals, design issues, +# specific licenses, porting, etc. +# +# o http://www.freetype.org +# +# Holds the current FreeType web page, which will allow you to +# download our latest development version and read online +# documentation. +# +# You can also contact us individually at: +# +# David Turner +# Robert Wilhelm +# Werner Lemberg +# +# +# --- end of license --- +# +# This file is part of the FreeType project. +# +# This builds the Watcom library with Watcom's wcc386 under OS/2. +# +# You'll need Watcom's wmake. +# +# +# Invoke by "wmake -f arch\os2\Makefile.wat" when in the "lib" directory +# +# This will build "freetype\lib\libttf.lib" + +ARCH = arch\os2 +FT_MAKEFILE = $(ARCH)\Makefile.wat +FT_MAKE = wmake -h + + +.EXTENSIONS: +.EXTENSIONS: .lib .obj .c .h +.obj:.;.\extend;.\$(ARCH) +.c:.;.\extend;.\$(ARCH) +.h:.;.\extend;.\$(ARCH) + +CC = wcc386 + +CCFLAGS = /otexanl+ /s /w5 /zq -Iarch\os2 -I. -Iextend + +TTFILE = .\ttfile.c +TTMEMORY = .\ttmemory.c +TTMUTEX = .\ttmutex.c + +TTFILE_OBJ = ttfile.obj +TTMEMORY_OBJ = ttmemory.obj +TTMUTEX_OBJ = ttmutex.obj + +PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) +PORT_OBJS = $(TTFILE_OBJ) $(TTMEMORY_OBJ) $(TTMUTEX_OBJ) + +SRC_X = extend\ftxgasp.c extend\ftxkern.c extend\ftxpost.c & + extend\ftxcmap.c extend\ftxwidth.c extend\ftxsbit.c & + extend\ftxgsub.c extend\ftxgpos.c extend\ftxopen.c & + extend\ftxgdef.c + +OBJS_X = extend\ftxgasp.obj extend\ftxkern.obj extend\ftxpost.obj & + extend\ftxcmap.obj extend\ftxwidth.obj extend\ftxsbit.obj & + extend\ftxgsub.obj extend\ftxgpos.obj extend\ftxopen.obj & + extend\ftxgdef.obj + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c & + ttgload.c ttinterp.c ttload.c ttobjs.c & + ttraster.c ttextend.c $(PORT) + +OBJS_M = ttapi.obj ttcache.obj ttcalc.obj ttcmap.obj & + ttgload.obj ttinterp.obj ttload.obj ttobjs.obj & + ttraster.obj ttextend.obj $(PORT_OBJS) $(OBJS_X) + +SRC_S = freetype.c +OBJ_S = freetype.obj +OBJS_S = $(OBJ_S) $(OBJS_X) + + +.c.obj: + $(CC) $(CCFLAGS) $[* /fo=$[*.obj + +all: .symbolic + $(FT_MAKE) -f $(FT_MAKEFILE) libttf.lib + +debug: .symbolic + $(FT_MAKE) -f $(FT_MAKEFILE) LIB_FILES="$(OBJS_M)" libttf.lib + + +libttf.lib: $(OBJS_M) + wlib -q -n libttf.lib $(OBJS_M) + +# is this correct? Know nothing about wmake and the Watcom compiler... +$(OBJ_S): $(SRC_S) $(SRC_M) + $(CC) $(CCFLAGS) $(SRC_S) /fo=$(OBJ_S) + +clean: .symbolic + @-erase $(OBJS_M) + @-erase *.err + +distclean: .symbolic clean + @-erase libttf.lib + +new: .symbolic + @-wtouch *.c + +# end of Makefile.wat diff --git a/samples/WebAssembly/add.wat b/samples/WebAssembly/add.wat new file mode 100644 index 00000000..bbb69d98 --- /dev/null +++ b/samples/WebAssembly/add.wat @@ -0,0 +1,14 @@ +(module + (import "env" "printInt" (func $printInt (param i32))) + (func $add (param $lhs i32) (param $rhs i32) (result i32) + get_local $lhs + get_local $rhs + i32.add + ) + + (func $main + (call $printInt + (call $add (i32.const 9) (i32.const 8)))) + + (export "main" (func $main)) +) diff --git a/samples/WebAssembly/fibonacci.wat b/samples/WebAssembly/fibonacci.wat new file mode 100644 index 00000000..179f6bf5 --- /dev/null +++ b/samples/WebAssembly/fibonacci.wat @@ -0,0 +1,41 @@ +(module + (import "env" "printInt" (func $printInt (param i32))) + (import "env" "print" (func $print (param i32 i32))) + + (memory $memory 1) + (data (i32.const 0) "\n") + (data (i32.const 1) " ") + + (func $endl + (call $print (i32.const 0) (i32.const 1))) + (func $space + (call $print (i32.const 1) (i32.const 1))) + + (func $fibonacci_rec (param $a i32) (param $b i32) (param $n i32) (result i32) + (if (i32.eqz (get_local $n)) (return (get_local $a))) + (call $printInt (get_local $b)) + (call $space) + (set_local $a (i32.add (get_local $a) (get_local $b))) + (call $fibonacci_rec (get_local $b) (get_local $a) (i32.sub (get_local $n) (i32.const 1))) + ) + + (func $fibonacci_iter (param $a i32) (param $b i32) (param $n i32) (result i32) + (loop $fi + (if (i32.eqz (get_local $n)) (return (get_local $a))) + (call $printInt (get_local $b)) + (call $space) + (set_local $b (i32.add (get_local $a) (get_local $b))) + (set_local $a (i32.sub (get_local $b) (get_local $a))) + (set_local $n (i32.sub (get_local $n) (i32.const 1))) + (br $fi)) + (get_local $b)) + + (func $main + (drop (call $fibonacci_rec (i32.const 0) (i32.const 1) (i32.const 9))) + (call $endl) + (drop (call $fibonacci_iter (i32.const 0) (i32.const 1) (i32.const 9)))) + + (export "main" (func $main)) + (export "memory" (memory $memory)) +) + diff --git a/samples/WebAssembly/imported-min.wast b/samples/WebAssembly/imported-min.wast new file mode 100644 index 00000000..8972a2ee --- /dev/null +++ b/samples/WebAssembly/imported-min.wast @@ -0,0 +1,48 @@ +(module + (memory 256 256) + (data (i32.const 10) "waka waka waka waka waka") + ;; stack imports are special + (import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32)) + (import "env" "STACK_MAX" (global $STACK_MAX$asm2wasm$import i32)) + ;; other imports must not be touched! + (import "env" "tempDoublePtr" (global $tempDoublePtr i32)) + (export "test1" $test1) + (export "test2" $test2) + (export "test3" $test3) + ;; ok to modify a global, if we keep it the same value + (global $mine (mut i32) (i32.const 1)) + ;; stack imports are ok to use. their uses are the same as other + ;; globals - must keep the same value (which means, unwind the stack) + ;; here the global names are "minified" + (global $global0 (mut i32) (get_global $STACKTOP$asm2wasm$import)) + (global $global1 (mut i32) (get_global $STACK_MAX$asm2wasm$import)) + ;; a global initialized by an import, so bad, but ok if not used + (global $do-not-use (mut i32) (get_global $tempDoublePtr)) + (func $test1 + (local $temp i32) + (set_global $mine (i32.const 1)) + (set_local $temp (get_global $global0)) + (set_global $global0 (i32.const 1337)) ;; bad + (set_global $global0 (get_local $temp)) ;; save us + (set_global $global1 (i32.const 913370)) ;; bad + (set_global $global1 (get_local $temp)) ;; save us + ;; use the stack memory + (i32.store (get_local $temp) (i32.const 1337)) + (if + (i32.ne + (i32.load (get_local $temp)) + (i32.const 1337) + ) + (unreachable) ;; they should be equal, never get here + ) + ;; finally, do a valid store + (i32.store8 (i32.const 12) (i32.const 115)) + ) + (func $test2 + (set_global $tempDoublePtr (i32.const 1)) ;; bad! + (i32.store8 (i32.const 13) (i32.const 115)) + ) + (func $test3 + (i32.store8 (i32.const 14) (i32.const 115)) + ) +) diff --git a/samples/WebAssembly/local-cse.wast b/samples/WebAssembly/local-cse.wast new file mode 100644 index 00000000..26a25d23 --- /dev/null +++ b/samples/WebAssembly/local-cse.wast @@ -0,0 +1,164 @@ +(module + (memory 100 100) + (func $basics + (local $x i32) + (local $y i32) + (drop + (i32.add (i32.const 1) (i32.const 2)) + ) + (drop + (i32.add (i32.const 1) (i32.const 2)) + ) + (if (i32.const 0) (nop)) + (drop ;; we can't do this yet, non-linear + (i32.add (i32.const 1) (i32.const 2)) + ) + (drop + (i32.add (get_local $x) (get_local $y)) + ) + (drop + (i32.add (get_local $x) (get_local $y)) + ) + (drop + (i32.add (get_local $x) (get_local $y)) + ) + (call $basics) ;; side effects, but no matter for our locals + (drop + (i32.add (get_local $x) (get_local $y)) + ) + (set_local $x (i32.const 100)) + (drop ;; x was changed! + (i32.add (get_local $x) (get_local $y)) + ) + ) + (func $recursive1 + (local $x i32) + (local $y i32) + (drop + (i32.add + (i32.const 1) + (i32.add + (i32.const 2) + (i32.const 3) + ) + ) + ) + (drop + (i32.add + (i32.const 1) + (i32.add + (i32.const 2) + (i32.const 3) + ) + ) + ) + (drop + (i32.add + (i32.const 2) + (i32.const 3) + ) + ) + ) + (func $recursive2 + (local $x i32) + (local $y i32) + (drop + (i32.add + (i32.const 1) + (i32.add + (i32.const 2) + (i32.const 3) + ) + ) + ) + (drop + (i32.add + (i32.const 2) + (i32.const 3) + ) + ) + (drop + (i32.add + (i32.const 1) + (i32.add + (i32.const 2) + (i32.const 3) + ) + ) + ) + ) + (func $self + (local $x i32) + (local $y i32) + (drop + (i32.add + (i32.add + (i32.const 2) + (i32.const 3) + ) + (i32.add + (i32.const 2) + (i32.const 3) + ) + ) + ) + (drop + (i32.add + (i32.const 2) + (i32.const 3) + ) + ) + ) + (func $loads + (drop + (i32.load (i32.const 10)) + ) + (drop + (i32.load (i32.const 10)) ;; implicit traps, sad + ) + ) + (func $8 (param $var$0 i32) (result i32) + (local $var$1 i32) + (local $var$2 i32) + (local $var$3 i32) + (block $label$0 i32 + (i32.store + (tee_local $var$2 + (i32.add + (get_local $var$1) + (i32.const 4) + ) + ) + (i32.and + (i32.load + (get_local $var$2) + ) + (i32.xor + (tee_local $var$2 + (i32.const 74) + ) + (i32.const -1) + ) + ) + ) + (i32.store + (tee_local $var$1 + (i32.add + (get_local $var$1) + (i32.const 4) + ) + ) + (i32.or + (i32.load + (get_local $var$1) + ) + (i32.and + (get_local $var$2) + (i32.const 8) + ) + ) + ) + (i32.const 0) + ) + ) +) diff --git a/samples/WebAssembly/print.wat b/samples/WebAssembly/print.wat new file mode 100644 index 00000000..3f71669b --- /dev/null +++ b/samples/WebAssembly/print.wat @@ -0,0 +1,23 @@ +(module + (import "env" "printInt" (func $printInt (param i32))) + (import "env" "printFloat" (func $printFloat (param f32))) + (import "env" "print" (func $print (param i32 i32))) + + (memory $memory 1) + (data (i32.const 0) "\n") + (data (i32.const 1) "Hello World!") + + (func $endl + (call $print (i32.const 0) (i32.const 1))) + + (func $main + (call $printInt (i32.const 9)) + (call $endl) + (call $printFloat (f32.const 6.28)) + (call $endl) + (call $print (i32.const 1) (i32.const 12)) + ) + + (export "main" (func $main)) + (export "memory" (memory $memory)) +) diff --git a/samples/WebAssembly/remove-unused-brs_shrink-level=1_ignore-implicit-traps.wast b/samples/WebAssembly/remove-unused-brs_shrink-level=1_ignore-implicit-traps.wast new file mode 100644 index 00000000..c0ec7d4c --- /dev/null +++ b/samples/WebAssembly/remove-unused-brs_shrink-level=1_ignore-implicit-traps.wast @@ -0,0 +1,81 @@ +(module + (memory 256 256) + (type $0 (func (param i32))) + (type $1 (func)) + (type $2 (func (result i32))) + (func $b14 (type $2) + (drop + (if i32 ;; with shrinking, this can become a select + (i32.const 1) + (block $block1 i32 + (i32.const 12) + ) + (block $block3 i32 + (i32.const 27) + ) + ) + ) + (drop + (if i32 + (i32.const 1) + (i32.load (i32.const 10)) ;; load may have side effects, unless ignored + (i32.const 27) + ) + ) + (drop + (if i32 + (i32.const 1) + (i32.rem_s (i32.const 11) (i32.const 12)) ;; rem may have side effects, unless ignored + (i32.const 27) + ) + ) + (drop + (if i32 + (i32.const 1) + (i32.trunc_u/f64 (f64.const 12.34)) ;; float to int may have side effects, unless ignored + (i32.const 27) + ) + ) + (i32.const 0) + ) + (func $join-br_ifs + (block $out + (br_if $out (i32.const 1)) + (br_if $out (i32.const 2)) + (br_if $out (i32.const 3)) + ) + (block $out2 + (block $out3 + (br_if $out2 (i32.const 1)) + (br_if $out3 (i32.const 2)) + (br_if $out2 (i32.const 3)) + ) + (unreachable) + ) + (block $out4 + (block $out5 + (br_if $out4 (i32.const 1)) + (br_if $out5 (i32.const 2)) + (br_if $out5 (i32.const 3)) + ) + (unreachable) + ) + (block $out6 + (block $out7 + (br_if $out6 (i32.const 1)) + (br_if $out6 (i32.const 2)) + (br_if $out7 (i32.const 3)) + ) + (unreachable) + ) + (block $out8 + (br_if $out8 (call $b14)) ;; side effect + (br_if $out8 (i32.const 0)) + ) + (block $out8 + (br_if $out8 (i32.const 1)) + (br_if $out8 (call $b14)) ;; side effect + ) + ) +) + diff --git a/vendor/README.md b/vendor/README.md index b96c844e..94638ec2 100644 --- a/vendor/README.md +++ b/vendor/README.md @@ -370,6 +370,7 @@ This is a list of grammars that Linguist selects to provide syntax highlighting - **Wavefront Material:** [Alhadis/language-wavefront](https://github.com/Alhadis/language-wavefront) - **Wavefront Object:** [Alhadis/language-wavefront](https://github.com/Alhadis/language-wavefront) - **Web Ontology Language:** [textmate/xml.tmbundle](https://github.com/textmate/xml.tmbundle) +- **WebAssembly:** [Alhadis/language-webassembly](https://github.com/Alhadis/language-webassembly) - **WebIDL:** [andik/IDL-Syntax](https://github.com/andik/IDL-Syntax) - **wisp:** [atom/language-clojure](https://github.com/atom/language-clojure) - **World of Warcraft Addon Data:** [nebularg/language-toc-wow](https://github.com/nebularg/language-toc-wow) diff --git a/vendor/grammars/language-webassembly b/vendor/grammars/language-webassembly new file mode 160000 index 00000000..47874fed --- /dev/null +++ b/vendor/grammars/language-webassembly @@ -0,0 +1 @@ +Subproject commit 47874fed72b52b256e7482d3a10d55e508216623 diff --git a/vendor/licenses/grammar/language-webassembly.txt b/vendor/licenses/grammar/language-webassembly.txt new file mode 100644 index 00000000..10f0d90d --- /dev/null +++ b/vendor/licenses/grammar/language-webassembly.txt @@ -0,0 +1,18 @@ +--- +type: grammar +name: language-webassembly +license: isc +--- +Copyright (c) 2016-2017, John Gardner + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.