diff options
198 files changed, 33585 insertions, 1471 deletions
@@ -14,5 +14,9 @@ under the licensing terms detailed in LICENSE. * Julien Hamaide <julien.hamaide@gmail.com> * Ehsan Akhgari <ehsan.akhgari@gmail.com> (copyright owned by Mozilla Foundation) * Adrian Taylor <adrian@macrobug.com> - - +* Richard Assar <richard.assar@gmail.com> +* Nathan Hammond <emscripten@nathanhammond.com> +* Behdad Esfahbod <behdad@behdad.org> +* David Benjamin <davidben@mit.edu> +* Pierre Renaux <pierre@talansoft.com> +* Brian Anderson <banderson@mozilla.com> @@ -4,9 +4,9 @@ See emcc.py. This script forwards to there, noting that we want C++ and not C by default ''' -import os, sys +import os, subprocess, sys from tools import shared os.environ['EMMAKEN_CXX'] = '1' -exit(os.execvp(shared.EMCC, [shared.EMCC] + sys.argv[1:])) +exit(subprocess.call(['python', shared.EMCC] + sys.argv[1:])) @@ -7,7 +7,7 @@ emar - ar helper script This script acts as a frontend replacement for ar. See emcc. ''' -import os, sys +import os, subprocess, sys from tools import shared DEBUG = os.environ.get('EMCC_DEBUG') @@ -18,5 +18,5 @@ if DEBUG: print >> sys.stderr, 'emar:', sys.argv, ' ==> ', newargs if len(newargs) > 2: - os.execvp(shared.LLVM_AR, newargs) + subprocess.call(newargs) @@ -74,10 +74,19 @@ emcc can be influenced by a few environment variables: EMMAKEN_COMPILER - The compiler to be used, if you don't want the default clang. ''' -import os, sys, shutil, tempfile -from subprocess import Popen, PIPE, STDOUT +import os, sys, shutil, tempfile, subprocess, shlex +from subprocess import PIPE, STDOUT from tools import shared +def execute(cmd, *args, **kw): + try: + return subprocess.Popen(cmd, *args, **kw).communicate() # let compiler frontend print directly, so colors are saved (PIPE kills that) + except: + if not isinstance(cmd, str): + cmd = ' '.join(cmd) + print >> sys.stderr, 'Invoking Process failed: <<< ' + cmd + ' >>>' + raise + # Mapping of emcc opt levels to llvm opt levels. We use llvm opt level 3 in emcc opt # levels 2 and 3 (emcc 3 is unsafe opts, so unsuitable for the only level to get # llvm opt level 3, and speed-wise emcc level 2 is already the slowest/most optimizing @@ -151,18 +160,29 @@ Options that are modified or new in %s include: break the generated code! If that happens, try -O2 and then adding dangerous optimizations one by one. + -s OPTION=VALUE JavaScript code generation option passed into the emscripten compiler. For the available options, see src/settings.js + --typed-arrays <mode> 0: No typed arrays 1: Parallel typed arrays 2: Shared (C-like) typed arrays (default) + --llvm-opts <level> 0: No LLVM optimizations (default in -O0) 1: -O1 LLVM optimizations (default in -O1) 2: -O2 LLVM optimizations 3: -O3 LLVM optimizations (default in -O2+) + + --llvm-lto <level> 0: No LLVM LTO (default in -O0) + 1: LLVM LTO (default in -O1+) + Note: If LLVM optimizations are not run + (see --llvm-opts), setting this to 1 has no + effect. + --closure <on> 0: No closure compiler (default in -O0, -O1) 1: Run closure compiler (default in -O2, -O3) + --js-transform <cmd> <cmd> will be called on the generated code before it is optimized. This lets you modify the JavaScript, for example adding some code @@ -177,23 +197,61 @@ Options that are modified or new in %s include: list of arguments, for example, <cmd> of "python processor.py" will cause a python script to be run. + --pre-js <file> A file whose contents are added before the - generated code + generated code. This is done *before* + optimization, so it will be minified + properly if closure compiler is run. + --post-js <file> A file whose contents are added after the - generated code - --compress <on> 0: Do not compress the generated JavaScript's + generated code This is done *before* + optimization, so it will be minified + properly if closure compiler is run. + + --embed-file <file> A file to embed inside the generated + JavaScript. The compiled code will be able + to access the file in the current directory + with the same basename as given here (that is, + just the filename, without a path to it). + If a directory is passed here, its entire + contents will be embedded. + + --preload-file <name> A file to preload before running the + compiled code asynchronously. Otherwise + similar to --embed-file, except that this + option is only relevant when generating + HTML (it uses asynchronous binary XHRs). + If a directory is passed here, its entire + contents will be preloaded. + + --compression <codec> Compress both the compiled code and embedded/ + preloaded files. <codec> should be a triple, + + <native_encoder>,<js_decoder>,<js_name> + + where native_encoder is a native executable + that compresses stdin to stdout (the simplest + possible interface), js_decoder is a + JavaScript file that implements a decoder, + and js_name is the name of the function to + call in the decoder file (which should + receive an array/typed array and return + an array/typed array. + Compression only works when generating HTML. + When compression is on, all filed specified + to be preloaded are compressed in one big + archive, which is given the same name as the + output HTML but with suffix .data.compress + + --minify <on> 0: Do not minify the generated JavaScript's whitespace (default if closure compiler will not be run) - 1: Compress the generated JavaScript's + 1: Minify the generated JavaScript's whitespace (default if closure compiler will be run). Note that this by itself will not minify the code (closure does that) - --embed-file <filename> A file to embed inside the generated - JavaScript. The compiled code will be able - to access the file in the current directory - with the same basename as given here (that is, - just the filename, without a path to it). + --ignore-dynamic-linking Normally emcc will treat dynamic linking like static linking, by linking in the code from the dynamic library. This fails if the same @@ -202,6 +260,7 @@ Options that are modified or new in %s include: which allows the build system to proceed without errors. However, you will need to manually link to the shared libraries later on yourself. + --shell-file <path> The path name to a skeleton HTML file used when generating HTML output. The shell file used needs to have this token inside it: @@ -210,13 +269,16 @@ Options that are modified or new in %s include: target other than HTML is specified using the -o option. + --js-library <lib> A JavaScript library to use in addition to + those in Emscripten's src/library_* + The target file, if specified (-o <target>), defines what will be generated: <name>.js JavaScript (default) <name>.html HTML with embedded JavaScript <name>.bc LLVM bitcode - <name>.o LLVM bitcode + <name>.o LLVM bitcode (same as .bc) The -c option (which tells gcc not to run the linker) will cause LLVM bitcode to be generated, as %s only generates @@ -234,15 +296,15 @@ the source of emcc (search for 'os.environ'). # If this is a configure-type thing, do not compile to JavaScript, instead use clang # to compile to a native binary (using our headers, so things make sense later) -CONFIGURE_CONFIG = os.environ.get('EMMAKEN_JUST_CONFIGURE') +CONFIGURE_CONFIG = os.environ.get('EMMAKEN_JUST_CONFIGURE') or 'conftest.c' in sys.argv CMAKE_CONFIG = 'CMakeFiles/cmTryCompileExec.dir' in ' '.join(sys.argv)# or 'CMakeCCompilerId' in ' '.join(sys.argv) if CONFIGURE_CONFIG or CMAKE_CONFIG: compiler = shared.CLANG if not ('CXXCompiler' in ' '.join(sys.argv) or os.environ.get('EMMAKEN_CXX')): compiler = shared.to_cc(compiler) - cmd = [compiler] + shared.EMSDK_OPTS + sys.argv[1:] - if DEBUG: print >> sys.stderr, 'emcc, just configuring: ', compiler, cmd - exit(os.execvp(compiler, cmd)) + cmd = [compiler] + shared.EMSDK_OPTS + ['-DEMSCRIPTEN'] + sys.argv[1:] + if DEBUG: print >> sys.stderr, 'emcc, just configuring: ', ' '.join(cmd) + exit(subprocess.call(cmd)) if os.environ.get('EMMAKEN_COMPILER'): CXX = os.environ['EMMAKEN_COMPILER'] @@ -258,7 +320,7 @@ if os.environ.get('EMMAKEN_CXX'): CC_ADDITIONAL_ARGS = shared.COMPILER_OPTS # + ['-g']? EMMAKEN_CFLAGS = os.environ.get('EMMAKEN_CFLAGS') -if EMMAKEN_CFLAGS: CC_ADDITIONAL_ARGS += EMMAKEN_CFLAGS.split(' ') +if EMMAKEN_CFLAGS: CC_ADDITIONAL_ARGS += shlex.split(EMMAKEN_CFLAGS) # ---------------- Utilities --------------- @@ -269,8 +331,12 @@ STATICLIB_SUFFIXES = ('.a',) ASSEMBLY_SUFFIXES = ('.ll',) LIB_PREFIXES = ('', 'lib') +IMAGE_SUFFIXES = ('.jpg', '.png', '.bmp') +AUDIO_SUFFIXES = ('.ogg', '.wav', '.mp3') +AUDIO_MIMETYPES = { 'ogg': 'audio/ogg', 'wav': 'audio/wav', 'mp3': 'audio/mpeg' } + def suffix(name): - return name.split('.')[:-1] + return name.split('.')[-1] def unsuffixed(name): return '.'.join(name.split('.')[:-1]) @@ -278,6 +344,13 @@ def unsuffixed(name): def unsuffixed_basename(name): return os.path.basename(unsuffixed(name)) +seen_names = {} +def unsuffixed_uniquename(name): + ret = unsuffixed_basename(name) + if name not in seen_names: + seen_names[name] = str(len(seen_names)) + return ret + '_' + seen_names[name] + # ---------------- End configs ------------- if len(sys.argv) == 1 or sys.argv[1] in ['x', 't']: @@ -296,6 +369,12 @@ for i in range(1, len(sys.argv)): if arg.endswith('.h') and sys.argv[i-1] != '-include': header = True +if '-M' in sys.argv or '-MM' in sys.argv: + # Just output dependencies, do not compile. Warning: clang and gcc behave differently with -MF! (clang seems to not recognize it) + cmd = [CC] + shared.COMPILER_OPTS + sys.argv[1:] + if DEBUG: print >> sys.stderr, 'emcc, just dependencies: ', ' '.join(cmd) + exit(subprocess.call(cmd)) + # Check if a target is specified target = None for i in range(len(sys.argv)-1): @@ -308,8 +387,12 @@ for i in range(len(sys.argv)-1): break if header: # header or such - if DEBUG: print >> sys.stderr, 'Just copy.' - shutil.copy(sys.argv[-1], sys.argv[-2]) + if len(sys.argv) >= 3: # if there is a source and a target, then copy, otherwise do nothing + sys.argv = filter(lambda arg: not arg.startswith('-I'), sys.argv) + if DEBUG: print >> sys.stderr, 'Just copy:', sys.argv[-1], target + shutil.copy(sys.argv[-1], target) + else: + if DEBUG: print >> sys.stderr, 'No-op.' exit(0) if TEMP_DIR: @@ -323,6 +406,21 @@ else: def in_temp(name): return os.path.join(temp_dir, name) +class Compression: + on = False + + @staticmethod + def compressed_name(filename): + return filename + '.compress' + + @staticmethod + def compress(filename): + execute(Compression.encoder, stdin=open(filename, 'rb'), stdout=open(Compression.compressed_name(filename), 'wb')) + + @staticmethod + def worth_it(original, compressed): + return compressed < original - 1500 # save at least one TCP packet or so + try: call = CXX if use_cxx else CC @@ -332,14 +430,17 @@ try: opt_level = 0 llvm_opts = None + llvm_lto = None closure = None js_transform = None pre_js = None post_js = None - compress_whitespace = None - embed_files = [] + minify_whitespace = None + data_files = [] + compression = None ignore_dynamic_linking = False shell_path = shared.path_from_root('src', 'shell.html') + js_libraries = [] def check_bad_eq(arg): assert '=' not in arg, 'Invalid parameter (do not use "=" with "--" options)' @@ -357,6 +458,11 @@ try: llvm_opts = eval(newargs[i+1]) newargs[i] = '' newargs[i+1] = '' + elif newargs[i].startswith('--llvm-lto'): + check_bad_eq(newargs[i]) + llvm_lto = eval(newargs[i+1]) + newargs[i] = '' + newargs[i+1] = '' elif newargs[i].startswith('--closure'): check_bad_eq(newargs[i]) closure = int(newargs[i+1]) @@ -377,20 +483,31 @@ try: post_js = open(newargs[i+1]).read() newargs[i] = '' newargs[i+1] = '' - elif newargs[i].startswith('--compress'): + elif newargs[i].startswith('--minify'): check_bad_eq(newargs[i]) - compress_whitespace = int(newargs[i+1]) + minify_whitespace = int(newargs[i+1]) newargs[i] = '' newargs[i+1] = '' elif newargs[i].startswith('--embed-file'): check_bad_eq(newargs[i]) - embed_files.append(newargs[i+1]) + data_files.append({ 'name': newargs[i+1], 'mode': 'embed' }) newargs[i] = '' newargs[i+1] = '' - elif newargs[i] == '-MF': # clang cannot handle this, so we fake it - f = open(newargs[i+1], 'w') - f.write('\n') - f.close() + elif newargs[i].startswith('--preload-file'): + check_bad_eq(newargs[i]) + data_files.append({ 'name': newargs[i+1], 'mode': 'preload' }) + newargs[i] = '' + newargs[i+1] = '' + elif newargs[i].startswith('--compression'): + check_bad_eq(newargs[i]) + parts = newargs[i+1].split(',') + assert len(parts) == 3, '--compression requires specifying native_encoder,js_decoder,js_name - see emcc --help. got: %s' % newargs[i+1] + Compression.encoder = parts[0] + Compression.decoder = parts[1] + Compression.js_name = parts[2] + assert os.path.exists(Compression.encoder), 'native encoder %s does not exist' % Compression.encoder + assert os.path.exists(Compression.decoder), 'js decoder %s does not exist' % Compression.decoder + Compression.on = True newargs[i] = '' newargs[i+1] = '' elif newargs[i] == '--ignore-dynamic-linking': @@ -401,12 +518,18 @@ try: shell_path = newargs[i+1] newargs[i] = '' newargs[i+1] = '' + elif newargs[i].startswith('--js-library'): + check_bad_eq(newargs[i]) + js_libraries.append(newargs[i+1]) + newargs[i] = '' + newargs[i+1] = '' newargs = [ arg for arg in newargs if arg is not '' ] if llvm_opts is None: llvm_opts = LLVM_OPT_LEVEL[opt_level] + if llvm_lto is None: llvm_lto = llvm_opts > 0 if closure is None: closure = 1 if opt_level >= 2 else 0 - if compress_whitespace is None: - compress_whitespace = closure # if closure is run, compress whitespace + if minify_whitespace is None: + minify_whitespace = closure # if closure is run, minify whitespace if closure: assert os.path.exists(shared.CLOSURE_COMPILER), 'emcc: fatal: Closure compiler (%s) does not exist' % shared.CLOSURE_COMPILER @@ -428,11 +551,16 @@ try: input_files = [] has_source_inputs = False - lib_dirs = [] + lib_dirs = [shared.path_from_root('system', 'lib')] libs = [] for i in range(len(newargs)): # find input files XXX this a simple heuristic. we should really analyze based on a full understanding of gcc params, # right now we just assume that what is left contains no more |-x OPT| things arg = newargs[i] + + if i > 0: + prev = newargs[i-1] + if prev in ['-MT', '-install_name']: continue # ignore this gcc-style argument + if arg.endswith(SOURCE_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + ASSEMBLY_SUFFIXES) or shared.Building.is_ar(arg): # we already removed -o <target>, so all these should be inputs newargs[i] = '' if os.path.exists(arg): @@ -443,6 +571,16 @@ try: # this should be bitcode, make sure it is valid if arg.endswith(ASSEMBLY_SUFFIXES) or shared.Building.is_bitcode(arg): input_files.append(arg) + elif arg.endswith(STATICLIB_SUFFIXES + DYNAMICLIB_SUFFIXES): + # if it's not, and it's a library, just add it to libs to find later + l = unsuffixed_basename(arg) + for prefix in LIB_PREFIXES: + if not prefix: continue + if l.startswith(prefix): + l = l[len(prefix):] + break; + libs.append(l) + newargs[i] = '' else: print >> sys.stderr, 'emcc: %s: warning: Not valid LLVM bitcode' % arg else: @@ -453,6 +591,7 @@ try: elif arg.startswith('-l'): libs.append(arg[2:]) newargs[i] = '' + newargs = [ arg for arg in newargs if arg is not '' ] # Find library files @@ -475,7 +614,10 @@ try: if ignore_dynamic_linking: input_files = filter(lambda input_file: not input_file.endswith(DYNAMICLIB_SUFFIXES), input_files) - assert len(input_files) > 0, 'emcc: no input files' + if len(input_files) == 0: + print >> sys.stderr, 'emcc: no input files' + print >> sys.stderr, 'note that input files without a known suffix are ignored, make sure your input files end with one of: ' + str(SOURCE_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + STATICLIB_SUFFIXES + ASSEMBLY_SUFFIXES) + exit(0) newargs += CC_ADDITIONAL_ARGS @@ -495,6 +637,8 @@ try: else: final_suffix = '' + assert not (Compression.on and final_suffix != 'html'), 'Compression only works when generating HTML' + # Apply optimization level settings shared.Settings.apply_opt_level(opt_level, noisy=True) @@ -513,18 +657,18 @@ try: for input_file in input_files: if input_file.endswith(SOURCE_SUFFIXES): if DEBUG: print >> sys.stderr, 'emcc: compiling source file: ', input_file - output_file = in_temp(unsuffixed_basename(input_file) + '.o') + output_file = in_temp(unsuffixed_uniquename(input_file) + '.o') temp_files.append(output_file) args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file] if DEBUG: print >> sys.stderr, "emcc running:", call, ' '.join(args) - Popen([call] + args).communicate() # let compiler frontend print directly, so colors are saved (PIPE kills that) + execute([call] + args) # let compiler frontend print directly, so colors are saved (PIPE kills that) if not os.path.exists(output_file): print >> sys.stderr, 'emcc: compiler frontend failed to generate LLVM bitcode, halting' sys.exit(1) else: # bitcode if input_file.endswith(BITCODE_SUFFIXES): if DEBUG: print >> sys.stderr, 'emcc: copying bitcode file: ', input_file - temp_file = in_temp(unsuffixed_basename(input_file) + '.o') + temp_file = in_temp(unsuffixed_uniquename(input_file) + '.o') shutil.copyfile(input_file, temp_file) temp_files.append(temp_file) elif input_file.endswith(DYNAMICLIB_SUFFIXES) or shared.Building.is_ar(input_file): @@ -537,7 +681,7 @@ try: # Note that by assembling the .ll file, then disassembling it later, we will # remove annotations which is a good thing for compilation time if DEBUG: print >> sys.stderr, 'emcc: assembling assembly file: ', input_file - temp_file = in_temp(unsuffixed_basename(input_file) + '.o') + temp_file = in_temp(unsuffixed_uniquename(input_file) + '.o') shared.Building.llvm_as(input_file, temp_file) temp_files.append(temp_file) @@ -549,10 +693,10 @@ try: print >> sys.stderr, 'emcc: warning: -Ox flags ignored, since not generating JavaScript' if not specified_target: for input_file in input_files: - shutil.move(in_temp(unsuffixed_basename(input_file) + '.o'), unsuffixed_basename(input_file) + '.' + final_suffix) + shutil.move(in_temp(unsuffixed_uniquename(input_file) + '.o'), unsuffixed_basename(input_file) + '.' + final_suffix) else: if len(input_files) == 1: - shutil.move(in_temp(unsuffixed_basename(input_files[0]) + '.o'), specified_target) + shutil.move(in_temp(unsuffixed_uniquename(input_files[0]) + '.o'), specified_target) else: assert not has_dash_c, 'fatal error: cannot specify -o with -c with multiple files' + str(sys.argv) # We have a specified target (-o <target>), which is not JavaScript or HTML, and @@ -560,7 +704,7 @@ try: ld_args = temp_files + ['-b', specified_target] #[arg.split('-Wl,')[1] for arg in filter(lambda arg: arg.startswith('-Wl,'), sys.argv)] if DEBUG: print >> sys.stderr, 'emcc: link: ' + str(ld_args) - Popen([shared.LLVM_LD, '-disable-opt'] + ld_args).communicate() + execute([shared.LLVM_LD, '-disable-opt'] + ld_args) exit(0) ## Continue on to create JavaScript @@ -578,9 +722,9 @@ try: # dlmalloc def create_dlmalloc(): if DEBUG: print >> sys.stderr, 'emcc: building dlmalloc for cache' - Popen([shared.EMCC, shared.path_from_root('system', 'lib', 'dlmalloc.c'), '-g', '-o', in_temp('dlmalloc.o')], stdout=stdout, stderr=stderr).communicate() + execute(['python', shared.EMCC, shared.path_from_root('system', 'lib', 'dlmalloc.c'), '-g', '-o', in_temp('dlmalloc.o')], stdout=stdout, stderr=stderr) # we include the libc++ new stuff here, so that the common case of using just new/delete is quick to link - Popen([shared.EMXX, shared.path_from_root('system', 'lib', 'libcxx', 'new.cpp'), '-g', '-o', in_temp('new.o')], stdout=stdout, stderr=stderr).communicate() + execute(['python', shared.EMXX, shared.path_from_root('system', 'lib', 'libcxx', 'new.cpp'), '-g', '-o', in_temp('new.o')], stdout=stdout, stderr=stderr) shared.Building.link([in_temp('dlmalloc.o'), in_temp('new.o')], in_temp('dlmalloc_full.o')) return in_temp('dlmalloc_full.o') def fix_dlmalloc(): @@ -679,7 +823,7 @@ try: shared.Building.llvm_opt(in_temp(target_basename + '.bc'), llvm_opts) if DEBUG: save_intermediate('opt', 'bc') # Do LTO in a separate pass to work around LLVM bug XXX (see failure e.g. in cubescript) - if shared.Building.can_use_unsafe_opts() and shared.Building.can_build_standalone(): + if llvm_lto and shared.Building.can_use_unsafe_opts() and shared.Building.can_build_standalone(): lto_opts = [] if not shared.Building.can_inline(): lto_opts.append('-disable-inlining') lto_opts.append('-std-link-opts') @@ -702,25 +846,221 @@ try: if AUTODEBUG: if DEBUG: print >> sys.stderr, 'emcc: autodebug' - Popen(['python', shared.AUTODEBUGGER, final, final + '.ad.ll']).communicate()[0] + execute(['python', shared.AUTODEBUGGER, final, final + '.ad.ll']) final += '.ad.ll' if DEBUG: save_intermediate('autodebug', 'll') # Emscripten if DEBUG: print >> sys.stderr, 'emcc: LLVM => JS' - final = shared.Building.emscripten(final, append_ext=False) + extra_args = [] if not js_libraries else ['--libraries', ','.join(map(os.path.abspath, js_libraries))] + final = shared.Building.emscripten(final, append_ext=False, extra_args=extra_args) if DEBUG: save_intermediate('original') - # Embed files - if len(embed_files) > 0: - if DEBUG: print >> sys.stderr, 'emcc: embedding files' - src = open(final).read().replace( - '// {{PRE_RUN_ADDITIONS}}', - '\n'.join(map(lambda embed_file: "FS.createDataFile('/', '%s', %s, true, false);" % (os.path.basename(embed_file), str(map(ord, open(embed_file, 'rb').read()))), embed_files)) - ) - final += '.ef.js' + # Embed and preload files + if len(data_files) > 0: + if DEBUG: print >> sys.stderr, 'emcc: setting up files' + code = '' + + if final_suffix == 'html': + code += ''' + var BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : (typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : console.log("warning: cannot build blobs")); + var URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : console.log("warning: cannot create object URLs"); + var hasBlobConstructor; + try { + new Blob(); + hasBlobConstructor = true; + } catch(e) { + hasBlobConstructor = false; + console.log("warning: no blob constructor, cannot create blobs with mimetypes"); + } +''' + + code += 'var preloadedImages = {}; // maps url to image data\n' + code += 'var preloadedAudios = {}; // maps url to audio data\n' + + # Expand directories into individual files + def add(mode, dirname, names): + for name in names: + fullname = os.path.join(dirname, name) + if not os.path.isdir(fullname): + data_files.append({ 'name': fullname, 'mode': mode }) + + for file_ in data_files: + if os.path.isdir(file_['name']): + os.path.walk(file_['name'], add, file_['mode']) + data_files = filter(lambda file_: not os.path.isdir(file_['name']), data_files) + + for file_ in data_files: + file_['name'] = file_['name'].replace(os.path.sep, '/') + file_['net_name'] = file_['name'] + + data_target = unsuffixed(target) + '.data' + + # Set up folders + partial_dirs = [] + for file_ in data_files: + dirname = os.path.dirname(file_['name']) + if dirname != '' and dirname != '/': + parts = dirname.split('/') + for i in range(len(parts)): + partial = '/'.join(parts[:i+1]) + if partial not in partial_dirs: + code += '''FS.createFolder('/%s', '%s', true, false);\n''' % ('/'.join(parts[:i]), parts[i]) + partial_dirs.append(partial) + + if final_suffix == 'html': + # Bundle all datafiles into one archive. Avoids doing lots of simultaneous XHRs which has overhead. + data = open(data_target, 'wb') + start = 0 + for file_ in data_files: + file_['data_start'] = start + curr = open(file_['name'], 'rb').read() + file_['data_end'] = start + len(curr) + start += len(curr) + data.write(curr) + data.close() + if Compression.on: + Compression.compress(data_target) + + # Data requests - for getting a block of data out of the big archive - have a similar API to XHRs + code += ''' + function DataRequest() {} + DataRequest.prototype = { + requests: {}, + open: function(mode, name) { + this.requests[name] = this; + }, + send: function() {} + }; + ''' + + counter = 0 + for file_ in data_files: + filename = file_['name'] + if file_['mode'] == 'embed': + # Embed + code += '''FS.createDataFile('/', '%s', %s, true, true);\n''' % (os.path.basename(filename), str(map(ord, open(filename, 'rb').read()))) + elif file_['mode'] == 'preload': + # Preload + assert final_suffix == 'html', 'Can only preload files when generating HTML' + + varname = 'filePreload%d' % counter + counter += 1 + image = filename.endswith(IMAGE_SUFFIXES) + audio = filename.endswith(AUDIO_SUFFIXES) + + if image: + finish = ''' + var bb = new BlobBuilder(); + bb.append(byteArray.buffer); + var b = bb.getBlob(); + var url = URLObject.createObjectURL(b); + var img = new Image(); + img.onload = function() { + assert(img.complete, 'Image %(filename)s could not be decoded'); + var canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + preloadedImages['%(filename)s'] = canvas; + URLObject.revokeObjectURL(url); + removeRunDependency(); + }; + img.onerror = function(event) { + console.log('Image %(filename)s could not be decoded'); + }; + img.src = url; +''' % { 'filename': filename } + elif audio: + # Need actual blob constructor here, to set the mimetype or else audios fail to decode + finish = ''' + if (hasBlobConstructor) { + var b = new Blob([byteArray.buffer], { type: '%(mimetype)s' }); + var url = URLObject.createObjectURL(b); // XXX we never revoke this! + var audio = new Audio(); + audio['oncanplaythrough'] = function() { // XXX string for closure + audio['oncanplaythrough'] = null; + preloadedAudios['%(filename)s'] = audio; + removeRunDependency(); + }; + audio.onerror = function(event) { + console.log('Audio %(filename)s could not be decoded'); + }; + audio.src = url; + } else { + preloadedAudios['%(filename)s'] = new Audio(); // empty shim + removeRunDependency(); + } +''' % { 'filename': filename, 'mimetype': AUDIO_MIMETYPES[suffix(filename)] } + else: + finish = 'removeRunDependency();\n' + + code += ''' + var %(varname)s = new %(request)s(); + %(varname)s.open('GET', '%(netname)s', true); + %(varname)s.responseType = 'arraybuffer'; + %(varname)s.onload = function() { + var arrayBuffer = %(varname)s.response; + assert(arrayBuffer, 'Loading file %(filename)s failed.'); + var byteArray = arrayBuffer.byteLength ? new Uint8Array(arrayBuffer) : arrayBuffer; + FS.createDataFile('/%(dirname)s', '%(basename)s', byteArray, true, true); + %(finish)s + }; + addRunDependency(); + %(varname)s.send(null); +''' % { + 'request': 'DataRequest', # In the past we also supported XHRs here + 'varname': varname, + 'filename': filename, + 'netname': file_['net_name'], + 'dirname': os.path.dirname(filename), + 'basename': os.path.basename(filename), + 'finish': finish + } + else: + assert 0 + + if final_suffix == 'html': + # Get the big archive and split it up + use_data = '' + for file_ in data_files: + if file_['mode'] == 'preload': + use_data += ''' + curr = DataRequest.prototype.requests['%s']; + curr.response = byteArray.subarray(%d,%d); + curr.onload(); + ''' % (file_['name'], file_['data_start'], file_['data_end']) + use_data += ' removeRunDependency();\n' + + if Compression.on: + use_data = ''' + Module["decompress"](byteArray, function(decompressed) { + byteArray = new Uint8Array(decompressed); + %s + }); + ''' % use_data + + code += ''' + var dataFile = new XMLHttpRequest(); + dataFile.open('GET', '%s', true); + dataFile.responseType = 'arraybuffer'; + dataFile.onload = function() { + var arrayBuffer = dataFile.response; + assert(arrayBuffer, 'Loading data file failed.'); + var byteArray = new Uint8Array(arrayBuffer); + var curr; + %s + }; + addRunDependency(); + dataFile.send(null); + if (Module['setStatus']) Module['setStatus']('Downloading...'); + ''' % (Compression.compressed_name(data_target) if Compression.on else data_target, use_data) + + src = open(final).read().replace('// {{PRE_RUN_ADDITIONS}}', code) + final += '.files.js' open(final, 'w').write(src) - if DEBUG: save_intermediate('embedded_files') + if DEBUG: save_intermediate('files') # Apply pre and postjs files if pre_js or post_js: @@ -734,8 +1074,9 @@ try: if js_transform: shutil.copyfile(final, final + '.tr.js') final += '.tr.js' + posix = True if not shared.WINDOWS else False if DEBUG: print >> sys.stderr, 'emcc: applying transform: %s' % js_transform - Popen(js_transform.split(' ') + [os.path.abspath(final)]).communicate() + execute(shlex.split(js_transform, posix=posix) + [os.path.abspath(final)]) if DEBUG: save_intermediate('transformed') # It is useful to run several js optimizer passes together, to save on unneeded unparsing/reparsing @@ -790,7 +1131,7 @@ try: if DEBUG: print >> sys.stderr, 'emcc: running post-closure post-opts' js_optimizer_queue += ['simplifyExpressionsPost'] - if compress_whitespace: + if minify_whitespace: js_optimizer_queue += ['compress'] flush_js_optimizer_queue() @@ -800,7 +1141,71 @@ try: if DEBUG: print >> sys.stderr, 'emcc: generating HTML' shell = open(shell_path).read() html = open(target, 'w') - html.write(shell.replace('{{{ SCRIPT_CODE }}}', open(final).read())) + if not Compression.on: + html.write(shell.replace('{{{ SCRIPT_CODE }}}', open(final).read())) + else: + # Compress the main code + js_target = unsuffixed(target) + '.js' + shutil.move(final, js_target) + Compression.compress(js_target) + + # Run the decompressor in a worker, and add code to + # 1. download the compressed file + # 2. decompress to a typed array + # 3. convert to a string of source code + # 4. insert a script element with that source code (more effective than eval) + decoding = ''' + var decompressWorker = new Worker('decompress.js'); + var decompressCallbacks = []; + var decompressions = 0; + Module["decompress"] = function(data, callback) { + var id = decompressCallbacks.length; + decompressCallbacks.push(callback); + decompressWorker.postMessage({ data: data, id: id }); + if (Module['setStatus']) { + decompressions++; + Module['setStatus']('Decompressing...'); + } + }; + decompressWorker.onmessage = function(event) { + decompressCallbacks[event.data.id](event.data.data); + decompressCallbacks[event.data.id] = null; + if (Module['setStatus']) { + decompressions--; + if (decompressions == 0) { + Module['setStatus'](''); + } + } + }; + var compiledCodeXHR = new XMLHttpRequest(); + compiledCodeXHR.open('GET', '%s', true); + compiledCodeXHR.responseType = 'arraybuffer'; + compiledCodeXHR.onload = function() { + var arrayBuffer = compiledCodeXHR.response; + if (!arrayBuffer) throw('Loading compressed code failed.'); + var byteArray = new Uint8Array(arrayBuffer); + Module.decompress(byteArray, function(decompressed) { + var source = Array.prototype.slice.apply(decompressed).map(function(x) { return String.fromCharCode(x) }).join(''); // createObjectURL instead? + var scriptTag = document.createElement('script'); + scriptTag.setAttribute('type', 'text/javascript'); + scriptTag.innerHTML = source; + document.body.appendChild(scriptTag); + }); + }; + compiledCodeXHR.send(null); +''' % Compression.compressed_name(js_target) + html.write(shell.replace('{{{ SCRIPT_CODE }}}', decoding)) + + # Add decompressor with web worker glue code + decompressor = open('decompress.js', 'w') + decompressor.write(open(Compression.decoder).read()) + decompressor.write(''' + onmessage = function(event) { + postMessage({ data: %s(event.data.data), id: event.data.id }); + }; +''' % Compression.js_name) + decompressor.close() + html.close() else: # copy final JS to output @@ -9,7 +9,7 @@ This script acts as a frontend replacement for the ld linker. See emcc. We could use the compiler code for this, but here we want to be careful to use all the linker flags we have been passed, sending them to ld. ''' -import os, sys +import os, subprocess, sys from tools import shared DEBUG = os.environ.get('EMCC_DEBUG') @@ -56,5 +56,5 @@ if target: newargs.append('-o=' + actual_target) if DEBUG: print >> sys.stderr, "emld running:", call, ' '.join(newargs) -os.execvp(call, [call] + newargs) +subprocess.call([call] + newargs) diff --git a/emscripten.py b/emscripten.py index 5674c33a..45c9f418 100755 --- a/emscripten.py +++ b/emscripten.py @@ -35,7 +35,7 @@ def path_from_root(*pathelems): temp_files = shared.TempFiles() -def emscript(infile, settings, outfile): +def emscript(infile, settings, outfile, libraries=[]): """Runs the emscripten LLVM-to-JS compiler. Args: @@ -49,7 +49,7 @@ def emscript(infile, settings, outfile): s.write(settings) s.close() compiler = path_from_root('src', 'compiler.js') - shared.run_js(compiler, shared.COMPILER_ENGINE, [settings_file, infile], stdout=outfile, cwd=path_from_root('src')) + shared.run_js(compiler, shared.COMPILER_ENGINE, [settings_file, infile] + libraries, stdout=outfile, cwd=path_from_root('src')) outfile.close() @@ -123,8 +123,11 @@ def main(args): #print >> sys.stderr, 'new defs:', str(defines).replace(',', ',\n '), '\n\n' settings.setdefault('C_DEFINES', {}).update(defines) + # libraries + libraries = args.libraries[0].split(',') if len(args.libraries) > 0 else [] + # Compile the assembly to Javascript. - emscript(args.infile, json.dumps(settings), args.outfile) + emscript(args.infile, json.dumps(settings), args.outfile, libraries) if __name__ == '__main__': parser = optparse.OptionParser( @@ -136,6 +139,10 @@ if __name__ == '__main__': default=[], action='append', help='System headers (comma separated) whose #defines should be exposed to the compiled code.') + parser.add_option('-L', '--libraries', + default=[], + action='append', + help='Library files (comma separated) to use in addition to those in emscripten src/library_*.') parser.add_option('-o', '--outfile', default=sys.stdout, help='Where to write the output; defaults to stdout.') diff --git a/settings.py b/settings.py index e4c541f3..48eaa9ab 100644 --- a/settings.py +++ b/settings.py @@ -10,8 +10,6 @@ NODE_JS = 'node' SPIDERMONKEY_ENGINE = [os.path.expanduser('~/Dev/mozilla-central/js/src/js'), '-m', '-n'] V8_ENGINE = os.path.expanduser('~/Dev/v8/d8') -CLOSURE_COMPILER = os.path.expanduser('~/Dev/closure-compiler/compiler.jar') # optional (needed for the benchmarks) - TEMP_DIR = '/tmp' diff --git a/src/compiler.js b/src/compiler.js index 134ac5bd..4442e38e 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -8,7 +8,8 @@ try { } catch(e) {} -// The environment setup code appears here, in shell.js, in js_optimizer.js and in tests/hello_world.js because it can't be shared. Keep them in sync! +// The environment setup code appears here, in js_optimizer.js and in tests/hello_world.js because it can't be shared. Keep them in sync! +// It also appears, in modified form, in shell.js. // *** Environment setup code *** var arguments_ = []; @@ -28,11 +29,14 @@ if (ENVIRONMENT_IS_NODE) { }; var nodeFS = require('fs'); + var nodePath = require('path'); read = function(filename) { + filename = nodePath['normalize'](filename); var ret = nodeFS['readFileSync'](filename).toString(); - if (!ret && filename[0] != '/') { - filename = __dirname.split('/').slice(0, -1).join('/') + '/src/' + filename; + // The path is absolute if the normalized version is the same as the resolved. + if (!ret && filename != nodePath['resolve'](filename)) { + filename = path.join(__dirname, '..', 'src', filename); ret = nodeFS['readFileSync'](filename).toString(); } return ret; @@ -50,9 +54,9 @@ if (ENVIRONMENT_IS_NODE) { this['read'] = function(f) { snarf(f) }; } - if (!this['arguments']) { + if (typeof scriptArgs != 'undefined') { arguments_ = scriptArgs; - } else { + } else if (typeof arguments != 'undefined') { arguments_ = arguments; } @@ -110,6 +114,7 @@ load('settings.js'); var settings_file = arguments_[0]; var ll_file = arguments_[1]; +additionalLibraries = Array.prototype.slice.call(arguments_, 2); if (settings_file) { var settings = JSON.parse(read(settings_file)); @@ -118,6 +123,7 @@ if (settings_file) { } } + if (CORRECT_SIGNS >= 2) { CORRECT_SIGNS_LINES = set(CORRECT_SIGNS_LINES); // for fast checking } diff --git a/src/gl-matrix.js b/src/gl-matrix.js new file mode 100644 index 00000000..a21cd431 --- /dev/null +++ b/src/gl-matrix.js @@ -0,0 +1,1952 @@ +(function() { + +/** + * @fileoverview gl-matrix - High performance matrix and vector operations for WebGL + * @author Brandon Jones + * @version 1.2.4 + */ + +// Modifed for emscripten: Global scoping etc. + +/* + * Copyright (c) 2011 Brandon Jones + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + */ + + +/** + * @class 3 Dimensional Vector + * @name vec3 + */ +var vec3 = {}; + +/** + * @class 3x3 Matrix + * @name mat3 + */ +var mat3 = {}; + +/** + * @class 4x4 Matrix + * @name mat4 + */ +var mat4 = {}; + +/** + * @class Quaternion + * @name quat4 + */ +var quat4 = {}; + +var MatrixArray = Float32Array; + +/* + * vec3 + */ + +/** + * Creates a new instance of a vec3 using the default array type + * Any javascript array-like objects containing at least 3 numeric elements can serve as a vec3 + * + * @param {vec3} [vec] vec3 containing values to initialize with + * + * @returns {vec3} New vec3 + */ +vec3.create = function (vec) { + var dest = new MatrixArray(3); + + if (vec) { + dest[0] = vec[0]; + dest[1] = vec[1]; + dest[2] = vec[2]; + } else { + dest[0] = dest[1] = dest[2] = 0; + } + + return dest; +}; + +/** + * Copies the values of one vec3 to another + * + * @param {vec3} vec vec3 containing values to copy + * @param {vec3} dest vec3 receiving copied values + * + * @returns {vec3} dest + */ +vec3.set = function (vec, dest) { + dest[0] = vec[0]; + dest[1] = vec[1]; + dest[2] = vec[2]; + + return dest; +}; + +/** + * Performs a vector addition + * + * @param {vec3} vec First operand + * @param {vec3} vec2 Second operand + * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec + * + * @returns {vec3} dest if specified, vec otherwise + */ +vec3.add = function (vec, vec2, dest) { + if (!dest || vec === dest) { + vec[0] += vec2[0]; + vec[1] += vec2[1]; + vec[2] += vec2[2]; + return vec; + } + + dest[0] = vec[0] + vec2[0]; + dest[1] = vec[1] + vec2[1]; + dest[2] = vec[2] + vec2[2]; + return dest; +}; + +/** + * Performs a vector subtraction + * + * @param {vec3} vec First operand + * @param {vec3} vec2 Second operand + * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec + * + * @returns {vec3} dest if specified, vec otherwise + */ +vec3.subtract = function (vec, vec2, dest) { + if (!dest || vec === dest) { + vec[0] -= vec2[0]; + vec[1] -= vec2[1]; + vec[2] -= vec2[2]; + return vec; + } + + dest[0] = vec[0] - vec2[0]; + dest[1] = vec[1] - vec2[1]; + dest[2] = vec[2] - vec2[2]; + return dest; +}; + +/** + * Performs a vector multiplication + * + * @param {vec3} vec First operand + * @param {vec3} vec2 Second operand + * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec + * + * @returns {vec3} dest if specified, vec otherwise + */ +vec3.multiply = function (vec, vec2, dest) { + if (!dest || vec === dest) { + vec[0] *= vec2[0]; + vec[1] *= vec2[1]; + vec[2] *= vec2[2]; + return vec; + } + + dest[0] = vec[0] * vec2[0]; + dest[1] = vec[1] * vec2[1]; + dest[2] = vec[2] * vec2[2]; + return dest; +}; + +/** + * Negates the components of a vec3 + * + * @param {vec3} vec vec3 to negate + * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec + * + * @returns {vec3} dest if specified, vec otherwise + */ +vec3.negate = function (vec, dest) { + if (!dest) { dest = vec; } + + dest[0] = -vec[0]; + dest[1] = -vec[1]; + dest[2] = -vec[2]; + return dest; +}; + +/** + * Multiplies the components of a vec3 by a scalar value + * + * @param {vec3} vec vec3 to scale + * @param {number} val Value to scale by + * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec + * + * @returns {vec3} dest if specified, vec otherwise + */ +vec3.scale = function (vec, val, dest) { + if (!dest || vec === dest) { + vec[0] *= val; + vec[1] *= val; + vec[2] *= val; + return vec; + } + + dest[0] = vec[0] * val; + dest[1] = vec[1] * val; + dest[2] = vec[2] * val; + return dest; +}; + +/** + * Generates a unit vector of the same direction as the provided vec3 + * If vector length is 0, returns [0, 0, 0] + * + * @param {vec3} vec vec3 to normalize + * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec + * + * @returns {vec3} dest if specified, vec otherwise + */ +vec3.normalize = function (vec, dest) { + if (!dest) { dest = vec; } + + var x = vec[0], y = vec[1], z = vec[2], + len = Math.sqrt(x * x + y * y + z * z); + + if (!len) { + dest[0] = 0; + dest[1] = 0; + dest[2] = 0; + return dest; + } else if (len === 1) { + dest[0] = x; + dest[1] = y; + dest[2] = z; + return dest; + } + + len = 1 / len; + dest[0] = x * len; + dest[1] = y * len; + dest[2] = z * len; + return dest; +}; + +/** + * Generates the cross product of two vec3s + * + * @param {vec3} vec First operand + * @param {vec3} vec2 Second operand + * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec + * + * @returns {vec3} dest if specified, vec otherwise + */ +vec3.cross = function (vec, vec2, dest) { + if (!dest) { dest = vec; } + + var x = vec[0], y = vec[1], z = vec[2], + x2 = vec2[0], y2 = vec2[1], z2 = vec2[2]; + + dest[0] = y * z2 - z * y2; + dest[1] = z * x2 - x * z2; + dest[2] = x * y2 - y * x2; + return dest; +}; + +/** + * Caclulates the length of a vec3 + * + * @param {vec3} vec vec3 to calculate length of + * + * @returns {number} Length of vec + */ +vec3.length = function (vec) { + var x = vec[0], y = vec[1], z = vec[2]; + return Math.sqrt(x * x + y * y + z * z); +}; + +/** + * Caclulates the dot product of two vec3s + * + * @param {vec3} vec First operand + * @param {vec3} vec2 Second operand + * + * @returns {number} Dot product of vec and vec2 + */ +vec3.dot = function (vec, vec2) { + return vec[0] * vec2[0] + vec[1] * vec2[1] + vec[2] * vec2[2]; +}; + +/** + * Generates a unit vector pointing from one vector to another + * + * @param {vec3} vec Origin vec3 + * @param {vec3} vec2 vec3 to point to + * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec + * + * @returns {vec3} dest if specified, vec otherwise + */ +vec3.direction = function (vec, vec2, dest) { + if (!dest) { dest = vec; } + + var x = vec[0] - vec2[0], + y = vec[1] - vec2[1], + z = vec[2] - vec2[2], + len = Math.sqrt(x * x + y * y + z * z); + + if (!len) { + dest[0] = 0; + dest[1] = 0; + dest[2] = 0; + return dest; + } + + len = 1 / len; + dest[0] = x * len; + dest[1] = y * len; + dest[2] = z * len; + return dest; +}; + +/** + * Performs a linear interpolation between two vec3 + * + * @param {vec3} vec First vector + * @param {vec3} vec2 Second vector + * @param {number} lerp Interpolation amount between the two inputs + * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec + * + * @returns {vec3} dest if specified, vec otherwise + */ +vec3.lerp = function (vec, vec2, lerp, dest) { + if (!dest) { dest = vec; } + + dest[0] = vec[0] + lerp * (vec2[0] - vec[0]); + dest[1] = vec[1] + lerp * (vec2[1] - vec[1]); + dest[2] = vec[2] + lerp * (vec2[2] - vec[2]); + + return dest; +}; + +/** + * Calculates the euclidian distance between two vec3 + * + * Params: + * @param {vec3} vec First vector + * @param {vec3} vec2 Second vector + * + * @returns {number} Distance between vec and vec2 + */ +vec3.dist = function (vec, vec2) { + var x = vec2[0] - vec[0], + y = vec2[1] - vec[1], + z = vec2[2] - vec[2]; + + return Math.sqrt(x*x + y*y + z*z); +}; + +/** + * Projects the specified vec3 from screen space into object space + * Based on the <a href="http://webcvs.freedesktop.org/mesa/Mesa/src/glu/mesa/project.c?revision=1.4&view=markup">Mesa gluUnProject implementation</a> + * + * @param {vec3} vec Screen-space vector to project + * @param {mat4} view View matrix + * @param {mat4} proj Projection matrix + * @param {vec4} viewport Viewport as given to gl.viewport [x, y, width, height] + * @param {vec3} [dest] vec3 receiving unprojected result. If not specified result is written to vec + * + * @returns {vec3} dest if specified, vec otherwise + */ +vec3.unproject = function (vec, view, proj, viewport, dest) { + if (!dest) { dest = vec; } + + var m = mat4.create(); + var v = new MatrixArray(4); + + v[0] = (vec[0] - viewport[0]) * 2.0 / viewport[2] - 1.0; + v[1] = (vec[1] - viewport[1]) * 2.0 / viewport[3] - 1.0; + v[2] = 2.0 * vec[2] - 1.0; + v[3] = 1.0; + + mat4.multiply(proj, view, m); + if(!mat4.inverse(m)) { return null; } + + mat4.multiplyVec4(m, v); + if(v[3] === 0.0) { return null; } + + dest[0] = v[0] / v[3]; + dest[1] = v[1] / v[3]; + dest[2] = v[2] / v[3]; + + return dest; +}; + +/** + * Returns a string representation of a vector + * + * @param {vec3} vec Vector to represent as a string + * + * @returns {string} String representation of vec + */ +vec3.str = function (vec) { + return '[' + vec[0] + ', ' + vec[1] + ', ' + vec[2] + ']'; +}; + +/* + * mat3 + */ + +/** + * Creates a new instance of a mat3 using the default array type + * Any javascript array-like object containing at least 9 numeric elements can serve as a mat3 + * + * @param {mat3} [mat] mat3 containing values to initialize with + * + * @returns {mat3} New mat3 + */ +mat3.create = function (mat) { + var dest = new MatrixArray(9); + + if (mat) { + dest[0] = mat[0]; + dest[1] = mat[1]; + dest[2] = mat[2]; + dest[3] = mat[3]; + dest[4] = mat[4]; + dest[5] = mat[5]; + dest[6] = mat[6]; + dest[7] = mat[7]; + dest[8] = mat[8]; + } + + return dest; +}; + +/** + * Copies the values of one mat3 to another + * + * @param {mat3} mat mat3 containing values to copy + * @param {mat3} dest mat3 receiving copied values + * + * @returns {mat3} dest + */ +mat3.set = function (mat, dest) { + dest[0] = mat[0]; + dest[1] = mat[1]; + dest[2] = mat[2]; + dest[3] = mat[3]; + dest[4] = mat[4]; + dest[5] = mat[5]; + dest[6] = mat[6]; + dest[7] = mat[7]; + dest[8] = mat[8]; + return dest; +}; + +/** + * Sets a mat3 to an identity matrix + * + * @param {mat3} dest mat3 to set + * + * @returns dest if specified, otherwise a new mat3 + */ +mat3.identity = function (dest) { + if (!dest) { dest = mat3.create(); } + dest[0] = 1; + dest[1] = 0; + dest[2] = 0; + dest[3] = 0; + dest[4] = 1; + dest[5] = 0; + dest[6] = 0; + dest[7] = 0; + dest[8] = 1; + return dest; +}; + +/** + * Transposes a mat3 (flips the values over the diagonal) + * + * Params: + * @param {mat3} mat mat3 to transpose + * @param {mat3} [dest] mat3 receiving transposed values. If not specified result is written to mat + * + * @returns {mat3} dest is specified, mat otherwise + */ +mat3.transpose = function (mat, dest) { + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (!dest || mat === dest) { + var a01 = mat[1], a02 = mat[2], + a12 = mat[5]; + + mat[1] = mat[3]; + mat[2] = mat[6]; + mat[3] = a01; + mat[5] = mat[7]; + mat[6] = a02; + mat[7] = a12; + return mat; + } + + dest[0] = mat[0]; + dest[1] = mat[3]; + dest[2] = mat[6]; + dest[3] = mat[1]; + dest[4] = mat[4]; + dest[5] = mat[7]; + dest[6] = mat[2]; + dest[7] = mat[5]; + dest[8] = mat[8]; + return dest; +}; + +/** + * Copies the elements of a mat3 into the upper 3x3 elements of a mat4 + * + * @param {mat3} mat mat3 containing values to copy + * @param {mat4} [dest] mat4 receiving copied values + * + * @returns {mat4} dest if specified, a new mat4 otherwise + */ +mat3.toMat4 = function (mat, dest) { + if (!dest) { dest = mat4.create(); } + + dest[15] = 1; + dest[14] = 0; + dest[13] = 0; + dest[12] = 0; + + dest[11] = 0; + dest[10] = mat[8]; + dest[9] = mat[7]; + dest[8] = mat[6]; + + dest[7] = 0; + dest[6] = mat[5]; + dest[5] = mat[4]; + dest[4] = mat[3]; + + dest[3] = 0; + dest[2] = mat[2]; + dest[1] = mat[1]; + dest[0] = mat[0]; + + return dest; +}; + +/** + * Returns a string representation of a mat3 + * + * @param {mat3} mat mat3 to represent as a string + * + * @param {string} String representation of mat + */ +mat3.str = function (mat) { + return '[' + mat[0] + ', ' + mat[1] + ', ' + mat[2] + + ', ' + mat[3] + ', ' + mat[4] + ', ' + mat[5] + + ', ' + mat[6] + ', ' + mat[7] + ', ' + mat[8] + ']'; +}; + +/* + * mat4 + */ + +/** + * Creates a new instance of a mat4 using the default array type + * Any javascript array-like object containing at least 16 numeric elements can serve as a mat4 + * + * @param {mat4} [mat] mat4 containing values to initialize with + * + * @returns {mat4} New mat4 + */ +mat4.create = function (mat) { + var dest = new MatrixArray(16); + + if (mat) { + dest[0] = mat[0]; + dest[1] = mat[1]; + dest[2] = mat[2]; + dest[3] = mat[3]; + dest[4] = mat[4]; + dest[5] = mat[5]; + dest[6] = mat[6]; + dest[7] = mat[7]; + dest[8] = mat[8]; + dest[9] = mat[9]; + dest[10] = mat[10]; + dest[11] = mat[11]; + dest[12] = mat[12]; + dest[13] = mat[13]; + dest[14] = mat[14]; + dest[15] = mat[15]; + } + + return dest; +}; + +/** + * Copies the values of one mat4 to another + * + * @param {mat4} mat mat4 containing values to copy + * @param {mat4} dest mat4 receiving copied values + * + * @returns {mat4} dest + */ +mat4.set = function (mat, dest) { + dest[0] = mat[0]; + dest[1] = mat[1]; + dest[2] = mat[2]; + dest[3] = mat[3]; + dest[4] = mat[4]; + dest[5] = mat[5]; + dest[6] = mat[6]; + dest[7] = mat[7]; + dest[8] = mat[8]; + dest[9] = mat[9]; + dest[10] = mat[10]; + dest[11] = mat[11]; + dest[12] = mat[12]; + dest[13] = mat[13]; + dest[14] = mat[14]; + dest[15] = mat[15]; + return dest; +}; + +/** + * Sets a mat4 to an identity matrix + * + * @param {mat4} dest mat4 to set + * + * @returns {mat4} dest + */ +mat4.identity = function (dest) { + if (!dest) { dest = mat4.create(); } + dest[0] = 1; + dest[1] = 0; + dest[2] = 0; + dest[3] = 0; + dest[4] = 0; + dest[5] = 1; + dest[6] = 0; + dest[7] = 0; + dest[8] = 0; + dest[9] = 0; + dest[10] = 1; + dest[11] = 0; + dest[12] = 0; + dest[13] = 0; + dest[14] = 0; + dest[15] = 1; + return dest; +}; + +/** + * Transposes a mat4 (flips the values over the diagonal) + * + * @param {mat4} mat mat4 to transpose + * @param {mat4} [dest] mat4 receiving transposed values. If not specified result is written to mat + * + * @param {mat4} dest is specified, mat otherwise + */ +mat4.transpose = function (mat, dest) { + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (!dest || mat === dest) { + var a01 = mat[1], a02 = mat[2], a03 = mat[3], + a12 = mat[6], a13 = mat[7], + a23 = mat[11]; + + mat[1] = mat[4]; + mat[2] = mat[8]; + mat[3] = mat[12]; + mat[4] = a01; + mat[6] = mat[9]; + mat[7] = mat[13]; + mat[8] = a02; + mat[9] = a12; + mat[11] = mat[14]; + mat[12] = a03; + mat[13] = a13; + mat[14] = a23; + return mat; + } + + dest[0] = mat[0]; + dest[1] = mat[4]; + dest[2] = mat[8]; + dest[3] = mat[12]; + dest[4] = mat[1]; + dest[5] = mat[5]; + dest[6] = mat[9]; + dest[7] = mat[13]; + dest[8] = mat[2]; + dest[9] = mat[6]; + dest[10] = mat[10]; + dest[11] = mat[14]; + dest[12] = mat[3]; + dest[13] = mat[7]; + dest[14] = mat[11]; + dest[15] = mat[15]; + return dest; +}; + +/** + * Calculates the determinant of a mat4 + * + * @param {mat4} mat mat4 to calculate determinant of + * + * @returns {number} determinant of mat + */ +mat4.determinant = function (mat) { + // Cache the matrix values (makes for huge speed increases!) + var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3], + a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7], + a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11], + a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; + + return (a30 * a21 * a12 * a03 - a20 * a31 * a12 * a03 - a30 * a11 * a22 * a03 + a10 * a31 * a22 * a03 + + a20 * a11 * a32 * a03 - a10 * a21 * a32 * a03 - a30 * a21 * a02 * a13 + a20 * a31 * a02 * a13 + + a30 * a01 * a22 * a13 - a00 * a31 * a22 * a13 - a20 * a01 * a32 * a13 + a00 * a21 * a32 * a13 + + a30 * a11 * a02 * a23 - a10 * a31 * a02 * a23 - a30 * a01 * a12 * a23 + a00 * a31 * a12 * a23 + + a10 * a01 * a32 * a23 - a00 * a11 * a32 * a23 - a20 * a11 * a02 * a33 + a10 * a21 * a02 * a33 + + a20 * a01 * a12 * a33 - a00 * a21 * a12 * a33 - a10 * a01 * a22 * a33 + a00 * a11 * a22 * a33); +}; + +/** + * Calculates the inverse matrix of a mat4 + * + * @param {mat4} mat mat4 to calculate inverse of + * @param {mat4} [dest] mat4 receiving inverse matrix. If not specified result is written to mat + * + * @param {mat4} dest is specified, mat otherwise, null if matrix cannot be inverted + */ +mat4.inverse = function (mat, dest) { + if (!dest) { dest = mat; } + + // Cache the matrix values (makes for huge speed increases!) + var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3], + a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7], + a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11], + a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15], + + b00 = a00 * a11 - a01 * a10, + b01 = a00 * a12 - a02 * a10, + b02 = a00 * a13 - a03 * a10, + b03 = a01 * a12 - a02 * a11, + b04 = a01 * a13 - a03 * a11, + b05 = a02 * a13 - a03 * a12, + b06 = a20 * a31 - a21 * a30, + b07 = a20 * a32 - a22 * a30, + b08 = a20 * a33 - a23 * a30, + b09 = a21 * a32 - a22 * a31, + b10 = a21 * a33 - a23 * a31, + b11 = a22 * a33 - a23 * a32, + + d = (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06), + invDet; + + // Calculate the determinant + if (!d) { return null; } + invDet = 1 / d; + + dest[0] = (a11 * b11 - a12 * b10 + a13 * b09) * invDet; + dest[1] = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet; + dest[2] = (a31 * b05 - a32 * b04 + a33 * b03) * invDet; + dest[3] = (-a21 * b05 + a22 * b04 - a23 * b03) * invDet; + dest[4] = (-a10 * b11 + a12 * b08 - a13 * b07) * invDet; + dest[5] = (a00 * b11 - a02 * b08 + a03 * b07) * invDet; + dest[6] = (-a30 * b05 + a32 * b02 - a33 * b01) * invDet; + dest[7] = (a20 * b05 - a22 * b02 + a23 * b01) * invDet; + dest[8] = (a10 * b10 - a11 * b08 + a13 * b06) * invDet; + dest[9] = (-a00 * b10 + a01 * b08 - a03 * b06) * invDet; + dest[10] = (a30 * b04 - a31 * b02 + a33 * b00) * invDet; + dest[11] = (-a20 * b04 + a21 * b02 - a23 * b00) * invDet; + dest[12] = (-a10 * b09 + a11 * b07 - a12 * b06) * invDet; + dest[13] = (a00 * b09 - a01 * b07 + a02 * b06) * invDet; + dest[14] = (-a30 * b03 + a31 * b01 - a32 * b00) * invDet; + dest[15] = (a20 * b03 - a21 * b01 + a22 * b00) * invDet; + + return dest; +}; + +/** + * Copies the upper 3x3 elements of a mat4 into another mat4 + * + * @param {mat4} mat mat4 containing values to copy + * @param {mat4} [dest] mat4 receiving copied values + * + * @returns {mat4} dest is specified, a new mat4 otherwise + */ +mat4.toRotationMat = function (mat, dest) { + if (!dest) { dest = mat4.create(); } + + dest[0] = mat[0]; + dest[1] = mat[1]; + dest[2] = mat[2]; + dest[3] = mat[3]; + dest[4] = mat[4]; + dest[5] = mat[5]; + dest[6] = mat[6]; + dest[7] = mat[7]; + dest[8] = mat[8]; + dest[9] = mat[9]; + dest[10] = mat[10]; + dest[11] = mat[11]; + dest[12] = 0; + dest[13] = 0; + dest[14] = 0; + dest[15] = 1; + + return dest; +}; + +/** + * Copies the upper 3x3 elements of a mat4 into a mat3 + * + * @param {mat4} mat mat4 containing values to copy + * @param {mat3} [dest] mat3 receiving copied values + * + * @returns {mat3} dest is specified, a new mat3 otherwise + */ +mat4.toMat3 = function (mat, dest) { + if (!dest) { dest = mat3.create(); } + + dest[0] = mat[0]; + dest[1] = mat[1]; + dest[2] = mat[2]; + dest[3] = mat[4]; + dest[4] = mat[5]; + dest[5] = mat[6]; + dest[6] = mat[8]; + dest[7] = mat[9]; + dest[8] = mat[10]; + + return dest; +}; + +/** + * Calculates the inverse of the upper 3x3 elements of a mat4 and copies the result into a mat3 + * The resulting matrix is useful for calculating transformed normals + * + * Params: + * @param {mat4} mat mat4 containing values to invert and copy + * @param {mat3} [dest] mat3 receiving values + * + * @returns {mat3} dest is specified, a new mat3 otherwise, null if the matrix cannot be inverted + */ +mat4.toInverseMat3 = function (mat, dest) { + // Cache the matrix values (makes for huge speed increases!) + var a00 = mat[0], a01 = mat[1], a02 = mat[2], + a10 = mat[4], a11 = mat[5], a12 = mat[6], + a20 = mat[8], a21 = mat[9], a22 = mat[10], + + b01 = a22 * a11 - a12 * a21, + b11 = -a22 * a10 + a12 * a20, + b21 = a21 * a10 - a11 * a20, + + d = a00 * b01 + a01 * b11 + a02 * b21, + id; + + if (!d) { return null; } + id = 1 / d; + + if (!dest) { dest = mat3.create(); } + + dest[0] = b01 * id; + dest[1] = (-a22 * a01 + a02 * a21) * id; + dest[2] = (a12 * a01 - a02 * a11) * id; + dest[3] = b11 * id; + dest[4] = (a22 * a00 - a02 * a20) * id; + dest[5] = (-a12 * a00 + a02 * a10) * id; + dest[6] = b21 * id; + dest[7] = (-a21 * a00 + a01 * a20) * id; + dest[8] = (a11 * a00 - a01 * a10) * id; + + return dest; +}; + +/** + * Performs a matrix multiplication + * + * @param {mat4} mat First operand + * @param {mat4} mat2 Second operand + * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat + * + * @returns {mat4} dest if specified, mat otherwise + */ +mat4.multiply = function (mat, mat2, dest) { + if (!dest) { dest = mat; } + + // Cache the matrix values (makes for huge speed increases!) + var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3], + a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7], + a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11], + a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15], + + b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], b03 = mat2[3], + b10 = mat2[4], b11 = mat2[5], b12 = mat2[6], b13 = mat2[7], + b20 = mat2[8], b21 = mat2[9], b22 = mat2[10], b23 = mat2[11], + b30 = mat2[12], b31 = mat2[13], b32 = mat2[14], b33 = mat2[15]; + + dest[0] = b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30; + dest[1] = b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31; + dest[2] = b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32; + dest[3] = b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33; + dest[4] = b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30; + dest[5] = b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31; + dest[6] = b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32; + dest[7] = b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33; + dest[8] = b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30; + dest[9] = b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31; + dest[10] = b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32; + dest[11] = b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33; + dest[12] = b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30; + dest[13] = b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31; + dest[14] = b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32; + dest[15] = b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33; + + return dest; +}; + +/** + * Transforms a vec3 with the given matrix + * 4th vector component is implicitly '1' + * + * @param {mat4} mat mat4 to transform the vector with + * @param {vec3} vec vec3 to transform + * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec + * + * @returns {vec3} dest if specified, vec otherwise + */ +mat4.multiplyVec3 = function (mat, vec, dest) { + if (!dest) { dest = vec; } + + var x = vec[0], y = vec[1], z = vec[2]; + + dest[0] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12]; + dest[1] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13]; + dest[2] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14]; + + return dest; +}; + +/** + * Transforms a vec4 with the given matrix + * + * @param {mat4} mat mat4 to transform the vector with + * @param {vec4} vec vec4 to transform + * @param {vec4} [dest] vec4 receiving operation result. If not specified result is written to vec + * + * @returns {vec4} dest if specified, vec otherwise + */ +mat4.multiplyVec4 = function (mat, vec, dest) { + if (!dest) { dest = vec; } + + var x = vec[0], y = vec[1], z = vec[2], w = vec[3]; + + dest[0] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12] * w; + dest[1] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13] * w; + dest[2] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14] * w; + dest[3] = mat[3] * x + mat[7] * y + mat[11] * z + mat[15] * w; + + return dest; +}; + +/** + * Translates a matrix by the given vector + * + * @param {mat4} mat mat4 to translate + * @param {vec3} vec vec3 specifying the translation + * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat + * + * @returns {mat4} dest if specified, mat otherwise + */ +mat4.translate = function (mat, vec, dest) { + var x = vec[0], y = vec[1], z = vec[2], + a00, a01, a02, a03, + a10, a11, a12, a13, + a20, a21, a22, a23; + + if (!dest || mat === dest) { + mat[12] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12]; + mat[13] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13]; + mat[14] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14]; + mat[15] = mat[3] * x + mat[7] * y + mat[11] * z + mat[15]; + return mat; + } + + a00 = mat[0]; a01 = mat[1]; a02 = mat[2]; a03 = mat[3]; + a10 = mat[4]; a11 = mat[5]; a12 = mat[6]; a13 = mat[7]; + a20 = mat[8]; a21 = mat[9]; a22 = mat[10]; a23 = mat[11]; + + dest[0] = a00; dest[1] = a01; dest[2] = a02; dest[3] = a03; + dest[4] = a10; dest[5] = a11; dest[6] = a12; dest[7] = a13; + dest[8] = a20; dest[9] = a21; dest[10] = a22; dest[11] = a23; + + dest[12] = a00 * x + a10 * y + a20 * z + mat[12]; + dest[13] = a01 * x + a11 * y + a21 * z + mat[13]; + dest[14] = a02 * x + a12 * y + a22 * z + mat[14]; + dest[15] = a03 * x + a13 * y + a23 * z + mat[15]; + return dest; +}; + +/** + * Scales a matrix by the given vector + * + * @param {mat4} mat mat4 to scale + * @param {vec3} vec vec3 specifying the scale for each axis + * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat + * + * @param {mat4} dest if specified, mat otherwise + */ +mat4.scale = function (mat, vec, dest) { + var x = vec[0], y = vec[1], z = vec[2]; + + if (!dest || mat === dest) { + mat[0] *= x; + mat[1] *= x; + mat[2] *= x; + mat[3] *= x; + mat[4] *= y; + mat[5] *= y; + mat[6] *= y; + mat[7] *= y; + mat[8] *= z; + mat[9] *= z; + mat[10] *= z; + mat[11] *= z; + return mat; + } + + dest[0] = mat[0] * x; + dest[1] = mat[1] * x; + dest[2] = mat[2] * x; + dest[3] = mat[3] * x; + dest[4] = mat[4] * y; + dest[5] = mat[5] * y; + dest[6] = mat[6] * y; + dest[7] = mat[7] * y; + dest[8] = mat[8] * z; + dest[9] = mat[9] * z; + dest[10] = mat[10] * z; + dest[11] = mat[11] * z; + dest[12] = mat[12]; + dest[13] = mat[13]; + dest[14] = mat[14]; + dest[15] = mat[15]; + return dest; +}; + +/** + * Rotates a matrix by the given angle around the specified axis + * If rotating around a primary axis (X,Y,Z) one of the specialized rotation functions should be used instead for performance + * + * @param {mat4} mat mat4 to rotate + * @param {number} angle Angle (in radians) to rotate + * @param {vec3} axis vec3 representing the axis to rotate around + * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat + * + * @returns {mat4} dest if specified, mat otherwise + */ +mat4.rotate = function (mat, angle, axis, dest) { + var x = axis[0], y = axis[1], z = axis[2], + len = Math.sqrt(x * x + y * y + z * z), + s, c, t, + a00, a01, a02, a03, + a10, a11, a12, a13, + a20, a21, a22, a23, + b00, b01, b02, + b10, b11, b12, + b20, b21, b22; + + if (!len) { return null; } + if (len !== 1) { + len = 1 / len; + x *= len; + y *= len; + z *= len; + } + + s = Math.sin(angle); + c = Math.cos(angle); + t = 1 - c; + + a00 = mat[0]; a01 = mat[1]; a02 = mat[2]; a03 = mat[3]; + a10 = mat[4]; a11 = mat[5]; a12 = mat[6]; a13 = mat[7]; + a20 = mat[8]; a21 = mat[9]; a22 = mat[10]; a23 = mat[11]; + + // Construct the elements of the rotation matrix + b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; + b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; + b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; + + if (!dest) { + dest = mat; + } else if (mat !== dest) { // If the source and destination differ, copy the unchanged last row + dest[12] = mat[12]; + dest[13] = mat[13]; + dest[14] = mat[14]; + dest[15] = mat[15]; + } + + // Perform rotation-specific matrix multiplication + dest[0] = a00 * b00 + a10 * b01 + a20 * b02; + dest[1] = a01 * b00 + a11 * b01 + a21 * b02; + dest[2] = a02 * b00 + a12 * b01 + a22 * b02; + dest[3] = a03 * b00 + a13 * b01 + a23 * b02; + + dest[4] = a00 * b10 + a10 * b11 + a20 * b12; + dest[5] = a01 * b10 + a11 * b11 + a21 * b12; + dest[6] = a02 * b10 + a12 * b11 + a22 * b12; + dest[7] = a03 * b10 + a13 * b11 + a23 * b12; + + dest[8] = a00 * b20 + a10 * b21 + a20 * b22; + dest[9] = a01 * b20 + a11 * b21 + a21 * b22; + dest[10] = a02 * b20 + a12 * b21 + a22 * b22; + dest[11] = a03 * b20 + a13 * b21 + a23 * b22; + return dest; +}; + +/** + * Rotates a matrix by the given angle around the X axis + * + * @param {mat4} mat mat4 to rotate + * @param {number} angle Angle (in radians) to rotate + * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat + * + * @returns {mat4} dest if specified, mat otherwise + */ +mat4.rotateX = function (mat, angle, dest) { + var s = Math.sin(angle), + c = Math.cos(angle), + a10 = mat[4], + a11 = mat[5], + a12 = mat[6], + a13 = mat[7], + a20 = mat[8], + a21 = mat[9], + a22 = mat[10], + a23 = mat[11]; + + if (!dest) { + dest = mat; + } else if (mat !== dest) { // If the source and destination differ, copy the unchanged rows + dest[0] = mat[0]; + dest[1] = mat[1]; + dest[2] = mat[2]; + dest[3] = mat[3]; + + dest[12] = mat[12]; + dest[13] = mat[13]; + dest[14] = mat[14]; + dest[15] = mat[15]; + } + + // Perform axis-specific matrix multiplication + dest[4] = a10 * c + a20 * s; + dest[5] = a11 * c + a21 * s; + dest[6] = a12 * c + a22 * s; + dest[7] = a13 * c + a23 * s; + + dest[8] = a10 * -s + a20 * c; + dest[9] = a11 * -s + a21 * c; + dest[10] = a12 * -s + a22 * c; + dest[11] = a13 * -s + a23 * c; + return dest; +}; + +/** + * Rotates a matrix by the given angle around the Y axis + * + * @param {mat4} mat mat4 to rotate + * @param {number} angle Angle (in radians) to rotate + * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat + * + * @returns {mat4} dest if specified, mat otherwise + */ +mat4.rotateY = function (mat, angle, dest) { + var s = Math.sin(angle), + c = Math.cos(angle), + a00 = mat[0], + a01 = mat[1], + a02 = mat[2], + a03 = mat[3], + a20 = mat[8], + a21 = mat[9], + a22 = mat[10], + a23 = mat[11]; + + if (!dest) { + dest = mat; + } else if (mat !== dest) { // If the source and destination differ, copy the unchanged rows + dest[4] = mat[4]; + dest[5] = mat[5]; + dest[6] = mat[6]; + dest[7] = mat[7]; + + dest[12] = mat[12]; + dest[13] = mat[13]; + dest[14] = mat[14]; + dest[15] = mat[15]; + } + + // Perform axis-specific matrix multiplication + dest[0] = a00 * c + a20 * -s; + dest[1] = a01 * c + a21 * -s; + dest[2] = a02 * c + a22 * -s; + dest[3] = a03 * c + a23 * -s; + + dest[8] = a00 * s + a20 * c; + dest[9] = a01 * s + a21 * c; + dest[10] = a02 * s + a22 * c; + dest[11] = a03 * s + a23 * c; + return dest; +}; + +/** + * Rotates a matrix by the given angle around the Z axis + * + * @param {mat4} mat mat4 to rotate + * @param {number} angle Angle (in radians) to rotate + * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat + * + * @returns {mat4} dest if specified, mat otherwise + */ +mat4.rotateZ = function (mat, angle, dest) { + var s = Math.sin(angle), + c = Math.cos(angle), + a00 = mat[0], + a01 = mat[1], + a02 = mat[2], + a03 = mat[3], + a10 = mat[4], + a11 = mat[5], + a12 = mat[6], + a13 = mat[7]; + + if (!dest) { + dest = mat; + } else if (mat !== dest) { // If the source and destination differ, copy the unchanged last row + dest[8] = mat[8]; + dest[9] = mat[9]; + dest[10] = mat[10]; + dest[11] = mat[11]; + + dest[12] = mat[12]; + dest[13] = mat[13]; + dest[14] = mat[14]; + dest[15] = mat[15]; + } + + // Perform axis-specific matrix multiplication + dest[0] = a00 * c + a10 * s; + dest[1] = a01 * c + a11 * s; + dest[2] = a02 * c + a12 * s; + dest[3] = a03 * c + a13 * s; + + dest[4] = a00 * -s + a10 * c; + dest[5] = a01 * -s + a11 * c; + dest[6] = a02 * -s + a12 * c; + dest[7] = a03 * -s + a13 * c; + + return dest; +}; + +/** + * Generates a frustum matrix with the given bounds + * + * @param {number} left Left bound of the frustum + * @param {number} right Right bound of the frustum + * @param {number} bottom Bottom bound of the frustum + * @param {number} top Top bound of the frustum + * @param {number} near Near bound of the frustum + * @param {number} far Far bound of the frustum + * @param {mat4} [dest] mat4 frustum matrix will be written into + * + * @returns {mat4} dest if specified, a new mat4 otherwise + */ +mat4.frustum = function (left, right, bottom, top, near, far, dest) { + if (!dest) { dest = mat4.create(); } + var rl = (right - left), + tb = (top - bottom), + fn = (far - near); + dest[0] = (near * 2) / rl; + dest[1] = 0; + dest[2] = 0; + dest[3] = 0; + dest[4] = 0; + dest[5] = (near * 2) / tb; + dest[6] = 0; + dest[7] = 0; + dest[8] = (right + left) / rl; + dest[9] = (top + bottom) / tb; + dest[10] = -(far + near) / fn; + dest[11] = -1; + dest[12] = 0; + dest[13] = 0; + dest[14] = -(far * near * 2) / fn; + dest[15] = 0; + return dest; +}; + +/** + * Generates a perspective projection matrix with the given bounds + * + * @param {number} fovy Vertical field of view + * @param {number} aspect Aspect ratio. typically viewport width/height + * @param {number} near Near bound of the frustum + * @param {number} far Far bound of the frustum + * @param {mat4} [dest] mat4 frustum matrix will be written into + * + * @returns {mat4} dest if specified, a new mat4 otherwise + */ +mat4.perspective = function (fovy, aspect, near, far, dest) { + var top = near * Math.tan(fovy * Math.PI / 360.0), + right = top * aspect; + return mat4.frustum(-right, right, -top, top, near, far, dest); +}; + +/** + * Generates a orthogonal projection matrix with the given bounds + * + * @param {number} left Left bound of the frustum + * @param {number} right Right bound of the frustum + * @param {number} bottom Bottom bound of the frustum + * @param {number} top Top bound of the frustum + * @param {number} near Near bound of the frustum + * @param {number} far Far bound of the frustum + * @param {mat4} [dest] mat4 frustum matrix will be written into + * + * @returns {mat4} dest if specified, a new mat4 otherwise + */ +mat4.ortho = function (left, right, bottom, top, near, far, dest) { + if (!dest) { dest = mat4.create(); } + var rl = (right - left), + tb = (top - bottom), + fn = (far - near); + dest[0] = 2 / rl; + dest[1] = 0; + dest[2] = 0; + dest[3] = 0; + dest[4] = 0; + dest[5] = 2 / tb; + dest[6] = 0; + dest[7] = 0; + dest[8] = 0; + dest[9] = 0; + dest[10] = -2 / fn; + dest[11] = 0; + dest[12] = -(left + right) / rl; + dest[13] = -(top + bottom) / tb; + dest[14] = -(far + near) / fn; + dest[15] = 1; + return dest; +}; + +/** + * Generates a look-at matrix with the given eye position, focal point, and up axis + * + * @param {vec3} eye Position of the viewer + * @param {vec3} center Point the viewer is looking at + * @param {vec3} up vec3 pointing "up" + * @param {mat4} [dest] mat4 frustum matrix will be written into + * + * @returns {mat4} dest if specified, a new mat4 otherwise + */ +mat4.lookAt = function (eye, center, up, dest) { + if (!dest) { dest = mat4.create(); } + + var x0, x1, x2, y0, y1, y2, z0, z1, z2, len, + eyex = eye[0], + eyey = eye[1], + eyez = eye[2], + upx = up[0], + upy = up[1], + upz = up[2], + centerx = center[0], + centery = center[1], + centerz = center[2]; + + if (eyex === centerx && eyey === centery && eyez === centerz) { + return mat4.identity(dest); + } + + //vec3.direction(eye, center, z); + z0 = eyex - centerx; + z1 = eyey - centery; + z2 = eyez - centerz; + + // normalize (no check needed for 0 because of early return) + len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); + z0 *= len; + z1 *= len; + z2 *= len; + + //vec3.normalize(vec3.cross(up, z, x)); + x0 = upy * z2 - upz * z1; + x1 = upz * z0 - upx * z2; + x2 = upx * z1 - upy * z0; + len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); + if (!len) { + x0 = 0; + x1 = 0; + x2 = 0; + } else { + len = 1 / len; + x0 *= len; + x1 *= len; + x2 *= len; + } + + //vec3.normalize(vec3.cross(z, x, y)); + y0 = z1 * x2 - z2 * x1; + y1 = z2 * x0 - z0 * x2; + y2 = z0 * x1 - z1 * x0; + + len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); + if (!len) { + y0 = 0; + y1 = 0; + y2 = 0; + } else { + len = 1 / len; + y0 *= len; + y1 *= len; + y2 *= len; + } + + dest[0] = x0; + dest[1] = y0; + dest[2] = z0; + dest[3] = 0; + dest[4] = x1; + dest[5] = y1; + dest[6] = z1; + dest[7] = 0; + dest[8] = x2; + dest[9] = y2; + dest[10] = z2; + dest[11] = 0; + dest[12] = -(x0 * eyex + x1 * eyey + x2 * eyez); + dest[13] = -(y0 * eyex + y1 * eyey + y2 * eyez); + dest[14] = -(z0 * eyex + z1 * eyey + z2 * eyez); + dest[15] = 1; + + return dest; +}; + +/** + * Creates a matrix from a quaternion rotation and vector translation + * This is equivalent to (but much faster than): + * + * mat4.identity(dest); + * mat4.translate(dest, vec); + * var quatMat = mat4.create(); + * quat4.toMat4(quat, quatMat); + * mat4.multiply(dest, quatMat); + * + * @param {quat4} quat Rotation quaternion + * @param {vec3} vec Translation vector + * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to a new mat4 + * + * @returns {mat4} dest if specified, a new mat4 otherwise + */ +mat4.fromRotationTranslation = function (quat, vec, dest) { + if (!dest) { dest = mat4.create(); } + + // Quaternion math + var x = quat[0], y = quat[1], z = quat[2], w = quat[3], + x2 = x + x, + y2 = y + y, + z2 = z + z, + + xx = x * x2, + xy = x * y2, + xz = x * z2, + yy = y * y2, + yz = y * z2, + zz = z * z2, + wx = w * x2, + wy = w * y2, + wz = w * z2; + + dest[0] = 1 - (yy + zz); + dest[1] = xy + wz; + dest[2] = xz - wy; + dest[3] = 0; + dest[4] = xy - wz; + dest[5] = 1 - (xx + zz); + dest[6] = yz + wx; + dest[7] = 0; + dest[8] = xz + wy; + dest[9] = yz - wx; + dest[10] = 1 - (xx + yy); + dest[11] = 0; + dest[12] = vec[0]; + dest[13] = vec[1]; + dest[14] = vec[2]; + dest[15] = 1; + + return dest; +}; + +/** + * Returns a string representation of a mat4 + * + * @param {mat4} mat mat4 to represent as a string + * + * @returns {string} String representation of mat + */ +mat4.str = function (mat) { + return '[' + mat[0] + ', ' + mat[1] + ', ' + mat[2] + ', ' + mat[3] + + ', ' + mat[4] + ', ' + mat[5] + ', ' + mat[6] + ', ' + mat[7] + + ', ' + mat[8] + ', ' + mat[9] + ', ' + mat[10] + ', ' + mat[11] + + ', ' + mat[12] + ', ' + mat[13] + ', ' + mat[14] + ', ' + mat[15] + ']'; +}; + +/* + * quat4 + */ + +/** + * Creates a new instance of a quat4 using the default array type + * Any javascript array containing at least 4 numeric elements can serve as a quat4 + * + * @param {quat4} [quat] quat4 containing values to initialize with + * + * @returns {quat4} New quat4 + */ +quat4.create = function (quat) { + var dest = new MatrixArray(4); + + if (quat) { + dest[0] = quat[0]; + dest[1] = quat[1]; + dest[2] = quat[2]; + dest[3] = quat[3]; + } + + return dest; +}; + +/** + * Copies the values of one quat4 to another + * + * @param {quat4} quat quat4 containing values to copy + * @param {quat4} dest quat4 receiving copied values + * + * @returns {quat4} dest + */ +quat4.set = function (quat, dest) { + dest[0] = quat[0]; + dest[1] = quat[1]; + dest[2] = quat[2]; + dest[3] = quat[3]; + + return dest; +}; + +/** + * Calculates the W component of a quat4 from the X, Y, and Z components. + * Assumes that quaternion is 1 unit in length. + * Any existing W component will be ignored. + * + * @param {quat4} quat quat4 to calculate W component of + * @param {quat4} [dest] quat4 receiving calculated values. If not specified result is written to quat + * + * @returns {quat4} dest if specified, quat otherwise + */ +quat4.calculateW = function (quat, dest) { + var x = quat[0], y = quat[1], z = quat[2]; + + if (!dest || quat === dest) { + quat[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z)); + return quat; + } + dest[0] = x; + dest[1] = y; + dest[2] = z; + dest[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z)); + return dest; +}; + +/** + * Calculates the dot product of two quaternions + * + * @param {quat4} quat First operand + * @param {quat4} quat2 Second operand + * + * @return {number} Dot product of quat and quat2 + */ +quat4.dot = function(quat, quat2){ + return quat[0]*quat2[0] + quat[1]*quat2[1] + quat[2]*quat2[2] + quat[3]*quat2[3]; +}; + +/** + * Calculates the inverse of a quat4 + * + * @param {quat4} quat quat4 to calculate inverse of + * @param {quat4} [dest] quat4 receiving inverse values. If not specified result is written to quat + * + * @returns {quat4} dest if specified, quat otherwise + */ +quat4.inverse = function(quat, dest) { + var q0 = quat[0], q1 = quat[1], q2 = quat[2], q3 = quat[3], + dot = q0*q0 + q1*q1 + q2*q2 + q3*q3, + invDot = dot ? 1.0/dot : 0; + + // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0 + + if(!dest || quat === dest) { + quat[0] *= -invDot; + quat[1] *= -invDot; + quat[2] *= -invDot; + quat[3] *= invDot; + return quat; + } + dest[0] = -quat[0]*invDot; + dest[1] = -quat[1]*invDot; + dest[2] = -quat[2]*invDot; + dest[3] = quat[3]*invDot; + return dest; +}; + + +/** + * Calculates the conjugate of a quat4 + * If the quaternion is normalized, this function is faster than quat4.inverse and produces the same result. + * + * @param {quat4} quat quat4 to calculate conjugate of + * @param {quat4} [dest] quat4 receiving conjugate values. If not specified result is written to quat + * + * @returns {quat4} dest if specified, quat otherwise + */ +quat4.conjugate = function (quat, dest) { + if (!dest || quat === dest) { + quat[0] *= -1; + quat[1] *= -1; + quat[2] *= -1; + return quat; + } + dest[0] = -quat[0]; + dest[1] = -quat[1]; + dest[2] = -quat[2]; + dest[3] = quat[3]; + return dest; +}; + +/** + * Calculates the length of a quat4 + * + * Params: + * @param {quat4} quat quat4 to calculate length of + * + * @returns Length of quat + */ +quat4.length = function (quat) { + var x = quat[0], y = quat[1], z = quat[2], w = quat[3]; + return Math.sqrt(x * x + y * y + z * z + w * w); +}; + +/** + * Generates a unit quaternion of the same direction as the provided quat4 + * If quaternion length is 0, returns [0, 0, 0, 0] + * + * @param {quat4} quat quat4 to normalize + * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat + * + * @returns {quat4} dest if specified, quat otherwise + */ +quat4.normalize = function (quat, dest) { + if (!dest) { dest = quat; } + + var x = quat[0], y = quat[1], z = quat[2], w = quat[3], + len = Math.sqrt(x * x + y * y + z * z + w * w); + if (len === 0) { + dest[0] = 0; + dest[1] = 0; + dest[2] = 0; + dest[3] = 0; + return dest; + } + len = 1 / len; + dest[0] = x * len; + dest[1] = y * len; + dest[2] = z * len; + dest[3] = w * len; + + return dest; +}; + +/** + * Performs quaternion addition + * + * @param {quat4} quat First operand + * @param {quat4} quat2 Second operand + * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat + * + * @returns {quat4} dest if specified, quat otherwise + */ +quat4.add = function (quat, quat2, dest) { + if(!dest || quat === dest) { + quat[0] += quat2[0]; + quat[1] += quat2[1]; + quat[2] += quat2[2]; + quat[3] += quat2[3]; + return quat; + } + dest[0] = quat[0]+quat2[0]; + dest[1] = quat[1]+quat2[1]; + dest[2] = quat[2]+quat2[2]; + dest[3] = quat[3]+quat2[3]; + return dest; +}; + +/** + * Performs a quaternion multiplication + * + * @param {quat4} quat First operand + * @param {quat4} quat2 Second operand + * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat + * + * @returns {quat4} dest if specified, quat otherwise + */ +quat4.multiply = function (quat, quat2, dest) { + if (!dest) { dest = quat; } + + var qax = quat[0], qay = quat[1], qaz = quat[2], qaw = quat[3], + qbx = quat2[0], qby = quat2[1], qbz = quat2[2], qbw = quat2[3]; + + dest[0] = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; + dest[1] = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; + dest[2] = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; + dest[3] = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; + + return dest; +}; + +/** + * Transforms a vec3 with the given quaternion + * + * @param {quat4} quat quat4 to transform the vector with + * @param {vec3} vec vec3 to transform + * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec + * + * @returns dest if specified, vec otherwise + */ +quat4.multiplyVec3 = function (quat, vec, dest) { + if (!dest) { dest = vec; } + + var x = vec[0], y = vec[1], z = vec[2], + qx = quat[0], qy = quat[1], qz = quat[2], qw = quat[3], + + // calculate quat * vec + ix = qw * x + qy * z - qz * y, + iy = qw * y + qz * x - qx * z, + iz = qw * z + qx * y - qy * x, + iw = -qx * x - qy * y - qz * z; + + // calculate result * inverse quat + dest[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; + dest[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; + dest[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; + + return dest; +}; + +/** + * Multiplies the components of a quaternion by a scalar value + * + * @param {quat4} quat to scale + * @param {number} val Value to scale by + * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat + * + * @returns {quat4} dest if specified, quat otherwise + */ +quat4.scale = function (quat, val, dest) { + if(!dest || quat === dest) { + quat[0] *= val; + quat[1] *= val; + quat[2] *= val; + quat[3] *= val; + return quat; + } + dest[0] = quat[0]*val; + dest[1] = quat[1]*val; + dest[2] = quat[2]*val; + dest[3] = quat[3]*val; + return dest; +}; + +/** + * Calculates a 3x3 matrix from the given quat4 + * + * @param {quat4} quat quat4 to create matrix from + * @param {mat3} [dest] mat3 receiving operation result + * + * @returns {mat3} dest if specified, a new mat3 otherwise + */ +quat4.toMat3 = function (quat, dest) { + if (!dest) { dest = mat3.create(); } + + var x = quat[0], y = quat[1], z = quat[2], w = quat[3], + x2 = x + x, + y2 = y + y, + z2 = z + z, + + xx = x * x2, + xy = x * y2, + xz = x * z2, + yy = y * y2, + yz = y * z2, + zz = z * z2, + wx = w * x2, + wy = w * y2, + wz = w * z2; + + dest[0] = 1 - (yy + zz); + dest[1] = xy + wz; + dest[2] = xz - wy; + + dest[3] = xy - wz; + dest[4] = 1 - (xx + zz); + dest[5] = yz + wx; + + dest[6] = xz + wy; + dest[7] = yz - wx; + dest[8] = 1 - (xx + yy); + + return dest; +}; + +/** + * Calculates a 4x4 matrix from the given quat4 + * + * @param {quat4} quat quat4 to create matrix from + * @param {mat4} [dest] mat4 receiving operation result + * + * @returns {mat4} dest if specified, a new mat4 otherwise + */ +quat4.toMat4 = function (quat, dest) { + if (!dest) { dest = mat4.create(); } + + var x = quat[0], y = quat[1], z = quat[2], w = quat[3], + x2 = x + x, + y2 = y + y, + z2 = z + z, + + xx = x * x2, + xy = x * y2, + xz = x * z2, + yy = y * y2, + yz = y * z2, + zz = z * z2, + wx = w * x2, + wy = w * y2, + wz = w * z2; + + dest[0] = 1 - (yy + zz); + dest[1] = xy + wz; + dest[2] = xz - wy; + dest[3] = 0; + + dest[4] = xy - wz; + dest[5] = 1 - (xx + zz); + dest[6] = yz + wx; + dest[7] = 0; + + dest[8] = xz + wy; + dest[9] = yz - wx; + dest[10] = 1 - (xx + yy); + dest[11] = 0; + + dest[12] = 0; + dest[13] = 0; + dest[14] = 0; + dest[15] = 1; + + return dest; +}; + +/** + * Performs a spherical linear interpolation between two quat4 + * + * @param {quat4} quat First quaternion + * @param {quat4} quat2 Second quaternion + * @param {number} slerp Interpolation amount between the two inputs + * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat + * + * @returns {quat4} dest if specified, quat otherwise + */ +quat4.slerp = function (quat, quat2, slerp, dest) { + if (!dest) { dest = quat; } + + var cosHalfTheta = quat[0] * quat2[0] + quat[1] * quat2[1] + quat[2] * quat2[2] + quat[3] * quat2[3], + halfTheta, + sinHalfTheta, + ratioA, + ratioB; + + if (Math.abs(cosHalfTheta) >= 1.0) { + if (dest !== quat) { + dest[0] = quat[0]; + dest[1] = quat[1]; + dest[2] = quat[2]; + dest[3] = quat[3]; + } + return dest; + } + + halfTheta = Math.acos(cosHalfTheta); + sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta); + + if (Math.abs(sinHalfTheta) < 0.001) { + dest[0] = (quat[0] * 0.5 + quat2[0] * 0.5); + dest[1] = (quat[1] * 0.5 + quat2[1] * 0.5); + dest[2] = (quat[2] * 0.5 + quat2[2] * 0.5); + dest[3] = (quat[3] * 0.5 + quat2[3] * 0.5); + return dest; + } + + ratioA = Math.sin((1 - slerp) * halfTheta) / sinHalfTheta; + ratioB = Math.sin(slerp * halfTheta) / sinHalfTheta; + + dest[0] = (quat[0] * ratioA + quat2[0] * ratioB); + dest[1] = (quat[1] * ratioA + quat2[1] * ratioB); + dest[2] = (quat[2] * ratioA + quat2[2] * ratioB); + dest[3] = (quat[3] * ratioA + quat2[3] * ratioB); + + return dest; +}; + +/** + * Returns a string representation of a quaternion + * + * @param {quat4} quat quat4 to represent as a string + * + * @returns {string} String representation of quat + */ +quat4.str = function (quat) { + return '[' + quat[0] + ', ' + quat[1] + ', ' + quat[2] + ', ' + quat[3] + ']'; +}; + + +return { + vec3: vec3, + mat3: mat3, + mat4: mat4, + quat4: quat4 +}; + +})(); + diff --git a/src/intertyper.js b/src/intertyper.js index bd7b70f9..0f9ce659 100644 --- a/src/intertyper.js +++ b/src/intertyper.js @@ -69,11 +69,11 @@ function intertyper(data, sidePass, baseLineNums) { if (mainPass && (line[0] == '%' || line[0] == '@')) { // If this isn't a type, it's a global variable, make a note of the information now, we will need it later - var testType = /[@%\w\d\.\" ]+ = type .*/.exec(line); + var testType = /[@%\w\d\.\" $]+ = type .*/.exec(line); if (!testType) { - var global = /([@%\w\d\.\" ]+) = .*/.exec(line); + var global = /([@%\w\d\.\" $]+) = .*/.exec(line); var globalIdent = toNiceIdent(global[1]); - var testAlias = /[@%\w\d\.\" ]+ = alias .*/.exec(line); + var testAlias = /[@%\w\d\.\" $]+ = alias .*/.exec(line); var testString = /^[^"]+c\"[^"]+"/.exec(line); Variables.globals[globalIdent] = { name: globalIdent, @@ -118,7 +118,7 @@ function intertyper(data, sidePass, baseLineNums) { var func = funcHeader.processItem(tokenizer.processItem({ lineText: currFunctionLines[0], lineNum: currFunctionLineNum }, true))[0]; if (SKIP_STACK_IN_SMALL && /emscripten_autodebug/.exec(func.ident)) { - warn('Disabling SKIP_STACK_IN_SMALL because we are apparently processing autodebugger data'); + warnOnce('Disabling SKIP_STACK_IN_SMALL because we are apparently processing autodebugger data'); SKIP_STACK_IN_SMALL = 0; } @@ -334,9 +334,12 @@ function intertyper(data, sidePass, baseLineNums) { return 'Phi'; if (tokensLength >= 3 && token0Text == 'landingpad') return 'Landingpad'; + if (token0Text == 'fence') + return '/dev/null'; } else if (item.indent === 0) { if ((tokensLength >= 1 && token0Text.substr(-1) == ':') || - (tokensLength >= 3 && token1Text == '<label>')) + (tokensLength >= 3 && token1Text == '<label>') || + (tokensLength >= 2 && token1Text == ':')) return 'Label'; if (tokensLength >= 4 && token0Text == 'declare') return 'External'; @@ -545,13 +548,15 @@ function intertyper(data, sidePass, baseLineNums) { // label substrate.addActor('Label', { processItem: function(item) { + var rawLabel = item.tokens[0].text.substr(-1) == ':' ? + '%' + item.tokens[0].text.substr(0, item.tokens[0].text.length-1) : + (item.tokens[1].text == '<label>' ? + '%' + item.tokens[2].text.substr(1) : + '%' + item.tokens[0].text) + var niceLabel = toNiceIdent(rawLabel); return [{ intertype: 'label', - ident: toNiceIdent( - item.tokens[0].text.substr(-1) == ':' ? - '%' + item.tokens[0].text.substr(0, item.tokens[0].text.length-1) : - '%' + item.tokens[2].text.substr(1) - ), + ident: niceLabel, lineNum: item.lineNum }]; } @@ -655,17 +660,19 @@ function intertyper(data, sidePass, baseLineNums) { item.type = item.tokens[1].text; Types.needAnalysis[item.type] = 0; while (['@', '%'].indexOf(item.tokens[2].text[0]) == -1 && !(item.tokens[2].text in PARSABLE_LLVM_FUNCTIONS) && - item.tokens[2].text != 'null') { - // We cannot compile assembly. If you hit this, perhaps tell the compiler not - // to generate arch-specific code? |-U__i386__ -U__x86_64__| might help, it undefines - // the standard archs. + item.tokens[2].text != 'null' && item.tokens[2].text != 'asm') { assert(item.tokens[2].text != 'asm', 'Inline assembly cannot be compiled to JavaScript!'); item.tokens.splice(2, 1); } var tokensLeft = item.tokens.slice(2); item.ident = eatLLVMIdent(tokensLeft); - // We cannot compile assembly, see above. - assert(item.ident != 'asm', 'Inline assembly cannot be compiled to JavaScript!'); + if (item.ident == 'asm') { + // Inline assembly is just JavaScript that we paste into the code + item.intertype = 'value'; + if (tokensLeft[0].text == 'sideeffect') tokensLeft.splice(0, 1); + item.ident = tokensLeft[0].text.substr(1, tokensLeft[0].text.length-2); + return { forward: null, ret: [item], item: item }; + } if (item.ident.substr(-2) == '()') { // See comment in isStructType() item.ident = item.ident.substr(0, item.ident.length-2); diff --git a/src/jsifier.js b/src/jsifier.js index d4d57fc6..904517e1 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -166,23 +166,27 @@ function JSify(data, functionsOnly, givenFunctions) { ret[index++] = 0; } // Add current value(s) - var currValue = flatten(values[i]); + var currValue = values[i]; if (USE_TYPED_ARRAYS == 2 && typeData.fields[i] == 'i64') { // 'flatten' out the 64-bit value into two 32-bit halves - ret[index++] = currValue>>>0; + var parts = parseI64Constant(currValue, true); + ret[index++] = parts[0]; ret[index++] = 0; ret[index++] = 0; ret[index++] = 0; - ret[index++] = Math.floor(currValue/4294967296); + ret[index++] = parts[1]; ret[index++] = 0; ret[index++] = 0; ret[index++] = 0; - } else if (typeof currValue == 'object') { - for (var j = 0; j < currValue.length; j++) { - ret[index++] = currValue[j]; - } } else { - ret[index++] = currValue; + currValue = flatten(currValue); + if (typeof currValue == 'object') { + for (var j = 0; j < currValue.length; j++) { + ret[index++] = currValue[j]; + } + } else { + ret[index++] = currValue; + } } i += 1; } @@ -229,7 +233,7 @@ function JSify(data, functionsOnly, givenFunctions) { return makeEmptyStruct(type); } else if (value.intertype === 'string') { return JSON.stringify(parseLLVMString(value.text)) + - ' /* ' + value.text.substr(0, 20).replace(/\*/g, '_') + ' */'; // make string safe for inclusion in comment + ' /* ' + value.text.substr(0, 20).replace(/[*<>]/g, '_') + ' */'; // make string safe for inclusion in comment } else { return alignStruct(handleSegments(value.contents), type); } @@ -371,11 +375,15 @@ function JSify(data, functionsOnly, givenFunctions) { processItem: function(item) { function addFromLibrary(ident) { if (ident in addedLibraryItems) return ''; + addedLibraryItems[ident] = true; + + // dependencies can be JS functions, which we just run + if (typeof ident == 'function') return ident(); + // Don't replace implemented functions with library ones (which can happen when we add dependencies). // Note: We don't return the dependencies here. Be careful not to end up where this matters if (('_' + ident) in Functions.implementedFunctions) return ''; - addedLibraryItems[ident] = true; var snippet = LibraryManager.library[ident]; var redirectedIdent = null; var deps = LibraryManager.library[ident + '__deps'] || []; @@ -400,7 +408,8 @@ function JSify(data, functionsOnly, givenFunctions) { // name the function; overwrite if it's already named snippet = snippet.replace(/function(?:\s+([^(]+))?\s*\(/, 'function _' + ident + '('); if (LIBRARY_DEBUG) { - snippet = snippet.replace('{', '{ print("[library call:' + ident + ']"); '); + snippet = snippet.replace('{', '{ var ret = (function() {Module.printErr("[library call:' + ident + ': " + Array.prototype.slice.call(arguments) + "]"); '); + snippet = snippet.substr(0, snippet.length-1) + '}).apply(this, arguments); Module.printErr(" [ return:" + ret); return ret; }'; } } @@ -540,7 +549,7 @@ function JSify(data, functionsOnly, givenFunctions) { } }); - if (LABEL_DEBUG) func.JS += " print(INDENT + ' Entering: " + func.ident + "'); INDENT += ' ';\n"; + if (LABEL_DEBUG) func.JS += " Module.print(INDENT + ' Entering: " + func.ident + "'); INDENT += ' ';\n"; if (true) { // TODO: optimize away when not needed if (CLOSURE_ANNOTATIONS) func.JS += '/** @type {number} */'; @@ -558,7 +567,7 @@ function JSify(data, functionsOnly, givenFunctions) { if (!label) return ''; var ret = ''; if (LABEL_DEBUG) { - ret += indent + "print(INDENT + '" + func.ident + ":" + label.ident + "');\n"; + ret += indent + "Module.print(INDENT + '" + func.ident + ":" + label.ident + "');\n"; } if (EXECUTION_TIMEOUT > 0) { ret += indent + 'if (Date.now() - START_TIME >= ' + (EXECUTION_TIMEOUT*1000) + ') throw "Timed out!" + (new Error().stack);\n'; @@ -921,13 +930,16 @@ function JSify(data, functionsOnly, givenFunctions) { }); var ret = ''; var first = true; + var signedIdent = makeSignOp(item.ident, item.type, 're'); // we need to standardize for purpose of comparison for (var targetLabel in targetLabels) { if (!first) { ret += 'else '; } else { first = false; } - ret += 'if (' + targetLabels[targetLabel].map(function(value) { return makeComparison(item.ident, value, item.type) }).join(' || ') + ') {\n'; + ret += 'if (' + targetLabels[targetLabel].map(function(value) { + return makeComparison(signedIdent, makeSignOp(value, item.type, 're'), item.type) + }).join(' || ') + ') {\n'; ret += ' ' + getPhiSetsForLabel(phiSets, targetLabel) + makeBranch(targetLabel, item.currLabelId || null) + '\n'; ret += '}\n'; } @@ -948,7 +960,7 @@ function JSify(data, functionsOnly, givenFunctions) { + '}\n'; } if (LABEL_DEBUG) { - ret += "print(INDENT + 'Exiting: " + item.funcData.ident + "');\n" + ret += "Module.print(INDENT + 'Exiting: " + item.funcData.ident + "');\n" + "INDENT = INDENT.substr(0, INDENT.length-2);\n"; } ret += 'return'; @@ -958,7 +970,7 @@ function JSify(data, functionsOnly, givenFunctions) { return ret + ';'; }); makeFuncLineActor('resume', function(item) { - return (EXCEPTION_DEBUG ? 'print("Resuming exception");' : '') + + return (EXCEPTION_DEBUG ? 'Module.print("Resuming exception");' : '') + 'throw ' + makeGetValue('_llvm_eh_exception.buf', '0', 'void*') + ';'; }); makeFuncLineActor('invoke', function(item) { @@ -971,7 +983,7 @@ function JSify(data, functionsOnly, givenFunctions) { + '} catch(e) { ' + 'if (typeof e != "number") throw e; ' + 'if (ABORT) throw e; __THREW__ = true; ' - + (EXCEPTION_DEBUG ? 'print("Exception: " + e + ", currently at: " + (new Error().stack)); ' : '') + + (EXCEPTION_DEBUG ? 'Module.print("Exception: " + e + ", currently at: " + (new Error().stack)); ' : '') + 'return null } })();'; if (item.assignTo) { ret = 'var ' + item.assignTo + ' = ' + ret; @@ -1192,6 +1204,12 @@ function JSify(data, functionsOnly, givenFunctions) { // This is the main pass. Print out the generated code that we have here, together with the // rest of the output that we started to print out earlier (see comment on the // "Final shape that will be created"). + if (PRECISE_I64_MATH && preciseI64MathUsed) { + print(read('long.js')); + } else { + print('// Warning: printing of i64 values may be slightly rounded! No deep i64 math used, so precise i64 code not included'); + print('var i64Math = null;'); + } var generated = itemsDict.functionStub.concat(itemsDict.GlobalVariablePostSet); generated.forEach(function(item) { print(indentify(item.JS || '', 2)); }); if (RUNTIME_TYPE_INFO) { diff --git a/src/library.js b/src/library.js index 817f87e2..c491f078 100644 --- a/src/library.js +++ b/src/library.js @@ -26,7 +26,8 @@ LibraryManager.library = { _impure_ptr: 0, $FS__deps: ['$ERRNO_CODES', '__setErrNo', 'stdin', 'stdout', 'stderr', '_impure_ptr'], - $FS__postset: '__ATINIT__.unshift({ func: function() { FS.ignorePermissions = false; if (!FS.init.initialized) FS.init() } });' + + $FS__postset: '__ATINIT__.unshift({ func: function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() } });' + + '__ATMAIN__.push({ func: function() { FS.ignorePermissions = false } });' + '__ATEXIT__.push({ func: function() { FS.quit() } });', $FS: { // The path to the current folder. @@ -86,6 +87,23 @@ LibraryManager.library = { parentPath: null, parentObject: null }; +#if FS_LOG + var inputPath = path; + function log() { + print('FS.analyzePath("' + inputPath + '", ' + + dontResolveLastLink + ', ' + + linksVisited + ') => {' + + 'isRoot: ' + ret.isRoot + ', ' + + 'exists: ' + ret.exists + ', ' + + 'error: ' + ret.error + ', ' + + 'name: "' + ret.name + '", ' + + 'path: "' + ret.path + '", ' + + 'object: ' + ret.object + ', ' + + 'parentExists: ' + ret.parentExists + ', ' + + 'parentPath: "' + ret.parentPath + '", ' + + 'parentObject: ' + ret.parentObject + '}'); + } +#endif path = FS.absolutePath(path); if (path == '/') { ret.isRoot = true; @@ -123,8 +141,12 @@ LibraryManager.library = { break; } var link = FS.absolutePath(current.link, traversed.join('/')); - return FS.analyzePath([link].concat(path).join('/'), - dontResolveLastLink, linksVisited + 1); + ret = FS.analyzePath([link].concat(path).join('/'), + dontResolveLastLink, linksVisited + 1); +#if FS_LOG + log(); +#endif + return ret; } traversed.push(target); if (path.length == 0) { @@ -133,8 +155,10 @@ LibraryManager.library = { ret.object = current; } } - return ret; } +#if FS_LOG + log(); +#endif return ret; }, // Finds the file system object at a given path. If dontResolveLastLink is @@ -152,6 +176,13 @@ LibraryManager.library = { }, // Creates a file system record: file, link, device or folder. createObject: function(parent, name, properties, canRead, canWrite) { +#if FS_LOG + print('FS.createObject("' + parent + '", ' + + '"' + name + '", ' + + JSON.stringify(properties) + ', ' + + canRead + ', ' + + canWrite + ')'); +#endif if (!parent) parent = '/'; if (typeof parent === 'string') parent = FS.findObject(parent); @@ -219,8 +250,8 @@ LibraryManager.library = { // Creates a file record from existing data. createDataFile: function(parent, name, data, canRead, canWrite) { if (typeof data === 'string') { - var dataArray = []; - for (var i = 0; i < data.length; i++) dataArray.push(data.charCodeAt(i)); + var dataArray = new Array(data.length); + for (var i = 0, len = data.length; i < len; ++i) dataArray[i] = data.charCodeAt(i); data = dataArray; } var properties = {isDevice: false, contents: data}; @@ -255,29 +286,13 @@ LibraryManager.library = { var success = true; if (typeof XMLHttpRequest !== 'undefined') { // Browser. - // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. - var xhr = new XMLHttpRequest(); - xhr.open('GET', obj.url, false); - - // Some hints to the browser that we want binary data. - if (typeof Uint8Array != 'undefined') xhr.responseType = 'arraybuffer'; - if (xhr.overrideMimeType) { - xhr.overrideMimeType('text/plain; charset=x-user-defined'); - } - - xhr.send(null); - if (xhr.status != 200 && xhr.status != 0) success = false; - if (xhr.response !== undefined) { - obj.contents = new Uint8Array(xhr.response || []); - } else { - obj.contents = intArrayFromString(xhr.responseText || '', true); - } - } else if (typeof read !== 'undefined') { + assert('Cannot do synchronous binary XHRs in modern browsers. Use --embed-file or --preload-file in emcc'); + } else if (Module['read']) { // Command-line. try { // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as // read() will try to parse UTF8. - obj.contents = intArrayFromString(read(obj.url), true); + obj.contents = intArrayFromString(Module['read'](obj.url), true); } catch (e) { success = false; } @@ -309,34 +324,52 @@ LibraryManager.library = { FS.ensureRoot(); + // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here + input = input || Module['stdin']; + output = output || Module['stdout']; + error = error || Module['stderr']; + // Default handlers. - if (!input) input = function() { - if (!input.cache || !input.cache.length) { - var result; - if (typeof window != 'undefined' && - typeof window.prompt == 'function') { - // Browser. - result = window.prompt('Input: '); - } else if (typeof readline == 'function') { - // Command line. - result = readline(); + var stdinOverridden = true, stdoutOverridden = true, stderrOverridden = true; + if (!input) { + stdinOverridden = false; + input = function() { + if (!input.cache || !input.cache.length) { + var result; + if (typeof window != 'undefined' && + typeof window.prompt == 'function') { + // Browser. + result = window.prompt('Input: '); + } else if (typeof readline == 'function') { + // Command line. + result = readline(); + } + if (!result) result = ''; + input.cache = intArrayFromString(result + '\n', true); } - if (!result) result = ''; - input.cache = intArrayFromString(result + '\n', true); - } - return input.cache.shift(); - }; - if (!output) output = function(val) { + return input.cache.shift(); + }; + } + function simpleOutput(val) { if (val === null || val === '\n'.charCodeAt(0)) { output.printer(output.buffer.join('')); output.buffer = []; } else { output.buffer.push(String.fromCharCode(val)); } - }; - if (!output.printer) output.printer = print; + } + if (!output) { + stdoutOverridden = false; + output = simpleOutput; + } + if (!output.printer) output.printer = Module['print']; if (!output.buffer) output.buffer = []; - if (!error) error = output; + if (!error) { + stderrOverridden = false; + error = simpleOutput; + } + if (!error.printer) error.printer = Module['print']; + if (!error.buffer) error.buffer = []; // Create the temporary folder. FS.createFolder('/', 'tmp', true, true); @@ -356,6 +389,7 @@ LibraryManager.library = { isRead: true, isWrite: false, isAppend: false, + isTerminal: !stdinOverridden, error: false, eof: false, ungotten: [] @@ -367,6 +401,7 @@ LibraryManager.library = { isRead: false, isWrite: true, isAppend: false, + isTerminal: !stdoutOverridden, error: false, eof: false, ungotten: [] @@ -378,6 +413,7 @@ LibraryManager.library = { isRead: false, isWrite: true, isAppend: false, + isTerminal: !stderrOverridden, error: false, eof: false, ungotten: [] @@ -400,9 +436,24 @@ LibraryManager.library = { quit: function() { if (!FS.init.initialized) return; - // Flush any partially-printed lines in stdout and stderr - if (FS.streams[2].object.output.buffer.length > 0) FS.streams[2].object.output('\n'.charCodeAt(0)); - if (FS.streams[3].object.output.buffer.length > 0) FS.streams[3].object.output('\n'.charCodeAt(0)); + // Flush any partially-printed lines in stdout and stderr. Careful, they may have been closed + if (FS.streams[2] && FS.streams[2].object.output.buffer.length > 0) FS.streams[2].object.output('\n'.charCodeAt(0)); + if (FS.streams[3] && FS.streams[3].object.output.buffer.length > 0) FS.streams[3].object.output('\n'.charCodeAt(0)); + }, + + // Standardizes a path. Useful for making comparisons of pathnames work in a consistent manner. + // For example, ./file and file are really the same, so this function will remove ./ + standardizePath: function(path) { + if (path.substr(0, 2) == './') path = path.substr(2); + return path; + }, + + deleteFile: function(path) { + var path = FS.analyzePath(path); + if (!path.parentExists || !path.exists) { + throw 'Invalid path ' + path; + } + delete path.parentObject.contents[path.name]; } }, @@ -1386,9 +1437,13 @@ LibraryManager.library = { isatty: function(fildes) { // int isatty(int fildes); // http://pubs.opengroup.org/onlinepubs/000095399/functions/isatty.html - // For now it's easier to pretend we have no terminals. - ___setErrNo(FS.streams[fildes] ? ERRNO_CODES.ENOTTY : ERRNO_CODES.EBADF); - return -1; + if (!FS.streams[fildes]) { + ___setErrNo(ERRNO_CODES.EBADF); + return 0; + } + if (FS.streams[fildes].isTerminal) return 1; + ___setErrNo(ERRNO_CODES.ENOTTY); + return 0; }, lchown__deps: ['chown'], lchown: function(path, owner, group) { @@ -2239,7 +2294,7 @@ LibraryManager.library = { (type === 'x' && (next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0) || next >= 'a'.charCodeAt(0) && next <= 'f'.charCodeAt(0) || next >= 'A'.charCodeAt(0) && next <= 'F'.charCodeAt(0))) || - (type === 's') && + (type === 's' && (next != ' '.charCodeAt(0) && next != '\t'.charCodeAt(0) && next != '\n'.charCodeAt(0))) && (formatIndex >= format.length || next !== format[formatIndex].charCodeAt(0))) { // Stop when we read something that is coming up buffer.push(String.fromCharCode(next)); next = get(); @@ -2433,6 +2488,10 @@ LibraryManager.library = { var signed = next == 'd'.charCodeAt(0) || next == 'i'.charCodeAt(0); argSize = argSize || 4; var currArg = getNextArg('i' + (argSize * 8)); +#if PRECISE_I64_MATH == 1 + var origArg = currArg; +#endif + var argText; #if USE_TYPED_ARRAYS == 2 // Flatten i64-1 [low, high] into a (slightly rounded) double if (argSize == 8) { @@ -2446,11 +2505,16 @@ LibraryManager.library = { } // Format the number. var currAbsArg = Math.abs(currArg); - var argText; var prefix = ''; if (next == 'd'.charCodeAt(0) || next == 'i'.charCodeAt(0)) { +#if PRECISE_I64_MATH == 1 + if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1]); else +#endif argText = reSign(currArg, 8 * argSize, 1).toString(10); } else if (next == 'u'.charCodeAt(0)) { +#if PRECISE_I64_MATH == 1 + if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], true); else +#endif argText = unSign(currArg, 8 * argSize, 1).toString(10); currArg = Math.abs(currArg); } else if (next == 'o'.charCodeAt(0)) { @@ -2711,7 +2775,9 @@ LibraryManager.library = { var flush = function(filedes) { // Right now we write all data directly, except for output devices. if (filedes in FS.streams && FS.streams[filedes].object.output) { - FS.streams[filedes].object.output(null); + if (!FS.streams[filedes].isTerminal) { // don't flush terminals, it would cause a \n to also appear + FS.streams[filedes].object.output(null); + } } }; try { @@ -3237,8 +3303,9 @@ LibraryManager.library = { } var info = FS.streams[stream]; if (!info) return -1; - return allocate(info.object.contents.slice(offset, offset+num), - 'i8', ALLOC_NORMAL); + var contents = info.object.contents; + contents = Array.prototype.slice.call(contents, offset, offset+num); + return allocate(contents, 'i8', ALLOC_NORMAL); }, __01mmap64_: 'mmap', @@ -3300,9 +3367,9 @@ LibraryManager.library = { }, __cxa_atexit: 'atexit', - abort: function(code) { + abort: function() { ABORT = true; - throw 'ABORT: ' + code + ', at ' + (new Error().stack); + throw 'abort() at ' + (new Error().stack); }, bsearch: function(key, base, num, size, compar) { @@ -3553,7 +3620,7 @@ LibraryManager.library = { ENV['USER'] = 'root'; ENV['PATH'] = '/'; ENV['PWD'] = '/'; - ENV['HOME'] = '/'; + ENV['HOME'] = '/home/emscripten'; ENV['LANG'] = 'en_US.UTF-8'; ENV['_'] = './this.program'; // Allocate memory. @@ -4191,11 +4258,13 @@ LibraryManager.library = { isdigit: function(chr) { return chr >= '0'.charCodeAt(0) && chr <= '9'.charCodeAt(0); }, + isdigit_l: 'isdigit', // no locale support yet isxdigit: function(chr) { return (chr >= '0'.charCodeAt(0) && chr <= '9'.charCodeAt(0)) || (chr >= 'a'.charCodeAt(0) && chr <= 'f'.charCodeAt(0)) || (chr >= 'A'.charCodeAt(0) && chr <= 'F'.charCodeAt(0)); }, + isxdigit_l: 'isxdigit', // no locale support yet isalnum: function(chr) { return (chr >= '0'.charCodeAt(0) && chr <= '9'.charCodeAt(0)) || (chr >= 'a'.charCodeAt(0) && chr <= 'z'.charCodeAt(0)) || @@ -4394,7 +4463,7 @@ LibraryManager.library = { ___cxa_throw.initialized = true; } #if EXCEPTION_DEBUG - print('Compiled code throwing an exception, ' + [ptr,type,destructor] + ', at ' + new Error().stack); + Module.printErr('Compiled code throwing an exception, ' + [ptr,type,destructor] + ', at ' + new Error().stack); #endif {{{ makeSetValue('_llvm_eh_exception.buf', '0', 'ptr', 'void*') }}} {{{ makeSetValue('_llvm_eh_exception.buf', QUANTUM_SIZE, 'type', 'void*') }}} @@ -4518,12 +4587,12 @@ LibraryManager.library = { // return the type of the catch block which should be called. for (var i = 0; i < typeArray.length; i++) { if (___cxa_does_inherit(typeArray[i], throwntype, thrown)) - return { 'f0':thrown, 'f1':typeArray[i]}; + return { f0:thrown, f1:typeArray[i] }; } // Shouldn't happen unless we have bogus data in typeArray // or encounter a type for which emscripten doesn't have suitable // typeinfo defined. Best-efforts match just in case. - return {'f0':thrown,'f1':throwntype}; + return { f0:thrown, f1 :throwntype }; }, // Recursively walks up the base types of 'possibilityType' @@ -4586,16 +4655,20 @@ LibraryManager.library = { _ZTIPv: [0], llvm_uadd_with_overflow_i32: function(x, y) { + x = x>>>0; + y = y>>>0; return { - f0: x+y, - f1: 0 // We never overflow... for now + f0: (x+y)>>>0, + f1: x+y > 4294967295 }; }, llvm_umul_with_overflow_i32: function(x, y) { + x = x>>>0; + y = y>>>0; return { - f0: x*y, - f1: 0 // We never overflow... for now + f0: (x*y)>>>0, + f1: x*y > 4294967295 }; }, @@ -4948,7 +5021,7 @@ LibraryManager.library = { var lib_module = eval(lib_data)(FUNCTION_TABLE.length); } catch (e) { #if ASSERTIONS - print('Error in loading dynamic library: ' + e); + Module.printErr('Error in loading dynamic library: ' + e); #endif DLFCN_DATA.errorMsg = 'Could not evaluate dynamic lib: ' + filename; return 0; @@ -5183,7 +5256,7 @@ LibraryManager.library = { var dst = Number(start.getTimezoneOffset() != date.getTimezoneOffset()); {{{ makeSetValue('tmPtr', 'offsets.tm_isdst', 'dst', 'i32') }}} - var timezone = date.toString().match(/\(([A-Z]+)\)/)[1]; + var timezone = 'GMT'; // XXX do not rely on browser timezone info, it is very unpredictable | date.toString().match(/\(([A-Z]+)\)/)[1]; if (!(timezone in ___tm_timezones)) { ___tm_timezones[timezone] = allocate(intArrayFromString(timezone), 'i8', ALLOC_NORMAL); } @@ -5245,8 +5318,8 @@ LibraryManager.library = { var summer = new Date(2000, 6, 1); {{{ makeSetValue('__daylight', '0', 'Number(winter.getTimezoneOffset() != summer.getTimezoneOffset())', 'i32') }}} - var winterName = winter.toString().match(/\(([A-Z]+)\)/)[1]; - var summerName = summer.toString().match(/\(([A-Z]+)\)/)[1]; + var winterName = 'GMT'; // XXX do not rely on browser timezone info, it is very unpredictable | winter.toString().match(/\(([A-Z]+)\)/)[1]; + var summerName = 'GMT'; // XXX do not rely on browser timezone info, it is very unpredictable | summer.toString().match(/\(([A-Z]+)\)/)[1]; var winterNamePtr = allocate(intArrayFromString(winterName), 'i8', ALLOC_NORMAL); var summerNamePtr = allocate(intArrayFromString(summerName), 'i8', ALLOC_NORMAL); __tzname = _malloc(2 * {{{ Runtime.QUANTUM_SIZE }}}); // glibc does not need the double __ @@ -5266,6 +5339,7 @@ LibraryManager.library = { // TODO: Implement. return 0; }, + strftime_l: 'strftime', // no locale support yet strptime: function(buf, format, tm) { // char *strptime(const char *restrict buf, const char *restrict format, struct tm *restrict tm); @@ -5273,6 +5347,7 @@ LibraryManager.library = { // TODO: Implement. return 0; }, + strptime_l: 'strptime', // no locale support yet getdate: function(string) { // struct tm *getdate(const char *string); @@ -5985,12 +6060,12 @@ LibraryManager.library = { invalid: 0, dump: function() { if (Profiling.invalid) { - print('Invalid # of calls to Profiling begin and end!'); + Module.printErr('Invalid # of calls to Profiling begin and end!'); return; } - print('Profiling data:') + Module.printErr('Profiling data:') for (var i = 0; i < Profiling.max_; i++) { - print('Block ' + i + ': ' + Profiling.times[i]); + Module.printErr('Block ' + i + ': ' + Profiling.times[i]); } } }, @@ -6010,3 +6085,12 @@ LibraryManager.library = { } }; +function autoAddDeps(object, name) { + name = [name]; + for (var item in object) { + if (item.substr(-6) != '__deps' && !object[item + '__deps']) { + object[item + '__deps'] = name; + } + } +} + diff --git a/src/library_browser.js b/src/library_browser.js index 9c3057b8..299e8a72 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -3,10 +3,131 @@ // Utilities for browser environments mergeInto(LibraryManager.library, { + emscripten_set_main_loop: function(func, fps) { + fps = fps || 60; // TODO: use requestAnimationFrame + _emscripten_set_main_loop.cancel = false; + var jsFunc = FUNCTION_TABLE[func]; + function doOne() { + if (_emscripten_set_main_loop.cancel) return; + jsFunc(); + setTimeout(doOne, 1000/fps); // doing this each time means that on exception, we stop + } + setTimeout(doOne, 1000/fps); + }, + + emscripten_cancel_main_loop: function(func) { + _emscripten_set_main_loop.cancel = true; + }, + + emscripten_async_call: function(func, millis) { + // TODO: cache these to avoid generating garbage + setTimeout(function() { + FUNCTION_TABLE[func](); + }, millis); + }, + $Browser: { + createContext: function(canvas, useWebGL) { +#if !USE_TYPED_ARRAYS + if (useWebGL) { + Module.print('(USE_TYPED_ARRAYS needs to be enabled for WebGL)'); + return null; + } +#endif + try { + var ctx = canvas.getContext(useWebGL ? 'experimental-webgl' : '2d'); + if (!ctx) throw ':('; + } catch (e) { + Module.print('Could not create canvas - ' + e); + return null; + } + if (useWebGL) { +#if GL_DEBUG + // Useful to debug native webgl apps: var Module = { printErr: function(x) { console.log(x) } }; + var tempCtx = ctx; + var wrapper = {}; + wrapper.objectMap = new WeakMap(); + wrapper.objectCounter = 1; + for (var prop in tempCtx) { + (function(prop) { + switch (typeof tempCtx[prop]) { + case 'function': { + wrapper[prop] = function() { + var printArgs = Array.prototype.slice.call(arguments).map(function(arg) { + if (typeof arg == 'undefined') return '!UNDEFINED!'; + if (!arg) return arg; + if (wrapper.objectMap[arg]) return '<' + arg + '|' + wrapper.objectMap[arg] + '>'; + if (arg.toString() == '[object HTMLImageElement]') { + return arg + '\n\n'; + } + if (arg.byteLength) { + return '{' + Array.prototype.slice.call(arg, 0, Math.min(arg.length, 40)) + '}'; // Useful for correct arrays, less so for compiled arrays, see the code below for that + var buf = new ArrayBuffer(32); + var i8buf = new Int8Array(buf); + var i16buf = new Int16Array(buf); + var f32buf = new Float32Array(buf); + switch(arg.toString()) { + case '[object Uint8Array]': + i8buf.set(arg.subarray(0, 32)); + break; + case '[object Float32Array]': + f32buf.set(arg.subarray(0, 5)); + break; + case '[object Uint16Array]': + i16buf.set(arg.subarray(0, 16)); + break; + default: + alert('unknown array for debugging: ' + arg); + throw 'see alert'; + } + var ret = '{' + arg.byteLength + ':\n'; + var arr = Array.prototype.slice.call(i8buf); + ret += 'i8:' + arr.toString().replace(/,/g, ',') + '\n'; + arr = Array.prototype.slice.call(f32buf, 0, 8); + ret += 'f32:' + arr.toString().replace(/,/g, ',') + '}'; + return ret; + } + return arg; + }); + console.log('[gl_f:' + prop + ':' + printArgs + ']'); + var ret = tempCtx[prop].apply(tempCtx, arguments); + var printRet = ret; + if (typeof ret == 'object') { + wrapper.objectMap[ret] = wrapper.objectCounter++; + printRet = '<' + ret + '|' + wrapper.objectMap[ret] + '>'; + } + if (typeof printRet != 'undefined') console.log('[ gl:' + prop + ':return:' + printRet + ']'); + return ret; + } + break; + } + case 'number': case 'string': { + wrapper.__defineGetter__(prop, function() { + //console.log('[gl_g:' + prop + ':' + tempCtx[prop] + ']'); + return tempCtx[prop]; + }); + wrapper.__defineSetter__(prop, function(value) { + console.log('[gl_s:' + prop + ':' + value + ']'); + tempCtx[prop] = value; + }); + break; + } + } + })(prop); + } + ctx = wrapper; +#endif + // Set the background of the WebGL canvas to black + canvas.style.backgroundColor = "black"; + } + return ctx; + }, + // Given binary data for an image, in a format like PNG or JPG, we convert it // to flat pixel data. We do so using the browser's native code. - decodeImage: function(pixels, format) { + // This is deprecated, it is preferred to load binary files, createObjectURL, etc., + // see the sdl_* tests. + /*decodeImage: function(pixels, format) { function encodeBase64(data) { var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; var PAD = '='; @@ -31,14 +152,17 @@ mergeInto(LibraryManager.library, { } return ret; } - var img = new Image(); + var image = new Image(); + image.src = 'data:image/' + format + ';base64,' + encodeBase64(pixels); + assert(image.complete, 'Image could not be decoded'); // page reload might fix it, decoding is async... need .onload handler... var canvas = document.createElement('canvas'); - img.src = 'data:image/' + format + ';base64,' + encodeBase64(pixels); + canvas.width = image.width; + canvas.height = image.height; var ctx = canvas.getContext('2d'); - ctx.drawImage(img, 0, 0); + ctx.drawImage(image, 0, 0); var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); return imageData; - }, + },*/ } }); diff --git a/src/library_egl.js b/src/library_egl.js new file mode 100644 index 00000000..f1558f80 --- /dev/null +++ b/src/library_egl.js @@ -0,0 +1,20 @@ + +var LibraryEGL = { + eglGetDisplay: function(x_display) { return 3 }, + eglInitialize: function(display, majorVersion, minorVersion) { return 1 }, + eglGetConfigs: function(display, hmm1, hmm2, numConfigs) { return 1 }, + eglChooseConfig: function(display, attribList, config, hmm, numConfigs) { return 1 }, + eglCreateWindowSurface: function(display, config, hWnd, hmm) { return 4 }, + + eglCreateContext__deps: ['glutCreateWindow', '$GL'], + eglCreateContext: function(display, config, hmm, contextAttribs) { + _glutCreateWindow(); + return 1; + }, + + eglMakeCurrent: function(display, surface, surface_, context) { return 1 }, + eglSwapBuffers: function() {}, +}; + +mergeInto(LibraryManager.library, LibraryEGL); + diff --git a/src/library_gl.js b/src/library_gl.js index 1d5168fb..052226cf 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -1,49 +1,120 @@ -//"use strict"; - -// XXX FIXME Hardcoded '4' in many places, here and in library_SDL, for RGBA +/* + * GL support. See https://github.com/kripken/emscripten/wiki/OpenGL-support + * for current status. + */ var LibraryGL = { $GL: { - hashtable: function(name) { - if (!this._hashtables) { - this._hashtables = {}; + counter: 1, + buffers: {}, + programs: {}, + framebuffers: {}, + renderbuffers: {}, + textures: {}, + uniforms: {}, + shaders: {}, + + packAlignment: 4, // default alignment is 4 bytes + unpackAlignment: 4, // default alignment is 4 bytes + + // Linear lookup in one of the tables (buffers, programs, etc.). TODO: consider using a weakmap to make this faster, if it matters + scan: function(table, object) { + for (var item in table) { + if (table[item] == object) return item; } - if (!(name in this._hashtables)) { - this._hashtables[name] = { - table: {}, - counter: 1, - add: function(obj) { - var id = this.counter++; - this.table[id] = obj; - return id; - }, - get: function(id) { - if( id == 0 ) return null; -#if ASSERTIONS - assert(id < this.counter, "Invalid id " + id + " for the hashtable " + name); -#endif - return this.table[id]; - }, - remove: function(id) { - if( id == 0 ) return; -#if ASSERTIONS - assert(id < this.counter, "Invalid id " + id + " for the hashtable " + name); -#endif - delete this.table[id]; + return 0; + }, + + // Find a token in a shader source string + findToken: function(source, token) { + function isIdentChar(ch) { + if (ch >= 48 && ch <= 57) // 0-9 + return true; + if (ch >= 65 && ch <= 90) // A-Z + return true; + if (ch >= 97 && ch <= 122) // a-z + return true; + return false; + } + var i = -1; + do { + i = source.indexOf(token, i + 1); + if (i < 0) { + break; + } + if (i > 0 && isIdentChar(source[i - 1])) { + continue; + } + i += token.length; + if (i < source.length - 1 && isIdentChar(source[i + 1])) { + continue; + } + return true; + } while (true); + return false; + }, + + getSource: function(shader, count, string, length) { + var source = ''; + for (var i = 0; i < count; ++i) { + var frag; + if (length) { + var len = {{{ makeGetValue('length', 'i*4', 'i32') }}}; + if (len < 0) { + frag = Pointer_stringify({{{ makeGetValue('string', 'i*4', 'i32') }}}); + } else { + frag = Pointer_stringify({{{ makeGetValue('string', 'i*4', 'i32') }}}, len); } - }; + } else { + frag = Pointer_stringify({{{ makeGetValue('string', 'i*4', 'i32') }}}); + } + source += frag; + } + // Let's see if we need to enable the standard derivatives extension + type = Module.ctx.getShaderParameter(GL.shaders[shader], 0x8B4F /* GL_SHADER_TYPE */); + if (type == 0x8B30 /* GL_FRAGMENT_SHADER */) { + if (GL.findToken(source, "dFdx") || + GL.findToken(source, "dFdy") || + GL.findToken(source, "fwidth")) { + source = "#extension GL_OES_standard_derivatives : enable\n" + source; + var extension = Module.ctx.getExtension("OES_standard_derivatives"); +#if GL_DEBUG + if (!extension) { + Module.printErr("Shader attempts to use the standard derivatives extension which is not available."); + } +#endif + } } - return this._hashtables[name]; + return source; }, + + computeImageSize: function(width, height, sizePerPixel, alignment) { + function roundedToNextMultipleOf(x, y) { + return Math.floor((x + y - 1) / y) * y + } + var plainRowSize = width * sizePerPixel; + var alignedRowSize = roundedToNextMultipleOf(plainRowSize, alignment); + return (height <= 0) ? 0 : + ((height - 1) * alignedRowSize + plainRowSize); + } + }, + + glPixelStorei: function(pname, param) { + if (pname == 0x0D05 /* GL_PACK_ALIGNMENT */) { + GL.packAlignment = param; + } else if (pname == 0x0cf5 /* GL_UNPACK_ALIGNMENT */) { + GL.unpackAlignment = param; + } + Module.ctx.pixelStorei(pname, param); }, glGetString: function(name_) { switch(name_) { - case Module.ctx.VENDOR: - case Module.ctx.RENDERER: - case Module.ctx.VERSION: + case 0x1F00 /* GL_VENDOR */: + case 0x1F01 /* GL_RENDERER */: + case 0x1F02 /* GL_VERSION */: return allocate(intArrayFromString(Module.ctx.getParameter(name_)), 'i8', ALLOC_NORMAL); - case 0x1F03: // Extensions + case 0x1F03 /* GL_EXTENSIONS */: return allocate(intArrayFromString(Module.ctx.getSupportedExtensions().join(' ')), 'i8', ALLOC_NORMAL); default: throw 'Failure: Invalid glGetString value: ' + name_; @@ -51,289 +122,674 @@ var LibraryGL = { }, glGetIntegerv: function(name_, p) { - {{{ makeSetValue('p', '0', 'Module.ctx.getParameter(name_)', 'i32') }}}; + var result = Module.ctx.getParameter(name_); + switch (typeof(result)) { + case "number": + {{{ makeSetValue('p', '0', 'result', 'i32') }}}; + break; + case "boolean": + {{{ makeSetValue('p', '0', 'result ? 1 : 0', 'i8') }}}; + break; + case "string": + throw 'Native code calling glGetIntegerv(' + name_ + ') on a name which returns a string!'; + case "object": + if (result === null) { + {{{ makeSetValue('p', '0', '0', 'i32') }}}; + } else if (result instanceof Float32Array || + result instanceof Uint32Array || + result instanceof Int32Array || + result instanceof Array) { + for (var i = 0; i < result.length; ++i) { + {{{ makeSetValue('p', 'i*4', 'result[i]', 'i32') }}}; + } + } else if (result instanceof WebGLBuffer) { + {{{ makeSetValue('p', '0', 'GL.scan(GL.buffers, result)', 'i32') }}}; + } else if (result instanceof WebGLProgram) { + {{{ makeSetValue('p', '0', 'GL.scan(GL.programs, result)', 'i32') }}}; + } else if (result instanceof WebGLFramebuffer) { + {{{ makeSetValue('p', '0', 'GL.scan(GL.framebuffers, result)', 'i32') }}}; + } else if (result instanceof WebGLRenderbuffer) { + {{{ makeSetValue('p', '0', 'GL.scan(GL.renderbuffers, result)', 'i32') }}}; + } else if (result instanceof WebGLTexture) { + {{{ makeSetValue('p', '0', 'GL.scan(GL.textures, result)', 'i32') }}}; + } else { + throw 'Unknown object returned from WebGL getParameter'; + } + break; + case "undefined": + throw 'Native code calling glGetIntegerv(' + name_ + ') and it returns undefined'; + default: + throw 'Why did we hit the default case?'; + } + }, + + glGetFloatv: function(name_, p) { + var result = Module.ctx.getParameter(name_); + switch (typeof(result)) { + case "number": + {{{ makeSetValue('p', '0', 'result', 'float') }}}; + break; + case "boolean": + {{{ makeSetValue('p', '0', 'result ? 1.0 : 0.0', 'float') }}}; + break; + case "string": + {{{ makeSetValue('p', '0', '0', 'float') }}}; + case "object": + if (result === null) { + throw 'Native code calling glGetFloatv(' + name_ + ') and it returns null'; + } else if (result instanceof Float32Array || + result instanceof Uint32Array || + result instanceof Int32Array || + result instanceof Array) { + for (var i = 0; i < result.length; ++i) { + {{{ makeSetValue('p', 'i*4', 'result[i]', 'float') }}}; + } + } else if (result instanceof WebGLBuffer) { + {{{ makeSetValue('p', '0', 'GL.scan(GL.buffers, result)', 'float') }}}; + } else if (result instanceof WebGLProgram) { + {{{ makeSetValue('p', '0', 'GL.scan(GL.programs, result)', 'float') }}}; + } else if (result instanceof WebGLFramebuffer) { + {{{ makeSetValue('p', '0', 'GL.scan(GL.framebuffers, result)', 'float') }}}; + } else if (result instanceof WebGLRenderbuffer) { + {{{ makeSetValue('p', '0', 'GL.scan(GL.renderbuffers, result)', 'float') }}}; + } else if (result instanceof WebGLTexture) { + {{{ makeSetValue('p', '0', 'GL.scan(GL.textures, result)', 'float') }}}; + } else { + throw 'Unknown object returned from WebGL getParameter'; + } + break; + case "undefined": + throw 'Native code calling glGetFloatv(' + name_ + ') and it returns undefined'; + default: + throw 'Why did we hit the default case?'; + } + }, + + glGetBooleanv: function(name_, p) { + var result = Module.ctx.getParameter(name_); + switch (typeof(result)) { + case "number": + {{{ makeSetValue('p', '0', 'result != 0', 'i8') }}}; + break; + case "boolean": + {{{ makeSetValue('p', '0', 'result != 0', 'i8') }}}; + break; + case "string": + throw 'Native code calling glGetBooleanv(' + name_ + ') on a name which returns a string!'; + case "object": + if (result === null) { + {{{ makeSetValue('p', '0', '0', 'i8') }}}; + } else if (result instanceof Float32Array || + result instanceof Uint32Array || + result instanceof Int32Array || + result instanceof Array) { + for (var i = 0; i < result.length; ++i) { + {{{ makeSetValue('p', 'i', 'result[i] != 0', 'i8') }}}; + } + } else if (result instanceof WebGLBuffer || + result instanceof WebGLProgram || + result instanceof WebGLFramebuffer || + result instanceof WebGLRenderbuffer || + result instanceof WebGLTexture) { + {{{ makeSetValue('p', '0', '1', 'i8') }}}; // non-zero ID is always 1! + } else { + throw 'Unknown object returned from WebGL getParameter'; + } + break; + case "undefined": + throw 'Unknown object returned from WebGL getParameter'; + default: + throw 'Why did we hit the default case?'; + } }, - glGenTextures__deps: ['$GL'], glGenTextures: function(n, textures) { for (var i = 0; i < n; i++) { - var id = GL.hashtable("texture").add(Module.ctx.createTexture()); - {{{ makeSetValue('textures', 'i', 'id', 'i32') }}}; + var id = GL.counter++; + GL.textures[id] = Module.ctx.createTexture(); + {{{ makeSetValue('textures', 'i*4', 'id', 'i32') }}}; } }, glDeleteTextures: function(n, textures) { for (var i = 0; i < n; i++) { - var id = {{{ makeGetValue('textures', 'i', 'i32') }}}; - Module.ctx.deleteTexture(GL.hashtable("texture").get(id)); - GL.hashtable("texture").remove(id); + var id = {{{ makeGetValue('textures', 'i*4', 'i32') }}}; + Module.ctx.deleteTexture(GL.textures[id]); + GL.textures[id] = null; + } + }, + + glCompressedTexImage2D: function(target, level, internalformat, width, height, border, imageSize, data) { + if (data) { + data = {{{ makeHEAPView('U8', 'data', 'data+imageSize') }}}; + } else { + data = null; } + Module.ctx.compressedTexImage2D(target, level, internalformat, width, height, border, data); + }, + + glCompressedTexSubImage2D: function(target, level, xoffset, yoffset, width, height, format, imageSize, data) { + if (data) { + data = {{{ makeHEAPView('U8', 'data', 'data+imageSize') }}}; + } else { + data = null; + } + Module.ctx.compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, data); }, glTexImage2D: function(target, level, internalformat, width, height, border, format, type, pixels) { if (pixels) { - pixels = new Uint8Array(Array_copy(pixels, pixels + width*height*4)); // TODO: optimize + var sizePerPixel; + switch (type) { + case 0x1401 /* GL_UNSIGNED_BYTE */: + switch (format) { + case 0x1906 /* GL_ALPHA */: + case 0x1909 /* GL_LUMINANCE */: + sizePerPixel = 1; + break; + case 0x1907 /* GL_RGB */: + sizePerPixel = 3; + break; + case 0x1908 /* GL_RGBA */: + sizePerPixel = 4; + break; + case 0x190A /* GL_LUMINANCE_ALPHA */: + sizePerPixel = 2; + break; + default: + throw 'Invalid format (' + format + ') passed to glTexImage2D'; + } + break; + case 0x8363 /* GL_UNSIGNED_SHORT_5_6_5 */: + case 0x8033 /* GL_UNSIGNED_SHORT_4_4_4_4 */: + case 0x8034 /* GL_UNSIGNED_SHORT_5_5_5_1 */: + sizePerPixel = 2; + break; + default: + throw 'Invalid type (' + type + ') passed to glTexImage2D'; + } + var bytes = GL.computeImageSize(width, height, sizePerPixel, GL.unpackAlignment); + pixels = {{{ makeHEAPView('U8', 'pixels', 'pixels+bytes') }}}; + } else { + pixels = null; } Module.ctx.texImage2D(target, level, internalformat, width, height, border, format, type, pixels); }, glTexSubImage2D: function(target, level, xoffset, yoffset, width, height, format, type, pixels) { if (pixels) { - pixels = new Uint8Array(Array_copy(pixels, pixels + width*height*4)); // TODO: optimize + var sizePerPixel; + switch (type) { + case 0x1401 /* GL_UNSIGNED_BYTE */: + switch (format) { + case 0x1906 /* GL_ALPHA */: + case 0x1909 /* GL_LUMINANCE */: + sizePerPixel = 1; + break; + case 0x1907 /* GL_RGB */: + sizePerPixel = 3; + break; + case 0x1908 /* GL_RGBA */: + sizePerPixel = 4; + break; + case 0x190A /* GL_LUMINANCE_ALPHA */: + sizePerPixel = 2; + break; + default: + throw 'Invalid format (' + format + ') passed to glTexSubImage2D'; + } + break; + case 0x8363 /* GL_UNSIGNED_SHORT_5_6_5 */: + case 0x8033 /* GL_UNSIGNED_SHORT_4_4_4_4 */: + case 0x8034 /* GL_UNSIGNED_SHORT_5_5_5_1 */: + sizePerPixel = 2; + break; + default: + throw 'Invalid type (' + type + ') passed to glTexSubImage2D'; + } + var bytes = GL.computeImageSize(width, height, sizePerPixel, GL.unpackAlignment); + pixels = {{{ makeHEAPView('U8', 'pixels', 'pixels+bytes') }}}; + } else { + pixels = null; } Module.ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); }, + glReadPixels: function(x, y, width, height, format, type, pixels) { + Module.ctx.readPixels(x, y, width, height, format, type, HEAPU8.subarray(pixels)); + }, + glBindTexture: function(target, texture) { - Module.ctx.bindTexture(target, GL.hashtable("texture").get(texture)); + Module.ctx.bindTexture(target, GL.textures[texture]); + }, + + glGetTexParameterfv: function(target, pname, params) { + {{{ makeSetValue('params', '0', 'Module.getTexParameter(target, pname)', 'float') }}}; + }, + + glGetTexParameteriv: function(target, pname, params) { + {{{ makeSetValue('params', '0', 'Module.getTexParameter(target, pname)', 'i32') }}}; + }, + + glIsTexture: function(texture) { + var fb = GL.textures[texture]; + if (typeof(fb) == 'undefined') { + return 0; + } + return Module.ctx.isTexture(fb); }, - glGenBuffers__deps: ['$GL'], glGenBuffers: function(n, buffers) { for (var i = 0; i < n; i++) { - var id = GL.hashtable("buffer").add(Module.ctx.createBuffer()); - {{{ makeSetValue('buffers', 'i', 'id', 'i32') }}}; + var id = GL.counter++; + GL.buffers[id] = Module.ctx.createBuffer(); + {{{ makeSetValue('buffers', 'i*4', 'id', 'i32') }}}; } }, glDeleteBuffers: function(n, buffers) { for (var i = 0; i < n; i++) { - var id = {{{ makeGetValue('buffers', 'i', 'i32') }}}; - Module.ctx.deleteBuffer(GL.hashtable("buffer").get(id)); - GL.hashtable("buffer").remove(id); + var id = {{{ makeGetValue('buffers', 'i*4', 'i32') }}}; + Module.ctx.deleteBuffer(GL.buffers[id]); + GL.buffers[id] = null; } }, + glGetBufferParameteriv: function(target, value, data) { + {{{ makeSetValue('data', '0', 'Module.ctx.getBufferParameter(target, value)', 'i32') }}}; + }, + glBufferData: function(target, size, data, usage) { - var floatArray = new Float32Array(TypedArray_copy(data, size)); - Module.ctx.bufferData(target, floatArray, usage); + Module.ctx.bufferData(target, HEAPU8.subarray(data, data+size), usage); + }, + + glBufferSubData: function(target, offset, size, data) { + var floatArray = {{{ makeHEAPView('F32', 'data', 'data+size') }}}; + Module.ctx.bufferSubData(target, offset, floatArray); + }, + + glIsBuffer: function(buffer) { + var fb = GL.buffers[buffer]; + if (typeof(fb) == 'undefined') { + return 0; + } + return Module.ctx.isBuffer(fb); + }, + + glGenRenderbuffers: function(n, renderbuffers) { + for (var i = 0; i < n; i++) { + var id = GL.counter++; + GL.renderbuffers[id] = Module.ctx.createRenderbuffer(); + {{{ makeSetValue('renderbuffers', 'i*4', 'id', 'i32') }}}; + } + }, + + glDeleteRenderbuffers: function(n, renderbuffers) { + for (var i = 0; i < n; i++) { + var id = {{{ makeGetValue('renderbuffers', 'i*4', 'i32') }}}; + Module.ctx.deleteRenderbuffer(GL.renderbuffers[id]); + GL.renderbuffers[id]; + } + }, + + glBindRenderbuffer: function(target, renderbuffer) { + Module.ctx.bindRenderbuffer(target, GL.renderbuffers[renderbuffer]); + }, + + glGetRenderbufferParameteriv: function(target, pname, params) { + {{{ makeSetValue('params', '0', 'Module.ctx.getRenderbufferParameter(target, pname)', 'i32') }}}; + }, + + glIsRenderbuffer: function(renderbuffer) { + var fb = GL.renderbuffers[renderbuffer]; + if (typeof(fb) == 'undefined') { + return 0; + } + return Module.ctx.isRenderbuffer(fb); + }, + + glGetUniformfv: function(program, location, params) { + var data = Module.ctx.getUniform(GL.programs[program], GL.uniforms[location]); + if (typeof data == 'number') { + {{{ makeSetValue('params', '0', 'data', 'float') }}}; + } else { + for (var i = 0; i < data.length; i++) { + {{{ makeSetValue('params', 'i', 'data[i]', 'float') }}}; + } + } + }, + + glGetUniformiv: function(program, location, params) { + var data = Module.ctx.getUniform(GL.programs[program], GL.uniforms[location]); + if (typeof data == 'number' || typeof data == 'boolean') { + {{{ makeSetValue('params', '0', 'data', 'i32') }}}; + } else { + for (var i = 0; i < data.length; i++) { + {{{ makeSetValue('params', 'i', 'data[i]', 'i32') }}}; + } + } }, - glBindAttribLocation_deps: ['$GL'], glGetUniformLocation: function(program, name) { name = Pointer_stringify(name); - return GL.hashtable("uniform").add( - Module.ctx.getUniformLocation(GL.hashtable("program").get(program), name)); + var loc = Module.ctx.getUniformLocation(GL.programs[program], name); + if (!loc) return -1; + var id = GL.counter++; + GL.uniforms[id] = loc; + return id; + }, + + glGetVertexAttribfv: function(index, pname, params) { + var data = Module.ctx.getVertexAttrib(index, pname); + if (typeof data == 'number') { + {{{ makeSetValue('params', '0', 'data', 'float') }}}; + } else { + for (var i = 0; i < data.length; i++) { + {{{ makeSetValue('params', 'i', 'data[i]', 'float') }}}; + } + } + }, + + glGetVertexAttribiv: function(index, pname, params) { + var data = Module.ctx.getVertexAttrib(index, pname); + if (typeof data == 'number' || typeof data == 'boolean') { + {{{ makeSetValue('params', '0', 'data', 'i32') }}}; + } else { + for (var i = 0; i < data.length; i++) { + {{{ makeSetValue('params', 'i', 'data[i]', 'i32') }}}; + } + } + }, + + glGetVertexAttribPointerv: function(index, pname, pointer) { + {{{ makeSetValue('pointer', '0', 'Module.ctx.getVertexAttribOffset(index, pname)', 'i32') }}}; + }, + + glGetActiveUniform: function(program, index, bufSize, length, size, type, name) { + program = GL.programs[program]; + var info = Module.ctx.getActiveUniform(program, index); + + var infoname = info.name.slice(0, bufsize - 1); + writeStringToMemory(infoname, name); + + if (length) { + {{{ makeSetValue('length', '0', 'infoname.length', 'i32') }}}; + } + if (size) { + {{{ makeSetValue('size', '0', 'info.size', 'i32') }}}; + } + if (type) { + {{{ makeSetValue('type', '0', 'info.type', 'i32') }}}; + } }, - glUniform1f: function(Location, v0) { - Location = GL.hashtable("uniform").get(Location); - Module.ctx.uniform1f(Location, v0); + glUniform1f: function(location, v0) { + location = GL.uniforms[location]; + Module.ctx.uniform1f(location, v0); }, - glUniform2f: function(Location, v0, v1) { - Location = GL.hashtable("uniform").get(Location); - Module.ctx.uniform2f(Location, v0, v1); + glUniform2f: function(location, v0, v1) { + location = GL.uniforms[location]; + Module.ctx.uniform2f(location, v0, v1); }, - glUniform3f: function(Location, v0, v1, v2) { - Location = GL.hashtable("uniform").get(Location); - Module.ctx.uniform3f(Location, v0, v1, v2); + glUniform3f: function(location, v0, v1, v2) { + location = GL.uniforms[location]; + Module.ctx.uniform3f(location, v0, v1, v2); }, - glUniform4f: function(Location, v0, v1, v2, v3) { - Location = GL.hashtable("uniform").get(Location); - Module.ctx.uniform4f(Location, v0, v1, v2, v3); + glUniform4f: function(location, v0, v1, v2, v3) { + location = GL.uniforms[location]; + Module.ctx.uniform4f(location, v0, v1, v2, v3); }, - glUniform1i: function(Location, v0) { - Location = GL.hashtable("uniform").get(Location); - Module.ctx.uniform1i(Location, v0); + glUniform1i: function(location, v0) { + location = GL.uniforms[location]; + Module.ctx.uniform1i(location, v0); }, - glUniform2i: function(Location, v0, v1) { - Location = GL.hashtable("uniform").get(Location); - Module.ctx.uniform2i(Location, v0, v1); + glUniform2i: function(location, v0, v1) { + location = GL.uniforms[location]; + Module.ctx.uniform2i(location, v0, v1); }, - glUniform3i: function(Location, v0, v1, v2) { - Location = GL.hashtable("uniform").get(Location); - Module.ctx.uniform3i(Location, v0, v1, v2); + glUniform3i: function(location, v0, v1, v2) { + location = GL.uniforms[location]; + Module.ctx.uniform3i(location, v0, v1, v2); }, - glUniform4i: function(Location, v0, v1, v2, v3) { - Location = GL.hashtable("uniform").get(Location); - Module.ctx.uniform4i(Location, v0, v1, v2, v3); + glUniform4i: function(location, v0, v1, v2, v3) { + location = GL.uniforms[location]; + Module.ctx.uniform4i(location, v0, v1, v2, v3); }, - glUniform1fv: function(Location, count, value) { - Location = GL.hashtable("uniform").get(Location); - value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize - Module.ctx.uniform1fv(Location, value); + glUniform1iv: function(location, count, value) { + location = GL.uniforms[location]; + value = {{{ makeHEAPView('32', 'value', 'value+count*4') }}}; + Module.ctx.uniform1iv(location, value); }, - glUniform2fv: function(Location, count, value) { - Location = GL.hashtable("uniform").get(Location); + glUniform2iv: function(location, count, value) { + location = GL.uniforms[location]; count *= 2; - value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize - Module.ctx.uniform2fv(Location, value); + value = {{{ makeHEAPView('32', 'value', 'value+count*4') }}}; + Module.ctx.uniform2iv(location, value); }, - glUniform3fv: function(Location, count, value) { - Location = GL.hashtable("uniform").get(Location); + glUniform3iv: function(location, count, value) { + location = GL.uniforms[location]; count *= 3; - value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize - Module.ctx.uniform3fv(Location, value); + value = {{{ makeHEAPView('32', 'value', 'value+count*4') }}}; + Module.ctx.uniform3iv(location, value); }, - glUniform4fv: function(Location, count, value) { - Location = GL.hashtable("uniform").get(Location); + glUniform4iv: function(location, count, value) { + location = GL.uniforms[location]; count *= 4; - value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize - Module.ctx.uniform4fv(Location, value); + value = {{{ makeHEAPView('32', 'value', 'value+count*4') }}}; + Module.ctx.uniform4iv(location, value); }, - glUniform1fi: function(Location, count, value) { - Location = GL.hashtable("uniform").get(Location); - value = new Uint32Array(TypedArray_copy(value, count*4)); // TODO: optimize - Module.ctx.uniform1fi(Location, value); + glUniform1fv: function(location, count, value) { + location = GL.uniforms[location]; + value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}}; + Module.ctx.uniform1fv(location, value); }, - glUniform2fi: function(Location, count, value) { - Location = GL.hashtable("uniform").get(Location); + glUniform2fv: function(location, count, value) { + location = GL.uniforms[location]; count *= 2; - value = new Uint32Array(TypedArray_copy(value, count*4)); // TODO: optimize - Module.ctx.uniform2fi(Location, value); + value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}}; + Module.ctx.uniform2fv(location, value); }, - glUniform3fi: function(Location, count, value) { - Location = GL.hashtable("uniform").get(Location); + glUniform3fv: function(location, count, value) { + location = GL.uniforms[location]; count *= 3; - value = new Uint32Array(TypedArray_copy(value, count*4)); // TODO: optimize - Module.ctx.uniform3fi(Location, value); + value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}}; + Module.ctx.uniform3fv(location, value); }, - glUniform4fi: function(Location, count, value) { - Location = GL.hashtable("uniform").get(Location); + glUniform4fv: function(location, count, value) { + location = GL.uniforms[location]; count *= 4; - value = new Uint32Array(TypedArray_copy(value, count*4)); // TODO: optimize - Module.ctx.uniform4fi(Location, value); + value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}}; + Module.ctx.uniform4fv(location, value); }, - glUniformMatrix2fv: function(Location, count, transpose, value) { - Location = GL.hashtable("uniform").get(Location); + glUniformMatrix2fv: function(location, count, transpose, value) { + location = GL.uniforms[location]; count *= 4; - value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize - Module.ctx.uniformMatrix2fv(Location, transpose, value); + value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}}; + Module.ctx.uniformMatrix2fv(location, transpose, value); }, - glUniformMatrix3fv: function(Location, count, transpose, value) { - Location = GL.hashtable("uniform").get(Location); + glUniformMatrix3fv: function(location, count, transpose, value) { + location = GL.uniforms[location]; count *= 9; - value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize - Module.ctx.uniformMatrix3fv(Location, transpose, value); + value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}}; + Module.ctx.uniformMatrix3fv(location, transpose, value); }, - glUniformMatrix4fv: function(Location, count, transpose, value) { - Location = GL.hashtable("uniform").get(Location); + glUniformMatrix4fv: function(location, count, transpose, value) { + location = GL.uniforms[location]; count *= 16; - value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize - Module.ctx.uniformMatrix4fv(Location, transpose, value); + value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}}; + Module.ctx.uniformMatrix4fv(location, transpose, value); }, glBindBuffer: function(target, buffer) { - Module.ctx.bindBuffer(target, GL.hashtable("buffer").get(buffer)); + Module.ctx.bindBuffer(target, GL.buffers[buffer]); }, glVertexAttrib1fv: function(index, v) { - v = new Float32Array(TypedArray_copy(v, 1*4)); // TODO: optimize + v = {{{ makeHEAPView('F32', 'v', 'v+1*4') }}}; Module.ctx.vertexAttrib1fv(index, v); }, glVertexAttrib2fv: function(index, v) { - v = new Float32Array(TypedArray_copy(v, 2*4)); // TODO: optimize + v = {{{ makeHEAPView('F32', 'v', 'v+2*4') }}}; Module.ctx.vertexAttrib2fv(index, v); }, glVertexAttrib3fv: function(index, v) { - v = new Float32Array(TypedArray_copy(v, 3*4)); // TODO: optimize + v = {{{ makeHEAPView('F32', 'v', 'v+3*4') }}}; Module.ctx.vertexAttrib3fv(index, v); }, glVertexAttrib4fv: function(index, v) { - v = new Float32Array(TypedArray_copy(v, 4*4)); // TODO: optimize + v = {{{ makeHEAPView('F32', 'v', 'v+4*4') }}}; Module.ctx.vertexAttrib4fv(index, v); }, glGetAttribLocation: function(program, name) { - program = GL.hashtable("program").get(program); + program = GL.programs[program]; name = Pointer_stringify(name); - Module.ctx.getAttribLocation(program, name); + return Module.ctx.getAttribLocation(program, name); + }, + + glGetActiveAttrib: function(program, index, bufSize, length, size, type, name) { + program = GL.programs[program]; + var info = Module.ctx.getActiveAttrib(program, index); + + var infoname = info.name.slice(0, bufsize - 1); + writeStringToMemory(infoname, name); + + if (length) { + {{{ makeSetValue('length', '0', 'infoname.length', 'i32') }}}; + } + if (size) { + {{{ makeSetValue('size', '0', 'info.size', 'i32') }}}; + } + if (type) { + {{{ makeSetValue('type', '0', 'info.type', 'i32') }}}; + } }, - glCreateShader_deps: ['$GL'], glCreateShader: function(shaderType) { - var shader = Module.ctx.createShader(shaderType); - return GL.hashtable("shader").add(shader); + var id = GL.counter++; + GL.shaders[id] = Module.ctx.createShader(shaderType); + return id; + }, + + glDeleteShader: function(shader) { + Module.ctx.deleteShader(GL.shaders[shader]); + GL.shaders[shader] = null; + }, + + glDetachShader: function(program, shader) { + Module.ctx.detachShader(GL.programs[program], + GL.shaders[shader]); + }, + + glGetAttachedShaders: function(program, maxCount, count, shaders) { + var result = Module.ctx.getAttachedShaders(GL.programs[program]); + var len = result.length; + if (len > maxCount) { + len = maxCount; + } + {{{ makeSetValue('count', '0', 'len', 'i32') }}}; + for (var i = 0; i < len; ++i) { + {{{ makeSetValue('shaders', 'i*4', 'GL.shaders[result[i]]', 'i32') }}}; + } }, - glShaderSource_deps: ['$GL'], glShaderSource: function(shader, count, string, length) { - var source = ""; - for (var i = 0; i < count; ++i) { - var frag = string[i]; - if (length) { - var len = {{{ makeGetValue('length', 'i', 'i32') }}}; - if (len < 0) { - frag = Pointer_stringify({{{ makeGetValue('string', 'i', 'i32') }}}); - } else { - frag = Pointer_stringify({{{ makeGetValue('string', 'i', 'i32') }}}, len); - } - } else { - frag = Pointer_stringify({{{ makeGetValue('string', 'i', 'i32') }}}); - } - if (source.length) { - source += "\n"; - } - source += frag; + var source = GL.getSource(shader, count, string, length); + Module.ctx.shaderSource(GL.shaders[shader], source); + }, + + glGetShaderSource: function(shader, bufsize, length, source) { + var result = Module.ctx.getShaderSource(GL.shaders[shader]); + result.slice(0, bufsize - 1); + writeStringToMemory(result, source); + if (length) { + {{{ makeSetValue('length', '0', 'result.length', 'i32') }}}; } - Module.ctx.shaderSource(GL.hashtable("shader").get(shader), source); }, - glCompileShader_deps: ['$GL'], glCompileShader: function(shader) { - Module.ctx.compileShader(GL.hashtable("shader").get(shader)); + Module.ctx.compileShader(GL.shaders[shader]); }, - glGetShaderInfoLog_deps: ['$GL'], glGetShaderInfoLog: function(shader, maxLength, length, infoLog) { - var log = Module.ctx.getShaderInfoLog(GL.hashtable("shader").get(shader)); - log.slice(0, maxLength - 1); + var log = Module.ctx.getShaderInfoLog(GL.shaders[shader]); + // Work around a bug in Chromium which causes getShaderInfoLog to return null + if (!log) { + log = ""; + } + log = log.substr(0, maxLength - 1); writeStringToMemory(log, infoLog); if (length) { - {{{ makeSetValue('length', 'i', 'log.length', 'i32') }}} + {{{ makeSetValue('length', '0', 'log.length', 'i32') }}} } }, - - glGetShaderiv_deps: ['$GL'], - glGetShaderiv : function(shader, pname, p) { - {{{ makeSetValue('p', '0', 'Module.ctx.getShaderParameter(GL.hashtable("shader").get(shader),pname)', 'i32') }}}; + + glGetShaderiv : function(shader, pname, p) { + {{{ makeSetValue('p', '0', 'Module.ctx.getShaderParameter(GL.shaders[shader], pname)', 'i32') }}}; + }, + + glGetProgramiv : function(program, pname, p) { + {{{ makeSetValue('p', '0', 'Module.ctx.getProgramParameter(GL.programs[program], pname)', 'i32') }}}; }, - glGetProgramiv_deps: ['$GL'], - glGetProgramiv : function(program, pname, p) { - {{{ makeSetValue('p', '0', 'Module.ctx.getProgramParameter(GL.hashtable("program").get(program),pname)', 'i32') }}}; + glIsShader: function(shader) { + var fb = GL.shaders[shader]; + if (typeof(fb) == 'undefined') { + return 0; + } + return Module.ctx.isShader(fb); }, - glCreateProgram_deps: ['$GL'], glCreateProgram: function() { - return GL.hashtable("program").add(Module.ctx.createProgram()); + var id = GL.counter++; + GL.programs[id] = Module.ctx.createProgram(); + return id; + }, + + glDeleteProgram: function(program) { + Module.ctx.deleteProgram(GL.programs[program]); + GL.programs[program] = null; }, - glAttachShader_deps: ['$GL'], glAttachShader: function(program, shader) { - Module.ctx.attachShader(GL.hashtable("program").get(program), - GL.hashtable("shader").get(shader)); + Module.ctx.attachShader(GL.programs[program], + GL.shaders[shader]); + }, + + glGetShaderPrecisionFormat: function(shaderType, precisionType, range, precision) { + var result = Module.ctx.getShaderPrecisionFormat(shaderType, precisionType); + {{{ makeSetValue('range', '0', 'result.rangeMin', 'i32') }}}; + {{{ makeSetValue('range', '4', 'result.rangeMax', 'i32') }}}; + {{{ makeSetValue('precision', '0', 'result.precision', 'i32') }}}; }, - glLinkProgram_deps: ['$GL'], glLinkProgram: function(program) { - Module.ctx.linkProgram(GL.hashtable("program").get(program)); + Module.ctx.linkProgram(GL.programs[program]); }, - glGetProgramInfoLog_deps: ['$GL'], glGetProgramInfoLog: function(program, maxLength, length, infoLog) { - var log = Module.ctx.getProgramInfoLog(GL.hashtable("program").get(program)); + var log = Module.ctx.getProgramInfoLog(GL.programs[program]); // Work around a bug in Chromium which causes getProgramInfoLog to return null if (!log) { log = ""; @@ -341,224 +797,790 @@ var LibraryGL = { log = log.substr(0, maxLength - 1); writeStringToMemory(log, infoLog); if (length) { - {{{ makeSetValue('length', 'i', 'log.length', 'i32') }}} + {{{ makeSetValue('length', '0', 'log.length', 'i32') }}} } }, - glUseProgram_deps: ['$Gl'], glUseProgram: function(program) { - Module.ctx.useProgram(GL.hashtable("program").get(program)); + Module.ctx.useProgram(GL.programs[program]); + }, + + glValidateProgram: function(program) { + Module.ctx.validateProgram(GL.programs[program]); + }, + + glIsProgram: function(program) { + var fb = GL.programs[program]; + if (typeof(fb) == 'undefined') { + return 0; + } + return Module.ctx.isProgram(fb); }, - glBindAttribLocation_deps: ['$GL'], glBindAttribLocation: function(program, index, name) { name = Pointer_stringify(name); - Module.ctx.bindAttribLocation(GL.hashtable("program").get(program), index, name); + Module.ctx.bindAttribLocation(GL.programs[program], index, name); }, - glBindFramebuffer_deps: ['$GL'], glBindFramebuffer: function(target, framebuffer) { - Module.ctx.bindFramebuffer(target, GL.hashtable("framebuffer").get(framebuffer)); + Module.ctx.bindFramebuffer(target, GL.framebuffers[framebuffer]); }, - glGenFramebuffers_deps: ['$GL'], glGenFramebuffers: function(n, ids) { for (var i = 0; i < n; ++i) { - var fb = GL.hashtable("framebuffer").add(Module.ctx.createFramebuffer()); - {{{ makeSetValue('ids', 'i', 'fb', 'i32') }}}; + var id = GL.counter++; + GL.framebuffers[id] = Module.ctx.createFramebuffer(); + {{{ makeSetValue('ids', 'i*4', 'id', 'i32') }}}; } }, - glDeleteFramebuffers_deps: ['$GL'], glDeleteFramebuffers: function(n, framebuffers) { for (var i = 0; i < n; ++i) { - var fb = GL.hashtable("framebuffer").get({{{ makeGetValue('framebuffers', 'i', 'i32' ) }}}); - Module.ctx.deleteFramebuffer(fb); + var id = {{{ makeGetValue('framebuffers', 'i*4', 'i32') }}}; + Module.ctx.deleteFramebuffer(GL.framebuffers[id]); + GL.framebuffers[id] = null; } }, - glFramebufferRenderbuffer_deps: ['$GL'], glFramebufferRenderbuffer: function(target, attachment, renderbuffertarget, renderbuffer) { Module.ctx.framebufferRenderbuffer(target, attachment, renderbuffertarget, - GL.hashtable("renderbuffer").get(renderbuffer)); + GL.renderbuffers[renderbuffer]); }, - glFramebufferTexture2D_deps: ['$GL'], glFramebufferTexture2D: function(target, attachment, textarget, texture, level) { Module.ctx.framebufferTexture2D(target, attachment, textarget, - GL.hashtable("texture").get(texture), level); + GL.textures[texture], level); }, - glGetFramebufferAttachmentParameteriv_deps: ['$GL'], glGetFramebufferAttachmentParameteriv: function(target, attachment, pname, params) { var result = Module.ctx.getFramebufferAttachmentParameter(target, attachment, pname); {{{ makeSetValue('params', '0', 'params', 'i32') }}}; }, - glIsFramebuffer_deps: ['$GL'], glIsFramebuffer: function(framebuffer) { - var fb = GL.hashtable("framebuffer").get(framebuffer); + var fb = GL.framebuffers[framebuffer]; if (typeof(fb) == 'undefined') { - return false; + return 0; } return Module.ctx.isFramebuffer(fb); }, -}; + // GL emulation: provides misc. functionality not present in OpenGL ES 2.0 or WebGL + + $GLEmulation__deps: ['glCreateShader', 'glShaderSource', 'glCompileShader', 'glCreateProgram', 'glDeleteShader', 'glDeleteProgram', 'glAttachShader', 'glActiveTexture', 'glGetShaderiv', 'glGetProgramiv', 'glLinkProgram', 'glGetProgramInfoLog', 'glGetShaderInfoLog'], + $GLEmulation__postset: 'GLEmulation.init();', + $GLEmulation: { + init: function() { + // Add some emulation workarounds + Module.printErr('WARNING: using emscripten GL emulation. This is a collection of limited workarounds, do not expect it to work'); + _glEnable = function(cap) { + if (cap == 0x0DE1) return; // GL_TEXTURE_2D + if (cap == 0x0B20) return; // GL_LINE_SMOOTH + if (cap == 0x0B60) return; // GL_FOG + Module.ctx.enable(cap); + }; + _glDisable = function(cap) { + if (cap == 0x0DE1) return; // GL_TEXTURE_2D + if (cap == 0x0B20) return; // GL_LINE_SMOOTH + if (cap == 0x0B60) return; // GL_FOG + Module.ctx.disable(cap); + }; + var glGetIntegerv = _glGetIntegerv; + _glGetIntegerv = function(pname, params) { + switch (pname) { + case 0x84E2: pname = Module.ctx.MAX_TEXTURE_IMAGE_UNITS /* fake it */; break; // GL_MAX_TEXTURE_UNITS + case 0x8B4A: { // GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB + var result = Module.ctx.getParameter(Module.ctx.MAX_VERTEX_UNIFORM_VECTORS); + {{{ makeSetValue('params', '0', 'result*4', 'i32') }}}; // GLES gives num of 4-element vectors, GL wants individual components, so multiply + return; + } + case 0x8B49: { // GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB + var result = Module.ctx.getParameter(Module.ctx.MAX_FRAGMENT_UNIFORM_VECTORS); + {{{ makeSetValue('params', '0', 'result*4', 'i32') }}}; // GLES gives num of 4-element vectors, GL wants individual components, so multiply + return; + } + case 0x8B4B: { // GL_MAX_VARYING_FLOATS_ARB + var result = Module.ctx.getParameter(Module.ctx.MAX_VARYING_VECTORS); + {{{ makeSetValue('params', '0', 'result*4', 'i32') }}}; // GLES gives num of 4-element vectors, GL wants individual components, so multiply + return; + } + } + glGetIntegerv(pname, params); + }; + // Do some automatic rewriting to work around GLSL differences. Note that this must be done in + // tandem with the rest of the program, by itself it cannot suffice. + // Note that we need to remember shader types for this rewriting, saving sources makes it easier to debug. + GL.shaderTypes = {}; + GL.shaderSources = {}; + GL.shaderOriginalSources = {}; + var glCreateShader = _glCreateShader; + _glCreateShader = function(shaderType) { + var id = glCreateShader(shaderType); + GL.shaderTypes[id] = shaderType; + return id; + }; + var glShaderSource = _glShaderSource; + _glShaderSource = function(shader, count, string, length) { + var source = GL.getSource(shader, count, string, length); + GL.shaderOriginalSources[shader] = source; + if (GL.shaderTypes[shader] == Module.ctx.VERTEX_SHADER) { + // Replace ftransform() with explicit project/modelview transforms, and add position and matrix info. + source = 'attribute vec4 a_position; \n\ + uniform mat4 u_modelView; \n\ + uniform mat4 u_projection; \n' + + source.replace(/ftransform\(\)/g, 'u_projection * u_modelView * a_position') + .replace(/gl_Vertex/g, 'a_position') + .replace(/gl_ModelViewMatrix/g, 'u_modelView') + .replace(/gl_ProjectionMatrix/g, 'u_projection') + .replace(/gl_ModelViewProjectionMatrix/g, 'u_modelView * u_projection') + .replace(/gl_ModelViewMatrixTranspose\[2\]/g, 'vec3(u_modelView[0][0], u_modelView[1][0], u_modelView[2][0])'); // XXX extremely inefficient + for (var i = 0; i <= 6; i++) { + // XXX To handle both regular texture mapping and cube mapping, we use vec4 for tex coordinates. + var old = source; + source = source.replace(new RegExp('gl_TexCoord\\[' + i + '\\]', 'g'), 'v_texCoord' + i) + .replace(new RegExp('gl_MultiTexCoord' + i, 'g'), 'a_texCoord' + i); + if (source != old) { + source = 'attribute vec4 a_texCoord' + i + '; \n\ + varying vec4 v_texCoord' + i + '; \n' + source; + } + } + if (source.indexOf('gl_Color') >= 0) { + source = 'attribute vec4 a_color; \n\ + varying vec4 v_color; \n' + + source.replace(/gl_Color/g, 'a_color').replace(/gl_FrontColor/g, 'v_color'); + } + if (source.indexOf('gl_FogFragCoord') >= 0) { + source = 'varying float v_fogCoord; \n' + + source.replace(/gl_FogFragCoord/g, 'v_fogCoord'); + } + } else { // Fragment shader + for (var i = 0; i <= 6; i++) { + var old = 0; + source = source.replace(new RegExp('gl_TexCoord\\[' + i + '\\]', 'g'), 'v_texCoord' + i); + if (source != old) { + source = 'varying vec4 v_texCoord' + i + '; \n' + source; + } + } + if (source.indexOf('gl_Color') >= 0) { + source = 'varying vec4 v_color; \n' + source.replace(/gl_Color/g, 'v_color'); + } + source = source.replace(/gl_Fog.color/g, 'vec4(0.0)'); // XXX TODO + source = 'precision mediump float;\n' + source; + } + GL.shaderSources[shader] = source; + Module.ctx.shaderSource(GL.shaders[shader], source); + }; + var glCompileShader = _glCompileShader; + _glCompileShader = function(shader) { + Module.ctx.compileShader(GL.shaders[shader]); + if (!Module.ctx.getShaderParameter(GL.shaders[shader], Module.ctx.COMPILE_STATUS)) { + console.log('Failed to compile shader: ' + Module.ctx.getShaderInfoLog(GL.shaders[shader])); + console.log('Type: ' + GL.shaderTypes[shader]); + console.log('Original source: ' + GL.shaderOriginalSources[shader]); + console.log('Source: ' + GL.shaderSources[shader]); + throw 'Shader compilation halt'; + } + }; + }, + procReplacements: { + 'glCreateShaderObjectARB': 'glCreateShader', + 'glShaderSourceARB': 'glShaderSource', + 'glCompileShaderARB': 'glCompileShader', + 'glCreateProgramObjectARB': 'glCreateProgram', + 'glAttachObjectARB': 'glAttachShader', + 'glLinkProgramARB': 'glLinkProgram', + 'glActiveTextureARB': 'glActiveTexture' + }, -// Simple pass-through functions -[[0, 'shadeModel fogi fogfv getError finish flush'], - [1, 'clearDepth depthFunc enable disable frontFace cullFace clear enableVertexAttribArray disableVertexAttribArray lineWidth clearStencil depthMask stencilMask stencilMaskSeparate checkFramebufferStatus'], - [2, 'pixelStorei vertexAttrib1f depthRange polygonOffset'], - [3, 'texParameteri texParameterf drawArrays vertexAttrib2f'], - [4, 'viewport clearColor scissor vertexAttrib3f colorMask'], - [5, 'vertexAttrib4f'], - [6, 'vertexAttribPointer']].forEach(function(data) { - var num = data[0]; - var names = data[1]; - var args = range(num).map(function(i) { return 'x' + i }).join(', '); - var stub = '(function(' + args + ') { ' + (num > 0 ? 'Module.ctx.NAME(' + args + ')' : '') + ' })'; - names.split(' ').forEach(function(name_) { - var cName = 'gl' + name_[0].toUpperCase() + name_.substr(1); -#if ASSERTIONS - assert(!(cName in LibraryGL), "Cannot reimplement the existing function " + cName); -#endif - LibraryGL[cName] = eval(stub.replace('NAME', name_)); - //print(cName + ': ' + LibraryGL[cName]); - }); -}); + procs: { + glDeleteObjectARB: function(id) { + if (GL.programs[id]) { + _glDeleteProgram(id); + } else if (GL.shaders[id]) { + _glDeleteShader(id); + } else { + console.log('WARNING: deleteObjectARB received invalid id: ' + id); + } + }, -var LibraryGLUT = { - $GLUT: { - initTime: null, - idleFunc: null, - keyboardFunc: null, - reshapeFunc: null, - lastX: 0, - lastY: 0, - - onMousemove: function(event) { - GLUT.lastX = event['clientX']; - GLUT.lastY = event['clientY']; + glGetObjectParameterivARB: function(id, type, result) { + if (GL.programs[id]) { + if (type == 0x8B84) { // GL_OBJECT_INFO_LOG_LENGTH_ARB + {{{ makeSetValue('result', '0', 'Module.ctx.getProgramInfoLog(GL.programs[id]).length', 'i32') }}}; + return; + } + _glGetProgramiv(id, type, result); + } else if (GL.shaders[id]) { + if (type == 0x8B84) { // GL_OBJECT_INFO_LOG_LENGTH_ARB + {{{ makeSetValue('result', '0', 'Module.ctx.getShaderInfoLog(GL.shaders[id]).length', 'i32') }}}; + return; + } + _glGetShaderiv(id, type, result); + } else { + console.log('WARNING: getObjectParameterivARB received invalid id: ' + id); + } + }, + + glGetInfoLogARB: function(id, maxLength, length, infoLog) { + if (GL.programs[id]) { + _glGetProgramInfoLog(id, maxLength, length, infoLog); + } else if (GL.shaders[id]) { + _glGetShaderInfoLog(id, maxLength, length, infoLog); + } else { + console.log('WARNING: getObjectParameterivARB received invalid id: ' + id); + } + } }, - onKeydown: function(event) { - if (GLUT.keyboardFunc) { - var key = null; - switch (event['keyCode']) { - case 0x70 /*DOM_VK_F1*/: key = 1 /* GLUT_KEY_F1 */; break; - case 0x71 /*DOM_VK_F2*/: key = 2 /* GLUT_KEY_F2 */; break; - case 0x72 /*DOM_VK_F3*/: key = 3 /* GLUT_KEY_F3 */; break; - case 0x73 /*DOM_VK_F4*/: key = 4 /* GLUT_KEY_F4 */; break; - case 0x74 /*DOM_VK_F5*/: key = 5 /* GLUT_KEY_F5 */; break; - case 0x75 /*DOM_VK_F6*/: key = 6 /* GLUT_KEY_F6 */; break; - case 0x76 /*DOM_VK_F7*/: key = 7 /* GLUT_KEY_F7 */; break; - case 0x77 /*DOM_VK_F8*/: key = 8 /* GLUT_KEY_F8 */; break; - case 0x78 /*DOM_VK_F9*/: key = 9 /* GLUT_KEY_F9 */; break; - case 0x79 /*DOM_VK_F10*/: key = 10 /* GLUT_KEY_F10 */; break; - case 0x7a /*DOM_VK_F11*/: key = 11 /* GLUT_KEY_F11 */; break; - case 0x7b /*DOM_VK_F12*/: key = 12 /* GLUT_KEY_F12 */; break; - case 0x25 /*DOM_VK_LEFT*/: key = 100 /* GLUT_KEY_LEFT */; break; - case 0x26 /*DOM_VK_UP*/: key = 101 /* GLUT_KEY_UP */; break; - case 0x27 /*DOM_VK_RIGHT*/: key = 102 /* GLUT_KEY_RIGHT */; break; - case 0x28 /*DOM_VK_DOWN*/: key = 103 /* GLUT_KEY_DOWN */; break; - case 0x21 /*DOM_VK_PAGE_UP*/: key = 104 /* GLUT_KEY_PAGE_UP */; break; - case 0x22 /*DOM_VK_PAGE_DOWN*/: key = 105 /* GLUT_KEY_PAGE_DOWN */; break; - case 0x24 /*DOM_VK_HOME*/: key = 106 /* GLUT_KEY_HOME */; break; - case 0x23 /*DOM_VK_END*/: key = 107 /* GLUT_KEY_END */; break; - case 0x2d /*DOM_VK_INSERT*/: key = 108 /* GLUT_KEY_INSERT */; break; - default: return; - }; - if (key !== null) { - FUNCTION_TABLE[GLUT.keyboardFunc](key, GLUT.lastX, GLUT.lastY); + getProcAddress: function(name_) { + name_ = GLEmulation.procReplacements[name_] || name_; + var func = GLEmulation.procs[name_]; + if (!func) { + try { + func = eval('_' + name_); // XXX closure, need Module. and for them to be exported + } catch(e) { + console.log('WARNING: getProcAddress failed for ' + name_); + func = function() { + console.log('WARNING: empty replacement for ' + name_ + ' called, no-op'); + return 0; + }; } } + return Runtime.addFunction(func); + } + }, + + // GL Immediate mode + + $GLImmediate: { + // Vertex and index data + maxElements: 1024, + vertexData: null, // current vertex data. either tempData (glBegin etc.) or a view into the heap (gl*Pointer) + tempData: null, + indexData: null, + vertexCounter: 0, + mode: 0, + + renderers: {}, + renderer: null, + + // The following data structures are used for OpenGL Immediate Mode matrix routines. + matrix: { + 'm': null, // modelview + 'p': null // projection + }, + matrixStack: { + 'm': [], // modelview + 'p': [] // projection + }, + currentMatrix: 'm', // default is modelview + tempMatrix: null, + initMatrixLibrary: function() { + GL.immediate.matrix['m'] = GL.immediate.matrix.lib.mat4.create(); + GL.immediate.matrix['p'] = GL.immediate.matrix.lib.mat4.create(); + GL.immediate.currentMatrix = GL.immediate.matrix.lib.mat4.create(); }, + + // Clientside attributes + TEXTURE: 0, + VERTEX: 1, + NUM_ATTRIBUTES: 2, + ATTRIBUTE_BY_NAME: { + 'T': 0, + 'V': 1 + }, + + totalEnabledClientAttributes: 0, + enabledClientAttributes: [0, 0], + clientAttributes: [null, null], + + setClientAttribute: function(which, name, size, type, stride, pointer) { + this.clientAttributes[which] = { + size: size, type: type, stride: stride, pointer: pointer, name: name + size + }; + }, + + // Renderers + setRenderer: function(renderer) { + this.renderer = renderer; + if (this.renderers[renderer]) return; + + // Create renderer + var vertexSize = 0; + for (var i = 0; i < renderer.length; i+=2) { + var which = renderer[i]; + var size = parseInt(renderer[i+1]); + if (which == 'V') { + positionSize = size; + positionOffset = vertexSize; + } else if (which == 'T') { + textureSize = size; + textureOffset = vertexSize; + } + vertexSize += size * 4; // XXX assuming float + } + // TODO: verify vertexSize is equal to the stride in enabled client arrays + // TODO: assert that we can create the renderer type we were asked + // TODO: use bufferSubData to prevent reallocation of new buffers? Or all on GPU and doesn't matter? Anyhow, use DYNAMIC as hint + this.renderers[renderer] = { + vertexSize: vertexSize, + init: function() { + this.vertexShader = Module.ctx.createShader(Module.ctx.VERTEX_SHADER); + var zero = positionSize == 2 ? '0, ' : ''; + Module.ctx.shaderSource(this.vertexShader, 'attribute vec' + positionSize + ' a_position; \n\ + attribute vec2 a_texCoord; \n\ + varying vec2 v_texCoord; \n\ + uniform mat4 u_modelView; \n\ + uniform mat4 u_projection; \n\ + void main() \n\ + { \n\ + gl_Position = u_projection * (u_modelView * vec4(a_position, ' + zero + '1.0)); \n\ + v_texCoord = a_texCoord; \n\ + } \n'); + Module.ctx.compileShader(this.vertexShader); + + this.fragmentShader = Module.ctx.createShader(Module.ctx.FRAGMENT_SHADER); + Module.ctx.shaderSource(this.fragmentShader, 'precision mediump float; \n\ + varying vec2 v_texCoord; \n\ + uniform sampler2D s_texture; \n\ + void main() \n\ + { \n\ + gl_FragColor = texture2D( s_texture, v_texCoord );\n\ + } \n'); + Module.ctx.compileShader(this.fragmentShader); + + this.program = Module.ctx.createProgram(); + Module.ctx.attachShader(this.program, this.vertexShader); + Module.ctx.attachShader(this.program, this.fragmentShader); + Module.ctx.linkProgram(this.program); + + this.positionLocation = Module.ctx.getAttribLocation(this.program, 'a_position'); + this.texCoordLocation = Module.ctx.getAttribLocation(this.program, 'a_texCoord'); + this.textureLocation = Module.ctx.getUniformLocation(this.program, 's_texture'); + this.modelViewLocation = Module.ctx.getUniformLocation(this.program, 'u_modelView'); + this.projectionLocation = Module.ctx.getUniformLocation(this.program, 'u_projection'); + }, + + prepare: function() { + Module.ctx.vertexAttribPointer(this.texCoordLocation, textureSize, Module.ctx.FLOAT, false, + vertexSize, textureOffset); + Module.ctx.vertexAttribPointer(this.positionLocation, positionSize, Module.ctx.FLOAT, false, + vertexSize, positionOffset); + + Module.ctx.enableVertexAttribArray(this.texCoordLocation); + Module.ctx.enableVertexAttribArray(this.positionLocation); + + var texture = Module.ctx.getParameter(Module.ctx.TEXTURE_BINDING_2D); + Module.ctx.activeTexture(Module.ctx.TEXTURE0); + Module.ctx.bindTexture(Module.ctx.TEXTURE_2D, texture); + Module.ctx.uniform1i(this.textureLocation, 0); + + Module.ctx.uniformMatrix4fv(this.modelViewLocation, false, GL.immediate.matrix["m"]); + Module.ctx.uniformMatrix4fv(this.projectionLocation, false, GL.immediate.matrix["p"]); + } + }; + this.renderers[renderer].init(); + }, + + // Main functions + initted: false, + init: function() { + Module.printErr('WARNING: using emscripten GL immediate mode emulation. This is very limited in what it supports'); + GL.immediate.initted = true; + + // Buffers for data + this.tempData = new Float32Array(this.maxElements); + this.indexData = new Uint16Array(this.maxElements); + + this.vertexObject = Module.ctx.createBuffer(); + this.indexObject = Module.ctx.createBuffer(); + + // Replace some functions with immediate-mode aware versions + _glDrawArrays = function(mode, first, count) { + if (GL.immediate.totalEnabledClientAttributes == 0) { + Module.ctx.drawArrays(mode, first, count); + return; + } +#if ASSERTIONS + assert(first == 0); // TODO +#endif + // Client attributes are to be used here, emulate that + var stride = 0, bytes = 0, attributes = [], start, renderer = ''; + for (var i = 0; i < GL.immediate.NUM_ATTRIBUTES; i++) { + if (GL.immediate.enabledClientAttributes[i]) attributes.push(GL.immediate.clientAttributes[i]); + } + attributes.sort(function(x, y) { return x.pointer - y.pointer }); + start = attributes[0].pointer; + for (var i = 0; i < attributes.length; i++) { + var attribute = attributes[i]; +#if ASSERTIONS + assert(attribute.stride); + assert(stride == 0 || stride == attribute.stride); // must all be in the same buffer +#endif + stride = attribute.stride; + bytes += attribute.size * 4 * count; // XXX assuming float + renderer += attribute.name; + } + for (var i = 0; i < attributes.length; i++) { + var attribute = attributes[i]; + attribute.offset = attribute.pointer - start; +#if ASSERTIONS + assert(0 <= attribute.offset && attribute.offset < stride); // must all be in the same buffer +#endif + } + GL.immediate.vertexData = {{{ makeHEAPView('F32', 'start', 'start + bytes') }}}; // XXX assuming float + GL.immediate.vertexCounter = bytes / 4; // XXX assuming float + GL.immediate.mode = mode; + GL.immediate.setRenderer(renderer); + GL.immediate.flush(); + }; + }, + flush: function() { + var renderer = this.renderers[this.renderer]; + + // Generate index data in a format suitable for GLES 2.0/WebGL + // TODO: if the mode is one that works in GLES 2.0/WebGL (not GL_QUADS), do not generate indexes at all + var numVertexes = 4 * this.vertexCounter / renderer.vertexSize; // XXX assuming float + assert(numVertexes % 1 == 0); + var numIndexes = 0; + + if (GL.immediate.mode == 7) { // GL_QUADS + var numQuads = numVertexes / 4; + assert(numQuads % 1 == 0); + for (var i = 0; i < numQuads; i++) { + var start = i*4; + GL.immediate.indexData[numIndexes++] = start; + GL.immediate.indexData[numIndexes++] = start+1; + GL.immediate.indexData[numIndexes++] = start+2; + GL.immediate.indexData[numIndexes++] = start; + GL.immediate.indexData[numIndexes++] = start+2; + GL.immediate.indexData[numIndexes++] = start+3; + } + } else if (GL.immediate.mode == 5) { // GL_TRIANGLE_STRIP + var numTriangles = numVertexes - 2; + assert(numTriangles > 0); + for (var i = 0; i < numTriangles; i++) { + if (i % 2 == 0) { + GL.immediate.indexData[numIndexes++] = i; + GL.immediate.indexData[numIndexes++] = i+1; + GL.immediate.indexData[numIndexes++] = i+2; + } else { + GL.immediate.indexData[numIndexes++] = i+1; + GL.immediate.indexData[numIndexes++] = i; + GL.immediate.indexData[numIndexes++] = i+2; + } + } + } else { + throw 'unsupported immediate mode ' + GL.immediate.mode; + } + assert(numIndexes < GL.immediate.maxElements, 'too many immediate mode indexes'); + + // Upload the data + Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, this.vertexObject); + Module.ctx.bufferData(Module.ctx.ARRAY_BUFFER, this.vertexData.subarray(0, this.vertexCounter), Module.ctx.STATIC_DRAW); + Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.indexObject); + Module.ctx.bufferData(Module.ctx.ELEMENT_ARRAY_BUFFER, this.indexData.subarray(0, numIndexes), Module.ctx.STATIC_DRAW); + + // Render + Module.ctx.useProgram(renderer.program); + Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, this.vertexObject); + + renderer.prepare(); + + Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.indexObject); + Module.ctx.drawElements(Module.ctx.TRIANGLES, numIndexes, Module.ctx.UNSIGNED_SHORT, 0); + + this.vertexCounter = 0; + } }, - glutInit__deps: ['$GLUT'], - glutInit: function(argcp, argv) { - // Ignore arguments - GLUT.initTime = Date.now(); - window.addEventListener("keydown", GLUT.onKeydown, true); - window.addEventListener("mousemove", GLUT.onMousemove, true); + $GLImmediateSetup__deps: ['$GLImmediate', function() { return 'GL.immediate = GLImmediate; GL.immediate.matrix.lib = ' + read('gl-matrix.js') + '; GL.immediate.initMatrixLibrary();\n' }], + $GLImmediateSetup: {}, + + glBegin__deps: ['$GL', '$GLImmediateSetup'], + glBegin: function(mode) { + if (!GL.immediate.initted) GL.immediate.init(); + GL.immediate.mode = mode; + GL.immediate.renderer = null; + GL.immediate.vertexData = GL.immediate.tempData; }, - glutInitWindowSize: function(width, height) { - Module['canvas'].width = width; - Module['canvas'].height = height; + glEnd: function() { + GL.immediate.flush(); + GL.immediate.mode = 0; }, - glutGet: function(type) { - switch (type) { - case 700: /* GLUT_ELAPSED_TIME */ - var now = Date.now(); - return now - GLUT.initTime; + glVertex3f: function(x, y, z) { +#if ASSERTIONS + assert(GL.immediate.mode); // must be in begin/end +#endif + GL.immediate.vertexData[GL.immediate.vertexCounter++] = x; + GL.immediate.vertexData[GL.immediate.vertexCounter++] = y; + GL.immediate.vertexData[GL.immediate.vertexCounter++] = z || 0; +#if ASSERTIONS + assert(GL.immediate.vertexCounter < GL.immediate.maxElements); + assert(GL.immediate.vertexCounter % 5 == 0); +#endif + if (!GL.immediate.renderer) { + // Decide renderer based on attributes used // TODO: generalize + GL.immediate.setRenderer('T2V3'); + } + }, + + glVertex2f: 'glVertex3f', + + glTexCoord2i: function(u, v) { +#if ASSERTIONS + assert(GL.immediate.mode); // must be in begin/end +#endif + GL.immediate.vertexData[GL.immediate.vertexCounter++] = u; + GL.immediate.vertexData[GL.immediate.vertexCounter++] = v; + }, + glTexCoord2f: 'glTexCoord2i', + + glColor4b: function(){}, // TODO, including scaling for different arg types + glColor4s: 'glColor4b', + glColor4i: 'glColor4b', + glColor4f: 'glColor4b', + glColor4d: 'glColor4b', + glColor4ub: 'glColor4b', + glColor4us: 'glColor4b', + glColor4ui: 'glColor4b', + + glColor3b__deps: ['glColor4b'], + glColor3b: function(r, g, b) { + _glColor4b(r, g, b, 1); // FIXME: scaling + }, + glColor3s: 'glColor3b', + glColor3i: 'glColor3b', + glColor3f: 'glColor3b', + glColor3d: 'glColor3b', + glColor3ub: 'glColor3b', + glColor3us: 'glColor3b', + glColor3ui: 'glColor3b', + + // ClientState/gl*Pointer + + glEnableClientState: function(cap, disable) { + if (!GL.immediate.initted) GL.immediate.init(); + switch(cap) { + case 0x8078: // GL_TEXTURE_COORD_ARRAY + GL.immediate.enabledClientAttributes[GL.immediate.TEXTURE] = !disable; break; + case 0x8074: // GL_VERTEX_ARRAY + GL.immediate.enabledClientAttributes[GL.immediate.VERTEX] = !disable; break; default: - throw "glutGet(" + type + ") not implemented yet"; + throw 'unhandled clientstate: ' + cap; + } + if (!disable) { + GL.immediate.totalEnabledClientAttributes++; + } else { + GL.immediate.totalEnabledClientAttributes--; } }, + glDisableClientState: function(cap) { + _glEnableClientState(cap, 1); + }, + + glTexCoordPointer: function(size, type, stride, pointer) { + GL.immediate.setClientAttribute(GL.immediate.TEXTURE, 'T', size, type, stride, pointer); + }, - glutDisplayFunc: function(func) { - var RAF = window['setTimeout']; - if (window['requestAnimationFrame']) { - RAF = window['requestAnimationFrame']; - } else if (window['mozRequestAnimationFrame']) { - RAF = window['mozRequestAnimationFrame']; - } else if (window['webkitRequestAnimationFrame']) { - RAF = window['webkitRequestAnimationFrame']; - } else if (window['msRequestAnimationFrame']) { - RAF = window['msRequestAnimationFrame']; + glVertexPointer: function(size, type, stride, pointer) { + GL.immediate.setClientAttribute(GL.immediate.VERTEX, 'V', size, type, stride, pointer); + }, + + // OpenGL Immediate Mode matrix routines. + // Note that in the future we might make these available only in certain modes. + glMatrixMode__deps: ['$GL', '$GLImmediateSetup'], + glMatrixMode: function(mode) { + if (mode == 0x1700 /* GL_MODELVIEW */) { + GL.immediate.currentMatrix = 'm'; + } else if (mode == 0x1701 /* GL_PROJECTION */) { + GL.immediate.currentMatrix = 'p'; + } else { + throw "Wrong mode " + mode + " passed to glMatrixMode"; } - RAF.apply(window, [function() { - if (GLUT.reshapeFunc) { - FUNCTION_TABLE[GLUT.reshapeFunc](Module['canvas'].width, - Module['canvas'].height); - } - if (GLUT.idleFunc) { - FUNCTION_TABLE[GLUT.idleFunc](); - } - FUNCTION_TABLE[func](); - _glutDisplayFunc(func); - }]); }, - glutIdleFunc: function(func) { - GLUT.idleFunc = func; + glPushMatrix: function() { + GL.immediate.matrixStack[GL.immediate.currentMatrix].push( + Array.prototype.slice.call(GL.immediate.matrix[GL.immediate.currentMatrix])); }, - glutSpecialFunc: function(func) { - GLUT.keyboardFunc = func; + glPopMatrix: function() { + GL.immediate.matrix[GL.immediate.currentMatrix] = GL.immediate.matrixStack[GL.immediate.currentMatrix].pop(); }, - glutReshapeFunc: function(func) { - GLUT.reshapeFunc = func; + glLoadIdentity__deps: ['$GL', '$GLImmediateSetup'], + glLoadIdentity: function() { + GL.immediate.matrix.lib.mat4.identity(GL.immediate.matrix[GL.immediate.currentMatrix]); }, - glutCreateWindow: function(name) { -#if USE_TYPED_ARRAYS - try { - var ctx = Module.canvas.getContext('experimental-webgl'); - if (!ctx) throw 'Could not create canvas :('; - Module.ctx = ctx; - // Set the background of the canvas to black, because glut gives us a - // window which has a black background by default. - Module.canvas.style.backgroundColor = "black"; - } catch (e) { - Module.print('(canvas not available)'); - } -#else - Module.print('(USE_TYPED_ARRAYS needs to be enabled for WebGL)'); -#endif + glLoadMatrixd: function(matrix) { + GL.immediate.matrix.lib.mat4.set(GL.immediate.matrix[GL.immediate.currentMatrix], + {{{ makeHEAPView('F64', 'matrix', 'matrix+16*8') }}}); + }, + + glLoadMatrixf: function(matrix) { + GL.immediate.matrix.lib.mat4.set(GL.immediate.matrix[GL.immediate.currentMatrix], + {{{ makeHEAPView('F32', 'matrix', 'matrix+16*4') }}}); + }, + + glLoadTransposeMatrixd: function(matrix) { + GL.immediate.matrix.lib.mat4.set(GL.immediate.matrix[GL.immediate.currentMatrix], + {{{ makeHEAPView('F64', 'matrix', 'matrix+16*8') }}}); + GL.immediate.matrix.lib.mat4.transpose(GL.immediate.matrix[GL.immediate.currentMatrix]); + }, + + glLoadTransposeMatrixf: function(matrix) { + GL.immediate.matrix.lib.mat4.set(GL.immediate.matrix[GL.immediate.currentMatrix], + {{{ makeHEAPView('F32', 'matrix', 'matrix+16*4') }}}); + GL.immediate.matrix.lib.mat4.transpose(GL.immediate.matrix[GL.immediate.currentMatrix]); + }, + + glMultMatrixd: function(matrix) { + GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix], + {{{ makeHEAPView('F64', 'matrix', 'matrix+16*8') }}}); + }, + + glMultMatrixf: function(matrix) { + GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix], + {{{ makeHEAPView('F32', 'matrix', 'matrix+16*4') }}}); + }, + + glMultTransposeMatrixd: function(matrix) { + var colMajor = GL.immediate.matrix.lib.mat4.create(); + GL.immediate.matrix.lib.mat4.set(colMajor, + {{{ makeHEAPView('F64', 'matrix', 'matrix+16*8') }}}); + GL.immediate.matrix.lib.mat4.transpose(colMajor); + GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix], colMajor); }, - glutInitDisplayMode: function(mode) {}, - glutMainLoop: function() {}, - glutSwapBuffers: function() {}, - glutPostRedisplay: function() {}, + glMultTransposeMatrixf: function(matrix) { + var colMajor = GL.immediate.matrix.lib.mat4.create(); + GL.immediate.matrix.lib.mat4.set(colMajor, + {{{ makeHEAPView('F32', 'matrix', 'matrix+16*4') }}}); + GL.immediate.matrix.lib.mat4.transpose(colMajor); + GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix], colMajor); + }, + + glFrustum: function(left, right, bottom, top_, nearVal, farVal) { + GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix], + GL.immediate.matrix.lib.mat4.frustum(left, right, bottom, top_, nearVal, farVal)); + }, + + glOrtho: function(left, right, bottom, top_, nearVal, farVal) { + GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix], + GL.immediate.matrix.lib.mat4.ortho(left, right, bottom, top_, nearVal, farVal)); + }, + + glScaled: function(x, y, z) { + GL.immediate.matrix.lib.mat4.scale(GL.immediate.matrix[GL.immediate.currentMatrix], [x, y, z]); + }, + glScalef: 'glScaled', + + glTranslated: function(x, y, z) { + GL.immediate.matrix.lib.mat4.translate(GL.immediate.matrix[GL.immediate.currentMatrix], [x, y, z]); + }, + glTranslatef: 'glTranslated', + + glRotated: function(angle, x, y, z) { + GL.immediate.matrix.lib.mat4.rotate(GL.immediate.matrix[GL.immediate.currentMatrix], angle, [x, y, z]); + }, + glRotatef: 'glRotated', + + // GLU + + gluPerspective: function(fov, aspect, near, far) { + GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix], + GL.immediate.matrix.lib.mat4.perspective(fov, aspect, near, far, GL.immediate.currentMatrix)); + }, + + gluLookAt: function(ex, ey, ez, cx, cy, cz, ux, uy, uz) { + GL.immediate.matrix.lib.mat4.lookAt(GL.immediate.matrix[GL.immediate.currentMatrix], [ex, ey, ez], + [cx, cy, cz], [ux, uy, uz]); + }, + + gluProject: function(objX, objY, objZ, model, proj, view, winX, winY, winZ) { + // The algorithm for this functions comes from Mesa + + var inVec = new Float32Array(4); + var outVec = new Float32Array(4); + GL.immediate.matrix.lib.mat4.multiplyVec4({{{ makeHEAPView('F64', 'model', 'model+16*8') }}}, + [objX, objY, objZ, 1.0], outVec); + GL.immediate.matrix.lib.mat4.multiplyVec4({{{ makeHEAPView('F64', 'proj', 'proj+16*8') }}}, + outVec, inVec); + if (inVec[3] == 0.0) { + return 0 /* GL_FALSE */; + } + inVec[0] /= inVec[3]; + inVec[1] /= inVec[3]; + inVec[2] /= inVec[3]; + // Map x, y and z to range 0-1 */ + inVec[0] = inVec[0] * 0.5 + 0.5; + inVec[1] = inVec[1] * 0.5 + 0.5; + inVec[2] = inVec[2] * 0.5 + 0.5; + // Map x, y to viewport + inVec[0] = inVec[0] * {{{ makeGetValue('view', '2*4', 'i32') }}} + {{{ makeGetValue('view', '0*4', 'i32') }}}; + inVec[1] = inVec[1] * {{{ makeGetValue('view', '3*4', 'i32') }}} + {{{ makeGetValue('view', '1*4', 'i32') }}}; + + {{{ makeSetValue('winX', '0', 'inVec[0]', 'double') }}}; + {{{ makeSetValue('winY', '0', 'inVec[1]', 'double') }}}; + {{{ makeSetValue('winZ', '0', 'inVec[2]', 'double') }}}; + + return 1 /* GL_TRUE */; + }, + + gluUnProject: function(winX, winY, winZ, model, proj, view, objX, objY, objZ) { + var result = GL.immediate.matrix.lib.mat4.unproject([winX, winY, winZ], + {{{ makeHEAPView('F64', 'model', 'model+16*8') }}}, + {{{ makeHEAPView('F64', 'proj', 'proj+16*8') }}}, + {{{ makeHEAPView('32', 'view', 'view+4*4') }}}); + + if (result === null) { + return 0 /* GL_FALSE */; + } + + {{{ makeSetValue('objX', '0', 'result[0]', 'double') }}}; + {{{ makeSetValue('objY', '0', 'result[1]', 'double') }}}; + {{{ makeSetValue('objZ', '0', 'result[2]', 'double') }}}; + + return 1 /* GL_TRUE */; + } }; +// Simple pass-through functions. Starred ones have return values. [X] ones have X in the C name but not in the JS name +[[0, 'shadeModel fogi fogfv getError* finish flush'], + [1, 'clearDepth clearDepth[f] depthFunc enable disable frontFace cullFace clear enableVertexAttribArray disableVertexAttribArray lineWidth clearStencil depthMask stencilMask checkFramebufferStatus* generateMipmap activeTexture blendEquation polygonOffset hint sampleCoverage isEnabled*'], + [2, 'blendFunc blendEquationSeparate depthRange depthRange[f] stencilMaskSeparate'], + [3, 'texParameteri texParameterf drawArrays vertexAttrib2f stencilFunc stencilOp'], + [4, 'viewport clearColor scissor vertexAttrib3f colorMask drawElements renderbufferStorage blendFuncSeparate blendColor stencilFuncSeparate stencilOpSeparate'], + [5, 'vertexAttrib4f'], + [6, 'vertexAttribPointer'], + [8, 'copyTexImage2D copyTexSubImage2D']].forEach(function(data) { + var num = data[0]; + var names = data[1]; + var args = range(num).map(function(i) { return 'x' + i }).join(', '); + var plainStub = '(function(' + args + ') { ' + (num > 0 ? 'Module.ctx.NAME(' + args + ')' : '') + ' })'; + var returnStub = '(function(' + args + ') { ' + (num > 0 ? 'return Module.ctx.NAME(' + args + ')' : '') + ' })'; + names.split(' ').forEach(function(name) { + var stub = plainStub; + if (name[name.length-1] == '*') { + name = name.substr(0, name.length-1); + stub = returnStub; + } + var cName = name; + if (name.indexOf('[') >= 0) { + cName = name.replace('[', '').replace(']', ''); + name = cName.substr(0, cName.length-1); + } + var cName = 'gl' + cName[0].toUpperCase() + cName.substr(1); + assert(!(cName in LibraryGL), "Cannot reimplement the existing function " + cName); + LibraryGL[cName] = eval(stub.replace('NAME', name)); + }); +}); + +autoAddDeps(LibraryGL, '$GL'); mergeInto(LibraryManager.library, LibraryGL); -mergeInto(LibraryManager.library, LibraryGLUT); diff --git a/src/library_glut.js b/src/library_glut.js new file mode 100644 index 00000000..e4b2d138 --- /dev/null +++ b/src/library_glut.js @@ -0,0 +1,444 @@ + +var LibraryGLUT = { + $GLUT: { + initTime: null, + idleFunc: null, + displayFunc: null, + keyboardFunc: null, + keyboardUpFunc: null, + specialFunc: null, + specialUpFunc: null, + reshapeFunc: null, + motionFunc: null, + passiveMotionFunc: null, + mouseFunc: null, + lastX: 0, + lastY: 0, + buttons: 0, + modifiers: 0, + initWindowWidth: 256, + initWindowHeight: 256, + // Set when going fullscreen + windowX: 0, + windowY: 0, + windowWidth: 0, + windowHeight: 0, + + savePosition: function(event) { + /* TODO maybe loop here ala http://www.quirksmode.org/js/findpos.html */ + GLUT.lastX = event['clientX'] - Module['canvas'].offsetLeft; + GLUT.lastY = event['clientY'] - Module['canvas'].offsetTop; + }, + + saveModifiers: function(event) { + GLUT.modifiers = 0; + if (event['shiftKey']) + GLUT.modifiers += 1; /* GLUT_ACTIVE_SHIFT */ + if (event['ctrlKey']) + GLUT.modifiers += 2; /* GLUT_ACTIVE_CTRL */ + if (event['altKey']) + GLUT.modifiers += 4; /* GLUT_ACTIVE_ALT */ + }, + + onMousemove: function(event) { + /* Send motion event only if the motion changed, prevents + * spamming our app with uncessary callback call. It does happen in + * Chrome on Windows. + */ + var newX = event['clientX'] - Module['canvas'].offsetLeft; + var newY = event['clientY'] - Module['canvas'].offsetTop; + if (newX == GLUT.lastX && newY == GLUT.lastY) + return; + + GLUT.savePosition(event); + if (GLUT.buttons == 0 && event.target == Module["canvas"] && GLUT.passiveMotionFunc) { + event.preventDefault(); + GLUT.saveModifiers(event); + FUNCTION_TABLE[GLUT.passiveMotionFunc](GLUT.lastX, GLUT.lastY); + } else if (GLUT.buttons != 0 && GLUT.motionFunc) { + event.preventDefault(); + GLUT.saveModifiers(event); + FUNCTION_TABLE[GLUT.motionFunc](GLUT.lastX, GLUT.lastY); + } + }, + + getSpecialKey: function(keycode) { + var key = null; + switch (keycode) { + case 0x70 /*DOM_VK_F1*/: key = 1 /* GLUT_KEY_F1 */; break; + case 0x71 /*DOM_VK_F2*/: key = 2 /* GLUT_KEY_F2 */; break; + case 0x72 /*DOM_VK_F3*/: key = 3 /* GLUT_KEY_F3 */; break; + case 0x73 /*DOM_VK_F4*/: key = 4 /* GLUT_KEY_F4 */; break; + case 0x74 /*DOM_VK_F5*/: key = 5 /* GLUT_KEY_F5 */; break; + case 0x75 /*DOM_VK_F6*/: key = 6 /* GLUT_KEY_F6 */; break; + case 0x76 /*DOM_VK_F7*/: key = 7 /* GLUT_KEY_F7 */; break; + case 0x77 /*DOM_VK_F8*/: key = 8 /* GLUT_KEY_F8 */; break; + case 0x78 /*DOM_VK_F9*/: key = 9 /* GLUT_KEY_F9 */; break; + case 0x79 /*DOM_VK_F10*/: key = 10 /* GLUT_KEY_F10 */; break; + case 0x7a /*DOM_VK_F11*/: key = 11 /* GLUT_KEY_F11 */; break; + case 0x7b /*DOM_VK_F12*/: key = 12 /* GLUT_KEY_F12 */; break; + case 0x25 /*DOM_VK_LEFT*/: key = 100 /* GLUT_KEY_LEFT */; break; + case 0x26 /*DOM_VK_UP*/: key = 101 /* GLUT_KEY_UP */; break; + case 0x27 /*DOM_VK_RIGHT*/: key = 102 /* GLUT_KEY_RIGHT */; break; + case 0x28 /*DOM_VK_DOWN*/: key = 103 /* GLUT_KEY_DOWN */; break; + case 0x21 /*DOM_VK_PAGE_UP*/: key = 104 /* GLUT_KEY_PAGE_UP */; break; + case 0x22 /*DOM_VK_PAGE_DOWN*/: key = 105 /* GLUT_KEY_PAGE_DOWN */; break; + case 0x24 /*DOM_VK_HOME*/: key = 106 /* GLUT_KEY_HOME */; break; + case 0x23 /*DOM_VK_END*/: key = 107 /* GLUT_KEY_END */; break; + case 0x2d /*DOM_VK_INSERT*/: key = 108 /* GLUT_KEY_INSERT */; break; + + case 16 /*DOM_VK_SHIFT*/: + case 0x05 /*DOM_VK_LEFT_SHIFT*/: + key = 112 /* GLUT_KEY_SHIFT_L */; + break; + case 0x06 /*DOM_VK_RIGHT_SHIFT*/: + key = 113 /* GLUT_KEY_SHIFT_R */; + break; + + case 17 /*DOM_VK_CONTROL*/: + case 0x03 /*DOM_VK_LEFT_CONTROL*/: + key = 114 /* GLUT_KEY_CONTROL_L */; + break; + case 0x04 /*DOM_VK_RIGHT_CONTROL*/: + key = 115 /* GLUT_KEY_CONTROL_R */; + break; + + case 18 /*DOM_VK_ALT*/: + case 0x02 /*DOM_VK_LEFT_ALT*/: + key = 116 /* GLUT_KEY_ALT_L */; + break; + case 0x01 /*DOM_VK_RIGHT_ALT*/: + key = 117 /* GLUT_KEY_ALT_R */; + break; + }; + return key; + }, + + getASCIIKey: function(event) { + if (event['ctrlKey'] || event['altKey'] || event['metaKey']) return null; + + var keycode = event['keyCode']; + + /* The exact list is soooo hard to find in a canonical place! */ + + if (48 <= keycode && keycode <= 57) + return keycode; // numeric TODO handle shift? + if (65 <= keycode && keycode <= 90) + return event['shiftKey'] ? keycode : keycode + 32; + if (106 <= keycode && keycode <= 111) + return keycode - 106 + 42; // *,+-./ TODO handle shift? + + switch (keycode) { + case 27: // escape + case 32: // space + case 61: // equal + return keycode; + } + + var s = event['shiftKey']; + switch (keycode) { + case 186: return s ? 58 : 59; // colon / semi-colon + case 187: return s ? 43 : 61; // add / equal (these two may be wrong) + case 188: return s ? 60 : 44; // less-than / comma + case 189: return s ? 95 : 45; // dash + case 190: return s ? 62 : 46; // greater-than / period + case 191: return s ? 63 : 47; // forward slash + case 219: return s ? 123 : 91; // open bracket + case 220: return s ? 124 : 47; // back slash + case 221: return s ? 125 : 93; // close braket + case 222: return s ? 34 : 39; // single quote + } + + return null; + }, + + onKeydown: function(event) { + if (GLUT.specialFunc || GLUT.keyboardFunc) { + var key = GLUT.getSpecialKey(event['keyCode']); + if (key !== null) { + if( GLUT.specialFunc ) { + event.preventDefault(); + GLUT.saveModifiers(event); + FUNCTION_TABLE[GLUT.specialFunc](key, GLUT.lastX, GLUT.lastY); + } + } + else + { + key = GLUT.getASCIIKey(event); + if( key !== null && GLUT.keyboardFunc ) { + event.preventDefault(); + GLUT.saveModifiers(event); + FUNCTION_TABLE[GLUT.keyboardFunc](key, GLUT.lastX, GLUT.lastY); + } + } + } + }, + + onKeyup: function(event) { + if (GLUT.specialUpFunc || GLUT.keyboardUpFunc) { + var key = GLUT.getSpecialKey(event['keyCode']); + if (key !== null) { + if(GLUT.specialUpFunc) { + event.preventDefault (); + GLUT.saveModifiers(event); + FUNCTION_TABLE[GLUT.specialUpFunc](key, GLUT.lastX, GLUT.lastY); + } + } + else + { + key = GLUT.getASCIIKey(event); + if( key !== null && GLUT.keyboardUpFunc ) { + event.preventDefault (); + GLUT.saveModifiers(event); + FUNCTION_TABLE[GLUT.keyboardUpFunc](key, GLUT.lastX, GLUT.lastY); + } + } + } + }, + + onMouseButtonDown: function(event){ + GLUT.savePosition(event); + GLUT.buttons |= (1 << event['button']); + + if(event.target == Module["canvas"] && GLUT.mouseFunc){ + try { + event.target.setCapture(); + } catch (e) {} + event.preventDefault(); + GLUT.saveModifiers(event); + FUNCTION_TABLE[GLUT.mouseFunc](event['button'], 0/*GLUT_DOWN*/, GLUT.lastX, GLUT.lastY); + } + }, + + onMouseButtonUp: function(event){ + GLUT.savePosition(event); + GLUT.buttons &= ~(1 << event['button']); + + if(GLUT.mouseFunc) { + event.preventDefault(); + GLUT.saveModifiers(event); + FUNCTION_TABLE[GLUT.mouseFunc](event['button'], 1/*GLUT_UP*/, GLUT.lastX, GLUT.lastY); + } + }, + + // TODO add fullscreen API ala: + // http://johndyer.name/native-fullscreen-javascript-api-plus-jquery-plugin/ + onFullScreenEventChange: function(event){ + var width; + var height; + if (document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen) { + width = screen["width"]; + height = screen["height"]; + } else { + width = GLUT.windowWidth; + height = GLUT.windowHeight; + // TODO set position + document.removeEventListener('fullscreenchange', GLUT.onFullScreenEventChange, true); + document.removeEventListener('mozfullscreenchange', GLUT.onFullScreenEventChange, true); + document.removeEventListener('webkitfullscreenchange', GLUT.onFullScreenEventChange, true); + } + Module['canvas'].width = width; + Module['canvas'].height = height; + /* Can't call _glutReshapeWindow as that requests cancelling fullscreen. */ + if (GLUT.reshapeFunc) { + FUNCTION_TABLE[GLUT.reshapeFunc](width, height); + } + _glutPostRedisplay(); + }, + + requestFullScreen: function() { + var RFS = Module["canvas"]['requestFullscreen'] || + Module["canvas"]['requestFullScreen'] || + Module["canvas"]['mozRequestFullScreen'] || + Module["canvas"]['webkitRequestFullScreen'] || + (function() {}); + RFS.apply(Module["canvas"], []); + }, + + cancelFullScreen: function() { + var CFS = document['exitFullscreen'] || + document['cancelFullScreen'] || + document['mozCancelFullScreen'] || + document['webkitCancelFullScreen'] || + (function() {}); + CFS.apply(document, []); + }, + + requestAnimationFrame: function(func) { + var RAF = window['requestAnimationFrame'] || + window['mozRequestAnimationFrame'] || + window['webkitRequestAnimationFrame'] || + window['msRequestAnimationFrame'] || + window['setTimeout']; + RAF.apply(window, [func]); + }, + }, + + glutGetModifiers: function() { return GLUT.modifiers; }, + + glutInit: function(argcp, argv) { + // Ignore arguments + GLUT.initTime = Date.now(); + }, + + glutInitWindowSize: function(width, height) { + Module['canvas'].width = GLUT.initWindowWidth = width; + Module['canvas'].height = GLUT.initWindowHeight = height; + }, + + glutInitWindowPosition: function(x, y) { + // Ignore for now + }, + + glutGet: function(type) { + switch (type) { + case 100: /* GLUT_WINDOW_X */ + return 0; /* TODO */ + case 101: /* GLUT_WINDOW_Y */ + return 0; /* TODO */ + case 102: /* GLUT_WINDOW_WIDTH */ + return Module['canvas'].width; + case 103: /* GLUT_WINDOW_HEIGHT */ + return Module['canvas'].height; + case 500: /* GLUT_INIT_WINDOW_X */ + return 0; /* TODO */ + case 501: /* GLUT_INIT_WINDOW_Y */ + return 0; /* TODO */ + case 502: /* GLUT_INIT_WINDOW_WIDTH */ + return GLUT.initWindowWidth; + case 503: /* GLUT_INIT_WINDOW_HEIGHT */ + return GLUT.initWindowHeight; + case 700: /* GLUT_ELAPSED_TIME */ + var now = Date.now(); + return now - GLUT.initTime; + + default: + throw "glutGet(" + type + ") not implemented yet"; + } + }, + + glutIdleFunc: function(func) { + var callback = function() { + if (GLUT.idleFunc) { + FUNCTION_TABLE[GLUT.idleFunc](); + window.setTimeout(callback, 0); + } + } + if (!GLUT.idleFunc) + window.setTimeout(callback, 0); + GLUT.idleFunc = func; + }, + + glutTimerFunc: function(msec, func, value) { + window.setTimeout(function() { FUNCTION_TABLE[func](value); }, msec); + }, + + glutDisplayFunc: function(func) { + GLUT.displayFunc = func; + }, + + glutKeyboardFunc: function(func) { + GLUT.keyboardFunc = func; + }, + + glutKeyboardUpFunc: function(func) { + GLUT.keyboardUpFunc = func; + }, + + glutSpecialFunc: function(func) { + GLUT.specialFunc = func; + }, + + glutSpecialUpFunc: function(func) { + GLUT.specialUpFunc = func; + }, + + glutReshapeFunc: function(func) { + GLUT.reshapeFunc = func; + }, + + glutMotionFunc: function(func) { + GLUT.motionFunc = func; + }, + + glutPassiveMotionFunc: function(func) { + GLUT.passiveMotionFunc = func; + }, + + glutMouseFunc: function(func) { + GLUT.mouseFunc = func; + }, + + glutCreateWindow__deps: ['$Browser'], + glutCreateWindow: function(name) { + Module.ctx = Browser.createContext(Module['canvas'], true); + return 1; + }, + + glutReshapeWindow__deps: ['$GLUT', 'glutPostRedisplay'], + glutReshapeWindow: function(width, height) { + GLUT.cancelFullScreen(); + Module['canvas'].width = width; + Module['canvas'].height = height; + if (GLUT.reshapeFunc) { + FUNCTION_TABLE[GLUT.reshapeFunc](width, height); + } + _glutPostRedisplay(); + }, + + glutPositionWindow__deps: ['$GLUT', 'glutPostRedisplay'], + glutPositionWindow: function(x, y) { + GLUT.cancelFullScreen(); + /* TODO */ + _glutPostRedisplay(); + }, + + glutFullScreen__deps: ['$GLUT', 'glutPostRedisplay'], + glutFullScreen: function() { + GLUT.windowX = 0; // TODO + GLUT.windowY = 0; // TODO + GLUT.windowWidth = Module['canvas'].width; + GLUT.windowHeight = Module['canvas'].height; + document.addEventListener('fullscreenchange', GLUT.onFullScreenEventChange, true); + document.addEventListener('mozfullscreenchange', GLUT.onFullScreenEventChange, true); + document.addEventListener('webkitfullscreenchange', GLUT.onFullScreenEventChange, true); + GLUT.requestFullScreen(); + }, + + glutInitDisplayMode: function(mode) {}, + glutSwapBuffers: function() {}, + + glutPostRedisplay: function() { + if (GLUT.displayFunc) { + GLUT.requestAnimationFrame(FUNCTION_TABLE[GLUT.displayFunc]); + } + }, + + glutMainLoop__deps: ['$GLUT', 'glutReshapeWindow', 'glutPostRedisplay'], + glutMainLoop: function() { + + window.addEventListener("keydown", GLUT.onKeydown, true); + window.addEventListener("keyup", GLUT.onKeyup, true); + window.addEventListener("mousemove", GLUT.onMousemove, true); + window.addEventListener("mousedown", GLUT.onMouseButtonDown, true); + window.addEventListener("mouseup", GLUT.onMouseButtonUp, true); + + __ATEXIT__.push({ func: function() { + window.removeEventListener("keydown", GLUT.onKeydown, true); + window.removeEventListener("keyup", GLUT.onKeyup, true); + window.removeEventListener("mousemove", GLUT.onMousemove, true); + window.removeEventListener("mousedown", GLUT.onMouseButtonDown, true); + window.removeEventListener("mouseup", GLUT.onMouseButtonUp, true); + Module["canvas"].width = Module["canvas"].height = 1; + } }); + + _glutReshapeWindow(Module['canvas'].width, Module['canvas'].height); + _glutPostRedisplay(); + throw 'GLUT mainloop called, simulating infinite loop by throwing so we get right into the JS event loop'; + }, + +}; + +autoAddDeps(LibraryGLUT, '$GLUT'); +mergeInto(LibraryManager.library, LibraryGLUT); + diff --git a/src/library_sdl.js b/src/library_sdl.js index 7b413c13..f71527af 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -75,50 +75,146 @@ // // * SDL_Quit does nothing. -mergeInto(LibraryManager.library, { - $SDL__deps: ['$Browser'], +var LibrarySDL = { + $SDL__deps: ['$FS', '$Browser'], $SDL: { defaults: { width: 320, height: 200, - copyScreenOnLock: false + copyOnLock: true }, + version: null, + surfaces: {}, events: [], + audios: [null], + fonts: [null], + + keyboardState: null, + startTime: null, + mouseX: 0, + mouseY: 0, + + DOMEventToSDLEvent: { + 'keydown': 0x300, + 'keyup': 0x301, + 'mousedown': 0x401, + 'mouseup': 0x402, + 'mousemove': 0x400 + }, + + keyCodes: { // DOM code ==> SDL code + 38: 1106, // up arrow + 40: 1105, // down arrow + 37: 1104, // left arrow + 39: 1103, // right arrow + + 33: 1099, // pagedup + 34: 1102, // pagedown - keyCodes: { - 38: 273, // up arrow - 40: 274, // down arrow - 37: 276, // left arrow - 39: 275, // right arrow 17: 305, // control (right, or left) 18: 308, // alt 109: 45, // minus 16: 304 // shift }, + scanCodes: { // SDL keycode ==> SDL scancode + 97: 4, // A + 98: 5, + 99: 6, + 100: 7, + 101: 8, + 102: 9, + 103: 10, + 104: 11, + 105: 12, + 106: 13, + 107: 14, + 108: 15, + 109: 16, + 110: 17, + 111: 18, + 112: 19, + 113: 20, + 114: 21, + 115: 22, + 116: 23, + 117: 24, + 118: 25, + 119: 26, + 120: 27, + 121: 28, + 122: 29, // Z + 48: 30, // 0 + 49: 31, + 50: 32, + 51: 33, + 52: 34, + 53: 35, + 54: 36, + 55: 37, + 56: 38, + 57: 39, // 9 + 13: 40, // return + 9: 43, // tab + 32: 44, // space + 92: 49, // backslash + 47: 56, // slash + 1106: 82, // up arrow + 1105: 81, // down arrow + 1104: 80, // left arrow + 1103: 79 // right arrow + }, + structs: { Rect: Runtime.generateStructInfo([ - ['i16', 'x'], ['i16', 'y'], ['i16', 'w'], ['i16', 'h'], + ['i32', 'x'], ['i32', 'y'], ['i32', 'w'], ['i32', 'h'], ]), PixelFormat: Runtime.generateStructInfo([ + ['i32', 'format'], ['void*', 'palette'], ['i8', 'BitsPerPixel'], ['i8', 'BytesPerPixel'], + ['i8', 'padding1'], ['i8', 'padding2'], + ['i32', 'Rmask'], ['i32', 'Gmask'], ['i32', 'Bmask'], ['i32', 'Amask'], ['i8', 'Rloss'], ['i8', 'Gloss'], ['i8', 'Bloss'], ['i8', 'Aloss'], - ['i8', 'Rshift'], ['i8', 'Gshift'], ['i8', 'Bshift'], ['i8', 'Ashift'], - ['i32', 'Rmask'], ['i32', 'Gmask'], ['i32', 'Bmask'], ['i32', 'Amask'] // Docs say i8, ./include/SDL_video.h says i32... + ['i8', 'Rshift'], ['i8', 'Gshift'], ['i8', 'Bshift'], ['i8', 'Ashift'] ]), KeyboardEvent: Runtime.generateStructInfo([ - ['i8', 'type'], - ['i8', 'which'], + ['i32', 'type'], + ['i32', 'windowID'], ['i8', 'state'], + ['i8', 'repeat'], + ['i8', 'padding2'], + ['i8', 'padding3'], ['i32', 'keysym'] ]), keysym: Runtime.generateStructInfo([ - ['i8', 'scancode'], + ['i32', 'scancode'], ['i32', 'sym'], - ['i32', 'mod'], - ['i16', 'unicode'] + ['i16', 'mod'], + ['i32', 'unicode'] + ]), + MouseMotionEvent: Runtime.generateStructInfo([ + ['i32', 'type'], + ['i32', 'windowID'], + ['i8', 'state'], + ['i8', 'padding1'], + ['i8', 'padding2'], + ['i8', 'padding3'], + ['i32', 'x'], + ['i32', 'y'], + ['i32', 'xrel'], + ['i32', 'yrel'] + ]), + MouseButtonEvent: Runtime.generateStructInfo([ + ['i32', 'type'], + ['i32', 'windowID'], + ['i8', 'button'], + ['i8', 'state'], + ['i8', 'padding1'], + ['i8', 'padding2'], + ['i32', 'x'], + ['i32', 'y'] ]), AudioSpec: Runtime.generateStructInfo([ ['i32', 'freq'], @@ -129,12 +225,45 @@ mergeInto(LibraryManager.library, { ['i32', 'size'], ['void*', 'callback'], ['void*', 'userdata'] + ]), + version: Runtime.generateStructInfo([ + ['i8', 'major'], + ['i8', 'minor'], + ['i8', 'patch'] ]) }, - makeSurface: function(width, height, flags) { + loadRect: function(rect) { + return { + x: {{{ makeGetValue('rect + SDL.structs.Rect.x', '0', 'i32') }}}, + y: {{{ makeGetValue('rect + SDL.structs.Rect.y', '0', 'i32') }}}, + w: {{{ makeGetValue('rect + SDL.structs.Rect.w', '0', 'i32') }}}, + h: {{{ makeGetValue('rect + SDL.structs.Rect.h', '0', 'i32') }}} + }; + }, + + // Load SDL color into a CSS-style color specification + loadColorToCSSRGB: function(color) { + var rgba = {{{ makeGetValue('color', '0', 'i32') }}}; + return 'rgb(' + (rgba&255) + ',' + ((rgba >> 8)&255) + ',' + ((rgba >> 16)&255) + ')'; + }, + loadColorToCSSRGBA: function(color) { + var rgba = {{{ makeGetValue('color', '0', 'i32') }}}; + return 'rgba(' + (rgba&255) + ',' + ((rgba >> 8)&255) + ',' + ((rgba >> 16)&255) + ',' + (((rgba >> 24)&255)/255) + ')'; + }, + + translateColorToCSSRGBA: function(rgba) { + return 'rgba(' + ((rgba >> 24)&255) + ',' + ((rgba >> 16)&255) + ',' + ((rgba >> 8)&255) + ',' + ((rgba&255)/255) + ')'; + }, + + translateRGBAToCSSRGBA: function(r, g, b, a) { + return 'rgba(' + r + ',' + g + ',' + b + ',' + (a/255) + ')'; + }, + + makeSurface: function(width, height, flags, usePageCanvas, source, rmask, gmask, bmask, amask) { + flags = flags || 0; var surf = _malloc(14*Runtime.QUANTUM_SIZE); // SDL_Surface has 14 fields of quantum size - var buffer = _malloc(width*height*4); + var buffer = _malloc(width*height*4); // TODO: only allocate when locked the first time var pixelFormat = _malloc(18*Runtime.QUANTUM_SIZE); flags |= 1; // SDL_HWSURFACE - this tells SDL_MUSTLOCK that this needs to be locked @@ -142,70 +271,69 @@ mergeInto(LibraryManager.library, { {{{ makeSetValue('surf+Runtime.QUANTUM_SIZE*1', '0', 'pixelFormat', 'void*') }}} // SDL_Surface.format TODO {{{ makeSetValue('surf+Runtime.QUANTUM_SIZE*2', '0', 'width', 'i32') }}} // SDL_Surface.w {{{ makeSetValue('surf+Runtime.QUANTUM_SIZE*3', '0', 'height', 'i32') }}} // SDL_Surface.h - {{{ makeSetValue('surf+Runtime.QUANTUM_SIZE*4', '0', 'width*4', 'i16') }}} // SDL_Surface.pitch, assuming RGBA for now, + {{{ makeSetValue('surf+Runtime.QUANTUM_SIZE*4', '0', 'width*4', 'i32') }}} // SDL_Surface.pitch, assuming RGBA for now, // since that is what ImageData gives us in browsers {{{ makeSetValue('surf+Runtime.QUANTUM_SIZE*5', '0', 'buffer', 'void*') }}} // SDL_Surface.pixels {{{ makeSetValue('surf+Runtime.QUANTUM_SIZE*6', '0', '0', 'i32*') }}} // SDL_Surface.offset + {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.format', '0', '-2042224636', 'i32') }}} // SDL_PIXELFORMAT_RGBA8888 {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.palette', '0', '0', 'i32') }}} // TODO {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.BitsPerPixel', '0', '32', 'i8') }}} // TODO {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.BytesPerPixel', '0', '4', 'i8') }}} // TODO - {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.Rmask', '0', '0xff', 'i32') }}} - {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.Gmask', '0', '0xff', 'i32') }}} - {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.Bmask', '0', '0xff', 'i32') }}} - {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.Amask', '0', '0xff', 'i32') }}} + {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.Rmask', '0', 'rmask || 0x000000ff', 'i32') }}} + {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.Gmask', '0', 'gmask || 0x0000ff00', 'i32') }}} + {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.Bmask', '0', 'bmask || 0x00ff0000', 'i32') }}} + {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.Amask', '0', 'amask || 0xff000000', 'i32') }}} // Decide if we want to use WebGL or not var useWebGL = (flags & 0x04000000) != 0; // SDL_OPENGL - + var canvas; + if (!usePageCanvas) { + canvas = document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + } else { + canvas = Module['canvas']; + } + var ctx = Browser.createContext(canvas, useWebGL); + if (usePageCanvas) { + Module.ctx = ctx; + } SDL.surfaces[surf] = { width: width, height: height, - canvas: Module['canvas'], - ctx: SDL.createContext(useWebGL), + canvas: canvas, + ctx: ctx, surf: surf, buffer: buffer, pixelFormat: pixelFormat, - alpha: 255 + alpha: 255, + flags: flags, + locked: 0, + usePageCanvas: usePageCanvas, + source: source }; return surf; }, - createContext: function(useWebGL) { -#if !USE_TYPED_ARRAYS - if (useWebGL) { - Module.print('(USE_TYPED_ARRAYS needs to be enabled for WebGL)'); - return null; - } -#endif - try { - var ctx = Module.canvas.getContext(useWebGL ? 'experimental-webgl' : '2d'); - if (!ctx) throw 'Could not create canvas :('; - if (useWebGL) { - // Set the background of the WebGL canvas to black, because SDL gives us a - // window which has a black background by default. - Module.canvas.style.backgroundColor = "black"; - } - return Module.ctx = ctx; - } catch (e) { - Module.print('(canvas not available)'); - return null; - } - }, - freeSurface: function(surf) { _free(SDL.surfaces[surf].buffer); _free(SDL.surfaces[surf].pixelFormat); _free(surf); - delete SDL.surfaces[surf]; + SDL.surfaces[surf] = null; }, receiveEvent: function(event) { switch(event.type) { - case 'keydown': case 'keyup': - //print('zz receive Event: ' + event.keyCode); + case 'keydown': case 'keyup': case 'mousedown': case 'mouseup': case 'mousemove': SDL.events.push(event); + if ((event.keyCode >= 37 && event.keyCode <= 40) || // arrow keys + event.keyCode == 32 || // space + event.keyCode == 33 || event.keyCode == 34) { // page up/down + event.preventDefault(); + } + break; } //event.preventDefault(); return false; @@ -214,45 +342,113 @@ mergeInto(LibraryManager.library, { makeCEvent: function(event, ptr) { if (typeof event === 'number') { // This is a pointer to a native C event that was SDL_PushEvent'ed - _memcpy(ptr, event, SDL.structs.KeyboardEvent.__size__); + _memcpy(ptr, event, SDL.structs.KeyboardEvent.__size__); // XXX return; } switch(event.type) { - case 'keydown': case 'keyup': + case 'keydown': case 'keyup': { var down = event.type === 'keydown'; + //Module.print('Received key event: ' + event.keyCode); var key = SDL.keyCodes[event.keyCode] || event.keyCode; if (key >= 65 && key <= 90) { key = String.fromCharCode(key).toLowerCase().charCodeAt(0); } - //print('zz passing over Event: ' + key); - {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.type', 'down ? 2 : 3', 'i8') }}} - {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.which', '1', 'i8') }}} + var scan = SDL.scanCodes[key] || key; + {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.type', 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}} + //{{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.which', '1', 'i32') }}} {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.state', 'down ? 1 : 0', 'i8') }}} + {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.repeat', '0', 'i8') }}} // TODO - {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.scancode', 'key', 'i8') }}} + {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.scancode', 'scan', 'i32') }}} {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.sym', 'key', 'i32') }}} {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.mod', '0', 'i32') }}} //{{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.unicode', 'key', 'i32') }}} + {{{ makeSetValue('SDL.keyboardState', 'SDL.keyCodes[event.keyCode] || event.keyCode', 'event.type == "keydown"', 'i8') }}}; + break; - case 'keypress': break // TODO + } + case 'mousedown': case 'mouseup': case 'mousemove': { + var x = event.pageX - Module['canvas'].offsetLeft; + var y = event.pageY - Module['canvas'].offsetTop; + if (event.type != 'mousemove') { + var down = event.type === 'mousedown'; + {{{ makeSetValue('ptr', 'SDL.structs.MouseButtonEvent.type', 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}}; + {{{ makeSetValue('ptr', 'SDL.structs.MouseButtonEvent.button', 'event.button+1', 'i8') }}}; // DOM buttons are 0-2, SDL 1-3 + {{{ makeSetValue('ptr', 'SDL.structs.MouseButtonEvent.state', 'down ? 1 : 0', 'i8') }}}; + {{{ makeSetValue('ptr', 'SDL.structs.MouseButtonEvent.x', 'x', 'i32') }}}; + {{{ makeSetValue('ptr', 'SDL.structs.MouseButtonEvent.y', 'y', 'i32') }}}; + } else { + {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.type', 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}}; + {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.button', 'event.button', 'i8') }}}; + {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.state', 'down ? 1 : 0', 'i8') }}}; + {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.x', 'x', 'i32') }}}; + {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.y', 'y', 'i32') }}}; + {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.xrel', 'x - SDL.mouseX', 'i32') }}}; + {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.yrel', 'y - SDL.mouseY', 'i32') }}}; + } + SDL.mouseX = x; + SDL.mouseY = y; + break; + } default: throw 'Unhandled SDL event: ' + event.type; } + }, + + estimateTextWidth: function(fontData, text) { + var h = fontData.size; + var fontString = h + 'px sans-serif'; + // TODO: use temp context, not screen's, to avoid affecting its performance? + var tempCtx = SDL.surfaces[SDL.screen].ctx; + tempCtx.save(); + tempCtx.font = fontString; + var ret = tempCtx.measureText(text).width | 0; + tempCtx.restore(); + return ret; + }, + + // Debugging + + debugSurface: function(surfData) { + console.log('dumping surface ' + [surfData.surf, surfData.source, surfData.width, surfData.height]); + var image = surfData.ctx.getImageData(0, 0, surfData.width, surfData.height); + var data = image.data; + var num = Math.min(surfData.width, surfData.height); + for (var i = 0; i < num; i++) { + console.log(' diagonal ' + i + ':' + [data[i*surfData.width*4 + i*4 + 0], data[i*surfData.width*4 + i*4 + 1], data[i*surfData.width*4 + i*4 + 2], data[i*surfData.width*4 + i*4 + 3]]); + } + } + }, + + SDL_Linked_Version: function() { + if (SDL.version === null) { + SDL.version = _malloc(SDL.structs.version.__size__); + {{{ makeSetValue('SDL.version + SDL.structs.version.major', '0', '1', 'i8') }}} + {{{ makeSetValue('SDL.version + SDL.structs.version.minor', '0', '3', 'i8') }}} + {{{ makeSetValue('SDL.version + SDL.structs.version.patch', '0', '0', 'i8') }}} } + return SDL.version; }, - SDL_Init__deps: ['$SDL'], SDL_Init: function(what) { SDL.startTime = Date.now(); - ['keydown', 'keyup', 'keypress'].forEach(function(event) { + ['keydown', 'keyup'].forEach(function(event) { addEventListener(event, SDL.receiveEvent, true); }); + SDL.keyboardState = _malloc(0x10000); + _memset(SDL.keyboardState, 0, 0x10000); return 0; // success }, - SDL_WasInit: function() { return 0 }, // TODO + SDL_WasInit__deps: ['SDL_Init'], + SDL_WasInit: function() { + if (SDL.startTime === null) { + _SDL_Init(); + } + return 1; + }, SDL_GetVideoInfo: function() { // %struct.SDL_VideoInfo = type { i32, i32, %struct.SDL_PixelFormat*, i32, i32 } - 5 fields of quantum size @@ -269,46 +465,66 @@ mergeInto(LibraryManager.library, { return -1; // -1 == all modes are ok. TODO }, - SDL_GL_SetAttribute: function(attr, value) { - // TODO - }, - SDL_SetVideoMode: function(width, height, depth, flags) { + ['mousedown', 'mouseup', 'mousemove'].forEach(function(event) { + Module['canvas'].addEventListener(event, SDL.receiveEvent, true); + }); Module['canvas'].width = width; Module['canvas'].height = height; - return SDL.screen = SDL.makeSurface(width, height, flags); + return SDL.screen = SDL.makeSurface(width, height, flags, true, 'screen'); }, SDL_Quit: function() { - print('SDL_Quit called (and ignored)'); + for (var i = 0; i < SDL.audios; i++) { + SDL.audios[i].pause(); + } + Module.print('SDL_Quit called (and ignored)'); }, + // Copy data from the canvas backing to a C++-accessible storage SDL_LockSurface: function(surf) { var surfData = SDL.surfaces[surf]; + + surfData.locked++; + if (surfData.locked > 1) return 0; + if (!surfData.image) { surfData.image = surfData.ctx.getImageData(0, 0, surfData.width, surfData.height); - var data = surfData.image.data; - var num = data.length; - for (var i = 0; i < num/4; i++) { - data[i*4+3] = 255; // opacity, as canvases blend alpha + if (surf == SDL.screen) { + var data = surfData.image.data; + var num = data.length; + for (var i = 0; i < num/4; i++) { + data[i*4+3] = 255; // opacity, as canvases blend alpha + } } } - if (SDL.defaults.copyScreenOnLock) { + if (SDL.defaults.copyOnLock) { // Copy pixel data to somewhere accessible to 'C/C++' +#if USE_TYPED_ARRAYS == 2 + HEAPU8.set(surfData.image.data, surfData.buffer); +#else var num2 = surfData.image.data.length; for (var i = 0; i < num2; i++) { {{{ makeSetValue('surfData.buffer', 'i', 'surfData.image.data[i]', 'i8') }}}; } +#endif } // Mark in C/C++-accessible SDL structure // SDL_Surface has the following fields: Uint32 flags, SDL_PixelFormat *format; int w, h; Uint16 pitch; void *pixels; ... // So we have fields all of the same size, and 5 of them before us. // TODO: Use macros like in library.js {{{ makeSetValue('surf', '5*Runtime.QUANTUM_SIZE', 'surfData.buffer', 'void*') }}}; + + return 0; }, + // Copy data from the C++-accessible storage to the canvas backing SDL_UnlockSurface: function(surf) { var surfData = SDL.surfaces[surf]; + + surfData.locked--; + if (surfData.locked > 0) return; + // Copy pixel data to image var num = surfData.image.data.length; if (!surfData.colors) { @@ -318,12 +534,14 @@ mergeInto(LibraryManager.library, { assert(buffer % 4 == 0, 'Invalid buffer offset: ' + buffer); var src = buffer >> 2; var dst = 0; + var isScreen = surf == SDL.screen; while (dst < num) { + // TODO: access underlying data buffer and write in 32-bit chunks or more var val = HEAP32[src]; // This is optimized. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}}; - data[dst] = val & 0xff; + data[dst ] = val & 0xff; data[dst+1] = (val >> 8) & 0xff; data[dst+2] = (val >> 16) & 0xff; - data[dst+3] = 0xff; + data[dst+3] = isScreen ? 0xff : ((val >> 24) & 0xff); src++; dst += 4; } @@ -361,7 +579,8 @@ mergeInto(LibraryManager.library, { }, SDL_Flip: function(surf) { - // We actually do this in Unlock... + // We actually do this in Unlock, since the screen surface has as its canvas + // backing the page canvas element }, SDL_UpdateRect: function(surf, x, y, w, h) { @@ -369,7 +588,7 @@ mergeInto(LibraryManager.library, { }, SDL_Delay: function(delay) { - print('SDL_Delay called! - potential infinite loop'); + throw 'SDL_Delay called! Potential infinite loop, quitting. ' + new Error().stack; }, SDL_WM_SetCaption: function(title, icon) { @@ -381,6 +600,16 @@ mergeInto(LibraryManager.library, { // TODO }, + SDL_GetKeyboardState: function() { + return SDL.keyboardState; + }, + + SDL_GetMouseState: function(x, y) { + if (x) {{{ makeSetValue('x', '0', 'SDL.mouseX', 'i32') }}}; + if (y) {{{ makeSetValue('y', '0', 'SDL.mouseY', 'i32') }}}; + return 0; + }, + SDL_ShowCursor: function(toggle) { // TODO }, @@ -390,55 +619,65 @@ mergeInto(LibraryManager.library, { }, SDL_CreateRGBSurface: function(flags, width, height, depth, rmask, gmask, bmask, amask) { - return SDL.makeSurface(width, height, flags); + return SDL.makeSurface(width, height, flags, false, 'CreateRGBSurface', rmask, gmask, bmask, amask); + }, + + SDL_DisplayFormatAlpha: function(surf) { + var oldData = SDL.surfaces[surf]; + var ret = SDL.makeSurface(oldData.width, oldData.height, oldData.flags, false, 'copy:' + oldData.source); + var newData = SDL.surfaces[ret]; + //newData.ctx.putImageData(oldData.ctx.getImageData(0, 0, oldData.width, oldData.height), 0, 0); + newData.ctx.drawImage(oldData.canvas, 0, 0); + return ret; }, SDL_FreeSurface: function(surf) { - SDL.freeSurface(surf); + if (surf) SDL.freeSurface(surf); }, SDL_UpperBlit: function(src, srcrect, dst, dstrect) { - assert(!srcrect && !dstrect); // TODO var srcData = SDL.surfaces[src]; var dstData = SDL.surfaces[dst]; - assert(srcData.width === dstData.width && srcData.height === dstData.height); - {{{ makeCopyValues('dstData.buffer', 'srcData.buffer', 'srcData.width*srcData.height*4', 'i8', null, 1) }}} + var sr, dr; + if (srcrect) { + sr = SDL.loadRect(srcrect); + } else { + sr = { x: 0, y: 0, w: srcData.width, h: srcData.height }; + } + if (dstrect) { + dr = SDL.loadRect(dstrect); + } else { + dr = { x: 0, y: 0, w: -1, h: -1 }; + } + dstData.ctx.drawImage(srcData.canvas, sr.x, sr.y, sr.w, sr.h, dr.x, dr.y, sr.w, sr.h); + if (dst != SDL.screen) { + // XXX As in IMG_Load, for compatibility we write out |pixels| + console.log('WARNING: copying canvas data to memory for compatibility'); + _SDL_LockSurface(dst); + dstData.locked--; // The surface is not actually locked in this hack + } return 0; }, SDL_FillRect: function(surf, rect, color) { var surfData = SDL.surfaces[surf]; - var c1 = color & 0xff; - var c2 = (color >> 8) & 0xff; - var c3 = (color >> 16) & 0xff; - var rx = {{{ makeGetValue('rect + SDL.structs.Rect.x', '0', 'i16') }}}; - var ry = {{{ makeGetValue('rect + SDL.structs.Rect.y', '0', 'i16') }}}; - var rw = {{{ makeGetValue('rect + SDL.structs.Rect.w', '0', 'i16') }}}; - var rh = {{{ makeGetValue('rect + SDL.structs.Rect.h', '0', 'i16') }}}; - var data = surfData.image.data; - var width = surfData.width; - for (var y = ry; y < ry + rh; y++) { - var base = y*width*4; - for (var x = rx; x < rx + rw; x++) { - var start = x*4 + base; - data[start] = c1; - data[start+1] = c2; - data[start+2] = c3; - } - } + assert(!surfData.locked); // but we could unlock and re-lock if we must.. + var r = SDL.loadRect(rect); + surfData.ctx.save(); + surfData.ctx.fillStyle = SDL.translateColorToCSSRGBA(color); + surfData.ctx.fillRect(r.x, r.y, r.w, r.h); + surfData.ctx.restore(); }, SDL_BlitSurface__deps: ['SDL_UpperBlit'], SDL_BlitSurface: function(src, srcrect, dst, dstrect) { - return _SDL_Blit(src, srcrect, dst, dstrect); + return _SDL_UpperBlit(src, srcrect, dst, dstrect); }, SDL_SetAlpha: function(surf, flag, alpha) { SDL.surfaces[surf].alpha = alpha; }, - SDL_GL_SwapBuffers: function() {}, - SDL_GetTicks: function() { return Math.floor(Date.now() - SDL.startTime); }, @@ -453,10 +692,30 @@ mergeInto(LibraryManager.library, { SDL_PushEvent: function(ptr) { SDL.events.push(ptr); // XXX Should we copy it? Not clear from API - return 0; }, + SDL_PeepEvents: function(events, numEvents, action, from, to) { + switch(action) { + case 2: { // SDL_GETEVENT + assert(numEvents == 1); + var got = 0; + while (SDL.events.length > 0 && numEvents > 0) { + var type = SDL.DOMEventToSDLEvent[SDL.events[0].type]; + if (type < from || type > to) break; + SDL.makeCEvent(SDL.events.shift(), events); + got++; + numEvents--; + // events += sizeof(..) + } + return got; + } + default: throw 'SDL_PeepEvents does not yet support that action: ' + action; + } + }, + + SDL_PumpEvents: function(){}, + SDL_SetColors: function(surf, colors, firstColor, nColors) { var surfData = SDL.surfaces[surf]; surfData.colors = []; @@ -476,18 +735,26 @@ mergeInto(LibraryManager.library, { // SDL_Image + IMG_Load__deps: ['SDL_LockSurface'], IMG_Load: function(filename) { - filename = Pointer_stringify(filename); - var format = filename.split('.').slice(-1)[0]; - var data = readBinary(filename); - var raw = Browser.decodeImage(data, format); - var surf = SDL.makeSurface(raw.width, raw.height, 0); - // XXX Extremely inefficient! - for (var i = 0; i < raw.width*raw.height*4; i++) { - {{{ makeSetValue('SDL.surfaces[surf].buffer', 'i', 'raw.data[i]', 'i8') }}} + filename = FS.standardizePath(Pointer_stringify(filename)); + var raw = preloadedImages[filename]; + if (!raw) { + Module.printErr('Cannot find preloaded image ' + filename); + return 0; } + var surf = SDL.makeSurface(raw.width, raw.height, 0, false, 'load:' + filename); + var surfData = SDL.surfaces[surf]; + surfData.ctx.drawImage(raw, 0, 0, raw.width, raw.height, 0, 0, raw.width, raw.height); + // XXX SDL does not specify that loaded images must have available pixel data, in fact + // there are cases where you just want to blit them, so you just need the hardware + // accelerated version. However, code everywhere seems to assume that the pixels + // are in fact available, so we retrieve it here. This does add overhead though. + _SDL_LockSurface(surf); + surfData.locked--; // The surface is not actually locked in this hack return surf; }, + SDL_LoadBMP: 'IMG_Load', // SDL_Audio @@ -560,15 +827,225 @@ mergeInto(LibraryManager.library, { SDL_CondWait: function() {}, SDL_DestroyCond: function() {}, -//SDL_CreateYUVOverlay -//SDL_CreateThread, SDL_WaitThread etc - // SDL Mixer - Mix_OpenAudio: function() { return -1 }, + Mix_OpenAudio: function(frequency, format, channels, chunksize) { + return 0; + }, + + Mix_AllocateChannels: function(num) { + return num; // fake it + }, + + Mix_ChannelFinished: function(func) { + SDL.channelFinished = func; // TODO + }, + + Mix_HookMusicFinished: function(func) { + SDL.hookMusicFinished = func; + }, + + Mix_VolumeMusic: function(func) { + return 0; // TODO + }, + + Mix_LoadWAV_RW: function(filename, freesrc) { + filename = FS.standardizePath(Pointer_stringify(filename)); + var raw = preloadedAudios[filename]; + if (!raw) { + Module.printErr('Cannot find preloaded audio ' + filename); + return 0; + } + var id = SDL.audios.length; + SDL.audios.push({ + source: filename, + audio: raw + }); + return id; + }, + + Mix_FreeChunk: function(id) { + SDL.audios[id].audio.pause(); + SDL.audios[id] = null; + }, + + Mix_PlayChannel: function(channel, id, loops) { + // TODO: handle loops + var audio = SDL.audios[id].audio; + if (!audio) return 0; + if (audio.currentTime) audio.src = audio.src; // This hack prevents lags on replaying // TODO: parallel sounds through //cloneNode(true).play() + audio.play(); + return 1; // XXX should return channel + }, + Mix_PlayChannelTimed: 'Mix_PlayChannel', // XXX ignore Timing + + Mix_LoadMUS: 'Mix_LoadWAV_RW', + Mix_FreeMusic: 'Mix_FreeChunk', + + Mix_PlayMusic: function(id, loops) { + loops = Math.max(loops, 1); + var audio = SDL.audios[id].audio; + if (!audio) return 0; + audio.loop = loops != 1; // TODO: handle N loops for finite N + audio.play(); + SDL.music = audio; + return 0; + }, + + Mix_PauseMusic: function(id) { + var audio = SDL.audios[id]; + if (!audio) return 0; + audio.audio.pause(); + return 0; + }, + + Mix_ResumeMusic: function(id) { + var audio = SDL.audios[id]; + if (!audio) return 0; + audio.audio.play(); + return 0; + }, + + Mix_HaltMusic: function() { + var audio = SDL.music; + if (!audio) return 0; + audio.src = audio.src; // rewind + audio.pause(); + SDL.music = null; + if (SDL.hookMusicFinished) { + FUNCTION_TABLE[SDL.hookMusicFinished](); + } + return 0; + }, + + Mix_FadeInMusicPos: 'Mix_PlayMusic', // XXX ignore fading in effect + + Mix_FadeOutMusic: 'Mix_HaltMusic', // XXX ignore fading out effect + + // SDL TTF + + TTF_Init: function() { return 0 }, + + TTF_OpenFont: function(filename, size) { + filename = FS.standardizePath(Pointer_stringify(filename)); + var id = SDL.fonts.length; + SDL.fonts.push({ + name: filename, // but we don't actually do anything with it.. + size: size + }); + return id; + }, + + TTF_RenderText_Solid: function(font, text, color) { + // XXX the font and color are ignored + text = Pointer_stringify(text) || ' '; // if given an empty string, still return a valid surface + var fontData = SDL.fonts[font]; + var w = SDL.estimateTextWidth(fontData, text); + var h = fontData.size; + var color = SDL.loadColorToCSSRGB(color); // XXX alpha breaks fonts? + var fontString = h + 'px sans-serif'; + var surf = SDL.makeSurface(w, h, 0, false, 'text:' + text); // bogus numbers.. + var surfData = SDL.surfaces[surf]; + surfData.ctx.save(); + surfData.ctx.fillStyle = color; + surfData.ctx.font = fontString; + surfData.ctx.textBaseline = 'top'; + surfData.ctx.fillText(text, 0, 0); + surfData.ctx.restore(); + return surf; + }, + TTF_RenderText_Blended: 'TTF_RenderText_Solid', // XXX ignore blending vs. solid + TTF_RenderText_Shaded: 'TTF_RenderText_Solid', // XXX ignore blending vs. solid + + TTF_SizeText: function(font, text, w, h) { + var fontData = SDL.fonts[font]; + if (w) { + {{{ makeSetValue('w', '0', 'SDL.estimateTextWidth(fontData, Pointer_stringify(text))', 'i32') }}}; + } + if (h) { + {{{ makeSetValue('h', '0', 'fontData.size', 'i32') }}}; + } + return 0; + }, + + TTF_FontAscent: function(font) { + var fontData = SDL.fonts[font]; + return Math.floor(fontData.size*0.98); // XXX + }, + + TTF_FontDescent: function(font) { + var fontData = SDL.fonts[font]; + return Math.floor(fontData.size*0.02); // XXX + }, + + // SDL gfx + + boxRGBA: function(surf, x1, y1, x2, y2, r, g, b, a) { + var surfData = SDL.surfaces[surf]; + assert(!surfData.locked); // but we could unlock and re-lock if we must.. + // TODO: if ctx does not change, leave as is, and also do not re-set xStyle etc. + surfData.ctx.save(); + surfData.ctx.fillStyle = SDL.translateRGBAToCSSRGBA(r, g, b, a); + surfData.ctx.fillRect(x1, y1, x2-x1, y2-y1); + surfData.ctx.restore(); + }, + + rectangleRGBA: function(surf, x1, y1, x2, y2, r, g, b, a) { + var surfData = SDL.surfaces[surf]; + assert(!surfData.locked); // but we could unlock and re-lock if we must.. + surfData.ctx.save(); + surfData.ctx.strokeStyle = SDL.translateRGBAToCSSRGBA(r, g, b, a); + surfData.ctx.strokeRect(x1, y1, x2-x1, y2-y1); + surfData.ctx.restore(); + }, + + lineRGBA: function(surf, x1, y1, x2, y2, r, g, b, a) { + var surfData = SDL.surfaces[surf]; + assert(!surfData.locked); // but we could unlock and re-lock if we must.. + surfData.ctx.save(); + surfData.ctx.strokeStyle = SDL.translateRGBAToCSSRGBA(r, g, b, a); + surfData.ctx.beginPath(); + surfData.ctx.moveTo(x1, y1); + surfData.ctx.lineTo(x2, y2); + surfData.ctx.stroke(); + surfData.ctx.restore(); + }, + + pixelRGBA__deps: ['boxRGBA'], + pixelRGBA: function(surf, x1, y1, r, g, b, a) { + // This cannot be fast, to render many pixels this way! + _boxRGBA(surf, x1, y1, x1, y1, r, g, b, a); + }, + + // GL + + SDL_GL_SetAttribute: function(attr, value) { + console.log('TODO: SDL_GL_SetAttribute'); + }, + + SDL_GL_GetProcAddress__deps: ['$GLEmulation'], + SDL_GL_GetProcAddress: function(name_) { + return GLEmulation.getProcAddress(Pointer_stringify(name_)); + }, + + SDL_GL_SwapBuffers: function() {}, + + // Misc SDL_InitSubSystem: function(flags) { return 0 }, + SDL_NumJoysticks: function() { return 0 }, + + SDL_RWFromFile: function(filename, mode) { + return filename; // XXX We just forward the filename + }, + + SDL_EnableUNICODE: function(on) { + var ret = SDL.unicode || 0; + SDL.unicode = on; + return ret; + }, + SDL_AddTimer: function(interval, callback, param) { return window.setTimeout(function() { FUNCTION_TABLE[callback](interval, param); @@ -577,6 +1054,9 @@ mergeInto(LibraryManager.library, { SDL_RemoveTimer: function(id) { window.clearTimeout(id); return true; - }, -}); + } +}; + +autoAddDeps(LibrarySDL, '$SDL'); +mergeInto(LibraryManager.library, LibrarySDL); diff --git a/src/library_xlib.js b/src/library_xlib.js new file mode 100644 index 00000000..a110c786 --- /dev/null +++ b/src/library_xlib.js @@ -0,0 +1,24 @@ + +var LibraryXlib = { + XOpenDisplay: function() { + return 1; // We support 1 display, the canvas + }, + + XCreateWindow: function(display, parent, x, y, width, height, border_width, depth, class_, visual, valuemask, attributes) { + // All we can do is set the width and height + Module['canvas'].width = width; + Module['canvas'].height = height; + return 2; + }, + + XChangeWindowAttributes: function(){}, + XSetWMHints: function(){}, + XMapWindow: function(){}, + XStoreName: function(){}, + XInternAtom: function(display, name_, hmm) { return 0 }, + XSendEvent: function(){}, + XPending: function(display) { return 0 }, +}; + +mergeInto(LibraryManager.library, LibraryXlib); + diff --git a/src/long.js b/src/long.js new file mode 100644 index 00000000..71cffa79 --- /dev/null +++ b/src/long.js @@ -0,0 +1,1633 @@ +// TODO: strip out parts of this we do not need + +//======= begin closure i64 code ======= + +// Copyright 2009 The Closure Library Authors. All Rights Reserved. +// +// Licensed 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. + +/** + * @fileoverview Defines a Long class for representing a 64-bit two's-complement + * integer value, which faithfully simulates the behavior of a Java "long". This + * implementation is derived from LongLib in GWT. + * + */ + +var i64Math = (function() { // Emscripten wrapper +var goog = { math: {} }; + + +/** + * Constructs a 64-bit two's-complement integer, given its low and high 32-bit + * values as *signed* integers. See the from* functions below for more + * convenient ways of constructing Longs. + * + * The internal representation of a long is the two given signed, 32-bit values. + * We use 32-bit pieces because these are the size of integers on which + * Javascript performs bit-operations. For operations like addition and + * multiplication, we split each number into 16-bit pieces, which can easily be + * multiplied within Javascript's floating-point representation without overflow + * or change in sign. + * + * In the algorithms below, we frequently reduce the negative case to the + * positive case by negating the input(s) and then post-processing the result. + * Note that we must ALWAYS check specially whether those values are MIN_VALUE + * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + * a positive number, it overflows back into a negative). Not handling this + * case would often result in infinite recursion. + * + * @param {number} low The low (signed) 32 bits of the long. + * @param {number} high The high (signed) 32 bits of the long. + * @constructor + */ +goog.math.Long = function(low, high) { + /** + * @type {number} + * @private + */ + this.low_ = low | 0; // force into 32 signed bits. + + /** + * @type {number} + * @private + */ + this.high_ = high | 0; // force into 32 signed bits. +}; + + +// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the +// from* methods on which they depend. + + +/** + * A cache of the Long representations of small integer values. + * @type {!Object} + * @private + */ +goog.math.Long.IntCache_ = {}; + + +/** + * Returns a Long representing the given (32-bit) integer value. + * @param {number} value The 32-bit integer in question. + * @return {!goog.math.Long} The corresponding Long value. + */ +goog.math.Long.fromInt = function(value) { + if (-128 <= value && value < 128) { + var cachedObj = goog.math.Long.IntCache_[value]; + if (cachedObj) { + return cachedObj; + } + } + + var obj = new goog.math.Long(value | 0, value < 0 ? -1 : 0); + if (-128 <= value && value < 128) { + goog.math.Long.IntCache_[value] = obj; + } + return obj; +}; + + +/** + * Returns a Long representing the given value, provided that it is a finite + * number. Otherwise, zero is returned. + * @param {number} value The number in question. + * @return {!goog.math.Long} The corresponding Long value. + */ +goog.math.Long.fromNumber = function(value) { + if (isNaN(value) || !isFinite(value)) { + return goog.math.Long.ZERO; + } else if (value <= -goog.math.Long.TWO_PWR_63_DBL_) { + return goog.math.Long.MIN_VALUE; + } else if (value + 1 >= goog.math.Long.TWO_PWR_63_DBL_) { + return goog.math.Long.MAX_VALUE; + } else if (value < 0) { + return goog.math.Long.fromNumber(-value).negate(); + } else { + return new goog.math.Long( + (value % goog.math.Long.TWO_PWR_32_DBL_) | 0, + (value / goog.math.Long.TWO_PWR_32_DBL_) | 0); + } +}; + + +/** + * Returns a Long representing the 64-bit integer that comes by concatenating + * the given high and low bits. Each is assumed to use 32 bits. + * @param {number} lowBits The low 32-bits. + * @param {number} highBits The high 32-bits. + * @return {!goog.math.Long} The corresponding Long value. + */ +goog.math.Long.fromBits = function(lowBits, highBits) { + return new goog.math.Long(lowBits, highBits); +}; + + +/** + * Returns a Long representation of the given string, written using the given + * radix. + * @param {string} str The textual representation of the Long. + * @param {number=} opt_radix The radix in which the text is written. + * @return {!goog.math.Long} The corresponding Long value. + */ +goog.math.Long.fromString = function(str, opt_radix) { + if (str.length == 0) { + throw Error('number format error: empty string'); + } + + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (str.charAt(0) == '-') { + return goog.math.Long.fromString(str.substring(1), radix).negate(); + } else if (str.indexOf('-') >= 0) { + throw Error('number format error: interior "-" character: ' + str); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 8)); + + var result = goog.math.Long.ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i); + var value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = goog.math.Long.fromNumber(Math.pow(radix, size)); + result = result.multiply(power).add(goog.math.Long.fromNumber(value)); + } else { + result = result.multiply(radixToPower); + result = result.add(goog.math.Long.fromNumber(value)); + } + } + return result; +}; + + +// NOTE: the compiler should inline these constant values below and then remove +// these variables, so there should be no runtime penalty for these. + + +/** + * Number used repeated below in calculations. This must appear before the + * first call to any from* function below. + * @type {number} + * @private + */ +goog.math.Long.TWO_PWR_16_DBL_ = 1 << 16; + + +/** + * @type {number} + * @private + */ +goog.math.Long.TWO_PWR_24_DBL_ = 1 << 24; + + +/** + * @type {number} + * @private + */ +goog.math.Long.TWO_PWR_32_DBL_ = + goog.math.Long.TWO_PWR_16_DBL_ * goog.math.Long.TWO_PWR_16_DBL_; + + +/** + * @type {number} + * @private + */ +goog.math.Long.TWO_PWR_31_DBL_ = + goog.math.Long.TWO_PWR_32_DBL_ / 2; + + +/** + * @type {number} + * @private + */ +goog.math.Long.TWO_PWR_48_DBL_ = + goog.math.Long.TWO_PWR_32_DBL_ * goog.math.Long.TWO_PWR_16_DBL_; + + +/** + * @type {number} + * @private + */ +goog.math.Long.TWO_PWR_64_DBL_ = + goog.math.Long.TWO_PWR_32_DBL_ * goog.math.Long.TWO_PWR_32_DBL_; + + +/** + * @type {number} + * @private + */ +goog.math.Long.TWO_PWR_63_DBL_ = + goog.math.Long.TWO_PWR_64_DBL_ / 2; + + +/** @type {!goog.math.Long} */ +goog.math.Long.ZERO = goog.math.Long.fromInt(0); + + +/** @type {!goog.math.Long} */ +goog.math.Long.ONE = goog.math.Long.fromInt(1); + + +/** @type {!goog.math.Long} */ +goog.math.Long.NEG_ONE = goog.math.Long.fromInt(-1); + + +/** @type {!goog.math.Long} */ +goog.math.Long.MAX_VALUE = + goog.math.Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); + + +/** @type {!goog.math.Long} */ +goog.math.Long.MIN_VALUE = goog.math.Long.fromBits(0, 0x80000000 | 0); + + +/** + * @type {!goog.math.Long} + * @private + */ +goog.math.Long.TWO_PWR_24_ = goog.math.Long.fromInt(1 << 24); + + +/** @return {number} The value, assuming it is a 32-bit integer. */ +goog.math.Long.prototype.toInt = function() { + return this.low_; +}; + + +/** @return {number} The closest floating-point representation to this value. */ +goog.math.Long.prototype.toNumber = function() { + return this.high_ * goog.math.Long.TWO_PWR_32_DBL_ + + this.getLowBitsUnsigned(); +}; + + +/** + * @param {number=} opt_radix The radix in which the text should be written. + * @return {string} The textual representation of this value. + */ +goog.math.Long.prototype.toString = function(opt_radix) { + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (this.isZero()) { + return '0'; + } + + if (this.isNegative()) { + if (this.equals(goog.math.Long.MIN_VALUE)) { + // We need to change the Long value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixLong = goog.math.Long.fromNumber(radix); + var div = this.div(radixLong); + var rem = div.multiply(radixLong).subtract(this); + return div.toString(radix) + rem.toInt().toString(radix); + } else { + return '-' + this.negate().toString(radix); + } + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 6)); + + var rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower); + var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); + var digits = intval.toString(radix); + + rem = remDiv; + if (rem.isZero()) { + return digits + result; + } else { + while (digits.length < 6) { + digits = '0' + digits; + } + result = '' + digits + result; + } + } +}; + + +/** @return {number} The high 32-bits as a signed value. */ +goog.math.Long.prototype.getHighBits = function() { + return this.high_; +}; + + +/** @return {number} The low 32-bits as a signed value. */ +goog.math.Long.prototype.getLowBits = function() { + return this.low_; +}; + + +/** @return {number} The low 32-bits as an unsigned value. */ +goog.math.Long.prototype.getLowBitsUnsigned = function() { + return (this.low_ >= 0) ? + this.low_ : goog.math.Long.TWO_PWR_32_DBL_ + this.low_; +}; + + +/** + * @return {number} Returns the number of bits needed to represent the absolute + * value of this Long. + */ +goog.math.Long.prototype.getNumBitsAbs = function() { + if (this.isNegative()) { + if (this.equals(goog.math.Long.MIN_VALUE)) { + return 64; + } else { + return this.negate().getNumBitsAbs(); + } + } else { + var val = this.high_ != 0 ? this.high_ : this.low_; + for (var bit = 31; bit > 0; bit--) { + if ((val & (1 << bit)) != 0) { + break; + } + } + return this.high_ != 0 ? bit + 33 : bit + 1; + } +}; + + +/** @return {boolean} Whether this value is zero. */ +goog.math.Long.prototype.isZero = function() { + return this.high_ == 0 && this.low_ == 0; +}; + + +/** @return {boolean} Whether this value is negative. */ +goog.math.Long.prototype.isNegative = function() { + return this.high_ < 0; +}; + + +/** @return {boolean} Whether this value is odd. */ +goog.math.Long.prototype.isOdd = function() { + return (this.low_ & 1) == 1; +}; + + +/** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long equals the other. + */ +goog.math.Long.prototype.equals = function(other) { + return (this.high_ == other.high_) && (this.low_ == other.low_); +}; + + +/** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long does not equal the other. + */ +goog.math.Long.prototype.notEquals = function(other) { + return (this.high_ != other.high_) || (this.low_ != other.low_); +}; + + +/** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is less than the other. + */ +goog.math.Long.prototype.lessThan = function(other) { + return this.compare(other) < 0; +}; + + +/** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is less than or equal to the other. + */ +goog.math.Long.prototype.lessThanOrEqual = function(other) { + return this.compare(other) <= 0; +}; + + +/** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is greater than the other. + */ +goog.math.Long.prototype.greaterThan = function(other) { + return this.compare(other) > 0; +}; + + +/** + * @param {goog.math.Long} other Long to compare against. + * @return {boolean} Whether this Long is greater than or equal to the other. + */ +goog.math.Long.prototype.greaterThanOrEqual = function(other) { + return this.compare(other) >= 0; +}; + + +/** + * Compares this Long with the given one. + * @param {goog.math.Long} other Long to compare against. + * @return {number} 0 if they are the same, 1 if the this is greater, and -1 + * if the given one is greater. + */ +goog.math.Long.prototype.compare = function(other) { + if (this.equals(other)) { + return 0; + } + + var thisNeg = this.isNegative(); + var otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) { + return -1; + } + if (!thisNeg && otherNeg) { + return 1; + } + + // at this point, the signs are the same, so subtraction will not overflow + if (this.subtract(other).isNegative()) { + return -1; + } else { + return 1; + } +}; + + +/** @return {!goog.math.Long} The negation of this value. */ +goog.math.Long.prototype.negate = function() { + if (this.equals(goog.math.Long.MIN_VALUE)) { + return goog.math.Long.MIN_VALUE; + } else { + return this.not().add(goog.math.Long.ONE); + } +}; + + +/** + * Returns the sum of this and the given Long. + * @param {goog.math.Long} other Long to add to this one. + * @return {!goog.math.Long} The sum of this and the given Long. + */ +goog.math.Long.prototype.add = function(other) { + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + + +/** + * Returns the difference of this and the given Long. + * @param {goog.math.Long} other Long to subtract from this. + * @return {!goog.math.Long} The difference of this and the given Long. + */ +goog.math.Long.prototype.subtract = function(other) { + return this.add(other.negate()); +}; + + +/** + * Returns the product of this and the given long. + * @param {goog.math.Long} other Long to multiply with this. + * @return {!goog.math.Long} The product of this and the other. + */ +goog.math.Long.prototype.multiply = function(other) { + if (this.isZero()) { + return goog.math.Long.ZERO; + } else if (other.isZero()) { + return goog.math.Long.ZERO; + } + + if (this.equals(goog.math.Long.MIN_VALUE)) { + return other.isOdd() ? goog.math.Long.MIN_VALUE : goog.math.Long.ZERO; + } else if (other.equals(goog.math.Long.MIN_VALUE)) { + return this.isOdd() ? goog.math.Long.MIN_VALUE : goog.math.Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().multiply(other.negate()); + } else { + return this.negate().multiply(other).negate(); + } + } else if (other.isNegative()) { + return this.multiply(other.negate()).negate(); + } + + // If both longs are small, use float multiplication + if (this.lessThan(goog.math.Long.TWO_PWR_24_) && + other.lessThan(goog.math.Long.TWO_PWR_24_)) { + return goog.math.Long.fromNumber(this.toNumber() * other.toNumber()); + } + + // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + + +/** + * Returns this Long divided by the given one. + * @param {goog.math.Long} other Long by which to divide. + * @return {!goog.math.Long} This Long divided by the given one. + */ +goog.math.Long.prototype.div = function(other) { + if (other.isZero()) { + throw Error('division by zero'); + } else if (this.isZero()) { + return goog.math.Long.ZERO; + } + + if (this.equals(goog.math.Long.MIN_VALUE)) { + if (other.equals(goog.math.Long.ONE) || + other.equals(goog.math.Long.NEG_ONE)) { + return goog.math.Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + } else if (other.equals(goog.math.Long.MIN_VALUE)) { + return goog.math.Long.ONE; + } else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shiftRight(1); + var approx = halfThis.div(other).shiftLeft(1); + if (approx.equals(goog.math.Long.ZERO)) { + return other.isNegative() ? goog.math.Long.ONE : goog.math.Long.NEG_ONE; + } else { + var rem = this.subtract(other.multiply(approx)); + var result = approx.add(rem.div(other)); + return result; + } + } + } else if (other.equals(goog.math.Long.MIN_VALUE)) { + return goog.math.Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().div(other.negate()); + } else { + return this.negate().div(other).negate(); + } + } else if (other.isNegative()) { + return this.div(other.negate()).negate(); + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + var res = goog.math.Long.ZERO; + var rem = this; + while (rem.greaterThanOrEqual(other)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2); + var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + var approxRes = goog.math.Long.fromNumber(approx); + var approxRem = approxRes.multiply(other); + while (approxRem.isNegative() || approxRem.greaterThan(rem)) { + approx -= delta; + approxRes = goog.math.Long.fromNumber(approx); + approxRem = approxRes.multiply(other); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) { + approxRes = goog.math.Long.ONE; + } + + res = res.add(approxRes); + rem = rem.subtract(approxRem); + } + return res; +}; + + +/** + * Returns this Long modulo the given one. + * @param {goog.math.Long} other Long by which to mod. + * @return {!goog.math.Long} This Long modulo the given one. + */ +goog.math.Long.prototype.modulo = function(other) { + return this.subtract(this.div(other).multiply(other)); +}; + + +/** @return {!goog.math.Long} The bitwise-NOT of this value. */ +goog.math.Long.prototype.not = function() { + return goog.math.Long.fromBits(~this.low_, ~this.high_); +}; + + +/** + * Returns the bitwise-AND of this Long and the given one. + * @param {goog.math.Long} other The Long with which to AND. + * @return {!goog.math.Long} The bitwise-AND of this and the other. + */ +goog.math.Long.prototype.and = function(other) { + return goog.math.Long.fromBits(this.low_ & other.low_, + this.high_ & other.high_); +}; + + +/** + * Returns the bitwise-OR of this Long and the given one. + * @param {goog.math.Long} other The Long with which to OR. + * @return {!goog.math.Long} The bitwise-OR of this and the other. + */ +goog.math.Long.prototype.or = function(other) { + return goog.math.Long.fromBits(this.low_ | other.low_, + this.high_ | other.high_); +}; + + +/** + * Returns the bitwise-XOR of this Long and the given one. + * @param {goog.math.Long} other The Long with which to XOR. + * @return {!goog.math.Long} The bitwise-XOR of this and the other. + */ +goog.math.Long.prototype.xor = function(other) { + return goog.math.Long.fromBits(this.low_ ^ other.low_, + this.high_ ^ other.high_); +}; + + +/** + * Returns this Long with bits shifted to the left by the given amount. + * @param {number} numBits The number of bits by which to shift. + * @return {!goog.math.Long} This shifted to the left by the given amount. + */ +goog.math.Long.prototype.shiftLeft = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var low = this.low_; + if (numBits < 32) { + var high = this.high_; + return goog.math.Long.fromBits( + low << numBits, + (high << numBits) | (low >>> (32 - numBits))); + } else { + return goog.math.Long.fromBits(0, low << (numBits - 32)); + } + } +}; + + +/** + * Returns this Long with bits shifted to the right by the given amount. + * @param {number} numBits The number of bits by which to shift. + * @return {!goog.math.Long} This shifted to the right by the given amount. + */ +goog.math.Long.prototype.shiftRight = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return goog.math.Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >> numBits); + } else { + return goog.math.Long.fromBits( + high >> (numBits - 32), + high >= 0 ? 0 : -1); + } + } +}; + + +/** + * Returns this Long with bits shifted to the right by the given amount, with + * the new top bits matching the current sign bit. + * @param {number} numBits The number of bits by which to shift. + * @return {!goog.math.Long} This shifted to the right by the given amount, with + * zeros placed into the new leading bits. + */ +goog.math.Long.prototype.shiftRightUnsigned = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return goog.math.Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >>> numBits); + } else if (numBits == 32) { + return goog.math.Long.fromBits(high, 0); + } else { + return goog.math.Long.fromBits(high >>> (numBits - 32), 0); + } + } +}; + +//======= begin jsbn ======= + +var navigator = { appName: 'Modern Browser' }; // polyfill a little + +// Copyright (c) 2005 Tom Wu +// All Rights Reserved. +// http://www-cs-students.stanford.edu/~tjw/jsbn/ + +/* + * Copyright (c) 2003-2005 Tom Wu + * All Rights Reserved. + * + * 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 above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF + * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * In addition, the following condition applies: + * + * All redistributions must retain an intact copy of this copyright notice + * and disclaimer. + */ + +// Basic JavaScript BN library - subset useful for RSA encryption. + +// Bits per digit +var dbits; + +// JavaScript engine analysis +var canary = 0xdeadbeefcafe; +var j_lm = ((canary&0xffffff)==0xefcafe); + +// (public) Constructor +function BigInteger(a,b,c) { + if(a != null) + if("number" == typeof a) this.fromNumber(a,b,c); + else if(b == null && "string" != typeof a) this.fromString(a,256); + else this.fromString(a,b); +} + +// return new, unset BigInteger +function nbi() { return new BigInteger(null); } + +// am: Compute w_j += (x*this_i), propagate carries, +// c is initial carry, returns final carry. +// c < 3*dvalue, x < 2*dvalue, this_i < dvalue +// We need to select the fastest one that works in this environment. + +// am1: use a single mult and divide to get the high bits, +// max digit bits should be 26 because +// max internal value = 2*dvalue^2-2*dvalue (< 2^53) +function am1(i,x,w,j,c,n) { + while(--n >= 0) { + var v = x*this[i++]+w[j]+c; + c = Math.floor(v/0x4000000); + w[j++] = v&0x3ffffff; + } + return c; +} +// am2 avoids a big mult-and-extract completely. +// Max digit bits should be <= 30 because we do bitwise ops +// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) +function am2(i,x,w,j,c,n) { + var xl = x&0x7fff, xh = x>>15; + while(--n >= 0) { + var l = this[i]&0x7fff; + var h = this[i++]>>15; + var m = xh*l+h*xl; + l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff); + c = (l>>>30)+(m>>>15)+xh*h+(c>>>30); + w[j++] = l&0x3fffffff; + } + return c; +} +// Alternately, set max digit bits to 28 since some +// browsers slow down when dealing with 32-bit numbers. +function am3(i,x,w,j,c,n) { + var xl = x&0x3fff, xh = x>>14; + while(--n >= 0) { + var l = this[i]&0x3fff; + var h = this[i++]>>14; + var m = xh*l+h*xl; + l = xl*l+((m&0x3fff)<<14)+w[j]+c; + c = (l>>28)+(m>>14)+xh*h; + w[j++] = l&0xfffffff; + } + return c; +} +if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) { + BigInteger.prototype.am = am2; + dbits = 30; +} +else if(j_lm && (navigator.appName != "Netscape")) { + BigInteger.prototype.am = am1; + dbits = 26; +} +else { // Mozilla/Netscape seems to prefer am3 + BigInteger.prototype.am = am3; + dbits = 28; +} + +BigInteger.prototype.DB = dbits; +BigInteger.prototype.DM = ((1<<dbits)-1); +BigInteger.prototype.DV = (1<<dbits); + +var BI_FP = 52; +BigInteger.prototype.FV = Math.pow(2,BI_FP); +BigInteger.prototype.F1 = BI_FP-dbits; +BigInteger.prototype.F2 = 2*dbits-BI_FP; + +// Digit conversions +var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz"; +var BI_RC = new Array(); +var rr,vv; +rr = "0".charCodeAt(0); +for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv; +rr = "a".charCodeAt(0); +for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv; +rr = "A".charCodeAt(0); +for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv; + +function int2char(n) { return BI_RM.charAt(n); } +function intAt(s,i) { + var c = BI_RC[s.charCodeAt(i)]; + return (c==null)?-1:c; +} + +// (protected) copy this to r +function bnpCopyTo(r) { + for(var i = this.t-1; i >= 0; --i) r[i] = this[i]; + r.t = this.t; + r.s = this.s; +} + +// (protected) set from integer value x, -DV <= x < DV +function bnpFromInt(x) { + this.t = 1; + this.s = (x<0)?-1:0; + if(x > 0) this[0] = x; + else if(x < -1) this[0] = x+DV; + else this.t = 0; +} + +// return bigint initialized to value +function nbv(i) { var r = nbi(); r.fromInt(i); return r; } + +// (protected) set from string and radix +function bnpFromString(s,b) { + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 256) k = 8; // byte array + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else { this.fromRadix(s,b); return; } + this.t = 0; + this.s = 0; + var i = s.length, mi = false, sh = 0; + while(--i >= 0) { + var x = (k==8)?s[i]&0xff:intAt(s,i); + if(x < 0) { + if(s.charAt(i) == "-") mi = true; + continue; + } + mi = false; + if(sh == 0) + this[this.t++] = x; + else if(sh+k > this.DB) { + this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh; + this[this.t++] = (x>>(this.DB-sh)); + } + else + this[this.t-1] |= x<<sh; + sh += k; + if(sh >= this.DB) sh -= this.DB; + } + if(k == 8 && (s[0]&0x80) != 0) { + this.s = -1; + if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh; + } + this.clamp(); + if(mi) BigInteger.ZERO.subTo(this,this); +} + +// (protected) clamp off excess high words +function bnpClamp() { + var c = this.s&this.DM; + while(this.t > 0 && this[this.t-1] == c) --this.t; +} + +// (public) return string representation in given radix +function bnToString(b) { + if(this.s < 0) return "-"+this.negate().toString(b); + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else return this.toRadix(b); + var km = (1<<k)-1, d, m = false, r = "", i = this.t; + var p = this.DB-(i*this.DB)%k; + if(i-- > 0) { + if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); } + while(i >= 0) { + if(p < k) { + d = (this[i]&((1<<p)-1))<<(k-p); + d |= this[--i]>>(p+=this.DB-k); + } + else { + d = (this[i]>>(p-=k))&km; + if(p <= 0) { p += this.DB; --i; } + } + if(d > 0) m = true; + if(m) r += int2char(d); + } + } + return m?r:"0"; +} + +// (public) -this +function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; } + +// (public) |this| +function bnAbs() { return (this.s<0)?this.negate():this; } + +// (public) return + if this > a, - if this < a, 0 if equal +function bnCompareTo(a) { + var r = this.s-a.s; + if(r != 0) return r; + var i = this.t; + r = i-a.t; + if(r != 0) return r; + while(--i >= 0) if((r=this[i]-a[i]) != 0) return r; + return 0; +} + +// returns bit length of the integer x +function nbits(x) { + var r = 1, t; + if((t=x>>>16) != 0) { x = t; r += 16; } + if((t=x>>8) != 0) { x = t; r += 8; } + if((t=x>>4) != 0) { x = t; r += 4; } + if((t=x>>2) != 0) { x = t; r += 2; } + if((t=x>>1) != 0) { x = t; r += 1; } + return r; +} + +// (public) return the number of bits in "this" +function bnBitLength() { + if(this.t <= 0) return 0; + return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM)); +} + +// (protected) r = this << n*DB +function bnpDLShiftTo(n,r) { + var i; + for(i = this.t-1; i >= 0; --i) r[i+n] = this[i]; + for(i = n-1; i >= 0; --i) r[i] = 0; + r.t = this.t+n; + r.s = this.s; +} + +// (protected) r = this >> n*DB +function bnpDRShiftTo(n,r) { + for(var i = n; i < this.t; ++i) r[i-n] = this[i]; + r.t = Math.max(this.t-n,0); + r.s = this.s; +} + +// (protected) r = this << n +function bnpLShiftTo(n,r) { + var bs = n%this.DB; + var cbs = this.DB-bs; + var bm = (1<<cbs)-1; + var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i; + for(i = this.t-1; i >= 0; --i) { + r[i+ds+1] = (this[i]>>cbs)|c; + c = (this[i]&bm)<<bs; + } + for(i = ds-1; i >= 0; --i) r[i] = 0; + r[ds] = c; + r.t = this.t+ds+1; + r.s = this.s; + r.clamp(); +} + +// (protected) r = this >> n +function bnpRShiftTo(n,r) { + r.s = this.s; + var ds = Math.floor(n/this.DB); + if(ds >= this.t) { r.t = 0; return; } + var bs = n%this.DB; + var cbs = this.DB-bs; + var bm = (1<<bs)-1; + r[0] = this[ds]>>bs; + for(var i = ds+1; i < this.t; ++i) { + r[i-ds-1] |= (this[i]&bm)<<cbs; + r[i-ds] = this[i]>>bs; + } + if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs; + r.t = this.t-ds; + r.clamp(); +} + +// (protected) r = this - a +function bnpSubTo(a,r) { + var i = 0, c = 0, m = Math.min(a.t,this.t); + while(i < m) { + c += this[i]-a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + if(a.t < this.t) { + c -= a.s; + while(i < this.t) { + c += this[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while(i < a.t) { + c -= a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c -= a.s; + } + r.s = (c<0)?-1:0; + if(c < -1) r[i++] = this.DV+c; + else if(c > 0) r[i++] = c; + r.t = i; + r.clamp(); +} + +// (protected) r = this * a, r != this,a (HAC 14.12) +// "this" should be the larger one if appropriate. +function bnpMultiplyTo(a,r) { + var x = this.abs(), y = a.abs(); + var i = x.t; + r.t = i+y.t; + while(--i >= 0) r[i] = 0; + for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t); + r.s = 0; + r.clamp(); + if(this.s != a.s) BigInteger.ZERO.subTo(r,r); +} + +// (protected) r = this^2, r != this (HAC 14.16) +function bnpSquareTo(r) { + var x = this.abs(); + var i = r.t = 2*x.t; + while(--i >= 0) r[i] = 0; + for(i = 0; i < x.t-1; ++i) { + var c = x.am(i,x[i],r,2*i,0,1); + if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) { + r[i+x.t] -= x.DV; + r[i+x.t+1] = 1; + } + } + if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1); + r.s = 0; + r.clamp(); +} + +// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) +// r != q, this != m. q or r may be null. +function bnpDivRemTo(m,q,r) { + var pm = m.abs(); + if(pm.t <= 0) return; + var pt = this.abs(); + if(pt.t < pm.t) { + if(q != null) q.fromInt(0); + if(r != null) this.copyTo(r); + return; + } + if(r == null) r = nbi(); + var y = nbi(), ts = this.s, ms = m.s; + var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus + if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } + else { pm.copyTo(y); pt.copyTo(r); } + var ys = y.t; + var y0 = y[ys-1]; + if(y0 == 0) return; + var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0); + var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2; + var i = r.t, j = i-ys, t = (q==null)?nbi():q; + y.dlShiftTo(j,t); + if(r.compareTo(t) >= 0) { + r[r.t++] = 1; + r.subTo(t,r); + } + BigInteger.ONE.dlShiftTo(ys,t); + t.subTo(y,y); // "negative" y so we can replace sub with am later + while(y.t < ys) y[y.t++] = 0; + while(--j >= 0) { + // Estimate quotient digit + var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2); + if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out + y.dlShiftTo(j,t); + r.subTo(t,r); + while(r[i] < --qd) r.subTo(t,r); + } + } + if(q != null) { + r.drShiftTo(ys,q); + if(ts != ms) BigInteger.ZERO.subTo(q,q); + } + r.t = ys; + r.clamp(); + if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder + if(ts < 0) BigInteger.ZERO.subTo(r,r); +} + +// (public) this mod a +function bnMod(a) { + var r = nbi(); + this.abs().divRemTo(a,null,r); + if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r); + return r; +} + +// Modular reduction using "classic" algorithm +function Classic(m) { this.m = m; } +function cConvert(x) { + if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); + else return x; +} +function cRevert(x) { return x; } +function cReduce(x) { x.divRemTo(this.m,null,x); } +function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } +function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + +Classic.prototype.convert = cConvert; +Classic.prototype.revert = cRevert; +Classic.prototype.reduce = cReduce; +Classic.prototype.mulTo = cMulTo; +Classic.prototype.sqrTo = cSqrTo; + +// (protected) return "-1/this % 2^DB"; useful for Mont. reduction +// justification: +// xy == 1 (mod m) +// xy = 1+km +// xy(2-xy) = (1+km)(1-km) +// x[y(2-xy)] = 1-k^2m^2 +// x[y(2-xy)] == 1 (mod m^2) +// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 +// should reduce x and y(2-xy) by m^2 at each step to keep size bounded. +// JS multiply "overflows" differently from C/C++, so care is needed here. +function bnpInvDigit() { + if(this.t < 1) return 0; + var x = this[0]; + if((x&1) == 0) return 0; + var y = x&3; // y == 1/x mod 2^2 + y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 + y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 + y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 + // last step - calculate inverse mod DV directly; + // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints + y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits + // we really want the negative inverse, and -DV < y < DV + return (y>0)?this.DV-y:-y; +} + +// Montgomery reduction +function Montgomery(m) { + this.m = m; + this.mp = m.invDigit(); + this.mpl = this.mp&0x7fff; + this.mph = this.mp>>15; + this.um = (1<<(m.DB-15))-1; + this.mt2 = 2*m.t; +} + +// xR mod m +function montConvert(x) { + var r = nbi(); + x.abs().dlShiftTo(this.m.t,r); + r.divRemTo(this.m,null,r); + if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r); + return r; +} + +// x/R mod m +function montRevert(x) { + var r = nbi(); + x.copyTo(r); + this.reduce(r); + return r; +} + +// x = x/R mod m (HAC 14.32) +function montReduce(x) { + while(x.t <= this.mt2) // pad x so am has enough room later + x[x.t++] = 0; + for(var i = 0; i < this.m.t; ++i) { + // faster way of calculating u0 = x[i]*mp mod DV + var j = x[i]&0x7fff; + var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM; + // use am to combine the multiply-shift-add into one call + j = i+this.m.t; + x[j] += this.m.am(0,u0,x,i,0,this.m.t); + // propagate carry + while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; } + } + x.clamp(); + x.drShiftTo(this.m.t,x); + if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); +} + +// r = "x^2/R mod m"; x != r +function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + +// r = "xy/R mod m"; x,y != r +function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + +Montgomery.prototype.convert = montConvert; +Montgomery.prototype.revert = montRevert; +Montgomery.prototype.reduce = montReduce; +Montgomery.prototype.mulTo = montMulTo; +Montgomery.prototype.sqrTo = montSqrTo; + +// (protected) true iff this is even +function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; } + +// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) +function bnpExp(e,z) { + if(e > 0xffffffff || e < 1) return BigInteger.ONE; + var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; + g.copyTo(r); + while(--i >= 0) { + z.sqrTo(r,r2); + if((e&(1<<i)) > 0) z.mulTo(r2,g,r); + else { var t = r; r = r2; r2 = t; } + } + return z.revert(r); +} + +// (public) this^e % m, 0 <= e < 2^32 +function bnModPowInt(e,m) { + var z; + if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); + return this.exp(e,z); +} + +// protected +BigInteger.prototype.copyTo = bnpCopyTo; +BigInteger.prototype.fromInt = bnpFromInt; +BigInteger.prototype.fromString = bnpFromString; +BigInteger.prototype.clamp = bnpClamp; +BigInteger.prototype.dlShiftTo = bnpDLShiftTo; +BigInteger.prototype.drShiftTo = bnpDRShiftTo; +BigInteger.prototype.lShiftTo = bnpLShiftTo; +BigInteger.prototype.rShiftTo = bnpRShiftTo; +BigInteger.prototype.subTo = bnpSubTo; +BigInteger.prototype.multiplyTo = bnpMultiplyTo; +BigInteger.prototype.squareTo = bnpSquareTo; +BigInteger.prototype.divRemTo = bnpDivRemTo; +BigInteger.prototype.invDigit = bnpInvDigit; +BigInteger.prototype.isEven = bnpIsEven; +BigInteger.prototype.exp = bnpExp; + +// public +BigInteger.prototype.toString = bnToString; +BigInteger.prototype.negate = bnNegate; +BigInteger.prototype.abs = bnAbs; +BigInteger.prototype.compareTo = bnCompareTo; +BigInteger.prototype.bitLength = bnBitLength; +BigInteger.prototype.mod = bnMod; +BigInteger.prototype.modPowInt = bnModPowInt; + +// "constants" +BigInteger.ZERO = nbv(0); +BigInteger.ONE = nbv(1); + +// jsbn2 stuff + +// (protected) convert from radix string +function bnpFromRadix(s,b) { + this.fromInt(0); + if(b == null) b = 10; + var cs = this.chunkSize(b); + var d = Math.pow(b,cs), mi = false, j = 0, w = 0; + for(var i = 0; i < s.length; ++i) { + var x = intAt(s,i); + if(x < 0) { + if(s.charAt(i) == "-" && this.signum() == 0) mi = true; + continue; + } + w = b*w+x; + if(++j >= cs) { + this.dMultiply(d); + this.dAddOffset(w,0); + j = 0; + w = 0; + } + } + if(j > 0) { + this.dMultiply(Math.pow(b,j)); + this.dAddOffset(w,0); + } + if(mi) BigInteger.ZERO.subTo(this,this); +} + +// (protected) return x s.t. r^x < DV +function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); } + +// (public) 0 if this == 0, 1 if this > 0 +function bnSigNum() { + if(this.s < 0) return -1; + else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0; + else return 1; +} + +// (protected) this *= n, this >= 0, 1 < n < DV +function bnpDMultiply(n) { + this[this.t] = this.am(0,n-1,this,0,0,this.t); + ++this.t; + this.clamp(); +} + +// (protected) this += n << w words, this >= 0 +function bnpDAddOffset(n,w) { + if(n == 0) return; + while(this.t <= w) this[this.t++] = 0; + this[w] += n; + while(this[w] >= this.DV) { + this[w] -= this.DV; + if(++w >= this.t) this[this.t++] = 0; + ++this[w]; + } +} + +// (protected) convert to radix string +function bnpToRadix(b) { + if(b == null) b = 10; + if(this.signum() == 0 || b < 2 || b > 36) return "0"; + var cs = this.chunkSize(b); + var a = Math.pow(b,cs); + var d = nbv(a), y = nbi(), z = nbi(), r = ""; + this.divRemTo(d,y,z); + while(y.signum() > 0) { + r = (a+z.intValue()).toString(b).substr(1) + r; + y.divRemTo(d,y,z); + } + return z.intValue().toString(b) + r; +} + +// (public) return value as integer +function bnIntValue() { + if(this.s < 0) { + if(this.t == 1) return this[0]-this.DV; + else if(this.t == 0) return -1; + } + else if(this.t == 1) return this[0]; + else if(this.t == 0) return 0; + // assumes 16 < DB < 32 + return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0]; +} + +// (protected) r = this + a +function bnpAddTo(a,r) { + var i = 0, c = 0, m = Math.min(a.t,this.t); + while(i < m) { + c += this[i]+a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + if(a.t < this.t) { + c += a.s; + while(i < this.t) { + c += this[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while(i < a.t) { + c += a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += a.s; + } + r.s = (c<0)?-1:0; + if(c > 0) r[i++] = c; + else if(c < -1) r[i++] = this.DV+c; + r.t = i; + r.clamp(); +} + +BigInteger.prototype.fromRadix = bnpFromRadix; +BigInteger.prototype.chunkSize = bnpChunkSize; +BigInteger.prototype.signum = bnSigNum; +BigInteger.prototype.dMultiply = bnpDMultiply; +BigInteger.prototype.dAddOffset = bnpDAddOffset; +BigInteger.prototype.toRadix = bnpToRadix; +BigInteger.prototype.intValue = bnIntValue; +BigInteger.prototype.addTo = bnpAddTo; + +//======= end jsbn ======= + +// Emscripten wrapper +var Wrapper = { + result: [0, 0], // return result stored here + add: function(xl, xh, yl, yh) { + var x = new goog.math.Long(xl, xh); + var y = new goog.math.Long(yl, yh); + var ret = x.add(y); + Wrapper.result[0] = ret.low_; + Wrapper.result[1] = ret.high_; + }, + subtract: function(xl, xh, yl, yh) { + var x = new goog.math.Long(xl, xh); + var y = new goog.math.Long(yl, yh); + var ret = x.subtract(y); + Wrapper.result[0] = ret.low_; + Wrapper.result[1] = ret.high_; + }, + multiply: function(xl, xh, yl, yh) { + var x = new goog.math.Long(xl, xh); + var y = new goog.math.Long(yl, yh); + var ret = x.multiply(y); + Wrapper.result[0] = ret.low_; + Wrapper.result[1] = ret.high_; + }, + makeTwo32: function() { + Wrapper.two32 = new BigInteger(); + Wrapper.two32.fromString('4294967296', 10); + }, + lh2bignum: function(l, h) { + var a = new BigInteger(); + a.fromString(h.toString(), 10); + var b = new BigInteger(); + a.multiplyTo(Wrapper.two32, b); + var c = new BigInteger(); + c.fromString(l.toString(), 10); + var d = new BigInteger(); + c.addTo(b, d); + return d; + }, + divide: function(xl, xh, yl, yh, unsigned) { + if (!Wrapper.two32) Wrapper.makeTwo32(); + if (!unsigned) { + var x = new goog.math.Long(xl, xh); + var y = new goog.math.Long(yl, yh); + var ret = x.div(y); + Wrapper.result[0] = ret.low_; + Wrapper.result[1] = ret.high_; + } else { + // slow precise bignum division + var x = Wrapper.lh2bignum(xl >>> 0, xh >>> 0); + var y = Wrapper.lh2bignum(yl >>> 0, yh >>> 0); + var z = new BigInteger(); + x.divRemTo(y, z, null); + var l = new BigInteger(); + var h = new BigInteger(); + z.divRemTo(Wrapper.two32, h, l); + Wrapper.result[0] = parseInt(l.toString()) | 0; + Wrapper.result[1] = parseInt(h.toString()) | 0; + } + }, + modulo: function(xl, xh, yl, yh, unsigned) { + if (!Wrapper.two32) Wrapper.makeTwo32(); + if (!unsigned) { + var x = new goog.math.Long(xl, xh); + var y = new goog.math.Long(yl, yh); + var ret = x.modulo(y); + Wrapper.result[0] = ret.low_; + Wrapper.result[1] = ret.high_; + } else { + // slow precise bignum division + var x = Wrapper.lh2bignum(xl >>> 0, xh >>> 0); + var y = Wrapper.lh2bignum(yl >>> 0, yh >>> 0); + var z = new BigInteger(); + x.divRemTo(y, null, z); + var l = new BigInteger(); + var h = new BigInteger(); + z.divRemTo(Wrapper.two32, h, l); + Wrapper.result[0] = parseInt(l.toString()) | 0; + Wrapper.result[1] = parseInt(h.toString()) | 0; + } + }, + stringify: function(l, h, unsigned) { + var ret = new goog.math.Long(l, h).toString(); + if (unsigned && ret[0] == '-') { + // unsign slowly using jsbn bignums + if (!Wrapper.two64) { + Wrapper.two64 = new BigInteger(); + Wrapper.two64.fromString('18446744073709551616', 10); + } + var bignum = new BigInteger(); + bignum.fromString(ret, 10); + ret = new BigInteger(); + Wrapper.two64.addTo(bignum, ret); + ret = ret.toString(10); + } + return ret; + } +}; +return Wrapper; +})(); + +//======= end closure i64 code ======= + diff --git a/src/modules.js b/src/modules.js index fd22b9fe..a6aaa99a 100644 --- a/src/modules.js +++ b/src/modules.js @@ -259,8 +259,9 @@ var LibraryManager = { load: function() { assert(!this.library); - for (var suffix in set('', '_sdl', '_browser', '_gl')) { - eval(processMacros(preprocess(read('library' + suffix + '.js')))); + var libraries = ['library.js', 'library_browser.js', 'library_sdl.js', 'library_gl.js', 'library_glut.js', 'library_xlib.js', 'library_egl.js'].concat(additionalLibraries); + for (var i = 0; i < libraries.length; i++) { + eval(processMacros(preprocess(read(libraries[i])))); } }, diff --git a/src/parseTools.js b/src/parseTools.js index ff578c0a..92fb038a 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -123,7 +123,7 @@ function isPointerType(type) { function isStructType(type) { if (isPointerType(type)) return false; if (/^\[\d+\ x\ (.*)\]/.test(type)) return true; // [15 x ?] blocks. Like structs - if (/<?{ [^}]* }>?/.test(type)) return true; // { i32, i8 } etc. - anonymous struct types + if (/<?{ ?[^}]* ?}>?/.test(type)) return true; // { i32, i8 } etc. - anonymous struct types // See comment in isStructPointerType() return type[0] == '%'; } @@ -412,7 +412,7 @@ function cleanSegment(segment) { return segment; } -var MATHOPS = set(['add', 'sub', 'sdiv', 'udiv', 'mul', 'icmp', 'zext', 'urem', 'srem', 'fadd', 'fsub', 'fmul', 'fdiv', 'fcmp', 'uitofp', 'sitofp', 'fpext', 'fptrunc', 'fptoui', 'fptosi', 'trunc', 'sext', 'select', 'shl', 'shr', 'ashl', 'ashr', 'lshr', 'lshl', 'xor', 'or', 'and', 'ptrtoint', 'inttoptr']); +var MATHOPS = set(['add', 'sub', 'sdiv', 'udiv', 'mul', 'icmp', 'zext', 'urem', 'srem', 'fadd', 'fsub', 'fmul', 'fdiv', 'fcmp', 'frem', 'uitofp', 'sitofp', 'fpext', 'fptrunc', 'fptoui', 'fptosi', 'trunc', 'sext', 'select', 'shl', 'shr', 'ashl', 'ashr', 'lshr', 'lshl', 'xor', 'or', 'and', 'ptrtoint', 'inttoptr']); var PARSABLE_LLVM_FUNCTIONS = set('getelementptr', 'bitcast'); mergeInto(PARSABLE_LLVM_FUNCTIONS, MATHOPS); @@ -499,7 +499,7 @@ function IEEEUnHex(stringy) { while (stringy.length < 16) stringy = '0' + stringy; if (FAKE_X86_FP80 && stringy.length > 16) { stringy = stringy.substr(stringy.length-16, 16); - warnOnce('.ll contains floating-point values with more than 64 bits. Faking values for them. If they are used, this will almost certainly fail!'); + warnOnce('.ll contains floating-point values with more than 64 bits. Faking values for them. If they are used, this will almost certainly break horribly!'); } assert(stringy.length === 16, 'Can only unhex 16-digit double numbers, nothing platform-specific'); // |long double| can cause x86_fp80 which causes this var top = eval('0x' + stringy[0]); @@ -559,12 +559,12 @@ function splitI64(value) { return makeInlineCalculation(makeI64('VALUE>>>0', 'Math.min(Math.floor(VALUE/4294967296), 4294967295)'), value, 'tempBigIntP'); } } -function mergeI64(value) { +function mergeI64(value, unsigned) { assert(USE_TYPED_ARRAYS == 2); if (legalizedI64s) { - return RuntimeGenerator.makeBigInt(value + '$0', value + '$1'); + return RuntimeGenerator.makeBigInt(value + '$0', value + '$1', unsigned); } else { - return makeInlineCalculation(RuntimeGenerator.makeBigInt('VALUE[0]', 'VALUE[1]'), value, 'tempI64'); + return makeInlineCalculation(RuntimeGenerator.makeBigInt('VALUE[0]', 'VALUE[1]', unsigned), value, 'tempI64'); } } @@ -683,16 +683,14 @@ function parseArbitraryInt(str, bits) { return ret; } -function parseI64Constant(str) { - assert(USE_TYPED_ARRAYS == 2); - +function parseI64Constant(str, legalized) { if (!isNumber(str)) { // This is a variable. Copy it, so we do not modify the original return legalizedI64s ? str : makeCopyI64(str); } var parsed = parseArbitraryInt(str, 64); - if (legalizedI64s) return parsed; + if (legalizedI64s || legalized) return parsed; return '[' + parsed[0] + ',' + parsed[1] + ']'; } @@ -988,7 +986,7 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe, value = range(typeData.fields.length).map(function(i) { return value + '.f' + i }); } for (var i = 0; i < typeData.fields.length; i++) { - ret.push(makeSetValue(ptr, pos + typeData.flatIndexes[i], value[i], typeData.fields[i], noNeedFirst)); + ret.push(makeSetValue(ptr, getFastValue(pos, '+', typeData.flatIndexes[i]), value[i], typeData.fields[i], noNeedFirst)); } return ret.join('; '); } @@ -1145,6 +1143,13 @@ function makeCopyValues(dest, src, num, type, modifier, align, sep) { } } +function makeHEAPView(which, start, end) { + // Assumes USE_TYPED_ARRAYS == 2 + var size = parseInt(which.replace('U', '').replace('F', ''))/8; + var mod = size == 1 ? '' : ('>>' + log2(size)); + return 'HEAP' + which + '.subarray(' + start + mod + ',' + end + mod + ')'; +} + var PLUS_MUL = set('+', '*'); var MUL_DIV = set('*', '/'); var PLUS_MINUS = set('+', '-'); @@ -1288,17 +1293,11 @@ function makeGetSlabs(ptr, type, allowMultiple, unsigned) { } } else { // USE_TYPED_ARRAYS == 2) if (isPointerType(type)) type = 'i32'; // Hardcoded 32-bit - var warn64 = function() { - warnOnce('.ll contains i64 or double values. These 64-bit values are dangerous in USE_TYPED_ARRAYS == 2. ' + - 'We store i64 as i32, and double as float. This can cause serious problems!'); - }; switch(type) { case 'i1': case 'i8': return [unsigned ? 'HEAPU8' : 'HEAP8']; break; case 'i16': return [unsigned ? 'HEAPU16' : 'HEAP16']; break; - case 'i64': warn64(); - case 'i32': return [unsigned ? 'HEAPU32' : 'HEAP32']; break; - case 'float': return ['HEAPF32']; break; - case 'double': warn64(); return ['HEAPF32']; break; + case 'i32': case 'i64': return [unsigned ? 'HEAPU32' : 'HEAP32']; break; + case 'float': case 'double': return ['HEAPF32']; break; default: { throw 'what, exactly, can we do for unknown types in TA2?! ' + new Error().stack; } @@ -1317,8 +1316,7 @@ function finalizeLLVMFunctionCall(item, noIndexizeFunctions) { var newType = item.type; if (isPossiblyFunctionType(oldType) && isPossiblyFunctionType(newType) && countNormalArgs(oldType) != countNormalArgs(newType)) { - warn('Casting a function pointer type to another with a different number of arguments. See more info in the source (grep for this text). ' + - oldType + ' ==> ' + newType); + warnOnce('Casting a function pointer type to another with a different number of arguments. See more info in the source'); // This may be dangerous as clang generates different code for C and C++ calling conventions. The only problem // case appears to be passing a structure by value, C will have (field1, field2) as function args, and the // function will internally create a structure with that data, while C++ will have (struct* byVal) and it @@ -1412,7 +1410,7 @@ function handleOverflow(text, bits) { // TODO: handle overflows of i64s if (!bits) return text; var correct = correctOverflows(); - warn(!correct || bits <= 32, 'Cannot correct overflows of this many bits: ' + bits + ' at line ' + Framework.currItem.lineNum); + warnOnce(!correct || bits <= 32, 'Cannot correct overflows of this many bits: ' + bits); if (CHECK_OVERFLOWS) return 'CHECK_OVERFLOW(' + text + ', ' + bits + ', ' + Math.floor(correctSpecificOverflow() && !PGO) + ( PGO ? ', "' + Debugging.getIdentifier() + '"' : '' ) + ')'; @@ -1537,7 +1535,8 @@ function makeRounding(value, bits, signed, floatConversion) { // TODO: handle roundings of i64s assert(bits); // C rounds to 0 (-5.5 to -5, +5.5 to 5), while JS has no direct way to do that. - if (bits <= 32 && signed) return '((' + value + ')|0)'; // This is fast and even correct, for all cases + if (bits <= 32 && signed) return '((' + value + ')&-1)'; // This is fast and even correct, for all cases. Note that it is the same + // as |0, but &-1 hints to the js optimizer that this is a rounding correction // Do Math.floor, which is reasonably fast, if we either don't care, or if we can be sure // the value is non-negative if (!correctRoundings() || (!signed && !floatConversion)) return 'Math.floor(' + value + ')'; @@ -1561,6 +1560,8 @@ function isSignedOp(op, variant) { } var legalizedI64s = USE_TYPED_ARRAYS == 2; // We do not legalize globals, but do legalize function lines. This will be true in the latter case +var preciseI64MathUsed = false; // Set to true if we actually use precise i64 math: If PRECISE_I64_MATH is set, and also such math is actually + // needed (+,-,*,/,% - we do not need it for bitops) function processMathop(item) { var op = item.op; @@ -1617,6 +1618,11 @@ function processMathop(item) { return result; } } + function i64PreciseOp(type, lastArg) { + preciseI64MathUsed = true; + return finish(['(i64Math.' + type + '(' + low1 + ',' + high1 + ',' + low2 + ',' + high2 + + (lastArg ? ',' + lastArg : '') + '),i64Math.result[0])', 'i64Math.result[1]']); + } switch (op) { // basic integer ops case 'or': { @@ -1672,22 +1678,22 @@ function processMathop(item) { case 'fptoui': case 'fptosi': return finish(splitI64(idents[0])); case 'icmp': { switch (variant) { - case 'uge': return high1 + ' >= ' + high2 + ' && (' + high1 + ' > ' + high2 + ' || ' + - low1 + ' >= ' + low2 + ')'; + case 'uge': return '(' + high1 + '>>>0) >= (' + high2 + '>>>0) && ((' + high1 + '>>>0) > (' + high2 + '>>>0) || ' + + '(' + low1 + '>>>0) >= (' + low2 + '>>>0))'; case 'sge': return '(' + high1 + '|0) >= (' + high2 + '|0) && ((' + high1 + '|0) > (' + high2 + '|0) || ' + - '(' + low1 + '|0) >= (' + low2 + '|0))'; - case 'ule': return high1 + ' <= ' + high2 + ' && (' + high1 + ' < ' + high2 + ' || ' + - low1 + ' <= ' + low2 + ')'; + '(' + low1 + '>>>0) >= (' + low2 + '>>>0))'; + case 'ule': return '(' + high1 + '>>>0) <= (' + high2 + '>>>0) && ((' + high1 + '>>>0) < (' + high2 + '>>>0) || ' + + '(' + low1 + '>>>0) <= (' + low2 + '>>>0))'; case 'sle': return '(' + high1 + '|0) <= (' + high2 + '|0) && ((' + high1 + '|0) < (' + high2 + '|0) || ' + - '(' + low1 + '|0) <= (' + low2 + '|0))'; - case 'ugt': return high1 + ' > ' + high2 + ' || (' + high1 + ' == ' + high2 + ' && ' + - low1 + ' > ' + low2 + ')'; + '(' + low1 + '>>>0) <= (' + low2 + '>>>0))'; + case 'ugt': return '(' + high1 + '>>>0) > (' + high2 + '>>>0) || ((' + high1 + '>>>0) == (' + high2 + '>>>0) && ' + + '(' + low1 + '>>>0) > (' + low2 + '>>>0))'; case 'sgt': return '(' + high1 + '|0) > (' + high2 + '|0) || ((' + high1 + '|0) == (' + high2 + '|0) && ' + - '(' + low1 + '|0) > (' + low2 + '|0))'; - case 'ult': return high1 + ' < ' + high2 + ' || (' + high1 + ' == ' + high2 + ' && ' + - low1 + ' < ' + low2 + ')'; + '(' + low1 + '>>>0) > (' + low2 + '>>>0))'; + case 'ult': return '(' + high1 + '>>>0) < (' + high2 + '>>>0) || ((' + high1 + '>>>0) == (' + high2 + '>>>0) && ' + + '(' + low1 + '>>>0) < (' + low2 + '>>>0))'; case 'slt': return '(' + high1 + '|0) < (' + high2 + '|0) || ((' + high1 + '|0) == (' + high2 + '|0) && ' + - '(' + low1 + '|0) < (' + low2 + '|0))'; + '(' + low1 + '>>>0) < (' + low2 + '>>>0))'; case 'ne': return low1 + ' != ' + low2 + ' || ' + high1 + ' != ' + high2 + ''; case 'eq': return low1 + ' == ' + low2 + ' && ' + high1 + ' == ' + high2 + ''; default: throw 'Unknown icmp variant: ' + variant; @@ -1702,11 +1708,46 @@ function processMathop(item) { case 'ptrtoint': return makeI64(idents[0], 0); case 'inttoptr': return '(' + idents[0] + '[0])'; // just directly truncate the i64 to a 'pointer', which is an i32 // Dangerous, rounded operations. TODO: Fully emulate - case 'add': warnI64_1(); return finish(splitI64(mergeI64(idents[0]) + '+' + mergeI64(idents[1]))); - case 'sub': warnI64_1(); return finish(splitI64(mergeI64(idents[0]) + '-' + mergeI64(idents[1]))); - case 'sdiv': case 'udiv': warnI64_1(); return finish(splitI64(makeRounding(mergeI64(idents[0]) + '/' + mergeI64(idents[1]), bits, op[0] === 's'))); - case 'mul': warnI64_1(); return finish(splitI64(mergeI64(idents[0]) + '*' + mergeI64(idents[1]))); - case 'urem': case 'srem': warnI64_1(); return finish(splitI64(mergeI64(idents[0]) + '%' + mergeI64(idents[1]))); + case 'add': { + if (PRECISE_I64_MATH) { + return i64PreciseOp('add'); + } else { + warnI64_1(); + return finish(splitI64(mergeI64(idents[0]) + '+' + mergeI64(idents[1]))); + } + } + case 'sub': { + if (PRECISE_I64_MATH) { + return i64PreciseOp('subtract'); + } else { + warnI64_1(); + return finish(splitI64(mergeI64(idents[0]) + '-' + mergeI64(idents[1]))); + } + } + case 'sdiv': case 'udiv': { + if (PRECISE_I64_MATH) { + return i64PreciseOp('divide', op[0] === 'u'); + } else { + warnI64_1(); + return finish(splitI64(makeRounding(mergeI64(idents[0], op[0] === 'u') + '/' + mergeI64(idents[1], op[0] === 'u'), bits, op[0] === 's'))); + } + } + case 'mul': { + if (PRECISE_I64_MATH) { + return i64PreciseOp('multiply'); + } else { + warnI64_1(); + return finish(splitI64(mergeI64(idents[0], op[0] === 'u') + '*' + mergeI64(idents[1], op[0] === 'u'))); + } + } + case 'urem': case 'srem': { + if (PRECISE_I64_MATH) { + return i64PreciseOp('modulo', op[0] === 'u'); + } else { + warnI64_1(); + return finish(splitI64(mergeI64(idents[0], op[0] === 'u') + '%' + mergeI64(idents[1], op[0] === 'u'))); + } + } case 'bitcast': { // Pointers are not 64-bit, so there is really only one possible type of bitcast here, int to float or vice versa assert(USE_TYPED_ARRAYS == 2, 'Can only bitcast ints <-> floats with typed arrays mode 2'); @@ -1782,6 +1823,7 @@ function processMathop(item) { case 'fsub': return getFastValue(idents[0], '-', idents[1], item.type); case 'fdiv': return getFastValue(idents[0], '/', idents[1], item.type); case 'fmul': return getFastValue(idents[0], '*', idents[1], item.type); + case 'frem': return getFastValue(idents[0], '%', idents[1], item.type); case 'uitofp': case 'sitofp': return idents[0]; case 'fptoui': case 'fptosi': return makeRounding(idents[0], bitsLeft, op === 'fptosi', true); diff --git a/src/postamble.js b/src/postamble.js index 390f9f27..cf863669 100644 --- a/src/postamble.js +++ b/src/postamble.js @@ -32,38 +32,49 @@ Module.callMain = function callMain(args) { function run(args) { args = args || Module['arguments']; - initRuntime(); + if (Module['setStatus']) { + Module['setStatus'](''); // clear the status from "Downloading.." etc. + } + + if (Module['preRun']) { + Module['preRun'](); + } var ret = null; if (Module['_main']) { + preMain(); ret = Module.callMain(args); - exitRuntime(); + if (!Module['noExitRuntime']) { + exitRuntime(); + } + } + + if (Module['postRun']) { + Module['postRun'](); } + return ret; } Module['run'] = run; // {{PRE_RUN_ADDITIONS}} -if (Module['preRun']) { - Module['preRun'](); -} +initRuntime(); #if INVOKE_RUN #else -Module['noInitialRun'] = true; +addRunDependency(); #endif +if (Module['noInitialRun']) { + addRunDependency(); +} -if (!Module['noInitialRun']) { +if (runDependencies == 0) { var ret = run(); #if CATCH_EXIT_CODE - print('Exit Status: ' + ret); + Module.print('Exit Status: ' + ret); #endif } // {{POST_RUN_ADDITIONS}} -if (Module['postRun']) { - Module['postRun'](); -} - diff --git a/src/preamble.js b/src/preamble.js index 98d12a43..986592ee 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -14,7 +14,7 @@ var HEAP_WATCHED = []; var HEAP_HISTORY = []; function SAFE_HEAP_CLEAR(dest) { #if SAFE_HEAP_LOG - print('SAFE_HEAP clear: ' + dest); + Module.print('SAFE_HEAP clear: ' + dest); #endif HEAP_HISTORY[dest] = []; } @@ -22,7 +22,7 @@ var SAFE_HEAP_ERRORS = 0; var ACCEPTABLE_SAFE_HEAP_ERRORS = 0; function SAFE_HEAP_ACCESS(dest, type, store, ignore) { - //if (dest === A_NUMBER) print ([dest, type, store] + ' ' + new Error().stack); // Something like this may be useful, in debugging + //if (dest === A_NUMBER) Module.print ([dest, type, store] + ' ' + new Error().stack); // Something like this may be useful, in debugging #if USE_TYPED_ARRAYS // When using typed arrays, reads over the top of TOTAL_MEMORY will fail silently, so we must @@ -59,12 +59,12 @@ function SAFE_HEAP_ACCESS(dest, type, store, ignore) { // assert((history && history[0]) /* || HEAP[dest] === 0 */, "Loading from where there was no store! " + dest + ',' + HEAP[dest] + ',' + type + ', \n\n' + new Error().stack + '\n'); // if (history[0].type !== type) { if (history !== type && !ignore) { - print('Load-store consistency assumption failure! ' + dest); - print('\n'); - print(JSON.stringify(history)); - print('\n'); - print('LOAD: ' + type + ', ' + new Error().stack); - print('\n'); + Module.print('Load-store consistency assumption failure! ' + dest); + Module.print('\n'); + Module.print(JSON.stringify(history)); + Module.print('\n'); + Module.print('LOAD: ' + type + ', ' + new Error().stack); + Module.print('\n'); SAFE_HEAP_ERRORS++; assert(SAFE_HEAP_ERRORS <= ACCEPTABLE_SAFE_HEAP_ERRORS, 'Load-store consistency assumption failure!'); } @@ -73,15 +73,15 @@ function SAFE_HEAP_ACCESS(dest, type, store, ignore) { function SAFE_HEAP_STORE(dest, value, type, ignore) { #if SAFE_HEAP_LOG - print('SAFE_HEAP store: ' + [dest, type, value, ignore]); + Module.print('SAFE_HEAP store: ' + [dest, type, value, ignore]); #endif - if (!ignore && !value && value !== 0 && value !== false && !isNaN(value)) { // false can be the result of a mathop comparator; NaN can be the result of a math function + if (!ignore && !value && (value === null || value === undefined)) { throw('Warning: Writing an invalid value of ' + JSON.stringify(value) + ' at ' + dest + ' :: ' + new Error().stack + '\n'); } SAFE_HEAP_ACCESS(dest, type, true, ignore); if (dest in HEAP_WATCHED) { - print((new Error()).stack); + Module.print((new Error()).stack); throw "Bad store!" + dest; } @@ -104,10 +104,10 @@ function SAFE_HEAP_STORE(dest, value, type, ignore) { } function SAFE_HEAP_LOAD(dest, type, unsigned, ignore) { - SAFE_HEAP_ACCESS(dest, type, ignore); + SAFE_HEAP_ACCESS(dest, type, false, ignore); #if SAFE_HEAP_LOG - print('SAFE_HEAP load: ' + [dest, type, getValue(dest, type, 1), ignore]); + Module.print('SAFE_HEAP load: ' + [dest, type, getValue(dest, type, 1), ignore]); #endif #if USE_TYPED_ARRAYS == 2 @@ -132,7 +132,7 @@ function SAFE_HEAP_LOAD(dest, type, unsigned, ignore) { function SAFE_HEAP_COPY_HISTORY(dest, src) { #if SAFE_HEAP_LOG - print('SAFE_HEAP copy: ' + [dest, src]); + Module.print('SAFE_HEAP copy: ' + [dest, src]); #endif HEAP_HISTORY[dest] = HEAP_HISTORY[src]; SAFE_HEAP_ACCESS(dest, HEAP_HISTORY[dest] || null, true, false); @@ -160,7 +160,7 @@ var CorrectionsMonitor = { sig = (new Error().stack).toString().split('\n')[2].split(':').slice(-1)[0]; // Spidermonkey-specific FIXME sig = type + '|' + sig; if (!this.sigs[sig]) { - //print('Correction: ' + sig); + //Module.print('Correction: ' + sig); this.sigs[sig] = [0, 0]; // fail, succeed } this.sigs[sig][succeed ? 1 : 0]++; @@ -181,7 +181,7 @@ var CorrectionsMonitor = { items.sort(function(x, y) { return y.total - x.total; }); for (var i = 0; i < items.length; i++) { var item = items[i]; - print(item.sig + ' : ' + item.total + ' hits, %' + (Math.ceil(100*item.fails/item.total)) + ' failures'); + Module.print(item.sig + ' : ' + item.total + ' hits, %' + (Math.ceil(100*item.fails/item.total)) + ' failures'); } #endif } @@ -253,7 +253,7 @@ Module['stopProfiling'] = stopProfiling; function printProfiling() { function dumpData(name_, node, indent) { - print(indent + ('________' + node.time).substr(-8) + ': ' + name_ + ' (' + node.calls + ')'); + Module.print(indent + ('________' + node.time).substr(-8) + ': ' + name_ + ' (' + node.calls + ')'); var children = []; for (var child in node.children) { children.push(node.children[child]); @@ -265,57 +265,6 @@ function printProfiling() { dumpData('root', PROFILING_ROOT, ' '); } Module['printProfiling'] = printProfiling; - -function printXULProfiling() { - function dumpData(name_, node, indent) { - var children = []; - for (var child in node.children) { - children.push(node.children[child]); - children[children.length-1].name_ = child; - } - print('<treeitem' + (children.length > 0 ? ' container="true"' : '') + '>'); - print(' <treerow>'); - print(' <treecell label="' + name_ + '"/>'); - print(' <treecell label="' + node.time + '"/>'); - print(' <treecell label="' + node.calls + '"/>'); - print(' </treerow>'); - - if (children.length > 0) { - print(' <treechildren>'); - children.sort(function(x, y) { return y.time - x.time }); - children.forEach(function(child) { dumpData(child.name_, child, indent + ' ') }); - print(' </treechildren>'); - } - - print('</treeitem>'); - } - - print('<?xml version="1.0"?>'); - print('<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> '); - print('<?xml-stylesheet href="file://C:/main.css" type="text/css"?> '); - print('<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> '); - print('<tree id="myTree" flex="1" hidecolumnpicker="false" seltype="single" class="tree"'); - print(' rows="5">'); - print(' <treecols id="myTree2-treeCols">'); - print(' <treecol id="myTree2-treeCol0" primary="true" flex="2" label="Name"'); - print(' persist="width" ordinal="1"/>'); - print(' <splitter class="tree-splitter" ordinal="2"/>'); - print(' <treecol id="myTree2-treeCol1" flex="1" label="Milliseconds"'); - print(' persist="width" ordinal="3"/>'); - print(' <treecol id="myTree2-treeCol2" flex="1" label="Calls"'); - print(' persist="width" ordinal="4"/>'); - print(' </treecols>'); - print(' <treechildren>'); - - dumpData('root', PROFILING_ROOT, ' '); - - print(' </treechildren>'); - print('</tree>'); - print('</window>'); - - // This requires dom.allow_XUL_XBL_for_file -} -Module['printXULProfiling'] = printXULProfiling; #endif //======================================== @@ -335,7 +284,7 @@ var tempI64, tempI64b; #endif function abort(text) { - print(text + ':\n' + (new Error).stack); + Module.print(text + ':\n' + (new Error).stack); ABORT = true; throw "Assertion: " + text; } @@ -366,18 +315,26 @@ var globalScope = this; // -s EXPORTED_FUNCTIONS='["_func1","_func2"]' // // @param ident The name of the C function (note that C++ functions will be name-mangled - use extern "C") -// @param returnType The return type of the function, one of the JS types 'number' or 'string' (use 'number' for any C pointer). -// @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType. +// @param returnType The return type of the function, one of the JS types 'number', 'string' or 'array' (use 'number' for any C pointer, and +// 'array' for JavaScript arrays and typed arrays). +// @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType, +// except that 'array' is not possible (there is no way for us to know the length of the array) // @param args An array of the arguments to the function, as native JS values (as in returnType) // Note that string arguments will be stored on the stack (the JS string will become a C string on the stack). // @return The return value, as a native JS value (as in returnType) function ccall(ident, returnType, argTypes, args) { + var stack = 0; function toC(value, type) { if (type == 'string') { - var ret = STACKTOP; - Runtime.stackAlloc(value.length+1); + if (!stack) stack = Runtime.stackSave(); + var ret = Runtime.stackAlloc(value.length+1); writeStringToMemory(value, ret); return ret; + } else if (type == 'array') { + if (!stack) stack = Runtime.stackSave(); + var ret = Runtime.stackAlloc(value.length); + writeArrayToMemory(value, ret); + return ret; } return value; } @@ -385,6 +342,7 @@ function ccall(ident, returnType, argTypes, args) { if (type == 'string') { return Pointer_stringify(value); } + assert(type != 'array'); return value; } try { @@ -399,7 +357,9 @@ function ccall(ident, returnType, argTypes, args) { var cArgs = args ? args.map(function(arg) { return toC(arg, argTypes[i++]); }) : []; - return fromC(func.apply(null, cArgs), returnType); + var ret = fromC(func.apply(null, cArgs), returnType); + if (stack) Runtime.stackRestore(stack); + return ret; } Module["ccall"] = ccall; @@ -416,6 +376,7 @@ function cwrap(ident, returnType, argTypes) { return ccall(ident, returnType, argTypes, Array.prototype.slice.call(arguments)); } } +Module["cwrap"] = cwrap; // Sets a value in memory in a dynamic way at run-time. Uses the // type data. This is the same as makeSetValue, except that @@ -594,7 +555,7 @@ var FHEAP; #endif #endif #if USE_TYPED_ARRAYS == 2 -var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32; +var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; #endif var STACK_ROOT, STACKTOP, STACK_MAX; @@ -603,7 +564,7 @@ var STATICTOP; function enlargeMemory() { // TOTAL_MEMORY is the current size of the actual array, and STATICTOP is the new top. #if ASSERTIONS - printErr('Warning: Enlarging memory arrays, this is not fast! ' + [STATICTOP, TOTAL_MEMORY]); + Module.printErr('Warning: Enlarging memory arrays, this is not fast! ' + [STATICTOP, TOTAL_MEMORY]); assert(STATICTOP >= TOTAL_MEMORY); assert(TOTAL_MEMORY > 4); // So the loop below will not be infinite #endif @@ -631,6 +592,7 @@ function enlargeMemory() { HEAPU16 = new Uint16Array(buffer); HEAPU32 = new Uint32Array(buffer); HEAPF32 = new Float32Array(buffer); + HEAPF64 = new Float64Array(buffer); HEAP8.set(oldHEAP8); #endif } @@ -662,6 +624,7 @@ var FAST_MEMORY = Module['FAST_MEMORY'] || {{{ FAST_MEMORY }}}; HEAPU16 = new Uint16Array(buffer); HEAPU32 = new Uint32Array(buffer); HEAPF32 = new Float32Array(buffer); + HEAPF64 = new Float64Array(buffer); // Endianness check (note: assumes compiler arch was little-endian) HEAP32[0] = 255; @@ -697,6 +660,7 @@ Module['HEAPU8'] = HEAPU8; Module['HEAPU16'] = HEAPU16; Module['HEAPU32'] = HEAPU32; Module['HEAPF32'] = HEAPF32; +Module['HEAPF64'] = HEAPF64; #endif STACK_ROOT = STACKTOP = Runtime.alignMemory(STATICTOP); @@ -707,7 +671,7 @@ var tempDoublePtr = Runtime.alignMemory(STACK_MAX, 8); var tempDoubleI8 = HEAP8.subarray(tempDoublePtr); var tempDoubleI32 = HEAP32.subarray(tempDoublePtr >> 2); var tempDoubleF32 = HEAPF32.subarray(tempDoublePtr >> 2); -var tempDoubleF64 = new Float64Array(HEAP8.buffer).subarray(tempDoublePtr >> 3); +var tempDoubleF64 = HEAPF64.subarray(tempDoublePtr >> 3); function copyTempFloat(ptr) { // functions, because inlining this code is increases code size too much tempDoubleI8[0] = HEAP8[ptr]; tempDoubleI8[1] = HEAP8[ptr+1]; @@ -741,12 +705,15 @@ function callRuntimeCallbacks(callbacks) { } var __ATINIT__ = []; // functions called during startup +var __ATMAIN__ = []; // functions called when main() is to be run var __ATEXIT__ = []; // functions called during shutdown function initRuntime() { callRuntimeCallbacks(__ATINIT__); } - +function preMain() { + callRuntimeCallbacks(__ATMAIN__); +} function exitRuntime() { callRuntimeCallbacks(__ATEXIT__); @@ -774,11 +741,14 @@ Module['Array_copy'] = Array_copy; #if USE_TYPED_ARRAYS // Copies a list of num items on the HEAP into a // JavaScript typed array. -function TypedArray_copy(ptr, num) { +function TypedArray_copy(ptr, num, offset /*optional*/) { // TODO: optimize this! - var arr = new Uint8Array(num); - for (var i = 0; i < num; ++i) { - arr[i] = {{{ makeGetValue('ptr', 'i', 'i8') }}}; + if (offset === undefined) { + offset = 0; + } + var arr = new Uint8Array(num - offset); + for (var i = offset; i < num; ++i) { + arr[i - offset] = {{{ makeGetValue('ptr', 'i', 'i8') }}}; } return arr.buffer; } @@ -807,11 +777,14 @@ Module['String_copy'] = String_copy; // This processes a JS string into a C-line array of numbers, 0-terminated. // For LLVM-originating strings, see parser.js:parseLLVMString function -function intArrayFromString(stringy, dontAddNull) { +function intArrayFromString(stringy, dontAddNull, length /* optional */) { var ret = []; var t; var i = 0; - while (i < stringy.length) { + if (length === undefined) { + length = stringy.length; + } + while (i < length) { var chr = stringy.charCodeAt(i); if (chr > 0xFF) { #if ASSERTIONS @@ -865,10 +838,36 @@ function writeStringToMemory(string, buffer, dontAddNull) { } Module['writeStringToMemory'] = writeStringToMemory; +function writeArrayToMemory(array, buffer) { + for (var i = 0; i < array.length; i++) { + {{{ makeSetValue('buffer', 'i', 'array[i]', 'i8') }}}; + } +} +Module['writeArrayToMemory'] = writeArrayToMemory; + var STRING_TABLE = []; {{{ unSign }}} {{{ reSign }}} +// A counter of dependencies for calling run(). If we need to +// do asynchronous work before running, increment this and +// decrement it. Incrementing must happen in Module.preRun +// or PRE_RUN_ADDITIONS (used by emcc to add file preloading). +var runDependencies = 0; +function addRunDependency() { + runDependencies++; + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } +} +function removeRunDependency() { + runDependencies--; + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } + if (runDependencies == 0) run(); +} + // === Body === diff --git a/src/runtime.js b/src/runtime.js index 852d08d8..0e4b7b2d 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -306,6 +306,13 @@ var Runtime = { }); } return ret; + }, + + addFunction: function(func) { + var ret = FUNCTION_TABLE.length; + FUNCTION_TABLE.push(func); + FUNCTION_TABLE.push(0); + return ret; } }; diff --git a/src/settings.js b/src/settings.js index 4ceb3750..7df86c90 100644 --- a/src/settings.js +++ b/src/settings.js @@ -67,6 +67,8 @@ var DOUBLE_MODE = 1; // How to load and store 64-bit doubles. Without typed arra // then load it aligned, and that load-store will make JS engines alter it if it is being // stored to a typed array for security reasons. That will 'fix' the number from being a // NaN or an infinite number. +var PRECISE_I64_MATH = 1; // If enabled, i64 addition etc. is emulated - which is slow but precise. If disabled, + // we use the 'double trick' which is fast but incurs rounding at high values. var CLOSURE_ANNOTATIONS = 0; // If set, the generated code will be annotated for the closure // compiler. This potentially lets closure optimize the code better. @@ -99,6 +101,9 @@ var SAFE_HEAP_LOG = 0; // Log out all SAFE_HEAP operations var LABEL_DEBUG = 0; // Print out labels and functions as we enter them var EXCEPTION_DEBUG = 1; // Print out exceptions in emscriptened code var LIBRARY_DEBUG = 0; // Print out when we enter a library call (library*.js) + +var GL_DEBUG = 0; // Print out all calls into WebGL + var DISABLE_EXCEPTION_CATCHING = 0; // Disables generating code to actually catch exceptions. If the code you // are compiling does not actually rely on catching exceptions (but the // compiler generates code for it, maybe because of stdlibc++ stuff), @@ -136,6 +141,9 @@ var CORRECT_OVERFLOWS = 1; // Experimental code that tries to prevent unexpected var CORRECT_ROUNDINGS = 1; // C rounds to 0 (-5.5 to -5, +5.5 to 5), while JS has no direct way to do that: // Math.floor is to negative, ceil to positive. With CORRECT_ROUNDINGS, // we will do slow but correct C rounding operations. +var FS_LOG = 0; // Log all FS operations. This is especially helpful when you're porting + // a new project and want to see a list of file system operations happening + // so that you can create a virtual file system with all of the required files. var PGO = 0; // Profile-guided optimization. // When run with the CHECK_* options, will not fail on errors. Instead, will @@ -148,8 +156,8 @@ var PGO = 0; // Profile-guided optimization. var PROFILE = 0; // Enables runtime profiling. See test_profiling for a usage example. -var EXPORTED_FUNCTIONS = ['_main']; // Functions that are explicitly exported, so they are guaranteed to - // be accessible outside of the generated code. +var EXPORTED_FUNCTIONS = ['_main', '_malloc', '_free']; // Functions that are explicitly exported, so they are guaranteed to + // be accessible outside of the generated code even after running closure compiler. var IGNORED_FUNCTIONS = []; // Functions that we should not generate, neither a stub nor a complete function. // This is useful if your project code includes a function, and you want to replace diff --git a/src/shell.html b/src/shell.html index 69217b18..37509889 100644 --- a/src/shell.html +++ b/src/shell.html @@ -1,31 +1,44 @@ +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <html> <head> <title>Emscripten-Generated Code</title> <body> <center> - <canvas id='canvas' width='256' height='256'></canvas> + <canvas id='canvas' width='256' height='256' style="border: 1px solid black" + oncontextmenu="event.preventDefault()"></canvas> + <hr> + <textarea id="output" style="font-family: monospace; width: 80%" rows="8"></textarea> + <hr> + <div id='status'>Downloading...</div> </center> <hr> - <div id='output'></div> - <hr> <script type='text/javascript'> - /** - * TODO: Encapsulate this part in a reusable token such as - * EMSCRIPTEN_ENVIRONMENT so that we can share code - * between the default shell and custom ones. - */ // connect to canvas var Module = { print: (function() { var element = document.getElementById('output'); + element.value = ''; // clear browser cache return function(text) { - element.innerHTML += text.replace('\n', '<br>', 'g') + '<br>'; + // These replacements are necessary if you render to raw HTML + //text = text.replace(/&/g, "&"); + //text = text.replace(/</g, "<"); + //text = text.replace(/>/g, ">"); + //text = text.replace('\n', '<br>', 'g'); + element.value += text + "\n"; + element.scrollTop = 99999; // focus on bottom }; })(), - canvas: document.getElementById('canvas') + canvas: document.getElementById('canvas'), + setStatus: function(text) { + document.getElementById('status').innerHTML = text; + }, + totalDependencies: 0, + monitorRunDependencies: function(left) { + this.totalDependencies = Math.max(this.totalDependencies, left); + Module.setStatus(left ? 'Downloading: ' + (this.totalDependencies-left) + '/' + this.totalDependencies : 'All downloads complete.'); + } }; - // The compiled code {{{ SCRIPT_CODE }}} </script> </body> diff --git a/src/shell.js b/src/shell.js index bc527192..e48be3b0 100644 --- a/src/shell.js +++ b/src/shell.js @@ -1,9 +1,13 @@ // TODO: " u s e s t r i c t "; +try { + this['Module'] = Module; +} catch(e) { + this['Module'] = Module = {}; +} +// The environment setup code below is customized to use Module. // *** Environment setup code *** -var arguments_ = []; - var ENVIRONMENT_IS_NODE = typeof process === 'object'; var ENVIRONMENT_IS_WEB = typeof window === 'object'; var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function'; @@ -12,61 +16,81 @@ var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIR if (ENVIRONMENT_IS_NODE) { // Expose functionality in the same simple way that the shells work // Note that we pollute the global namespace here, otherwise we break in node - print = function(x) { + Module['print'] = function(x) { process['stdout'].write(x + '\n'); }; - printErr = function(x) { + Module['printErr'] = function(x) { process['stderr'].write(x + '\n'); }; var nodeFS = require('fs'); + var nodePath = require('path'); - read = function(filename) { + Module['read'] = function(filename) { + filename = nodePath['normalize'](filename); var ret = nodeFS['readFileSync'](filename).toString(); - if (!ret && filename[0] != '/') { - filename = __dirname.split('/').slice(0, -1).join('/') + '/src/' + filename; + // The path is absolute if the normalized version is the same as the resolved. + if (!ret && filename != nodePath['resolve'](filename)) { + filename = path.join(__dirname, '..', 'src', filename); ret = nodeFS['readFileSync'](filename).toString(); } return ret; }; - load = function(f) { + Module['load'] = function(f) { globalEval(read(f)); }; - arguments_ = process['argv'].slice(2); - -} else if (ENVIRONMENT_IS_SHELL) { - // Polyfill over SpiderMonkey/V8 differences - if (!this['read']) { - this['read'] = function(f) { snarf(f) }; + if (!Module['arguments']) { + Module['arguments'] = process['argv'].slice(2); } +} else if (ENVIRONMENT_IS_SHELL) { + Module['print'] = print; + Module['printErr'] = printErr; - if (!this['arguments']) { - arguments_ = scriptArgs; + // Polyfill over SpiderMonkey/V8 differences + if (typeof read != 'undefined') { + Module['read'] = read; } else { - arguments_ = arguments; + Module['read'] = function(f) { snarf(f) }; } + if (!Module['arguments']) { + if (typeof scriptArgs != 'undefined') { + Module['arguments'] = scriptArgs; + } else if (typeof arguments != 'undefined') { + Module['arguments'] = arguments; + } + } } else if (ENVIRONMENT_IS_WEB) { - this['print'] = printErr = function(x) { - console.log(x); - }; + if (!Module['print']) { + Module['print'] = function(x) { + console.log(x); + }; + } - this['read'] = function(url) { + if (!Module['printErr']) { + Module['printErr'] = function(x) { + console.log(x); + }; + } + + Module['read'] = function(url) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, false); xhr.send(null); return xhr.responseText; }; - if (this['arguments']) { - arguments_ = arguments; + if (!Module['arguments']) { + if (typeof arguments != 'undefined') { + Module['arguments'] = arguments; + } } } else if (ENVIRONMENT_IS_WORKER) { // We can do very little here... - this['load'] = importScripts; + Module['load'] = importScripts; } else { throw 'Unknown runtime environment. Where are we?'; @@ -75,34 +99,25 @@ if (ENVIRONMENT_IS_NODE) { function globalEval(x) { eval.call(null, x); } - -if (typeof load == 'undefined' && typeof read != 'undefined') { - this['load'] = function(f) { - globalEval(read(f)); +if (!Module['load'] == 'undefined' && Module['read']) { + Module['load'] = function(f) { + globalEval(Module['read'](f)); }; } - -if (typeof printErr === 'undefined') { - this['printErr'] = function(){}; +if (!Module['printErr']) { + Module['printErr'] = function(){}; } - -if (typeof print === 'undefined') { - this['print'] = printErr; +if (!Module['print']) { + Module['print'] = Module['printErr']; +} +if (!Module['arguments']) { + Module['arguments'] = []; } // *** Environment setup code *** - -try { - this['Module'] = Module; -} catch(e) { - this['Module'] = Module = {}; -} -if (!Module.arguments) { - Module.arguments = arguments_; -} -if (Module.print) { - print = Module.print; -} +// Closure helpers +Module.print = Module['print']; +Module.printErr = Module['printErr']; {{BODY}} diff --git a/src/utility.js b/src/utility.js index 31eff100..7d5e0970 100644 --- a/src/utility.js +++ b/src/utility.js @@ -62,15 +62,21 @@ function warn(a, msg) { a = false; } if (!a) { - dprint('Warning: ' + msg); + printErr('Warning: ' + msg); } } -function warnOnce(msg) { - if (!warnOnce.msgs) warnOnce.msgs = {}; - if (msg in warnOnce.msgs) return; - warnOnce.msgs[msg] = true; - dprint('Warning: ' + msg); +function warnOnce(a, msg) { + if (!msg) { + msg = a; + a = false; + } + if (!a) { + if (!warnOnce.msgs) warnOnce.msgs = {}; + if (msg in warnOnce.msgs) return; + warnOnce.msgs[msg] = true; + printErr('Warning: ' + msg); + } } function dedup(items, ident) { diff --git a/system/include/SDL/SDL_gfxPrimitives.h b/system/include/SDL/SDL_gfxPrimitives.h new file mode 100644 index 00000000..e2f2cf26 --- /dev/null +++ b/system/include/SDL/SDL_gfxPrimitives.h @@ -0,0 +1,246 @@ +/* + +SDL_gfxPrimitives.h: graphics primitives for SDL + +Copyright (C) 2001-2011 Andreas Schiffler + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Andreas Schiffler -- aschiffler at ferzkopp dot net + +*/ + +#ifndef _SDL_gfxPrimitives_h +#define _SDL_gfxPrimitives_h + +#include <math.h> +#ifndef M_PI +#define M_PI 3.1415926535897932384626433832795 +#endif + +#include "SDL.h" + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + + /* ----- Versioning */ + +#define SDL_GFXPRIMITIVES_MAJOR 2 +#define SDL_GFXPRIMITIVES_MINOR 0 +#define SDL_GFXPRIMITIVES_MICRO 23 + + + /* ---- Function Prototypes */ + +#ifdef _MSC_VER +# if defined(DLL_EXPORT) && !defined(LIBSDL_GFX_DLL_IMPORT) +# define SDL_GFXPRIMITIVES_SCOPE __declspec(dllexport) +# else +# ifdef LIBSDL_GFX_DLL_IMPORT +# define SDL_GFXPRIMITIVES_SCOPE __declspec(dllimport) +# endif +# endif +#endif +#ifndef SDL_GFXPRIMITIVES_SCOPE +# define SDL_GFXPRIMITIVES_SCOPE extern +#endif + + /* Note: all ___Color routines expect the color to be in format 0xRRGGBBAA */ + + /* Pixel */ + + SDL_GFXPRIMITIVES_SCOPE int pixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int pixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Horizontal line */ + + SDL_GFXPRIMITIVES_SCOPE int hlineColor(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int hlineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Vertical line */ + + SDL_GFXPRIMITIVES_SCOPE int vlineColor(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int vlineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Rectangle */ + + SDL_GFXPRIMITIVES_SCOPE int rectangleColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int rectangleRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, + Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Rounded-Corner Rectangle */ + + SDL_GFXPRIMITIVES_SCOPE int roundedRectangleColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int roundedRectangleRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, + Sint16 x2, Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Filled rectangle (Box) */ + + SDL_GFXPRIMITIVES_SCOPE int boxColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int boxRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, + Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Rounded-Corner Filled rectangle (Box) */ + + SDL_GFXPRIMITIVES_SCOPE int roundedBoxColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int roundedBoxRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, + Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Line */ + + SDL_GFXPRIMITIVES_SCOPE int lineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int lineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, + Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* AA Line */ + + SDL_GFXPRIMITIVES_SCOPE int aalineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int aalineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, + Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Thick Line */ + SDL_GFXPRIMITIVES_SCOPE int thickLineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, + Uint8 width, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int thickLineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, + Uint8 width, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Circle */ + + SDL_GFXPRIMITIVES_SCOPE int circleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int circleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Arc */ + + SDL_GFXPRIMITIVES_SCOPE int arcColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int arcRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, + Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* AA Circle */ + + SDL_GFXPRIMITIVES_SCOPE int aacircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int aacircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, + Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Filled Circle */ + + SDL_GFXPRIMITIVES_SCOPE int filledCircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int filledCircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, + Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Ellipse */ + + SDL_GFXPRIMITIVES_SCOPE int ellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int ellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, + Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* AA Ellipse */ + + SDL_GFXPRIMITIVES_SCOPE int aaellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int aaellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, + Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Filled Ellipse */ + + SDL_GFXPRIMITIVES_SCOPE int filledEllipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int filledEllipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, + Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Pie */ + + SDL_GFXPRIMITIVES_SCOPE int pieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, + Sint16 start, Sint16 end, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int pieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, + Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Filled Pie */ + + SDL_GFXPRIMITIVES_SCOPE int filledPieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, + Sint16 start, Sint16 end, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int filledPieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, + Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Trigon */ + + SDL_GFXPRIMITIVES_SCOPE int trigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int trigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, + Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* AA-Trigon */ + + SDL_GFXPRIMITIVES_SCOPE int aatrigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int aatrigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, + Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Filled Trigon */ + + SDL_GFXPRIMITIVES_SCOPE int filledTrigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int filledTrigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, + Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Polygon */ + + SDL_GFXPRIMITIVES_SCOPE int polygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int polygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, + int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* AA-Polygon */ + + SDL_GFXPRIMITIVES_SCOPE int aapolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int aapolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, + int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Filled Polygon */ + + SDL_GFXPRIMITIVES_SCOPE int filledPolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int filledPolygonRGBA(SDL_Surface * dst, const Sint16 * vx, + const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + SDL_GFXPRIMITIVES_SCOPE int texturedPolygon(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface * texture,int texture_dx,int texture_dy); + + /* (Note: These MT versions are required for multi-threaded operation.) */ + + SDL_GFXPRIMITIVES_SCOPE int filledPolygonColorMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color, int **polyInts, int *polyAllocated); + SDL_GFXPRIMITIVES_SCOPE int filledPolygonRGBAMT(SDL_Surface * dst, const Sint16 * vx, + const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a, + int **polyInts, int *polyAllocated); + SDL_GFXPRIMITIVES_SCOPE int texturedPolygonMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface * texture,int texture_dx,int texture_dy, int **polyInts, int *polyAllocated); + + /* Bezier */ + + SDL_GFXPRIMITIVES_SCOPE int bezierColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int bezierRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, + int n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Characters/Strings */ + + SDL_GFXPRIMITIVES_SCOPE void gfxPrimitivesSetFont(const void *fontdata, Uint32 cw, Uint32 ch); + SDL_GFXPRIMITIVES_SCOPE void gfxPrimitivesSetFontRotation(Uint32 rotation); + SDL_GFXPRIMITIVES_SCOPE int characterColor(SDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int characterRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + SDL_GFXPRIMITIVES_SCOPE int stringColor(SDL_Surface * dst, Sint16 x, Sint16 y, const char *s, Uint32 color); + SDL_GFXPRIMITIVES_SCOPE int stringRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, const char *s, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + + /* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif + +#endif /* _SDL_gfxPrimitives_h */ diff --git a/system/include/SDL/SDL_image.h b/system/include/SDL/SDL_image.h new file mode 100644 index 00000000..3f07d74a --- /dev/null +++ b/system/include/SDL/SDL_image.h @@ -0,0 +1,138 @@ +/* + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* A simple library to load images of various formats as SDL surfaces */ + +#ifndef _SDL_IMAGE_H +#define _SDL_IMAGE_H + +#include "SDL.h" +#include "SDL_version.h" +#include "begin_code.h" + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL +*/ +#define SDL_IMAGE_MAJOR_VERSION 1 +#define SDL_IMAGE_MINOR_VERSION 2 +#define SDL_IMAGE_PATCHLEVEL 12 + +/* This macro can be used to fill a version structure with the compile-time + * version of the SDL_image library. + */ +#define SDL_IMAGE_VERSION(X) \ +{ \ + (X)->major = SDL_IMAGE_MAJOR_VERSION; \ + (X)->minor = SDL_IMAGE_MINOR_VERSION; \ + (X)->patch = SDL_IMAGE_PATCHLEVEL; \ +} + +/* This function gets the version of the dynamically linked SDL_image library. + it should NOT be used to fill a version structure, instead you should + use the SDL_IMAGE_VERSION() macro. + */ +extern DECLSPEC const SDL_version * SDLCALL IMG_Linked_Version(void); + +typedef enum +{ + IMG_INIT_JPG = 0x00000001, + IMG_INIT_PNG = 0x00000002, + IMG_INIT_TIF = 0x00000004, + IMG_INIT_WEBP = 0x00000008 +} IMG_InitFlags; + +/* Loads dynamic libraries and prepares them for use. Flags should be + one or more flags from IMG_InitFlags OR'd together. + It returns the flags successfully initialized, or 0 on failure. + */ +extern DECLSPEC int SDLCALL IMG_Init(int flags); + +/* Unloads libraries loaded with IMG_Init */ +extern DECLSPEC void SDLCALL IMG_Quit(void); + +/* Load an image from an SDL data source. + The 'type' may be one of: "BMP", "GIF", "PNG", etc. + + If the image format supports a transparent pixel, SDL will set the + colorkey for the surface. You can enable RLE acceleration on the + surface afterwards by calling: + SDL_SetColorKey(image, SDL_RLEACCEL, image->format->colorkey); + */ +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadTyped_RW(SDL_RWops *src, int freesrc, char *type); +/* Convenience functions */ +extern DECLSPEC SDL_Surface * SDLCALL IMG_Load(const char *file); +extern DECLSPEC SDL_Surface * SDLCALL IMG_Load_RW(SDL_RWops *src, int freesrc); + +/* Invert the alpha of a surface for use with OpenGL + This function is now a no-op, and only provided for backwards compatibility. +*/ +extern DECLSPEC int SDLCALL IMG_InvertAlpha(int on); + +/* Functions to detect a file type, given a seekable source */ +extern DECLSPEC int SDLCALL IMG_isICO(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isCUR(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isBMP(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isGIF(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isJPG(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isLBM(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isPCX(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isPNG(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isPNM(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isTIF(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isXCF(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isXPM(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isXV(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isWEBP(SDL_RWops *src); + +/* Individual loading functions */ +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadICO_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadCUR_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadBMP_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadGIF_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadJPG_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadLBM_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadPCX_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadPNG_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadPNM_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadTGA_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadTIF_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadXCF_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadXPM_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadXV_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadWEBP_RW(SDL_RWops *src); + +extern DECLSPEC SDL_Surface * SDLCALL IMG_ReadXPMFromArray(char **xpm); + +/* We'll use SDL for reporting errors */ +#define IMG_SetError SDL_SetError +#define IMG_GetError SDL_GetError + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include "close_code.h" + +#endif /* _SDL_IMAGE_H */ diff --git a/system/include/SDL/SDL_keycode.h b/system/include/SDL/SDL_keycode.h index 5be1f715..472ca28e 100644 --- a/system/include/SDL/SDL_keycode.h +++ b/system/include/SDL/SDL_keycode.h @@ -41,7 +41,9 @@ */ typedef Sint32 SDL_Keycode; -#define SDLK_SCANCODE_MASK (1<<30) +// XXX Emscripten: We use a mask of 10, which is closer to old SDL, and gives +// a better chance of SDL 1.X apps working +#define SDLK_SCANCODE_MASK (1<<10) #define SDL_SCANCODE_TO_KEYCODE(X) (X | SDLK_SCANCODE_MASK) enum diff --git a/system/include/SDL/SDL_mixer.h b/system/include/SDL/SDL_mixer.h new file mode 100644 index 00000000..9c25ef6b --- /dev/null +++ b/system/include/SDL/SDL_mixer.h @@ -0,0 +1,634 @@ +/* + SDL_mixer: An audio mixer library based on the SDL library + Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* $Id$ */ + +#ifndef _SDL_MIXER_H +#define _SDL_MIXER_H + +#include "SDL_types.h" +#include "SDL_rwops.h" +#include "SDL_audio.h" +#include "SDL_endian.h" +#include "SDL_version.h" +#include "begin_code.h" + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL +*/ +#define SDL_MIXER_MAJOR_VERSION 1 +#define SDL_MIXER_MINOR_VERSION 2 +#define SDL_MIXER_PATCHLEVEL 12 + +/* This macro can be used to fill a version structure with the compile-time + * version of the SDL_mixer library. + */ +#define SDL_MIXER_VERSION(X) \ +{ \ + (X)->major = SDL_MIXER_MAJOR_VERSION; \ + (X)->minor = SDL_MIXER_MINOR_VERSION; \ + (X)->patch = SDL_MIXER_PATCHLEVEL; \ +} + +/* Backwards compatibility */ +#define MIX_MAJOR_VERSION SDL_MIXER_MAJOR_VERSION +#define MIX_MINOR_VERSION SDL_MIXER_MINOR_VERSION +#define MIX_PATCHLEVEL SDL_MIXER_PATCHLEVEL +#define MIX_VERSION(X) SDL_MIXER_VERSION(X) + +/* This function gets the version of the dynamically linked SDL_mixer library. + it should NOT be used to fill a version structure, instead you should + use the SDL_MIXER_VERSION() macro. + */ +extern DECLSPEC const SDL_version * SDLCALL Mix_Linked_Version(void); + +typedef enum +{ + MIX_INIT_FLAC = 0x00000001, + MIX_INIT_MOD = 0x00000002, + MIX_INIT_MP3 = 0x00000004, + MIX_INIT_OGG = 0x00000008, + MIX_INIT_FLUIDSYNTH = 0x00000010 +} MIX_InitFlags; + +/* Loads dynamic libraries and prepares them for use. Flags should be + one or more flags from MIX_InitFlags OR'd together. + It returns the flags successfully initialized, or 0 on failure. + */ +extern DECLSPEC int SDLCALL Mix_Init(int flags); + +/* Unloads libraries loaded with Mix_Init */ +extern DECLSPEC void SDLCALL Mix_Quit(void); + + +/* The default mixer has 8 simultaneous mixing channels */ +#ifndef MIX_CHANNELS +#define MIX_CHANNELS 8 +#endif + +/* Good default values for a PC soundcard */ +#define MIX_DEFAULT_FREQUENCY 22050 +#if SDL_BYTEORDER == SDL_LIL_ENDIAN +#define MIX_DEFAULT_FORMAT AUDIO_S16LSB +#else +#define MIX_DEFAULT_FORMAT AUDIO_S16MSB +#endif +#define MIX_DEFAULT_CHANNELS 2 +#define MIX_MAX_VOLUME 128 /* Volume of a chunk */ + +/* The internal format for an audio chunk */ +typedef struct Mix_Chunk { + int allocated; + Uint8 *abuf; + Uint32 alen; + Uint8 volume; /* Per-sample volume, 0-128 */ +} Mix_Chunk; + +/* The different fading types supported */ +typedef enum { + MIX_NO_FADING, + MIX_FADING_OUT, + MIX_FADING_IN +} Mix_Fading; + +typedef enum { + MUS_NONE, + MUS_CMD, + MUS_WAV, + MUS_MOD, + MUS_MID, + MUS_OGG, + MUS_MP3, + MUS_MP3_MAD, + MUS_FLAC, + MUS_MODPLUG +} Mix_MusicType; + +/* The internal format for a music chunk interpreted via mikmod */ +typedef struct _Mix_Music Mix_Music; + +/* Open the mixer with a certain audio format */ +extern DECLSPEC int SDLCALL Mix_OpenAudio(int frequency, Uint16 format, int channels, + int chunksize); + +/* Dynamically change the number of channels managed by the mixer. + If decreasing the number of channels, the upper channels are + stopped. + This function returns the new number of allocated channels. + */ +extern DECLSPEC int SDLCALL Mix_AllocateChannels(int numchans); + +/* Find out what the actual audio device parameters are. + This function returns 1 if the audio has been opened, 0 otherwise. + */ +extern DECLSPEC int SDLCALL Mix_QuerySpec(int *frequency,Uint16 *format,int *channels); + +/* Load a wave file or a music (.mod .s3m .it .xm) file */ +extern DECLSPEC Mix_Chunk * SDLCALL Mix_LoadWAV_RW(SDL_RWops *src, int freesrc); +#define Mix_LoadWAV(file) Mix_LoadWAV_RW(SDL_RWFromFile(file, "rb"), 1) +extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS(const char *file); + +/* Load a music file from an SDL_RWop object (Ogg and MikMod specific currently) + Matt Campbell (matt@campbellhome.dhs.org) April 2000 */ +extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS_RW(SDL_RWops *rw); + +/* Load a music file from an SDL_RWop object assuming a specific format */ +extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUSType_RW(SDL_RWops *rw, Mix_MusicType type, int freesrc); + +/* Load a wave file of the mixer format from a memory buffer */ +extern DECLSPEC Mix_Chunk * SDLCALL Mix_QuickLoad_WAV(Uint8 *mem); + +/* Load raw audio data of the mixer format from a memory buffer */ +extern DECLSPEC Mix_Chunk * SDLCALL Mix_QuickLoad_RAW(Uint8 *mem, Uint32 len); + +/* Free an audio chunk previously loaded */ +extern DECLSPEC void SDLCALL Mix_FreeChunk(Mix_Chunk *chunk); +extern DECLSPEC void SDLCALL Mix_FreeMusic(Mix_Music *music); + +/* Get a list of chunk/music decoders that this build of SDL_mixer provides. + This list can change between builds AND runs of the program, if external + libraries that add functionality become available. + You must successfully call Mix_OpenAudio() before calling these functions. + This API is only available in SDL_mixer 1.2.9 and later. + + // usage... + int i; + const int total = Mix_GetNumChunkDecoders(); + for (i = 0; i < total; i++) + printf("Supported chunk decoder: [%s]\n", Mix_GetChunkDecoder(i)); + + Appearing in this list doesn't promise your specific audio file will + decode...but it's handy to know if you have, say, a functioning Timidity + install. + + These return values are static, read-only data; do not modify or free it. + The pointers remain valid until you call Mix_CloseAudio(). +*/ +extern DECLSPEC int SDLCALL Mix_GetNumChunkDecoders(void); +extern DECLSPEC const char * SDLCALL Mix_GetChunkDecoder(int index); +extern DECLSPEC int SDLCALL Mix_GetNumMusicDecoders(void); +extern DECLSPEC const char * SDLCALL Mix_GetMusicDecoder(int index); + +/* Find out the music format of a mixer music, or the currently playing + music, if 'music' is NULL. +*/ +extern DECLSPEC Mix_MusicType SDLCALL Mix_GetMusicType(const Mix_Music *music); + +/* Set a function that is called after all mixing is performed. + This can be used to provide real-time visual display of the audio stream + or add a custom mixer filter for the stream data. +*/ +extern DECLSPEC void SDLCALL Mix_SetPostMix(void (*mix_func) + (void *udata, Uint8 *stream, int len), void *arg); + +/* Add your own music player or additional mixer function. + If 'mix_func' is NULL, the default music player is re-enabled. + */ +extern DECLSPEC void SDLCALL Mix_HookMusic(void (*mix_func) + (void *udata, Uint8 *stream, int len), void *arg); + +/* Add your own callback when the music has finished playing. + This callback is only called if the music finishes naturally. + */ +extern DECLSPEC void SDLCALL Mix_HookMusicFinished(void (*music_finished)(void)); + +/* Get a pointer to the user data for the current music hook */ +extern DECLSPEC void * SDLCALL Mix_GetMusicHookData(void); + +/* + * Add your own callback when a channel has finished playing. NULL + * to disable callback. The callback may be called from the mixer's audio + * callback or it could be called as a result of Mix_HaltChannel(), etc. + * do not call SDL_LockAudio() from this callback; you will either be + * inside the audio callback, or SDL_mixer will explicitly lock the audio + * before calling your callback. + */ +extern DECLSPEC void SDLCALL Mix_ChannelFinished(void (*channel_finished)(int channel)); + + +/* Special Effects API by ryan c. gordon. (icculus@icculus.org) */ + +#define MIX_CHANNEL_POST -2 + +/* This is the format of a special effect callback: + * + * myeffect(int chan, void *stream, int len, void *udata); + * + * (chan) is the channel number that your effect is affecting. (stream) is + * the buffer of data to work upon. (len) is the size of (stream), and + * (udata) is a user-defined bit of data, which you pass as the last arg of + * Mix_RegisterEffect(), and is passed back unmolested to your callback. + * Your effect changes the contents of (stream) based on whatever parameters + * are significant, or just leaves it be, if you prefer. You can do whatever + * you like to the buffer, though, and it will continue in its changed state + * down the mixing pipeline, through any other effect functions, then finally + * to be mixed with the rest of the channels and music for the final output + * stream. + * + * DO NOT EVER call SDL_LockAudio() from your callback function! + */ +typedef void (*Mix_EffectFunc_t)(int chan, void *stream, int len, void *udata); + +/* + * This is a callback that signifies that a channel has finished all its + * loops and has completed playback. This gets called if the buffer + * plays out normally, or if you call Mix_HaltChannel(), implicitly stop + * a channel via Mix_AllocateChannels(), or unregister a callback while + * it's still playing. + * + * DO NOT EVER call SDL_LockAudio() from your callback function! + */ +typedef void (*Mix_EffectDone_t)(int chan, void *udata); + + +/* Register a special effect function. At mixing time, the channel data is + * copied into a buffer and passed through each registered effect function. + * After it passes through all the functions, it is mixed into the final + * output stream. The copy to buffer is performed once, then each effect + * function performs on the output of the previous effect. Understand that + * this extra copy to a buffer is not performed if there are no effects + * registered for a given chunk, which saves CPU cycles, and any given + * effect will be extra cycles, too, so it is crucial that your code run + * fast. Also note that the data that your function is given is in the + * format of the sound device, and not the format you gave to Mix_OpenAudio(), + * although they may in reality be the same. This is an unfortunate but + * necessary speed concern. Use Mix_QuerySpec() to determine if you can + * handle the data before you register your effect, and take appropriate + * actions. + * You may also specify a callback (Mix_EffectDone_t) that is called when + * the channel finishes playing. This gives you a more fine-grained control + * than Mix_ChannelFinished(), in case you need to free effect-specific + * resources, etc. If you don't need this, you can specify NULL. + * You may set the callbacks before or after calling Mix_PlayChannel(). + * Things like Mix_SetPanning() are just internal special effect functions, + * so if you are using that, you've already incurred the overhead of a copy + * to a separate buffer, and that these effects will be in the queue with + * any functions you've registered. The list of registered effects for a + * channel is reset when a chunk finishes playing, so you need to explicitly + * set them with each call to Mix_PlayChannel*(). + * You may also register a special effect function that is to be run after + * final mixing occurs. The rules for these callbacks are identical to those + * in Mix_RegisterEffect, but they are run after all the channels and the + * music have been mixed into a single stream, whereas channel-specific + * effects run on a given channel before any other mixing occurs. These + * global effect callbacks are call "posteffects". Posteffects only have + * their Mix_EffectDone_t function called when they are unregistered (since + * the main output stream is never "done" in the same sense as a channel). + * You must unregister them manually when you've had enough. Your callback + * will be told that the channel being mixed is (MIX_CHANNEL_POST) if the + * processing is considered a posteffect. + * + * After all these effects have finished processing, the callback registered + * through Mix_SetPostMix() runs, and then the stream goes to the audio + * device. + * + * DO NOT EVER call SDL_LockAudio() from your callback function! + * + * returns zero if error (no such channel), nonzero if added. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_RegisterEffect(int chan, Mix_EffectFunc_t f, + Mix_EffectDone_t d, void *arg); + + +/* You may not need to call this explicitly, unless you need to stop an + * effect from processing in the middle of a chunk's playback. + * Posteffects are never implicitly unregistered as they are for channels, + * but they may be explicitly unregistered through this function by + * specifying MIX_CHANNEL_POST for a channel. + * returns zero if error (no such channel or effect), nonzero if removed. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_UnregisterEffect(int channel, Mix_EffectFunc_t f); + + +/* You may not need to call this explicitly, unless you need to stop all + * effects from processing in the middle of a chunk's playback. Note that + * this will also shut off some internal effect processing, since + * Mix_SetPanning() and others may use this API under the hood. This is + * called internally when a channel completes playback. + * Posteffects are never implicitly unregistered as they are for channels, + * but they may be explicitly unregistered through this function by + * specifying MIX_CHANNEL_POST for a channel. + * returns zero if error (no such channel), nonzero if all effects removed. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_UnregisterAllEffects(int channel); + + +#define MIX_EFFECTSMAXSPEED "MIX_EFFECTSMAXSPEED" + +/* + * These are the internally-defined mixing effects. They use the same API that + * effects defined in the application use, but are provided here as a + * convenience. Some effects can reduce their quality or use more memory in + * the name of speed; to enable this, make sure the environment variable + * MIX_EFFECTSMAXSPEED (see above) is defined before you call + * Mix_OpenAudio(). + */ + + +/* Set the panning of a channel. The left and right channels are specified + * as integers between 0 and 255, quietest to loudest, respectively. + * + * Technically, this is just individual volume control for a sample with + * two (stereo) channels, so it can be used for more than just panning. + * If you want real panning, call it like this: + * + * Mix_SetPanning(channel, left, 255 - left); + * + * ...which isn't so hard. + * + * Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and + * the panning will be done to the final mixed stream before passing it on + * to the audio device. + * + * This uses the Mix_RegisterEffect() API internally, and returns without + * registering the effect function if the audio device is not configured + * for stereo output. Setting both (left) and (right) to 255 causes this + * effect to be unregistered, since that is the data's normal state. + * + * returns zero if error (no such channel or Mix_RegisterEffect() fails), + * nonzero if panning effect enabled. Note that an audio device in mono + * mode is a no-op, but this call will return successful in that case. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_SetPanning(int channel, Uint8 left, Uint8 right); + + +/* Set the position of a channel. (angle) is an integer from 0 to 360, that + * specifies the location of the sound in relation to the listener. (angle) + * will be reduced as neccesary (540 becomes 180 degrees, -100 becomes 260). + * Angle 0 is due north, and rotates clockwise as the value increases. + * For efficiency, the precision of this effect may be limited (angles 1 + * through 7 might all produce the same effect, 8 through 15 are equal, etc). + * (distance) is an integer between 0 and 255 that specifies the space + * between the sound and the listener. The larger the number, the further + * away the sound is. Using 255 does not guarantee that the channel will be + * culled from the mixing process or be completely silent. For efficiency, + * the precision of this effect may be limited (distance 0 through 5 might + * all produce the same effect, 6 through 10 are equal, etc). Setting (angle) + * and (distance) to 0 unregisters this effect, since the data would be + * unchanged. + * + * If you need more precise positional audio, consider using OpenAL for + * spatialized effects instead of SDL_mixer. This is only meant to be a + * basic effect for simple "3D" games. + * + * If the audio device is configured for mono output, then you won't get + * any effectiveness from the angle; however, distance attenuation on the + * channel will still occur. While this effect will function with stereo + * voices, it makes more sense to use voices with only one channel of sound, + * so when they are mixed through this effect, the positioning will sound + * correct. You can convert them to mono through SDL before giving them to + * the mixer in the first place if you like. + * + * Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and + * the positioning will be done to the final mixed stream before passing it + * on to the audio device. + * + * This is a convenience wrapper over Mix_SetDistance() and Mix_SetPanning(). + * + * returns zero if error (no such channel or Mix_RegisterEffect() fails), + * nonzero if position effect is enabled. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_SetPosition(int channel, Sint16 angle, Uint8 distance); + + +/* Set the "distance" of a channel. (distance) is an integer from 0 to 255 + * that specifies the location of the sound in relation to the listener. + * Distance 0 is overlapping the listener, and 255 is as far away as possible + * A distance of 255 does not guarantee silence; in such a case, you might + * want to try changing the chunk's volume, or just cull the sample from the + * mixing process with Mix_HaltChannel(). + * For efficiency, the precision of this effect may be limited (distances 1 + * through 7 might all produce the same effect, 8 through 15 are equal, etc). + * (distance) is an integer between 0 and 255 that specifies the space + * between the sound and the listener. The larger the number, the further + * away the sound is. + * Setting (distance) to 0 unregisters this effect, since the data would be + * unchanged. + * If you need more precise positional audio, consider using OpenAL for + * spatialized effects instead of SDL_mixer. This is only meant to be a + * basic effect for simple "3D" games. + * + * Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and + * the distance attenuation will be done to the final mixed stream before + * passing it on to the audio device. + * + * This uses the Mix_RegisterEffect() API internally. + * + * returns zero if error (no such channel or Mix_RegisterEffect() fails), + * nonzero if position effect is enabled. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_SetDistance(int channel, Uint8 distance); + + +/* + * !!! FIXME : Haven't implemented, since the effect goes past the + * end of the sound buffer. Will have to think about this. + * --ryan. + */ +#if 0 +/* Causes an echo effect to be mixed into a sound. (echo) is the amount + * of echo to mix. 0 is no echo, 255 is infinite (and probably not + * what you want). + * + * Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and + * the reverbing will be done to the final mixed stream before passing it on + * to the audio device. + * + * This uses the Mix_RegisterEffect() API internally. If you specify an echo + * of zero, the effect is unregistered, as the data is already in that state. + * + * returns zero if error (no such channel or Mix_RegisterEffect() fails), + * nonzero if reversing effect is enabled. + * Error messages can be retrieved from Mix_GetError(). + */ +extern no_parse_DECLSPEC int SDLCALL Mix_SetReverb(int channel, Uint8 echo); +#endif + +/* Causes a channel to reverse its stereo. This is handy if the user has his + * speakers hooked up backwards, or you would like to have a minor bit of + * psychedelia in your sound code. :) Calling this function with (flip) + * set to non-zero reverses the chunks's usual channels. If (flip) is zero, + * the effect is unregistered. + * + * This uses the Mix_RegisterEffect() API internally, and thus is probably + * more CPU intensive than having the user just plug in his speakers + * correctly. Mix_SetReverseStereo() returns without registering the effect + * function if the audio device is not configured for stereo output. + * + * If you specify MIX_CHANNEL_POST for (channel), then this the effect is used + * on the final mixed stream before sending it on to the audio device (a + * posteffect). + * + * returns zero if error (no such channel or Mix_RegisterEffect() fails), + * nonzero if reversing effect is enabled. Note that an audio device in mono + * mode is a no-op, but this call will return successful in that case. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_SetReverseStereo(int channel, int flip); + +/* end of effects API. --ryan. */ + + +/* Reserve the first channels (0 -> n-1) for the application, i.e. don't allocate + them dynamically to the next sample if requested with a -1 value below. + Returns the number of reserved channels. + */ +extern DECLSPEC int SDLCALL Mix_ReserveChannels(int num); + +/* Channel grouping functions */ + +/* Attach a tag to a channel. A tag can be assigned to several mixer + channels, to form groups of channels. + If 'tag' is -1, the tag is removed (actually -1 is the tag used to + represent the group of all the channels). + Returns true if everything was OK. + */ +extern DECLSPEC int SDLCALL Mix_GroupChannel(int which, int tag); +/* Assign several consecutive channels to a group */ +extern DECLSPEC int SDLCALL Mix_GroupChannels(int from, int to, int tag); +/* Finds the first available channel in a group of channels, + returning -1 if none are available. + */ +extern DECLSPEC int SDLCALL Mix_GroupAvailable(int tag); +/* Returns the number of channels in a group. This is also a subtle + way to get the total number of channels when 'tag' is -1 + */ +extern DECLSPEC int SDLCALL Mix_GroupCount(int tag); +/* Finds the "oldest" sample playing in a group of channels */ +extern DECLSPEC int SDLCALL Mix_GroupOldest(int tag); +/* Finds the "most recent" (i.e. last) sample playing in a group of channels */ +extern DECLSPEC int SDLCALL Mix_GroupNewer(int tag); + +/* Play an audio chunk on a specific channel. + If the specified channel is -1, play on the first free channel. + If 'loops' is greater than zero, loop the sound that many times. + If 'loops' is -1, loop inifinitely (~65000 times). + Returns which channel was used to play the sound. +*/ +#define Mix_PlayChannel(channel,chunk,loops) Mix_PlayChannelTimed(channel,chunk,loops,-1) +/* The same as above, but the sound is played at most 'ticks' milliseconds */ +extern DECLSPEC int SDLCALL Mix_PlayChannelTimed(int channel, Mix_Chunk *chunk, int loops, int ticks); +extern DECLSPEC int SDLCALL Mix_PlayMusic(Mix_Music *music, int loops); + +/* Fade in music or a channel over "ms" milliseconds, same semantics as the "Play" functions */ +extern DECLSPEC int SDLCALL Mix_FadeInMusic(Mix_Music *music, int loops, int ms); +extern DECLSPEC int SDLCALL Mix_FadeInMusicPos(Mix_Music *music, int loops, int ms, double position); +#define Mix_FadeInChannel(channel,chunk,loops,ms) Mix_FadeInChannelTimed(channel,chunk,loops,ms,-1) +extern DECLSPEC int SDLCALL Mix_FadeInChannelTimed(int channel, Mix_Chunk *chunk, int loops, int ms, int ticks); + +/* Set the volume in the range of 0-128 of a specific channel or chunk. + If the specified channel is -1, set volume for all channels. + Returns the original volume. + If the specified volume is -1, just return the current volume. +*/ +extern DECLSPEC int SDLCALL Mix_Volume(int channel, int volume); +extern DECLSPEC int SDLCALL Mix_VolumeChunk(Mix_Chunk *chunk, int volume); +extern DECLSPEC int SDLCALL Mix_VolumeMusic(int volume); + +/* Halt playing of a particular channel */ +extern DECLSPEC int SDLCALL Mix_HaltChannel(int channel); +extern DECLSPEC int SDLCALL Mix_HaltGroup(int tag); +extern DECLSPEC int SDLCALL Mix_HaltMusic(void); + +/* Change the expiration delay for a particular channel. + The sample will stop playing after the 'ticks' milliseconds have elapsed, + or remove the expiration if 'ticks' is -1 +*/ +extern DECLSPEC int SDLCALL Mix_ExpireChannel(int channel, int ticks); + +/* Halt a channel, fading it out progressively till it's silent + The ms parameter indicates the number of milliseconds the fading + will take. + */ +extern DECLSPEC int SDLCALL Mix_FadeOutChannel(int which, int ms); +extern DECLSPEC int SDLCALL Mix_FadeOutGroup(int tag, int ms); +extern DECLSPEC int SDLCALL Mix_FadeOutMusic(int ms); + +/* Query the fading status of a channel */ +extern DECLSPEC Mix_Fading SDLCALL Mix_FadingMusic(void); +extern DECLSPEC Mix_Fading SDLCALL Mix_FadingChannel(int which); + +/* Pause/Resume a particular channel */ +extern DECLSPEC void SDLCALL Mix_Pause(int channel); +extern DECLSPEC void SDLCALL Mix_Resume(int channel); +extern DECLSPEC int SDLCALL Mix_Paused(int channel); + +/* Pause/Resume the music stream */ +extern DECLSPEC void SDLCALL Mix_PauseMusic(void); +extern DECLSPEC void SDLCALL Mix_ResumeMusic(void); +extern DECLSPEC void SDLCALL Mix_RewindMusic(void); +extern DECLSPEC int SDLCALL Mix_PausedMusic(void); + +/* Set the current position in the music stream. + This returns 0 if successful, or -1 if it failed or isn't implemented. + This function is only implemented for MOD music formats (set pattern + order number) and for OGG, FLAC, MP3_MAD, and MODPLUG music (set + position in seconds), at the moment. +*/ +extern DECLSPEC int SDLCALL Mix_SetMusicPosition(double position); + +/* Check the status of a specific channel. + If the specified channel is -1, check all channels. +*/ +extern DECLSPEC int SDLCALL Mix_Playing(int channel); +extern DECLSPEC int SDLCALL Mix_PlayingMusic(void); + +/* Stop music and set external music playback command */ +extern DECLSPEC int SDLCALL Mix_SetMusicCMD(const char *command); + +/* Synchro value is set by MikMod from modules while playing */ +extern DECLSPEC int SDLCALL Mix_SetSynchroValue(int value); +extern DECLSPEC int SDLCALL Mix_GetSynchroValue(void); + +/* Set/Get/Iterate SoundFonts paths to use by supported MIDI backends */ +extern DECLSPEC int SDLCALL Mix_SetSoundFonts(const char *paths); +extern DECLSPEC const char* SDLCALL Mix_GetSoundFonts(void); +extern DECLSPEC int SDLCALL Mix_EachSoundFont(int (*function)(const char*, void*), void *data); + +/* Get the Mix_Chunk currently associated with a mixer channel + Returns NULL if it's an invalid channel, or there's no chunk associated. +*/ +extern DECLSPEC Mix_Chunk * SDLCALL Mix_GetChunk(int channel); + +/* Close the mixer, halting all playing audio */ +extern DECLSPEC void SDLCALL Mix_CloseAudio(void); + +/* We'll use SDL for reporting errors */ +#define Mix_SetError SDL_SetError +#define Mix_GetError SDL_GetError + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include "close_code.h" + +#endif /* _SDL_MIXER_H */ diff --git a/system/include/SDL/SDL_ttf.h b/system/include/SDL/SDL_ttf.h new file mode 100644 index 00000000..5ae5bea7 --- /dev/null +++ b/system/include/SDL/SDL_ttf.h @@ -0,0 +1,249 @@ +/* + SDL_ttf: A companion library to SDL for working with TrueType (tm) fonts + Copyright (C) 2001-2012 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* This library is a wrapper around the excellent FreeType 2.0 library, + available at: + http://www.freetype.org/ +*/ + +#ifndef _SDL_TTF_H +#define _SDL_TTF_H + +#include "SDL.h" +#include "begin_code.h" + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL +*/ +#define SDL_TTF_MAJOR_VERSION 2 +#define SDL_TTF_MINOR_VERSION 0 +#define SDL_TTF_PATCHLEVEL 11 + +/* This macro can be used to fill a version structure with the compile-time + * version of the SDL_ttf library. + */ +#define SDL_TTF_VERSION(X) \ +{ \ + (X)->major = SDL_TTF_MAJOR_VERSION; \ + (X)->minor = SDL_TTF_MINOR_VERSION; \ + (X)->patch = SDL_TTF_PATCHLEVEL; \ +} + +/* Backwards compatibility */ +#define TTF_MAJOR_VERSION SDL_TTF_MAJOR_VERSION +#define TTF_MINOR_VERSION SDL_TTF_MINOR_VERSION +#define TTF_PATCHLEVEL SDL_TTF_PATCHLEVEL +#define TTF_VERSION(X) SDL_TTF_VERSION(X) + +/* This function gets the version of the dynamically linked SDL_ttf library. + it should NOT be used to fill a version structure, instead you should + use the SDL_TTF_VERSION() macro. + */ +extern DECLSPEC const SDL_version * SDLCALL TTF_Linked_Version(void); + +/* ZERO WIDTH NO-BREAKSPACE (Unicode byte order mark) */ +#define UNICODE_BOM_NATIVE 0xFEFF +#define UNICODE_BOM_SWAPPED 0xFFFE + +/* This function tells the library whether UNICODE text is generally + byteswapped. A UNICODE BOM character in a string will override + this setting for the remainder of that string. +*/ +extern DECLSPEC void SDLCALL TTF_ByteSwappedUNICODE(int swapped); + +/* The internal structure containing font information */ +typedef struct _TTF_Font TTF_Font; + +/* Initialize the TTF engine - returns 0 if successful, -1 on error */ +extern DECLSPEC int SDLCALL TTF_Init(void); + +/* Open a font file and create a font of the specified point size. + * Some .fon fonts will have several sizes embedded in the file, so the + * point size becomes the index of choosing which size. If the value + * is too high, the last indexed size will be the default. */ +extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFont(const char *file, int ptsize); +extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFontIndex(const char *file, int ptsize, long index); +extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFontRW(SDL_RWops *src, int freesrc, int ptsize); +extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFontIndexRW(SDL_RWops *src, int freesrc, int ptsize, long index); + +/* Set and retrieve the font style */ +#define TTF_STYLE_NORMAL 0x00 +#define TTF_STYLE_BOLD 0x01 +#define TTF_STYLE_ITALIC 0x02 +#define TTF_STYLE_UNDERLINE 0x04 +#define TTF_STYLE_STRIKETHROUGH 0x08 +extern DECLSPEC int SDLCALL TTF_GetFontStyle(const TTF_Font *font); +extern DECLSPEC void SDLCALL TTF_SetFontStyle(TTF_Font *font, int style); +extern DECLSPEC int SDLCALL TTF_GetFontOutline(const TTF_Font *font); +extern DECLSPEC void SDLCALL TTF_SetFontOutline(TTF_Font *font, int outline); + +/* Set and retrieve FreeType hinter settings */ +#define TTF_HINTING_NORMAL 0 +#define TTF_HINTING_LIGHT 1 +#define TTF_HINTING_MONO 2 +#define TTF_HINTING_NONE 3 +extern DECLSPEC int SDLCALL TTF_GetFontHinting(const TTF_Font *font); +extern DECLSPEC void SDLCALL TTF_SetFontHinting(TTF_Font *font, int hinting); + +/* Get the total height of the font - usually equal to point size */ +extern DECLSPEC int SDLCALL TTF_FontHeight(const TTF_Font *font); + +/* Get the offset from the baseline to the top of the font + This is a positive value, relative to the baseline. + */ +extern DECLSPEC int SDLCALL TTF_FontAscent(const TTF_Font *font); + +/* Get the offset from the baseline to the bottom of the font + This is a negative value, relative to the baseline. + */ +extern DECLSPEC int SDLCALL TTF_FontDescent(const TTF_Font *font); + +/* Get the recommended spacing between lines of text for this font */ +extern DECLSPEC int SDLCALL TTF_FontLineSkip(const TTF_Font *font); + +/* Get/Set whether or not kerning is allowed for this font */ +extern DECLSPEC int SDLCALL TTF_GetFontKerning(const TTF_Font *font); +extern DECLSPEC void SDLCALL TTF_SetFontKerning(TTF_Font *font, int allowed); + +/* Get the number of faces of the font */ +extern DECLSPEC long SDLCALL TTF_FontFaces(const TTF_Font *font); + +/* Get the font face attributes, if any */ +extern DECLSPEC int SDLCALL TTF_FontFaceIsFixedWidth(const TTF_Font *font); +extern DECLSPEC char * SDLCALL TTF_FontFaceFamilyName(const TTF_Font *font); +extern DECLSPEC char * SDLCALL TTF_FontFaceStyleName(const TTF_Font *font); + +/* Check wether a glyph is provided by the font or not */ +extern DECLSPEC int SDLCALL TTF_GlyphIsProvided(const TTF_Font *font, Uint16 ch); + +/* Get the metrics (dimensions) of a glyph + To understand what these metrics mean, here is a useful link: + http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html + */ +extern DECLSPEC int SDLCALL TTF_GlyphMetrics(TTF_Font *font, Uint16 ch, + int *minx, int *maxx, + int *miny, int *maxy, int *advance); + +/* Get the dimensions of a rendered string of text */ +extern DECLSPEC int SDLCALL TTF_SizeText(TTF_Font *font, const char *text, int *w, int *h); +extern DECLSPEC int SDLCALL TTF_SizeUTF8(TTF_Font *font, const char *text, int *w, int *h); +extern DECLSPEC int SDLCALL TTF_SizeUNICODE(TTF_Font *font, const Uint16 *text, int *w, int *h); + +/* Create an 8-bit palettized surface and render the given text at + fast quality with the given font and color. The 0 pixel is the + colorkey, giving a transparent background, and the 1 pixel is set + to the text color. + This function returns the new surface, or NULL if there was an error. +*/ +extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Solid(TTF_Font *font, + const char *text, SDL_Color fg); +extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Solid(TTF_Font *font, + const char *text, SDL_Color fg); +extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Solid(TTF_Font *font, + const Uint16 *text, SDL_Color fg); + +/* Create an 8-bit palettized surface and render the given glyph at + fast quality with the given font and color. The 0 pixel is the + colorkey, giving a transparent background, and the 1 pixel is set + to the text color. The glyph is rendered without any padding or + centering in the X direction, and aligned normally in the Y direction. + This function returns the new surface, or NULL if there was an error. +*/ +extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_Solid(TTF_Font *font, + Uint16 ch, SDL_Color fg); + +/* Create an 8-bit palettized surface and render the given text at + high quality with the given font and colors. The 0 pixel is background, + while other pixels have varying degrees of the foreground color. + This function returns the new surface, or NULL if there was an error. +*/ +extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Shaded(TTF_Font *font, + const char *text, SDL_Color fg, SDL_Color bg); +extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Shaded(TTF_Font *font, + const char *text, SDL_Color fg, SDL_Color bg); +extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Shaded(TTF_Font *font, + const Uint16 *text, SDL_Color fg, SDL_Color bg); + +/* Create an 8-bit palettized surface and render the given glyph at + high quality with the given font and colors. The 0 pixel is background, + while other pixels have varying degrees of the foreground color. + The glyph is rendered without any padding or centering in the X + direction, and aligned normally in the Y direction. + This function returns the new surface, or NULL if there was an error. +*/ +extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_Shaded(TTF_Font *font, + Uint16 ch, SDL_Color fg, SDL_Color bg); + +/* Create a 32-bit ARGB surface and render the given text at high quality, + using alpha blending to dither the font with the given color. + This function returns the new surface, or NULL if there was an error. +*/ +extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Blended(TTF_Font *font, + const char *text, SDL_Color fg); +extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Blended(TTF_Font *font, + const char *text, SDL_Color fg); +extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Blended(TTF_Font *font, + const Uint16 *text, SDL_Color fg); + +/* Create a 32-bit ARGB surface and render the given glyph at high quality, + using alpha blending to dither the font with the given color. + The glyph is rendered without any padding or centering in the X + direction, and aligned normally in the Y direction. + This function returns the new surface, or NULL if there was an error. +*/ +extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_Blended(TTF_Font *font, + Uint16 ch, SDL_Color fg); + +/* For compatibility with previous versions, here are the old functions */ +#define TTF_RenderText(font, text, fg, bg) \ + TTF_RenderText_Shaded(font, text, fg, bg) +#define TTF_RenderUTF8(font, text, fg, bg) \ + TTF_RenderUTF8_Shaded(font, text, fg, bg) +#define TTF_RenderUNICODE(font, text, fg, bg) \ + TTF_RenderUNICODE_Shaded(font, text, fg, bg) + +/* Close an opened font file */ +extern DECLSPEC void SDLCALL TTF_CloseFont(TTF_Font *font); + +/* De-initialize the TTF engine */ +extern DECLSPEC void SDLCALL TTF_Quit(void); + +/* Check if the TTF engine is initialized */ +extern DECLSPEC int SDLCALL TTF_WasInit(void); + +/* Get the kerning size of two glyphs */ +extern DECLSPEC int TTF_GetFontKerningSize(TTF_Font *font, int prev_index, int index); + +/* We'll use SDL for reporting errors */ +#define TTF_SetError SDL_SetError +#define TTF_GetError SDL_GetError + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include "close_code.h" + +#endif /* _SDL_TTF_H */ diff --git a/system/include/X11/X.h b/system/include/X11/X.h new file mode 100644 index 00000000..5cf695d7 --- /dev/null +++ b/system/include/X11/X.h @@ -0,0 +1,717 @@ +/* Definitions for the X window system likely to be used by applications */ + +#ifndef X_H +#define X_H + +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +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 +OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, 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. + +******************************************************************/ + +#define X_PROTOCOL 11 /* current protocol version */ +#define X_PROTOCOL_REVISION 0 /* current minor version */ + +/* Resources */ + +/* + * _XSERVER64 must ONLY be defined when compiling X server sources on + * systems where unsigned long is not 32 bits, must NOT be used in + * client or library code. + */ +#ifndef _XSERVER64 +# ifndef _XTYPEDEF_XID +# define _XTYPEDEF_XID +typedef unsigned long XID; +# endif +# ifndef _XTYPEDEF_MASK +# define _XTYPEDEF_MASK +typedef unsigned long Mask; +# endif +# ifndef _XTYPEDEF_ATOM +# define _XTYPEDEF_ATOM +typedef unsigned long Atom; /* Also in Xdefs.h */ +# endif +typedef unsigned long VisualID; +typedef unsigned long Time; +#else +# include <X11/Xmd.h> +# ifndef _XTYPEDEF_XID +# define _XTYPEDEF_XID +typedef CARD32 XID; +# endif +# ifndef _XTYPEDEF_MASK +# define _XTYPEDEF_MASK +typedef CARD32 Mask; +# endif +# ifndef _XTYPEDEF_ATOM +# define _XTYPEDEF_ATOM +typedef CARD32 Atom; +# endif +typedef CARD32 VisualID; +typedef CARD32 Time; +#endif + +typedef XID Window; +typedef XID Drawable; +#ifndef _XTYPEDEF_FONT +# define _XTYPEDEF_FONT +typedef XID Font; +#endif +typedef XID Pixmap; +typedef XID Cursor; +typedef XID Colormap; +typedef XID GContext; +typedef XID KeySym; + +typedef unsigned char KeyCode; + +/***************************************************************** + * RESERVED RESOURCE AND CONSTANT DEFINITIONS + *****************************************************************/ + +#ifndef None +#define None 0L /* universal null resource or null atom */ +#endif + +#define ParentRelative 1L /* background pixmap in CreateWindow + and ChangeWindowAttributes */ + +#define CopyFromParent 0L /* border pixmap in CreateWindow + and ChangeWindowAttributes + special VisualID and special window + class passed to CreateWindow */ + +#define PointerWindow 0L /* destination window in SendEvent */ +#define InputFocus 1L /* destination window in SendEvent */ + +#define PointerRoot 1L /* focus window in SetInputFocus */ + +#define AnyPropertyType 0L /* special Atom, passed to GetProperty */ + +#define AnyKey 0L /* special Key Code, passed to GrabKey */ + +#define AnyButton 0L /* special Button Code, passed to GrabButton */ + +#define AllTemporary 0L /* special Resource ID passed to KillClient */ + +#define CurrentTime 0L /* special Time */ + +#define NoSymbol 0L /* special KeySym */ + +/***************************************************************** + * EVENT DEFINITIONS + *****************************************************************/ + +/* Input Event Masks. Used as event-mask window attribute and as arguments + to Grab requests. Not to be confused with event names. */ + +#define NoEventMask 0L +#define KeyPressMask (1L<<0) +#define KeyReleaseMask (1L<<1) +#define ButtonPressMask (1L<<2) +#define ButtonReleaseMask (1L<<3) +#define EnterWindowMask (1L<<4) +#define LeaveWindowMask (1L<<5) +#define PointerMotionMask (1L<<6) +#define PointerMotionHintMask (1L<<7) +#define Button1MotionMask (1L<<8) +#define Button2MotionMask (1L<<9) +#define Button3MotionMask (1L<<10) +#define Button4MotionMask (1L<<11) +#define Button5MotionMask (1L<<12) +#define ButtonMotionMask (1L<<13) +#define KeymapStateMask (1L<<14) +#define ExposureMask (1L<<15) +#define VisibilityChangeMask (1L<<16) +#define StructureNotifyMask (1L<<17) +#define ResizeRedirectMask (1L<<18) +#define SubstructureNotifyMask (1L<<19) +#define SubstructureRedirectMask (1L<<20) +#define FocusChangeMask (1L<<21) +#define PropertyChangeMask (1L<<22) +#define ColormapChangeMask (1L<<23) +#define OwnerGrabButtonMask (1L<<24) + +/* Event names. Used in "type" field in XEvent structures. Not to be +confused with event masks above. They start from 2 because 0 and 1 +are reserved in the protocol for errors and replies. */ + +#define KeyPress 2 +#define KeyRelease 3 +#define ButtonPress 4 +#define ButtonRelease 5 +#define MotionNotify 6 +#define EnterNotify 7 +#define LeaveNotify 8 +#define FocusIn 9 +#define FocusOut 10 +#define KeymapNotify 11 +#define Expose 12 +#define GraphicsExpose 13 +#define NoExpose 14 +#define VisibilityNotify 15 +#define CreateNotify 16 +#define DestroyNotify 17 +#define UnmapNotify 18 +#define MapNotify 19 +#define MapRequest 20 +#define ReparentNotify 21 +#define ConfigureNotify 22 +#define ConfigureRequest 23 +#define GravityNotify 24 +#define ResizeRequest 25 +#define CirculateNotify 26 +#define CirculateRequest 27 +#define PropertyNotify 28 +#define SelectionClear 29 +#define SelectionRequest 30 +#define SelectionNotify 31 +#define ColormapNotify 32 +#define ClientMessage 33 +#define MappingNotify 34 +#define GenericEvent 35 +#define LASTEvent 36 /* must be bigger than any event # */ + + +/* Key masks. Used as modifiers to GrabButton and GrabKey, results of QueryPointer, + state in various key-, mouse-, and button-related events. */ + +#define ShiftMask (1<<0) +#define LockMask (1<<1) +#define ControlMask (1<<2) +#define Mod1Mask (1<<3) +#define Mod2Mask (1<<4) +#define Mod3Mask (1<<5) +#define Mod4Mask (1<<6) +#define Mod5Mask (1<<7) + +/* modifier names. Used to build a SetModifierMapping request or + to read a GetModifierMapping request. These correspond to the + masks defined above. */ +#define ShiftMapIndex 0 +#define LockMapIndex 1 +#define ControlMapIndex 2 +#define Mod1MapIndex 3 +#define Mod2MapIndex 4 +#define Mod3MapIndex 5 +#define Mod4MapIndex 6 +#define Mod5MapIndex 7 + + +/* button masks. Used in same manner as Key masks above. Not to be confused + with button names below. */ + +#define Button1Mask (1<<8) +#define Button2Mask (1<<9) +#define Button3Mask (1<<10) +#define Button4Mask (1<<11) +#define Button5Mask (1<<12) + +#define AnyModifier (1<<15) /* used in GrabButton, GrabKey */ + + +/* button names. Used as arguments to GrabButton and as detail in ButtonPress + and ButtonRelease events. Not to be confused with button masks above. + Note that 0 is already defined above as "AnyButton". */ + +#define Button1 1 +#define Button2 2 +#define Button3 3 +#define Button4 4 +#define Button5 5 + +/* Notify modes */ + +#define NotifyNormal 0 +#define NotifyGrab 1 +#define NotifyUngrab 2 +#define NotifyWhileGrabbed 3 + +#define NotifyHint 1 /* for MotionNotify events */ + +/* Notify detail */ + +#define NotifyAncestor 0 +#define NotifyVirtual 1 +#define NotifyInferior 2 +#define NotifyNonlinear 3 +#define NotifyNonlinearVirtual 4 +#define NotifyPointer 5 +#define NotifyPointerRoot 6 +#define NotifyDetailNone 7 + +/* Visibility notify */ + +#define VisibilityUnobscured 0 +#define VisibilityPartiallyObscured 1 +#define VisibilityFullyObscured 2 + +/* Circulation request */ + +#define PlaceOnTop 0 +#define PlaceOnBottom 1 + +/* protocol families */ + +#define FamilyInternet 0 /* IPv4 */ +#define FamilyDECnet 1 +#define FamilyChaos 2 +#define FamilyInternet6 6 /* IPv6 */ + +/* authentication families not tied to a specific protocol */ +#define FamilyServerInterpreted 5 + +/* Property notification */ + +#define PropertyNewValue 0 +#define PropertyDelete 1 + +/* Color Map notification */ + +#define ColormapUninstalled 0 +#define ColormapInstalled 1 + +/* GrabPointer, GrabButton, GrabKeyboard, GrabKey Modes */ + +#define GrabModeSync 0 +#define GrabModeAsync 1 + +/* GrabPointer, GrabKeyboard reply status */ + +#define GrabSuccess 0 +#define AlreadyGrabbed 1 +#define GrabInvalidTime 2 +#define GrabNotViewable 3 +#define GrabFrozen 4 + +/* AllowEvents modes */ + +#define AsyncPointer 0 +#define SyncPointer 1 +#define ReplayPointer 2 +#define AsyncKeyboard 3 +#define SyncKeyboard 4 +#define ReplayKeyboard 5 +#define AsyncBoth 6 +#define SyncBoth 7 + +/* Used in SetInputFocus, GetInputFocus */ + +#define RevertToNone (int)None +#define RevertToPointerRoot (int)PointerRoot +#define RevertToParent 2 + +/***************************************************************** + * ERROR CODES + *****************************************************************/ + +#define Success 0 /* everything's okay */ +#define BadRequest 1 /* bad request code */ +#define BadValue 2 /* int parameter out of range */ +#define BadWindow 3 /* parameter not a Window */ +#define BadPixmap 4 /* parameter not a Pixmap */ +#define BadAtom 5 /* parameter not an Atom */ +#define BadCursor 6 /* parameter not a Cursor */ +#define BadFont 7 /* parameter not a Font */ +#define BadMatch 8 /* parameter mismatch */ +#define BadDrawable 9 /* parameter not a Pixmap or Window */ +#define BadAccess 10 /* depending on context: + - key/button already grabbed + - attempt to free an illegal + cmap entry + - attempt to store into a read-only + color map entry. + - attempt to modify the access control + list from other than the local host. + */ +#define BadAlloc 11 /* insufficient resources */ +#define BadColor 12 /* no such colormap */ +#define BadGC 13 /* parameter not a GC */ +#define BadIDChoice 14 /* choice not in range or already used */ +#define BadName 15 /* font or color name doesn't exist */ +#define BadLength 16 /* Request length incorrect */ +#define BadImplementation 17 /* server is defective */ + +#define FirstExtensionError 128 +#define LastExtensionError 255 + +/***************************************************************** + * WINDOW DEFINITIONS + *****************************************************************/ + +/* Window classes used by CreateWindow */ +/* Note that CopyFromParent is already defined as 0 above */ + +#define InputOutput 1 +#define InputOnly 2 + +/* Window attributes for CreateWindow and ChangeWindowAttributes */ + +#define CWBackPixmap (1L<<0) +#define CWBackPixel (1L<<1) +#define CWBorderPixmap (1L<<2) +#define CWBorderPixel (1L<<3) +#define CWBitGravity (1L<<4) +#define CWWinGravity (1L<<5) +#define CWBackingStore (1L<<6) +#define CWBackingPlanes (1L<<7) +#define CWBackingPixel (1L<<8) +#define CWOverrideRedirect (1L<<9) +#define CWSaveUnder (1L<<10) +#define CWEventMask (1L<<11) +#define CWDontPropagate (1L<<12) +#define CWColormap (1L<<13) +#define CWCursor (1L<<14) + +/* ConfigureWindow structure */ + +#define CWX (1<<0) +#define CWY (1<<1) +#define CWWidth (1<<2) +#define CWHeight (1<<3) +#define CWBorderWidth (1<<4) +#define CWSibling (1<<5) +#define CWStackMode (1<<6) + + +/* Bit Gravity */ + +#define ForgetGravity 0 +#define NorthWestGravity 1 +#define NorthGravity 2 +#define NorthEastGravity 3 +#define WestGravity 4 +#define CenterGravity 5 +#define EastGravity 6 +#define SouthWestGravity 7 +#define SouthGravity 8 +#define SouthEastGravity 9 +#define StaticGravity 10 + +/* Window gravity + bit gravity above */ + +#define UnmapGravity 0 + +/* Used in CreateWindow for backing-store hint */ + +#define NotUseful 0 +#define WhenMapped 1 +#define Always 2 + +/* Used in GetWindowAttributes reply */ + +#define IsUnmapped 0 +#define IsUnviewable 1 +#define IsViewable 2 + +/* Used in ChangeSaveSet */ + +#define SetModeInsert 0 +#define SetModeDelete 1 + +/* Used in ChangeCloseDownMode */ + +#define DestroyAll 0 +#define RetainPermanent 1 +#define RetainTemporary 2 + +/* Window stacking method (in configureWindow) */ + +#define Above 0 +#define Below 1 +#define TopIf 2 +#define BottomIf 3 +#define Opposite 4 + +/* Circulation direction */ + +#define RaiseLowest 0 +#define LowerHighest 1 + +/* Property modes */ + +#define PropModeReplace 0 +#define PropModePrepend 1 +#define PropModeAppend 2 + +/***************************************************************** + * GRAPHICS DEFINITIONS + *****************************************************************/ + +/* graphics functions, as in GC.alu */ + +#define GXclear 0x0 /* 0 */ +#define GXand 0x1 /* src AND dst */ +#define GXandReverse 0x2 /* src AND NOT dst */ +#define GXcopy 0x3 /* src */ +#define GXandInverted 0x4 /* NOT src AND dst */ +#define GXnoop 0x5 /* dst */ +#define GXxor 0x6 /* src XOR dst */ +#define GXor 0x7 /* src OR dst */ +#define GXnor 0x8 /* NOT src AND NOT dst */ +#define GXequiv 0x9 /* NOT src XOR dst */ +#define GXinvert 0xa /* NOT dst */ +#define GXorReverse 0xb /* src OR NOT dst */ +#define GXcopyInverted 0xc /* NOT src */ +#define GXorInverted 0xd /* NOT src OR dst */ +#define GXnand 0xe /* NOT src OR NOT dst */ +#define GXset 0xf /* 1 */ + +/* LineStyle */ + +#define LineSolid 0 +#define LineOnOffDash 1 +#define LineDoubleDash 2 + +/* capStyle */ + +#define CapNotLast 0 +#define CapButt 1 +#define CapRound 2 +#define CapProjecting 3 + +/* joinStyle */ + +#define JoinMiter 0 +#define JoinRound 1 +#define JoinBevel 2 + +/* fillStyle */ + +#define FillSolid 0 +#define FillTiled 1 +#define FillStippled 2 +#define FillOpaqueStippled 3 + +/* fillRule */ + +#define EvenOddRule 0 +#define WindingRule 1 + +/* subwindow mode */ + +#define ClipByChildren 0 +#define IncludeInferiors 1 + +/* SetClipRectangles ordering */ + +#define Unsorted 0 +#define YSorted 1 +#define YXSorted 2 +#define YXBanded 3 + +/* CoordinateMode for drawing routines */ + +#define CoordModeOrigin 0 /* relative to the origin */ +#define CoordModePrevious 1 /* relative to previous point */ + +/* Polygon shapes */ + +#define Complex 0 /* paths may intersect */ +#define Nonconvex 1 /* no paths intersect, but not convex */ +#define Convex 2 /* wholly convex */ + +/* Arc modes for PolyFillArc */ + +#define ArcChord 0 /* join endpoints of arc */ +#define ArcPieSlice 1 /* join endpoints to center of arc */ + +/* GC components: masks used in CreateGC, CopyGC, ChangeGC, OR'ed into + GC.stateChanges */ + +#define GCFunction (1L<<0) +#define GCPlaneMask (1L<<1) +#define GCForeground (1L<<2) +#define GCBackground (1L<<3) +#define GCLineWidth (1L<<4) +#define GCLineStyle (1L<<5) +#define GCCapStyle (1L<<6) +#define GCJoinStyle (1L<<7) +#define GCFillStyle (1L<<8) +#define GCFillRule (1L<<9) +#define GCTile (1L<<10) +#define GCStipple (1L<<11) +#define GCTileStipXOrigin (1L<<12) +#define GCTileStipYOrigin (1L<<13) +#define GCFont (1L<<14) +#define GCSubwindowMode (1L<<15) +#define GCGraphicsExposures (1L<<16) +#define GCClipXOrigin (1L<<17) +#define GCClipYOrigin (1L<<18) +#define GCClipMask (1L<<19) +#define GCDashOffset (1L<<20) +#define GCDashList (1L<<21) +#define GCArcMode (1L<<22) + +#define GCLastBit 22 +/***************************************************************** + * FONTS + *****************************************************************/ + +/* used in QueryFont -- draw direction */ + +#define FontLeftToRight 0 +#define FontRightToLeft 1 + +#define FontChange 255 + +/***************************************************************** + * IMAGING + *****************************************************************/ + +/* ImageFormat -- PutImage, GetImage */ + +#define XYBitmap 0 /* depth 1, XYFormat */ +#define XYPixmap 1 /* depth == drawable depth */ +#define ZPixmap 2 /* depth == drawable depth */ + +/***************************************************************** + * COLOR MAP STUFF + *****************************************************************/ + +/* For CreateColormap */ + +#define AllocNone 0 /* create map with no entries */ +#define AllocAll 1 /* allocate entire map writeable */ + + +/* Flags used in StoreNamedColor, StoreColors */ + +#define DoRed (1<<0) +#define DoGreen (1<<1) +#define DoBlue (1<<2) + +/***************************************************************** + * CURSOR STUFF + *****************************************************************/ + +/* QueryBestSize Class */ + +#define CursorShape 0 /* largest size that can be displayed */ +#define TileShape 1 /* size tiled fastest */ +#define StippleShape 2 /* size stippled fastest */ + +/***************************************************************** + * KEYBOARD/POINTER STUFF + *****************************************************************/ + +#define AutoRepeatModeOff 0 +#define AutoRepeatModeOn 1 +#define AutoRepeatModeDefault 2 + +#define LedModeOff 0 +#define LedModeOn 1 + +/* masks for ChangeKeyboardControl */ + +#define KBKeyClickPercent (1L<<0) +#define KBBellPercent (1L<<1) +#define KBBellPitch (1L<<2) +#define KBBellDuration (1L<<3) +#define KBLed (1L<<4) +#define KBLedMode (1L<<5) +#define KBKey (1L<<6) +#define KBAutoRepeatMode (1L<<7) + +#define MappingSuccess 0 +#define MappingBusy 1 +#define MappingFailed 2 + +#define MappingModifier 0 +#define MappingKeyboard 1 +#define MappingPointer 2 + +/***************************************************************** + * SCREEN SAVER STUFF + *****************************************************************/ + +#define DontPreferBlanking 0 +#define PreferBlanking 1 +#define DefaultBlanking 2 + +#define DisableScreenSaver 0 +#define DisableScreenInterval 0 + +#define DontAllowExposures 0 +#define AllowExposures 1 +#define DefaultExposures 2 + +/* for ForceScreenSaver */ + +#define ScreenSaverReset 0 +#define ScreenSaverActive 1 + +/***************************************************************** + * HOSTS AND CONNECTIONS + *****************************************************************/ + +/* for ChangeHosts */ + +#define HostInsert 0 +#define HostDelete 1 + +/* for ChangeAccessControl */ + +#define EnableAccess 1 +#define DisableAccess 0 + +/* Display classes used in opening the connection + * Note that the statically allocated ones are even numbered and the + * dynamically changeable ones are odd numbered */ + +#define StaticGray 0 +#define GrayScale 1 +#define StaticColor 2 +#define PseudoColor 3 +#define TrueColor 4 +#define DirectColor 5 + + +/* Byte order used in imageByteOrder and bitmapBitOrder */ + +#define LSBFirst 0 +#define MSBFirst 1 + +#endif /* X_H */ diff --git a/system/include/X11/Xatom.h b/system/include/X11/Xatom.h new file mode 100644 index 00000000..485a4236 --- /dev/null +++ b/system/include/X11/Xatom.h @@ -0,0 +1,79 @@ +#ifndef XATOM_H +#define XATOM_H 1 + +/* THIS IS A GENERATED FILE + * + * Do not change! Changing this file implies a protocol change! + */ + +#define XA_PRIMARY ((Atom) 1) +#define XA_SECONDARY ((Atom) 2) +#define XA_ARC ((Atom) 3) +#define XA_ATOM ((Atom) 4) +#define XA_BITMAP ((Atom) 5) +#define XA_CARDINAL ((Atom) 6) +#define XA_COLORMAP ((Atom) 7) +#define XA_CURSOR ((Atom) 8) +#define XA_CUT_BUFFER0 ((Atom) 9) +#define XA_CUT_BUFFER1 ((Atom) 10) +#define XA_CUT_BUFFER2 ((Atom) 11) +#define XA_CUT_BUFFER3 ((Atom) 12) +#define XA_CUT_BUFFER4 ((Atom) 13) +#define XA_CUT_BUFFER5 ((Atom) 14) +#define XA_CUT_BUFFER6 ((Atom) 15) +#define XA_CUT_BUFFER7 ((Atom) 16) +#define XA_DRAWABLE ((Atom) 17) +#define XA_FONT ((Atom) 18) +#define XA_INTEGER ((Atom) 19) +#define XA_PIXMAP ((Atom) 20) +#define XA_POINT ((Atom) 21) +#define XA_RECTANGLE ((Atom) 22) +#define XA_RESOURCE_MANAGER ((Atom) 23) +#define XA_RGB_COLOR_MAP ((Atom) 24) +#define XA_RGB_BEST_MAP ((Atom) 25) +#define XA_RGB_BLUE_MAP ((Atom) 26) +#define XA_RGB_DEFAULT_MAP ((Atom) 27) +#define XA_RGB_GRAY_MAP ((Atom) 28) +#define XA_RGB_GREEN_MAP ((Atom) 29) +#define XA_RGB_RED_MAP ((Atom) 30) +#define XA_STRING ((Atom) 31) +#define XA_VISUALID ((Atom) 32) +#define XA_WINDOW ((Atom) 33) +#define XA_WM_COMMAND ((Atom) 34) +#define XA_WM_HINTS ((Atom) 35) +#define XA_WM_CLIENT_MACHINE ((Atom) 36) +#define XA_WM_ICON_NAME ((Atom) 37) +#define XA_WM_ICON_SIZE ((Atom) 38) +#define XA_WM_NAME ((Atom) 39) +#define XA_WM_NORMAL_HINTS ((Atom) 40) +#define XA_WM_SIZE_HINTS ((Atom) 41) +#define XA_WM_ZOOM_HINTS ((Atom) 42) +#define XA_MIN_SPACE ((Atom) 43) +#define XA_NORM_SPACE ((Atom) 44) +#define XA_MAX_SPACE ((Atom) 45) +#define XA_END_SPACE ((Atom) 46) +#define XA_SUPERSCRIPT_X ((Atom) 47) +#define XA_SUPERSCRIPT_Y ((Atom) 48) +#define XA_SUBSCRIPT_X ((Atom) 49) +#define XA_SUBSCRIPT_Y ((Atom) 50) +#define XA_UNDERLINE_POSITION ((Atom) 51) +#define XA_UNDERLINE_THICKNESS ((Atom) 52) +#define XA_STRIKEOUT_ASCENT ((Atom) 53) +#define XA_STRIKEOUT_DESCENT ((Atom) 54) +#define XA_ITALIC_ANGLE ((Atom) 55) +#define XA_X_HEIGHT ((Atom) 56) +#define XA_QUAD_WIDTH ((Atom) 57) +#define XA_WEIGHT ((Atom) 58) +#define XA_POINT_SIZE ((Atom) 59) +#define XA_RESOLUTION ((Atom) 60) +#define XA_COPYRIGHT ((Atom) 61) +#define XA_NOTICE ((Atom) 62) +#define XA_FONT_NAME ((Atom) 63) +#define XA_FAMILY_NAME ((Atom) 64) +#define XA_FULL_NAME ((Atom) 65) +#define XA_CAP_HEIGHT ((Atom) 66) +#define XA_WM_CLASS ((Atom) 67) +#define XA_WM_TRANSIENT_FOR ((Atom) 68) + +#define XA_LAST_PREDEFINED ((Atom) 68) +#endif /* XATOM_H */ diff --git a/system/include/X11/Xfuncproto.h b/system/include/X11/Xfuncproto.h new file mode 100644 index 00000000..b5b572a3 --- /dev/null +++ b/system/include/X11/Xfuncproto.h @@ -0,0 +1,127 @@ +/* Xfuncproto.h. Generated from Xfuncproto.h.in by configure. */ +/* + * +Copyright 1989, 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +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 +OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + */ + +/* Definitions to make function prototypes manageable */ + +#ifndef _XFUNCPROTO_H_ +#define _XFUNCPROTO_H_ + +#ifndef NeedFunctionPrototypes +#define NeedFunctionPrototypes 1 +#endif /* NeedFunctionPrototypes */ + +#ifndef NeedVarargsPrototypes +#define NeedVarargsPrototypes 1 +#endif /* NeedVarargsPrototypes */ + +#if NeedFunctionPrototypes + +#ifndef NeedNestedPrototypes +#define NeedNestedPrototypes 1 +#endif /* NeedNestedPrototypes */ + +#ifndef _Xconst +#define _Xconst const +#endif /* _Xconst */ + +/* Function prototype configuration (see configure for more info) */ +#ifndef NARROWPROTO +#define NARROWPROTO /**/ +#endif +#ifndef FUNCPROTO +#define FUNCPROTO 15 +#endif + +#ifndef NeedWidePrototypes +#ifdef NARROWPROTO +#define NeedWidePrototypes 0 +#else +#define NeedWidePrototypes 1 /* default to make interropt. easier */ +#endif +#endif /* NeedWidePrototypes */ + +#endif /* NeedFunctionPrototypes */ + +#ifndef _XFUNCPROTOBEGIN +#if defined(__cplusplus) || defined(c_plusplus) /* for C++ V2.0 */ +#define _XFUNCPROTOBEGIN extern "C" { /* do not leave open across includes */ +#define _XFUNCPROTOEND } +#else +#define _XFUNCPROTOBEGIN +#define _XFUNCPROTOEND +#endif +#endif /* _XFUNCPROTOBEGIN */ + +#if defined(__GNUC__) && (__GNUC__ >= 4) +# define _X_SENTINEL(x) __attribute__ ((__sentinel__(x))) +# define _X_ATTRIBUTE_PRINTF(x,y) __attribute__((__format__(__printf__,x,y))) +#else +# define _X_SENTINEL(x) +# define _X_ATTRIBUTE_PRINTF(x,y) +#endif /* GNUC >= 4 */ + +#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__CYGWIN__) +# define _X_EXPORT __attribute__((visibility("default"))) +# define _X_HIDDEN __attribute__((visibility("hidden"))) +# define _X_INTERNAL __attribute__((visibility("internal"))) +#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) +# define _X_EXPORT __global +# define _X_HIDDEN __hidden +# define _X_INTERNAL __hidden +#else /* not gcc >= 4 and not Sun Studio >= 8 */ +# define _X_EXPORT +# define _X_HIDDEN +# define _X_INTERNAL +#endif /* GNUC >= 4 */ + +#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 303) +# define _X_LIKELY(x) __builtin_expect(!!(x), 1) +# define _X_UNLIKELY(x) __builtin_expect(!!(x), 0) +# define _X_INLINE inline +#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) +# define _X_LIKELY(x) (x) +# define _X_UNLIKELY(x) (x) +# define _X_INLINE inline +#else /* not gcc >= 3.3 and not Sun Studio >= 8 */ +# define _X_LIKELY(x) (x) +# define _X_UNLIKELY(x) (x) +# define _X_INLINE +#endif + +#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 301) +# define _X_DEPRECATED __attribute__((deprecated)) +#else /* not gcc >= 3.1 */ +# define _X_DEPRECATED +#endif + +#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205) +# define _X_NORETURN __attribute((noreturn)) +#else +# define _X_NORETURN +#endif /* GNUC */ + +#endif /* _XFUNCPROTO_H_ */ diff --git a/system/include/X11/Xlib.h b/system/include/X11/Xlib.h new file mode 100644 index 00000000..7c8bc515 --- /dev/null +++ b/system/include/X11/Xlib.h @@ -0,0 +1,4023 @@ +/* + +Copyright 1985, 1986, 1987, 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +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 +OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + + +/* + * Xlib.h - Header definition and support file for the C subroutine + * interface library (Xlib) to the X Window System Protocol (V11). + * Structures and symbols starting with "_" are private to the library. + */ +#ifndef _XLIB_H_ +#define _XLIB_H_ + +#define XlibSpecificationRelease 6 + +#include <sys/types.h> + +#if defined(__SCO__) || defined(__UNIXWARE__) +#include <stdint.h> +#endif + +#include <X11/X.h> + +/* applications should not depend on these two headers being included! */ +#include <X11/Xfuncproto.h> +#include <X11/Xosdefs.h> + +#ifndef X_WCHAR +#include <stddef.h> +#else +#ifdef __UNIXOS2__ +#include <stdlib.h> +#else +/* replace this with #include or typedef appropriate for your system */ +typedef unsigned long wchar_t; +#endif +#endif + +#if defined(ISC) && defined(USE_XMBTOWC) +#define wctomb(a,b) _Xwctomb(a,b) +#define mblen(a,b) _Xmblen(a,b) +#ifndef USE_XWCHAR_STRING +#define mbtowc(a,b,c) _Xmbtowc(a,b,c) +#endif +#endif + +extern int +_Xmblen( +#ifdef ISC + char const *str, + size_t len +#else + char *str, + int len +#endif + ); + +/* API mentioning "UTF8" or "utf8" is an XFree86 extension, introduced in + November 2000. Its presence is indicated through the following macro. */ +#define X_HAVE_UTF8_STRING 1 + +typedef char *XPointer; + +#define Bool int +#define Status int +#define True 1 +#define False 0 + +#define QueuedAlready 0 +#define QueuedAfterReading 1 +#define QueuedAfterFlush 2 + +#define ConnectionNumber(dpy) (((_XPrivDisplay)dpy)->fd) +#define RootWindow(dpy, scr) (ScreenOfDisplay(dpy,scr)->root) +#define DefaultScreen(dpy) (((_XPrivDisplay)dpy)->default_screen) +#define DefaultRootWindow(dpy) (ScreenOfDisplay(dpy,DefaultScreen(dpy))->root) +#define DefaultVisual(dpy, scr) (ScreenOfDisplay(dpy,scr)->root_visual) +#define DefaultGC(dpy, scr) (ScreenOfDisplay(dpy,scr)->default_gc) +#define BlackPixel(dpy, scr) (ScreenOfDisplay(dpy,scr)->black_pixel) +#define WhitePixel(dpy, scr) (ScreenOfDisplay(dpy,scr)->white_pixel) +#define AllPlanes ((unsigned long)~0L) +#define QLength(dpy) (((_XPrivDisplay)dpy)->qlen) +#define DisplayWidth(dpy, scr) (ScreenOfDisplay(dpy,scr)->width) +#define DisplayHeight(dpy, scr) (ScreenOfDisplay(dpy,scr)->height) +#define DisplayWidthMM(dpy, scr)(ScreenOfDisplay(dpy,scr)->mwidth) +#define DisplayHeightMM(dpy, scr)(ScreenOfDisplay(dpy,scr)->mheight) +#define DisplayPlanes(dpy, scr) (ScreenOfDisplay(dpy,scr)->root_depth) +#define DisplayCells(dpy, scr) (DefaultVisual(dpy,scr)->map_entries) +#define ScreenCount(dpy) (((_XPrivDisplay)dpy)->nscreens) +#define ServerVendor(dpy) (((_XPrivDisplay)dpy)->vendor) +#define ProtocolVersion(dpy) (((_XPrivDisplay)dpy)->proto_major_version) +#define ProtocolRevision(dpy) (((_XPrivDisplay)dpy)->proto_minor_version) +#define VendorRelease(dpy) (((_XPrivDisplay)dpy)->release) +#define DisplayString(dpy) (((_XPrivDisplay)dpy)->display_name) +#define DefaultDepth(dpy, scr) (ScreenOfDisplay(dpy,scr)->root_depth) +#define DefaultColormap(dpy, scr)(ScreenOfDisplay(dpy,scr)->cmap) +#define BitmapUnit(dpy) (((_XPrivDisplay)dpy)->bitmap_unit) +#define BitmapBitOrder(dpy) (((_XPrivDisplay)dpy)->bitmap_bit_order) +#define BitmapPad(dpy) (((_XPrivDisplay)dpy)->bitmap_pad) +#define ImageByteOrder(dpy) (((_XPrivDisplay)dpy)->byte_order) +#ifdef CRAY /* unable to get WORD64 without pulling in other symbols */ +#define NextRequest(dpy) XNextRequest(dpy) +#else +#define NextRequest(dpy) (((_XPrivDisplay)dpy)->request + 1) +#endif +#define LastKnownRequestProcessed(dpy) (((_XPrivDisplay)dpy)->last_request_read) + +/* macros for screen oriented applications (toolkit) */ +#define ScreenOfDisplay(dpy, scr)(&((_XPrivDisplay)dpy)->screens[scr]) +#define DefaultScreenOfDisplay(dpy) ScreenOfDisplay(dpy,DefaultScreen(dpy)) +#define DisplayOfScreen(s) ((s)->display) +#define RootWindowOfScreen(s) ((s)->root) +#define BlackPixelOfScreen(s) ((s)->black_pixel) +#define WhitePixelOfScreen(s) ((s)->white_pixel) +#define DefaultColormapOfScreen(s)((s)->cmap) +#define DefaultDepthOfScreen(s) ((s)->root_depth) +#define DefaultGCOfScreen(s) ((s)->default_gc) +#define DefaultVisualOfScreen(s)((s)->root_visual) +#define WidthOfScreen(s) ((s)->width) +#define HeightOfScreen(s) ((s)->height) +#define WidthMMOfScreen(s) ((s)->mwidth) +#define HeightMMOfScreen(s) ((s)->mheight) +#define PlanesOfScreen(s) ((s)->root_depth) +#define CellsOfScreen(s) (DefaultVisualOfScreen((s))->map_entries) +#define MinCmapsOfScreen(s) ((s)->min_maps) +#define MaxCmapsOfScreen(s) ((s)->max_maps) +#define DoesSaveUnders(s) ((s)->save_unders) +#define DoesBackingStore(s) ((s)->backing_store) +#define EventMaskOfScreen(s) ((s)->root_input_mask) + +/* + * Extensions need a way to hang private data on some structures. + */ +typedef struct _XExtData { + int number; /* number returned by XRegisterExtension */ + struct _XExtData *next; /* next item on list of data for structure */ + int (*free_private)( /* called to free private storage */ + struct _XExtData *extension + ); + XPointer private_data; /* data private to this extension. */ +} XExtData; + +/* + * This file contains structures used by the extension mechanism. + */ +typedef struct { /* public to extension, cannot be changed */ + int extension; /* extension number */ + int major_opcode; /* major op-code assigned by server */ + int first_event; /* first event number for the extension */ + int first_error; /* first error number for the extension */ +} XExtCodes; + +/* + * Data structure for retrieving info about pixmap formats. + */ + +typedef struct { + int depth; + int bits_per_pixel; + int scanline_pad; +} XPixmapFormatValues; + + +/* + * Data structure for setting graphics context. + */ +typedef struct { + int function; /* logical operation */ + unsigned long plane_mask;/* plane mask */ + unsigned long foreground;/* foreground pixel */ + unsigned long background;/* background pixel */ + int line_width; /* line width */ + int line_style; /* LineSolid, LineOnOffDash, LineDoubleDash */ + int cap_style; /* CapNotLast, CapButt, + CapRound, CapProjecting */ + int join_style; /* JoinMiter, JoinRound, JoinBevel */ + int fill_style; /* FillSolid, FillTiled, + FillStippled, FillOpaeueStippled */ + int fill_rule; /* EvenOddRule, WindingRule */ + int arc_mode; /* ArcChord, ArcPieSlice */ + Pixmap tile; /* tile pixmap for tiling operations */ + Pixmap stipple; /* stipple 1 plane pixmap for stipping */ + int ts_x_origin; /* offset for tile or stipple operations */ + int ts_y_origin; + Font font; /* default text font for text operations */ + int subwindow_mode; /* ClipByChildren, IncludeInferiors */ + Bool graphics_exposures;/* boolean, should exposures be generated */ + int clip_x_origin; /* origin for clipping */ + int clip_y_origin; + Pixmap clip_mask; /* bitmap clipping; other calls for rects */ + int dash_offset; /* patterned/dashed line information */ + char dashes; +} XGCValues; + +/* + * Graphics context. The contents of this structure are implementation + * dependent. A GC should be treated as opaque by application code. + */ + +typedef struct _XGC +#ifdef XLIB_ILLEGAL_ACCESS +{ + XExtData *ext_data; /* hook for extension to hang data */ + GContext gid; /* protocol ID for graphics context */ + /* there is more to this structure, but it is private to Xlib */ +} +#endif +*GC; + +/* + * Visual structure; contains information about colormapping possible. + */ +typedef struct { + XExtData *ext_data; /* hook for extension to hang data */ + VisualID visualid; /* visual id of this visual */ +#if defined(__cplusplus) || defined(c_plusplus) + int c_class; /* C++ class of screen (monochrome, etc.) */ +#else + int class; /* class of screen (monochrome, etc.) */ +#endif + unsigned long red_mask, green_mask, blue_mask; /* mask values */ + int bits_per_rgb; /* log base 2 of distinct color values */ + int map_entries; /* color map entries */ +} Visual; + +/* + * Depth structure; contains information for each possible depth. + */ +typedef struct { + int depth; /* this depth (Z) of the depth */ + int nvisuals; /* number of Visual types at this depth */ + Visual *visuals; /* list of visuals possible at this depth */ +} Depth; + +/* + * Information about the screen. The contents of this structure are + * implementation dependent. A Screen should be treated as opaque + * by application code. + */ + +struct _XDisplay; /* Forward declare before use for C++ */ + +typedef struct { + XExtData *ext_data; /* hook for extension to hang data */ + struct _XDisplay *display;/* back pointer to display structure */ + Window root; /* Root window id. */ + int width, height; /* width and height of screen */ + int mwidth, mheight; /* width and height of in millimeters */ + int ndepths; /* number of depths possible */ + Depth *depths; /* list of allowable depths on the screen */ + int root_depth; /* bits per pixel */ + Visual *root_visual; /* root visual */ + GC default_gc; /* GC for the root root visual */ + Colormap cmap; /* default color map */ + unsigned long white_pixel; + unsigned long black_pixel; /* White and Black pixel values */ + int max_maps, min_maps; /* max and min color maps */ + int backing_store; /* Never, WhenMapped, Always */ + Bool save_unders; + long root_input_mask; /* initial root input mask */ +} Screen; + +/* + * Format structure; describes ZFormat data the screen will understand. + */ +typedef struct { + XExtData *ext_data; /* hook for extension to hang data */ + int depth; /* depth of this image format */ + int bits_per_pixel; /* bits/pixel at this depth */ + int scanline_pad; /* scanline must padded to this multiple */ +} ScreenFormat; + +/* + * Data structure for setting window attributes. + */ +typedef struct { + Pixmap background_pixmap; /* background or None or ParentRelative */ + unsigned long background_pixel; /* background pixel */ + Pixmap border_pixmap; /* border of the window */ + unsigned long border_pixel; /* border pixel value */ + int bit_gravity; /* one of bit gravity values */ + int win_gravity; /* one of the window gravity values */ + int backing_store; /* NotUseful, WhenMapped, Always */ + unsigned long backing_planes;/* planes to be preseved if possible */ + unsigned long backing_pixel;/* value to use in restoring planes */ + Bool save_under; /* should bits under be saved? (popups) */ + long event_mask; /* set of events that should be saved */ + long do_not_propagate_mask; /* set of events that should not propagate */ + Bool override_redirect; /* boolean value for override-redirect */ + Colormap colormap; /* color map to be associated with window */ + Cursor cursor; /* cursor to be displayed (or None) */ +} XSetWindowAttributes; + +typedef struct { + int x, y; /* location of window */ + int width, height; /* width and height of window */ + int border_width; /* border width of window */ + int depth; /* depth of window */ + Visual *visual; /* the associated visual structure */ + Window root; /* root of screen containing window */ +#if defined(__cplusplus) || defined(c_plusplus) + int c_class; /* C++ InputOutput, InputOnly*/ +#else + int class; /* InputOutput, InputOnly*/ +#endif + int bit_gravity; /* one of bit gravity values */ + int win_gravity; /* one of the window gravity values */ + int backing_store; /* NotUseful, WhenMapped, Always */ + unsigned long backing_planes;/* planes to be preserved if possible */ + unsigned long backing_pixel;/* value to be used when restoring planes */ + Bool save_under; /* boolean, should bits under be saved? */ + Colormap colormap; /* color map to be associated with window */ + Bool map_installed; /* boolean, is color map currently installed*/ + int map_state; /* IsUnmapped, IsUnviewable, IsViewable */ + long all_event_masks; /* set of events all people have interest in*/ + long your_event_mask; /* my event mask */ + long do_not_propagate_mask; /* set of events that should not propagate */ + Bool override_redirect; /* boolean value for override-redirect */ + Screen *screen; /* back pointer to correct screen */ +} XWindowAttributes; + +/* + * Data structure for host setting; getting routines. + * + */ + +typedef struct { + int family; /* for example FamilyInternet */ + int length; /* length of address, in bytes */ + char *address; /* pointer to where to find the bytes */ +} XHostAddress; + +/* + * Data structure for ServerFamilyInterpreted addresses in host routines + */ +typedef struct { + int typelength; /* length of type string, in bytes */ + int valuelength; /* length of value string, in bytes */ + char *type; /* pointer to where to find the type string */ + char *value; /* pointer to where to find the address */ +} XServerInterpretedAddress; + +/* + * Data structure for "image" data, used by image manipulation routines. + */ +typedef struct _XImage { + int width, height; /* size of image */ + int xoffset; /* number of pixels offset in X direction */ + int format; /* XYBitmap, XYPixmap, ZPixmap */ + char *data; /* pointer to image data */ + int byte_order; /* data byte order, LSBFirst, MSBFirst */ + int bitmap_unit; /* quant. of scanline 8, 16, 32 */ + int bitmap_bit_order; /* LSBFirst, MSBFirst */ + int bitmap_pad; /* 8, 16, 32 either XY or ZPixmap */ + int depth; /* depth of image */ + int bytes_per_line; /* accelarator to next line */ + int bits_per_pixel; /* bits per pixel (ZPixmap) */ + unsigned long red_mask; /* bits in z arrangment */ + unsigned long green_mask; + unsigned long blue_mask; + XPointer obdata; /* hook for the object routines to hang on */ + struct funcs { /* image manipulation routines */ + struct _XImage *(*create_image)( + struct _XDisplay* /* display */, + Visual* /* visual */, + unsigned int /* depth */, + int /* format */, + int /* offset */, + char* /* data */, + unsigned int /* width */, + unsigned int /* height */, + int /* bitmap_pad */, + int /* bytes_per_line */); + int (*destroy_image) (struct _XImage *); + unsigned long (*get_pixel) (struct _XImage *, int, int); + int (*put_pixel) (struct _XImage *, int, int, unsigned long); + struct _XImage *(*sub_image)(struct _XImage *, int, int, unsigned int, unsigned int); + int (*add_pixel) (struct _XImage *, long); + } f; +} XImage; + +/* + * Data structure for XReconfigureWindow + */ +typedef struct { + int x, y; + int width, height; + int border_width; + Window sibling; + int stack_mode; +} XWindowChanges; + +/* + * Data structure used by color operations + */ +typedef struct { + unsigned long pixel; + unsigned short red, green, blue; + char flags; /* do_red, do_green, do_blue */ + char pad; +} XColor; + +/* + * Data structures for graphics operations. On most machines, these are + * congruent with the wire protocol structures, so reformatting the data + * can be avoided on these architectures. + */ +typedef struct { + short x1, y1, x2, y2; +} XSegment; + +typedef struct { + short x, y; +} XPoint; + +typedef struct { + short x, y; + unsigned short width, height; +} XRectangle; + +typedef struct { + short x, y; + unsigned short width, height; + short angle1, angle2; +} XArc; + + +/* Data structure for XChangeKeyboardControl */ + +typedef struct { + int key_click_percent; + int bell_percent; + int bell_pitch; + int bell_duration; + int led; + int led_mode; + int key; + int auto_repeat_mode; /* On, Off, Default */ +} XKeyboardControl; + +/* Data structure for XGetKeyboardControl */ + +typedef struct { + int key_click_percent; + int bell_percent; + unsigned int bell_pitch, bell_duration; + unsigned long led_mask; + int global_auto_repeat; + char auto_repeats[32]; +} XKeyboardState; + +/* Data structure for XGetMotionEvents. */ + +typedef struct { + Time time; + short x, y; +} XTimeCoord; + +/* Data structure for X{Set,Get}ModifierMapping */ + +typedef struct { + int max_keypermod; /* The server's max # of keys per modifier */ + KeyCode *modifiermap; /* An 8 by max_keypermod array of modifiers */ +} XModifierKeymap; + + +/* + * Display datatype maintaining display specific data. + * The contents of this structure are implementation dependent. + * A Display should be treated as opaque by application code. + */ +#ifndef XLIB_ILLEGAL_ACCESS +typedef struct _XDisplay Display; +#endif + +struct _XPrivate; /* Forward declare before use for C++ */ +struct _XrmHashBucketRec; + +typedef struct +#ifdef XLIB_ILLEGAL_ACCESS +_XDisplay +#endif +{ + XExtData *ext_data; /* hook for extension to hang data */ + struct _XPrivate *private1; + int fd; /* Network socket. */ + int private2; + int proto_major_version;/* major version of server's X protocol */ + int proto_minor_version;/* minor version of servers X protocol */ + char *vendor; /* vendor of the server hardware */ + XID private3; + XID private4; + XID private5; + int private6; + XID (*resource_alloc)( /* allocator function */ + struct _XDisplay* + ); + int byte_order; /* screen byte order, LSBFirst, MSBFirst */ + int bitmap_unit; /* padding and data requirements */ + int bitmap_pad; /* padding requirements on bitmaps */ + int bitmap_bit_order; /* LeastSignificant or MostSignificant */ + int nformats; /* number of pixmap formats in list */ + ScreenFormat *pixmap_format; /* pixmap format list */ + int private8; + int release; /* release of the server */ + struct _XPrivate *private9, *private10; + int qlen; /* Length of input event queue */ + unsigned long last_request_read; /* seq number of last event read */ + unsigned long request; /* sequence number of last request. */ + XPointer private11; + XPointer private12; + XPointer private13; + XPointer private14; + unsigned max_request_size; /* maximum number 32 bit words in request*/ + struct _XrmHashBucketRec *db; + int (*private15)( + struct _XDisplay* + ); + char *display_name; /* "host:display" string used on this connect*/ + int default_screen; /* default screen for operations */ + int nscreens; /* number of screens on this server*/ + Screen *screens; /* pointer to list of screens */ + unsigned long motion_buffer; /* size of motion buffer */ + unsigned long private16; + int min_keycode; /* minimum defined keycode */ + int max_keycode; /* maximum defined keycode */ + XPointer private17; + XPointer private18; + int private19; + char *xdefaults; /* contents of defaults from server */ + /* there is more to this structure, but it is private to Xlib */ +} +#ifdef XLIB_ILLEGAL_ACCESS +Display, +#endif +*_XPrivDisplay; + +#undef _XEVENT_ +#ifndef _XEVENT_ +/* + * Definitions of specific events. + */ +typedef struct { + int type; /* of event */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; /* "event" window it is reported relative to */ + Window root; /* root window that the event occurred on */ + Window subwindow; /* child window */ + Time time; /* milliseconds */ + int x, y; /* pointer x, y coordinates in event window */ + int x_root, y_root; /* coordinates relative to root */ + unsigned int state; /* key or button mask */ + unsigned int keycode; /* detail */ + Bool same_screen; /* same screen flag */ +} XKeyEvent; +typedef XKeyEvent XKeyPressedEvent; +typedef XKeyEvent XKeyReleasedEvent; + +typedef struct { + int type; /* of event */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; /* "event" window it is reported relative to */ + Window root; /* root window that the event occurred on */ + Window subwindow; /* child window */ + Time time; /* milliseconds */ + int x, y; /* pointer x, y coordinates in event window */ + int x_root, y_root; /* coordinates relative to root */ + unsigned int state; /* key or button mask */ + unsigned int button; /* detail */ + Bool same_screen; /* same screen flag */ +} XButtonEvent; +typedef XButtonEvent XButtonPressedEvent; +typedef XButtonEvent XButtonReleasedEvent; + +typedef struct { + int type; /* of event */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; /* "event" window reported relative to */ + Window root; /* root window that the event occurred on */ + Window subwindow; /* child window */ + Time time; /* milliseconds */ + int x, y; /* pointer x, y coordinates in event window */ + int x_root, y_root; /* coordinates relative to root */ + unsigned int state; /* key or button mask */ + char is_hint; /* detail */ + Bool same_screen; /* same screen flag */ +} XMotionEvent; +typedef XMotionEvent XPointerMovedEvent; + +typedef struct { + int type; /* of event */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; /* "event" window reported relative to */ + Window root; /* root window that the event occurred on */ + Window subwindow; /* child window */ + Time time; /* milliseconds */ + int x, y; /* pointer x, y coordinates in event window */ + int x_root, y_root; /* coordinates relative to root */ + int mode; /* NotifyNormal, NotifyGrab, NotifyUngrab */ + int detail; + /* + * NotifyAncestor, NotifyVirtual, NotifyInferior, + * NotifyNonlinear,NotifyNonlinearVirtual + */ + Bool same_screen; /* same screen flag */ + Bool focus; /* boolean focus */ + unsigned int state; /* key or button mask */ +} XCrossingEvent; +typedef XCrossingEvent XEnterWindowEvent; +typedef XCrossingEvent XLeaveWindowEvent; + +typedef struct { + int type; /* FocusIn or FocusOut */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; /* window of event */ + int mode; /* NotifyNormal, NotifyWhileGrabbed, + NotifyGrab, NotifyUngrab */ + int detail; + /* + * NotifyAncestor, NotifyVirtual, NotifyInferior, + * NotifyNonlinear,NotifyNonlinearVirtual, NotifyPointer, + * NotifyPointerRoot, NotifyDetailNone + */ +} XFocusChangeEvent; +typedef XFocusChangeEvent XFocusInEvent; +typedef XFocusChangeEvent XFocusOutEvent; + +/* generated on EnterWindow and FocusIn when KeyMapState selected */ +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; + char key_vector[32]; +} XKeymapEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; + int x, y; + int width, height; + int count; /* if non-zero, at least this many more */ +} XExposeEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Drawable drawable; + int x, y; + int width, height; + int count; /* if non-zero, at least this many more */ + int major_code; /* core is CopyArea or CopyPlane */ + int minor_code; /* not defined in the core */ +} XGraphicsExposeEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Drawable drawable; + int major_code; /* core is CopyArea or CopyPlane */ + int minor_code; /* not defined in the core */ +} XNoExposeEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; + int state; /* Visibility state */ +} XVisibilityEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window parent; /* parent of the window */ + Window window; /* window id of window created */ + int x, y; /* window location */ + int width, height; /* size of window */ + int border_width; /* border width */ + Bool override_redirect; /* creation should be overridden */ +} XCreateWindowEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window event; + Window window; +} XDestroyWindowEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window event; + Window window; + Bool from_configure; +} XUnmapEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window event; + Window window; + Bool override_redirect; /* boolean, is override set... */ +} XMapEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window parent; + Window window; +} XMapRequestEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window event; + Window window; + Window parent; + int x, y; + Bool override_redirect; +} XReparentEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window event; + Window window; + int x, y; + int width, height; + int border_width; + Window above; + Bool override_redirect; +} XConfigureEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window event; + Window window; + int x, y; +} XGravityEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; + int width, height; +} XResizeRequestEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window parent; + Window window; + int x, y; + int width, height; + int border_width; + Window above; + int detail; /* Above, Below, TopIf, BottomIf, Opposite */ + unsigned long value_mask; +} XConfigureRequestEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window event; + Window window; + int place; /* PlaceOnTop, PlaceOnBottom */ +} XCirculateEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window parent; + Window window; + int place; /* PlaceOnTop, PlaceOnBottom */ +} XCirculateRequestEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; + Atom atom; + Time time; + int state; /* NewValue, Deleted */ +} XPropertyEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; + Atom selection; + Time time; +} XSelectionClearEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window owner; + Window requestor; + Atom selection; + Atom target; + Atom property; + Time time; +} XSelectionRequestEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window requestor; + Atom selection; + Atom target; + Atom property; /* ATOM or None */ + Time time; +} XSelectionEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; + Colormap colormap; /* COLORMAP or None */ +#if defined(__cplusplus) || defined(c_plusplus) + Bool c_new; /* C++ */ +#else + Bool new; +#endif + int state; /* ColormapInstalled, ColormapUninstalled */ +} XColormapEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; + Atom message_type; + int format; + union { + char b[20]; + short s[10]; + long l[5]; + } data; +} XClientMessageEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; /* unused */ + int request; /* one of MappingModifier, MappingKeyboard, + MappingPointer */ + int first_keycode; /* first keycode */ + int count; /* defines range of change w. first_keycode*/ +} XMappingEvent; + +typedef struct { + int type; + Display *display; /* Display the event was read from */ + XID resourceid; /* resource id */ + unsigned long serial; /* serial number of failed request */ + unsigned char error_code; /* error code of failed request */ + unsigned char request_code; /* Major op-code of failed request */ + unsigned char minor_code; /* Minor op-code of failed request */ +} XErrorEvent; + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display;/* Display the event was read from */ + Window window; /* window on which event was requested in event mask */ +} XAnyEvent; + + +/*************************************************************** + * + * GenericEvent. This event is the standard event for all newer extensions. + */ + +typedef struct + { + int type; /* of event. Always GenericEvent */ + unsigned long serial; /* # of last request processed */ + Bool send_event; /* true if from SendEvent request */ + Display *display; /* Display the event was read from */ + int extension; /* major opcode of extension that caused the event */ + int evtype; /* actual event type. */ + } XGenericEvent; + +typedef struct { + int type; /* of event. Always GenericEvent */ + unsigned long serial; /* # of last request processed */ + Bool send_event; /* true if from SendEvent request */ + Display *display; /* Display the event was read from */ + int extension; /* major opcode of extension that caused the event */ + int evtype; /* actual event type. */ + unsigned int cookie; + void *data; +} XGenericEventCookie; + +/* + * this union is defined so Xlib can always use the same sized + * event structure internally, to avoid memory fragmentation. + */ +typedef union _XEvent { + int type; /* must not be changed; first element */ + XAnyEvent xany; + XKeyEvent xkey; + XButtonEvent xbutton; + XMotionEvent xmotion; + XCrossingEvent xcrossing; + XFocusChangeEvent xfocus; + XExposeEvent xexpose; + XGraphicsExposeEvent xgraphicsexpose; + XNoExposeEvent xnoexpose; + XVisibilityEvent xvisibility; + XCreateWindowEvent xcreatewindow; + XDestroyWindowEvent xdestroywindow; + XUnmapEvent xunmap; + XMapEvent xmap; + XMapRequestEvent xmaprequest; + XReparentEvent xreparent; + XConfigureEvent xconfigure; + XGravityEvent xgravity; + XResizeRequestEvent xresizerequest; + XConfigureRequestEvent xconfigurerequest; + XCirculateEvent xcirculate; + XCirculateRequestEvent xcirculaterequest; + XPropertyEvent xproperty; + XSelectionClearEvent xselectionclear; + XSelectionRequestEvent xselectionrequest; + XSelectionEvent xselection; + XColormapEvent xcolormap; + XClientMessageEvent xclient; + XMappingEvent xmapping; + XErrorEvent xerror; + XKeymapEvent xkeymap; + XGenericEvent xgeneric; + XGenericEventCookie xcookie; + long pad[24]; +} XEvent; +#endif + +#define XAllocID(dpy) ((*((_XPrivDisplay)dpy)->resource_alloc)((dpy))) + +/* + * per character font metric information. + */ +typedef struct { + short lbearing; /* origin to left edge of raster */ + short rbearing; /* origin to right edge of raster */ + short width; /* advance to next char's origin */ + short ascent; /* baseline to top edge of raster */ + short descent; /* baseline to bottom edge of raster */ + unsigned short attributes; /* per char flags (not predefined) */ +} XCharStruct; + +/* + * To allow arbitrary information with fonts, there are additional properties + * returned. + */ +typedef struct { + Atom name; + unsigned long card32; +} XFontProp; + +typedef struct { + XExtData *ext_data; /* hook for extension to hang data */ + Font fid; /* Font id for this font */ + unsigned direction; /* hint about direction the font is painted */ + unsigned min_char_or_byte2;/* first character */ + unsigned max_char_or_byte2;/* last character */ + unsigned min_byte1; /* first row that exists */ + unsigned max_byte1; /* last row that exists */ + Bool all_chars_exist;/* flag if all characters have non-zero size*/ + unsigned default_char; /* char to print for undefined character */ + int n_properties; /* how many properties there are */ + XFontProp *properties; /* pointer to array of additional properties*/ + XCharStruct min_bounds; /* minimum bounds over all existing char*/ + XCharStruct max_bounds; /* maximum bounds over all existing char*/ + XCharStruct *per_char; /* first_char to last_char information */ + int ascent; /* log. extent above baseline for spacing */ + int descent; /* log. descent below baseline for spacing */ +} XFontStruct; + +/* + * PolyText routines take these as arguments. + */ +typedef struct { + char *chars; /* pointer to string */ + int nchars; /* number of characters */ + int delta; /* delta between strings */ + Font font; /* font to print it in, None don't change */ +} XTextItem; + +typedef struct { /* normal 16 bit characters are two bytes */ + unsigned char byte1; + unsigned char byte2; +} XChar2b; + +typedef struct { + XChar2b *chars; /* two byte characters */ + int nchars; /* number of characters */ + int delta; /* delta between strings */ + Font font; /* font to print it in, None don't change */ +} XTextItem16; + + +typedef union { Display *display; + GC gc; + Visual *visual; + Screen *screen; + ScreenFormat *pixmap_format; + XFontStruct *font; } XEDataObject; + +typedef struct { + XRectangle max_ink_extent; + XRectangle max_logical_extent; +} XFontSetExtents; + +/* unused: +typedef void (*XOMProc)(); + */ + +typedef struct _XOM *XOM; +typedef struct _XOC *XOC, *XFontSet; + +typedef struct { + char *chars; + int nchars; + int delta; + XFontSet font_set; +} XmbTextItem; + +typedef struct { + wchar_t *chars; + int nchars; + int delta; + XFontSet font_set; +} XwcTextItem; + +#define XNRequiredCharSet "requiredCharSet" +#define XNQueryOrientation "queryOrientation" +#define XNBaseFontName "baseFontName" +#define XNOMAutomatic "omAutomatic" +#define XNMissingCharSet "missingCharSet" +#define XNDefaultString "defaultString" +#define XNOrientation "orientation" +#define XNDirectionalDependentDrawing "directionalDependentDrawing" +#define XNContextualDrawing "contextualDrawing" +#define XNFontInfo "fontInfo" + +typedef struct { + int charset_count; + char **charset_list; +} XOMCharSetList; + +typedef enum { + XOMOrientation_LTR_TTB, + XOMOrientation_RTL_TTB, + XOMOrientation_TTB_LTR, + XOMOrientation_TTB_RTL, + XOMOrientation_Context +} XOrientation; + +typedef struct { + int num_orientation; + XOrientation *orientation; /* Input Text description */ +} XOMOrientation; + +typedef struct { + int num_font; + XFontStruct **font_struct_list; + char **font_name_list; +} XOMFontInfo; + +typedef struct _XIM *XIM; +typedef struct _XIC *XIC; + +typedef void (*XIMProc)( + XIM, + XPointer, + XPointer +); + +typedef Bool (*XICProc)( + XIC, + XPointer, + XPointer +); + +typedef void (*XIDProc)( + Display*, + XPointer, + XPointer +); + +typedef unsigned long XIMStyle; + +typedef struct { + unsigned short count_styles; + XIMStyle *supported_styles; +} XIMStyles; + +#define XIMPreeditArea 0x0001L +#define XIMPreeditCallbacks 0x0002L +#define XIMPreeditPosition 0x0004L +#define XIMPreeditNothing 0x0008L +#define XIMPreeditNone 0x0010L +#define XIMStatusArea 0x0100L +#define XIMStatusCallbacks 0x0200L +#define XIMStatusNothing 0x0400L +#define XIMStatusNone 0x0800L + +#define XNVaNestedList "XNVaNestedList" +#define XNQueryInputStyle "queryInputStyle" +#define XNClientWindow "clientWindow" +#define XNInputStyle "inputStyle" +#define XNFocusWindow "focusWindow" +#define XNResourceName "resourceName" +#define XNResourceClass "resourceClass" +#define XNGeometryCallback "geometryCallback" +#define XNDestroyCallback "destroyCallback" +#define XNFilterEvents "filterEvents" +#define XNPreeditStartCallback "preeditStartCallback" +#define XNPreeditDoneCallback "preeditDoneCallback" +#define XNPreeditDrawCallback "preeditDrawCallback" +#define XNPreeditCaretCallback "preeditCaretCallback" +#define XNPreeditStateNotifyCallback "preeditStateNotifyCallback" +#define XNPreeditAttributes "preeditAttributes" +#define XNStatusStartCallback "statusStartCallback" +#define XNStatusDoneCallback "statusDoneCallback" +#define XNStatusDrawCallback "statusDrawCallback" +#define XNStatusAttributes "statusAttributes" +#define XNArea "area" +#define XNAreaNeeded "areaNeeded" +#define XNSpotLocation "spotLocation" +#define XNColormap "colorMap" +#define XNStdColormap "stdColorMap" +#define XNForeground "foreground" +#define XNBackground "background" +#define XNBackgroundPixmap "backgroundPixmap" +#define XNFontSet "fontSet" +#define XNLineSpace "lineSpace" +#define XNCursor "cursor" + +#define XNQueryIMValuesList "queryIMValuesList" +#define XNQueryICValuesList "queryICValuesList" +#define XNVisiblePosition "visiblePosition" +#define XNR6PreeditCallback "r6PreeditCallback" +#define XNStringConversionCallback "stringConversionCallback" +#define XNStringConversion "stringConversion" +#define XNResetState "resetState" +#define XNHotKey "hotKey" +#define XNHotKeyState "hotKeyState" +#define XNPreeditState "preeditState" +#define XNSeparatorofNestedList "separatorofNestedList" + +#define XBufferOverflow -1 +#define XLookupNone 1 +#define XLookupChars 2 +#define XLookupKeySym 3 +#define XLookupBoth 4 + +typedef void *XVaNestedList; + +typedef struct { + XPointer client_data; + XIMProc callback; +} XIMCallback; + +typedef struct { + XPointer client_data; + XICProc callback; +} XICCallback; + +typedef unsigned long XIMFeedback; + +#define XIMReverse 1L +#define XIMUnderline (1L<<1) +#define XIMHighlight (1L<<2) +#define XIMPrimary (1L<<5) +#define XIMSecondary (1L<<6) +#define XIMTertiary (1L<<7) +#define XIMVisibleToForward (1L<<8) +#define XIMVisibleToBackword (1L<<9) +#define XIMVisibleToCenter (1L<<10) + +typedef struct _XIMText { + unsigned short length; + XIMFeedback *feedback; + Bool encoding_is_wchar; + union { + char *multi_byte; + wchar_t *wide_char; + } string; +} XIMText; + +typedef unsigned long XIMPreeditState; + +#define XIMPreeditUnKnown 0L +#define XIMPreeditEnable 1L +#define XIMPreeditDisable (1L<<1) + +typedef struct _XIMPreeditStateNotifyCallbackStruct { + XIMPreeditState state; +} XIMPreeditStateNotifyCallbackStruct; + +typedef unsigned long XIMResetState; + +#define XIMInitialState 1L +#define XIMPreserveState (1L<<1) + +typedef unsigned long XIMStringConversionFeedback; + +#define XIMStringConversionLeftEdge (0x00000001) +#define XIMStringConversionRightEdge (0x00000002) +#define XIMStringConversionTopEdge (0x00000004) +#define XIMStringConversionBottomEdge (0x00000008) +#define XIMStringConversionConcealed (0x00000010) +#define XIMStringConversionWrapped (0x00000020) + +typedef struct _XIMStringConversionText { + unsigned short length; + XIMStringConversionFeedback *feedback; + Bool encoding_is_wchar; + union { + char *mbs; + wchar_t *wcs; + } string; +} XIMStringConversionText; + +typedef unsigned short XIMStringConversionPosition; + +typedef unsigned short XIMStringConversionType; + +#define XIMStringConversionBuffer (0x0001) +#define XIMStringConversionLine (0x0002) +#define XIMStringConversionWord (0x0003) +#define XIMStringConversionChar (0x0004) + +typedef unsigned short XIMStringConversionOperation; + +#define XIMStringConversionSubstitution (0x0001) +#define XIMStringConversionRetrieval (0x0002) + +typedef enum { + XIMForwardChar, XIMBackwardChar, + XIMForwardWord, XIMBackwardWord, + XIMCaretUp, XIMCaretDown, + XIMNextLine, XIMPreviousLine, + XIMLineStart, XIMLineEnd, + XIMAbsolutePosition, + XIMDontChange +} XIMCaretDirection; + +typedef struct _XIMStringConversionCallbackStruct { + XIMStringConversionPosition position; + XIMCaretDirection direction; + XIMStringConversionOperation operation; + unsigned short factor; + XIMStringConversionText *text; +} XIMStringConversionCallbackStruct; + +typedef struct _XIMPreeditDrawCallbackStruct { + int caret; /* Cursor offset within pre-edit string */ + int chg_first; /* Starting change position */ + int chg_length; /* Length of the change in character count */ + XIMText *text; +} XIMPreeditDrawCallbackStruct; + +typedef enum { + XIMIsInvisible, /* Disable caret feedback */ + XIMIsPrimary, /* UI defined caret feedback */ + XIMIsSecondary /* UI defined caret feedback */ +} XIMCaretStyle; + +typedef struct _XIMPreeditCaretCallbackStruct { + int position; /* Caret offset within pre-edit string */ + XIMCaretDirection direction; /* Caret moves direction */ + XIMCaretStyle style; /* Feedback of the caret */ +} XIMPreeditCaretCallbackStruct; + +typedef enum { + XIMTextType, + XIMBitmapType +} XIMStatusDataType; + +typedef struct _XIMStatusDrawCallbackStruct { + XIMStatusDataType type; + union { + XIMText *text; + Pixmap bitmap; + } data; +} XIMStatusDrawCallbackStruct; + +typedef struct _XIMHotKeyTrigger { + KeySym keysym; + int modifier; + int modifier_mask; +} XIMHotKeyTrigger; + +typedef struct _XIMHotKeyTriggers { + int num_hot_key; + XIMHotKeyTrigger *key; +} XIMHotKeyTriggers; + +typedef unsigned long XIMHotKeyState; + +#define XIMHotKeyStateON (0x0001L) +#define XIMHotKeyStateOFF (0x0002L) + +typedef struct { + unsigned short count_values; + char **supported_values; +} XIMValuesList; + +_XFUNCPROTOBEGIN + +#if defined(WIN32) && !defined(_XLIBINT_) +#define _Xdebug (*_Xdebug_p) +#endif + +extern int _Xdebug; + +extern XFontStruct *XLoadQueryFont( + Display* /* display */, + _Xconst char* /* name */ +); + +extern XFontStruct *XQueryFont( + Display* /* display */, + XID /* font_ID */ +); + + +extern XTimeCoord *XGetMotionEvents( + Display* /* display */, + Window /* w */, + Time /* start */, + Time /* stop */, + int* /* nevents_return */ +); + +extern XModifierKeymap *XDeleteModifiermapEntry( + XModifierKeymap* /* modmap */, +#if NeedWidePrototypes + unsigned int /* keycode_entry */, +#else + KeyCode /* keycode_entry */, +#endif + int /* modifier */ +); + +extern XModifierKeymap *XGetModifierMapping( + Display* /* display */ +); + +extern XModifierKeymap *XInsertModifiermapEntry( + XModifierKeymap* /* modmap */, +#if NeedWidePrototypes + unsigned int /* keycode_entry */, +#else + KeyCode /* keycode_entry */, +#endif + int /* modifier */ +); + +extern XModifierKeymap *XNewModifiermap( + int /* max_keys_per_mod */ +); + +extern XImage *XCreateImage( + Display* /* display */, + Visual* /* visual */, + unsigned int /* depth */, + int /* format */, + int /* offset */, + char* /* data */, + unsigned int /* width */, + unsigned int /* height */, + int /* bitmap_pad */, + int /* bytes_per_line */ +); +extern Status XInitImage( + XImage* /* image */ +); +extern XImage *XGetImage( + Display* /* display */, + Drawable /* d */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */, + unsigned long /* plane_mask */, + int /* format */ +); +extern XImage *XGetSubImage( + Display* /* display */, + Drawable /* d */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */, + unsigned long /* plane_mask */, + int /* format */, + XImage* /* dest_image */, + int /* dest_x */, + int /* dest_y */ +); + +/* + * X function declarations. + */ +extern Display *XOpenDisplay( + _Xconst char* /* display_name */ +); + +extern void XrmInitialize( + void +); + +extern char *XFetchBytes( + Display* /* display */, + int* /* nbytes_return */ +); +extern char *XFetchBuffer( + Display* /* display */, + int* /* nbytes_return */, + int /* buffer */ +); +extern char *XGetAtomName( + Display* /* display */, + Atom /* atom */ +); +extern Status XGetAtomNames( + Display* /* dpy */, + Atom* /* atoms */, + int /* count */, + char** /* names_return */ +); +extern char *XGetDefault( + Display* /* display */, + _Xconst char* /* program */, + _Xconst char* /* option */ +); +extern char *XDisplayName( + _Xconst char* /* string */ +); +extern char *XKeysymToString( + KeySym /* keysym */ +); + +extern int (*XSynchronize( + Display* /* display */, + Bool /* onoff */ +))( + Display* /* display */ +); +extern int (*XSetAfterFunction( + Display* /* display */, + int (*) ( + Display* /* display */ + ) /* procedure */ +))( + Display* /* display */ +); +extern Atom XInternAtom( + Display* /* display */, + _Xconst char* /* atom_name */, + Bool /* only_if_exists */ +); +extern Status XInternAtoms( + Display* /* dpy */, + char** /* names */, + int /* count */, + Bool /* onlyIfExists */, + Atom* /* atoms_return */ +); +extern Colormap XCopyColormapAndFree( + Display* /* display */, + Colormap /* colormap */ +); +extern Colormap XCreateColormap( + Display* /* display */, + Window /* w */, + Visual* /* visual */, + int /* alloc */ +); +extern Cursor XCreatePixmapCursor( + Display* /* display */, + Pixmap /* source */, + Pixmap /* mask */, + XColor* /* foreground_color */, + XColor* /* background_color */, + unsigned int /* x */, + unsigned int /* y */ +); +extern Cursor XCreateGlyphCursor( + Display* /* display */, + Font /* source_font */, + Font /* mask_font */, + unsigned int /* source_char */, + unsigned int /* mask_char */, + XColor _Xconst * /* foreground_color */, + XColor _Xconst * /* background_color */ +); +extern Cursor XCreateFontCursor( + Display* /* display */, + unsigned int /* shape */ +); +extern Font XLoadFont( + Display* /* display */, + _Xconst char* /* name */ +); +extern GC XCreateGC( + Display* /* display */, + Drawable /* d */, + unsigned long /* valuemask */, + XGCValues* /* values */ +); +extern GContext XGContextFromGC( + GC /* gc */ +); +extern void XFlushGC( + Display* /* display */, + GC /* gc */ +); +extern Pixmap XCreatePixmap( + Display* /* display */, + Drawable /* d */, + unsigned int /* width */, + unsigned int /* height */, + unsigned int /* depth */ +); +extern Pixmap XCreateBitmapFromData( + Display* /* display */, + Drawable /* d */, + _Xconst char* /* data */, + unsigned int /* width */, + unsigned int /* height */ +); +extern Pixmap XCreatePixmapFromBitmapData( + Display* /* display */, + Drawable /* d */, + char* /* data */, + unsigned int /* width */, + unsigned int /* height */, + unsigned long /* fg */, + unsigned long /* bg */, + unsigned int /* depth */ +); +extern Window XCreateSimpleWindow( + Display* /* display */, + Window /* parent */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */, + unsigned int /* border_width */, + unsigned long /* border */, + unsigned long /* background */ +); +extern Window XGetSelectionOwner( + Display* /* display */, + Atom /* selection */ +); +extern Window XCreateWindow( + Display* /* display */, + Window /* parent */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */, + unsigned int /* border_width */, + int /* depth */, + unsigned int /* class */, + Visual* /* visual */, + unsigned long /* valuemask */, + XSetWindowAttributes* /* attributes */ +); +extern Colormap *XListInstalledColormaps( + Display* /* display */, + Window /* w */, + int* /* num_return */ +); +extern char **XListFonts( + Display* /* display */, + _Xconst char* /* pattern */, + int /* maxnames */, + int* /* actual_count_return */ +); +extern char **XListFontsWithInfo( + Display* /* display */, + _Xconst char* /* pattern */, + int /* maxnames */, + int* /* count_return */, + XFontStruct** /* info_return */ +); +extern char **XGetFontPath( + Display* /* display */, + int* /* npaths_return */ +); +extern char **XListExtensions( + Display* /* display */, + int* /* nextensions_return */ +); +extern Atom *XListProperties( + Display* /* display */, + Window /* w */, + int* /* num_prop_return */ +); +extern XHostAddress *XListHosts( + Display* /* display */, + int* /* nhosts_return */, + Bool* /* state_return */ +); +extern KeySym XKeycodeToKeysym( + Display* /* display */, +#if NeedWidePrototypes + unsigned int /* keycode */, +#else + KeyCode /* keycode */, +#endif + int /* index */ +); +extern KeySym XLookupKeysym( + XKeyEvent* /* key_event */, + int /* index */ +); +extern KeySym *XGetKeyboardMapping( + Display* /* display */, +#if NeedWidePrototypes + unsigned int /* first_keycode */, +#else + KeyCode /* first_keycode */, +#endif + int /* keycode_count */, + int* /* keysyms_per_keycode_return */ +); +extern KeySym XStringToKeysym( + _Xconst char* /* string */ +); +extern long XMaxRequestSize( + Display* /* display */ +); +extern long XExtendedMaxRequestSize( + Display* /* display */ +); +extern char *XResourceManagerString( + Display* /* display */ +); +extern char *XScreenResourceString( + Screen* /* screen */ +); +extern unsigned long XDisplayMotionBufferSize( + Display* /* display */ +); +extern VisualID XVisualIDFromVisual( + Visual* /* visual */ +); + +/* multithread routines */ + +extern Status XInitThreads( + void +); + +extern void XLockDisplay( + Display* /* display */ +); + +extern void XUnlockDisplay( + Display* /* display */ +); + +/* routines for dealing with extensions */ + +extern XExtCodes *XInitExtension( + Display* /* display */, + _Xconst char* /* name */ +); + +extern XExtCodes *XAddExtension( + Display* /* display */ +); +extern XExtData *XFindOnExtensionList( + XExtData** /* structure */, + int /* number */ +); +extern XExtData **XEHeadOfExtensionList( + XEDataObject /* object */ +); + +/* these are routines for which there are also macros */ +extern Window XRootWindow( + Display* /* display */, + int /* screen_number */ +); +extern Window XDefaultRootWindow( + Display* /* display */ +); +extern Window XRootWindowOfScreen( + Screen* /* screen */ +); +extern Visual *XDefaultVisual( + Display* /* display */, + int /* screen_number */ +); +extern Visual *XDefaultVisualOfScreen( + Screen* /* screen */ +); +extern GC XDefaultGC( + Display* /* display */, + int /* screen_number */ +); +extern GC XDefaultGCOfScreen( + Screen* /* screen */ +); +extern unsigned long XBlackPixel( + Display* /* display */, + int /* screen_number */ +); +extern unsigned long XWhitePixel( + Display* /* display */, + int /* screen_number */ +); +extern unsigned long XAllPlanes( + void +); +extern unsigned long XBlackPixelOfScreen( + Screen* /* screen */ +); +extern unsigned long XWhitePixelOfScreen( + Screen* /* screen */ +); +extern unsigned long XNextRequest( + Display* /* display */ +); +extern unsigned long XLastKnownRequestProcessed( + Display* /* display */ +); +extern char *XServerVendor( + Display* /* display */ +); +extern char *XDisplayString( + Display* /* display */ +); +extern Colormap XDefaultColormap( + Display* /* display */, + int /* screen_number */ +); +extern Colormap XDefaultColormapOfScreen( + Screen* /* screen */ +); +extern Display *XDisplayOfScreen( + Screen* /* screen */ +); +extern Screen *XScreenOfDisplay( + Display* /* display */, + int /* screen_number */ +); +extern Screen *XDefaultScreenOfDisplay( + Display* /* display */ +); +extern long XEventMaskOfScreen( + Screen* /* screen */ +); + +extern int XScreenNumberOfScreen( + Screen* /* screen */ +); + +typedef int (*XErrorHandler) ( /* WARNING, this type not in Xlib spec */ + Display* /* display */, + XErrorEvent* /* error_event */ +); + +extern XErrorHandler XSetErrorHandler ( + XErrorHandler /* handler */ +); + + +typedef int (*XIOErrorHandler) ( /* WARNING, this type not in Xlib spec */ + Display* /* display */ +); + +extern XIOErrorHandler XSetIOErrorHandler ( + XIOErrorHandler /* handler */ +); + + +extern XPixmapFormatValues *XListPixmapFormats( + Display* /* display */, + int* /* count_return */ +); +extern int *XListDepths( + Display* /* display */, + int /* screen_number */, + int* /* count_return */ +); + +/* ICCCM routines for things that don't require special include files; */ +/* other declarations are given in Xutil.h */ +extern Status XReconfigureWMWindow( + Display* /* display */, + Window /* w */, + int /* screen_number */, + unsigned int /* mask */, + XWindowChanges* /* changes */ +); + +extern Status XGetWMProtocols( + Display* /* display */, + Window /* w */, + Atom** /* protocols_return */, + int* /* count_return */ +); +extern Status XSetWMProtocols( + Display* /* display */, + Window /* w */, + Atom* /* protocols */, + int /* count */ +); +extern Status XIconifyWindow( + Display* /* display */, + Window /* w */, + int /* screen_number */ +); +extern Status XWithdrawWindow( + Display* /* display */, + Window /* w */, + int /* screen_number */ +); +extern Status XGetCommand( + Display* /* display */, + Window /* w */, + char*** /* argv_return */, + int* /* argc_return */ +); +extern Status XGetWMColormapWindows( + Display* /* display */, + Window /* w */, + Window** /* windows_return */, + int* /* count_return */ +); +extern Status XSetWMColormapWindows( + Display* /* display */, + Window /* w */, + Window* /* colormap_windows */, + int /* count */ +); +extern void XFreeStringList( + char** /* list */ +); +extern int XSetTransientForHint( + Display* /* display */, + Window /* w */, + Window /* prop_window */ +); + +/* The following are given in alphabetical order */ + +extern int XActivateScreenSaver( + Display* /* display */ +); + +extern int XAddHost( + Display* /* display */, + XHostAddress* /* host */ +); + +extern int XAddHosts( + Display* /* display */, + XHostAddress* /* hosts */, + int /* num_hosts */ +); + +extern int XAddToExtensionList( + struct _XExtData** /* structure */, + XExtData* /* ext_data */ +); + +extern int XAddToSaveSet( + Display* /* display */, + Window /* w */ +); + +extern Status XAllocColor( + Display* /* display */, + Colormap /* colormap */, + XColor* /* screen_in_out */ +); + +extern Status XAllocColorCells( + Display* /* display */, + Colormap /* colormap */, + Bool /* contig */, + unsigned long* /* plane_masks_return */, + unsigned int /* nplanes */, + unsigned long* /* pixels_return */, + unsigned int /* npixels */ +); + +extern Status XAllocColorPlanes( + Display* /* display */, + Colormap /* colormap */, + Bool /* contig */, + unsigned long* /* pixels_return */, + int /* ncolors */, + int /* nreds */, + int /* ngreens */, + int /* nblues */, + unsigned long* /* rmask_return */, + unsigned long* /* gmask_return */, + unsigned long* /* bmask_return */ +); + +extern Status XAllocNamedColor( + Display* /* display */, + Colormap /* colormap */, + _Xconst char* /* color_name */, + XColor* /* screen_def_return */, + XColor* /* exact_def_return */ +); + +extern int XAllowEvents( + Display* /* display */, + int /* event_mode */, + Time /* time */ +); + +extern int XAutoRepeatOff( + Display* /* display */ +); + +extern int XAutoRepeatOn( + Display* /* display */ +); + +extern int XBell( + Display* /* display */, + int /* percent */ +); + +extern int XBitmapBitOrder( + Display* /* display */ +); + +extern int XBitmapPad( + Display* /* display */ +); + +extern int XBitmapUnit( + Display* /* display */ +); + +extern int XCellsOfScreen( + Screen* /* screen */ +); + +extern int XChangeActivePointerGrab( + Display* /* display */, + unsigned int /* event_mask */, + Cursor /* cursor */, + Time /* time */ +); + +extern int XChangeGC( + Display* /* display */, + GC /* gc */, + unsigned long /* valuemask */, + XGCValues* /* values */ +); + +extern int XChangeKeyboardControl( + Display* /* display */, + unsigned long /* value_mask */, + XKeyboardControl* /* values */ +); + +extern int XChangeKeyboardMapping( + Display* /* display */, + int /* first_keycode */, + int /* keysyms_per_keycode */, + KeySym* /* keysyms */, + int /* num_codes */ +); + +extern int XChangePointerControl( + Display* /* display */, + Bool /* do_accel */, + Bool /* do_threshold */, + int /* accel_numerator */, + int /* accel_denominator */, + int /* threshold */ +); + +extern int XChangeProperty( + Display* /* display */, + Window /* w */, + Atom /* property */, + Atom /* type */, + int /* format */, + int /* mode */, + _Xconst unsigned char* /* data */, + int /* nelements */ +); + +extern int XChangeSaveSet( + Display* /* display */, + Window /* w */, + int /* change_mode */ +); + +extern int XChangeWindowAttributes( + Display* /* display */, + Window /* w */, + unsigned long /* valuemask */, + XSetWindowAttributes* /* attributes */ +); + +extern Bool XCheckIfEvent( + Display* /* display */, + XEvent* /* event_return */, + Bool (*) ( + Display* /* display */, + XEvent* /* event */, + XPointer /* arg */ + ) /* predicate */, + XPointer /* arg */ +); + +extern Bool XCheckMaskEvent( + Display* /* display */, + long /* event_mask */, + XEvent* /* event_return */ +); + +extern Bool XCheckTypedEvent( + Display* /* display */, + int /* event_type */, + XEvent* /* event_return */ +); + +extern Bool XCheckTypedWindowEvent( + Display* /* display */, + Window /* w */, + int /* event_type */, + XEvent* /* event_return */ +); + +extern Bool XCheckWindowEvent( + Display* /* display */, + Window /* w */, + long /* event_mask */, + XEvent* /* event_return */ +); + +extern int XCirculateSubwindows( + Display* /* display */, + Window /* w */, + int /* direction */ +); + +extern int XCirculateSubwindowsDown( + Display* /* display */, + Window /* w */ +); + +extern int XCirculateSubwindowsUp( + Display* /* display */, + Window /* w */ +); + +extern int XClearArea( + Display* /* display */, + Window /* w */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */, + Bool /* exposures */ +); + +extern int XClearWindow( + Display* /* display */, + Window /* w */ +); + +extern int XCloseDisplay( + Display* /* display */ +); + +extern int XConfigureWindow( + Display* /* display */, + Window /* w */, + unsigned int /* value_mask */, + XWindowChanges* /* values */ +); + +extern int XConnectionNumber( + Display* /* display */ +); + +extern int XConvertSelection( + Display* /* display */, + Atom /* selection */, + Atom /* target */, + Atom /* property */, + Window /* requestor */, + Time /* time */ +); + +extern int XCopyArea( + Display* /* display */, + Drawable /* src */, + Drawable /* dest */, + GC /* gc */, + int /* src_x */, + int /* src_y */, + unsigned int /* width */, + unsigned int /* height */, + int /* dest_x */, + int /* dest_y */ +); + +extern int XCopyGC( + Display* /* display */, + GC /* src */, + unsigned long /* valuemask */, + GC /* dest */ +); + +extern int XCopyPlane( + Display* /* display */, + Drawable /* src */, + Drawable /* dest */, + GC /* gc */, + int /* src_x */, + int /* src_y */, + unsigned int /* width */, + unsigned int /* height */, + int /* dest_x */, + int /* dest_y */, + unsigned long /* plane */ +); + +extern int XDefaultDepth( + Display* /* display */, + int /* screen_number */ +); + +extern int XDefaultDepthOfScreen( + Screen* /* screen */ +); + +extern int XDefaultScreen( + Display* /* display */ +); + +extern int XDefineCursor( + Display* /* display */, + Window /* w */, + Cursor /* cursor */ +); + +extern int XDeleteProperty( + Display* /* display */, + Window /* w */, + Atom /* property */ +); + +extern int XDestroyWindow( + Display* /* display */, + Window /* w */ +); + +extern int XDestroySubwindows( + Display* /* display */, + Window /* w */ +); + +extern int XDoesBackingStore( + Screen* /* screen */ +); + +extern Bool XDoesSaveUnders( + Screen* /* screen */ +); + +extern int XDisableAccessControl( + Display* /* display */ +); + + +extern int XDisplayCells( + Display* /* display */, + int /* screen_number */ +); + +extern int XDisplayHeight( + Display* /* display */, + int /* screen_number */ +); + +extern int XDisplayHeightMM( + Display* /* display */, + int /* screen_number */ +); + +extern int XDisplayKeycodes( + Display* /* display */, + int* /* min_keycodes_return */, + int* /* max_keycodes_return */ +); + +extern int XDisplayPlanes( + Display* /* display */, + int /* screen_number */ +); + +extern int XDisplayWidth( + Display* /* display */, + int /* screen_number */ +); + +extern int XDisplayWidthMM( + Display* /* display */, + int /* screen_number */ +); + +extern int XDrawArc( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */, + int /* angle1 */, + int /* angle2 */ +); + +extern int XDrawArcs( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + XArc* /* arcs */, + int /* narcs */ +); + +extern int XDrawImageString( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst char* /* string */, + int /* length */ +); + +extern int XDrawImageString16( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst XChar2b* /* string */, + int /* length */ +); + +extern int XDrawLine( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x1 */, + int /* y1 */, + int /* x2 */, + int /* y2 */ +); + +extern int XDrawLines( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + XPoint* /* points */, + int /* npoints */, + int /* mode */ +); + +extern int XDrawPoint( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */ +); + +extern int XDrawPoints( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + XPoint* /* points */, + int /* npoints */, + int /* mode */ +); + +extern int XDrawRectangle( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */ +); + +extern int XDrawRectangles( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + XRectangle* /* rectangles */, + int /* nrectangles */ +); + +extern int XDrawSegments( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + XSegment* /* segments */, + int /* nsegments */ +); + +extern int XDrawString( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst char* /* string */, + int /* length */ +); + +extern int XDrawString16( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst XChar2b* /* string */, + int /* length */ +); + +extern int XDrawText( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + XTextItem* /* items */, + int /* nitems */ +); + +extern int XDrawText16( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + XTextItem16* /* items */, + int /* nitems */ +); + +extern int XEnableAccessControl( + Display* /* display */ +); + +extern int XEventsQueued( + Display* /* display */, + int /* mode */ +); + +extern Status XFetchName( + Display* /* display */, + Window /* w */, + char** /* window_name_return */ +); + +extern int XFillArc( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */, + int /* angle1 */, + int /* angle2 */ +); + +extern int XFillArcs( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + XArc* /* arcs */, + int /* narcs */ +); + +extern int XFillPolygon( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + XPoint* /* points */, + int /* npoints */, + int /* shape */, + int /* mode */ +); + +extern int XFillRectangle( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */ +); + +extern int XFillRectangles( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + XRectangle* /* rectangles */, + int /* nrectangles */ +); + +extern int XFlush( + Display* /* display */ +); + +extern int XForceScreenSaver( + Display* /* display */, + int /* mode */ +); + +extern int XFree( + void* /* data */ +); + +extern int XFreeColormap( + Display* /* display */, + Colormap /* colormap */ +); + +extern int XFreeColors( + Display* /* display */, + Colormap /* colormap */, + unsigned long* /* pixels */, + int /* npixels */, + unsigned long /* planes */ +); + +extern int XFreeCursor( + Display* /* display */, + Cursor /* cursor */ +); + +extern int XFreeExtensionList( + char** /* list */ +); + +extern int XFreeFont( + Display* /* display */, + XFontStruct* /* font_struct */ +); + +extern int XFreeFontInfo( + char** /* names */, + XFontStruct* /* free_info */, + int /* actual_count */ +); + +extern int XFreeFontNames( + char** /* list */ +); + +extern int XFreeFontPath( + char** /* list */ +); + +extern int XFreeGC( + Display* /* display */, + GC /* gc */ +); + +extern int XFreeModifiermap( + XModifierKeymap* /* modmap */ +); + +extern int XFreePixmap( + Display* /* display */, + Pixmap /* pixmap */ +); + +extern int XGeometry( + Display* /* display */, + int /* screen */, + _Xconst char* /* position */, + _Xconst char* /* default_position */, + unsigned int /* bwidth */, + unsigned int /* fwidth */, + unsigned int /* fheight */, + int /* xadder */, + int /* yadder */, + int* /* x_return */, + int* /* y_return */, + int* /* width_return */, + int* /* height_return */ +); + +extern int XGetErrorDatabaseText( + Display* /* display */, + _Xconst char* /* name */, + _Xconst char* /* message */, + _Xconst char* /* default_string */, + char* /* buffer_return */, + int /* length */ +); + +extern int XGetErrorText( + Display* /* display */, + int /* code */, + char* /* buffer_return */, + int /* length */ +); + +extern Bool XGetFontProperty( + XFontStruct* /* font_struct */, + Atom /* atom */, + unsigned long* /* value_return */ +); + +extern Status XGetGCValues( + Display* /* display */, + GC /* gc */, + unsigned long /* valuemask */, + XGCValues* /* values_return */ +); + +extern Status XGetGeometry( + Display* /* display */, + Drawable /* d */, + Window* /* root_return */, + int* /* x_return */, + int* /* y_return */, + unsigned int* /* width_return */, + unsigned int* /* height_return */, + unsigned int* /* border_width_return */, + unsigned int* /* depth_return */ +); + +extern Status XGetIconName( + Display* /* display */, + Window /* w */, + char** /* icon_name_return */ +); + +extern int XGetInputFocus( + Display* /* display */, + Window* /* focus_return */, + int* /* revert_to_return */ +); + +extern int XGetKeyboardControl( + Display* /* display */, + XKeyboardState* /* values_return */ +); + +extern int XGetPointerControl( + Display* /* display */, + int* /* accel_numerator_return */, + int* /* accel_denominator_return */, + int* /* threshold_return */ +); + +extern int XGetPointerMapping( + Display* /* display */, + unsigned char* /* map_return */, + int /* nmap */ +); + +extern int XGetScreenSaver( + Display* /* display */, + int* /* timeout_return */, + int* /* interval_return */, + int* /* prefer_blanking_return */, + int* /* allow_exposures_return */ +); + +extern Status XGetTransientForHint( + Display* /* display */, + Window /* w */, + Window* /* prop_window_return */ +); + +extern int XGetWindowProperty( + Display* /* display */, + Window /* w */, + Atom /* property */, + long /* long_offset */, + long /* long_length */, + Bool /* delete */, + Atom /* req_type */, + Atom* /* actual_type_return */, + int* /* actual_format_return */, + unsigned long* /* nitems_return */, + unsigned long* /* bytes_after_return */, + unsigned char** /* prop_return */ +); + +extern Status XGetWindowAttributes( + Display* /* display */, + Window /* w */, + XWindowAttributes* /* window_attributes_return */ +); + +extern int XGrabButton( + Display* /* display */, + unsigned int /* button */, + unsigned int /* modifiers */, + Window /* grab_window */, + Bool /* owner_events */, + unsigned int /* event_mask */, + int /* pointer_mode */, + int /* keyboard_mode */, + Window /* confine_to */, + Cursor /* cursor */ +); + +extern int XGrabKey( + Display* /* display */, + int /* keycode */, + unsigned int /* modifiers */, + Window /* grab_window */, + Bool /* owner_events */, + int /* pointer_mode */, + int /* keyboard_mode */ +); + +extern int XGrabKeyboard( + Display* /* display */, + Window /* grab_window */, + Bool /* owner_events */, + int /* pointer_mode */, + int /* keyboard_mode */, + Time /* time */ +); + +extern int XGrabPointer( + Display* /* display */, + Window /* grab_window */, + Bool /* owner_events */, + unsigned int /* event_mask */, + int /* pointer_mode */, + int /* keyboard_mode */, + Window /* confine_to */, + Cursor /* cursor */, + Time /* time */ +); + +extern int XGrabServer( + Display* /* display */ +); + +extern int XHeightMMOfScreen( + Screen* /* screen */ +); + +extern int XHeightOfScreen( + Screen* /* screen */ +); + +extern int XIfEvent( + Display* /* display */, + XEvent* /* event_return */, + Bool (*) ( + Display* /* display */, + XEvent* /* event */, + XPointer /* arg */ + ) /* predicate */, + XPointer /* arg */ +); + +extern int XImageByteOrder( + Display* /* display */ +); + +extern int XInstallColormap( + Display* /* display */, + Colormap /* colormap */ +); + +extern KeyCode XKeysymToKeycode( + Display* /* display */, + KeySym /* keysym */ +); + +extern int XKillClient( + Display* /* display */, + XID /* resource */ +); + +extern Status XLookupColor( + Display* /* display */, + Colormap /* colormap */, + _Xconst char* /* color_name */, + XColor* /* exact_def_return */, + XColor* /* screen_def_return */ +); + +extern int XLowerWindow( + Display* /* display */, + Window /* w */ +); + +extern int XMapRaised( + Display* /* display */, + Window /* w */ +); + +extern int XMapSubwindows( + Display* /* display */, + Window /* w */ +); + +extern int XMapWindow( + Display* /* display */, + Window /* w */ +); + +extern int XMaskEvent( + Display* /* display */, + long /* event_mask */, + XEvent* /* event_return */ +); + +extern int XMaxCmapsOfScreen( + Screen* /* screen */ +); + +extern int XMinCmapsOfScreen( + Screen* /* screen */ +); + +extern int XMoveResizeWindow( + Display* /* display */, + Window /* w */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */ +); + +extern int XMoveWindow( + Display* /* display */, + Window /* w */, + int /* x */, + int /* y */ +); + +extern int XNextEvent( + Display* /* display */, + XEvent* /* event_return */ +); + +extern int XNoOp( + Display* /* display */ +); + +extern Status XParseColor( + Display* /* display */, + Colormap /* colormap */, + _Xconst char* /* spec */, + XColor* /* exact_def_return */ +); + +extern int XParseGeometry( + _Xconst char* /* parsestring */, + int* /* x_return */, + int* /* y_return */, + unsigned int* /* width_return */, + unsigned int* /* height_return */ +); + +extern int XPeekEvent( + Display* /* display */, + XEvent* /* event_return */ +); + +extern int XPeekIfEvent( + Display* /* display */, + XEvent* /* event_return */, + Bool (*) ( + Display* /* display */, + XEvent* /* event */, + XPointer /* arg */ + ) /* predicate */, + XPointer /* arg */ +); + +extern int XPending( + Display* /* display */ +); + +extern int XPlanesOfScreen( + Screen* /* screen */ +); + +extern int XProtocolRevision( + Display* /* display */ +); + +extern int XProtocolVersion( + Display* /* display */ +); + + +extern int XPutBackEvent( + Display* /* display */, + XEvent* /* event */ +); + +extern int XPutImage( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + XImage* /* image */, + int /* src_x */, + int /* src_y */, + int /* dest_x */, + int /* dest_y */, + unsigned int /* width */, + unsigned int /* height */ +); + +extern int XQLength( + Display* /* display */ +); + +extern Status XQueryBestCursor( + Display* /* display */, + Drawable /* d */, + unsigned int /* width */, + unsigned int /* height */, + unsigned int* /* width_return */, + unsigned int* /* height_return */ +); + +extern Status XQueryBestSize( + Display* /* display */, + int /* class */, + Drawable /* which_screen */, + unsigned int /* width */, + unsigned int /* height */, + unsigned int* /* width_return */, + unsigned int* /* height_return */ +); + +extern Status XQueryBestStipple( + Display* /* display */, + Drawable /* which_screen */, + unsigned int /* width */, + unsigned int /* height */, + unsigned int* /* width_return */, + unsigned int* /* height_return */ +); + +extern Status XQueryBestTile( + Display* /* display */, + Drawable /* which_screen */, + unsigned int /* width */, + unsigned int /* height */, + unsigned int* /* width_return */, + unsigned int* /* height_return */ +); + +extern int XQueryColor( + Display* /* display */, + Colormap /* colormap */, + XColor* /* def_in_out */ +); + +extern int XQueryColors( + Display* /* display */, + Colormap /* colormap */, + XColor* /* defs_in_out */, + int /* ncolors */ +); + +extern Bool XQueryExtension( + Display* /* display */, + _Xconst char* /* name */, + int* /* major_opcode_return */, + int* /* first_event_return */, + int* /* first_error_return */ +); + +extern int XQueryKeymap( + Display* /* display */, + char [32] /* keys_return */ +); + +extern Bool XQueryPointer( + Display* /* display */, + Window /* w */, + Window* /* root_return */, + Window* /* child_return */, + int* /* root_x_return */, + int* /* root_y_return */, + int* /* win_x_return */, + int* /* win_y_return */, + unsigned int* /* mask_return */ +); + +extern int XQueryTextExtents( + Display* /* display */, + XID /* font_ID */, + _Xconst char* /* string */, + int /* nchars */, + int* /* direction_return */, + int* /* font_ascent_return */, + int* /* font_descent_return */, + XCharStruct* /* overall_return */ +); + +extern int XQueryTextExtents16( + Display* /* display */, + XID /* font_ID */, + _Xconst XChar2b* /* string */, + int /* nchars */, + int* /* direction_return */, + int* /* font_ascent_return */, + int* /* font_descent_return */, + XCharStruct* /* overall_return */ +); + +extern Status XQueryTree( + Display* /* display */, + Window /* w */, + Window* /* root_return */, + Window* /* parent_return */, + Window** /* children_return */, + unsigned int* /* nchildren_return */ +); + +extern int XRaiseWindow( + Display* /* display */, + Window /* w */ +); + +extern int XReadBitmapFile( + Display* /* display */, + Drawable /* d */, + _Xconst char* /* filename */, + unsigned int* /* width_return */, + unsigned int* /* height_return */, + Pixmap* /* bitmap_return */, + int* /* x_hot_return */, + int* /* y_hot_return */ +); + +extern int XReadBitmapFileData( + _Xconst char* /* filename */, + unsigned int* /* width_return */, + unsigned int* /* height_return */, + unsigned char** /* data_return */, + int* /* x_hot_return */, + int* /* y_hot_return */ +); + +extern int XRebindKeysym( + Display* /* display */, + KeySym /* keysym */, + KeySym* /* list */, + int /* mod_count */, + _Xconst unsigned char* /* string */, + int /* bytes_string */ +); + +extern int XRecolorCursor( + Display* /* display */, + Cursor /* cursor */, + XColor* /* foreground_color */, + XColor* /* background_color */ +); + +extern int XRefreshKeyboardMapping( + XMappingEvent* /* event_map */ +); + +extern int XRemoveFromSaveSet( + Display* /* display */, + Window /* w */ +); + +extern int XRemoveHost( + Display* /* display */, + XHostAddress* /* host */ +); + +extern int XRemoveHosts( + Display* /* display */, + XHostAddress* /* hosts */, + int /* num_hosts */ +); + +extern int XReparentWindow( + Display* /* display */, + Window /* w */, + Window /* parent */, + int /* x */, + int /* y */ +); + +extern int XResetScreenSaver( + Display* /* display */ +); + +extern int XResizeWindow( + Display* /* display */, + Window /* w */, + unsigned int /* width */, + unsigned int /* height */ +); + +extern int XRestackWindows( + Display* /* display */, + Window* /* windows */, + int /* nwindows */ +); + +extern int XRotateBuffers( + Display* /* display */, + int /* rotate */ +); + +extern int XRotateWindowProperties( + Display* /* display */, + Window /* w */, + Atom* /* properties */, + int /* num_prop */, + int /* npositions */ +); + +extern int XScreenCount( + Display* /* display */ +); + +extern int XSelectInput( + Display* /* display */, + Window /* w */, + long /* event_mask */ +); + +extern Status XSendEvent( + Display* /* display */, + Window /* w */, + Bool /* propagate */, + long /* event_mask */, + XEvent* /* event_send */ +); + +extern int XSetAccessControl( + Display* /* display */, + int /* mode */ +); + +extern int XSetArcMode( + Display* /* display */, + GC /* gc */, + int /* arc_mode */ +); + +extern int XSetBackground( + Display* /* display */, + GC /* gc */, + unsigned long /* background */ +); + +extern int XSetClipMask( + Display* /* display */, + GC /* gc */, + Pixmap /* pixmap */ +); + +extern int XSetClipOrigin( + Display* /* display */, + GC /* gc */, + int /* clip_x_origin */, + int /* clip_y_origin */ +); + +extern int XSetClipRectangles( + Display* /* display */, + GC /* gc */, + int /* clip_x_origin */, + int /* clip_y_origin */, + XRectangle* /* rectangles */, + int /* n */, + int /* ordering */ +); + +extern int XSetCloseDownMode( + Display* /* display */, + int /* close_mode */ +); + +extern int XSetCommand( + Display* /* display */, + Window /* w */, + char** /* argv */, + int /* argc */ +); + +extern int XSetDashes( + Display* /* display */, + GC /* gc */, + int /* dash_offset */, + _Xconst char* /* dash_list */, + int /* n */ +); + +extern int XSetFillRule( + Display* /* display */, + GC /* gc */, + int /* fill_rule */ +); + +extern int XSetFillStyle( + Display* /* display */, + GC /* gc */, + int /* fill_style */ +); + +extern int XSetFont( + Display* /* display */, + GC /* gc */, + Font /* font */ +); + +extern int XSetFontPath( + Display* /* display */, + char** /* directories */, + int /* ndirs */ +); + +extern int XSetForeground( + Display* /* display */, + GC /* gc */, + unsigned long /* foreground */ +); + +extern int XSetFunction( + Display* /* display */, + GC /* gc */, + int /* function */ +); + +extern int XSetGraphicsExposures( + Display* /* display */, + GC /* gc */, + Bool /* graphics_exposures */ +); + +extern int XSetIconName( + Display* /* display */, + Window /* w */, + _Xconst char* /* icon_name */ +); + +extern int XSetInputFocus( + Display* /* display */, + Window /* focus */, + int /* revert_to */, + Time /* time */ +); + +extern int XSetLineAttributes( + Display* /* display */, + GC /* gc */, + unsigned int /* line_width */, + int /* line_style */, + int /* cap_style */, + int /* join_style */ +); + +extern int XSetModifierMapping( + Display* /* display */, + XModifierKeymap* /* modmap */ +); + +extern int XSetPlaneMask( + Display* /* display */, + GC /* gc */, + unsigned long /* plane_mask */ +); + +extern int XSetPointerMapping( + Display* /* display */, + _Xconst unsigned char* /* map */, + int /* nmap */ +); + +extern int XSetScreenSaver( + Display* /* display */, + int /* timeout */, + int /* interval */, + int /* prefer_blanking */, + int /* allow_exposures */ +); + +extern int XSetSelectionOwner( + Display* /* display */, + Atom /* selection */, + Window /* owner */, + Time /* time */ +); + +extern int XSetState( + Display* /* display */, + GC /* gc */, + unsigned long /* foreground */, + unsigned long /* background */, + int /* function */, + unsigned long /* plane_mask */ +); + +extern int XSetStipple( + Display* /* display */, + GC /* gc */, + Pixmap /* stipple */ +); + +extern int XSetSubwindowMode( + Display* /* display */, + GC /* gc */, + int /* subwindow_mode */ +); + +extern int XSetTSOrigin( + Display* /* display */, + GC /* gc */, + int /* ts_x_origin */, + int /* ts_y_origin */ +); + +extern int XSetTile( + Display* /* display */, + GC /* gc */, + Pixmap /* tile */ +); + +extern int XSetWindowBackground( + Display* /* display */, + Window /* w */, + unsigned long /* background_pixel */ +); + +extern int XSetWindowBackgroundPixmap( + Display* /* display */, + Window /* w */, + Pixmap /* background_pixmap */ +); + +extern int XSetWindowBorder( + Display* /* display */, + Window /* w */, + unsigned long /* border_pixel */ +); + +extern int XSetWindowBorderPixmap( + Display* /* display */, + Window /* w */, + Pixmap /* border_pixmap */ +); + +extern int XSetWindowBorderWidth( + Display* /* display */, + Window /* w */, + unsigned int /* width */ +); + +extern int XSetWindowColormap( + Display* /* display */, + Window /* w */, + Colormap /* colormap */ +); + +extern int XStoreBuffer( + Display* /* display */, + _Xconst char* /* bytes */, + int /* nbytes */, + int /* buffer */ +); + +extern int XStoreBytes( + Display* /* display */, + _Xconst char* /* bytes */, + int /* nbytes */ +); + +extern int XStoreColor( + Display* /* display */, + Colormap /* colormap */, + XColor* /* color */ +); + +extern int XStoreColors( + Display* /* display */, + Colormap /* colormap */, + XColor* /* color */, + int /* ncolors */ +); + +extern int XStoreName( + Display* /* display */, + Window /* w */, + _Xconst char* /* window_name */ +); + +extern int XStoreNamedColor( + Display* /* display */, + Colormap /* colormap */, + _Xconst char* /* color */, + unsigned long /* pixel */, + int /* flags */ +); + +extern int XSync( + Display* /* display */, + Bool /* discard */ +); + +extern int XTextExtents( + XFontStruct* /* font_struct */, + _Xconst char* /* string */, + int /* nchars */, + int* /* direction_return */, + int* /* font_ascent_return */, + int* /* font_descent_return */, + XCharStruct* /* overall_return */ +); + +extern int XTextExtents16( + XFontStruct* /* font_struct */, + _Xconst XChar2b* /* string */, + int /* nchars */, + int* /* direction_return */, + int* /* font_ascent_return */, + int* /* font_descent_return */, + XCharStruct* /* overall_return */ +); + +extern int XTextWidth( + XFontStruct* /* font_struct */, + _Xconst char* /* string */, + int /* count */ +); + +extern int XTextWidth16( + XFontStruct* /* font_struct */, + _Xconst XChar2b* /* string */, + int /* count */ +); + +extern Bool XTranslateCoordinates( + Display* /* display */, + Window /* src_w */, + Window /* dest_w */, + int /* src_x */, + int /* src_y */, + int* /* dest_x_return */, + int* /* dest_y_return */, + Window* /* child_return */ +); + +extern int XUndefineCursor( + Display* /* display */, + Window /* w */ +); + +extern int XUngrabButton( + Display* /* display */, + unsigned int /* button */, + unsigned int /* modifiers */, + Window /* grab_window */ +); + +extern int XUngrabKey( + Display* /* display */, + int /* keycode */, + unsigned int /* modifiers */, + Window /* grab_window */ +); + +extern int XUngrabKeyboard( + Display* /* display */, + Time /* time */ +); + +extern int XUngrabPointer( + Display* /* display */, + Time /* time */ +); + +extern int XUngrabServer( + Display* /* display */ +); + +extern int XUninstallColormap( + Display* /* display */, + Colormap /* colormap */ +); + +extern int XUnloadFont( + Display* /* display */, + Font /* font */ +); + +extern int XUnmapSubwindows( + Display* /* display */, + Window /* w */ +); + +extern int XUnmapWindow( + Display* /* display */, + Window /* w */ +); + +extern int XVendorRelease( + Display* /* display */ +); + +extern int XWarpPointer( + Display* /* display */, + Window /* src_w */, + Window /* dest_w */, + int /* src_x */, + int /* src_y */, + unsigned int /* src_width */, + unsigned int /* src_height */, + int /* dest_x */, + int /* dest_y */ +); + +extern int XWidthMMOfScreen( + Screen* /* screen */ +); + +extern int XWidthOfScreen( + Screen* /* screen */ +); + +extern int XWindowEvent( + Display* /* display */, + Window /* w */, + long /* event_mask */, + XEvent* /* event_return */ +); + +extern int XWriteBitmapFile( + Display* /* display */, + _Xconst char* /* filename */, + Pixmap /* bitmap */, + unsigned int /* width */, + unsigned int /* height */, + int /* x_hot */, + int /* y_hot */ +); + +extern Bool XSupportsLocale (void); + +extern char *XSetLocaleModifiers( + const char* /* modifier_list */ +); + +extern XOM XOpenOM( + Display* /* display */, + struct _XrmHashBucketRec* /* rdb */, + _Xconst char* /* res_name */, + _Xconst char* /* res_class */ +); + +extern Status XCloseOM( + XOM /* om */ +); + +extern char *XSetOMValues( + XOM /* om */, + ... +) _X_SENTINEL(0); + +extern char *XGetOMValues( + XOM /* om */, + ... +) _X_SENTINEL(0); + +extern Display *XDisplayOfOM( + XOM /* om */ +); + +extern char *XLocaleOfOM( + XOM /* om */ +); + +extern XOC XCreateOC( + XOM /* om */, + ... +) _X_SENTINEL(0); + +extern void XDestroyOC( + XOC /* oc */ +); + +extern XOM XOMOfOC( + XOC /* oc */ +); + +extern char *XSetOCValues( + XOC /* oc */, + ... +) _X_SENTINEL(0); + +extern char *XGetOCValues( + XOC /* oc */, + ... +) _X_SENTINEL(0); + +extern XFontSet XCreateFontSet( + Display* /* display */, + _Xconst char* /* base_font_name_list */, + char*** /* missing_charset_list */, + int* /* missing_charset_count */, + char** /* def_string */ +); + +extern void XFreeFontSet( + Display* /* display */, + XFontSet /* font_set */ +); + +extern int XFontsOfFontSet( + XFontSet /* font_set */, + XFontStruct*** /* font_struct_list */, + char*** /* font_name_list */ +); + +extern char *XBaseFontNameListOfFontSet( + XFontSet /* font_set */ +); + +extern char *XLocaleOfFontSet( + XFontSet /* font_set */ +); + +extern Bool XContextDependentDrawing( + XFontSet /* font_set */ +); + +extern Bool XDirectionalDependentDrawing( + XFontSet /* font_set */ +); + +extern Bool XContextualDrawing( + XFontSet /* font_set */ +); + +extern XFontSetExtents *XExtentsOfFontSet( + XFontSet /* font_set */ +); + +extern int XmbTextEscapement( + XFontSet /* font_set */, + _Xconst char* /* text */, + int /* bytes_text */ +); + +extern int XwcTextEscapement( + XFontSet /* font_set */, + _Xconst wchar_t* /* text */, + int /* num_wchars */ +); + +extern int Xutf8TextEscapement( + XFontSet /* font_set */, + _Xconst char* /* text */, + int /* bytes_text */ +); + +extern int XmbTextExtents( + XFontSet /* font_set */, + _Xconst char* /* text */, + int /* bytes_text */, + XRectangle* /* overall_ink_return */, + XRectangle* /* overall_logical_return */ +); + +extern int XwcTextExtents( + XFontSet /* font_set */, + _Xconst wchar_t* /* text */, + int /* num_wchars */, + XRectangle* /* overall_ink_return */, + XRectangle* /* overall_logical_return */ +); + +extern int Xutf8TextExtents( + XFontSet /* font_set */, + _Xconst char* /* text */, + int /* bytes_text */, + XRectangle* /* overall_ink_return */, + XRectangle* /* overall_logical_return */ +); + +extern Status XmbTextPerCharExtents( + XFontSet /* font_set */, + _Xconst char* /* text */, + int /* bytes_text */, + XRectangle* /* ink_extents_buffer */, + XRectangle* /* logical_extents_buffer */, + int /* buffer_size */, + int* /* num_chars */, + XRectangle* /* overall_ink_return */, + XRectangle* /* overall_logical_return */ +); + +extern Status XwcTextPerCharExtents( + XFontSet /* font_set */, + _Xconst wchar_t* /* text */, + int /* num_wchars */, + XRectangle* /* ink_extents_buffer */, + XRectangle* /* logical_extents_buffer */, + int /* buffer_size */, + int* /* num_chars */, + XRectangle* /* overall_ink_return */, + XRectangle* /* overall_logical_return */ +); + +extern Status Xutf8TextPerCharExtents( + XFontSet /* font_set */, + _Xconst char* /* text */, + int /* bytes_text */, + XRectangle* /* ink_extents_buffer */, + XRectangle* /* logical_extents_buffer */, + int /* buffer_size */, + int* /* num_chars */, + XRectangle* /* overall_ink_return */, + XRectangle* /* overall_logical_return */ +); + +extern void XmbDrawText( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + XmbTextItem* /* text_items */, + int /* nitems */ +); + +extern void XwcDrawText( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + XwcTextItem* /* text_items */, + int /* nitems */ +); + +extern void Xutf8DrawText( + Display* /* display */, + Drawable /* d */, + GC /* gc */, + int /* x */, + int /* y */, + XmbTextItem* /* text_items */, + int /* nitems */ +); + +extern void XmbDrawString( + Display* /* display */, + Drawable /* d */, + XFontSet /* font_set */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst char* /* text */, + int /* bytes_text */ +); + +extern void XwcDrawString( + Display* /* display */, + Drawable /* d */, + XFontSet /* font_set */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst wchar_t* /* text */, + int /* num_wchars */ +); + +extern void Xutf8DrawString( + Display* /* display */, + Drawable /* d */, + XFontSet /* font_set */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst char* /* text */, + int /* bytes_text */ +); + +extern void XmbDrawImageString( + Display* /* display */, + Drawable /* d */, + XFontSet /* font_set */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst char* /* text */, + int /* bytes_text */ +); + +extern void XwcDrawImageString( + Display* /* display */, + Drawable /* d */, + XFontSet /* font_set */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst wchar_t* /* text */, + int /* num_wchars */ +); + +extern void Xutf8DrawImageString( + Display* /* display */, + Drawable /* d */, + XFontSet /* font_set */, + GC /* gc */, + int /* x */, + int /* y */, + _Xconst char* /* text */, + int /* bytes_text */ +); + +extern XIM XOpenIM( + Display* /* dpy */, + struct _XrmHashBucketRec* /* rdb */, + char* /* res_name */, + char* /* res_class */ +); + +extern Status XCloseIM( + XIM /* im */ +); + +extern char *XGetIMValues( + XIM /* im */, ... +) _X_SENTINEL(0); + +extern char *XSetIMValues( + XIM /* im */, ... +) _X_SENTINEL(0); + +extern Display *XDisplayOfIM( + XIM /* im */ +); + +extern char *XLocaleOfIM( + XIM /* im*/ +); + +extern XIC XCreateIC( + XIM /* im */, ... +) _X_SENTINEL(0); + +extern void XDestroyIC( + XIC /* ic */ +); + +extern void XSetICFocus( + XIC /* ic */ +); + +extern void XUnsetICFocus( + XIC /* ic */ +); + +extern wchar_t *XwcResetIC( + XIC /* ic */ +); + +extern char *XmbResetIC( + XIC /* ic */ +); + +extern char *Xutf8ResetIC( + XIC /* ic */ +); + +extern char *XSetICValues( + XIC /* ic */, ... +) _X_SENTINEL(0); + +extern char *XGetICValues( + XIC /* ic */, ... +) _X_SENTINEL(0); + +extern XIM XIMOfIC( + XIC /* ic */ +); + +extern Bool XFilterEvent( + XEvent* /* event */, + Window /* window */ +); + +extern int XmbLookupString( + XIC /* ic */, + XKeyPressedEvent* /* event */, + char* /* buffer_return */, + int /* bytes_buffer */, + KeySym* /* keysym_return */, + Status* /* status_return */ +); + +extern int XwcLookupString( + XIC /* ic */, + XKeyPressedEvent* /* event */, + wchar_t* /* buffer_return */, + int /* wchars_buffer */, + KeySym* /* keysym_return */, + Status* /* status_return */ +); + +extern int Xutf8LookupString( + XIC /* ic */, + XKeyPressedEvent* /* event */, + char* /* buffer_return */, + int /* bytes_buffer */, + KeySym* /* keysym_return */, + Status* /* status_return */ +); + +extern XVaNestedList XVaCreateNestedList( + int /*unused*/, ... +) _X_SENTINEL(0); + +/* internal connections for IMs */ + +extern Bool XRegisterIMInstantiateCallback( + Display* /* dpy */, + struct _XrmHashBucketRec* /* rdb */, + char* /* res_name */, + char* /* res_class */, + XIDProc /* callback */, + XPointer /* client_data */ +); + +extern Bool XUnregisterIMInstantiateCallback( + Display* /* dpy */, + struct _XrmHashBucketRec* /* rdb */, + char* /* res_name */, + char* /* res_class */, + XIDProc /* callback */, + XPointer /* client_data */ +); + +typedef void (*XConnectionWatchProc)( + Display* /* dpy */, + XPointer /* client_data */, + int /* fd */, + Bool /* opening */, /* open or close flag */ + XPointer* /* watch_data */ /* open sets, close uses */ +); + + +extern Status XInternalConnectionNumbers( + Display* /* dpy */, + int** /* fd_return */, + int* /* count_return */ +); + +extern void XProcessInternalConnection( + Display* /* dpy */, + int /* fd */ +); + +extern Status XAddConnectionWatch( + Display* /* dpy */, + XConnectionWatchProc /* callback */, + XPointer /* client_data */ +); + +extern void XRemoveConnectionWatch( + Display* /* dpy */, + XConnectionWatchProc /* callback */, + XPointer /* client_data */ +); + +extern void XSetAuthorization( + char * /* name */, + int /* namelen */, + char * /* data */, + int /* datalen */ +); + +extern int _Xmbtowc( + wchar_t * /* wstr */, +#ifdef ISC + char const * /* str */, + size_t /* len */ +#else + char * /* str */, + int /* len */ +#endif +); + +extern int _Xwctomb( + char * /* str */, + wchar_t /* wc */ +); + +extern Bool XGetEventData( + Display* /* dpy */, + XGenericEventCookie* /* cookie*/ +); + +extern void XFreeEventData( + Display* /* dpy */, + XGenericEventCookie* /* cookie*/ +); + +_XFUNCPROTOEND + +#endif /* _XLIB_H_ */ diff --git a/system/include/X11/Xosdefs.h b/system/include/X11/Xosdefs.h new file mode 100644 index 00000000..33eaee43 --- /dev/null +++ b/system/include/X11/Xosdefs.h @@ -0,0 +1,116 @@ +/* + * O/S-dependent (mis)feature macro definitions + * +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +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 +OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + */ + +#ifndef _XOSDEFS_H_ +# define _XOSDEFS_H_ + +/* + * X_NOT_POSIX means does not have POSIX header files. Lack of this + * symbol does NOT mean that the POSIX environment is the default. + * You may still have to define _POSIX_SOURCE to get it. + */ + + +# ifdef _SCO_DS +# ifndef __SCO__ +# define __SCO__ +# endif +# endif + +# ifdef __i386__ +# ifdef SYSV +# if !defined(__SCO__) && \ + !defined(__UNIXWARE__) && !defined(__sun) +# if !defined(_POSIX_SOURCE) +# define X_NOT_POSIX +# endif +# endif +# endif +# endif + +# ifdef __sun +/* Imake configs define SVR4 on Solaris, but cc & gcc only define __SVR4 + * This check allows non-Imake configured programs to build correctly. + */ +# if defined(__SVR4) && !defined(SVR4) +# define SVR4 1 +# endif +# ifdef SVR4 +/* define this to whatever it needs to be */ +# define X_POSIX_C_SOURCE 199300L +# endif +# endif + +# ifdef WIN32 +# ifndef _POSIX_ +# define X_NOT_POSIX +# endif +# endif + + +# ifdef __APPLE__ +# define NULL_NOT_ZERO + +/* Defining any of these will sanitize the namespace to JUST want is defined by + * that particular standard. If that happens, we don't get some expected + * prototypes, typedefs, etc (like fd_mask). We can define _DARWIN_C_SOURCE to + * loosen our belts a tad. + */ +# if defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) +# ifndef _DARWIN_C_SOURCE +# define _DARWIN_C_SOURCE +# endif +# endif + +# endif + +# ifdef __GNU__ +# ifndef PATH_MAX +# define PATH_MAX 4096 +# endif +# ifndef MAXPATHLEN +# define MAXPATHLEN 4096 +# endif +# endif + +# if defined(__SCO__) || defined(__UNIXWARE__) +# ifndef PATH_MAX +# define PATH_MAX 1024 +# endif +# ifndef MAXPATHLEN +# define MAXPATHLEN 1024 +# endif +# endif + +# if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) \ + || defined(__APPLE__) || defined(__DragonFly__) +# ifndef CSRG_BASED +# define CSRG_BASED +# endif +# endif + +#endif /* _XOSDEFS_H_ */ + diff --git a/system/include/X11/Xutil.h b/system/include/X11/Xutil.h new file mode 100644 index 00000000..8ff34d9f --- /dev/null +++ b/system/include/X11/Xutil.h @@ -0,0 +1,826 @@ + +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +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 +OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, 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. + +******************************************************************/ + +#ifndef _XUTIL_H_ +#define _XUTIL_H_ + +/* You must include <X11/Xlib.h> before including this file */ +#include <X11/Xlib.h> +#include <X11/keysym.h> + +/* + * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding + * value (x, y, width, height) was found in the parsed string. + */ +#define NoValue 0x0000 +#define XValue 0x0001 +#define YValue 0x0002 +#define WidthValue 0x0004 +#define HeightValue 0x0008 +#define AllValues 0x000F +#define XNegative 0x0010 +#define YNegative 0x0020 + +/* + * new version containing base_width, base_height, and win_gravity fields; + * used with WM_NORMAL_HINTS. + */ +typedef struct { + long flags; /* marks which fields in this structure are defined */ + int x, y; /* obsolete for new window mgrs, but clients */ + int width, height; /* should set so old wm's don't mess up */ + int min_width, min_height; + int max_width, max_height; + int width_inc, height_inc; + struct { + int x; /* numerator */ + int y; /* denominator */ + } min_aspect, max_aspect; + int base_width, base_height; /* added by ICCCM version 1 */ + int win_gravity; /* added by ICCCM version 1 */ +} XSizeHints; + +/* + * The next block of definitions are for window manager properties that + * clients and applications use for communication. + */ + +/* flags argument in size hints */ +#define USPosition (1L << 0) /* user specified x, y */ +#define USSize (1L << 1) /* user specified width, height */ + +#define PPosition (1L << 2) /* program specified position */ +#define PSize (1L << 3) /* program specified size */ +#define PMinSize (1L << 4) /* program specified minimum size */ +#define PMaxSize (1L << 5) /* program specified maximum size */ +#define PResizeInc (1L << 6) /* program specified resize increments */ +#define PAspect (1L << 7) /* program specified min and max aspect ratios */ +#define PBaseSize (1L << 8) /* program specified base for incrementing */ +#define PWinGravity (1L << 9) /* program specified window gravity */ + +/* obsolete */ +#define PAllHints (PPosition|PSize|PMinSize|PMaxSize|PResizeInc|PAspect) + + + +typedef struct { + long flags; /* marks which fields in this structure are defined */ + Bool input; /* does this application rely on the window manager to + get keyboard input? */ + int initial_state; /* see below */ + Pixmap icon_pixmap; /* pixmap to be used as icon */ + Window icon_window; /* window to be used as icon */ + int icon_x, icon_y; /* initial position of icon */ + Pixmap icon_mask; /* icon mask bitmap */ + XID window_group; /* id of related window group */ + /* this structure may be extended in the future */ +} XWMHints; + +/* definition for flags of XWMHints */ + +#define InputHint (1L << 0) +#define StateHint (1L << 1) +#define IconPixmapHint (1L << 2) +#define IconWindowHint (1L << 3) +#define IconPositionHint (1L << 4) +#define IconMaskHint (1L << 5) +#define WindowGroupHint (1L << 6) +#define AllHints (InputHint|StateHint|IconPixmapHint|IconWindowHint| \ +IconPositionHint|IconMaskHint|WindowGroupHint) +#define XUrgencyHint (1L << 8) + +/* definitions for initial window state */ +#define WithdrawnState 0 /* for windows that are not mapped */ +#define NormalState 1 /* most applications want to start this way */ +#define IconicState 3 /* application wants to start as an icon */ + +/* + * Obsolete states no longer defined by ICCCM + */ +#define DontCareState 0 /* don't know or care */ +#define ZoomState 2 /* application wants to start zoomed */ +#define InactiveState 4 /* application believes it is seldom used; */ + /* some wm's may put it on inactive menu */ + + +/* + * new structure for manipulating TEXT properties; used with WM_NAME, + * WM_ICON_NAME, WM_CLIENT_MACHINE, and WM_COMMAND. + */ +typedef struct { + unsigned char *value; /* same as Property routines */ + Atom encoding; /* prop type */ + int format; /* prop data format: 8, 16, or 32 */ + unsigned long nitems; /* number of data items in value */ +} XTextProperty; + +#define XNoMemory -1 +#define XLocaleNotSupported -2 +#define XConverterNotFound -3 + +typedef enum { + XStringStyle, /* STRING */ + XCompoundTextStyle, /* COMPOUND_TEXT */ + XTextStyle, /* text in owner's encoding (current locale)*/ + XStdICCTextStyle, /* STRING, else COMPOUND_TEXT */ + /* The following is an XFree86 extension, introduced in November 2000 */ + XUTF8StringStyle /* UTF8_STRING */ +} XICCEncodingStyle; + +typedef struct { + int min_width, min_height; + int max_width, max_height; + int width_inc, height_inc; +} XIconSize; + +typedef struct { + char *res_name; + char *res_class; +} XClassHint; + +#ifdef XUTIL_DEFINE_FUNCTIONS +extern int XDestroyImage( + XImage *ximage); +extern unsigned long XGetPixel( + XImage *ximage, + int x, int y); +extern int XPutPixel( + XImage *ximage, + int x, int y, + unsigned long pixel); +extern XImage *XSubImage( + XImage *ximage, + int x, int y, + unsigned int width, unsigned int height); +extern int XAddPixel( + XImage *ximage, + long value); +#else +/* + * These macros are used to give some sugar to the image routines so that + * naive people are more comfortable with them. + */ +#define XDestroyImage(ximage) \ + ((*((ximage)->f.destroy_image))((ximage))) +#define XGetPixel(ximage, x, y) \ + ((*((ximage)->f.get_pixel))((ximage), (x), (y))) +#define XPutPixel(ximage, x, y, pixel) \ + ((*((ximage)->f.put_pixel))((ximage), (x), (y), (pixel))) +#define XSubImage(ximage, x, y, width, height) \ + ((*((ximage)->f.sub_image))((ximage), (x), (y), (width), (height))) +#define XAddPixel(ximage, value) \ + ((*((ximage)->f.add_pixel))((ximage), (value))) +#endif + +/* + * Compose sequence status structure, used in calling XLookupString. + */ +typedef struct _XComposeStatus { + XPointer compose_ptr; /* state table pointer */ + int chars_matched; /* match state */ +} XComposeStatus; + +/* + * Keysym macros, used on Keysyms to test for classes of symbols + */ +#define IsKeypadKey(keysym) \ + (((KeySym)(keysym) >= XK_KP_Space) && ((KeySym)(keysym) <= XK_KP_Equal)) + +#define IsPrivateKeypadKey(keysym) \ + (((KeySym)(keysym) >= 0x11000000) && ((KeySym)(keysym) <= 0x1100FFFF)) + +#define IsCursorKey(keysym) \ + (((KeySym)(keysym) >= XK_Home) && ((KeySym)(keysym) < XK_Select)) + +#define IsPFKey(keysym) \ + (((KeySym)(keysym) >= XK_KP_F1) && ((KeySym)(keysym) <= XK_KP_F4)) + +#define IsFunctionKey(keysym) \ + (((KeySym)(keysym) >= XK_F1) && ((KeySym)(keysym) <= XK_F35)) + +#define IsMiscFunctionKey(keysym) \ + (((KeySym)(keysym) >= XK_Select) && ((KeySym)(keysym) <= XK_Break)) + +#ifdef XK_XKB_KEYS +#define IsModifierKey(keysym) \ + ((((KeySym)(keysym) >= XK_Shift_L) && ((KeySym)(keysym) <= XK_Hyper_R)) \ + || (((KeySym)(keysym) >= XK_ISO_Lock) && \ + ((KeySym)(keysym) <= XK_ISO_Last_Group_Lock)) \ + || ((KeySym)(keysym) == XK_Mode_switch) \ + || ((KeySym)(keysym) == XK_Num_Lock)) +#else +#define IsModifierKey(keysym) \ + ((((KeySym)(keysym) >= XK_Shift_L) && ((KeySym)(keysym) <= XK_Hyper_R)) \ + || ((KeySym)(keysym) == XK_Mode_switch) \ + || ((KeySym)(keysym) == XK_Num_Lock)) +#endif +/* + * opaque reference to Region data type + */ +typedef struct _XRegion *Region; + +/* Return values from XRectInRegion() */ + +#define RectangleOut 0 +#define RectangleIn 1 +#define RectanglePart 2 + + +/* + * Information used by the visual utility routines to find desired visual + * type from the many visuals a display may support. + */ + +typedef struct { + Visual *visual; + VisualID visualid; + int screen; + int depth; +#if defined(__cplusplus) || defined(c_plusplus) + int c_class; /* C++ */ +#else + int class; +#endif + unsigned long red_mask; + unsigned long green_mask; + unsigned long blue_mask; + int colormap_size; + int bits_per_rgb; +} XVisualInfo; + +#define VisualNoMask 0x0 +#define VisualIDMask 0x1 +#define VisualScreenMask 0x2 +#define VisualDepthMask 0x4 +#define VisualClassMask 0x8 +#define VisualRedMaskMask 0x10 +#define VisualGreenMaskMask 0x20 +#define VisualBlueMaskMask 0x40 +#define VisualColormapSizeMask 0x80 +#define VisualBitsPerRGBMask 0x100 +#define VisualAllMask 0x1FF + +/* + * This defines a window manager property that clients may use to + * share standard color maps of type RGB_COLOR_MAP: + */ +typedef struct { + Colormap colormap; + unsigned long red_max; + unsigned long red_mult; + unsigned long green_max; + unsigned long green_mult; + unsigned long blue_max; + unsigned long blue_mult; + unsigned long base_pixel; + VisualID visualid; /* added by ICCCM version 1 */ + XID killid; /* added by ICCCM version 1 */ +} XStandardColormap; + +#define ReleaseByFreeingColormap ((XID) 1L) /* for killid field above */ + + +/* + * return codes for XReadBitmapFile and XWriteBitmapFile + */ +#define BitmapSuccess 0 +#define BitmapOpenFailed 1 +#define BitmapFileInvalid 2 +#define BitmapNoMemory 3 + +/**************************************************************** + * + * Context Management + * + ****************************************************************/ + + +/* Associative lookup table return codes */ + +#define XCSUCCESS 0 /* No error. */ +#define XCNOMEM 1 /* Out of memory */ +#define XCNOENT 2 /* No entry in table */ + +typedef int XContext; + +#define XUniqueContext() ((XContext) XrmUniqueQuark()) +#define XStringToContext(string) ((XContext) XrmStringToQuark(string)) + +_XFUNCPROTOBEGIN + +/* The following declarations are alphabetized. */ + +extern XClassHint *XAllocClassHint ( + void +); + +extern XIconSize *XAllocIconSize ( + void +); + +extern XSizeHints *XAllocSizeHints ( + void +); + +extern XStandardColormap *XAllocStandardColormap ( + void +); + +extern XWMHints *XAllocWMHints ( + void +); + +extern int XClipBox( + Region /* r */, + XRectangle* /* rect_return */ +); + +extern Region XCreateRegion( + void +); + +extern const char *XDefaultString (void); + +extern int XDeleteContext( + Display* /* display */, + XID /* rid */, + XContext /* context */ +); + +extern int XDestroyRegion( + Region /* r */ +); + +extern int XEmptyRegion( + Region /* r */ +); + +extern int XEqualRegion( + Region /* r1 */, + Region /* r2 */ +); + +extern int XFindContext( + Display* /* display */, + XID /* rid */, + XContext /* context */, + XPointer* /* data_return */ +); + +extern Status XGetClassHint( + Display* /* display */, + Window /* w */, + XClassHint* /* class_hints_return */ +); + +extern Status XGetIconSizes( + Display* /* display */, + Window /* w */, + XIconSize** /* size_list_return */, + int* /* count_return */ +); + +extern Status XGetNormalHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* hints_return */ +); + +extern Status XGetRGBColormaps( + Display* /* display */, + Window /* w */, + XStandardColormap** /* stdcmap_return */, + int* /* count_return */, + Atom /* property */ +); + +extern Status XGetSizeHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* hints_return */, + Atom /* property */ +); + +extern Status XGetStandardColormap( + Display* /* display */, + Window /* w */, + XStandardColormap* /* colormap_return */, + Atom /* property */ +); + +extern Status XGetTextProperty( + Display* /* display */, + Window /* window */, + XTextProperty* /* text_prop_return */, + Atom /* property */ +); + +extern XVisualInfo *XGetVisualInfo( + Display* /* display */, + long /* vinfo_mask */, + XVisualInfo* /* vinfo_template */, + int* /* nitems_return */ +); + +extern Status XGetWMClientMachine( + Display* /* display */, + Window /* w */, + XTextProperty* /* text_prop_return */ +); + +extern XWMHints *XGetWMHints( + Display* /* display */, + Window /* w */ +); + +extern Status XGetWMIconName( + Display* /* display */, + Window /* w */, + XTextProperty* /* text_prop_return */ +); + +extern Status XGetWMName( + Display* /* display */, + Window /* w */, + XTextProperty* /* text_prop_return */ +); + +extern Status XGetWMNormalHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* hints_return */, + long* /* supplied_return */ +); + +extern Status XGetWMSizeHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* hints_return */, + long* /* supplied_return */, + Atom /* property */ +); + +extern Status XGetZoomHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* zhints_return */ +); + +extern int XIntersectRegion( + Region /* sra */, + Region /* srb */, + Region /* dr_return */ +); + +extern void XConvertCase( + KeySym /* sym */, + KeySym* /* lower */, + KeySym* /* upper */ +); + +extern int XLookupString( + XKeyEvent* /* event_struct */, + char* /* buffer_return */, + int /* bytes_buffer */, + KeySym* /* keysym_return */, + XComposeStatus* /* status_in_out */ +); + +extern Status XMatchVisualInfo( + Display* /* display */, + int /* screen */, + int /* depth */, + int /* class */, + XVisualInfo* /* vinfo_return */ +); + +extern int XOffsetRegion( + Region /* r */, + int /* dx */, + int /* dy */ +); + +extern Bool XPointInRegion( + Region /* r */, + int /* x */, + int /* y */ +); + +extern Region XPolygonRegion( + XPoint* /* points */, + int /* n */, + int /* fill_rule */ +); + +extern int XRectInRegion( + Region /* r */, + int /* x */, + int /* y */, + unsigned int /* width */, + unsigned int /* height */ +); + +extern int XSaveContext( + Display* /* display */, + XID /* rid */, + XContext /* context */, + _Xconst char* /* data */ +); + +extern int XSetClassHint( + Display* /* display */, + Window /* w */, + XClassHint* /* class_hints */ +); + +extern int XSetIconSizes( + Display* /* display */, + Window /* w */, + XIconSize* /* size_list */, + int /* count */ +); + +extern int XSetNormalHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* hints */ +); + +extern void XSetRGBColormaps( + Display* /* display */, + Window /* w */, + XStandardColormap* /* stdcmaps */, + int /* count */, + Atom /* property */ +); + +extern int XSetSizeHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* hints */, + Atom /* property */ +); + +extern int XSetStandardProperties( + Display* /* display */, + Window /* w */, + _Xconst char* /* window_name */, + _Xconst char* /* icon_name */, + Pixmap /* icon_pixmap */, + char** /* argv */, + int /* argc */, + XSizeHints* /* hints */ +); + +extern void XSetTextProperty( + Display* /* display */, + Window /* w */, + XTextProperty* /* text_prop */, + Atom /* property */ +); + +extern void XSetWMClientMachine( + Display* /* display */, + Window /* w */, + XTextProperty* /* text_prop */ +); + +extern int XSetWMHints( + Display* /* display */, + Window /* w */, + XWMHints* /* wm_hints */ +); + +extern void XSetWMIconName( + Display* /* display */, + Window /* w */, + XTextProperty* /* text_prop */ +); + +extern void XSetWMName( + Display* /* display */, + Window /* w */, + XTextProperty* /* text_prop */ +); + +extern void XSetWMNormalHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* hints */ +); + +extern void XSetWMProperties( + Display* /* display */, + Window /* w */, + XTextProperty* /* window_name */, + XTextProperty* /* icon_name */, + char** /* argv */, + int /* argc */, + XSizeHints* /* normal_hints */, + XWMHints* /* wm_hints */, + XClassHint* /* class_hints */ +); + +extern void XmbSetWMProperties( + Display* /* display */, + Window /* w */, + _Xconst char* /* window_name */, + _Xconst char* /* icon_name */, + char** /* argv */, + int /* argc */, + XSizeHints* /* normal_hints */, + XWMHints* /* wm_hints */, + XClassHint* /* class_hints */ +); + +extern void Xutf8SetWMProperties( + Display* /* display */, + Window /* w */, + _Xconst char* /* window_name */, + _Xconst char* /* icon_name */, + char** /* argv */, + int /* argc */, + XSizeHints* /* normal_hints */, + XWMHints* /* wm_hints */, + XClassHint* /* class_hints */ +); + +extern void XSetWMSizeHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* hints */, + Atom /* property */ +); + +extern int XSetRegion( + Display* /* display */, + GC /* gc */, + Region /* r */ +); + +extern void XSetStandardColormap( + Display* /* display */, + Window /* w */, + XStandardColormap* /* colormap */, + Atom /* property */ +); + +extern int XSetZoomHints( + Display* /* display */, + Window /* w */, + XSizeHints* /* zhints */ +); + +extern int XShrinkRegion( + Region /* r */, + int /* dx */, + int /* dy */ +); + +extern Status XStringListToTextProperty( + char** /* list */, + int /* count */, + XTextProperty* /* text_prop_return */ +); + +extern int XSubtractRegion( + Region /* sra */, + Region /* srb */, + Region /* dr_return */ +); + +extern int XmbTextListToTextProperty( + Display* display, + char** list, + int count, + XICCEncodingStyle style, + XTextProperty* text_prop_return +); + +extern int XwcTextListToTextProperty( + Display* display, + wchar_t** list, + int count, + XICCEncodingStyle style, + XTextProperty* text_prop_return +); + +extern int Xutf8TextListToTextProperty( + Display* display, + char** list, + int count, + XICCEncodingStyle style, + XTextProperty* text_prop_return +); + +extern void XwcFreeStringList( + wchar_t** list +); + +extern Status XTextPropertyToStringList( + XTextProperty* /* text_prop */, + char*** /* list_return */, + int* /* count_return */ +); + +extern int XmbTextPropertyToTextList( + Display* display, + const XTextProperty* text_prop, + char*** list_return, + int* count_return +); + +extern int XwcTextPropertyToTextList( + Display* display, + const XTextProperty* text_prop, + wchar_t*** list_return, + int* count_return +); + +extern int Xutf8TextPropertyToTextList( + Display* display, + const XTextProperty* text_prop, + char*** list_return, + int* count_return +); + +extern int XUnionRectWithRegion( + XRectangle* /* rectangle */, + Region /* src_region */, + Region /* dest_region_return */ +); + +extern int XUnionRegion( + Region /* sra */, + Region /* srb */, + Region /* dr_return */ +); + +extern int XWMGeometry( + Display* /* display */, + int /* screen_number */, + _Xconst char* /* user_geometry */, + _Xconst char* /* default_geometry */, + unsigned int /* border_width */, + XSizeHints* /* hints */, + int* /* x_return */, + int* /* y_return */, + int* /* width_return */, + int* /* height_return */, + int* /* gravity_return */ +); + +extern int XXorRegion( + Region /* sra */, + Region /* srb */, + Region /* dr_return */ +); + +_XFUNCPROTOEND + +#endif /* _XUTIL_H_ */ diff --git a/system/include/X11/keysym.h b/system/include/X11/keysym.h new file mode 100644 index 00000000..641b25bf --- /dev/null +++ b/system/include/X11/keysym.h @@ -0,0 +1,73 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +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 +OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, 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. + +******************************************************************/ + +/* default keysyms */ +#define XK_MISCELLANY +#define XK_XKB_KEYS +#define XK_LATIN1 +#define XK_LATIN2 +#define XK_LATIN3 +#define XK_LATIN4 +#define XK_LATIN8 +#define XK_LATIN9 +#define XK_CAUCASUS +#define XK_GREEK +#define XK_KATAKANA +#define XK_ARABIC +#define XK_CYRILLIC +#define XK_HEBREW +#define XK_THAI +#define XK_KOREAN +#define XK_ARMENIAN +#define XK_GEORGIAN +#define XK_VIETNAMESE +#define XK_CURRENCY +#define XK_MATHEMATICAL +#define XK_BRAILLE + +#include <X11/keysymdef.h> + diff --git a/system/include/X11/keysymdef.h b/system/include/X11/keysymdef.h new file mode 100644 index 00000000..ec125a65 --- /dev/null +++ b/system/include/X11/keysymdef.h @@ -0,0 +1,2389 @@ +/*********************************************************** +Copyright 1987, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +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 OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, 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. + +******************************************************************/ + +/* + * The "X11 Window System Protocol" standard defines in Appendix A the + * keysym codes. These 29-bit integer values identify characters or + * functions associated with each key (e.g., via the visible + * engraving) of a keyboard layout. This file assigns mnemonic macro + * names for these keysyms. + * + * This file is also compiled (by src/util/makekeys.c in libX11) into + * hash tables that can be accessed with X11 library functions such as + * XStringToKeysym() and XKeysymToString(). + * + * Where a keysym corresponds one-to-one to an ISO 10646 / Unicode + * character, this is noted in a comment that provides both the U+xxxx + * Unicode position, as well as the official Unicode name of the + * character. + * + * Where the correspondence is either not one-to-one or semantically + * unclear, the Unicode position and name are enclosed in + * parentheses. Such legacy keysyms should be considered deprecated + * and are not recommended for use in future keyboard mappings. + * + * For any future extension of the keysyms with characters already + * found in ISO 10646 / Unicode, the following algorithm shall be + * used. The new keysym code position will simply be the character's + * Unicode number plus 0x01000000. The keysym values in the range + * 0x01000100 to 0x0110ffff are reserved to represent Unicode + * characters in the range U+0100 to U+10FFFF. + * + * While most newer Unicode-based X11 clients do already accept + * Unicode-mapped keysyms in the range 0x01000100 to 0x0110ffff, it + * will remain necessary for clients -- in the interest of + * compatibility with existing servers -- to also understand the + * existing legacy keysym values in the range 0x0100 to 0x20ff. + * + * Where several mnemonic names are defined for the same keysym in this + * file, all but the first one listed should be considered deprecated. + * + * Mnemonic names for keysyms are defined in this file with lines + * that match one of these Perl regular expressions: + * + * /^\#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-f]+)\s*\/\* U+([0-9A-F]{4,6}) (.*) \*\/\s*$/ + * /^\#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-f]+)\s*\/\*\(U+([0-9A-F]{4,6}) (.*)\)\*\/\s*$/ + * /^\#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-f]+)\s*(\/\*\s*(.*)\s*\*\/)?\s*$/ + * + * Before adding new keysyms, please do consider the following: In + * addition to the keysym names defined in this file, the + * XStringToKeysym() and XKeysymToString() functions will also handle + * any keysym string of the form "U0020" to "U007E" and "U00A0" to + * "U10FFFF" for all possible Unicode characters. In other words, + * every possible Unicode character has already a keysym string + * defined algorithmically, even if it is not listed here. Therefore, + * defining an additional keysym macro is only necessary where a + * non-hexadecimal mnemonic name is needed, or where the new keysym + * does not represent any existing Unicode character. + * + * When adding new keysyms to this file, do not forget to also update the + * following: + * + * - the mappings in src/KeyBind.c in the repo + * git://anongit.freedesktop.org/xorg/lib/libX11 + * + * - the protocol specification in specs/XProtocol/X11.keysyms + * in the repo git://anongit.freedesktop.org/xorg/doc/xorg-docs + * + */ + +#define XK_VoidSymbol 0xffffff /* Void symbol */ + +#ifdef XK_MISCELLANY +/* + * TTY function keys, cleverly chosen to map to ASCII, for convenience of + * programming, but could have been arbitrary (at the cost of lookup + * tables in client code). + */ + +#define XK_BackSpace 0xff08 /* Back space, back char */ +#define XK_Tab 0xff09 +#define XK_Linefeed 0xff0a /* Linefeed, LF */ +#define XK_Clear 0xff0b +#define XK_Return 0xff0d /* Return, enter */ +#define XK_Pause 0xff13 /* Pause, hold */ +#define XK_Scroll_Lock 0xff14 +#define XK_Sys_Req 0xff15 +#define XK_Escape 0xff1b +#define XK_Delete 0xffff /* Delete, rubout */ + + + +/* International & multi-key character composition */ + +#define XK_Multi_key 0xff20 /* Multi-key character compose */ +#define XK_Codeinput 0xff37 +#define XK_SingleCandidate 0xff3c +#define XK_MultipleCandidate 0xff3d +#define XK_PreviousCandidate 0xff3e + +/* Japanese keyboard support */ + +#define XK_Kanji 0xff21 /* Kanji, Kanji convert */ +#define XK_Muhenkan 0xff22 /* Cancel Conversion */ +#define XK_Henkan_Mode 0xff23 /* Start/Stop Conversion */ +#define XK_Henkan 0xff23 /* Alias for Henkan_Mode */ +#define XK_Romaji 0xff24 /* to Romaji */ +#define XK_Hiragana 0xff25 /* to Hiragana */ +#define XK_Katakana 0xff26 /* to Katakana */ +#define XK_Hiragana_Katakana 0xff27 /* Hiragana/Katakana toggle */ +#define XK_Zenkaku 0xff28 /* to Zenkaku */ +#define XK_Hankaku 0xff29 /* to Hankaku */ +#define XK_Zenkaku_Hankaku 0xff2a /* Zenkaku/Hankaku toggle */ +#define XK_Touroku 0xff2b /* Add to Dictionary */ +#define XK_Massyo 0xff2c /* Delete from Dictionary */ +#define XK_Kana_Lock 0xff2d /* Kana Lock */ +#define XK_Kana_Shift 0xff2e /* Kana Shift */ +#define XK_Eisu_Shift 0xff2f /* Alphanumeric Shift */ +#define XK_Eisu_toggle 0xff30 /* Alphanumeric toggle */ +#define XK_Kanji_Bangou 0xff37 /* Codeinput */ +#define XK_Zen_Koho 0xff3d /* Multiple/All Candidate(s) */ +#define XK_Mae_Koho 0xff3e /* Previous Candidate */ + +/* 0xff31 thru 0xff3f are under XK_KOREAN */ + +/* Cursor control & motion */ + +#define XK_Home 0xff50 +#define XK_Left 0xff51 /* Move left, left arrow */ +#define XK_Up 0xff52 /* Move up, up arrow */ +#define XK_Right 0xff53 /* Move right, right arrow */ +#define XK_Down 0xff54 /* Move down, down arrow */ +#define XK_Prior 0xff55 /* Prior, previous */ +#define XK_Page_Up 0xff55 +#define XK_Next 0xff56 /* Next */ +#define XK_Page_Down 0xff56 +#define XK_End 0xff57 /* EOL */ +#define XK_Begin 0xff58 /* BOL */ + + +/* Misc functions */ + +#define XK_Select 0xff60 /* Select, mark */ +#define XK_Print 0xff61 +#define XK_Execute 0xff62 /* Execute, run, do */ +#define XK_Insert 0xff63 /* Insert, insert here */ +#define XK_Undo 0xff65 +#define XK_Redo 0xff66 /* Redo, again */ +#define XK_Menu 0xff67 +#define XK_Find 0xff68 /* Find, search */ +#define XK_Cancel 0xff69 /* Cancel, stop, abort, exit */ +#define XK_Help 0xff6a /* Help */ +#define XK_Break 0xff6b +#define XK_Mode_switch 0xff7e /* Character set switch */ +#define XK_script_switch 0xff7e /* Alias for mode_switch */ +#define XK_Num_Lock 0xff7f + +/* Keypad functions, keypad numbers cleverly chosen to map to ASCII */ + +#define XK_KP_Space 0xff80 /* Space */ +#define XK_KP_Tab 0xff89 +#define XK_KP_Enter 0xff8d /* Enter */ +#define XK_KP_F1 0xff91 /* PF1, KP_A, ... */ +#define XK_KP_F2 0xff92 +#define XK_KP_F3 0xff93 +#define XK_KP_F4 0xff94 +#define XK_KP_Home 0xff95 +#define XK_KP_Left 0xff96 +#define XK_KP_Up 0xff97 +#define XK_KP_Right 0xff98 +#define XK_KP_Down 0xff99 +#define XK_KP_Prior 0xff9a +#define XK_KP_Page_Up 0xff9a +#define XK_KP_Next 0xff9b +#define XK_KP_Page_Down 0xff9b +#define XK_KP_End 0xff9c +#define XK_KP_Begin 0xff9d +#define XK_KP_Insert 0xff9e +#define XK_KP_Delete 0xff9f +#define XK_KP_Equal 0xffbd /* Equals */ +#define XK_KP_Multiply 0xffaa +#define XK_KP_Add 0xffab +#define XK_KP_Separator 0xffac /* Separator, often comma */ +#define XK_KP_Subtract 0xffad +#define XK_KP_Decimal 0xffae +#define XK_KP_Divide 0xffaf + +#define XK_KP_0 0xffb0 +#define XK_KP_1 0xffb1 +#define XK_KP_2 0xffb2 +#define XK_KP_3 0xffb3 +#define XK_KP_4 0xffb4 +#define XK_KP_5 0xffb5 +#define XK_KP_6 0xffb6 +#define XK_KP_7 0xffb7 +#define XK_KP_8 0xffb8 +#define XK_KP_9 0xffb9 + + + +/* + * Auxiliary functions; note the duplicate definitions for left and right + * function keys; Sun keyboards and a few other manufacturers have such + * function key groups on the left and/or right sides of the keyboard. + * We've not found a keyboard with more than 35 function keys total. + */ + +#define XK_F1 0xffbe +#define XK_F2 0xffbf +#define XK_F3 0xffc0 +#define XK_F4 0xffc1 +#define XK_F5 0xffc2 +#define XK_F6 0xffc3 +#define XK_F7 0xffc4 +#define XK_F8 0xffc5 +#define XK_F9 0xffc6 +#define XK_F10 0xffc7 +#define XK_F11 0xffc8 +#define XK_L1 0xffc8 +#define XK_F12 0xffc9 +#define XK_L2 0xffc9 +#define XK_F13 0xffca +#define XK_L3 0xffca +#define XK_F14 0xffcb +#define XK_L4 0xffcb +#define XK_F15 0xffcc +#define XK_L5 0xffcc +#define XK_F16 0xffcd +#define XK_L6 0xffcd +#define XK_F17 0xffce +#define XK_L7 0xffce +#define XK_F18 0xffcf +#define XK_L8 0xffcf +#define XK_F19 0xffd0 +#define XK_L9 0xffd0 +#define XK_F20 0xffd1 +#define XK_L10 0xffd1 +#define XK_F21 0xffd2 +#define XK_R1 0xffd2 +#define XK_F22 0xffd3 +#define XK_R2 0xffd3 +#define XK_F23 0xffd4 +#define XK_R3 0xffd4 +#define XK_F24 0xffd5 +#define XK_R4 0xffd5 +#define XK_F25 0xffd6 +#define XK_R5 0xffd6 +#define XK_F26 0xffd7 +#define XK_R6 0xffd7 +#define XK_F27 0xffd8 +#define XK_R7 0xffd8 +#define XK_F28 0xffd9 +#define XK_R8 0xffd9 +#define XK_F29 0xffda +#define XK_R9 0xffda +#define XK_F30 0xffdb +#define XK_R10 0xffdb +#define XK_F31 0xffdc +#define XK_R11 0xffdc +#define XK_F32 0xffdd +#define XK_R12 0xffdd +#define XK_F33 0xffde +#define XK_R13 0xffde +#define XK_F34 0xffdf +#define XK_R14 0xffdf +#define XK_F35 0xffe0 +#define XK_R15 0xffe0 + +/* Modifiers */ + +#define XK_Shift_L 0xffe1 /* Left shift */ +#define XK_Shift_R 0xffe2 /* Right shift */ +#define XK_Control_L 0xffe3 /* Left control */ +#define XK_Control_R 0xffe4 /* Right control */ +#define XK_Caps_Lock 0xffe5 /* Caps lock */ +#define XK_Shift_Lock 0xffe6 /* Shift lock */ + +#define XK_Meta_L 0xffe7 /* Left meta */ +#define XK_Meta_R 0xffe8 /* Right meta */ +#define XK_Alt_L 0xffe9 /* Left alt */ +#define XK_Alt_R 0xffea /* Right alt */ +#define XK_Super_L 0xffeb /* Left super */ +#define XK_Super_R 0xffec /* Right super */ +#define XK_Hyper_L 0xffed /* Left hyper */ +#define XK_Hyper_R 0xffee /* Right hyper */ +#endif /* XK_MISCELLANY */ + +/* + * Keyboard (XKB) Extension function and modifier keys + * (from Appendix C of "The X Keyboard Extension: Protocol Specification") + * Byte 3 = 0xfe + */ + +#ifdef XK_XKB_KEYS +#define XK_ISO_Lock 0xfe01 +#define XK_ISO_Level2_Latch 0xfe02 +#define XK_ISO_Level3_Shift 0xfe03 +#define XK_ISO_Level3_Latch 0xfe04 +#define XK_ISO_Level3_Lock 0xfe05 +#define XK_ISO_Level5_Shift 0xfe11 +#define XK_ISO_Level5_Latch 0xfe12 +#define XK_ISO_Level5_Lock 0xfe13 +#define XK_ISO_Group_Shift 0xff7e /* Alias for mode_switch */ +#define XK_ISO_Group_Latch 0xfe06 +#define XK_ISO_Group_Lock 0xfe07 +#define XK_ISO_Next_Group 0xfe08 +#define XK_ISO_Next_Group_Lock 0xfe09 +#define XK_ISO_Prev_Group 0xfe0a +#define XK_ISO_Prev_Group_Lock 0xfe0b +#define XK_ISO_First_Group 0xfe0c +#define XK_ISO_First_Group_Lock 0xfe0d +#define XK_ISO_Last_Group 0xfe0e +#define XK_ISO_Last_Group_Lock 0xfe0f + +#define XK_ISO_Left_Tab 0xfe20 +#define XK_ISO_Move_Line_Up 0xfe21 +#define XK_ISO_Move_Line_Down 0xfe22 +#define XK_ISO_Partial_Line_Up 0xfe23 +#define XK_ISO_Partial_Line_Down 0xfe24 +#define XK_ISO_Partial_Space_Left 0xfe25 +#define XK_ISO_Partial_Space_Right 0xfe26 +#define XK_ISO_Set_Margin_Left 0xfe27 +#define XK_ISO_Set_Margin_Right 0xfe28 +#define XK_ISO_Release_Margin_Left 0xfe29 +#define XK_ISO_Release_Margin_Right 0xfe2a +#define XK_ISO_Release_Both_Margins 0xfe2b +#define XK_ISO_Fast_Cursor_Left 0xfe2c +#define XK_ISO_Fast_Cursor_Right 0xfe2d +#define XK_ISO_Fast_Cursor_Up 0xfe2e +#define XK_ISO_Fast_Cursor_Down 0xfe2f +#define XK_ISO_Continuous_Underline 0xfe30 +#define XK_ISO_Discontinuous_Underline 0xfe31 +#define XK_ISO_Emphasize 0xfe32 +#define XK_ISO_Center_Object 0xfe33 +#define XK_ISO_Enter 0xfe34 + +#define XK_dead_grave 0xfe50 +#define XK_dead_acute 0xfe51 +#define XK_dead_circumflex 0xfe52 +#define XK_dead_tilde 0xfe53 +#define XK_dead_perispomeni 0xfe53 /* alias for dead_tilde */ +#define XK_dead_macron 0xfe54 +#define XK_dead_breve 0xfe55 +#define XK_dead_abovedot 0xfe56 +#define XK_dead_diaeresis 0xfe57 +#define XK_dead_abovering 0xfe58 +#define XK_dead_doubleacute 0xfe59 +#define XK_dead_caron 0xfe5a +#define XK_dead_cedilla 0xfe5b +#define XK_dead_ogonek 0xfe5c +#define XK_dead_iota 0xfe5d +#define XK_dead_voiced_sound 0xfe5e +#define XK_dead_semivoiced_sound 0xfe5f +#define XK_dead_belowdot 0xfe60 +#define XK_dead_hook 0xfe61 +#define XK_dead_horn 0xfe62 +#define XK_dead_stroke 0xfe63 +#define XK_dead_abovecomma 0xfe64 +#define XK_dead_psili 0xfe64 /* alias for dead_abovecomma */ +#define XK_dead_abovereversedcomma 0xfe65 +#define XK_dead_dasia 0xfe65 /* alias for dead_abovereversedcomma */ +#define XK_dead_doublegrave 0xfe66 +#define XK_dead_belowring 0xfe67 +#define XK_dead_belowmacron 0xfe68 +#define XK_dead_belowcircumflex 0xfe69 +#define XK_dead_belowtilde 0xfe6a +#define XK_dead_belowbreve 0xfe6b +#define XK_dead_belowdiaeresis 0xfe6c +#define XK_dead_invertedbreve 0xfe6d +#define XK_dead_belowcomma 0xfe6e +#define XK_dead_currency 0xfe6f + +/* dead vowels for universal syllable entry */ +#define XK_dead_a 0xfe80 +#define XK_dead_A 0xfe81 +#define XK_dead_e 0xfe82 +#define XK_dead_E 0xfe83 +#define XK_dead_i 0xfe84 +#define XK_dead_I 0xfe85 +#define XK_dead_o 0xfe86 +#define XK_dead_O 0xfe87 +#define XK_dead_u 0xfe88 +#define XK_dead_U 0xfe89 +#define XK_dead_small_schwa 0xfe8a +#define XK_dead_capital_schwa 0xfe8b + +#define XK_First_Virtual_Screen 0xfed0 +#define XK_Prev_Virtual_Screen 0xfed1 +#define XK_Next_Virtual_Screen 0xfed2 +#define XK_Last_Virtual_Screen 0xfed4 +#define XK_Terminate_Server 0xfed5 + +#define XK_AccessX_Enable 0xfe70 +#define XK_AccessX_Feedback_Enable 0xfe71 +#define XK_RepeatKeys_Enable 0xfe72 +#define XK_SlowKeys_Enable 0xfe73 +#define XK_BounceKeys_Enable 0xfe74 +#define XK_StickyKeys_Enable 0xfe75 +#define XK_MouseKeys_Enable 0xfe76 +#define XK_MouseKeys_Accel_Enable 0xfe77 +#define XK_Overlay1_Enable 0xfe78 +#define XK_Overlay2_Enable 0xfe79 +#define XK_AudibleBell_Enable 0xfe7a + +#define XK_Pointer_Left 0xfee0 +#define XK_Pointer_Right 0xfee1 +#define XK_Pointer_Up 0xfee2 +#define XK_Pointer_Down 0xfee3 +#define XK_Pointer_UpLeft 0xfee4 +#define XK_Pointer_UpRight 0xfee5 +#define XK_Pointer_DownLeft 0xfee6 +#define XK_Pointer_DownRight 0xfee7 +#define XK_Pointer_Button_Dflt 0xfee8 +#define XK_Pointer_Button1 0xfee9 +#define XK_Pointer_Button2 0xfeea +#define XK_Pointer_Button3 0xfeeb +#define XK_Pointer_Button4 0xfeec +#define XK_Pointer_Button5 0xfeed +#define XK_Pointer_DblClick_Dflt 0xfeee +#define XK_Pointer_DblClick1 0xfeef +#define XK_Pointer_DblClick2 0xfef0 +#define XK_Pointer_DblClick3 0xfef1 +#define XK_Pointer_DblClick4 0xfef2 +#define XK_Pointer_DblClick5 0xfef3 +#define XK_Pointer_Drag_Dflt 0xfef4 +#define XK_Pointer_Drag1 0xfef5 +#define XK_Pointer_Drag2 0xfef6 +#define XK_Pointer_Drag3 0xfef7 +#define XK_Pointer_Drag4 0xfef8 +#define XK_Pointer_Drag5 0xfefd + +#define XK_Pointer_EnableKeys 0xfef9 +#define XK_Pointer_Accelerate 0xfefa +#define XK_Pointer_DfltBtnNext 0xfefb +#define XK_Pointer_DfltBtnPrev 0xfefc + +#endif /* XK_XKB_KEYS */ + +/* + * 3270 Terminal Keys + * Byte 3 = 0xfd + */ + +#ifdef XK_3270 +#define XK_3270_Duplicate 0xfd01 +#define XK_3270_FieldMark 0xfd02 +#define XK_3270_Right2 0xfd03 +#define XK_3270_Left2 0xfd04 +#define XK_3270_BackTab 0xfd05 +#define XK_3270_EraseEOF 0xfd06 +#define XK_3270_EraseInput 0xfd07 +#define XK_3270_Reset 0xfd08 +#define XK_3270_Quit 0xfd09 +#define XK_3270_PA1 0xfd0a +#define XK_3270_PA2 0xfd0b +#define XK_3270_PA3 0xfd0c +#define XK_3270_Test 0xfd0d +#define XK_3270_Attn 0xfd0e +#define XK_3270_CursorBlink 0xfd0f +#define XK_3270_AltCursor 0xfd10 +#define XK_3270_KeyClick 0xfd11 +#define XK_3270_Jump 0xfd12 +#define XK_3270_Ident 0xfd13 +#define XK_3270_Rule 0xfd14 +#define XK_3270_Copy 0xfd15 +#define XK_3270_Play 0xfd16 +#define XK_3270_Setup 0xfd17 +#define XK_3270_Record 0xfd18 +#define XK_3270_ChangeScreen 0xfd19 +#define XK_3270_DeleteWord 0xfd1a +#define XK_3270_ExSelect 0xfd1b +#define XK_3270_CursorSelect 0xfd1c +#define XK_3270_PrintScreen 0xfd1d +#define XK_3270_Enter 0xfd1e +#endif /* XK_3270 */ + +/* + * Latin 1 + * (ISO/IEC 8859-1 = Unicode U+0020..U+00FF) + * Byte 3 = 0 + */ +#ifdef XK_LATIN1 +#define XK_space 0x0020 /* U+0020 SPACE */ +#define XK_exclam 0x0021 /* U+0021 EXCLAMATION MARK */ +#define XK_quotedbl 0x0022 /* U+0022 QUOTATION MARK */ +#define XK_numbersign 0x0023 /* U+0023 NUMBER SIGN */ +#define XK_dollar 0x0024 /* U+0024 DOLLAR SIGN */ +#define XK_percent 0x0025 /* U+0025 PERCENT SIGN */ +#define XK_ampersand 0x0026 /* U+0026 AMPERSAND */ +#define XK_apostrophe 0x0027 /* U+0027 APOSTROPHE */ +#define XK_quoteright 0x0027 /* deprecated */ +#define XK_parenleft 0x0028 /* U+0028 LEFT PARENTHESIS */ +#define XK_parenright 0x0029 /* U+0029 RIGHT PARENTHESIS */ +#define XK_asterisk 0x002a /* U+002A ASTERISK */ +#define XK_plus 0x002b /* U+002B PLUS SIGN */ +#define XK_comma 0x002c /* U+002C COMMA */ +#define XK_minus 0x002d /* U+002D HYPHEN-MINUS */ +#define XK_period 0x002e /* U+002E FULL STOP */ +#define XK_slash 0x002f /* U+002F SOLIDUS */ +#define XK_0 0x0030 /* U+0030 DIGIT ZERO */ +#define XK_1 0x0031 /* U+0031 DIGIT ONE */ +#define XK_2 0x0032 /* U+0032 DIGIT TWO */ +#define XK_3 0x0033 /* U+0033 DIGIT THREE */ +#define XK_4 0x0034 /* U+0034 DIGIT FOUR */ +#define XK_5 0x0035 /* U+0035 DIGIT FIVE */ +#define XK_6 0x0036 /* U+0036 DIGIT SIX */ +#define XK_7 0x0037 /* U+0037 DIGIT SEVEN */ +#define XK_8 0x0038 /* U+0038 DIGIT EIGHT */ +#define XK_9 0x0039 /* U+0039 DIGIT NINE */ +#define XK_colon 0x003a /* U+003A COLON */ +#define XK_semicolon 0x003b /* U+003B SEMICOLON */ +#define XK_less 0x003c /* U+003C LESS-THAN SIGN */ +#define XK_equal 0x003d /* U+003D EQUALS SIGN */ +#define XK_greater 0x003e /* U+003E GREATER-THAN SIGN */ +#define XK_question 0x003f /* U+003F QUESTION MARK */ +#define XK_at 0x0040 /* U+0040 COMMERCIAL AT */ +#define XK_A 0x0041 /* U+0041 LATIN CAPITAL LETTER A */ +#define XK_B 0x0042 /* U+0042 LATIN CAPITAL LETTER B */ +#define XK_C 0x0043 /* U+0043 LATIN CAPITAL LETTER C */ +#define XK_D 0x0044 /* U+0044 LATIN CAPITAL LETTER D */ +#define XK_E 0x0045 /* U+0045 LATIN CAPITAL LETTER E */ +#define XK_F 0x0046 /* U+0046 LATIN CAPITAL LETTER F */ +#define XK_G 0x0047 /* U+0047 LATIN CAPITAL LETTER G */ +#define XK_H 0x0048 /* U+0048 LATIN CAPITAL LETTER H */ +#define XK_I 0x0049 /* U+0049 LATIN CAPITAL LETTER I */ +#define XK_J 0x004a /* U+004A LATIN CAPITAL LETTER J */ +#define XK_K 0x004b /* U+004B LATIN CAPITAL LETTER K */ +#define XK_L 0x004c /* U+004C LATIN CAPITAL LETTER L */ +#define XK_M 0x004d /* U+004D LATIN CAPITAL LETTER M */ +#define XK_N 0x004e /* U+004E LATIN CAPITAL LETTER N */ +#define XK_O 0x004f /* U+004F LATIN CAPITAL LETTER O */ +#define XK_P 0x0050 /* U+0050 LATIN CAPITAL LETTER P */ +#define XK_Q 0x0051 /* U+0051 LATIN CAPITAL LETTER Q */ +#define XK_R 0x0052 /* U+0052 LATIN CAPITAL LETTER R */ +#define XK_S 0x0053 /* U+0053 LATIN CAPITAL LETTER S */ +#define XK_T 0x0054 /* U+0054 LATIN CAPITAL LETTER T */ +#define XK_U 0x0055 /* U+0055 LATIN CAPITAL LETTER U */ +#define XK_V 0x0056 /* U+0056 LATIN CAPITAL LETTER V */ +#define XK_W 0x0057 /* U+0057 LATIN CAPITAL LETTER W */ +#define XK_X 0x0058 /* U+0058 LATIN CAPITAL LETTER X */ +#define XK_Y 0x0059 /* U+0059 LATIN CAPITAL LETTER Y */ +#define XK_Z 0x005a /* U+005A LATIN CAPITAL LETTER Z */ +#define XK_bracketleft 0x005b /* U+005B LEFT SQUARE BRACKET */ +#define XK_backslash 0x005c /* U+005C REVERSE SOLIDUS */ +#define XK_bracketright 0x005d /* U+005D RIGHT SQUARE BRACKET */ +#define XK_asciicircum 0x005e /* U+005E CIRCUMFLEX ACCENT */ +#define XK_underscore 0x005f /* U+005F LOW LINE */ +#define XK_grave 0x0060 /* U+0060 GRAVE ACCENT */ +#define XK_quoteleft 0x0060 /* deprecated */ +#define XK_a 0x0061 /* U+0061 LATIN SMALL LETTER A */ +#define XK_b 0x0062 /* U+0062 LATIN SMALL LETTER B */ +#define XK_c 0x0063 /* U+0063 LATIN SMALL LETTER C */ +#define XK_d 0x0064 /* U+0064 LATIN SMALL LETTER D */ +#define XK_e 0x0065 /* U+0065 LATIN SMALL LETTER E */ +#define XK_f 0x0066 /* U+0066 LATIN SMALL LETTER F */ +#define XK_g 0x0067 /* U+0067 LATIN SMALL LETTER G */ +#define XK_h 0x0068 /* U+0068 LATIN SMALL LETTER H */ +#define XK_i 0x0069 /* U+0069 LATIN SMALL LETTER I */ +#define XK_j 0x006a /* U+006A LATIN SMALL LETTER J */ +#define XK_k 0x006b /* U+006B LATIN SMALL LETTER K */ +#define XK_l 0x006c /* U+006C LATIN SMALL LETTER L */ +#define XK_m 0x006d /* U+006D LATIN SMALL LETTER M */ +#define XK_n 0x006e /* U+006E LATIN SMALL LETTER N */ +#define XK_o 0x006f /* U+006F LATIN SMALL LETTER O */ +#define XK_p 0x0070 /* U+0070 LATIN SMALL LETTER P */ +#define XK_q 0x0071 /* U+0071 LATIN SMALL LETTER Q */ +#define XK_r 0x0072 /* U+0072 LATIN SMALL LETTER R */ +#define XK_s 0x0073 /* U+0073 LATIN SMALL LETTER S */ +#define XK_t 0x0074 /* U+0074 LATIN SMALL LETTER T */ +#define XK_u 0x0075 /* U+0075 LATIN SMALL LETTER U */ +#define XK_v 0x0076 /* U+0076 LATIN SMALL LETTER V */ +#define XK_w 0x0077 /* U+0077 LATIN SMALL LETTER W */ +#define XK_x 0x0078 /* U+0078 LATIN SMALL LETTER X */ +#define XK_y 0x0079 /* U+0079 LATIN SMALL LETTER Y */ +#define XK_z 0x007a /* U+007A LATIN SMALL LETTER Z */ +#define XK_braceleft 0x007b /* U+007B LEFT CURLY BRACKET */ +#define XK_bar 0x007c /* U+007C VERTICAL LINE */ +#define XK_braceright 0x007d /* U+007D RIGHT CURLY BRACKET */ +#define XK_asciitilde 0x007e /* U+007E TILDE */ + +#define XK_nobreakspace 0x00a0 /* U+00A0 NO-BREAK SPACE */ +#define XK_exclamdown 0x00a1 /* U+00A1 INVERTED EXCLAMATION MARK */ +#define XK_cent 0x00a2 /* U+00A2 CENT SIGN */ +#define XK_sterling 0x00a3 /* U+00A3 POUND SIGN */ +#define XK_currency 0x00a4 /* U+00A4 CURRENCY SIGN */ +#define XK_yen 0x00a5 /* U+00A5 YEN SIGN */ +#define XK_brokenbar 0x00a6 /* U+00A6 BROKEN BAR */ +#define XK_section 0x00a7 /* U+00A7 SECTION SIGN */ +#define XK_diaeresis 0x00a8 /* U+00A8 DIAERESIS */ +#define XK_copyright 0x00a9 /* U+00A9 COPYRIGHT SIGN */ +#define XK_ordfeminine 0x00aa /* U+00AA FEMININE ORDINAL INDICATOR */ +#define XK_guillemotleft 0x00ab /* U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */ +#define XK_notsign 0x00ac /* U+00AC NOT SIGN */ +#define XK_hyphen 0x00ad /* U+00AD SOFT HYPHEN */ +#define XK_registered 0x00ae /* U+00AE REGISTERED SIGN */ +#define XK_macron 0x00af /* U+00AF MACRON */ +#define XK_degree 0x00b0 /* U+00B0 DEGREE SIGN */ +#define XK_plusminus 0x00b1 /* U+00B1 PLUS-MINUS SIGN */ +#define XK_twosuperior 0x00b2 /* U+00B2 SUPERSCRIPT TWO */ +#define XK_threesuperior 0x00b3 /* U+00B3 SUPERSCRIPT THREE */ +#define XK_acute 0x00b4 /* U+00B4 ACUTE ACCENT */ +#define XK_mu 0x00b5 /* U+00B5 MICRO SIGN */ +#define XK_paragraph 0x00b6 /* U+00B6 PILCROW SIGN */ +#define XK_periodcentered 0x00b7 /* U+00B7 MIDDLE DOT */ +#define XK_cedilla 0x00b8 /* U+00B8 CEDILLA */ +#define XK_onesuperior 0x00b9 /* U+00B9 SUPERSCRIPT ONE */ +#define XK_masculine 0x00ba /* U+00BA MASCULINE ORDINAL INDICATOR */ +#define XK_guillemotright 0x00bb /* U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */ +#define XK_onequarter 0x00bc /* U+00BC VULGAR FRACTION ONE QUARTER */ +#define XK_onehalf 0x00bd /* U+00BD VULGAR FRACTION ONE HALF */ +#define XK_threequarters 0x00be /* U+00BE VULGAR FRACTION THREE QUARTERS */ +#define XK_questiondown 0x00bf /* U+00BF INVERTED QUESTION MARK */ +#define XK_Agrave 0x00c0 /* U+00C0 LATIN CAPITAL LETTER A WITH GRAVE */ +#define XK_Aacute 0x00c1 /* U+00C1 LATIN CAPITAL LETTER A WITH ACUTE */ +#define XK_Acircumflex 0x00c2 /* U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX */ +#define XK_Atilde 0x00c3 /* U+00C3 LATIN CAPITAL LETTER A WITH TILDE */ +#define XK_Adiaeresis 0x00c4 /* U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS */ +#define XK_Aring 0x00c5 /* U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE */ +#define XK_AE 0x00c6 /* U+00C6 LATIN CAPITAL LETTER AE */ +#define XK_Ccedilla 0x00c7 /* U+00C7 LATIN CAPITAL LETTER C WITH CEDILLA */ +#define XK_Egrave 0x00c8 /* U+00C8 LATIN CAPITAL LETTER E WITH GRAVE */ +#define XK_Eacute 0x00c9 /* U+00C9 LATIN CAPITAL LETTER E WITH ACUTE */ +#define XK_Ecircumflex 0x00ca /* U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX */ +#define XK_Ediaeresis 0x00cb /* U+00CB LATIN CAPITAL LETTER E WITH DIAERESIS */ +#define XK_Igrave 0x00cc /* U+00CC LATIN CAPITAL LETTER I WITH GRAVE */ +#define XK_Iacute 0x00cd /* U+00CD LATIN CAPITAL LETTER I WITH ACUTE */ +#define XK_Icircumflex 0x00ce /* U+00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX */ +#define XK_Idiaeresis 0x00cf /* U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS */ +#define XK_ETH 0x00d0 /* U+00D0 LATIN CAPITAL LETTER ETH */ +#define XK_Eth 0x00d0 /* deprecated */ +#define XK_Ntilde 0x00d1 /* U+00D1 LATIN CAPITAL LETTER N WITH TILDE */ +#define XK_Ograve 0x00d2 /* U+00D2 LATIN CAPITAL LETTER O WITH GRAVE */ +#define XK_Oacute 0x00d3 /* U+00D3 LATIN CAPITAL LETTER O WITH ACUTE */ +#define XK_Ocircumflex 0x00d4 /* U+00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX */ +#define XK_Otilde 0x00d5 /* U+00D5 LATIN CAPITAL LETTER O WITH TILDE */ +#define XK_Odiaeresis 0x00d6 /* U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS */ +#define XK_multiply 0x00d7 /* U+00D7 MULTIPLICATION SIGN */ +#define XK_Oslash 0x00d8 /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */ +#define XK_Ooblique 0x00d8 /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */ +#define XK_Ugrave 0x00d9 /* U+00D9 LATIN CAPITAL LETTER U WITH GRAVE */ +#define XK_Uacute 0x00da /* U+00DA LATIN CAPITAL LETTER U WITH ACUTE */ +#define XK_Ucircumflex 0x00db /* U+00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX */ +#define XK_Udiaeresis 0x00dc /* U+00DC LATIN CAPITAL LETTER U WITH DIAERESIS */ +#define XK_Yacute 0x00dd /* U+00DD LATIN CAPITAL LETTER Y WITH ACUTE */ +#define XK_THORN 0x00de /* U+00DE LATIN CAPITAL LETTER THORN */ +#define XK_Thorn 0x00de /* deprecated */ +#define XK_ssharp 0x00df /* U+00DF LATIN SMALL LETTER SHARP S */ +#define XK_agrave 0x00e0 /* U+00E0 LATIN SMALL LETTER A WITH GRAVE */ +#define XK_aacute 0x00e1 /* U+00E1 LATIN SMALL LETTER A WITH ACUTE */ +#define XK_acircumflex 0x00e2 /* U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX */ +#define XK_atilde 0x00e3 /* U+00E3 LATIN SMALL LETTER A WITH TILDE */ +#define XK_adiaeresis 0x00e4 /* U+00E4 LATIN SMALL LETTER A WITH DIAERESIS */ +#define XK_aring 0x00e5 /* U+00E5 LATIN SMALL LETTER A WITH RING ABOVE */ +#define XK_ae 0x00e6 /* U+00E6 LATIN SMALL LETTER AE */ +#define XK_ccedilla 0x00e7 /* U+00E7 LATIN SMALL LETTER C WITH CEDILLA */ +#define XK_egrave 0x00e8 /* U+00E8 LATIN SMALL LETTER E WITH GRAVE */ +#define XK_eacute 0x00e9 /* U+00E9 LATIN SMALL LETTER E WITH ACUTE */ +#define XK_ecircumflex 0x00ea /* U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX */ +#define XK_ediaeresis 0x00eb /* U+00EB LATIN SMALL LETTER E WITH DIAERESIS */ +#define XK_igrave 0x00ec /* U+00EC LATIN SMALL LETTER I WITH GRAVE */ +#define XK_iacute 0x00ed /* U+00ED LATIN SMALL LETTER I WITH ACUTE */ +#define XK_icircumflex 0x00ee /* U+00EE LATIN SMALL LETTER I WITH CIRCUMFLEX */ +#define XK_idiaeresis 0x00ef /* U+00EF LATIN SMALL LETTER I WITH DIAERESIS */ +#define XK_eth 0x00f0 /* U+00F0 LATIN SMALL LETTER ETH */ +#define XK_ntilde 0x00f1 /* U+00F1 LATIN SMALL LETTER N WITH TILDE */ +#define XK_ograve 0x00f2 /* U+00F2 LATIN SMALL LETTER O WITH GRAVE */ +#define XK_oacute 0x00f3 /* U+00F3 LATIN SMALL LETTER O WITH ACUTE */ +#define XK_ocircumflex 0x00f4 /* U+00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX */ +#define XK_otilde 0x00f5 /* U+00F5 LATIN SMALL LETTER O WITH TILDE */ +#define XK_odiaeresis 0x00f6 /* U+00F6 LATIN SMALL LETTER O WITH DIAERESIS */ +#define XK_division 0x00f7 /* U+00F7 DIVISION SIGN */ +#define XK_oslash 0x00f8 /* U+00F8 LATIN SMALL LETTER O WITH STROKE */ +#define XK_ooblique 0x00f8 /* U+00F8 LATIN SMALL LETTER O WITH STROKE */ +#define XK_ugrave 0x00f9 /* U+00F9 LATIN SMALL LETTER U WITH GRAVE */ +#define XK_uacute 0x00fa /* U+00FA LATIN SMALL LETTER U WITH ACUTE */ +#define XK_ucircumflex 0x00fb /* U+00FB LATIN SMALL LETTER U WITH CIRCUMFLEX */ +#define XK_udiaeresis 0x00fc /* U+00FC LATIN SMALL LETTER U WITH DIAERESIS */ +#define XK_yacute 0x00fd /* U+00FD LATIN SMALL LETTER Y WITH ACUTE */ +#define XK_thorn 0x00fe /* U+00FE LATIN SMALL LETTER THORN */ +#define XK_ydiaeresis 0x00ff /* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */ +#endif /* XK_LATIN1 */ + +/* + * Latin 2 + * Byte 3 = 1 + */ + +#ifdef XK_LATIN2 +#define XK_Aogonek 0x01a1 /* U+0104 LATIN CAPITAL LETTER A WITH OGONEK */ +#define XK_breve 0x01a2 /* U+02D8 BREVE */ +#define XK_Lstroke 0x01a3 /* U+0141 LATIN CAPITAL LETTER L WITH STROKE */ +#define XK_Lcaron 0x01a5 /* U+013D LATIN CAPITAL LETTER L WITH CARON */ +#define XK_Sacute 0x01a6 /* U+015A LATIN CAPITAL LETTER S WITH ACUTE */ +#define XK_Scaron 0x01a9 /* U+0160 LATIN CAPITAL LETTER S WITH CARON */ +#define XK_Scedilla 0x01aa /* U+015E LATIN CAPITAL LETTER S WITH CEDILLA */ +#define XK_Tcaron 0x01ab /* U+0164 LATIN CAPITAL LETTER T WITH CARON */ +#define XK_Zacute 0x01ac /* U+0179 LATIN CAPITAL LETTER Z WITH ACUTE */ +#define XK_Zcaron 0x01ae /* U+017D LATIN CAPITAL LETTER Z WITH CARON */ +#define XK_Zabovedot 0x01af /* U+017B LATIN CAPITAL LETTER Z WITH DOT ABOVE */ +#define XK_aogonek 0x01b1 /* U+0105 LATIN SMALL LETTER A WITH OGONEK */ +#define XK_ogonek 0x01b2 /* U+02DB OGONEK */ +#define XK_lstroke 0x01b3 /* U+0142 LATIN SMALL LETTER L WITH STROKE */ +#define XK_lcaron 0x01b5 /* U+013E LATIN SMALL LETTER L WITH CARON */ +#define XK_sacute 0x01b6 /* U+015B LATIN SMALL LETTER S WITH ACUTE */ +#define XK_caron 0x01b7 /* U+02C7 CARON */ +#define XK_scaron 0x01b9 /* U+0161 LATIN SMALL LETTER S WITH CARON */ +#define XK_scedilla 0x01ba /* U+015F LATIN SMALL LETTER S WITH CEDILLA */ +#define XK_tcaron 0x01bb /* U+0165 LATIN SMALL LETTER T WITH CARON */ +#define XK_zacute 0x01bc /* U+017A LATIN SMALL LETTER Z WITH ACUTE */ +#define XK_doubleacute 0x01bd /* U+02DD DOUBLE ACUTE ACCENT */ +#define XK_zcaron 0x01be /* U+017E LATIN SMALL LETTER Z WITH CARON */ +#define XK_zabovedot 0x01bf /* U+017C LATIN SMALL LETTER Z WITH DOT ABOVE */ +#define XK_Racute 0x01c0 /* U+0154 LATIN CAPITAL LETTER R WITH ACUTE */ +#define XK_Abreve 0x01c3 /* U+0102 LATIN CAPITAL LETTER A WITH BREVE */ +#define XK_Lacute 0x01c5 /* U+0139 LATIN CAPITAL LETTER L WITH ACUTE */ +#define XK_Cacute 0x01c6 /* U+0106 LATIN CAPITAL LETTER C WITH ACUTE */ +#define XK_Ccaron 0x01c8 /* U+010C LATIN CAPITAL LETTER C WITH CARON */ +#define XK_Eogonek 0x01ca /* U+0118 LATIN CAPITAL LETTER E WITH OGONEK */ +#define XK_Ecaron 0x01cc /* U+011A LATIN CAPITAL LETTER E WITH CARON */ +#define XK_Dcaron 0x01cf /* U+010E LATIN CAPITAL LETTER D WITH CARON */ +#define XK_Dstroke 0x01d0 /* U+0110 LATIN CAPITAL LETTER D WITH STROKE */ +#define XK_Nacute 0x01d1 /* U+0143 LATIN CAPITAL LETTER N WITH ACUTE */ +#define XK_Ncaron 0x01d2 /* U+0147 LATIN CAPITAL LETTER N WITH CARON */ +#define XK_Odoubleacute 0x01d5 /* U+0150 LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ +#define XK_Rcaron 0x01d8 /* U+0158 LATIN CAPITAL LETTER R WITH CARON */ +#define XK_Uring 0x01d9 /* U+016E LATIN CAPITAL LETTER U WITH RING ABOVE */ +#define XK_Udoubleacute 0x01db /* U+0170 LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ +#define XK_Tcedilla 0x01de /* U+0162 LATIN CAPITAL LETTER T WITH CEDILLA */ +#define XK_racute 0x01e0 /* U+0155 LATIN SMALL LETTER R WITH ACUTE */ +#define XK_abreve 0x01e3 /* U+0103 LATIN SMALL LETTER A WITH BREVE */ +#define XK_lacute 0x01e5 /* U+013A LATIN SMALL LETTER L WITH ACUTE */ +#define XK_cacute 0x01e6 /* U+0107 LATIN SMALL LETTER C WITH ACUTE */ +#define XK_ccaron 0x01e8 /* U+010D LATIN SMALL LETTER C WITH CARON */ +#define XK_eogonek 0x01ea /* U+0119 LATIN SMALL LETTER E WITH OGONEK */ +#define XK_ecaron 0x01ec /* U+011B LATIN SMALL LETTER E WITH CARON */ +#define XK_dcaron 0x01ef /* U+010F LATIN SMALL LETTER D WITH CARON */ +#define XK_dstroke 0x01f0 /* U+0111 LATIN SMALL LETTER D WITH STROKE */ +#define XK_nacute 0x01f1 /* U+0144 LATIN SMALL LETTER N WITH ACUTE */ +#define XK_ncaron 0x01f2 /* U+0148 LATIN SMALL LETTER N WITH CARON */ +#define XK_odoubleacute 0x01f5 /* U+0151 LATIN SMALL LETTER O WITH DOUBLE ACUTE */ +#define XK_udoubleacute 0x01fb /* U+0171 LATIN SMALL LETTER U WITH DOUBLE ACUTE */ +#define XK_rcaron 0x01f8 /* U+0159 LATIN SMALL LETTER R WITH CARON */ +#define XK_uring 0x01f9 /* U+016F LATIN SMALL LETTER U WITH RING ABOVE */ +#define XK_tcedilla 0x01fe /* U+0163 LATIN SMALL LETTER T WITH CEDILLA */ +#define XK_abovedot 0x01ff /* U+02D9 DOT ABOVE */ +#endif /* XK_LATIN2 */ + +/* + * Latin 3 + * Byte 3 = 2 + */ + +#ifdef XK_LATIN3 +#define XK_Hstroke 0x02a1 /* U+0126 LATIN CAPITAL LETTER H WITH STROKE */ +#define XK_Hcircumflex 0x02a6 /* U+0124 LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ +#define XK_Iabovedot 0x02a9 /* U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE */ +#define XK_Gbreve 0x02ab /* U+011E LATIN CAPITAL LETTER G WITH BREVE */ +#define XK_Jcircumflex 0x02ac /* U+0134 LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ +#define XK_hstroke 0x02b1 /* U+0127 LATIN SMALL LETTER H WITH STROKE */ +#define XK_hcircumflex 0x02b6 /* U+0125 LATIN SMALL LETTER H WITH CIRCUMFLEX */ +#define XK_idotless 0x02b9 /* U+0131 LATIN SMALL LETTER DOTLESS I */ +#define XK_gbreve 0x02bb /* U+011F LATIN SMALL LETTER G WITH BREVE */ +#define XK_jcircumflex 0x02bc /* U+0135 LATIN SMALL LETTER J WITH CIRCUMFLEX */ +#define XK_Cabovedot 0x02c5 /* U+010A LATIN CAPITAL LETTER C WITH DOT ABOVE */ +#define XK_Ccircumflex 0x02c6 /* U+0108 LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ +#define XK_Gabovedot 0x02d5 /* U+0120 LATIN CAPITAL LETTER G WITH DOT ABOVE */ +#define XK_Gcircumflex 0x02d8 /* U+011C LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ +#define XK_Ubreve 0x02dd /* U+016C LATIN CAPITAL LETTER U WITH BREVE */ +#define XK_Scircumflex 0x02de /* U+015C LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ +#define XK_cabovedot 0x02e5 /* U+010B LATIN SMALL LETTER C WITH DOT ABOVE */ +#define XK_ccircumflex 0x02e6 /* U+0109 LATIN SMALL LETTER C WITH CIRCUMFLEX */ +#define XK_gabovedot 0x02f5 /* U+0121 LATIN SMALL LETTER G WITH DOT ABOVE */ +#define XK_gcircumflex 0x02f8 /* U+011D LATIN SMALL LETTER G WITH CIRCUMFLEX */ +#define XK_ubreve 0x02fd /* U+016D LATIN SMALL LETTER U WITH BREVE */ +#define XK_scircumflex 0x02fe /* U+015D LATIN SMALL LETTER S WITH CIRCUMFLEX */ +#endif /* XK_LATIN3 */ + + +/* + * Latin 4 + * Byte 3 = 3 + */ + +#ifdef XK_LATIN4 +#define XK_kra 0x03a2 /* U+0138 LATIN SMALL LETTER KRA */ +#define XK_kappa 0x03a2 /* deprecated */ +#define XK_Rcedilla 0x03a3 /* U+0156 LATIN CAPITAL LETTER R WITH CEDILLA */ +#define XK_Itilde 0x03a5 /* U+0128 LATIN CAPITAL LETTER I WITH TILDE */ +#define XK_Lcedilla 0x03a6 /* U+013B LATIN CAPITAL LETTER L WITH CEDILLA */ +#define XK_Emacron 0x03aa /* U+0112 LATIN CAPITAL LETTER E WITH MACRON */ +#define XK_Gcedilla 0x03ab /* U+0122 LATIN CAPITAL LETTER G WITH CEDILLA */ +#define XK_Tslash 0x03ac /* U+0166 LATIN CAPITAL LETTER T WITH STROKE */ +#define XK_rcedilla 0x03b3 /* U+0157 LATIN SMALL LETTER R WITH CEDILLA */ +#define XK_itilde 0x03b5 /* U+0129 LATIN SMALL LETTER I WITH TILDE */ +#define XK_lcedilla 0x03b6 /* U+013C LATIN SMALL LETTER L WITH CEDILLA */ +#define XK_emacron 0x03ba /* U+0113 LATIN SMALL LETTER E WITH MACRON */ +#define XK_gcedilla 0x03bb /* U+0123 LATIN SMALL LETTER G WITH CEDILLA */ +#define XK_tslash 0x03bc /* U+0167 LATIN SMALL LETTER T WITH STROKE */ +#define XK_ENG 0x03bd /* U+014A LATIN CAPITAL LETTER ENG */ +#define XK_eng 0x03bf /* U+014B LATIN SMALL LETTER ENG */ +#define XK_Amacron 0x03c0 /* U+0100 LATIN CAPITAL LETTER A WITH MACRON */ +#define XK_Iogonek 0x03c7 /* U+012E LATIN CAPITAL LETTER I WITH OGONEK */ +#define XK_Eabovedot 0x03cc /* U+0116 LATIN CAPITAL LETTER E WITH DOT ABOVE */ +#define XK_Imacron 0x03cf /* U+012A LATIN CAPITAL LETTER I WITH MACRON */ +#define XK_Ncedilla 0x03d1 /* U+0145 LATIN CAPITAL LETTER N WITH CEDILLA */ +#define XK_Omacron 0x03d2 /* U+014C LATIN CAPITAL LETTER O WITH MACRON */ +#define XK_Kcedilla 0x03d3 /* U+0136 LATIN CAPITAL LETTER K WITH CEDILLA */ +#define XK_Uogonek 0x03d9 /* U+0172 LATIN CAPITAL LETTER U WITH OGONEK */ +#define XK_Utilde 0x03dd /* U+0168 LATIN CAPITAL LETTER U WITH TILDE */ +#define XK_Umacron 0x03de /* U+016A LATIN CAPITAL LETTER U WITH MACRON */ +#define XK_amacron 0x03e0 /* U+0101 LATIN SMALL LETTER A WITH MACRON */ +#define XK_iogonek 0x03e7 /* U+012F LATIN SMALL LETTER I WITH OGONEK */ +#define XK_eabovedot 0x03ec /* U+0117 LATIN SMALL LETTER E WITH DOT ABOVE */ +#define XK_imacron 0x03ef /* U+012B LATIN SMALL LETTER I WITH MACRON */ +#define XK_ncedilla 0x03f1 /* U+0146 LATIN SMALL LETTER N WITH CEDILLA */ +#define XK_omacron 0x03f2 /* U+014D LATIN SMALL LETTER O WITH MACRON */ +#define XK_kcedilla 0x03f3 /* U+0137 LATIN SMALL LETTER K WITH CEDILLA */ +#define XK_uogonek 0x03f9 /* U+0173 LATIN SMALL LETTER U WITH OGONEK */ +#define XK_utilde 0x03fd /* U+0169 LATIN SMALL LETTER U WITH TILDE */ +#define XK_umacron 0x03fe /* U+016B LATIN SMALL LETTER U WITH MACRON */ +#endif /* XK_LATIN4 */ + +/* + * Latin 8 + */ +#ifdef XK_LATIN8 +#define XK_Babovedot 0x1001e02 /* U+1E02 LATIN CAPITAL LETTER B WITH DOT ABOVE */ +#define XK_babovedot 0x1001e03 /* U+1E03 LATIN SMALL LETTER B WITH DOT ABOVE */ +#define XK_Dabovedot 0x1001e0a /* U+1E0A LATIN CAPITAL LETTER D WITH DOT ABOVE */ +#define XK_Wgrave 0x1001e80 /* U+1E80 LATIN CAPITAL LETTER W WITH GRAVE */ +#define XK_Wacute 0x1001e82 /* U+1E82 LATIN CAPITAL LETTER W WITH ACUTE */ +#define XK_dabovedot 0x1001e0b /* U+1E0B LATIN SMALL LETTER D WITH DOT ABOVE */ +#define XK_Ygrave 0x1001ef2 /* U+1EF2 LATIN CAPITAL LETTER Y WITH GRAVE */ +#define XK_Fabovedot 0x1001e1e /* U+1E1E LATIN CAPITAL LETTER F WITH DOT ABOVE */ +#define XK_fabovedot 0x1001e1f /* U+1E1F LATIN SMALL LETTER F WITH DOT ABOVE */ +#define XK_Mabovedot 0x1001e40 /* U+1E40 LATIN CAPITAL LETTER M WITH DOT ABOVE */ +#define XK_mabovedot 0x1001e41 /* U+1E41 LATIN SMALL LETTER M WITH DOT ABOVE */ +#define XK_Pabovedot 0x1001e56 /* U+1E56 LATIN CAPITAL LETTER P WITH DOT ABOVE */ +#define XK_wgrave 0x1001e81 /* U+1E81 LATIN SMALL LETTER W WITH GRAVE */ +#define XK_pabovedot 0x1001e57 /* U+1E57 LATIN SMALL LETTER P WITH DOT ABOVE */ +#define XK_wacute 0x1001e83 /* U+1E83 LATIN SMALL LETTER W WITH ACUTE */ +#define XK_Sabovedot 0x1001e60 /* U+1E60 LATIN CAPITAL LETTER S WITH DOT ABOVE */ +#define XK_ygrave 0x1001ef3 /* U+1EF3 LATIN SMALL LETTER Y WITH GRAVE */ +#define XK_Wdiaeresis 0x1001e84 /* U+1E84 LATIN CAPITAL LETTER W WITH DIAERESIS */ +#define XK_wdiaeresis 0x1001e85 /* U+1E85 LATIN SMALL LETTER W WITH DIAERESIS */ +#define XK_sabovedot 0x1001e61 /* U+1E61 LATIN SMALL LETTER S WITH DOT ABOVE */ +#define XK_Wcircumflex 0x1000174 /* U+0174 LATIN CAPITAL LETTER W WITH CIRCUMFLEX */ +#define XK_Tabovedot 0x1001e6a /* U+1E6A LATIN CAPITAL LETTER T WITH DOT ABOVE */ +#define XK_Ycircumflex 0x1000176 /* U+0176 LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */ +#define XK_wcircumflex 0x1000175 /* U+0175 LATIN SMALL LETTER W WITH CIRCUMFLEX */ +#define XK_tabovedot 0x1001e6b /* U+1E6B LATIN SMALL LETTER T WITH DOT ABOVE */ +#define XK_ycircumflex 0x1000177 /* U+0177 LATIN SMALL LETTER Y WITH CIRCUMFLEX */ +#endif /* XK_LATIN8 */ + +/* + * Latin 9 + * Byte 3 = 0x13 + */ + +#ifdef XK_LATIN9 +#define XK_OE 0x13bc /* U+0152 LATIN CAPITAL LIGATURE OE */ +#define XK_oe 0x13bd /* U+0153 LATIN SMALL LIGATURE OE */ +#define XK_Ydiaeresis 0x13be /* U+0178 LATIN CAPITAL LETTER Y WITH DIAERESIS */ +#endif /* XK_LATIN9 */ + +/* + * Katakana + * Byte 3 = 4 + */ + +#ifdef XK_KATAKANA +#define XK_overline 0x047e /* U+203E OVERLINE */ +#define XK_kana_fullstop 0x04a1 /* U+3002 IDEOGRAPHIC FULL STOP */ +#define XK_kana_openingbracket 0x04a2 /* U+300C LEFT CORNER BRACKET */ +#define XK_kana_closingbracket 0x04a3 /* U+300D RIGHT CORNER BRACKET */ +#define XK_kana_comma 0x04a4 /* U+3001 IDEOGRAPHIC COMMA */ +#define XK_kana_conjunctive 0x04a5 /* U+30FB KATAKANA MIDDLE DOT */ +#define XK_kana_middledot 0x04a5 /* deprecated */ +#define XK_kana_WO 0x04a6 /* U+30F2 KATAKANA LETTER WO */ +#define XK_kana_a 0x04a7 /* U+30A1 KATAKANA LETTER SMALL A */ +#define XK_kana_i 0x04a8 /* U+30A3 KATAKANA LETTER SMALL I */ +#define XK_kana_u 0x04a9 /* U+30A5 KATAKANA LETTER SMALL U */ +#define XK_kana_e 0x04aa /* U+30A7 KATAKANA LETTER SMALL E */ +#define XK_kana_o 0x04ab /* U+30A9 KATAKANA LETTER SMALL O */ +#define XK_kana_ya 0x04ac /* U+30E3 KATAKANA LETTER SMALL YA */ +#define XK_kana_yu 0x04ad /* U+30E5 KATAKANA LETTER SMALL YU */ +#define XK_kana_yo 0x04ae /* U+30E7 KATAKANA LETTER SMALL YO */ +#define XK_kana_tsu 0x04af /* U+30C3 KATAKANA LETTER SMALL TU */ +#define XK_kana_tu 0x04af /* deprecated */ +#define XK_prolongedsound 0x04b0 /* U+30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK */ +#define XK_kana_A 0x04b1 /* U+30A2 KATAKANA LETTER A */ +#define XK_kana_I 0x04b2 /* U+30A4 KATAKANA LETTER I */ +#define XK_kana_U 0x04b3 /* U+30A6 KATAKANA LETTER U */ +#define XK_kana_E 0x04b4 /* U+30A8 KATAKANA LETTER E */ +#define XK_kana_O 0x04b5 /* U+30AA KATAKANA LETTER O */ +#define XK_kana_KA 0x04b6 /* U+30AB KATAKANA LETTER KA */ +#define XK_kana_KI 0x04b7 /* U+30AD KATAKANA LETTER KI */ +#define XK_kana_KU 0x04b8 /* U+30AF KATAKANA LETTER KU */ +#define XK_kana_KE 0x04b9 /* U+30B1 KATAKANA LETTER KE */ +#define XK_kana_KO 0x04ba /* U+30B3 KATAKANA LETTER KO */ +#define XK_kana_SA 0x04bb /* U+30B5 KATAKANA LETTER SA */ +#define XK_kana_SHI 0x04bc /* U+30B7 KATAKANA LETTER SI */ +#define XK_kana_SU 0x04bd /* U+30B9 KATAKANA LETTER SU */ +#define XK_kana_SE 0x04be /* U+30BB KATAKANA LETTER SE */ +#define XK_kana_SO 0x04bf /* U+30BD KATAKANA LETTER SO */ +#define XK_kana_TA 0x04c0 /* U+30BF KATAKANA LETTER TA */ +#define XK_kana_CHI 0x04c1 /* U+30C1 KATAKANA LETTER TI */ +#define XK_kana_TI 0x04c1 /* deprecated */ +#define XK_kana_TSU 0x04c2 /* U+30C4 KATAKANA LETTER TU */ +#define XK_kana_TU 0x04c2 /* deprecated */ +#define XK_kana_TE 0x04c3 /* U+30C6 KATAKANA LETTER TE */ +#define XK_kana_TO 0x04c4 /* U+30C8 KATAKANA LETTER TO */ +#define XK_kana_NA 0x04c5 /* U+30CA KATAKANA LETTER NA */ +#define XK_kana_NI 0x04c6 /* U+30CB KATAKANA LETTER NI */ +#define XK_kana_NU 0x04c7 /* U+30CC KATAKANA LETTER NU */ +#define XK_kana_NE 0x04c8 /* U+30CD KATAKANA LETTER NE */ +#define XK_kana_NO 0x04c9 /* U+30CE KATAKANA LETTER NO */ +#define XK_kana_HA 0x04ca /* U+30CF KATAKANA LETTER HA */ +#define XK_kana_HI 0x04cb /* U+30D2 KATAKANA LETTER HI */ +#define XK_kana_FU 0x04cc /* U+30D5 KATAKANA LETTER HU */ +#define XK_kana_HU 0x04cc /* deprecated */ +#define XK_kana_HE 0x04cd /* U+30D8 KATAKANA LETTER HE */ +#define XK_kana_HO 0x04ce /* U+30DB KATAKANA LETTER HO */ +#define XK_kana_MA 0x04cf /* U+30DE KATAKANA LETTER MA */ +#define XK_kana_MI 0x04d0 /* U+30DF KATAKANA LETTER MI */ +#define XK_kana_MU 0x04d1 /* U+30E0 KATAKANA LETTER MU */ +#define XK_kana_ME 0x04d2 /* U+30E1 KATAKANA LETTER ME */ +#define XK_kana_MO 0x04d3 /* U+30E2 KATAKANA LETTER MO */ +#define XK_kana_YA 0x04d4 /* U+30E4 KATAKANA LETTER YA */ +#define XK_kana_YU 0x04d5 /* U+30E6 KATAKANA LETTER YU */ +#define XK_kana_YO 0x04d6 /* U+30E8 KATAKANA LETTER YO */ +#define XK_kana_RA 0x04d7 /* U+30E9 KATAKANA LETTER RA */ +#define XK_kana_RI 0x04d8 /* U+30EA KATAKANA LETTER RI */ +#define XK_kana_RU 0x04d9 /* U+30EB KATAKANA LETTER RU */ +#define XK_kana_RE 0x04da /* U+30EC KATAKANA LETTER RE */ +#define XK_kana_RO 0x04db /* U+30ED KATAKANA LETTER RO */ +#define XK_kana_WA 0x04dc /* U+30EF KATAKANA LETTER WA */ +#define XK_kana_N 0x04dd /* U+30F3 KATAKANA LETTER N */ +#define XK_voicedsound 0x04de /* U+309B KATAKANA-HIRAGANA VOICED SOUND MARK */ +#define XK_semivoicedsound 0x04df /* U+309C KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */ +#define XK_kana_switch 0xff7e /* Alias for mode_switch */ +#endif /* XK_KATAKANA */ + +/* + * Arabic + * Byte 3 = 5 + */ + +#ifdef XK_ARABIC +#define XK_Farsi_0 0x10006f0 /* U+06F0 EXTENDED ARABIC-INDIC DIGIT ZERO */ +#define XK_Farsi_1 0x10006f1 /* U+06F1 EXTENDED ARABIC-INDIC DIGIT ONE */ +#define XK_Farsi_2 0x10006f2 /* U+06F2 EXTENDED ARABIC-INDIC DIGIT TWO */ +#define XK_Farsi_3 0x10006f3 /* U+06F3 EXTENDED ARABIC-INDIC DIGIT THREE */ +#define XK_Farsi_4 0x10006f4 /* U+06F4 EXTENDED ARABIC-INDIC DIGIT FOUR */ +#define XK_Farsi_5 0x10006f5 /* U+06F5 EXTENDED ARABIC-INDIC DIGIT FIVE */ +#define XK_Farsi_6 0x10006f6 /* U+06F6 EXTENDED ARABIC-INDIC DIGIT SIX */ +#define XK_Farsi_7 0x10006f7 /* U+06F7 EXTENDED ARABIC-INDIC DIGIT SEVEN */ +#define XK_Farsi_8 0x10006f8 /* U+06F8 EXTENDED ARABIC-INDIC DIGIT EIGHT */ +#define XK_Farsi_9 0x10006f9 /* U+06F9 EXTENDED ARABIC-INDIC DIGIT NINE */ +#define XK_Arabic_percent 0x100066a /* U+066A ARABIC PERCENT SIGN */ +#define XK_Arabic_superscript_alef 0x1000670 /* U+0670 ARABIC LETTER SUPERSCRIPT ALEF */ +#define XK_Arabic_tteh 0x1000679 /* U+0679 ARABIC LETTER TTEH */ +#define XK_Arabic_peh 0x100067e /* U+067E ARABIC LETTER PEH */ +#define XK_Arabic_tcheh 0x1000686 /* U+0686 ARABIC LETTER TCHEH */ +#define XK_Arabic_ddal 0x1000688 /* U+0688 ARABIC LETTER DDAL */ +#define XK_Arabic_rreh 0x1000691 /* U+0691 ARABIC LETTER RREH */ +#define XK_Arabic_comma 0x05ac /* U+060C ARABIC COMMA */ +#define XK_Arabic_fullstop 0x10006d4 /* U+06D4 ARABIC FULL STOP */ +#define XK_Arabic_0 0x1000660 /* U+0660 ARABIC-INDIC DIGIT ZERO */ +#define XK_Arabic_1 0x1000661 /* U+0661 ARABIC-INDIC DIGIT ONE */ +#define XK_Arabic_2 0x1000662 /* U+0662 ARABIC-INDIC DIGIT TWO */ +#define XK_Arabic_3 0x1000663 /* U+0663 ARABIC-INDIC DIGIT THREE */ +#define XK_Arabic_4 0x1000664 /* U+0664 ARABIC-INDIC DIGIT FOUR */ +#define XK_Arabic_5 0x1000665 /* U+0665 ARABIC-INDIC DIGIT FIVE */ +#define XK_Arabic_6 0x1000666 /* U+0666 ARABIC-INDIC DIGIT SIX */ +#define XK_Arabic_7 0x1000667 /* U+0667 ARABIC-INDIC DIGIT SEVEN */ +#define XK_Arabic_8 0x1000668 /* U+0668 ARABIC-INDIC DIGIT EIGHT */ +#define XK_Arabic_9 0x1000669 /* U+0669 ARABIC-INDIC DIGIT NINE */ +#define XK_Arabic_semicolon 0x05bb /* U+061B ARABIC SEMICOLON */ +#define XK_Arabic_question_mark 0x05bf /* U+061F ARABIC QUESTION MARK */ +#define XK_Arabic_hamza 0x05c1 /* U+0621 ARABIC LETTER HAMZA */ +#define XK_Arabic_maddaonalef 0x05c2 /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */ +#define XK_Arabic_hamzaonalef 0x05c3 /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */ +#define XK_Arabic_hamzaonwaw 0x05c4 /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */ +#define XK_Arabic_hamzaunderalef 0x05c5 /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */ +#define XK_Arabic_hamzaonyeh 0x05c6 /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */ +#define XK_Arabic_alef 0x05c7 /* U+0627 ARABIC LETTER ALEF */ +#define XK_Arabic_beh 0x05c8 /* U+0628 ARABIC LETTER BEH */ +#define XK_Arabic_tehmarbuta 0x05c9 /* U+0629 ARABIC LETTER TEH MARBUTA */ +#define XK_Arabic_teh 0x05ca /* U+062A ARABIC LETTER TEH */ +#define XK_Arabic_theh 0x05cb /* U+062B ARABIC LETTER THEH */ +#define XK_Arabic_jeem 0x05cc /* U+062C ARABIC LETTER JEEM */ +#define XK_Arabic_hah 0x05cd /* U+062D ARABIC LETTER HAH */ +#define XK_Arabic_khah 0x05ce /* U+062E ARABIC LETTER KHAH */ +#define XK_Arabic_dal 0x05cf /* U+062F ARABIC LETTER DAL */ +#define XK_Arabic_thal 0x05d0 /* U+0630 ARABIC LETTER THAL */ +#define XK_Arabic_ra 0x05d1 /* U+0631 ARABIC LETTER REH */ +#define XK_Arabic_zain 0x05d2 /* U+0632 ARABIC LETTER ZAIN */ +#define XK_Arabic_seen 0x05d3 /* U+0633 ARABIC LETTER SEEN */ +#define XK_Arabic_sheen 0x05d4 /* U+0634 ARABIC LETTER SHEEN */ +#define XK_Arabic_sad 0x05d5 /* U+0635 ARABIC LETTER SAD */ +#define XK_Arabic_dad 0x05d6 /* U+0636 ARABIC LETTER DAD */ +#define XK_Arabic_tah 0x05d7 /* U+0637 ARABIC LETTER TAH */ +#define XK_Arabic_zah 0x05d8 /* U+0638 ARABIC LETTER ZAH */ +#define XK_Arabic_ain 0x05d9 /* U+0639 ARABIC LETTER AIN */ +#define XK_Arabic_ghain 0x05da /* U+063A ARABIC LETTER GHAIN */ +#define XK_Arabic_tatweel 0x05e0 /* U+0640 ARABIC TATWEEL */ +#define XK_Arabic_feh 0x05e1 /* U+0641 ARABIC LETTER FEH */ +#define XK_Arabic_qaf 0x05e2 /* U+0642 ARABIC LETTER QAF */ +#define XK_Arabic_kaf 0x05e3 /* U+0643 ARABIC LETTER KAF */ +#define XK_Arabic_lam 0x05e4 /* U+0644 ARABIC LETTER LAM */ +#define XK_Arabic_meem 0x05e5 /* U+0645 ARABIC LETTER MEEM */ +#define XK_Arabic_noon 0x05e6 /* U+0646 ARABIC LETTER NOON */ +#define XK_Arabic_ha 0x05e7 /* U+0647 ARABIC LETTER HEH */ +#define XK_Arabic_heh 0x05e7 /* deprecated */ +#define XK_Arabic_waw 0x05e8 /* U+0648 ARABIC LETTER WAW */ +#define XK_Arabic_alefmaksura 0x05e9 /* U+0649 ARABIC LETTER ALEF MAKSURA */ +#define XK_Arabic_yeh 0x05ea /* U+064A ARABIC LETTER YEH */ +#define XK_Arabic_fathatan 0x05eb /* U+064B ARABIC FATHATAN */ +#define XK_Arabic_dammatan 0x05ec /* U+064C ARABIC DAMMATAN */ +#define XK_Arabic_kasratan 0x05ed /* U+064D ARABIC KASRATAN */ +#define XK_Arabic_fatha 0x05ee /* U+064E ARABIC FATHA */ +#define XK_Arabic_damma 0x05ef /* U+064F ARABIC DAMMA */ +#define XK_Arabic_kasra 0x05f0 /* U+0650 ARABIC KASRA */ +#define XK_Arabic_shadda 0x05f1 /* U+0651 ARABIC SHADDA */ +#define XK_Arabic_sukun 0x05f2 /* U+0652 ARABIC SUKUN */ +#define XK_Arabic_madda_above 0x1000653 /* U+0653 ARABIC MADDAH ABOVE */ +#define XK_Arabic_hamza_above 0x1000654 /* U+0654 ARABIC HAMZA ABOVE */ +#define XK_Arabic_hamza_below 0x1000655 /* U+0655 ARABIC HAMZA BELOW */ +#define XK_Arabic_jeh 0x1000698 /* U+0698 ARABIC LETTER JEH */ +#define XK_Arabic_veh 0x10006a4 /* U+06A4 ARABIC LETTER VEH */ +#define XK_Arabic_keheh 0x10006a9 /* U+06A9 ARABIC LETTER KEHEH */ +#define XK_Arabic_gaf 0x10006af /* U+06AF ARABIC LETTER GAF */ +#define XK_Arabic_noon_ghunna 0x10006ba /* U+06BA ARABIC LETTER NOON GHUNNA */ +#define XK_Arabic_heh_doachashmee 0x10006be /* U+06BE ARABIC LETTER HEH DOACHASHMEE */ +#define XK_Farsi_yeh 0x10006cc /* U+06CC ARABIC LETTER FARSI YEH */ +#define XK_Arabic_farsi_yeh 0x10006cc /* U+06CC ARABIC LETTER FARSI YEH */ +#define XK_Arabic_yeh_baree 0x10006d2 /* U+06D2 ARABIC LETTER YEH BARREE */ +#define XK_Arabic_heh_goal 0x10006c1 /* U+06C1 ARABIC LETTER HEH GOAL */ +#define XK_Arabic_switch 0xff7e /* Alias for mode_switch */ +#endif /* XK_ARABIC */ + +/* + * Cyrillic + * Byte 3 = 6 + */ +#ifdef XK_CYRILLIC +#define XK_Cyrillic_GHE_bar 0x1000492 /* U+0492 CYRILLIC CAPITAL LETTER GHE WITH STROKE */ +#define XK_Cyrillic_ghe_bar 0x1000493 /* U+0493 CYRILLIC SMALL LETTER GHE WITH STROKE */ +#define XK_Cyrillic_ZHE_descender 0x1000496 /* U+0496 CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER */ +#define XK_Cyrillic_zhe_descender 0x1000497 /* U+0497 CYRILLIC SMALL LETTER ZHE WITH DESCENDER */ +#define XK_Cyrillic_KA_descender 0x100049a /* U+049A CYRILLIC CAPITAL LETTER KA WITH DESCENDER */ +#define XK_Cyrillic_ka_descender 0x100049b /* U+049B CYRILLIC SMALL LETTER KA WITH DESCENDER */ +#define XK_Cyrillic_KA_vertstroke 0x100049c /* U+049C CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE */ +#define XK_Cyrillic_ka_vertstroke 0x100049d /* U+049D CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE */ +#define XK_Cyrillic_EN_descender 0x10004a2 /* U+04A2 CYRILLIC CAPITAL LETTER EN WITH DESCENDER */ +#define XK_Cyrillic_en_descender 0x10004a3 /* U+04A3 CYRILLIC SMALL LETTER EN WITH DESCENDER */ +#define XK_Cyrillic_U_straight 0x10004ae /* U+04AE CYRILLIC CAPITAL LETTER STRAIGHT U */ +#define XK_Cyrillic_u_straight 0x10004af /* U+04AF CYRILLIC SMALL LETTER STRAIGHT U */ +#define XK_Cyrillic_U_straight_bar 0x10004b0 /* U+04B0 CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE */ +#define XK_Cyrillic_u_straight_bar 0x10004b1 /* U+04B1 CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE */ +#define XK_Cyrillic_HA_descender 0x10004b2 /* U+04B2 CYRILLIC CAPITAL LETTER HA WITH DESCENDER */ +#define XK_Cyrillic_ha_descender 0x10004b3 /* U+04B3 CYRILLIC SMALL LETTER HA WITH DESCENDER */ +#define XK_Cyrillic_CHE_descender 0x10004b6 /* U+04B6 CYRILLIC CAPITAL LETTER CHE WITH DESCENDER */ +#define XK_Cyrillic_che_descender 0x10004b7 /* U+04B7 CYRILLIC SMALL LETTER CHE WITH DESCENDER */ +#define XK_Cyrillic_CHE_vertstroke 0x10004b8 /* U+04B8 CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE */ +#define XK_Cyrillic_che_vertstroke 0x10004b9 /* U+04B9 CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE */ +#define XK_Cyrillic_SHHA 0x10004ba /* U+04BA CYRILLIC CAPITAL LETTER SHHA */ +#define XK_Cyrillic_shha 0x10004bb /* U+04BB CYRILLIC SMALL LETTER SHHA */ + +#define XK_Cyrillic_SCHWA 0x10004d8 /* U+04D8 CYRILLIC CAPITAL LETTER SCHWA */ +#define XK_Cyrillic_schwa 0x10004d9 /* U+04D9 CYRILLIC SMALL LETTER SCHWA */ +#define XK_Cyrillic_I_macron 0x10004e2 /* U+04E2 CYRILLIC CAPITAL LETTER I WITH MACRON */ +#define XK_Cyrillic_i_macron 0x10004e3 /* U+04E3 CYRILLIC SMALL LETTER I WITH MACRON */ +#define XK_Cyrillic_O_bar 0x10004e8 /* U+04E8 CYRILLIC CAPITAL LETTER BARRED O */ +#define XK_Cyrillic_o_bar 0x10004e9 /* U+04E9 CYRILLIC SMALL LETTER BARRED O */ +#define XK_Cyrillic_U_macron 0x10004ee /* U+04EE CYRILLIC CAPITAL LETTER U WITH MACRON */ +#define XK_Cyrillic_u_macron 0x10004ef /* U+04EF CYRILLIC SMALL LETTER U WITH MACRON */ + +#define XK_Serbian_dje 0x06a1 /* U+0452 CYRILLIC SMALL LETTER DJE */ +#define XK_Macedonia_gje 0x06a2 /* U+0453 CYRILLIC SMALL LETTER GJE */ +#define XK_Cyrillic_io 0x06a3 /* U+0451 CYRILLIC SMALL LETTER IO */ +#define XK_Ukrainian_ie 0x06a4 /* U+0454 CYRILLIC SMALL LETTER UKRAINIAN IE */ +#define XK_Ukranian_je 0x06a4 /* deprecated */ +#define XK_Macedonia_dse 0x06a5 /* U+0455 CYRILLIC SMALL LETTER DZE */ +#define XK_Ukrainian_i 0x06a6 /* U+0456 CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */ +#define XK_Ukranian_i 0x06a6 /* deprecated */ +#define XK_Ukrainian_yi 0x06a7 /* U+0457 CYRILLIC SMALL LETTER YI */ +#define XK_Ukranian_yi 0x06a7 /* deprecated */ +#define XK_Cyrillic_je 0x06a8 /* U+0458 CYRILLIC SMALL LETTER JE */ +#define XK_Serbian_je 0x06a8 /* deprecated */ +#define XK_Cyrillic_lje 0x06a9 /* U+0459 CYRILLIC SMALL LETTER LJE */ +#define XK_Serbian_lje 0x06a9 /* deprecated */ +#define XK_Cyrillic_nje 0x06aa /* U+045A CYRILLIC SMALL LETTER NJE */ +#define XK_Serbian_nje 0x06aa /* deprecated */ +#define XK_Serbian_tshe 0x06ab /* U+045B CYRILLIC SMALL LETTER TSHE */ +#define XK_Macedonia_kje 0x06ac /* U+045C CYRILLIC SMALL LETTER KJE */ +#define XK_Ukrainian_ghe_with_upturn 0x06ad /* U+0491 CYRILLIC SMALL LETTER GHE WITH UPTURN */ +#define XK_Byelorussian_shortu 0x06ae /* U+045E CYRILLIC SMALL LETTER SHORT U */ +#define XK_Cyrillic_dzhe 0x06af /* U+045F CYRILLIC SMALL LETTER DZHE */ +#define XK_Serbian_dze 0x06af /* deprecated */ +#define XK_numerosign 0x06b0 /* U+2116 NUMERO SIGN */ +#define XK_Serbian_DJE 0x06b1 /* U+0402 CYRILLIC CAPITAL LETTER DJE */ +#define XK_Macedonia_GJE 0x06b2 /* U+0403 CYRILLIC CAPITAL LETTER GJE */ +#define XK_Cyrillic_IO 0x06b3 /* U+0401 CYRILLIC CAPITAL LETTER IO */ +#define XK_Ukrainian_IE 0x06b4 /* U+0404 CYRILLIC CAPITAL LETTER UKRAINIAN IE */ +#define XK_Ukranian_JE 0x06b4 /* deprecated */ +#define XK_Macedonia_DSE 0x06b5 /* U+0405 CYRILLIC CAPITAL LETTER DZE */ +#define XK_Ukrainian_I 0x06b6 /* U+0406 CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */ +#define XK_Ukranian_I 0x06b6 /* deprecated */ +#define XK_Ukrainian_YI 0x06b7 /* U+0407 CYRILLIC CAPITAL LETTER YI */ +#define XK_Ukranian_YI 0x06b7 /* deprecated */ +#define XK_Cyrillic_JE 0x06b8 /* U+0408 CYRILLIC CAPITAL LETTER JE */ +#define XK_Serbian_JE 0x06b8 /* deprecated */ +#define XK_Cyrillic_LJE 0x06b9 /* U+0409 CYRILLIC CAPITAL LETTER LJE */ +#define XK_Serbian_LJE 0x06b9 /* deprecated */ +#define XK_Cyrillic_NJE 0x06ba /* U+040A CYRILLIC CAPITAL LETTER NJE */ +#define XK_Serbian_NJE 0x06ba /* deprecated */ +#define XK_Serbian_TSHE 0x06bb /* U+040B CYRILLIC CAPITAL LETTER TSHE */ +#define XK_Macedonia_KJE 0x06bc /* U+040C CYRILLIC CAPITAL LETTER KJE */ +#define XK_Ukrainian_GHE_WITH_UPTURN 0x06bd /* U+0490 CYRILLIC CAPITAL LETTER GHE WITH UPTURN */ +#define XK_Byelorussian_SHORTU 0x06be /* U+040E CYRILLIC CAPITAL LETTER SHORT U */ +#define XK_Cyrillic_DZHE 0x06bf /* U+040F CYRILLIC CAPITAL LETTER DZHE */ +#define XK_Serbian_DZE 0x06bf /* deprecated */ +#define XK_Cyrillic_yu 0x06c0 /* U+044E CYRILLIC SMALL LETTER YU */ +#define XK_Cyrillic_a 0x06c1 /* U+0430 CYRILLIC SMALL LETTER A */ +#define XK_Cyrillic_be 0x06c2 /* U+0431 CYRILLIC SMALL LETTER BE */ +#define XK_Cyrillic_tse 0x06c3 /* U+0446 CYRILLIC SMALL LETTER TSE */ +#define XK_Cyrillic_de 0x06c4 /* U+0434 CYRILLIC SMALL LETTER DE */ +#define XK_Cyrillic_ie 0x06c5 /* U+0435 CYRILLIC SMALL LETTER IE */ +#define XK_Cyrillic_ef 0x06c6 /* U+0444 CYRILLIC SMALL LETTER EF */ +#define XK_Cyrillic_ghe 0x06c7 /* U+0433 CYRILLIC SMALL LETTER GHE */ +#define XK_Cyrillic_ha 0x06c8 /* U+0445 CYRILLIC SMALL LETTER HA */ +#define XK_Cyrillic_i 0x06c9 /* U+0438 CYRILLIC SMALL LETTER I */ +#define XK_Cyrillic_shorti 0x06ca /* U+0439 CYRILLIC SMALL LETTER SHORT I */ +#define XK_Cyrillic_ka 0x06cb /* U+043A CYRILLIC SMALL LETTER KA */ +#define XK_Cyrillic_el 0x06cc /* U+043B CYRILLIC SMALL LETTER EL */ +#define XK_Cyrillic_em 0x06cd /* U+043C CYRILLIC SMALL LETTER EM */ +#define XK_Cyrillic_en 0x06ce /* U+043D CYRILLIC SMALL LETTER EN */ +#define XK_Cyrillic_o 0x06cf /* U+043E CYRILLIC SMALL LETTER O */ +#define XK_Cyrillic_pe 0x06d0 /* U+043F CYRILLIC SMALL LETTER PE */ +#define XK_Cyrillic_ya 0x06d1 /* U+044F CYRILLIC SMALL LETTER YA */ +#define XK_Cyrillic_er 0x06d2 /* U+0440 CYRILLIC SMALL LETTER ER */ +#define XK_Cyrillic_es 0x06d3 /* U+0441 CYRILLIC SMALL LETTER ES */ +#define XK_Cyrillic_te 0x06d4 /* U+0442 CYRILLIC SMALL LETTER TE */ +#define XK_Cyrillic_u 0x06d5 /* U+0443 CYRILLIC SMALL LETTER U */ +#define XK_Cyrillic_zhe 0x06d6 /* U+0436 CYRILLIC SMALL LETTER ZHE */ +#define XK_Cyrillic_ve 0x06d7 /* U+0432 CYRILLIC SMALL LETTER VE */ +#define XK_Cyrillic_softsign 0x06d8 /* U+044C CYRILLIC SMALL LETTER SOFT SIGN */ +#define XK_Cyrillic_yeru 0x06d9 /* U+044B CYRILLIC SMALL LETTER YERU */ +#define XK_Cyrillic_ze 0x06da /* U+0437 CYRILLIC SMALL LETTER ZE */ +#define XK_Cyrillic_sha 0x06db /* U+0448 CYRILLIC SMALL LETTER SHA */ +#define XK_Cyrillic_e 0x06dc /* U+044D CYRILLIC SMALL LETTER E */ +#define XK_Cyrillic_shcha 0x06dd /* U+0449 CYRILLIC SMALL LETTER SHCHA */ +#define XK_Cyrillic_che 0x06de /* U+0447 CYRILLIC SMALL LETTER CHE */ +#define XK_Cyrillic_hardsign 0x06df /* U+044A CYRILLIC SMALL LETTER HARD SIGN */ +#define XK_Cyrillic_YU 0x06e0 /* U+042E CYRILLIC CAPITAL LETTER YU */ +#define XK_Cyrillic_A 0x06e1 /* U+0410 CYRILLIC CAPITAL LETTER A */ +#define XK_Cyrillic_BE 0x06e2 /* U+0411 CYRILLIC CAPITAL LETTER BE */ +#define XK_Cyrillic_TSE 0x06e3 /* U+0426 CYRILLIC CAPITAL LETTER TSE */ +#define XK_Cyrillic_DE 0x06e4 /* U+0414 CYRILLIC CAPITAL LETTER DE */ +#define XK_Cyrillic_IE 0x06e5 /* U+0415 CYRILLIC CAPITAL LETTER IE */ +#define XK_Cyrillic_EF 0x06e6 /* U+0424 CYRILLIC CAPITAL LETTER EF */ +#define XK_Cyrillic_GHE 0x06e7 /* U+0413 CYRILLIC CAPITAL LETTER GHE */ +#define XK_Cyrillic_HA 0x06e8 /* U+0425 CYRILLIC CAPITAL LETTER HA */ +#define XK_Cyrillic_I 0x06e9 /* U+0418 CYRILLIC CAPITAL LETTER I */ +#define XK_Cyrillic_SHORTI 0x06ea /* U+0419 CYRILLIC CAPITAL LETTER SHORT I */ +#define XK_Cyrillic_KA 0x06eb /* U+041A CYRILLIC CAPITAL LETTER KA */ +#define XK_Cyrillic_EL 0x06ec /* U+041B CYRILLIC CAPITAL LETTER EL */ +#define XK_Cyrillic_EM 0x06ed /* U+041C CYRILLIC CAPITAL LETTER EM */ +#define XK_Cyrillic_EN 0x06ee /* U+041D CYRILLIC CAPITAL LETTER EN */ +#define XK_Cyrillic_O 0x06ef /* U+041E CYRILLIC CAPITAL LETTER O */ +#define XK_Cyrillic_PE 0x06f0 /* U+041F CYRILLIC CAPITAL LETTER PE */ +#define XK_Cyrillic_YA 0x06f1 /* U+042F CYRILLIC CAPITAL LETTER YA */ +#define XK_Cyrillic_ER 0x06f2 /* U+0420 CYRILLIC CAPITAL LETTER ER */ +#define XK_Cyrillic_ES 0x06f3 /* U+0421 CYRILLIC CAPITAL LETTER ES */ +#define XK_Cyrillic_TE 0x06f4 /* U+0422 CYRILLIC CAPITAL LETTER TE */ +#define XK_Cyrillic_U 0x06f5 /* U+0423 CYRILLIC CAPITAL LETTER U */ +#define XK_Cyrillic_ZHE 0x06f6 /* U+0416 CYRILLIC CAPITAL LETTER ZHE */ +#define XK_Cyrillic_VE 0x06f7 /* U+0412 CYRILLIC CAPITAL LETTER VE */ +#define XK_Cyrillic_SOFTSIGN 0x06f8 /* U+042C CYRILLIC CAPITAL LETTER SOFT SIGN */ +#define XK_Cyrillic_YERU 0x06f9 /* U+042B CYRILLIC CAPITAL LETTER YERU */ +#define XK_Cyrillic_ZE 0x06fa /* U+0417 CYRILLIC CAPITAL LETTER ZE */ +#define XK_Cyrillic_SHA 0x06fb /* U+0428 CYRILLIC CAPITAL LETTER SHA */ +#define XK_Cyrillic_E 0x06fc /* U+042D CYRILLIC CAPITAL LETTER E */ +#define XK_Cyrillic_SHCHA 0x06fd /* U+0429 CYRILLIC CAPITAL LETTER SHCHA */ +#define XK_Cyrillic_CHE 0x06fe /* U+0427 CYRILLIC CAPITAL LETTER CHE */ +#define XK_Cyrillic_HARDSIGN 0x06ff /* U+042A CYRILLIC CAPITAL LETTER HARD SIGN */ +#endif /* XK_CYRILLIC */ + +/* + * Greek + * (based on an early draft of, and not quite identical to, ISO/IEC 8859-7) + * Byte 3 = 7 + */ + +#ifdef XK_GREEK +#define XK_Greek_ALPHAaccent 0x07a1 /* U+0386 GREEK CAPITAL LETTER ALPHA WITH TONOS */ +#define XK_Greek_EPSILONaccent 0x07a2 /* U+0388 GREEK CAPITAL LETTER EPSILON WITH TONOS */ +#define XK_Greek_ETAaccent 0x07a3 /* U+0389 GREEK CAPITAL LETTER ETA WITH TONOS */ +#define XK_Greek_IOTAaccent 0x07a4 /* U+038A GREEK CAPITAL LETTER IOTA WITH TONOS */ +#define XK_Greek_IOTAdieresis 0x07a5 /* U+03AA GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ +#define XK_Greek_IOTAdiaeresis 0x07a5 /* old typo */ +#define XK_Greek_OMICRONaccent 0x07a7 /* U+038C GREEK CAPITAL LETTER OMICRON WITH TONOS */ +#define XK_Greek_UPSILONaccent 0x07a8 /* U+038E GREEK CAPITAL LETTER UPSILON WITH TONOS */ +#define XK_Greek_UPSILONdieresis 0x07a9 /* U+03AB GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ +#define XK_Greek_OMEGAaccent 0x07ab /* U+038F GREEK CAPITAL LETTER OMEGA WITH TONOS */ +#define XK_Greek_accentdieresis 0x07ae /* U+0385 GREEK DIALYTIKA TONOS */ +#define XK_Greek_horizbar 0x07af /* U+2015 HORIZONTAL BAR */ +#define XK_Greek_alphaaccent 0x07b1 /* U+03AC GREEK SMALL LETTER ALPHA WITH TONOS */ +#define XK_Greek_epsilonaccent 0x07b2 /* U+03AD GREEK SMALL LETTER EPSILON WITH TONOS */ +#define XK_Greek_etaaccent 0x07b3 /* U+03AE GREEK SMALL LETTER ETA WITH TONOS */ +#define XK_Greek_iotaaccent 0x07b4 /* U+03AF GREEK SMALL LETTER IOTA WITH TONOS */ +#define XK_Greek_iotadieresis 0x07b5 /* U+03CA GREEK SMALL LETTER IOTA WITH DIALYTIKA */ +#define XK_Greek_iotaaccentdieresis 0x07b6 /* U+0390 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ +#define XK_Greek_omicronaccent 0x07b7 /* U+03CC GREEK SMALL LETTER OMICRON WITH TONOS */ +#define XK_Greek_upsilonaccent 0x07b8 /* U+03CD GREEK SMALL LETTER UPSILON WITH TONOS */ +#define XK_Greek_upsilondieresis 0x07b9 /* U+03CB GREEK SMALL LETTER UPSILON WITH DIALYTIKA */ +#define XK_Greek_upsilonaccentdieresis 0x07ba /* U+03B0 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ +#define XK_Greek_omegaaccent 0x07bb /* U+03CE GREEK SMALL LETTER OMEGA WITH TONOS */ +#define XK_Greek_ALPHA 0x07c1 /* U+0391 GREEK CAPITAL LETTER ALPHA */ +#define XK_Greek_BETA 0x07c2 /* U+0392 GREEK CAPITAL LETTER BETA */ +#define XK_Greek_GAMMA 0x07c3 /* U+0393 GREEK CAPITAL LETTER GAMMA */ +#define XK_Greek_DELTA 0x07c4 /* U+0394 GREEK CAPITAL LETTER DELTA */ +#define XK_Greek_EPSILON 0x07c5 /* U+0395 GREEK CAPITAL LETTER EPSILON */ +#define XK_Greek_ZETA 0x07c6 /* U+0396 GREEK CAPITAL LETTER ZETA */ +#define XK_Greek_ETA 0x07c7 /* U+0397 GREEK CAPITAL LETTER ETA */ +#define XK_Greek_THETA 0x07c8 /* U+0398 GREEK CAPITAL LETTER THETA */ +#define XK_Greek_IOTA 0x07c9 /* U+0399 GREEK CAPITAL LETTER IOTA */ +#define XK_Greek_KAPPA 0x07ca /* U+039A GREEK CAPITAL LETTER KAPPA */ +#define XK_Greek_LAMDA 0x07cb /* U+039B GREEK CAPITAL LETTER LAMDA */ +#define XK_Greek_LAMBDA 0x07cb /* U+039B GREEK CAPITAL LETTER LAMDA */ +#define XK_Greek_MU 0x07cc /* U+039C GREEK CAPITAL LETTER MU */ +#define XK_Greek_NU 0x07cd /* U+039D GREEK CAPITAL LETTER NU */ +#define XK_Greek_XI 0x07ce /* U+039E GREEK CAPITAL LETTER XI */ +#define XK_Greek_OMICRON 0x07cf /* U+039F GREEK CAPITAL LETTER OMICRON */ +#define XK_Greek_PI 0x07d0 /* U+03A0 GREEK CAPITAL LETTER PI */ +#define XK_Greek_RHO 0x07d1 /* U+03A1 GREEK CAPITAL LETTER RHO */ +#define XK_Greek_SIGMA 0x07d2 /* U+03A3 GREEK CAPITAL LETTER SIGMA */ +#define XK_Greek_TAU 0x07d4 /* U+03A4 GREEK CAPITAL LETTER TAU */ +#define XK_Greek_UPSILON 0x07d5 /* U+03A5 GREEK CAPITAL LETTER UPSILON */ +#define XK_Greek_PHI 0x07d6 /* U+03A6 GREEK CAPITAL LETTER PHI */ +#define XK_Greek_CHI 0x07d7 /* U+03A7 GREEK CAPITAL LETTER CHI */ +#define XK_Greek_PSI 0x07d8 /* U+03A8 GREEK CAPITAL LETTER PSI */ +#define XK_Greek_OMEGA 0x07d9 /* U+03A9 GREEK CAPITAL LETTER OMEGA */ +#define XK_Greek_alpha 0x07e1 /* U+03B1 GREEK SMALL LETTER ALPHA */ +#define XK_Greek_beta 0x07e2 /* U+03B2 GREEK SMALL LETTER BETA */ +#define XK_Greek_gamma 0x07e3 /* U+03B3 GREEK SMALL LETTER GAMMA */ +#define XK_Greek_delta 0x07e4 /* U+03B4 GREEK SMALL LETTER DELTA */ +#define XK_Greek_epsilon 0x07e5 /* U+03B5 GREEK SMALL LETTER EPSILON */ +#define XK_Greek_zeta 0x07e6 /* U+03B6 GREEK SMALL LETTER ZETA */ +#define XK_Greek_eta 0x07e7 /* U+03B7 GREEK SMALL LETTER ETA */ +#define XK_Greek_theta 0x07e8 /* U+03B8 GREEK SMALL LETTER THETA */ +#define XK_Greek_iota 0x07e9 /* U+03B9 GREEK SMALL LETTER IOTA */ +#define XK_Greek_kappa 0x07ea /* U+03BA GREEK SMALL LETTER KAPPA */ +#define XK_Greek_lamda 0x07eb /* U+03BB GREEK SMALL LETTER LAMDA */ +#define XK_Greek_lambda 0x07eb /* U+03BB GREEK SMALL LETTER LAMDA */ +#define XK_Greek_mu 0x07ec /* U+03BC GREEK SMALL LETTER MU */ +#define XK_Greek_nu 0x07ed /* U+03BD GREEK SMALL LETTER NU */ +#define XK_Greek_xi 0x07ee /* U+03BE GREEK SMALL LETTER XI */ +#define XK_Greek_omicron 0x07ef /* U+03BF GREEK SMALL LETTER OMICRON */ +#define XK_Greek_pi 0x07f0 /* U+03C0 GREEK SMALL LETTER PI */ +#define XK_Greek_rho 0x07f1 /* U+03C1 GREEK SMALL LETTER RHO */ +#define XK_Greek_sigma 0x07f2 /* U+03C3 GREEK SMALL LETTER SIGMA */ +#define XK_Greek_finalsmallsigma 0x07f3 /* U+03C2 GREEK SMALL LETTER FINAL SIGMA */ +#define XK_Greek_tau 0x07f4 /* U+03C4 GREEK SMALL LETTER TAU */ +#define XK_Greek_upsilon 0x07f5 /* U+03C5 GREEK SMALL LETTER UPSILON */ +#define XK_Greek_phi 0x07f6 /* U+03C6 GREEK SMALL LETTER PHI */ +#define XK_Greek_chi 0x07f7 /* U+03C7 GREEK SMALL LETTER CHI */ +#define XK_Greek_psi 0x07f8 /* U+03C8 GREEK SMALL LETTER PSI */ +#define XK_Greek_omega 0x07f9 /* U+03C9 GREEK SMALL LETTER OMEGA */ +#define XK_Greek_switch 0xff7e /* Alias for mode_switch */ +#endif /* XK_GREEK */ + +/* + * Technical + * (from the DEC VT330/VT420 Technical Character Set, http://vt100.net/charsets/technical.html) + * Byte 3 = 8 + */ + +#ifdef XK_TECHNICAL +#define XK_leftradical 0x08a1 /* U+23B7 RADICAL SYMBOL BOTTOM */ +#define XK_topleftradical 0x08a2 /*(U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT)*/ +#define XK_horizconnector 0x08a3 /*(U+2500 BOX DRAWINGS LIGHT HORIZONTAL)*/ +#define XK_topintegral 0x08a4 /* U+2320 TOP HALF INTEGRAL */ +#define XK_botintegral 0x08a5 /* U+2321 BOTTOM HALF INTEGRAL */ +#define XK_vertconnector 0x08a6 /*(U+2502 BOX DRAWINGS LIGHT VERTICAL)*/ +#define XK_topleftsqbracket 0x08a7 /* U+23A1 LEFT SQUARE BRACKET UPPER CORNER */ +#define XK_botleftsqbracket 0x08a8 /* U+23A3 LEFT SQUARE BRACKET LOWER CORNER */ +#define XK_toprightsqbracket 0x08a9 /* U+23A4 RIGHT SQUARE BRACKET UPPER CORNER */ +#define XK_botrightsqbracket 0x08aa /* U+23A6 RIGHT SQUARE BRACKET LOWER CORNER */ +#define XK_topleftparens 0x08ab /* U+239B LEFT PARENTHESIS UPPER HOOK */ +#define XK_botleftparens 0x08ac /* U+239D LEFT PARENTHESIS LOWER HOOK */ +#define XK_toprightparens 0x08ad /* U+239E RIGHT PARENTHESIS UPPER HOOK */ +#define XK_botrightparens 0x08ae /* U+23A0 RIGHT PARENTHESIS LOWER HOOK */ +#define XK_leftmiddlecurlybrace 0x08af /* U+23A8 LEFT CURLY BRACKET MIDDLE PIECE */ +#define XK_rightmiddlecurlybrace 0x08b0 /* U+23AC RIGHT CURLY BRACKET MIDDLE PIECE */ +#define XK_topleftsummation 0x08b1 +#define XK_botleftsummation 0x08b2 +#define XK_topvertsummationconnector 0x08b3 +#define XK_botvertsummationconnector 0x08b4 +#define XK_toprightsummation 0x08b5 +#define XK_botrightsummation 0x08b6 +#define XK_rightmiddlesummation 0x08b7 +#define XK_lessthanequal 0x08bc /* U+2264 LESS-THAN OR EQUAL TO */ +#define XK_notequal 0x08bd /* U+2260 NOT EQUAL TO */ +#define XK_greaterthanequal 0x08be /* U+2265 GREATER-THAN OR EQUAL TO */ +#define XK_integral 0x08bf /* U+222B INTEGRAL */ +#define XK_therefore 0x08c0 /* U+2234 THEREFORE */ +#define XK_variation 0x08c1 /* U+221D PROPORTIONAL TO */ +#define XK_infinity 0x08c2 /* U+221E INFINITY */ +#define XK_nabla 0x08c5 /* U+2207 NABLA */ +#define XK_approximate 0x08c8 /* U+223C TILDE OPERATOR */ +#define XK_similarequal 0x08c9 /* U+2243 ASYMPTOTICALLY EQUAL TO */ +#define XK_ifonlyif 0x08cd /* U+21D4 LEFT RIGHT DOUBLE ARROW */ +#define XK_implies 0x08ce /* U+21D2 RIGHTWARDS DOUBLE ARROW */ +#define XK_identical 0x08cf /* U+2261 IDENTICAL TO */ +#define XK_radical 0x08d6 /* U+221A SQUARE ROOT */ +#define XK_includedin 0x08da /* U+2282 SUBSET OF */ +#define XK_includes 0x08db /* U+2283 SUPERSET OF */ +#define XK_intersection 0x08dc /* U+2229 INTERSECTION */ +#define XK_union 0x08dd /* U+222A UNION */ +#define XK_logicaland 0x08de /* U+2227 LOGICAL AND */ +#define XK_logicalor 0x08df /* U+2228 LOGICAL OR */ +#define XK_partialderivative 0x08ef /* U+2202 PARTIAL DIFFERENTIAL */ +#define XK_function 0x08f6 /* U+0192 LATIN SMALL LETTER F WITH HOOK */ +#define XK_leftarrow 0x08fb /* U+2190 LEFTWARDS ARROW */ +#define XK_uparrow 0x08fc /* U+2191 UPWARDS ARROW */ +#define XK_rightarrow 0x08fd /* U+2192 RIGHTWARDS ARROW */ +#define XK_downarrow 0x08fe /* U+2193 DOWNWARDS ARROW */ +#endif /* XK_TECHNICAL */ + +/* + * Special + * (from the DEC VT100 Special Graphics Character Set) + * Byte 3 = 9 + */ + +#ifdef XK_SPECIAL +#define XK_blank 0x09df +#define XK_soliddiamond 0x09e0 /* U+25C6 BLACK DIAMOND */ +#define XK_checkerboard 0x09e1 /* U+2592 MEDIUM SHADE */ +#define XK_ht 0x09e2 /* U+2409 SYMBOL FOR HORIZONTAL TABULATION */ +#define XK_ff 0x09e3 /* U+240C SYMBOL FOR FORM FEED */ +#define XK_cr 0x09e4 /* U+240D SYMBOL FOR CARRIAGE RETURN */ +#define XK_lf 0x09e5 /* U+240A SYMBOL FOR LINE FEED */ +#define XK_nl 0x09e8 /* U+2424 SYMBOL FOR NEWLINE */ +#define XK_vt 0x09e9 /* U+240B SYMBOL FOR VERTICAL TABULATION */ +#define XK_lowrightcorner 0x09ea /* U+2518 BOX DRAWINGS LIGHT UP AND LEFT */ +#define XK_uprightcorner 0x09eb /* U+2510 BOX DRAWINGS LIGHT DOWN AND LEFT */ +#define XK_upleftcorner 0x09ec /* U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT */ +#define XK_lowleftcorner 0x09ed /* U+2514 BOX DRAWINGS LIGHT UP AND RIGHT */ +#define XK_crossinglines 0x09ee /* U+253C BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ +#define XK_horizlinescan1 0x09ef /* U+23BA HORIZONTAL SCAN LINE-1 */ +#define XK_horizlinescan3 0x09f0 /* U+23BB HORIZONTAL SCAN LINE-3 */ +#define XK_horizlinescan5 0x09f1 /* U+2500 BOX DRAWINGS LIGHT HORIZONTAL */ +#define XK_horizlinescan7 0x09f2 /* U+23BC HORIZONTAL SCAN LINE-7 */ +#define XK_horizlinescan9 0x09f3 /* U+23BD HORIZONTAL SCAN LINE-9 */ +#define XK_leftt 0x09f4 /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ +#define XK_rightt 0x09f5 /* U+2524 BOX DRAWINGS LIGHT VERTICAL AND LEFT */ +#define XK_bott 0x09f6 /* U+2534 BOX DRAWINGS LIGHT UP AND HORIZONTAL */ +#define XK_topt 0x09f7 /* U+252C BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ +#define XK_vertbar 0x09f8 /* U+2502 BOX DRAWINGS LIGHT VERTICAL */ +#endif /* XK_SPECIAL */ + +/* + * Publishing + * (these are probably from a long forgotten DEC Publishing + * font that once shipped with DECwrite) + * Byte 3 = 0x0a + */ + +#ifdef XK_PUBLISHING +#define XK_emspace 0x0aa1 /* U+2003 EM SPACE */ +#define XK_enspace 0x0aa2 /* U+2002 EN SPACE */ +#define XK_em3space 0x0aa3 /* U+2004 THREE-PER-EM SPACE */ +#define XK_em4space 0x0aa4 /* U+2005 FOUR-PER-EM SPACE */ +#define XK_digitspace 0x0aa5 /* U+2007 FIGURE SPACE */ +#define XK_punctspace 0x0aa6 /* U+2008 PUNCTUATION SPACE */ +#define XK_thinspace 0x0aa7 /* U+2009 THIN SPACE */ +#define XK_hairspace 0x0aa8 /* U+200A HAIR SPACE */ +#define XK_emdash 0x0aa9 /* U+2014 EM DASH */ +#define XK_endash 0x0aaa /* U+2013 EN DASH */ +#define XK_signifblank 0x0aac /*(U+2423 OPEN BOX)*/ +#define XK_ellipsis 0x0aae /* U+2026 HORIZONTAL ELLIPSIS */ +#define XK_doubbaselinedot 0x0aaf /* U+2025 TWO DOT LEADER */ +#define XK_onethird 0x0ab0 /* U+2153 VULGAR FRACTION ONE THIRD */ +#define XK_twothirds 0x0ab1 /* U+2154 VULGAR FRACTION TWO THIRDS */ +#define XK_onefifth 0x0ab2 /* U+2155 VULGAR FRACTION ONE FIFTH */ +#define XK_twofifths 0x0ab3 /* U+2156 VULGAR FRACTION TWO FIFTHS */ +#define XK_threefifths 0x0ab4 /* U+2157 VULGAR FRACTION THREE FIFTHS */ +#define XK_fourfifths 0x0ab5 /* U+2158 VULGAR FRACTION FOUR FIFTHS */ +#define XK_onesixth 0x0ab6 /* U+2159 VULGAR FRACTION ONE SIXTH */ +#define XK_fivesixths 0x0ab7 /* U+215A VULGAR FRACTION FIVE SIXTHS */ +#define XK_careof 0x0ab8 /* U+2105 CARE OF */ +#define XK_figdash 0x0abb /* U+2012 FIGURE DASH */ +#define XK_leftanglebracket 0x0abc /*(U+27E8 MATHEMATICAL LEFT ANGLE BRACKET)*/ +#define XK_decimalpoint 0x0abd /*(U+002E FULL STOP)*/ +#define XK_rightanglebracket 0x0abe /*(U+27E9 MATHEMATICAL RIGHT ANGLE BRACKET)*/ +#define XK_marker 0x0abf +#define XK_oneeighth 0x0ac3 /* U+215B VULGAR FRACTION ONE EIGHTH */ +#define XK_threeeighths 0x0ac4 /* U+215C VULGAR FRACTION THREE EIGHTHS */ +#define XK_fiveeighths 0x0ac5 /* U+215D VULGAR FRACTION FIVE EIGHTHS */ +#define XK_seveneighths 0x0ac6 /* U+215E VULGAR FRACTION SEVEN EIGHTHS */ +#define XK_trademark 0x0ac9 /* U+2122 TRADE MARK SIGN */ +#define XK_signaturemark 0x0aca /*(U+2613 SALTIRE)*/ +#define XK_trademarkincircle 0x0acb +#define XK_leftopentriangle 0x0acc /*(U+25C1 WHITE LEFT-POINTING TRIANGLE)*/ +#define XK_rightopentriangle 0x0acd /*(U+25B7 WHITE RIGHT-POINTING TRIANGLE)*/ +#define XK_emopencircle 0x0ace /*(U+25CB WHITE CIRCLE)*/ +#define XK_emopenrectangle 0x0acf /*(U+25AF WHITE VERTICAL RECTANGLE)*/ +#define XK_leftsinglequotemark 0x0ad0 /* U+2018 LEFT SINGLE QUOTATION MARK */ +#define XK_rightsinglequotemark 0x0ad1 /* U+2019 RIGHT SINGLE QUOTATION MARK */ +#define XK_leftdoublequotemark 0x0ad2 /* U+201C LEFT DOUBLE QUOTATION MARK */ +#define XK_rightdoublequotemark 0x0ad3 /* U+201D RIGHT DOUBLE QUOTATION MARK */ +#define XK_prescription 0x0ad4 /* U+211E PRESCRIPTION TAKE */ +#define XK_minutes 0x0ad6 /* U+2032 PRIME */ +#define XK_seconds 0x0ad7 /* U+2033 DOUBLE PRIME */ +#define XK_latincross 0x0ad9 /* U+271D LATIN CROSS */ +#define XK_hexagram 0x0ada +#define XK_filledrectbullet 0x0adb /*(U+25AC BLACK RECTANGLE)*/ +#define XK_filledlefttribullet 0x0adc /*(U+25C0 BLACK LEFT-POINTING TRIANGLE)*/ +#define XK_filledrighttribullet 0x0add /*(U+25B6 BLACK RIGHT-POINTING TRIANGLE)*/ +#define XK_emfilledcircle 0x0ade /*(U+25CF BLACK CIRCLE)*/ +#define XK_emfilledrect 0x0adf /*(U+25AE BLACK VERTICAL RECTANGLE)*/ +#define XK_enopencircbullet 0x0ae0 /*(U+25E6 WHITE BULLET)*/ +#define XK_enopensquarebullet 0x0ae1 /*(U+25AB WHITE SMALL SQUARE)*/ +#define XK_openrectbullet 0x0ae2 /*(U+25AD WHITE RECTANGLE)*/ +#define XK_opentribulletup 0x0ae3 /*(U+25B3 WHITE UP-POINTING TRIANGLE)*/ +#define XK_opentribulletdown 0x0ae4 /*(U+25BD WHITE DOWN-POINTING TRIANGLE)*/ +#define XK_openstar 0x0ae5 /*(U+2606 WHITE STAR)*/ +#define XK_enfilledcircbullet 0x0ae6 /*(U+2022 BULLET)*/ +#define XK_enfilledsqbullet 0x0ae7 /*(U+25AA BLACK SMALL SQUARE)*/ +#define XK_filledtribulletup 0x0ae8 /*(U+25B2 BLACK UP-POINTING TRIANGLE)*/ +#define XK_filledtribulletdown 0x0ae9 /*(U+25BC BLACK DOWN-POINTING TRIANGLE)*/ +#define XK_leftpointer 0x0aea /*(U+261C WHITE LEFT POINTING INDEX)*/ +#define XK_rightpointer 0x0aeb /*(U+261E WHITE RIGHT POINTING INDEX)*/ +#define XK_club 0x0aec /* U+2663 BLACK CLUB SUIT */ +#define XK_diamond 0x0aed /* U+2666 BLACK DIAMOND SUIT */ +#define XK_heart 0x0aee /* U+2665 BLACK HEART SUIT */ +#define XK_maltesecross 0x0af0 /* U+2720 MALTESE CROSS */ +#define XK_dagger 0x0af1 /* U+2020 DAGGER */ +#define XK_doubledagger 0x0af2 /* U+2021 DOUBLE DAGGER */ +#define XK_checkmark 0x0af3 /* U+2713 CHECK MARK */ +#define XK_ballotcross 0x0af4 /* U+2717 BALLOT X */ +#define XK_musicalsharp 0x0af5 /* U+266F MUSIC SHARP SIGN */ +#define XK_musicalflat 0x0af6 /* U+266D MUSIC FLAT SIGN */ +#define XK_malesymbol 0x0af7 /* U+2642 MALE SIGN */ +#define XK_femalesymbol 0x0af8 /* U+2640 FEMALE SIGN */ +#define XK_telephone 0x0af9 /* U+260E BLACK TELEPHONE */ +#define XK_telephonerecorder 0x0afa /* U+2315 TELEPHONE RECORDER */ +#define XK_phonographcopyright 0x0afb /* U+2117 SOUND RECORDING COPYRIGHT */ +#define XK_caret 0x0afc /* U+2038 CARET */ +#define XK_singlelowquotemark 0x0afd /* U+201A SINGLE LOW-9 QUOTATION MARK */ +#define XK_doublelowquotemark 0x0afe /* U+201E DOUBLE LOW-9 QUOTATION MARK */ +#define XK_cursor 0x0aff +#endif /* XK_PUBLISHING */ + +/* + * APL + * Byte 3 = 0x0b + */ + +#ifdef XK_APL +#define XK_leftcaret 0x0ba3 /*(U+003C LESS-THAN SIGN)*/ +#define XK_rightcaret 0x0ba6 /*(U+003E GREATER-THAN SIGN)*/ +#define XK_downcaret 0x0ba8 /*(U+2228 LOGICAL OR)*/ +#define XK_upcaret 0x0ba9 /*(U+2227 LOGICAL AND)*/ +#define XK_overbar 0x0bc0 /*(U+00AF MACRON)*/ +#define XK_downtack 0x0bc2 /* U+22A4 DOWN TACK */ +#define XK_upshoe 0x0bc3 /*(U+2229 INTERSECTION)*/ +#define XK_downstile 0x0bc4 /* U+230A LEFT FLOOR */ +#define XK_underbar 0x0bc6 /*(U+005F LOW LINE)*/ +#define XK_jot 0x0bca /* U+2218 RING OPERATOR */ +#define XK_quad 0x0bcc /* U+2395 APL FUNCTIONAL SYMBOL QUAD */ +#define XK_uptack 0x0bce /* U+22A5 UP TACK */ +#define XK_circle 0x0bcf /* U+25CB WHITE CIRCLE */ +#define XK_upstile 0x0bd3 /* U+2308 LEFT CEILING */ +#define XK_downshoe 0x0bd6 /*(U+222A UNION)*/ +#define XK_rightshoe 0x0bd8 /*(U+2283 SUPERSET OF)*/ +#define XK_leftshoe 0x0bda /*(U+2282 SUBSET OF)*/ +#define XK_lefttack 0x0bdc /* U+22A3 LEFT TACK */ +#define XK_righttack 0x0bfc /* U+22A2 RIGHT TACK */ +#endif /* XK_APL */ + +/* + * Hebrew + * Byte 3 = 0x0c + */ + +#ifdef XK_HEBREW +#define XK_hebrew_doublelowline 0x0cdf /* U+2017 DOUBLE LOW LINE */ +#define XK_hebrew_aleph 0x0ce0 /* U+05D0 HEBREW LETTER ALEF */ +#define XK_hebrew_bet 0x0ce1 /* U+05D1 HEBREW LETTER BET */ +#define XK_hebrew_beth 0x0ce1 /* deprecated */ +#define XK_hebrew_gimel 0x0ce2 /* U+05D2 HEBREW LETTER GIMEL */ +#define XK_hebrew_gimmel 0x0ce2 /* deprecated */ +#define XK_hebrew_dalet 0x0ce3 /* U+05D3 HEBREW LETTER DALET */ +#define XK_hebrew_daleth 0x0ce3 /* deprecated */ +#define XK_hebrew_he 0x0ce4 /* U+05D4 HEBREW LETTER HE */ +#define XK_hebrew_waw 0x0ce5 /* U+05D5 HEBREW LETTER VAV */ +#define XK_hebrew_zain 0x0ce6 /* U+05D6 HEBREW LETTER ZAYIN */ +#define XK_hebrew_zayin 0x0ce6 /* deprecated */ +#define XK_hebrew_chet 0x0ce7 /* U+05D7 HEBREW LETTER HET */ +#define XK_hebrew_het 0x0ce7 /* deprecated */ +#define XK_hebrew_tet 0x0ce8 /* U+05D8 HEBREW LETTER TET */ +#define XK_hebrew_teth 0x0ce8 /* deprecated */ +#define XK_hebrew_yod 0x0ce9 /* U+05D9 HEBREW LETTER YOD */ +#define XK_hebrew_finalkaph 0x0cea /* U+05DA HEBREW LETTER FINAL KAF */ +#define XK_hebrew_kaph 0x0ceb /* U+05DB HEBREW LETTER KAF */ +#define XK_hebrew_lamed 0x0cec /* U+05DC HEBREW LETTER LAMED */ +#define XK_hebrew_finalmem 0x0ced /* U+05DD HEBREW LETTER FINAL MEM */ +#define XK_hebrew_mem 0x0cee /* U+05DE HEBREW LETTER MEM */ +#define XK_hebrew_finalnun 0x0cef /* U+05DF HEBREW LETTER FINAL NUN */ +#define XK_hebrew_nun 0x0cf0 /* U+05E0 HEBREW LETTER NUN */ +#define XK_hebrew_samech 0x0cf1 /* U+05E1 HEBREW LETTER SAMEKH */ +#define XK_hebrew_samekh 0x0cf1 /* deprecated */ +#define XK_hebrew_ayin 0x0cf2 /* U+05E2 HEBREW LETTER AYIN */ +#define XK_hebrew_finalpe 0x0cf3 /* U+05E3 HEBREW LETTER FINAL PE */ +#define XK_hebrew_pe 0x0cf4 /* U+05E4 HEBREW LETTER PE */ +#define XK_hebrew_finalzade 0x0cf5 /* U+05E5 HEBREW LETTER FINAL TSADI */ +#define XK_hebrew_finalzadi 0x0cf5 /* deprecated */ +#define XK_hebrew_zade 0x0cf6 /* U+05E6 HEBREW LETTER TSADI */ +#define XK_hebrew_zadi 0x0cf6 /* deprecated */ +#define XK_hebrew_qoph 0x0cf7 /* U+05E7 HEBREW LETTER QOF */ +#define XK_hebrew_kuf 0x0cf7 /* deprecated */ +#define XK_hebrew_resh 0x0cf8 /* U+05E8 HEBREW LETTER RESH */ +#define XK_hebrew_shin 0x0cf9 /* U+05E9 HEBREW LETTER SHIN */ +#define XK_hebrew_taw 0x0cfa /* U+05EA HEBREW LETTER TAV */ +#define XK_hebrew_taf 0x0cfa /* deprecated */ +#define XK_Hebrew_switch 0xff7e /* Alias for mode_switch */ +#endif /* XK_HEBREW */ + +/* + * Thai + * Byte 3 = 0x0d + */ + +#ifdef XK_THAI +#define XK_Thai_kokai 0x0da1 /* U+0E01 THAI CHARACTER KO KAI */ +#define XK_Thai_khokhai 0x0da2 /* U+0E02 THAI CHARACTER KHO KHAI */ +#define XK_Thai_khokhuat 0x0da3 /* U+0E03 THAI CHARACTER KHO KHUAT */ +#define XK_Thai_khokhwai 0x0da4 /* U+0E04 THAI CHARACTER KHO KHWAI */ +#define XK_Thai_khokhon 0x0da5 /* U+0E05 THAI CHARACTER KHO KHON */ +#define XK_Thai_khorakhang 0x0da6 /* U+0E06 THAI CHARACTER KHO RAKHANG */ +#define XK_Thai_ngongu 0x0da7 /* U+0E07 THAI CHARACTER NGO NGU */ +#define XK_Thai_chochan 0x0da8 /* U+0E08 THAI CHARACTER CHO CHAN */ +#define XK_Thai_choching 0x0da9 /* U+0E09 THAI CHARACTER CHO CHING */ +#define XK_Thai_chochang 0x0daa /* U+0E0A THAI CHARACTER CHO CHANG */ +#define XK_Thai_soso 0x0dab /* U+0E0B THAI CHARACTER SO SO */ +#define XK_Thai_chochoe 0x0dac /* U+0E0C THAI CHARACTER CHO CHOE */ +#define XK_Thai_yoying 0x0dad /* U+0E0D THAI CHARACTER YO YING */ +#define XK_Thai_dochada 0x0dae /* U+0E0E THAI CHARACTER DO CHADA */ +#define XK_Thai_topatak 0x0daf /* U+0E0F THAI CHARACTER TO PATAK */ +#define XK_Thai_thothan 0x0db0 /* U+0E10 THAI CHARACTER THO THAN */ +#define XK_Thai_thonangmontho 0x0db1 /* U+0E11 THAI CHARACTER THO NANGMONTHO */ +#define XK_Thai_thophuthao 0x0db2 /* U+0E12 THAI CHARACTER THO PHUTHAO */ +#define XK_Thai_nonen 0x0db3 /* U+0E13 THAI CHARACTER NO NEN */ +#define XK_Thai_dodek 0x0db4 /* U+0E14 THAI CHARACTER DO DEK */ +#define XK_Thai_totao 0x0db5 /* U+0E15 THAI CHARACTER TO TAO */ +#define XK_Thai_thothung 0x0db6 /* U+0E16 THAI CHARACTER THO THUNG */ +#define XK_Thai_thothahan 0x0db7 /* U+0E17 THAI CHARACTER THO THAHAN */ +#define XK_Thai_thothong 0x0db8 /* U+0E18 THAI CHARACTER THO THONG */ +#define XK_Thai_nonu 0x0db9 /* U+0E19 THAI CHARACTER NO NU */ +#define XK_Thai_bobaimai 0x0dba /* U+0E1A THAI CHARACTER BO BAIMAI */ +#define XK_Thai_popla 0x0dbb /* U+0E1B THAI CHARACTER PO PLA */ +#define XK_Thai_phophung 0x0dbc /* U+0E1C THAI CHARACTER PHO PHUNG */ +#define XK_Thai_fofa 0x0dbd /* U+0E1D THAI CHARACTER FO FA */ +#define XK_Thai_phophan 0x0dbe /* U+0E1E THAI CHARACTER PHO PHAN */ +#define XK_Thai_fofan 0x0dbf /* U+0E1F THAI CHARACTER FO FAN */ +#define XK_Thai_phosamphao 0x0dc0 /* U+0E20 THAI CHARACTER PHO SAMPHAO */ +#define XK_Thai_moma 0x0dc1 /* U+0E21 THAI CHARACTER MO MA */ +#define XK_Thai_yoyak 0x0dc2 /* U+0E22 THAI CHARACTER YO YAK */ +#define XK_Thai_rorua 0x0dc3 /* U+0E23 THAI CHARACTER RO RUA */ +#define XK_Thai_ru 0x0dc4 /* U+0E24 THAI CHARACTER RU */ +#define XK_Thai_loling 0x0dc5 /* U+0E25 THAI CHARACTER LO LING */ +#define XK_Thai_lu 0x0dc6 /* U+0E26 THAI CHARACTER LU */ +#define XK_Thai_wowaen 0x0dc7 /* U+0E27 THAI CHARACTER WO WAEN */ +#define XK_Thai_sosala 0x0dc8 /* U+0E28 THAI CHARACTER SO SALA */ +#define XK_Thai_sorusi 0x0dc9 /* U+0E29 THAI CHARACTER SO RUSI */ +#define XK_Thai_sosua 0x0dca /* U+0E2A THAI CHARACTER SO SUA */ +#define XK_Thai_hohip 0x0dcb /* U+0E2B THAI CHARACTER HO HIP */ +#define XK_Thai_lochula 0x0dcc /* U+0E2C THAI CHARACTER LO CHULA */ +#define XK_Thai_oang 0x0dcd /* U+0E2D THAI CHARACTER O ANG */ +#define XK_Thai_honokhuk 0x0dce /* U+0E2E THAI CHARACTER HO NOKHUK */ +#define XK_Thai_paiyannoi 0x0dcf /* U+0E2F THAI CHARACTER PAIYANNOI */ +#define XK_Thai_saraa 0x0dd0 /* U+0E30 THAI CHARACTER SARA A */ +#define XK_Thai_maihanakat 0x0dd1 /* U+0E31 THAI CHARACTER MAI HAN-AKAT */ +#define XK_Thai_saraaa 0x0dd2 /* U+0E32 THAI CHARACTER SARA AA */ +#define XK_Thai_saraam 0x0dd3 /* U+0E33 THAI CHARACTER SARA AM */ +#define XK_Thai_sarai 0x0dd4 /* U+0E34 THAI CHARACTER SARA I */ +#define XK_Thai_saraii 0x0dd5 /* U+0E35 THAI CHARACTER SARA II */ +#define XK_Thai_saraue 0x0dd6 /* U+0E36 THAI CHARACTER SARA UE */ +#define XK_Thai_sarauee 0x0dd7 /* U+0E37 THAI CHARACTER SARA UEE */ +#define XK_Thai_sarau 0x0dd8 /* U+0E38 THAI CHARACTER SARA U */ +#define XK_Thai_sarauu 0x0dd9 /* U+0E39 THAI CHARACTER SARA UU */ +#define XK_Thai_phinthu 0x0dda /* U+0E3A THAI CHARACTER PHINTHU */ +#define XK_Thai_maihanakat_maitho 0x0dde +#define XK_Thai_baht 0x0ddf /* U+0E3F THAI CURRENCY SYMBOL BAHT */ +#define XK_Thai_sarae 0x0de0 /* U+0E40 THAI CHARACTER SARA E */ +#define XK_Thai_saraae 0x0de1 /* U+0E41 THAI CHARACTER SARA AE */ +#define XK_Thai_sarao 0x0de2 /* U+0E42 THAI CHARACTER SARA O */ +#define XK_Thai_saraaimaimuan 0x0de3 /* U+0E43 THAI CHARACTER SARA AI MAIMUAN */ +#define XK_Thai_saraaimaimalai 0x0de4 /* U+0E44 THAI CHARACTER SARA AI MAIMALAI */ +#define XK_Thai_lakkhangyao 0x0de5 /* U+0E45 THAI CHARACTER LAKKHANGYAO */ +#define XK_Thai_maiyamok 0x0de6 /* U+0E46 THAI CHARACTER MAIYAMOK */ +#define XK_Thai_maitaikhu 0x0de7 /* U+0E47 THAI CHARACTER MAITAIKHU */ +#define XK_Thai_maiek 0x0de8 /* U+0E48 THAI CHARACTER MAI EK */ +#define XK_Thai_maitho 0x0de9 /* U+0E49 THAI CHARACTER MAI THO */ +#define XK_Thai_maitri 0x0dea /* U+0E4A THAI CHARACTER MAI TRI */ +#define XK_Thai_maichattawa 0x0deb /* U+0E4B THAI CHARACTER MAI CHATTAWA */ +#define XK_Thai_thanthakhat 0x0dec /* U+0E4C THAI CHARACTER THANTHAKHAT */ +#define XK_Thai_nikhahit 0x0ded /* U+0E4D THAI CHARACTER NIKHAHIT */ +#define XK_Thai_leksun 0x0df0 /* U+0E50 THAI DIGIT ZERO */ +#define XK_Thai_leknung 0x0df1 /* U+0E51 THAI DIGIT ONE */ +#define XK_Thai_leksong 0x0df2 /* U+0E52 THAI DIGIT TWO */ +#define XK_Thai_leksam 0x0df3 /* U+0E53 THAI DIGIT THREE */ +#define XK_Thai_leksi 0x0df4 /* U+0E54 THAI DIGIT FOUR */ +#define XK_Thai_lekha 0x0df5 /* U+0E55 THAI DIGIT FIVE */ +#define XK_Thai_lekhok 0x0df6 /* U+0E56 THAI DIGIT SIX */ +#define XK_Thai_lekchet 0x0df7 /* U+0E57 THAI DIGIT SEVEN */ +#define XK_Thai_lekpaet 0x0df8 /* U+0E58 THAI DIGIT EIGHT */ +#define XK_Thai_lekkao 0x0df9 /* U+0E59 THAI DIGIT NINE */ +#endif /* XK_THAI */ + +/* + * Korean + * Byte 3 = 0x0e + */ + +#ifdef XK_KOREAN + +#define XK_Hangul 0xff31 /* Hangul start/stop(toggle) */ +#define XK_Hangul_Start 0xff32 /* Hangul start */ +#define XK_Hangul_End 0xff33 /* Hangul end, English start */ +#define XK_Hangul_Hanja 0xff34 /* Start Hangul->Hanja Conversion */ +#define XK_Hangul_Jamo 0xff35 /* Hangul Jamo mode */ +#define XK_Hangul_Romaja 0xff36 /* Hangul Romaja mode */ +#define XK_Hangul_Codeinput 0xff37 /* Hangul code input mode */ +#define XK_Hangul_Jeonja 0xff38 /* Jeonja mode */ +#define XK_Hangul_Banja 0xff39 /* Banja mode */ +#define XK_Hangul_PreHanja 0xff3a /* Pre Hanja conversion */ +#define XK_Hangul_PostHanja 0xff3b /* Post Hanja conversion */ +#define XK_Hangul_SingleCandidate 0xff3c /* Single candidate */ +#define XK_Hangul_MultipleCandidate 0xff3d /* Multiple candidate */ +#define XK_Hangul_PreviousCandidate 0xff3e /* Previous candidate */ +#define XK_Hangul_Special 0xff3f /* Special symbols */ +#define XK_Hangul_switch 0xff7e /* Alias for mode_switch */ + +/* Hangul Consonant Characters */ +#define XK_Hangul_Kiyeog 0x0ea1 +#define XK_Hangul_SsangKiyeog 0x0ea2 +#define XK_Hangul_KiyeogSios 0x0ea3 +#define XK_Hangul_Nieun 0x0ea4 +#define XK_Hangul_NieunJieuj 0x0ea5 +#define XK_Hangul_NieunHieuh 0x0ea6 +#define XK_Hangul_Dikeud 0x0ea7 +#define XK_Hangul_SsangDikeud 0x0ea8 +#define XK_Hangul_Rieul 0x0ea9 +#define XK_Hangul_RieulKiyeog 0x0eaa +#define XK_Hangul_RieulMieum 0x0eab +#define XK_Hangul_RieulPieub 0x0eac +#define XK_Hangul_RieulSios 0x0ead +#define XK_Hangul_RieulTieut 0x0eae +#define XK_Hangul_RieulPhieuf 0x0eaf +#define XK_Hangul_RieulHieuh 0x0eb0 +#define XK_Hangul_Mieum 0x0eb1 +#define XK_Hangul_Pieub 0x0eb2 +#define XK_Hangul_SsangPieub 0x0eb3 +#define XK_Hangul_PieubSios 0x0eb4 +#define XK_Hangul_Sios 0x0eb5 +#define XK_Hangul_SsangSios 0x0eb6 +#define XK_Hangul_Ieung 0x0eb7 +#define XK_Hangul_Jieuj 0x0eb8 +#define XK_Hangul_SsangJieuj 0x0eb9 +#define XK_Hangul_Cieuc 0x0eba +#define XK_Hangul_Khieuq 0x0ebb +#define XK_Hangul_Tieut 0x0ebc +#define XK_Hangul_Phieuf 0x0ebd +#define XK_Hangul_Hieuh 0x0ebe + +/* Hangul Vowel Characters */ +#define XK_Hangul_A 0x0ebf +#define XK_Hangul_AE 0x0ec0 +#define XK_Hangul_YA 0x0ec1 +#define XK_Hangul_YAE 0x0ec2 +#define XK_Hangul_EO 0x0ec3 +#define XK_Hangul_E 0x0ec4 +#define XK_Hangul_YEO 0x0ec5 +#define XK_Hangul_YE 0x0ec6 +#define XK_Hangul_O 0x0ec7 +#define XK_Hangul_WA 0x0ec8 +#define XK_Hangul_WAE 0x0ec9 +#define XK_Hangul_OE 0x0eca +#define XK_Hangul_YO 0x0ecb +#define XK_Hangul_U 0x0ecc +#define XK_Hangul_WEO 0x0ecd +#define XK_Hangul_WE 0x0ece +#define XK_Hangul_WI 0x0ecf +#define XK_Hangul_YU 0x0ed0 +#define XK_Hangul_EU 0x0ed1 +#define XK_Hangul_YI 0x0ed2 +#define XK_Hangul_I 0x0ed3 + +/* Hangul syllable-final (JongSeong) Characters */ +#define XK_Hangul_J_Kiyeog 0x0ed4 +#define XK_Hangul_J_SsangKiyeog 0x0ed5 +#define XK_Hangul_J_KiyeogSios 0x0ed6 +#define XK_Hangul_J_Nieun 0x0ed7 +#define XK_Hangul_J_NieunJieuj 0x0ed8 +#define XK_Hangul_J_NieunHieuh 0x0ed9 +#define XK_Hangul_J_Dikeud 0x0eda +#define XK_Hangul_J_Rieul 0x0edb +#define XK_Hangul_J_RieulKiyeog 0x0edc +#define XK_Hangul_J_RieulMieum 0x0edd +#define XK_Hangul_J_RieulPieub 0x0ede +#define XK_Hangul_J_RieulSios 0x0edf +#define XK_Hangul_J_RieulTieut 0x0ee0 +#define XK_Hangul_J_RieulPhieuf 0x0ee1 +#define XK_Hangul_J_RieulHieuh 0x0ee2 +#define XK_Hangul_J_Mieum 0x0ee3 +#define XK_Hangul_J_Pieub 0x0ee4 +#define XK_Hangul_J_PieubSios 0x0ee5 +#define XK_Hangul_J_Sios 0x0ee6 +#define XK_Hangul_J_SsangSios 0x0ee7 +#define XK_Hangul_J_Ieung 0x0ee8 +#define XK_Hangul_J_Jieuj 0x0ee9 +#define XK_Hangul_J_Cieuc 0x0eea +#define XK_Hangul_J_Khieuq 0x0eeb +#define XK_Hangul_J_Tieut 0x0eec +#define XK_Hangul_J_Phieuf 0x0eed +#define XK_Hangul_J_Hieuh 0x0eee + +/* Ancient Hangul Consonant Characters */ +#define XK_Hangul_RieulYeorinHieuh 0x0eef +#define XK_Hangul_SunkyeongeumMieum 0x0ef0 +#define XK_Hangul_SunkyeongeumPieub 0x0ef1 +#define XK_Hangul_PanSios 0x0ef2 +#define XK_Hangul_KkogjiDalrinIeung 0x0ef3 +#define XK_Hangul_SunkyeongeumPhieuf 0x0ef4 +#define XK_Hangul_YeorinHieuh 0x0ef5 + +/* Ancient Hangul Vowel Characters */ +#define XK_Hangul_AraeA 0x0ef6 +#define XK_Hangul_AraeAE 0x0ef7 + +/* Ancient Hangul syllable-final (JongSeong) Characters */ +#define XK_Hangul_J_PanSios 0x0ef8 +#define XK_Hangul_J_KkogjiDalrinIeung 0x0ef9 +#define XK_Hangul_J_YeorinHieuh 0x0efa + +/* Korean currency symbol */ +#define XK_Korean_Won 0x0eff /*(U+20A9 WON SIGN)*/ + +#endif /* XK_KOREAN */ + +/* + * Armenian + */ + +#ifdef XK_ARMENIAN +#define XK_Armenian_ligature_ew 0x1000587 /* U+0587 ARMENIAN SMALL LIGATURE ECH YIWN */ +#define XK_Armenian_full_stop 0x1000589 /* U+0589 ARMENIAN FULL STOP */ +#define XK_Armenian_verjaket 0x1000589 /* U+0589 ARMENIAN FULL STOP */ +#define XK_Armenian_separation_mark 0x100055d /* U+055D ARMENIAN COMMA */ +#define XK_Armenian_but 0x100055d /* U+055D ARMENIAN COMMA */ +#define XK_Armenian_hyphen 0x100058a /* U+058A ARMENIAN HYPHEN */ +#define XK_Armenian_yentamna 0x100058a /* U+058A ARMENIAN HYPHEN */ +#define XK_Armenian_exclam 0x100055c /* U+055C ARMENIAN EXCLAMATION MARK */ +#define XK_Armenian_amanak 0x100055c /* U+055C ARMENIAN EXCLAMATION MARK */ +#define XK_Armenian_accent 0x100055b /* U+055B ARMENIAN EMPHASIS MARK */ +#define XK_Armenian_shesht 0x100055b /* U+055B ARMENIAN EMPHASIS MARK */ +#define XK_Armenian_question 0x100055e /* U+055E ARMENIAN QUESTION MARK */ +#define XK_Armenian_paruyk 0x100055e /* U+055E ARMENIAN QUESTION MARK */ +#define XK_Armenian_AYB 0x1000531 /* U+0531 ARMENIAN CAPITAL LETTER AYB */ +#define XK_Armenian_ayb 0x1000561 /* U+0561 ARMENIAN SMALL LETTER AYB */ +#define XK_Armenian_BEN 0x1000532 /* U+0532 ARMENIAN CAPITAL LETTER BEN */ +#define XK_Armenian_ben 0x1000562 /* U+0562 ARMENIAN SMALL LETTER BEN */ +#define XK_Armenian_GIM 0x1000533 /* U+0533 ARMENIAN CAPITAL LETTER GIM */ +#define XK_Armenian_gim 0x1000563 /* U+0563 ARMENIAN SMALL LETTER GIM */ +#define XK_Armenian_DA 0x1000534 /* U+0534 ARMENIAN CAPITAL LETTER DA */ +#define XK_Armenian_da 0x1000564 /* U+0564 ARMENIAN SMALL LETTER DA */ +#define XK_Armenian_YECH 0x1000535 /* U+0535 ARMENIAN CAPITAL LETTER ECH */ +#define XK_Armenian_yech 0x1000565 /* U+0565 ARMENIAN SMALL LETTER ECH */ +#define XK_Armenian_ZA 0x1000536 /* U+0536 ARMENIAN CAPITAL LETTER ZA */ +#define XK_Armenian_za 0x1000566 /* U+0566 ARMENIAN SMALL LETTER ZA */ +#define XK_Armenian_E 0x1000537 /* U+0537 ARMENIAN CAPITAL LETTER EH */ +#define XK_Armenian_e 0x1000567 /* U+0567 ARMENIAN SMALL LETTER EH */ +#define XK_Armenian_AT 0x1000538 /* U+0538 ARMENIAN CAPITAL LETTER ET */ +#define XK_Armenian_at 0x1000568 /* U+0568 ARMENIAN SMALL LETTER ET */ +#define XK_Armenian_TO 0x1000539 /* U+0539 ARMENIAN CAPITAL LETTER TO */ +#define XK_Armenian_to 0x1000569 /* U+0569 ARMENIAN SMALL LETTER TO */ +#define XK_Armenian_ZHE 0x100053a /* U+053A ARMENIAN CAPITAL LETTER ZHE */ +#define XK_Armenian_zhe 0x100056a /* U+056A ARMENIAN SMALL LETTER ZHE */ +#define XK_Armenian_INI 0x100053b /* U+053B ARMENIAN CAPITAL LETTER INI */ +#define XK_Armenian_ini 0x100056b /* U+056B ARMENIAN SMALL LETTER INI */ +#define XK_Armenian_LYUN 0x100053c /* U+053C ARMENIAN CAPITAL LETTER LIWN */ +#define XK_Armenian_lyun 0x100056c /* U+056C ARMENIAN SMALL LETTER LIWN */ +#define XK_Armenian_KHE 0x100053d /* U+053D ARMENIAN CAPITAL LETTER XEH */ +#define XK_Armenian_khe 0x100056d /* U+056D ARMENIAN SMALL LETTER XEH */ +#define XK_Armenian_TSA 0x100053e /* U+053E ARMENIAN CAPITAL LETTER CA */ +#define XK_Armenian_tsa 0x100056e /* U+056E ARMENIAN SMALL LETTER CA */ +#define XK_Armenian_KEN 0x100053f /* U+053F ARMENIAN CAPITAL LETTER KEN */ +#define XK_Armenian_ken 0x100056f /* U+056F ARMENIAN SMALL LETTER KEN */ +#define XK_Armenian_HO 0x1000540 /* U+0540 ARMENIAN CAPITAL LETTER HO */ +#define XK_Armenian_ho 0x1000570 /* U+0570 ARMENIAN SMALL LETTER HO */ +#define XK_Armenian_DZA 0x1000541 /* U+0541 ARMENIAN CAPITAL LETTER JA */ +#define XK_Armenian_dza 0x1000571 /* U+0571 ARMENIAN SMALL LETTER JA */ +#define XK_Armenian_GHAT 0x1000542 /* U+0542 ARMENIAN CAPITAL LETTER GHAD */ +#define XK_Armenian_ghat 0x1000572 /* U+0572 ARMENIAN SMALL LETTER GHAD */ +#define XK_Armenian_TCHE 0x1000543 /* U+0543 ARMENIAN CAPITAL LETTER CHEH */ +#define XK_Armenian_tche 0x1000573 /* U+0573 ARMENIAN SMALL LETTER CHEH */ +#define XK_Armenian_MEN 0x1000544 /* U+0544 ARMENIAN CAPITAL LETTER MEN */ +#define XK_Armenian_men 0x1000574 /* U+0574 ARMENIAN SMALL LETTER MEN */ +#define XK_Armenian_HI 0x1000545 /* U+0545 ARMENIAN CAPITAL LETTER YI */ +#define XK_Armenian_hi 0x1000575 /* U+0575 ARMENIAN SMALL LETTER YI */ +#define XK_Armenian_NU 0x1000546 /* U+0546 ARMENIAN CAPITAL LETTER NOW */ +#define XK_Armenian_nu 0x1000576 /* U+0576 ARMENIAN SMALL LETTER NOW */ +#define XK_Armenian_SHA 0x1000547 /* U+0547 ARMENIAN CAPITAL LETTER SHA */ +#define XK_Armenian_sha 0x1000577 /* U+0577 ARMENIAN SMALL LETTER SHA */ +#define XK_Armenian_VO 0x1000548 /* U+0548 ARMENIAN CAPITAL LETTER VO */ +#define XK_Armenian_vo 0x1000578 /* U+0578 ARMENIAN SMALL LETTER VO */ +#define XK_Armenian_CHA 0x1000549 /* U+0549 ARMENIAN CAPITAL LETTER CHA */ +#define XK_Armenian_cha 0x1000579 /* U+0579 ARMENIAN SMALL LETTER CHA */ +#define XK_Armenian_PE 0x100054a /* U+054A ARMENIAN CAPITAL LETTER PEH */ +#define XK_Armenian_pe 0x100057a /* U+057A ARMENIAN SMALL LETTER PEH */ +#define XK_Armenian_JE 0x100054b /* U+054B ARMENIAN CAPITAL LETTER JHEH */ +#define XK_Armenian_je 0x100057b /* U+057B ARMENIAN SMALL LETTER JHEH */ +#define XK_Armenian_RA 0x100054c /* U+054C ARMENIAN CAPITAL LETTER RA */ +#define XK_Armenian_ra 0x100057c /* U+057C ARMENIAN SMALL LETTER RA */ +#define XK_Armenian_SE 0x100054d /* U+054D ARMENIAN CAPITAL LETTER SEH */ +#define XK_Armenian_se 0x100057d /* U+057D ARMENIAN SMALL LETTER SEH */ +#define XK_Armenian_VEV 0x100054e /* U+054E ARMENIAN CAPITAL LETTER VEW */ +#define XK_Armenian_vev 0x100057e /* U+057E ARMENIAN SMALL LETTER VEW */ +#define XK_Armenian_TYUN 0x100054f /* U+054F ARMENIAN CAPITAL LETTER TIWN */ +#define XK_Armenian_tyun 0x100057f /* U+057F ARMENIAN SMALL LETTER TIWN */ +#define XK_Armenian_RE 0x1000550 /* U+0550 ARMENIAN CAPITAL LETTER REH */ +#define XK_Armenian_re 0x1000580 /* U+0580 ARMENIAN SMALL LETTER REH */ +#define XK_Armenian_TSO 0x1000551 /* U+0551 ARMENIAN CAPITAL LETTER CO */ +#define XK_Armenian_tso 0x1000581 /* U+0581 ARMENIAN SMALL LETTER CO */ +#define XK_Armenian_VYUN 0x1000552 /* U+0552 ARMENIAN CAPITAL LETTER YIWN */ +#define XK_Armenian_vyun 0x1000582 /* U+0582 ARMENIAN SMALL LETTER YIWN */ +#define XK_Armenian_PYUR 0x1000553 /* U+0553 ARMENIAN CAPITAL LETTER PIWR */ +#define XK_Armenian_pyur 0x1000583 /* U+0583 ARMENIAN SMALL LETTER PIWR */ +#define XK_Armenian_KE 0x1000554 /* U+0554 ARMENIAN CAPITAL LETTER KEH */ +#define XK_Armenian_ke 0x1000584 /* U+0584 ARMENIAN SMALL LETTER KEH */ +#define XK_Armenian_O 0x1000555 /* U+0555 ARMENIAN CAPITAL LETTER OH */ +#define XK_Armenian_o 0x1000585 /* U+0585 ARMENIAN SMALL LETTER OH */ +#define XK_Armenian_FE 0x1000556 /* U+0556 ARMENIAN CAPITAL LETTER FEH */ +#define XK_Armenian_fe 0x1000586 /* U+0586 ARMENIAN SMALL LETTER FEH */ +#define XK_Armenian_apostrophe 0x100055a /* U+055A ARMENIAN APOSTROPHE */ +#endif /* XK_ARMENIAN */ + +/* + * Georgian + */ + +#ifdef XK_GEORGIAN +#define XK_Georgian_an 0x10010d0 /* U+10D0 GEORGIAN LETTER AN */ +#define XK_Georgian_ban 0x10010d1 /* U+10D1 GEORGIAN LETTER BAN */ +#define XK_Georgian_gan 0x10010d2 /* U+10D2 GEORGIAN LETTER GAN */ +#define XK_Georgian_don 0x10010d3 /* U+10D3 GEORGIAN LETTER DON */ +#define XK_Georgian_en 0x10010d4 /* U+10D4 GEORGIAN LETTER EN */ +#define XK_Georgian_vin 0x10010d5 /* U+10D5 GEORGIAN LETTER VIN */ +#define XK_Georgian_zen 0x10010d6 /* U+10D6 GEORGIAN LETTER ZEN */ +#define XK_Georgian_tan 0x10010d7 /* U+10D7 GEORGIAN LETTER TAN */ +#define XK_Georgian_in 0x10010d8 /* U+10D8 GEORGIAN LETTER IN */ +#define XK_Georgian_kan 0x10010d9 /* U+10D9 GEORGIAN LETTER KAN */ +#define XK_Georgian_las 0x10010da /* U+10DA GEORGIAN LETTER LAS */ +#define XK_Georgian_man 0x10010db /* U+10DB GEORGIAN LETTER MAN */ +#define XK_Georgian_nar 0x10010dc /* U+10DC GEORGIAN LETTER NAR */ +#define XK_Georgian_on 0x10010dd /* U+10DD GEORGIAN LETTER ON */ +#define XK_Georgian_par 0x10010de /* U+10DE GEORGIAN LETTER PAR */ +#define XK_Georgian_zhar 0x10010df /* U+10DF GEORGIAN LETTER ZHAR */ +#define XK_Georgian_rae 0x10010e0 /* U+10E0 GEORGIAN LETTER RAE */ +#define XK_Georgian_san 0x10010e1 /* U+10E1 GEORGIAN LETTER SAN */ +#define XK_Georgian_tar 0x10010e2 /* U+10E2 GEORGIAN LETTER TAR */ +#define XK_Georgian_un 0x10010e3 /* U+10E3 GEORGIAN LETTER UN */ +#define XK_Georgian_phar 0x10010e4 /* U+10E4 GEORGIAN LETTER PHAR */ +#define XK_Georgian_khar 0x10010e5 /* U+10E5 GEORGIAN LETTER KHAR */ +#define XK_Georgian_ghan 0x10010e6 /* U+10E6 GEORGIAN LETTER GHAN */ +#define XK_Georgian_qar 0x10010e7 /* U+10E7 GEORGIAN LETTER QAR */ +#define XK_Georgian_shin 0x10010e8 /* U+10E8 GEORGIAN LETTER SHIN */ +#define XK_Georgian_chin 0x10010e9 /* U+10E9 GEORGIAN LETTER CHIN */ +#define XK_Georgian_can 0x10010ea /* U+10EA GEORGIAN LETTER CAN */ +#define XK_Georgian_jil 0x10010eb /* U+10EB GEORGIAN LETTER JIL */ +#define XK_Georgian_cil 0x10010ec /* U+10EC GEORGIAN LETTER CIL */ +#define XK_Georgian_char 0x10010ed /* U+10ED GEORGIAN LETTER CHAR */ +#define XK_Georgian_xan 0x10010ee /* U+10EE GEORGIAN LETTER XAN */ +#define XK_Georgian_jhan 0x10010ef /* U+10EF GEORGIAN LETTER JHAN */ +#define XK_Georgian_hae 0x10010f0 /* U+10F0 GEORGIAN LETTER HAE */ +#define XK_Georgian_he 0x10010f1 /* U+10F1 GEORGIAN LETTER HE */ +#define XK_Georgian_hie 0x10010f2 /* U+10F2 GEORGIAN LETTER HIE */ +#define XK_Georgian_we 0x10010f3 /* U+10F3 GEORGIAN LETTER WE */ +#define XK_Georgian_har 0x10010f4 /* U+10F4 GEORGIAN LETTER HAR */ +#define XK_Georgian_hoe 0x10010f5 /* U+10F5 GEORGIAN LETTER HOE */ +#define XK_Georgian_fi 0x10010f6 /* U+10F6 GEORGIAN LETTER FI */ +#endif /* XK_GEORGIAN */ + +/* + * Azeri (and other Turkic or Caucasian languages) + */ + +#ifdef XK_CAUCASUS +/* latin */ +#define XK_Xabovedot 0x1001e8a /* U+1E8A LATIN CAPITAL LETTER X WITH DOT ABOVE */ +#define XK_Ibreve 0x100012c /* U+012C LATIN CAPITAL LETTER I WITH BREVE */ +#define XK_Zstroke 0x10001b5 /* U+01B5 LATIN CAPITAL LETTER Z WITH STROKE */ +#define XK_Gcaron 0x10001e6 /* U+01E6 LATIN CAPITAL LETTER G WITH CARON */ +#define XK_Ocaron 0x10001d1 /* U+01D2 LATIN CAPITAL LETTER O WITH CARON */ +#define XK_Obarred 0x100019f /* U+019F LATIN CAPITAL LETTER O WITH MIDDLE TILDE */ +#define XK_xabovedot 0x1001e8b /* U+1E8B LATIN SMALL LETTER X WITH DOT ABOVE */ +#define XK_ibreve 0x100012d /* U+012D LATIN SMALL LETTER I WITH BREVE */ +#define XK_zstroke 0x10001b6 /* U+01B6 LATIN SMALL LETTER Z WITH STROKE */ +#define XK_gcaron 0x10001e7 /* U+01E7 LATIN SMALL LETTER G WITH CARON */ +#define XK_ocaron 0x10001d2 /* U+01D2 LATIN SMALL LETTER O WITH CARON */ +#define XK_obarred 0x1000275 /* U+0275 LATIN SMALL LETTER BARRED O */ +#define XK_SCHWA 0x100018f /* U+018F LATIN CAPITAL LETTER SCHWA */ +#define XK_schwa 0x1000259 /* U+0259 LATIN SMALL LETTER SCHWA */ +/* those are not really Caucasus */ +/* For Inupiak */ +#define XK_Lbelowdot 0x1001e36 /* U+1E36 LATIN CAPITAL LETTER L WITH DOT BELOW */ +#define XK_lbelowdot 0x1001e37 /* U+1E37 LATIN SMALL LETTER L WITH DOT BELOW */ +#endif /* XK_CAUCASUS */ + +/* + * Vietnamese + */ + +#ifdef XK_VIETNAMESE +#define XK_Abelowdot 0x1001ea0 /* U+1EA0 LATIN CAPITAL LETTER A WITH DOT BELOW */ +#define XK_abelowdot 0x1001ea1 /* U+1EA1 LATIN SMALL LETTER A WITH DOT BELOW */ +#define XK_Ahook 0x1001ea2 /* U+1EA2 LATIN CAPITAL LETTER A WITH HOOK ABOVE */ +#define XK_ahook 0x1001ea3 /* U+1EA3 LATIN SMALL LETTER A WITH HOOK ABOVE */ +#define XK_Acircumflexacute 0x1001ea4 /* U+1EA4 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE */ +#define XK_acircumflexacute 0x1001ea5 /* U+1EA5 LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE */ +#define XK_Acircumflexgrave 0x1001ea6 /* U+1EA6 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE */ +#define XK_acircumflexgrave 0x1001ea7 /* U+1EA7 LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE */ +#define XK_Acircumflexhook 0x1001ea8 /* U+1EA8 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */ +#define XK_acircumflexhook 0x1001ea9 /* U+1EA9 LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */ +#define XK_Acircumflextilde 0x1001eaa /* U+1EAA LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE */ +#define XK_acircumflextilde 0x1001eab /* U+1EAB LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE */ +#define XK_Acircumflexbelowdot 0x1001eac /* U+1EAC LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW */ +#define XK_acircumflexbelowdot 0x1001ead /* U+1EAD LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW */ +#define XK_Abreveacute 0x1001eae /* U+1EAE LATIN CAPITAL LETTER A WITH BREVE AND ACUTE */ +#define XK_abreveacute 0x1001eaf /* U+1EAF LATIN SMALL LETTER A WITH BREVE AND ACUTE */ +#define XK_Abrevegrave 0x1001eb0 /* U+1EB0 LATIN CAPITAL LETTER A WITH BREVE AND GRAVE */ +#define XK_abrevegrave 0x1001eb1 /* U+1EB1 LATIN SMALL LETTER A WITH BREVE AND GRAVE */ +#define XK_Abrevehook 0x1001eb2 /* U+1EB2 LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE */ +#define XK_abrevehook 0x1001eb3 /* U+1EB3 LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE */ +#define XK_Abrevetilde 0x1001eb4 /* U+1EB4 LATIN CAPITAL LETTER A WITH BREVE AND TILDE */ +#define XK_abrevetilde 0x1001eb5 /* U+1EB5 LATIN SMALL LETTER A WITH BREVE AND TILDE */ +#define XK_Abrevebelowdot 0x1001eb6 /* U+1EB6 LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW */ +#define XK_abrevebelowdot 0x1001eb7 /* U+1EB7 LATIN SMALL LETTER A WITH BREVE AND DOT BELOW */ +#define XK_Ebelowdot 0x1001eb8 /* U+1EB8 LATIN CAPITAL LETTER E WITH DOT BELOW */ +#define XK_ebelowdot 0x1001eb9 /* U+1EB9 LATIN SMALL LETTER E WITH DOT BELOW */ +#define XK_Ehook 0x1001eba /* U+1EBA LATIN CAPITAL LETTER E WITH HOOK ABOVE */ +#define XK_ehook 0x1001ebb /* U+1EBB LATIN SMALL LETTER E WITH HOOK ABOVE */ +#define XK_Etilde 0x1001ebc /* U+1EBC LATIN CAPITAL LETTER E WITH TILDE */ +#define XK_etilde 0x1001ebd /* U+1EBD LATIN SMALL LETTER E WITH TILDE */ +#define XK_Ecircumflexacute 0x1001ebe /* U+1EBE LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE */ +#define XK_ecircumflexacute 0x1001ebf /* U+1EBF LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE */ +#define XK_Ecircumflexgrave 0x1001ec0 /* U+1EC0 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE */ +#define XK_ecircumflexgrave 0x1001ec1 /* U+1EC1 LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE */ +#define XK_Ecircumflexhook 0x1001ec2 /* U+1EC2 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */ +#define XK_ecircumflexhook 0x1001ec3 /* U+1EC3 LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */ +#define XK_Ecircumflextilde 0x1001ec4 /* U+1EC4 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE */ +#define XK_ecircumflextilde 0x1001ec5 /* U+1EC5 LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE */ +#define XK_Ecircumflexbelowdot 0x1001ec6 /* U+1EC6 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW */ +#define XK_ecircumflexbelowdot 0x1001ec7 /* U+1EC7 LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW */ +#define XK_Ihook 0x1001ec8 /* U+1EC8 LATIN CAPITAL LETTER I WITH HOOK ABOVE */ +#define XK_ihook 0x1001ec9 /* U+1EC9 LATIN SMALL LETTER I WITH HOOK ABOVE */ +#define XK_Ibelowdot 0x1001eca /* U+1ECA LATIN CAPITAL LETTER I WITH DOT BELOW */ +#define XK_ibelowdot 0x1001ecb /* U+1ECB LATIN SMALL LETTER I WITH DOT BELOW */ +#define XK_Obelowdot 0x1001ecc /* U+1ECC LATIN CAPITAL LETTER O WITH DOT BELOW */ +#define XK_obelowdot 0x1001ecd /* U+1ECD LATIN SMALL LETTER O WITH DOT BELOW */ +#define XK_Ohook 0x1001ece /* U+1ECE LATIN CAPITAL LETTER O WITH HOOK ABOVE */ +#define XK_ohook 0x1001ecf /* U+1ECF LATIN SMALL LETTER O WITH HOOK ABOVE */ +#define XK_Ocircumflexacute 0x1001ed0 /* U+1ED0 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE */ +#define XK_ocircumflexacute 0x1001ed1 /* U+1ED1 LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE */ +#define XK_Ocircumflexgrave 0x1001ed2 /* U+1ED2 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE */ +#define XK_ocircumflexgrave 0x1001ed3 /* U+1ED3 LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE */ +#define XK_Ocircumflexhook 0x1001ed4 /* U+1ED4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */ +#define XK_ocircumflexhook 0x1001ed5 /* U+1ED5 LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */ +#define XK_Ocircumflextilde 0x1001ed6 /* U+1ED6 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE */ +#define XK_ocircumflextilde 0x1001ed7 /* U+1ED7 LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE */ +#define XK_Ocircumflexbelowdot 0x1001ed8 /* U+1ED8 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW */ +#define XK_ocircumflexbelowdot 0x1001ed9 /* U+1ED9 LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW */ +#define XK_Ohornacute 0x1001eda /* U+1EDA LATIN CAPITAL LETTER O WITH HORN AND ACUTE */ +#define XK_ohornacute 0x1001edb /* U+1EDB LATIN SMALL LETTER O WITH HORN AND ACUTE */ +#define XK_Ohorngrave 0x1001edc /* U+1EDC LATIN CAPITAL LETTER O WITH HORN AND GRAVE */ +#define XK_ohorngrave 0x1001edd /* U+1EDD LATIN SMALL LETTER O WITH HORN AND GRAVE */ +#define XK_Ohornhook 0x1001ede /* U+1EDE LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE */ +#define XK_ohornhook 0x1001edf /* U+1EDF LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE */ +#define XK_Ohorntilde 0x1001ee0 /* U+1EE0 LATIN CAPITAL LETTER O WITH HORN AND TILDE */ +#define XK_ohorntilde 0x1001ee1 /* U+1EE1 LATIN SMALL LETTER O WITH HORN AND TILDE */ +#define XK_Ohornbelowdot 0x1001ee2 /* U+1EE2 LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW */ +#define XK_ohornbelowdot 0x1001ee3 /* U+1EE3 LATIN SMALL LETTER O WITH HORN AND DOT BELOW */ +#define XK_Ubelowdot 0x1001ee4 /* U+1EE4 LATIN CAPITAL LETTER U WITH DOT BELOW */ +#define XK_ubelowdot 0x1001ee5 /* U+1EE5 LATIN SMALL LETTER U WITH DOT BELOW */ +#define XK_Uhook 0x1001ee6 /* U+1EE6 LATIN CAPITAL LETTER U WITH HOOK ABOVE */ +#define XK_uhook 0x1001ee7 /* U+1EE7 LATIN SMALL LETTER U WITH HOOK ABOVE */ +#define XK_Uhornacute 0x1001ee8 /* U+1EE8 LATIN CAPITAL LETTER U WITH HORN AND ACUTE */ +#define XK_uhornacute 0x1001ee9 /* U+1EE9 LATIN SMALL LETTER U WITH HORN AND ACUTE */ +#define XK_Uhorngrave 0x1001eea /* U+1EEA LATIN CAPITAL LETTER U WITH HORN AND GRAVE */ +#define XK_uhorngrave 0x1001eeb /* U+1EEB LATIN SMALL LETTER U WITH HORN AND GRAVE */ +#define XK_Uhornhook 0x1001eec /* U+1EEC LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE */ +#define XK_uhornhook 0x1001eed /* U+1EED LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE */ +#define XK_Uhorntilde 0x1001eee /* U+1EEE LATIN CAPITAL LETTER U WITH HORN AND TILDE */ +#define XK_uhorntilde 0x1001eef /* U+1EEF LATIN SMALL LETTER U WITH HORN AND TILDE */ +#define XK_Uhornbelowdot 0x1001ef0 /* U+1EF0 LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW */ +#define XK_uhornbelowdot 0x1001ef1 /* U+1EF1 LATIN SMALL LETTER U WITH HORN AND DOT BELOW */ +#define XK_Ybelowdot 0x1001ef4 /* U+1EF4 LATIN CAPITAL LETTER Y WITH DOT BELOW */ +#define XK_ybelowdot 0x1001ef5 /* U+1EF5 LATIN SMALL LETTER Y WITH DOT BELOW */ +#define XK_Yhook 0x1001ef6 /* U+1EF6 LATIN CAPITAL LETTER Y WITH HOOK ABOVE */ +#define XK_yhook 0x1001ef7 /* U+1EF7 LATIN SMALL LETTER Y WITH HOOK ABOVE */ +#define XK_Ytilde 0x1001ef8 /* U+1EF8 LATIN CAPITAL LETTER Y WITH TILDE */ +#define XK_ytilde 0x1001ef9 /* U+1EF9 LATIN SMALL LETTER Y WITH TILDE */ +#define XK_Ohorn 0x10001a0 /* U+01A0 LATIN CAPITAL LETTER O WITH HORN */ +#define XK_ohorn 0x10001a1 /* U+01A1 LATIN SMALL LETTER O WITH HORN */ +#define XK_Uhorn 0x10001af /* U+01AF LATIN CAPITAL LETTER U WITH HORN */ +#define XK_uhorn 0x10001b0 /* U+01B0 LATIN SMALL LETTER U WITH HORN */ + +#endif /* XK_VIETNAMESE */ + +#ifdef XK_CURRENCY +#define XK_EcuSign 0x10020a0 /* U+20A0 EURO-CURRENCY SIGN */ +#define XK_ColonSign 0x10020a1 /* U+20A1 COLON SIGN */ +#define XK_CruzeiroSign 0x10020a2 /* U+20A2 CRUZEIRO SIGN */ +#define XK_FFrancSign 0x10020a3 /* U+20A3 FRENCH FRANC SIGN */ +#define XK_LiraSign 0x10020a4 /* U+20A4 LIRA SIGN */ +#define XK_MillSign 0x10020a5 /* U+20A5 MILL SIGN */ +#define XK_NairaSign 0x10020a6 /* U+20A6 NAIRA SIGN */ +#define XK_PesetaSign 0x10020a7 /* U+20A7 PESETA SIGN */ +#define XK_RupeeSign 0x10020a8 /* U+20A8 RUPEE SIGN */ +#define XK_WonSign 0x10020a9 /* U+20A9 WON SIGN */ +#define XK_NewSheqelSign 0x10020aa /* U+20AA NEW SHEQEL SIGN */ +#define XK_DongSign 0x10020ab /* U+20AB DONG SIGN */ +#define XK_EuroSign 0x20ac /* U+20AC EURO SIGN */ +#endif /* XK_CURRENCY */ + +#ifdef XK_MATHEMATICAL +/* one, two and three are defined above. */ +#define XK_zerosuperior 0x1002070 /* U+2070 SUPERSCRIPT ZERO */ +#define XK_foursuperior 0x1002074 /* U+2074 SUPERSCRIPT FOUR */ +#define XK_fivesuperior 0x1002075 /* U+2075 SUPERSCRIPT FIVE */ +#define XK_sixsuperior 0x1002076 /* U+2076 SUPERSCRIPT SIX */ +#define XK_sevensuperior 0x1002077 /* U+2077 SUPERSCRIPT SEVEN */ +#define XK_eightsuperior 0x1002078 /* U+2078 SUPERSCRIPT EIGHT */ +#define XK_ninesuperior 0x1002079 /* U+2079 SUPERSCRIPT NINE */ +#define XK_zerosubscript 0x1002080 /* U+2080 SUBSCRIPT ZERO */ +#define XK_onesubscript 0x1002081 /* U+2081 SUBSCRIPT ONE */ +#define XK_twosubscript 0x1002082 /* U+2082 SUBSCRIPT TWO */ +#define XK_threesubscript 0x1002083 /* U+2083 SUBSCRIPT THREE */ +#define XK_foursubscript 0x1002084 /* U+2084 SUBSCRIPT FOUR */ +#define XK_fivesubscript 0x1002085 /* U+2085 SUBSCRIPT FIVE */ +#define XK_sixsubscript 0x1002086 /* U+2086 SUBSCRIPT SIX */ +#define XK_sevensubscript 0x1002087 /* U+2087 SUBSCRIPT SEVEN */ +#define XK_eightsubscript 0x1002088 /* U+2088 SUBSCRIPT EIGHT */ +#define XK_ninesubscript 0x1002089 /* U+2089 SUBSCRIPT NINE */ +#define XK_partdifferential 0x1002202 /* U+2202 PARTIAL DIFFERENTIAL */ +#define XK_emptyset 0x1002205 /* U+2205 NULL SET */ +#define XK_elementof 0x1002208 /* U+2208 ELEMENT OF */ +#define XK_notelementof 0x1002209 /* U+2209 NOT AN ELEMENT OF */ +#define XK_containsas 0x100220B /* U+220B CONTAINS AS MEMBER */ +#define XK_squareroot 0x100221A /* U+221A SQUARE ROOT */ +#define XK_cuberoot 0x100221B /* U+221B CUBE ROOT */ +#define XK_fourthroot 0x100221C /* U+221C FOURTH ROOT */ +#define XK_dintegral 0x100222C /* U+222C DOUBLE INTEGRAL */ +#define XK_tintegral 0x100222D /* U+222D TRIPLE INTEGRAL */ +#define XK_because 0x1002235 /* U+2235 BECAUSE */ +#define XK_approxeq 0x1002248 /* U+2245 ALMOST EQUAL TO */ +#define XK_notapproxeq 0x1002247 /* U+2247 NOT ALMOST EQUAL TO */ +#define XK_notidentical 0x1002262 /* U+2262 NOT IDENTICAL TO */ +#define XK_stricteq 0x1002263 /* U+2263 STRICTLY EQUIVALENT TO */ +#endif /* XK_MATHEMATICAL */ + +#ifdef XK_BRAILLE +#define XK_braille_dot_1 0xfff1 +#define XK_braille_dot_2 0xfff2 +#define XK_braille_dot_3 0xfff3 +#define XK_braille_dot_4 0xfff4 +#define XK_braille_dot_5 0xfff5 +#define XK_braille_dot_6 0xfff6 +#define XK_braille_dot_7 0xfff7 +#define XK_braille_dot_8 0xfff8 +#define XK_braille_dot_9 0xfff9 +#define XK_braille_dot_10 0xfffa +#define XK_braille_blank 0x1002800 /* U+2800 BRAILLE PATTERN BLANK */ +#define XK_braille_dots_1 0x1002801 /* U+2801 BRAILLE PATTERN DOTS-1 */ +#define XK_braille_dots_2 0x1002802 /* U+2802 BRAILLE PATTERN DOTS-2 */ +#define XK_braille_dots_12 0x1002803 /* U+2803 BRAILLE PATTERN DOTS-12 */ +#define XK_braille_dots_3 0x1002804 /* U+2804 BRAILLE PATTERN DOTS-3 */ +#define XK_braille_dots_13 0x1002805 /* U+2805 BRAILLE PATTERN DOTS-13 */ +#define XK_braille_dots_23 0x1002806 /* U+2806 BRAILLE PATTERN DOTS-23 */ +#define XK_braille_dots_123 0x1002807 /* U+2807 BRAILLE PATTERN DOTS-123 */ +#define XK_braille_dots_4 0x1002808 /* U+2808 BRAILLE PATTERN DOTS-4 */ +#define XK_braille_dots_14 0x1002809 /* U+2809 BRAILLE PATTERN DOTS-14 */ +#define XK_braille_dots_24 0x100280a /* U+280a BRAILLE PATTERN DOTS-24 */ +#define XK_braille_dots_124 0x100280b /* U+280b BRAILLE PATTERN DOTS-124 */ +#define XK_braille_dots_34 0x100280c /* U+280c BRAILLE PATTERN DOTS-34 */ +#define XK_braille_dots_134 0x100280d /* U+280d BRAILLE PATTERN DOTS-134 */ +#define XK_braille_dots_234 0x100280e /* U+280e BRAILLE PATTERN DOTS-234 */ +#define XK_braille_dots_1234 0x100280f /* U+280f BRAILLE PATTERN DOTS-1234 */ +#define XK_braille_dots_5 0x1002810 /* U+2810 BRAILLE PATTERN DOTS-5 */ +#define XK_braille_dots_15 0x1002811 /* U+2811 BRAILLE PATTERN DOTS-15 */ +#define XK_braille_dots_25 0x1002812 /* U+2812 BRAILLE PATTERN DOTS-25 */ +#define XK_braille_dots_125 0x1002813 /* U+2813 BRAILLE PATTERN DOTS-125 */ +#define XK_braille_dots_35 0x1002814 /* U+2814 BRAILLE PATTERN DOTS-35 */ +#define XK_braille_dots_135 0x1002815 /* U+2815 BRAILLE PATTERN DOTS-135 */ +#define XK_braille_dots_235 0x1002816 /* U+2816 BRAILLE PATTERN DOTS-235 */ +#define XK_braille_dots_1235 0x1002817 /* U+2817 BRAILLE PATTERN DOTS-1235 */ +#define XK_braille_dots_45 0x1002818 /* U+2818 BRAILLE PATTERN DOTS-45 */ +#define XK_braille_dots_145 0x1002819 /* U+2819 BRAILLE PATTERN DOTS-145 */ +#define XK_braille_dots_245 0x100281a /* U+281a BRAILLE PATTERN DOTS-245 */ +#define XK_braille_dots_1245 0x100281b /* U+281b BRAILLE PATTERN DOTS-1245 */ +#define XK_braille_dots_345 0x100281c /* U+281c BRAILLE PATTERN DOTS-345 */ +#define XK_braille_dots_1345 0x100281d /* U+281d BRAILLE PATTERN DOTS-1345 */ +#define XK_braille_dots_2345 0x100281e /* U+281e BRAILLE PATTERN DOTS-2345 */ +#define XK_braille_dots_12345 0x100281f /* U+281f BRAILLE PATTERN DOTS-12345 */ +#define XK_braille_dots_6 0x1002820 /* U+2820 BRAILLE PATTERN DOTS-6 */ +#define XK_braille_dots_16 0x1002821 /* U+2821 BRAILLE PATTERN DOTS-16 */ +#define XK_braille_dots_26 0x1002822 /* U+2822 BRAILLE PATTERN DOTS-26 */ +#define XK_braille_dots_126 0x1002823 /* U+2823 BRAILLE PATTERN DOTS-126 */ +#define XK_braille_dots_36 0x1002824 /* U+2824 BRAILLE PATTERN DOTS-36 */ +#define XK_braille_dots_136 0x1002825 /* U+2825 BRAILLE PATTERN DOTS-136 */ +#define XK_braille_dots_236 0x1002826 /* U+2826 BRAILLE PATTERN DOTS-236 */ +#define XK_braille_dots_1236 0x1002827 /* U+2827 BRAILLE PATTERN DOTS-1236 */ +#define XK_braille_dots_46 0x1002828 /* U+2828 BRAILLE PATTERN DOTS-46 */ +#define XK_braille_dots_146 0x1002829 /* U+2829 BRAILLE PATTERN DOTS-146 */ +#define XK_braille_dots_246 0x100282a /* U+282a BRAILLE PATTERN DOTS-246 */ +#define XK_braille_dots_1246 0x100282b /* U+282b BRAILLE PATTERN DOTS-1246 */ +#define XK_braille_dots_346 0x100282c /* U+282c BRAILLE PATTERN DOTS-346 */ +#define XK_braille_dots_1346 0x100282d /* U+282d BRAILLE PATTERN DOTS-1346 */ +#define XK_braille_dots_2346 0x100282e /* U+282e BRAILLE PATTERN DOTS-2346 */ +#define XK_braille_dots_12346 0x100282f /* U+282f BRAILLE PATTERN DOTS-12346 */ +#define XK_braille_dots_56 0x1002830 /* U+2830 BRAILLE PATTERN DOTS-56 */ +#define XK_braille_dots_156 0x1002831 /* U+2831 BRAILLE PATTERN DOTS-156 */ +#define XK_braille_dots_256 0x1002832 /* U+2832 BRAILLE PATTERN DOTS-256 */ +#define XK_braille_dots_1256 0x1002833 /* U+2833 BRAILLE PATTERN DOTS-1256 */ +#define XK_braille_dots_356 0x1002834 /* U+2834 BRAILLE PATTERN DOTS-356 */ +#define XK_braille_dots_1356 0x1002835 /* U+2835 BRAILLE PATTERN DOTS-1356 */ +#define XK_braille_dots_2356 0x1002836 /* U+2836 BRAILLE PATTERN DOTS-2356 */ +#define XK_braille_dots_12356 0x1002837 /* U+2837 BRAILLE PATTERN DOTS-12356 */ +#define XK_braille_dots_456 0x1002838 /* U+2838 BRAILLE PATTERN DOTS-456 */ +#define XK_braille_dots_1456 0x1002839 /* U+2839 BRAILLE PATTERN DOTS-1456 */ +#define XK_braille_dots_2456 0x100283a /* U+283a BRAILLE PATTERN DOTS-2456 */ +#define XK_braille_dots_12456 0x100283b /* U+283b BRAILLE PATTERN DOTS-12456 */ +#define XK_braille_dots_3456 0x100283c /* U+283c BRAILLE PATTERN DOTS-3456 */ +#define XK_braille_dots_13456 0x100283d /* U+283d BRAILLE PATTERN DOTS-13456 */ +#define XK_braille_dots_23456 0x100283e /* U+283e BRAILLE PATTERN DOTS-23456 */ +#define XK_braille_dots_123456 0x100283f /* U+283f BRAILLE PATTERN DOTS-123456 */ +#define XK_braille_dots_7 0x1002840 /* U+2840 BRAILLE PATTERN DOTS-7 */ +#define XK_braille_dots_17 0x1002841 /* U+2841 BRAILLE PATTERN DOTS-17 */ +#define XK_braille_dots_27 0x1002842 /* U+2842 BRAILLE PATTERN DOTS-27 */ +#define XK_braille_dots_127 0x1002843 /* U+2843 BRAILLE PATTERN DOTS-127 */ +#define XK_braille_dots_37 0x1002844 /* U+2844 BRAILLE PATTERN DOTS-37 */ +#define XK_braille_dots_137 0x1002845 /* U+2845 BRAILLE PATTERN DOTS-137 */ +#define XK_braille_dots_237 0x1002846 /* U+2846 BRAILLE PATTERN DOTS-237 */ +#define XK_braille_dots_1237 0x1002847 /* U+2847 BRAILLE PATTERN DOTS-1237 */ +#define XK_braille_dots_47 0x1002848 /* U+2848 BRAILLE PATTERN DOTS-47 */ +#define XK_braille_dots_147 0x1002849 /* U+2849 BRAILLE PATTERN DOTS-147 */ +#define XK_braille_dots_247 0x100284a /* U+284a BRAILLE PATTERN DOTS-247 */ +#define XK_braille_dots_1247 0x100284b /* U+284b BRAILLE PATTERN DOTS-1247 */ +#define XK_braille_dots_347 0x100284c /* U+284c BRAILLE PATTERN DOTS-347 */ +#define XK_braille_dots_1347 0x100284d /* U+284d BRAILLE PATTERN DOTS-1347 */ +#define XK_braille_dots_2347 0x100284e /* U+284e BRAILLE PATTERN DOTS-2347 */ +#define XK_braille_dots_12347 0x100284f /* U+284f BRAILLE PATTERN DOTS-12347 */ +#define XK_braille_dots_57 0x1002850 /* U+2850 BRAILLE PATTERN DOTS-57 */ +#define XK_braille_dots_157 0x1002851 /* U+2851 BRAILLE PATTERN DOTS-157 */ +#define XK_braille_dots_257 0x1002852 /* U+2852 BRAILLE PATTERN DOTS-257 */ +#define XK_braille_dots_1257 0x1002853 /* U+2853 BRAILLE PATTERN DOTS-1257 */ +#define XK_braille_dots_357 0x1002854 /* U+2854 BRAILLE PATTERN DOTS-357 */ +#define XK_braille_dots_1357 0x1002855 /* U+2855 BRAILLE PATTERN DOTS-1357 */ +#define XK_braille_dots_2357 0x1002856 /* U+2856 BRAILLE PATTERN DOTS-2357 */ +#define XK_braille_dots_12357 0x1002857 /* U+2857 BRAILLE PATTERN DOTS-12357 */ +#define XK_braille_dots_457 0x1002858 /* U+2858 BRAILLE PATTERN DOTS-457 */ +#define XK_braille_dots_1457 0x1002859 /* U+2859 BRAILLE PATTERN DOTS-1457 */ +#define XK_braille_dots_2457 0x100285a /* U+285a BRAILLE PATTERN DOTS-2457 */ +#define XK_braille_dots_12457 0x100285b /* U+285b BRAILLE PATTERN DOTS-12457 */ +#define XK_braille_dots_3457 0x100285c /* U+285c BRAILLE PATTERN DOTS-3457 */ +#define XK_braille_dots_13457 0x100285d /* U+285d BRAILLE PATTERN DOTS-13457 */ +#define XK_braille_dots_23457 0x100285e /* U+285e BRAILLE PATTERN DOTS-23457 */ +#define XK_braille_dots_123457 0x100285f /* U+285f BRAILLE PATTERN DOTS-123457 */ +#define XK_braille_dots_67 0x1002860 /* U+2860 BRAILLE PATTERN DOTS-67 */ +#define XK_braille_dots_167 0x1002861 /* U+2861 BRAILLE PATTERN DOTS-167 */ +#define XK_braille_dots_267 0x1002862 /* U+2862 BRAILLE PATTERN DOTS-267 */ +#define XK_braille_dots_1267 0x1002863 /* U+2863 BRAILLE PATTERN DOTS-1267 */ +#define XK_braille_dots_367 0x1002864 /* U+2864 BRAILLE PATTERN DOTS-367 */ +#define XK_braille_dots_1367 0x1002865 /* U+2865 BRAILLE PATTERN DOTS-1367 */ +#define XK_braille_dots_2367 0x1002866 /* U+2866 BRAILLE PATTERN DOTS-2367 */ +#define XK_braille_dots_12367 0x1002867 /* U+2867 BRAILLE PATTERN DOTS-12367 */ +#define XK_braille_dots_467 0x1002868 /* U+2868 BRAILLE PATTERN DOTS-467 */ +#define XK_braille_dots_1467 0x1002869 /* U+2869 BRAILLE PATTERN DOTS-1467 */ +#define XK_braille_dots_2467 0x100286a /* U+286a BRAILLE PATTERN DOTS-2467 */ +#define XK_braille_dots_12467 0x100286b /* U+286b BRAILLE PATTERN DOTS-12467 */ +#define XK_braille_dots_3467 0x100286c /* U+286c BRAILLE PATTERN DOTS-3467 */ +#define XK_braille_dots_13467 0x100286d /* U+286d BRAILLE PATTERN DOTS-13467 */ +#define XK_braille_dots_23467 0x100286e /* U+286e BRAILLE PATTERN DOTS-23467 */ +#define XK_braille_dots_123467 0x100286f /* U+286f BRAILLE PATTERN DOTS-123467 */ +#define XK_braille_dots_567 0x1002870 /* U+2870 BRAILLE PATTERN DOTS-567 */ +#define XK_braille_dots_1567 0x1002871 /* U+2871 BRAILLE PATTERN DOTS-1567 */ +#define XK_braille_dots_2567 0x1002872 /* U+2872 BRAILLE PATTERN DOTS-2567 */ +#define XK_braille_dots_12567 0x1002873 /* U+2873 BRAILLE PATTERN DOTS-12567 */ +#define XK_braille_dots_3567 0x1002874 /* U+2874 BRAILLE PATTERN DOTS-3567 */ +#define XK_braille_dots_13567 0x1002875 /* U+2875 BRAILLE PATTERN DOTS-13567 */ +#define XK_braille_dots_23567 0x1002876 /* U+2876 BRAILLE PATTERN DOTS-23567 */ +#define XK_braille_dots_123567 0x1002877 /* U+2877 BRAILLE PATTERN DOTS-123567 */ +#define XK_braille_dots_4567 0x1002878 /* U+2878 BRAILLE PATTERN DOTS-4567 */ +#define XK_braille_dots_14567 0x1002879 /* U+2879 BRAILLE PATTERN DOTS-14567 */ +#define XK_braille_dots_24567 0x100287a /* U+287a BRAILLE PATTERN DOTS-24567 */ +#define XK_braille_dots_124567 0x100287b /* U+287b BRAILLE PATTERN DOTS-124567 */ +#define XK_braille_dots_34567 0x100287c /* U+287c BRAILLE PATTERN DOTS-34567 */ +#define XK_braille_dots_134567 0x100287d /* U+287d BRAILLE PATTERN DOTS-134567 */ +#define XK_braille_dots_234567 0x100287e /* U+287e BRAILLE PATTERN DOTS-234567 */ +#define XK_braille_dots_1234567 0x100287f /* U+287f BRAILLE PATTERN DOTS-1234567 */ +#define XK_braille_dots_8 0x1002880 /* U+2880 BRAILLE PATTERN DOTS-8 */ +#define XK_braille_dots_18 0x1002881 /* U+2881 BRAILLE PATTERN DOTS-18 */ +#define XK_braille_dots_28 0x1002882 /* U+2882 BRAILLE PATTERN DOTS-28 */ +#define XK_braille_dots_128 0x1002883 /* U+2883 BRAILLE PATTERN DOTS-128 */ +#define XK_braille_dots_38 0x1002884 /* U+2884 BRAILLE PATTERN DOTS-38 */ +#define XK_braille_dots_138 0x1002885 /* U+2885 BRAILLE PATTERN DOTS-138 */ +#define XK_braille_dots_238 0x1002886 /* U+2886 BRAILLE PATTERN DOTS-238 */ +#define XK_braille_dots_1238 0x1002887 /* U+2887 BRAILLE PATTERN DOTS-1238 */ +#define XK_braille_dots_48 0x1002888 /* U+2888 BRAILLE PATTERN DOTS-48 */ +#define XK_braille_dots_148 0x1002889 /* U+2889 BRAILLE PATTERN DOTS-148 */ +#define XK_braille_dots_248 0x100288a /* U+288a BRAILLE PATTERN DOTS-248 */ +#define XK_braille_dots_1248 0x100288b /* U+288b BRAILLE PATTERN DOTS-1248 */ +#define XK_braille_dots_348 0x100288c /* U+288c BRAILLE PATTERN DOTS-348 */ +#define XK_braille_dots_1348 0x100288d /* U+288d BRAILLE PATTERN DOTS-1348 */ +#define XK_braille_dots_2348 0x100288e /* U+288e BRAILLE PATTERN DOTS-2348 */ +#define XK_braille_dots_12348 0x100288f /* U+288f BRAILLE PATTERN DOTS-12348 */ +#define XK_braille_dots_58 0x1002890 /* U+2890 BRAILLE PATTERN DOTS-58 */ +#define XK_braille_dots_158 0x1002891 /* U+2891 BRAILLE PATTERN DOTS-158 */ +#define XK_braille_dots_258 0x1002892 /* U+2892 BRAILLE PATTERN DOTS-258 */ +#define XK_braille_dots_1258 0x1002893 /* U+2893 BRAILLE PATTERN DOTS-1258 */ +#define XK_braille_dots_358 0x1002894 /* U+2894 BRAILLE PATTERN DOTS-358 */ +#define XK_braille_dots_1358 0x1002895 /* U+2895 BRAILLE PATTERN DOTS-1358 */ +#define XK_braille_dots_2358 0x1002896 /* U+2896 BRAILLE PATTERN DOTS-2358 */ +#define XK_braille_dots_12358 0x1002897 /* U+2897 BRAILLE PATTERN DOTS-12358 */ +#define XK_braille_dots_458 0x1002898 /* U+2898 BRAILLE PATTERN DOTS-458 */ +#define XK_braille_dots_1458 0x1002899 /* U+2899 BRAILLE PATTERN DOTS-1458 */ +#define XK_braille_dots_2458 0x100289a /* U+289a BRAILLE PATTERN DOTS-2458 */ +#define XK_braille_dots_12458 0x100289b /* U+289b BRAILLE PATTERN DOTS-12458 */ +#define XK_braille_dots_3458 0x100289c /* U+289c BRAILLE PATTERN DOTS-3458 */ +#define XK_braille_dots_13458 0x100289d /* U+289d BRAILLE PATTERN DOTS-13458 */ +#define XK_braille_dots_23458 0x100289e /* U+289e BRAILLE PATTERN DOTS-23458 */ +#define XK_braille_dots_123458 0x100289f /* U+289f BRAILLE PATTERN DOTS-123458 */ +#define XK_braille_dots_68 0x10028a0 /* U+28a0 BRAILLE PATTERN DOTS-68 */ +#define XK_braille_dots_168 0x10028a1 /* U+28a1 BRAILLE PATTERN DOTS-168 */ +#define XK_braille_dots_268 0x10028a2 /* U+28a2 BRAILLE PATTERN DOTS-268 */ +#define XK_braille_dots_1268 0x10028a3 /* U+28a3 BRAILLE PATTERN DOTS-1268 */ +#define XK_braille_dots_368 0x10028a4 /* U+28a4 BRAILLE PATTERN DOTS-368 */ +#define XK_braille_dots_1368 0x10028a5 /* U+28a5 BRAILLE PATTERN DOTS-1368 */ +#define XK_braille_dots_2368 0x10028a6 /* U+28a6 BRAILLE PATTERN DOTS-2368 */ +#define XK_braille_dots_12368 0x10028a7 /* U+28a7 BRAILLE PATTERN DOTS-12368 */ +#define XK_braille_dots_468 0x10028a8 /* U+28a8 BRAILLE PATTERN DOTS-468 */ +#define XK_braille_dots_1468 0x10028a9 /* U+28a9 BRAILLE PATTERN DOTS-1468 */ +#define XK_braille_dots_2468 0x10028aa /* U+28aa BRAILLE PATTERN DOTS-2468 */ +#define XK_braille_dots_12468 0x10028ab /* U+28ab BRAILLE PATTERN DOTS-12468 */ +#define XK_braille_dots_3468 0x10028ac /* U+28ac BRAILLE PATTERN DOTS-3468 */ +#define XK_braille_dots_13468 0x10028ad /* U+28ad BRAILLE PATTERN DOTS-13468 */ +#define XK_braille_dots_23468 0x10028ae /* U+28ae BRAILLE PATTERN DOTS-23468 */ +#define XK_braille_dots_123468 0x10028af /* U+28af BRAILLE PATTERN DOTS-123468 */ +#define XK_braille_dots_568 0x10028b0 /* U+28b0 BRAILLE PATTERN DOTS-568 */ +#define XK_braille_dots_1568 0x10028b1 /* U+28b1 BRAILLE PATTERN DOTS-1568 */ +#define XK_braille_dots_2568 0x10028b2 /* U+28b2 BRAILLE PATTERN DOTS-2568 */ +#define XK_braille_dots_12568 0x10028b3 /* U+28b3 BRAILLE PATTERN DOTS-12568 */ +#define XK_braille_dots_3568 0x10028b4 /* U+28b4 BRAILLE PATTERN DOTS-3568 */ +#define XK_braille_dots_13568 0x10028b5 /* U+28b5 BRAILLE PATTERN DOTS-13568 */ +#define XK_braille_dots_23568 0x10028b6 /* U+28b6 BRAILLE PATTERN DOTS-23568 */ +#define XK_braille_dots_123568 0x10028b7 /* U+28b7 BRAILLE PATTERN DOTS-123568 */ +#define XK_braille_dots_4568 0x10028b8 /* U+28b8 BRAILLE PATTERN DOTS-4568 */ +#define XK_braille_dots_14568 0x10028b9 /* U+28b9 BRAILLE PATTERN DOTS-14568 */ +#define XK_braille_dots_24568 0x10028ba /* U+28ba BRAILLE PATTERN DOTS-24568 */ +#define XK_braille_dots_124568 0x10028bb /* U+28bb BRAILLE PATTERN DOTS-124568 */ +#define XK_braille_dots_34568 0x10028bc /* U+28bc BRAILLE PATTERN DOTS-34568 */ +#define XK_braille_dots_134568 0x10028bd /* U+28bd BRAILLE PATTERN DOTS-134568 */ +#define XK_braille_dots_234568 0x10028be /* U+28be BRAILLE PATTERN DOTS-234568 */ +#define XK_braille_dots_1234568 0x10028bf /* U+28bf BRAILLE PATTERN DOTS-1234568 */ +#define XK_braille_dots_78 0x10028c0 /* U+28c0 BRAILLE PATTERN DOTS-78 */ +#define XK_braille_dots_178 0x10028c1 /* U+28c1 BRAILLE PATTERN DOTS-178 */ +#define XK_braille_dots_278 0x10028c2 /* U+28c2 BRAILLE PATTERN DOTS-278 */ +#define XK_braille_dots_1278 0x10028c3 /* U+28c3 BRAILLE PATTERN DOTS-1278 */ +#define XK_braille_dots_378 0x10028c4 /* U+28c4 BRAILLE PATTERN DOTS-378 */ +#define XK_braille_dots_1378 0x10028c5 /* U+28c5 BRAILLE PATTERN DOTS-1378 */ +#define XK_braille_dots_2378 0x10028c6 /* U+28c6 BRAILLE PATTERN DOTS-2378 */ +#define XK_braille_dots_12378 0x10028c7 /* U+28c7 BRAILLE PATTERN DOTS-12378 */ +#define XK_braille_dots_478 0x10028c8 /* U+28c8 BRAILLE PATTERN DOTS-478 */ +#define XK_braille_dots_1478 0x10028c9 /* U+28c9 BRAILLE PATTERN DOTS-1478 */ +#define XK_braille_dots_2478 0x10028ca /* U+28ca BRAILLE PATTERN DOTS-2478 */ +#define XK_braille_dots_12478 0x10028cb /* U+28cb BRAILLE PATTERN DOTS-12478 */ +#define XK_braille_dots_3478 0x10028cc /* U+28cc BRAILLE PATTERN DOTS-3478 */ +#define XK_braille_dots_13478 0x10028cd /* U+28cd BRAILLE PATTERN DOTS-13478 */ +#define XK_braille_dots_23478 0x10028ce /* U+28ce BRAILLE PATTERN DOTS-23478 */ +#define XK_braille_dots_123478 0x10028cf /* U+28cf BRAILLE PATTERN DOTS-123478 */ +#define XK_braille_dots_578 0x10028d0 /* U+28d0 BRAILLE PATTERN DOTS-578 */ +#define XK_braille_dots_1578 0x10028d1 /* U+28d1 BRAILLE PATTERN DOTS-1578 */ +#define XK_braille_dots_2578 0x10028d2 /* U+28d2 BRAILLE PATTERN DOTS-2578 */ +#define XK_braille_dots_12578 0x10028d3 /* U+28d3 BRAILLE PATTERN DOTS-12578 */ +#define XK_braille_dots_3578 0x10028d4 /* U+28d4 BRAILLE PATTERN DOTS-3578 */ +#define XK_braille_dots_13578 0x10028d5 /* U+28d5 BRAILLE PATTERN DOTS-13578 */ +#define XK_braille_dots_23578 0x10028d6 /* U+28d6 BRAILLE PATTERN DOTS-23578 */ +#define XK_braille_dots_123578 0x10028d7 /* U+28d7 BRAILLE PATTERN DOTS-123578 */ +#define XK_braille_dots_4578 0x10028d8 /* U+28d8 BRAILLE PATTERN DOTS-4578 */ +#define XK_braille_dots_14578 0x10028d9 /* U+28d9 BRAILLE PATTERN DOTS-14578 */ +#define XK_braille_dots_24578 0x10028da /* U+28da BRAILLE PATTERN DOTS-24578 */ +#define XK_braille_dots_124578 0x10028db /* U+28db BRAILLE PATTERN DOTS-124578 */ +#define XK_braille_dots_34578 0x10028dc /* U+28dc BRAILLE PATTERN DOTS-34578 */ +#define XK_braille_dots_134578 0x10028dd /* U+28dd BRAILLE PATTERN DOTS-134578 */ +#define XK_braille_dots_234578 0x10028de /* U+28de BRAILLE PATTERN DOTS-234578 */ +#define XK_braille_dots_1234578 0x10028df /* U+28df BRAILLE PATTERN DOTS-1234578 */ +#define XK_braille_dots_678 0x10028e0 /* U+28e0 BRAILLE PATTERN DOTS-678 */ +#define XK_braille_dots_1678 0x10028e1 /* U+28e1 BRAILLE PATTERN DOTS-1678 */ +#define XK_braille_dots_2678 0x10028e2 /* U+28e2 BRAILLE PATTERN DOTS-2678 */ +#define XK_braille_dots_12678 0x10028e3 /* U+28e3 BRAILLE PATTERN DOTS-12678 */ +#define XK_braille_dots_3678 0x10028e4 /* U+28e4 BRAILLE PATTERN DOTS-3678 */ +#define XK_braille_dots_13678 0x10028e5 /* U+28e5 BRAILLE PATTERN DOTS-13678 */ +#define XK_braille_dots_23678 0x10028e6 /* U+28e6 BRAILLE PATTERN DOTS-23678 */ +#define XK_braille_dots_123678 0x10028e7 /* U+28e7 BRAILLE PATTERN DOTS-123678 */ +#define XK_braille_dots_4678 0x10028e8 /* U+28e8 BRAILLE PATTERN DOTS-4678 */ +#define XK_braille_dots_14678 0x10028e9 /* U+28e9 BRAILLE PATTERN DOTS-14678 */ +#define XK_braille_dots_24678 0x10028ea /* U+28ea BRAILLE PATTERN DOTS-24678 */ +#define XK_braille_dots_124678 0x10028eb /* U+28eb BRAILLE PATTERN DOTS-124678 */ +#define XK_braille_dots_34678 0x10028ec /* U+28ec BRAILLE PATTERN DOTS-34678 */ +#define XK_braille_dots_134678 0x10028ed /* U+28ed BRAILLE PATTERN DOTS-134678 */ +#define XK_braille_dots_234678 0x10028ee /* U+28ee BRAILLE PATTERN DOTS-234678 */ +#define XK_braille_dots_1234678 0x10028ef /* U+28ef BRAILLE PATTERN DOTS-1234678 */ +#define XK_braille_dots_5678 0x10028f0 /* U+28f0 BRAILLE PATTERN DOTS-5678 */ +#define XK_braille_dots_15678 0x10028f1 /* U+28f1 BRAILLE PATTERN DOTS-15678 */ +#define XK_braille_dots_25678 0x10028f2 /* U+28f2 BRAILLE PATTERN DOTS-25678 */ +#define XK_braille_dots_125678 0x10028f3 /* U+28f3 BRAILLE PATTERN DOTS-125678 */ +#define XK_braille_dots_35678 0x10028f4 /* U+28f4 BRAILLE PATTERN DOTS-35678 */ +#define XK_braille_dots_135678 0x10028f5 /* U+28f5 BRAILLE PATTERN DOTS-135678 */ +#define XK_braille_dots_235678 0x10028f6 /* U+28f6 BRAILLE PATTERN DOTS-235678 */ +#define XK_braille_dots_1235678 0x10028f7 /* U+28f7 BRAILLE PATTERN DOTS-1235678 */ +#define XK_braille_dots_45678 0x10028f8 /* U+28f8 BRAILLE PATTERN DOTS-45678 */ +#define XK_braille_dots_145678 0x10028f9 /* U+28f9 BRAILLE PATTERN DOTS-145678 */ +#define XK_braille_dots_245678 0x10028fa /* U+28fa BRAILLE PATTERN DOTS-245678 */ +#define XK_braille_dots_1245678 0x10028fb /* U+28fb BRAILLE PATTERN DOTS-1245678 */ +#define XK_braille_dots_345678 0x10028fc /* U+28fc BRAILLE PATTERN DOTS-345678 */ +#define XK_braille_dots_1345678 0x10028fd /* U+28fd BRAILLE PATTERN DOTS-1345678 */ +#define XK_braille_dots_2345678 0x10028fe /* U+28fe BRAILLE PATTERN DOTS-2345678 */ +#define XK_braille_dots_12345678 0x10028ff /* U+28ff BRAILLE PATTERN DOTS-12345678 */ +#endif /* XK_BRAILLE */ diff --git a/system/include/emscripten.h b/system/include/emscripten.h index 7b135c5a..7bb2ae8e 100644 --- a/system/include/emscripten.h +++ b/system/include/emscripten.h @@ -19,6 +19,30 @@ extern void emscripten_run_script(const char *script); extern int emscripten_run_script_int(const char *script); /* + * Set a C function as the main event loop. The JS environment + * will call that function at a specified number of frames per + * second. Setting 0 as the fps will use the default browser + * frame rate. + */ +extern void emscripten_set_main_loop(void (*func)(), int fps); +extern void emscripten_cancel_main_loop(); + +/* + * Call a C function asynchronously, that is, after returning + * control to the JS event loop. This is done by a setTimeout. + * When building natively this becomes a simple direct call, + * after SDL_Delay (you must include SDL.h for that). + */ +#if EMSCRIPTEN +extern void emscripten_async_call(void (*func)(), int millis); +#else +void emscripten_async_call(void (*func)(), int millis) { + SDL_Delay(millis); + func(); +} +#endif + +/* * This macro-looking function will cause Emscripten to * generate a comment in the generated code. * XXX This is deprecated for now, because it requires us to diff --git a/system/include/libc/stdio.h b/system/include/libc/stdio.h index 19e460a3..4e14df79 100644 --- a/system/include/libc/stdio.h +++ b/system/include/libc/stdio.h @@ -142,6 +142,7 @@ typedef _fpos64_t fpos64_t; #define TMP_MAX 26 +#if 0 /* XXX Emscripten: do not use impure stuff for std*, it makes comparing to native builds harder */ #ifndef _REENT_ONLY #define stdin (_REENT->_stdin) #define stdout (_REENT->_stdout) @@ -151,6 +152,14 @@ typedef _fpos64_t fpos64_t; #define stdout (_impure_ptr->_stdout) #define stderr (_impure_ptr->_stderr) #endif /* _REENT_ONLY */ +#else +extern FILE *stdin; +extern FILE *stdout; +extern FILE *stderr; +#define stdin stdin +#define stdout stdout +#define stderr stderr +#endif #define _stdin_r(x) ((x)->_stdin) #define _stdout_r(x) ((x)->_stdout) diff --git a/system/include/libc/sys/types.h b/system/include/libc/sys/types.h index ab6e895b..77acc92e 100644 --- a/system/include/libc/sys/types.h +++ b/system/include/libc/sys/types.h @@ -24,7 +24,7 @@ #include <machine/_types.h> -#if defined(__rtems__) || defined(__XMK__) +#if defined(__rtems__) || defined(__XMK__) || defined(EMSCRIPTEN) /* * The following section is RTEMS specific and is needed to more * closely match the types defined in the BSD sys/types.h. @@ -140,14 +140,11 @@ typedef unsigned long vm_size_t; #define __BIT_TYPES_DEFINED__ +// XXX Emscripten: removed unsigned types which are already defined typedef signed char int8_t; -typedef unsigned char u_int8_t; typedef short int16_t; -typedef unsigned short u_int16_t; typedef int int32_t; -typedef unsigned int u_int32_t; typedef long long int64_t; -typedef unsigned long long u_int64_t; typedef int32_t register_t; #endif /* __MS_types__ */ diff --git a/system/include/libc/sys/unistd.h b/system/include/libc/sys/unistd.h index 05b9286a..082c5e4d 100644 --- a/system/include/libc/sys/unistd.h +++ b/system/include/libc/sys/unistd.h @@ -260,9 +260,10 @@ int _EXFUN(unlinkat, (int, const char *, int)); #include <sys/features.h> -#define STDIN_FILENO 0 /* standard input file descriptor */ -#define STDOUT_FILENO 1 /* standard output file descriptor */ -#define STDERR_FILENO 2 /* standard error file descriptor */ +/* XXX Emscripten: start these at 1, we can use pointers as equals to file descriptors */ +#define STDIN_FILENO 1 /* standard input file descriptor */ +#define STDOUT_FILENO 2 /* standard output file descriptor */ +#define STDERR_FILENO 3 /* standard error file descriptor */ /* * sysconf values per IEEE Std 1003.1, 2008 Edition diff --git a/system/include/libcxx/ios b/system/include/libcxx/ios index e2f2b6fd..477a51fa 100644 --- a/system/include/libcxx/ios +++ b/system/include/libcxx/ios @@ -8,6 +8,12 @@ // //===----------------------------------------------------------------------===// +// Emscripten note: +// __except has been renamed to __exceptXXX in this header to avoid compilation +// errors on windows using clang version 3.0 (tags/RELEASE_30/final). This can +// be reverted once emscripten upgrades to clang 3.1: +// http://comments.gmane.org/gmane.comp.compilers.clang.scm/41578 + #ifndef _LIBCPP_IOS #define _LIBCPP_IOS @@ -317,7 +323,7 @@ public: _LIBCPP_INLINE_VISIBILITY bool bad() const; _LIBCPP_INLINE_VISIBILITY iostate exceptions() const; - _LIBCPP_INLINE_VISIBILITY void exceptions(iostate __except); + _LIBCPP_INLINE_VISIBILITY void exceptions(iostate __exceptXXX); void __set_badbit_and_consider_rethrow(); void __set_failbit_and_consider_rethrow(); @@ -553,9 +559,9 @@ ios_base::exceptions() const inline _LIBCPP_INLINE_VISIBILITY void -ios_base::exceptions(iostate __except) +ios_base::exceptions(iostate __exceptXXX) { - __exceptions_ = __except; + __exceptions_ = __exceptXXX; clear(__rdstate_); } @@ -584,7 +590,7 @@ public: _LIBCPP_ALWAYS_INLINE bool bad() const {return ios_base::bad();} _LIBCPP_ALWAYS_INLINE iostate exceptions() const {return ios_base::exceptions();} - _LIBCPP_ALWAYS_INLINE void exceptions(iostate __except) {ios_base::exceptions(__except);} + _LIBCPP_ALWAYS_INLINE void exceptions(iostate __exceptXXX) {ios_base::exceptions(__exceptXXX);} // 27.5.4.1 Constructor/destructor: _LIBCPP_INLINE_VISIBILITY diff --git a/system/include/net/arpa/nameser.h b/system/include/net/arpa/nameser.h new file mode 100644 index 00000000..6a2c8376 --- /dev/null +++ b/system/include/net/arpa/nameser.h @@ -0,0 +1,535 @@ +/* + * Copyright (c) 1983, 1989, 1993 + * The 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: + * 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. + * 4. Neither the name of the University 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 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. + */ + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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. + */ + +/* + * $BINDId: nameser.h,v 8.37 2000/03/30 21:16:49 vixie Exp $ + */ + +#ifndef _ARPA_NAMESER_H_ +#define _ARPA_NAMESER_H_ + +/*! \file */ + +#define BIND_4_COMPAT + +#include <sys/param.h> +#if (!defined(BSD)) || (BSD < 199306) +# include <sys/bitypes.h> +#else +# include <sys/types.h> +#endif +#include <sys/cdefs.h> + +/*% + * Revision information. This is the release date in YYYYMMDD format. + * It can change every day so the right thing to do with it is use it + * in preprocessor commands such as "#if (__NAMESER > 19931104)". Do not + * compare for equality; rather, use it to determine whether your libbind.a + * contains a new enough lib/nameser/ to support the feature you need. + */ + +#define __NAMESER 19991006 /*%< New interface version stamp. */ +/* + * Define constants based on RFC 883, RFC 1034, RFC 1035 + */ +#define NS_PACKETSZ 512 /*%< default UDP packet size */ +#define NS_MAXDNAME 1025 /*%< maximum domain name */ +#define NS_MAXMSG 65535 /*%< maximum message size */ +#define NS_MAXCDNAME 255 /*%< maximum compressed domain name */ +#define NS_MAXLABEL 63 /*%< maximum length of domain label */ +#define NS_HFIXEDSZ 12 /*%< #/bytes of fixed data in header */ +#define NS_QFIXEDSZ 4 /*%< #/bytes of fixed data in query */ +#define NS_RRFIXEDSZ 10 /*%< #/bytes of fixed data in r record */ +#define NS_INT32SZ 4 /*%< #/bytes of data in a u_int32_t */ +#define NS_INT16SZ 2 /*%< #/bytes of data in a u_int16_t */ +#define NS_INT8SZ 1 /*%< #/bytes of data in a u_int8_t */ +#define NS_INADDRSZ 4 /*%< IPv4 T_A */ +#define NS_IN6ADDRSZ 16 /*%< IPv6 T_AAAA */ +#define NS_CMPRSFLGS 0xc0 /*%< Flag bits indicating name compression. */ +#define NS_DEFAULTPORT 53 /*%< For both TCP and UDP. */ +/* + * These can be expanded with synonyms, just keep ns_parse.c:ns_parserecord() + * in synch with it. + */ +typedef enum __ns_sect { + ns_s_qd = 0, /*%< Query: Question. */ + ns_s_zn = 0, /*%< Update: Zone. */ + ns_s_an = 1, /*%< Query: Answer. */ + ns_s_pr = 1, /*%< Update: Prerequisites. */ + ns_s_ns = 2, /*%< Query: Name servers. */ + ns_s_ud = 2, /*%< Update: Update. */ + ns_s_ar = 3, /*%< Query|Update: Additional records. */ + ns_s_max = 4 +} ns_sect; + +/*% + * This is a message handle. It is caller allocated and has no dynamic data. + * This structure is intended to be opaque to all but ns_parse.c, thus the + * leading _'s on the member names. Use the accessor functions, not the _'s. + */ +typedef struct __ns_msg { + const u_char *_msg, *_eom; + u_int16_t _id, _flags, _counts[ns_s_max]; + const u_char *_sections[ns_s_max]; + ns_sect _sect; + int _rrnum; + const u_char *_msg_ptr; +} ns_msg; + +/* Private data structure - do not use from outside library. */ +struct _ns_flagdata { int mask, shift; }; +extern const struct _ns_flagdata _ns_flagdata[]; + +/* Accessor macros - this is part of the public interface. */ + +#define ns_msg_id(handle) ((handle)._id + 0) +#define ns_msg_base(handle) ((handle)._msg + 0) +#define ns_msg_end(handle) ((handle)._eom + 0) +#define ns_msg_size(handle) ((handle)._eom - (handle)._msg) +#define ns_msg_count(handle, section) ((handle)._counts[section] + 0) + +/*% + * This is a parsed record. It is caller allocated and has no dynamic data. + */ +typedef struct __ns_rr { + char name[NS_MAXDNAME]; + u_int16_t type; + u_int16_t rr_class; + u_int32_t ttl; + u_int16_t rdlength; + const u_char * rdata; +} ns_rr; + +/* Accessor macros - this is part of the public interface. */ +#define ns_rr_name(rr) (((rr).name[0] != '\0') ? (rr).name : ".") +#define ns_rr_type(rr) ((ns_type)((rr).type + 0)) +#define ns_rr_class(rr) ((ns_class)((rr).rr_class + 0)) +#define ns_rr_ttl(rr) ((rr).ttl + 0) +#define ns_rr_rdlen(rr) ((rr).rdlength + 0) +#define ns_rr_rdata(rr) ((rr).rdata + 0) + +/*% + * These don't have to be in the same order as in the packet flags word, + * and they can even overlap in some cases, but they will need to be kept + * in synch with ns_parse.c:ns_flagdata[]. + */ +typedef enum __ns_flag { + ns_f_qr, /*%< Question/Response. */ + ns_f_opcode, /*%< Operation code. */ + ns_f_aa, /*%< Authoritative Answer. */ + ns_f_tc, /*%< Truncation occurred. */ + ns_f_rd, /*%< Recursion Desired. */ + ns_f_ra, /*%< Recursion Available. */ + ns_f_z, /*%< MBZ. */ + ns_f_ad, /*%< Authentic Data (DNSSEC). */ + ns_f_cd, /*%< Checking Disabled (DNSSEC). */ + ns_f_rcode, /*%< Response code. */ + ns_f_max +} ns_flag; + +/*% + * Currently defined opcodes. + */ +typedef enum __ns_opcode { + ns_o_query = 0, /*%< Standard query. */ + ns_o_iquery = 1, /*%< Inverse query (deprecated/unsupported). */ + ns_o_status = 2, /*%< Name server status query (unsupported). */ + /* Opcode 3 is undefined/reserved. */ + ns_o_notify = 4, /*%< Zone change notification. */ + ns_o_update = 5, /*%< Zone update message. */ + ns_o_max = 6 +} ns_opcode; + +/*% + * Currently defined response codes. + */ +typedef enum __ns_rcode { + ns_r_noerror = 0, /*%< No error occurred. */ + ns_r_formerr = 1, /*%< Format error. */ + ns_r_servfail = 2, /*%< Server failure. */ + ns_r_nxdomain = 3, /*%< Name error. */ + ns_r_notimpl = 4, /*%< Unimplemented. */ + ns_r_refused = 5, /*%< Operation refused. */ + /* these are for BIND_UPDATE */ + ns_r_yxdomain = 6, /*%< Name exists */ + ns_r_yxrrset = 7, /*%< RRset exists */ + ns_r_nxrrset = 8, /*%< RRset does not exist */ + ns_r_notauth = 9, /*%< Not authoritative for zone */ + ns_r_notzone = 10, /*%< Zone of record different from zone section */ + ns_r_max = 11, + /* The following are EDNS extended rcodes */ + ns_r_badvers = 16, + /* The following are TSIG errors */ + ns_r_badsig = 16, + ns_r_badkey = 17, + ns_r_badtime = 18 +} ns_rcode; + +/* BIND_UPDATE */ +typedef enum __ns_update_operation { + ns_uop_delete = 0, + ns_uop_add = 1, + ns_uop_max = 2 +} ns_update_operation; + +/*% + * This structure is used for TSIG authenticated messages + */ +struct ns_tsig_key { + char name[NS_MAXDNAME], alg[NS_MAXDNAME]; + unsigned char *data; + int len; +}; +typedef struct ns_tsig_key ns_tsig_key; + +/*% + * This structure is used for TSIG authenticated TCP messages + */ +struct ns_tcp_tsig_state { + int counter; + struct dst_key *key; + void *ctx; + unsigned char sig[NS_PACKETSZ]; + int siglen; +}; +typedef struct ns_tcp_tsig_state ns_tcp_tsig_state; + +#define NS_TSIG_FUDGE 300 +#define NS_TSIG_TCP_COUNT 100 +#define NS_TSIG_ALG_HMAC_MD5 "HMAC-MD5.SIG-ALG.REG.INT" + +#define NS_TSIG_ERROR_NO_TSIG -10 +#define NS_TSIG_ERROR_NO_SPACE -11 +#define NS_TSIG_ERROR_FORMERR -12 + +/*% + * Currently defined type values for resources and queries. + */ +typedef enum __ns_type { + ns_t_invalid = 0, /*%< Cookie. */ + ns_t_a = 1, /*%< Host address. */ + ns_t_ns = 2, /*%< Authoritative server. */ + ns_t_md = 3, /*%< Mail destination. */ + ns_t_mf = 4, /*%< Mail forwarder. */ + ns_t_cname = 5, /*%< Canonical name. */ + ns_t_soa = 6, /*%< Start of authority zone. */ + ns_t_mb = 7, /*%< Mailbox domain name. */ + ns_t_mg = 8, /*%< Mail group member. */ + ns_t_mr = 9, /*%< Mail rename name. */ + ns_t_null = 10, /*%< Null resource record. */ + ns_t_wks = 11, /*%< Well known service. */ + ns_t_ptr = 12, /*%< Domain name pointer. */ + ns_t_hinfo = 13, /*%< Host information. */ + ns_t_minfo = 14, /*%< Mailbox information. */ + ns_t_mx = 15, /*%< Mail routing information. */ + ns_t_txt = 16, /*%< Text strings. */ + ns_t_rp = 17, /*%< Responsible person. */ + ns_t_afsdb = 18, /*%< AFS cell database. */ + ns_t_x25 = 19, /*%< X_25 calling address. */ + ns_t_isdn = 20, /*%< ISDN calling address. */ + ns_t_rt = 21, /*%< Router. */ + ns_t_nsap = 22, /*%< NSAP address. */ + ns_t_nsap_ptr = 23, /*%< Reverse NSAP lookup (deprecated). */ + ns_t_sig = 24, /*%< Security signature. */ + ns_t_key = 25, /*%< Security key. */ + ns_t_px = 26, /*%< X.400 mail mapping. */ + ns_t_gpos = 27, /*%< Geographical position (withdrawn). */ + ns_t_aaaa = 28, /*%< Ip6 Address. */ + ns_t_loc = 29, /*%< Location Information. */ + ns_t_nxt = 30, /*%< Next domain (security). */ + ns_t_eid = 31, /*%< Endpoint identifier. */ + ns_t_nimloc = 32, /*%< Nimrod Locator. */ + ns_t_srv = 33, /*%< Server Selection. */ + ns_t_atma = 34, /*%< ATM Address */ + ns_t_naptr = 35, /*%< Naming Authority PoinTeR */ + ns_t_kx = 36, /*%< Key Exchange */ + ns_t_cert = 37, /*%< Certification record */ + ns_t_a6 = 38, /*%< IPv6 address (deprecated, use ns_t_aaaa) */ + ns_t_dname = 39, /*%< Non-terminal DNAME (for IPv6) */ + ns_t_sink = 40, /*%< Kitchen sink (experimentatl) */ + ns_t_opt = 41, /*%< EDNS0 option (meta-RR) */ + ns_t_apl = 42, /*%< Address prefix list (RFC3123) */ + ns_t_tkey = 249, /*%< Transaction key */ + ns_t_tsig = 250, /*%< Transaction signature. */ + ns_t_ixfr = 251, /*%< Incremental zone transfer. */ + ns_t_axfr = 252, /*%< Transfer zone of authority. */ + ns_t_mailb = 253, /*%< Transfer mailbox records. */ + ns_t_maila = 254, /*%< Transfer mail agent records. */ + ns_t_any = 255, /*%< Wildcard match. */ + ns_t_zxfr = 256, /*%< BIND-specific, nonstandard. */ + ns_t_max = 65536 +} ns_type; + +/* Exclusively a QTYPE? (not also an RTYPE) */ +#define ns_t_qt_p(t) (ns_t_xfr_p(t) || (t) == ns_t_any || \ + (t) == ns_t_mailb || (t) == ns_t_maila) +/* Some kind of meta-RR? (not a QTYPE, but also not an RTYPE) */ +#define ns_t_mrr_p(t) ((t) == ns_t_tsig || (t) == ns_t_opt) +/* Exclusively an RTYPE? (not also a QTYPE or a meta-RR) */ +#define ns_t_rr_p(t) (!ns_t_qt_p(t) && !ns_t_mrr_p(t)) +#define ns_t_udp_p(t) ((t) != ns_t_axfr && (t) != ns_t_zxfr) +#define ns_t_xfr_p(t) ((t) == ns_t_axfr || (t) == ns_t_ixfr || \ + (t) == ns_t_zxfr) + +/*% + * Values for class field + */ +typedef enum __ns_class { + ns_c_invalid = 0, /*%< Cookie. */ + ns_c_in = 1, /*%< Internet. */ + ns_c_2 = 2, /*%< unallocated/unsupported. */ + ns_c_chaos = 3, /*%< MIT Chaos-net. */ + ns_c_hs = 4, /*%< MIT Hesiod. */ + /* Query class values which do not appear in resource records */ + ns_c_none = 254, /*%< for prereq. sections in update requests */ + ns_c_any = 255, /*%< Wildcard match. */ + ns_c_max = 65536 +} ns_class; + +/* DNSSEC constants. */ + +typedef enum __ns_key_types { + ns_kt_rsa = 1, /*%< key type RSA/MD5 */ + ns_kt_dh = 2, /*%< Diffie Hellman */ + ns_kt_dsa = 3, /*%< Digital Signature Standard (MANDATORY) */ + ns_kt_private = 254 /*%< Private key type starts with OID */ +} ns_key_types; + +typedef enum __ns_cert_types { + cert_t_pkix = 1, /*%< PKIX (X.509v3) */ + cert_t_spki = 2, /*%< SPKI */ + cert_t_pgp = 3, /*%< PGP */ + cert_t_url = 253, /*%< URL private type */ + cert_t_oid = 254 /*%< OID private type */ +} ns_cert_types; + +/* Flags field of the KEY RR rdata. */ +#define NS_KEY_TYPEMASK 0xC000 /*%< Mask for "type" bits */ +#define NS_KEY_TYPE_AUTH_CONF 0x0000 /*%< Key usable for both */ +#define NS_KEY_TYPE_CONF_ONLY 0x8000 /*%< Key usable for confidentiality */ +#define NS_KEY_TYPE_AUTH_ONLY 0x4000 /*%< Key usable for authentication */ +#define NS_KEY_TYPE_NO_KEY 0xC000 /*%< No key usable for either; no key */ +/* The type bits can also be interpreted independently, as single bits: */ +#define NS_KEY_NO_AUTH 0x8000 /*%< Key unusable for authentication */ +#define NS_KEY_NO_CONF 0x4000 /*%< Key unusable for confidentiality */ +#define NS_KEY_RESERVED2 0x2000 /* Security is *mandatory* if bit=0 */ +#define NS_KEY_EXTENDED_FLAGS 0x1000 /*%< reserved - must be zero */ +#define NS_KEY_RESERVED4 0x0800 /*%< reserved - must be zero */ +#define NS_KEY_RESERVED5 0x0400 /*%< reserved - must be zero */ +#define NS_KEY_NAME_TYPE 0x0300 /*%< these bits determine the type */ +#define NS_KEY_NAME_USER 0x0000 /*%< key is assoc. with user */ +#define NS_KEY_NAME_ENTITY 0x0200 /*%< key is assoc. with entity eg host */ +#define NS_KEY_NAME_ZONE 0x0100 /*%< key is zone key */ +#define NS_KEY_NAME_RESERVED 0x0300 /*%< reserved meaning */ +#define NS_KEY_RESERVED8 0x0080 /*%< reserved - must be zero */ +#define NS_KEY_RESERVED9 0x0040 /*%< reserved - must be zero */ +#define NS_KEY_RESERVED10 0x0020 /*%< reserved - must be zero */ +#define NS_KEY_RESERVED11 0x0010 /*%< reserved - must be zero */ +#define NS_KEY_SIGNATORYMASK 0x000F /*%< key can sign RR's of same name */ +#define NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED2 | \ + NS_KEY_RESERVED4 | \ + NS_KEY_RESERVED5 | \ + NS_KEY_RESERVED8 | \ + NS_KEY_RESERVED9 | \ + NS_KEY_RESERVED10 | \ + NS_KEY_RESERVED11 ) +#define NS_KEY_RESERVED_BITMASK2 0xFFFF /*%< no bits defined here */ +/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */ +#define NS_ALG_MD5RSA 1 /*%< MD5 with RSA */ +#define NS_ALG_DH 2 /*%< Diffie Hellman KEY */ +#define NS_ALG_DSA 3 /*%< DSA KEY */ +#define NS_ALG_DSS NS_ALG_DSA +#define NS_ALG_EXPIRE_ONLY 253 /*%< No alg, no security */ +#define NS_ALG_PRIVATE_OID 254 /*%< Key begins with OID giving alg */ +/* Protocol values */ +/* value 0 is reserved */ +#define NS_KEY_PROT_TLS 1 +#define NS_KEY_PROT_EMAIL 2 +#define NS_KEY_PROT_DNSSEC 3 +#define NS_KEY_PROT_IPSEC 4 +#define NS_KEY_PROT_ANY 255 + +/* Signatures */ +#define NS_MD5RSA_MIN_BITS 512 /*%< Size of a mod or exp in bits */ +#define NS_MD5RSA_MAX_BITS 4096 + /* Total of binary mod and exp */ +#define NS_MD5RSA_MAX_BYTES ((NS_MD5RSA_MAX_BITS+7/8)*2+3) + /* Max length of text sig block */ +#define NS_MD5RSA_MAX_BASE64 (((NS_MD5RSA_MAX_BYTES+2)/3)*4) +#define NS_MD5RSA_MIN_SIZE ((NS_MD5RSA_MIN_BITS+7)/8) +#define NS_MD5RSA_MAX_SIZE ((NS_MD5RSA_MAX_BITS+7)/8) + +#define NS_DSA_SIG_SIZE 41 +#define NS_DSA_MIN_SIZE 213 +#define NS_DSA_MAX_BYTES 405 + +/* Offsets into SIG record rdata to find various values */ +#define NS_SIG_TYPE 0 /*%< Type flags */ +#define NS_SIG_ALG 2 /*%< Algorithm */ +#define NS_SIG_LABELS 3 /*%< How many labels in name */ +#define NS_SIG_OTTL 4 /*%< Original TTL */ +#define NS_SIG_EXPIR 8 /*%< Expiration time */ +#define NS_SIG_SIGNED 12 /*%< Signature time */ +#define NS_SIG_FOOT 16 /*%< Key footprint */ +#define NS_SIG_SIGNER 18 /*%< Domain name of who signed it */ +/* How RR types are represented as bit-flags in NXT records */ +#define NS_NXT_BITS 8 +#define NS_NXT_BIT_SET( n,p) (p[(n)/NS_NXT_BITS] |= (0x80>>((n)%NS_NXT_BITS))) +#define NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS))) +#define NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] & (0x80>>((n)%NS_NXT_BITS))) +#define NS_NXT_MAX 127 + +/*% + * EDNS0 extended flags and option codes, host order. + */ +#define NS_OPT_DNSSEC_OK 0x8000U +#define NS_OPT_NSID 3 + +/*% + * Inline versions of get/put short/long. Pointer is advanced. + */ +#define NS_GET16(s, cp) do { \ + register const u_char *t_cp = (const u_char *)(cp); \ + (s) = ((u_int16_t)t_cp[0] << 8) \ + | ((u_int16_t)t_cp[1]) \ + ; \ + (cp) += NS_INT16SZ; \ +} while (0) + +#define NS_GET32(l, cp) do { \ + register const u_char *t_cp = (const u_char *)(cp); \ + (l) = ((u_int32_t)t_cp[0] << 24) \ + | ((u_int32_t)t_cp[1] << 16) \ + | ((u_int32_t)t_cp[2] << 8) \ + | ((u_int32_t)t_cp[3]) \ + ; \ + (cp) += NS_INT32SZ; \ +} while (0) + +#define NS_PUT16(s, cp) do { \ + register u_int16_t t_s = (u_int16_t)(s); \ + register u_char *t_cp = (u_char *)(cp); \ + *t_cp++ = t_s >> 8; \ + *t_cp = t_s; \ + (cp) += NS_INT16SZ; \ +} while (0) + +#define NS_PUT32(l, cp) do { \ + register u_int32_t t_l = (u_int32_t)(l); \ + register u_char *t_cp = (u_char *)(cp); \ + *t_cp++ = t_l >> 24; \ + *t_cp++ = t_l >> 16; \ + *t_cp++ = t_l >> 8; \ + *t_cp = t_l; \ + (cp) += NS_INT32SZ; \ +} while (0) + +__BEGIN_DECLS +int ns_msg_getflag (ns_msg, int) __THROW; +u_int ns_get16 (const u_char *) __THROW; +u_long ns_get32 (const u_char *) __THROW; +void ns_put16 (u_int, u_char *) __THROW; +void ns_put32 (u_long, u_char *) __THROW; +int ns_initparse (const u_char *, int, ns_msg *) __THROW; +int ns_skiprr (const u_char *, const u_char *, ns_sect, int) + __THROW; +int ns_parserr (ns_msg *, ns_sect, int, ns_rr *) __THROW; +int ns_sprintrr (const ns_msg *, const ns_rr *, + const char *, const char *, char *, size_t) + __THROW; +int ns_sprintrrf (const u_char *, size_t, const char *, + ns_class, ns_type, u_long, const u_char *, + size_t, const char *, const char *, + char *, size_t) __THROW; +int ns_format_ttl (u_long, char *, size_t) __THROW; +int ns_parse_ttl (const char *, u_long *) __THROW; +u_int32_t ns_datetosecs (const char *, int *) __THROW; +int ns_name_ntol (const u_char *, u_char *, size_t) __THROW; +int ns_name_ntop (const u_char *, char *, size_t) __THROW; +int ns_name_pton (const char *, u_char *, size_t) __THROW; +int ns_name_unpack (const u_char *, const u_char *, + const u_char *, u_char *, size_t) __THROW; +int ns_name_pack (const u_char *, u_char *, int, + const u_char **, const u_char **) __THROW; +int ns_name_uncompress (const u_char *, const u_char *, + const u_char *, char *, size_t) __THROW; +int ns_name_compress (const char *, u_char *, size_t, + const u_char **, const u_char **) __THROW; +int ns_name_skip (const u_char **, const u_char *) __THROW; +void ns_name_rollback (const u_char *, const u_char **, + const u_char **) __THROW; +int ns_sign (u_char *, int *, int, int, void *, + const u_char *, int, u_char *, int *, time_t) __THROW; +int ns_sign2 (u_char *, int *, int, int, void *, + const u_char *, int, u_char *, int *, time_t, + u_char **, u_char **) __THROW; +int ns_sign_tcp (u_char *, int *, int, int, + ns_tcp_tsig_state *, int) __THROW; +int ns_sign_tcp2 (u_char *, int *, int, int, + ns_tcp_tsig_state *, int, + u_char **, u_char **) __THROW; +int ns_sign_tcp_init (void *, const u_char *, int, + ns_tcp_tsig_state *) __THROW; +u_char *ns_find_tsig (u_char *, u_char *) __THROW; +int ns_verify (u_char *, int *, void *, const u_char *, int, + u_char *, int *, time_t *, int) __THROW; +int ns_verify_tcp (u_char *, int *, ns_tcp_tsig_state *, int) + __THROW; +int ns_verify_tcp_init (void *, const u_char *, int, + ns_tcp_tsig_state *) __THROW; +int ns_samedomain (const char *, const char *) __THROW; +int ns_subdomain (const char *, const char *) __THROW; +int ns_makecanon (const char *, char *, size_t) __THROW; +int ns_samename (const char *, const char *) __THROW; +__END_DECLS + +#ifdef BIND_4_COMPAT +#include <arpa/nameser_compat.h> +#endif + +#endif /* !_ARPA_NAMESER_H_ */ +/*! \file */ diff --git a/system/include/net/arpa/nameser_compat.h b/system/include/net/arpa/nameser_compat.h new file mode 100644 index 00000000..d59c9e41 --- /dev/null +++ b/system/include/net/arpa/nameser_compat.h @@ -0,0 +1,187 @@ +/* Copyright (c) 1983, 1989 + * The 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: + * 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. + * 4. Neither the name of the University 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 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. + */ + +/*% + * from nameser.h 8.1 (Berkeley) 6/2/93 + * $BINDId: nameser_compat.h,v 8.11 1999/01/02 08:00:58 vixie Exp $ + */ + +#ifndef _ARPA_NAMESER_COMPAT_ +#define _ARPA_NAMESER_COMPAT_ + +#define __BIND 19950621 /*%< (DEAD) interface version stamp. */ + +#include <endian.h> + +/*% + * Structure for query header. The order of the fields is machine- and + * compiler-dependent, depending on the byte/bit order and the layout + * of bit fields. We use bit fields only in int variables, as this + * is all ANSI requires. This requires a somewhat confusing rearrangement. + */ + +typedef struct { + unsigned id :16; /*%< query identification number */ +#if BYTE_ORDER == BIG_ENDIAN + /* fields in third byte */ + unsigned qr: 1; /*%< response flag */ + unsigned opcode: 4; /*%< purpose of message */ + unsigned aa: 1; /*%< authoritive answer */ + unsigned tc: 1; /*%< truncated message */ + unsigned rd: 1; /*%< recursion desired */ + /* fields in fourth byte */ + unsigned ra: 1; /*%< recursion available */ + unsigned unused :1; /*%< unused bits (MBZ as of 4.9.3a3) */ + unsigned ad: 1; /*%< authentic data from named */ + unsigned cd: 1; /*%< checking disabled by resolver */ + unsigned rcode :4; /*%< response code */ +#endif +#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN + /* fields in third byte */ + unsigned rd :1; /*%< recursion desired */ + unsigned tc :1; /*%< truncated message */ + unsigned aa :1; /*%< authoritive answer */ + unsigned opcode :4; /*%< purpose of message */ + unsigned qr :1; /*%< response flag */ + /* fields in fourth byte */ + unsigned rcode :4; /*%< response code */ + unsigned cd: 1; /*%< checking disabled by resolver */ + unsigned ad: 1; /*%< authentic data from named */ + unsigned unused :1; /*%< unused bits (MBZ as of 4.9.3a3) */ + unsigned ra :1; /*%< recursion available */ +#endif + /* remaining bytes */ + unsigned qdcount :16; /*%< number of question entries */ + unsigned ancount :16; /*%< number of answer entries */ + unsigned nscount :16; /*%< number of authority entries */ + unsigned arcount :16; /*%< number of resource entries */ +} HEADER; + +#define PACKETSZ NS_PACKETSZ +#define MAXDNAME NS_MAXDNAME +#define MAXCDNAME NS_MAXCDNAME +#define MAXLABEL NS_MAXLABEL +#define HFIXEDSZ NS_HFIXEDSZ +#define QFIXEDSZ NS_QFIXEDSZ +#define RRFIXEDSZ NS_RRFIXEDSZ +#define INT32SZ NS_INT32SZ +#define INT16SZ NS_INT16SZ +#define INT8SZ NS_INT8SZ +#define INADDRSZ NS_INADDRSZ +#define IN6ADDRSZ NS_IN6ADDRSZ +#define INDIR_MASK NS_CMPRSFLGS +#define NAMESERVER_PORT NS_DEFAULTPORT + +#define S_ZONE ns_s_zn +#define S_PREREQ ns_s_pr +#define S_UPDATE ns_s_ud +#define S_ADDT ns_s_ar + +#define QUERY ns_o_query +#define IQUERY ns_o_iquery +#define STATUS ns_o_status +#define NS_NOTIFY_OP ns_o_notify +#define NS_UPDATE_OP ns_o_update + +#define NOERROR ns_r_noerror +#define FORMERR ns_r_formerr +#define SERVFAIL ns_r_servfail +#define NXDOMAIN ns_r_nxdomain +#define NOTIMP ns_r_notimpl +#define REFUSED ns_r_refused +#define YXDOMAIN ns_r_yxdomain +#define YXRRSET ns_r_yxrrset +#define NXRRSET ns_r_nxrrset +#define NOTAUTH ns_r_notauth +#define NOTZONE ns_r_notzone +/*#define BADSIG ns_r_badsig*/ +/*#define BADKEY ns_r_badkey*/ +/*#define BADTIME ns_r_badtime*/ + + +#define DELETE ns_uop_delete +#define ADD ns_uop_add + +#define T_A ns_t_a +#define T_NS ns_t_ns +#define T_MD ns_t_md +#define T_MF ns_t_mf +#define T_CNAME ns_t_cname +#define T_SOA ns_t_soa +#define T_MB ns_t_mb +#define T_MG ns_t_mg +#define T_MR ns_t_mr +#define T_NULL ns_t_null +#define T_WKS ns_t_wks +#define T_PTR ns_t_ptr +#define T_HINFO ns_t_hinfo +#define T_MINFO ns_t_minfo +#define T_MX ns_t_mx +#define T_TXT ns_t_txt +#define T_RP ns_t_rp +#define T_AFSDB ns_t_afsdb +#define T_X25 ns_t_x25 +#define T_ISDN ns_t_isdn +#define T_RT ns_t_rt +#define T_NSAP ns_t_nsap +#define T_NSAP_PTR ns_t_nsap_ptr +#define T_SIG ns_t_sig +#define T_KEY ns_t_key +#define T_PX ns_t_px +#define T_GPOS ns_t_gpos +#define T_AAAA ns_t_aaaa +#define T_LOC ns_t_loc +#define T_NXT ns_t_nxt +#define T_EID ns_t_eid +#define T_NIMLOC ns_t_nimloc +#define T_SRV ns_t_srv +#define T_ATMA ns_t_atma +#define T_NAPTR ns_t_naptr +#define T_A6 ns_t_a6 +#define T_DNAME ns_t_dname +#define T_TSIG ns_t_tsig +#define T_IXFR ns_t_ixfr +#define T_AXFR ns_t_axfr +#define T_MAILB ns_t_mailb +#define T_MAILA ns_t_maila +#define T_ANY ns_t_any + +#define C_IN ns_c_in +#define C_CHAOS ns_c_chaos +#define C_HS ns_c_hs +/* BIND_UPDATE */ +#define C_NONE ns_c_none +#define C_ANY ns_c_any + +#define GETSHORT NS_GET16 +#define GETLONG NS_GET32 +#define PUTSHORT NS_PUT16 +#define PUTLONG NS_PUT32 + +#endif /* _ARPA_NAMESER_COMPAT_ */ +/*! \file */ diff --git a/system/include/net/if.h b/system/include/net/if.h index 9a4badf3..dd7884aa 100644 --- a/system/include/net/if.h +++ b/system/include/net/if.h @@ -2,6 +2,10 @@ #ifndef _NET_IF_H #define _NET_IF_H +#include <sys/socket.h> +#include <sys/types.h> +#include <sys/ioctl.h> + #ifdef __cplusplus extern "C" { #endif @@ -11,6 +15,61 @@ struct if_nameindex { char *if_name; }; +#define IFHWADDRLEN 6 +#define IFNAMSIZ 16 + +struct ifmap { + unsigned long int mem_start; + unsigned long int mem_end; + unsigned short int base_addr; + unsigned char irq; + unsigned char dma; + unsigned char port; +}; + +struct ifreq { + union { + char ifrn_name[IFNAMSIZ]; + } ifr_ifrn; + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_destaddr; + struct sockaddr ifru_broadaddr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; + short int ifru_flags; + int ifru_ivalue; + int ifru_mtu; + struct ifmap ifru_map; + char ifru_slave[IFNAMSIZ]; + char ifru_newname[IFNAMSIZ]; + caddr_t ifru_data; + } ifr_ifru; +}; +#define ifr_name ifr_ifrn.ifrn_name +#define ifr_addr ifr_ifru.ifru_addr +#define ifr_destaddr ifr_ifru.ifru_destaddr +#define ifr_broadaddr ifr_ifru.ifru_broadaddr +#define ifr_netmask ifr_ifru.ifru_netmask +#define ifr_hwaddr ifr_ifru.ifru_hwaddr +#define ifr_flags ifr_ifru.ifru_flags +#define ifr_ivalue ifr_ifru.ifru_ivalue +#define ifr_mtu ifr_ifru.ifru_mtu +#define ifr_map ifr_ifru.ifru_map +#define ifr_slave ifr_ifru.ifru_slave +#define ifr_newname ifr_ifru.ifru_newname +#define ifr_data ifr_ifru.ifru_data + +struct ifconf { + int ifc_len; + union { + caddr_t ifcu_buf; + struct ifreq* ifcu_req; + } ifc_ifcu; +}; +#define ifc_buf ifc_ifcu.ifcu_buf +#define ifc_req ifc_ifcu.ifcu_req + #define IF_NAMESIZE abort(0); unsigned if_nametoindex(const char *a); @@ -18,6 +77,8 @@ char *if_indextoname(unsigned int a, char *b); struct if_nameindex *if_nameindex(); void if_freenameindex(struct if_nameindex *a); + + #ifdef __cplusplus } #endif diff --git a/system/include/net/resolv.h b/system/include/net/resolv.h new file mode 100644 index 00000000..ed15a702 --- /dev/null +++ b/system/include/net/resolv.h @@ -0,0 +1,389 @@ +/* + * Copyright (c) 1983, 1987, 1989 + * The 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: + * 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. + * 4. Neither the name of the University 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 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. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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. + */ + +/* + * @(#)resolv.h 8.1 (Berkeley) 6/2/93 + * $BINDId: resolv.h,v 8.31 2000/03/30 20:16:50 vixie Exp $ + */ + +#ifndef _RESOLV_H_ + +/* These headers are needed for types used in the `struct res_state' + declaration. */ +#include <sys/types.h> +#include <netinet/in.h> + +#ifndef __need_res_state +# define _RESOLV_H_ + +# include <sys/param.h> +# include <sys/cdefs.h> +# include <stdio.h> +# include <arpa/nameser.h> +#endif + +#ifndef __res_state_defined +# define __res_state_defined + +typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error } + res_sendhookact; + +typedef res_sendhookact (*res_send_qhook) (struct sockaddr_in * const *__ns, + const u_char **__query, + int *__querylen, + u_char *__ans, + int __anssiz, + int *__resplen); + +typedef res_sendhookact (*res_send_rhook) (const struct sockaddr_in *__ns, + const u_char *__query, + int __querylen, + u_char *__ans, + int __anssiz, + int *__resplen); + +/* + * Global defines and variables for resolver stub. + */ +# define MAXNS 3 /* max # name servers we'll track */ +# define MAXDFLSRCH 3 /* # default domain levels to try */ +# define MAXDNSRCH 6 /* max # domains in search path */ +# define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */ + +# define RES_TIMEOUT 5 /* min. seconds between retries */ +# define MAXRESOLVSORT 10 /* number of net to sort on */ +# define RES_MAXNDOTS 15 /* should reflect bit field size */ +# define RES_MAXRETRANS 30 /* only for resolv.conf/RES_OPTIONS */ +# define RES_MAXRETRY 5 /* only for resolv.conf/RES_OPTIONS */ +# define RES_DFLRETRY 2 /* Default #/tries. */ +# define RES_MAXTIME 65535 /* Infinity, in milliseconds. */ + +struct __res_state { + int retrans; /* retransmition time interval */ + int retry; /* number of times to retransmit */ + u_long options; /* option flags - see below. */ + int nscount; /* number of name servers */ + struct sockaddr_in + nsaddr_list[MAXNS]; /* address of name server */ +# define nsaddr nsaddr_list[0] /* for backward compatibility */ + u_short id; /* current message id */ + /* 2 byte hole here. */ + char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */ + char defdname[256]; /* default domain (deprecated) */ + u_long pfcode; /* RES_PRF_ flags - see below. */ + unsigned ndots:4; /* threshold for initial abs. query */ + unsigned nsort:4; /* number of elements in sort_list[] */ + unsigned ipv6_unavail:1; /* connecting to IPv6 server failed */ + unsigned unused:23; + struct { + struct in_addr addr; + u_int32_t mask; + } sort_list[MAXRESOLVSORT]; + /* 4 byte hole here on 64-bit architectures. */ + res_send_qhook qhook; /* query hook */ + res_send_rhook rhook; /* response hook */ + int res_h_errno; /* last one set for this context */ + int _vcsock; /* PRIVATE: for res_send VC i/o */ + u_int _flags; /* PRIVATE: see below */ + /* 4 byte hole here on 64-bit architectures. */ + union { + char pad[52]; /* On an i386 this means 512b total. */ + struct { + u_int16_t nscount; + u_int16_t nsmap[MAXNS]; + int nssocks[MAXNS]; + u_int16_t nscount6; + u_int16_t nsinit; + struct sockaddr_in6 *nsaddrs[MAXNS]; +#ifdef _LIBC + unsigned long long int initstamp + __attribute__((packed)); +#else + unsigned int _initstamp[2]; +#endif + } _ext; + } _u; +}; + +typedef struct __res_state *res_state; +# undef __need_res_state +#endif + +#ifdef _RESOLV_H_ +/* + * Revision information. This is the release date in YYYYMMDD format. + * It can change every day so the right thing to do with it is use it + * in preprocessor commands such as "#if (__RES > 19931104)". Do not + * compare for equality; rather, use it to determine whether your resolver + * is new enough to contain a certain feature. + */ + +#define __RES 19991006 + +/* + * Resolver configuration file. + * Normally not present, but may contain the address of the + * inital name server(s) to query and the domain search list. + */ + +#ifndef _PATH_RESCONF +#define _PATH_RESCONF "/etc/resolv.conf" +#endif + +struct res_sym { + int number; /* Identifying number, like T_MX */ + char * name; /* Its symbolic name, like "MX" */ + char * humanname; /* Its fun name, like "mail exchanger" */ +}; + +/* + * Resolver flags (used to be discrete per-module statics ints). + */ +#define RES_F_VC 0x00000001 /* socket is TCP */ +#define RES_F_CONN 0x00000002 /* socket is connected */ +#define RES_F_EDNS0ERR 0x00000004 /* EDNS0 caused errors */ + +/* res_findzonecut() options */ +#define RES_EXHAUSTIVE 0x00000001 /* always do all queries */ + +/* + * Resolver options (keep these in synch with res_debug.c, please) + */ +#define RES_INIT 0x00000001 /* address initialized */ +#define RES_DEBUG 0x00000002 /* print debug messages */ +#define RES_AAONLY 0x00000004 /* authoritative answers only (!IMPL)*/ +#define RES_USEVC 0x00000008 /* use virtual circuit */ +#define RES_PRIMARY 0x00000010 /* query primary server only (!IMPL) */ +#define RES_IGNTC 0x00000020 /* ignore trucation errors */ +#define RES_RECURSE 0x00000040 /* recursion desired */ +#define RES_DEFNAMES 0x00000080 /* use default domain name */ +#define RES_STAYOPEN 0x00000100 /* Keep TCP socket open */ +#define RES_DNSRCH 0x00000200 /* search up local domain tree */ +#define RES_INSECURE1 0x00000400 /* type 1 security disabled */ +#define RES_INSECURE2 0x00000800 /* type 2 security disabled */ +#define RES_NOALIASES 0x00001000 /* shuts off HOSTALIASES feature */ +#define RES_USE_INET6 0x00002000 /* use/map IPv6 in gethostbyname() */ +#define RES_ROTATE 0x00004000 /* rotate ns list after each query */ +#define RES_NOCHECKNAME 0x00008000 /* do not check names for sanity. */ +#define RES_KEEPTSIG 0x00010000 /* do not strip TSIG records */ +#define RES_BLAST 0x00020000 /* blast all recursive servers */ +#define RES_USEBSTRING 0x00040000 /* IPv6 reverse lookup with byte + strings */ +#define RES_NOIP6DOTINT 0x00080000 /* Do not use .ip6.int in IPv6 + reverse lookup */ +#define RES_USE_EDNS0 0x00100000 /* Use EDNS0. */ +#define RES_SNGLKUP 0x00200000 /* one outstanding request at a time */ +#define RES_SNGLKUPREOP 0x00400000 /* -"-, but open new socket for each + request */ +#define RES_USE_DNSSEC 0x00800000 /* use DNSSEC using OK bit in OPT */ +#define RES_NOTLDQUERY 0x01000000 /* Do not look up unqualified name + as a TLD. */ + +#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH|RES_NOIP6DOTINT) + +/* + * Resolver "pfcode" values. Used by dig. + */ +#define RES_PRF_STATS 0x00000001 +#define RES_PRF_UPDATE 0x00000002 +#define RES_PRF_CLASS 0x00000004 +#define RES_PRF_CMD 0x00000008 +#define RES_PRF_QUES 0x00000010 +#define RES_PRF_ANS 0x00000020 +#define RES_PRF_AUTH 0x00000040 +#define RES_PRF_ADD 0x00000080 +#define RES_PRF_HEAD1 0x00000100 +#define RES_PRF_HEAD2 0x00000200 +#define RES_PRF_TTLID 0x00000400 +#define RES_PRF_HEADX 0x00000800 +#define RES_PRF_QUERY 0x00001000 +#define RES_PRF_REPLY 0x00002000 +#define RES_PRF_INIT 0x00004000 +/* 0x00008000 */ + +/* Things involving an internal (static) resolver context. */ +__BEGIN_DECLS +extern struct __res_state *__res_state(void) __attribute__ ((__const__)); +__END_DECLS +#define _res (*__res_state()) + +#ifndef __BIND_NOSTATIC +#define fp_nquery __fp_nquery +#define fp_query __fp_query +#define hostalias __hostalias +#define p_query __p_query +#define res_close __res_close +#define res_init __res_init +#define res_isourserver __res_isourserver +#define res_mkquery __res_mkquery +#define res_query __res_query +#define res_querydomain __res_querydomain +#define res_search __res_search +#define res_send __res_send + +__BEGIN_DECLS +void fp_nquery (const u_char *, int, FILE *) __THROW; +void fp_query (const u_char *, FILE *) __THROW; +const char * hostalias (const char *) __THROW; +void p_query (const u_char *) __THROW; +void res_close (void) __THROW; +int res_init (void) __THROW; +int res_isourserver (const struct sockaddr_in *) __THROW; +int res_mkquery (int, const char *, int, int, const u_char *, + int, const u_char *, u_char *, int) __THROW; +int res_query (const char *, int, int, u_char *, int) __THROW; +int res_querydomain (const char *, const char *, int, int, + u_char *, int) __THROW; +int res_search (const char *, int, int, u_char *, int) __THROW; +int res_send (const u_char *, int, u_char *, int) __THROW; +__END_DECLS +#endif + +#define b64_ntop __b64_ntop +#define b64_pton __b64_pton +#define dn_comp __dn_comp +#define dn_count_labels __dn_count_labels +#define dn_expand __dn_expand +#define dn_skipname __dn_skipname +#define fp_resstat __fp_resstat +#define loc_aton __loc_aton +#define loc_ntoa __loc_ntoa +#define p_cdname __p_cdname +#define p_cdnname __p_cdnname +#define p_class __p_class +#define p_fqname __p_fqname +#define p_fqnname __p_fqnname +#define p_option __p_option +#define p_secstodate __p_secstodate +#define p_section __p_section +#define p_time __p_time +#define p_type __p_type +#define p_rcode __p_rcode +#define putlong __putlong +#define putshort __putshort +#define res_dnok __res_dnok +#define res_hnok __res_hnok +#define res_hostalias __res_hostalias +#define res_mailok __res_mailok +#define res_nameinquery __res_nameinquery +#define res_nclose __res_nclose +#define res_ninit __res_ninit +#define res_nmkquery __res_nmkquery +#define res_npquery __res_npquery +#define res_nquery __res_nquery +#define res_nquerydomain __res_nquerydomain +#define res_nsearch __res_nsearch +#define res_nsend __res_nsend +#define res_nisourserver __res_nisourserver +#define res_ownok __res_ownok +#define res_queriesmatch __res_queriesmatch +#define res_randomid __res_randomid +#define sym_ntop __sym_ntop +#define sym_ntos __sym_ntos +#define sym_ston __sym_ston +__BEGIN_DECLS +int res_hnok (const char *) __THROW; +int res_ownok (const char *) __THROW; +int res_mailok (const char *) __THROW; +int res_dnok (const char *) __THROW; +int sym_ston (const struct res_sym *, const char *, int *) __THROW; +const char * sym_ntos (const struct res_sym *, int, int *) __THROW; +const char * sym_ntop (const struct res_sym *, int, int *) __THROW; +int b64_ntop (u_char const *, size_t, char *, size_t) __THROW; +int b64_pton (char const *, u_char *, size_t) __THROW; +int loc_aton (const char *__ascii, u_char *__binary) __THROW; +const char * loc_ntoa (const u_char *__binary, char *__ascii) __THROW; +int dn_skipname (const u_char *, const u_char *) __THROW; +void putlong (u_int32_t, u_char *) __THROW; +void putshort (u_int16_t, u_char *) __THROW; +const char * p_class (int) __THROW; +const char * p_time (u_int32_t) __THROW; +const char * p_type (int) __THROW; +const char * p_rcode (int) __THROW; +const u_char * p_cdnname (const u_char *, const u_char *, int, FILE *) + __THROW; +const u_char * p_cdname (const u_char *, const u_char *, FILE *) __THROW; +const u_char * p_fqnname (const u_char *__cp, const u_char *__msg, + int, char *, int) __THROW; +const u_char * p_fqname (const u_char *, const u_char *, FILE *) __THROW; +const char * p_option (u_long __option) __THROW; +char * p_secstodate (u_long) __THROW; +int dn_count_labels (const char *) __THROW; +int dn_comp (const char *, u_char *, int, u_char **, u_char **) + __THROW; +int dn_expand (const u_char *, const u_char *, const u_char *, + char *, int) __THROW; +u_int res_randomid (void) __THROW; +int res_nameinquery (const char *, int, int, + const u_char *, const u_char *) __THROW; +int res_queriesmatch (const u_char *, const u_char *, + const u_char *, const u_char *) __THROW; +const char * p_section (int __section, int __opcode) __THROW; +/* Things involving a resolver context. */ +int res_ninit (res_state) __THROW; +int res_nisourserver (const res_state, + const struct sockaddr_in *) __THROW; +void fp_resstat (const res_state, FILE *) __THROW; +void res_npquery (const res_state, const u_char *, int, FILE *) + __THROW; +const char * res_hostalias (const res_state, const char *, char *, size_t) + __THROW; +int res_nquery (res_state, const char *, int, int, u_char *, int) + __THROW; +int res_nsearch (res_state, const char *, int, int, u_char *, int) + __THROW; +int res_nquerydomain (res_state, const char *, const char *, int, + int, u_char *, int) __THROW; +int res_nmkquery (res_state, int, const char *, int, int, + const u_char *, int, const u_char *, u_char *, + int) __THROW; +int res_nsend (res_state, const u_char *, int, u_char *, int) + __THROW; +void res_nclose (res_state) __THROW; +__END_DECLS +#endif + +#endif /* !_RESOLV_H_ */ diff --git a/system/include/netdb.h b/system/include/netdb.h new file mode 100644 index 00000000..20f876df --- /dev/null +++ b/system/include/netdb.h @@ -0,0 +1,55 @@ +#ifndef _NETDB_H +#define _NETDB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define HOST_NOT_FOUND 1 +#define TRY_AGAIN 2 +#define NO_RECOVERY 3 +#define NO_DATA 4 + +#define IP_TOS 1 +#define IP_TTL 2 +#define IP_HDRINCL 3 +#define IP_OPTIONS 4 +#define IP_ROUTER_ALERT 5 +#define IP_RECVOPTS 6 +#define IP_RETOPTS 7 +#define IP_PKTINFO 8 +#define IP_PKTOPTIONS 9 +#define IP_MTU_DISCOVER 10 +#define IP_RECVERR 11 +#define IP_RECVTTL 12 +#define IP_RECVTOS 13 +#define IP_MTU 14 +#define IP_FREEBIND 15 +#define IP_IPSEC_POLICY 16 +#define IP_XFRM_POLICY 17 +#define IP_PASSSEC 18 +#define IP_TRANSPARENT 19 + +typedef int socklen_t; + +struct hostent { + char* h_name; + char** h_aliases; + int h_addrtype; + int h_length; + char** h_addr_list; +}; +#define h_addr h_addr_list[0] + +struct hostent* gethostbyaddr(const void* addr, socklen_t len, int type); +struct hostent* gethostbyname(const char* name); +void sethostent(int stayopen); +void endhostent(void); +void herror(const char* s); +const char* hstrerror(int err); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/system/include/pty.h b/system/include/pty.h new file mode 100644 index 00000000..0ad5b6d5 --- /dev/null +++ b/system/include/pty.h @@ -0,0 +1,6 @@ + +#include <sys/termios.h> + +int openpty(int *amaster, int *aslave, char *name, struct termios *termp, struct winsize *winp); +int forkpty(int *amaster, char *name, struct termios *termp, struct winsize *winp); + diff --git a/system/include/sys/bitypes.h b/system/include/sys/bitypes.h new file mode 100644 index 00000000..88c62c0b --- /dev/null +++ b/system/include/sys/bitypes.h @@ -0,0 +1,3 @@ + +#include <sys/types.h> + diff --git a/system/include/sys/ioctl.h b/system/include/sys/ioctl.h new file mode 100644 index 00000000..b7ade699 --- /dev/null +++ b/system/include/sys/ioctl.h @@ -0,0 +1,20 @@ +#ifndef _IOCTL_H +#define _IOCTL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define SIOCGIFCONF 1 // bogus value +#define SIOCGIFNETMASK 2 // bogus value + +int ioctl(int d, int request, ...); + +#define SO_RCVTIMEO 1000 +#define SO_SNDTIMEO 2000 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/system/include/sys/socket.h b/system/include/sys/socket.h index 2c23ddb7..33c10932 100644 --- a/system/include/sys/socket.h +++ b/system/include/sys/socket.h @@ -1,10 +1,14 @@ #ifndef _SYS_SOCKET_H #define _SYS_SOCKET_H +#include <netdb.h> +#include <sys/select.h> + #ifdef __cplusplus extern "C" { #endif +// Note that the values of these constants are mostly arbitrary numbers. #define SOMAXCONN 128 #define PF_INET 2 #define SO_BROADCAST 6 @@ -17,8 +21,10 @@ extern "C" { #define SO_REUSEADDR 30 #define SO_SNDBUF 40 #define SO_RCVBUF 60 +#define SO_LINGER 70 +#define SO_NOSIGPIPE 80 -typedef int socklen_t; +#define SHUT_RDWR 1 typedef unsigned int sa_family_t; #define AF_INET 1 @@ -41,6 +47,7 @@ int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen); int listen(int sockfd, int backlog); int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen); +int shutdown(int sockfd, int how); int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); ssize_t recv(int s, void *buf, size_t len, int flags); ssize_t send(int s, const void *buf, size_t len, int flags); diff --git a/tests/browser_harness.html b/tests/browser_harness.html new file mode 100644 index 00000000..86f3749f --- /dev/null +++ b/tests/browser_harness.html @@ -0,0 +1,29 @@ +<html> +<head> + <title>Emscripten Browser Test Harness</title> +</head> +<body> +<h2><b>Running tests...</b></h2> +<div id="output"></div> +<script> + var counter = 0; + function check() { + var request = new XMLHttpRequest(); + request.open('GET', '/check', false); + try { + request.send(null); + if (request.responseText != 'False') { + window.open(request.responseText); + document.getElementById('output').innerHTML += 'opened test window ' + (counter++) + '..<br>'; + } + setTimeout(check, 333); + } catch(e) { + document.write('Tests complete. View log in console.'); + return; + } + } + check(); +</script> +</body> +</html> + diff --git a/tests/cases/aliasbitcastdollar.ll b/tests/cases/aliasbitcastdollar.ll new file mode 100644 index 00000000..1ecf6047 --- /dev/null +++ b/tests/cases/aliasbitcastdollar.ll @@ -0,0 +1,27 @@ +; ModuleID = '/tmp/emscripten/tmp/src.cpp.o' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" +target triple = "i386-pc-linux-gnu" + +@.str = private constant [14 x i8] c"hello, world!\00", align 1 ; [#uses=1] + +@"other$name" = alias bitcast (void ()* @original to void (i32)*) ; [#uses=1] + +; [#uses=2] +define void @original() { +entry: + %0 = call i32 bitcast (i32 (i8*)* @puts to i32 (i32*)*)(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ; [#uses=0] + br label %return + +return: ; preds = %entry + ret void +} + +; [#uses=1] +declare i32 @puts(i8*) + +; [#uses=0] +define i32 @main() { +entry: + call void @"other$name"(i32 5) + ret i32 0 +} diff --git a/tests/cases/complexphi.ll b/tests/cases/complexphi.ll index 6f64af06..fcb7185f 100644 --- a/tests/cases/complexphi.ll +++ b/tests/cases/complexphi.ll @@ -3,6 +3,7 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3 target triple = "i386-pc-linux-gnu" @.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*] +@_dispatchTable = internal global i64 0 ; [#uses=0] define i32 @main() { @@ -19,6 +20,9 @@ cond.null: cond.end: ; preds = %cond.false, %cond.true %cond = phi { i32, i32 } [ { i32 5, i32 6 }, %entry ], [ zeroinitializer, %cond.null ] ; [#uses=1] store { i32, i32 } %cond, { i32, i32 }* %comp + + store { i32, i32 } { i32 ptrtoint (i64* @_dispatchTable to i32), i32 0 }, { i32, i32 }* getelementptr inbounds ([1 x i64]* @_dispatchTable, i32 0, i32 0, i32 1), align 4 + ret i32 0 ; [debug line = 6:13] } diff --git a/tests/cases/emptystruct.ll b/tests/cases/emptystruct.ll new file mode 100644 index 00000000..d4165fdd --- /dev/null +++ b/tests/cases/emptystruct.ll @@ -0,0 +1,21 @@ +; ModuleID = 'emptystruct.c' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" +target triple = "i386-pc-linux-gnu" + +%struct.s = type { {}, i32 } + +@.str = private constant [14 x i8] c"hello, world!\00", align 1 ; [#uses=1] + +define i32 @main() nounwind { +entry: + %z = alloca %struct.s, align 4 + %0 = bitcast %struct.s* %z to i8* + call void @llvm.memset.p0i8.i32(i8* %0, i8 0, i32 4, i32 4, i1 false) + %0 = call i32 bitcast (i32 (i8*)* @puts to i32 (i32*)*)(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ; [#uses=0] + ret i32 0 +} + +declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) nounwind + +declare i32 @puts(i8*) + diff --git a/tests/cases/frem.ll b/tests/cases/frem.ll new file mode 100644 index 00000000..442cd04c --- /dev/null +++ b/tests/cases/frem.ll @@ -0,0 +1,13 @@ +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" +target triple = "i386-pc-linux-gnu" + +@.str2 = private constant [6 x i8] c"*%f*\0A\00", align 1 ; [#uses=1] + +declare i32 @printf(i8* noalias, ...) nounwind + +define i32 @main() { +entry: + %c = frem double 2.5, 1.0 + %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([6 x i8]* @.str2, i32 0, i32 0), double %c) + ret i32 0 +} diff --git a/tests/cases/frem.txt b/tests/cases/frem.txt new file mode 100644 index 00000000..3a7ecb6a --- /dev/null +++ b/tests/cases/frem.txt @@ -0,0 +1 @@ +*0.500000* diff --git a/tests/cases/quotedlabel.ll b/tests/cases/quotedlabel.ll new file mode 100644 index 00000000..d32e380a --- /dev/null +++ b/tests/cases/quotedlabel.ll @@ -0,0 +1,19 @@ +; ModuleID = '/tmp/emscripten/tmp/src.cpp.o' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" +target triple = "i386-pc-linux-gnu" + +@.str = private constant [14 x i8] c"hello, world!\00", align 1 ; [#uses=1] + +; [#uses=1] +declare i32 @puts(i8*) + +; [#uses=0] +define i32 @main() { +entry: + br label %"finish$$$" + +"finish$$$": ; preds = %entry + %0 = call i32 bitcast (i32 (i8*)* @puts to i32 (i32*)*)(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ; [#uses=0] + ret i32 0 +} + diff --git a/tests/cases/uadd_overflow.ll b/tests/cases/uadd_overflow.ll new file mode 100644 index 00000000..a808b9de --- /dev/null +++ b/tests/cases/uadd_overflow.ll @@ -0,0 +1,25 @@ +; ModuleID = 'tests/hello_world.bc' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" +target triple = "i386-pc-linux-gnu" + +@.str2 = private constant [9 x i8] c"*%d,%d*\0A\00", align 1 ; [#uses=1] + +; [#uses=0] +define i32 @main() { +entry: + %retval = alloca i32, align 4 ; [#uses=1 type=i32*] + %mul7 = bitcast i32 -259741926 to i32 + %shl10 = shl i32 4014, 16 + %uadd1 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %mul7, i32 %shl10) + %a0 = extractvalue { i32, i1 } %uadd1, 0 + %a1 = extractvalue { i32, i1 } %uadd1, 1 + %a2 = zext i1 %a1 to i32 + call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @.str2, i32 0, i32 0), i32 %a0, i32 %a2) ; [#uses=0] + ret i32 1 +} + +; [#uses=1] +declare i32 @printf(i8*, ...) + +declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone + diff --git a/tests/cases/uadd_overflow.txt b/tests/cases/uadd_overflow.txt new file mode 100644 index 00000000..dcda9240 --- /dev/null +++ b/tests/cases/uadd_overflow.txt @@ -0,0 +1 @@ +*3319578,1* diff --git a/tests/cube2hash/Makefile b/tests/cube2hash/Makefile new file mode 100644 index 00000000..5d0a7a63 --- /dev/null +++ b/tests/cube2hash/Makefile @@ -0,0 +1,14 @@ +all: cube2hash.bc + +cube2hash.bc: cube2crypto.o tiger.o hashstring.o + $(CXX) $^ -o $@ + +hashstring.o: hashstring.cpp + $(CXX) -c $^ -o $@ + +cube2crypto.o: cube2crypto.c cube2crypto.h + $(CC) -c $< -o $@ + +tiger.o: tiger.c tiger.h + $(CC) -c $< -o $@ + diff --git a/tests/cube2hash/cube2crypto.c b/tests/cube2hash/cube2crypto.c new file mode 100644 index 00000000..52613318 --- /dev/null +++ b/tests/cube2hash/cube2crypto.c @@ -0,0 +1,23 @@ +#include <stdlib.h> +#include "util.h" +#include "tiger.h" +#include "cube2crypto.h" + +char *cube2crypto_hashstring(char *string) +{ + char *result = (char *)malloc(49); + union hashval hv; + + tiger_hash((uchar *)string, strlen(string), &hv); + + int i; + for(i = 0; i < sizeof(hv.bytes); i++) + { + uchar c = hv.bytes[i]; + *(result+(i*2)) = "0123456789ABCDEF"[c&0xF]; + *(result+(i*2)+1) = "0123456789ABCDEF"[c>>4]; + } + *(result+(i*2)+2) = '\0'; + + return result; +} diff --git a/tests/cube2hash/cube2crypto.h b/tests/cube2hash/cube2crypto.h new file mode 100644 index 00000000..90bd06a8 --- /dev/null +++ b/tests/cube2hash/cube2crypto.h @@ -0,0 +1,9 @@ +#ifdef __cplusplus +extern "C" { +#endif + +char *cube2crypto_hashstring(char *string); + +#ifdef __cplusplus +} /* closing brace for extern "C" */ +#endif
\ No newline at end of file diff --git a/tests/cube2hash/hashstring.cpp b/tests/cube2hash/hashstring.cpp new file mode 100644 index 00000000..b08d5d5e --- /dev/null +++ b/tests/cube2hash/hashstring.cpp @@ -0,0 +1,28 @@ +#include "cube2crypto.h" +#include <stdlib.h> +#include <stdio.h> + +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +void help() +{ + printf("Usage: hashstring <seed>\n"); +} + +int main(int argc, char **argv) +{ + if(argc != 2 || !argv[1]) + { + help(); + return EXIT_FAILURE; + } + + char *answer = cube2crypto_hashstring(argv[1]); + + printf("hash value: %s\n", answer); + + free(answer); + + return EXIT_SUCCESS; +} diff --git a/tests/cube2hash/readme.txt b/tests/cube2hash/readme.txt new file mode 100644 index 00000000..6eb129c2 --- /dev/null +++ b/tests/cube2hash/readme.txt @@ -0,0 +1,27 @@ +This directory contains zlib code (c) the Cube 2/Sauerbraten project. +http://sauerbraten.org/ + +LICENSE +======= + +Sauerbraten game engine source code, any release. + +Copyright (C) 2001-2009 Wouter van Oortmerssen, Lee Salzman, Mike Dysart, Robert Pointon, and Quinton Reeves + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + + diff --git a/tests/cube2hash/tiger.c b/tests/cube2hash/tiger.c new file mode 100644 index 00000000..f8707248 --- /dev/null +++ b/tests/cube2hash/tiger.c @@ -0,0 +1,175 @@ +///////////////////////// cryptography ///////////////////////////////// + +/* Based off the reference implementation of Tiger, a cryptographically + * secure 192 bit hash function by Ross Anderson and Eli Biham. More info at: + * http://www.cs.technion.ac.il/~biham/Reports/Tiger/ + */ + +#define TIGER_PASSES 3 + +#include "tiger.h" +#include "util.h" + +chunk sboxes[4*256]; + +#define sb1 (sboxes) +#define sb2 (sboxes+256) +#define sb3 (sboxes+256*2) +#define sb4 (sboxes+256*3) + +#define round(a, b, c, x) \ + c ^= x; \ + a -= sb1[((c)>>(0*8))&0xFF] ^ sb2[((c)>>(2*8))&0xFF] ^ \ + sb3[((c)>>(4*8))&0xFF] ^ sb4[((c)>>(6*8))&0xFF] ; \ + b += sb4[((c)>>(1*8))&0xFF] ^ sb3[((c)>>(3*8))&0xFF] ^ \ + sb2[((c)>>(5*8))&0xFF] ^ sb1[((c)>>(7*8))&0xFF] ; \ + b *= mul; + +void tiger_compress(const chunk *str, chunk state[3]) +{ + chunk a, b, c; + chunk aa, bb, cc; + chunk x0, x1, x2, x3, x4, x5, x6, x7; + + a = state[0]; + b = state[1]; + c = state[2]; + + x0=str[0]; x1=str[1]; x2=str[2]; x3=str[3]; + x4=str[4]; x5=str[5]; x6=str[6]; x7=str[7]; + + aa = a; + bb = b; + cc = c; + + int pass; + + for(pass = 0; pass < TIGER_PASSES; pass++) + { + if(pass) + { + x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5ULL; x1 ^= x0; x2 += x1; x3 -= x2 ^ ((~x1)<<19); + x4 ^= x3; x5 += x4; x6 -= x5 ^ ((~x4)>>23); x7 ^= x6; + x0 += x7; x1 -= x0 ^ ((~x7)<<19); x2 ^= x1; x3 += x2; + x4 -= x3 ^ ((~x2)>>23); x5 ^= x4; x6 += x5; x7 -= x6 ^ 0x0123456789ABCDEFULL; + } + + uint mul = !pass ? 5 : (pass==1 ? 7 : 9); + round(a, b, c, x0) round(b, c, a, x1) round(c, a, b, x2) round(a, b, c, x3) + round(b, c, a, x4) round(c, a, b, x5) round(a, b, c, x6) round(b, c, a, x7) + + chunk tmp = a; a = c; c = b; b = tmp; + + } + + a ^= aa; + b -= bb; + c += cc; + + state[0] = a; + state[1] = b; + state[2] = c; +} + +void tiger_gensboxes() +{ + const char *str = "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham"; + chunk state[3] = { 0x0123456789ABCDEFULL, 0xFEDCBA9876543210ULL, 0xF096A5B4C3B2E187ULL }; + uchar temp[64]; + int i, j, col, sb, pass; + + if(BIGENDIAN) + { + for(j = 0; j < 64; j++) + { + temp[j^7] = str[j]; + } + } + else + { + for(j = 0; j < 64; j++) + { + temp[j] = str[j]; + } + } + + for(i = 0; i < 1024; i++) + { + for(col = 0; col < 8; col++) + { + ((uchar *)&sboxes[i])[col] = i&0xFF; + } + } + + int abc = 2; + for(pass = 0; pass < 5; pass++) + { + for(i = 0; i < 256; i++) + { + for(sb = 0; sb < 1024; sb += 256) + { + abc++; + if(abc >= 3) { abc = 0; tiger_compress((chunk *)temp, state); } + for(col = 0; col < 8; col++) + { + uchar val = ((uchar *)&sboxes[sb+i])[col]; + ((uchar *)&sboxes[sb+i])[col] = ((uchar *)&sboxes[sb + ((uchar *)&state[abc])[col]])[col]; + ((uchar *)&sboxes[sb + ((uchar *)&state[abc])[col]])[col] = val; + } + } + } + } +} + +void tiger_hash(const uchar *str, int length, union hashval *val) +{ + static int init = false; + if(!init) { tiger_gensboxes(); init = true; } + + uchar temp[64]; + + val->chunks[0] = 0x0123456789ABCDEFULL; + val->chunks[1] = 0xFEDCBA9876543210ULL; + val->chunks[2] = 0xF096A5B4C3B2E187ULL; + + int i, j; + for(i = length; i >= 64; i -= 64, str += 64) + { + if(BIGENDIAN) + { + for(j = 0; j < 64; j++) + { + temp[j^7] = str[j]; + } + + tiger_compress((chunk *)temp, val->chunks); + } + else + { + tiger_compress((chunk *)str, val->chunks); + } + } + + if(BIGENDIAN) + { + for(j = 0; j < i; j++) temp[j^7] = str[j]; + temp[j^7] = 0x01; + while(++j&7) temp[j^7] = 0; + } + else + { + for(j = 0; j < i; j++) temp[j] = str[j]; + temp[j] = 0x01; + while(++j&7) temp[j] = 0; + } + + if(j > 56) + { + while(j < 64) temp[j++] = 0; + tiger_compress((chunk *)temp, val->chunks); + j = 0; + } + while(j < 56) temp[j++] = 0; + *(chunk *)(temp+56) = (chunk)length<<3; + tiger_compress((chunk *)temp, val->chunks); +} diff --git a/tests/cube2hash/tiger.h b/tests/cube2hash/tiger.h new file mode 100644 index 00000000..b0d70797 --- /dev/null +++ b/tests/cube2hash/tiger.h @@ -0,0 +1,12 @@ +#ifndef _TIGER_H +#define _TIGER_H + +union hashval +{ + unsigned char bytes[3*8]; + unsigned long long int chunks[3]; +}; + +void tiger_hash(const unsigned char *str, int length, union hashval *val); + +#endif diff --git a/tests/cube2hash/util.h b/tests/cube2hash/util.h new file mode 100644 index 00000000..844b8ed0 --- /dev/null +++ b/tests/cube2hash/util.h @@ -0,0 +1,22 @@ +#ifndef _UTIL_H +#define _UTIL_H + +#include <string.h> +#include <ctype.h> +#include <stdlib.h> +#include <stdio.h> + +#define BIGENDIAN 0 + +#ifndef bool +#define bool unsigned short int +#define true 1 +#define false 0 +#endif + +typedef unsigned long long int chunk; +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned int uint; + +#endif diff --git a/tests/emscripten_api_browser.cpp b/tests/emscripten_api_browser.cpp new file mode 100644 index 00000000..37ffbdd6 --- /dev/null +++ b/tests/emscripten_api_browser.cpp @@ -0,0 +1,38 @@ +#include<stdio.h> +#include<math.h> +#include<SDL.h> +#include<emscripten.h> +#include<assert.h> + +int last = 0; + +extern "C" { + +void third() { + int now = SDL_GetTicks(); + printf("thard! %d\n", now); + assert(fabs(now - last - 1000) < 500); + int result = 1; + REPORT_RESULT(); +} + +void second() { + int now = SDL_GetTicks(); + printf("sacond! %d\n", now); + assert(fabs(now - last - 500) < 250); + last = now; + emscripten_async_call(third, 1000); +} + +} + +int main() { + SDL_Init(0); + last = SDL_GetTicks(); + printf("frist! %d\n", last); + + emscripten_async_call(second, 500); + + return 1; +} + diff --git a/tests/env/output.txt b/tests/env/output.txt index fa342d48..0ec94064 100644 --- a/tests/env/output.txt +++ b/tests/env/output.txt @@ -2,7 +2,7 @@ List: USER=root PATH=/ PWD=/ -HOME=/ +HOME=/home/emscripten LANG=en_US.UTF-8 _=./this.program diff --git a/tests/filesystem/src.js b/tests/filesystem/src.js index 5fdef564..801b45d6 100644 --- a/tests/filesystem/src.js +++ b/tests/filesystem/src.js @@ -10,18 +10,18 @@ FS.createLink('/abc', 'rootLink', '/', true, true); FS.createLink('/abc', 'relativeLink', '../def', true, true); function explore(path) { - print(path); + Module.print(path); var ret = FS.analyzePath(path); - print(' isRoot: ' + ret.isRoot); - print(' exists: ' + ret.exists); - print(' error: ' + ret.error); - print(' path: ' + ret.path); - print(' name: ' + ret.name); - print(' object.contents: ' + (ret.object && JSON.stringify(Object.keys(ret.object.contents || {})))); - print(' parentExists: ' + ret.parentExists); - print(' parentPath: ' + ret.parentPath); - print(' parentObject.contents: ' + (ret.parentObject && JSON.stringify(Object.keys(ret.parentObject.contents)))); - print(''); + Module.print(' isRoot: ' + ret.isRoot); + Module.print(' exists: ' + ret.exists); + Module.print(' error: ' + ret.error); + Module.print(' path: ' + ret.path); + Module.print(' name: ' + ret.name); + Module.print(' object.contents: ' + (ret.object && JSON.stringify(Object.keys(ret.object.contents || {})))); + Module.print(' parentExists: ' + ret.parentExists); + Module.print(' parentPath: ' + ret.parentPath); + Module.print(' parentObject.contents: ' + (ret.parentObject && JSON.stringify(Object.keys(ret.parentObject.contents)))); + Module.print(''); } FS.currentPath = '/abc'; diff --git a/tests/freetype/main_2.c b/tests/freetype/main_2.c new file mode 100644 index 00000000..85e5609d --- /dev/null +++ b/tests/freetype/main_2.c @@ -0,0 +1,135 @@ +/* example1.c */ +/* */ +/* This small program shows how to print a rotated string with the */ +/* FreeType 2 library. */ + + +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <stdlib.h> + +#include <ft2build.h> +#include FT_FREETYPE_H + +int WIDTH = 0; +int HEIGHT = 0; + +/* origin is the upper left corner */ +unsigned char *image; + + +/* Replace this function with something useful. */ + +void +draw_bitmap( FT_Bitmap* bitmap, + FT_Int x, + FT_Int y) +{ + FT_Int i, j, p, q; + FT_Int x_max = x + bitmap->width; + FT_Int y_max = y + bitmap->rows; + + for ( i = x, p = 0; i < x_max; i++, p++ ) + { + for ( j = y, q = 0; j < y_max; j++, q++ ) + { + if ( i < 0 || j < 0 || + i >= WIDTH || j >= HEIGHT ) + continue; + + image[j*WIDTH + i] |= bitmap->buffer[q * bitmap->width + p]; + } + } +} + + +void +show_image( void ) +{ + int i, j; + int count = 0; + + for ( i = 0; i < HEIGHT; i++ ) + { + for ( j = 0; j < WIDTH; j++ ) + { + if (image[i*WIDTH + j]) count++; + putchar(image[i*WIDTH + j] == 0? ' ' + : image[i*WIDTH + j] < 128 ? '+' + : '*' ); + } + putchar( '\n' ); + } + printf("Non-0s: %d\n", count); +} + + +int +main( int argc, + char** argv ) +{ + FT_Library library; + FT_Face face; + + FT_GlyphSlot slot; + FT_Error error; + + FT_UInt glyphIndex; + + char* filename; + char* text; + + int target_height; + + if ( argc != 6 ) + { + fprintf ( stderr, "usage: %s font sample-text width height angle\n", argv[0] ); + exit( 1 ); + } + + // Only test the character 'w' + text = "w"; + + filename = argv[1]; /* first argument */ + WIDTH = atoi(argv[3]); + HEIGHT = atoi(argv[4]); + target_height = HEIGHT; + + image = (unsigned char*)malloc(WIDTH*HEIGHT); + for (int x = 0; x < WIDTH; x++) + for (int y = 0; y < HEIGHT; y++) + image[y*WIDTH + x] = 0; + + error = FT_Init_FreeType( &library ); /* initialize library */ + if (error) printf("Init Error! %d\n", error); + + error = FT_New_Face( library, argv[1], 0, &face ); /* create face object */ + if (error) printf("New_Face Error! %d\n", error); + + /* use 50pt at 100dpi */ + error = FT_Set_Char_Size( face, 0, 32 * 64, 0, 0 ); /* set character size */ + if (error) printf("Set_Cshar_Size Error! %d\n", error); + + slot = face->glyph; + + glyphIndex = FT_Get_Char_Index(face, text[0]); + + /* load glyph image into the slot (erase previous one) */ + error = FT_Load_Glyph(face, glyphIndex, FT_LOAD_NO_BITMAP); + if(error) printf("FT_Load_Glyph Error! %d\n", error); + + error = FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL); + if(error) printf("FT_Render_Glyph Error! %d\n", error); + + /* now, draw to our target surface (convert position) */ + draw_bitmap(&slot->bitmap, slot->bitmap_left, target_height - slot->bitmap_top); + + show_image(); + + FT_Done_Face(face); + FT_Done_FreeType(library); + return 0; +} + +/* EOF */
\ No newline at end of file diff --git a/tests/freetype/main_3.c b/tests/freetype/main_3.c new file mode 100644 index 00000000..c3941a17 --- /dev/null +++ b/tests/freetype/main_3.c @@ -0,0 +1,184 @@ +/* example1.c */ +/* */ +/* This small program shows how to print a rotated string with the */ +/* FreeType 2 library. */ + + +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <stdlib.h> + +#include <ft2build.h> +#include FT_FREETYPE_H + + +int WIDTH = 0; +int HEIGHT = 0; + +/* origin is the upper left corner */ +unsigned char *image; + +unsigned char pixelData[32 * 32]; + +/* Replace this function with something useful. */ +void +draw_bitmap( FT_Bitmap* bitmap, + FT_Int x, + FT_Int y) +{ + FT_Int i, j, p, q; + FT_Int x_max = x + bitmap->width; + FT_Int y_max = y + bitmap->rows; + int xbyte; + int xbit; + unsigned char* pcur; + + unsigned char* src = bitmap->buffer; + unsigned char* dest = pixelData; + + // Note: FT_RENDER_MONO_MODE render characater's one pixel by a single bit, + // translate the single bit to a single char for displaying image. + for(int _y = 0; _y < bitmap->rows; ++_y) + { + for(int _x = 0; _x < bitmap->width; ++_x) + { + xbyte = _x / 8; + xbit = _x - xbyte * 8; + pcur = dest + _x; + + // test if the pixel bit be set + if(src[xbyte] & (0x80 >> xbit)) + { + *pcur = 0xFF; + } + else + { + *pcur = 0; + } + } + src += bitmap->pitch; + dest += bitmap->width; + } + + // display the character to ref txt file + for ( i = x, p = 0; i < x_max; i++, p++ ) + { + for ( j = y, q = 0; j < y_max; j++, q++ ) + { + if ( i < 0 || j < 0 || + i >= WIDTH || j >= HEIGHT ) + continue; + + image[j*WIDTH + i] |= pixelData[q * bitmap->width + p]; + } + } +} + + +void +show_image( void ) +{ + int i, j; + int count = 0; + + for ( i = 0; i < HEIGHT; i++ ) + { + for ( j = 0; j < WIDTH; j++ ) { + if (image[i*WIDTH + j]) count++; + putchar( image[i*WIDTH + j] == 0 ? ' ' + : image[i*WIDTH + j] < 128 ? '+' + : '*'); + } + putchar('\n'); + } + printf("Non-0s: %d\n", count); +} + + +int +main( int argc, + char** argv ) +{ + FT_Library library; + FT_Face face; + + FT_GlyphSlot slot; + FT_Error error; + FT_Vector pen; /* untransformed origin */ + + char* filename; + char* text; + + double angle; + int target_height; + int n, num_chars; + FT_UInt glyphIndex; + + if ( argc != 6 ) + { + fprintf ( stderr, "usage: %s font sample-text width height angle\n", argv[0] ); + exit( 1 ); + } + + filename = argv[1]; /* first argument */ + text = argv[2]; /* second argument */ + num_chars = strlen( text ); + WIDTH = atoi(argv[3]); + HEIGHT = atoi(argv[4]); + angle = ( ((float)atoi(argv[5])) / 360 ) * 3.14159 * 2; /* use 25 degrees */ + target_height = HEIGHT; + + image = (unsigned char*)malloc(WIDTH*HEIGHT); + for (int x = 0; x < WIDTH; x++) + for (int y = 0; y < HEIGHT; y++) + image[y*WIDTH + x] = 0; + + error = FT_Init_FreeType( &library ); /* initialize library */ + if (error) printf("Init Error! %d\n", error); + + error = FT_New_Face( library, argv[1], 0, &face ); /* create face object */ + if (error) printf("New_Face Error! %d\n", error); + + /* use 50pt at 100dpi */ + error = FT_Set_Char_Size( face, 32 * 64, 0, + 0, 0 ); /* set character size */ + if (error) printf("Set_Char_Size Error! %d\n", error); + + slot = face->glyph; + pen.x = 0; + pen.y = 0; + for ( n = 0; n < num_chars; n++ ) + { + /* set transformation */ + FT_Set_Transform( face, 0, &pen ); + + /* load glyph image into the slot (erase previous one) */ + glyphIndex = FT_Get_Char_Index(face, text[n]); + + /* load glyph image into the slot (erase previous one) */ + error = FT_Load_Glyph(face, glyphIndex, FT_LOAD_DEFAULT); + if(error) printf("FT_Load_Glyph Error! %d\n", error); + + error = FT_Render_Glyph(slot, FT_RENDER_MODE_MONO); + if(error) printf("FT_Render_Glyph Error! %d\n", error); + + /* now, draw to our target surface (convert position) */ + draw_bitmap(&slot->bitmap, + slot->bitmap_left, + target_height - slot->bitmap_top ); + + /* increment pen position */ + pen.x += slot->advance.x; + pen.y += slot->advance.y; + } + + show_image(); + + FT_Done_Face ( face ); + FT_Done_FreeType( library ); + + return 0; +} + +/* EOF */ diff --git a/tests/freetype/ref_2.txt b/tests/freetype/ref_2.txt new file mode 100644 index 00000000..c15bb415 --- /dev/null +++ b/tests/freetype/ref_2.txt @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + +****+ +***** +**** +****+ +*****+ +**** ++**** ******+ ****+ ++**** ******* ****+ ++****+ +***+*** +**** + ****+ +***+***+ +***+ + +***+ **** ***+ ****+ + +**** ***+ +*** ****+ + +**** +***+ +*** +**** + ****++*** +***++***+ + +***+**** ***++***+ + +***+***+ +*******+ + *******+ +******* + ******* +******+ + +*****+ ******+ + +*****+ +***** + *****+ +***** +Non-0s: 285 diff --git a/tests/freetype/ref_3.txt b/tests/freetype/ref_3.txt new file mode 100644 index 00000000..2b121eb7 --- /dev/null +++ b/tests/freetype/ref_3.txt @@ -0,0 +1,33 @@ + + + + + + + + + + +***** ***** **** +***** ****** ***** +***** ******* ***** +***** ******* **** + ***** ******* **** + ***** *** **** ***** + ***** **** **** **** + **** **** **** **** + ***** **** **** **** + ***** **** ***** **** + ***** **** **** **** + **** **** **** **** + **** **** **** **** + ***** *** **** **** + **** **** **** **** + **** **** **** **** + **** **** **** *** + ******* ******** + ******* ******* + ******* ******* + ******* ****** + ***** ***** +Non-0s: 342 diff --git a/tests/freetype/ref_4.txt b/tests/freetype/ref_4.txt new file mode 100644 index 00000000..e8124c1d --- /dev/null +++ b/tests/freetype/ref_4.txt @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + ****** ****** + ********** ********** + ************ ************ + ***** ***** ***** ***** + **** **** **** **** + **** *** **** + **** **** **** + **************** *********** + **************** ************* + **************** ************** + **** ***** **** + **** **** **** + **** **** **** ***** + ***** **** ***** ****** + ************* ********** ***** + *********** ********* ***** + ******* ***** **** +Non-0s: 332 diff --git a/tests/gears.png b/tests/gears.png Binary files differnew file mode 100644 index 00000000..ffb855c4 --- /dev/null +++ b/tests/gears.png diff --git a/tests/gl/LICENSE.TXT b/tests/gl/LICENSE.TXT deleted file mode 100644 index 45e1d8ad..00000000 --- a/tests/gl/LICENSE.TXT +++ /dev/null @@ -1,11 +0,0 @@ -THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION -AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN. - -THE ORIGINAL AUTHOR IS KYLE FOLEY. - -THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY -OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF -MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, -ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE -RESULTING FROM THE USE, MODIFICATION, OR -REDISTRIBUTION OF THIS SOFTWARE. diff --git a/tests/gl/sdl_ogl.c b/tests/gl/sdl_ogl.c deleted file mode 100644 index 6f81c7ff..00000000 --- a/tests/gl/sdl_ogl.c +++ /dev/null @@ -1,202 +0,0 @@ -/******************************************************************* - * * - * Using SDL With OpenGL * - * * - * Tutorial by Kyle Foley (sdw) * - * * - * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL * - * * - *******************************************************************/ - -/* - Combined with opengl.org tutorial #2, - http://www.opengl.org/wiki/Tutorial2:_VAOs,_VBOs,_Vertex_and_Fragment_Shaders_%28C_/_SDL%29 - - Build with - - gcc sdl_ogl.c -lSDL -lGL - - g++ will fail! - - Or, to JS: - - ~/Dev/emscripten/tools/emmaken.py sdl_ogl.c -o sdl_ogl.o - ~/Dev/emscripten/emscripten.py sdl_ogl.o > sdl_ogl.js -*/ - -#include "SDL/SDL.h" -#include "SDL/SDL_opengl.h" - -#include <stdio.h> -#include <stdlib.h> - -char* filetobuf(char *file) -{ - FILE *fptr; - long length; - char *buf; - - fptr = fopen(file, "r"); /* Open file for reading */ - if (!fptr) /* Return NULL on failure */ - return NULL; - fseek(fptr, 0, SEEK_END); /* Seek to the end of the file */ - length = ftell(fptr); /* Find out how many bytes into the file we are */ - buf = (char*)malloc(length+1); /* Allocate a buffer for the entire length of the file and a null terminator */ - fseek(fptr, 0, SEEK_SET); /* Go back to the beginning of the file */ - fread(buf, length, 1, fptr); /* Read the contents of the file in to the buffer */ - fclose(fptr); /* Close the file */ - buf[length] = 0; /* Null terminator */ - - return buf; /* Return the buffer */ -} - -void drawscene() -{ - int i; /* Simple iterator */ - GLuint vao, vbo[2]; /* Create handles for our Vertex Array Object and two Vertex Buffer Objects */ - - /* We're going to create a simple diamond made from lines */ - const GLfloat diamond[4][2] = { - { 0.0, 1.0 }, /* Top point */ - { 1.0, 0.0 }, /* Right point */ - { 0.0, -1.0 }, /* Bottom point */ - { -1.0, 0.0 } }; /* Left point */ - - const GLfloat colors[4][3] = { - { 1.0, 0.0, 0.0 }, /* Red */ - { 0.0, 1.0, 0.0 }, /* Green */ - { 0.0, 0.0, 1.0 }, /* Blue */ - { 1.0, 1.0, 1.0 } }; /* White */ - - /* These pointers will receive the contents of our shader source code files */ - GLchar *vertexsource, *fragmentsource; - - /* These are handles used to reference the shaders */ - GLuint vertexshader, fragmentshader; - - /* This is a handle to the shader program */ - GLuint shaderprogram; - - /* Allocate and assign a Vertex Array Object to our handle */ - glGenVertexArrays(1, &vao); - - /* Bind our Vertex Array Object as the current used object */ - glBindVertexArray(vao); - - /* Allocate and assign two Vertex Buffer Objects to our handle */ - glGenBuffers(2, vbo); - - /* Bind our first VBO as being the active buffer and storing vertex attributes (coordinates) */ - glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); - - /* Copy the vertex data from diamond to our buffer */ - /* 8 * sizeof(GLfloat) is the size of the diamond array, since it contains 8 GLfloat values */ - glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), diamond, GL_STATIC_DRAW); - - /* Specify that our coordinate data is going into attribute index 0, and contains two floats per vertex */ - glVertexAttribPointer((GLuint)0, 2, GL_FLOAT, GL_FALSE, 0, 0); - - /* Enable attribute index 0 as being used */ - glEnableVertexAttribArray(0); - - /* Bind our second VBO as being the active buffer and storing vertex attributes (colors) */ - glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); - - /* Copy the color data from colors to our buffer */ - /* 12 * sizeof(GLfloat) is the size of the colors array, since it contains 12 GLfloat values */ - glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), colors, GL_STATIC_DRAW); - - /* Specify that our color data is going into attribute index 1, and contains three floats per vertex */ - glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0); - - /* Enable attribute index 1 as being used */ - glEnableVertexAttribArray(1); - - /* Read our shaders into the appropriate buffers */ - vertexsource = filetobuf("tutorial2.vert"); - fragmentsource = filetobuf("tutorial2.frag"); - - /* Assign our handles a "name" to new shader objects */ - vertexshader = glCreateShader(GL_VERTEX_SHADER); - fragmentshader = glCreateShader(GL_FRAGMENT_SHADER); - - /* Associate the source code buffers with each handle */ - glShaderSource(vertexshader, 1, (const GLchar**)&vertexsource, 0); - glShaderSource(fragmentshader, 1, (const GLchar**)&fragmentsource, 0); - - /* Compile our shader objects */ - glCompileShader(vertexshader); - glCompileShader(fragmentshader); - - /* Assign our program handle a "name" */ - shaderprogram = glCreateProgram(); - - /* Attach our shaders to our program */ - glAttachShader(shaderprogram, vertexshader); - glAttachShader(shaderprogram, fragmentshader); - - /* Bind attribute index 0 (coordinates) to in_Position and attribute index 1 (color) to in_Color */ - glBindAttribLocation(shaderprogram, 0, "in_Position"); - glBindAttribLocation(shaderprogram, 1, "in_Color"); - - /* Link our program, and set it as being actively used */ - glLinkProgram(shaderprogram); - glUseProgram(shaderprogram); - - /* Loop our display increasing the number of shown vertexes each time. - * Start with 2 vertexes (a line) and increase to 3 (a triangle) and 4 (a diamond) */ - for (i=4; i <= 4; i++) - { - /* Make our background black */ - glClearColor(0.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - - /* Invoke glDrawArrays telling that our data is a line loop and we want to draw 2-4 vertexes */ - glDrawArrays(GL_LINE_LOOP, 0, i); - - /* Swap our buffers to make our changes visible */ - SDL_GL_SwapBuffers(); - - /* Sleep for 2 seconds */ - SDL_Delay(2000); - } - - /* Cleanup all the things we bound and allocated */ - glUseProgram(0); - glDisableVertexAttribArray(0); - glDisableVertexAttribArray(1); - glDetachShader(shaderprogram, vertexshader); - glDetachShader(shaderprogram, fragmentshader); - glDeleteProgram(shaderprogram); - glDeleteShader(vertexshader); - glDeleteShader(fragmentshader); - glDeleteBuffers(2, vbo); - glDeleteVertexArrays(1, &vao); - free(vertexsource); - free(fragmentsource); -} - -int main(int argc, char *argv[]) -{ - SDL_Surface *screen; - - // Slightly different SDL initialization - if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) { - printf("Unable to initialize SDL: %s\n", SDL_GetError()); - return 1; - } - - SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new* - - screen = SDL_SetVideoMode( 512, 384, 32, SDL_OPENGL); // *changed* - if ( !screen ) { - printf("Unable to set video mode: %s\n", SDL_GetError()); - return 1; - } - - drawscene(); - - SDL_Quit(); - - return 0; -} diff --git a/tests/gl/tutorial2.frag b/tests/gl/tutorial2.frag deleted file mode 100644 index faa30eaf..00000000 --- a/tests/gl/tutorial2.frag +++ /dev/null @@ -1,11 +0,0 @@ -#version 150 -// It was expressed that some drivers required this next line to function properly -precision highp float; - -in vec3 ex_Color; -out vec4 gl_FragColor; - -void main(void) { - // Pass through our original color with full opacity. - gl_FragColor = vec4(ex_Color,1.0); -} diff --git a/tests/gl/tutorial2.vert b/tests/gl/tutorial2.vert deleted file mode 100644 index d9de08e3..00000000 --- a/tests/gl/tutorial2.vert +++ /dev/null @@ -1,19 +0,0 @@ -#version 150 -// in_Position was bound to attribute index 0 and in_Color was bound to attribute index 1 -in vec2 in_Position; -in vec3 in_Color; - -// We output the ex_Color variable to the next shader in the chain -out vec3 ex_Color; -void main(void) { - // Since we are using flat lines, our input only had two points: x and y. - // Set the Z coordinate to 0 and W coordinate to 1 - - gl_Position = vec4(in_Position.x, in_Position.y, 0.0, 1.0); - - // GLSL allows shorthand use of vectors too, the following is also valid: - // gl_Position = vec4(in_Position, 0.0, 1.0); - // We're simply passing the color through unmodified - - ex_Color = in_Color; -} diff --git a/tests/glbook/CH02_HelloTriangle.png b/tests/glbook/CH02_HelloTriangle.png Binary files differnew file mode 100644 index 00000000..d6351e2a --- /dev/null +++ b/tests/glbook/CH02_HelloTriangle.png diff --git a/tests/glbook/CH08_SimpleVertexShader.png b/tests/glbook/CH08_SimpleVertexShader.png Binary files differnew file mode 100644 index 00000000..84b276fd --- /dev/null +++ b/tests/glbook/CH08_SimpleVertexShader.png diff --git a/tests/glbook/CH09_SimpleTexture2D.png b/tests/glbook/CH09_SimpleTexture2D.png Binary files differnew file mode 100644 index 00000000..e33539e9 --- /dev/null +++ b/tests/glbook/CH09_SimpleTexture2D.png diff --git a/tests/glbook/CH09_TextureCubemap.png b/tests/glbook/CH09_TextureCubemap.png Binary files differnew file mode 100644 index 00000000..b592b047 --- /dev/null +++ b/tests/glbook/CH09_TextureCubemap.png diff --git a/tests/glbook/CH09_TextureWrap.png b/tests/glbook/CH09_TextureWrap.png Binary files differnew file mode 100644 index 00000000..3367e254 --- /dev/null +++ b/tests/glbook/CH09_TextureWrap.png diff --git a/tests/glbook/CH10_MultiTexture.png b/tests/glbook/CH10_MultiTexture.png Binary files differnew file mode 100644 index 00000000..8e006eb3 --- /dev/null +++ b/tests/glbook/CH10_MultiTexture.png diff --git a/tests/glbook/CH13_ParticleSystem.png b/tests/glbook/CH13_ParticleSystem.png Binary files differnew file mode 100644 index 00000000..39b9af0a --- /dev/null +++ b/tests/glbook/CH13_ParticleSystem.png diff --git a/tests/glbook/Chapter_10/MultiTexture/MultiTexture.c b/tests/glbook/Chapter_10/MultiTexture/MultiTexture.c new file mode 100644 index 00000000..61bda608 --- /dev/null +++ b/tests/glbook/Chapter_10/MultiTexture/MultiTexture.c @@ -0,0 +1,227 @@ +//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// MultiTexture.c
+//
+// This is an example that draws a quad with a basemap and
+// lightmap to demonstrate multitexturing.
+//
+#include <stdlib.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint positionLoc;
+ GLint texCoordLoc;
+
+ // Sampler locations
+ GLint baseMapLoc;
+ GLint lightMapLoc;
+
+ // Texture handle
+ GLuint baseMapTexId;
+ GLuint lightMapTexId;
+
+ GLuint vertexObject, indexObject;
+
+} UserData;
+
+
+///
+// Load texture from disk
+//
+GLuint LoadTexture ( char *fileName )
+{
+ int width,
+ height;
+ char *buffer = esLoadTGA ( fileName, &width, &height );
+ GLuint texId;
+
+ if ( buffer == NULL )
+ {
+ esLogMessage ( "Error loading (%s) image.\n", fileName );
+ return 0;
+ }
+
+ glGenTextures ( 1, &texId );
+ glBindTexture ( GL_TEXTURE_2D, texId );
+
+ glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+
+ free ( buffer );
+
+ return texId;
+}
+
+
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = a_position; \n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_baseMap; \n"
+ "uniform sampler2D s_lightMap; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 baseColor; \n"
+ " vec4 lightColor; \n"
+ " \n"
+ " baseColor = texture2D( s_baseMap, v_texCoord ); \n"
+ " lightColor = texture2D( s_lightMap, v_texCoord ); \n"
+ " gl_FragColor = baseColor * (lightColor + 0.25); \n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
+ userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
+
+ // Get the sampler location
+ userData->baseMapLoc = glGetUniformLocation ( userData->programObject, "s_baseMap" );
+ userData->lightMapLoc = glGetUniformLocation ( userData->programObject, "s_lightMap" );
+
+ // Load the textures
+ userData->baseMapTexId = LoadTexture ( "basemap.tga" );
+ userData->lightMapTexId = LoadTexture ( "lightmap.tga" );
+
+ if ( userData->baseMapTexId == 0 || userData->lightMapTexId == 0 )
+ return FALSE;
+
+ GLfloat vVertices[] = { -0.5, 0.5, 0.0, // Position 0
+ 0.0, 0.0, // TexCoord 0
+ -0.5, -0.5, 0.0, // Position 1
+ 0.0, 1.0, // TexCoord 1
+ 0.5, -0.5, 0.0, // Position 2
+ 1.0, 1.0, // TexCoord 2
+ 0.5, 0.5, 0.0, // Position 3
+ 1.0, 0.0 // TexCoord 3
+ };
+ GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
+
+ glGenBuffers(1, &userData->vertexObject);
+ glBindBuffer ( GL_ARRAY_BUFFER, userData->vertexObject );
+ glBufferData ( GL_ARRAY_BUFFER, 5 * 4 * 4, vVertices, GL_STATIC_DRAW );
+
+ glGenBuffers(1, &userData->indexObject);
+ glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->indexObject );
+ glBufferData ( GL_ELEMENT_ARRAY_BUFFER, 6 * 2, indices, GL_STATIC_DRAW );
+
+ glClearColor ( 0.0, 0.0, 0.0, 1.0 );
+
+ return TRUE;
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex position
+ glBindBuffer ( GL_ARRAY_BUFFER, userData->vertexObject );
+ glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
+ GL_FALSE, 5 * sizeof(GLfloat), 0 );
+ // Load the texture coordinate
+ glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
+ GL_FALSE, 5 * sizeof(GLfloat), 3 * sizeof(GLfloat) );
+
+ glEnableVertexAttribArray ( userData->positionLoc );
+ glEnableVertexAttribArray ( userData->texCoordLoc );
+
+ // Bind the base map
+ glActiveTexture ( GL_TEXTURE0 );
+ glBindTexture ( GL_TEXTURE_2D, userData->baseMapTexId );
+
+ // Set the base map sampler to texture unit to 0
+ glUniform1i ( userData->baseMapLoc, 0 );
+
+ // Bind the light map
+ glActiveTexture ( GL_TEXTURE1 );
+ glBindTexture ( GL_TEXTURE_2D, userData->lightMapTexId );
+
+ // Set the light map sampler to texture unit 1
+ glUniform1i ( userData->lightMapLoc, 1 );
+
+ glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->indexObject );
+ glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 );
+
+ eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete texture object
+ glDeleteTextures ( 1, &userData->baseMapTexId );
+ glDeleteTextures ( 1, &userData->lightMapTexId );
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+}
+
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "MultiTexture", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_10/MultiTexture/MultiTexture_orig.c b/tests/glbook/Chapter_10/MultiTexture/MultiTexture_orig.c new file mode 100644 index 00000000..5324ad92 --- /dev/null +++ b/tests/glbook/Chapter_10/MultiTexture/MultiTexture_orig.c @@ -0,0 +1,213 @@ +//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// MultiTexture.c
+//
+// This is an example that draws a quad with a basemap and
+// lightmap to demonstrate multitexturing.
+//
+#include <stdlib.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint positionLoc;
+ GLint texCoordLoc;
+
+ // Sampler locations
+ GLint baseMapLoc;
+ GLint lightMapLoc;
+
+ // Texture handle
+ GLuint baseMapTexId;
+ GLuint lightMapTexId;
+
+} UserData;
+
+
+///
+// Load texture from disk
+//
+GLuint LoadTexture ( char *fileName )
+{
+ int width,
+ height;
+ char *buffer = esLoadTGA ( fileName, &width, &height );
+ GLuint texId;
+
+ if ( buffer == NULL )
+ {
+ esLogMessage ( "Error loading (%s) image.\n", fileName );
+ return 0;
+ }
+
+ glGenTextures ( 1, &texId );
+ glBindTexture ( GL_TEXTURE_2D, texId );
+
+ glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+
+ free ( buffer );
+
+ return texId;
+}
+
+
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = a_position; \n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_baseMap; \n"
+ "uniform sampler2D s_lightMap; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 baseColor; \n"
+ " vec4 lightColor; \n"
+ " \n"
+ " baseColor = texture2D( s_baseMap, v_texCoord ); \n"
+ " lightColor = texture2D( s_lightMap, v_texCoord ); \n"
+ " gl_FragColor = baseColor * (lightColor + 0.25); \n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
+ userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
+
+ // Get the sampler location
+ userData->baseMapLoc = glGetUniformLocation ( userData->programObject, "s_baseMap" );
+ userData->lightMapLoc = glGetUniformLocation ( userData->programObject, "s_lightMap" );
+
+ // Load the textures
+ userData->baseMapTexId = LoadTexture ( "basemap.tga" );
+ userData->lightMapTexId = LoadTexture ( "lightmap.tga" );
+
+ if ( userData->baseMapTexId == 0 || userData->lightMapTexId == 0 )
+ return FALSE;
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+ return TRUE;
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ GLfloat vVertices[] = { -0.5f, 0.5f, 0.0f, // Position 0
+ 0.0f, 0.0f, // TexCoord 0
+ -0.5f, -0.5f, 0.0f, // Position 1
+ 0.0f, 1.0f, // TexCoord 1
+ 0.5f, -0.5f, 0.0f, // Position 2
+ 1.0f, 1.0f, // TexCoord 2
+ 0.5f, 0.5f, 0.0f, // Position 3
+ 1.0f, 0.0f // TexCoord 3
+ };
+ GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex position
+ glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
+ GL_FALSE, 5 * sizeof(GLfloat), vVertices );
+ // Load the texture coordinate
+ glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
+ GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] );
+
+ glEnableVertexAttribArray ( userData->positionLoc );
+ glEnableVertexAttribArray ( userData->texCoordLoc );
+
+ // Bind the base map
+ glActiveTexture ( GL_TEXTURE0 );
+ glBindTexture ( GL_TEXTURE_2D, userData->baseMapTexId );
+
+ // Set the base map sampler to texture unit to 0
+ glUniform1i ( userData->baseMapLoc, 0 );
+
+ // Bind the light map
+ glActiveTexture ( GL_TEXTURE1 );
+ glBindTexture ( GL_TEXTURE_2D, userData->lightMapTexId );
+
+ // Set the light map sampler to texture unit 1
+ glUniform1i ( userData->lightMapLoc, 1 );
+
+ glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
+
+ eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete texture object
+ glDeleteTextures ( 1, &userData->baseMapTexId );
+ glDeleteTextures ( 1, &userData->lightMapTexId );
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+}
+
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "MultiTexture", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_10/MultiTexture/basemap.tga b/tests/glbook/Chapter_10/MultiTexture/basemap.tga Binary files differnew file mode 100644 index 00000000..8acafae2 --- /dev/null +++ b/tests/glbook/Chapter_10/MultiTexture/basemap.tga diff --git a/tests/glbook/Chapter_10/MultiTexture/lightmap.tga b/tests/glbook/Chapter_10/MultiTexture/lightmap.tga Binary files differnew file mode 100644 index 00000000..d95b2628 --- /dev/null +++ b/tests/glbook/Chapter_10/MultiTexture/lightmap.tga diff --git a/tests/glbook/Chapter_11/Multisample/Multisample.c b/tests/glbook/Chapter_11/Multisample/Multisample.c new file mode 100644 index 00000000..fd064c70 --- /dev/null +++ b/tests/glbook/Chapter_11/Multisample/Multisample.c @@ -0,0 +1,302 @@ +//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// Multisample.c
+//
+// This example shows various multi-sampling
+// operations.
+//
+#include <stdlib.h>
+#include <stdio.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint positionLoc;
+
+ // Uniform locations
+ GLint colorLoc;
+
+} UserData;
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "attribute vec4 a_position; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = a_position; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "uniform vec4 u_color; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = u_color; \n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
+
+ // Get the sampler location
+ userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" );
+
+ // Set the clear color
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+
+ // Set the stencil clear value
+ glClearStencil ( 0x1 );
+
+ // Set the depth clear value
+ glClearDepthf( 0.75f );
+
+ // Enable the depth and stencil tests
+ glEnable( GL_DEPTH_TEST );
+ glEnable( GL_STENCIL_TEST );
+
+ return TRUE;
+}
+
+///
+// Initialize the stencil buffer values, and then use those
+// values to control rendering
+//
+void Draw ( ESContext *esContext )
+{
+ int i;
+
+ UserData *userData = esContext->userData;
+
+ GLfloat vVertices[] = {
+ -0.75f, 0.25f, 0.50f, // Quad #0
+ -0.25f, 0.25f, 0.50f,
+ -0.25f, 0.75f, 0.50f,
+ -0.75f, 0.75f, 0.50f,
+ 0.25f, 0.25f, 0.90f, // Quad #1
+ 0.75f, 0.25f, 0.90f,
+ 0.75f, 0.75f, 0.90f,
+ 0.25f, 0.75f, 0.90f,
+ -0.75f, -0.75f, 0.50f, // Quad #2
+ -0.25f, -0.75f, 0.50f,
+ -0.25f, -0.25f, 0.50f,
+ -0.75f, -0.25f, 0.50f,
+ 0.25f, -0.75f, 0.50f, // Quad #3
+ 0.75f, -0.75f, 0.50f,
+ 0.75f, -0.25f, 0.50f,
+ 0.25f, -0.25f, 0.50f,
+ -1.00f, -1.00f, 0.00f, // Big Quad
+ 1.00f, -1.00f, 0.00f,
+ 1.00f, 1.00f, 0.00f,
+ -1.00f, 1.00f, 0.00f
+ };
+
+ GLubyte indices[][6] = {
+ { 0, 1, 2, 0, 2, 3 }, // Quad #0
+ { 4, 5, 6, 4, 6, 7 }, // Quad #1
+ { 8, 9, 10, 8, 10, 11 }, // Quad #2
+ { 12, 13, 14, 12, 14, 15 }, // Quad #3
+ { 16, 17, 18, 16, 18, 19 } // Big Quad
+ };
+
+#define NumTests 4
+ GLfloat colors[NumTests][4] = {
+ { 1.0f, 0.0f, 0.0f, 1.0f },
+ { 0.0f, 1.0f, 0.0f, 1.0f },
+ { 0.0f, 0.0f, 1.0f, 1.0f },
+ { 1.0f, 1.0f, 0.0f, 0.0f }
+ };
+
+ GLint numStencilBits;
+ GLuint stencilValues[NumTests] = {
+ 0x7, // Result of test 0
+ 0x0, // Result of test 1
+ 0x2, // Result of test 2
+ 0xff // Result of test 3. We need to fill this
+ // value in a run-time
+ };
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color, depth, and stencil buffers. At this
+ // point, the stencil buffer will be 0x1 for all pixels
+ glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex position
+ glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
+ GL_FALSE, 0, vVertices );
+
+ glEnableVertexAttribArray ( userData->positionLoc );
+
+ // Test 0:
+ //
+ // Initialize upper-left region. In this case, the
+ // stencil-buffer values will be replaced because the
+ // stencil test for the rendered pixels will fail the
+ // stencil test, which is
+ //
+ // ref mask stencil mask
+ // ( 0x7 & 0x3 ) < ( 0x1 & 0x7 )
+ //
+ // The value in the stencil buffer for these pixels will
+ // be 0x7.
+ //
+ glStencilFunc( GL_LESS, 0x7, 0x3 );
+ glStencilOp( GL_REPLACE, GL_DECR, GL_DECR );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[0] );
+
+ // Test 1:
+ //
+ // Initialize the upper-right region. Here, we'll decrement
+ // the stencil-buffer values where the stencil test passes
+ // but the depth test fails. The stencil test is
+ //
+ // ref mask stencil mask
+ // ( 0x3 & 0x3 ) > ( 0x1 & 0x3 )
+ //
+ // but where the geometry fails the depth test. The
+ // stencil values for these pixels will be 0x0.
+ //
+ glStencilFunc( GL_GREATER, 0x3, 0x3 );
+ glStencilOp( GL_KEEP, GL_DECR, GL_KEEP );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[1] );
+
+ // Test 2:
+ //
+ // Initialize the lower-left region. Here we'll increment
+ // (with saturation) the stencil value where both the
+ // stencil and depth tests pass. The stencil test for
+ // these pixels will be
+ //
+ // ref mask stencil mask
+ // ( 0x1 & 0x3 ) == ( 0x1 & 0x3 )
+ //
+ // The stencil values for these pixels will be 0x2.
+ //
+ glStencilFunc( GL_EQUAL, 0x1, 0x3 );
+ glStencilOp( GL_KEEP, GL_INCR, GL_INCR );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[2] );
+
+ // Test 3:
+ //
+ // Finally, initialize the lower-right region. We'll invert
+ // the stencil value where the stencil tests fails. The
+ // stencil test for these pixels will be
+ //
+ // ref mask stencil mask
+ // ( 0x2 & 0x1 ) == ( 0x1 & 0x1 )
+ //
+ // The stencil value here will be set to ~((2^s-1) & 0x1),
+ // (with the 0x1 being from the stencil clear value),
+ // where 's' is the number of bits in the stencil buffer
+ //
+ glStencilFunc( GL_EQUAL, 0x2, 0x1 );
+ glStencilOp( GL_INVERT, GL_KEEP, GL_KEEP );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[3] );
+
+ // Since we don't know at compile time how many stecil bits are present,
+ // we'll query, and update the value correct value in the
+ // stencilValues arrays for the fourth tests. We'll use this value
+ // later in rendering.
+ glGetIntegerv( GL_STENCIL_BITS, &numStencilBits );
+
+ stencilValues[3] = ~(((1 << numStencilBits) - 1) & 0x1) & 0xff;
+
+ // Use the stencil buffer for controlling where rendering will
+ // occur. We diable writing to the stencil buffer so we
+ // can test against them without modifying the values we
+ // generated.
+ glStencilMask( 0x0 );
+
+ for ( i = 0; i < NumTests; ++i )
+ {
+ glStencilFunc( GL_EQUAL, stencilValues[i], 0xff );
+ glUniform4fv( userData->colorLoc, 1, colors[i] );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[4] );
+ }
+
+ //eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
+}
+
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+}
+
+
+///
+// Handle keyboard input
+//
+void Key ( ESContext *esContext, unsigned char key, int x, int y)
+{
+ switch ( key )
+ {
+ case 'm':
+ printf( "Saw an 'm'\n" );
+ break;
+
+ case 'a':
+ printf( "Saw an 'a'\n" );
+ break;
+
+ case '1':
+ printf( "Saw a '1'\n" );
+ break;
+
+ case 033: // ASCII Escape Key
+ ShutDown( esContext );
+ exit( 0 );
+ break;
+ }
+}
+
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "Multi-sampling", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+ esRegisterKeyFunc( &esContext, Key );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_11/Stencil_Test/Stencil_Test.c b/tests/glbook/Chapter_11/Stencil_Test/Stencil_Test.c new file mode 100644 index 00000000..b3a0486d --- /dev/null +++ b/tests/glbook/Chapter_11/Stencil_Test/Stencil_Test.c @@ -0,0 +1,273 @@ +//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// Stencil_Test.c
+//
+// This example shows various stencil buffer
+// operations.
+//
+#include <stdlib.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint positionLoc;
+
+ // Uniform locations
+ GLint colorLoc;
+
+} UserData;
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "attribute vec4 a_position; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = a_position; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "uniform vec4 u_color; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = u_color; \n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
+
+ // Get the sampler location
+ userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" );
+
+ // Set the clear color
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+
+ // Set the stencil clear value
+ glClearStencil ( 0x1 );
+
+ // Set the depth clear value
+ glClearDepthf( 0.75f );
+
+ // Enable the depth and stencil tests
+ glEnable( GL_DEPTH_TEST );
+ glEnable( GL_STENCIL_TEST );
+
+ return TRUE;
+}
+
+///
+// Initialize the stencil buffer values, and then use those
+// values to control rendering
+//
+void Draw ( ESContext *esContext )
+{
+ int i;
+
+ UserData *userData = esContext->userData;
+
+ GLfloat vVertices[] = {
+ -0.75f, 0.25f, 0.50f, // Quad #0
+ -0.25f, 0.25f, 0.50f,
+ -0.25f, 0.75f, 0.50f,
+ -0.75f, 0.75f, 0.50f,
+ 0.25f, 0.25f, 0.90f, // Quad #1
+ 0.75f, 0.25f, 0.90f,
+ 0.75f, 0.75f, 0.90f,
+ 0.25f, 0.75f, 0.90f,
+ -0.75f, -0.75f, 0.50f, // Quad #2
+ -0.25f, -0.75f, 0.50f,
+ -0.25f, -0.25f, 0.50f,
+ -0.75f, -0.25f, 0.50f,
+ 0.25f, -0.75f, 0.50f, // Quad #3
+ 0.75f, -0.75f, 0.50f,
+ 0.75f, -0.25f, 0.50f,
+ 0.25f, -0.25f, 0.50f,
+ -1.00f, -1.00f, 0.00f, // Big Quad
+ 1.00f, -1.00f, 0.00f,
+ 1.00f, 1.00f, 0.00f,
+ -1.00f, 1.00f, 0.00f
+ };
+
+ GLubyte indices[][6] = {
+ { 0, 1, 2, 0, 2, 3 }, // Quad #0
+ { 4, 5, 6, 4, 6, 7 }, // Quad #1
+ { 8, 9, 10, 8, 10, 11 }, // Quad #2
+ { 12, 13, 14, 12, 14, 15 }, // Quad #3
+ { 16, 17, 18, 16, 18, 19 } // Big Quad
+ };
+
+#define NumTests 4
+ GLfloat colors[NumTests][4] = {
+ { 1.0f, 0.0f, 0.0f, 1.0f },
+ { 0.0f, 1.0f, 0.0f, 1.0f },
+ { 0.0f, 0.0f, 1.0f, 1.0f },
+ { 1.0f, 1.0f, 0.0f, 0.0f }
+ };
+
+ GLint numStencilBits;
+ GLuint stencilValues[NumTests] = {
+ 0x7, // Result of test 0
+ 0x0, // Result of test 1
+ 0x2, // Result of test 2
+ 0xff // Result of test 3. We need to fill this
+ // value in a run-time
+ };
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color, depth, and stencil buffers. At this
+ // point, the stencil buffer will be 0x1 for all pixels
+ glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex position
+ glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
+ GL_FALSE, 0, vVertices );
+
+ glEnableVertexAttribArray ( userData->positionLoc );
+
+ // Test 0:
+ //
+ // Initialize upper-left region. In this case, the
+ // stencil-buffer values will be replaced because the
+ // stencil test for the rendered pixels will fail the
+ // stencil test, which is
+ //
+ // ref mask stencil mask
+ // ( 0x7 & 0x3 ) < ( 0x1 & 0x7 )
+ //
+ // The value in the stencil buffer for these pixels will
+ // be 0x7.
+ //
+ glStencilFunc( GL_LESS, 0x7, 0x3 );
+ glStencilOp( GL_REPLACE, GL_DECR, GL_DECR );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[0] );
+
+ // Test 1:
+ //
+ // Initialize the upper-right region. Here, we'll decrement
+ // the stencil-buffer values where the stencil test passes
+ // but the depth test fails. The stencil test is
+ //
+ // ref mask stencil mask
+ // ( 0x3 & 0x3 ) > ( 0x1 & 0x3 )
+ //
+ // but where the geometry fails the depth test. The
+ // stencil values for these pixels will be 0x0.
+ //
+ glStencilFunc( GL_GREATER, 0x3, 0x3 );
+ glStencilOp( GL_KEEP, GL_DECR, GL_KEEP );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[1] );
+
+ // Test 2:
+ //
+ // Initialize the lower-left region. Here we'll increment
+ // (with saturation) the stencil value where both the
+ // stencil and depth tests pass. The stencil test for
+ // these pixels will be
+ //
+ // ref mask stencil mask
+ // ( 0x1 & 0x3 ) == ( 0x1 & 0x3 )
+ //
+ // The stencil values for these pixels will be 0x2.
+ //
+ glStencilFunc( GL_EQUAL, 0x1, 0x3 );
+ glStencilOp( GL_KEEP, GL_INCR, GL_INCR );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[2] );
+
+ // Test 3:
+ //
+ // Finally, initialize the lower-right region. We'll invert
+ // the stencil value where the stencil tests fails. The
+ // stencil test for these pixels will be
+ //
+ // ref mask stencil mask
+ // ( 0x2 & 0x1 ) == ( 0x1 & 0x1 )
+ //
+ // The stencil value here will be set to ~((2^s-1) & 0x1),
+ // (with the 0x1 being from the stencil clear value),
+ // where 's' is the number of bits in the stencil buffer
+ //
+ glStencilFunc( GL_EQUAL, 0x2, 0x1 );
+ glStencilOp( GL_INVERT, GL_KEEP, GL_KEEP );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[3] );
+
+ // Since we don't know at compile time how many stecil bits are present,
+ // we'll query, and update the value correct value in the
+ // stencilValues arrays for the fourth tests. We'll use this value
+ // later in rendering.
+ glGetIntegerv( GL_STENCIL_BITS, &numStencilBits );
+
+ stencilValues[3] = ~(((1 << numStencilBits) - 1) & 0x1) & 0xff;
+
+ // Use the stencil buffer for controlling where rendering will
+ // occur. We diable writing to the stencil buffer so we
+ // can test against them without modifying the values we
+ // generated.
+ glStencilMask( 0x0 );
+
+ for ( i = 0; i < NumTests; ++i )
+ {
+ glStencilFunc( GL_EQUAL, stencilValues[i], 0xff );
+ glUniform4fv( userData->colorLoc, 1, colors[i] );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[4] );
+ }
+
+ eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+}
+
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "Stencil Test", 320, 240,
+ ES_WINDOW_RGB | ES_WINDOW_DEPTH | ES_WINDOW_STENCIL );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_13/ParticleSystem/ParticleSystem.c b/tests/glbook/Chapter_13/ParticleSystem/ParticleSystem.c new file mode 100644 index 00000000..f48e871a --- /dev/null +++ b/tests/glbook/Chapter_13/ParticleSystem/ParticleSystem.c @@ -0,0 +1,310 @@ +//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// ParticleSystem.c
+//
+// This is an example that demonstrates rendering a particle system
+// using a vertex shader and point sprites.
+//
+#include <stdlib.h>
+#include <math.h>
+#include "esUtil.h"
+
+#define NUM_PARTICLES 2000
+#define PARTICLE_SIZE 7
+
+int randomTemp = 8765;
+float myrandom() {
+ int curr = randomTemp;
+ randomTemp = (1140671485 * randomTemp + 12820163) % 4294967296;
+ return ((float)curr) / 4294967296;
+}
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint lifetimeLoc;
+ GLint startPositionLoc;
+ GLint endPositionLoc;
+
+ // Uniform location
+ GLint timeLoc;
+ GLint colorLoc;
+ GLint centerPositionLoc;
+ GLint samplerLoc;
+
+ // Texture handle
+ GLuint textureId;
+
+ // Particle vertex data
+ GLfloat particleData[ NUM_PARTICLES * PARTICLE_SIZE ];
+
+ // Current time
+ float time;
+
+ GLuint vertexObject;
+} UserData;
+
+///
+// Load texture from disk
+//
+GLuint LoadTexture ( char *fileName )
+{
+ int width,
+ height;
+ char *buffer = esLoadTGA ( fileName, &width, &height );
+ GLuint texId;
+
+ if ( buffer == NULL )
+ {
+ esLogMessage ( "Error loading (%s) image.\n", fileName );
+ return 0;
+ }
+
+ glGenTextures ( 1, &texId );
+ glBindTexture ( GL_TEXTURE_2D, texId );
+
+ glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+
+ free ( buffer );
+
+ return texId;
+}
+
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ int i;
+
+ GLbyte vShaderStr[] =
+ "uniform float u_time; \n"
+ "uniform vec3 u_centerPosition; \n"
+ "attribute float a_lifetime; \n"
+ "attribute vec3 a_startPosition; \n"
+ "attribute vec3 a_endPosition; \n"
+ "varying float v_lifetime; \n"
+ "void main() \n"
+ "{ \n"
+ " if ( u_time <= a_lifetime ) \n"
+ " { \n"
+ " gl_Position.xyz = a_startPosition + \n"
+ " (u_time * a_endPosition); \n"
+ " gl_Position.xyz += u_centerPosition; \n"
+ " gl_Position.w = 1.0; \n"
+ " } \n"
+ " else \n"
+ " gl_Position = vec4( -1000, -1000, 0, 0 ); \n"
+ " v_lifetime = 1.0 - ( u_time / a_lifetime ); \n"
+ " v_lifetime = clamp ( v_lifetime, 0.0, 1.0 ); \n"
+ " gl_PointSize = ( v_lifetime * v_lifetime ) * 40.0; \n"
+ "}";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "uniform vec4 u_color; \n"
+ "varying float v_lifetime; \n"
+ "uniform sampler2D s_texture; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 texColor; \n"
+ " texColor = texture2D( s_texture, gl_PointCoord ); \n"
+ " gl_FragColor = vec4( u_color ) * texColor; \n"
+ " gl_FragColor.a *= v_lifetime; \n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->lifetimeLoc = glGetAttribLocation ( userData->programObject, "a_lifetime" );
+ userData->startPositionLoc = glGetAttribLocation ( userData->programObject, "a_startPosition" );
+ userData->endPositionLoc = glGetAttribLocation ( userData->programObject, "a_endPosition" );
+
+ // Get the uniform locations
+ userData->timeLoc = glGetUniformLocation ( userData->programObject, "u_time" );
+ userData->centerPositionLoc = glGetUniformLocation ( userData->programObject, "u_centerPosition" );
+ userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" );
+ userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 1.0f );
+
+ // Fill in particle data array
+ for ( i = 0; i < NUM_PARTICLES; i++ )
+ {
+ GLfloat *particleData = &userData->particleData[i * PARTICLE_SIZE];
+
+ // Lifetime of particle
+ (*particleData++) = myrandom();
+
+ // End position of particle
+ (*particleData++) = myrandom() * 2 - 1.0f;
+ (*particleData++) = myrandom() * 2 - 1.0f;
+ (*particleData++) = myrandom() * 2 - 1.0f;
+
+ // Start position of particle
+ (*particleData++) = myrandom() * 0.25 - 0.125f;
+ (*particleData++) = myrandom() * 0.25 - 0.125f;
+ (*particleData++) = myrandom() * 0.25 - 0.125f;
+ }
+
+ glGenBuffers(1, &userData->vertexObject);
+ glBindBuffer( GL_ARRAY_BUFFER, userData->vertexObject );
+ glBufferData( GL_ARRAY_BUFFER, NUM_PARTICLES * PARTICLE_SIZE * 4, userData->particleData, GL_STATIC_DRAW );
+
+ // Initialize time to cause reset on first update
+ userData->time = 1.0f;
+
+ userData->textureId = LoadTexture ( "smoke.tga" );
+ if ( userData->textureId <= 0 )
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+///
+// Update time-based variables
+//
+void Update ( ESContext *esContext, float deltaTime )
+{
+// deltaTime = 0.1;
+ UserData *userData = esContext->userData;
+
+ userData->time += deltaTime;
+
+ if ( userData->time >= 1.0f )
+ {
+ float centerPos[3];
+ float color[4];
+
+ userData->time = 0.0f;
+
+ // Pick a new start location and color
+ centerPos[0] = myrandom() - 0.5f;
+ centerPos[1] = myrandom() - 0.5f;
+ centerPos[2] = myrandom() - 0.5f;
+
+ glUniform3fv ( userData->centerPositionLoc, 1, ¢erPos[0] );
+
+ // Random color
+ color[0] = myrandom() * 0.5 + 0.5f;
+ color[1] = myrandom() * 0.5 + 0.5f;
+ color[2] = myrandom() * 0.5 + 0.5f;
+ color[3] = 1.0;
+
+ glUniform4fv ( userData->colorLoc, 1, &color[0] );
+ }
+
+ // Load uniform time variable
+ glUniform1f ( userData->timeLoc, userData->time );
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex attributes
+ glBindBuffer( GL_ARRAY_BUFFER, userData->vertexObject );
+ glVertexAttribPointer ( userData->lifetimeLoc, 1, GL_FLOAT,
+ GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
+ 0 );
+
+ glVertexAttribPointer ( userData->endPositionLoc, 3, GL_FLOAT,
+ GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
+ 4 );
+
+ glVertexAttribPointer ( userData->startPositionLoc, 3, GL_FLOAT,
+ GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
+ 4 * 4 );
+
+
+ glEnableVertexAttribArray ( userData->lifetimeLoc );
+ glEnableVertexAttribArray ( userData->endPositionLoc );
+ glEnableVertexAttribArray ( userData->startPositionLoc );
+ // Blend particles
+ glEnable ( GL_BLEND );
+ glBlendFunc ( GL_SRC_ALPHA, GL_ONE );
+
+ // Bind the texture
+ glActiveTexture ( GL_TEXTURE0 );
+ glBindTexture ( GL_TEXTURE_2D, userData->textureId );
+ //glEnable ( GL_TEXTURE_2D );
+
+ // Set the sampler texture unit to 0
+ glUniform1i ( userData->samplerLoc, 0 );
+
+ Update ( esContext, 133 * 0.001125 );
+
+ glDrawArrays( GL_POINTS, 0, NUM_PARTICLES );
+
+ eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete texture object
+ glDeleteTextures ( 1, &userData->textureId );
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+}
+
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "ParticleSystem", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+// esRegisterUpdateFunc ( &esContext, Update );
+
+ Draw (&esContext);
+ Draw (&esContext);
+ //esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_13/ParticleSystem/ParticleSystem_orig.c b/tests/glbook/Chapter_13/ParticleSystem/ParticleSystem_orig.c new file mode 100644 index 00000000..378d05a7 --- /dev/null +++ b/tests/glbook/Chapter_13/ParticleSystem/ParticleSystem_orig.c @@ -0,0 +1,294 @@ +//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// ParticleSystem.c
+//
+// This is an example that demonstrates rendering a particle system
+// using a vertex shader and point sprites.
+//
+#include <stdlib.h>
+#include <math.h>
+#include "esUtil.h"
+
+#define NUM_PARTICLES 1000
+#define PARTICLE_SIZE 7
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint lifetimeLoc;
+ GLint startPositionLoc;
+ GLint endPositionLoc;
+
+ // Uniform location
+ GLint timeLoc;
+ GLint colorLoc;
+ GLint centerPositionLoc;
+ GLint samplerLoc;
+
+ // Texture handle
+ GLuint textureId;
+
+ // Particle vertex data
+ float particleData[ NUM_PARTICLES * PARTICLE_SIZE ];
+
+ // Current time
+ float time;
+
+} UserData;
+
+///
+// Load texture from disk
+//
+GLuint LoadTexture ( char *fileName )
+{
+ int width,
+ height;
+ char *buffer = esLoadTGA ( fileName, &width, &height );
+ GLuint texId;
+
+ if ( buffer == NULL )
+ {
+ esLogMessage ( "Error loading (%s) image.\n", fileName );
+ return 0;
+ }
+
+ glGenTextures ( 1, &texId );
+ glBindTexture ( GL_TEXTURE_2D, texId );
+
+ glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+
+ free ( buffer );
+
+ return texId;
+}
+
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ int i;
+
+ GLbyte vShaderStr[] =
+ "uniform float u_time; \n"
+ "uniform vec3 u_centerPosition; \n"
+ "attribute float a_lifetime; \n"
+ "attribute vec3 a_startPosition; \n"
+ "attribute vec3 a_endPosition; \n"
+ "varying float v_lifetime; \n"
+ "void main() \n"
+ "{ \n"
+ " if ( u_time <= a_lifetime ) \n"
+ " { \n"
+ " gl_Position.xyz = a_startPosition + \n"
+ " (u_time * a_endPosition); \n"
+ " gl_Position.xyz += u_centerPosition; \n"
+ " gl_Position.w = 1.0; \n"
+ " } \n"
+ " else \n"
+ " gl_Position = vec4( -1000, -1000, 0, 0 ); \n"
+ " v_lifetime = 1.0 - ( u_time / a_lifetime ); \n"
+ " v_lifetime = clamp ( v_lifetime, 0.0, 1.0 ); \n"
+ " gl_PointSize = ( v_lifetime * v_lifetime ) * 40.0; \n"
+ "}";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "uniform vec4 u_color; \n"
+ "varying float v_lifetime; \n"
+ "uniform sampler2D s_texture; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 texColor; \n"
+ " texColor = texture2D( s_texture, gl_PointCoord ); \n"
+ " gl_FragColor = vec4( u_color ) * texColor; \n"
+ " gl_FragColor.a *= v_lifetime; \n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->lifetimeLoc = glGetAttribLocation ( userData->programObject, "a_lifetime" );
+ userData->startPositionLoc = glGetAttribLocation ( userData->programObject, "a_startPosition" );
+ userData->endPositionLoc = glGetAttribLocation ( userData->programObject, "a_endPosition" );
+
+ // Get the uniform locations
+ userData->timeLoc = glGetUniformLocation ( userData->programObject, "u_time" );
+ userData->centerPositionLoc = glGetUniformLocation ( userData->programObject, "u_centerPosition" );
+ userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" );
+ userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+
+ // Fill in particle data array
+ srand ( 0 );
+ for ( i = 0; i < NUM_PARTICLES; i++ )
+ {
+ float *particleData = &userData->particleData[i * PARTICLE_SIZE];
+
+ // Lifetime of particle
+ (*particleData++) = ( (float)(rand() % 10000) / 10000.0f );
+
+ // End position of particle
+ (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
+ (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
+ (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
+
+ // Start position of particle
+ (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
+ (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
+ (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
+
+ }
+
+ // Initialize time to cause reset on first update
+ userData->time = 1.0f;
+
+ userData->textureId = LoadTexture ( "smoke.tga" );
+ if ( userData->textureId <= 0 )
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+///
+// Update time-based variables
+//
+void Update ( ESContext *esContext, float deltaTime )
+{
+ UserData *userData = esContext->userData;
+
+ userData->time += deltaTime;
+
+ if ( userData->time >= 1.0f )
+ {
+ float centerPos[3];
+ float color[4];
+
+ userData->time = 0.0f;
+
+ // Pick a new start location and color
+ centerPos[0] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
+ centerPos[1] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
+ centerPos[2] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
+
+ glUniform3fv ( userData->centerPositionLoc, 1, ¢erPos[0] );
+
+ // Random color
+ color[0] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
+ color[1] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
+ color[2] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
+ color[3] = 0.5;
+
+ glUniform4fv ( userData->colorLoc, 1, &color[0] );
+ }
+
+ // Load uniform time variable
+ glUniform1f ( userData->timeLoc, userData->time );
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex attributes
+ glVertexAttribPointer ( userData->lifetimeLoc, 1, GL_FLOAT,
+ GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
+ userData->particleData );
+
+ glVertexAttribPointer ( userData->endPositionLoc, 3, GL_FLOAT,
+ GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
+ &userData->particleData[1] );
+
+ glVertexAttribPointer ( userData->startPositionLoc, 3, GL_FLOAT,
+ GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
+ &userData->particleData[4] );
+
+
+ glEnableVertexAttribArray ( userData->lifetimeLoc );
+ glEnableVertexAttribArray ( userData->endPositionLoc );
+ glEnableVertexAttribArray ( userData->startPositionLoc );
+ // Blend particles
+ glEnable ( GL_BLEND );
+ glBlendFunc ( GL_SRC_ALPHA, GL_ONE );
+
+ // Bind the texture
+ glActiveTexture ( GL_TEXTURE0 );
+ glBindTexture ( GL_TEXTURE_2D, userData->textureId );
+ glEnable ( GL_TEXTURE_2D );
+
+ // Set the sampler texture unit to 0
+ glUniform1i ( userData->samplerLoc, 0 );
+
+ glDrawArrays( GL_POINTS, 0, NUM_PARTICLES );
+
+ eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete texture object
+ glDeleteTextures ( 1, &userData->textureId );
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+}
+
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "ParticleSystem", 640, 480, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+ esRegisterUpdateFunc ( &esContext, Update );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_13/ParticleSystem/smoke.tga b/tests/glbook/Chapter_13/ParticleSystem/smoke.tga Binary files differnew file mode 100644 index 00000000..06a0705c --- /dev/null +++ b/tests/glbook/Chapter_13/ParticleSystem/smoke.tga diff --git a/tests/glbook/Chapter_15/Hello_Triangle_KD/Hello_Triangle_KD.c b/tests/glbook/Chapter_15/Hello_Triangle_KD/Hello_Triangle_KD.c new file mode 100644 index 00000000..af49c13c --- /dev/null +++ b/tests/glbook/Chapter_15/Hello_Triangle_KD/Hello_Triangle_KD.c @@ -0,0 +1,306 @@ +//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// Hello_Triangle_KD.c
+//
+// This is a simple example that draws a single triangle with
+// a minimal vertex/fragment shader using OpenKODE.
+//
+#include <KD/kd.h>
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // EGL handles
+ EGLDisplay eglDisplay;
+ EGLContext eglContext;
+ EGLSurface eglSurface;
+
+} UserData;
+
+///
+// Create a shader object, load the shader source, and
+// compile the shader.
+//
+GLuint LoadShader ( GLenum type, const char *shaderSrc )
+{
+ GLuint shader;
+ GLint compiled;
+
+ // Create the shader object
+ shader = glCreateShader ( type );
+
+ if ( shader == 0 )
+ return 0;
+
+ // Load the shader source
+ glShaderSource ( shader, 1, &shaderSrc, NULL );
+
+ // Compile the shader
+ glCompileShader ( shader );
+
+ // Check the compile status
+ glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
+
+ if ( !compiled )
+ {
+ GLint infoLen = 0;
+
+ glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
+
+ if ( infoLen > 1 )
+ {
+ char* infoLog = kdMalloc (sizeof(char) * infoLen );
+
+ glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
+ kdLogMessage ( infoLog );
+
+ kdFree ( infoLog );
+ }
+
+ glDeleteShader ( shader );
+ return 0;
+ }
+
+ return shader;
+
+}
+
+///
+// Initialize the shader and program object
+//
+int Init ( UserData *userData )
+{
+ GLbyte vShaderStr[] =
+ "attribute vec4 vPosition; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = vPosition; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float;\n"\
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
+ "} \n";
+
+ GLuint vertexShader;
+ GLuint fragmentShader;
+ GLuint programObject;
+ GLint linked;
+
+ // Load the vertex/fragment shaders
+ vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr );
+ fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr );
+
+ // Create the program object
+ programObject = glCreateProgram ( );
+
+ if ( programObject == 0 )
+ return 0;
+
+ glAttachShader ( programObject, vertexShader );
+ glAttachShader ( programObject, fragmentShader );
+
+ // Bind vPosition to attribute 0
+ glBindAttribLocation ( programObject, 0, "vPosition" );
+
+ // Link the program
+ glLinkProgram ( programObject );
+
+ // Check the link status
+ glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
+
+ if ( !linked )
+ {
+ GLint infoLen = 0;
+
+ glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
+
+ if ( infoLen > 1 )
+ {
+ char* infoLog = kdMalloc (sizeof(char) * infoLen );
+
+ glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
+ kdLogMessage ( infoLog );
+
+ kdFree ( infoLog );
+ }
+
+ glDeleteProgram ( programObject );
+ return FALSE;
+ }
+
+ // Store the program object
+ userData->programObject = programObject;
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+ return TRUE;
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( UserData *userData )
+{
+ GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f,
+ -0.5f, -0.5f, 0.0f,
+ 0.5f, -0.5f, 0.0f };
+
+ // Set the viewport
+ glViewport ( 0, 0, 320, 240 );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex data
+ glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices );
+ glEnableVertexAttribArray ( 0 );
+
+ glDrawArrays ( GL_TRIANGLES, 0, 3 );
+
+ eglSwapBuffers ( userData->eglDisplay, userData->eglSurface );
+}
+
+
+///
+// InitEGLContext()
+//
+// Initialize an EGL rendering context and all associated elements
+//
+EGLBoolean InitEGLContext ( UserData *userData,
+ KDWindow *window,
+ EGLConfig config )
+{
+ EGLContext context;
+ EGLSurface surface;
+ EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
+
+ // Get native window handle
+ EGLNativeWindowType hWnd; + if(kdRealizeWindow(window, &hWnd) != 0)
+ {
+ return EGL_FALSE;
+ }
+ surface = eglCreateWindowSurface(userData->eglDisplay, config, hWnd, NULL);
+ if ( surface == EGL_NO_SURFACE )
+ {
+ return EGL_FALSE;
+ }
+
+ // Create a GL context
+ context = eglCreateContext(userData->eglDisplay, config, EGL_NO_CONTEXT, contextAttribs );
+ if ( context == EGL_NO_CONTEXT )
+ {
+ return EGL_FALSE;
+ }
+
+ // Make the context current
+ if ( !eglMakeCurrent(userData->eglDisplay, surface, surface, context) )
+ {
+ return EGL_FALSE;
+ }
+
+ userData->eglContext = context;
+ userData->eglSurface = surface;
+
+ return EGL_TRUE;
+}
+
+///
+// kdMain()
+//
+// Main function for OpenKODE application
+//
+KDint kdMain ( KDint argc, const KDchar *const *argv )
+{
+ EGLint attribList[] =
+ {
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, EGL_DONT_CARE,
+ EGL_DEPTH_SIZE, EGL_DONT_CARE,
+ EGL_STENCIL_SIZE, EGL_DONT_CARE,
+ EGL_NONE
+ };
+ EGLint majorVersion,
+ minorVersion;
+ UserData userData;
+ EGLint numConfigs;
+ EGLConfig config;
+ KDWindow *window = KD_NULL;
+
+ userData.eglDisplay = eglGetDisplay( EGL_DEFAULT_DISPLAY );
+
+ // Initialize EGL
+ if ( !eglInitialize(userData.eglDisplay, &majorVersion, &minorVersion) )
+ {
+ return EGL_FALSE;
+ }
+
+ // Get configs
+ if ( !eglGetConfigs(userData.eglDisplay, NULL, 0, &numConfigs) )
+ {
+ return EGL_FALSE;
+ }
+
+ // Choose config
+ if ( !eglChooseConfig(userData.eglDisplay, attribList, &config, 1, &numConfigs) )
+ {
+ return EGL_FALSE;
+ }
+
+
+ // Use OpenKODE to create a Window
+ window = kdCreateWindow ( userData.eglDisplay, config, KD_NULL );
+ if( !window )
+ kdExit ( 0 );
+
+ if ( !InitEGLContext ( &userData, window, config ) )
+ kdExit ( 0 );
+
+ if ( !Init ( &userData ) )
+ kdExit ( 0 );
+
+ // Main Loop
+ while ( 1 )
+ {
+ // Wait for an event
+ const KDEvent *evt = kdWaitEvent ( 0 );
+ if ( evt )
+ {
+ // Exit app
+ if ( evt->type == KD_EVENT_WINDOW_CLOSE)
+ break;
+ }
+
+ // Draw frame
+ Draw ( &userData );
+ }
+
+ // EGL clean up
+ eglMakeCurrent ( 0, 0, 0, 0 );
+ eglDestroySurface ( userData.eglDisplay, userData.eglSurface );
+ eglDestroyContext ( userData.eglDisplay, userData.eglContext );
+
+ // Destroy the window
+ kdDestroyWindow(window);
+
+ return 0;
+}
diff --git a/tests/glbook/Chapter_2/Hello_Triangle/Hello_Triangle.c b/tests/glbook/Chapter_2/Hello_Triangle/Hello_Triangle.c new file mode 100644 index 00000000..5d4e0bd9 --- /dev/null +++ b/tests/glbook/Chapter_2/Hello_Triangle/Hello_Triangle.c @@ -0,0 +1,200 @@ +// +// Book: OpenGL(R) ES 2.0 Programming Guide +// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner +// ISBN-10: 0321502795 +// ISBN-13: 9780321502797 +// Publisher: Addison-Wesley Professional +// URLs: http://safari.informit.com/9780321563835 +// http://www.opengles-book.com +// + +// Hello_Triangle.c +// +// This is a simple example that draws a single triangle with +// a minimal vertex/fragment shader. The purpose of this +// example is to demonstrate the basic concepts of +// OpenGL ES 2.0 rendering. +#include <stdlib.h> +#include "esUtil.h" + +typedef struct +{ + // Handle to a program object + GLuint programObject; + +} UserData; + +/// +// Create a shader object, load the shader source, and +// compile the shader. +// +GLuint LoadShader ( GLenum type, const char *shaderSrc ) +{ + GLuint shader; + GLint compiled; + + // Create the shader object + shader = glCreateShader ( type ); + + if ( shader == 0 ) + return 0; + + // Load the shader source + glShaderSource ( shader, 1, &shaderSrc, NULL ); + + // Compile the shader + glCompileShader ( shader ); + + // Check the compile status + glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled ); + + if ( !compiled ) + { + GLint infoLen = 0; + + glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen ); + + if ( infoLen > 1 ) + { + char* infoLog = malloc (sizeof(char) * infoLen ); + + glGetShaderInfoLog ( shader, infoLen, NULL, infoLog ); + esLogMessage ( "Error compiling shader:\n%s\n", infoLog ); + + free ( infoLog ); + } + + glDeleteShader ( shader ); + return 0; + } + + return shader; + +} + +/// +// Initialize the shader and program object +// +int Init ( ESContext *esContext ) +{ + esContext->userData = malloc(sizeof(UserData)); + + UserData *userData = esContext->userData; + GLbyte vShaderStr[] = + "attribute vec4 vPosition; \n" + "void main() \n" + "{ \n" + " gl_Position = vPosition; \n" + "} \n"; + + GLbyte fShaderStr[] = + "precision mediump float;\n"\ + "void main() \n" + "{ \n" + " gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n" + "} \n"; + + GLuint vertexShader; + GLuint fragmentShader; + GLuint programObject; + GLint linked; + + // Load the vertex/fragment shaders + vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr ); + fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr ); + + // Create the program object + programObject = glCreateProgram ( ); + + if ( programObject == 0 ) + return 0; + + glAttachShader ( programObject, vertexShader ); + glAttachShader ( programObject, fragmentShader ); + + // Bind vPosition to attribute 0 + glBindAttribLocation ( programObject, 0, "vPosition" ); + + // Link the program + glLinkProgram ( programObject ); + + // Check the link status + glGetProgramiv ( programObject, GL_LINK_STATUS, &linked ); + + if ( !linked ) + { + GLint infoLen = 0; + + glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen ); + + if ( infoLen > 1 ) + { + char* infoLog = malloc (sizeof(char) * infoLen ); + + glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog ); + esLogMessage ( "Error linking program:\n%s\n", infoLog ); + + free ( infoLog ); + } + + glDeleteProgram ( programObject ); + return GL_FALSE; + } + + // Store the program object + userData->programObject = programObject; + + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); + return GL_TRUE; +} + +/// +// Draw a triangle using the shader pair created in Init() +// +void Draw ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f, + -0.5f, -0.5f, 0.0f, + 0.5f, -0.5f, 0.0f }; + + // No clientside arrays, so do this in a webgl-friendly manner + GLuint vertexPosObject; + glGenBuffers(1, &vertexPosObject); + glBindBuffer(GL_ARRAY_BUFFER, vertexPosObject); + glBufferData(GL_ARRAY_BUFFER, 9*4, vVertices, GL_STATIC_DRAW); + + // Set the viewport + glViewport ( 0, 0, esContext->width, esContext->height ); + + // Clear the color buffer + glClear ( GL_COLOR_BUFFER_BIT ); + + // Use the program object + glUseProgram ( userData->programObject ); + + // Load the vertex data + glBindBuffer(GL_ARRAY_BUFFER, vertexPosObject); + glVertexAttribPointer(0 /* ? */, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(0); + + glDrawArrays ( GL_TRIANGLES, 0, 3 ); +} + +int main ( int argc, char *argv[] ) +{ + ESContext esContext; + UserData userData; + + esInitContext ( &esContext ); + esContext.userData = &userData; + + esCreateWindow ( &esContext, "Hello Triangle", 320, 240, ES_WINDOW_RGB ); + + if ( !Init ( &esContext ) ) + return 0; + + esRegisterDrawFunc ( &esContext, Draw ); + + esMainLoop ( &esContext ); +} diff --git a/tests/glbook/Chapter_2/Hello_Triangle/Hello_Triangle_orig.c b/tests/glbook/Chapter_2/Hello_Triangle/Hello_Triangle_orig.c new file mode 100644 index 00000000..fd4c506a --- /dev/null +++ b/tests/glbook/Chapter_2/Hello_Triangle/Hello_Triangle_orig.c @@ -0,0 +1,193 @@ +// +// Book: OpenGL(R) ES 2.0 Programming Guide +// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner +// ISBN-10: 0321502795 +// ISBN-13: 9780321502797 +// Publisher: Addison-Wesley Professional +// URLs: http://safari.informit.com/9780321563835 +// http://www.opengles-book.com +// + +// Hello_Triangle.c +// +// This is a simple example that draws a single triangle with +// a minimal vertex/fragment shader. The purpose of this +// example is to demonstrate the basic concepts of +// OpenGL ES 2.0 rendering. +#include <stdlib.h> +#include "esUtil.h" + +typedef struct +{ + // Handle to a program object + GLuint programObject; + +} UserData; + +/// +// Create a shader object, load the shader source, and +// compile the shader. +// +GLuint LoadShader ( GLenum type, const char *shaderSrc ) +{ + GLuint shader; + GLint compiled; + + // Create the shader object + shader = glCreateShader ( type ); + + if ( shader == 0 ) + return 0; + + // Load the shader source + glShaderSource ( shader, 1, &shaderSrc, NULL ); + + // Compile the shader + glCompileShader ( shader ); + + // Check the compile status + glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled ); + + if ( !compiled ) + { + GLint infoLen = 0; + + glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen ); + + if ( infoLen > 1 ) + { + char* infoLog = malloc (sizeof(char) * infoLen ); + + glGetShaderInfoLog ( shader, infoLen, NULL, infoLog ); + esLogMessage ( "Error compiling shader:\n%s\n", infoLog ); + + free ( infoLog ); + } + + glDeleteShader ( shader ); + return 0; + } + + return shader; + +} + +/// +// Initialize the shader and program object +// +int Init ( ESContext *esContext ) +{ + esContext->userData = malloc(sizeof(UserData)); + + UserData *userData = esContext->userData; + GLbyte vShaderStr[] = + "attribute vec4 vPosition; \n" + "void main() \n" + "{ \n" + " gl_Position = vPosition; \n" + "} \n"; + + GLbyte fShaderStr[] = + "precision mediump float;\n"\ + "void main() \n" + "{ \n" + " gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n" + "} \n"; + + GLuint vertexShader; + GLuint fragmentShader; + GLuint programObject; + GLint linked; + + // Load the vertex/fragment shaders + vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr ); + fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr ); + + // Create the program object + programObject = glCreateProgram ( ); + + if ( programObject == 0 ) + return 0; + + glAttachShader ( programObject, vertexShader ); + glAttachShader ( programObject, fragmentShader ); + + // Bind vPosition to attribute 0 + glBindAttribLocation ( programObject, 0, "vPosition" ); + + // Link the program + glLinkProgram ( programObject ); + + // Check the link status + glGetProgramiv ( programObject, GL_LINK_STATUS, &linked ); + + if ( !linked ) + { + GLint infoLen = 0; + + glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen ); + + if ( infoLen > 1 ) + { + char* infoLog = malloc (sizeof(char) * infoLen ); + + glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog ); + esLogMessage ( "Error linking program:\n%s\n", infoLog ); + + free ( infoLog ); + } + + glDeleteProgram ( programObject ); + return GL_FALSE; + } + + // Store the program object + userData->programObject = programObject; + + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); + return GL_TRUE; +} + +/// +// Draw a triangle using the shader pair created in Init() +// +void Draw ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f, + -0.5f, -0.5f, 0.0f, + 0.5f, -0.5f, 0.0f }; + + // Set the viewport + glViewport ( 0, 0, esContext->width, esContext->height ); + + // Clear the color buffer + glClear ( GL_COLOR_BUFFER_BIT ); + + // Use the program object + glUseProgram ( userData->programObject ); + + // Load the vertex data + glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices ); + glEnableVertexAttribArray ( 0 ); + + glDrawArrays ( GL_TRIANGLES, 0, 3 ); +} + +int main ( int argc, char *argv[] ) +{ + ESContext esContext; + UserData userData; + + esInitContext ( &esContext ); + esContext.userData = &userData; + + esCreateWindow ( &esContext, "Hello Triangle", 320, 240, ES_WINDOW_RGB ); + + if ( !Init ( &esContext ) ) + return 0; + + esRegisterDrawFunc ( &esContext, Draw ); + + esMainLoop ( &esContext ); +} diff --git a/tests/glbook/Chapter_8/Simple_VertexShader/Simple_VertexShader.c b/tests/glbook/Chapter_8/Simple_VertexShader/Simple_VertexShader.c new file mode 100644 index 00000000..44380c18 --- /dev/null +++ b/tests/glbook/Chapter_8/Simple_VertexShader/Simple_VertexShader.c @@ -0,0 +1,209 @@ +// +// Book: OpenGL(R) ES 2.0 Programming Guide +// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner +// ISBN-10: 0321502795 +// ISBN-13: 9780321502797 +// Publisher: Addison-Wesley Professional +// URLs: http://safari.informit.com/9780321563835 +// http://www.opengles-book.com +// + +// Simple_VertexShader.c +// +// This is a simple example that draws a rotating cube in perspective +// using a vertex shader to transform the object +// +#include <stdlib.h> +#include "esUtil.h" + +typedef struct +{ + // Handle to a program object + GLuint programObject; + + // Attribute locations + GLint positionLoc; + + // Uniform locations + GLint mvpLoc; + + // Vertex daata + GLfloat *vertices; + GLushort *indices; + int numIndices; + + // Rotation angle + GLfloat angle; + + // MVP matrix + ESMatrix mvpMatrix; + + GLuint vertPosObject, indicesObject; +} UserData; + +/// +// Initialize the shader and program object +// +int Init ( ESContext *esContext ) +{ + esContext->userData = malloc(sizeof(UserData)); + + UserData *userData = esContext->userData; + GLbyte vShaderStr[] = + "uniform mat4 u_mvpMatrix; \n" + "attribute vec4 a_position; \n" + "void main() \n" + "{ \n" + " gl_Position = u_mvpMatrix * a_position; \n" + "} \n"; + + GLbyte fShaderStr[] = + "precision mediump float; \n" + "void main() \n" + "{ \n" + " gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 ); \n" + "} \n"; + + // Load the shaders and get a linked program object + userData->programObject = esLoadProgram ( vShaderStr, fShaderStr ); + + // Get the attribute locations + userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" ); + + // Get the uniform locations + userData->mvpLoc = glGetUniformLocation( userData->programObject, "u_mvpMatrix" ); + + // Generate the vertex data + userData->numIndices = esGenCube( 1.0, &userData->vertices, + NULL, NULL, &userData->indices ); + + // Starting rotation angle for the cube + userData->angle = 45.0f; + + glGenBuffers(1, &userData->vertPosObject); + glBindBuffer(GL_ARRAY_BUFFER, userData->vertPosObject); + glBufferData(GL_ARRAY_BUFFER, 24 * sizeof(GLfloat) * 3, userData->vertices, GL_STATIC_DRAW); + + glGenBuffers(1, &userData->indicesObject); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->indicesObject); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, userData->numIndices * sizeof(GLushort), userData->indices, GL_STATIC_DRAW); + + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); + return GL_TRUE; +} + + +/// +// Update MVP matrix based on time +// +void Update ( ESContext *esContext, float deltaTime ) +{ + UserData *userData = (UserData*) esContext->userData; + ESMatrix perspective; + ESMatrix modelview; + float aspect; + + // Compute a rotation angle based on time to rotate the cube + userData->angle += ( deltaTime * 40.0f ); + if( userData->angle >= 360.0f ) + userData->angle -= 360.0f; + + // Compute the window aspect ratio + aspect = (GLfloat) esContext->width / (GLfloat) esContext->height; + + // Generate a perspective matrix with a 60 degree FOV + esMatrixLoadIdentity( &perspective ); + esPerspective( &perspective, 60.0f, aspect, 1.0f, 20.0f ); + + // Generate a model view matrix to rotate/translate the cube + esMatrixLoadIdentity( &modelview ); + + // Translate away from the viewer + esTranslate( &modelview, 0.0, 0.0, -2.0 ); + + // Rotate the cube + esRotate( &modelview, userData->angle, 1.0, 0.0, 1.0 ); + + // Compute the final MVP by multiplying the + // modevleiw and perspective matrices together + esMatrixMultiply( &userData->mvpMatrix, &modelview, &perspective ); +} + +/// +// Draw a triangle using the shader pair created in Init() +// +void Draw ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + // Set the viewport + glViewport ( 0, 0, esContext->width, esContext->height ); + + + // Clear the color buffer + glClear ( GL_COLOR_BUFFER_BIT ); + + // Use the program object + glUseProgram ( userData->programObject ); + + // Load the vertex position + glBindBuffer(GL_ARRAY_BUFFER, userData->vertPosObject); + glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, + GL_FALSE, 0, 0 ); + glEnableVertexAttribArray ( userData->positionLoc ); + + + // Load the index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->indicesObject); + + // Load the MVP matrix + glUniformMatrix4fv( userData->mvpLoc, 1, GL_FALSE, (GLfloat*) &userData->mvpMatrix.m[0][0] ); + + // Draw the cube + glDrawElements ( GL_TRIANGLES, userData->numIndices, GL_UNSIGNED_SHORT, 0 ); +} + +/// +// Cleanup +// +void ShutDown ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + if ( userData->vertices != NULL ) + { + free ( userData->vertices ); + } + + if ( userData->indices != NULL ) + { + free ( userData->indices ); + } + + // Delete program object + glDeleteProgram ( userData->programObject ); + + free(userData); +} + +int main ( int argc, char *argv[] ) +{ + ESContext esContext; + UserData userData; + + esInitContext ( &esContext ); + esContext.userData = &userData; + + esCreateWindow ( &esContext, "Simple Texture 2D", 320, 240, ES_WINDOW_RGB ); + + if ( !Init ( &esContext ) ) + return 0; + + esRegisterDrawFunc ( &esContext, Draw ); + esRegisterUpdateFunc ( &esContext, Update ); + + esMainLoop ( &esContext ); + + ShutDown ( &esContext ); +} + diff --git a/tests/glbook/Chapter_8/Simple_VertexShader/Simple_VertexShader_orig.c b/tests/glbook/Chapter_8/Simple_VertexShader/Simple_VertexShader_orig.c new file mode 100644 index 00000000..6036bf0c --- /dev/null +++ b/tests/glbook/Chapter_8/Simple_VertexShader/Simple_VertexShader_orig.c @@ -0,0 +1,196 @@ +// +// Book: OpenGL(R) ES 2.0 Programming Guide +// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner +// ISBN-10: 0321502795 +// ISBN-13: 9780321502797 +// Publisher: Addison-Wesley Professional +// URLs: http://safari.informit.com/9780321563835 +// http://www.opengles-book.com +// + +// Simple_VertexShader.c +// +// This is a simple example that draws a rotating cube in perspective +// using a vertex shader to transform the object +// +#include <stdlib.h> +#include "esUtil.h" + +typedef struct +{ + // Handle to a program object + GLuint programObject; + + // Attribute locations + GLint positionLoc; + + // Uniform locations + GLint mvpLoc; + + // Vertex daata + GLfloat *vertices; + GLuint *indices; + int numIndices; + + // Rotation angle + GLfloat angle; + + // MVP matrix + ESMatrix mvpMatrix; +} UserData; + +/// +// Initialize the shader and program object +// +int Init ( ESContext *esContext ) +{ + esContext->userData = malloc(sizeof(UserData)); + + UserData *userData = esContext->userData; + GLbyte vShaderStr[] = + "uniform mat4 u_mvpMatrix; \n" + "attribute vec4 a_position; \n" + "void main() \n" + "{ \n" + " gl_Position = u_mvpMatrix * a_position; \n" + "} \n"; + + GLbyte fShaderStr[] = + "precision mediump float; \n" + "void main() \n" + "{ \n" + " gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 ); \n" + "} \n"; + + // Load the shaders and get a linked program object + userData->programObject = esLoadProgram ( vShaderStr, fShaderStr ); + + // Get the attribute locations + userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" ); + + // Get the uniform locations + userData->mvpLoc = glGetUniformLocation( userData->programObject, "u_mvpMatrix" ); + + // Generate the vertex data + userData->numIndices = esGenCube( 1.0, &userData->vertices, + NULL, NULL, &userData->indices ); + + // Starting rotation angle for the cube + userData->angle = 45.0f; + + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); + return GL_TRUE; +} + + +/// +// Update MVP matrix based on time +// +void Update ( ESContext *esContext, float deltaTime ) +{ + UserData *userData = (UserData*) esContext->userData; + ESMatrix perspective; + ESMatrix modelview; + float aspect; + + // Compute a rotation angle based on time to rotate the cube + userData->angle += ( deltaTime * 40.0f ); + if( userData->angle >= 360.0f ) + userData->angle -= 360.0f; + + // Compute the window aspect ratio + aspect = (GLfloat) esContext->width / (GLfloat) esContext->height; + + // Generate a perspective matrix with a 60 degree FOV + esMatrixLoadIdentity( &perspective ); + esPerspective( &perspective, 60.0f, aspect, 1.0f, 20.0f ); + + // Generate a model view matrix to rotate/translate the cube + esMatrixLoadIdentity( &modelview ); + + // Translate away from the viewer + esTranslate( &modelview, 0.0, 0.0, -2.0 ); + + // Rotate the cube + esRotate( &modelview, userData->angle, 1.0, 0.0, 1.0 ); + + // Compute the final MVP by multiplying the + // modevleiw and perspective matrices together + esMatrixMultiply( &userData->mvpMatrix, &modelview, &perspective ); +} + +/// +// Draw a triangle using the shader pair created in Init() +// +void Draw ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + // Set the viewport + glViewport ( 0, 0, esContext->width, esContext->height ); + + + // Clear the color buffer + glClear ( GL_COLOR_BUFFER_BIT ); + + // Use the program object + glUseProgram ( userData->programObject ); + + // Load the vertex position + glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, + GL_FALSE, 3 * sizeof(GLfloat), userData->vertices ); + + glEnableVertexAttribArray ( userData->positionLoc ); + + + // Load the MVP matrix + glUniformMatrix4fv( userData->mvpLoc, 1, GL_FALSE, (GLfloat*) &userData->mvpMatrix.m[0][0] ); + + // Draw the cube + glDrawElements ( GL_TRIANGLES, userData->numIndices, GL_UNSIGNED_INT, userData->indices ); +} + +/// +// Cleanup +// +void ShutDown ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + if ( userData->vertices != NULL ) + { + free ( userData->vertices ); + } + + if ( userData->indices != NULL ) + { + free ( userData->indices ); + } + + // Delete program object + glDeleteProgram ( userData->programObject ); + + free(userData); +} + +int main ( int argc, char *argv[] ) +{ + ESContext esContext; + UserData userData; + + esInitContext ( &esContext ); + esContext.userData = &userData; + + esCreateWindow ( &esContext, "Simple Texture 2D", 320, 240, ES_WINDOW_RGB ); + + if ( !Init ( &esContext ) ) + return 0; + + esRegisterDrawFunc ( &esContext, Draw ); + esRegisterUpdateFunc ( &esContext, Update ); + + esMainLoop ( &esContext ); + + ShutDown ( &esContext ); +} + diff --git a/tests/glbook/Chapter_9/MipMap2D/MipMap2D.c b/tests/glbook/Chapter_9/MipMap2D/MipMap2D.c new file mode 100644 index 00000000..38ab38a5 --- /dev/null +++ b/tests/glbook/Chapter_9/MipMap2D/MipMap2D.c @@ -0,0 +1,348 @@ +// +// Book: OpenGL(R) ES 2.0 Programming Guide +// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner +// ISBN-10: 0321502795 +// ISBN-13: 9780321502797 +// Publisher: Addison-Wesley Professional +// URLs: http://safari.informit.com/9780321563835 +// http://www.opengles-book.com +// + +// MipMap2D.c +// +// This is a simple example that demonstrates generating a mipmap chain +// and rendering with it +// +#include <stdlib.h> +#include "esUtil.h" + +typedef struct +{ + // Handle to a program object + GLuint programObject; + + // Attribute locations + GLint positionLoc; + GLint texCoordLoc; + + // Sampler location + GLint samplerLoc; + + // Offset location + GLint offsetLoc; + + // Texture handle + GLuint textureId; + +} UserData; + + +/// +// From an RGB8 source image, generate the next level mipmap +// +GLboolean GenMipMap2D( GLubyte *src, GLubyte **dst, int srcWidth, int srcHeight, int *dstWidth, int *dstHeight ) +{ + int x, + y; + int texelSize = 3; + + *dstWidth = srcWidth / 2; + if ( *dstWidth <= 0 ) + *dstWidth = 1; + + *dstHeight = srcHeight / 2; + if ( *dstHeight <= 0 ) + *dstHeight = 1; + + *dst = malloc ( sizeof(GLubyte) * texelSize * (*dstWidth) * (*dstHeight) ); + if ( *dst == NULL ) + return GL_FALSE; + + for ( y = 0; y < *dstHeight; y++ ) + { + for( x = 0; x < *dstWidth; x++ ) + { + int srcIndex[4]; + float r = 0.0f, + g = 0.0f, + b = 0.0f; + int sample; + + // Compute the offsets for 2x2 grid of pixels in previous + // image to perform box filter + srcIndex[0] = + (((y * 2) * srcWidth) + (x * 2)) * texelSize; + srcIndex[1] = + (((y * 2) * srcWidth) + (x * 2 + 1)) * texelSize; + srcIndex[2] = + ((((y * 2) + 1) * srcWidth) + (x * 2)) * texelSize; + srcIndex[3] = + ((((y * 2) + 1) * srcWidth) + (x * 2 + 1)) * texelSize; + + // Sum all pixels + for ( sample = 0; sample < 4; sample++ ) + { + r += src[srcIndex[sample]]; + g += src[srcIndex[sample] + 1]; + b += src[srcIndex[sample] + 2]; + } + + // Average results + r /= 4.0; + g /= 4.0; + b /= 4.0; + + // Store resulting pixels + (*dst)[ ( y * (*dstWidth) + x ) * texelSize ] = (GLubyte)( r ); + (*dst)[ ( y * (*dstWidth) + x ) * texelSize + 1] = (GLubyte)( g ); + (*dst)[ ( y * (*dstWidth) + x ) * texelSize + 2] = (GLubyte)( b ); + } + } + + return GL_TRUE; +} + +/// +// Generate an RGB8 checkerboard image +// +GLubyte* GenCheckImage( int width, int height, int checkSize ) +{ + int x, + y; + GLubyte *pixels = malloc( width * height * 3 ); + + if ( pixels == NULL ) + return NULL; + + for ( y = 0; y < height; y++ ) + for ( x = 0; x < width; x++ ) + { + GLubyte rColor = 0; + GLubyte bColor = 0; + + if ( ( x / checkSize ) % 2 == 0 ) + { + rColor = 255 * ( ( y / checkSize ) % 2 ); + bColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) ); + } + else + { + bColor = 255 * ( ( y / checkSize ) % 2 ); + rColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) ); + } + + pixels[(y * height + x) * 3] = rColor; + pixels[(y * height + x) * 3 + 1] = 0; + pixels[(y * height + x) * 3 + 2] = bColor; + } + + return pixels; +} + +/// +// Create a mipmapped 2D texture image +// +GLuint CreateMipMappedTexture2D( ) +{ + // Texture object handle + GLuint textureId; + int width = 256, + height = 256; + int level; + GLubyte *pixels; + GLubyte *prevImage; + GLubyte *newImage; + + pixels = GenCheckImage( width, height, 8 ); + if ( pixels == NULL ) + return 0; + + // Generate a texture object + glGenTextures ( 1, &textureId ); + + // Bind the texture object + glBindTexture ( GL_TEXTURE_2D, textureId ); + + // Load mipmap level 0 + glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, + 0, GL_RGB, GL_UNSIGNED_BYTE, pixels ); + + level = 1; + prevImage = &pixels[0]; + + while ( width > 1 && height > 1 ) + { + int newWidth, + newHeight; + + // Generate the next mipmap level + GenMipMap2D( prevImage, &newImage, width, height, + &newWidth, &newHeight ); + + // Load the mipmap level + glTexImage2D( GL_TEXTURE_2D, level, GL_RGB, + newWidth, newHeight, 0, GL_RGB, + GL_UNSIGNED_BYTE, newImage ); + + // Free the previous image + free ( prevImage ); + + // Set the previous image for the next iteration + prevImage = newImage; + level++; + + // Half the width and height + width = newWidth; + height = newHeight; + } + + free ( newImage ); + + // Set the filtering mode + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST ); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + return textureId; + +} + + +/// +// Initialize the shader and program object +// +int Init ( ESContext *esContext ) +{ + esContext->userData = malloc(sizeof(UserData)); + + UserData *userData = esContext->userData; + GLbyte vShaderStr[] = + "uniform float u_offset; \n" + "attribute vec4 a_position; \n" + "attribute vec2 a_texCoord; \n" + "varying vec2 v_texCoord; \n" + "void main() \n" + "{ \n" + " gl_Position = a_position; \n" + " gl_Position.x += u_offset;\n" + " v_texCoord = a_texCoord; \n" + "} \n"; + + GLbyte fShaderStr[] = + "precision mediump float; \n" + "varying vec2 v_texCoord; \n" + "uniform sampler2D s_texture; \n" + "void main() \n" + "{ \n" + " gl_FragColor = texture2D( s_texture, v_texCoord );\n" + "} \n"; + + // Load the shaders and get a linked program object + userData->programObject = esLoadProgram ( vShaderStr, fShaderStr ); + + // Get the attribute locations + userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" ); + userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" ); + + // Get the sampler location + userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" ); + + // Get the offset location + userData->offsetLoc = glGetUniformLocation( userData->programObject, "u_offset" ); + + // Load the texture + userData->textureId = CreateMipMappedTexture2D (); + + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); + return GL_TRUE; +} + +/// +// Draw a triangle using the shader pair created in Init() +// +void Draw ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + GLfloat vVertices[] = { -0.5f, 0.5f, 0.0f, 1.5f, // Position 0 + 0.0f, 0.0f, // TexCoord 0 + -0.5f, -0.5f, 0.0f, 0.75f, // Position 1 + 0.0f, 1.0f, // TexCoord 1 + 0.5f, -0.5f, 0.0f, 0.75f, // Position 2 + 1.0f, 1.0f, // TexCoord 2 + 0.5f, 0.5f, 0.0f, 1.5f, // Position 3 + 1.0f, 0.0f // TexCoord 3 + }; + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; + + // Set the viewport + glViewport ( 0, 0, esContext->width, esContext->height ); + + // Clear the color buffer + glClear ( GL_COLOR_BUFFER_BIT ); + + // Use the program object + glUseProgram ( userData->programObject ); + + // Load the vertex position + glVertexAttribPointer ( userData->positionLoc, 4, GL_FLOAT, + GL_FALSE, 6 * sizeof(GLfloat), vVertices ); + // Load the texture coordinate + glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT, + GL_FALSE, 6 * sizeof(GLfloat), &vVertices[4] ); + + glEnableVertexAttribArray ( userData->positionLoc ); + glEnableVertexAttribArray ( userData->texCoordLoc ); + + // Bind the texture + glActiveTexture ( GL_TEXTURE0 ); + glBindTexture ( GL_TEXTURE_2D, userData->textureId ); + + // Set the sampler texture unit to 0 + glUniform1i ( userData->samplerLoc, 0 ); + + // Draw quad with nearest sampling + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glUniform1f ( userData->offsetLoc, -0.6f ); + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); + + // Draw quad with trilinear filtering + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); + glUniform1f ( userData->offsetLoc, 0.6f ); + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); + +} + +/// +// Cleanup +// +void ShutDown ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + // Delete texture object + glDeleteTextures ( 1, &userData->textureId ); + + // Delete program object + glDeleteProgram ( userData->programObject ); + + free(esContext->userData); +} + +int main ( int argc, char *argv[] ) +{ + ESContext esContext; + UserData userData; + + esInitContext ( &esContext ); + esContext.userData = &userData; + + esCreateWindow ( &esContext, "MipMap 2D", 320, 240, ES_WINDOW_RGB ); + + if ( !Init ( &esContext ) ) + return 0; + + esRegisterDrawFunc ( &esContext, Draw ); + + esMainLoop ( &esContext ); + + ShutDown ( &esContext ); +} diff --git a/tests/glbook/Chapter_9/Simple_Texture2D/Simple_Texture2D.c b/tests/glbook/Chapter_9/Simple_Texture2D/Simple_Texture2D.c new file mode 100644 index 00000000..5276bda4 --- /dev/null +++ b/tests/glbook/Chapter_9/Simple_Texture2D/Simple_Texture2D.c @@ -0,0 +1,213 @@ +// +// Book: OpenGL(R) ES 2.0 Programming Guide +// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner +// ISBN-10: 0321502795 +// ISBN-13: 9780321502797 +// Publisher: Addison-Wesley Professional +// URLs: http://safari.informit.com/9780321563835 +// http://www.opengles-book.com +// + +// Simple_Texture2D.c +// +// This is a simple example that draws a quad with a 2D +// texture image. The purpose of this example is to demonstrate +// the basics of 2D texturing +// +#include <stdlib.h> +#include "esUtil.h" + +typedef struct +{ + // Handle to a program object + GLuint programObject; + + // Attribute locations + GLint positionLoc; + GLint texCoordLoc; + + // Sampler location + GLint samplerLoc; + + // Texture handle + GLuint textureId; + + GLuint vertexObject, indexObject; + +} UserData; + +/// +// Create a simple 2x2 texture image with four different colors +// +GLuint CreateSimpleTexture2D( ) +{ + // Texture object handle + GLuint textureId; + + // 2x2 Image, 3 bytes per pixel (R, G, B) + GLubyte pixels[4 * 3] = + { + 255, 0, 0, // Red + 0, 255, 0, // Green + 0, 0, 255, // Blue + 255, 255, 0 // Yellow + }; + + // Use tightly packed data + glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 ); + + // Generate a texture object + glGenTextures ( 1, &textureId ); + + // Bind the texture object + glBindTexture ( GL_TEXTURE_2D, textureId ); + + // Load the texture + glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels ); + + // Set the filtering mode + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + + return textureId; + +} + + +/// +// Initialize the shader and program object +// +int Init ( ESContext *esContext ) +{ + esContext->userData = malloc(sizeof(UserData)); + UserData *userData = esContext->userData; + GLbyte vShaderStr[] = + "attribute vec4 a_position; \n" + "attribute vec2 a_texCoord; \n" + "varying vec2 v_texCoord; \n" + "void main() \n" + "{ \n" + " gl_Position = a_position; \n" + " v_texCoord = a_texCoord; \n" + "} \n"; + + GLbyte fShaderStr[] = + "precision mediump float; \n" + "varying vec2 v_texCoord; \n" + "uniform sampler2D s_texture; \n" + "void main() \n" + "{ \n" + " gl_FragColor = texture2D( s_texture, v_texCoord );\n" + "} \n"; + + // Load the shaders and get a linked program object + userData->programObject = esLoadProgram ( vShaderStr, fShaderStr ); + + // Get the attribute locations + userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" ); + userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" ); + + // Get the sampler location + userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" ); + + // Load the texture + userData->textureId = CreateSimpleTexture2D (); + + // Setup the vertex data + GLfloat vVertices[] = { -0.5, 0.5, 0.0, // Position 0 + 0.0, 0.0, // TexCoord 0 + -0.5, -0.5, 0.0, // Position 1 + 0.0, 1.0, // TexCoord 1 + 0.5, -0.5, 0.0, // Position 2 + 1.0, 1.0, // TexCoord 2 + 0.5, 0.5, 0.0, // Position 3 + 1.0, 0.0 // TexCoord 3 + }; + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; + + glGenBuffers(1, &userData->vertexObject); + glBindBuffer(GL_ARRAY_BUFFER, userData->vertexObject ); + glBufferData(GL_ARRAY_BUFFER, sizeof(vVertices), vVertices, GL_STATIC_DRAW ); + + glGenBuffers(1, &userData->indexObject); + glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->indexObject ); + glBufferData ( GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW ); + + glClearColor ( 0.0f, 0.0f, 0.0f, 1.0f ); + return GL_TRUE; +} + +/// +// Draw a triangle using the shader pair created in Init() +// +void Draw ( ESContext *esContext ) +{ + // Set the viewport + glViewport ( 0, 0, esContext->width, esContext->height ); + + // Clear the color buffer + glClear ( GL_COLOR_BUFFER_BIT ); + + UserData *userData = esContext->userData; + + // Use the program object + glUseProgram ( userData->programObject ); + + // Load the vertex position + glBindBuffer (GL_ARRAY_BUFFER, userData->vertexObject ); + glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, + GL_FALSE, 5 * 4, 0 ); + // Load the texture coordinate + glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT, + GL_FALSE, 5 * 4, + 3 * 4 ); + + glEnableVertexAttribArray ( userData->positionLoc ); + glEnableVertexAttribArray ( userData->texCoordLoc ); + + // Bind the texture + glActiveTexture ( GL_TEXTURE0 ); + glBindTexture ( GL_TEXTURE_2D, userData->textureId ); + + // Set the sampler texture unit to 0 + glUniform1i ( userData->samplerLoc, 0 ); + + glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->indexObject ); + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 ); +} + +/// +// Cleanup +// +void ShutDown ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + // Delete texture object + glDeleteTextures ( 1, &userData->textureId ); + + // Delete program object + glDeleteProgram ( userData->programObject ); + + free(esContext->userData); +} + +int main ( int argc, char *argv[] ) +{ + ESContext esContext; + UserData userData; + + esInitContext ( &esContext ); + esContext.userData = &userData; + + esCreateWindow ( &esContext, "Simple Texture 2D", 320, 240, ES_WINDOW_RGB ); + + if ( !Init ( &esContext ) ) + return 0; + + esRegisterDrawFunc ( &esContext, Draw ); + + esMainLoop ( &esContext ); + + ShutDown ( &esContext ); +} diff --git a/tests/glbook/Chapter_9/Simple_Texture2D/Simple_Texture2D_orig.c b/tests/glbook/Chapter_9/Simple_Texture2D/Simple_Texture2D_orig.c new file mode 100644 index 00000000..cc465c9a --- /dev/null +++ b/tests/glbook/Chapter_9/Simple_Texture2D/Simple_Texture2D_orig.c @@ -0,0 +1,199 @@ +// +// Book: OpenGL(R) ES 2.0 Programming Guide +// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner +// ISBN-10: 0321502795 +// ISBN-13: 9780321502797 +// Publisher: Addison-Wesley Professional +// URLs: http://safari.informit.com/9780321563835 +// http://www.opengles-book.com +// + +// Simple_Texture2D.c +// +// This is a simple example that draws a quad with a 2D +// texture image. The purpose of this example is to demonstrate +// the basics of 2D texturing +// +#include <stdlib.h> +#include "esUtil.h" + +typedef struct +{ + // Handle to a program object + GLuint programObject; + + // Attribute locations + GLint positionLoc; + GLint texCoordLoc; + + // Sampler location + GLint samplerLoc; + + // Texture handle + GLuint textureId; + +} UserData; + +/// +// Create a simple 2x2 texture image with four different colors +// +GLuint CreateSimpleTexture2D( ) +{ + // Texture object handle + GLuint textureId; + + // 2x2 Image, 3 bytes per pixel (R, G, B) + GLubyte pixels[4 * 3] = + { + 255, 0, 0, // Red + 0, 255, 0, // Green + 0, 0, 255, // Blue + 255, 255, 0 // Yellow + }; + + // Use tightly packed data + glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 ); + + // Generate a texture object + glGenTextures ( 1, &textureId ); + + // Bind the texture object + glBindTexture ( GL_TEXTURE_2D, textureId ); + + // Load the texture + glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels ); + + // Set the filtering mode + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + + return textureId; + +} + + +/// +// Initialize the shader and program object +// +int Init ( ESContext *esContext ) +{ + esContext->userData = malloc(sizeof(UserData)); + UserData *userData = esContext->userData; + GLbyte vShaderStr[] = + "attribute vec4 a_position; \n" + "attribute vec2 a_texCoord; \n" + "varying vec2 v_texCoord; \n" + "void main() \n" + "{ \n" + " gl_Position = a_position; \n" + " v_texCoord = a_texCoord; \n" + "} \n"; + + GLbyte fShaderStr[] = + "precision mediump float; \n" + "varying vec2 v_texCoord; \n" + "uniform sampler2D s_texture; \n" + "void main() \n" + "{ \n" + " gl_FragColor = texture2D( s_texture, v_texCoord );\n" + "} \n"; + + // Load the shaders and get a linked program object + userData->programObject = esLoadProgram ( vShaderStr, fShaderStr ); + + // Get the attribute locations + userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" ); + userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" ); + + // Get the sampler location + userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" ); + + // Load the texture + userData->textureId = CreateSimpleTexture2D (); + + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); + return GL_TRUE; +} + +/// +// Draw a triangle using the shader pair created in Init() +// +void Draw ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + GLfloat vVertices[] = { -0.5f, 0.5f, 0.0f, // Position 0 + 0.0f, 0.0f, // TexCoord 0 + -0.5f, -0.5f, 0.0f, // Position 1 + 0.0f, 1.0f, // TexCoord 1 + 0.5f, -0.5f, 0.0f, // Position 2 + 1.0f, 1.0f, // TexCoord 2 + 0.5f, 0.5f, 0.0f, // Position 3 + 1.0f, 0.0f // TexCoord 3 + }; + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; + + // Set the viewport + glViewport ( 0, 0, esContext->width, esContext->height ); + + // Clear the color buffer + glClear ( GL_COLOR_BUFFER_BIT ); + + // Use the program object + glUseProgram ( userData->programObject ); + + // Load the vertex position + glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, + GL_FALSE, 5 * sizeof(GLfloat), vVertices ); + // Load the texture coordinate + glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT, + GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] ); + + glEnableVertexAttribArray ( userData->positionLoc ); + glEnableVertexAttribArray ( userData->texCoordLoc ); + + // Bind the texture + glActiveTexture ( GL_TEXTURE0 ); + glBindTexture ( GL_TEXTURE_2D, userData->textureId ); + + // Set the sampler texture unit to 0 + glUniform1i ( userData->samplerLoc, 0 ); + + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); + +} + +/// +// Cleanup +// +void ShutDown ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + // Delete texture object + glDeleteTextures ( 1, &userData->textureId ); + + // Delete program object + glDeleteProgram ( userData->programObject ); + + free(esContext->userData); +} + +int main ( int argc, char *argv[] ) +{ + ESContext esContext; + UserData userData; + + esInitContext ( &esContext ); + esContext.userData = &userData; + + esCreateWindow ( &esContext, "Simple Texture 2D", 320, 240, ES_WINDOW_RGB ); + + if ( !Init ( &esContext ) ) + return 0; + + esRegisterDrawFunc ( &esContext, Draw ); + + esMainLoop ( &esContext ); + + ShutDown ( &esContext ); +} diff --git a/tests/glbook/Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap.c b/tests/glbook/Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap.c new file mode 100644 index 00000000..9f4a9017 --- /dev/null +++ b/tests/glbook/Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap.c @@ -0,0 +1,244 @@ +// +// Book: OpenGL(R) ES 2.0 Programming Guide +// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner +// ISBN-10: 0321502795 +// ISBN-13: 9780321502797 +// Publisher: Addison-Wesley Professional +// URLs: http://safari.informit.com/9780321563835 +// http://www.opengles-book.com +// + +// Simple_TextureCubemap.c +// +// This is a simple example that draws a sphere with a cubemap image applied. +// +#include <stdlib.h> +#include "esUtil.h" + +typedef struct +{ + // Handle to a program object + GLuint programObject; + + // Attribute locations + GLint positionLoc; + GLint normalLoc; + + // Sampler location + GLint samplerLoc; + + // Texture handle + GLuint textureId; + + // Vertex data + int numIndices; + GLfloat *vertices; + GLfloat *normals; + GLushort *indices; + + GLuint vertPosObject, vertNormalObject, indicesObject; +} UserData; + +/// +// Create a simple cubemap with a 1x1 face with a different +// color for each face +GLuint CreateSimpleTextureCubemap( ) +{ + GLuint textureId; + // Six 1x1 RGB faces + GLubyte cubePixels[6][3] = + { + // Face 0 - Red + 255, 0, 0, + // Face 1 - Green, + 0, 255, 0, + // Face 3 - Blue + 0, 0, 255, + // Face 4 - Yellow + 255, 255, 0, + // Face 5 - Purple + 255, 0, 255, + // Face 6 - White + 255, 255, 255 + }; + + // Generate a texture object + glGenTextures ( 1, &textureId ); + + // Bind the texture object + glBindTexture ( GL_TEXTURE_CUBE_MAP, textureId ); + + // Load the cube face - Positive X + glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, 1, 1, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[0] ); + + // Load the cube face - Negative X + glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, 1, 1, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[1] ); + + // Load the cube face - Positive Y + glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, 1, 1, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[2] ); + + // Load the cube face - Negative Y + glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, 1, 1, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[3] ); + + // Load the cube face - Positive Z + glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, 1, 1, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[4] ); + + // Load the cube face - Negative Z + glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, 1, 1, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[5] ); + + // Set the filtering mode + glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + + return textureId; + +} + +#include <stdio.h> +/// +// Initialize the shader and program object +// +int Init ( ESContext *esContext ) +{ + //esContext->userData = malloc(sizeof(UserData)); + UserData *userData = esContext->userData; + GLbyte vShaderStr[] = + "attribute vec4 a_position; \n" + "attribute vec3 a_normal; \n" + "varying vec3 v_normal; \n" + "void main() \n" + "{ \n" + " gl_Position = a_position; \n" + " v_normal = a_normal; \n" + "} \n"; + + GLbyte fShaderStr[] = + "precision mediump float; \n" + "varying vec3 v_normal; \n" + "uniform samplerCube s_texture; \n" + "void main() \n" + "{ \n" + " gl_FragColor = textureCube( s_texture, v_normal );\n" + "} \n"; + + // Load the shaders and get a linked program object + userData->programObject = esLoadProgram ( vShaderStr, fShaderStr ); + + // Get the attribute locations + userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" ); + userData->normalLoc = glGetAttribLocation ( userData->programObject, "a_normal" ); + + // Get the sampler locations + userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" ); + + // Load the texture + userData->textureId = CreateSimpleTextureCubemap (); + + // Generate the vertex data + userData->numIndices = esGenSphere ( 20, 0.75f, &userData->vertices, &userData->normals, + NULL, &userData->indices ); + + // Generate the VBOs + glGenBuffers(1, &userData->vertPosObject); + glBindBuffer(GL_ARRAY_BUFFER, userData->vertPosObject); + glBufferData(GL_ARRAY_BUFFER, 21 * 21 * 4 * 3, userData->vertices, GL_STATIC_DRAW ); + + glGenBuffers(1, &userData->vertNormalObject); + glBindBuffer(GL_ARRAY_BUFFER, userData->vertNormalObject ); + glBufferData(GL_ARRAY_BUFFER, 21 * 21 * 4 * 3, userData->normals, GL_STATIC_DRAW ); + + glGenBuffers(1, &userData->indicesObject); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->indicesObject ); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, 2 * userData->numIndices, userData->indices, GL_STATIC_DRAW ); + + glClearColor ( 0.0f, 0.0f, 0.0f, 1.0f ); + return GL_TRUE; +} + +/// +// Draw a triangle using the shader pair created in Init() +// +void Draw ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + // Set the viewport + glViewport ( 0, 0, esContext->width, esContext->height ); + + // Clear the color buffer + glClear ( GL_COLOR_BUFFER_BIT ); + + glCullFace ( GL_BACK ); + glEnable ( GL_CULL_FACE ); + + // Use the program object + glUseProgram ( userData->programObject ); + + // Load the vertex position + glBindBuffer ( GL_ARRAY_BUFFER, userData->vertPosObject ); + glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, + GL_FALSE, 0, 0 ); + // Load the normal + glBindBuffer ( GL_ARRAY_BUFFER, userData->vertNormalObject ); + glVertexAttribPointer ( userData->normalLoc, 3, GL_FLOAT, + GL_FALSE, 0, 0 ); + + glEnableVertexAttribArray ( userData->positionLoc ); + glEnableVertexAttribArray ( userData->normalLoc ); + + // Bind the texture + glActiveTexture ( GL_TEXTURE0 ); + glBindTexture ( GL_TEXTURE_CUBE_MAP, userData->textureId ); + + // Set the sampler texture unit to 0 + glUniform1i ( userData->samplerLoc, 0 ); + + glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->indicesObject ); + glDrawElements ( GL_TRIANGLES, userData->numIndices, + GL_UNSIGNED_SHORT, 0 ); +} + +/// +// Cleanup +// +void ShutDown ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + // Delete texture object + glDeleteTextures ( 1, &userData->textureId ); + + // Delete program object + glDeleteProgram ( userData->programObject ); + + free ( userData->vertices ); + free ( userData->normals ); + + //free ( esContext->userData); +} + +int main ( int argc, char *argv[] ) +{ + ESContext esContext; + UserData userData; + + esInitContext ( &esContext ); + esContext.userData = &userData; + + esCreateWindow ( &esContext, "Simple Texture Cubemap", 320, 240, ES_WINDOW_RGB ); + + if ( !Init ( &esContext ) ) + return 0; + + esRegisterDrawFunc ( &esContext, Draw ); + + esMainLoop ( &esContext ); + + ShutDown ( &esContext ); +} diff --git a/tests/glbook/Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap_orig.c b/tests/glbook/Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap_orig.c new file mode 100644 index 00000000..b981d943 --- /dev/null +++ b/tests/glbook/Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap_orig.c @@ -0,0 +1,227 @@ +// +// Book: OpenGL(R) ES 2.0 Programming Guide +// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner +// ISBN-10: 0321502795 +// ISBN-13: 9780321502797 +// Publisher: Addison-Wesley Professional +// URLs: http://safari.informit.com/9780321563835 +// http://www.opengles-book.com +// + +// Simple_TextureCubemap.c +// +// This is a simple example that draws a sphere with a cubemap image applied. +// +#include <stdlib.h> +#include "esUtil.h" + +typedef struct +{ + // Handle to a program object + GLuint programObject; + + // Attribute locations + GLint positionLoc; + GLint normalLoc; + + // Sampler location + GLint samplerLoc; + + // Texture handle + GLuint textureId; + + // Vertex data + int numIndices; + GLfloat *vertices; + GLfloat *normals; + GLuint *indices; + +} UserData; + +/// +// Create a simple cubemap with a 1x1 face with a different +// color for each face +GLuint CreateSimpleTextureCubemap( ) +{ + GLuint textureId; + // Six 1x1 RGB faces + GLubyte cubePixels[6][3] = + { + // Face 0 - Red + 255, 0, 0, + // Face 1 - Green, + 0, 255, 0, + // Face 3 - Blue + 0, 0, 255, + // Face 4 - Yellow + 255, 255, 0, + // Face 5 - Purple + 255, 0, 255, + // Face 6 - White + 255, 255, 255 + }; + + // Generate a texture object + glGenTextures ( 1, &textureId ); + + // Bind the texture object + glBindTexture ( GL_TEXTURE_CUBE_MAP, textureId ); + + // Load the cube face - Positive X + glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, 1, 1, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[0] ); + + // Load the cube face - Negative X + glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, 1, 1, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[1] ); + + // Load the cube face - Positive Y + glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, 1, 1, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[2] ); + + // Load the cube face - Negative Y + glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, 1, 1, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[3] ); + + // Load the cube face - Positive Z + glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, 1, 1, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[4] ); + + // Load the cube face - Negative Z + glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, 1, 1, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[5] ); + + // Set the filtering mode + glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + + return textureId; + +} + +#include <stdio.h> +/// +// Initialize the shader and program object +// +int Init ( ESContext *esContext ) +{ + //esContext->userData = malloc(sizeof(UserData)); + UserData *userData = esContext->userData; + GLbyte vShaderStr[] = + "attribute vec4 a_position; \n" + "attribute vec3 a_normal; \n" + "varying vec3 v_normal; \n" + "void main() \n" + "{ \n" + " gl_Position = a_position; \n" + " v_normal = a_normal; \n" + "} \n"; + + GLbyte fShaderStr[] = + "precision mediump float; \n" + "varying vec3 v_normal; \n" + "uniform samplerCube s_texture; \n" + "void main() \n" + "{ \n" + " gl_FragColor = textureCube( s_texture, v_normal );\n" + "} \n"; + + // Load the shaders and get a linked program object + userData->programObject = esLoadProgram ( vShaderStr, fShaderStr ); + + // Get the attribute locations + userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" ); + userData->normalLoc = glGetAttribLocation ( userData->programObject, "a_normal" ); + + // Get the sampler locations + userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" ); + + // Load the texture + userData->textureId = CreateSimpleTextureCubemap (); + + // Generate the vertex data + userData->numIndices = esGenSphere ( 20, 0.75f, &userData->vertices, &userData->normals, + NULL, &userData->indices ); + + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); + return GL_TRUE; +} + +/// +// Draw a triangle using the shader pair created in Init() +// +void Draw ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + // Set the viewport + glViewport ( 0, 0, esContext->width, esContext->height ); + + // Clear the color buffer + glClear ( GL_COLOR_BUFFER_BIT ); + + glCullFace ( GL_BACK ); + glEnable ( GL_CULL_FACE ); + + // Use the program object + glUseProgram ( userData->programObject ); + + // Load the vertex position + glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, + GL_FALSE, 0, userData->vertices ); + // Load the normal + glVertexAttribPointer ( userData->normalLoc, 3, GL_FLOAT, + GL_FALSE, 0, userData->normals ); + + glEnableVertexAttribArray ( userData->positionLoc ); + glEnableVertexAttribArray ( userData->normalLoc ); + + // Bind the texture + glActiveTexture ( GL_TEXTURE0 ); + glBindTexture ( GL_TEXTURE_CUBE_MAP, userData->textureId ); + + // Set the sampler texture unit to 0 + glUniform1i ( userData->samplerLoc, 0 ); + + glDrawElements ( GL_TRIANGLES, userData->numIndices, + GL_UNSIGNED_INT, userData->indices ); +} + +/// +// Cleanup +// +void ShutDown ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + // Delete texture object + glDeleteTextures ( 1, &userData->textureId ); + + // Delete program object + glDeleteProgram ( userData->programObject ); + + free ( userData->vertices ); + free ( userData->normals ); + + //free ( esContext->userData); +} + +int main ( int argc, char *argv[] ) +{ + ESContext esContext; + UserData userData; + + esInitContext ( &esContext ); + esContext.userData = &userData; + + esCreateWindow ( &esContext, "Simple Texture Cubemap", 320, 240, ES_WINDOW_RGB ); + + if ( !Init ( &esContext ) ) + return 0; + + esRegisterDrawFunc ( &esContext, Draw ); + + esMainLoop ( &esContext ); + + ShutDown ( &esContext ); +} diff --git a/tests/glbook/Chapter_9/TextureWrap/TextureWrap.c b/tests/glbook/Chapter_9/TextureWrap/TextureWrap.c new file mode 100644 index 00000000..30f39444 --- /dev/null +++ b/tests/glbook/Chapter_9/TextureWrap/TextureWrap.c @@ -0,0 +1,275 @@ +// +// Book: OpenGL(R) ES 2.0 Programming Guide +// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner +// ISBN-10: 0321502795 +// ISBN-13: 9780321502797 +// Publisher: Addison-Wesley Professional +// URLs: http://safari.informit.com/9780321563835 +// http://www.opengles-book.com +// + +// TextureWrap.c +// +// This is an example that demonstrates the three texture +// wrap modes available on 2D textures +// +#include <stdlib.h> +#include "esUtil.h" + +typedef struct +{ + // Handle to a program object + GLuint programObject; + + // Attribute locations + GLint positionLoc; + GLint texCoordLoc; + + // Sampler location + GLint samplerLoc; + + // Offset location + GLint offsetLoc; + + // Texture handle + GLuint textureId; + + GLuint vertexObject, indexObject; + +} UserData; + +/// +// Generate an RGB8 checkerboard image +// +GLubyte* GenCheckImage( int width, int height, int checkSize ) +{ + int x, + y; + GLubyte *pixels = malloc( width * height * 3 ); + + if ( pixels == NULL ) + return NULL; + + for ( y = 0; y < height; y++ ) + for ( x = 0; x < width; x++ ) + { + GLubyte rColor = 0; + GLubyte bColor = 0; + + if ( ( x / checkSize ) % 2 == 0 ) + { + rColor = 255 * ( ( y / checkSize ) % 2 ); + bColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) ); + } + else + { + bColor = 255 * ( ( y / checkSize ) % 2 ); + rColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) ); + } + + pixels[(y * height + x) * 3] = rColor; + pixels[(y * height + x) * 3 + 1] = 0; + pixels[(y * height + x) * 3 + 2] = bColor; + } + + return pixels; +} + +/// +// Create a mipmapped 2D texture image +// +GLuint CreateTexture2D( ) +{ + // Texture object handle + GLuint textureId; + int width = 256, + height = 256; + GLubyte *pixels; + + pixels = GenCheckImage( width, height, 64 ); + if ( pixels == NULL ) + return 0; + + // Use tightly packed data + glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 ); + + // Generate a texture object + glGenTextures ( 1, &textureId ); + + // Bind the texture object + glBindTexture ( GL_TEXTURE_2D, textureId ); + + // Load mipmap level 0 + glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, + 0, GL_RGB, GL_UNSIGNED_BYTE, pixels ); + + // Set the filtering mode + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + return textureId; + +} + + +/// +// Initialize the shader and program object +// +int Init ( ESContext *esContext ) +{ + esContext->userData = malloc(sizeof(UserData)); + + UserData *userData = esContext->userData; + GLbyte vShaderStr[] = + "uniform float u_offset; \n" + "attribute vec4 a_position; \n" + "attribute vec2 a_texCoord; \n" + "varying vec2 v_texCoord; \n" + "void main() \n" + "{ \n" + " gl_Position = a_position; \n" + " gl_Position.x += u_offset;\n" + " v_texCoord = a_texCoord; \n" + "} \n"; + + GLbyte fShaderStr[] = + "precision mediump float; \n" + "varying vec2 v_texCoord; \n" + "uniform sampler2D s_texture; \n" + "void main() \n" + "{ \n" + " gl_FragColor = texture2D( s_texture, v_texCoord );\n" + "} \n"; + + // Load the shaders and get a linked program object + userData->programObject = esLoadProgram ( vShaderStr, fShaderStr ); + + // Get the attribute locations + userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" ); + userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" ); + + // Get the sampler location + userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" ); + + // Get the offset location + userData->offsetLoc = glGetUniformLocation( userData->programObject, "u_offset" ); + + // Load the texture + userData->textureId = CreateTexture2D (); + + // Setup the vertex data + GLfloat vVertices[] = { -0.3, 0.3, 0.0, 1.0, // Position 0 + -1.0, -1.0, // TexCoord 0 + -0.3, -0.3, 0.0, 1.0, // Position 1 + -1.0, 2.0, // TexCoord 1 + 0.3, -0.3, 0.0, 1.0, // Position 2 + 2.0, 2.0, // TexCoord 2 + 0.3, 0.3, 0.0, 1.0, // Position 3 + 2.0, -1.0 // TexCoord 3 + }; + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; + + glGenBuffers(1, &userData->vertexObject); + glBindBuffer ( GL_ARRAY_BUFFER, userData->vertexObject ); + glBufferData ( GL_ARRAY_BUFFER, 6 * 4 * 4, vVertices, GL_STATIC_DRAW ); + + glGenBuffers(1, &userData->indexObject); + glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->indexObject ); + glBufferData ( GL_ELEMENT_ARRAY_BUFFER, 6 * 2, indices, GL_STATIC_DRAW ); + + glClearColor ( 0.0, 0.0, 0.0, 1.0 ); + + return GL_TRUE; +} + +/// +// Draw a triangle using the shader pair created in Init() +// +void Draw ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + // Set the viewport + glViewport ( 0, 0, esContext->width, esContext->height ); + + // Clear the color buffer + glClear ( GL_COLOR_BUFFER_BIT ); + + // Use the program object + glUseProgram ( userData->programObject ); + + // Load the vertex position + glBindBuffer ( GL_ARRAY_BUFFER, userData->vertexObject ); + glVertexAttribPointer ( userData->positionLoc, 4, GL_FLOAT, + GL_FALSE, 6 * sizeof(GLfloat), 0 ); + // Load the texture coordinate + glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT, + GL_FALSE, 6 * sizeof(GLfloat), 4 * sizeof(GLfloat) ); + + glEnableVertexAttribArray ( userData->positionLoc ); + glEnableVertexAttribArray ( userData->texCoordLoc ); + + // Bind the texture + glActiveTexture ( GL_TEXTURE0 ); + glBindTexture ( GL_TEXTURE_2D, userData->textureId ); + + // Set the sampler texture unit to 0 + glUniform1i ( userData->samplerLoc, 0 ); + + // Draw quad with repeat wrap mode + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + glUniform1f ( userData->offsetLoc, -0.7f ); + glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->indexObject ); + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 ); + + // Draw quad with clamp to edge wrap mode + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + glUniform1f ( userData->offsetLoc, 0.0f ); + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 ); + + // Draw quad with mirrored repeat + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT ); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT ); + glUniform1f ( userData->offsetLoc, 0.7f ); + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 ); + +} + +/// +// Cleanup +// +void ShutDown ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + // Delete texture object + glDeleteTextures ( 1, &userData->textureId ); + + // Delete program object + glDeleteProgram ( userData->programObject ); + + free ( esContext->userData); +} + +int main ( int argc, char *argv[] ) +{ + ESContext esContext; + UserData userData; + + esInitContext ( &esContext ); + esContext.userData = &userData; + + esCreateWindow ( &esContext, "MipMap 2D", 320, 240, ES_WINDOW_RGB ); + + if ( !Init ( &esContext ) ) + return 0; + + esRegisterDrawFunc ( &esContext, Draw ); + + esMainLoop ( &esContext ); + + ShutDown ( &esContext ); +} + diff --git a/tests/glbook/Chapter_9/TextureWrap/TextureWrap_orig.c b/tests/glbook/Chapter_9/TextureWrap/TextureWrap_orig.c new file mode 100644 index 00000000..fe22282f --- /dev/null +++ b/tests/glbook/Chapter_9/TextureWrap/TextureWrap_orig.c @@ -0,0 +1,257 @@ +// +// Book: OpenGL(R) ES 2.0 Programming Guide +// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner +// ISBN-10: 0321502795 +// ISBN-13: 9780321502797 +// Publisher: Addison-Wesley Professional +// URLs: http://safari.informit.com/9780321563835 +// http://www.opengles-book.com +// + +// TextureWrap.c +// +// This is an example that demonstrates the three texture +// wrap modes available on 2D textures +// +#include <stdlib.h> +#include "esUtil.h" + +typedef struct +{ + // Handle to a program object + GLuint programObject; + + // Attribute locations + GLint positionLoc; + GLint texCoordLoc; + + // Sampler location + GLint samplerLoc; + + // Offset location + GLint offsetLoc; + + // Texture handle + GLuint textureId; + +} UserData; + +/// +// Generate an RGB8 checkerboard image +// +GLubyte* GenCheckImage( int width, int height, int checkSize ) +{ + int x, + y; + GLubyte *pixels = malloc( width * height * 3 ); + + if ( pixels == NULL ) + return NULL; + + for ( y = 0; y < height; y++ ) + for ( x = 0; x < width; x++ ) + { + GLubyte rColor = 0; + GLubyte bColor = 0; + + if ( ( x / checkSize ) % 2 == 0 ) + { + rColor = 255 * ( ( y / checkSize ) % 2 ); + bColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) ); + } + else + { + bColor = 255 * ( ( y / checkSize ) % 2 ); + rColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) ); + } + + pixels[(y * height + x) * 3] = rColor; + pixels[(y * height + x) * 3 + 1] = 0; + pixels[(y * height + x) * 3 + 2] = bColor; + } + + return pixels; +} + +/// +// Create a mipmapped 2D texture image +// +GLuint CreateTexture2D( ) +{ + // Texture object handle + GLuint textureId; + int width = 256, + height = 256; + GLubyte *pixels; + + pixels = GenCheckImage( width, height, 64 ); + if ( pixels == NULL ) + return 0; + + // Generate a texture object + glGenTextures ( 1, &textureId ); + + // Bind the texture object + glBindTexture ( GL_TEXTURE_2D, textureId ); + + // Load mipmap level 0 + glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, + 0, GL_RGB, GL_UNSIGNED_BYTE, pixels ); + + // Set the filtering mode + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + return textureId; + +} + + +/// +// Initialize the shader and program object +// +int Init ( ESContext *esContext ) +{ + esContext->userData = malloc(sizeof(UserData)); + + UserData *userData = esContext->userData; + GLbyte vShaderStr[] = + "uniform float u_offset; \n" + "attribute vec4 a_position; \n" + "attribute vec2 a_texCoord; \n" + "varying vec2 v_texCoord; \n" + "void main() \n" + "{ \n" + " gl_Position = a_position; \n" + " gl_Position.x += u_offset;\n" + " v_texCoord = a_texCoord; \n" + "} \n"; + + GLbyte fShaderStr[] = + "precision mediump float; \n" + "varying vec2 v_texCoord; \n" + "uniform sampler2D s_texture; \n" + "void main() \n" + "{ \n" + " gl_FragColor = texture2D( s_texture, v_texCoord );\n" + "} \n"; + + // Load the shaders and get a linked program object + userData->programObject = esLoadProgram ( vShaderStr, fShaderStr ); + + // Get the attribute locations + userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" ); + userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" ); + + // Get the sampler location + userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" ); + + // Get the offset location + userData->offsetLoc = glGetUniformLocation( userData->programObject, "u_offset" ); + + // Load the texture + userData->textureId = CreateTexture2D (); + + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); + return GL_TRUE; +} + +/// +// Draw a triangle using the shader pair created in Init() +// +void Draw ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + GLfloat vVertices[] = { -0.3f, 0.3f, 0.0f, 1.0f, // Position 0 + -1.0f, -1.0f, // TexCoord 0 + -0.3f, -0.3f, 0.0f, 1.0f, // Position 1 + -1.0f, 2.0f, // TexCoord 1 + 0.3f, -0.3f, 0.0f, 1.0f, // Position 2 + 2.0f, 2.0f, // TexCoord 2 + 0.3f, 0.3f, 0.0f, 1.0f, // Position 3 + 2.0f, -1.0f // TexCoord 3 + }; + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; + + // Set the viewport + glViewport ( 0, 0, esContext->width, esContext->height ); + + // Clear the color buffer + glClear ( GL_COLOR_BUFFER_BIT ); + + // Use the program object + glUseProgram ( userData->programObject ); + + // Load the vertex position + glVertexAttribPointer ( userData->positionLoc, 4, GL_FLOAT, + GL_FALSE, 6 * sizeof(GLfloat), vVertices ); + // Load the texture coordinate + glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT, + GL_FALSE, 6 * sizeof(GLfloat), &vVertices[4] ); + + glEnableVertexAttribArray ( userData->positionLoc ); + glEnableVertexAttribArray ( userData->texCoordLoc ); + + // Bind the texture + glActiveTexture ( GL_TEXTURE0 ); + glBindTexture ( GL_TEXTURE_2D, userData->textureId ); + + // Set the sampler texture unit to 0 + glUniform1i ( userData->samplerLoc, 0 ); + + // Draw quad with repeat wrap mode + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + glUniform1f ( userData->offsetLoc, -0.7f ); + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); + + // Draw quad with clamp to edge wrap mode + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + glUniform1f ( userData->offsetLoc, 0.0f ); + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); + + // Draw quad with mirrored repeat + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT ); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT ); + glUniform1f ( userData->offsetLoc, 0.7f ); + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); + +} + +/// +// Cleanup +// +void ShutDown ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + + // Delete texture object + glDeleteTextures ( 1, &userData->textureId ); + + // Delete program object + glDeleteProgram ( userData->programObject ); + + free ( esContext->userData); +} + +int main ( int argc, char *argv[] ) +{ + ESContext esContext; + UserData userData; + + esInitContext ( &esContext ); + esContext.userData = &userData; + + esCreateWindow ( &esContext, "MipMap 2D", 640, 480, ES_WINDOW_RGB ); + + if ( !Init ( &esContext ) ) + return 0; + + esRegisterDrawFunc ( &esContext, Draw ); + + esMainLoop ( &esContext ); + + ShutDown ( &esContext ); +} + diff --git a/tests/glbook/Common/esShader.c b/tests/glbook/Common/esShader.c new file mode 100644 index 00000000..4ea2cbcb --- /dev/null +++ b/tests/glbook/Common/esShader.c @@ -0,0 +1,155 @@ +//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// ESShader.c
+//
+// Utility functions for loading shaders and creating program objects.
+//
+
+///
+// Includes
+//
+#include "esUtil.h"
+#include <stdlib.h>
+
+//////////////////////////////////////////////////////////////////
+//
+// Private Functions
+//
+//
+
+
+
+//////////////////////////////////////////////////////////////////
+//
+// Public Functions
+//
+//
+
+//
+///
+/// \brief Load a shader, check for compile errors, print error messages to output log
+/// \param type Type of shader (GL_VERTEX_SHADER or GL_FRAGMENT_SHADER)
+/// \param shaderSrc Shader source string
+/// \return A new shader object on success, 0 on failure
+//
+GLuint ESUTIL_API esLoadShader ( GLenum type, const char *shaderSrc )
+{
+ GLuint shader;
+ GLint compiled;
+
+ // Create the shader object
+ shader = glCreateShader ( type );
+
+ if ( shader == 0 )
+ return 0;
+
+ // Load the shader source
+ glShaderSource ( shader, 1, &shaderSrc, NULL );
+
+ // Compile the shader
+ glCompileShader ( shader );
+
+ // Check the compile status
+ glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
+
+ if ( !compiled )
+ {
+ GLint infoLen = 0;
+
+ glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
+
+ if ( infoLen > 1 )
+ {
+ char* infoLog = malloc (sizeof(char) * infoLen );
+
+ glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
+ esLogMessage ( "Error compiling shader:\n%s\n", infoLog );
+
+ free ( infoLog );
+ }
+
+ glDeleteShader ( shader );
+ return 0;
+ }
+
+ return shader;
+
+}
+
+
+//
+///
+/// \brief Load a vertex and fragment shader, create a program object, link program.
+// Errors output to log.
+/// \param vertShaderSrc Vertex shader source code
+/// \param fragShaderSrc Fragment shader source code
+/// \return A new program object linked with the vertex/fragment shader pair, 0 on failure
+//
+GLuint ESUTIL_API esLoadProgram ( const char *vertShaderSrc, const char *fragShaderSrc )
+{
+ GLuint vertexShader;
+ GLuint fragmentShader;
+ GLuint programObject;
+ GLint linked;
+
+ // Load the vertex/fragment shaders
+ vertexShader = esLoadShader ( GL_VERTEX_SHADER, vertShaderSrc );
+ if ( vertexShader == 0 )
+ return 0;
+
+ fragmentShader = esLoadShader ( GL_FRAGMENT_SHADER, fragShaderSrc );
+ if ( fragmentShader == 0 )
+ {
+ glDeleteShader( vertexShader );
+ return 0;
+ }
+
+ // Create the program object
+ programObject = glCreateProgram ( );
+
+ if ( programObject == 0 )
+ return 0;
+
+ glAttachShader ( programObject, vertexShader );
+ glAttachShader ( programObject, fragmentShader );
+
+ // Link the program
+ glLinkProgram ( programObject );
+
+ // Check the link status
+ glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
+
+ if ( !linked )
+ {
+ GLint infoLen = 0;
+
+ glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
+
+ if ( infoLen > 1 )
+ {
+ char* infoLog = malloc (sizeof(char) * infoLen );
+
+ glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
+ esLogMessage ( "Error linking program:\n%s\n", infoLog );
+
+ free ( infoLog );
+ }
+
+ glDeleteProgram ( programObject );
+ return 0;
+ }
+
+ // Free up no longer needed shader resources
+ glDeleteShader ( vertexShader );
+ glDeleteShader ( fragmentShader );
+
+ return programObject;
+}
\ No newline at end of file diff --git a/tests/glbook/Common/esShapes.c b/tests/glbook/Common/esShapes.c new file mode 100644 index 00000000..6a8ab7ad --- /dev/null +++ b/tests/glbook/Common/esShapes.c @@ -0,0 +1,280 @@ +// +// Book: OpenGL(R) ES 2.0 Programming Guide +// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner +// ISBN-10: 0321502795 +// ISBN-13: 9780321502797 +// Publisher: Addison-Wesley Professional +// URLs: http://safari.informit.com/9780321563835 +// http://www.opengles-book.com +// + +// ESShapes.c +// +// Utility functions for generating shapes +// + +/// +// Includes +// +#include "esUtil.h" +#include <stdlib.h> +#include <math.h> +#include <string.h> + +/// +// Defines +// +#define ES_PI (3.14159265f) + +////////////////////////////////////////////////////////////////// +// +// Private Functions +// +// + + + +////////////////////////////////////////////////////////////////// +// +// Public Functions +// +// + +// +/// \brief Generates geometry for a sphere. Allocates memory for the vertex data and stores +/// the results in the arrays. Generate index list for a TRIANGLE_STRIP +/// \param numSlices The number of slices in the sphere +/// \param vertices If not NULL, will contain array of float3 positions +/// \param normals If not NULL, will contain array of float3 normals +/// \param texCoords If not NULL, will contain array of float2 texCoords +/// \param indices If not NULL, will contain the array of indices for the triangle strip +/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array +/// if it is not NULL ) as a GL_TRIANGLE_STRIP +// +int ESUTIL_API esGenSphere ( int numSlices, float radius, GLfloat **vertices, GLfloat **normals, + GLfloat **texCoords, GLushort **indices ) +{ + int i; + int j; + int numParallels = numSlices; + int numVertices = ( numParallels + 1 ) * ( numSlices + 1 ); + int numIndices = numParallels * numSlices * 6; + float angleStep = (2.0f * ES_PI) / ((float) numSlices); + + // Allocate memory for buffers + if ( vertices != NULL ) + *vertices = malloc ( sizeof(GLfloat) * 3 * numVertices ); + + if ( normals != NULL ) + *normals = malloc ( sizeof(GLfloat) * 3 * numVertices ); + + if ( texCoords != NULL ) + *texCoords = malloc ( sizeof(GLfloat) * 2 * numVertices ); + + if ( indices != NULL ) + *indices = malloc ( sizeof(GLushort) * numIndices ); + + for ( i = 0; i < numParallels + 1; i++ ) + { + for ( j = 0; j < numSlices + 1; j++ ) + { + int vertex = ( i * (numSlices + 1) + j ) * 3; + + if ( vertices ) + { + (*vertices)[vertex + 0] = radius * sinf ( angleStep * (float)i ) * + sinf ( angleStep * (float)j ); + (*vertices)[vertex + 1] = radius * cosf ( angleStep * (float)i ); + (*vertices)[vertex + 2] = radius * sinf ( angleStep * (float)i ) * + cosf ( angleStep * (float)j ); + } + + if ( normals ) + { + (*normals)[vertex + 0] = (*vertices)[vertex + 0] / radius; + (*normals)[vertex + 1] = (*vertices)[vertex + 1] / radius; + (*normals)[vertex + 2] = (*vertices)[vertex + 2] / radius; + } + + if ( texCoords ) + { + int texIndex = ( i * (numSlices + 1) + j ) * 2; + (*texCoords)[texIndex + 0] = (float) j / (float) numSlices; + (*texCoords)[texIndex + 1] = ( 1.0f - (float) i ) / (float) (numParallels - 1 ); + } + } + } + + // Generate the indices + if ( indices != NULL ) + { + GLushort *indexBuf = (*indices); + for ( i = 0; i < numParallels ; i++ ) + { + for ( j = 0; j < numSlices; j++ ) + { + *indexBuf++ = i * ( numSlices + 1 ) + j; + *indexBuf++ = ( i + 1 ) * ( numSlices + 1 ) + j; + *indexBuf++ = ( i + 1 ) * ( numSlices + 1 ) + ( j + 1 ); + + *indexBuf++ = i * ( numSlices + 1 ) + j; + *indexBuf++ = ( i + 1 ) * ( numSlices + 1 ) + ( j + 1 ); + *indexBuf++ = i * ( numSlices + 1 ) + ( j + 1 ); + } + } + } + + return numIndices; +} + +// +/// \brief Generates geometry for a cube. Allocates memory for the vertex data and stores +/// the results in the arrays. Generate index list for a TRIANGLES +/// \param scale The size of the cube, use 1.0 for a unit cube. +/// \param vertices If not NULL, will contain array of float3 positions +/// \param normals If not NULL, will contain array of float3 normals +/// \param texCoords If not NULL, will contain array of float2 texCoords +/// \param indices If not NULL, will contain the array of indices for the triangle strip +/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array +/// if it is not NULL ) as a GL_TRIANGLE_STRIP +// +int ESUTIL_API esGenCube ( float scale, GLfloat **vertices, GLfloat **normals, + GLfloat **texCoords, GLushort **indices ) +{ + int i; + int numVertices = 24; + int numIndices = 36; + + GLfloat cubeVerts[] = + { + -0.5f, -0.5f, -0.5f, + -0.5f, -0.5f, 0.5f, + 0.5f, -0.5f, 0.5f, + 0.5f, -0.5f, -0.5f, + -0.5f, 0.5f, -0.5f, + -0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, -0.5f, + -0.5f, -0.5f, -0.5f, + -0.5f, 0.5f, -0.5f, + 0.5f, 0.5f, -0.5f, + 0.5f, -0.5f, -0.5f, + -0.5f, -0.5f, 0.5f, + -0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, + 0.5f, -0.5f, 0.5f, + -0.5f, -0.5f, -0.5f, + -0.5f, -0.5f, 0.5f, + -0.5f, 0.5f, 0.5f, + -0.5f, 0.5f, -0.5f, + 0.5f, -0.5f, -0.5f, + 0.5f, -0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, -0.5f, + }; + + GLfloat cubeNormals[] = + { + 0.0f, -1.0f, 0.0f, + 0.0f, -1.0f, 0.0f, + 0.0f, -1.0f, 0.0f, + 0.0f, -1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, -1.0f, + 0.0f, 0.0f, -1.0f, + 0.0f, 0.0f, -1.0f, + 0.0f, 0.0f, -1.0f, + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, + -1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + }; + + GLfloat cubeTex[] = + { + 0.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, + 0.0f, 1.0f, + 0.0f, 0.0f, + 0.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.0f, + 0.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.0f, + 0.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.0f, + 0.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, 0.0f, + }; + + // Allocate memory for buffers + if ( vertices != NULL ) + { + *vertices = malloc ( sizeof(GLfloat) * 3 * numVertices ); + memcpy( *vertices, cubeVerts, sizeof( cubeVerts ) ); + for ( i = 0; i < numVertices * 3; i++ ) + { + (*vertices)[i] *= scale; + } + } + + if ( normals != NULL ) + { + *normals = malloc ( sizeof(GLfloat) * 3 * numVertices ); + memcpy( *normals, cubeNormals, sizeof( cubeNormals ) ); + } + + if ( texCoords != NULL ) + { + *texCoords = malloc ( sizeof(GLfloat) * 2 * numVertices ); + memcpy( *texCoords, cubeTex, sizeof( cubeTex ) ) ; + } + + + // Generate the indices + if ( indices != NULL ) + { + GLushort cubeIndices[] = + { + 0, 2, 1, + 0, 3, 2, + 4, 5, 6, + 4, 6, 7, + 8, 9, 10, + 8, 10, 11, + 12, 15, 14, + 12, 14, 13, + 16, 17, 18, + 16, 18, 19, + 20, 23, 22, + 20, 22, 21 + }; + + *indices = malloc ( sizeof(GLushort) * numIndices ); + memcpy( *indices, cubeIndices, sizeof( cubeIndices ) ); + } + + return numIndices; +} diff --git a/tests/glbook/Common/esTransform.c b/tests/glbook/Common/esTransform.c new file mode 100644 index 00000000..5182218c --- /dev/null +++ b/tests/glbook/Common/esTransform.c @@ -0,0 +1,213 @@ +//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// ESUtil.c
+//
+// A utility library for OpenGL ES. This library provides a
+// basic common framework for the example applications in the
+// OpenGL ES 2.0 Programming Guide.
+//
+
+///
+// Includes
+//
+#include "esUtil.h"
+#include <math.h>
+#include <string.h>
+
+#define PI 3.1415926535897932384626433832795f
+
+void ESUTIL_API
+esScale(ESMatrix *result, GLfloat sx, GLfloat sy, GLfloat sz)
+{
+ result->m[0][0] *= sx;
+ result->m[0][1] *= sx;
+ result->m[0][2] *= sx;
+ result->m[0][3] *= sx;
+
+ result->m[1][0] *= sy;
+ result->m[1][1] *= sy;
+ result->m[1][2] *= sy;
+ result->m[1][3] *= sy;
+
+ result->m[2][0] *= sz;
+ result->m[2][1] *= sz;
+ result->m[2][2] *= sz;
+ result->m[2][3] *= sz;
+}
+
+void ESUTIL_API
+esTranslate(ESMatrix *result, GLfloat tx, GLfloat ty, GLfloat tz)
+{
+ result->m[3][0] += (result->m[0][0] * tx + result->m[1][0] * ty + result->m[2][0] * tz);
+ result->m[3][1] += (result->m[0][1] * tx + result->m[1][1] * ty + result->m[2][1] * tz);
+ result->m[3][2] += (result->m[0][2] * tx + result->m[1][2] * ty + result->m[2][2] * tz);
+ result->m[3][3] += (result->m[0][3] * tx + result->m[1][3] * ty + result->m[2][3] * tz);
+}
+
+void ESUTIL_API
+esRotate(ESMatrix *result, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
+{
+ GLfloat sinAngle, cosAngle;
+ GLfloat mag = sqrtf(x * x + y * y + z * z);
+
+ sinAngle = sinf ( angle * PI / 180.0f );
+ cosAngle = cosf ( angle * PI / 180.0f );
+ if ( mag > 0.0f )
+ {
+ GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs;
+ GLfloat oneMinusCos;
+ ESMatrix rotMat;
+
+ x /= mag;
+ y /= mag;
+ z /= mag;
+
+ xx = x * x;
+ yy = y * y;
+ zz = z * z;
+ xy = x * y;
+ yz = y * z;
+ zx = z * x;
+ xs = x * sinAngle;
+ ys = y * sinAngle;
+ zs = z * sinAngle;
+ oneMinusCos = 1.0f - cosAngle;
+
+ rotMat.m[0][0] = (oneMinusCos * xx) + cosAngle;
+ rotMat.m[0][1] = (oneMinusCos * xy) - zs;
+ rotMat.m[0][2] = (oneMinusCos * zx) + ys;
+ rotMat.m[0][3] = 0.0F;
+
+ rotMat.m[1][0] = (oneMinusCos * xy) + zs;
+ rotMat.m[1][1] = (oneMinusCos * yy) + cosAngle;
+ rotMat.m[1][2] = (oneMinusCos * yz) - xs;
+ rotMat.m[1][3] = 0.0F;
+
+ rotMat.m[2][0] = (oneMinusCos * zx) - ys;
+ rotMat.m[2][1] = (oneMinusCos * yz) + xs;
+ rotMat.m[2][2] = (oneMinusCos * zz) + cosAngle;
+ rotMat.m[2][3] = 0.0F;
+
+ rotMat.m[3][0] = 0.0F;
+ rotMat.m[3][1] = 0.0F;
+ rotMat.m[3][2] = 0.0F;
+ rotMat.m[3][3] = 1.0F;
+
+ esMatrixMultiply( result, &rotMat, result );
+ }
+}
+
+void ESUTIL_API
+esFrustum(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ)
+{
+ float deltaX = right - left;
+ float deltaY = top - bottom;
+ float deltaZ = farZ - nearZ;
+ ESMatrix frust;
+
+ if ( (nearZ <= 0.0f) || (farZ <= 0.0f) ||
+ (deltaX <= 0.0f) || (deltaY <= 0.0f) || (deltaZ <= 0.0f) )
+ return;
+
+ frust.m[0][0] = 2.0f * nearZ / deltaX;
+ frust.m[0][1] = frust.m[0][2] = frust.m[0][3] = 0.0f;
+
+ frust.m[1][1] = 2.0f * nearZ / deltaY;
+ frust.m[1][0] = frust.m[1][2] = frust.m[1][3] = 0.0f;
+
+ frust.m[2][0] = (right + left) / deltaX;
+ frust.m[2][1] = (top + bottom) / deltaY;
+ frust.m[2][2] = -(nearZ + farZ) / deltaZ;
+ frust.m[2][3] = -1.0f;
+
+ frust.m[3][2] = -2.0f * nearZ * farZ / deltaZ;
+ frust.m[3][0] = frust.m[3][1] = frust.m[3][3] = 0.0f;
+
+ esMatrixMultiply(result, &frust, result);
+}
+
+
+void ESUTIL_API
+esPerspective(ESMatrix *result, float fovy, float aspect, float nearZ, float farZ)
+{
+ GLfloat frustumW, frustumH;
+
+ frustumH = tanf( fovy / 360.0f * PI ) * nearZ;
+ frustumW = frustumH * aspect;
+
+ esFrustum( result, -frustumW, frustumW, -frustumH, frustumH, nearZ, farZ );
+}
+
+void ESUTIL_API
+esOrtho(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ)
+{
+ float deltaX = right - left;
+ float deltaY = top - bottom;
+ float deltaZ = farZ - nearZ;
+ ESMatrix ortho;
+
+ if ( (deltaX == 0.0f) || (deltaY == 0.0f) || (deltaZ == 0.0f) )
+ return;
+
+ esMatrixLoadIdentity(&ortho);
+ ortho.m[0][0] = 2.0f / deltaX;
+ ortho.m[3][0] = -(right + left) / deltaX;
+ ortho.m[1][1] = 2.0f / deltaY;
+ ortho.m[3][1] = -(top + bottom) / deltaY;
+ ortho.m[2][2] = -2.0f / deltaZ;
+ ortho.m[3][2] = -(nearZ + farZ) / deltaZ;
+
+ esMatrixMultiply(result, &ortho, result);
+}
+
+
+void ESUTIL_API
+esMatrixMultiply(ESMatrix *result, ESMatrix *srcA, ESMatrix *srcB)
+{
+ ESMatrix tmp;
+ int i;
+
+ for (i=0; i<4; i++)
+ {
+ tmp.m[i][0] = (srcA->m[i][0] * srcB->m[0][0]) +
+ (srcA->m[i][1] * srcB->m[1][0]) +
+ (srcA->m[i][2] * srcB->m[2][0]) +
+ (srcA->m[i][3] * srcB->m[3][0]) ;
+
+ tmp.m[i][1] = (srcA->m[i][0] * srcB->m[0][1]) +
+ (srcA->m[i][1] * srcB->m[1][1]) +
+ (srcA->m[i][2] * srcB->m[2][1]) +
+ (srcA->m[i][3] * srcB->m[3][1]) ;
+
+ tmp.m[i][2] = (srcA->m[i][0] * srcB->m[0][2]) +
+ (srcA->m[i][1] * srcB->m[1][2]) +
+ (srcA->m[i][2] * srcB->m[2][2]) +
+ (srcA->m[i][3] * srcB->m[3][2]) ;
+
+ tmp.m[i][3] = (srcA->m[i][0] * srcB->m[0][3]) +
+ (srcA->m[i][1] * srcB->m[1][3]) +
+ (srcA->m[i][2] * srcB->m[2][3]) +
+ (srcA->m[i][3] * srcB->m[3][3]) ;
+ }
+ memcpy(result, &tmp, sizeof(ESMatrix));
+}
+
+
+void ESUTIL_API
+esMatrixLoadIdentity(ESMatrix *result)
+{
+ memset(result, 0x0, sizeof(ESMatrix));
+ result->m[0][0] = 1.0f;
+ result->m[1][1] = 1.0f;
+ result->m[2][2] = 1.0f;
+ result->m[3][3] = 1.0f;
+}
+
diff --git a/tests/glbook/Common/esUtil.c b/tests/glbook/Common/esUtil.c new file mode 100644 index 00000000..fa080648 --- /dev/null +++ b/tests/glbook/Common/esUtil.c @@ -0,0 +1,420 @@ +//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// ESUtil.c
+//
+// A utility library for OpenGL ES. This library provides a
+// basic common framework for the example applications in the
+// OpenGL ES 2.0 Programming Guide.
+//
+
+///
+// Includes
+//
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/time.h>
+#include <GLES2/gl2.h>
+#include <EGL/egl.h>
+#include "esUtil.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+
+// X11 related local variables
+static Display *x_display = NULL;
+
+///
+// CreateEGLContext()
+//
+// Creates an EGL rendering context and all associated elements
+//
+EGLBoolean CreateEGLContext ( EGLNativeWindowType hWnd, EGLDisplay* eglDisplay,
+ EGLContext* eglContext, EGLSurface* eglSurface,
+ EGLint attribList[])
+{
+ EGLint numConfigs;
+ EGLint majorVersion;
+ EGLint minorVersion;
+ EGLDisplay display;
+ EGLContext context;
+ EGLSurface surface;
+ EGLConfig config;
+ EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
+
+ // Get Display
+ display = eglGetDisplay((EGLNativeDisplayType)x_display);
+ if ( display == EGL_NO_DISPLAY )
+ {
+ return EGL_FALSE;
+ }
+
+ // Initialize EGL
+ if ( !eglInitialize(display, &majorVersion, &minorVersion) )
+ {
+ return EGL_FALSE;
+ }
+
+ // Get configs
+ if ( !eglGetConfigs(display, NULL, 0, &numConfigs) )
+ {
+ return EGL_FALSE;
+ }
+
+ // Choose config
+ if ( !eglChooseConfig(display, attribList, &config, 1, &numConfigs) )
+ {
+ return EGL_FALSE;
+ }
+
+ // Create a surface
+ surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)hWnd, NULL);
+ if ( surface == EGL_NO_SURFACE )
+ {
+ return EGL_FALSE;
+ }
+
+ // Create a GL context
+ context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs );
+ if ( context == EGL_NO_CONTEXT )
+ {
+ return EGL_FALSE;
+ }
+
+ // Make the context current
+ if ( !eglMakeCurrent(display, surface, surface, context) )
+ {
+ return EGL_FALSE;
+ }
+
+ *eglDisplay = display;
+ *eglSurface = surface;
+ *eglContext = context;
+ return EGL_TRUE;
+}
+
+
+///
+// WinCreate()
+//
+// This function initialized the native X11 display and window for EGL
+//
+EGLBoolean WinCreate(ESContext *esContext, const char *title)
+{
+ Window root;
+ XSetWindowAttributes swa;
+ XSetWindowAttributes xattr;
+ Atom wm_state;
+ XWMHints hints;
+ XEvent xev;
+ EGLConfig ecfg;
+ EGLint num_config;
+ Window win;
+
+ /*
+ * X11 native display initialization
+ */
+
+ x_display = XOpenDisplay(NULL);
+ if ( x_display == NULL )
+ {
+ return EGL_FALSE;
+ }
+
+ root = DefaultRootWindow(x_display);
+
+ swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask;
+ win = XCreateWindow(
+ x_display, root,
+ 0, 0, esContext->width, esContext->height, 0,
+ CopyFromParent, InputOutput,
+ CopyFromParent, CWEventMask,
+ &swa );
+
+ xattr.override_redirect = FALSE;
+ XChangeWindowAttributes ( x_display, win, CWOverrideRedirect, &xattr );
+
+ hints.input = TRUE;
+ hints.flags = InputHint;
+ XSetWMHints(x_display, win, &hints);
+
+ // make the window visible on the screen
+ XMapWindow (x_display, win);
+ XStoreName (x_display, win, title);
+
+ // get identifiers for the provided atom name strings
+ wm_state = XInternAtom (x_display, "_NET_WM_STATE", FALSE);
+
+ memset ( &xev, 0, sizeof(xev) );
+ xev.type = ClientMessage;
+ xev.xclient.window = win;
+ xev.xclient.message_type = wm_state;
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = 1;
+ xev.xclient.data.l[1] = FALSE;
+ XSendEvent (
+ x_display,
+ DefaultRootWindow ( x_display ),
+ FALSE,
+ SubstructureNotifyMask,
+ &xev );
+
+ esContext->hWnd = (EGLNativeWindowType) win;
+ return EGL_TRUE;
+}
+
+
+///
+// userInterrupt()
+//
+// Reads from X11 event loop and interrupt program if there is a keypress, or
+// window close action.
+//
+GLboolean userInterrupt(ESContext *esContext)
+{
+ XEvent xev;
+ KeySym key;
+ GLboolean userinterrupt = GL_FALSE;
+ char text;
+
+ // Pump all messages from X server. Keypresses are directed to keyfunc (if defined)
+ while ( XPending ( x_display ) )
+ {
+ XNextEvent( x_display, &xev );
+ if ( xev.type == KeyPress )
+ {
+ if (XLookupString(&xev.xkey,&text,1,&key,0)==1)
+ {
+ if (esContext->keyFunc != NULL)
+ esContext->keyFunc(esContext, text, 0, 0);
+ }
+ }
+ if ( xev.type == DestroyNotify )
+ userinterrupt = GL_TRUE;
+ }
+ return userinterrupt;
+}
+
+
+//////////////////////////////////////////////////////////////////
+//
+// Public Functions
+//
+//
+
+///
+// esInitContext()
+//
+// Initialize ES utility context. This must be called before calling any other
+// functions.
+//
+void ESUTIL_API esInitContext ( ESContext *esContext )
+{
+ if ( esContext != NULL )
+ {
+ memset( esContext, 0, sizeof( ESContext) );
+ }
+}
+
+
+///
+// esCreateWindow()
+//
+// title - name for title bar of window
+// width - width of window to create
+// height - height of window to create
+// flags - bitwise or of window creation flags
+// ES_WINDOW_ALPHA - specifies that the framebuffer should have alpha
+// ES_WINDOW_DEPTH - specifies that a depth buffer should be created
+// ES_WINDOW_STENCIL - specifies that a stencil buffer should be created
+// ES_WINDOW_MULTISAMPLE - specifies that a multi-sample buffer should be created
+//
+GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, const char* title, GLint width, GLint height, GLuint flags )
+{
+ EGLint attribList[] =
+ {
+ EGL_RED_SIZE, 5,
+ EGL_GREEN_SIZE, 6,
+ EGL_BLUE_SIZE, 5,
+ EGL_ALPHA_SIZE, (flags & ES_WINDOW_ALPHA) ? 8 : EGL_DONT_CARE,
+ EGL_DEPTH_SIZE, (flags & ES_WINDOW_DEPTH) ? 8 : EGL_DONT_CARE,
+ EGL_STENCIL_SIZE, (flags & ES_WINDOW_STENCIL) ? 8 : EGL_DONT_CARE,
+ EGL_SAMPLE_BUFFERS, (flags & ES_WINDOW_MULTISAMPLE) ? 1 : 0,
+ EGL_NONE
+ };
+
+ if ( esContext == NULL )
+ {
+ return GL_FALSE;
+ }
+
+ esContext->width = width;
+ esContext->height = height;
+
+ if ( !WinCreate ( esContext, title) )
+ {
+ return GL_FALSE;
+ }
+
+
+ if ( !CreateEGLContext ( esContext->hWnd,
+ &esContext->eglDisplay,
+ &esContext->eglContext,
+ &esContext->eglSurface,
+ attribList) )
+ {
+ return GL_FALSE;
+ }
+
+
+ return GL_TRUE;
+}
+
+
+///
+// esMainLoop()
+//
+// Start the main loop for the OpenGL ES application
+//
+
+void ESUTIL_API esMainLoop ( ESContext *esContext )
+{
+ struct timeval t1, t2;
+ struct timezone tz;
+ float deltatime;
+ float totaltime = 0.0f;
+ unsigned int frames = 0;
+
+ gettimeofday ( &t1 , &tz );
+
+ // Just one iteration! while(userInterrupt(esContext) == GL_FALSE)
+ {
+ gettimeofday(&t2, &tz);
+ deltatime = (float)(t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec) * 1e-6);
+ t1 = t2;
+
+ if (esContext->updateFunc != NULL)
+ esContext->updateFunc(esContext, deltatime);
+ if (esContext->drawFunc != NULL)
+ esContext->drawFunc(esContext);
+
+ eglSwapBuffers(esContext->eglDisplay, esContext->eglSurface);
+
+ totaltime += deltatime;
+ frames++;
+ if (totaltime > 2.0f)
+ {
+ printf("%4d frames rendered in %1.4f seconds -> FPS=%3.4f\n", frames, totaltime, frames/totaltime);
+ totaltime -= 2.0f;
+ frames = 0;
+ }
+ }
+}
+
+
+///
+// esRegisterDrawFunc()
+//
+void ESUTIL_API esRegisterDrawFunc ( ESContext *esContext, void (ESCALLBACK *drawFunc) (ESContext* ) )
+{
+ esContext->drawFunc = drawFunc;
+}
+
+
+///
+// esRegisterUpdateFunc()
+//
+void ESUTIL_API esRegisterUpdateFunc ( ESContext *esContext, void (ESCALLBACK *updateFunc) ( ESContext*, float ) )
+{
+ esContext->updateFunc = updateFunc;
+}
+
+
+///
+// esRegisterKeyFunc()
+//
+void ESUTIL_API esRegisterKeyFunc ( ESContext *esContext,
+ void (ESCALLBACK *keyFunc) (ESContext*, unsigned char, int, int ) )
+{
+ esContext->keyFunc = keyFunc;
+}
+
+
+///
+// esLogMessage()
+//
+// Log an error message to the debug output for the platform
+//
+void ESUTIL_API esLogMessage ( const char *formatStr, ... )
+{
+ va_list params;
+ char buf[BUFSIZ];
+
+ va_start ( params, formatStr );
+ vsprintf ( buf, formatStr, params );
+
+ printf ( "%s", buf );
+
+ va_end ( params );
+}
+
+
+///
+// esLoadTGA()
+//
+// Loads a 24-bit TGA image from a file. This is probably the simplest TGA loader ever.
+// Does not support loading of compressed TGAs nor TGAa with alpha channel. But for the
+// sake of the examples, this is sufficient.
+//
+
+char* ESUTIL_API esLoadTGA ( char *fileName, int *width, int *height )
+{
+ char *buffer = NULL;
+ FILE *f;
+ unsigned char tgaheader[12];
+ unsigned char attributes[6];
+ unsigned int imagesize;
+
+ f = fopen(fileName, "rb");
+ if(f == NULL) return NULL;
+
+ if(fread(&tgaheader, sizeof(tgaheader), 1, f) == 0)
+ {
+ fclose(f);
+ return NULL;
+ }
+
+ if(fread(attributes, sizeof(attributes), 1, f) == 0)
+ {
+ fclose(f);
+ return 0;
+ }
+
+ *width = attributes[1] * 256 + attributes[0];
+ *height = attributes[3] * 256 + attributes[2];
+ imagesize = attributes[4] / 8 * *width * *height;
+ buffer = malloc(imagesize);
+ if (buffer == NULL)
+ {
+ fclose(f);
+ return 0;
+ }
+
+ if(fread(buffer, 1, imagesize, f) != imagesize)
+ {
+ free(buffer);
+ return NULL;
+ }
+ fclose(f);
+ return buffer;
+}
diff --git a/tests/glbook/Common/esUtil.h b/tests/glbook/Common/esUtil.h new file mode 100644 index 00000000..c468b430 --- /dev/null +++ b/tests/glbook/Common/esUtil.h @@ -0,0 +1,281 @@ +//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+//
+/// \file ESUtil.h
+/// \brief A utility library for OpenGL ES. This library provides a
+/// basic common framework for the example applications in the
+/// OpenGL ES 2.0 Programming Guide.
+//
+#ifndef ESUTIL_H
+#define ESUTIL_H
+
+///
+// Includes
+//
+#include <GLES2/gl2.h>
+#include <EGL/egl.h>
+
+#ifdef __cplusplus
+
+extern "C" {
+#endif
+
+
+///
+// Macros
+//
+#define ESUTIL_API
+#define ESCALLBACK
+
+
+/// esCreateWindow flag - RGB color buffer
+#define ES_WINDOW_RGB 0
+/// esCreateWindow flag - ALPHA color buffer
+#define ES_WINDOW_ALPHA 1
+/// esCreateWindow flag - depth buffer
+#define ES_WINDOW_DEPTH 2
+/// esCreateWindow flag - stencil buffer
+#define ES_WINDOW_STENCIL 4
+/// esCreateWindow flat - multi-sample buffer
+#define ES_WINDOW_MULTISAMPLE 8
+
+
+///
+// Types
+//
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+typedef struct
+{
+ GLfloat m[4][4];
+} ESMatrix;
+
+typedef struct _escontext
+{
+ /// Put your user data here...
+ void* userData;
+
+ /// Window width
+ GLint width;
+
+ /// Window height
+ GLint height;
+
+ /// Window handle
+ EGLNativeWindowType hWnd;
+
+ /// EGL display
+ EGLDisplay eglDisplay;
+
+ /// EGL context
+ EGLContext eglContext;
+
+ /// EGL surface
+ EGLSurface eglSurface;
+
+ /// Callbacks
+ void (ESCALLBACK *drawFunc) ( struct _escontext * );
+ void (ESCALLBACK *keyFunc) ( struct _escontext *, unsigned char, int, int );
+ void (ESCALLBACK *updateFunc) ( struct _escontext *, float deltaTime );
+} ESContext;
+
+
+///
+// Public Functions
+//
+
+//
+///
+/// \brief Initialize ES framework context. This must be called before calling any other functions.
+/// \param esContext Application context
+//
+void ESUTIL_API esInitContext ( ESContext *esContext );
+
+//
+/// \brief Create a window with the specified parameters
+/// \param esContext Application context
+/// \param title Name for title bar of window
+/// \param width Width in pixels of window to create
+/// \param height Height in pixels of window to create
+/// \param flags Bitfield for the window creation flags
+/// ES_WINDOW_RGB - specifies that the color buffer should have R,G,B channels
+/// ES_WINDOW_ALPHA - specifies that the color buffer should have alpha
+/// ES_WINDOW_DEPTH - specifies that a depth buffer should be created
+/// ES_WINDOW_STENCIL - specifies that a stencil buffer should be created
+/// ES_WINDOW_MULTISAMPLE - specifies that a multi-sample buffer should be created
+/// \return GL_TRUE if window creation is succesful, GL_FALSE otherwise
+GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, const char *title, GLint width, GLint height, GLuint flags );
+
+//
+/// \brief Start the main loop for the OpenGL ES application
+/// \param esContext Application context
+//
+void ESUTIL_API esMainLoop ( ESContext *esContext );
+
+//
+/// \brief Register a draw callback function to be used to render each frame
+/// \param esContext Application context
+/// \param drawFunc Draw callback function that will be used to render the scene
+//
+void ESUTIL_API esRegisterDrawFunc ( ESContext *esContext, void (ESCALLBACK *drawFunc) ( ESContext* ) );
+
+//
+/// \brief Register an update callback function to be used to update on each time step
+/// \param esContext Application context
+/// \param updateFunc Update callback function that will be used to render the scene
+//
+void ESUTIL_API esRegisterUpdateFunc ( ESContext *esContext, void (ESCALLBACK *updateFunc) ( ESContext*, float ) );
+
+//
+/// \brief Register an keyboard input processing callback function
+/// \param esContext Application context
+/// \param keyFunc Key callback function for application processing of keyboard input
+//
+void ESUTIL_API esRegisterKeyFunc ( ESContext *esContext,
+ void (ESCALLBACK *drawFunc) ( ESContext*, unsigned char, int, int ) );
+//
+/// \brief Log a message to the debug output for the platform
+/// \param formatStr Format string for error log.
+//
+void ESUTIL_API esLogMessage ( const char *formatStr, ... );
+
+//
+///
+/// \brief Load a shader, check for compile errors, print error messages to output log
+/// \param type Type of shader (GL_VERTEX_SHADER or GL_FRAGMENT_SHADER)
+/// \param shaderSrc Shader source string
+/// \return A new shader object on success, 0 on failure
+//
+GLuint ESUTIL_API esLoadShader ( GLenum type, const char *shaderSrc );
+
+//
+///
+/// \brief Load a vertex and fragment shader, create a program object, link program.
+/// Errors output to log.
+/// \param vertShaderSrc Vertex shader source code
+/// \param fragShaderSrc Fragment shader source code
+/// \return A new program object linked with the vertex/fragment shader pair, 0 on failure
+//
+GLuint ESUTIL_API esLoadProgram ( const char *vertShaderSrc, const char *fragShaderSrc );
+
+
+//
+/// \brief Generates geometry for a sphere. Allocates memory for the vertex data and stores
+/// the results in the arrays. Generate index list for a TRIANGLE_STRIP
+/// \param numSlices The number of slices in the sphere
+/// \param vertices If not NULL, will contain array of float3 positions
+/// \param normals If not NULL, will contain array of float3 normals
+/// \param texCoords If not NULL, will contain array of float2 texCoords
+/// \param indices If not NULL, will contain the array of indices for the triangle strip
+/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array
+/// if it is not NULL ) as a GL_TRIANGLE_STRIP
+//
+int ESUTIL_API esGenSphere ( int numSlices, float radius, GLfloat **vertices, GLfloat **normals,
+ GLfloat **texCoords, GLushort **indices );
+
+//
+/// \brief Generates geometry for a cube. Allocates memory for the vertex data and stores
+/// the results in the arrays. Generate index list for a TRIANGLES
+/// \param scale The size of the cube, use 1.0 for a unit cube.
+/// \param vertices If not NULL, will contain array of float3 positions
+/// \param normals If not NULL, will contain array of float3 normals
+/// \param texCoords If not NULL, will contain array of float2 texCoords
+/// \param indices If not NULL, will contain the array of indices for the triangle strip
+/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array
+/// if it is not NULL ) as a GL_TRIANGLES
+//
+int ESUTIL_API esGenCube ( float scale, GLfloat **vertices, GLfloat **normals,
+ GLfloat **texCoords, GLushort **indices );
+
+//
+/// \brief Loads a 24-bit TGA image from a file
+/// \param fileName Name of the file on disk
+/// \param width Width of loaded image in pixels
+/// \param height Height of loaded image in pixels
+/// \return Pointer to loaded image. NULL on failure.
+//
+char* ESUTIL_API esLoadTGA ( char *fileName, int *width, int *height );
+
+
+//
+/// \brief multiply matrix specified by result with a scaling matrix and return new matrix in result
+/// \param result Specifies the input matrix. Scaled matrix is returned in result.
+/// \param sx, sy, sz Scale factors along the x, y and z axes respectively
+//
+void ESUTIL_API esScale(ESMatrix *result, GLfloat sx, GLfloat sy, GLfloat sz);
+
+//
+/// \brief multiply matrix specified by result with a translation matrix and return new matrix in result
+/// \param result Specifies the input matrix. Translated matrix is returned in result.
+/// \param tx, ty, tz Scale factors along the x, y and z axes respectively
+//
+void ESUTIL_API esTranslate(ESMatrix *result, GLfloat tx, GLfloat ty, GLfloat tz);
+
+//
+/// \brief multiply matrix specified by result with a rotation matrix and return new matrix in result
+/// \param result Specifies the input matrix. Rotated matrix is returned in result.
+/// \param angle Specifies the angle of rotation, in degrees.
+/// \param x, y, z Specify the x, y and z coordinates of a vector, respectively
+//
+void ESUTIL_API esRotate(ESMatrix *result, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+
+//
+// \brief multiply matrix specified by result with a perspective matrix and return new matrix in result
+/// \param result Specifies the input matrix. new matrix is returned in result.
+/// \param left, right Coordinates for the left and right vertical clipping planes
+/// \param bottom, top Coordinates for the bottom and top horizontal clipping planes
+/// \param nearZ, farZ Distances to the near and far depth clipping planes. Both distances must be positive.
+//
+void ESUTIL_API esFrustum(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ);
+
+//
+/// \brief multiply matrix specified by result with a perspective matrix and return new matrix in result
+/// \param result Specifies the input matrix. new matrix is returned in result.
+/// \param fovy Field of view y angle in degrees
+/// \param aspect Aspect ratio of screen
+/// \param nearZ Near plane distance
+/// \param farZ Far plane distance
+//
+void ESUTIL_API esPerspective(ESMatrix *result, float fovy, float aspect, float nearZ, float farZ);
+
+//
+/// \brief multiply matrix specified by result with a perspective matrix and return new matrix in result
+/// \param result Specifies the input matrix. new matrix is returned in result.
+/// \param left, right Coordinates for the left and right vertical clipping planes
+/// \param bottom, top Coordinates for the bottom and top horizontal clipping planes
+/// \param nearZ, farZ Distances to the near and far depth clipping planes. These values are negative if plane is behind the viewer
+//
+void ESUTIL_API esOrtho(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ);
+
+//
+/// \brief perform the following operation - result matrix = srcA matrix * srcB matrix
+/// \param result Returns multiplied matrix
+/// \param srcA, srcB Input matrices to be multiplied
+//
+void ESUTIL_API esMatrixMultiply(ESMatrix *result, ESMatrix *srcA, ESMatrix *srcB);
+
+//
+//// \brief return an indentity matrix
+//// \param result returns identity matrix
+//
+void ESUTIL_API esMatrixLoadIdentity(ESMatrix *result);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ESUTIL_H
diff --git a/tests/glbook/Makefile b/tests/glbook/Makefile new file mode 100644 index 00000000..62cffedf --- /dev/null +++ b/tests/glbook/Makefile @@ -0,0 +1,60 @@ +# Straight forward Makefile to compile all examples in a row + +INCDIR=-I./Common +LIBS=-lGLESv2 -lEGL -lm -lX11 + +COMMONSRC=./Common/esShader.c \ + ./Common/esTransform.c \ + ./Common/esShapes.c \ + ./Common/esUtil.c +COMMONHRD=esUtil.h + +CH02SRC=./Chapter_2/Hello_Triangle/Hello_Triangle.c +CH08SRC=./Chapter_8/Simple_VertexShader/Simple_VertexShader.c +CH09SRC1=./Chapter_9/Simple_Texture2D/Simple_Texture2D.c +CH09SRC2=./Chapter_9/MipMap2D/MipMap2D.c +CH09SRC3=./Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap.c +CH09SRC4=./Chapter_9/TextureWrap/TextureWrap.c +CH10SRC=./Chapter_10/MultiTexture/MultiTexture.c +CH11SRC=./Chapter_11/Multisample/Multisample.c +CH11SRC2=./Chapter_11/Stencil_Test/Stencil_Test.c +CH13SRC2=./Chapter_13/ParticleSystem/ParticleSystem.c + +default: all + +all: ./Chapter_2/Hello_Triangle/CH02_HelloTriangle.bc \ + ./Chapter_8/Simple_VertexShader/CH08_SimpleVertexShader.bc \ + ./Chapter_9/Simple_Texture2D/CH09_SimpleTexture2D.bc \ + ./Chapter_9/MipMap2D/CH09_MipMap2D.bc \ + ./Chapter_9/Simple_TextureCubemap/CH09_TextureCubemap.bc \ + ./Chapter_9/TextureWrap/CH09_TextureWrap.bc \ + ./Chapter_10/MultiTexture/CH10_MultiTexture.bc \ + ./Chapter_13/ParticleSystem/CH13_ParticleSystem.bc +# ./Chapter_11/Multisample/CH11_Multisample.bc \ +# ./Chapter_11/Stencil_Test/CH11_Stencil_Test.bc \ + +clean: + find . -name "CH??_*" | xargs rm -f + +./Chapter_2/Hello_Triangle/CH02_HelloTriangle.bc: ${COMMONSRC} ${COMMONHDR} ${CH02SRC} + $(CC) ${COMMONSRC} ${CH02SRC} -o $@ ${INCDIR} ${LIBS} +./Chapter_8/Simple_VertexShader/CH08_SimpleVertexShader.bc: ${COMMONSRC} ${COMMONHDR} ${CH08SRC} + $(CC) ${COMMONSRC} ${CH08SRC} -o ./$@ ${INCDIR} ${LIBS} +./Chapter_9/Simple_Texture2D/CH09_SimpleTexture2D.bc: ${COMMONSRC} ${COMMONHDR} ${CH09SRC1} + $(CC) ${COMMONSRC} ${CH09SRC1} -o ./$@ ${INCDIR} ${LIBS} +./Chapter_9/MipMap2D/CH09_MipMap2D.bc: ${COMMONSRC} ${COMMONHDR} ${CH09SRC2} + $(CC) ${COMMONSRC} ${CH09SRC2} -o ./$@ ${INCDIR} ${LIBS} +./Chapter_9/Simple_TextureCubemap/CH09_TextureCubemap.bc: ${COMMONSRC} ${COMMONHDR} ${CH09SRC3} + $(CC) ${COMMONSRC} ${CH09SRC3} -o ./$@ ${INCDIR} ${LIBS} +./Chapter_9/TextureWrap/CH09_TextureWrap.bc: ${COMMONSRC} ${COMMONHDR} ${CH09SRC4} + $(CC) ${COMMONSRC} ${CH09SRC4} -o ./$@ ${INCDIR} ${LIBS} +./Chapter_10/MultiTexture/CH10_MultiTexture.bc: ${COMMONSRC} ${COMMONHDR} ${CH10SRC} + $(CC) ${COMMONSRC} ${CH10SRC} -o ./$@ ${INCDIR} ${LIBS} +./Chapter_11/Multisample/CH11_Multisample.bc: ${COMMONSRC} ${COMMONHDR} ${CH11SRC} + $(CC) ${COMMONSRC} ${CH11SRC} -o ./$@ ${INCDIR} ${LIBS} +./Chapter_11/Stencil_Test/CH11_Stencil_Test.bc: ${COMMONSRC} ${COMMONHDR} ${CH11SRC2} + $(CC) ${COMMONSRC} ${CH11SRC2} -o ./$@ ${INCDIR} ${LIBS} +./Chapter_13/Noise3D/CH13_Noise3D.bc: ${COMMONSRC} ${COMMONHDR} ${CH13SRC1} + $(CC) ${COMMONSRC} ${CH13SRC1} -o ./$@ ${INCDIR} ${LIBS} +./Chapter_13/ParticleSystem/CH13_ParticleSystem.bc: ${COMMONSRC} ${COMMONHDR} ${CH13SRC2} + $(CC) ${COMMONSRC} ${CH13SRC2} -o ./$@ ${INCDIR} ${LIBS} diff --git a/tests/glbook/README.linux b/tests/glbook/README.linux new file mode 100644 index 00000000..7b76357b --- /dev/null +++ b/tests/glbook/README.linux @@ -0,0 +1,32 @@ +OpenGL ES 2.0 Programming Guide - Example code for Linux/X11 environment + +Adaptation code for Linux/X11 environment for the examples of the book +OpenGL ES 2.0 Programming Guide written by Jarkko Vatjus-Anttila. All +original example code has remained unmodified. Adaptation changes are +in esUtil.c|h files, which encapsulates all X11 specific internals from +the application layer. + +Prerequisites for building the source is a valid GCC toolchain (4.5.2 +4.6.1 are tested) and properly setup X11 & GLESv2 & EGL environment. +Mesa project offers such setup, and version 7.11 has been tested with +software rendering. Also native GLESv2 renderer has been tested using +NVidia Tegra2 setup. More details about the tested environments are +below: + +The code has been tested with three configurations +- ATI Radeon HD 3200 graphics with Mesa 7.11-0ubuntu3, Ubuntu 11.10 +- NVidia Quadro FX 2800M/PCI/SSE2 with Mesa 7.11-0ubuntu3, Ubuntu 11.10 +- NVidia Tegra 2, native EGL/GLESv2 drivers, Ubuntu 10.10 + +Native GLESv2 on Tegra2 renders all the test cases correctly. However, +Mesa 7.11 has problems with the Chapter 13 particle test, which at least +with the mentioned test setups create only a black screen. + +Compiling the examples should be as easy as running "make" in the root +linux directory. + +31st Oct 2011 - Jarkko Vatjus-Anttila <jvatjusanttila@gmail.com> + +Website: http://code.google.com/p/opengles-book-samples/ +License: MIT + diff --git a/tests/hello_world.js b/tests/hello_world.js index 766e848e..01082eb4 100644 --- a/tests/hello_world.js +++ b/tests/hello_world.js @@ -39,9 +39,9 @@ if (ENVIRONMENT_IS_NODE) { this['read'] = function(f) { snarf(f) }; } - if (!this['arguments']) { + if (typeof scriptArgs != 'undefined') { arguments_ = scriptArgs; - } else { + } else if (typeof arguments != 'undefined') { arguments_ = arguments; } diff --git a/tests/hello_world_file.cpp b/tests/hello_world_file.cpp new file mode 100644 index 00000000..71fb953b --- /dev/null +++ b/tests/hello_world_file.cpp @@ -0,0 +1,13 @@ +#include <stdio.h> +int main() { + FILE *file = fopen("tests/hello_world_file.txt", "rb"); + while (!feof(file)) { + char c = fgetc(file); + if (c != EOF) { + putchar(c); + } + } + fclose (file); + return 0; +} + diff --git a/tests/hello_world_file.txt b/tests/hello_world_file.txt new file mode 100644 index 00000000..8de0d699 --- /dev/null +++ b/tests/hello_world_file.txt @@ -0,0 +1,4 @@ +== +This data has been read from a file. +The file is readable as if it were at the same location in the filesystem, including directories, as in the local filesystem where you compiled the source. +== diff --git a/tests/hello_world_gles.c b/tests/hello_world_gles.c index 4f2cb45c..6f7a4324 100644 --- a/tests/hello_world_gles.c +++ b/tests/hello_world_gles.c @@ -46,17 +46,28 @@ #include <string.h> #include <sys/time.h> #include <unistd.h> +#ifdef __APPLE__ +#include <OpenGL/gl.h> +#include <Glut/glut.h> +#else #include <GL/gl.h> #include <GL/glut.h> - -#ifndef HAVE_BUILTIN_SINCOS -#include "sincos.h" #endif #define STRIPS_PER_TOOTH 7 #define VERTICES_PER_TOOTH 34 #define GEAR_VERTEX_STRIDE 6 +#ifndef HAVE_BUILTIN_SINCOS +#define sincos _sincos +static void +sincos (double a, double *s, double *c) +{ + *s = sin (a); + *c = cos (a); +} +#endif + /** * Struct describing the vertices in triangle strip */ @@ -715,7 +726,7 @@ main(int argc, char *argv[]) glutCreateWindow("es2gears"); /* Set up glut callback functions */ - gears_idle(); + glutIdleFunc (gears_idle); glutReshapeFunc(gears_reshape); glutDisplayFunc(gears_draw); glutSpecialFunc(gears_special); diff --git a/tests/hello_world_gles_deriv.c b/tests/hello_world_gles_deriv.c new file mode 100644 index 00000000..2e0f0664 --- /dev/null +++ b/tests/hello_world_gles_deriv.c @@ -0,0 +1,730 @@ +/* + * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * + * 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 above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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 + * BRIAN PAUL 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. + */ + +/* + * Ported to GLES2. + * Kristian Høgsberg <krh@bitplanet.net> + * May 3, 2010 + * + * Improve GLES2 port: + * * Refactor gear drawing. + * * Use correct normals for surfaces. + * * Improve shader. + * * Use perspective projection transformation. + * * Add FPS count. + * * Add comments. + * Alexandros Frantzis <alexandros.frantzis@linaro.org> + * Jul 13, 2010 + */ + +#define GL_GLEXT_PROTOTYPES +#define EGL_EGLEXT_PROTOTYPES + +#define _GNU_SOURCE + +#include <math.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/time.h> +#include <unistd.h> +#include <GL/gl.h> +#include <GL/glut.h> + +#ifndef HAVE_BUILTIN_SINCOS +#include "sincos.h" +#endif + +#define STRIPS_PER_TOOTH 7 +#define VERTICES_PER_TOOTH 34 +#define GEAR_VERTEX_STRIDE 6 + +/** + * Struct describing the vertices in triangle strip + */ +struct vertex_strip { + /** The first vertex in the strip */ + GLint first; + /** The number of consecutive vertices in the strip after the first */ + GLint count; +}; + +/* Each vertex consist of GEAR_VERTEX_STRIDE GLfloat attributes */ +typedef GLfloat GearVertex[GEAR_VERTEX_STRIDE]; + +/** + * Struct representing a gear. + */ +struct gear { + /** The array of vertices comprising the gear */ + GearVertex *vertices; + /** The number of vertices comprising the gear */ + int nvertices; + /** The array of triangle strips comprising the gear */ + struct vertex_strip *strips; + /** The number of triangle strips comprising the gear */ + int nstrips; + /** The Vertex Buffer Object holding the vertices in the graphics card */ + GLuint vbo; +}; + +/** The view rotation [x, y, z] */ +static GLfloat view_rot[3] = { 20.0, 30.0, 0.0 }; +/** The gears */ +static struct gear *gear1, *gear2, *gear3; +/** The current gear rotation angle */ +static GLfloat angle = 0.0; +/** The location of the shader uniforms */ +static GLuint ModelViewProjectionMatrix_location, + NormalMatrix_location, + LightSourcePosition_location, + MaterialColor_location; +/** The projection matrix */ +static GLfloat ProjectionMatrix[16]; +/** The direction of the directional light for the scene */ +static const GLfloat LightSourcePosition[4] = { 5.0, 5.0, 10.0, 1.0}; + +/** + * Fills a gear vertex. + * + * @param v the vertex to fill + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coortinate + * @param n pointer to the normal table + * + * @return the operation error code + */ +static GearVertex * +vert(GearVertex *v, GLfloat x, GLfloat y, GLfloat z, GLfloat n[3]) +{ + v[0][0] = x; + v[0][1] = y; + v[0][2] = z; + v[0][3] = n[0]; + v[0][4] = n[1]; + v[0][5] = n[2]; + + return v + 1; +} + +/** + * Create a gear wheel. + * + * @param inner_radius radius of hole at center + * @param outer_radius radius at center of teeth + * @param width width of gear + * @param teeth number of teeth + * @param tooth_depth depth of tooth + * + * @return pointer to the constructed struct gear + */ +static struct gear * +create_gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, + GLint teeth, GLfloat tooth_depth) +{ + GLfloat r0, r1, r2; + GLfloat da; + GearVertex *v; + struct gear *gear; + double s[5], c[5]; + GLfloat normal[3]; + int cur_strip = 0; + int i; + + /* Allocate memory for the gear */ + gear = malloc(sizeof *gear); + if (gear == NULL) + return NULL; + + /* Calculate the radii used in the gear */ + r0 = inner_radius; + r1 = outer_radius - tooth_depth / 2.0; + r2 = outer_radius + tooth_depth / 2.0; + + da = 2.0 * M_PI / teeth / 4.0; + + /* Allocate memory for the triangle strip information */ + gear->nstrips = STRIPS_PER_TOOTH * teeth; + gear->strips = calloc(gear->nstrips, sizeof (*gear->strips)); + + /* Allocate memory for the vertices */ + gear->vertices = calloc(VERTICES_PER_TOOTH * teeth, sizeof(*gear->vertices)); + v = gear->vertices; + + for (i = 0; i < teeth; i++) { + /* Calculate needed sin/cos for varius angles */ + sincos(i * 2.0 * M_PI / teeth, &s[0], &c[0]); + sincos(i * 2.0 * M_PI / teeth + da, &s[1], &c[1]); + sincos(i * 2.0 * M_PI / teeth + da * 2, &s[2], &c[2]); + sincos(i * 2.0 * M_PI / teeth + da * 3, &s[3], &c[3]); + sincos(i * 2.0 * M_PI / teeth + da * 4, &s[4], &c[4]); + + /* A set of macros for making the creation of the gears easier */ +#define GEAR_POINT(r, da) { (r) * c[(da)], (r) * s[(da)] } +#define SET_NORMAL(x, y, z) do { \ + normal[0] = (x); normal[1] = (y); normal[2] = (z); \ +} while(0) + +#define GEAR_VERT(v, point, sign) vert((v), p[(point)].x, p[(point)].y, (sign) * width * 0.5, normal) + +#define START_STRIP do { \ + gear->strips[cur_strip].first = v - gear->vertices; \ +} while(0); + +#define END_STRIP do { \ + int _tmp = (v - gear->vertices); \ + gear->strips[cur_strip].count = _tmp - gear->strips[cur_strip].first; \ + cur_strip++; \ +} while (0) + +#define QUAD_WITH_NORMAL(p1, p2) do { \ + SET_NORMAL((p[(p1)].y - p[(p2)].y), -(p[(p1)].x - p[(p2)].x), 0); \ + v = GEAR_VERT(v, (p1), -1); \ + v = GEAR_VERT(v, (p1), 1); \ + v = GEAR_VERT(v, (p2), -1); \ + v = GEAR_VERT(v, (p2), 1); \ +} while(0) + + struct point { + GLfloat x; + GLfloat y; + }; + + /* Create the 7 points (only x,y coords) used to draw a tooth */ + struct point p[7] = { + GEAR_POINT(r2, 1), // 0 + GEAR_POINT(r2, 2), // 1 + GEAR_POINT(r1, 0), // 2 + GEAR_POINT(r1, 3), // 3 + GEAR_POINT(r0, 0), // 4 + GEAR_POINT(r1, 4), // 5 + GEAR_POINT(r0, 4), // 6 + }; + + /* Front face */ + START_STRIP; + SET_NORMAL(0, 0, 1.0); + v = GEAR_VERT(v, 0, +1); + v = GEAR_VERT(v, 1, +1); + v = GEAR_VERT(v, 2, +1); + v = GEAR_VERT(v, 3, +1); + v = GEAR_VERT(v, 4, +1); + v = GEAR_VERT(v, 5, +1); + v = GEAR_VERT(v, 6, +1); + END_STRIP; + + /* Inner face */ + START_STRIP; + QUAD_WITH_NORMAL(4, 6); + END_STRIP; + + /* Back face */ + START_STRIP; + SET_NORMAL(0, 0, -1.0); + v = GEAR_VERT(v, 6, -1); + v = GEAR_VERT(v, 5, -1); + v = GEAR_VERT(v, 4, -1); + v = GEAR_VERT(v, 3, -1); + v = GEAR_VERT(v, 2, -1); + v = GEAR_VERT(v, 1, -1); + v = GEAR_VERT(v, 0, -1); + END_STRIP; + + /* Outer face */ + START_STRIP; + QUAD_WITH_NORMAL(0, 2); + END_STRIP; + + START_STRIP; + QUAD_WITH_NORMAL(1, 0); + END_STRIP; + + START_STRIP; + QUAD_WITH_NORMAL(3, 1); + END_STRIP; + + START_STRIP; + QUAD_WITH_NORMAL(5, 3); + END_STRIP; + } + + gear->nvertices = (v - gear->vertices); + + /* Store the vertices in a vertex buffer object (VBO) */ + glGenBuffers(1, &gear->vbo); + glBindBuffer(GL_ARRAY_BUFFER, gear->vbo); + glBufferData(GL_ARRAY_BUFFER, gear->nvertices * sizeof(GearVertex), + gear->vertices, GL_STATIC_DRAW); + + return gear; +} + +/** + * Multiplies two 4x4 matrices. + * + * The result is stored in matrix m. + * + * @param m the first matrix to multiply + * @param n the second matrix to multiply + */ +static void +multiply(GLfloat *m, const GLfloat *n) +{ + GLfloat tmp[16]; + const GLfloat *row, *column; + div_t d; + int i, j; + + for (i = 0; i < 16; i++) { + tmp[i] = 0; + d = div(i, 4); + row = n + d.quot * 4; + column = m + d.rem; + for (j = 0; j < 4; j++) + tmp[i] += row[j] * column[j * 4]; + } + memcpy(m, &tmp, sizeof tmp); +} + +/** + * Rotates a 4x4 matrix. + * + * @param[in,out] m the matrix to rotate + * @param angle the angle to rotate + * @param x the x component of the direction to rotate to + * @param y the y component of the direction to rotate to + * @param z the z component of the direction to rotate to + */ +static void +rotate(GLfloat *m, GLfloat angle, GLfloat x, GLfloat y, GLfloat z) +{ + double s, c; + + sincos(angle, &s, &c); + GLfloat r[16] = { + x * x * (1 - c) + c, y * x * (1 - c) + z * s, x * z * (1 - c) - y * s, 0, + x * y * (1 - c) - z * s, y * y * (1 - c) + c, y * z * (1 - c) + x * s, 0, + x * z * (1 - c) + y * s, y * z * (1 - c) - x * s, z * z * (1 - c) + c, 0, + 0, 0, 0, 1 + }; + + multiply(m, r); +} + + +/** + * Translates a 4x4 matrix. + * + * @param[in,out] m the matrix to translate + * @param x the x component of the direction to translate to + * @param y the y component of the direction to translate to + * @param z the z component of the direction to translate to + */ +static void +translate(GLfloat *m, GLfloat x, GLfloat y, GLfloat z) +{ + GLfloat t[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 }; + + multiply(m, t); +} + +/** + * Creates an identity 4x4 matrix. + * + * @param m the matrix make an identity matrix + */ +static void +identity(GLfloat *m) +{ + GLfloat t[16] = { + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0, + }; + + memcpy(m, t, sizeof(t)); +} + +/** + * Transposes a 4x4 matrix. + * + * @param m the matrix to transpose + */ +static void +transpose(GLfloat *m) +{ + GLfloat t[16] = { + m[0], m[4], m[8], m[12], + m[1], m[5], m[9], m[13], + m[2], m[6], m[10], m[14], + m[3], m[7], m[11], m[15]}; + + memcpy(m, t, sizeof(t)); +} + +/** + * Inverts a 4x4 matrix. + * + * This function can currently handle only pure translation-rotation matrices. + * Read http://www.gamedev.net/community/forums/topic.asp?topic_id=425118 + * for an explanation. + */ +static void +invert(GLfloat *m) +{ + GLfloat t[16]; + identity(t); + + // Extract and invert the translation part 't'. The inverse of a + // translation matrix can be calculated by negating the translation + // coordinates. + t[12] = -m[12]; t[13] = -m[13]; t[14] = -m[14]; + + // Invert the rotation part 'r'. The inverse of a rotation matrix is + // equal to its transpose. + m[12] = m[13] = m[14] = 0; + transpose(m); + + // inv(m) = inv(r) * inv(t) + multiply(m, t); +} + +/** + * Calculate a perspective projection transformation. + * + * @param m the matrix to save the transformation in + * @param fovy the field of view in the y direction + * @param aspect the view aspect ratio + * @param zNear the near clipping plane + * @param zFar the far clipping plane + */ +void perspective(GLfloat *m, GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar) +{ + GLfloat tmp[16]; + identity(tmp); + + double sine, cosine, cotangent, deltaZ; + GLfloat radians = fovy / 2 * M_PI / 180; + + deltaZ = zFar - zNear; + sincos(radians, &sine, &cosine); + + if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) + return; + + cotangent = cosine / sine; + + tmp[0] = cotangent / aspect; + tmp[5] = cotangent; + tmp[10] = -(zFar + zNear) / deltaZ; + tmp[11] = -1; + tmp[14] = -2 * zNear * zFar / deltaZ; + tmp[15] = 0; + + memcpy(m, tmp, sizeof(tmp)); +} + +/** + * Draws a gear. + * + * @param gear the gear to draw + * @param transform the current transformation matrix + * @param x the x position to draw the gear at + * @param y the y position to draw the gear at + * @param angle the rotation angle of the gear + * @param color the color of the gear + */ +static void +draw_gear(struct gear *gear, GLfloat *transform, + GLfloat x, GLfloat y, GLfloat angle, const GLfloat color[4]) +{ + GLfloat model_view[16]; + GLfloat normal_matrix[16]; + GLfloat model_view_projection[16]; + + /* Translate and rotate the gear */ + memcpy(model_view, transform, sizeof (model_view)); + translate(model_view, x, y, 0); + rotate(model_view, 2 * M_PI * angle / 360.0, 0, 0, 1); + + /* Create and set the ModelViewProjectionMatrix */ + memcpy(model_view_projection, ProjectionMatrix, sizeof(model_view_projection)); + multiply(model_view_projection, model_view); + + glUniformMatrix4fv(ModelViewProjectionMatrix_location, 1, GL_FALSE, + model_view_projection); + + /* + * Create and set the NormalMatrix. It's the inverse transpose of the + * ModelView matrix. + */ + memcpy(normal_matrix, model_view, sizeof (normal_matrix)); + invert(normal_matrix); + transpose(normal_matrix); + glUniformMatrix4fv(NormalMatrix_location, 1, GL_FALSE, normal_matrix); + + /* Set the gear color */ + glUniform4fv(MaterialColor_location, 1, color); + + /* Set the vertex buffer object to use */ + glBindBuffer(GL_ARRAY_BUFFER, gear->vbo); + + /* Set up the position of the attributes in the vertex buffer object */ + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, + 6 * sizeof(GLfloat), NULL); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, + 6 * sizeof(GLfloat), (GLfloat *) 0 + 3); + + /* Enable the attributes */ + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + + /* Draw the triangle strips that comprise the gear */ + int n; + for (n = 0; n < gear->nstrips; n++) + glDrawArrays(GL_TRIANGLE_STRIP, gear->strips[n].first, gear->strips[n].count); + + /* Disable the attributes */ + glDisableVertexAttribArray(1); + glDisableVertexAttribArray(0); +} + +/** + * Draws the gears. + */ +static void +gears_draw(void) +{ + const static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 }; + const static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 }; + const static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 }; + GLfloat transform[16]; + identity(transform); + + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* Translate and rotate the view */ + translate(transform, 0, 0, -20); + rotate(transform, 2 * M_PI * view_rot[0] / 360.0, 1, 0, 0); + rotate(transform, 2 * M_PI * view_rot[1] / 360.0, 0, 1, 0); + rotate(transform, 2 * M_PI * view_rot[2] / 360.0, 0, 0, 1); + + /* Draw the gears */ + draw_gear(gear1, transform, -3.0, -2.0, angle, red); + draw_gear(gear2, transform, 3.1, -2.0, -2 * angle - 9.0, green); + draw_gear(gear3, transform, -3.1, 4.2, -2 * angle - 25.0, blue); + + glutSwapBuffers(); +} + +/** + * Handles a new window size or exposure. + * + * @param width the window width + * @param height the window height + */ +static void +gears_reshape(int width, int height) +{ + /* Update the projection matrix */ + perspective(ProjectionMatrix, 60.0, width / (float)height, 1.0, 1024.0); + + /* Set the viewport */ + glViewport(0, 0, (GLint) width, (GLint) height); +} + +/** + * Handles special glut events. + * + * @param special the event to handle. + */ +static void +gears_special(int special, int crap, int morecrap) +{ + switch (special) { + case GLUT_KEY_LEFT: + view_rot[1] += 5.0; + break; + case GLUT_KEY_RIGHT: + view_rot[1] -= 5.0; + break; + case GLUT_KEY_UP: + view_rot[0] += 5.0; + break; + case GLUT_KEY_DOWN: + view_rot[0] -= 5.0; + break; + } +} + +static void +gears_idle(void) +{ + static int frames = 0; + static double tRot0 = -1.0, tRate0 = -1.0; + double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0; + + if (tRot0 < 0.0) + tRot0 = t; + dt = t - tRot0; + tRot0 = t; + + /* advance rotation for next frame */ + angle += 70.0 * dt; /* 70 degrees per second */ + if (angle > 3600.0) + angle -= 3600.0; + + glutPostRedisplay(); + frames++; + + if (tRate0 < 0.0) + tRate0 = t; + if (t - tRate0 >= 5.0) { + GLfloat seconds = t - tRate0; + GLfloat fps = frames / seconds; + printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds, + fps); + tRate0 = t; + frames = 0; + } +} + +static const char vertex_shader[] = +"attribute vec3 position;\n" +"attribute vec3 normal;\n" +"\n" +"uniform mat4 ModelViewProjectionMatrix;\n" +"uniform mat4 NormalMatrix;\n" +"uniform vec4 LightSourcePosition;\n" +"uniform vec4 MaterialColor;\n" +"\n" +"varying vec4 Color;\n" +"\n" +"void main(void)\n" +"{\n" +" // Transform the normal to eye coordinates\n" +" vec3 N = normalize(vec3(NormalMatrix * vec4(normal, 1.0)));\n" +"\n" +" // The LightSourcePosition is actually its direction for directional light\n" +" vec3 L = normalize(LightSourcePosition.xyz);\n" +"\n" +" // Multiply the diffuse value by the vertex color (which is fixed in this case)\n" +" // to get the actual color that we will use to draw this vertex with\n" +" float diffuse = max(dot(N, L), 0.0);\n" +" Color = diffuse * MaterialColor;\n" +"\n" +" // Transform the position to clip coordinates\n" +" gl_Position = ModelViewProjectionMatrix * vec4(position, 1.0);\n" +"}"; + +static const char fragment_shader[] = +"#ifdef GL_ES\n" +"precision mediump float;\n" +"#endif\n" +"varying vec4 Color;\n" +"\n" +"void main(void)\n" +"{\n" +" vec2 d = dFdx(Color.xy);\n" +" gl_FragColor = Color;\n" +"}"; + +static void +gears_init(void) +{ + GLuint v, f, program; + const char *p; + char msg[512]; + + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + + /* Compile the vertex shader */ + p = vertex_shader; + v = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(v, 1, &p, NULL); + glCompileShader(v); + glGetShaderInfoLog(v, sizeof msg, NULL, msg); + printf("vertex shader info: %s\n", msg); + + /* Compile the fragment shader */ + p = fragment_shader; + f = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(f, 1, &p, NULL); + glCompileShader(f); + glGetShaderInfoLog(f, sizeof msg, NULL, msg); + printf("fragment shader info: %s\n", msg); + + /* Create and link the shader program */ + program = glCreateProgram(); + glAttachShader(program, v); + glAttachShader(program, f); + glBindAttribLocation(program, 0, "position"); + glBindAttribLocation(program, 1, "normal"); + + glLinkProgram(program); + glGetProgramInfoLog(program, sizeof msg, NULL, msg); + printf("info: %s\n", msg); + + /* Enable the shaders */ + glUseProgram(program); + + /* Get the locations of the uniforms so we can access them */ + ModelViewProjectionMatrix_location = glGetUniformLocation(program, "ModelViewProjectionMatrix"); + NormalMatrix_location = glGetUniformLocation(program, "NormalMatrix"); + LightSourcePosition_location = glGetUniformLocation(program, "LightSourcePosition"); + MaterialColor_location = glGetUniformLocation(program, "MaterialColor"); + + /* Set the LightSourcePosition uniform which is constant throught the program */ + glUniform4fv(LightSourcePosition_location, 1, LightSourcePosition); + + /* make the gears */ + gear1 = create_gear(1.0, 4.0, 1.0, 20, 0.7); + gear2 = create_gear(0.5, 2.0, 2.0, 10, 0.7); + gear3 = create_gear(1.3, 2.0, 0.5, 10, 0.7); +} + +int +main(int argc, char *argv[]) +{ + /* Initialize the window */ + glutInit(&argc, argv); + glutInitWindowSize(300, 300); + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); + + glutCreateWindow("es2gears"); + + /* Set up glut callback functions */ + gears_idle(); + glutReshapeFunc(gears_reshape); + glutDisplayFunc(gears_draw); + glutSpecialFunc(gears_special); + + /* Initialize the gears */ + gears_init(); + + glutMainLoop(); + + return 0; +} diff --git a/tests/hello_world_gles_shell.html b/tests/hello_world_gles_shell.html index d3429e3a..343ddb64 100644 --- a/tests/hello_world_gles_shell.html +++ b/tests/hello_world_gles_shell.html @@ -36,7 +36,7 @@ var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://localhost:8888/report_gl_result?' + result, true); xhr.send(); - setTimeout(function() { _glutDisplayFunc = function(){} }, 2000); // Stop rendering after a while + setTimeout(function() { window.close() }, 1000); } function doTest() { var firstImage = Module.canvas.toDataURL(); diff --git a/tests/hello_world_sdl.cpp b/tests/hello_world_sdl.cpp index df69b055..b6401995 100644 --- a/tests/hello_world_sdl.cpp +++ b/tests/hello_world_sdl.cpp @@ -14,13 +14,14 @@ int main() { *((char*)screen->pixels + i*256*4 + j*4 + 0) = i; *((char*)screen->pixels + i*256*4 + j*4 + 1) = j; *((char*)screen->pixels + i*256*4 + j*4 + 2) = 255-i; - *((char*)screen->pixels + i*256*4 + j*4 + 3) = 255; + *((char*)screen->pixels + i*256*4 + j*4 + 3) = (i+j)%255; // actually ignored, since this is to the screen } } if (SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen); SDL_Flip(screen); - printf("you should see a colored cube."); + printf("you should see a smoothly-colored square - no sharp lines but the square borders!\n"); + printf("and here is some text that should be HTML-friendly: amp: |&| double-quote: |\"| quote: |'| less-than, greater-than, html-like tags: |<cheez></cheez>|\nanother line.\n"); SDL_Quit(); diff --git a/tests/htmltest.png b/tests/htmltest.png Binary files differnew file mode 100644 index 00000000..980245ee --- /dev/null +++ b/tests/htmltest.png diff --git a/tests/i64_precise.txt b/tests/i64_precise.txt new file mode 100644 index 00000000..69f1f306 --- /dev/null +++ b/tests/i64_precise.txt @@ -0,0 +1,128 @@ +unsigned 0: 0,5,5,18446744073709551611,0,0,0,0,0 +unsigned 1: 0,35,35,18446744073709551581,0,0,0,0,0 +unsigned 2: 1,195,196,18446744073709551422,195,0,195,1,0 +unsigned 3: 3,1020,1023,18446744073709550599,3060,0,340,3,0 +unsigned 4: 6,5195,5201,18446744073709546427,31170,0,865,6,5 +unsigned 5: 12,26165,26177,18446744073709525463,313980,0,2180,12,5 +unsigned 6: 25,131205,131230,18446744073709420436,3280125,0,5248,25,5 +unsigned 7: 51,656790,656841,18446744073708894877,33496290,0,12878,51,12 +unsigned 8: 102,3285485,3285587,18446744073706266233,335119470,0,32210,102,65 +unsigned 9: 204,16430495,16430699,18446744073693121325,3351820980,0,80541,204,131 +unsigned 10: 409,82158615,82159024,18446744073627393410,33602873535,0,200876,409,331 +unsigned 11: 819,410805360,410806179,18446744073298747075,336449589840,0,501593,819,693 +unsigned 12: 1638,2054051375,2054053013,18446744071655501879,3364536152250,0,1253999,1638,1013 +unsigned 13: 3276,10270306025,10270309301,18446744063439248867,33645522537900,0,3135014,3276,161 +unsigned 14: 6553,51351628425,51351634978,18446744022357929744,336507221069025,0,7836354,6553,663 +unsigned 15: 13107,256758338730,256758351837,18446743816951225993,3365331545734110,0,19589405,13107,7395 +unsigned 16: 26214,1283792086865,1283792113079,18446742789917490965,33653325765079110,0,48973528,26214,23873 +unsigned 17: 52428,6418961220755,6418961273183,18446737654748383289,336533298881743140,0,122433837,52428,14519 +unsigned 18: 104857,32094807676635,32094807781492,18446711978901979838,3365365248548916195,0,306081689,104857,13162 +unsigned 19: 209715,160474041528900,160474041738615,18446583599668232431,15207069545523711884,0,765200589,209715,6765 +unsigned 20: 419430,802370213935955,802370214355385,18445941703496035091,4496745504385676562,0,1913001487,419430,243545 +unsigned 21: 838860,4011851082262685,4011851083101545,18442732222628127791,8073977451737544988,0,4782503733,838860,798305 +unsigned 22: 1677721,20059255436479245,20059255438156966,18426684818274750092,6972899699173253061,0,11956252223,1677721,655462 +unsigned 23: 3355443,100296277232727870,100296277236083313,18346447796480179189,14489229932752165722,0,29890621665,3355443,1255275 +unsigned 24: 6710886,501481386264302645,501481386271013531,17945262687451959857,15765766351451925278,0,74726554178,6710886,2920937 +unsigned 25: 13421772,2507406931522839815,2507406931536261587,15939337142200133573,10086413084431357332,0,186816385461,13421772,1182923 +unsigned 26: 26843545,12537034658016852255,12537034658043695800,5909709415719542906,2731509698427185799,0,467040946269,26843545,2368650 +unsigned 27: 53687091,7344941069760912792,7344941069814599883,11101803004002325915,16256528535618547016,0,136810189059,53687091,23175423 +unsigned 28: 107374182,18277961276705625079,18277961276812999261,168782797111300719,15164270991448465002,0,170226780183,107374182,62189773 +unsigned 29: 214748364,17602830091911144401,17602830092125892765,843913982013155579,4760510224565868172,0,81969565513,214748364,203573669 +unsigned 30: 429496729,14227174171159966481,14227174171589463210,4219569902979081864,9259055794720517673,0,33125221242,429496729,319649063 +unsigned 31: 858993459,15795638647556079442,15795638648415072901,2651105427012465633,8773778578690814806,0,18388543570,858993459,389570812 +unsigned 32: 1717986918,5191216968711994521,5191216970429981439,13255527106715544013,2882763035818302198,0,3021685971,1717986918,229867143 +unsigned 33: 3435973836,7509340821390028539,7509340824826002375,10937403255755496913,3002188606886016004,0,2185505821,3435973836,2008329183 +unsigned 34: 6871947673,653216062610254563,653216069482202236,17793528017971244726,1160311421120597163,0,95055447,6871947673,4792629732 +unsigned 35: 13743895347,3266080519209703020,3266080532953598367,15180663568243743943,7490496812310051716,0,237638634,13743895347,3109667022 +unsigned 36: 27487790694,16330403008365375515,16330403035853166209,2116341092831966795,8496689265331596482,0,594096600,27487790694,15548335115 +unsigned 37: 54975581388,7865039571622391941,7865039626597973329,10581704557062741063,3801217959335798268,0,143064236,54975581388,21692352373 +unsigned 38: 109951162777,2431711359960298133,2431711469911460910,16015032823700416260,10929097356750440461,0,22116285,109951162777,107902774688 +unsigned 39: 219902325555,12158560098336373990,12158560318238699545,6288184195275503181,3390366976150811602,0,55290729,219902325555,209605094395 +unsigned 40: 439804651110,5452574867622981757,5452575307427632867,12994169645891220969,4388876164940275662,0,12397719,439804651110,388268163667 +unsigned 41: 879609302220,8816143458544890479,8816144338154192699,9630601494773963357,18063307631679153268,0,10022794,879609302220,621910087799 +unsigned 42: 1759218604441,7187255533584415783,7187257292803020224,11259490299343740274,10731539484643328591,0,4085481,1759218604441,1350294194662 +unsigned 43: 3518437208883,17489586370770660544,17489589889207869427,957161221376099955,6745745258281429568,0,4970839,3518437208883,1473803897707 +unsigned 44: 7036874417766,13661061112131362751,13661068149005780517,4785689998452606631,1049124659338985498,0,1941353,7036874417766,3850578085353 +unsigned 45: 14073748835532,12965284445760691897,12965298519509527429,5481473701697695251,3112351931422336876,0,921238,14073748835532,12216012863281 +unsigned 46: 28147497671065,9486612220139870617,9486640367637541682,8960160001067352064,11094552886493166961,0,337032,28147497671065,4785065491537 +unsigned 47: 56294995342131,10540417378210381818,10540473673205723949,7906382990494511929,3425601976498736334,0,187235,56294995342131,23925326484033 +unsigned 48: 112589990684262,15810287593493069793,15810400183483754055,2636569070207166085,4740441117117290918,0,140423,112589990684262,63331636946967 +unsigned 49: 225179981368524,5267839372347670371,5268064552329038895,13179129881343249769,3129072874530825956,0,23393,225179981368524,204068193788439 +unsigned 50: 450359962737049,7899208187469855979,7899658547432593028,10547986246202432686,9662536335886195571,0,17539,450359962737049,344801024753568 +unsigned 51: 900719925474099,2616063588812288148,2616964308737762247,15831581204822737567,18056837904917260668,0,2904,900719925474099,372925235504652 +unsigned 52: 1801439850948198,13107339541825663715,13109140981676611913,5341205971734836099,3467025862604273778,0,7276,1801439850948198,63186326575067 +unsigned 53: 3602879701896396,10250508683528109677,10254111563230006073,8199838269883338335,8794376607022815964,0,2845,3602879701896396,315931632863057 +unsigned 54: 7205759403792793,14467141661278337053,14474347420682129846,3986808171835007356,17354123729136361045,0,2007,7205759403792793,5182537866201502 +unsigned 55: 14411518807585587,17211648867376814222,17226060386184399809,1249506725140322981,17050849970911342154,0,1194,14411518807585587,4295411119623344 +unsigned 56: 28823037615171174,12703613606273432261,12732436643888603435,5771953505051290529,11664739411905079422,0,440,28823037615171174,21477055598115701 +unsigned 57: 57646075230342348,9042526938693641687,9100173013923984035,9461863210246252277,16227931067794422612,0,156,57646075230342348,49739202760235399 +unsigned 58: 115292150460684697,10048528802959375663,10163820953420060360,8513507421210860650,10457660234102286359,0,87,115292150460684697,18111712879807024 +unsigned 59: 230584300921369395,16807920381198316008,17038504682119685403,1869407993432605003,16929834404840843576,0,72,230584300921369395,205850714859719568 +unsigned 60: 461168601842738790,17170154638794455431,17631323240637194221,1737758036757834975,7428164801607120330,0,37,461168601842738790,106916370613120201 +unsigned 61: 922337203685477580,7452110880706682785,8374448084392160365,11916970396688346411,17096741387571593292,0,8,922337203685477580,73413251222862145 +unsigned 62: 1844674407370955161,9590438292969086497,11435112700340041658,10700980188111420280,7158457875815234233,0,5,1844674407370955161,367066256114310692 +unsigned 63: 3689348814741910323,11058703317426329250,14748052132168239573,11077389571025132689,16235003410224285766,0,2,3689348814741910323,3680005687942508604 +signed 0: 0,5,5,-5,0,0,0,0,0 +signed 1: 0,-35,-35,35,0,0,0,0,0 +signed 2: -1,-155,-156,154,155,0,155,-1,0 +signed 3: -2,740,738,-742,-1480,0,-370,-2,0 +signed 4: -4,3770,3766,-3774,-15080,0,-942,-4,2 +signed 5: -9,-18990,-18999,18981,170910,0,2110,-9,0 +signed 6: -18,-94675,-94693,94657,1704150,0,5259,-18,-13 +signed 7: 36,472825,472861,-472789,17021700,0,13134,36,1 +signed 8: -97,2365585,2365488,-2365682,-229461745,0,-24387,-97,46 +signed 9: -138,-11830000,-11830138,11829862,1632540000,0,85724,-138,-88 +signed 10: -295,-59145570,-59145865,59145275,17447943150,0,200493,-295,-135 +signed 11: -584,295719085,295718501,-295719669,-172699945640,0,-506368,-584,173 +signed 12: -1170,1478612985,1478611815,-1478614155,-1729977192450,0,-1263771,-1170,915 +signed 13: -2340,-7393100035,-7393102375,7393097695,17299854081900,0,3159444,-2340,-1075 +signed 14: 4681,-36965429955,-36965425274,36965434636,-173035177619355,0,-7896908,4681,-3607 +signed 15: -12483,184826962530,184826950047,-184826975013,-2307194973261990,0,-14806293,-12483,7011 +signed 16: -17684,924135077915,924135060231,-924135095599,-16342404717848860,0,-52258260,-17684,8075 +signed 17: -37796,-4620675956515,-4620675994311,4620675918719,174643068452440940,0,122253041,-37796,-18879 +signed 18: -74782,-23103378660835,-23103378735617,23103378586053,1727716863014562970,0,308943043,-74782,-19209 +signed 19: -149835,115516891056645,115516890906810,-115516891206480,1138270702237148041,0,-770960663,-149835,116040 +signed 20: -299580,577584459776930,577584459477350,-577584460076510,-7012055796586724856,0,-1927980705,-299580,173030 +signed 21: 599190,-2887922307872510,-2887922307273320,2887922308471700,3579775274568585004,0,-4819710455,599190,-341060 +signed 22: -1597831,-14439611515395080,-14439611516992911,14439611513797249,-4817928955413000136,0,9037007991,-1597831,-127559 +signed 23: -2263592,72198057543021515,72198057540757923,-72198057545285107,-7239720930239415736,0,-31895349313,-2263592,909219 +signed 24: -4837874,360990287787675695,360990287782837821,-360990287792513569,1520893864324420754,0,-74617546423,-4837874,4050993 +signed 25: -9572186,-1804951439081961265,-1804951439091533451,1804951439072389079,-284040605827480006,0,188562094288,-9572186,-7687697 +signed 26: -19178892,-9024757195122122935,-9024757195141301827,9024757195102944043,3158545232664844052,0,470556755579,-19178892,-2084467 +signed 27: -38346278,8230297827616317263,8230297827577970985,-8230297827654663541,-2447170876606408634,0,-214630943519,-38346278,34444981 +signed 28: 76696392,4258000991812928973,4258000991889625365,-4258000991736232581,-4010249384068861784,0,55517617984,76696392,5815245 +signed 29: -204522434,-2843260888422929769,-2843260888627452203,2843260888218407335,-3330061828535700334,0,13901951159,-204522434,-35128763 +signed 30: -289739796,4230439635940999721,4230439635651259925,-4230439636230739517,-8819265314490703668,0,-14600823547,-289739796,1223309 +signed 31: -619247950,-2705454115284166249,-2705454115903414199,2705454114664918299,4237355741738226942,0,4368935117,-619247950,-398906099 +signed 32: -1225239782,4919473515667317101,4919473514442077319,-4919473516892556883,8469738706080185362,0,-4015110828,-1225239782,62757605 +signed 33: -2454898270,-6150623541450507939,-6150623543905406209,6150623538995609669,-6720592984569904678,0,2505449458,-2454898270,-1433870279 +signed 34: -4908323638,6140370513791418107,6140370508883094469,-6140370518699741745,-2321546656369961458,0,-1251011743,-4908323638,4208937073 +signed 35: 9817138243,6191635431204939047,6191635441022077290,-6191635421387800804,1329921992230270261,0,630696571,9817138243,4311874294 +signed 36: -26178871659,-5935310598711333102,-5935310624890204761,5935310572532461443,-1523401759741279878,0,226721406,-26178871659,-8689300548 +signed 37: -37086693937,-7216935710162846787,-7216935747249540724,7216935673076152850,4375670093386346195,0,194596361,-37086693937,-28501883530 +signed 38: -79263737669,808810785560934332,808810706297196663,-808810864824672001,1308775974572414548,0,-10204045,-79263737669,39518263227 +signed 39: -156830692073,-4044056280265052755,-4044056437095744828,4044056123434360682,3200853909245289355,0,25786127,-156830692073,-136972781484 +signed 40: -314226978567,-1773532614211033644,-1773532928438012211,1773532299984055077,149458714710412084,0,5644113,-314226978567,-39530307573 +signed 41: -628265425661,8867653647073783295,8867653018808357634,-8867654275339208956,1335113139221865725,0,-14114502,-628265425661,40050747473 +signed 42: 1256593695147,7444798936855240458,7444800193448935605,-7444797680261545311,194995390784062894,0,5924587,1256593695147,266305361169 +signed 43: -3350895572451,-330556800290685833,-330560151186258284,330553449395113382,-3084978225808244869,0,98647,-3350895572451,-1004755112036 +signed 44: -4747096823988,-1652712795001069340,-1652717542097893328,1652708047904245352,888305014260137904,0,348152,-4747096823988,-1541535999164 +signed 45: -10145758421614,8263411788629022480,8263401642870600866,-8263421934387444094,1433933448381331232,0,-814469,-10145758421614,6072735489514 +signed 46: -20074328585350,4423871910654789418,4423851836326204068,-4423891984983374768,1087756533121529860,0,-220374,-20074328585350,11822986868518 +signed 47: -40221053256659,-3673218795363245364,-3673259016416502023,3673178574309988705,-3788250272949359140,0,91325,-40221053256659,-31106698862189 +signed 48: -80417974484665,81856366510594781,81775948536110116,-81936784485079446,3556652555309224011,0,-1017,-80417974484665,71286459690476 +signed 49: 160843992978882,-411694492447657140,-411533648454678258,411855336440636022,8646015829301599128,0,-2559,160843992978882,-94714414698102 +signed 50: -428914633273835,-2052038742739178170,-2052467657372452005,2051609828105904335,4194688249318378174,0,4784,-428914633273835,-111137157151530 +signed 51: -607628393470471,-8195664785915717831,-8196272414309188302,8195057157522247360,245300141642486641,0,13487,-607628393470471,-580643179475454 +signed 52: -1298657077966675,-4065355925989985798,-4066654583067952473,4064057268912019123,1136007313742779890,0,3130,-1298657077966675,-559271954293048 +signed 53: -2569514058924772,1841492845356505789,1838923331297581017,-1844062359415430561,6068344375485822380,0,-716,-2569514058924772,1720779166369037 +signed 54: -5148294816852404,-9162055424674236611,-9167203719491089015,9156907129857384207,-6087205165210098660,0,1779,-5148294816852404,-3238945493809895 +signed 55: -10293500734037188,8762386464941522003,8752092964207484815,-8772679965675559191,8399093139116719220,0,-851,-10293500734037188,2617340275875015 +signed 56: 20588031101296916,7227264643807960523,7247852674909257439,-7206676612706663607,-3352533841896882468,0,351,20588031101296916,865727252743007 +signed 57: -54901073059050929,-66351167506463323,-121252240565514252,11450094447412394,1896642381847523307,0,1,-54901073059050929,-11450094447412394 +signed 58: -77776434364220271,834890677930987460,757114243566767189,-912667112295207731,-3500275542106939900,0,-10,-77776434364220271,57126334288784750 +signed 59: -166228105979734405,-6667874979350953385,-6834103085330687790,6501646873371218980,-4513011972483376691,0,40,-166228105979734405,-18750740161577185 +signed 60: -328897799542370857,8487580243799899162,8158682444257528305,-8816478043342270019,-905439778191045674,0,-25,-328897799542370857,265135255240627737 +signed 61: -658981736557107698,3017604953772543563,2358623217215435865,-3676586690329651261,-378165734266082790,0,-4,-658981736557107698,381678007544112771 +signed 62: -1317568093956760068,-2041941969204984387,-3359510063161744455,724373875248224319,-7186442770938425588,0,1,-1317568093956760068,-724373875248224319 +signed 63: 2635267980966005246,7574178278953946467,-8237297813789599903,-4938910297987941221,1110862422097806138,0,2,2635267980966005246,2303642317021935975 diff --git a/tests/python/ccproxy.py b/tests/python/ccproxy.py index 853b30f4..82750096 100644 --- a/tests/python/ccproxy.py +++ b/tests/python/ccproxy.py @@ -85,4 +85,4 @@ with open('ccproxy.log', 'a') as f: print "Running:", call, newargs -os.execvp(call, [call] + newargs) +subprocess.call([call] + newargs) diff --git a/tests/runner.py b/tests/runner.py index 26ae51f5..58a18555 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -14,7 +14,38 @@ will use 4 processes. To install nose do something like ''' from subprocess import Popen, PIPE, STDOUT -import os, unittest, tempfile, shutil, time, inspect, sys, math, glob, tempfile, re, difflib, webbrowser, hashlib, BaseHTTPServer, threading, platform +import os, unittest, tempfile, shutil, time, inspect, sys, math, glob, tempfile, re, difflib, webbrowser, hashlib, threading, platform, BaseHTTPServer, multiprocessing, functools + + +if len(sys.argv) == 1: + print ''' +============================================================================== +Running the main part of the test suite. Don't forget to run the other parts! + + sanity - tests for first run, etc., modifies ~/.emscripten + benchmark - run before and after each set of changes before pushing to + master, verify no regressions + browser - runs pages in a web browser + +To run one of those parts, do something like + + python tests/runner.py sanity + +To run a specific set of tests, you can do things like + + python tests/runner.py o1 + +(that runs the o1 (-O1) tests). You can run individual tests with + + python tests/runner.py test_hello_world + +Combinations work too, for example + + python tests/runner.py browser.test_sdl_image +============================================================================== + +''' + time.sleep(2) # Setup @@ -48,7 +79,7 @@ class RunnerCore(unittest.TestCase): if not self.save_dir: dirname = tempfile.mkdtemp(prefix='emscripten_test_' + self.__class__.__name__ + '_', dir=TEMP_DIR) else: - dirname = EMSCRIPTEN_TEMP_DIR + dirname = CANONICAL_TEMP_DIR if not os.path.exists(dirname): os.makedirs(dirname) self.working_dir = dirname @@ -62,6 +93,8 @@ class RunnerCore(unittest.TestCase): shutil.copy(os.path.join(self.get_dir(), name), os.path.join(TEMP_DIR, self.id().replace('__main__.', '').replace('.test_', '.')+'.'+suff)) if not self.save_dir: + # rmtree() fails on Windows if the current working directory is inside the tree. + os.chdir(os.path.join(self.get_dir(), '..')) shutil.rmtree(self.get_dir()) def skip(self, why): @@ -134,7 +167,7 @@ class RunnerCore(unittest.TestCase): transform = open(transform_filename, 'w') transform.write(''' import sys -sys.path += ['%s'] +sys.path += [%r] ''' % path_from_root('')) transform.write(post1) transform.write(''' @@ -162,6 +195,9 @@ process(sys.argv[1]) additional_files = final_additional_files else: # copy whole directory, and use a specific main .cpp file + # (rmtree() fails on Windows if the current working directory is inside the tree.) + if os.getcwd().startswith(os.path.abspath(dirname)): + os.chdir(os.path.join(dirname, '..')) shutil.rmtree(dirname) shutil.copytree(src, dirname) shutil.move(os.path.join(dirname, main_file), filename) @@ -252,7 +288,13 @@ process(sys.argv[1]) library_cache = {} - def get_library(self, name, generated_libs, configure=['./configure'], configure_args=[], make=['make'], make_args=['-j', '2'], cache=True): + def get_build_dir(self): + ret = os.path.join(self.get_dir(), 'building') + if not os.path.exists(ret): + os.makedirs(ret) + return ret + + def get_library(self, name, generated_libs, configure=['sh', './configure'], configure_args=[], make=['make'], make_args=['-j', '2'], cache=True): build_dir = self.get_build_dir() output_dir = self.get_dir() @@ -274,12 +316,20 @@ process(sys.argv[1]) return Building.build_library(name, build_dir, output_dir, generated_libs, configure, configure_args, make, make_args, self.library_cache, cache_name, copy_project=True) + def clear(self): + for name in os.listdir(self.get_dir()): + try_delete(name) + emcc_debug = os.environ.get('EMCC_DEBUG') + if emcc_debug: + for name in os.listdir(EMSCRIPTEN_TEMP_DIR): + try_delete(os.path.join(EMSCRIPTEN_TEMP_DIR, name)) + ################################################################################################### sys.argv = map(lambda arg: arg if not arg.startswith('test_') else 'default.' + arg, sys.argv) -if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv): +if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'browser' not in str(sys.argv): # Tests print "Running Emscripten tests..." @@ -568,13 +618,13 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv): return 0; } ''' - self.do_run(src, '*1311918518731868200\n' + + self.do_run(src, '*1311918518731868041\n' + '0,0,0,1,1\n' + '1,0,1,0,1*\n' + '*245127260211081*\n' + '*245127260209443*\n' + - '*18446744073709552000*\n' + - '*576460752303423500*\n' + + '*18446744073709551615*\n' + + '*576460752303423487*\n' + 'm1: 127\n' + '*123*\n' + '*127*\n' + @@ -689,6 +739,51 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv): self.do_run(src, '*1,1,0,0,1,0*\n') + def test_i64_cmp2(self): + if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2') + src = r''' + #include <inttypes.h> + #include <stdio.h> + + typedef int32_t INT32; + typedef int64_t INT64; + typedef uint8_t UINT8; + + void interface_clock_changed() + { + UINT8 m_divshift; + INT32 m_divisor; + + //INT64 attos = m_attoseconds_per_cycle; + INT64 attos = 279365114840; + m_divshift = 0; + while (attos >= (1UL << 31)) + { + m_divshift++; + printf("m_divshift is %i, on %Ld >?= %lu\n", m_divshift, attos, 1UL << 31); + attos >>= 1; + } + m_divisor = attos; + + printf("m_divisor is %i\n",m_divisor); + } + + int main() { + interface_clock_changed(); + return 0; + } + ''' + self.do_run(src, '''m_divshift is 1, on 279365114840 >?= 2147483648 +m_divshift is 2, on 139682557420 >?= 2147483648 +m_divshift is 3, on 69841278710 >?= 2147483648 +m_divshift is 4, on 34920639355 >?= 2147483648 +m_divshift is 5, on 17460319677 >?= 2147483648 +m_divshift is 6, on 8730159838 >?= 2147483648 +m_divshift is 7, on 4365079919 >?= 2147483648 +m_divshift is 8, on 2182539959 >?= 2147483648 +m_divisor is 1091269979 +''') + def test_i64_double(self): if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2') src = r''' @@ -731,6 +826,101 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv): ''' self.do_run(src, '*0,0,0,0*\n*1,1,0,0*\n') # same as gcc + def test_i64_umul(self): + if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2') + src = r''' + #include <inttypes.h> + #include <stdio.h> + + typedef uint32_t UINT32; + typedef uint64_t UINT64; + + int main() { + volatile UINT32 testu32a = 2375724032U; + UINT32 bigu32 = 0xffffffffU; + volatile UINT64 testu64a = 14746250828952703000U; + + while ((UINT64)testu32a * (UINT64)bigu32 < testu64a) { + printf("testu64a is %llu\n", testu64a); + testu64a /= 2; + } + + return 0; + } + ''' + self.do_run(src, 'testu64a is 14746250828952703000\n') + + def test_i64_precise(self): + if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2') + + src = r''' + #include <inttypes.h> + #include <stdio.h> + + int main() { + uint64_t x = 0, y = 0; + for (int i = 0; i < 64; i++) { + x += 1ULL << i; + y += x; + x /= 3; + y *= 5; + printf("unsigned %d: %llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu\n", i, x, y, x+y, x-y, x*y, y ? x/y : 0, x ? y/x : 0, y ? x%y : 0, x ? y%x : 0); + } + int64_t x2 = 0, y2 = 0; + for (int i = 0; i < 64; i++) { + x2 += 1LL << i; + y2 += x2; + x2 /= 3 * (i % 7 ? -1 : 1); + y2 *= 5 * (i % 2 ? -1 : 1); + printf("signed %d: %lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld\n", i, x2, y2, x2+y2, x2-y2, x2*y2, y2 ? x2/y2 : 0, x2 ? y2/x2 : 0, y2 ? x2%y2 : 0, x2 ? y2%x2 : 0); + } + return 0; + } + ''' + self.do_run(src, open(path_from_root('tests', 'i64_precise.txt')).read()) + + # Verify that without precision, we do not include the precision code + Settings.PRECISE_I64_MATH = 0 + self.do_run(src, 'unsigned') + code = open(os.path.join(self.get_dir(), 'src.cpp.o.js')).read() + assert 'goog.math.Long' not in code and 'jsbn' not in code, 'i64 precise math should not have been included if not asked for' + + # Verify that even if we ask for precision, if it is not needed it is not included + Settings.PRECISE_I64_MATH = 1 + src = ''' + #include <inttypes.h> + #include <stdio.h> + + int main(int argc, char **argv) { + uint64_t x = 2125299906845564, y = 1225891506842664; + if (argc == 12) { + x = x >> 1; + y = y >> 1; + } + x = x & 12ULL; + y = y | 12ULL; + x = x ^ y; + x <<= 2; + y >>= 3; + printf("*%llu, %llu*\\n", x, y); + } + ''' + self.do_run(src, '*4903566027370624, 153236438355333*') + code = open(os.path.join(self.get_dir(), 'src.cpp.o.js')).read() + assert 'goog.math.Long' not in code and 'jsbn' not in code, 'i64 precise math should not have been included if not actually used' + + def test_cube2hash(self): + # A good test of i64 math + if Settings.USE_TYPED_ARRAYS != 2: return self.skip('requires ta2 C-style memory aliasing') + self.do_run('', 'Usage: hashstring <seed>', + libraries=self.get_library('cube2hash', ['cube2hash.bc'], configure=None), + includes=[path_from_root('tests', 'cube2hash')]) + + for text, output in [('fleefl', '892BDB6FD3F62E863D63DA55851700FDE3ACF30204798CE9'), + ('fleefl2', 'AA2CC5F96FC9D540CA24FDAF1F71E2942753DB83E8A81B61'), + ('64bitisslow', '64D8470573635EC354FEE7B7F87C566FCAF1EFB491041670')]: + self.do_run('', 'hash value: ' + output, [text], no_build=True) + def test_unaligned(self): if Settings.QUANTUM_SIZE == 1: return self.skip('No meaning to unaligned addresses in q1') @@ -1440,6 +1630,9 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv): if self.emcc_args is None: if Building.LLVM_OPTS: return self.skip('optimizing bitcode before emcc can confuse libcxx inclusion') self.emcc_args = [] # libc++ auto-inclusion is only done if we use emcc + else: + if '-O2' in self.emcc_args: + self.emcc_args += ['--closure', '1'] # Use closure here for some additional coverage src = ''' #include <stdio.h> @@ -1520,6 +1713,8 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv): def test_uncaught_exception(self): if self.emcc_args is None: return self.skip('no libcxx inclusion without emcc') + if '-O2' in self.emcc_args: + self.emcc_args += ['--closure', '1'] # Use closure here for some additional coverage Settings.EXCEPTION_DEBUG = 0 # Messes up expected output. Settings.DISABLE_EXCEPTION_CATCHING = 0 @@ -1623,6 +1818,18 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv): ''' self.do_run(src, '*51,87,78,550,100,78,550*') + def test_isdigit_l(self): + if self.emcc_args is None: return self.skip('no libcxx inclusion without emcc') + + src = ''' + #include <iostream> + int main() { + using namespace std; + use_facet<num_put<char> >(cout.getloc()).put(cout, cout, '0', 3.14159265); + } + ''' + self.do_run(src, '3.14159') + def test_polymorph(self): src = ''' #include <stdio.h> @@ -1797,75 +2004,81 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv): ''' self.do_run(src, 'z:1*', force_c=True) - if self.emcc_args is not None: # too slow in other modes - # We should not blow up the stack with numerous allocas + def test_alloca_stack(self): + if self.emcc_args is None: return # too slow in other modes - src = ''' - #include <stdio.h> - #include <stdlib.h> + # We should not blow up the stack with numerous allocas + src = ''' + #include <stdio.h> + #include <stdlib.h> - func(int i) { - char *pc = (char *)alloca(100); - *pc = i; - (*pc)++; - return (*pc) % 10; - } - int main() { - int total = 0; - for (int i = 0; i < 1024*1024; i++) - total += func(i); - printf("ok:%d*\\n", total); - return 0; - } - ''' - self.do_run(src, 'ok:-32768*', force_c=True) + func(int i) { + char *pc = (char *)alloca(100); + *pc = i; + (*pc)++; + return (*pc) % 10; + } + int main() { + int total = 0; + for (int i = 0; i < 1024*1024; i++) + total += func(i); + printf("ok:%d*\\n", total); + return 0; + } + ''' + self.do_run(src, 'ok:-32768*', force_c=True) - # We should also not blow up the stack with byval arguments - src = r''' - #include<stdio.h> - struct vec { - int x, y, z; - vec(int x_, int y_, int z_) : x(x_), y(y_), z(z_) {} - static vec add(vec a, vec b) { - return vec(a.x+b.x, a.y+b.y, a.z+b.z); - } - }; - int main() { - int total = 0; - for (int i = 0; i < 1000; i++) { - for (int j = 0; j < 1000; j++) { - vec c(i+i%10, j*2, i%255); - vec d(j*2, j%255, i%120); - vec f = vec::add(c, d); - total += (f.x + f.y + f.z) % 100; - total %= 10240; - } + def test_stack_byval(self): + if self.emcc_args is None: return # too slow in other modes + + # We should also not blow up the stack with byval arguments + src = r''' + #include<stdio.h> + struct vec { + int x, y, z; + vec(int x_, int y_, int z_) : x(x_), y(y_), z(z_) {} + static vec add(vec a, vec b) { + return vec(a.x+b.x, a.y+b.y, a.z+b.z); + } + }; + int main() { + int total = 0; + for (int i = 0; i < 1000; i++) { + for (int j = 0; j < 1000; j++) { + vec c(i+i%10, j*2, i%255); + vec d(j*2, j%255, i%120); + vec f = vec::add(c, d); + total += (f.x + f.y + f.z) % 100; + total %= 10240; } - printf("sum:%d*\n", total); - return 1; } - ''' - self.do_run(src, 'sum:9780*') + printf("sum:%d*\n", total); + return 1; + } + ''' + self.do_run(src, 'sum:9780*') - # We should not blow up the stack with numerous varargs + def test_stack_varargs(self): + if self.emcc_args is None: return # too slow in other modes - src = r''' - #include <stdio.h> - #include <stdlib.h> + # We should not blow up the stack with numerous varargs + src = r''' + #include <stdio.h> + #include <stdlib.h> - void func(int i) { - printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", - i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i); - } - int main() { - for (int i = 0; i < 1024; i++) - func(i); - printf("ok!\n"); - return 0; - } - ''' - Settings.TOTAL_STACK = 1024 - self.do_run(src, 'ok!') + void func(int i) { + printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", + i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i); + } + int main() { + for (int i = 0; i < 1024; i++) + func(i); + printf("ok!\n"); + return 0; + } + ''' + Settings.TOTAL_STACK = 1024 + self.do_run(src, 'ok!') def test_array2(self): src = ''' @@ -2117,7 +2330,7 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv): int main() { // EMSCRIPTEN_COMMENT("hello from the source"); - emscripten_run_script("print('hello world' + '!')"); + emscripten_run_script("Module.print('hello world' + '!')"); printf("*%d*\n", emscripten_run_script_int("5*20")); return 0; } @@ -2131,6 +2344,18 @@ def process(filename): self.do_run(src, 'hello world!\n*100*', post_build=check) + def test_inlinejs(self): + src = r''' + #include <stdio.h> + + int main() { + asm("Module.print('Inline JS is very cool')"); + return 0; + } + ''' + + self.do_run(src, 'Inline JS is very cool') + def test_memorygrowth(self): # With typed arrays in particular, it is dangerous to use more memory than TOTAL_MEMORY, # since we then need to enlarge the heap(s). @@ -2218,6 +2443,8 @@ def process(filename): self.do_run(src, '*nameA,nameB*') def test_llvmswitch(self): + Settings.CORRECT_SIGNS = 1 + src = ''' #include <stdio.h> #include <string.h> @@ -2229,18 +2456,20 @@ def process(filename): case 'b': case 'c': return p-1; - case 'd': + case 0xfffffff1: return p+1; } return p; } int main( int argc, const char *argv[] ) { - printf("*%d,%d,%d,%d,%d*\\n", switcher('a'), switcher('b'), switcher('c'), switcher('d'), switcher('e')); + unsigned int x = 0xfffffff1; + x >>= 0; // force it to be unsigned for purpose of checking our switch comparison in signed/unsigned + printf("*%d,%d,%d,%d,%d,%d*\\n", switcher('a'), switcher('b'), switcher('c'), switcher(x), switcher(-15), switcher('e')); return 0; } ''' - self.do_run(src, '*96,97,98,101,101*') + self.do_run(src, '*96,97,98,-14,-14,101*') def test_indirectbr(self): src = ''' @@ -2415,6 +2644,8 @@ def process(filename): # part 2: make sure we warn about mixing c and c++ calling conventions here + if not (self.emcc_args is None or self.emcc_args == []): return # Optimized code is missing the warning comments + header = r''' struct point { @@ -2467,17 +2698,11 @@ def process(filename): all_name = os.path.join(self.get_dir(), 'all.bc') Building.link([supp_name + '.o', main_name + '.o'], all_name) - try: - # This will fail! See explanation near the warning we check for, in the compiler source code - self.do_ll_run(all_name, 'pre: 54,2\ndump: 55,3\ndump: 55,3\npost: 54,2') - except Exception, e: - # Check for warning in the generated code - generated = open(os.path.join(self.get_dir(), 'src.cpp.o.js')).read() - if self.emcc_args is None or self.emcc_args == []: # Optimized code is missing the warning comments - assert 'Casting a function pointer type to another with a different number of arguments.' in generated, 'Missing expected warning' - assert 'void (i32, i32)* ==> void (%struct.point*)*' in generated, 'Missing expected warning details' - return - raise Exception('We should not have gotten to here!') + # This will fail! See explanation near the warning we check for, in the compiler source code + output = Popen(['python', EMCC, all_name], stderr=PIPE).communicate() + # Check for warning in the generated code + generated = open(os.path.join(self.get_dir(), 'src.cpp.o.js')).read() + assert 'Casting a function pointer type to another with a different number of arguments.' in output[1], 'Missing expected warning' def test_stdlibs(self): if Settings.USE_TYPED_ARRAYS == 2: @@ -3527,12 +3752,20 @@ at function.:blag sscanf("-3.03", "%f", &a); printf("%.4f\n", a); + char buffy[100]; + sscanf("cheez some thing moar 123\nyet more\n", "cheez %s", buffy); + printf("|%s|\n", buffy); + sscanf("cheez something\nmoar 123\nyet more\n", "cheez %s", buffy); + printf("|%s|\n", buffy); + sscanf("cheez somethingmoar\tyet more\n", "cheez %s", buffy); + printf("|%s|\n", buffy); return 0; } ''' - self.do_run(src, 'en-us : 2\nen-r : 99\nen : 3\n1.234567, 0.000000\n-3.0300') + self.do_run(src, 'en-us : 2\nen-r : 99\nen : 3\n1.234567, 0.000000\n-3.0300\n|some|\n|something|\n|somethingmoar|') - # Part 2: doubles + def test_sscanf_2(self): + # doubles if Settings.USE_TYPED_ARRAYS == 2: for ftype in ['float', 'double']: src = r''' @@ -3601,6 +3834,7 @@ Pass: 0.000012 0.000012''') def process(filename): src = \'\'\' var Module = { + 'noFSInit': true, 'preRun': function() { FS.createDataFile('/', 'somefile.binary', [100, 200, 50, 25, 10, 77, 123], true, false); // 200 becomes -56, since signed chars are used in memory FS.createLazyFile('/', 'test.file', 'test.file', true, false); @@ -3622,6 +3856,37 @@ def process(filename): self.do_run(src, 'size: 7\ndata: 100,-56,50,25,10,77,123\nloop: 100 -56 50 25 10 77 123 \ninput:hi there!\ntexto\ntexte\n$\n5 : 10,30,20,11,88\nother=some data.\nseeked=me da.\nseeked=ata.\nseeked=ta.\nfscanfed: 10 - hello\n', post_build=post, extra_emscripten_args=['-H', 'libc/fcntl.h']) + def test_files_m(self): + # Test for Module.stdin etc. + + Settings.CORRECT_SIGNS = 1 + + post = ''' +def process(filename): + src = \'\'\' + var data = [10, 20, 40, 30]; + var Module = { + stdin: function() { return data.pop() || null }, + stdout: function(x) { Module.print('got: ' + x) } + }; + \'\'\' + open(filename, 'r').read() + open(filename, 'w').write(src) +''' + src = r''' + #include <stdio.h> + #include <unistd.h> + + int main () { + char c; + fprintf(stderr, "isatty? %d,%d,%d\n", isatty(fileno(stdin)), isatty(fileno(stdout)), isatty(fileno(stderr))); + while ((c = fgetc(stdin)) != EOF) { + putc(c+5, stdout); + } + return 0; + } + ''' + self.do_run(src, 'isatty? 0,0,1\ngot: 35\ngot: 45\ngot: 25\ngot: 15\n', post_build=post) + def test_folders(self): add_pre_run = ''' def process(filename): @@ -3926,8 +4191,8 @@ def process(filename): ).replace( '// {{POST_RUN_ADDITIONS}}', \'\'\' - print('first changed: ' + (TEST_F1.timestamp == 1200000000000)); - print('second changed: ' + (TEST_F2.timestamp == 1200000000000)); + Module.print('first changed: ' + (TEST_F1.timestamp == 1200000000000)); + Module.print('second changed: ' + (TEST_F2.timestamp == 1200000000000)); \'\'\' ) open(filename, 'w').write(src) @@ -4334,7 +4599,7 @@ def process(filename): ''' # FIXME: should not have so many newlines in output here - self.do_run(src, 'hello world\n\n77.\n') + self.do_run(src, 'hello world\n77.\n') def test_stdvec(self): src = ''' @@ -4413,7 +4678,7 @@ def process(filename): # emcc should build in dlmalloc automatically, and do all the sign correction etc. for it try_delete(os.path.join(self.get_dir(), 'src.cpp.o.js')) - output = Popen([EMCC, path_from_root('tests', 'dlmalloc_test.c'), + output = Popen(['python', EMCC, path_from_root('tests', 'dlmalloc_test.c'), '-o', os.path.join(self.get_dir(), 'src.cpp.o.js')], stdout=PIPE, stderr=self.stderr_redirect).communicate() self.do_run('x', '*1,0*', ['200', '1'], no_build=True) @@ -4560,12 +4825,6 @@ def process(filename): finally: del os.environ['EMCC_LEAVE_INPUTS_RAW'] - def get_build_dir(self): - ret = os.path.join(self.get_dir(), 'building') - if not os.path.exists(ret): - os.makedirs(ret) - return ret - def get_freetype(self): Settings.INIT_STACK = 1 # TODO: Investigate why this is necessary @@ -4588,6 +4847,10 @@ def process(filename): ) open(filename, 'w').write(src) ''' + + # Not needed for js, but useful for debugging + shutil.copyfile(path_from_root('tests', 'freetype', 'LiberationSansBold.ttf'), os.path.join(self.get_dir(), 'font.ttf')) + # Main self.do_run(open(path_from_root('tests', 'freetype', 'main.c'), 'r').read(), open(path_from_root('tests', 'freetype', 'ref.txt'), 'r').read(), @@ -4597,6 +4860,29 @@ def process(filename): post_build=post) #build_ll_hook=self.do_autodebug) + # github issue 324 + print '[issue 324]' + self.do_run(open(path_from_root('tests', 'freetype', 'main_2.c'), 'r').read(), + open(path_from_root('tests', 'freetype', 'ref_2.txt'), 'r').read(), + ['font.ttf', 'w', '32', '32', '25'], + libraries=self.get_freetype(), + includes=[path_from_root('tests', 'freetype', 'include')], + post_build=post) + + print '[issue 324 case 2]' + self.do_run(open(path_from_root('tests', 'freetype', 'main_3.c'), 'r').read(), + open(path_from_root('tests', 'freetype', 'ref_3.txt'), 'r').read(), + ['font.ttf', 'W', '32', '32', '0'], + libraries=self.get_freetype(), + includes=[path_from_root('tests', 'freetype', 'include')], + post_build=post) + + print '[issue 324 case 3]' + self.do_run('', + open(path_from_root('tests', 'freetype', 'ref_4.txt'), 'r').read(), + ['font.ttf', 'ea', '40', '32', '0'], + no_build=True) + def test_sqlite(self): # gcc -O3 -I/home/alon/Dev/emscripten/tests/sqlite -ldl src.c if self.emcc_args is None: return self.skip('Very slow without ta2, and we would also need to include dlmalloc manually without emcc') @@ -4681,9 +4967,9 @@ def process(filename): src = open(filename, 'a') src.write( \'\'\' - FS.createDataFile('/', 'paper.pdf', eval(read('paper.pdf.js')), true, false); + FS.createDataFile('/', 'paper.pdf', eval(Module.read('paper.pdf.js')), true, false); run(); - print("Data: " + JSON.stringify(FS.root.contents['filename-1.ppm'].contents.map(function(x) { return unSign(x, 8) }))); + Module.print("Data: " + JSON.stringify(FS.root.contents['filename-1.ppm'].contents.map(function(x) { return unSign(x, 8) }))); \'\'\' ) src.close() @@ -4728,7 +5014,7 @@ def process(filename): )) ).replace( '// {{POST_RUN_ADDITIONS}}', - "print('Data: ' + JSON.stringify(FS.root.contents['image.raw'].contents));" + "Module.print('Data: ' + JSON.stringify(FS.root.contents['image.raw'].contents));" ) open(filename, 'w').write(src) ''' @@ -4963,7 +5249,7 @@ Block 0: ''', post_build=post1) void KEEPALIVE print_int(int x) { printf("%d\n", x); } void KEEPALIVE print_float(float x) { printf("%.2f\n", x); } void KEEPALIVE print_string(char *x) { printf("%s\n", x); } - int KEEPALIVE multi(int x, float y, int z, char *str) { puts(str); return (x+y)*z; } + int KEEPALIVE multi(int x, float y, int z, char *str) { if (x) puts(str); return (x+y)*z; } int * KEEPALIVE pointer(int *in) { printf("%d\n", *in); static int ret = 21; return &ret; } } @@ -4986,24 +5272,30 @@ def process(filename): src = \'\'\' var Module = { 'postRun': function() { - print('*'); + Module.print('*'); var ret; - ret = ccall('get_int', 'number'); print([typeof ret, ret]); - ret = ccall('get_float', 'number'); print([typeof ret, ret.toFixed(2)]); - ret = ccall('get_string', 'string'); print([typeof ret, ret]); - ret = ccall('print_int', null, ['number'], [12]); print(typeof ret); - ret = ccall('print_float', null, ['number'], [14.56]); print(typeof ret); - ret = ccall('print_string', null, ['string'], ["cheez"]); print(typeof ret); - ret = ccall('multi', 'number', ['number', 'number', 'number', 'string'], [2, 1.4, 3, 'more']); print([typeof ret, ret]); + ret = Module['ccall']('get_int', 'number'); Module.print([typeof ret, ret]); + ret = ccall('get_float', 'number'); Module.print([typeof ret, ret.toFixed(2)]); + ret = ccall('get_string', 'string'); Module.print([typeof ret, ret]); + ret = ccall('print_int', null, ['number'], [12]); Module.print(typeof ret); + ret = ccall('print_float', null, ['number'], [14.56]); Module.print(typeof ret); + ret = ccall('print_string', null, ['string'], ["cheez"]); Module.print(typeof ret); + ret = ccall('print_string', null, ['array'], [[97, 114, 114, 45, 97, 121, 0]]); Module.print(typeof ret); + ret = ccall('multi', 'number', ['number', 'number', 'number', 'string'], [2, 1.4, 3, 'more']); Module.print([typeof ret, ret]); var p = ccall('malloc', 'pointer', ['number'], [4]); setValue(p, 650, 'i32'); - ret = ccall('pointer', 'pointer', ['pointer'], [p]); print([typeof ret, getValue(ret, 'i32')]); - print('*'); + ret = ccall('pointer', 'pointer', ['pointer'], [p]); Module.print([typeof ret, getValue(ret, 'i32')]); + Module.print('*'); // part 2: cwrap - var multi = cwrap('multi', 'number', ['number', 'number', 'number', 'string']); - print(multi(2, 1.4, 3, 'atr')); - print(multi(8, 5.4, 4, 'bret')); - print('*'); + var multi = Module['cwrap']('multi', 'number', ['number', 'number', 'number', 'string']); + Module.print(multi(2, 1.4, 3, 'atr')); + Module.print(multi(8, 5.4, 4, 'bret')); + Module.print('*'); + // part 3: avoid stack explosion + for (var i = 0; i < TOTAL_STACK/60; i++) { + ccall('multi', 'number', ['number', 'number', 'number', 'string'], [0, 0, 0, '123456789012345678901234567890123456789012345678901234567890']); + } + Module.print('stack is ok.'); } }; \'\'\' + open(filename, 'r').read() @@ -5012,7 +5304,7 @@ def process(filename): Settings.EXPORTED_FUNCTIONS = ['_get_int', '_get_float', '_get_string', '_print_int', '_print_float', '_print_string', '_multi', '_pointer', '_malloc'] - self.do_run(src, '*\nnumber,5\nnumber,3.14\nstring,hello world\n12\nundefined\n14.56\nundefined\ncheez\nundefined\nmore\nnumber,10\n650\nnumber,21\n*\natr\n10\nbret\n53\n*\n', post_build=post) + self.do_run(src, '*\nnumber,5\nnumber,3.14\nstring,hello world\n12\nundefined\n14.56\nundefined\ncheez\nundefined\narr-ay\nundefined\nmore\nnumber,10\n650\nnumber,21\n*\natr\n10\nbret\n53\n*\nstack is ok.\n', post_build=post) def test_scriptaclass(self): header_filename = os.path.join(self.get_dir(), 'header.h') @@ -5043,9 +5335,9 @@ def process(filename): script_src = ''' var sme = Module._.ScriptMe.__new__(83); // malloc(sizeof(ScriptMe)), ScriptMe::ScriptMe(sme, 83) / new ScriptMe(83) (at addr sme) Module._.ScriptMe.mulVal(sme, 2); // ScriptMe::mulVal(sme, 2) sme.mulVal(2) - print('*' + Module._.ScriptMe.getVal(sme) + '*'); + Module.print('*' + Module._.ScriptMe.getVal(sme) + '*'); _free(sme); - print('*ok*'); + Module.print('*ok*'); ''' post = ''' def process(filename): @@ -5104,7 +5396,7 @@ def process(filename): open(header_filename, 'w').write(header) basename = os.path.join(self.get_dir(), 'bindingtest') - output = Popen([BINDINGS_GENERATOR, basename, header_filename], stdout=PIPE, stderr=self.stderr_redirect).communicate()[0] + output = Popen(['python', BINDINGS_GENERATOR, basename, header_filename], stdout=PIPE, stderr=self.stderr_redirect).communicate()[0] #print output assert 'Traceback' not in output, 'Failure in binding generation: ' + output @@ -5129,55 +5421,55 @@ def process(filename): script_src_2 = \'\'\' var sme = new Module.Parent(42); sme.mulVal(2); - print('*') - print(sme.getVal()); + Module.print('*') + Module.print(sme.getVal()); - print('c1'); + Module.print('c1'); var c1 = new Module.Child1(); - print(c1.getVal()); + Module.print(c1.getVal()); c1.mulVal(2); - print(c1.getVal()); - print(c1.getValSqr()); - print(c1.getValSqr(3)); - print(c1.getValTimes()); // default argument should be 1 - print(c1.getValTimes(2)); + Module.print(c1.getVal()); + Module.print(c1.getValSqr()); + Module.print(c1.getValSqr(3)); + Module.print(c1.getValTimes()); // default argument should be 1 + Module.print(c1.getValTimes(2)); - print('c1 v2'); + Module.print('c1 v2'); c1 = new Module.Child1(8); // now with a parameter, we should handle the overloading automatically and properly and use constructor #2 - print(c1.getVal()); + Module.print(c1.getVal()); c1.mulVal(2); - print(c1.getVal()); - print(c1.getValSqr()); - print(c1.getValSqr(3)); + Module.print(c1.getVal()); + Module.print(c1.getValSqr()); + Module.print(c1.getValSqr(3)); - print('c2') + Module.print('c2') var c2 = new Module.Child2(); - print(c2.getVal()); + Module.print(c2.getVal()); c2.mulVal(2); - print(c2.getVal()); - print(c2.getValCube()); + Module.print(c2.getVal()); + Module.print(c2.getValCube()); var succeeded; try { succeeded = 0; - print(c2.doSomethingSecret()); // should fail since private + Module.print(c2.doSomethingSecret()); // should fail since private succeeded = 1; } catch(e) {} - print(succeeded); + Module.print(succeeded); try { succeeded = 0; - print(c2.getValSqr()); // function from the other class + Module.print(c2.getValSqr()); // function from the other class succeeded = 1; } catch(e) {} - print(succeeded); + Module.print(succeeded); try { succeeded = 0; c2.getValCube(); // sanity succeeded = 1; } catch(e) {} - print(succeeded); + Module.print(succeeded); Module.Child2.prototype.printStatic(); // static calls go through the prototype @@ -5191,12 +5483,12 @@ def process(filename): Module.customizeVTable(c3, [{ original: Module.Child2.prototype.virtualFunc, replacement: function() { - print('*js virtualf replacement*'); + Module.print('*js virtualf replacement*'); } }, { original: Module.Child2.prototype.virtualFunc2, replacement: function() { - print('*js virtualf2 replacement*'); + Module.print('*js virtualf2 replacement*'); } }]); c3.virtualFunc(); @@ -5207,7 +5499,7 @@ def process(filename): Module.Child2.prototype.runVirtualFunc(c2); c2.virtualFunc2(); - print('*ok*'); + Module.print('*ok*'); \'\'\' src = open(filename, 'a') src.write(script_src_2 + '\\n') @@ -5256,6 +5548,48 @@ Child2:9 *ok* ''', post_build=[post2, post3]) + def test_scriptaclass_2(self): + header_filename = os.path.join(self.get_dir(), 'header.h') + header = ''' + #include <stdio.h> + #include <string.h> + + class StringUser { + char *s; + int i; + public: + StringUser(char *string, int integer) : s(strdup(string)), i(integer) {} + void Print(int anotherInteger, char *anotherString) { + printf("|%s|%d|%s|%d|\\n", s, i, anotherString, anotherInteger); + } + void CallOther(StringUser *fr) { fr->Print(i, s); } + }; + ''' + open(header_filename, 'w').write(header) + + basename = os.path.join(self.get_dir(), 'bindingtest') + output = Popen(['python', BINDINGS_GENERATOR, basename, header_filename], stdout=PIPE, stderr=self.stderr_redirect).communicate()[0] + #print output + assert 'Traceback' not in output, 'Failure in binding generation: ' + output + + src = ''' + #include "header.h" + + #include "bindingtest.cpp" + ''' + + post = ''' +def process(filename): + src = open(filename, 'a') + src.write(open('bindingtest.js').read() + '\\n\\n') + src.write(\'\'\' + var user = new Module.StringUser("hello", 43); + user.Print(41, "world"); + \'\'\') + src.close() +''' + self.do_run(src, '|hello|43|world|41|', post_build=post) + def test_typeinfo(self): if self.emcc_args is not None and self.emcc_args != []: return self.skip('full LLVM opts optimize out all the code that uses the type') @@ -5288,12 +5622,12 @@ def process(filename): '// {{POST_RUN_ADDITIONS}}', \'\'\' if (Runtime.typeInfo) { - print('|' + Runtime.typeInfo.UserStruct.fields + '|' + Runtime.typeInfo.UserStruct.flatIndexes + '|'); + Module.print('|' + Runtime.typeInfo.UserStruct.fields + '|' + Runtime.typeInfo.UserStruct.flatIndexes + '|'); var t = Runtime.generateStructInfo(['x', { us: ['x', 'y', 'z'] }, 'y'], 'Encloser') - print('|' + [t.x, t.us.x, t.us.y, t.us.z, t.y] + '|'); - print('|' + JSON.stringify(Runtime.generateStructInfo(['x', 'y', 'z'], 'UserStruct')) + '|'); + Module.print('|' + [t.x, t.us.x, t.us.y, t.us.z, t.y] + '|'); + Module.print('|' + JSON.stringify(Runtime.generateStructInfo(['x', 'y', 'z'], 'UserStruct')) + '|'); } else { - print('No type info.'); + Module.print('No type info.'); } \'\'\' ) @@ -5745,6 +6079,7 @@ class %s(T): Settings.CATCH_EXIT_CODE = 0 Settings.EMULATE_UNALIGNED_ACCESSES = int(Settings.USE_TYPED_ARRAYS == 2 and Building.LLVM_OPTS == 2) Settings.DOUBLE_MODE = 1 if Settings.USE_TYPED_ARRAYS and Building.LLVM_OPTS == 0 else 0 + Settings.PRECISE_I64_MATH = 0 Building.pick_llvm_opts(3) @@ -5779,29 +6114,20 @@ TT = %s class other(RunnerCore): def test_emcc(self): - emcc_debug = os.environ.get('EMCC_DEBUG') - - def clear(): - for name in os.listdir(self.get_dir()): - try_delete(name) - if emcc_debug: - for name in os.listdir(EMSCRIPTEN_TEMP_DIR): - try_delete(os.path.join(EMSCRIPTEN_TEMP_DIR, name)) - for compiler in [EMCC, EMXX]: shortcompiler = os.path.basename(compiler) suffix = '.c' if compiler == EMCC else '.cpp' # --version - output = Popen([compiler, '--version'], stdout=PIPE, stderr=PIPE).communicate() + output = Popen(['python', compiler, '--version'], stdout=PIPE, stderr=PIPE).communicate() self.assertContained('''emcc (Emscripten GCC-like replacement) 2.0 Copyright (C) 2011 the Emscripten authors. This is free and open source software under the MIT license. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -''', output[0], output[1]) +''', output[0].replace('\r', ''), output[1].replace('\r', '')) # --help - output = Popen([compiler, '--help'], stdout=PIPE, stderr=PIPE).communicate() + output = Popen(['python', compiler, '--help'], stdout=PIPE, stderr=PIPE).communicate() self.assertContained('''%s [options] file... Most normal gcc/g++ options will work, for example: @@ -5810,19 +6136,19 @@ Most normal gcc/g++ options will work, for example: Options that are modified or new in %s include: -O0 No optimizations (default) -''' % (shortcompiler, shortcompiler), output[0], output[1]) +''' % (shortcompiler, shortcompiler), output[0].replace('\r', ''), output[1].replace('\r', '')) # emcc src.cpp ==> writes a.out.js - clear() - output = Popen([compiler, path_from_root('tests', 'hello_world' + suffix)], stdout=PIPE, stderr=PIPE).communicate() + self.clear() + output = Popen(['python', compiler, path_from_root('tests', 'hello_world' + suffix)], stdout=PIPE, stderr=PIPE).communicate() assert len(output[0]) == 0, output[0] assert os.path.exists('a.out.js'), '\n'.join(output) self.assertContained('hello, world!', run_js('a.out.js')) # properly report source code errors, and stop there - clear() + self.clear() assert not os.path.exists('a.out.js') - output = Popen([compiler, path_from_root('tests', 'hello_world_error' + suffix)], stdout=PIPE, stderr=PIPE).communicate() + output = Popen(['python', compiler, path_from_root('tests', 'hello_world_error' + suffix)], stdout=PIPE, stderr=PIPE).communicate() assert not os.path.exists('a.out.js'), 'compilation failed, so no output file is expected' assert len(output[0]) == 0, output[0] self.assertNotContained('IOError', output[1]) # no python stack @@ -5830,36 +6156,36 @@ Options that are modified or new in %s include: self.assertContained('error: invalid preprocessing directive', output[1]) self.assertContained("error: use of undeclared identifier 'cheez", output[1]) self.assertContained('2 errors generated', output[1]) - assert output[1].split('2 errors generated.')[1].replace('\n', '') == 'emcc: compiler frontend failed to generate LLVM bitcode, halting' + assert output[1].split('2 errors generated.')[1].replace('\r', '').replace('\n', '') == 'emcc: compiler frontend failed to generate LLVM bitcode, halting' # emcc src.cpp -c and emcc src.cpp -o src.[o|bc] ==> should give a .bc file # regression check: -o js should create "js", with bitcode content for args in [['-c'], ['-o', 'src.o'], ['-o', 'src.bc'], ['-o', 'src.so'], ['-o', 'js']]: target = args[1] if len(args) == 2 else 'hello_world.o' - clear() - Popen([compiler, path_from_root('tests', 'hello_world' + suffix)] + args, stdout=PIPE, stderr=PIPE).communicate() + self.clear() + Popen(['python', compiler, path_from_root('tests', 'hello_world' + suffix)] + args, stdout=PIPE, stderr=PIPE).communicate() syms = Building.llvm_nm(target) assert len(syms.defs) == 1 and 'main' in syms.defs, 'Failed to generate valid bitcode' if target == 'js': # make sure emcc can recognize the target as a bitcode file shutil.move(target, target + '.bc') target += '.bc' - output = Popen([compiler, target, '-o', target + '.js'], stdout = PIPE, stderr = PIPE).communicate() + output = Popen(['python', compiler, target, '-o', target + '.js'], stdout = PIPE, stderr = PIPE).communicate() assert len(output[0]) == 0, output[0] assert os.path.exists(target + '.js'), 'Expected %s to exist since args are %s : %s' % (target + '.js', str(args), '\n'.join(output)) self.assertContained('hello, world!', run_js(target + '.js')) # handle singleton archives - clear() - Popen([compiler, path_from_root('tests', 'hello_world' + suffix), '-o', 'a.bc'], stdout=PIPE, stderr=PIPE).communicate() + self.clear() + Popen(['python', compiler, path_from_root('tests', 'hello_world' + suffix), '-o', 'a.bc'], stdout=PIPE, stderr=PIPE).communicate() Popen([LLVM_AR, 'r', 'a.a', 'a.bc'], stdout=PIPE, stderr=PIPE).communicate() assert os.path.exists('a.a') - output = Popen([compiler, 'a.a']).communicate() + output = Popen(['python', compiler, 'a.a']).communicate() assert os.path.exists('a.out.js'), output self.assertContained('hello, world!', run_js('a.out.js')) # emcc src.ll ==> generates .js - clear() - output = Popen([compiler, path_from_root('tests', 'hello_world.ll')], stdout=PIPE, stderr=PIPE).communicate() + self.clear() + output = Popen(['python', compiler, path_from_root('tests', 'hello_world.ll')], stdout=PIPE, stderr=PIPE).communicate() assert len(output[0]) == 0, output[0] assert os.path.exists('a.out.js'), '\n'.join(output) self.assertContained('hello, world!', run_js('a.out.js')) @@ -5870,8 +6196,8 @@ Options that are modified or new in %s include: os.chdir('a_dir') os.mkdir('b_dir') for path in [os.path.abspath(os.path.join('..', 'file1.js')), os.path.join('b_dir', 'file2.js')]: - clear() - output = Popen([compiler, path_from_root('tests', 'hello_world.ll'), '-o', path], stdout=PIPE, stderr=PIPE).communicate() + self.clear() + output = Popen(['python', compiler, path_from_root('tests', 'hello_world.ll'), '-o', path], stdout=PIPE, stderr=PIPE).communicate() assert os.path.exists(path), path + ' does not exist; ' + '\n'.join(output) self.assertContained('hello, world!', run_js(path)) finally: @@ -5884,8 +6210,8 @@ Options that are modified or new in %s include: # dlmalloc. dlmalloc is special in that it is the only part of libc that is (1) hard to write well, and # very speed-sensitive. So we do not implement it in JS in library.js, instead we compile it from source for source, has_malloc in [('hello_world' + suffix, False), ('hello_malloc.cpp', True)]: - clear() - output = Popen([compiler, path_from_root('tests', source)], stdout=PIPE, stderr=PIPE).communicate() + self.clear() + output = Popen(['python', compiler, path_from_root('tests', source)], stdout=PIPE, stderr=PIPE).communicate() assert os.path.exists('a.out.js'), '\n'.join(output) self.assertContained('hello, world!', run_js('a.out.js')) generated = open('a.out.js').read() @@ -5910,15 +6236,15 @@ Options that are modified or new in %s include: (['-O1', '-o', 'something.bc'], 0, [], 0, 0), # -Ox is ignored and warned about ]: #print params, opt_level, bc_params, closure - clear() - output = Popen([compiler, path_from_root('tests', 'hello_world_loop' + ('_malloc' if has_malloc else '') + '.cpp')] + params, + self.clear() + output = Popen(['python', compiler, path_from_root('tests', 'hello_world_loop' + ('_malloc' if has_malloc else '') + '.cpp')] + params, stdout=PIPE, stderr=PIPE).communicate() assert len(output[0]) == 0, output[0] if bc_params is not None: if '-O1' in params and 'something.bc' in params: assert 'warning: -Ox flags ignored, since not generating JavaScript' in output[1] assert os.path.exists('something.bc'), output[1] - output = Popen([compiler, 'something.bc', '-o', 'something.js'] + bc_params, stdout=PIPE, stderr=PIPE).communicate() + output = Popen(['python', compiler, 'something.bc', '-o', 'something.js'] + bc_params, stdout=PIPE, stderr=PIPE).communicate() assert os.path.exists('something.js'), output[1] assert ('Warning: Applying some potentially unsafe optimizations!' in output[1]) == (opt_level >= 3), 'unsafe warning should appear in opt >= 3' self.assertContained('hello, world!', run_js('something.js')) @@ -5939,7 +6265,7 @@ Options that are modified or new in %s include: assert ('assert(STACKTOP < STACK_MAX' in generated) == (opt_level == 0), 'assertions should be in opt == 0' assert 'var $i;' in generated or 'var $i_01;' in generated or 'var $storemerge3;' in generated or 'var $storemerge4;' in generated or 'var $i_04;' in generated, 'micro opts should always be on' if opt_level >= 1: - assert 'HEAP8[HEAP32[' in generated or 'HEAP8[$vla1 + $storemerge4 / 2 | 0]' in generated or 'HEAP8[$vla1 + ($storemerge4 / 2 | 0)]' in generated or 'HEAP8[$vla1 + $i_04 / 2 | 0]' in generated or 'HEAP8[$vla1 + ($i_04 / 2 | 0)]' in generated or 'HEAP8[$1 + $i_01 / 2 | 0]' in generated or 'HEAP8[$1 + ($i_01 / 2 | 0)]' in generated, 'eliminator should create compound expressions, and fewer one-time vars' + assert 'HEAP8[HEAP32[' in generated or 'HEAP8[$vla1 + (($storemerge4 | 0) / 2 & -1) | 0]' in generated or 'HEAP8[$vla1 + (($storemerge4 | 0) / 2 & -1) | 0]' in generated or 'HEAP8[$vla1 + (($i_04 | 0) / 2 & -1) | 0]' in generated or 'HEAP8[$vla1 + ($i_04 / 2 & -1)]' in generated or 'HEAP8[$1 + (($i_01 | 0) / 2 & -1) | 0]' in generated or 'HEAP8[$1 + (($i_01 | 0) / 2 & -1) | 0]' in generated or 'HEAP8[$1 + ($i_01 / 2 & -1)]' in generated, 'eliminator should create compound expressions, and fewer one-time vars' assert ('_puts(' in generated) == (opt_level >= 1), 'with opt >= 1, llvm opts are run and they should optimize printf to puts' assert ('function _malloc(bytes) {' in generated) == (not has_malloc), 'If malloc is needed, it should be there, if not not' assert 'function _main() {' in generated, 'Should be unminified, including whitespace' @@ -5958,8 +6284,8 @@ Options that are modified or new in %s include: (['--typed-arrays', '2'], lambda generated: 'new Uint16Array' in generated and 'new Uint32Array' in generated, 'typed arrays 2 selected'), (['--llvm-opts', '1'], lambda generated: '_puts(' in generated, 'llvm opts requested'), ]: - clear() - output = Popen([compiler, path_from_root('tests', 'hello_world_loop.cpp'), '-o', 'a.out.js'] + params, stdout=PIPE, stderr=PIPE).communicate() + self.clear() + output = Popen(['python', compiler, path_from_root('tests', 'hello_world_loop.cpp'), '-o', 'a.out.js'] + params, stdout=PIPE, stderr=PIPE).communicate() assert len(output[0]) == 0, output[0] assert os.path.exists('a.out.js'), '\n'.join(output) self.assertContained('hello, world!', run_js('a.out.js')) @@ -5967,16 +6293,16 @@ Options that are modified or new in %s include: # Compiling two source files into a final JS. for args, target in [([], 'a.out.js'), (['-o', 'combined.js'], 'combined.js')]: - clear() - output = Popen([compiler, path_from_root('tests', 'twopart_main.cpp'), path_from_root('tests', 'twopart_side.cpp')] + args, + self.clear() + output = Popen(['python', compiler, path_from_root('tests', 'twopart_main.cpp'), path_from_root('tests', 'twopart_side.cpp')] + args, stdout=PIPE, stderr=PIPE).communicate() assert len(output[0]) == 0, output[0] assert os.path.exists(target), '\n'.join(output) self.assertContained('side got: hello from main, over', run_js(target)) # Compiling two files with -c will generate separate .bc files - clear() - output = Popen([compiler, path_from_root('tests', 'twopart_main.cpp'), path_from_root('tests', 'twopart_side.cpp'), '-c'] + args, + self.clear() + output = Popen(['python', compiler, path_from_root('tests', 'twopart_main.cpp'), path_from_root('tests', 'twopart_side.cpp'), '-c'] + args, stdout=PIPE, stderr=PIPE).communicate() if '-o' in args: # specifying -o and -c is an error @@ -5988,30 +6314,30 @@ Options that are modified or new in %s include: assert not os.path.exists(target), 'We should only have created bitcode here: ' + '\n'.join(output) # Compiling one of them alone is expected to fail - output = Popen([compiler, 'twopart_main.o'] + args, stdout=PIPE, stderr=PIPE).communicate() + output = Popen(['python', compiler, 'twopart_main.o'] + args, stdout=PIPE, stderr=PIPE).communicate() assert os.path.exists(target), '\n'.join(output) #print '\n'.join(output) self.assertContained('is not a function', run_js(target, stderr=STDOUT)) try_delete(target) # Combining those bc files into js should work - output = Popen([compiler, 'twopart_main.o', 'twopart_side.o'] + args, stdout=PIPE, stderr=PIPE).communicate() + output = Popen(['python', compiler, 'twopart_main.o', 'twopart_side.o'] + args, stdout=PIPE, stderr=PIPE).communicate() assert os.path.exists(target), '\n'.join(output) self.assertContained('side got: hello from main, over', run_js(target)) # Combining bc files into another bc should also work try_delete(target) assert not os.path.exists(target) - output = Popen([compiler, 'twopart_main.o', 'twopart_side.o', '-o', 'combined.bc'] + args, stdout=PIPE, stderr=PIPE).communicate() + output = Popen(['python', compiler, 'twopart_main.o', 'twopart_side.o', '-o', 'combined.bc'] + args, stdout=PIPE, stderr=PIPE).communicate() syms = Building.llvm_nm('combined.bc') assert len(syms.defs) == 2 and 'main' in syms.defs, 'Failed to generate valid bitcode' - output = Popen([compiler, 'combined.bc', '-o', 'combined.bc.js'], stdout = PIPE, stderr = PIPE).communicate() + output = Popen(['python', compiler, 'combined.bc', '-o', 'combined.bc.js'], stdout = PIPE, stderr = PIPE).communicate() assert len(output[0]) == 0, output[0] assert os.path.exists('combined.bc.js'), 'Expected %s to exist' % ('combined.bc.js') self.assertContained('side got: hello from main, over', run_js('combined.bc.js')) # --js-transform <transform> - clear() + self.clear() trans = os.path.join(self.get_dir(), 't.py') trans_file = open(trans, 'w') trans_file.write(''' @@ -6021,86 +6347,46 @@ f.write('transformed!') f.close() ''') trans_file.close() - output = Popen([compiler, path_from_root('tests', 'hello_world' + suffix), '--js-transform', 'python t.py'], stdout=PIPE, stderr=PIPE).communicate() + output = Popen(['python', compiler, path_from_root('tests', 'hello_world' + suffix), '--js-transform', 'python t.py'], stdout=PIPE, stderr=PIPE).communicate() assert open('a.out.js').read() == 'transformed!', 'Transformed output must be as expected' # TODO: Add in files test a clear example of using disablePermissions, and link to it from the wiki # TODO: test normal project linking, static and dynamic: get_library should not need to be told what to link! # TODO: deprecate llvm optimizations, dlmalloc, etc. in emscripten.py. - # For browser tests which report their success - def run_test_server(expectedResult): - class TestServerHandler(BaseHTTPServer.BaseHTTPRequestHandler): - def do_GET(s): - assert s.path == expectedResult, 'Expected %s, got %s' % (expectedResult, s.path) - httpd = BaseHTTPServer.HTTPServer(('localhost', 8888), TestServerHandler) - httpd.handle_request() - - # Finally, do some web browser tests - def run_browser(html_file, message, expectedResult = None): - webbrowser.open_new(os.path.abspath(html_file)) - print 'A web browser window should have opened a page containing the results of a part of this test.' - print 'You need to manually look at the page to see that it works ok: ' + message - print '(sleeping for a bit to keep the directory alive for the web browser..)' - if expectedResult is not None: - run_test_server(expectedResult) - else: - time.sleep(5) - print '(moving on..)' - - # test HTML generation. - clear() - output = Popen([EMCC, path_from_root('tests', 'hello_world_sdl.cpp'), '-o', 'something.html'], stdout=PIPE, stderr=PIPE).communicate() - assert len(output[0]) == 0, output[0] - assert os.path.exists('something.html'), output - run_browser('something.html', 'You should see "hello, world!" and a colored cube.') + def test_l_link(self): + # Linking with -lLIBNAME and -L/DIRNAME should work - # And test running in a web worker - clear() - output = Popen([EMCC, path_from_root('tests', 'hello_world_worker.cpp'), '-o', 'worker.js'], stdout=PIPE, stderr=PIPE).communicate() - assert len(output[0]) == 0, output[0] - assert os.path.exists('worker.js'), output - self.assertContained('you should not see this text when in a worker!', run_js('worker.js')) # code should run standalone - html_file = open('main.html', 'w') - html_file.write(''' - <html> - <body> - <script> - var worker = new Worker('worker.js'); - worker.onmessage = function(event) { - document.write("<hr>Called back by the worker: " + event.data + "<br><hr>"); - }; - </script> - </body> - </html> + open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(''' + extern void printey(); + int main() { + printey(); + return 0; + } ''') - html_file.close() - run_browser('main.html', 'You should see that the worker was called, and said "hello from worker!"') - # test the OpenGL ES implementation - clear() - output = Popen([EMCC, path_from_root('tests', 'hello_world_gles.c'), '-o', 'something.html', - '-DHAVE_BUILTIN_SINCOS', - '--shell-file', path_from_root('tests', 'hello_world_gles_shell.html')], - stdout=PIPE, stderr=PIPE).communicate() - assert len(output[0]) == 0, output[0] - assert os.path.exists('something.html'), output - run_browser('something.html', 'You should see animating gears.', '/report_gl_result?true') + try: + os.makedirs(os.path.join(self.get_dir(), 'libdir')); + except: + pass - # Make sure that OpenGL ES is not available if typed arrays are not used - clear() - output = Popen([EMCC, path_from_root('tests', 'hello_world_gles.c'), '-o', 'something.html', - '-DHAVE_BUILTIN_SINCOS', - '-s', 'USE_TYPED_ARRAYS=0', - '--shell-file', path_from_root('tests', 'hello_world_gles_shell.html')], - stdout=PIPE, stderr=PIPE).communicate() - assert len(output[0]) == 0, output[0] - assert os.path.exists('something.html'), output - run_browser('something.html', 'You should not see animating gears.', '/report_gl_result?false') + open(os.path.join(self.get_dir(), 'libdir', 'libfile.cpp'), 'w').write(''' + #include <stdio.h> + void printey() { + printf("hello from lib\\n"); + } + ''') - def test_emcc_l_link(self): - # Linking with -lLIBNAME and -L/DIRNAME should work + Popen(['python', EMCC, os.path.join(self.get_dir(), 'libdir', 'libfile.cpp'), '-c']).communicate() + shutil.move(os.path.join(self.get_dir(), 'libfile.o'), os.path.join(self.get_dir(), 'libdir', 'libfile.so')) + Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '-L' + os.path.join(self.get_dir(), 'libdir'), '-lfile']).communicate() + self.assertContained('hello from lib', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + assert not os.path.exists('a.out') and not os.path.exists('a.exe'), 'Must not leave unneeded linker stubs' + def test_local_link(self): + # Linking a local library directly, like /usr/lib/libsomething.so, cannot work of course since it + # doesn't contain bitcode. However, when we see that we should look for a bitcode file for that + # library in the -L paths and system/lib open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(''' extern void printey(); int main() { @@ -6110,23 +6396,88 @@ f.close() ''') try: - os.makedirs(os.path.join(self.get_dir(), 'libdir')); + os.makedirs(os.path.join(self.get_dir(), 'subdir')); except: pass + open(os.path.join(self.get_dir(), 'subdir', 'libfile.so'), 'w').write('this is not llvm bitcode!') - open(os.path.join(self.get_dir(), 'libdir', 'libfile.cpp'), 'w').write(''' + open(os.path.join(self.get_dir(), 'libfile.cpp'), 'w').write(''' #include <stdio.h> void printey() { printf("hello from lib\\n"); } ''') - Popen([EMCC, os.path.join(self.get_dir(), 'libdir', 'libfile.cpp'), '-c'], stdout=PIPE, stderr=STDOUT).communicate() - shutil.move(os.path.join(self.get_dir(), 'libfile.o'), os.path.join(self.get_dir(), 'libdir', 'libfile.so')) - Popen([EMCC, os.path.join(self.get_dir(), 'main.cpp'), '-L' + os.path.join(self.get_dir(), 'libdir'), '-lfile'], stdout=PIPE, stderr=STDOUT).communicate() + Popen(['python', EMCC, os.path.join(self.get_dir(), 'libfile.cpp'), '-o', 'libfile.so']).communicate() + Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), os.path.join(self.get_dir(), 'subdir', 'libfile.so'), '-L.']).communicate() self.assertContained('hello from lib', run_js(os.path.join(self.get_dir(), 'a.out.js'))) - def test_emcc_embed_file(self): + def test_js_libraries(self): + open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(''' + #include <stdio.h> + extern "C" { + extern void printey(); + extern int calcey(int x, int y); + } + int main() { + printey(); + printf("*%d*\\n", calcey(10, 22)); + return 0; + } + ''') + open(os.path.join(self.get_dir(), 'mylib1.js'), 'w').write(''' + mergeInto(LibraryManager.library, { + printey: function() { + Module.print('hello from lib!'); + } + }); + ''') + open(os.path.join(self.get_dir(), 'mylib2.js'), 'w').write(''' + mergeInto(LibraryManager.library, { + calcey: function(x, y) { + return x + y; + } + }); + ''') + + Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--js-library', os.path.join(self.get_dir(), 'mylib1.js'), + '--js-library', os.path.join(self.get_dir(), 'mylib2.js')]).communicate() + self.assertContained('hello from lib!\n*32*\n', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + + def test_identical_basenames(self): + # Issue 287: files in different dirs but with the same basename get confused as the same, + # causing multiply defined symbol errors + try: + os.makedirs(os.path.join(self.get_dir(), 'foo')); + except: + pass + try: + os.makedirs(os.path.join(self.get_dir(), 'bar')); + except: + pass + open(os.path.join(self.get_dir(), 'foo', 'main.cpp'), 'w').write(''' + extern void printey(); + int main() { + printey(); + return 0; + } + ''') + open(os.path.join(self.get_dir(), 'bar', 'main.cpp'), 'w').write(''' + #include<stdio.h> + void printey() { printf("hello there\\n"); } + ''') + + Popen(['python', EMCC, os.path.join(self.get_dir(), 'foo', 'main.cpp'), os.path.join(self.get_dir(), 'bar', 'main.cpp')]).communicate() + self.assertContained('hello there', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + + # ditto with first creating .o files + try_delete(os.path.join(self.get_dir(), 'a.out.js')) + Popen(['python', EMCC, os.path.join(self.get_dir(), 'foo', 'main.cpp'), '-o', os.path.join(self.get_dir(), 'foo', 'main.o')]).communicate() + Popen(['python', EMCC, os.path.join(self.get_dir(), 'bar', 'main.cpp'), '-o', os.path.join(self.get_dir(), 'bar', 'main.o')]).communicate() + Popen(['python', EMCC, os.path.join(self.get_dir(), 'foo', 'main.o'), os.path.join(self.get_dir(), 'bar', 'main.o')]).communicate() + self.assertContained('hello there', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + + def test_embed_file(self): open(os.path.join(self.get_dir(), 'somefile.txt'), 'w').write('''hello from a file with lots of data and stuff in it thank you very much''') open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(r''' #include <stdio.h> @@ -6141,10 +6492,10 @@ f.close() } ''') - Popen([EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--embed-file', 'somefile.txt']).communicate() + Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--embed-file', 'somefile.txt']).communicate() self.assertContained('|hello from a file wi|', run_js(os.path.join(self.get_dir(), 'a.out.js'))) - def test_emcc_multidynamic_link(self): + def test_multidynamic_link(self): # Linking the same dynamic library in will error, normally, since we statically link it, causing dupe symbols # A workaround is to use --ignore-dynamic-linking, see emcc --help for details @@ -6186,7 +6537,7 @@ f.close() ''') # This lets us link the same dynamic lib twice. We will need to link it in manually at the end. - compiler = [EMCC, '--ignore-dynamic-linking'] + compiler = ['python', EMCC, '--ignore-dynamic-linking'] # Build libfile normally into an .so Popen(compiler + [os.path.join(self.get_dir(), 'libdir', 'libfile.cpp'), '-o', os.path.join(self.get_dir(), 'libdir', 'libfile.so')]).communicate() @@ -6196,11 +6547,11 @@ f.close() Popen(compiler + [os.path.join(self.get_dir(), 'main.cpp'), '-L' + os.path.join(self.get_dir(), 'libdir'), '-lfile', '-lother', '-c']).communicate() # The normal build system is over. We need to do an additional step to link in the dynamic libraries, since we ignored them before - Popen([EMCC, os.path.join(self.get_dir(), 'main.o'), '-L' + os.path.join(self.get_dir(), 'libdir'), '-lfile', '-lother']).communicate() + Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.o'), '-L' + os.path.join(self.get_dir(), 'libdir'), '-lfile', '-lother']).communicate() self.assertContained('*hello from lib\n|hello from lib|\n*', run_js(os.path.join(self.get_dir(), 'a.out.js'))) - def test_emcc_js_link(self): + def test_js_link(self): open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(''' #include <stdio.h> int main() { @@ -6213,12 +6564,48 @@ f.close() if (typeof Module != 'undefined') throw 'This code should run before anything else!'; ''') open(os.path.join(self.get_dir(), 'after.js'), 'w').write(''' - print(MESSAGE); + Module.print(MESSAGE); ''') - Popen([EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--pre-js', 'before.js', '--post-js', 'after.js']).communicate() + Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--pre-js', 'before.js', '--post-js', 'after.js']).communicate() self.assertContained('hello from main\nhello from js\n', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + def test_prepost(self): + open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(''' + #include <stdio.h> + int main() { + printf("hello from main\\n"); + return 0; + } + ''') + open(os.path.join(self.get_dir(), 'pre.js'), 'w').write(''' + var Module = { + preRun: function() { Module.print('pre-run') }, + postRun: function() { Module.print('post-run') } + }; + ''') + + Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--pre-js', 'pre.js']).communicate() + self.assertContained('pre-run\nhello from main\npost-run\n', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + + # never run, so no preRun or postRun + src = open(os.path.join(self.get_dir(), 'a.out.js')).read().replace('// {{PRE_RUN_ADDITIONS}}', 'addRunDependency()') + open(os.path.join(self.get_dir(), 'a.out.js'), 'w').write(src) + self.assertNotContained('pre-run\nhello from main\npost-run\n', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + + # noInitialRun prevents run + for no_initial_run in [0, 1]: + Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp')]).communicate() + src = 'var Module = { noInitialRun: %d };\n' % no_initial_run + open(os.path.join(self.get_dir(), 'a.out.js')).read() + open(os.path.join(self.get_dir(), 'a.out.js'), 'w').write(src) + assert ('hello from main' in run_js(os.path.join(self.get_dir(), 'a.out.js'))) != no_initial_run, 'only run if no noInitialRun' + + if no_initial_run: + # Calling main later should still work, filesystem etc. must be set up. + src = open(os.path.join(self.get_dir(), 'a.out.js')).read() + '\n_main();\n'; + open(os.path.join(self.get_dir(), 'a.out.js'), 'w').write(src) + assert 'hello from main' in run_js(os.path.join(self.get_dir(), 'a.out.js')), 'main should print when called manually' + def test_eliminator(self): input = open(path_from_root('tools', 'eliminator', 'eliminator-test.js')).read() expected = open(path_from_root('tools', 'eliminator', 'eliminator-test-output.js')).read() @@ -6246,6 +6633,543 @@ f.close() output = Popen([NODE_JS, JS_OPTIMIZER, input] + passes, stdin=PIPE, stdout=PIPE).communicate()[0] self.assertIdentical(expected, output.replace('\n\n', '\n')) + def test_m_mm(self): + open(os.path.join(self.get_dir(), 'foo.c'), 'w').write('''#include <emscripten.h>''') + for opt in ['M', 'MM']: + output, err = Popen(['python', EMCC, os.path.join(self.get_dir(), 'foo.c'), '-' + opt], stdout=PIPE, stderr=PIPE).communicate() + assert 'foo.o: ' in output, '-%s failed to produce the right output: %s' % (opt, output) + assert 'error' not in err, 'Unexpected stderr: ' + err + + def test_llvm_nativizer(self): + # avoid impure_ptr problems etc. + shutil.copyfile(path_from_root('tests', 'files.cpp'), os.path.join(self.get_dir(), 'files.cpp')) + open(os.path.join(self.get_dir(), 'somefile.binary'), 'w').write('''waka waka############################''') + open(os.path.join(self.get_dir(), 'test.file'), 'w').write('''ay file..............,,,,,,,,,,,,,,''') + open(os.path.join(self.get_dir(), 'stdin'), 'w').write('''inter-active''') + Popen(['python', EMCC, os.path.join(self.get_dir(), 'files.cpp'), '-c']).communicate() + Popen(['python', path_from_root('tools', 'nativize_llvm.py'), os.path.join(self.get_dir(), 'files.o')]).communicate(input)[0] + output = Popen([os.path.join(self.get_dir(), 'files.o.run')], stdin=open(os.path.join(self.get_dir(), 'stdin')), stdout=PIPE, stderr=PIPE).communicate() + self.assertIdentical('''size: 37 +data: 119,97,107,97,32,119,97,107,97,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35 +loop: 119 97 107 97 32 119 97 107 97 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 +input:inter-active +texto +$ +5 : 10,30,20,11,88 +other=ay file... +seeked= file. +seeked=e... +seeked=,,. +fscanfed: 10 - hello +''', output[0]) + self.assertIdentical('texte\n', output[1]) + +elif 'browser' in str(sys.argv): + # Browser tests. + + # Run a server and a web page. When a test runs, we tell the server about it, + # which tells the web page, which then opens a window with the test. Doing + # it this way then allows the page to close() itself when done. + + def harness_server_func(q): + class TestServerHandler(BaseHTTPServer.BaseHTTPRequestHandler): + def do_GET(s): + s.send_response(200) + s.send_header("Content-type", "text/html") + s.end_headers() + if s.path == '/run_harness': + s.wfile.write(open(path_from_root('tests', 'browser_harness.html')).read()) + else: + result = 'False' + if not q.empty(): + result = q.get() + s.wfile.write(result) + s.wfile.close() + httpd = BaseHTTPServer.HTTPServer(('localhost', 9999), TestServerHandler) + httpd.serve_forever() # test runner will kill us + + def server_func(dir, q): + class TestServerHandler(BaseHTTPServer.BaseHTTPRequestHandler): + def do_GET(s): + if 'report_' in s.path: + q.put(s.path) + else: + filename = s.path[1:] + if os.path.exists(filename): + s.send_response(200) + s.send_header("Content-type", "text/html") + s.end_headers() + s.wfile.write(open(filename).read()) + s.wfile.close() + else: + s.send_response(500) + s.send_header("Content-type", "text/html") + s.end_headers() + os.chdir(dir) + httpd = BaseHTTPServer.HTTPServer(('localhost', 8888), TestServerHandler) + httpd.serve_forever() # test runner will kill us + + class browser(RunnerCore): + def __init__(self, *args, **kwargs): + super(browser, self).__init__(*args, **kwargs) + + if hasattr(browser, 'harness_server'): return + browser.harness_queue = multiprocessing.Queue() + browser.harness_server = multiprocessing.Process(target=harness_server_func, args=(browser.harness_queue,)) + browser.harness_server.start() + print '[Browser harness server on process %d]' % browser.harness_server.pid + webbrowser.open_new('http://localhost:9999/run_harness') + + def __del__(self): + if not hasattr(browser, 'harness_server'): return + + browser.harness_server.terminate() + delattr(browser, 'harness_server') + print '[Browser harness server terminated]' + # On Windows, shutil.rmtree() in tearDown() raises this exception if we do not wait a bit: + # WindowsError: [Error 32] The process cannot access the file because it is being used by another process. + time.sleep(0.1) + + def run_browser(self, html_file, message, expectedResult=None): + if expectedResult is not None: + try: + queue = multiprocessing.Queue() + server = multiprocessing.Process(target=functools.partial(server_func, self.get_dir()), args=(queue,)) + server.start() + browser.harness_queue.put('http://localhost:8888/' + html_file) + output = '[no http server activity]' + start = time.time() + while time.time() - start < 5: + if not queue.empty(): + output = queue.get() + break + time.sleep(0.1) + self.assertIdentical(expectedResult, output) + finally: + server.terminate() + time.sleep(0.1) # see comment about Windows above + else: + webbrowser.open_new(os.path.abspath(html_file)) + print 'A web browser window should have opened a page containing the results of a part of this test.' + print 'You need to manually look at the page to see that it works ok: ' + message + print '(sleeping for a bit to keep the directory alive for the web browser..)' + time.sleep(5) + print '(moving on..)' + + def with_report_result(self, code): + return code.replace('REPORT_RESULT();', ''' + char output[1000]; + sprintf(output, + "xhr = new XMLHttpRequest();" + "xhr.open('GET', 'http://localhost:8888/report_result?%d');" + "xhr.send();", result); + emscripten_run_script(output); + emscripten_run_script("setTimeout(function() { window.close() }, 1000)"); +''') + + def reftest(self, expected): + basename = os.path.basename(expected) + shutil.copyfile(expected, os.path.join(self.get_dir(), basename)) + open(os.path.join(self.get_dir(), 'reftest.js'), 'w').write(''' + function doReftest() { + if (doReftest.done) return; + doReftest.done = true; + var img = new Image(); + img.onload = function() { + assert(img.width == Module.canvas.width, 'Invalid width: ' + Module.canvas.width + ', should be ' + img.width); + assert(img.height == Module.canvas.height, 'Invalid height: ' + Module.canvas.height + ', should be ' + img.height); + + var canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + var expected = ctx.getImageData(0, 0, img.width, img.height).data; + + var actualUrl = Module.canvas.toDataURL(); + var actualImage = new Image(); + actualImage.onload = function() { + var actualCanvas = document.createElement('canvas'); + actualCanvas.width = actualImage.width; + actualCanvas.height = actualImage.height; + var actualCtx = actualCanvas.getContext('2d'); + actualCtx.drawImage(actualImage, 0, 0); + var actual = actualCtx.getImageData(0, 0, actualImage.width, actualImage.height).data; + + var total = 0; + for (var x = 0; x < img.width; x++) { + for (var y = 0; y < img.height; y++) { + total += Math.abs(expected[y*img.width*4 + x*4 + 0] - actual[y*img.width*4 + x*4 + 0]); + total += Math.abs(expected[y*img.width*4 + x*4 + 1] - actual[y*img.width*4 + x*4 + 1]); + total += Math.abs(expected[y*img.width*4 + x*4 + 2] - actual[y*img.width*4 + x*4 + 2]); + } + } + var wrong = Math.floor(total / (img.width*img.height*3)); // floor, to allow some margin of error for antialiasing + + xhr = new XMLHttpRequest(); + xhr.open('GET', 'http://localhost:8888/report_result?' + wrong); + xhr.send(); + setTimeout(function() { window.close() }, 1000); + }; + actualImage.src = actualUrl; + } + img.src = '%s'; + }; + Module['postRun'] = doReftest; + Module['preRun'] = function() { + setTimeout(doReftest, 0); // if run() throws an exception and postRun is not called, this will kick in + }; +''' % basename) + + def test_html(self): + # test HTML generation. + self.reftest(path_from_root('tests', 'htmltest.png')) + output = Popen(['python', EMCC, path_from_root('tests', 'hello_world_sdl.cpp'), '-o', 'something.html', '--pre-js', 'reftest.js']).communicate() + self.run_browser('something.html', 'You should see "hello, world!" and a colored cube.', '/report_result?0') + + def build_native_lzma(self): + lzma_native = path_from_root('third_party', 'lzma.js', 'lzma-native') + if os.path.isfile(lzma_native) and os.access(lzma_native, os.X_OK): return + + cwd = os.getcwd() + try: + os.chdir(path_from_root('third_party', 'lzma.js')) + Popen(['sh', './doit.sh']).communicate() + finally: + os.chdir(cwd) + + def test_compression(self): + open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(self.with_report_result(r''' + #include <stdio.h> + #include <emscripten.h> + int main() { + printf("hello compressed world\n"); + int result = 1; + REPORT_RESULT(); + return 0; + } + ''')) + + self.build_native_lzma() + Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '-o', 'page.html', + '--compression', '%s,%s,%s' % (path_from_root('third_party', 'lzma.js', 'lzma-native'), + path_from_root('third_party', 'lzma.js', 'lzma-decoder.js'), + 'LZMA.decompress')]).communicate() + assert os.path.exists(os.path.join(self.get_dir(), 'page.js')), 'must be side js' + assert os.path.exists(os.path.join(self.get_dir(), 'page.js.compress')), 'must be side compressed js' + assert os.stat(os.path.join(self.get_dir(), 'page.js')).st_size > os.stat(os.path.join(self.get_dir(), 'page.js.compress')).st_size, 'compressed file must be smaller' + shutil.move(os.path.join(self.get_dir(), 'page.js'), 'page.js.renamedsoitcannotbefound'); + self.run_browser('page.html', '', '/report_result?1') + + def test_preload_file(self): + open(os.path.join(self.get_dir(), 'somefile.txt'), 'w').write('''load me right before running the code please''') + open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(self.with_report_result(r''' + #include <stdio.h> + #include <string.h> + #include <emscripten.h> + int main() { + FILE *f = fopen("somefile.txt", "r"); + char buf[100]; + fread(buf, 1, 20, f); + buf[20] = 0; + fclose(f); + printf("|%s|\n", buf); + + int result = !strcmp("load me right before", buf); + REPORT_RESULT(); + return 0; + } + ''')) + + Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', 'somefile.txt', '-o', 'page.html']).communicate() + self.run_browser('page.html', 'You should see |load me right before|.', '/report_result?1') + + def test_multifile(self): + # a few files inside a directory + self.clear() + os.makedirs(os.path.join(self.get_dir(), 'subdirr')); + os.makedirs(os.path.join(self.get_dir(), 'subdirr', 'moar')); + open(os.path.join(self.get_dir(), 'subdirr', 'data1.txt'), 'w').write('''1214141516171819''') + open(os.path.join(self.get_dir(), 'subdirr', 'moar', 'data2.txt'), 'w').write('''3.14159265358979''') + open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(self.with_report_result(r''' + #include <stdio.h> + #include <string.h> + #include <emscripten.h> + int main() { + char buf[17]; + + FILE *f = fopen("subdirr/data1.txt", "r"); + fread(buf, 1, 16, f); + buf[16] = 0; + fclose(f); + printf("|%s|\n", buf); + int result = !strcmp("1214141516171819", buf); + + FILE *f2 = fopen("subdirr/moar/data2.txt", "r"); + fread(buf, 1, 16, f2); + buf[16] = 0; + fclose(f2); + printf("|%s|\n", buf); + result = result && !strcmp("3.14159265358979", buf); + + REPORT_RESULT(); + return 0; + } + ''')) + + # by individual files + Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', 'subdirr/data1.txt', '--preload-file', 'subdirr/moar/data2.txt', '-o', 'page.html']).communicate() + self.run_browser('page.html', 'You should see two cool numbers', '/report_result?1') + os.remove('page.html') + + # by directory, and remove files to make sure + Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', 'subdirr', '-o', 'page.html']).communicate() + shutil.rmtree(os.path.join(self.get_dir(), 'subdirr')) + self.run_browser('page.html', 'You should see two cool numbers', '/report_result?1') + + def test_compressed_file(self): + open(os.path.join(self.get_dir(), 'datafile.txt'), 'w').write('compress this please' + (2000*'.')) + open(os.path.join(self.get_dir(), 'datafile2.txt'), 'w').write('moar' + (100*'!')) + open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(self.with_report_result(r''' + #include <stdio.h> + #include <string.h> + #include <emscripten.h> + int main() { + char buf[21]; + FILE *f = fopen("datafile.txt", "r"); + fread(buf, 1, 20, f); + buf[20] = 0; + fclose(f); + printf("file says: |%s|\n", buf); + int result = !strcmp("compress this please", buf); + FILE *f2 = fopen("datafile2.txt", "r"); + fread(buf, 1, 5, f2); + buf[5] = 0; + fclose(f2); + result = result && !strcmp("moar!", buf); + printf("file 2 says: |%s|\n", buf); + REPORT_RESULT(); + return 0; + } + ''')) + + self.build_native_lzma() + Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '-o', 'page.html', '--preload-file', 'datafile.txt', '--preload-file', 'datafile2.txt', + '--compression', '%s,%s,%s' % (path_from_root('third_party', 'lzma.js', 'lzma-native'), + path_from_root('third_party', 'lzma.js', 'lzma-decoder.js'), + 'LZMA.decompress')]).communicate() + assert os.path.exists(os.path.join(self.get_dir(), 'datafile.txt')), 'must be data file' + assert os.path.exists(os.path.join(self.get_dir(), 'page.data.compress')), 'must be data file in compressed form' + assert os.stat(os.path.join(self.get_dir(), 'page.js')).st_size != os.stat(os.path.join(self.get_dir(), 'page.js.compress')).st_size, 'compressed file must be different' + shutil.move(os.path.join(self.get_dir(), 'datafile.txt'), 'datafile.txt.renamedsoitcannotbefound'); + self.run_browser('page.html', '', '/report_result?1') + + def test_sdl_image(self): + # load an image file, get pixel data + shutil.copyfile(path_from_root('tests', 'screenshot.jpg'), os.path.join(self.get_dir(), 'screenshot.jpg')) + open(os.path.join(self.get_dir(), 'sdl_image.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_image.c')).read())) + + Popen(['python', EMCC, os.path.join(self.get_dir(), 'sdl_image.c'), '--preload-file', 'screenshot.jpg', '-o', 'page.html']).communicate() + self.run_browser('page.html', '', '/report_result?600') + + def test_sdl_image_compressed(self): + for image, width in [(path_from_root('tests', 'screenshot2.png'), 300), + (path_from_root('tests', 'screenshot.jpg'), 600)]: + self.clear() + print image + + basename = os.path.basename(image) + shutil.copyfile(image, os.path.join(self.get_dir(), basename)) + open(os.path.join(self.get_dir(), 'sdl_image.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_image.c')).read()).replace('screenshot.jpg', basename)) + + self.build_native_lzma() + Popen(['python', EMCC, os.path.join(self.get_dir(), 'sdl_image.c'), '--preload-file', basename, '-o', 'page.html', + '--compression', '%s,%s,%s' % (path_from_root('third_party', 'lzma.js', 'lzma-native'), + path_from_root('third_party', 'lzma.js', 'lzma-decoder.js'), + 'LZMA.decompress')]).communicate() + shutil.move(os.path.join(self.get_dir(), basename), basename + '.renamedsoitcannotbefound'); + self.run_browser('page.html', '', '/report_result?' + str(width)) + + def test_sdl_canvas(self): + open(os.path.join(self.get_dir(), 'sdl_canvas.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_canvas.c')).read())) + + Popen(['python', EMCC, os.path.join(self.get_dir(), 'sdl_canvas.c'), '-o', 'page.html']).communicate() + self.run_browser('page.html', '', '/report_result?1') + + def test_sdl_key(self): + open(os.path.join(self.get_dir(), 'pre.js'), 'w').write(''' + Module.postRun = function() { + function doOne() { + _one(); + setTimeout(doOne, 1000/60); + } + setTimeout(doOne, 1000/60); + } + + function simulateKeyEvent(c) { + var event = document.createEvent("KeyboardEvent"); + event.initKeyEvent("keydown", true, true, window, + 0, 0, 0, 0, + c, c); + dispatchEvent(event); + var event2 = document.createEvent("KeyboardEvent"); + event2.initKeyEvent("keyup", true, true, window, + 0, 0, 0, 0, + c, c); + dispatchEvent(event2); + } + ''') + open(os.path.join(self.get_dir(), 'sdl_key.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_key.c')).read())) + + Popen(['python', EMCC, os.path.join(self.get_dir(), 'sdl_key.c'), '-o', 'page.html', '--pre-js', 'pre.js']).communicate() + self.run_browser('page.html', '', '/report_result?510510') + + def test_sdl_mouse(self): + open(os.path.join(self.get_dir(), 'pre.js'), 'w').write(''' + function simulateMouseEvent(x, y, button) { + var event = document.createEvent("MouseEvents"); + if (button >= 0) { + var event1 = document.createEvent("MouseEvents"); + event1.initMouseEvent('mousedown', true, true, window, + 1, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y, + 0, 0, 0, 0, + button, null); + Module['canvas'].dispatchEvent(event1); + var event2 = document.createEvent("MouseEvents"); + event2.initMouseEvent('mouseup', true, true, window, + 1, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y, + 0, 0, 0, 0, + button, null); + Module['canvas'].dispatchEvent(event2); + } else { + var event1 = document.createEvent("MouseEvents"); + event1.initMouseEvent('mousemove', true, true, window, + 0, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y, + 0, 0, 0, 0, + 0, null); + Module['canvas'].dispatchEvent(event1); + } + } + ''') + open(os.path.join(self.get_dir(), 'sdl_mouse.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_mouse.c')).read())) + + Popen(['python', EMCC, os.path.join(self.get_dir(), 'sdl_mouse.c'), '-o', 'page.html', '--pre-js', 'pre.js']).communicate() + self.run_browser('page.html', '', '/report_result?740') + + def test_sdl_audio(self): + shutil.copyfile(path_from_root('tests', 'sounds', 'alarmvictory_1.ogg'), os.path.join(self.get_dir(), 'sound.ogg')) + shutil.copyfile(path_from_root('tests', 'sounds', 'alarmcreatemiltaryfoot_1.wav'), os.path.join(self.get_dir(), 'sound2.wav')) + open(os.path.join(self.get_dir(), 'sdl_audio.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_audio.c')).read())) + + # use closure to check for a possible bug with closure minifying away newer Audio() attributes + Popen(['python', EMCC, '-O2', '--minify', '0', os.path.join(self.get_dir(), 'sdl_audio.c'), '--preload-file', 'sound.ogg', '--preload-file', 'sound2.wav', '-o', 'page.html', '-s', 'EXPORTED_FUNCTIONS=["_main", "_play", "_play2"]']).communicate() + self.run_browser('page.html', '', '/report_result?1') + + def test_sdl_gl_read(self): + # SDL, OpenGL, readPixels + open(os.path.join(self.get_dir(), 'sdl_gl_read.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_gl_read.c')).read())) + Popen(['python', EMCC, os.path.join(self.get_dir(), 'sdl_gl_read.c'), '-o', 'something.html']).communicate() + self.run_browser('something.html', '.', '/report_result?1') + + def test_sdl_ogl(self): + # SDL, OpenGL, textures, immediate mode + shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) + self.reftest(path_from_root('tests', 'screenshot-gray.png')) + Popen(['python', EMCC, path_from_root('tests', 'sdl_ogl.c'), '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png']).communicate() + self.run_browser('something.html', 'You should see an image with gray at the top.', '/report_result?0') + + def test_sdl_ogl_p(self): + # Immediate mode with pointers + shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) + self.reftest(path_from_root('tests', 'screenshot-gray.png')) + Popen(['python', EMCC, path_from_root('tests', 'sdl_ogl_p.c'), '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png']).communicate() + self.run_browser('something.html', 'You should see an image with gray at the top.', '/report_result?0') + + def test_worker(self): + # Test running in a web worker + output = Popen(['python', EMCC, path_from_root('tests', 'hello_world_worker.cpp'), '-o', 'worker.js'], stdout=PIPE, stderr=PIPE).communicate() + assert len(output[0]) == 0, output[0] + assert os.path.exists('worker.js'), output + self.assertContained('you should not see this text when in a worker!', run_js('worker.js')) # code should run standalone + html_file = open('main.html', 'w') + html_file.write(''' + <html> + <body> + Worker Test + <script> + var worker = new Worker('worker.js'); + worker.onmessage = function(event) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', 'http://localhost:8888/report_result?' + event.data); + xhr.send(); + setTimeout(function() { window.close() }, 1000); + }; + </script> + </body> + </html> + ''') + html_file.close() + self.run_browser('main.html', 'You should see that the worker was called, and said "hello from worker!"', '/report_result?hello%20from%20worker!') + + def test_glgears(self): + self.reftest(path_from_root('tests', 'gears.png')) + Popen(['python', EMCC, path_from_root('tests', 'hello_world_gles.c'), '-o', 'something.html', + '-DHAVE_BUILTIN_SINCOS', '--pre-js', 'reftest.js']).communicate() + self.run_browser('something.html', 'You should see animating gears.', '/report_result?0') + + def test_glgears_animation(self): + Popen(['python', EMCC, path_from_root('tests', 'hello_world_gles.c'), '-o', 'something.html', + '-DHAVE_BUILTIN_SINCOS', + '--shell-file', path_from_root('tests', 'hello_world_gles_shell.html')]).communicate() + self.run_browser('something.html', 'You should see animating gears.', '/report_gl_result?true') + + def test_glgears_bad(self): + # Make sure that OpenGL ES is not available if typed arrays are not used + Popen(['python', EMCC, path_from_root('tests', 'hello_world_gles.c'), '-o', 'something.html', + '-DHAVE_BUILTIN_SINCOS', + '-s', 'USE_TYPED_ARRAYS=0', + '--shell-file', path_from_root('tests', 'hello_world_gles_shell.html')]).communicate() + self.run_browser('something.html', 'You should not see animating gears.', '/report_gl_result?false') + + def test_glgears_deriv(self): + self.reftest(path_from_root('tests', 'gears.png')) + Popen(['python', EMCC, path_from_root('tests', 'hello_world_gles_deriv.c'), '-o', 'something.html', + '-DHAVE_BUILTIN_SINCOS', '--pre-js', 'reftest.js']).communicate() + self.run_browser('something.html', 'You should see animating gears.', '/report_result?0') + src = open('something.html').read() + assert 'gl-matrix' not in src, 'Should not include glMatrix when not needed' + + def test_glbook(self): + programs = self.get_library('glbook', [ + os.path.join('Chapter_2', 'Hello_Triangle', 'CH02_HelloTriangle.bc'), + os.path.join('Chapter_8', 'Simple_VertexShader', 'CH08_SimpleVertexShader.bc'), + os.path.join('Chapter_9', 'Simple_Texture2D', 'CH09_SimpleTexture2D.bc'), + os.path.join('Chapter_9', 'Simple_TextureCubemap', 'CH09_TextureCubemap.bc'), + os.path.join('Chapter_9', 'TextureWrap', 'CH09_TextureWrap.bc'), + os.path.join('Chapter_10', 'MultiTexture', 'CH10_MultiTexture.bc'), + os.path.join('Chapter_13', 'ParticleSystem', 'CH13_ParticleSystem.bc'), + ], configure=None) + for program in programs: + print program + basename = os.path.basename(program) + args = [] + if basename == 'CH10_MultiTexture.bc': + shutil.copyfile(path_from_root('tests', 'glbook', 'Chapter_10', 'MultiTexture', 'basemap.tga'), os.path.join(self.get_dir(), 'basemap.tga')) + shutil.copyfile(path_from_root('tests', 'glbook', 'Chapter_10', 'MultiTexture', 'lightmap.tga'), os.path.join(self.get_dir(), 'lightmap.tga')) + args = ['--preload-file', 'basemap.tga', '--preload-file', 'lightmap.tga'] + elif basename == 'CH13_ParticleSystem.bc': + shutil.copyfile(path_from_root('tests', 'glbook', 'Chapter_13', 'ParticleSystem', 'smoke.tga'), os.path.join(self.get_dir(), 'smoke.tga')) + args = ['--preload-file', 'smoke.tga', '-O2'] # test optimizations and closure here as well for more coverage + + self.reftest(path_from_root('tests', 'glbook', basename.replace('.bc', '.png'))) + Popen(['python', EMCC, program, '-o', 'program.html', '--pre-js', 'reftest.js'] + args).communicate() + self.run_browser('program.html', '', '/report_result?0') + + def test_emscripten_api(self): + open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(self.with_report_result(open(path_from_root('tests', 'emscripten_api_browser.cpp')).read())) + Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '-o', 'page.html']).communicate() + self.run_browser('page.html', '', '/report_result?1') + elif 'benchmark' in str(sys.argv): # Benchmarks. Run them with argument |benchmark|. To run a specific test, do # |benchmark.test_X|. @@ -6340,7 +7264,7 @@ elif 'benchmark' in str(sys.argv): final_filename = os.path.join(dirname, 'src.js') try_delete(final_filename) - output = Popen([EMCC, filename, '-O3', + output = Popen(['python', EMCC, filename, '-O3', '-s', 'INLINING_LIMIT=0', '-s', 'TOTAL_MEMORY=100*1024*1024', '-s', 'FAST_MEMORY=10*1024*1024', '-o', final_filename] + emcc_args, stdout=PIPE, stderr=self.stderr_redirect).communicate() @@ -6595,6 +7519,8 @@ elif 'sanity' in str(sys.argv): def do(self, command): if type(command) is not list: command = [command] + if command[0] == EMCC: + command = ['python'] + command return Popen(command, stdout=PIPE, stderr=STDOUT).communicate()[0] @@ -6628,7 +7554,7 @@ elif 'sanity' in str(sys.argv): self.assertContained('Please edit that file and change the paths to fit your system', output) self.assertContained('make sure LLVM_ROOT and NODE_JS are correct', output) self.assertContained('This command will now exit. When you are done editing those paths, re-run it.', output) - assert output.replace('\n', '').endswith('===='), 'We should have stopped: ' + output + assert output.split()[-1].endswith('===='), 'We should have stopped: ' + output assert (open(CONFIG_FILE).read() == open(path_from_root('settings.py')).read()), 'Settings should be copied from settings.py' # Second run, with bad EM_CONFIG @@ -6709,6 +7635,24 @@ elif 'sanity' in str(sys.argv): assert mtime(SANITY_FILE) >= mtime(CONFIG_FILE) self.assertNotContained(SANITY_FAIL_MESSAGE, output) + # emcc should be configurable directly from EM_CONFIG without any config file + restore() + config = open(CONFIG_FILE, 'r').read() + os.environ['EM_CONFIG'] = config + wipe() + dirname = tempfile.mkdtemp(prefix='emscripten_test_' + self.__class__.__name__ + '_', dir=TEMP_DIR) + open(os.path.join(dirname, 'main.cpp'), 'w').write(''' + #include <stdio.h> + int main() { + printf("hello from emcc with no config file\\n"); + return 0; + } + ''') + Popen(['python', EMCC, os.path.join(dirname, 'main.cpp'), '-o', os.path.join(dirname, 'a.out.js')]).communicate() + self.assertContained('hello from emcc with no config file', run_js(os.path.join(dirname, 'a.out.js'))) + del os.environ['EM_CONFIG'] + shutil.rmtree(dirname) + def test_emcc_caching(self): INCLUDING_MESSAGE = 'emcc: including X' BUILDING_MESSAGE = 'emcc: building X for cache' @@ -6732,8 +7676,8 @@ elif 'sanity' in str(sys.argv): assert not os.path.exists(EMCC_CACHE) try_delete('a.out.js') - basebc_name = os.path.join(EMSCRIPTEN_TEMP_DIR, 'emcc-0-basebc.bc') - dcebc_name = os.path.join(EMSCRIPTEN_TEMP_DIR, 'emcc-1-dce.bc') + basebc_name = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-0-basebc.bc') + dcebc_name = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-1-dce.bc') # Building a file that *does* need dlmalloc *should* trigger cache generation, but only the first time for filename, libname in [('hello_malloc.cpp', 'dlmalloc'), ('hello_libcxx.cpp', 'libcxx')]: diff --git a/tests/screenshot-gray.png b/tests/screenshot-gray.png Binary files differnew file mode 100644 index 00000000..16e45a7a --- /dev/null +++ b/tests/screenshot-gray.png diff --git a/tests/screenshot.jpg b/tests/screenshot.jpg Binary files differnew file mode 100644 index 00000000..0c15dd3e --- /dev/null +++ b/tests/screenshot.jpg diff --git a/tests/screenshot.png b/tests/screenshot.png Binary files differnew file mode 100644 index 00000000..44cf844a --- /dev/null +++ b/tests/screenshot.png diff --git a/tests/screenshot2.png b/tests/screenshot2.png Binary files differnew file mode 100644 index 00000000..f8a29fbe --- /dev/null +++ b/tests/screenshot2.png diff --git a/tests/sdl_audio.c b/tests/sdl_audio.c new file mode 100644 index 00000000..4927d868 --- /dev/null +++ b/tests/sdl_audio.c @@ -0,0 +1,50 @@ +#include <stdio.h> +#include <SDL/SDL.h> +#include <SDL/SDL_mixer.h> +#include <assert.h> +#include <emscripten.h> + +Mix_Chunk *sound, *sound2; + +void play2(); + +void play() { + int channel = Mix_PlayChannel(-1, sound, 1); + assert(channel >= 0); + + emscripten_run_script("setTimeout(Module['_play2'], 500)"); +} + +void play2() { + int channel2 = Mix_PlayChannel(-1, sound2, 1); + assert(channel2 >= 0); +} + +int main(int argc, char **argv) { + SDL_Init(SDL_INIT_AUDIO); + + int ret = Mix_OpenAudio(0, 0, 0, 0); // we ignore all these.. + assert(ret == 0); + + sound = Mix_LoadWAV("sound.ogg"); + assert(sound); + sound2 = Mix_LoadWAV("sound2.wav"); + assert(sound); + + play(); + if (argc == 12121) play2(); // keep it alive + + emscripten_run_script("element = document.createElement('input');" + "element.setAttribute('type', 'button');" + "element.setAttribute('value', 'replay!');" + "element.setAttribute('onclick', 'Module[\"_play\"]()');" + "document.body.appendChild(element);"); + + printf("you should hear two sounds. press the button to replay!\n"); + + int result = 1; + REPORT_RESULT(); + + return 0; +} + diff --git a/tests/sdl_canvas.c b/tests/sdl_canvas.c new file mode 100644 index 00000000..ab1340a8 --- /dev/null +++ b/tests/sdl_canvas.c @@ -0,0 +1,50 @@ +#include <stdio.h> +#include <SDL/SDL.h> +#include <SDL/SDL_ttf.h> +#include <emscripten.h> + +int main() { + SDL_Init(SDL_INIT_VIDEO); + SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE); + + printf("Init: %d\n", TTF_Init()); + + TTF_Font *font = TTF_OpenFont("myfont.ttf", 40); + printf("Font: %p\n", font); + + SDL_Color color = { 0xff, 0x99, 0x00, 0xff }; + + SDL_Surface *text = TTF_RenderText_Solid(font, "hello orange world", color); + + SDL_Color color2 = { 0xbb, 0, 0xff, 0xff }; + SDL_Surface *text2 = TTF_RenderText_Solid(font, "a second line, purple", color2); + + // render + SDL_Rect dest = { 0, 50, 0, 0 }; + SDL_BlitSurface (text, NULL, screen, NULL); + dest.y = 100; + SDL_BlitSurface (text2, NULL, screen, &dest); + + // fill stuff + SDL_Rect rect = { 200, 200, 175, 125 }; + SDL_FillRect(screen, &rect, 0x2222ffff); + + SDL_Flip(screen); + + SDL_LockSurface(screen); + int sum = 0; + for (int i = 0; i < screen->h; i++) { + sum += *((char*)screen->pixels + i*screen->w*4 + i*4 + 0); + } + printf("Sum: %d\n", sum); + + printf("you should see two lines of text in different colors and a blue rectangle\n"); + + SDL_Quit(); + + int result = sum > 3000 && sum < 5000; // varies a little on different browsers, font differences? + REPORT_RESULT(); + + return 0; +} + diff --git a/tests/sdl_gl_read.c b/tests/sdl_gl_read.c new file mode 100644 index 00000000..552eb8c0 --- /dev/null +++ b/tests/sdl_gl_read.c @@ -0,0 +1,155 @@ +// Built from glbook/hello triange and sdl_ogl, see details there + +#include "SDL/SDL.h" +#include "SDL/SDL_image.h" +#include "SDL/SDL_opengl.h" + +#include <stdio.h> +#include <stdlib.h> + +GLuint programObject; +int width = 512; +int height = 256; + +GLuint LoadShader ( GLenum type, const char *shaderSrc ) +{ + GLuint shader; + GLint compiled; + + shader = glCreateShader ( type ); + if ( shader == 0 ) + return 0; + + glShaderSource ( shader, 1, &shaderSrc, NULL ); + glCompileShader ( shader ); + glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled ); + if ( !compiled ) + { + GLint infoLen = 0; + glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen ); + if ( infoLen > 1 ) + { + char* infoLog = malloc (sizeof(char) * infoLen ); + glGetShaderInfoLog ( shader, infoLen, NULL, infoLog ); + printf ( "Error compiling shader:\n%s\n", infoLog ); + free ( infoLog ); + } + glDeleteShader ( shader ); + return 0; + } + return shader; +} + +int Init () +{ + GLbyte vShaderStr[] = + "attribute vec4 vPosition; \n" + "void main() \n" + "{ \n" + " gl_Position = vPosition; \n" + "} \n"; + + GLbyte fShaderStr[] = + "precision mediump float;\n"\ + "void main() \n" + "{ \n" + " gl_FragColor = vec4 ( 0.0, 0.0, 1.0, 1.0 );\n" + "} \n"; + + GLuint vertexShader; + GLuint fragmentShader; + GLint linked; + + vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr ); + fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr ); + + programObject = glCreateProgram ( ); + if ( programObject == 0 ) + return 0; + + glAttachShader ( programObject, vertexShader ); + glAttachShader ( programObject, fragmentShader ); + glBindAttribLocation ( programObject, 0, "vPosition" ); + glLinkProgram ( programObject ); + glGetProgramiv ( programObject, GL_LINK_STATUS, &linked ); + if ( !linked ) + { + GLint infoLen = 0; + glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen ); + if ( infoLen > 1 ) + { + char* infoLog = malloc (sizeof(char) * infoLen ); + glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog ); + printf ( "Error linking program:\n%s\n", infoLog ); + free ( infoLog ); + } + glDeleteProgram ( programObject ); + return GL_FALSE; + } + + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); + return GL_TRUE; +} + +/// +// Draw a triangle using the shader pair created in Init() +// +void Draw () +{ + GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f, + -0.5f, -0.5f, 0.0f, + 0.5f, -0.5f, 0.0f }; + + // No clientside arrays, so do this in a webgl-friendly manner + GLuint vertexPosObject; + glGenBuffers(1, &vertexPosObject); + glBindBuffer(GL_ARRAY_BUFFER, vertexPosObject); + glBufferData(GL_ARRAY_BUFFER, 9*4, vVertices, GL_STATIC_DRAW); + + glViewport ( 0, 0, width, height ); + glClear ( GL_COLOR_BUFFER_BIT ); + glUseProgram ( programObject ); + + glBindBuffer(GL_ARRAY_BUFFER, vertexPosObject); + glVertexAttribPointer(0 /* ? */, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(0); + + glDrawArrays ( GL_TRIANGLES, 0, 3 ); +} + +void Verify() { + unsigned char *data = malloc(width*height*4); + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); + // Should see some blue, and nothing else + int seen = 0; + int ok = 1; + for (int x = 0; x < width*height; x++) { + seen = seen || data[x*4+2] != 0; + ok = ok && (data[x*4+0] == 0); + ok = ok && (data[x*4+1] == 0); + } + int result = seen && ok; + REPORT_RESULT(); +} + +int main(int argc, char *argv[]) +{ + SDL_Surface *screen; + if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) { + printf("Unable to initialize SDL: %s\n", SDL_GetError()); + return 1; + } + + screen = SDL_SetVideoMode(width, height, 32, SDL_OPENGL); + if (!screen) { + printf("Unable to set video mode: %s\n", SDL_GetError()); + return 1; + } + + Init(); + Draw(); + Verify(); + + return 0; +} + diff --git a/tests/sdl_image.c b/tests/sdl_image.c new file mode 100644 index 00000000..d934f863 --- /dev/null +++ b/tests/sdl_image.c @@ -0,0 +1,35 @@ +#include <stdio.h> +#include <SDL/SDL.h> +#include <SDL/SDL_image.h> +#include <assert.h> +#include <emscripten.h> + +int main() { + SDL_Init(SDL_INIT_VIDEO); + SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_SWSURFACE); + + SDL_Surface *image = IMG_Load("screenshot.jpg"); + if (!image) + { + printf("IMG_Load: %s\n", IMG_GetError()); + return 1; + } + assert(image->format->BitsPerPixel == 32); + assert(image->format->BytesPerPixel == 4); + assert(image->pitch == 4*image->w); + + SDL_BlitSurface (image, NULL, screen, NULL); + SDL_FreeSurface (image); + + SDL_Flip(screen); + + printf("you should see an image.\n"); + + SDL_Quit(); + + int result = image->w; + REPORT_RESULT(); + + return 0; +} + diff --git a/tests/sdl_key.c b/tests/sdl_key.c new file mode 100644 index 00000000..f82f8e72 --- /dev/null +++ b/tests/sdl_key.c @@ -0,0 +1,55 @@ +#include <stdio.h> +#include <SDL/SDL.h> +#include <SDL/SDL_ttf.h> +#include <emscripten.h> + +int result = 1; + +void one() { + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch(event.type) { + case SDL_KEYDOWN: + break; + case SDL_KEYUP: + switch (event.key.keysym.sym) { + case SDLK_RIGHT: printf("right\n"); result *= 2; break; + case SDLK_LEFT: printf("left\n"); result *= 3; break; + case SDLK_DOWN: printf("down\n"); result *= 5; break; + case SDLK_UP: printf("up\n"); result *= 7; break; + case SDLK_SPACE: printf("space\n"); result *= 11; break; + case SDLK_a: printf("a\n"); result *= 13; break; + default: { + if (event.key.keysym.scancode == SDL_SCANCODE_B) { + printf("b scancode\n"); result *= 17; break; + } + printf("unknown key: sym %d scancode %d\n", event.key.keysym.sym, event.key.keysym.scancode); + REPORT_RESULT(); + emscripten_run_script("throw 'done'"); + } + } + break; + default: /* Report an unhandled event */ + printf("I don't know what this event is!\n"); + } + } +} + +int main(int argc, char **argv) { + SDL_Init(SDL_INIT_VIDEO); + SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE); + + emscripten_run_script("simulateKeyEvent(38)"); + emscripten_run_script("simulateKeyEvent(40)"); + emscripten_run_script("simulateKeyEvent(37)"); + emscripten_run_script("simulateKeyEvent(39)"); + emscripten_run_script("simulateKeyEvent(32)"); + emscripten_run_script("simulateKeyEvent(97)"); + emscripten_run_script("simulateKeyEvent(98)"); + emscripten_run_script("simulateKeyEvent(100)"); // trigger the end + + if (argc == 1337) one(); // keep it alive + + return 0; +} + diff --git a/tests/sdl_mouse.c b/tests/sdl_mouse.c new file mode 100644 index 00000000..7fc14638 --- /dev/null +++ b/tests/sdl_mouse.c @@ -0,0 +1,62 @@ +#include <stdio.h> +#include <SDL/SDL.h> +#include <SDL/SDL_ttf.h> +#include <assert.h> +#include <emscripten.h> + +int result = 1; + +void one() { + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch(event.type) { + case SDL_MOUSEMOTION: { + SDL_MouseMotionEvent *m = (SDL_MouseMotionEvent*)&event; + int x, y; + SDL_GetMouseState(&x, &y); + assert(x == m->x && y == m->y); + printf("motion: %d,%d %d,%d\n", m->x, m->y, m->xrel, m->yrel); + result += 2 * (m->x + m->y + m->xrel + m->yrel); + break; + } + case SDL_MOUSEBUTTONDOWN: { + SDL_MouseButtonEvent *m = (SDL_MouseButtonEvent*)&event; + if (m->button == 2) { + REPORT_RESULT(); + emscripten_run_script("throw 'done'"); + } + printf("button down: %d,%d %d,%d\n", m->button, m->state, m->x, m->y); + result += 3 * (m->button + m->state + m->x + m->y); + break; + } + case SDL_MOUSEBUTTONUP: { + SDL_MouseButtonEvent *m = (SDL_MouseButtonEvent*)&event; + printf("button up: %d,%d %d,%d\n", m->button, m->state, m->x, m->y); + result += 5 * (m->button + m->state + m->x + m->y); + // Remove another click we want to ignore + assert(SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONDOWN) == 1); + assert(SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_MOUSEBUTTONUP, SDL_MOUSEBUTTONUP) == 1); + break; + } + } + } +} + +int main() { + SDL_Init(SDL_INIT_VIDEO); + SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE); + + SDL_Rect rect = { 0, 0, 600, 450 }; + SDL_FillRect(screen, &rect, 0x2244ffff); + + emscripten_run_script("simulateMouseEvent(10, 20, -1)"); // move from 0,0 to 10,20 + emscripten_run_script("simulateMouseEvent(10, 20, 0)"); // click + emscripten_run_script("simulateMouseEvent(10, 20, 0)"); // click some more, but this one should be ignored through PeepEvent + emscripten_run_script("simulateMouseEvent(30, 77, -1)"); // move some more + emscripten_run_script("simulateMouseEvent(30, 77, 1)"); // trigger the end + + emscripten_set_main_loop(one, 0); + + return 0; +} + diff --git a/tests/sdl_ogl.c b/tests/sdl_ogl.c new file mode 100644 index 00000000..9aaae280 --- /dev/null +++ b/tests/sdl_ogl.c @@ -0,0 +1,155 @@ +/******************************************************************* + * * + * Using SDL With OpenGL * + * * + * Tutorial by Kyle Foley (sdw) * + * * + * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL * + * * + *******************************************************************/ + +/* +THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION +AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN. + +THE ORIGINAL AUTHOR IS KYLE FOLEY. + +THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY +OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF +MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, +ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE +RESULTING FROM THE USE, MODIFICATION, OR +REDISTRIBUTION OF THIS SOFTWARE. +*/ + +#include "SDL/SDL.h" +#include "SDL/SDL_image.h" +#include "SDL/SDL_opengl.h" + +#include <stdio.h> +#include <string.h> + +int main(int argc, char *argv[]) +{ + SDL_Surface *screen; + + // Slightly different SDL initialization + if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) { + printf("Unable to initialize SDL: %s\n", SDL_GetError()); + return 1; + } + + SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new* + + screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed* + if ( !screen ) { + printf("Unable to set video mode: %s\n", SDL_GetError()); + return 1; + } + + // Set the OpenGL state after creating the context with SDL_SetVideoMode + + glClearColor( 0, 0, 0, 0 ); + +#if !EMSCRIPTEN + glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL +#endif + + glViewport( 0, 0, 640, 480 ); + + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + + glOrtho( 0, 640, 480, 0, -1, 1 ); + + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + + // Load the OpenGL texture + + GLuint texture; // Texture object handle + SDL_Surface *surface; // Gives us the information to make the texture + + if ( (surface = IMG_Load("screenshot.png")) ) { + + // Check that the image's width is a power of 2 + if ( (surface->w & (surface->w - 1)) != 0 ) { + printf("warning: image.bmp's width is not a power of 2\n"); + } + + // Also check if the height is a power of 2 + if ( (surface->h & (surface->h - 1)) != 0 ) { + printf("warning: image.bmp's height is not a power of 2\n"); + } + + // Have OpenGL generate a texture object handle for us + glGenTextures( 1, &texture ); + + // Bind the texture object + glBindTexture( GL_TEXTURE_2D, texture ); + + // Set the texture's stretching properties + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + //SDL_LockSurface(surface); + + // Add some greyness + memset(surface->pixels, 0x66, surface->w*surface->h); + + // Edit the texture object's image data using the information SDL_Surface gives us + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); + + //SDL_UnlockSurface(surface); + } + else { + printf("SDL could not load image.bmp: %s\n", SDL_GetError()); + SDL_Quit(); + return 1; + } + + // Free the SDL_Surface only if it was successfully created + if ( surface ) { + SDL_FreeSurface( surface ); + } + + // Clear the screen before drawing + glClear( GL_COLOR_BUFFER_BIT ); + + // Bind the texture to which subsequent calls refer to + glBindTexture( GL_TEXTURE_2D, texture ); + + glBegin( GL_QUADS ); + glTexCoord2i( 0, 0 ); glVertex3f( 10, 10, 0 ); + glTexCoord2i( 1, 0 ); glVertex3f( 300, 10, 0 ); + glTexCoord2i( 1, 1 ); glVertex3f( 300, 128, 0 ); + glTexCoord2i( 0, 1 ); glVertex3f( 10, 128, 0 ); + + glTexCoord2f( 0, 0.5 ); glVertex3f( 410, 10, 0 ); + glTexCoord2f( 1, 0.5 ); glVertex3f( 600, 10, 0 ); + glTexCoord2f( 1, 1 ); glVertex3f( 630, 200, 0 ); + glTexCoord2f( 0.5, 1 ); glVertex3f( 310, 250, 0 ); + glEnd(); + + glBegin( GL_TRIANGLE_STRIP ); + glTexCoord2i( 0, 0 ); glVertex3f( 100, 300, 0 ); + glTexCoord2i( 1, 0 ); glVertex3f( 300, 300, 0 ); + glTexCoord2i( 1, 1 ); glVertex3f( 300, 400, 0 ); + glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 0 ); + glEnd(); + + SDL_GL_SwapBuffers(); + +#if !EMSCRIPTEN + // Wait for 3 seconds to give us a chance to see the image + SDL_Delay(3000); +#endif + + // Now we can delete the OpenGL texture and close down SDL + glDeleteTextures( 1, &texture ); + + SDL_Quit(); + + return 0; +} diff --git a/tests/sdl_ogl_p.c b/tests/sdl_ogl_p.c new file mode 100644 index 00000000..3978f66c --- /dev/null +++ b/tests/sdl_ogl_p.c @@ -0,0 +1,164 @@ +/******************************************************************* + * * + * Using SDL With OpenGL * + * * + * Tutorial by Kyle Foley (sdw) * + * * + * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL * + * * + *******************************************************************/ + +/* +THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION +AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN. + +THE ORIGINAL AUTHOR IS KYLE FOLEY. + +THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY +OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF +MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, +ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE +RESULTING FROM THE USE, MODIFICATION, OR +REDISTRIBUTION OF THIS SOFTWARE. +*/ + +#include "SDL/SDL.h" +#include "SDL/SDL_image.h" +#include "SDL/SDL_opengl.h" + +#include <stdio.h> +#include <string.h> + +int main(int argc, char *argv[]) +{ + SDL_Surface *screen; + + // Slightly different SDL initialization + if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) { + printf("Unable to initialize SDL: %s\n", SDL_GetError()); + return 1; + } + + SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new* + + screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed* + if ( !screen ) { + printf("Unable to set video mode: %s\n", SDL_GetError()); + return 1; + } + + // Set the OpenGL state after creating the context with SDL_SetVideoMode + + glClearColor( 0, 0, 0, 0 ); + +#if !EMSCRIPTEN + glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL +#endif + + glViewport( 0, 0, 640, 480 ); + + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + + glOrtho( 0, 640, 480, 0, -1, 1 ); + + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + + // Load the OpenGL texture + + GLuint texture; // Texture object handle + SDL_Surface *surface; // Gives us the information to make the texture + + if ( (surface = IMG_Load("screenshot.png")) ) { + + // Check that the image's width is a power of 2 + if ( (surface->w & (surface->w - 1)) != 0 ) { + printf("warning: image.bmp's width is not a power of 2\n"); + } + + // Also check if the height is a power of 2 + if ( (surface->h & (surface->h - 1)) != 0 ) { + printf("warning: image.bmp's height is not a power of 2\n"); + } + + // Have OpenGL generate a texture object handle for us + glGenTextures( 1, &texture ); + + // Bind the texture object + glBindTexture( GL_TEXTURE_2D, texture ); + + // Set the texture's stretching properties + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + //SDL_LockSurface(surface); + + // Add some greyness + memset(surface->pixels, 0x66, surface->w*surface->h); + + // Edit the texture object's image data using the information SDL_Surface gives us + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); + + //SDL_UnlockSurface(surface); + } + else { + printf("SDL could not load image.bmp: %s\n", SDL_GetError()); + SDL_Quit(); + return 1; + } + + // Free the SDL_Surface only if it was successfully created + if ( surface ) { + SDL_FreeSurface( surface ); + } + + // Clear the screen before drawing + glClear( GL_COLOR_BUFFER_BIT ); + + // Bind the texture to which subsequent calls refer to + glBindTexture( GL_TEXTURE_2D, texture ); + + // Use clientside vertex pointers to render two items + GLfloat vertexData[] = { 0, 0, 10, 10, // texture2, position2 + 1, 0, 300, 10, + 1, 1, 300, 128, + 0, 1, 10, 128, + 0, 0.5, 410, 10, + 1, 0.5, 600, 10, + 1, 1, 630, 200, + 0.5, 1, 310, 250 }; + + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, 4*4, &vertexData[0]); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 4*4, &vertexData[2]); + + glDrawArrays(GL_QUADS, 0, 8); + + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + // Render the last item using oldschool glBegin etc + glBegin( GL_TRIANGLE_STRIP ); + glTexCoord2i( 0, 0 ); glVertex3f( 100, 300, 0 ); + glTexCoord2i( 1, 0 ); glVertex3f( 300, 300, 0 ); + glTexCoord2i( 1, 1 ); glVertex3f( 300, 400, 0 ); + glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 0 ); + glEnd(); + + SDL_GL_SwapBuffers(); + +#if !EMSCRIPTEN + // Wait for 3 seconds to give us a chance to see the image + SDL_Delay(3000); +#endif + + // Now we can delete the OpenGL texture and close down SDL + glDeleteTextures( 1, &texture ); + + SDL_Quit(); + + return 0; +} diff --git a/tests/sounds/LICENSE.txt b/tests/sounds/LICENSE.txt new file mode 100644 index 00000000..1525d517 --- /dev/null +++ b/tests/sounds/LICENSE.txt @@ -0,0 +1,19 @@ +The files in this directory are Copyright (C) 2009 Wildfire Games. + +These files are licensed under the Creative Commons Attribution-Share Alike 3.0 +(CC-by-sa) license, available at http://creativecommons.org/licenses/by-sa/3.0/ + +Briefly, this means: + +* You may use, modify and distribute these files, for commercial and + non-commercial purposes. + +* If you distribute one of these files, you must include attribution (e.g. + in the credits screen of a game or a video, or in a text file accompanying + the files). The attribution must include: + * A link to http://creativecommons.org/licenses/by-sa/3.0/ + * The name "Wildfire Games" as the original author + * A link to http://www.wildfiregames.com/ + +* If you distribute one of these files, you must release it (and any + modifications you have made to it) under the CC-by-sa license.
\ No newline at end of file diff --git a/tests/sounds/alarmcreatemiltaryfoot_1.wav b/tests/sounds/alarmcreatemiltaryfoot_1.wav Binary files differnew file mode 100644 index 00000000..2de6314a --- /dev/null +++ b/tests/sounds/alarmcreatemiltaryfoot_1.wav diff --git a/tests/sounds/alarmvictory_1.ogg b/tests/sounds/alarmvictory_1.ogg Binary files differnew file mode 100644 index 00000000..cadb1539 --- /dev/null +++ b/tests/sounds/alarmvictory_1.ogg diff --git a/tests/time/output.txt b/tests/time/output.txt index 7ef34821..45b7d4bd 100644 --- a/tests/time/output.txt +++ b/tests/time/output.txt @@ -12,11 +12,11 @@ yday: 358 dst: 0 off: 0 zone: GMT -timegm <-> gmtime: 0 +timegm <-> gmtime: 1 old year: 102 new year: 70 old year again: 102 -localtime timezone: 0 +localtime timezone: 1 localtime daylight: 1 localtime tzname: 1 localtime <-> mktime: 1 diff --git a/tests/unistd/io.js b/tests/unistd/io.js index b129af44..e2e442ec 100644 --- a/tests/unistd/io.js +++ b/tests/unistd/io.js @@ -7,7 +7,7 @@ return null; } }, function(arg) { - print("TO DEVICE: " + arg); + Module.print("TO DEVICE: " + arg); }); FS.createDevice('/', 'broken-device', function() { throw new Error('Broken device input.'); diff --git a/tests/unistd/isatty.out b/tests/unistd/isatty.out index 9e7f41e8..6823c1f0 100644 --- a/tests/unistd/isatty.out +++ b/tests/unistd/isatty.out @@ -1,10 +1,10 @@ -read: -1 +read: 0 errno: 25 -write: -1 +write: 0 errno: 25 -all: -1 +all: 0 errno: 25 -folder: -1 +folder: 0 errno: 25 -file: -1 +file: 0 errno: 25 diff --git a/third_party/closure-compiler/COPYING b/third_party/closure-compiler/COPYING new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/third_party/closure-compiler/COPYING @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) 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. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. diff --git a/third_party/closure-compiler/README b/third_party/closure-compiler/README new file mode 100644 index 00000000..e6d12c4a --- /dev/null +++ b/third_party/closure-compiler/README @@ -0,0 +1,292 @@ +/* + * Copyright 2009 The Closure Compiler Authors. + * + * Licensed 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. + */ + +// +// Contents +// + +The Closure Compiler performs checking, instrumentation, and +optimizations on JavaScript code. The purpose of this README is to +explain how to build and run the Closure Compiler. + +The Closure Compiler requires Java 6 or higher. +http://www.java.com/ + + +// +// Building The Closure Compiler +// + +There are three ways to get a Closure Compiler executable. + +1) Use one we built for you. + +Pre-built Closure binaries can be found at +http://code.google.com/p/closure-compiler/downloads/list + + +2) Check out the source and build it with Apache Ant. + +First, check out the full source tree of the Closure Compiler. There +are instructions on how to do this at the project site. +http://code.google.com/p/closure-compiler/source/checkout + +Apache Ant is a cross-platform build tool. +http://ant.apache.org/ + +At the root of the source tree, there is an Ant file named +build.xml. To use it, navigate to the same directory and type the +command + +ant jar + +This will produce a jar file called "build/compiler.jar". + + +3) Check out the source and build it with Eclipse. + +Eclipse is a cross-platform IDE. +http://www.eclipse.org/ + +Under Eclipse's File menu, click "New > Project ..." and create a +"Java Project." You will see an options screen. Give the project a +name, select "Create project from existing source," and choose the +root of the checked-out source tree as the existing directory. Verify +that you are using JRE version 6 or higher. + +Eclipse can use the build.xml file to discover rules. When you +navigate to the build.xml file, you will see all the build rules in +the "Outline" pane. Run the "jar" rule to build the compiler in +build/compiler.jar. + + +// +// Running The Closure Compiler +// + +Once you have the jar binary, running the Closure Compiler is straightforward. + +On the command line, type + +java -jar compiler.jar + +This starts the compiler in interactive mode. Type + +var x = 17 + 25; + +then hit "Enter", then hit "Ctrl-Z" (on Windows) or "Ctrl-D" (on Mac or Linux) +and "Enter" again. The Compiler will respond: + +var x=42; + +The Closure Compiler has many options for reading input from a file, +writing output to a file, checking your code, and running +optimizations. To learn more, type + +java -jar compiler.jar --help + +You can read more detailed documentation about the many flags at +http://code.google.com/closure/compiler/docs/gettingstarted_app.html + + +// +// Compiling Multiple Scripts +// + +If you have multiple scripts, you should compile them all together with +one compile command. + +java -jar compiler.jar --js=in1.js --js=in2.js ... --js_output_file=out.js + +The Closure Compiler will concatenate the files in the order they're +passed at the command line. + +If you need to compile many, many scripts together, you may start to +run into problems with managing dependencies between scripts. You +should check out the Closure Library. It contains functions for +enforcing dependencies between scripts, and a tool called calcdeps.py +that knows how to give scripts to the Closure Compiler in the right +order. + +http://code.google.com/p/closure-library/ + +// +// Licensing +// + +Unless otherwise stated, all source files are licensed under +the Apache License, Version 2.0. + + +----- +Code under: +src/com/google/javascript/rhino +test/com/google/javascript/rhino + +URL: http://www.mozilla.org/rhino +Version: 1.5R3, with heavy modifications +License: Netscape Public License and MPL / GPL dual license + +Description: A partial copy of Mozilla Rhino. Mozilla Rhino is an +implementation of JavaScript for the JVM. The JavaScript parser and +the parse tree data structures were extracted and modified +significantly for use by Google's JavaScript compiler. + +Local Modifications: The packages have been renamespaced. All code not +relavant to parsing has been removed. A JSDoc parser and static typing +system have been added. + + +----- +Code in: +lib/rhino + +Rhino +URL: http://www.mozilla.org/rhino +Version: Trunk +License: Netscape Public License and MPL / GPL dual license + +Description: Mozilla Rhino is an implementation of JavaScript for the JVM. + +Local Modifications: Minor changes to parsing JSDoc that usually get pushed +up-stream to Rhino trunk. + + +----- +Code in: +lib/args4j.jar + +Args4j +URL: https://args4j.dev.java.net/ +Version: 2.0.12 +License: MIT + +Description: +args4j is a small Java class library that makes it easy to parse command line +options/arguments in your CUI application. + +Local Modifications: None. + + +----- +Code in: +lib/guava.jar + +Guava Libraries +URL: http://code.google.com/p/guava-libraries/ +Version: r08 +License: Apache License 2.0 + +Description: Google's core Java libraries. + +Local Modifications: None. + + +----- +Code in: +lib/jsr305.jar + +Annotations for software defect detection +URL: http://code.google.com/p/jsr-305/ +Version: svn revision 47 +License: BSD License + +Description: Annotations for software defect detection. + +Local Modifications: None. + + +----- +Code in: +lib/jarjar.jar + +Jar Jar Links +URL: http://jarjar.googlecode.com/ +Version: 1.1 +License: Apache License 2.0 + +Description: +A utility for repackaging Java libraries. + +Local Modifications: None. + + +---- +Code in: +lib/junit.jar + +JUnit +URL: http://sourceforge.net/projects/junit/ +Version: 4.8.2 +License: Common Public License 1.0 + +Description: A framework for writing and running automated tests in Java. + +Local Modifications: None. + + +--- +Code in: +lib/protobuf-java.jar + +Protocol Buffers +URL: http://code.google.com/p/protobuf/ +Version: 2.3.0 +License: New BSD License + +Description: Supporting libraries for protocol buffers, +an encoding of structured data. + +Local Modifications: None + + +--- +Code in: +lib/ant.jar +lib/ant-launcher.jar + +URL: http://ant.apache.org/bindownload.cgi +Version: 1.8.1 +License: Apache License 2.0 +Description: + Ant is a Java based build tool. In theory it is kind of like "make" + without make's wrinkles and with the full portability of pure java code. + +Local Modifications: None + + +--- +Code in: +lib/json.jar +URL: http://json.org/java/index.html +Version: JSON version 20090211 +License: MIT license +Description: +JSON is a set of java files for use in transmitting data in JSON format. + +Local Modifications: None + +--- +Code in: +tools/maven-ant-tasks-2.1.1.jar +URL: http://maven.apache.org +Version 2.1.1 +License: Apache License 2.0 +Description: + Maven Ant tasks are used to manage dependencies and to install/deploy to + maven repositories. + +Local Modifications: None diff --git a/third_party/closure-compiler/compiler.jar b/third_party/closure-compiler/compiler.jar Binary files differnew file mode 100644 index 00000000..d958a618 --- /dev/null +++ b/third_party/closure-compiler/compiler.jar diff --git a/third_party/lzma.js/README.markdown b/third_party/lzma.js/README.markdown new file mode 100644 index 00000000..e2c90730 --- /dev/null +++ b/third_party/lzma.js/README.markdown @@ -0,0 +1,37 @@ + +lzma.js +======= + +An LZMA implementation in JavaScript, compiled from lzip using Emscripten +with the goal of having a small and fast implementation as much as +possible. + +lzip is GPL, additional code is MIT + + +Building +-------- + +Run doit.sh. It will build both a native build, lzma-native, and lzma.js. +Both are useful because you can use the native build to compress locally, +and the JS build to decompress on the client browser. But, you can use +whichever you want in either location. + + +Usage +----- + +LZMA.compress(data) receives an array of 8-bit data and returns an + array of compressed data. + +LZMA.decompress(data) receives an array of compressed 8-bit data and + returns an array of decompressed data. + + +Use lzma-decoder.js if you just need to decode. It's 66K, or 23K +if your webserver does gzip. If you need compression too, use +lzma-full.js which is a little larger. + +See test-decoder.js, test-full.js and test-full.html for example +uses. + diff --git a/third_party/lzma.js/doit.sh b/third_party/lzma.js/doit.sh new file mode 100755 index 00000000..a8071534 --- /dev/null +++ b/third_party/lzma.js/doit.sh @@ -0,0 +1,35 @@ +cd lzip + +echo "native" +make clean +DECODER_ONLY=0 make lzip -j 4 # native build +mv lzip ../lzma-native + +exit # just build natively, that's it + +echo "bitcode full (encoder+decoder)" +make clean +DECODER_ONLY=0 ~/Dev/emscripten/emmake make lzip -j 4 +mv lzip lzip-full.bc + +echo "bitcode decoder only" +make clean +DECODER_ONLY=1 ~/Dev/emscripten/emmake make lzip -j 4 +mv lzip lzip-decoder.bc + +cd .. + +echo "javascript full" +~/Dev/emscripten/emcc -O2 lzip/lzip-full.bc -o lzma-full.raw.js +# -s INLINING_LIMIT=0 +cat pre.js > lzma-full.js +cat lzma-full.raw.js >> lzma-full.js +cat post.js >> lzma-full.js + +echo "javascript decoder" +~/Dev/emscripten/emcc -O2 lzip/lzip-decoder.bc -o lzma-decoder.raw.js +# -s INLINING_LIMIT=0 +cat pre.js > lzma-decoder.js +cat lzma-decoder.raw.js >> lzma-decoder.js +cat post.js >> lzma-decoder.js + diff --git a/third_party/lzma.js/lzip/AUTHORS b/third_party/lzma.js/lzip/AUTHORS new file mode 100644 index 00000000..ada24df3 --- /dev/null +++ b/third_party/lzma.js/lzip/AUTHORS @@ -0,0 +1,7 @@ +Lzip was written by Antonio Diaz Diaz. + +The ideas embodied in lzip are due to (at least) the following people: +Abraham Lempel and Jacob Ziv (for the LZ algorithm), Andrey Markov (for +the definition of Markov chains), G.N.N. Martin (for the definition of +range encoding), Igor Pavlov (for putting all the above together in +LZMA), and Julian Seward (for bzip2's CLI and the idea of unzcrash). diff --git a/third_party/lzma.js/lzip/COPYING b/third_party/lzma.js/lzip/COPYING new file mode 100644 index 00000000..44325404 --- /dev/null +++ b/third_party/lzma.js/lzip/COPYING @@ -0,0 +1,676 @@ + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. 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 +them 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 prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. 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. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey 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; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + 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. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +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. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + 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 +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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 <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program 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, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU 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. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. + diff --git a/third_party/lzma.js/lzip/ChangeLog b/third_party/lzma.js/lzip/ChangeLog new file mode 100644 index 00000000..88accb13 --- /dev/null +++ b/third_party/lzma.js/lzip/ChangeLog @@ -0,0 +1,201 @@ +2011-04-30 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 1.12 released. + * main.cc: Added new option `-F, --recompress'. + * encoder.h (update_prices): Update high length symbol prices + independently of the value of `pos_state'. This gives better + compression for large values of `--match-length' without being + slower. + * encoder.h encoder.cc: Optimize pair price calculations. This + reduces compression time for large values of `--match-length' + by up to 6%. + * Compression time of option `-0' has been reduced by 2%. + * main.cc (decompress): Print only one status line for each + multimember file when only one `-v' is specified. + * main.cc (decompress): Print up to 6 bytes of trailing garbage + when `-vvvv' is specified. + * main.cc (open_instream): Do not show the message + " and `--stdout' was not specified" for directories, etc. + * lziprecover.cc: If `-v' is not specified show errors only. + * testsuite/unzcrash.cc: Use Arg_parser. + * testsuite/unzcrash.cc: Added new options `-b', `-p' and `-s'. + +2010-09-16 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 1.11 released. + * Added new option `-0' which produces a compression speed and + ratio comparable to those of `gzip -9'. + * fast_encoder.h fast_encoder.cc: New files. + * main.cc: Match length limit set by options -1 to -8 has been + reduced to extend range of use towards gzip. Lower numbers now + compress less but faster. (-1 now takes 43% less time for only + 20% larger compressed size). + * encoder.cc: Compression of option -9 has been slightly increased. + * lziprecover.cc: Added new option `--merge' which tries to + produce a correct file merging the good parts of two or more + damaged copies. + * lziprecover.cc: Added new option `--repair' for repairing a + 1-byte error in single-member files. + * decoder.cc (decode_member): Detect file errors earlier to + improve efficiency of lziprecover's new repair capability. + This change also prevents (harmless) access to uninitialized + memory when decompressing a corrupt file. + * lziprecover.cc: Added new option `--force'. + * lziprecover.cc: Added new option `--output'. + * lziprecover.cc: Added new option `--split' to select the until + now only operation of splitting multimember files. + * lziprecover.cc: If no operation is specified, warn the user + and do nothing. + * main.cc: Fixed warning about fchown's return value being ignored. + * decoder.cc: `-tvvvv' now also shows compression ratio. + * main.cc: Set stdin/stdout in binary mode on MSVC and OS2. + * New examples have been added to the manual. + * testsuite: `test1' renamed to `test.txt'. Added new tests. + * Matchfinder types HC4 (4 bytes hash-chain) and HT4 (4 bytes + hash-table) have been tested and found no better than the + current BT4. + +2010-04-05 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 1.10 released. + * decoder.h: Input_buffer integrated in Range_decoder. + * main.cc: File specified with option `-o' is now created with + mode 0666 if umask allows it, deleted if interrupted by user. + * main.cc: New constant `o_binary'. + * main.cc: Dictionary size for options -2, -3, -4 and -8 has + been changed to improve linearity of compressed sizes. + * lzip.h: Fixed warnings produced by over-optimization (-O3). + * Makefile.in: Added quotes to directory names. + +2010-01-17 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 1.9 released. + * main.cc (main): Return at least 1 if closing stdout fails. + * Makefile.in: Added `--name' option to help2man invocation. + * testsuite/check.sh: Use `test1' instead of `COPYING' for testing. + +2009-09-02 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 1.8 released. + * Compression time has been reduced by 4%. + * Lzdiff and lzgrep have been moved to the new package zutils. + * Fixed warnings on sistems where uint32_t != unsigned int. + +2009-06-25 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 1.7 released. + * decoder.h (copy_block): Fixed memcpy overlap introduced in 1.6. + +2009-06-22 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 1.6 released. + * Decompression time has been reduced by 17%. + * Added decompression support for Sync Flush marker. + * Added support for .tbz extension to lzdiff and lzgrep. + * Added man pages for lzdiff, lzgrep and lziprecover. + * encoder.cc (Matchfinder): Reduce memory use to 9x if input file + is smaller than dictionary size limit. + * decoder.cc: Added extra flush calls to improve partial + decompression of corrupt files. + * `--test' no more needs `/dev/null'. + * Removed some `bashisms' from lzdiff and lzgrep. + * Dictionary size for options `-1' to `-4' has been changed. + * main.cc (signal_handler): Declared as `extern "C"'. + * Makefile.in: Extra files are now installed by default. + * testsuite/check.sh: Test lziprecover. + * Added `export LC_ALL=C' to all scripts. + +2009-04-12 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 1.5 released. + * lzip.h: Coded dictionary size implemented in File_header. + * Fixed some includes that prevented compilation with GCC 4.4. + * `member_size' and `volume_size' are now accurate limits. + * Compression speed has been improved. + * Implemented bt4 type matchfinder. + * Added chapter `Algorithm' to the manual. + * Lzdiff and lzgrep now accept `-h' for `--help' and + `-V' for `--version'. + * Makefile.in: Man page is now installed by default. + * testsuite/check.sh: Verify that files are open in binary mode. + +2009-01-24 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 1.4 released. + * Implemented compression of version 1 files. + * Added new option `--member-size'. + * Added new option `--volume-size'. + * Added new option `--output'. + * main.cc: Read from non regular files if `--stdout' is specified. + * Added `lziprecover', a member recoverer program. + * testsuite/unzcrash.cc: Test all 1-byte errors. + +2008-12-21 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 1.3 released. + * This version automatically chooses the smallest possible + dictionary size for each file during compression, saving + memory during decompression. + * Implemented decompression of version 1 files. + * testsuite/check.sh: Replaced `diff -q' with `cmp'. + +2008-12-10 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 1.2 released. + * encoder.cc: A 1-byte read outside allocated memory has been fixed. + * lzip.h: Dictionary size limit has been reduced to 512MiB because + setting it to 1GiB causes overflow of a 32 bit integer. + * Added `lzdiff', a diff/cmp wrapper for gzip, bzip2, lzip and + non-compressed files. + * Added `lzgrep', a grep wrapper for gzip, bzip2, lzip and + non-compressed files. + * `make install-info' should now work on Debian and OS X. + +2008-11-17 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 1.1 released. + * Changed short name of option `--dictionary-size' to `-s'. + * Changed short name of option `--match-length' to `-m'. + * Changed LONG_LONG_MAX to LLONG_MAX. + +2008-10-14 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 1.0 released. + * `-tvv' shows file version and dictionary size. + +2008-09-30 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 0.5 released. + * Decompression is now 1% faster. + +2008-09-23 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 0.4 released. + * Code cleanup for global variable `verbosity'. + * Regained the compression ratio of 0.2 with 5% faster speed. + * Fixed compilation on sistems where size_t != unsigned int. + +2008-09-15 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 0.3 released. + * encoder.cc: Compression is now 15% faster, 1% worse. + * main.cc (main): Make `-t' option override `-c'. + * main.cc (decompress): Show `done' instead of `ok' when not testing. + * encoder.h: Use trials[] to return the list of pairs. + +2008-09-09 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 0.2 released. + * encoder.cc: Small improvements in compression speed. + * Small documentation changes. + +2008-08-20 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 0.1 released. + + +Copyright (C) 2008, 2009, 2010, 2011 Antonio Diaz Diaz. + +This file is a collection of facts, and thus it is not copyrightable, +but just in case, you have unlimited permission to copy, distribute and +modify it. diff --git a/third_party/lzma.js/lzip/INSTALL b/third_party/lzma.js/lzip/INSTALL new file mode 100644 index 00000000..b516f570 --- /dev/null +++ b/third_party/lzma.js/lzip/INSTALL @@ -0,0 +1,56 @@ +Requirements +------------ +You will need a C++ compiler. +I use gcc 4.3.5 and 3.3.6, but the code should compile with any +standards compliant compiler. +Gcc is available at http://gcc.gnu.org. + + +Procedure +--------- +1. Unpack the archive if you have not done so already: + + lzip -cd lzip[version].tar.lz | tar -xf - +or + gzip -cd lzip[version].tar.gz | tar -xf - + +This creates the directory ./lzip[version] containing the source from +the main archive. + +2. Change to lzip directory and run configure. + (Try `configure --help' for usage instructions). + + cd lzip[version] + ./configure + +3. Run make. + + make + +4. Optionally, type `make check' to run the tests that come with lzip. + +5. Type `make install' to install the programs and any data files and + documentation. + + +Another way +----------- +You can also compile lzip into a separate directory. To do this, you +must use a version of `make' that supports the `VPATH' variable, such +as GNU `make'. `cd' to the directory where you want the object files +and executables to go and run the `configure' script. `configure' +automatically checks for the source code in `.', in `..' and in the +directory that `configure' is in. + +`configure' recognizes the option `--srcdir=DIR' to control where to +look for the sources. Usually `configure' can determine that directory +automatically. + +After running `configure', you can run `make' and `make install' as +explained above. + + +Copyright (C) 2008, 2009, 2010, 2011 Antonio Diaz Diaz. + +This file is free documentation: you have unlimited permission to copy, +distribute and modify it. diff --git a/third_party/lzma.js/lzip/Makefile b/third_party/lzma.js/lzip/Makefile new file mode 100644 index 00000000..ca6a6ef7 --- /dev/null +++ b/third_party/lzma.js/lzip/Makefile @@ -0,0 +1,158 @@ +# Makefile for Lzip - Data compressor based on the LZMA algorithm +# Copyright (C) 2008, 2009, 2010, 2011 Antonio Diaz Diaz. +# This file was generated automatically by configure. Do not edit. +# +# This Makefile is free software: you have unlimited permission +# to copy, distribute and modify it. + +pkgname = lzip +pkgversion = 1.12 +progname = lzip +VPATH = . +prefix = /usr/local +exec_prefix = $(prefix) +bindir = $(exec_prefix)/bin +datadir = $(prefix)/share +infodir = $(datadir)/info +mandir = $(datadir)/man +sysconfdir = $(prefix)/etc +CPPFLAGS = -DDECODER_ONLY=$(DECODER_ONLY) +CXXFLAGS = -Wall -W -O2 +LDFLAGS = + +DISTNAME = $(pkgname)-$(pkgversion) +INSTALL = install +INSTALL_PROGRAM = $(INSTALL) -p -m 755 +INSTALL_DATA = $(INSTALL) -p -m 644 +INSTALL_DIR = $(INSTALL) -d -m 755 +SHELL = /bin/sh + +objs = decoder.o encoder.o fast_encoder.o main.o +recobjs = decoder.o lziprecover.o +unzobjs = unzcrash.o + + +.PHONY : all install install-info install-man install-strip \ + uninstall uninstall-info uninstall-man \ + doc info man check dist clean distclean + +all : $(progname) + +$(progname) : $(objs) + $(CXX) $(LDFLAGS) -o $@ $(objs) + +$(progname)_profiled : $(objs) + $(CXX) $(LDFLAGS) -pg -o $@ $(objs) + +lziprecover : $(recobjs) + $(CXX) $(LDFLAGS) -o $@ $(recobjs) + +unzcrash : $(unzobjs) + $(CXX) $(LDFLAGS) -o $@ $(unzobjs) + +main.o : main.cc + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROGVERSION=\"$(pkgversion)\" -c -o $@ $< + +lziprecover.o : lziprecover.cc + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROGVERSION=\"$(pkgversion)\" -c -o $@ $< + +unzcrash.o : testsuite/unzcrash.cc + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROGVERSION=\"$(pkgversion)\" -c -o $@ $< + +%.o : %.cc + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< + +$(objs) : Makefile +decoder.o : lzip.h decoder.h +encoder.o : lzip.h encoder.h +fast_encoder.o : lzip.h encoder.h fast_encoder.h +main.o : lzip.h decoder.h encoder.h fast_encoder.h +lziprecover.o : lzip.h decoder.h Makefile +unzcrash.o : Makefile + + +doc : info man + +info : $(VPATH)/doc/$(pkgname).info + +$(VPATH)/doc/$(pkgname).info : $(VPATH)/doc/$(pkgname).texinfo + cd $(VPATH)/doc && makeinfo $(pkgname).texinfo + +man : $(VPATH)/doc/$(progname).1 $(VPATH)/doc/lziprecover.1 + +$(VPATH)/doc/$(progname).1 : $(progname) + help2man -n 'reduces the size of files' \ + -o $@ ./$(progname) + +$(VPATH)/doc/lziprecover.1 : lziprecover + help2man -n 'recovers data from damaged lzip files' \ + -o $@ --no-info ./lziprecover + +Makefile : $(VPATH)/configure $(VPATH)/Makefile.in + ./config.status + +check : all + @$(VPATH)/testsuite/check.sh $(VPATH)/testsuite $(pkgversion) + +install : all install-info install-man + if [ ! -d "$(DESTDIR)$(bindir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(bindir)" ; fi + $(INSTALL_PROGRAM) ./$(progname) "$(DESTDIR)$(bindir)/$(progname)" + $(INSTALL_PROGRAM) ./lziprecover "$(DESTDIR)$(bindir)/lziprecover" + +install-info : + if [ ! -d "$(DESTDIR)$(infodir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(infodir)" ; fi + $(INSTALL_DATA) $(VPATH)/doc/$(pkgname).info "$(DESTDIR)$(infodir)/$(pkgname).info" + -install-info --info-dir="$(DESTDIR)$(infodir)" $(DESTDIR)$(infodir)/$(pkgname).info + +install-man : + if [ ! -d "$(DESTDIR)$(mandir)/man1" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1" ; fi + $(INSTALL_DATA) $(VPATH)/doc/$(progname).1 "$(DESTDIR)$(mandir)/man1/$(progname).1" + $(INSTALL_DATA) $(VPATH)/doc/lziprecover.1 "$(DESTDIR)$(mandir)/man1/lziprecover.1" + +install-strip : all + $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install + +uninstall : uninstall-info uninstall-man + -rm -f "$(DESTDIR)$(bindir)/$(progname)" + -rm -f "$(DESTDIR)$(bindir)/lziprecover" + +uninstall-info : + -install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$(pkgname).info" + -rm -f "$(DESTDIR)$(infodir)/$(pkgname).info" + +uninstall-man : + -rm -f "$(DESTDIR)$(mandir)/man1/$(progname).1" + -rm -f "$(DESTDIR)$(mandir)/man1/lziprecover.1" + +dist : doc + ln -sf $(VPATH) $(DISTNAME) + tar -cvf $(DISTNAME).tar \ + $(DISTNAME)/AUTHORS \ + $(DISTNAME)/COPYING \ + $(DISTNAME)/ChangeLog \ + $(DISTNAME)/INSTALL \ + $(DISTNAME)/Makefile.in \ + $(DISTNAME)/NEWS \ + $(DISTNAME)/README \ + $(DISTNAME)/configure \ + $(DISTNAME)/doc/$(progname).1 \ + $(DISTNAME)/doc/lziprecover.1 \ + $(DISTNAME)/doc/$(pkgname).info \ + $(DISTNAME)/doc/$(pkgname).texinfo \ + $(DISTNAME)/testsuite/check.sh \ + $(DISTNAME)/testsuite/test.txt \ + $(DISTNAME)/testsuite/test_bad[1-5].lz \ + $(DISTNAME)/testsuite/test_sync.lz \ + $(DISTNAME)/testsuite/test_v[01].lz \ + $(DISTNAME)/testsuite/unzcrash.cc \ + $(DISTNAME)/*.h \ + $(DISTNAME)/*.cc + rm -f $(DISTNAME) + lzip -v -9 $(DISTNAME).tar + +clean : + -rm -f $(progname) $(progname)_profiled $(objs) + -rm -f lziprecover lziprecover.o unzcrash unzcrash.o + +distclean : clean + -rm -f Makefile config.status *.tar *.tar.lz diff --git a/third_party/lzma.js/lzip/Makefile.in b/third_party/lzma.js/lzip/Makefile.in new file mode 100644 index 00000000..30aba743 --- /dev/null +++ b/third_party/lzma.js/lzip/Makefile.in @@ -0,0 +1,138 @@ + +DISTNAME = $(pkgname)-$(pkgversion) +INSTALL = install +INSTALL_PROGRAM = $(INSTALL) -p -m 755 +INSTALL_DATA = $(INSTALL) -p -m 644 +INSTALL_DIR = $(INSTALL) -d -m 755 +SHELL = /bin/sh + +objs = arg_parser.o decoder.o encoder.o fast_encoder.o main.o +recobjs = arg_parser.o decoder.o lziprecover.o +unzobjs = arg_parser.o unzcrash.o + + +.PHONY : all install install-info install-man install-strip \ + uninstall uninstall-info uninstall-man \ + doc info man check dist clean distclean + +all : $(progname) lziprecover + +$(progname) : $(objs) + $(CXX) $(LDFLAGS) -o $@ $(objs) + +$(progname)_profiled : $(objs) + $(CXX) $(LDFLAGS) -pg -o $@ $(objs) + +lziprecover : $(recobjs) + $(CXX) $(LDFLAGS) -o $@ $(recobjs) + +unzcrash : $(unzobjs) + $(CXX) $(LDFLAGS) -o $@ $(unzobjs) + +main.o : main.cc + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROGVERSION=\"$(pkgversion)\" -c -o $@ $< + +lziprecover.o : lziprecover.cc + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROGVERSION=\"$(pkgversion)\" -c -o $@ $< + +unzcrash.o : testsuite/unzcrash.cc + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROGVERSION=\"$(pkgversion)\" -c -o $@ $< + +%.o : %.cc + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< + +$(objs) : Makefile +arg_parser.o : arg_parser.h +decoder.o : lzip.h decoder.h +encoder.o : lzip.h encoder.h +fast_encoder.o : lzip.h encoder.h fast_encoder.h +main.o : arg_parser.h lzip.h decoder.h encoder.h fast_encoder.h +lziprecover.o : arg_parser.h lzip.h decoder.h Makefile +unzcrash.o : arg_parser.h Makefile + + +doc : info man + +info : $(VPATH)/doc/$(pkgname).info + +$(VPATH)/doc/$(pkgname).info : $(VPATH)/doc/$(pkgname).texinfo + cd $(VPATH)/doc && makeinfo $(pkgname).texinfo + +man : $(VPATH)/doc/$(progname).1 $(VPATH)/doc/lziprecover.1 + +$(VPATH)/doc/$(progname).1 : $(progname) + help2man -n 'reduces the size of files' \ + -o $@ ./$(progname) + +$(VPATH)/doc/lziprecover.1 : lziprecover + help2man -n 'recovers data from damaged lzip files' \ + -o $@ --no-info ./lziprecover + +Makefile : $(VPATH)/configure $(VPATH)/Makefile.in + ./config.status + +check : all + @$(VPATH)/testsuite/check.sh $(VPATH)/testsuite $(pkgversion) + +install : all install-info install-man + if [ ! -d "$(DESTDIR)$(bindir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(bindir)" ; fi + $(INSTALL_PROGRAM) ./$(progname) "$(DESTDIR)$(bindir)/$(progname)" + $(INSTALL_PROGRAM) ./lziprecover "$(DESTDIR)$(bindir)/lziprecover" + +install-info : + if [ ! -d "$(DESTDIR)$(infodir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(infodir)" ; fi + $(INSTALL_DATA) $(VPATH)/doc/$(pkgname).info "$(DESTDIR)$(infodir)/$(pkgname).info" + -install-info --info-dir="$(DESTDIR)$(infodir)" $(DESTDIR)$(infodir)/$(pkgname).info + +install-man : + if [ ! -d "$(DESTDIR)$(mandir)/man1" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1" ; fi + $(INSTALL_DATA) $(VPATH)/doc/$(progname).1 "$(DESTDIR)$(mandir)/man1/$(progname).1" + $(INSTALL_DATA) $(VPATH)/doc/lziprecover.1 "$(DESTDIR)$(mandir)/man1/lziprecover.1" + +install-strip : all + $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install + +uninstall : uninstall-info uninstall-man + -rm -f "$(DESTDIR)$(bindir)/$(progname)" + -rm -f "$(DESTDIR)$(bindir)/lziprecover" + +uninstall-info : + -install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$(pkgname).info" + -rm -f "$(DESTDIR)$(infodir)/$(pkgname).info" + +uninstall-man : + -rm -f "$(DESTDIR)$(mandir)/man1/$(progname).1" + -rm -f "$(DESTDIR)$(mandir)/man1/lziprecover.1" + +dist : doc + ln -sf $(VPATH) $(DISTNAME) + tar -cvf $(DISTNAME).tar \ + $(DISTNAME)/AUTHORS \ + $(DISTNAME)/COPYING \ + $(DISTNAME)/ChangeLog \ + $(DISTNAME)/INSTALL \ + $(DISTNAME)/Makefile.in \ + $(DISTNAME)/NEWS \ + $(DISTNAME)/README \ + $(DISTNAME)/configure \ + $(DISTNAME)/doc/$(progname).1 \ + $(DISTNAME)/doc/lziprecover.1 \ + $(DISTNAME)/doc/$(pkgname).info \ + $(DISTNAME)/doc/$(pkgname).texinfo \ + $(DISTNAME)/testsuite/check.sh \ + $(DISTNAME)/testsuite/test.txt \ + $(DISTNAME)/testsuite/test_bad[1-5].lz \ + $(DISTNAME)/testsuite/test_sync.lz \ + $(DISTNAME)/testsuite/test_v[01].lz \ + $(DISTNAME)/testsuite/unzcrash.cc \ + $(DISTNAME)/*.h \ + $(DISTNAME)/*.cc + rm -f $(DISTNAME) + lzip -v -9 $(DISTNAME).tar + +clean : + -rm -f $(progname) $(progname)_profiled $(objs) + -rm -f lziprecover lziprecover.o unzcrash unzcrash.o + +distclean : clean + -rm -f Makefile config.status *.tar *.tar.lz diff --git a/third_party/lzma.js/lzip/NEWS b/third_party/lzma.js/lzip/NEWS new file mode 100644 index 00000000..affec93b --- /dev/null +++ b/third_party/lzma.js/lzip/NEWS @@ -0,0 +1,22 @@ +Changes in version 1.12: + +The option "-F, --recompress", which forces recompression of files whose +name already has the ".lz" or ".tlz" suffix, has been added. + +For large values of "--match-length", compression ratio has been +slightly increased and compression time has been reduced by up to 6%. + +Compression time of option "-0" has been reduced by 2%. + +Print only one status line for each multimember file when only one "-v" +is specified. + +Print up to 6 bytes of trailing garbage when "-vvvv" is specified. + +Do not show the message "and `--stdout' was not specified" for file +types that can't be read (directories, etc). + +If "--verbose" is not specified, lziprecover now only shows errors and +warnings. + +Options "--bits", "--position" and "--size" has been added to unzcrash. diff --git a/third_party/lzma.js/lzip/README b/third_party/lzma.js/lzip/README new file mode 100644 index 00000000..d075ab38 --- /dev/null +++ b/third_party/lzma.js/lzip/README @@ -0,0 +1,77 @@ +Description + +Lzip is a lossless data compressor based on the LZMA algorithm, with +very safe integrity checking and a user interface similar to the one of +gzip or bzip2. Lzip decompresses almost as fast as gzip and compresses +better than bzip2, which makes it well suited for software distribution +and data archiving. + +Lziprecover is a data recovery tool for lzip compressed files able to +repair slightly damaged files, recover badly damaged files from two or +more copies, and extract undamaged members from multi-member files. If +the cause of file corruption is damaged media, the combination GNU +ddrescue + lziprecover is the best option for recovering data from +multiple damaged copies. + +Lzip replaces every file given in the command line with a compressed +version of itself, with the name "original_name.lz". Each compressed +file has the same modification date, permissions, and, when possible, +ownership as the corresponding original, so that these properties can be +correctly restored at decompression time. Lzip is able to read from some +types of non regular files if the "--stdout" option is specified. + +If no file names are specified, lzip compresses (or decompresses) from +standard input to standard output. In this case, lzip will decline to +write compressed output to a terminal, as this would be entirely +incomprehensible and therefore pointless. + +Lzip will correctly decompress a file which is the concatenation of two +or more compressed files. The result is the concatenation of the +corresponding uncompressed files. Integrity testing of concatenated +compressed files is also supported. + +Lzip can produce multimember files and safely recover, with lziprecover, +the undamaged members in case of file damage. Lzip can also split the +compressed output in volumes of a given size, even when reading from +standard input. This allows the direct creation of multivolume +compressed tar archives. + +Lzip will automatically use the smallest possible dictionary size +without exceeding the given limit. Keep in mind that the decompression +memory requirement is affected at compression time by the choice of +dictionary size limit. + +As a self-check for your protection, lzip stores in the member trailer +the 32-bit CRC of the original data and the size of the original data, +to make sure that the decompressed version of the data is identical to +the original. This guards against corruption of the compressed data, and +against undetected bugs in lzip (hopefully very unlikely). The chances +of data corruption going undetected are microscopic, less than one +chance in 4000 million for each member processed. Be aware, though, that +the check occurs upon decompression, so it can only tell you that +something is wrong. It can't help you recover the original uncompressed +data. + +Lzip implements a simplified version of the LZMA (Lempel-Ziv-Markov +chain-Algorithm) algorithm. The high compression of LZMA comes from +combining two basic, well-proven compression ideas: sliding dictionaries +(LZ77/78) and markov models (the thing used by every compression +algorithm that uses a range encoder or similar order-0 entropy coder as +its last stage) with segregation of contexts according to what the bits +are used for. + +The ideas embodied in lzip are due to (at least) the following people: +Abraham Lempel and Jacob Ziv (for the LZ algorithm), Andrey Markov (for +the definition of Markov chains), G.N.N. Martin (for the definition of +range encoding), Igor Pavlov (for putting all the above together in +LZMA), and Julian Seward (for bzip2's CLI and the idea of unzcrash). + + +Copyright (C) 2008, 2009, 2010, 2011 Antonio Diaz Diaz. + +This file is free documentation: you have unlimited permission to copy, +distribute and modify it. + +The file Makefile.in is a data file used by configure to produce the +Makefile. It has the same copyright owner and permissions that configure +itself. diff --git a/third_party/lzma.js/lzip/config.status b/third_party/lzma.js/lzip/config.status new file mode 100755 index 00000000..610b2a05 --- /dev/null +++ b/third_party/lzma.js/lzip/config.status @@ -0,0 +1,8 @@ +#! /bin/sh +# This file was generated automatically by configure. Do not edit. +# Run this file to recreate the current configuration. +# +# This script is free software: you have unlimited permission +# to copy, distribute and modify it. + +exec /bin/sh ./configure --no-create diff --git a/third_party/lzma.js/lzip/configure b/third_party/lzma.js/lzip/configure new file mode 100755 index 00000000..8b291a6f --- /dev/null +++ b/third_party/lzma.js/lzip/configure @@ -0,0 +1,192 @@ +#! /bin/sh +# configure script for Lzip - Data compressor based on the LZMA algorithm +# Copyright (C) 2008, 2009, 2010, 2011 Antonio Diaz Diaz. +# +# This configure script is free software: you have unlimited permission +# to copy, distribute and modify it. + +args= +no_create= +pkgname=lzip +pkgversion=1.12 +progname=lzip +srctrigger=lzip.h + +# clear some things potentially inherited from environment. +LC_ALL=C +export LC_ALL +srcdir= +prefix=/usr/local +exec_prefix='$(prefix)' +bindir='$(exec_prefix)/bin' +datadir='$(prefix)/share' +infodir='$(datadir)/info' +mandir='$(datadir)/man' +sysconfdir='$(prefix)/etc' +CXX= +CPPFLAGS= +CXXFLAGS='-Wall -W -O2' +LDFLAGS= + +# Loop over all args +while [ -n "$1" ] ; do + + # Get the first arg, and shuffle + option=$1 + shift + + # Add the argument quoted to args + args="${args} \"${option}\"" + + # Split out the argument for options that take them + case ${option} in + *=*) optarg=`echo ${option} | sed -e 's,^[^=]*=,,'` ;; + esac + + # Process the options + case ${option} in + --help | --he* | -h) + echo "Usage: configure [options]" + echo + echo "Options: [defaults in brackets]" + echo " -h, --help display this help and exit" + echo " -V, --version output version information and exit" + echo " --srcdir=DIR find the sources in DIR [. or ..]" + echo " --prefix=DIR install into DIR [${prefix}]" + echo " --exec-prefix=DIR base directory for arch-dependent files [${exec_prefix}]" + echo " --bindir=DIR user executables directory [${bindir}]" + echo " --datadir=DIR base directory for doc and data [${datadir}]" + echo " --infodir=DIR info files directory [${infodir}]" + echo " --mandir=DIR man pages directory [${mandir}]" + echo " --sysconfdir=DIR read-only single-machine data directory [${sysconfdir}]" + echo " CXX=COMPILER C++ compiler to use [g++]" + echo " CPPFLAGS=OPTIONS command line options for the preprocessor [${CPPFLAGS}]" + echo " CXXFLAGS=OPTIONS command line options for the C++ compiler [${CXXFLAGS}]" + echo " LDFLAGS=OPTIONS command line options for the linker [${LDFLAGS}]" + echo + exit 0 ;; + --version | --ve* | -V) + echo "Configure script for ${pkgname} version ${pkgversion}" + exit 0 ;; + --srcdir* | --sr*) + srcdir=`echo ${optarg} | sed -e 's,/$,,'` ;; + --prefix* | --pr*) + prefix=`echo ${optarg} | sed -e 's,/$,,'` ;; + --exec-prefix* | --ex*) + exec_prefix=`echo ${optarg} | sed -e 's,/$,,'` ;; + --bindir* | --bi*) + bindir=`echo ${optarg} | sed -e 's,/$,,'` ;; + --datadir* | --da*) + datadir=`echo ${optarg} | sed -e 's,/$,,'` ;; + --infodir* | --inf*) + infodir=`echo ${optarg} | sed -e 's,/$,,'` ;; + --mandir* | --ma*) + mandir=`echo ${optarg} | sed -e 's,/$,,'` ;; + --sysconfdir* | --sy*) + sysconfdir=`echo ${optarg} | sed -e 's,/$,,'` ;; + --no-create | --no-c*) + no_create=yes ;; + + CXX=*) CXX=${optarg} ;; + CPPFLAGS=*) CPPFLAGS=${optarg} ;; + CXXFLAGS=*) CXXFLAGS=${optarg} ;; + LDFLAGS=*) LDFLAGS=${optarg} ;; + + --* | *=* | *-*-*) ;; + *) + echo "configure: Unrecognized option: \"${option}\"; use --help for usage." 1>&2 + exit 1 ;; + esac +done + +# Find the source files, if location was not specified. +srcdirtext= +if [ -z "${srcdir}" ] ; then + srcdirtext="or . or .." ; srcdir=. + if [ ! -r ${srcdir}/${srctrigger} ] ; then srcdir=.. ; fi + if [ ! -r ${srcdir}/${srctrigger} ] ; then + ## the sed command below emulates the dirname command + srcdir=`echo $0 | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + fi +fi + +if [ ! -r ${srcdir}/${srctrigger} ] ; then + exec 1>&2 + echo + echo "configure: Can't find sources in ${srcdir} ${srcdirtext}" + echo "configure: (At least ${srctrigger} is missing)." + exit 1 +fi + +# Set srcdir to . if that's what it is. +if [ "`pwd`" = "`cd ${srcdir} ; pwd`" ] ; then srcdir=. ; fi + +# checking whether we are using GNU C++. +if [ -z "${CXX}" ] ; then # Let the user override the test. + if [ -x /bin/g++ ] || + [ -x /usr/bin/g++ ] || + [ -x /usr/local/bin/g++ ] ; then + CXX="g++" + else + CXX="c++" + fi +fi + +echo +if [ -z "${no_create}" ] ; then + echo "creating config.status" + rm -f config.status + cat > config.status << EOF +#! /bin/sh +# This file was generated automatically by configure. Do not edit. +# Run this file to recreate the current configuration. +# +# This script is free software: you have unlimited permission +# to copy, distribute and modify it. + +exec /bin/sh $0 ${args} --no-create +EOF + chmod +x config.status +fi + +echo "creating Makefile" +echo "VPATH = ${srcdir}" +echo "prefix = ${prefix}" +echo "exec_prefix = ${exec_prefix}" +echo "bindir = ${bindir}" +echo "datadir = ${datadir}" +echo "infodir = ${infodir}" +echo "mandir = ${mandir}" +echo "sysconfdir = ${sysconfdir}" +echo "CXX = ${CXX}" +echo "CPPFLAGS = ${CPPFLAGS}" +echo "CXXFLAGS = ${CXXFLAGS}" +echo "LDFLAGS = ${LDFLAGS}" +rm -f Makefile +cat > Makefile << EOF +# Makefile for Lzip - Data compressor based on the LZMA algorithm +# Copyright (C) 2008, 2009, 2010, 2011 Antonio Diaz Diaz. +# This file was generated automatically by configure. Do not edit. +# +# This Makefile is free software: you have unlimited permission +# to copy, distribute and modify it. + +pkgname = ${pkgname} +pkgversion = ${pkgversion} +progname = ${progname} +VPATH = ${srcdir} +prefix = ${prefix} +exec_prefix = ${exec_prefix} +bindir = ${bindir} +datadir = ${datadir} +infodir = ${infodir} +mandir = ${mandir} +sysconfdir = ${sysconfdir} +CXX = ${CXX} +CPPFLAGS = ${CPPFLAGS} +CXXFLAGS = ${CXXFLAGS} +LDFLAGS = ${LDFLAGS} +EOF +cat ${srcdir}/Makefile.in >> Makefile + +echo "OK. Now you can run make." diff --git a/third_party/lzma.js/lzip/decoder.cc b/third_party/lzma.js/lzip/decoder.cc new file mode 100644 index 00000000..e0860c05 --- /dev/null +++ b/third_party/lzma.js/lzip/decoder.cc @@ -0,0 +1,252 @@ +/* Lzip - Data compressor based on the LZMA algorithm + Copyright (C) 2008, 2009, 2010, 2011 Antonio Diaz Diaz. + + 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 <http://www.gnu.org/licenses/>. +*/ + +#define _FILE_OFFSET_BITS 64 + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <unistd.h> + +#include "lzip.h" +#include "decoder.h" + + +const CRC32 crc32; + + +// Returns the number of bytes really read. +// If (returned value < size) and (errno == 0), means EOF was reached. +// +int readblock( const int fd, uint8_t * const buf, const int size ) + { + int rest = size; + errno = 0; + while( rest > 0 ) + { + errno = 0; + const int n = read( fd, buf + size - rest, rest ); + if( n > 0 ) rest -= n; + else if( n == 0 ) break; + else if( errno != EINTR && errno != EAGAIN ) break; + } + return ( rest > 0 ) ? size - rest : size; + } + + +// Returns the number of bytes really written. +// If (returned value < size), it is always an error. +// +int writeblock( const int fd, const uint8_t * const buf, const int size ) + { + int rest = size; + errno = 0; + while( rest > 0 ) + { + errno = 0; + const int n = write( fd, buf + size - rest, rest ); + if( n > 0 ) rest -= n; + else if( errno && errno != EINTR && errno != EAGAIN ) break; + } + return ( rest > 0 ) ? size - rest : size; + } + + +bool Range_decoder::read_block() + { + if( !at_stream_end ) + { + stream_pos = readblock( infd, buffer, buffer_size ); + if( stream_pos != buffer_size && errno ) exit(-1); + at_stream_end = ( stream_pos < buffer_size ); + partial_member_pos += pos; + pos = 0; + } + return pos < stream_pos; + } + + +void LZ_decoder::flush_data() + { + const int size = pos - stream_pos; + if( size > 0 ) + { + crc32.update( crc_, buffer + stream_pos, size ); + if( outfd >= 0 && + writeblock( outfd, buffer + stream_pos, size ) != size ) + exit(-1); + if( pos >= buffer_size ) { partial_data_pos += pos; pos = 0; } + stream_pos = pos; + } + } + + +bool LZ_decoder::verify_trailer() const + { + File_trailer trailer; + const int trailer_size = File_trailer::size( member_version ); + const long long member_size = range_decoder.member_position() + trailer_size; + bool error = false; + + for( int i = 0; i < trailer_size && !error; ++i ) + { + if( !range_decoder.finished() ) + trailer.data[i] = range_decoder.get_byte(); + else + { + error = true; + for( ; i < trailer_size; ++i ) trailer.data[i] = 0; + } + } + if( member_version == 0 ) trailer.member_size( member_size ); + if( !range_decoder.code_is_zero() ) + { + error = true; + pp( "Range decoder final code is not zero" ); + } + if( trailer.data_crc() != crc() ) + { + error = true; + } + if( trailer.data_size() != data_position() ) + { + error = true; + } + if( trailer.member_size() != member_size ) + { + error = true; + } + return !error; + } + + +// Return value: 0 = OK, 1 = decoder error, 2 = unexpected EOF, +// 3 = trailer error, 4 = unknown marker found. +int LZ_decoder::decode_member() + { + Bit_model bm_match[State::states][pos_states]; + Bit_model bm_rep[State::states]; + Bit_model bm_rep0[State::states]; + Bit_model bm_rep1[State::states]; + Bit_model bm_rep2[State::states]; + Bit_model bm_len[State::states][pos_states]; + Bit_model bm_dis_slot[max_dis_states][1<<dis_slot_bits]; + Bit_model bm_dis[modeled_distances-end_dis_model+1]; + Bit_model bm_align[dis_align_size]; + + unsigned int rep0 = 0; // rep[0-3] latest four distances + unsigned int rep1 = 0; // used for efficient coding of + unsigned int rep2 = 0; // repeated distances + unsigned int rep3 = 0; + + Len_decoder len_decoder; + Len_decoder rep_match_len_decoder; + Literal_decoder literal_decoder; + State state; + range_decoder.load(); + + while( true ) + { + if( range_decoder.finished() ) { flush_data(); return 2; } + const int pos_state = data_position() & pos_state_mask; + if( range_decoder.decode_bit( bm_match[state()][pos_state] ) == 0 ) + { + const uint8_t prev_byte = get_prev_byte(); + if( state.is_char() ) + put_byte( literal_decoder.decode( range_decoder, prev_byte ) ); + else + put_byte( literal_decoder.decode_matched( range_decoder, prev_byte, + get_byte( rep0 ) ) ); + state.set_char(); + } + else + { + int len; + if( range_decoder.decode_bit( bm_rep[state()] ) == 1 ) + { + len = 0; + if( range_decoder.decode_bit( bm_rep0[state()] ) == 1 ) + { + unsigned int distance; + if( range_decoder.decode_bit( bm_rep1[state()] ) == 0 ) + distance = rep1; + else + { + if( range_decoder.decode_bit( bm_rep2[state()] ) == 0 ) + distance = rep2; + else { distance = rep3; rep3 = rep2; } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + else + { + if( range_decoder.decode_bit( bm_len[state()][pos_state] ) == 0 ) + { state.set_short_rep(); len = 1; } + } + if( len == 0 ) + { + state.set_rep(); + len = min_match_len + rep_match_len_decoder.decode( range_decoder, pos_state ); + } + } + else + { + const unsigned int rep0_saved = rep0; + len = min_match_len + len_decoder.decode( range_decoder, pos_state ); + const int dis_slot = range_decoder.decode_tree( bm_dis_slot[get_dis_state(len)], dis_slot_bits ); + if( dis_slot < start_dis_model ) rep0 = dis_slot; + else + { + const int direct_bits = ( dis_slot >> 1 ) - 1; + rep0 = ( 2 | ( dis_slot & 1 ) ) << direct_bits; + if( dis_slot < end_dis_model ) + rep0 += range_decoder.decode_tree_reversed( bm_dis + rep0 - dis_slot, direct_bits ); + else + { + rep0 += range_decoder.decode( direct_bits - dis_align_bits ) << dis_align_bits; + rep0 += range_decoder.decode_tree_reversed( bm_align, dis_align_bits ); + if( rep0 == 0xFFFFFFFFU ) // Marker found + { + rep0 = rep0_saved; + range_decoder.normalize(); + flush_data(); + if( len == min_match_len ) // End Of Stream marker + { + if( verify_trailer() ) return 0; else return 3; + } + if( len == min_match_len + 1 ) // Sync Flush marker + { + range_decoder.load(); continue; + } + return 4; + } + } + } + rep3 = rep2; rep2 = rep1; rep1 = rep0_saved; + state.set_match(); + if( rep0 >= (unsigned int)dictionary_size || + ( rep0 >= (unsigned int)pos && !partial_data_pos ) ) + { flush_data(); return 1; } + } + copy_block( rep0, len ); + } + } + } diff --git a/third_party/lzma.js/lzip/decoder.h b/third_party/lzma.js/lzip/decoder.h new file mode 100644 index 00000000..25e279eb --- /dev/null +++ b/third_party/lzma.js/lzip/decoder.h @@ -0,0 +1,268 @@ +/* Lzip - Data compressor based on the LZMA algorithm + Copyright (C) 2008, 2009, 2010, 2011 Antonio Diaz Diaz. + + 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 <http://www.gnu.org/licenses/>. +*/ + +class Range_decoder + { + enum { buffer_size = 16384 }; + long long partial_member_pos; + uint8_t * const buffer; // input buffer + int pos; // current pos in buffer + int stream_pos; // when reached, a new block must be read + uint32_t code; + uint32_t range; + const int infd; // input file descriptor + bool at_stream_end; + + bool read_block(); + +public: + Range_decoder( const int ifd ) + : + partial_member_pos( 0 ), + buffer( new uint8_t[buffer_size] ), + pos( 0 ), + stream_pos( 0 ), + code( 0 ), + range( 0xFFFFFFFFU ), + infd( ifd ), + at_stream_end( false ) {} + + ~Range_decoder() { delete[] buffer; } + + bool code_is_zero() const { return ( code == 0 ); } + bool finished() { return pos >= stream_pos && !read_block(); } + long long member_position() const + { return partial_member_pos + pos; } + void reset_member_position() + { partial_member_pos = -pos; } + + uint8_t get_byte() + { + if( finished() ) return 0x55; // make code != 0 + return buffer[pos++]; + } + + void load() + { + code = 0; + range = 0xFFFFFFFFU; + for( int i = 0; i < 5; ++i ) code = (code << 8) | get_byte(); + } + + void normalize() + { + if( range <= 0x00FFFFFFU ) + { range <<= 8; code = (code << 8) | get_byte(); } + } + + int decode( const int num_bits ) + { + int symbol = 0; + for( int i = num_bits; i > 0; --i ) + { + symbol <<= 1; + if( range <= 0x00FFFFFFU ) + { + range <<= 7; code = (code << 8) | get_byte(); + if( code >= range ) { code -= range; symbol |= 1; } + } + else + { + range >>= 1; + if( code >= range ) { code -= range; symbol |= 1; } + } + } + return symbol; + } + + int decode_bit( Bit_model & bm ) + { + normalize(); + const uint32_t bound = ( range >> bit_model_total_bits ) * bm.probability; + if( code < bound ) + { + range = bound; + bm.probability += (bit_model_total - bm.probability) >> bit_model_move_bits; + return 0; + } + else + { + range -= bound; + code -= bound; + bm.probability -= bm.probability >> bit_model_move_bits; + return 1; + } + } + + int decode_tree( Bit_model bm[], const int num_bits ) + { + int model = 1; + for( int i = num_bits; i > 0; --i ) + model = ( model << 1 ) | decode_bit( bm[model] ); + return model - (1 << num_bits); + } + + int decode_tree_reversed( Bit_model bm[], const int num_bits ) + { + int model = 1; + int symbol = 0; + for( int i = 0; i < num_bits; ++i ) + { + const int bit = decode_bit( bm[model] ); + model <<= 1; + if( bit ) { model |= 1; symbol |= (1 << i); } + } + return symbol; + } + + int decode_matched( Bit_model bm[], const int match_byte ) + { + Bit_model * const bm1 = bm + 0x100; + int symbol = 1; + for( int i = 7; i >= 0; --i ) + { + const int match_bit = ( match_byte >> i ) & 1; + const int bit = decode_bit( bm1[(match_bit<<8)+symbol] ); + symbol = ( symbol << 1 ) | bit; + if( match_bit != bit ) + { + while( --i >= 0 ) + symbol = ( symbol << 1 ) | decode_bit( bm[symbol] ); + break; + } + } + return symbol & 0xFF; + } + }; + + +class Len_decoder + { + Bit_model choice1; + Bit_model choice2; + Bit_model bm_low[pos_states][len_low_symbols]; + Bit_model bm_mid[pos_states][len_mid_symbols]; + Bit_model bm_high[len_high_symbols]; + +public: + int decode( Range_decoder & range_decoder, const int pos_state ) + { + if( range_decoder.decode_bit( choice1 ) == 0 ) + return range_decoder.decode_tree( bm_low[pos_state], len_low_bits ); + if( range_decoder.decode_bit( choice2 ) == 0 ) + return len_low_symbols + + range_decoder.decode_tree( bm_mid[pos_state], len_mid_bits ); + return len_low_symbols + len_mid_symbols + + range_decoder.decode_tree( bm_high, len_high_bits ); + } + }; + + +class Literal_decoder + { + Bit_model bm_literal[1<<literal_context_bits][0x300]; + + int lstate( const int prev_byte ) const + { return ( prev_byte >> ( 8 - literal_context_bits ) ); } + +public: + uint8_t decode( Range_decoder & range_decoder, const uint8_t prev_byte ) + { return range_decoder.decode_tree( bm_literal[lstate(prev_byte)], 8 ); } + + uint8_t decode_matched( Range_decoder & range_decoder, + const uint8_t prev_byte, const uint8_t match_byte ) + { return range_decoder.decode_matched( bm_literal[lstate(prev_byte)], + match_byte ); } + }; + + +class LZ_decoder + { + long long partial_data_pos; + const int dictionary_size; + const int buffer_size; + uint8_t * const buffer; // output buffer + int pos; // current pos in buffer + int stream_pos; // first byte not yet written to file + uint32_t crc_; + const int outfd; // output file descriptor + const int member_version; + Range_decoder & range_decoder; + + void flush_data(); + bool verify_trailer() const; + + uint8_t get_prev_byte() const + { + const int i = ( ( pos > 0 ) ? pos : buffer_size ) - 1; + return buffer[i]; + } + + uint8_t get_byte( const int distance ) const + { + int i = pos - distance - 1; + if( i < 0 ) i += buffer_size; + return buffer[i]; + } + + void put_byte( const uint8_t b ) + { + buffer[pos] = b; + if( ++pos >= buffer_size ) flush_data(); + } + + void copy_block( const int distance, int len ) + { + int i = pos - distance - 1; + if( i < 0 ) i += buffer_size; + if( len < buffer_size - max( pos, i ) && len <= abs( pos - i ) ) + { + memcpy( buffer + pos, buffer + i, len ); + pos += len; + } + else for( ; len > 0; --len ) + { + buffer[pos] = buffer[i]; + if( ++pos >= buffer_size ) flush_data(); + if( ++i >= buffer_size ) i = 0; + } + } + +public: + LZ_decoder( const File_header & header, Range_decoder & rdec, const int ofd ) + : + partial_data_pos( 0 ), + dictionary_size( header.dictionary_size() ), + buffer_size( max( 65536, dictionary_size ) ), + buffer( new uint8_t[buffer_size] ), + pos( 0 ), + stream_pos( 0 ), + crc_( 0xFFFFFFFFU ), + outfd( ofd ), + member_version( header.version() ), + range_decoder( rdec ) + { buffer[buffer_size-1] = 0; } // prev_byte of first_byte + + ~LZ_decoder() { delete[] buffer; } + + uint32_t crc() const { return crc_ ^ 0xFFFFFFFFU; } + + long long data_position() const + { return partial_data_pos + pos; } + + int decode_member(); + }; diff --git a/third_party/lzma.js/lzip/encoder.cc b/third_party/lzma.js/lzip/encoder.cc new file mode 100644 index 00000000..f4f0ef30 --- /dev/null +++ b/third_party/lzma.js/lzip/encoder.cc @@ -0,0 +1,643 @@ +#if !DECODER_ONLY + +/* Lzip - Data compressor based on the LZMA algorithm + Copyright (C) 2008, 2009, 2010, 2011 Antonio Diaz Diaz. + + 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 <http://www.gnu.org/licenses/>. +*/ + +#define _FILE_OFFSET_BITS 64 + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#include "lzip.h" +#include "encoder.h" + + +Dis_slots dis_slots; +Prob_prices prob_prices; + + +bool Matchfinder::read_block() + { + if( !at_stream_end && stream_pos < buffer_size ) + { + const int size = buffer_size - stream_pos; + const int rd = readblock( infd, buffer + stream_pos, size ); + stream_pos += rd; + if( rd != size && errno ) throw Error( "Read error" ); + at_stream_end = ( rd < size ); + } + return pos < stream_pos; + } + + +Matchfinder::Matchfinder( const int dict_size, const int len_limit, + const int ifd ) + : + partial_data_pos( 0 ), + prev_positions( new int32_t[num_prev_positions] ), + pos( 0 ), + cyclic_pos( 0 ), + stream_pos( 0 ), + match_len_limit_( len_limit ), + cycles( ( len_limit < max_match_len ) ? 16 + ( len_limit / 2 ) : 256 ), + infd( ifd ), + at_stream_end( false ) + { + const int buffer_size_limit = ( 2 * dict_size ) + before_size + after_size; + buffer_size = max( 65536, dict_size ); + buffer = (uint8_t *)malloc( buffer_size ); + if( !buffer ) exit(-1); + if( read_block() && !at_stream_end && buffer_size < buffer_size_limit ) + { + buffer_size = buffer_size_limit; + buffer = (uint8_t *)realloc( buffer, buffer_size ); + if( !buffer ) exit(-1); + read_block(); + } + if( at_stream_end && stream_pos < dict_size ) + dictionary_size_ = max( (int)min_dictionary_size, stream_pos ); + else dictionary_size_ = dict_size; + pos_limit = buffer_size; + if( !at_stream_end ) pos_limit -= after_size; + prev_pos_tree = new int32_t[2*dictionary_size_]; + for( int i = 0; i < num_prev_positions; ++i ) prev_positions[i] = -1; + } + + +void Matchfinder::reset() + { + const int size = stream_pos - pos; + if( size > 0 ) memmove( buffer, buffer + pos, size ); + partial_data_pos = 0; + stream_pos -= pos; + pos = 0; + cyclic_pos = 0; + for( int i = 0; i < num_prev_positions; ++i ) prev_positions[i] = -1; + read_block(); + } + + +void Matchfinder::move_pos() + { + if( ++cyclic_pos >= dictionary_size_ ) cyclic_pos = 0; + if( ++pos >= pos_limit ) + { + if( pos > stream_pos ) + internal_error( "pos > stream_pos in Matchfinder::move_pos" ); + if( !at_stream_end ) + { + const int offset = pos - dictionary_size_ - before_size; + const int size = stream_pos - offset; + memmove( buffer, buffer + offset, size ); + partial_data_pos += offset; + pos -= offset; + stream_pos -= offset; + for( int i = 0; i < num_prev_positions; ++i ) + if( prev_positions[i] >= 0 ) prev_positions[i] -= offset; + for( int i = 0; i < 2 * dictionary_size_; ++i ) + if( prev_pos_tree[i] >= 0 ) prev_pos_tree[i] -= offset; + read_block(); + } + } + } + + +int Matchfinder::longest_match_len( int * const distances ) throw() + { + int len_limit = match_len_limit_; + if( len_limit > available_bytes() ) + { + len_limit = available_bytes(); + if( len_limit < 4 ) return 0; + } + + int maxlen = min_match_len - 1; + const int min_pos = (pos >= dictionary_size_) ? + (pos - dictionary_size_ + 1) : 0; + const uint8_t * const data = buffer + pos; + const int key2 = num_prev_positions4 + num_prev_positions3 + + ( ( (int)data[0] << 8 ) | data[1] ); + const uint32_t tmp = crc32[data[0]] ^ data[1] ^ ( (uint32_t)data[2] << 8 ); + const int key3 = num_prev_positions4 + + (int)( tmp & ( num_prev_positions3 - 1 ) ); + const int key4 = (int)( ( tmp ^ ( crc32[data[3]] << 5 ) ) & + ( num_prev_positions4 - 1 ) ); + + if( distances ) + { + int np = prev_positions[key2]; + if( np >= min_pos ) + { distances[2] = pos - np - 1; maxlen = 2; } + else distances[2] = 0x7FFFFFFF; + np = prev_positions[key3]; + if( np >= min_pos && buffer[np] == data[0] ) + { distances[3] = pos - np - 1; maxlen = 3; } + else distances[3] = 0x7FFFFFFF; + distances[4] = 0x7FFFFFFF; + } + + prev_positions[key2] = pos; + prev_positions[key3] = pos; + int newpos = prev_positions[key4]; + prev_positions[key4] = pos; + + int32_t * ptr0 = prev_pos_tree + ( cyclic_pos << 1 ); + int32_t * ptr1 = ptr0 + 1; + int len = 0, len0 = 0, len1 = 0; + + for( int count = cycles; ; ) + { + if( newpos < min_pos || --count < 0 ) { *ptr0 = *ptr1 = -1; break; } + const uint8_t * const newdata = buffer + newpos; + while( len < len_limit && newdata[len] == data[len] ) ++len; + + const int delta = pos - newpos; + if( distances ) while( maxlen < len ) distances[++maxlen] = delta - 1; + + int32_t * const newptr = prev_pos_tree + + ( ( cyclic_pos - delta + + ( ( cyclic_pos >= delta ) ? 0 : dictionary_size_ ) ) << 1 ); + + if( len < len_limit ) + { + if( newdata[len] < data[len] ) + { + *ptr0 = newpos; + ptr0 = newptr + 1; + newpos = *ptr0; + len0 = len; if( len1 < len ) len = len1; + } + else + { + *ptr1 = newpos; + ptr1 = newptr; + newpos = *ptr1; + len1 = len; if( len0 < len ) len = len0; + } + } + else + { + *ptr0 = newptr[0]; + *ptr1 = newptr[1]; + break; + } + } + if( distances ) + { + if( distances[3] > distances[4] ) distances[3] = distances[4]; + if( distances[2] > distances[3] ) distances[2] = distances[3]; + } + return maxlen; + } + + +void Range_encoder::flush_data() + { + if( pos > 0 ) + { + if( outfd >= 0 && writeblock( outfd, buffer, pos ) != pos ) + throw Error( "Write error" ); + partial_member_pos += pos; + pos = 0; + } + } + + +void Len_encoder::encode( Range_encoder & range_encoder, int symbol, + const int pos_state ) + { + symbol -= min_match_len; + if( symbol < len_low_symbols ) + { + range_encoder.encode_bit( choice1, 0 ); + range_encoder.encode_tree( bm_low[pos_state], symbol, len_low_bits ); + } + else + { + range_encoder.encode_bit( choice1, 1 ); + if( symbol < len_low_symbols + len_mid_symbols ) + { + range_encoder.encode_bit( choice2, 0 ); + range_encoder.encode_tree( bm_mid[pos_state], symbol - len_low_symbols, len_mid_bits ); + } + else + { + range_encoder.encode_bit( choice2, 1 ); + range_encoder.encode_tree( bm_high, symbol - len_low_symbols - len_mid_symbols, len_high_bits ); + } + } + if( --counters[pos_state] <= 0 ) update_prices( pos_state ); + } + + +void LZ_encoder::fill_align_prices() throw() + { + for( int i = 0; i < dis_align_size; ++i ) + align_prices[i] = price_symbol_reversed( bm_align, i, dis_align_bits ); + align_price_count = dis_align_size; + } + + +void LZ_encoder::fill_distance_prices() throw() + { + for( int dis = start_dis_model; dis < modeled_distances; ++dis ) + { + const int dis_slot = dis_slots.table( dis ); + const int direct_bits = ( dis_slot >> 1 ) - 1; + const int base = ( 2 | ( dis_slot & 1 ) ) << direct_bits; + const int price = + price_symbol_reversed( bm_dis + base - dis_slot, dis - base, direct_bits ); + for( int dis_state = 0; dis_state < max_dis_states; ++dis_state ) + dis_prices[dis_state][dis] = price; + } + + for( int dis_state = 0; dis_state < max_dis_states; ++dis_state ) + { + int * const dsp = dis_slot_prices[dis_state]; + const Bit_model * const bmds = bm_dis_slot[dis_state]; + int slot = 0; + for( ; slot < end_dis_model && slot < num_dis_slots; ++slot ) + dsp[slot] = price_symbol( bmds, slot, dis_slot_bits ); + for( ; slot < num_dis_slots; ++slot ) + dsp[slot] = price_symbol( bmds, slot, dis_slot_bits ) + + (((( slot >> 1 ) - 1 ) - dis_align_bits ) << price_shift ); + + int * const dp = dis_prices[dis_state]; + int dis = 0; + for( ; dis < start_dis_model; ++dis ) + dp[dis] = dsp[dis]; + for( ; dis < modeled_distances; ++dis ) + dp[dis] += dsp[dis_slots.table( dis )]; + } + } + + +// Return value == number of bytes advanced (ahead). +// trials[0]..trials[retval-1] contain the steps to encode. +// ( trials[0].dis == -1 && trials[0].price == 1 ) means literal. +int LZ_encoder::sequence_optimizer( const int reps[num_rep_distances], + const State & state ) + { + int main_len; + if( longest_match_found > 0 ) // from previous call + { + main_len = longest_match_found; + longest_match_found = 0; + } + else main_len = read_match_distances(); + + int replens[num_rep_distances]; + int rep_index = 0; + for( int i = 0; i < num_rep_distances; ++i ) + { + replens[i] = matchfinder.true_match_len( 0, reps[i] + 1, max_match_len ); + if( replens[i] > replens[rep_index] ) rep_index = i; + } + if( replens[rep_index] >= matchfinder.match_len_limit() ) + { + trials[0].dis = rep_index; + trials[0].price = replens[rep_index]; + move_pos( replens[rep_index], true ); + return replens[rep_index]; + } + + if( main_len >= matchfinder.match_len_limit() ) + { + trials[0].dis = match_distances[matchfinder.match_len_limit()] + + num_rep_distances; + trials[0].price = main_len; + move_pos( main_len, true ); + return main_len; + } + + { + const int pos_state = matchfinder.data_position() & pos_state_mask; + const uint8_t prev_byte = matchfinder[-1]; + const uint8_t cur_byte = matchfinder[0]; + const uint8_t match_byte = matchfinder[-reps[0]-1]; + + trials[0].state = state; + for( int i = 0; i < num_rep_distances; ++i ) trials[0].reps[i] = reps[i]; + trials[1].dis = -1; + trials[1].prev_index = 0; + trials[1].price = price0( bm_match[state()][pos_state] ); + if( state.is_char() ) + trials[1].price += literal_encoder.price_symbol( prev_byte, cur_byte ); + else + trials[1].price += literal_encoder.price_matched( prev_byte, cur_byte, match_byte ); + + const int match_price = price1( bm_match[state()][pos_state] ); + const int rep_match_price = match_price + price1( bm_rep[state()] ); + + if( match_byte == cur_byte ) + trials[1].update( 0, 0, rep_match_price + price_rep_len1( state, pos_state ) ); + + if( main_len < min_match_len ) + { + trials[0].dis = trials[1].dis; + trials[0].price = 1; + matchfinder.move_pos(); + return 1; + } + + if( main_len <= replens[rep_index] ) + { + main_len = replens[rep_index]; + for( int len = min_match_len; len <= main_len; ++len ) + trials[len].price = infinite_price; + } + else + { + const int normal_match_price = match_price + price0( bm_rep[state()] ); + for( int len = min_match_len; len <= main_len; ++len ) + { + trials[len].dis = match_distances[len] + num_rep_distances; + trials[len].prev_index = 0; + trials[len].price = normal_match_price + + price_pair( match_distances[len], len, pos_state ); + } + } + + for( int rep = 0; rep < num_rep_distances; ++rep ) + { + const int price = rep_match_price + + price_rep( rep, state, pos_state ); + for( int len = min_match_len; len <= replens[rep]; ++len ) + trials[len].update( rep, 0, price + + rep_match_len_encoder.price( len, pos_state ) ); + } + } + + int cur = 0; + int num_trials = main_len; + matchfinder.move_pos(); + + while( true ) + { + if( ++cur >= num_trials ) // no more initialized trials + { + backward( cur ); + return cur; + } + const int newlen = read_match_distances(); + if( newlen >= matchfinder.match_len_limit() ) + { + longest_match_found = newlen; + backward( cur ); + return cur; + } + + Trial & cur_trial = trials[cur]; + const int prev_index = cur_trial.prev_index; + + cur_trial.state = trials[prev_index].state; + + for( int i = 0; i < num_rep_distances; ++i ) + cur_trial.reps[i] = trials[prev_index].reps[i]; + if( prev_index == cur - 1 ) + { + if( cur_trial.dis == 0 ) cur_trial.state.set_short_rep(); + else cur_trial.state.set_char(); + } + else + { + if( cur_trial.dis < num_rep_distances ) cur_trial.state.set_rep(); + else cur_trial.state.set_match(); + mtf_reps( cur_trial.dis, cur_trial.reps ); + } + + const int pos_state = matchfinder.data_position() & pos_state_mask; + const uint8_t prev_byte = matchfinder[-1]; + const uint8_t cur_byte = matchfinder[0]; + const uint8_t match_byte = matchfinder[-cur_trial.reps[0]-1]; + + int next_price = cur_trial.price + + price0( bm_match[cur_trial.state()][pos_state] ); + if( cur_trial.state.is_char() ) + next_price += literal_encoder.price_symbol( prev_byte, cur_byte ); + else + next_price += literal_encoder.price_matched( prev_byte, cur_byte, match_byte ); + matchfinder.move_pos(); + + Trial & next_trial = trials[cur+1]; + + next_trial.update( -1, cur, next_price ); + + const int match_price = cur_trial.price + price1( bm_match[cur_trial.state()][pos_state] ); + const int rep_match_price = match_price + price1( bm_rep[cur_trial.state()] ); + + if( match_byte == cur_byte && next_trial.dis != 0 ) + next_trial.update( 0, cur, rep_match_price + + price_rep_len1( cur_trial.state, pos_state ) ); + + const int len_limit = min( min( max_num_trials - 1 - cur, + matchfinder.available_bytes() ), matchfinder.match_len_limit() ); + if( len_limit < min_match_len ) continue; + + for( int rep = 0; rep < num_rep_distances; ++rep ) + { + const int dis = cur_trial.reps[rep] + 1; + int len = 0; + const uint8_t * const data = matchfinder.ptr_to_current_pos() - 1; + while( len < len_limit && data[len] == data[len-dis] ) ++len; + if( len >= min_match_len ) + { + const int price = rep_match_price + + price_rep( rep, cur_trial.state, pos_state ); + while( num_trials < cur + len ) + trials[++num_trials].price = infinite_price; + for( ; len >= min_match_len; --len ) + trials[cur+len].update( rep, cur, price + + rep_match_len_encoder.price( len, pos_state ) ); + } + } + + if( newlen <= len_limit && + ( newlen > min_match_len || + ( newlen == min_match_len && + match_distances[min_match_len] < modeled_distances ) ) ) + { + const int normal_match_price = match_price + + price0( bm_rep[cur_trial.state()] ); + while( num_trials < cur + newlen ) + trials[++num_trials].price = infinite_price; + + int dis = match_distances[min_match_len]; + int dis_state = get_dis_state( min_match_len ); + int dis_price = infinite_price; + if( dis < modeled_distances ) + trials[cur+min_match_len].update( dis + num_rep_distances, cur, + normal_match_price + dis_prices[dis_state][dis] + + len_encoder.price( min_match_len, pos_state ) ); + for( int len = min_match_len + 1; len <= newlen; ++len ) + { + if( dis != match_distances[len] || dis_state < max_dis_states - 1 ) + { + dis = match_distances[len]; + dis_state = get_dis_state( len ); + dis_price = price_dis( dis, dis_state ); + } + trials[cur+len].update( dis + num_rep_distances, cur, + normal_match_price + dis_price + + len_encoder.price( len, pos_state ) ); + } + } + } + } + + + // End Of Stream mark => (dis == 0xFFFFFFFFU, len == min_match_len) +void LZ_encoder::full_flush( const State & state ) + { + const int pos_state = matchfinder.data_position() & pos_state_mask; + range_encoder.encode_bit( bm_match[state()][pos_state], 1 ); + range_encoder.encode_bit( bm_rep[state()], 0 ); + encode_pair( 0xFFFFFFFFU, min_match_len, pos_state ); + range_encoder.flush(); + File_trailer trailer; + trailer.data_crc( crc() ); + trailer.data_size( matchfinder.data_position() ); + trailer.member_size( range_encoder.member_position() + File_trailer::size() ); + for( int i = 0; i < File_trailer::size(); ++i ) + range_encoder.put_byte( trailer.data[i] ); + range_encoder.flush_data(); + } + + +LZ_encoder::LZ_encoder( Matchfinder & mf, const File_header & header, + const int outfd ) + : + longest_match_found( 0 ), + crc_( 0xFFFFFFFFU ), + matchfinder( mf ), + range_encoder( outfd ), + len_encoder( matchfinder.match_len_limit() ), + rep_match_len_encoder( matchfinder.match_len_limit() ), + num_dis_slots( 2 * real_bits( matchfinder.dictionary_size() - 1 ) ) + { + fill_align_prices(); + + for( int i = 0; i < File_header::size; ++i ) + range_encoder.put_byte( header.data[i] ); + } + + +bool LZ_encoder::encode_member( const long long member_size ) + { + const long long member_size_limit = + member_size - File_trailer::size() - max_marker_size; + const int fill_count = ( matchfinder.match_len_limit() > 12 ) ? 512 : 2048; + int fill_counter = 0; + int rep_distances[num_rep_distances]; + State state; + for( int i = 0; i < num_rep_distances; ++i ) rep_distances[i] = 0; + + if( matchfinder.data_position() != 0 || + range_encoder.member_position() != File_header::size ) + return false; // can be called only once + + if( !matchfinder.finished() ) // encode first byte + { + const uint8_t prev_byte = 0; + const uint8_t cur_byte = matchfinder[0]; + range_encoder.encode_bit( bm_match[state()][0], 0 ); + literal_encoder.encode( range_encoder, prev_byte, cur_byte ); + crc32.update( crc_, cur_byte ); + move_pos( 1 ); + } + + while( true ) + { + if( matchfinder.finished() ) { full_flush( state ); return true; } + if( fill_counter <= 0 ) + { fill_distance_prices(); fill_counter = fill_count; } + + int ahead = sequence_optimizer( rep_distances, state ); + if( ahead <= 0 ) return false; + fill_counter -= ahead; + + for( int i = 0; ; ) + { + const int pos_state = + ( matchfinder.data_position() - ahead ) & pos_state_mask; + const int dis = trials[i].dis; + const int len = trials[i].price; + + bool bit = ( dis < 0 && len == 1 ); + range_encoder.encode_bit( bm_match[state()][pos_state], !bit ); + if( bit ) // literal byte + { + const uint8_t prev_byte = matchfinder[-ahead-1]; + const uint8_t cur_byte = matchfinder[-ahead]; + crc32.update( crc_, cur_byte ); + if( state.is_char() ) + literal_encoder.encode( range_encoder, prev_byte, cur_byte ); + else + { + const uint8_t match_byte = matchfinder[-ahead-rep_distances[0]-1]; + literal_encoder.encode_matched( range_encoder, + prev_byte, cur_byte, match_byte ); + } + state.set_char(); + } + else // match or repeated match + { + crc32.update( crc_, matchfinder.ptr_to_current_pos() - ahead, len ); + mtf_reps( dis, rep_distances ); + bit = ( dis < num_rep_distances ); + range_encoder.encode_bit( bm_rep[state()], bit ); + if( bit ) + { + bit = ( dis == 0 ); + range_encoder.encode_bit( bm_rep0[state()], !bit ); + if( bit ) + range_encoder.encode_bit( bm_len[state()][pos_state], len > 1 ); + else + { + range_encoder.encode_bit( bm_rep1[state()], dis > 1 ); + if( dis > 1 ) + range_encoder.encode_bit( bm_rep2[state()], dis > 2 ); + } + if( len == 1 ) state.set_short_rep(); + else + { + rep_match_len_encoder.encode( range_encoder, len, pos_state ); + state.set_rep(); + } + } + else + { + encode_pair( dis - num_rep_distances, len, pos_state ); + state.set_match(); + } + } + ahead -= len; i += len; + if( range_encoder.member_position() >= member_size_limit ) + { + if( !matchfinder.dec_pos( ahead ) ) return false; + full_flush( state ); + return true; + } + if( ahead <= 0 ) break; + } + } + } + +#endif + diff --git a/third_party/lzma.js/lzip/encoder.h b/third_party/lzma.js/lzip/encoder.h new file mode 100644 index 00000000..2c445407 --- /dev/null +++ b/third_party/lzma.js/lzip/encoder.h @@ -0,0 +1,582 @@ +/* Lzip - Data compressor based on the LZMA algorithm + Copyright (C) 2008, 2009, 2010, 2011 Antonio Diaz Diaz. + + 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 <http://www.gnu.org/licenses/>. +*/ + +enum { max_num_trials = 1 << 12, + price_shift = 6 }; + +class Dis_slots + { + unsigned char data[1<<12]; + +public: + void init() throw() + { + for( int slot = 0; slot < 4; ++slot ) data[slot] = slot; + for( int i = 4, size = 2, slot = 4; slot < 24; slot += 2 ) + { + memset( &data[i], slot, size ); + memset( &data[i+size], slot + 1, size ); + size <<= 1; + i += size; + } + } + + unsigned char table( const int dis ) const throw() { return data[dis]; } + + int operator[]( const uint32_t dis ) const throw() + { + if( dis < (1 << 12) ) return data[dis]; + if( dis < (1 << 23) ) return data[dis>>11] + 22; + return data[dis>>22] + 44; + } + }; + +extern Dis_slots dis_slots; + + +class Prob_prices + { + int data[bit_model_total >> 2]; + +public: + void init() throw() + { + const int num_bits = ( bit_model_total_bits - 2 ); + int j = 1, end = 2; + data[0] = bit_model_total_bits << price_shift; + for( int i = num_bits - 1; i >= 0; --i, end <<= 1 ) + { + for( ; j < end; ++j ) + data[j] = ( i << price_shift ) + + ( ( (end - j) << price_shift ) >> ( num_bits - i - 1 ) ); + } + } + + int operator[]( const int probability ) const throw() + { return data[probability >> 2]; } + }; + +extern Prob_prices prob_prices; + + +inline int price0( const Bit_model & bm ) throw() + { return prob_prices[bm.probability]; } + +inline int price1( const Bit_model & bm ) throw() + { return prob_prices[bit_model_total-bm.probability]; } + +inline int price_bit( const Bit_model & bm, const int bit ) throw() + { if( bit ) return price1( bm ); else return price0( bm ); } + + +inline int price_symbol( const Bit_model bm[], int symbol, const int num_bits ) throw() + { + int price = 0; + symbol |= ( 1 << num_bits ); + while( symbol > 1 ) + { + const int bit = symbol & 1; + symbol >>= 1; + price += price_bit( bm[symbol], bit ); + } + return price; + } + + +inline int price_symbol_reversed( const Bit_model bm[], int symbol, + const int num_bits ) throw() + { + int price = 0; + int model = 1; + for( int i = num_bits; i > 0; --i ) + { + const int bit = symbol & 1; + symbol >>= 1; + price += price_bit( bm[model], bit ); + model = ( model << 1 ) | bit; + } + return price; + } + + +inline int price_matched( const Bit_model bm[], const int symbol, + const int match_byte ) throw() + { + int price = 0; + int model = 1; + + for( int i = 7; i >= 0; --i ) + { + const int match_bit = ( match_byte >> i ) & 1; + int bit = ( symbol >> i ) & 1; + price += price_bit( bm[(match_bit<<8)+model+0x100], bit ); + model = ( model << 1 ) | bit; + if( match_bit != bit ) + { + while( --i >= 0 ) + { + bit = ( symbol >> i ) & 1; + price += price_bit( bm[model], bit ); + model = ( model << 1 ) | bit; + } + break; + } + } + return price; + } + + +class Matchfinder + { + enum { // bytes to keep in buffer before dictionary + before_size = max_num_trials + 1, + // bytes to keep in buffer after pos + after_size = max_match_len, + num_prev_positions4 = 1 << 20, + num_prev_positions3 = 1 << 18, + num_prev_positions2 = 1 << 16, + num_prev_positions = num_prev_positions4 + num_prev_positions3 + + num_prev_positions2 }; + + long long partial_data_pos; + uint8_t * buffer; // input buffer + int32_t * const prev_positions; // last seen position of key + int32_t * prev_pos_tree; + int dictionary_size_; // bytes to keep in buffer before pos + int buffer_size; + int pos; // current pos in buffer + int cyclic_pos; // current pos in dictionary + int stream_pos; // first byte not yet read from file + int pos_limit; // when reached, a new block must be read + const int match_len_limit_; + const int cycles; + const int infd; // input file descriptor + bool at_stream_end; // stream_pos shows real end of file + + bool read_block(); + +public: + Matchfinder( const int dict_size, const int len_limit, const int ifd ); + + ~Matchfinder() + { delete[] prev_pos_tree; delete[] prev_positions; free( buffer ); } + + uint8_t operator[]( const int i ) const throw() { return buffer[pos+i]; } + int available_bytes() const throw() { return stream_pos - pos; } + long long data_position() const throw() { return partial_data_pos + pos; } + int dictionary_size() const throw() { return dictionary_size_; } + bool finished() const throw() { return at_stream_end && pos >= stream_pos; } + int match_len_limit() const throw() { return match_len_limit_; } + const uint8_t * ptr_to_current_pos() const throw() { return buffer + pos; } + + bool dec_pos( const int ahead ) throw() + { + if( ahead < 0 || pos < ahead ) return false; + pos -= ahead; + cyclic_pos -= ahead; + if( cyclic_pos < 0 ) cyclic_pos += dictionary_size_; + return true; + } + + int true_match_len( const int index, const int distance, int len_limit ) const throw() + { + if( index + len_limit > available_bytes() ) + len_limit = available_bytes() - index; + const uint8_t * const data = buffer + pos + index - distance; + int i = 0; + while( i < len_limit && data[i] == data[i+distance] ) ++i; + return i; + } + + void reset(); + void move_pos(); + int longest_match_len( int * const distances = 0 ) throw(); + }; + + +class Range_encoder + { + enum { buffer_size = 65536 }; + uint64_t low; + long long partial_member_pos; + uint8_t * const buffer; // output buffer + int pos; // current pos in buffer + uint32_t range; + int ff_count; + const int outfd; // output file descriptor + uint8_t cache; + + void shift_low() + { + const uint32_t carry = low >> 32; + if( low < 0xFF000000U || carry == 1 ) + { + put_byte( cache + carry ); + for( ; ff_count > 0; --ff_count ) put_byte( 0xFF + carry ); + cache = low >> 24; + } + else ++ff_count; + low = ( low & 0x00FFFFFFU ) << 8; + } + +public: + Range_encoder( const int ofd ) + : + low( 0 ), + partial_member_pos( 0 ), + buffer( new uint8_t[buffer_size] ), + pos( 0 ), + range( 0xFFFFFFFFU ), + ff_count( 0 ), + outfd( ofd ), + cache( 0 ) {} + + ~Range_encoder() { delete[] buffer; } + + long long member_position() const throw() + { return partial_member_pos + pos + ff_count; } + + void flush() { for( int i = 0; i < 5; ++i ) shift_low(); } + void flush_data(); + + void put_byte( const uint8_t b ) + { + buffer[pos] = b; + if( ++pos >= buffer_size ) flush_data(); + } + + void encode( const int symbol, const int num_bits ) + { + for( int i = num_bits - 1; i >= 0; --i ) + { + range >>= 1; + if( (symbol >> i) & 1 ) low += range; + if( range <= 0x00FFFFFFU ) { range <<= 8; shift_low(); } + } + } + + void encode_bit( Bit_model & bm, const int bit ) + { + const uint32_t bound = ( range >> bit_model_total_bits ) * bm.probability; + if( !bit ) + { + range = bound; + bm.probability += (bit_model_total - bm.probability) >> bit_model_move_bits; + } + else + { + low += bound; + range -= bound; + bm.probability -= bm.probability >> bit_model_move_bits; + } + if( range <= 0x00FFFFFFU ) { range <<= 8; shift_low(); } + } + + void encode_tree( Bit_model bm[], const int symbol, const int num_bits ) + { + int mask = ( 1 << ( num_bits - 1 ) ); + int model = 1; + for( int i = num_bits; i > 0; --i, mask >>= 1 ) + { + const int bit = ( symbol & mask ); + encode_bit( bm[model], bit ); + model <<= 1; + if( bit ) model |= 1; + } + } + + void encode_tree_reversed( Bit_model bm[], int symbol, const int num_bits ) + { + int model = 1; + for( int i = num_bits; i > 0; --i ) + { + const int bit = symbol & 1; + encode_bit( bm[model], bit ); + model = ( model << 1 ) | bit; + symbol >>= 1; + } + } + + void encode_matched( Bit_model bm[], int symbol, int match_byte ) + { + int model = 1; + for( int i = 7; i >= 0; --i ) + { + const int match_bit = ( match_byte >> i ) & 1; + int bit = ( symbol >> i ) & 1; + encode_bit( bm[(match_bit<<8)+model+0x100], bit ); + model = ( model << 1 ) | bit; + if( match_bit != bit ) + { + while( --i >= 0 ) + { + bit = ( symbol >> i ) & 1; + encode_bit( bm[model], bit ); + model = ( model << 1 ) | bit; + } + break; + } + } + } + }; + + +class Len_encoder + { + Bit_model choice1; + Bit_model choice2; + Bit_model bm_low[pos_states][len_low_symbols]; + Bit_model bm_mid[pos_states][len_mid_symbols]; + Bit_model bm_high[len_high_symbols]; + int prices[pos_states][max_len_symbols]; + const int len_symbols; + int counters[pos_states]; + + void update_prices( const int pos_state ) throw() + { + int * const pps = prices[pos_state]; + int tmp = price0( choice1 ); + int len = 0; + for( ; len < len_low_symbols && len < len_symbols; ++len ) + pps[len] = tmp + + price_symbol( bm_low[pos_state], len, len_low_bits ); + tmp = price1( choice1 ); + for( ; len < len_low_symbols + len_mid_symbols && len < len_symbols; ++len ) + pps[len] = tmp + price0( choice2 ) + + price_symbol( bm_mid[pos_state], len - len_low_symbols, len_mid_bits ); + for( ; len < len_symbols; ++len ) + // using 4 slots per value makes "price" faster + prices[3][len] = prices[2][len] = prices[1][len] = prices[0][len] = + tmp + price1( choice2 ) + + price_symbol( bm_high, len - len_low_symbols - len_mid_symbols, len_high_bits ); + counters[pos_state] = len_symbols; + } + +public: + Len_encoder( const int len_limit ) + : len_symbols( len_limit + 1 - min_match_len ) + { + for( int i = 0; i < pos_states; ++i ) update_prices( i ); + } + + void encode( Range_encoder & range_encoder, int symbol, + const int pos_state ); + + int price( const int symbol, const int pos_state ) const throw() + { return prices[pos_state][symbol - min_match_len]; } + }; + + +class Literal_encoder + { + Bit_model bm_literal[1<<literal_context_bits][0x300]; + + int lstate( const uint8_t prev_byte ) const throw() + { return ( prev_byte >> ( 8 - literal_context_bits ) ); } + +public: + void encode( Range_encoder & range_encoder, + uint8_t prev_byte, uint8_t symbol ) + { range_encoder.encode_tree( bm_literal[lstate(prev_byte)], symbol, 8 ); } + + void encode_matched( Range_encoder & range_encoder, + uint8_t prev_byte, uint8_t symbol, uint8_t match_byte ) + { range_encoder.encode_matched( bm_literal[lstate(prev_byte)], + symbol, match_byte ); } + + int price_symbol( uint8_t prev_byte, uint8_t symbol ) const throw() + { return ::price_symbol( bm_literal[lstate(prev_byte)], symbol, 8 ); } + + int price_matched( uint8_t prev_byte, uint8_t symbol, + uint8_t match_byte ) const throw() + { return ::price_matched( bm_literal[lstate(prev_byte)], + symbol, match_byte ); } + }; + + +class LZ_encoder + { + enum { infinite_price = 0x0FFFFFFF, + max_marker_size = 16, + num_rep_distances = 4 }; // must be 4 + + struct Trial + { + State state; + int dis; + int prev_index; // index of prev trial in trials[] + int price; // dual use var; cumulative price, match length + int reps[num_rep_distances]; + void update( const int d, const int p_i, const int pr ) throw() + { if( pr < price ) { dis = d; prev_index = p_i; price = pr; } } + }; + + int longest_match_found; + uint32_t crc_; + + Bit_model bm_match[State::states][pos_states]; + Bit_model bm_rep[State::states]; + Bit_model bm_rep0[State::states]; + Bit_model bm_rep1[State::states]; + Bit_model bm_rep2[State::states]; + Bit_model bm_len[State::states][pos_states]; + Bit_model bm_dis_slot[max_dis_states][1<<dis_slot_bits]; + Bit_model bm_dis[modeled_distances-end_dis_model+1]; + Bit_model bm_align[dis_align_size]; + + Matchfinder & matchfinder; + Range_encoder range_encoder; + Len_encoder len_encoder; + Len_encoder rep_match_len_encoder; + Literal_encoder literal_encoder; + + const int num_dis_slots; + int match_distances[max_match_len+1]; + Trial trials[max_num_trials]; + + int dis_slot_prices[max_dis_states][2*max_dictionary_bits]; + int dis_prices[max_dis_states][modeled_distances]; + int align_prices[dis_align_size]; + int align_price_count; + + void fill_align_prices() throw(); + void fill_distance_prices() throw(); + + uint32_t crc() const throw() { return crc_ ^ 0xFFFFFFFFU; } + + // move-to-front dis in/into reps + void mtf_reps( const int dis, int reps[num_rep_distances] ) throw() + { + if( dis >= num_rep_distances ) + { + for( int i = num_rep_distances - 1; i > 0; --i ) reps[i] = reps[i-1]; + reps[0] = dis - num_rep_distances; + } + else if( dis > 0 ) + { + const int distance = reps[dis]; + for( int i = dis; i > 0; --i ) reps[i] = reps[i-1]; + reps[0] = distance; + } + } + + int price_rep_len1( const State & state, const int pos_state ) const throw() + { + return price0( bm_rep0[state()] ) + price0( bm_len[state()][pos_state] ); + } + + int price_rep( const int rep, const State & state, + const int pos_state ) const throw() + { + if( rep == 0 ) return price0( bm_rep0[state()] ) + + price1( bm_len[state()][pos_state] ); + int price = price1( bm_rep0[state()] ); + if( rep == 1 ) + price += price0( bm_rep1[state()] ); + else + { + price += price1( bm_rep1[state()] ); + price += price_bit( bm_rep2[state()], rep - 2 ); + } + return price; + } + + int price_dis( const int dis, const int dis_state ) const throw() + { + if( dis < modeled_distances ) + return dis_prices[dis_state][dis]; + else + return dis_slot_prices[dis_state][dis_slots[dis]] + + align_prices[dis & (dis_align_size - 1)]; + } + + int price_pair( const int dis, const int len, const int pos_state ) const throw() + { + if( len <= min_match_len && dis >= modeled_distances ) + return infinite_price; + return len_encoder.price( len, pos_state ) + + price_dis( dis, get_dis_state( len ) ); + } + + void encode_pair( const uint32_t dis, const int len, const int pos_state ) throw() + { + len_encoder.encode( range_encoder, len, pos_state ); + const int dis_slot = dis_slots[dis]; + range_encoder.encode_tree( bm_dis_slot[get_dis_state(len)], dis_slot, dis_slot_bits ); + + if( dis_slot >= start_dis_model ) + { + const int direct_bits = ( dis_slot >> 1 ) - 1; + const uint32_t base = ( 2 | ( dis_slot & 1 ) ) << direct_bits; + const uint32_t direct_dis = dis - base; + + if( dis_slot < end_dis_model ) + range_encoder.encode_tree_reversed( bm_dis + base - dis_slot, + direct_dis, direct_bits ); + else + { + range_encoder.encode( direct_dis >> dis_align_bits, direct_bits - dis_align_bits ); + range_encoder.encode_tree_reversed( bm_align, direct_dis, dis_align_bits ); + if( --align_price_count <= 0 ) fill_align_prices(); + } + } + } + + int read_match_distances() throw() + { + int len = matchfinder.longest_match_len( match_distances ); + if( len == matchfinder.match_len_limit() ) + len += matchfinder.true_match_len( len, match_distances[len] + 1, max_match_len - len ); + return len; + } + + void move_pos( int n, bool skip = false ) + { + while( --n >= 0 ) + { + if( skip ) skip = false; + else matchfinder.longest_match_len(); + matchfinder.move_pos(); + } + } + + void backward( int cur ) + { + int & dis = trials[cur].dis; + while( cur > 0 ) + { + const int prev_index = trials[cur].prev_index; + Trial & prev_trial = trials[prev_index]; + prev_trial.price = cur - prev_index; // len + cur = dis; dis = prev_trial.dis; prev_trial.dis = cur; + cur = prev_index; + } + } + + int sequence_optimizer( const int reps[num_rep_distances], + const State & state ); + + void full_flush( const State & state ); + +public: + LZ_encoder( Matchfinder & mf, const File_header & header, const int outfd ); + + bool encode_member( const long long member_size ); + + long long member_position() const throw() + { return range_encoder.member_position(); } + }; diff --git a/third_party/lzma.js/lzip/fast_encoder.cc b/third_party/lzma.js/lzip/fast_encoder.cc new file mode 100644 index 00000000..59965af4 --- /dev/null +++ b/third_party/lzma.js/lzip/fast_encoder.cc @@ -0,0 +1,378 @@ +#if !DECODER_ONLY + +/* Lzip - Data compressor based on the LZMA algorithm + Copyright (C) 2008, 2009, 2010, 2011 Antonio Diaz Diaz. + + 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 <http://www.gnu.org/licenses/>. +*/ + +#define _FILE_OFFSET_BITS 64 + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#include "lzip.h" +#include "encoder.h" +#include "fast_encoder.h" + + +bool Fmatchfinder::read_block() + { + if( !at_stream_end && stream_pos < buffer_size ) + { + const int size = buffer_size - stream_pos; + const int rd = readblock( infd, buffer + stream_pos, size ); + stream_pos += rd; + if( rd != size && errno ) throw Error( "Read error" ); + at_stream_end = ( rd < size ); + } + return pos < stream_pos; + } + + +Fmatchfinder::Fmatchfinder( const int ifd ) + : + partial_data_pos( 0 ), + prev_positions( new int32_t[num_prev_positions] ), + pos( 0 ), + cyclic_pos( 0 ), + key4( 0 ), + stream_pos( 0 ), + match_len_limit_( 16 ), + infd( ifd ), + at_stream_end( false ) + { + const int dict_size = 65536; + const int buffer_size_limit = ( 16 * dict_size ) + before_size + after_size; + buffer_size = dict_size; + buffer = (uint8_t *)malloc( buffer_size ); + if( !buffer ) exit(-1); + if( read_block() && !at_stream_end && buffer_size < buffer_size_limit ) + { + buffer_size = buffer_size_limit; + buffer = (uint8_t *)realloc( buffer, buffer_size ); + if( !buffer ) exit(-1); + read_block(); + } + if( at_stream_end && stream_pos < dict_size ) + dictionary_size_ = max( (int)min_dictionary_size, stream_pos ); + else dictionary_size_ = dict_size; + pos_limit = buffer_size; + if( !at_stream_end ) pos_limit -= after_size; + prev_pos_chain = new int32_t[dictionary_size_]; + for( int i = 0; i < num_prev_positions; ++i ) prev_positions[i] = -1; + } + + +void Fmatchfinder::reset() + { + const int size = stream_pos - pos; + if( size > 0 ) memmove( buffer, buffer + pos, size ); + partial_data_pos = 0; + stream_pos -= pos; + pos = 0; + cyclic_pos = 0; + key4 = 0; + for( int i = 0; i < num_prev_positions; ++i ) prev_positions[i] = -1; + read_block(); + } + + +void Fmatchfinder::move_pos() + { + if( ++cyclic_pos >= dictionary_size_ ) cyclic_pos = 0; + if( ++pos >= pos_limit ) + { + if( pos > stream_pos ) + internal_error( "pos > stream_pos in Fmatchfinder::move_pos" ); + if( !at_stream_end ) + { + const int offset = pos - dictionary_size_ - before_size; + const int size = stream_pos - offset; + memmove( buffer, buffer + offset, size ); + partial_data_pos += offset; + pos -= offset; + stream_pos -= offset; + for( int i = 0; i < num_prev_positions; ++i ) + if( prev_positions[i] >= 0 ) prev_positions[i] -= offset; + for( int i = 0; i < dictionary_size_; ++i ) + if( prev_pos_chain[i] >= 0 ) prev_pos_chain[i] -= offset; + read_block(); + } + } + } + + +int Fmatchfinder::longest_match_len( int * const distance ) + { + int len_limit = match_len_limit_; + if( len_limit > available_bytes() ) + { + len_limit = available_bytes(); + if( len_limit < 4 ) return 0; + } + + const uint8_t * const data = buffer + pos; + key4 = ( ( key4 << 4 ) ^ data[3] ) & ( num_prev_positions - 1 ); + + int newpos = prev_positions[key4]; + prev_positions[key4] = pos; + + int32_t * ptr0 = prev_pos_chain + cyclic_pos; + int maxlen = 0; + + for( int count = 4; ; ) + { + if( newpos < (pos - dictionary_size_ + 1) || newpos < 0 || --count < 0 ) + { *ptr0 = -1; break; } + const uint8_t * const newdata = buffer + newpos; + int len = 0; + if( newdata[maxlen] == data[maxlen] ) + while( len < len_limit && newdata[len] == data[len] ) ++len; + + const int delta = pos - newpos; + if( maxlen < len ) { maxlen = len; *distance = delta - 1; } + + int32_t * const newptr = prev_pos_chain + + ( cyclic_pos - delta + + ( ( cyclic_pos >= delta ) ? 0 : dictionary_size_ ) ); + + if( len < len_limit ) + { + *ptr0 = newpos; + ptr0 = newptr; + newpos = *ptr0; + } + else + { + *ptr0 = *newptr; + break; + } + } + return maxlen; + } + + +void Fmatchfinder::longest_match_len() + { + int len_limit = match_len_limit_; + if( len_limit > available_bytes() ) + { + len_limit = available_bytes(); + if( len_limit < 4 ) return; + } + + const uint8_t * const data = buffer + pos; + key4 = ( ( key4 << 4 ) ^ data[3] ) & ( num_prev_positions - 1 ); + + const int newpos = prev_positions[key4]; + prev_positions[key4] = pos; + + int32_t * const ptr0 = prev_pos_chain + cyclic_pos; + + if( newpos < (pos - dictionary_size_ + 1) || newpos < 0 ) *ptr0 = -1; + else + { + const uint8_t * const newdata = buffer + newpos; + if( newdata[len_limit-1] != data[len_limit-1] || + memcmp( newdata, data, len_limit - 1 ) ) *ptr0 = newpos; + else + { + int idx = cyclic_pos - pos + newpos; + if( idx < 0 ) idx += dictionary_size_; + *ptr0 = prev_pos_chain[idx]; + } + } + } + + +// Return value == number of bytes advanced (len). +// *disp returns the distance to encode. +// ( *disp == -1 && len == 1 ) means literal. +int FLZ_encoder::sequence_optimizer( const int reps[num_rep_distances], + int * const disp, const State & state ) + { + const int main_len = read_match_distances(); + + int replen = 0; + int rep_index = 0; + for( int i = 0; i < num_rep_distances; ++i ) + { + const int len = fmatchfinder.true_match_len( 0, reps[i] + 1, max_match_len ); + if( len > replen ) { replen = len; rep_index = i; } + } + if( replen > min_match_len && replen + 4 > main_len ) + { + *disp = rep_index; + move_pos( replen, true ); + return replen; + } + + if( main_len > min_match_len || + ( main_len == min_match_len && match_distance < modeled_distances ) ) + { + *disp = num_rep_distances + match_distance; + move_pos( main_len, true ); + return main_len; + } + + const uint8_t cur_byte = fmatchfinder[0]; + const uint8_t match_byte = fmatchfinder[-reps[0]-1]; + + *disp = -1; + if( match_byte == cur_byte ) + { + const uint8_t prev_byte = fmatchfinder[-1]; + const int pos_state = fmatchfinder.data_position() & pos_state_mask; + int price = price0( bm_match[state()][pos_state] ); + if( state.is_char() ) + price += literal_encoder.price_symbol( prev_byte, cur_byte ); + else + price += literal_encoder.price_matched( prev_byte, cur_byte, match_byte ); + const int short_rep_price = price1( bm_match[state()][pos_state] ) + + price1( bm_rep[state()] ) + + price0( bm_rep0[state()] ) + + price0( bm_len[state()][pos_state] ); + if( short_rep_price < price ) *disp = 0; + } + + fmatchfinder.move_pos(); + return 1; + } + + + // End Of Stream mark => (dis == 0xFFFFFFFFU, len == min_match_len) +void FLZ_encoder::full_flush( const State & state ) + { + const int pos_state = fmatchfinder.data_position() & pos_state_mask; + range_encoder.encode_bit( bm_match[state()][pos_state], 1 ); + range_encoder.encode_bit( bm_rep[state()], 0 ); + encode_pair( 0xFFFFFFFFU, min_match_len, pos_state ); + range_encoder.flush(); + File_trailer trailer; + trailer.data_crc( crc() ); + trailer.data_size( fmatchfinder.data_position() ); + trailer.member_size( range_encoder.member_position() + File_trailer::size() ); + for( int i = 0; i < File_trailer::size(); ++i ) + range_encoder.put_byte( trailer.data[i] ); + range_encoder.flush_data(); + } + + +FLZ_encoder::FLZ_encoder( Fmatchfinder & mf, const File_header & header, + const int outfd ) + : + crc_( 0xFFFFFFFFU ), + fmatchfinder( mf ), + range_encoder( outfd ), + len_encoder( fmatchfinder.match_len_limit() ), + rep_match_len_encoder( fmatchfinder.match_len_limit() ), + num_dis_slots( 2 * real_bits( fmatchfinder.dictionary_size() - 1 ) ) + { + for( int i = 0; i < File_header::size; ++i ) + range_encoder.put_byte( header.data[i] ); + } + + +bool FLZ_encoder::encode_member( const long long member_size ) + { + const long long member_size_limit = + member_size - File_trailer::size() - max_marker_size; + int rep_distances[num_rep_distances]; + State state; + for( int i = 0; i < num_rep_distances; ++i ) rep_distances[i] = 0; + + if( fmatchfinder.data_position() != 0 || + range_encoder.member_position() != File_header::size ) + return false; // can be called only once + + if( !fmatchfinder.finished() ) // encode first byte + { + const uint8_t prev_byte = 0; + const uint8_t cur_byte = fmatchfinder[0]; + range_encoder.encode_bit( bm_match[state()][0], 0 ); + literal_encoder.encode( range_encoder, prev_byte, cur_byte ); + crc32.update( crc_, cur_byte ); + move_pos( 1 ); + } + + while( true ) + { + if( fmatchfinder.finished() ) { full_flush( state ); return true; } + + const int pos_state = fmatchfinder.data_position() & pos_state_mask; + int dis; + const int len = sequence_optimizer( rep_distances, &dis, state ); + if( len <= 0 ) return false; + + bool bit = ( dis < 0 && len == 1 ); + range_encoder.encode_bit( bm_match[state()][pos_state], !bit ); + if( bit ) // literal byte + { + const uint8_t prev_byte = fmatchfinder[-len-1]; + const uint8_t cur_byte = fmatchfinder[-len]; + crc32.update( crc_, cur_byte ); + if( state.is_char() ) + literal_encoder.encode( range_encoder, prev_byte, cur_byte ); + else + { + const uint8_t match_byte = fmatchfinder[-len-rep_distances[0]-1]; + literal_encoder.encode_matched( range_encoder, + prev_byte, cur_byte, match_byte ); + } + state.set_char(); + } + else // match or repeated match + { + crc32.update( crc_, fmatchfinder.ptr_to_current_pos() - len, len ); + mtf_reps( dis, rep_distances ); + bit = ( dis < num_rep_distances ); + range_encoder.encode_bit( bm_rep[state()], bit ); + if( bit ) + { + bit = ( dis == 0 ); + range_encoder.encode_bit( bm_rep0[state()], !bit ); + if( bit ) + range_encoder.encode_bit( bm_len[state()][pos_state], len > 1 ); + else + { + range_encoder.encode_bit( bm_rep1[state()], dis > 1 ); + if( dis > 1 ) + range_encoder.encode_bit( bm_rep2[state()], dis > 2 ); + } + if( len == 1 ) state.set_short_rep(); + else + { + rep_match_len_encoder.encode( range_encoder, len, pos_state ); + state.set_rep(); + } + } + else + { + encode_pair( dis - num_rep_distances, len, pos_state ); + state.set_match(); + } + } + if( range_encoder.member_position() >= member_size_limit ) + { + full_flush( state ); + return true; + } + } + } + +#endif + diff --git a/third_party/lzma.js/lzip/fast_encoder.h b/third_party/lzma.js/lzip/fast_encoder.h new file mode 100644 index 00000000..b18b8a82 --- /dev/null +++ b/third_party/lzma.js/lzip/fast_encoder.h @@ -0,0 +1,171 @@ +/* Lzip - Data compressor based on the LZMA algorithm + Copyright (C) 2008, 2009, 2010, 2011 Antonio Diaz Diaz. + + 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 <http://www.gnu.org/licenses/>. +*/ + +class Fmatchfinder + { + enum { // bytes to keep in buffer before dictionary + before_size = max_match_len + 1, + // bytes to keep in buffer after pos + after_size = max_match_len, + num_prev_positions = 1 << 16 }; + + long long partial_data_pos; + uint8_t * buffer; // input buffer + int32_t * const prev_positions; // last seen position of key + int32_t * prev_pos_chain; + int dictionary_size_; // bytes to keep in buffer before pos + int buffer_size; + int pos; // current pos in buffer + int cyclic_pos; // current pos in dictionary + int key4; // key made from latest 4 bytes + int stream_pos; // first byte not yet read from file + int pos_limit; // when reached, a new block must be read + const int match_len_limit_; + const int infd; // input file descriptor + bool at_stream_end; // stream_pos shows real end of file + + bool read_block(); + +public: + Fmatchfinder( const int ifd ); + + ~Fmatchfinder() + { delete[] prev_pos_chain; delete[] prev_positions; free( buffer ); } + + uint8_t operator[]( const int i ) const { return buffer[pos+i]; } + int available_bytes() const { return stream_pos - pos; } + long long data_position() const { return partial_data_pos + pos; } + int dictionary_size() const { return dictionary_size_; } + bool finished() const { return at_stream_end && pos >= stream_pos; } + int match_len_limit() const { return match_len_limit_; } + const uint8_t * ptr_to_current_pos() const { return buffer + pos; } + + int true_match_len( const int index, const int distance, int len_limit ) const + { + if( index + len_limit > available_bytes() ) + len_limit = available_bytes() - index; + const uint8_t * const data = buffer + pos + index - distance; + int i = 0; + while( i < len_limit && data[i] == data[i+distance] ) ++i; + return i; + } + + void reset(); + void move_pos(); + int longest_match_len( int * const distance ); + void longest_match_len(); + }; + + +class FLZ_encoder + { + enum { max_marker_size = 16, + num_rep_distances = 4 }; // must be 4 + + uint32_t crc_; + + Bit_model bm_match[State::states][pos_states]; + Bit_model bm_rep[State::states]; + Bit_model bm_rep0[State::states]; + Bit_model bm_rep1[State::states]; + Bit_model bm_rep2[State::states]; + Bit_model bm_len[State::states][pos_states]; + Bit_model bm_dis_slot[max_dis_states][1<<dis_slot_bits]; + Bit_model bm_dis[modeled_distances-end_dis_model+1]; + Bit_model bm_align[dis_align_size]; + + Fmatchfinder & fmatchfinder; + Range_encoder range_encoder; + Len_encoder len_encoder; + Len_encoder rep_match_len_encoder; + Literal_encoder literal_encoder; + + const int num_dis_slots; + int match_distance; + + uint32_t crc() const { return crc_ ^ 0xFFFFFFFFU; } + + // move-to-front dis in/into reps + void mtf_reps( const int dis, int reps[num_rep_distances] ) + { + if( dis >= num_rep_distances ) + { + for( int i = num_rep_distances - 1; i > 0; --i ) reps[i] = reps[i-1]; + reps[0] = dis - num_rep_distances; + } + else if( dis > 0 ) + { + const int distance = reps[dis]; + for( int i = dis; i > 0; --i ) reps[i] = reps[i-1]; + reps[0] = distance; + } + } + + void encode_pair( const uint32_t dis, const int len, const int pos_state ) + { + len_encoder.encode( range_encoder, len, pos_state ); + const int dis_slot = dis_slots[dis]; + range_encoder.encode_tree( bm_dis_slot[get_dis_state(len)], dis_slot, dis_slot_bits ); + + if( dis_slot >= start_dis_model ) + { + const int direct_bits = ( dis_slot >> 1 ) - 1; + const uint32_t base = ( 2 | ( dis_slot & 1 ) ) << direct_bits; + const uint32_t direct_dis = dis - base; + + if( dis_slot < end_dis_model ) + range_encoder.encode_tree_reversed( bm_dis + base - dis_slot, + direct_dis, direct_bits ); + else + { + range_encoder.encode( direct_dis >> dis_align_bits, direct_bits - dis_align_bits ); + range_encoder.encode_tree_reversed( bm_align, direct_dis, dis_align_bits ); + } + } + } + + int read_match_distances() + { + int len = fmatchfinder.longest_match_len( &match_distance ); + if( len == fmatchfinder.match_len_limit() ) + len += fmatchfinder.true_match_len( len, match_distance + 1, max_match_len - len ); + return len; + } + + void move_pos( int n, bool skip = false ) + { + while( --n >= 0 ) + { + if( skip ) skip = false; + else fmatchfinder.longest_match_len(); + fmatchfinder.move_pos(); + } + } + + int sequence_optimizer( const int reps[num_rep_distances], + int * const disp, const State & state ); + + void full_flush( const State & state ); + +public: + FLZ_encoder( Fmatchfinder & mf, const File_header & header, const int outfd ); + + bool encode_member( const long long member_size ); + + long long member_position() const + { return range_encoder.member_position(); } + }; diff --git a/third_party/lzma.js/lzip/lzip.h b/third_party/lzma.js/lzip/lzip.h new file mode 100644 index 00000000..1a49ca4b --- /dev/null +++ b/third_party/lzma.js/lzip/lzip.h @@ -0,0 +1,264 @@ +#define max(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a > _b ? _a : _b; }) + +#define min(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a < _b ? _a : _b; }) + +/* Lzip - Data compressor based on the LZMA algorithm + Copyright (C) 2008, 2009, 2010, 2011 Antonio Diaz Diaz. + + 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 <http://www.gnu.org/licenses/>. +*/ + +class State + { + unsigned char st; + +public: + enum { states = 12 }; + State() : st( 0 ) {} + unsigned char operator()() const { return st; } + bool is_char() const { return st < 7; } + + void set_char() + { + static const unsigned char next[states] = + { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5 }; + st = next[st]; + } + + void set_match() + { + static const unsigned char next[states] = + { 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 }; + st = next[st]; + } + + void set_rep() + { + static const unsigned char next[states] = + { 8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11 }; + st = next[st]; + } + + void set_short_rep() + { + static const unsigned char next[states] = + { 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11 }; + st = next[st]; + } + }; + + +enum { + min_dictionary_bits = 12, + min_dictionary_size = 1 << min_dictionary_bits, + max_dictionary_bits = 29, + max_dictionary_size = 1 << max_dictionary_bits, + literal_context_bits = 3, + pos_state_bits = 2, + pos_states = 1 << pos_state_bits, + pos_state_mask = pos_states - 1, + + dis_slot_bits = 6, + start_dis_model = 4, + end_dis_model = 14, + modeled_distances = 1 << (end_dis_model / 2), + dis_align_bits = 4, + dis_align_size = 1 << dis_align_bits, + + len_low_bits = 3, + len_mid_bits = 3, + len_high_bits = 8, + len_low_symbols = 1 << len_low_bits, + len_mid_symbols = 1 << len_mid_bits, + len_high_symbols = 1 << len_high_bits, + max_len_symbols = len_low_symbols + len_mid_symbols + len_high_symbols, + + min_match_len = 2, // must be 2 + max_match_len = min_match_len + max_len_symbols - 1, // 273 + min_match_len_limit = 5, + + max_dis_states = 4 }; + +inline int get_dis_state( int len ) + { + len -= min_match_len; + if( len >= max_dis_states ) len = max_dis_states - 1; + return len; + } + + +enum { bit_model_move_bits = 5, + bit_model_total_bits = 11, + bit_model_total = 1 << bit_model_total_bits }; + +struct Bit_model + { + unsigned int probability; + Bit_model() : probability( bit_model_total / 2 ) {} + }; + + +class CRC32 + { + uint32_t data[256]; // Table of CRCs of all 8-bit messages. + +public: + CRC32() + { + for( unsigned int n = 0; n < 256; ++n ) + { + unsigned int c = n; + for( int k = 0; k < 8; ++k ) + { if( c & 1 ) c = 0xEDB88320U ^ ( c >> 1 ); else c >>= 1; } + data[n] = c; + } + } + + uint32_t operator[]( const uint8_t byte ) const { return data[byte]; } + void update( uint32_t & crc, const uint8_t byte ) const + { crc = data[(crc^byte)&0xFF] ^ ( crc >> 8 ); } + void update( uint32_t & crc, const uint8_t * const buffer, const int size ) const + { + for( int i = 0; i < size; ++i ) + crc = data[(crc^buffer[i])&0xFF] ^ ( crc >> 8 ); + } + }; + +extern const CRC32 crc32; + + +inline int real_bits( const int value ) + { + int bits = 0; + for( int i = 1, mask = 1; mask > 0; ++i, mask <<= 1 ) + if( value & mask ) bits = i; + return bits; + } + +const uint8_t magic_string[4] = { 'L', 'Z', 'I', 'P' }; + +struct File_header + { + uint8_t data[6]; // 0-3 magic bytes + // 4 version + // 5 coded_dict_size + enum { size = 6 }; + + void set_magic() + { memcpy( data, magic_string, 4 ); data[4] = 1; } + + bool verify_magic() const + { return ( memcmp( data, magic_string, 4 ) == 0 ); } + + uint8_t version() const { return data[4]; } + bool verify_version() const { return ( data[4] <= 1 ); } + + int dictionary_size() const + { + int sz = ( 1 << ( data[5] & 0x1F ) ); + if( sz > min_dictionary_size && sz <= max_dictionary_size ) + sz -= ( sz / 16 ) * ( ( data[5] >> 5 ) & 0x07 ); + return sz; + } + + bool dictionary_size( const int sz ) + { + if( sz >= min_dictionary_size && sz <= max_dictionary_size ) + { + data[5] = real_bits( sz - 1 ); + if( sz > min_dictionary_size ) + { + const int base_size = 1 << data[5]; + const int wedge = base_size / 16; + for( int i = 7; i >= 1; --i ) + if( base_size - ( i * wedge ) >= sz ) + { data[5] |= ( i << 5 ); break; } + } + return true; + } + return false; + } + }; + + +struct File_trailer + { + uint8_t data[20]; // 0-3 CRC32 of the uncompressed data + // 4-11 size of the uncompressed data + // 12-19 member size including header and trailer + + static int size( const int version = 1 ) + { return ( ( version >= 1 ) ? 20 : 12 ); } + + uint32_t data_crc() const + { + uint32_t tmp = 0; + for( int i = 3; i >= 0; --i ) { tmp <<= 8; tmp += data[i]; } + return tmp; + } + + void data_crc( uint32_t crc ) + { for( int i = 0; i <= 3; ++i ) { data[i] = (uint8_t)crc; crc >>= 8; } } + + long long data_size() const + { + long long tmp = 0; + for( int i = 11; i >= 4; --i ) { tmp <<= 8; tmp += data[i]; } + return tmp; + } + + void data_size( long long sz ) + { + for( int i = 4; i <= 11; ++i ) { data[i] = (uint8_t)sz; sz >>= 8; } + } + + long long member_size() const + { + long long tmp = 0; + for( int i = 19; i >= 12; --i ) { tmp <<= 8; tmp += data[i]; } + return tmp; + } + + void member_size( long long sz ) + { + for( int i = 12; i <= 19; ++i ) { data[i] = (uint8_t)sz; sz >>= 8; } + } + }; + + +struct Error + { + const char * const msg; + Error( const char * const s ) : msg( s ) {} + }; + + +// defined in main.cc lziprecover.cc +void show_error( const char * const msg, const int errcode = 0, + const bool help = false ); +void internal_error( const char * const msg ); + +// defined in decoder.cc +int readblock( const int fd, uint8_t * const buf, const int size ); +int writeblock( const int fd, const uint8_t * const buf, const int size ); + +// XXX +extern void pp(const char *p=NULL); + diff --git a/third_party/lzma.js/lzip/main.cc b/third_party/lzma.js/lzip/main.cc new file mode 100644 index 00000000..86465b0a --- /dev/null +++ b/third_party/lzma.js/lzip/main.cc @@ -0,0 +1,545 @@ +/* Lzip - Data compressor based on the LZMA algorithm + Copyright (C) 2008, 2009, 2010, 2011 Antonio Diaz Diaz. + + 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 <http://www.gnu.org/licenses/>. +*/ +/* + Return values: 0 for a normal exit, 1 for environmental problems + (file not found, invalid flags, I/O errors, etc), 2 to indicate a + corrupt or invalid input file, 3 for an internal consistency error + (eg, bug) which caused lzip to panic. +*/ + +#define _FILE_OFFSET_BITS 64 + +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <stdint.h> +#include <unistd.h> +#include <utime.h> +#include <sys/stat.h> +#if defined(__MSVCRT__) +#include <io.h> +#define fchmod(x,y) 0 +#define fchown(x,y,z) 0 +#define SIGHUP SIGTERM +#define S_ISSOCK(x) 0 +#define S_IRGRP 0 +#define S_IWGRP 0 +#define S_IROTH 0 +#define S_IWOTH 0 +#endif +#if defined(__OS2__) +#include <io.h> +#endif + +#include "lzip.h" +#include "decoder.h" + +#if !DECODER_ONLY +#include "encoder.h" +#include "fast_encoder.h" +#endif + +#if CHAR_BIT != 8 +#error "Environments where CHAR_BIT != 8 are not supported." +#endif + +#ifndef LLONG_MAX +#define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL +#endif +#ifndef LLONG_MIN +#define LLONG_MIN (-LLONG_MAX - 1LL) +#endif +#ifndef ULLONG_MAX +#define ULLONG_MAX 0xFFFFFFFFFFFFFFFFULL +#endif + + +void pp(const char *p) { if (p) fputs(p, stderr); } + +namespace { + +const char * const Program_name = "Lzip"; +const char * const program_name = "lzip"; +const char * const program_year = "2011"; +const char * invocation_name = 0; + +#ifdef O_BINARY +const int o_binary = O_BINARY; +#else +const int o_binary = 0; +#endif + +struct { const char * from; const char * to; } const known_extensions[] = { +{ ".lz", "" }, +{ ".tlz", ".tar" }, +{ 0, 0 } }; + +struct Lzma_options +{ + int dictionary_size; // 4KiB..512MiB + int match_len_limit; // 5..273 +}; + +enum Mode { m_compress, m_decompress, m_test }; + +int outfd = -1; +int verbosity = 0; +bool delete_output_on_interrupt = false; + + +void show_help() +{ + printf( "%s - Data compressor based on the LZMA algorithm.\n", Program_name ); + printf( "<< Most of these are unsupported. Compressing/decompressing from stdin to stdout is the right way! >>\n" ); + printf( "\nUsage: %s [options] [files]\n", invocation_name ); + printf( "\nOptions:\n" ); + printf( " -h, --help display this help and exit\n" ); + printf( " -V, --version output version information and exit\n" ); + printf( " -b, --member-size=<n> set member size limit in bytes\n" ); + printf( " -c, --stdout send output to standard output\n" ); + printf( " -d, --decompress decompress\n" ); + printf( " -f, --force overwrite existing output files\n" ); + printf( " -F, --recompress force recompression of compressed files\n" ); + printf( " -k, --keep keep (don't delete) input files\n" ); + printf( " -m, --match-length=<n> set match length limit in bytes [36]\n" ); + printf( " -o, --output=<file> if reading stdin, place the output into <file>\n" ); + printf( " -q, --quiet suppress all messages\n" ); + printf( " -s, --dictionary-size=<n> set dictionary size limit in bytes [8MiB]\n" ); + printf( " -S, --volume-size=<n> set volume size limit in bytes\n" ); + printf( " -t, --test test compressed file integrity\n" ); + printf( " -v, --verbose be verbose (a 2nd -v gives more)\n" ); + printf( " -0 .. -9 set compression level [default 6]\n" ); + printf( " --fast alias for -0\n" ); + printf( " --best alias for -9\n" ); + printf( "If no file names are given, %s compresses or decompresses\n", program_name ); + printf( "from standard input to standard output.\n" ); + printf( "Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n" ); + printf( "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n" ); + printf( "\nReport bugs to lzip-bug@nongnu.org\n" ); + printf( "Lzip home page: http://www.nongnu.org/lzip/lzip.html\n" ); +} + + +void show_version() +{ + printf( "%s %s\n", Program_name, PROGVERSION ); + printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year ); + printf( "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n" ); + printf( "This is free software: you are free to change and redistribute it.\n" ); + printf( "There is NO WARRANTY, to the extent permitted by law.\n" ); +} + + +const char * format_num( long long num ) +{ + const char * const prefix[8] = + { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" }; + enum { buf_size = 16, factor = 1024 }; + static char buf[buf_size]; + const char *p = ""; + + for( int i = 0; i < 8 && ( llabs( num ) > 9999 || + ( llabs( num ) >= factor && num % factor == 0 ) ); ++i ) + { num /= factor; p = prefix[i]; } + snprintf( buf, buf_size, "%lld %s", num, p ); + return buf; +} + + +bool open_outstream( const bool force ) +{ + return false; +} + + +bool check_tty( const int infd, const Mode program_mode ) +{ + if( program_mode == m_compress && outfd >= 0 && isatty( outfd ) ) + { + show_error( "I won't write compressed data to a terminal.", 0, true ); + return false; + } + if( ( program_mode == m_decompress || program_mode == m_test ) && + isatty( infd ) ) + { + show_error( "I won't read compressed data from a terminal.", 0, true ); + return false; + } + return true; +} + + +void cleanup_and_fail( const int retval ) +{ + exit( retval ); +} + + + // Set permissions, owner and times. +void close_and_set_permissions( const struct stat * const in_statsp ) +{ + bool error = false; + if( in_statsp ) + { + if( ( fchown( outfd, in_statsp->st_uid, in_statsp->st_gid ) != 0 && + errno != EPERM ) || + fchmod( outfd, in_statsp->st_mode ) != 0 ) + error = true; + // fchown will in many cases return with EPERM, which can be safely ignored. + } + if( close( outfd ) == 0 ) outfd = -1; + else cleanup_and_fail( 1 ); + delete_output_on_interrupt = false; + if( !in_statsp ) return; + if( !error ) + { + struct utimbuf t; + t.actime = in_statsp->st_atime; + t.modtime = in_statsp->st_mtime; + //if( utime( output_filename.c_str(), &t ) != 0 ) error = true; + } + if( error ) + { + show_error( "Can't change output file attributes." ); + cleanup_and_fail( 1 ); + } +} + + +bool next_filename() +{ + return false; +} + +#if !DECODER_ONLY +int compress( const long long member_size, const long long volume_size, + const Lzma_options & encoder_options, const int infd, + const struct stat * const in_statsp ) +{ + File_header header; + header.set_magic(); + if( !header.dictionary_size( encoder_options.dictionary_size ) || + encoder_options.match_len_limit < min_match_len_limit || + encoder_options.match_len_limit > max_match_len ) + internal_error( "invalid argument to encoder" ); + int retval = 0; + + Matchfinder matchfinder( header.dictionary_size(), + encoder_options.match_len_limit, infd ); + header.dictionary_size( matchfinder.dictionary_size() ); + + long long in_size = 0, out_size = 0, partial_volume_size = 0; + while( true ) // encode one member per iteration + { + LZ_encoder encoder( matchfinder, header, outfd ); + const long long size = + min( member_size, volume_size - partial_volume_size ); + if( !encoder.encode_member( size ) ) + { pp( "Encoder error" ); retval = 1; break; } + in_size += matchfinder.data_position(); + out_size += encoder.member_position(); + if( matchfinder.finished() ) break; + partial_volume_size += encoder.member_position(); + if( partial_volume_size >= volume_size - min_dictionary_size ) + { + partial_volume_size = 0; + if( delete_output_on_interrupt ) + { + close_and_set_permissions( in_statsp ); + if( !next_filename() ) + { pp( "Too many volume files" ); retval = 1; break; } + if( !open_outstream( true ) ) { retval = 1; break; } + delete_output_on_interrupt = true; + } + } + matchfinder.reset(); + } + + if( retval == 0 && verbosity >= 1 ) + { + if( in_size <= 0 || out_size <= 0 ) + fprintf( stderr, "No data compressed.\n" ); + else + fprintf( stderr, "%6.3f:1, %6.3f bits/byte, " + "%5.2f%% saved, %lld in, %lld out.\n", + (double)in_size / out_size, + ( 8.0 * out_size ) / in_size, + 100.0 * ( 1.0 - ( (double)out_size / in_size ) ), + in_size, out_size ); + } + return retval; +} + + +int fcompress( const long long member_size, const long long volume_size, + const int infd, + const struct stat * const in_statsp ) +{ + if( verbosity >= 1 ) pp(); + File_header header; + header.set_magic(); + int retval = 0; + + Fmatchfinder fmatchfinder( infd ); + header.dictionary_size( fmatchfinder.dictionary_size() ); + + long long in_size = 0, out_size = 0, partial_volume_size = 0; + while( true ) // encode one member per iteration + { + FLZ_encoder encoder( fmatchfinder, header, outfd ); + const long long size = + min( member_size, volume_size - partial_volume_size ); + if( !encoder.encode_member( size ) ) + { pp( "Encoder error" ); retval = 1; break; } + in_size += fmatchfinder.data_position(); + out_size += encoder.member_position(); + if( fmatchfinder.finished() ) break; + partial_volume_size += encoder.member_position(); + if( partial_volume_size >= volume_size - min_dictionary_size ) + { + partial_volume_size = 0; + if( delete_output_on_interrupt ) + { + close_and_set_permissions( in_statsp ); + if( !next_filename() ) + { pp( "Too many volume files" ); retval = 1; break; } + if( !open_outstream( true ) ) { retval = 1; break; } + delete_output_on_interrupt = true; + } + } + fmatchfinder.reset(); + } + + if( retval == 0 && verbosity >= 1 ) + { + if( in_size <= 0 || out_size <= 0 ) + fprintf( stderr, "No data compressed.\n" ); + else + fprintf( stderr, "%6.3f:1, %6.3f bits/byte, " + "%5.2f%% saved, %lld in, %lld out.\n", + (double)in_size / out_size, + ( 8.0 * out_size ) / in_size, + 100.0 * ( 1.0 - ( (double)out_size / in_size ) ), + in_size, out_size ); + } + return retval; +} +#endif + +int decompress( const int infd, const bool testing ) +{ + int retval = 0; + + Range_decoder rdec( infd ); + long long partial_file_pos = 0; + for( bool first_member = true; ; first_member = false ) + { + File_header header; + int size; + rdec.reset_member_position(); + for( size = 0; size < File_header::size && !rdec.finished(); ++size ) + header.data[size] = rdec.get_byte(); + if( rdec.finished() ) // End Of File + { + if( first_member ) + { pp( "Error reading member header" ); retval = 1; } + break; + } + if( !header.verify_magic() ) + { + if( first_member ) + { pp( "Bad magic number (file not in lzip format)" ); retval = 2; } + break; + } + if( !header.verify_version() ) + { + if( verbosity >= 0 ) + { pp(); + fprintf( stderr, "Version %d member format not supported.\n", + header.version() ); } + retval = 2; break; + } + if( header.dictionary_size() < min_dictionary_size || + header.dictionary_size() > max_dictionary_size ) + { pp( "Invalid dictionary size in member header" ); retval = 2; break; } + + if( verbosity >= 2 || ( verbosity == 1 && first_member ) ) + { + pp(); + if( verbosity >= 2 ) + fprintf( stderr, "version %d, dictionary size %7sB. ", + header.version(), + format_num( header.dictionary_size() ) ); + } + LZ_decoder decoder( header, rdec, outfd ); + + const int result = decoder.decode_member(); + partial_file_pos += rdec.member_position(); + if( result != 0 ) + { + if( verbosity >= 0 && result <= 2 ) + { + pp(); + if( result == 2 ) + fprintf( stderr, "File ends unexpectedly at pos %lld\n", + partial_file_pos ); + else + fprintf( stderr, "Decoder error at pos %lld\n", + partial_file_pos ); + } + retval = 2; break; + } + if( verbosity >= 2 ) + { if( testing ) fprintf( stderr, "ok\n" ); + else fprintf( stderr, "done\n" ); } + } + if( verbosity == 1 && retval == 0 ) + { if( testing ) fprintf( stderr, "ok\n" ); + else fprintf( stderr, "done\n" ); } + return retval; +} + + +} // end namespace + + +void show_error( const char * const msg, const int errcode, const bool help ) +{ + if( verbosity >= 0 ) + { + if( msg && msg[0] ) + { + fprintf( stderr, "%s: %s", program_name, msg ); + if( errcode > 0 ) + fprintf( stderr, ": %s", strerror( errcode ) ); + fprintf( stderr, "\n" ); + } + if( help && invocation_name && invocation_name[0] ) + fprintf( stderr, "Try `%s --help' for more information.\n", + invocation_name ); + } +} + + +void internal_error( const char * const msg ) +{ + if( verbosity >= 0 ) + fprintf( stderr, "%s: internal error: %s.\n", program_name, msg ); + exit( 3 ); +} + + +int main( const int argc, const char * const argv[] ) +{ + // Mapping from gzip/bzip2 style 1..9 compression modes + // to the corresponding LZMA compression modes. + const Lzma_options option_mapping[] = + { + { 1 << 16, 16 }, // -0 entry values not used + { 1 << 20, 5 }, // -1 + { 3 << 19, 6 }, // -2 + { 1 << 21, 8 }, // -3 + { 3 << 20, 12 }, // -4 + { 1 << 22, 20 }, // -5 + { 1 << 23, 36 }, // -6 + { 1 << 24, 68 }, // -7 + { 3 << 23, 132 }, // -8 + { 1 << 25, 273 } }; // -9 + Lzma_options encoder_options = option_mapping[6]; // default = "-6" + long long member_size = LLONG_MAX; + long long volume_size = LLONG_MAX; + int infd = -1; + Mode program_mode = m_compress; + bool keep_input_files = false; + bool to_stdout = false; + bool zero = false; + invocation_name = argv[0]; + + // Greatly simplified argument parsing + int argind = 1; + for( ; argind < argc; ++argind ) + { + const int code = argv[argind][1]; + switch( code ) + { + case 'c': to_stdout = true; break; + case 'd': program_mode = m_decompress; break; + case 'h': show_help(); return 0; + case 'k': keep_input_files = true; break; + case 'q': verbosity = -1; break; + zero = false; break; + case 'v': if( verbosity < 4 ) ++verbosity; break; + case 'V': show_version(); return 0; + default : internal_error( "uncaught option" ); + } + } // end process options + +#if defined(__MSVCRT__) || defined(__OS2__) + _setmode( STDIN_FILENO, O_BINARY ); + _setmode( STDOUT_FILENO, O_BINARY ); +#endif + + if( program_mode == m_test ) + outfd = -1; +#if !DECODER_ONLY + else if( program_mode == m_compress ) + { + dis_slots.init(); + prob_prices.init(); + } +#endif + + int retval = 0; + { + struct stat in_stats; + + infd = STDIN_FILENO; + outfd = STDOUT_FILENO; + + if( !check_tty( infd, program_mode ) ) return 1; + + const struct stat * const in_statsp = 0; + //pp.set_name( "-" ); + int tmp = 0; +#if !DECODER_ONLY + if( program_mode == m_compress ) + { + if( zero ) + tmp = fcompress( member_size, volume_size, infd, in_statsp ); + else + tmp = compress( member_size, volume_size, encoder_options, infd, + in_statsp ); + } + else +#endif + tmp = decompress( infd, program_mode == m_test ); + if( tmp > retval ) retval = tmp; + //if( tmp && program_mode != m_test ) cleanup_and_fail( retval ); + + if( delete_output_on_interrupt ) + close_and_set_permissions( in_statsp ); + } + if( outfd >= 0 && close( outfd ) != 0 ) + { + show_error( "Can't close stdout", errno ); + if( retval < 1 ) retval = 1; + } + return retval; +} diff --git a/third_party/lzma.js/lzma-decoder.js b/third_party/lzma.js/lzma-decoder.js new file mode 100644 index 00000000..c2c1f92c --- /dev/null +++ b/third_party/lzma.js/lzma-decoder.js @@ -0,0 +1,27 @@ + +// This is lzma.js, powered by lzip (which is GPL, source code at https://github.com/kripken/lzma.js) +var LZMA = { + run: function(data, decompress) { + var inputIndex = 0; + var returnValue = []; + var Module = { + arguments: ['-q'].concat(decompress ? ['-d'] : []), + stdin: function() { return inputIndex < data.length ? data[inputIndex++] : null }, + stdout: function(x) { if (x !== null) returnValue.push(x) } + }; + + +function a(b){throw b}var ca=void 0,j=!0,l=null,m=!1;try{this.Module=Module}catch(ka){this.Module=Module={}}var la="object"===typeof process,sa="object"===typeof window,Ca="function"===typeof importScripts,Ka=!sa&&!la&&!Ca;if(la){Module.print=(function(b){process.stdout.write(b+"\n")});Module.printErr=(function(b){process.stderr.write(b+"\n")});var bb=require("fs");Module.read=(function(b){var d=bb.readFileSync(b).toString();!d&&"/"!=b[0]&&(b=__dirname.split("/").slice(0,-1).join("/")+"/src/"+b,d=bb.readFileSync(b).toString());return d});Module.load=(function(b){cb(read(b))});Module.arguments=process.argv.slice(2)}else{Ka?(Module.print=print,Module.printErr=printErr,Module.read="undefined"!=typeof read?read:(function(b){snarf(b)}),"undefined"!=typeof scriptArgs?Module.arguments=scriptArgs:"undefined"!=typeof arguments&&(Module.arguments=arguments)):sa?(Module.print||(Module.print=(function(b){console.log(b)})),Module.printErr||(Module.printErr=(function(b){console.log(b)})),Module.read=(function(b){var d=new XMLHttpRequest;d.open("GET",b,m);d.send(l);return d.responseText}),"undefined"!=typeof arguments&&(Module.arguments=arguments)):Ca?Module.load=importScripts:a("Unknown runtime environment. Where are we?")}function cb(b){eval.call(l,b)}"undefined"==!Module.load&&Module.read&&(Module.load=(function(b){cb(Module.read(b))}));Module.printErr||(Module.printErr=(function(){}));Module.print||(Module.print=Module.printErr);Module.arguments||(Module.arguments=[]);function db(b){if(1==vb){return 1}var d={"%i1":1,"%i8":1,"%i16":2,"%i32":4,"%i64":8,"%float":4,"%double":8}["%"+b];d||("*"==b[b.length-1]?d=vb:"i"==b[0]&&(b=parseInt(b.substr(1)),wb(0==b%8),d=b/8));return d}function xb(b){var d=n;n+=b;n=n+3>>2<<2;return d}function Hb(b){var d=Ib;Ib+=b;Ib=Ib+3>>2<<2;if(Ib>=Qb){for(;Qb<=Ib;){Qb=2*Qb+4095>>12<<12}var b=p,c=new ArrayBuffer(Qb);p=new Int8Array(c);Rb=new Int16Array(c);r=new Int32Array(c);s=new Uint8Array(c);Sb=new Uint16Array(c);z=new Uint32Array(c);Tb=new Float32Array(c);Ub=new Float64Array(c);p.set(b)}return d}var vb=4,Vb={},Yb,B,Zb;function $b(b){Module.print(b+":\n"+Error().stack);a("Assertion: "+b)}function wb(b,d){b||$b("Assertion failed: "+d)}var bc=this;Module.ccall=(function(b,d,c,e){try{var f=eval("_"+b)}catch(i){try{f=bc.Module["_"+b]}catch(h){}}wb(f,"Cannot call unknown function "+b+" (perhaps LLVM optimizations or closure removed it?)");var g=0,b=e?e.map((function(b){if("string"==c[g++]){var d=n;xb(b.length+1);cc(b,d);b=d}return b})):[];return(function(b,c){return"string"==c?dc(b):b})(f.apply(l,b),d)});function ec(b,d,c){c=c||"i8";"*"===c[c.length-1]&&(c="i32");switch(c){case"i1":p[b]=d;break;case"i8":p[b]=d;break;case"i16":Rb[b>>1]=d;break;case"i32":r[b>>2]=d;break;case"i64":r[b>>2]=d;break;case"float":Tb[b>>2]=d;break;case"double":fc[0]=d;r[b>>2]=gc[0];r[b+4>>2]=gc[1];break;default:$b("invalid type for setValue: "+c)}}Module.setValue=ec;Module.getValue=(function(b,d){d=d||"i8";"*"===d[d.length-1]&&(d="i32");switch(d){case"i1":return p[b];case"i8":return p[b];case"i16":return Rb[b>>1];case"i32":return r[b>>2];case"i64":return r[b>>2];case"float":return Tb[b>>2];case"double":return gc[0]=r[b>>2],gc[1]=r[b+4>>2],fc[0];default:$b("invalid type for setValue: "+d)}return l});var hc=1,D=2;Module.ALLOC_NORMAL=0;Module.ALLOC_STACK=hc;Module.ALLOC_STATIC=D;function F(b,d,c){var e,f;"number"===typeof b?(e=j,f=b):(e=m,f=b.length);var i="string"===typeof d?d:l,c=[ic,xb,Hb][c===ca?D:c](Math.max(f,i?1:d.length));if(e){return jc(c,f),c}e=0;for(var h;e<f;){var g=b[e];"function"===typeof g&&(g=Vb.Ua(g));h=i||d[e];0===h?e++:("i64"==h&&(h="i32"),ec(c+e,g,h),e+=db(h))}return c}Module.allocate=F;function dc(b,d){for(var c="undefined"==typeof d,e="",f=0,i,h=String.fromCharCode(0);;){i=String.fromCharCode(s[b+f]);if(c&&i==h){break}e+=i;f+=1;if(!c&&f==d){break}}return e}Module.Pointer_stringify=dc;Module.Array_stringify=(function(b){for(var d="",c=0;c<b.length;c++){d+=String.fromCharCode(b[c])}return d});var lc,mc=4096,p,s,Rb,Sb,r,z,Tb,Ub,n,nc,Ib,oc=Module.TOTAL_STACK||5242880,Qb=Module.TOTAL_MEMORY||10485760;wb(!!Int32Array&&!!Float64Array&&!!(new Int32Array(1)).subarray&&!!(new Int32Array(1)).set,"Cannot fallback to non-typed array case: Code is too specialized");var pc=new ArrayBuffer(Qb);p=new Int8Array(pc);Rb=new Int16Array(pc);r=new Int32Array(pc);s=new Uint8Array(pc);Sb=new Uint16Array(pc);z=new Uint32Array(pc);Tb=new Float32Array(pc);Ub=new Float64Array(pc);r[0]=255;wb(255===s[0]&&0===s[3],"Typed arrays 2 must be run on a little-endian system");var rc=qc("(null)");Ib=rc.length;for(var sc=0;sc<rc.length;sc++){p[sc]=rc[sc]}Module.HEAP=ca;Module.HEAP8=p;Module.HEAP16=Rb;Module.HEAP32=r;Module.HEAPU8=s;Module.HEAPU16=Sb;Module.HEAPU32=z;Module.HEAPF32=Tb;Module.HEAPF64=Ub;nc=(n=4*Math.ceil(Ib/4))+oc;var tc=8*Math.ceil(nc/8);p.subarray(tc);var gc=r.subarray(tc>>2);Tb.subarray(tc>>2);var fc=Ub.subarray(tc>>3);nc=tc+8;Ib=nc+4095>>12<<12;function uc(b){for(;0<b.length;){var d=b.shift(),c=d.l;"number"===typeof c&&(c=lc[c]);c(d.Pa===ca?l:d.Pa)}}var vc=[],yc=[];function zc(b,d){return Array.prototype.slice.call(p.subarray(b,b+d))}Module.Array_copy=zc;Module.TypedArray_copy=(function(b,d){for(var c=new Uint8Array(d),e=0;e<d;++e){c[e]=p[b+e]}return c.buffer});function Ac(b){for(var d=0;p[b+d];){d++}return d}Module.String_len=Ac;function Bc(b,d){var c=Ac(b);d&&c++;var e=zc(b,c);d&&(e[c-1]=0);return e}Module.String_copy=Bc;function qc(b,d){for(var c=[],e=0;e<b.length;){var f=b.charCodeAt(e);255<f&&(f&=255);c.push(f);e+=1}d||c.push(0);return c}Module.intArrayFromString=qc;Module.intArrayToString=(function(b){for(var d=[],c=0;c<b.length;c++){var e=b[c];255<e&&(e&=255);d.push(String.fromCharCode(e))}return d.join("")});function cc(b,d,c){for(var e=0;e<b.length;){var f=b.charCodeAt(e);255<f&&(f&=255);p[d+e]=f;e+=1}c||(p[d+e]=0)}Module.writeStringToMemory=cc;var I=[];function Cc(b,d){return 0<=b?b:32>=d?2*Math.abs(1<<d-1)+b:Math.pow(2,d)+b}function Dc(b,d){if(0>=b){return b}var c=32>=d?Math.abs(1<<d-1):Math.pow(2,d-1);if(b>=c&&(32>=d||b>c)){b=-2*c+b}return b}function Ec(b,d,c){var e=0>(c|0)?-1:0,f=(c>>>0)+4294967296*(e|0)+(b>>>0)+4294967296*(d|0)>>>0,b=Math.min(Math.floor(((c>>>0)+4294967296*(e|0)+(b>>>0)+4294967296*(d|0))/4294967296),4294967295);return[f,b]}function Fc(b,d,c){var e=0>(c|0)?-1:0,f=(c>>>0)+4294967296*(e|0)+(b>>>0)+4294967296*(d|0)>>>0,b=Math.min(Math.floor(((c>>>0)+4294967296*(e|0)+(b>>>0)+4294967296*(d|0))/4294967296),4294967295);return[f,b]}function Gc(b){var d=p[b+11|0],c=p[b+10|0]|d<<8|0,e=p[b+9|0]|c<<8|0,f=p[b+8|0]|e<<8|0,i=p[b+7|0]|f<<8|0,h=p[b+6|0]|i<<8|0,g=p[b+5|0]|h<<8|0;return[p[b+4|0]|g<<8|0,0|((((((0|d>>>24)<<8|c>>>24)<<8|e>>>24)<<8|f>>>24)<<8|i>>>24)<<8|h>>>24)<<8|g>>>24]}Gc.X=1;function Hc(b){var d=p[b+19|0],c=p[b+18|0]|d<<8|0,e=p[b+17|0]|c<<8|0,f=p[b+16|0]|e<<8|0,i=p[b+15|0]|f<<8|0,h=p[b+14|0]|i<<8|0,g=p[b+13|0]|h<<8|0;return[p[b+12|0]|g<<8|0,0|((((((0|d>>>24)<<8|c>>>24)<<8|e>>>24)<<8|f>>>24)<<8|i>>>24)<<8|h>>>24)<<8|g>>>24]}Hc.X=1;function Ic(b){var d,c;c=(b+20|0)>>2;d=(b+24|0)>>2;var e=r[d],f=r[c]-e|0;if(0<(f|0)){var i=b+16|0,h=b+28|0,e=r[i>>2]+e|0,g=0<(f|0);a:do{if(g){for(var k=0,o=r[h>>2];;){if(o=r[Jc+((s[e+k|0]&255^o&255)<<2)>>2]^o>>>8,r[h>>2]=o,k=k+1|0,(k|0)==(f|0)){break a}}}}while(0);h=r[b+32>>2];if(e=-1<(h|0)){i=r[i>>2]+r[d]|0;r[Kc>>2]=0;e=f;a:for(;;){g=i+(f-e)|0;if(0>=(e|0)){var w=0;break}for(;;){r[Kc>>2]=0;var t=Lc(h,g,e);if(0<(t|0)){break}if(0!=(r[Kc>>2]|0)&&4!=(r[Kc>>2]|0)&&11!=(r[Kc>>2]|0)){w=e;break a}}e=e-t|0}e=(f-w|0)!=(f|0)}e&&Mc(-1);f=r[c];(f|0)<(r[b+12>>2]|0)?c=f:(w=0>(f|0)?-1:0,b=(b|0)>>2,i=r[b],h=r[b+1],t=(i>>>0)+4294967296*(h|0)+(f>>>0)+4294967296*(w|0)>>>0,f=Math.min(Math.floor(((i>>>0)+4294967296*(h|0)+(f>>>0)+4294967296*(w|0))/4294967296),4294967295),r[b]=t,r[b+1]=f,c=r[c]=0);r[d]=c}}function Nc(b){var d,c=n;n+=20;var e=b+36|0,f=0<(r[e>>2]|0)?20:12;d=(b+40|0)>>2;for(var i=r[d],h=i|0,i=Ec(r[h>>2],r[h+4>>2],r[i+12>>2]),h=i[0],g=i[1],k=0>(f|0)?-1:0,i=(h>>>0)+4294967296*(g|0)+(f>>>0)+4294967296*(k|0)>>>0,h=Math.min(Math.floor(((h>>>0)+4294967296*(g|0)+(f>>>0)+4294967296*(k|0))/4294967296),4294967295),k=g=0;(g|0)<(f|0);){if(0!=(k&1)<<24>>24){break}if(Oc(r[d])){jc(c+g|0,f-g|0),g=f,k=1}else{var o=Pc(r[d]);p[c+g|0]=o}g=g+1|0}0==(r[e>>2]|0)&&(p[c+12|0]=i&255,p[c+13|0]=(i>>>8|h<<24)&255,p[c+14|0]=(i>>>16|h<<16)&255,p[c+15|0]=(i>>>24|h<<8)&255,p[c+16|0]=h&255,p[c+17|0]=(h>>>8|0)&255,p[c+18|0]=(h>>>16|0)&255,p[c+19|0]=(h>>>24|0)&255);0==(r[r[d]+20>>2]|0)?d=k:(Qc(I.G|0),d=1);e=(s[c|0]&255|(s[c+1|0]&255|(s[c+2|0]&255|(s[c+3|0]&255)<<8)<<8)<<8|0)==(r[b+28>>2]^-1|0);g=Gc(c);f=g[0];g=g[1];k=b|0;b=Fc(r[k>>2],r[k+4>>2],r[b+20>>2]);k=Hc(c);b=(k[0]==i&&k[1]==h)&(f==b[0]&&g==b[1])&e&0==(d&1)<<24>>24;n=c;return b}Nc.X=1;function Oc(b){if((r[b+12>>2]|0)<(r[b+16>>2]|0)){b=0}else{var d=b+32|0;if(0==(p[d]&1)<<24>>24){var c;c=r[b+28>>2];var e=r[b+8>>2];r[Kc>>2]=0;var f=16384;a:for(;;){var i=e+(16384-f)|0;if(0>=(f|0)){var h=0;break}for(;;){r[Kc>>2]=0;var g=Rc(c,i,f);if(0<(g|0)){break}if(0==(g|0)){h=f;break a}if(4!=(r[Kc>>2]|0)&&11!=(r[Kc>>2]|0)){h=f;break a}}f=f-g|0}c=16384-h|0;e=b+16|0;r[e>>2]=c;16384!=(c|0)&&0!=(r[Kc>>2]|0)&&Mc(-1);c=z[e>>2];p[d]=16384>(c|0)&1;d=b+12|0;e=r[d>>2];f=0>(e|0)?-1:0;b=(b|0)>>2;h=r[b];g=r[b+1];i=(h>>>0)+4294967296*(g|0)+(e>>>0)+4294967296*(f|0)>>>0;e=Math.min(Math.floor(((h>>>0)+4294967296*(g|0)+(e>>>0)+4294967296*(f|0))/4294967296),4294967295);r[b]=i;r[b+1]=e;d=r[d>>2]=0;b=c}else{d=r[b+12>>2],b=r[b+16>>2]}b=(d|0)<(b|0)^1}return b}function Pc(b){if(Oc(b)){b=85}else{var d=b+12|0,c=r[d>>2];r[d>>2]=c+1|0;b=p[r[b+8>>2]+c|0]}return b}function Sc(b){var d,c=n;n+=29280;for(var e,f=c+192,i=c+240,h=c+288,g=c+336,k=c+384,o=c+576,w=c+1600,t=c+2060,A=c+2124,y=c+3412,C=c+4700,v=c+29276,u=c+192|0,x=c|0;;){J(x);var q=x+4|0;if((q|0)==(u|0)){break}x=q}J(f|0);J(f+4|0);J(f+8|0);J(f+12|0);J(f+16|0);J(f+20|0);J(f+24|0);J(f+28|0);J(f+32|0);J(f+36|0);J(f+40|0);J(f+44|0);J(i|0);J(i+4|0);J(i+8|0);J(i+12|0);J(i+16|0);J(i+20|0);J(i+24|0);J(i+28|0);J(i+32|0);J(i+36|0);J(i+40|0);J(i+44|0);J(h|0);J(h+4|0);J(h+8|0);J(h+12|0);J(h+16|0);J(h+20|0);J(h+24|0);J(h+28|0);J(h+32|0);J(h+36|0);J(h+40|0);J(h+44|0);J(g|0);J(g+4|0);J(g+8|0);J(g+12|0);J(g+16|0);J(g+20|0);J(g+24|0);J(g+28|0);J(g+32|0);J(g+36|0);J(g+40|0);J(g+44|0);for(var E=k+192|0,G=k|0;;){J(G);var M=G+4|0;if((M|0)==(E|0)){break}G=M}for(var W=o+1024|0,H=o|0;;){J(H);var Q=H+4|0;if((Q|0)==(W|0)){break}H=Q}for(var K=w+460|0,V=w|0;;){J(V);var Da=V+4|0;if((Da|0)==(K|0)){break}V=Da}var qa=t|0;J(qa);J(t+4|0);J(t+8|0);J(t+12|0);J(t+16|0);J(t+20|0);J(t+24|0);J(t+28|0);J(t+32|0);J(t+36|0);J(t+40|0);J(t+44|0);J(t+48|0);J(t+52|0);J(t+56|0);J(t+60|0);Tc(A);Tc(y);for(var yb=C+24576|0,eb=C|0;;){J(eb);var La=eb+4|0;if((La|0)==(yb|0)){break}eb=La}p[v|0]=0;d=(b+40|0)>>2;Uc(r[d]);var Ea=b+8|0,Ma=b+20|0,fb=b|0,zb=v|0,$=0,ma=0,fa=0,S=0;a:for(;;){b:for(;;){if(Oc(r[d])){Ic(b);var na=2;break a}var oa=fb|0,gb=fb+4|0,Na=Fc(r[oa>>2],r[gb>>2],r[Ma>>2])[0]&3,Ab=s[zb],ra=Ab&255;if(0==(Vc(r[d],(ra<<4)+(Na<<2)+c|0)|0)){var Oa,Jb=r[b+20>>2];Oa=p[r[b+16>>2]+((0<(Jb|0)?Jb:r[b+12>>2])-1)|0];var U=r[d];if(7>(Ab&255)){var aa=Wc(U,C+3072*((Oa&255)>>5)|0,8)&255;Xc(b,aa)}else{for(var ta=r[b+20>>2]-$-1|0,Fa=U,Pa=C+3072*((Oa&255)>>5)|0,hb=p[r[b+16>>2]+(0>(ta|0)?r[b+12>>2]+ta|0:ta)|0]&255,ib=ca,Y=7,jb=1;;){if(-1>=(Y|0)){var Qa=jb,ib=7;break}var Ra=hb>>>(Y>>>0)&1,Sa=Vc(Fa,((Ra<<8)+jb+256<<2)+Pa|0),kb=Sa|jb<<1;if((Ra|0)!=(Sa|0)){ib=4;break}Y=Y-1|0;jb=kb}c:do{if(4==ib){if(0<(Y|0)){for(var ua=kb,va=Y;;){var Ta=va-1|0,Bb=ua<<1,lb=Vc(Fa,(ua<<2)+Pa|0)|Bb;if(0>=(Ta|0)){Qa=lb;break c}ua=lb;va=Ta}}else{Qa=kb}}}while(0);Xc(b,Qa&255)}var ga=v|0;p[ga]=p[I.D+(s[ga]&255)|0]}else{var Ga=Vc(r[d],(ra<<2)+f|0),Wb=z[d];if(1==(Ga|0)){var Kb=1==(Vc(Wb,(ra<<2)+i|0)|0),Cb=r[d];do{if(!Kb){if(0!=(Vc(Cb,(ra<<4)+(Na<<2)+k|0)|0)){var mb=$,nb=ma,N=fa,da=S;break}var ba=v|0;p[ba]=p[I.B+(s[ba]&255)|0];var Ha=$,Ua=ma,Va=fa,Wa=S,wa=1;e=37;break b}if(0==(Vc(Cb,(ra<<2)+h|0)|0)){mb=ma,nb=$,N=fa,da=S}else{var Lb=0==(Vc(r[d],(ra<<2)+g|0)|0),Mb=Lb?S:fa,mb=Lb?fa:S,nb=$,N=ma,da=Mb}}while(0);var Nb=v|0;p[Nb]=p[I.C+(s[Nb]&255)|0];var Xb=Yc(y,r[d],Na),Ha=mb,Ua=nb,Va=N,Wa=da,wa=Xb+2|0;e=37;break}var Xa=Yc(A,Wb,Na),ha=Xa+2|0,Z=ha-2|0,xa=Wc(r[d],((3<(Z|0)?3:Z)<<8)+o|0,6);if(4>(xa|0)){var ya=xa;e=33;break}var Db=xa>>1,ob=Db-1|0,Ya=(xa&1|2)<<ob,Eb=r[d];if(14>(xa|0)){ya=Zc(Eb,(Ya-xa<<2)+w|0,ob)+Ya|0;e=33;break}var pb=Eb,qb=Db-5|0,ia=ca,za=ca,Aa=0<(qb|0);c:do{if(Aa){for(var za=(pb+24|0)>>2,ia=(pb+20|0)>>2,ja=0,rb=qb,ea=r[za];;){var Za=ja<<1;if(16777216>ea>>>0){r[za]=ea<<7;var Ob=r[ia]<<8,sb=Pc(pb)&255|Ob;r[ia]=sb;var Ia=z[za];if(sb>>>0<Ia>>>0){var Ja=Za,tb=Ia}else{r[ia]=sb-Ia|0,Ja=Za|1,tb=Ia}}else{var $a=ea>>>1;r[za]=$a;var Fb=z[ia];Fb>>>0<$a>>>0?Ja=Za:(r[ia]=Fb-$a|0,Ja=Za|1);tb=$a}var pa=rb-1|0;if(0>=(pa|0)){var Gb=Ja;break c}ja=Ja;rb=pa;ea=tb}}else{Gb=0}}while(0);var ub=Gb<<4,Ba=Zc(r[d],qa,4),Pb=ub+Ya+Ba|0;if(-1!=(Pb|0)){ya=Pb;e=33;break}$c(r[d]);Ic(b);if(0==(Xa|0)){na=Nc(b)?0:3;break a}if(3!=(ha|0)){na=4;break a}Uc(r[d])}}do{if(33==e){var ab=v|0;p[ab]=p[I.F+(s[ab]&255)|0];if(ya>>>0<z[Ea>>2]>>>0){if(ya>>>0<z[Ma>>2]>>>0){Ha=ya;Ua=$;Va=ma;Wa=fa;wa=ha;break}oa=fb|0;gb=fb+4|0;if(!(0==r[oa>>2]&&0==r[gb>>2])){Ha=ya;Ua=$;Va=ma;Wa=fa;wa=ha;break}}Ic(b);na=1;break a}}while(0);ad(b,Ha,wa);$=Ha;ma=Ua;fa=Va;S=Wa}n=c;return na}Sc.X=1;function Uc(b){var d;d=(b+20|0)>>2;r[d]=0;r[b+24>>2]=-1;var c=Pc(b)&255;r[d]=c;c=Pc(b)&255|c<<8;r[d]=c;c=Pc(b)&255|c<<8;r[d]=c;c=Pc(b)&255|c<<8;r[d]=c;c<<=8;b=Pc(b);r[d]=b&255|c}function J(b){r[b>>2]=1024}function Vc(b,d){var c,e;$c(b);e=(b+24|0)>>2;var f=z[e];c=(d|0)>>2;var i=(f>>>11)*r[c]|0,h=b+20|0,g=z[h>>2];g>>>0<i>>>0?(r[e]=i,f=z[c],e=0,f=((2048-f|0)>>>5)+f|0):(r[e]=f-i|0,r[h>>2]=g-i|0,f=z[c],e=1,f=f-(f>>>5)|0);r[c]=f;return e}function Xc(b,d){var c;c=(b+20|0)>>2;p[r[b+16>>2]+r[c]|0]=d;var e=r[c]+1|0;r[c]=e;(e|0)<(r[b+12>>2]|0)||Ic(b)}function Yc(b,d,c){return 0==(Vc(d,b|0)|0)?Wc(d,(c<<5)+b+8|0,3):0==(Vc(d,b+4|0)|0)?Wc(d,(c<<5)+b+136|0,3)+8|0:Wc(d,b+264|0,8)+16|0}function Wc(b,d,c){var e=0<(c|0);a:do{if(e){for(var f=1,i=c;;){var h=f<<1,f=Vc(b,(f<<2)+d|0)|h,i=i-1|0;if(0>=(i|0)){var g=f;break a}}}else{g=1}}while(0);return g-(1<<c)|0}function Zc(b,d,c){var e=0<(c|0);a:do{if(e){for(var f=1,i=0,h=0;;){var g=Vc(b,(f<<2)+d|0),f=f<<1;0!=(g|0)&&(i|=1<<h,f|=1);h=h+1|0;if((h|0)==(c|0)){var k=i;break a}}}else{k=0}}while(0);return k}function $c(b){var d=b+24|0,c=z[d>>2];16777216>c>>>0&&(r[d>>2]=c<<8,d=b+20|0,c=r[d>>2]<<8,b=Pc(b)&255|c,r[d>>2]=b)}function ad(b,d,c){var e,f;e=(b+20|0)>>2;var i=r[e],h=i-d-1|0,d=(b+12|0)>>2;f=r[d];h=h+(0>(h|0)?f:0)|0;if((f-((i|0)>(h|0)?i:h)|0)>(c|0)){if(f=i-h|0,((-1<(f|0)?f:-f|0)|0)<(c|0)){f=3}else{f=r[b+16>>2];var g=f+i|0,k=f+h|0;f=c;if(20<=f&&k%2==g%2){if(k%4==g%4){for(f=k+f;k%4;){p[g++]=p[k++]}for(var k=k>>2,g=g>>2,o=f>>2;k<o;){r[g++]=r[k++]}k<<=2;for(g<<=2;k<f;){p[g++]=p[k++]}}else{f=k+f;k%2&&(p[g++]=p[k++]);k>>=1;g>>=1;for(o=f>>1;k<o;){Rb[g++]=Rb[k++]}k<<=1;g<<=1;k<f&&(p[g++]=p[k++])}}else{for(;f--;){p[g++]=p[k++]}}r[e]=r[e]+c|0;f=10}}else{f=3}a:do{if(3==f&&0<(c|0)){for(var g=b+16|0,k=c,o=h,w=i;;){var t=r[g>>2];p[t+w|0]=p[t+o|0];w=r[e]+1|0;r[e]=w;t=r[d];(w|0)<(t|0)?w=t:(Ic(b),w=r[d]);o=o+1|0;k=k-1|0;if(0>=(k|0)){break a}o=(o|0)<(w|0)?o:0;w=r[e]}}}while(0)}ad.X=1;function Tc(b){J(b|0);J(b+4|0);J(b+8|0);J(b+12|0);J(b+16|0);J(b+20|0);J(b+24|0);J(b+28|0);J(b+32|0);J(b+36|0);J(b+40|0);J(b+44|0);J(b+48|0);J(b+52|0);J(b+56|0);J(b+60|0);J(b+64|0);J(b+68|0);J(b+72|0);J(b+76|0);J(b+80|0);J(b+84|0);J(b+88|0);J(b+92|0);J(b+96|0);J(b+100|0);J(b+104|0);J(b+108|0);J(b+112|0);J(b+116|0);J(b+120|0);J(b+124|0);J(b+128|0);J(b+132|0);J(b+136|0);J(b+140|0);J(b+144|0);J(b+148|0);J(b+152|0);J(b+156|0);J(b+160|0);J(b+164|0);J(b+168|0);J(b+172|0);J(b+176|0);J(b+180|0);J(b+184|0);J(b+188|0);J(b+192|0);J(b+196|0);J(b+200|0);J(b+204|0);J(b+208|0);J(b+212|0);J(b+216|0);J(b+220|0);J(b+224|0);J(b+228|0);J(b+232|0);J(b+236|0);J(b+240|0);J(b+244|0);J(b+248|0);J(b+252|0);J(b+256|0);J(b+260|0);for(var d=b+1288|0,b=b+264|0;!(J(b),b=b+4|0,(b|0)==(d|0));){}}Tc.X=1;function Qc(b){0!=(b|0)&&Lc(r[r[bd>>2]+12>>2],b,Ac(b))}function cd(b,d,c){if(-1<(r[dd>>2]|0)){if(0!=(b|0)&&0!=p[b]<<24>>24){ed(r[r[bd>>2]+12>>2],I.H|0,(B=n,n+=8,r[B>>2]=I.i|0,r[B+4>>2]=b,B));if(0<(d|0)){var b=r[r[bd>>2]+12>>2],e;fd||(fd=ic(256));e=fd;if(d in gd){if(255<gd[d].length){L(hd)}else{for(var d=gd[d],f=0;f<d.length;f++){p[e+f]=d.charCodeAt(f)}p[e+f]=0}}else{L(id)}e=fd;ed(b,I.K|0,(B=n,n+=4,r[B>>2]=e,B))}jd(r[r[bd>>2]+12>>2])}b=r[kd>>2];0!=(b|0)&c&&0!=p[b]<<24>>24&&ed(r[r[bd>>2]+12>>2],I.aa|0,(B=n,n+=4,r[B>>2]=b,B))}}function ld(b,d){r[kd>>2]=r[d>>2];var c=1,e=0;a:for(;;){if((c|0)>=(b|0)){(c=2==(e|0))&&(p[md]=0);p[md]=1;var f=ca;if(0==(e|0)&s[md]){if(0==(nd(2)|0)){f=4}else{cd(I.Y|0,0,1);var i=0,f=7}}else{f=4}4==f&&(2>(e-1|0)>>>0?0==(nd(1)|0)?i=1:(cd(I.Z|0,0,1),i=0):i=1);if(!i){f=1;break}i=od(c);i=0<(i|0)?i:0;if(!s[md]){f=i;break}O[2]?(O[2].Ra&&pd(O[2].Ra),delete O[2],e=0):(L(qd),e=-1);if(0==(e|0)){f=i;break}cd(I.ka|0,r[Kc>>2],0);if(1<=(i|0)){f=i;break}f=1;break}var h=p[r[d+(c<<2)>>2]+1|0]<<24>>24;do{if(99==(h|0)||107==(h|0)){var g=e}else{if(100==(h|0)){g=1}else{if(104==(h|0)){i=n;rd(I.fa|0,(B=n,n+=4,r[B>>2]=I.p|0,B));P(I.na|0);e=r[kd>>2];rd(I.ga|0,(B=n,n+=4,r[B>>2]=e,B));P(I.oa|0);P(I.za|0);P(I.Ia|0);P(I.Ja|0);P(I.Ka|0);P(I.La|0);P(I.Ma|0);P(I.Na|0);P(I.Oa|0);P(I.pa|0);P(I.qa|0);P(I.ra|0);P(I.sa|0);P(I.ta|0);P(I.ua|0);P(I.va|0);P(I.wa|0);P(I.xa|0);P(I.ya|0);rd(I.ja|0,(B=n,n+=4,r[B>>2]=I.i|0,B));P(I.Aa|0);P(I.Ba|0);P(I.Ca|0);P(I.Da|0);P(I.Ea|0);n=i;f=0;break a}else{if(113==(h|0)){r[dd>>2]=-1,g=e}else{if(118==(h|0)){g=r[dd>>2],4>(g|0)&&(r[dd>>2]=g+1|0),g=e}else{if(86==(h|0)){i=n;rd(I.$|0,(B=n,n+=8,r[B>>2]=I.p|0,r[B+4>>2]=I.ba|0,B));rd(I.ca|0,(B=n,n+=4,r[B>>2]=I.da|0,B));P(I.Fa|0);P(I.Ga|0);P(I.Ha|0);n=i;f=0;break a}else{-1<(r[dd>>2]|0)&&ed(r[r[bd>>2]+12>>2],I.ha|0,(B=n,n+=8,r[B>>2]=I.i|0,r[B+4>>2]=I.ia|0,B)),Mc(3),g=e}}}}}}}while(0);c=c+1|0;e=g}return f}Module._main=ld;ld.X=1;function sd(b){var b=b&255,d=1<<(b&31);return 536866816>(d-4097|0)>>>0?d-d/16*(b>>>5)|0:d}function od(b){var d=n;n+=88;var c,e=d+36,f=d+44,i=d>>2,h=d|0;r[h>>2]=0;r[h+4>>2]=0;var h=d+8|0,g=td(16384);r[h>>2]=g;r[i+3]=0;r[i+4]=0;r[i+5]=0;r[i+6]=-1;r[i+7]=1;p[d+32|0]=0;for(var h=e+4|0,g=e+5|0,k=d|0,o=d+12|0,i=f+16|0,w=0,t=0,A=1;;){c=-r[d+12>>2]|0;var y=0>(c|0)?-1:0,C=d|0;r[C>>2]=c;r[C+4>>2]=y;for(c=0;6>(c|0);){if(Oc(d)){break}y=Pc(d);p[e+c|0]=y;c=c+1|0}if(Oc(d)){if(!A){c=41;break}Qc(I.la|0);var v=1;c=45;break}a:{c=I.z|0;for(y=0;4>y;y++){var C=p[(e|0)+y],u=p[c+y];if(C!=u){c=C>u?1:-1;break a}}c=0}if(0!=(c|0)){if(!A){c=41;break}Qc(I.ma|0);v=2;c=45;break}y=s[h];if(2<=(y&255)){if(-1>=(r[dd>>2]|0)){v=2;c=45;break}Qc(0);v=y&255;ed(r[r[bd>>2]+12>>2],I.I|0,(B=n,n+=4,r[B>>2]=v,B));v=2;c=45;break}u=sd(p[g]);if(536866816<(u-4096|0)>>>0){Qc(I.J|0);v=2;c=45;break}c=r[dd>>2];c=1<(c|0)?25:1!=(c|0)|A^1?27:25;if(25==c&&(Qc(0),1<(r[dd>>2]|0))){for(var A=r[r[bd>>2]+12>>2],C=0>(u|0)?-1:0,x=ud|0,q=0;8>(q|0);){var E=-1<(C|0)||-1==(C|0)&&4294967295<u>>>0,G=0-((u>>>0)+4294967296*(C|0))>>>0,M=Math.min(Math.floor((0-((u>>>0)+4294967296*(C|0)))/4294967296),4294967295),G=E?u:G,E=E?C:M;if(!(0<(E|0)||0==(E|0)&&9999<G>>>0)){if(!((0<(E|0)||0==(E|0)&&1023<G>>>0)&(0==(u&1023)&&0==(C&0)))){break}}x=(Zb=((u>>>0)+4294967296*(C|0))/1024,0<=Zb?Math.floor(Zb):Math.ceil(Zb))>>>0;C=Math.min(Math.floor((Zb=((u>>>0)+4294967296*(C|0))/1024,0<=Zb?Math.floor(Zb):Math.ceil(Zb))/4294967296),4294967295);u=x;x=r[vd+(q<<2)>>2];q=q+1|0}q=wd|0;C=(B=n,n+=12,r[B>>2]=u,r[B+4>>2]=C,r[B+8>>2]=x,B);C=xd(I.W|0,C);u=Math.min(C.length,15);for(x=0;x<u;x++){p[q+x]=C[x]}p[q+x]=0;y&=255;ed(A,I.L|0,(B=n,n+=8,r[B>>2]=y,r[B+4>>2]=wd|0,B))}A=f;y=e;C=d;u=s[md]?2:-1;x=A>>2;q=A|0;r[q>>2]=0;r[q+4>>2]=0;E=sd(p[y+5|0]);r[(A+8|0)>>2]=E;q=A+12|0;M=65536>(E|0)?65536:E;r[q>>2]=M;E=A+16|0;M=td(-1<(M|0)?M:-1);r[E>>2]=M;r[x+5]=0;r[x+6]=0;r[x+7]=-1;r[x+8]=u;r[(A+36|0)>>2]=p[y+4|0]&255;r[x+10]=C;p[M+(r[q>>2]-1)|0]=0;y=Sc(f);A=Ec(r[k>>2],r[k+4>>2],r[o>>2]);C=A[0];u=A[1];A=(C>>>0)+4294967296*(u|0)+(t>>>0)+4294967296*(w|0)>>>0;w=Math.min(Math.floor(((C>>>0)+4294967296*(u|0)+(t>>>0)+4294967296*(w|0))/4294967296),4294967295);t=z[dd>>2];if(0!=(y|0)){-1<(t|0)&3>(y|0)&&(Qc(0),v=r[r[bd>>2]+12>>2],2==(y|0)?ed(v,I.M|0,(B=n,n+=8,r[B>>2]=A,r[B+4>>2]=w,B)):ed(v,I.N|0,(B=n,n+=8,r[B>>2]=A,r[B+4>>2]=w,B)));v=r[i>>2];0!=(v|0)&&yd(v);v=2;c=45;break}1<(t|0)&&(t=r[r[bd>>2]+12>>2],b?zd(I.n|0,3,1,t):zd(I.o|0,5,1,t));t=r[i>>2];0!=(t|0)&&yd(t);t=A;A=0}41==c&&(1==(r[dd>>2]|0)&&(v=r[r[bd>>2]+12>>2],b?zd(I.n|0,3,1,v):zd(I.o|0,5,1,v)),v=0);b=r[d+8>>2];0!=(b|0)&&yd(b);n=d;return v}od.X=1;function ic(b){var d,c=245>b>>>0;do{if(c){var e=11>b>>>0?16:b+11&-8,f=e>>>3;d=z[R>>2];var i=d>>>(f>>>0);if(0!=(i&3|0)){var b=(i&1^1)+f|0,e=b<<1,c=(e<<2)+R+40|0,f=(e+2<<2)+R+40|0,h=z[f>>2],e=h+8|0,i=z[e>>2];(c|0)==(i|0)?r[R>>2]=d&(1<<b^-1):(i>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!")),r[f>>2]=i,r[i+12>>2]=c);d=b<<3;r[h+4>>2]=d|3;d=h+(d|4)|0;r[d>>2]|=1;h=e;d=38;break}if(e>>>0<=z[R+8>>2]>>>0){var g=e;d=30;break}if(0!=(i|0)){var b=2<<f,b=i<<f&(b|-b),c=(b&-b)-1|0,b=c>>>12&16,h=c>>>(b>>>0),c=h>>>5&8,f=h>>>(c>>>0),h=f>>>2&4,i=f>>>(h>>>0),f=i>>>1&2,i=i>>>(f>>>0),k=i>>>1&1,h=(c|b|h|f|k)+(i>>>(k>>>0))|0,b=h<<1,f=(b<<2)+R+40|0,i=(b+2<<2)+R+40|0,c=z[i>>2],b=c+8|0,k=z[b>>2];(f|0)==(k|0)?r[R>>2]=d&(1<<h^-1):(k>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!")),r[i>>2]=k,r[k+12>>2]=f);h<<=3;d=h-e|0;r[c+4>>2]=e|3;f=c;c=f+e|0;r[f+(e|4)>>2]=d|1;r[f+h>>2]=d;k=z[R+8>>2];0!=(k|0)&&(e=r[R+20>>2],f=k>>>2&1073741822,h=(f<<2)+R+40|0,i=z[R>>2],k=1<<(k>>>3),0==(i&k|0)?(r[R>>2]=i|k,i=h,f=(f+2<<2)+R+40|0):(f=(f+2<<2)+R+40|0,i=z[f>>2],i>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!"))),r[f>>2]=e,r[i+12>>2]=e,r[(e+8|0)>>2]=i,r[(e+12|0)>>2]=h);r[R+8>>2]=d;r[R+20>>2]=c;h=b;d=38;break}if(0==(r[R+4>>2]|0)){g=e;d=30;break}d=Ad(e);if(0==(d|0)){g=e;d=30;break}h=d}else{if(4294967231<b>>>0){g=-1;d=30;break}d=b+11&-8;if(0==(r[R+4>>2]|0)){g=d;d=30;break}e=Bd(d);if(0==(e|0)){g=d;d=30;break}h=e}d=38}while(0);30==d&&(e=z[R+8>>2],g>>>0>e>>>0?(d=z[R+12>>2],g>>>0<d>>>0?(d=d-g|0,r[R+12>>2]=d,e=z[R+24>>2],r[R+24>>2]=e+g|0,r[g+(e+4)>>2]=d|1,r[e+4>>2]=g|3,h=e+8|0):h=Cd(g)):(b=e-g|0,d=z[R+20>>2],15<b>>>0?(r[R+20>>2]=d+g|0,r[R+8>>2]=b,r[g+(d+4)>>2]=b|1,r[d+e>>2]=b,r[d+4>>2]=g|3):(r[R+8>>2]=0,r[R+20>>2]=0,r[d+4>>2]=e|3,g=e+(d+4)|0,r[g>>2]|=1),h=d+8|0));return h}Module._malloc=ic;ic.X=1;function Ad(b){var d,c,e=r[R+4>>2],f=(e&-e)-1|0,e=f>>>12&16,i=f>>>(e>>>0),f=i>>>5&8;c=i>>>(f>>>0);var i=c>>>2&4,h=c>>>(i>>>0);c=h>>>1&2;var h=h>>>(c>>>0),g=h>>>1&1,e=f=z[R+((f|e|i|c|g)+(h>>>(g>>>0))<<2)+304>>2];c=e>>2;f=(r[f+4>>2]&-8)-b|0;a:for(;;){for(i=e;;){h=r[i+16>>2];if(0==(h|0)){if(i=r[i+20>>2],0==(i|0)){break a}}else{i=h}h=(r[i+4>>2]&-8)-b|0;if(h>>>0<f>>>0){e=i;c=e>>2;f=h;continue a}}}var h=e,k=z[R+16>>2],g=h>>>0<k>>>0;do{if(!g){var o=h+b|0,i=o;if(h>>>0<o>>>0){var g=z[c+6],o=z[c+3],w=(o|0)==(e|0);do{if(w){d=e+20|0;var t=r[d>>2];if(0==(t|0)&&(d=e+16|0,t=r[d>>2],0==(t|0))){t=0;d=t>>2;break}for(;;){var A=t+20|0,y=r[A>>2];if(0==(y|0)&&(A=t+16|0,y=z[A>>2],0==(y|0))){break}d=A;t=y}d>>>0<k>>>0&&(T(),a("Reached an unreachable!"));r[d>>2]=0}else{d=z[c+2],d>>>0<k>>>0&&(T(),a("Reached an unreachable!")),r[d+12>>2]=o,r[o+8>>2]=d,t=o}d=t>>2}while(0);k=0==(g|0);a:do{if(!k){o=e+28|0;w=(r[o>>2]<<2)+R+304|0;A=(e|0)==(r[w>>2]|0);do{if(A){r[w>>2]=t;if(0!=(t|0)){break}r[R+4>>2]&=1<<r[o>>2]^-1;break a}g>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!"));y=g+16|0;(r[y>>2]|0)==(e|0)?r[y>>2]=t:r[g+20>>2]=t;if(0==(t|0)){break a}}while(0);t>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!"));r[d+6]=g;o=z[c+4];0!=(o|0)&&(o>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!")),r[d+4]=o,r[o+24>>2]=t);o=z[c+5];0!=(o|0)&&(o>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!")),r[d+5]=o,r[o+24>>2]=t)}}while(0);16>f>>>0?(b=f+b|0,r[c+1]=b|3,b=b+(h+4)|0,r[b>>2]|=1):(r[c+1]=b|3,r[b+(h+4)>>2]=f|1,r[h+f+b>>2]=f,k=z[R+8>>2],0!=(k|0)&&(b=z[R+20>>2],h=k>>>2&1073741822,c=(h<<2)+R+40|0,g=z[R>>2],k=1<<(k>>>3),0==(g&k|0)?(r[R>>2]=g|k,g=c,h=(h+2<<2)+R+40|0):(h=(h+2<<2)+R+40|0,g=z[h>>2],g>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!"))),r[h>>2]=b,r[g+12>>2]=b,r[b+8>>2]=g,r[b+12>>2]=c),r[R+8>>2]=f,r[R+20>>2]=i);return e+8|0}}}while(0);T();a("Reached an unreachable!")}Ad.X=1;function Bd(b){var d,c,e,f,i,h=b>>2,g=-b|0,k=b>>>8;if(0==(k|0)){var o=0}else{if(16777215<b>>>0){o=31}else{var w=(k+1048320|0)>>>16&8,t=k<<w,A=(t+520192|0)>>>16&4,y=t<<A,C=(y+245760|0)>>>16&2,v=14-(A|w|C)+(y<<C>>>15)|0,o=b>>>((v+7|0)>>>0)&1|v<<1}}var u=z[R+(o<<2)+304>>2],x=0==(u|0);a:do{if(x){var q=0,E=g,G=0}else{var M=31==(o|0)?0:25-(o>>>1)|0,W=0,H=g,Q=u;i=Q>>2;for(var K=b<<M,V=0;;){var Da=r[i+1]&-8,qa=Da-b|0;if(qa>>>0<H>>>0){if((Da|0)==(b|0)){q=Q;E=qa;G=Q;break a}var yb=Q,eb=qa}else{yb=W,eb=H}var La=z[i+5],Ea=z[((K>>>31<<2)+16>>2)+i],Ma=0==(La|0)|(La|0)==(Ea|0)?V:La;if(0==(Ea|0)){q=yb;E=eb;G=Ma;break a}W=yb;H=eb;Q=Ea;i=Q>>2;K<<=1;V=Ma}}}while(0);if(0==(G|0)&0==(q|0)){var fb=2<<o,zb=r[R+4>>2]&(fb|-fb);if(0==(zb|0)){var $=G}else{var ma=(zb&-zb)-1|0,fa=ma>>>12&16,S=ma>>>(fa>>>0),na=S>>>5&8,oa=S>>>(na>>>0),gb=oa>>>2&4,Na=oa>>>(gb>>>0),Ab=Na>>>1&2,ra=Na>>>(Ab>>>0),Oa=ra>>>1&1,$=r[R+((na|fa|gb|Ab|Oa)+(ra>>>(Oa>>>0))<<2)+304>>2]}}else{$=G}var Jb=0==($|0);a:do{if(Jb){var U=E,aa=q;f=aa>>2}else{var ta=$;e=ta>>2;for(var Fa=E,Pa=q;;){var hb=(r[e+1]&-8)-b|0,ib=hb>>>0<Fa>>>0,Y=ib?hb:Fa,jb=ib?ta:Pa,Qa=z[e+4];if(0!=(Qa|0)){ta=Qa}else{var Ra=z[e+5];if(0==(Ra|0)){U=Y;aa=jb;f=aa>>2;break a}ta=Ra}e=ta>>2;Fa=Y;Pa=jb}}}while(0);var Sa=0==(aa|0);a:do{if(Sa){var kb=0}else{if(U>>>0<(r[R+8>>2]-b|0)>>>0){var ua=aa;c=ua>>2;var va=z[R+16>>2],Ta=ua>>>0<va>>>0;do{if(!Ta){var Bb=ua+b|0,lb=Bb;if(ua>>>0<Bb>>>0){var ga=z[f+6],Ga=z[f+3],Wb=(Ga|0)==(aa|0);do{if(Wb){var Kb=aa+20|0,Cb=r[Kb>>2];if(0==(Cb|0)){var mb=aa+16|0,nb=r[mb>>2];if(0==(nb|0)){var N=0;d=N>>2;break}var da=mb,ba=nb}else{da=Kb,ba=Cb}for(;;){var Ha=ba+20|0,Ua=r[Ha>>2];if(0!=(Ua|0)){da=Ha,ba=Ua}else{var Va=ba+16|0,Wa=z[Va>>2];if(0==(Wa|0)){break}da=Va;ba=Wa}}da>>>0<va>>>0&&(T(),a("Reached an unreachable!"));r[da>>2]=0;N=ba}else{var wa=z[f+2];wa>>>0<va>>>0&&(T(),a("Reached an unreachable!"));r[wa+12>>2]=Ga;r[Ga+8>>2]=wa;N=Ga}d=N>>2}while(0);var Lb=0==(ga|0);b:do{if(!Lb){var Mb=aa+28|0,Nb=(r[Mb>>2]<<2)+R+304|0,Xb=(aa|0)==(r[Nb>>2]|0);do{if(Xb){r[Nb>>2]=N;if(0!=(N|0)){break}r[R+4>>2]&=1<<r[Mb>>2]^-1;break b}ga>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!"));var Xa=ga+16|0;(r[Xa>>2]|0)==(aa|0)?r[Xa>>2]=N:r[ga+20>>2]=N;if(0==(N|0)){break b}}while(0);N>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!"));r[d+6]=ga;var ha=z[f+4];0!=(ha|0)&&(ha>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!")),r[d+4]=ha,r[ha+24>>2]=N);var Z=z[f+5];0!=(Z|0)&&(Z>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!")),r[d+5]=Z,r[Z+24>>2]=N)}}while(0);var xa=16>U>>>0;b:do{if(xa){var ya=U+b|0;r[f+1]=ya|3;var Db=ya+(ua+4)|0;r[Db>>2]|=1}else{if(r[f+1]=b|3,r[h+(c+1)]=U|1,r[(U>>2)+c+h]=U,256>U>>>0){var ob=U>>>2&1073741822,Ya=(ob<<2)+R+40|0,Eb=z[R>>2],pb=1<<(U>>>3);if(0==(Eb&pb|0)){r[R>>2]=Eb|pb;var qb=Ya,ia=(ob+2<<2)+R+40|0}else{var za=(ob+2<<2)+R+40|0,Aa=z[za>>2];Aa>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!"));qb=Aa;ia=za}r[ia>>2]=lb;r[qb+12>>2]=lb;r[h+(c+2)]=qb;r[h+(c+3)]=Ya}else{var ja=Bb,rb=U>>>8;if(0==(rb|0)){var ea=0}else{if(16777215<U>>>0){ea=31}else{var Za=(rb+1048320|0)>>>16&8,Ob=rb<<Za,sb=(Ob+520192|0)>>>16&4,Ia=Ob<<sb,Ja=(Ia+245760|0)>>>16&2,tb=14-(sb|Za|Ja)+(Ia<<Ja>>>15)|0,ea=U>>>((tb+7|0)>>>0)&1|tb<<1}}var $a=(ea<<2)+R+304|0;r[h+(c+7)]=ea;var Fb=b+(ua+16)|0;r[h+(c+5)]=0;r[Fb>>2]=0;var pa=r[R+4>>2],Gb=1<<ea;if(0==(pa&Gb|0)){r[R+4>>2]=pa|Gb,r[$a>>2]=ja,r[h+(c+6)]=$a,r[h+(c+3)]=ja,r[h+(c+2)]=ja}else{for(var ub=U<<(31==(ea|0)?0:25-(ea>>>1)|0),Ba=r[$a>>2];;){if((r[Ba+4>>2]&-8|0)==(U|0)){var Pb=Ba+8|0,ab=z[Pb>>2],kc=z[R+16>>2],wc=Ba>>>0<kc>>>0;do{if(!wc&&ab>>>0>=kc>>>0){r[ab+12>>2]=ja;r[Pb>>2]=ja;r[h+(c+2)]=ab;r[h+(c+3)]=Ba;r[h+(c+6)]=0;break b}}while(0);T();a("Reached an unreachable!")}var ac=(ub>>>31<<2)+Ba+16|0,xc=z[ac>>2];if(0==(xc|0)){if(ac>>>0>=z[R+16>>2]>>>0){r[ac>>2]=ja;r[h+(c+6)]=Ba;r[h+(c+3)]=ja;r[h+(c+2)]=ja;break b}T();a("Reached an unreachable!")}ub<<=1;Ba=xc}}}}}while(0);kb=aa+8|0;break a}}}while(0);T();a("Reached an unreachable!")}kb=0}}while(0);return kb}Bd.X=1;function Cd(b){var d,c;0==(r[X>>2]|0)&&Dd();var e=0==(r[R+440>>2]&4|0);do{if(e){c=r[R+24>>2];if(0==(c|0)){c=6}else{if(c=Ed(c),0==(c|0)){c=6}else{var f=r[X+8>>2],f=b+47-r[R+12>>2]+f&-f;if(2147483647>f>>>0){var i=Fd(f);if((i|0)==(r[c>>2]+r[c+4>>2]|0)){var h=i,g=f;d=i;c=13}else{var k=i,o=f;c=15}}else{c=14}}}if(6==c){if(c=Fd(0),-1==(c|0)){c=14}else{var f=r[X+8>>2],f=f+(b+47)&-f,i=c,w=r[X+4>>2],t=w-1|0,f=0==(t&i|0)?f:f-i+(t+i&-w)|0;2147483647>f>>>0?(i=Fd(f),(i|0)==(c|0)?(h=c,g=f,d=i,c=13):(k=i,o=f,c=15)):c=14}}if(13==c){if(-1!=(h|0)){var A=g,y=h;c=26;break}k=d;o=g}else{if(14==c){r[R+440>>2]|=4;c=23;break}}c=-o|0;if(-1!=(k|0)&2147483647>o>>>0){if(o>>>0<(b+48|0)>>>0){f=r[X+8>>2],f=b+47-o+f&-f,2147483647>f>>>0?-1==(Fd(f)|0)?(Fd(c),c=22):(C=f+o|0,c=21):(C=o,c=21)}else{var C=o;c=21}}else{C=o,c=21}21==c&&-1!=(k|0)?(A=C,y=k,c=26):(r[R+440>>2]|=4,c=23)}else{c=23}}while(0);23==c&&(e=r[X+8>>2],e=e+(b+47)&-e,2147483647>e>>>0?(e=Fd(e),h=Fd(0),-1!=(h|0)&-1!=(e|0)&e>>>0<h>>>0?(h=h-e|0,h>>>0<=(b+40|0)>>>0|-1==(e|0)?c=49:(A=h,y=e,c=26)):c=49):c=49);a:do{if(26==c){e=r[R+432>>2]+A|0;r[R+432>>2]=e;e>>>0>z[R+436>>2]>>>0&&(r[R+436>>2]=e);e=z[R+24>>2];h=0==(e|0);b:do{if(h){g=z[R+16>>2];0==(g|0)|y>>>0<g>>>0&&(r[R+16>>2]=y);r[R+444>>2]=y;r[R+448>>2]=A;r[R+456>>2]=0;r[R+36>>2]=r[X>>2];r[R+32>>2]=-1;for(g=0;!(d=g<<1,k=(d<<2)+R+40|0,r[R+(d+3<<2)+40>>2]=k,r[R+(d+2<<2)+40>>2]=k,g=g+1|0,32==(g|0));){}Gd(y,A-40|0)}else{k=R+444|0;for(d=k>>2;0!=(k|0);){g=z[d];k=k+4|0;o=z[k>>2];C=g+o|0;if((y|0)==(C|0)){if(0!=(r[d+3]&8|0)){break}d=e;if(!(d>>>0>=g>>>0&d>>>0<C>>>0)){break}r[k>>2]=o+A|0;Gd(r[R+24>>2],r[R+12>>2]+A|0);break b}k=r[d+2];d=k>>2}y>>>0<z[R+16>>2]>>>0&&(r[R+16>>2]=y);d=y+A|0;for(k=R+444|0;0!=(k|0);){o=k|0;g=z[o>>2];if((g|0)==(d|0)){if(0!=(r[k+12>>2]&8|0)){break}r[o>>2]=y;var v=k+4|0;r[v>>2]=r[v>>2]+A|0;v=Hd(y,g,b);c=50;break a}k=r[k+8>>2]}Id(y,A)}}while(0);e=z[R+12>>2];e>>>0>b>>>0?(v=e-b|0,r[R+12>>2]=v,h=e=z[R+24>>2],r[R+24>>2]=h+b|0,r[b+(h+4)>>2]=v|1,r[e+4>>2]=b|3,v=e+8|0,c=50):c=49}}while(0);49==c&&(r[Kc>>2]=12,v=0);return v}Cd.X=1;function Jd(){var b;0==(r[X>>2]|0)&&Dd();var d=z[R+24>>2],c=0==(d|0);a:do{if(!c){var e=z[R+12>>2],f=40<e>>>0;do{if(f){var i=z[X+8>>2],h=(Math.floor(((e-41+i|0)>>>0)/(i>>>0))-1)*i|0,g=Ed(d);if(0==(r[g+12>>2]&8|0)){var k=Fd(0);b=(g+4|0)>>2;if((k|0)==(r[g>>2]+r[b]|0)&&(h=Fd(-(2147483646<h>>>0?-2147483648-i|0:h)|0),i=Fd(0),-1!=(h|0)&i>>>0<k>>>0&&(h=k-i|0,(k|0)!=(i|0)))){r[b]=r[b]-h|0;r[R+432>>2]=r[R+432>>2]-h|0;Gd(r[R+24>>2],r[R+12>>2]-h|0);break a}}}}while(0);z[R+12>>2]>>>0>z[R+28>>2]>>>0&&(r[R+28>>2]=-1)}}while(0)}Jd.X=1;function pd(b){var d,c,e,f,i,h,g=b>>2,k,o=0==(b|0);a:do{if(!o){var w=b-8|0,t=w,A=z[R+16>>2],y=w>>>0<A>>>0;b:do{if(!y){var C=z[b-4>>2],v=C&3;if(1!=(v|0)){var u=C&-8;h=u>>2;var x=b+(u-8)|0,q=x,E=0==(C&1|0);c:do{if(E){var G=z[w>>2];if(0==(v|0)){break a}var M=-8-G|0;i=M>>2;var W=b+M|0,H=W,Q=G+u|0;if(W>>>0<A>>>0){break b}if((H|0)==(r[R+20>>2]|0)){f=(b+(u-4)|0)>>2;if(3!=(r[f]&3|0)){var K=H;e=K>>2;var V=Q;break}r[R+8>>2]=Q;r[f]&=-2;r[i+(g+1)]=Q|1;r[x>>2]=Q;break a}if(256>G>>>0){var Da=z[i+(g+2)],qa=z[i+(g+3)];if((Da|0)==(qa|0)){r[R>>2]&=1<<(G>>>3)^-1,K=H,e=K>>2,V=Q}else{var yb=((G>>>2&1073741822)<<2)+R+40|0,eb=(Da|0)!=(yb|0)&Da>>>0<A>>>0;do{if(!eb&&(qa|0)==(yb|0)|qa>>>0>=A>>>0){r[Da+12>>2]=qa;r[qa+8>>2]=Da;K=H;e=K>>2;V=Q;break c}}while(0);T();a("Reached an unreachable!")}}else{var La=W,Ea=z[i+(g+6)],Ma=z[i+(g+3)],fb=(Ma|0)==(La|0);do{if(fb){var zb=M+(b+20)|0,$=r[zb>>2];if(0==($|0)){var ma=M+(b+16)|0,fa=r[ma>>2];if(0==(fa|0)){var S=0;c=S>>2;break}var na=ma,oa=fa}else{na=zb,oa=$,k=21}for(;;){var gb=oa+20|0,Na=r[gb>>2];if(0!=(Na|0)){na=gb,oa=Na}else{var Ab=oa+16|0,ra=z[Ab>>2];if(0==(ra|0)){break}na=Ab;oa=ra}}na>>>0<A>>>0&&(T(),a("Reached an unreachable!"));r[na>>2]=0;S=oa}else{var Oa=z[i+(g+2)];Oa>>>0<A>>>0&&(T(),a("Reached an unreachable!"));r[Oa+12>>2]=Ma;r[Ma+8>>2]=Oa;S=Ma}c=S>>2}while(0);if(0!=(Ea|0)){var Jb=M+(b+28)|0,U=(r[Jb>>2]<<2)+R+304|0,aa=(La|0)==(r[U>>2]|0);do{if(aa){r[U>>2]=S;if(0!=(S|0)){break}r[R+4>>2]&=1<<r[Jb>>2]^-1;K=H;e=K>>2;V=Q;break c}Ea>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!"));var ta=Ea+16|0;(r[ta>>2]|0)==(La|0)?r[ta>>2]=S:r[Ea+20>>2]=S;if(0==(S|0)){K=H;e=K>>2;V=Q;break c}}while(0);S>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!"));r[c+6]=Ea;var Fa=z[i+(g+4)];0!=(Fa|0)&&(Fa>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!")),r[c+4]=Fa,r[Fa+24>>2]=S);var Pa=z[i+(g+5)];0!=(Pa|0)&&(Pa>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!")),r[c+5]=Pa,r[Pa+24>>2]=S)}K=H;e=K>>2;V=Q}}else{K=t,e=K>>2,V=u}}while(0);var hb=K;if(hb>>>0<x>>>0){var ib=b+(u-4)|0,Y=z[ib>>2];if(0!=(Y&1|0)){var jb=0==(Y&2|0);do{if(jb){if((q|0)==(r[R+24>>2]|0)){var Qa=r[R+12>>2]+V|0;r[R+12>>2]=Qa;r[R+24>>2]=K;r[e+1]=Qa|1;(K|0)==(r[R+20>>2]|0)&&(r[R+20>>2]=0,r[R+8>>2]=0);if(Qa>>>0<=z[R+28>>2]>>>0){break a}Jd();break a}if((q|0)==(r[R+20>>2]|0)){var Ra=r[R+8>>2]+V|0;r[R+8>>2]=Ra;r[R+20>>2]=K;r[e+1]=Ra|1;r[(hb+Ra|0)>>2]=Ra;break a}var Sa=(Y&-8)+V|0,kb=Y>>>3,ua=256>Y>>>0;c:do{if(ua){var va=z[g+h],Ta=z[((u|4)>>2)+g];if((va|0)==(Ta|0)){r[R>>2]&=1<<kb^-1}else{var Bb=((Y>>>2&1073741822)<<2)+R+40|0;k=(va|0)==(Bb|0)?63:va>>>0<z[R+16>>2]>>>0?66:63;do{if(63==k&&!((Ta|0)!=(Bb|0)&&Ta>>>0<z[R+16>>2]>>>0)){r[va+12>>2]=Ta;r[Ta+8>>2]=va;break c}}while(0);T();a("Reached an unreachable!")}}else{var lb=x,ga=z[h+(g+4)],Ga=z[((u|4)>>2)+g],Wb=(Ga|0)==(lb|0);do{if(Wb){var Kb=u+(b+12)|0,Cb=r[Kb>>2];if(0==(Cb|0)){var mb=u+(b+8)|0,nb=r[mb>>2];if(0==(nb|0)){var N=0;d=N>>2;break}var da=mb,ba=nb}else{da=Kb,ba=Cb,k=73}for(;;){var Ha=ba+20|0,Ua=r[Ha>>2];if(0!=(Ua|0)){da=Ha,ba=Ua}else{var Va=ba+16|0,Wa=z[Va>>2];if(0==(Wa|0)){break}da=Va;ba=Wa}}da>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!"));r[da>>2]=0;N=ba}else{var wa=z[g+h];wa>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!"));r[wa+12>>2]=Ga;r[Ga+8>>2]=wa;N=Ga}d=N>>2}while(0);if(0!=(ga|0)){var Lb=u+(b+20)|0,Mb=(r[Lb>>2]<<2)+R+304|0,Nb=(lb|0)==(r[Mb>>2]|0);do{if(Nb){r[Mb>>2]=N;if(0!=(N|0)){break}r[R+4>>2]&=1<<r[Lb>>2]^-1;break c}ga>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!"));var Xb=ga+16|0;(r[Xb>>2]|0)==(lb|0)?r[Xb>>2]=N:r[ga+20>>2]=N;if(0==(N|0)){break c}}while(0);N>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!"));r[d+6]=ga;var Xa=z[h+(g+2)];0!=(Xa|0)&&(Xa>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!")),r[d+4]=Xa,r[Xa+24>>2]=N);var ha=z[h+(g+3)];0!=(ha|0)&&(ha>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!")),r[d+5]=ha,r[ha+24>>2]=N)}}}while(0);r[e+1]=Sa|1;r[hb+Sa>>2]=Sa;if((K|0)!=(r[R+20>>2]|0)){var Z=Sa}else{r[R+8>>2]=Sa;break a}}else{r[ib>>2]=Y&-2,r[e+1]=V|1,Z=r[hb+V>>2]=V}}while(0);if(256>Z>>>0){var xa=Z>>>2&1073741822,ya=(xa<<2)+R+40|0,Db=z[R>>2],ob=1<<(Z>>>3);if(0==(Db&ob|0)){r[R>>2]=Db|ob;var Ya=ya,Eb=(xa+2<<2)+R+40|0}else{var pb=(xa+2<<2)+R+40|0,qb=z[pb>>2];qb>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!"));Ya=qb;Eb=pb}r[Eb>>2]=K;r[Ya+12>>2]=K;r[e+2]=Ya;r[e+3]=ya;break a}var ia=K,za=Z>>>8;if(0==(za|0)){var Aa=0}else{if(16777215<Z>>>0){Aa=31}else{var ja=(za+1048320|0)>>>16&8,rb=za<<ja,ea=(rb+520192|0)>>>16&4,Za=rb<<ea,Ob=(Za+245760|0)>>>16&2,sb=14-(ea|ja|Ob)+(Za<<Ob>>>15)|0,Aa=Z>>>((sb+7|0)>>>0)&1|sb<<1}}var Ia=(Aa<<2)+R+304|0;r[e+7]=Aa;r[e+5]=0;r[e+4]=0;var Ja=r[R+4>>2],tb=1<<Aa,$a=0==(Ja&tb|0);c:do{if($a){r[R+4>>2]=Ja|tb,r[Ia>>2]=ia,r[e+6]=Ia,r[e+3]=K,r[e+2]=K}else{for(var Fb=Z<<(31==(Aa|0)?0:25-(Aa>>>1)|0),pa=r[Ia>>2];;){if((r[pa+4>>2]&-8|0)==(Z|0)){var Gb=pa+8|0,ub=z[Gb>>2],Ba=z[R+16>>2],Pb=pa>>>0<Ba>>>0;do{if(!Pb&&ub>>>0>=Ba>>>0){r[ub+12>>2]=ia;r[Gb>>2]=ia;r[e+2]=ub;r[e+3]=pa;r[e+6]=0;break c}}while(0);T();a("Reached an unreachable!")}var ab=(Fb>>>31<<2)+pa+16|0,kc=z[ab>>2];if(0==(kc|0)){if(ab>>>0>=z[R+16>>2]>>>0){r[ab>>2]=ia;r[e+6]=pa;r[e+3]=K;r[e+2]=K;break c}T();a("Reached an unreachable!")}Fb<<=1;pa=kc}}}while(0);var wc=r[R+32>>2]-1|0;r[R+32>>2]=wc;if(0!=(wc|0)){break a}var ac=r[R+452>>2],xc=0==(ac|0);c:do{if(!xc){for(var Qd=ac;;){var Rd=r[Qd+8>>2];if(0==(Rd|0)){break c}Qd=Rd}}}while(0);r[R+32>>2]=-1;break a}}}}}while(0);T();a("Reached an unreachable!")}}while(0)}Module._free=pd;pd.X=1;function Ed(b){var d,c=R+444|0;for(d=c>>2;;){var e=z[d];if(e>>>0<=b>>>0&&(e+r[d+1]|0)>>>0>b>>>0){var f=c;break}d=z[d+2];if(0==(d|0)){f=0;break}c=d;d=c>>2}return f}function Gd(b,d){var c=b+8|0,c=0==(c&7|0)?0:-c&7,e=d-c|0;r[R+24>>2]=b+c|0;r[R+12>>2]=e;r[c+(b+4)>>2]=e|1;r[d+(b+4)>>2]=40;r[R+28>>2]=r[X+16>>2]}function Dd(){if(0==(r[X>>2]|0)){var b=Kd();0==(b-1&b|0)?(r[X+8>>2]=b,r[X+4>>2]=b,r[X+12>>2]=-1,r[X+16>>2]=2097152,r[X+20>>2]=0,r[R+440>>2]=0,r[X>>2]=Math.floor(Date.now()/1e3)&-16^1431655768):(T(),a("Reached an unreachable!"))}}function Hd(b,d,c){var e,f,i,h=d>>2,g=b>>2,k,o=b+8|0,o=0==(o&7|0)?0:-o&7;f=d+8|0;var w=0==(f&7|0)?0:-f&7;i=w>>2;var t=d+w|0,A=o+c|0;f=A>>2;var y=b+A|0,C=t-(b+o)-c|0;r[(o+4>>2)+g]=c|3;c=(t|0)==(r[R+24>>2]|0);a:do{if(c){var v=r[R+12>>2]+C|0;r[R+12>>2]=v;r[R+24>>2]=y;r[f+(g+1)]=v|1}else{if((t|0)==(r[R+20>>2]|0)){v=r[R+8>>2]+C|0,r[R+8>>2]=v,r[R+20>>2]=y,r[f+(g+1)]=v|1,r[(b+v+A|0)>>2]=v}else{var u=z[i+(h+1)];if(1==(u&3|0)){var v=u&-8,x=u>>>3,q=256>u>>>0;b:do{if(q){var E=z[((w|8)>>2)+h],G=z[i+(h+3)];if((E|0)==(G|0)){r[R>>2]&=1<<x^-1}else{var M=((u>>>2&1073741822)<<2)+R+40|0;k=(E|0)==(M|0)?15:E>>>0<z[R+16>>2]>>>0?18:15;do{if(15==k&&!((G|0)!=(M|0)&&G>>>0<z[R+16>>2]>>>0)){r[E+12>>2]=G;r[G+8>>2]=E;break b}}while(0);T();a("Reached an unreachable!")}}else{k=t;E=z[((w|24)>>2)+h];G=z[i+(h+3)];M=(G|0)==(k|0);do{if(M){e=w|16;var W=e+(d+4)|0,H=r[W>>2];if(0==(H|0)){if(e=d+e|0,H=r[e>>2],0==(H|0)){H=0;e=H>>2;break}}else{e=W}for(;;){var W=H+20|0,Q=r[W>>2];if(0==(Q|0)&&(W=H+16|0,Q=z[W>>2],0==(Q|0))){break}e=W;H=Q}e>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!"));r[e>>2]=0}else{e=z[((w|8)>>2)+h],e>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!")),r[e+12>>2]=G,r[G+8>>2]=e,H=G}e=H>>2}while(0);if(0!=(E|0)){G=w+(d+28)|0;M=(r[G>>2]<<2)+R+304|0;W=(k|0)==(r[M>>2]|0);do{if(W){r[M>>2]=H;if(0!=(H|0)){break}r[R+4>>2]&=1<<r[G>>2]^-1;break b}E>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!"));Q=E+16|0;(r[Q>>2]|0)==(k|0)?r[Q>>2]=H:r[E+20>>2]=H;if(0==(H|0)){break b}}while(0);H>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!"));r[e+6]=E;k=w|16;E=z[(k>>2)+h];0!=(E|0)&&(E>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!")),r[e+4]=E,r[E+24>>2]=H);k=z[(k+4>>2)+h];0!=(k|0)&&(k>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!")),r[e+5]=k,r[k+24>>2]=H)}}}while(0);u=d+(v|w)|0;v=v+C|0}else{u=t,v=C}u=u+4|0;r[u>>2]&=-2;r[f+(g+1)]=v|1;r[(v>>2)+g+f]=v;if(256>v>>>0){x=v>>>2&1073741822,u=(x<<2)+R+40|0,q=z[R>>2],v=1<<(v>>>3),0==(q&v|0)?(r[R>>2]=q|v,v=u,x=(x+2<<2)+R+40|0):(x=(x+2<<2)+R+40|0,v=z[x>>2],v>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!"))),r[x>>2]=y,r[v+12>>2]=y,r[f+(g+2)]=v,r[f+(g+3)]=u}else{if(u=y,q=v>>>8,0==(q|0)?x=0:16777215<v>>>0?x=31:(x=(q+1048320|0)>>>16&8,k=q<<x,q=(k+520192|0)>>>16&4,k<<=q,E=(k+245760|0)>>>16&2,x=14-(q|x|E)+(k<<E>>>15)|0,x=v>>>((x+7|0)>>>0)&1|x<<1),q=(x<<2)+R+304|0,r[f+(g+7)]=x,k=A+(b+16)|0,r[f+(g+5)]=0,r[k>>2]=0,k=r[R+4>>2],E=1<<x,0==(k&E|0)){r[R+4>>2]=k|E,r[q>>2]=u,r[f+(g+6)]=q,r[f+(g+3)]=u,r[f+(g+2)]=u}else{x=v<<(31==(x|0)?0:25-(x>>>1)|0);for(q=r[q>>2];;){if((r[q+4>>2]&-8|0)==(v|0)){k=q+8|0;E=z[k>>2];G=z[R+16>>2];M=q>>>0<G>>>0;do{if(!M&&E>>>0>=G>>>0){r[E+12>>2]=u;r[k>>2]=u;r[f+(g+2)]=E;r[f+(g+3)]=q;r[f+(g+6)]=0;break a}}while(0);T();a("Reached an unreachable!")}k=(x>>>31<<2)+q+16|0;E=z[k>>2];if(0==(E|0)){if(k>>>0>=z[R+16>>2]>>>0){r[k>>2]=u;r[f+(g+6)]=q;r[f+(g+3)]=u;r[f+(g+2)]=u;break a}T();a("Reached an unreachable!")}x<<=1;q=E}}}}}}while(0);return b+(o|8)|0}Hd.X=1;function Id(b,d){var c,e,f=z[R+24>>2];e=f>>2;var i=Ed(f),h=r[i>>2];c=r[i+4>>2];var i=h+c|0,g=h+(c-39)|0,h=h+(c-47)+(0==(g&7|0)?0:-g&7)|0,h=h>>>0<(f+16|0)>>>0?f:h,g=h+8|0;c=g>>2;Gd(b,d-40|0);r[(h+4|0)>>2]=27;r[c]=r[R+444>>2];r[c+1]=r[R+448>>2];r[c+2]=r[R+452>>2];r[c+3]=r[R+456>>2];r[R+444>>2]=b;r[R+448>>2]=d;r[R+456>>2]=0;r[R+452>>2]=g;c=h+28|0;r[c>>2]=7;g=(h+32|0)>>>0<i>>>0;a:do{if(g){for(var k=c;;){var o=k+4|0;r[o>>2]=7;if((k+8|0)>>>0>=i>>>0){break a}k=o}}}while(0);i=(h|0)==(f|0);a:do{if(!i){if(c=h-f|0,g=f+c|0,k=c+(f+4)|0,r[k>>2]&=-2,r[e+1]=c|1,r[g>>2]=c,256>c>>>0){k=c>>>2&1073741822,g=(k<<2)+R+40|0,o=z[R>>2],c=1<<(c>>>3),0==(o&c|0)?(r[R>>2]=o|c,c=g,k=(k+2<<2)+R+40|0):(k=(k+2<<2)+R+40|0,c=z[k>>2],c>>>0<z[R+16>>2]>>>0&&(T(),a("Reached an unreachable!"))),r[k>>2]=f,r[c+12>>2]=f,r[e+2]=c,r[e+3]=g}else{g=f;o=c>>>8;if(0==(o|0)){k=0}else{if(16777215<c>>>0){k=31}else{var k=(o+1048320|0)>>>16&8,w=o<<k,o=(w+520192|0)>>>16&4,w=w<<o,t=(w+245760|0)>>>16&2,k=14-(o|k|t)+(w<<t>>>15)|0,k=c>>>((k+7|0)>>>0)&1|k<<1}}o=(k<<2)+R+304|0;r[e+7]=k;r[e+5]=0;r[e+4]=0;w=r[R+4>>2];t=1<<k;if(0==(w&t|0)){r[R+4>>2]=w|t,r[o>>2]=g,r[e+6]=o,r[e+3]=f,r[e+2]=f}else{k=c<<(31==(k|0)?0:25-(k>>>1)|0);for(o=r[o>>2];;){if((r[o+4>>2]&-8|0)==(c|0)){var w=o+8|0,t=z[w>>2],A=z[R+16>>2],y=o>>>0<A>>>0;do{if(!y&&t>>>0>=A>>>0){r[t+12>>2]=g;r[w>>2]=g;r[e+2]=t;r[e+3]=o;r[e+6]=0;break a}}while(0);T();a("Reached an unreachable!")}w=(k>>>31<<2)+o+16|0;t=z[w>>2];if(0==(t|0)){if(w>>>0>=z[R+16>>2]>>>0){r[w>>2]=g;r[e+6]=o;r[e+3]=f;r[e+2]=f;break a}T();a("Reached an unreachable!")}k<<=1;o=t}}}}}while(0)}Id.X=1;function yd(b){0!=(b|0)&&pd(b)}function Ld(b){Md(b|0)}function td(b){for(b=0==(b|0)?1:b;;){var d=ic(b);if(0==(d|0)){d=(Yb=r[Nd>>2],r[Nd>>2]=Yb,Yb);if(0==(d|0)){var c=ic(4);r[c>>2]=Od+8|0;var e=Pd;if(!Sd){try{r[__ZTVN10__cxxabiv119__pointer_type_infoE>>2]=0}catch(f){}try{r[__ZTVN10__cxxabiv117__class_type_infoE>>2]=1}catch(i){}try{r[Td>>2]=2}catch(h){}Sd=j}Module.Va("Compiled code throwing an exception, "+[c,e,2]+", at "+Error().stack);r[Ud>>2]=c;r[Ud+4>>2]=e;r[Ud+8>>2]=2;"uncaught_exception"in Vd?Vd.w++:Vd.w=1;a(c);a("Reached an unreachable!")}lc[d]()}else{return d}}return l}function L(b){Kc||(Kc=F([0],"i32",D));r[Kc>>2]=b}var Kc,Wd=13,qd=9,id=22,Xd=5,Yd=21,Zd=25,$d=6,hd=34,ae=0,be=0,ce=0,bd=0,de=2,O=[l],ee=j;function fe(b,d){if("string"!==typeof b){return l}d===ca&&(d="/");b&&"/"==b[0]&&(d="");for(var c=(d+"/"+b).split("/").reverse(),e=[""];c.length;){var f=c.pop();""==f||"."==f||(".."==f?1<e.length&&e.pop():e.push(f))}return 1==e.length?"/":e.join("/")}function ge(b,d,c){var e={Ta:m,k:m,error:0,name:l,path:l,object:l,s:m,u:l,t:l},b=fe(b);if("/"==b){e.Ta=j,e.k=e.s=j,e.name="/",e.path=e.u="/",e.object=e.t=he}else{if(b!==l){for(var c=c||0,b=b.slice(1).split("/"),f=he,i=[""];b.length;){1==b.length&&f.c&&(e.s=j,e.u=1==i.length?"/":i.join("/"),e.t=f,e.name=b[0]);var h=b.shift();if(f.c){if(f.v){if(!f.a.hasOwnProperty(h)){e.error=2;break}}else{e.error=Wd;break}}else{e.error=20;break}f=f.a[h];if(f.link&&!(d&&0==b.length)){if(40<c){e.error=40;break}e=fe(f.link,i.join("/"));return ge([e].concat(b).join("/"),d,c+1)}i.push(h);0==b.length&&(e.k=j,e.path=i.join("/"),e.object=f)}}}return e}function ie(b){je();b=ge(b,ca);if(b.k){return b.object}L(b.error);return l}function ke(b,d,c,e,f){b||(b="/");"string"===typeof b&&(b=ie(b));b||(L(Wd),a(Error("Parent path must exist.")));b.c||(L(20),a(Error("Parent must be a folder.")));!b.write&&!ee&&(L(Wd),a(Error("Parent folder must be writeable.")));if(!d||"."==d||".."==d){L(2),a(Error("Name must not be empty."))}b.a.hasOwnProperty(d)&&(L(17),a(Error("Can't overwrite object.")));b.a[d]={v:e===ca?j:e,write:f===ca?m:f,timestamp:Date.now(),Sa:de++};for(var i in c){c.hasOwnProperty(i)&&(b.a[d][i]=c[i])}return b.a[d]}function le(b,d){return ke(b,d,{c:j,d:m,a:{}},j,j)}function me(){var b="dev/shm/tmp",d=ie("/");d===l&&a(Error("Invalid parent."));for(b=b.split("/").reverse();b.length;){var c=b.pop();c&&(d.a.hasOwnProperty(c)||le(d,c),d=d.a[c])}}function ne(b,d,c,e){!c&&!e&&a(Error("A device must have at least one callback defined."));var f={d:j,input:c,e:e};f.c=m;return ke(b,d,f,Boolean(c),Boolean(e))}function je(){he||(he={v:j,write:j,c:j,d:m,timestamp:Date.now(),Sa:1,a:{}})}function oe(){var b,d,c;function e(b){b===l||10===b?(d.h(d.buffer.join("")),d.buffer=[]):d.buffer.push(String.fromCharCode(b))}wb(!pe,"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)");pe=j;je();b=b||Module.stdin;d=d||Module.stdout;c=c||Module.stderr;var f=j,i=j,h=j;b||(f=m,b=(function(){if(!b.j||!b.j.length){var c;"undefined"!=typeof window&&"function"==typeof window.prompt?c=window.prompt("Input: "):"function"==typeof readline&&(c=readline());c||(c="");b.j=qc(c+"\n",j)}return b.j.shift()}));d||(i=m,d=e);d.h||(d.h=Module.print);d.buffer||(d.buffer=[]);c||(h=m,c=e);c.h||(c.h=Module.print);c.buffer||(c.buffer=[]);le("/","tmp");var g=le("/","dev"),k=ne(g,"stdin",b),o=ne(g,"stdout",l,d);c=ne(g,"stderr",l,c);ne(g,"tty",b,d);O[1]={path:"/dev/stdin",object:k,position:0,f:j,g:m,r:m,m:!f,error:m,q:m,b:[]};O[2]={path:"/dev/stdout",object:o,position:0,f:m,g:j,r:m,m:!i,error:m,q:m,b:[]};O[3]={path:"/dev/stderr",object:c,position:0,f:m,g:j,r:m,m:!h,error:m,q:m,b:[]};ae=F([1],"void*",D);be=F([2],"void*",D);ce=F([3],"void*",D);me();O[ae]=O[1];O[be]=O[2];O[ce]=O[3];bd=F([F([0,0,0,0,ae,0,0,0,be,0,0,0,ce,0,0,0],"void*",D)],"void*",D)}var pe,he;function qe(b,d,c,e){var f=O[b];if(!f||f.object.d){return L(qd),-1}if(f.f){if(f.object.c){return L(Yd),-1}if(0>c||0>e){return L(id),-1}for(b=0;f.b.length&&0<c;){p[d++]=f.b.pop(),c--,b++}for(var f=f.object.a,c=Math.min(f.length-e,c),i=0;i<c;i++){p[d+i]=f[e+i],b++}return b}L(Wd);return-1}function Rc(b,d,c){var e=O[b];if(e){if(e.f){if(0>c){return L(id),-1}if(e.object.d){if(e.object.input){for(b=0;e.b.length&&0<c;){p[d++]=e.b.pop(),c--,b++}for(var f=0;f<c;f++){try{var i=e.object.input()}catch(h){return L(Xd),-1}if(i===l||i===ca){break}b++;p[d+f]=i}return b}L($d);return-1}i=e.b.length;b=qe(b,d,c,e.position);-1!=b&&(e.position+=e.b.length-i+b);return b}L(Wd);return-1}L(qd);return-1}function Lc(b,d,c){var e=O[b];if(e){if(e.g){if(0>c){return L(id),-1}if(e.object.d){if(e.object.e){for(var f=0;f<c;f++){try{e.object.e(p[d+f])}catch(i){return L(Xd),-1}}e.object.timestamp=Date.now();return f}L($d);return-1}f=e.position;b=O[b];if(!b||b.object.d){L(qd),d=-1}else{if(b.g){if(b.object.c){L(Yd),d=-1}else{if(0>c||0>f){L(id),d=-1}else{for(var h=b.object.a;h.length<f;){h.push(0)}for(var g=0;g<c;g++){h[f+g]=s[d+g]}b.object.timestamp=Date.now();d=g}}}else{L(Wd),d=-1}}-1!=d&&(e.position+=d);return d}L(Wd);return-1}L(qd);return-1}function Mc(b){uc(yc);a("exit("+b+") called, at "+Error().stack)}function zd(b,d,c,e){d*=c;0!=d&&-1==Lc(e,b,d)&&O[e]&&(O[e].error=j)}function xd(b,d){function c(b){var c;"double"===b?c=(gc[0]=r[d+f>>2],gc[1]=r[d+f+4>>2],fc[0]):"i64"==b?c=[r[d+f>>2],r[d+f+4>>2]]:(b="i32",c=r[d+f>>2]);f+=Math.max(db(b),vb);return c}for(var e=b,f=0,i=[],h,g;;){var k=e;h=p[e];if(0===h){break}g=p[e+1];if(37==h){var o=m,w=m,t=m,A=m;a:for(;;){switch(g){case 43:o=j;break;case 45:w=j;break;case 35:t=j;break;case 48:if(A){break a}else{A=j;break};default:break a}e++;g=p[e+1]}var y=0;if(42==g){y=c("i32"),e++,g=p[e+1]}else{for(;48<=g&&57>=g;){y=10*y+(g-48),e++,g=p[e+1]}}var C=m;if(46==g){var v=0,C=j;e++;g=p[e+1];if(42==g){v=c("i32"),e++}else{for(;;){g=p[e+1];if(48>g||57<g){break}v=10*v+(g-48);e++}}g=p[e+1]}else{v=6}var u;switch(String.fromCharCode(g)){case"h":g=p[e+2];104==g?(e++,u=1):u=2;break;case"l":g=p[e+2];108==g?(e++,u=8):u=4;break;case"L":case"q":case"j":u=8;break;case"z":case"t":case"I":u=4;break;default:u=l}u&&e++;g=p[e+1];if(-1!="d,i,u,o,x,X,p".split(",").indexOf(String.fromCharCode(g))){k=100==g||105==g;u=u||4;h=c("i"+8*u);8==u&&(h=117==g?(h[0]>>>0)+4294967296*(h[1]>>>0):(h[0]>>>0)+4294967296*(h[1]|0));4>=u&&(h=(k?Dc:Cc)(h&Math.pow(256,u)-1,8*u));var x=Math.abs(h),q,k="";if(100==g||105==g){q=Dc(h,8*u).toString(10)}else{if(117==g){q=Cc(h,8*u).toString(10),h=Math.abs(h)}else{if(111==g){q=(t?"0":"")+x.toString(8)}else{if(120==g||88==g){k=t?"0x":"";if(0>h){h=-h;q=(x-1).toString(16);t=[];for(x=0;x<q.length;x++){t.push((15-parseInt(q[x],16)).toString(16))}for(q=t.join("");q.length<2*u;){q="f"+q}}else{q=x.toString(16)}88==g&&(k=k.toUpperCase(),q=q.toUpperCase())}else{112==g&&(0===x?q="(nil)":(k="0x",q=x.toString(16)))}}}}if(C){for(;q.length<v;){q="0"+q}}for(o&&(k=0>h?"-"+k:"+"+k);k.length+q.length<y;){w?q+=" ":A?q="0"+q:k=" "+k}q=k+q;q.split("").forEach((function(b){i.push(b.charCodeAt(0))}))}else{if(-1!="f,F,e,E,g,G".split(",").indexOf(String.fromCharCode(g))){h=c("double");if(isNaN(h)){q="nan",A=m}else{if(isFinite(h)){C=m;u=Math.min(v,20);if(103==g||71==g){C=j,v=v||1,u=parseInt(h.toExponential(u).split("e")[1],10),v>u&&-4<=u?(g=(103==g?"f":"F").charCodeAt(0),v-=u+1):(g=(103==g?"e":"E").charCodeAt(0),v--),u=Math.min(v,20)}if(101==g||69==g){q=h.toExponential(u),/[eE][-+]\d$/.test(q)&&(q=q.slice(0,-1)+"0"+q.slice(-1))}else{if(102==g||70==g){q=h.toFixed(u)}}k=q.split("e");if(C&&!t){for(;1<k[0].length&&-1!=k[0].indexOf(".")&&("0"==k[0].slice(-1)||"."==k[0].slice(-1));){k[0]=k[0].slice(0,-1)}}else{for(t&&-1==q.indexOf(".")&&(k[0]+=".");v>u++;){k[0]+="0"}}q=k[0]+(1<k.length?"e"+k[1]:"");69==g&&(q=q.toUpperCase());o&&0<=h&&(q="+"+q)}else{q=(0>h?"-":"")+"inf",A=m}}for(;q.length<y;){q=w?q+" ":A&&("-"==q[0]||"+"==q[0])?q[0]+"0"+q.slice(1):(A?"0":" ")+q}97>g&&(q=q.toUpperCase());q.split("").forEach((function(b){i.push(b.charCodeAt(0))}))}else{if(115==g){(o=c("i8*"))?(o=Bc(o),C&&o.length>v&&(o=o.slice(0,v))):o=qc("(null)",j);if(!w){for(;o.length<y--;){i.push(32)}}i=i.concat(o);if(w){for(;o.length<y--;){i.push(32)}}}else{if(99==g){for(w&&i.push(c("i8"));0<--y;){i.push(32)}w||i.push(c("i8"))}else{if(110==g){w=c("i32*"),r[w>>2]=i.length}else{if(37==g){i.push(h)}else{for(x=k;x<e+2;x++){i.push(p[x])}}}}}}}e+=2}else{i.push(h),e+=1}}return i}function ed(b,d,c){d=xd(d,c);c=n;zd(F(d,"i8",hc),1,d.length,b);n=c}var gd={1:"Operation not permitted",2:"No such file or directory",3:"No such process",4:"Interrupted system call",5:"Input/output error",6:"No such device or address",8:"Exec format error",9:"Bad file descriptor",10:"No child processes",11:"Resource temporarily unavailable",12:"Cannot allocate memory",13:"Permission denied",14:"Bad address",16:"Device or resource busy",17:"File exists",18:"Invalid cross-device link",19:"No such device",20:"Not a directory",21:"Is a directory",22:"Invalid argument",23:"Too many open files in system",24:"Too many open files",25:"Inappropriate ioctl for device",26:"Text file busy",27:"File too large",28:"No space left on device",29:"Illegal seek",30:"Read-only file system",31:"Too many links",32:"Broken pipe",33:"Numerical argument out of domain",34:"Numerical result out of range",35:"Resource deadlock avoided",36:"File name too long",37:"No locks available",38:"Function not implemented",39:"Directory not empty",40:"Too many levels of symbolic links",42:"No message of desired type",43:"Identifier removed",60:"Device not a stream",61:"No data available",62:"Timer expired",63:"Out of streams resources",67:"Link has been severed",71:"Protocol error",72:"Multihop attempted",74:"Bad message",75:"Value too large for defined data type",84:"Invalid or incomplete multibyte or wide character",88:"Socket operation on non-socket",89:"Destination address required",90:"Message too long",91:"Protocol wrong type for socket",92:"Protocol not available",93:"Protocol not supported",95:"Operation not supported",97:"Address family not supported by protocol",98:"Address already in use",99:"Cannot assign requested address",100:"Network is down",101:"Network is unreachable",102:"Network dropped connection on reset",103:"Software caused connection abort",104:"Connection reset by peer",105:"No buffer space available",106:"Transport endpoint is already connected",107:"Transport endpoint is not connected",110:"Connection timed out",111:"Connection refused",113:"No route to host",114:"Operation already in progress",115:"Operation now in progress",116:"Stale NFS file handle",122:"Disk quota exceeded",125:"Operation canceled",130:"Owner died",131:"State not recoverable"},fd;function nd(b){if(!O[b]){return L(qd),0}if(O[b].m){return 1}L(Zd);return 0}function rd(b,d){ed(r[be>>2],b,d)}function T(){a("ABORT: undefined, at "+Error().stack)}function jc(b,d){var c=0;if(20<=d){for(var e=b+d;b%4;){p[b++]=c}0>c&&(c+=256);for(var f=b>>2,i=e>>2,h=c|c<<8|c<<16|c<<24;f<i;){r[f++]=h}for(b=f<<2;b<e;){p[b++]=c}}else{for(;d--;){p[b++]=c}}}function Kd(){switch(8){case 8:return mc;case 54:case 56:case 21:case 61:case 63:case 22:case 67:case 23:case 24:case 25:case 26:case 27:case 69:case 28:case 101:case 70:case 71:case 29:case 30:case 199:case 75:case 76:case 32:case 43:case 44:case 80:case 46:case 47:case 45:case 48:case 49:case 42:case 82:case 33:case 7:case 108:case 109:case 107:case 112:case 119:case 121:return 200809;case 13:case 104:case 94:case 95:case 34:case 35:case 77:case 81:case 83:case 84:case 85:case 86:case 87:case 88:case 89:case 90:case 91:case 94:case 95:case 110:case 111:case 113:case 114:case 115:case 116:case 117:case 118:case 120:case 40:case 16:case 79:case 19:return-1;case 92:case 93:case 5:case 72:case 6:case 74:case 92:case 93:case 96:case 97:case 98:case 99:case 102:case 103:case 105:return 1;case 38:case 66:case 50:case 51:case 4:return 1024;case 15:case 64:case 41:return 32;case 55:case 37:case 17:return 2147483647;case 18:case 1:return 47839;case 59:case 57:return 99;case 68:case 58:return 2048;case 0:return 2097152;case 3:return 65536;case 14:return 32768;case 73:return 32767;case 39:return 16384;case 60:return 1e3;case 106:return 700;case 52:return 256;case 62:return 255;case 2:return 100;case 65:return 64;case 36:return 20;case 100:return 16;case 20:return 6;case 53:return 4}L(id);return-1}function Fd(b){re||(Ib=Ib+4095>>12<<12,re=j);var d=Ib;0!=b&&Hb(b);return d}var re;function Vd(){return!!Vd.w}var Sd,Md;function jd(b){p[se]=Cc(10);-1==Lc(b,se,1)&&b in O&&(O[b].error=j)}function P(b){var d=r[be>>2];0>Lc(d,b,Ac(b))||jd(d)}L(0);vc.unshift({l:(function(){ee=m;pe||oe()})});yc.push({l:(function(){pe&&(O[2]&&0<O[2].object.e.buffer.length&&O[2].object.e(10),O[3]&&0<O[3].object.e.buffer.length&&O[3].object.e(10))})});var Ud=F(12,"void*",D),se=F([0],"i8",D);Module.Qa=(function(b){function d(){for(var b=0;3>b;b++){e.push(0)}}var c=b.length+1,e=[F(qc("/bin/this.program"),"i8",D)];d();for(var f=0;f<c-1;f+=1){e.push(F(qc(b[f]),"i8",D)),d()}e.push(0);e=F(e,"i32",D);return ld(c,e)});var Jc,vc=vc.concat([{l:(function(){for(var b=0;;){var d=b>>>1,d=0==(b&1|0)?d:d^-306674912,c=d>>>1,d=0==(d&1|0)?c:c^-306674912,c=d>>>1,d=0==(d&1|0)?c:c^-306674912,c=d>>>1,d=0==(d&1|0)?c:c^-306674912,c=d>>>1,d=0==(d&1|0)?c:c^-306674912,c=d>>>1,d=0==(d&1|0)?c:c^-306674912,c=d>>>1,d=0==(d&1|0)?c:c^-306674912,c=d>>>1;r[Jc+(b<<2)>>2]=0==(d&1|0)?c:c^-306674912;b=b+1|0;if(256==(b|0)){break}}})}]),dd,kd,md,vd,wd,ud,R,X,Nd,Od,Td,Pd;Jc=F(1024,"i32",D);I.G=F([82,97,110,103,101,32,100,101,99,111,100,101,114,32,102,105,110,97,108,32,99,111,100,101,32,105,115,32,110,111,116,32,122,101,114,111,0],"i8",D);I.F=F([7,7,7,7,7,7,7,10,10,10,10,10],"i8",D);I.C=F([8,8,8,8,8,8,8,11,11,11,11,11],"i8",D);I.B=F([9,9,9,9,9,9,9,11,11,11,11,11],"i8",D);I.D=F([0,0,0,0,1,2,3,4,5,6,4,5],"i8",D);dd=F(1,"i32",D);I.H=F([37,115,58,32,37,115,0],"i8",D);I.K=F([58,32,37,115,0],"i8",D);kd=F(1,"i8*",D);I.aa=F([84,114,121,32,96,37,115,32,45,45,104,101,108,112,39,32,102,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,46,10,0],"i8",D);I.ha=F([37,115,58,32,105,110,116,101,114,110,97,108,32,101,114,114,111,114,58,32,37,115,46,10,0],"i8",D);I.ia=F([117,110,99,97,117,103,104,116,32,111,112,116,105,111,110,0],"i8",D);md=F(1,"i1",D);I.ka=F([67,97,110,39,116,32,99,108,111,115,101,32,115,116,100,111,117,116,0],"i8",D);I.la=F([69,114,114,111,114,32,114,101,97,100,105,110,103,32,109,101,109,98,101,114,32,104,101,97,100,101,114,0],"i8",D);I.ma=F([66,97,100,32,109,97,103,105,99,32,110,117,109,98,101,114,32,40,102,105,108,101,32,110,111,116,32,105,110,32,108,122,105,112,32,102,111,114,109,97,116,41,0],"i8",D);I.I=F([86,101,114,115,105,111,110,32,37,100,32,109,101,109,98,101,114,32,102,111,114,109,97,116,32,110,111,116,32,115,117,112,112,111,114,116,101,100,46,10,0],"i8",D);I.J=F([73,110,118,97,108,105,100,32,100,105,99,116,105,111,110,97,114,121,32,115,105,122,101,32,105,110,32,109,101,109,98,101,114,32,104,101,97,100,101,114,0],"i8",D);I.L=F([118,101,114,115,105,111,110,32,37,100,44,32,100,105,99,116,105,111,110,97,114,121,32,115,105,122,101,32,37,55,115,66,46,32,32,0],"i8",D);I.M=F([70,105,108,101,32,101,110,100,115,32,117,110,101,120,112,101,99,116,101,100,108,121,32,97,116,32,112,111,115,32,37,108,108,100,10,0],"i8",D);I.N=F([68,101,99,111,100,101,114,32,101,114,114,111,114,32,97,116,32,112,111,115,32,37,108,108,100,10,0],"i8",D);I.n=F([111,107,10,0],"i8",D);I.o=F([100,111,110,101,10,0],"i8",D);vd=F(32,"*",D);I.O=F([75,105,0],"i8",D);I.P=F([77,105,0],"i8",D);I.Q=F([71,105,0],"i8",D);I.R=F([84,105,0],"i8",D);I.S=F([80,105,0],"i8",D);I.T=F([69,105,0],"i8",D);I.U=F([90,105,0],"i8",D);I.V=F([89,105,0],"i8",D);wd=F(16,"i8",D);ud=F(1,"i8",D);I.W=F([37,108,108,100,32,37,115,0],"i8",D);I.z=F([76,90,73,80],"i8",D);I.Y=F([73,32,119,111,110,39,116,32,119,114,105,116,101,32,99,111,109,112,114,101,115,115,101,100,32,100,97,116,97,32,116,111,32,97,32,116,101,114,109,105,110,97,108,46,0],"i8",D);I.Z=F([73,32,119,111,110,39,116,32,114,101,97,100,32,99,111,109,112,114,101,115,115,101,100,32,100,97,116,97,32,102,114,111,109,32,97,32,116,101,114,109,105,110,97,108,46,0],"i8",D);I.$=F([37,115,32,37,115,10,0],"i8",D);I.ba=F([49,46,49,50,0],"i8",D);I.ca=F([67,111,112,121,114,105,103,104,116,32,40,67,41,32,37,115,32,65,110,116,111,110,105,111,32,68,105,97,122,32,68,105,97,122,46,10,0],"i8",D);I.da=F([50,48,49,49,0],"i8",D);I.p=F([76,122,105,112,0],"i8",D);I.fa=F([37,115,32,45,32,68,97,116,97,32,99,111,109,112,114,101,115,115,111,114,32,98,97,115,101,100,32,111,110,32,116,104,101,32,76,90,77,65,32,97,108,103,111,114,105,116,104,109,46,10,0],"i8",D);I.ga=F([10,85,115,97,103,101,58,32,37,115,32,91,111,112,116,105,111,110,115,93,32,91,102,105,108,101,115,93,10,0],"i8",D);I.ja=F([73,102,32,110,111,32,102,105,108,101,32,110,97,109,101,115,32,97,114,101,32,103,105,118,101,110,44,32,37,115,32,99,111,109,112,114,101,115,115,101,115,32,111,114,32,100,101,99,111,109,112,114,101,115,115,101,115,10,0],"i8",D);I.i=F([108,122,105,112,0],"i8",D);R=F(468,["i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"*",0,0,0,"i32",0,0,0,"*",0,0,0,"i32",0,0,0,"*",0,0,0,"i32",0,0,0],D);X=F(24,"i32",D);Nd=F(1,"void ()*",D);Od=F([0,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,6,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],D);F(1,"void*",D);I.ea=F([115,116,100,58,58,98,97,100,95,97,108,108,111,99,0],"i8",D);I.A=F([83,116,57,98,97,100,95,97,108,108,111,99,0],"i8",D);Pd=F(12,"*",D);I.na=F([60,60,32,77,111,115,116,32,111,102,32,116,104,101,115,101,32,97,114,101,32,117,110,115,117,112,112,111,114,116,101,100,46,32,67,111,109,112,114,101,115,115,105,110,103,47,100,101,99,111,109,112,114,101,115,115,105,110,103,32,102,114,111,109,32,115,116,100,105,110,32,116,111,32,115,116,100,111,117,116,32,105,115,32,116,104,101,32,114,105,103,104,116,32,119,97,121,33,32,62,62,0],"i8",D);I.oa=F([10,79,112,116,105,111,110,115,58,0],"i8",D);I.za=F([32,32,45,104,44,32,45,45,104,101,108,112,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,100,105,115,112,108,97,121,32,116,104,105,115,32,104,101,108,112,32,97,110,100,32,101,120,105,116,0],"i8",D);I.Ia=F([32,32,45,86,44,32,45,45,118,101,114,115,105,111,110,32,32,32,32,32,32,32,32,32,32,32,32,32,32,111,117,116,112,117,116,32,118,101,114,115,105,111,110,32,105,110,102,111,114,109,97,116,105,111,110,32,97,110,100,32,101,120,105,116,0],"i8",D);I.Ja=F([32,32,45,98,44,32,45,45,109,101,109,98,101,114,45,115,105,122,101,61,60,110,62,32,32,32,32,32,32,115,101,116,32,109,101,109,98,101,114,32,115,105,122,101,32,108,105,109,105,116,32,105,110,32,98,121,116,101,115,0],"i8",D);I.Ka=F([32,32,45,99,44,32,45,45,115,116,100,111,117,116,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,115,101,110,100,32,111,117,116,112,117,116,32,116,111,32,115,116,97,110,100,97,114,100,32,111,117,116,112,117,116,0],"i8",D);I.La=F([32,32,45,100,44,32,45,45,100,101,99,111,109,112,114,101,115,115,32,32,32,32,32,32,32,32,32,32,32,100,101,99,111,109,112,114,101,115,115,0],"i8",D);I.Ma=F([32,32,45,102,44,32,45,45,102,111,114,99,101,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,111,118,101,114,119,114,105,116,101,32,101,120,105,115,116,105,110,103,32,111,117,116,112,117,116,32,102,105,108,101,115,0],"i8",D);I.Na=F([32,32,45,70,44,32,45,45,114,101,99,111,109,112,114,101,115,115,32,32,32,32,32,32,32,32,32,32,32,102,111,114,99,101,32,114,101,99,111,109,112,114,101,115,115,105,111,110,32,111,102,32,99,111,109,112,114,101,115,115,101,100,32,102,105,108,101,115,0],"i8",D);I.Oa=F([32,32,45,107,44,32,45,45,107,101,101,112,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,107,101,101,112,32,40,100,111,110,39,116,32,100,101,108,101,116,101,41,32,105,110,112,117,116,32,102,105,108,101,115,0],"i8",D);I.pa=F([32,32,45,109,44,32,45,45,109,97,116,99,104,45,108,101,110,103,116,104,61,60,110,62,32,32,32,32,32,115,101,116,32,109,97,116,99,104,32,108,101,110,103,116,104,32,108,105,109,105,116,32,105,110,32,98,121,116,101,115,32,91,51,54,93,0],"i8",D);I.qa=F([32,32,45,111,44,32,45,45,111,117,116,112,117,116,61,60,102,105,108,101,62,32,32,32,32,32,32,32,32,105,102,32,114,101,97,100,105,110,103,32,115,116,100,105,110,44,32,112,108,97,99,101,32,116,104,101,32,111,117,116,112,117,116,32,105,110,116,111,32,60,102,105,108,101,62,0],"i8",D);I.ra=F([32,32,45,113,44,32,45,45,113,117,105,101,116,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,115,117,112,112,114,101,115,115,32,97,108,108,32,109,101,115,115,97,103,101,115,0],"i8",D);I.sa=F([32,32,45,115,44,32,45,45,100,105,99,116,105,111,110,97,114,121,45,115,105,122,101,61,60,110,62,32,32,115,101,116,32,100,105,99,116,105,111,110,97,114,121,32,115,105,122,101,32,108,105,109,105,116,32,105,110,32,98,121,116,101,115,32,91,56,77,105,66,93,0],"i8",D);I.ta=F([32,32,45,83,44,32,45,45,118,111,108,117,109,101,45,115,105,122,101,61,60,110,62,32,32,32,32,32,32,115,101,116,32,118,111,108,117,109,101,32,115,105,122,101,32,108,105,109,105,116,32,105,110,32,98,121,116,101,115,0],"i8",D);I.ua=F([32,32,45,116,44,32,45,45,116,101,115,116,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,101,115,116,32,99,111,109,112,114,101,115,115,101,100,32,102,105,108,101,32,105,110,116,101,103,114,105,116,121,0],"i8",D);I.va=F([32,32,45,118,44,32,45,45,118,101,114,98,111,115,101,32,32,32,32,32,32,32,32,32,32,32,32,32,32,98,101,32,118,101,114,98,111,115,101,32,40,97,32,50,110,100,32,45,118,32,103,105,118,101,115,32,109,111,114,101,41,0],"i8",D);I.wa=F([32,32,45,48,32,46,46,32,45,57,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,115,101,116,32,99,111,109,112,114,101,115,115,105,111,110,32,108,101,118,101,108,32,91,100,101,102,97,117,108,116,32,54,93,0],"i8",D);I.xa=F([32,32,32,32,32,32,45,45,102,97,115,116,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,97,108,105,97,115,32,102,111,114,32,45,48,0],"i8",D);I.ya=F([32,32,32,32,32,32,45,45,98,101,115,116,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,97,108,105,97,115,32,102,111,114,32,45,57,0],"i8",D);I.Aa=F([102,114,111,109,32,115,116,97,110,100,97,114,100,32,105,110,112,117,116,32,116,111,32,115,116,97,110,100,97,114,100,32,111,117,116,112,117,116,46,0],"i8",D);I.Ba=F([78,117,109,98,101,114,115,32,109,97,121,32,98,101,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,109,117,108,116,105,112,108,105,101,114,58,32,107,32,61,32,107,66,32,61,32,49,48,94,51,32,61,32,49,48,48,48,44,0],"i8",D);I.Ca=F([75,105,32,61,32,75,105,66,32,61,32,50,94,49,48,32,61,32,49,48,50,52,44,32,77,32,61,32,49,48,94,54,44,32,77,105,32,61,32,50,94,50,48,44,32,71,32,61,32,49,48,94,57,44,32,71,105,32,61,32,50,94,51,48,44,32,101,116,99,46,46,46,0],"i8",D);I.Da=F([10,82,101,112,111,114,116,32,98,117,103,115,32,116,111,32,108,122,105,112,45,98,117,103,64,110,111,110,103,110,117,46,111,114,103,0],"i8",D);I.Ea=F([76,122,105,112,32,104,111,109,101,32,112,97,103,101,58,32,104,116,116,112,58,47,47,119,119,119,46,110,111,110,103,110,117,46,111,114,103,47,108,122,105,112,47,108,122,105,112,46,104,116,109,108,0],"i8",D);I.Fa=F([76,105,99,101,110,115,101,32,71,80,76,118,51,43,58,32,71,78,85,32,71,80,76,32,118,101,114,115,105,111,110,32,51,32,111,114,32,108,97,116,101,114,32,60,104,116,116,112,58,47,47,103,110,117,46,111,114,103,47,108,105,99,101,110,115,101,115,47,103,112,108,46,104,116,109,108,62,0],"i8",D);I.Ga=F([84,104,105,115,32,105,115,32,102,114,101,101,32,115,111,102,116,119,97,114,101,58,32,121,111,117,32,97,114,101,32,102,114,101,101,32,116,111,32,99,104,97,110,103,101,32,97,110,100,32,114,101,100,105,115,116,114,105,98,117,116,101,32,105,116,46,0],"i8",D);I.Ha=F([84,104,101,114,101,32,105,115,32,78,79,32,87,65,82,82,65,78,84,89,44,32,116,111,32,116,104,101,32,101,120,116,101,110,116,32,112,101,114,109,105,116,116,101,100,32,98,121,32,108,97,119,46,0],"i8",D);r[vd>>2]=I.O|0;r[vd+4>>2]=I.P|0;r[vd+8>>2]=I.Q|0;r[vd+12>>2]=I.R|0;r[vd+16>>2]=I.S|0;r[vd+20>>2]=I.T|0;r[vd+24>>2]=I.U|0;r[vd+28>>2]=I.V|0;r[Od+4>>2]=Pd;Td=F([2,0,0,0,0],["i8*",0,0,0,0],D);r[Pd>>2]=Td+8|0;r[Pd+4>>2]=I.A|0;r[Pd+8>>2]=ca;lc=[0,0,Ld,0,(function(b){Ld(b);yd(b)}),0,(function(){return I.ea|0}),0];Module.FUNCTION_TABLE=lc;function te(b){b=b||Module.arguments;uc(vc);var d=l;Module._main&&(d=Module.Qa(b),Module.noExitRuntime||uc(yc));return d}Module.run=te;Module.preRun&&Module.preRun();te();Module.postRun&&Module.postRun() + + return returnValue; + }, + + compress: function(data) { + return this.run(data); + }, + + decompress: function(data) { + return this.run(data, true); + } +}; + diff --git a/third_party/lzma.js/lzma-full.js b/third_party/lzma.js/lzma-full.js new file mode 100644 index 00000000..c5ce2cc1 --- /dev/null +++ b/third_party/lzma.js/lzma-full.js @@ -0,0 +1,27 @@ + +// This is lzma.js, powered by lzip (which is GPL, source code at https://github.com/kripken/lzma.js) +var LZMA = { + run: function(data, decompress) { + var inputIndex = 0; + var returnValue = []; + var Module = { + arguments: ['-q'].concat(decompress ? ['-d'] : []), + stdin: function() { return inputIndex < data.length ? data[inputIndex++] : null }, + stdout: function(x) { if (x !== null) returnValue.push(x) } + }; + + +function b(a){throw a}var aa=void 0,k=!0,ca=null,l=!1,ea=[],pa="object"===typeof process,ya="object"===typeof window,za="function"===typeof importScripts,Ca=!ya&&!pa&&!za;if(pa){print=(function(a){process.stdout.write(a+"\n")});printErr=(function(a){process.stderr.write(a+"\n")});var Da=require("fs");read=(function(a){var c=Da.readFileSync(a).toString();!c&&"/"!=a[0]&&(a=__dirname.split("/").slice(0,-1).join("/")+"/src/"+a,c=Da.readFileSync(a).toString());return c});load=(function(a){Ra(read(a))});ea=process.argv.slice(2)}else{Ca?(this.read||(this.read=(function(a){snarf(a)})),"undefined"!=typeof scriptArgs?ea=scriptArgs:"undefined"!=typeof arguments&&(ea=arguments)):ya?(this.print=printErr=(function(a){console.log(a)}),this.read=(function(a){var c=new XMLHttpRequest;c.open("GET",a,l);c.send(ca);return c.responseText}),this.arguments&&(ea=arguments)):za?this.load=importScripts:b("Unknown runtime environment. Where are we?")}function Ra(a){eval.call(ca,a)}"undefined"==typeof load&&"undefined"!=typeof read&&(this.load=(function(a){Ra(read(a))}));"undefined"===typeof printErr&&(this.printErr=(function(){}));"undefined"===typeof print&&(this.print=printErr);try{this.Module=Module}catch(ab){this.Module=Module={}}Module.arguments||(Module.arguments=ea);Module.print&&(print=Module.print);function nb(a){if(1==ob){return 1}var c={"%i1":1,"%i8":1,"%i16":2,"%i32":4,"%i64":8,"%float":4,"%double":8}["%"+a];c||("*"==a[a.length-1]?c=ob:"i"==a[0]&&(a=parseInt(a.substr(1)),qb(0==a%8),c=a/8));return c}function zb(a){var c=m;m+=a;m=m+3>>2<<2;return c}function Bb(a){var c=Cb;Cb+=a;Cb=Cb+3>>2<<2;if(Cb>=Db){for(;Db<=Cb;){Db=2*Db+4095>>12<<12}var a=n,d=new ArrayBuffer(Db);n=new Int8Array(d);Rb=new Int16Array(d);p=new Int32Array(d);w=new Uint8Array(d);Sb=new Uint16Array(d);x=new Uint32Array(d);Ub=new Float32Array(d);Vb=new Float64Array(d);n.set(a)}return c}var ob=4,Wb={},Xb,z,C,Yb;function ac(a){print(a+":\n"+Error().stack);b("Assertion: "+a)}function qb(a,c){a||ac("Assertion failed: "+c)}var bc=this;Module.ccall=(function(a,c,d,e){try{var f=eval("_"+a)}catch(g){try{f=bc.Module["_"+a]}catch(h){}}qb(f,"Cannot call unknown function "+a+" (perhaps LLVM optimizations or closure removed it?)");var i=0,a=e?e.map((function(a){if("string"==d[i++]){var c=m;zb(a.length+1);cc(a,c);a=c}return a})):[];return(function(a,c){return"string"==c?dc(a):a})(f.apply(ca,a),c)});function ec(a,c,d){d=d||"i8";"*"===d[d.length-1]&&(d="i32");switch(d){case"i1":n[a]=c;break;case"i8":n[a]=c;break;case"i16":Rb[a>>1]=c;break;case"i32":p[a>>2]=c;break;case"i64":p[a>>2]=c;break;case"float":Ub[a>>2]=c;break;case"double":fc[0]=c;p[a>>2]=jc[0];p[a+4>>2]=jc[1];break;default:ac("invalid type for setValue: "+d)}}Module.setValue=ec;Module.getValue=(function(a,c){c=c||"i8";"*"===c[c.length-1]&&(c="i32");switch(c){case"i1":return n[a];case"i8":return n[a];case"i16":return Rb[a>>1];case"i32":return p[a>>2];case"i64":return p[a>>2];case"float":return Ub[a>>2];case"double":return jc[0]=p[a>>2],jc[1]=p[a+4>>2],fc[0];default:ac("invalid type for setValue: "+c)}return ca});var kc=1,E=2;Module.ALLOC_NORMAL=0;Module.ALLOC_STACK=kc;Module.ALLOC_STATIC=E;function F(a,c,d){var e,f;"number"===typeof a?(e=k,f=a):(e=l,f=a.length);var g="string"===typeof c?c:ca,d=[nc,zb,Bb][d===aa?E:d](Math.max(f,g?1:c.length));if(e){return oc(d,0,f),d}e=0;for(var h;e<f;){var i=a[e];"function"===typeof i&&(i=Wb.fb(i));h=g||c[e];0===h?e++:("i64"==h&&(h="i32"),ec(d+e,i,h),e+=nb(h))}return d}Module.allocate=F;function dc(a,c){for(var d="undefined"==typeof c,e="",f=0,g,h=String.fromCharCode(0);;){g=String.fromCharCode(w[a+f]);if(d&&g==h){break}e+=g;f+=1;if(!d&&f==c){break}}return e}Module.Pointer_stringify=dc;Module.Array_stringify=(function(a){for(var c="",d=0;d<a.length;d++){c+=String.fromCharCode(a[d])}return c});var pc,qc=4096,n,w,Rb,Sb,p,x,Ub,Vb,m,rc,Cb,sc=Module.TOTAL_STACK||5242880,Db=Module.TOTAL_MEMORY||10485760;qb(!!Int32Array&&!!Float64Array&&!!(new Int32Array(1)).subarray&&!!(new Int32Array(1)).set,"Cannot fallback to non-typed array case: Code is too specialized");var tc=new ArrayBuffer(Db);n=new Int8Array(tc);Rb=new Int16Array(tc);p=new Int32Array(tc);w=new Uint8Array(tc);Sb=new Uint16Array(tc);x=new Uint32Array(tc);Ub=new Float32Array(tc);Vb=new Float64Array(tc);p[0]=255;qb(255===w[0]&&0===w[3],"Typed arrays 2 must be run on a little-endian system");var vc=uc("(null)");Cb=vc.length;for(var wc=0;wc<vc.length;wc++){n[wc]=vc[wc]}Module.HEAP=aa;Module.HEAP8=n;Module.HEAP16=Rb;Module.HEAP32=p;Module.HEAPU8=w;Module.HEAPU16=Sb;Module.HEAPU32=x;Module.HEAPF32=Ub;Module.HEAPF64=Vb;rc=(m=4*Math.ceil(Cb/4))+sc;var xc=8*Math.ceil(rc/8);n.subarray(xc);var jc=p.subarray(xc>>2);Ub.subarray(xc>>2);var fc=Vb.subarray(xc>>3);rc=xc+8;Cb=rc+4095>>12<<12;function yc(a){for(;0<a.length;){var c=a.shift(),d=c.l;"number"===typeof d&&(d=pc[d]);d(c.$a===aa?ca:c.$a)}}var Ac=[],Bc=[];function Cc(a,c){return Array.prototype.slice.call(n.subarray(a,a+c))}Module.Array_copy=Cc;Module.TypedArray_copy=(function(a,c){for(var d=new Uint8Array(c),e=0;e<c;++e){d[e]=n[a+e]}return d.buffer});function Dc(a){for(var c=0;n[a+c];){c++}return c}Module.String_len=Dc;function Ec(a,c){var d=Dc(a);c&&d++;var e=Cc(a,d);c&&(e[d-1]=0);return e}Module.String_copy=Ec;function uc(a,c){for(var d=[],e=0;e<a.length;){var f=a.charCodeAt(e);255<f&&(f&=255);d.push(f);e+=1}c||d.push(0);return d}Module.intArrayFromString=uc;Module.intArrayToString=(function(a){for(var c=[],d=0;d<a.length;d++){var e=a[d];255<e&&(e&=255);c.push(String.fromCharCode(e))}return c.join("")});function cc(a,c,d){for(var e=0;e<a.length;){var f=a.charCodeAt(e);255<f&&(f&=255);n[c+e]=f;e+=1}d||(n[c+e]=0)}Module.writeStringToMemory=cc;var K=[];function Fc(a,c){return 0<=a?a:32>=c?2*Math.abs(1<<c-1)+a:Math.pow(2,c)+a}function Gc(a,c){if(0>=a){return a}var d=32>=c?Math.abs(1<<c-1):Math.pow(2,c-1);if(a>=d&&(32>=c||a>d)){a=-2*d+a}return a}function Hc(a,c,d){var e=0>(d|0)?-1:0,f=(d>>>0)+4294967296*(e|0)+(a>>>0)+4294967296*(c|0)>>>0,a=Math.min(Math.floor(((d>>>0)+4294967296*(e|0)+(a>>>0)+4294967296*(c|0))/4294967296),4294967295);return[f,a]}function Ic(a,c,d){var e=0>(d|0)?-1:0,f=(d>>>0)+4294967296*(e|0)+(a>>>0)+4294967296*(c|0)>>>0,a=Math.min(Math.floor(((d>>>0)+4294967296*(e|0)+(a>>>0)+4294967296*(c|0))/4294967296),4294967295);return[f,a]}function Jc(a,c,d){var e=0<(d|0);a:do{if(e){for(var f=0,g=p[a>>2];;){if(g=p[Kc+((w[c+f|0]&255^g&255)<<2)>>2]^g>>>8,p[a>>2]=g,f=f+1|0,(f|0)==(d|0)){break a}}}}while(0)}function Lc(a,c,d){n[a+12|0]=c&255;n[a+13|0]=(c>>>8|d<<24)&255;n[a+14|0]=(c>>>16|d<<16)&255;n[a+15|0]=(c>>>24|d<<8)&255;n[a+16|0]=d&255;n[a+17|0]=(d>>>8|0)&255;n[a+18|0]=(d>>>16|0)&255;n[a+19|0]=(d>>>24|0)&255}function Mc(a){var c=n[a+11|0],d=n[a+10|0]|c<<8|0,e=n[a+9|0]|d<<8|0,f=n[a+8|0]|e<<8|0,g=n[a+7|0]|f<<8|0,h=n[a+6|0]|g<<8|0,i=n[a+5|0]|h<<8|0;return[n[a+4|0]|i<<8|0,0|((((((0|c>>>24)<<8|d>>>24)<<8|e>>>24)<<8|f>>>24)<<8|g>>>24)<<8|h>>>24)<<8|i>>>24]}Mc.X=1;function Nc(a){var c=n[a+19|0],d=n[a+18|0]|c<<8|0,e=n[a+17|0]|d<<8|0,f=n[a+16|0]|e<<8|0,g=n[a+15|0]|f<<8|0,h=n[a+14|0]|g<<8|0,i=n[a+13|0]|h<<8|0;return[n[a+12|0]|i<<8|0,0|((((((0|c>>>24)<<8|d>>>24)<<8|e>>>24)<<8|f>>>24)<<8|g>>>24)<<8|h>>>24)<<8|i>>>24]}Nc.X=1;function Oc(a,c,d){p[Pc>>2]=0;var e=d;a:for(;;){var f=c+(d-e)|0;if(0>=(e|0)){var g=0;break}for(;;){p[Pc>>2]=0;var h=Qc(a,f,e);if(0<(h|0)){break}if(0==(h|0)){g=e;break a}if(4!=(p[Pc>>2]|0)&&11!=(p[Pc>>2]|0)){g=e;break a}}e=e-h|0}return d-g|0}function Rc(a,c,d){p[Pc>>2]=0;var e=d;a:for(;;){var f=c+(d-e)|0;if(0>=(e|0)){var g=0;break}for(;;){p[Pc>>2]=0;var h=Sc(a,f,e);if(0<(h|0)){break}if(0!=(p[Pc>>2]|0)&&4!=(p[Pc>>2]|0)&&11!=(p[Pc>>2]|0)){g=e;break a}}e=e-h|0}return d-g|0}function Tc(a){var c,d;d=(a+20|0)>>2;c=(a+24|0)>>2;var e=p[c],f=p[d]-e|0;if(0<(f|0)){var g=a+16|0;Jc(a+28|0,p[g>>2]+e|0,f);e=p[a+32>>2];-1<(e|0)&&(Rc(e,p[g>>2]+p[c]|0,f)|0)!=(f|0)&&Uc(-1);f=p[d];if((f|0)<(p[a+12>>2]|0)){d=f}else{var g=0>(f|0)?-1:0,a=(a|0)>>2,h=p[a],i=p[a+1],e=(h>>>0)+4294967296*(i|0)+(f>>>0)+4294967296*(g|0)>>>0,f=Math.min(Math.floor(((h>>>0)+4294967296*(i|0)+(f>>>0)+4294967296*(g|0))/4294967296),4294967295);p[a]=e;p[a+1]=f;d=p[d]=0}p[c]=d}}function Vc(a){var c,d=m;m+=20;var e=a+36|0,f=0<(p[e>>2]|0)?20:12;c=(a+40|0)>>2;for(var g=p[c],h=g|0,g=Hc(p[h>>2],p[h+4>>2],p[g+12>>2]),h=g[0],i=g[1],j=0>(f|0)?-1:0,g=(h>>>0)+4294967296*(i|0)+(f>>>0)+4294967296*(j|0)>>>0,h=Math.min(Math.floor(((h>>>0)+4294967296*(i|0)+(f>>>0)+4294967296*(j|0))/4294967296),4294967295),j=i=0;(i|0)<(f|0);){if(0!=(j&1)<<24>>24){break}if(Wc(p[c])){oc(d+i|0,0,f-i|0),i=f,j=1}else{var o=Xc(p[c]);n[d+i|0]=o}i=i+1|0}0==(p[e>>2]|0)&&Lc(d,g,h);0==(p[p[c]+20>>2]|0)?c=j:(Yc(K.L|0),c=1);e=(w[d|0]&255|(w[d+1|0]&255|(w[d+2|0]&255|(w[d+3|0]&255)<<8)<<8)<<8|0)==(p[a+28>>2]^-1|0);i=Mc(d);f=i[0];i=i[1];j=a|0;a=Ic(p[j>>2],p[j+4>>2],p[a+20>>2]);j=Nc(d);a=(j[0]==g&&j[1]==h)&(f==a[0]&&i==a[1])&e&0==(c&1)<<24>>24;m=d;return a}Vc.X=1;function Wc(a){var c;if((p[a+12>>2]|0)<(p[a+16>>2]|0)){c=0}else{var d=a+32|0;if(0==(n[d]&1)<<24>>24){c=Oc(p[a+28>>2],p[a+8>>2],16384);var e=a+16|0;p[e>>2]=c;16384!=(c|0)&&0!=(p[Pc>>2]|0)&&Uc(-1);c=x[e>>2];n[d]=16384>(c|0)&1;var d=a+12|0,e=p[d>>2],f=0>(e|0)?-1:0,a=(a|0)>>2,g=p[a],h=p[a+1],i=(g>>>0)+4294967296*(h|0)+(e>>>0)+4294967296*(f|0)>>>0,e=Math.min(Math.floor(((g>>>0)+4294967296*(h|0)+(e>>>0)+4294967296*(f|0))/4294967296),4294967295);p[a]=i;p[a+1]=e;d=p[d>>2]=0}else{d=p[a+12>>2],c=p[a+16>>2]}c=(d|0)<(c|0)^1}return c}function Xc(a){if(Wc(a)){a=85}else{var c=a+12|0,d=p[c>>2];p[c>>2]=d+1|0;a=n[p[a+8>>2]+d|0]}return a}function Zc(a){var c,d=m;m+=29280;for(var e,f=d+192,g=d+240,h=d+288,i=d+336,j=d+384,o=d+576,u=d+1600,q=d+2060,t=d+2124,s=d+3412,B=d+4700,v=d+29276,y=d+192|0,A=d|0;;){T(A);var r=A+4|0;if((r|0)==(y|0)){break}A=r}T(f|0);T(f+4|0);T(f+8|0);T(f+12|0);T(f+16|0);T(f+20|0);T(f+24|0);T(f+28|0);T(f+32|0);T(f+36|0);T(f+40|0);T(f+44|0);T(g|0);T(g+4|0);T(g+8|0);T(g+12|0);T(g+16|0);T(g+20|0);T(g+24|0);T(g+28|0);T(g+32|0);T(g+36|0);T(g+40|0);T(g+44|0);T(h|0);T(h+4|0);T(h+8|0);T(h+12|0);T(h+16|0);T(h+20|0);T(h+24|0);T(h+28|0);T(h+32|0);T(h+36|0);T(h+40|0);T(h+44|0);T(i|0);T(i+4|0);T(i+8|0);T(i+12|0);T(i+16|0);T(i+20|0);T(i+24|0);T(i+28|0);T(i+32|0);T(i+36|0);T(i+40|0);T(i+44|0);for(var D=j+192|0,L=j|0;;){T(L);var H=L+4|0;if((H|0)==(D|0)){break}L=H}for(var P=o+1024|0,J=o|0;;){T(J);var G=J+4|0;if((G|0)==(P|0)){break}J=G}for(var I=u+460|0,M=u|0;;){T(M);var O=M+4|0;if((O|0)==(I|0)){break}M=O}var N=q|0;T(N);T(q+4|0);T(q+8|0);T(q+12|0);T(q+16|0);T(q+20|0);T(q+24|0);T(q+28|0);T(q+32|0);T(q+36|0);T(q+40|0);T(q+44|0);T(q+48|0);T(q+52|0);T(q+56|0);T(q+60|0);$c(t);$c(s);for(var Q=B+24576|0,$=B|0;;){T($);var ha=$+4|0;if((ha|0)==(Q|0)){break}$=ha}n[v|0]=0;c=(a+40|0)>>2;ad(p[c]);var ba=a+8|0,R=a+20|0,Sa=a|0,fa=v|0,U=0,qa=0,Aa=0,da=0;a:for(;;){b:for(;;){if(Wc(p[c])){Tc(a);var Ea=2;break a}var ra=Sa|0,pb=Sa+4|0,bb=Ic(p[ra>>2],p[pb>>2],p[R>>2])[0]&3,Eb=w[fa],sa=Eb&255;if(0==(bd(p[c],(sa<<4)+(bb<<2)+d|0)|0)){var Fa,Zb=p[a+20>>2];Fa=n[p[a+16>>2]+((0<(Zb|0)?Zb:p[a+12>>2])-1)|0];var ga=p[c];if(7>(Eb&255)){var ta=fd(ga,B+3072*((Fa&255)>>5)|0,8)&255;gd(a,ta)}else{for(var ia=p[a+20>>2]-U-1|0,La=ga,cb=B+3072*((Fa&255)>>5)|0,db=n[p[a+16>>2]+(0>(ia|0)?p[a+12>>2]+ia|0:ia)|0]&255,Fb=aa,ja=7,rb=1;;){if(-1>=(ja|0)){var Ga=rb,Fb=7;break}var sb=db>>>(ja>>>0)&1,tb=bd(La,((sb<<8)+rb+256<<2)+cb|0),Ta=tb|rb<<1;if((sb|0)!=(tb|0)){Fb=4;break}ja=ja-1|0;rb=Ta}c:do{if(4==Fb){if(0<(ja|0)){for(var Ma=Ta,Ua=ja;;){var ub=Ua-1|0,eb=Ma<<1,vb=bd(La,(Ma<<2)+cb|0)|eb;if(0>=(ub|0)){Ga=vb;break c}Ma=vb;Ua=ub}}else{Ga=Ta}}}while(0);gd(a,Ga&255)}hd(v)}else{var Na=bd(p[c],(sa<<2)+f|0),Va=x[c];if(1==(Na|0)){var Nb=1==(bd(Va,(sa<<2)+g|0)|0),Gb=p[c];do{if(!Nb){if(0!=(bd(Gb,(sa<<4)+(bb<<2)+j|0)|0)){var Hb=U,Ib=qa,Wa=Aa,Y=da;break}id(v);var na=U,ka=qa,ua=Aa,va=da,fb=1;e=37;break b}if(0==(bd(Gb,(sa<<2)+h|0)|0)){Hb=qa,Ib=U,Wa=Aa,Y=da}else{var Oa=0==(bd(p[c],(sa<<2)+i|0)|0),gb=Oa?da:Aa,Hb=Oa?Aa:da,Ib=U,Wa=qa,Y=gb}}while(0);jd(v);var Ob=kd(s,p[c],bb),na=Hb,ka=Ib,ua=Wa,va=Y,fb=Ob+2|0;e=37;break}var S=kd(t,Va,bb),oa=S+2|0,Xa=fd(p[c],(ld(oa)<<8)+o|0,6);if(4>(Xa|0)){var la=Xa;e=33;break}var wa=Xa>>1,ma=wa-1|0,Ya=(Xa&1|2)<<ma,Jb=p[c];if(14>(Xa|0)){la=md(Jb,(Ya-Xa<<2)+u|0,ma)+Ya|0;e=33;break}var wb=Jb,Za=wa-5|0,Ha=aa,Ia=aa,Pa=0<(Za|0);c:do{if(Pa){for(var Ia=(wb+24|0)>>2,Ha=(wb+20|0)>>2,hb=0,ib=Za,Qa=p[Ia];;){var xa=hb<<1;if(16777216>Qa>>>0){p[Ia]=Qa<<7;var Ja=p[Ha]<<8,jb=Xc(wb)&255|Ja;p[Ha]=jb;var Ba=x[Ia];if(jb>>>0<Ba>>>0){var $a=xa,xb=Ba}else{p[Ha]=jb-Ba|0,$a=xa|1,xb=Ba}}else{var kb=Qa>>>1;p[Ia]=kb;var yb=x[Ha];yb>>>0<kb>>>0?$a=xa:(p[Ha]=yb-kb|0,$a=xa|1);xb=kb}var Kb=ib-1|0;if(0>=(Kb|0)){var Lb=$a;break c}hb=$a;ib=Kb;Qa=xb}}else{Lb=0}}while(0);var Pb=Lb<<4,Qb=md(p[c],N,4),Ka=Pb+Ya+Qb|0;if(-1!=(Ka|0)){la=Ka;e=33;break}nd(p[c]);Tc(a);if(0==(S|0)){Ea=Vc(a)?0:3;break a}if(3!=(oa|0)){Ea=4;break a}ad(p[c])}}do{if(33==e){od(v);if(la>>>0<x[ba>>2]>>>0){if(la>>>0<x[R>>2]>>>0){na=la;ka=U;ua=qa;va=Aa;fb=oa;break}ra=Sa|0;pb=Sa+4|0;if(!(0==p[ra>>2]&&0==p[pb>>2])){na=la;ka=U;ua=qa;va=Aa;fb=oa;break}}Tc(a);Ea=1;break a}}while(0);pd(a,na,fb);U=na;qa=ka;Aa=ua;da=va}m=d;return Ea}Zc.X=1;function ad(a){var c;c=(a+20|0)>>2;p[c]=0;p[a+24>>2]=-1;var d=Xc(a)&255;p[c]=d;d=Xc(a)&255|d<<8;p[c]=d;d=Xc(a)&255|d<<8;p[c]=d;d=Xc(a)&255|d<<8;p[c]=d;d<<=8;a=Xc(a);p[c]=a&255|d}function ld(a){a=a-2|0;return 3<(a|0)?3:a}function hd(a){a|=0;n[a]=n[K.J+(w[a]&255)|0]}function id(a){a|=0;n[a]=n[K.H+(w[a]&255)|0]}function jd(a){a|=0;n[a]=n[K.I+(w[a]&255)|0]}function od(a){a|=0;n[a]=n[K.K+(w[a]&255)|0]}function T(a){p[a>>2]=1024}function bd(a,c){var d,e;nd(a);e=(a+24|0)>>2;var f=x[e];d=(c|0)>>2;var g=(f>>>11)*p[d]|0,h=a+20|0,i=x[h>>2];i>>>0<g>>>0?(p[e]=g,f=x[d],e=0,f=((2048-f|0)>>>5)+f|0):(p[e]=f-g|0,p[h>>2]=i-g|0,f=x[d],e=1,f=f-(f>>>5)|0);p[d]=f;return e}function gd(a,c){var d;d=(a+20|0)>>2;n[p[a+16>>2]+p[d]|0]=c;var e=p[d]+1|0;p[d]=e;(e|0)<(p[a+12>>2]|0)||Tc(a)}function kd(a,c,d){return 0==(bd(c,a|0)|0)?fd(c,(d<<5)+a+8|0,3):0==(bd(c,a+4|0)|0)?fd(c,(d<<5)+a+136|0,3)+8|0:fd(c,a+264|0,8)+16|0}function fd(a,c,d){var e=0<(d|0);a:do{if(e){for(var f=1,g=d;;){var h=f<<1,f=bd(a,(f<<2)+c|0)|h,g=g-1|0;if(0>=(g|0)){var i=f;break a}}}else{i=1}}while(0);return i-(1<<d)|0}function md(a,c,d){var e=0<(d|0);a:do{if(e){for(var f=1,g=0,h=0;;){var i=bd(a,(f<<2)+c|0),f=f<<1;0!=(i|0)&&(g|=1<<h,f|=1);h=h+1|0;if((h|0)==(d|0)){var j=g;break a}}}else{j=0}}while(0);return j}function nd(a){var c=a+24|0,d=x[c>>2];16777216>d>>>0&&(p[c>>2]=d<<8,c=a+20|0,d=p[c>>2]<<8,a=Xc(a)&255|d,p[c>>2]=a)}function pd(a,c,d){var e,f;e=(a+20|0)>>2;var g=p[e],h=g-c-1|0,c=(a+12|0)>>2;f=p[c];h=h+(0>(h|0)?f:0)|0;(f-((g|0)>(h|0)?g:h)|0)>(d|0)?(f=g-h|0,((-1<(f|0)?f:-f|0)|0)<(d|0)?f=3:(f=p[a+16>>2],qd(f+g|0,f+h|0,d),p[e]=p[e]+d|0,f=10)):f=3;a:do{if(3==f&&0<(d|0)){for(var i=a+16|0,j=d,o=h,u=g;;){var q=p[i>>2];n[q+u|0]=n[q+o|0];u=p[e]+1|0;p[e]=u;q=p[c];(u|0)<(q|0)?u=q:(Tc(a),u=p[c]);o=o+1|0;j=j-1|0;if(0>=(j|0)){break a}o=(o|0)<(u|0)?o:0;u=p[e]}}}while(0)}pd.X=1;function $c(a){T(a|0);T(a+4|0);T(a+8|0);T(a+12|0);T(a+16|0);T(a+20|0);T(a+24|0);T(a+28|0);T(a+32|0);T(a+36|0);T(a+40|0);T(a+44|0);T(a+48|0);T(a+52|0);T(a+56|0);T(a+60|0);T(a+64|0);T(a+68|0);T(a+72|0);T(a+76|0);T(a+80|0);T(a+84|0);T(a+88|0);T(a+92|0);T(a+96|0);T(a+100|0);T(a+104|0);T(a+108|0);T(a+112|0);T(a+116|0);T(a+120|0);T(a+124|0);T(a+128|0);T(a+132|0);T(a+136|0);T(a+140|0);T(a+144|0);T(a+148|0);T(a+152|0);T(a+156|0);T(a+160|0);T(a+164|0);T(a+168|0);T(a+172|0);T(a+176|0);T(a+180|0);T(a+184|0);T(a+188|0);T(a+192|0);T(a+196|0);T(a+200|0);T(a+204|0);T(a+208|0);T(a+212|0);T(a+216|0);T(a+220|0);T(a+224|0);T(a+228|0);T(a+232|0);T(a+236|0);T(a+240|0);T(a+244|0);T(a+248|0);T(a+252|0);T(a+256|0);T(a+260|0);for(var c=a+1288|0,a=a+264|0;!(T(a),a=a+4|0,(a|0)==(c|0));){}}$c.X=1;function rd(a,c,d,e){var f,g=a>>2,h=a|0;p[h>>2]=0;p[h+4>>2]=0;var h=a+12|0,i=sd(5505024);p[h>>2]=i;p[g+7]=0;p[g+8]=0;i=a+36|0;p[i>>2]=0;p[g+11]=d;p[g+12]=273>(d|0)?d/2+16|0:256;p[g+13]=e;e=a+56|0;n[e]=0;var j=(c<<1)+4370|0;f=65536>(c|0)?65536:c;d=(a+24|0)>>2;p[d]=f;var o=nc(f);f=(a+8|0)>>2;p[f]=o;0==(o|0)&&Uc(-1);td(a)&&0==(n[e]&1)<<24>>24&&(p[d]|0)<(j|0)&&(p[d]=j,j=0==(p[f]|0)?nc(j):ud(p[f],j),p[f]=j,0==(j|0)&&Uc(-1),td(a));0==(n[e]&1)<<24>>24?(p[g+5]=c,a=p[d]-273|0):(a=p[i>>2],(a|0)<(c|0)&&(c=4096>(a|0)?4096:a),p[g+5]=c,a=p[d]);p[g+10]=a;c=sd(4*(c<<1));p[g+4]=c;for(g=0;!(p[((g<<2)+p[h>>2]|0)>>2]=-1,g=g+1|0,1376256==(g|0));){}}rd.X=1;function td(a){var c,d=a+56|0,e=0==(n[d]&1)<<24>>24;c=(a+36|0)>>2;if(e){var f=p[c],e=p[a+24>>2];if((f|0)<(e|0)){e=e-f|0;f=Oc(p[a+52>>2],p[a+8>>2]+f|0,e);p[c]=p[c]+f|0;if((f|0)!=(e|0)&&0!=(p[Pc>>2]|0)){var g=nc(4);p[g>>2]=K.ea|0;vd(g,wd,0);b("Reached an unreachable!")}n[d]=(f|0)<(e|0)&1}}return(p[a+28>>2]|0)<(p[c]|0)}function xd(a){var c,d,e,f;e=(a+32|0)>>2;var g=p[e]+1|0;p[e]=g;f=(a+20|0)>>2;(g|0)<(p[f]|0)||(p[e]=0);e=(a+28|0)>>2;g=p[e]+1|0;p[e]=g;var h=(g|0)<(p[a+40>>2]|0);do{if(!h&&(d=(a+36|0)>>2,(g|0)>(p[d]|0)&&yd(K.O|0),0==(n[a+56|0]&1)<<24>>24)){var i=p[e]-p[f]-4097|0;c=p[a+8>>2];zd(c,c+i|0,p[d]-i|0);var j=i,o=0>(i|0)?-1:0;c=(a|0)>>2;var u=p[c],q=p[c+1],t=(u>>>0)+4294967296*(q|0)+(j>>>0)+4294967296*(o|0)>>>0,j=Math.min(Math.floor(((u>>>0)+4294967296*(q|0)+(j>>>0)+4294967296*(o|0))/4294967296),4294967295);p[c]=t;p[c+1]=j;p[e]=p[e]-i|0;p[d]=p[d]-i|0;d=a+12|0;for(c=0;!(t=(c<<2)+p[d>>2]|0,j=p[t>>2],-1<(j|0)&&(p[t>>2]=j-i|0),c=c+1|0,1376256==(c|0));){}d=p[f];c=0<(d<<1|0);a:do{if(c){t=a+16|0;j=0;for(o=d;;){if(u=(j<<2)+p[t>>2]|0,q=p[u>>2],-1<(q|0)&&(p[u>>2]=q-i|0,o=p[f]),j=j+1|0,(j|0)>=(o<<1|0)){break a}}}}while(0);td(a)}}while(0)}xd.X=1;function Ad(a,c){var d,e,f,g,h,i=c>>2,j;j=p[a+44>>2];h=(a+28|0)>>2;var o=x[h];g=p[a+36>>2]-o|0;if((j|0)>(g|0)){if(4>(g|0)){var u=0;j=38}else{var q=g;j=3}}else{q=j,j=3}do{if(3==j){u=a+20|0;g=p[u>>2];var t=o+1|0,s=(o|0)<(g|0)?0:t-g|0;g=(a+8|0)>>2;var B=x[g],v=B+o|0,y=w[v],A=w[B+t|0]&255,t=A|(y&255)<<8|1310720,y=p[Kc+((y&255)<<2)>>2]^A^(w[o+(B+2)|0]&255)<<8,A=y&262143|1048576,r=(y^p[Kc+((n[o+(B+3)|0]&255)<<2)>>2]<<5)&1048575,y=0!=(c|0);f=(a+12|0)>>2;if(y){j=p[p[f]+(t<<2)>>2];if((j|0)<(s|0)){p[i+2]=2147483647;var D=1}else{p[i+2]=o-1-j|0,D=2}j=p[p[f]+(A<<2)>>2];if((j|0)<(s|0)){j=10}else{if(n[p[g]+j|0]<<24>>24!=n[v]<<24>>24){j=10}else{p[i+3]=p[h]+(j^-1)|0;var L=3;j=11}}10==j&&(p[i+3]=2147483647,L=D);p[i+4]=2147483647;D=L;v=p[h]}else{D=1,v=o}p[((t<<2)+p[f]|0)>>2]=v;p[((A<<2)+p[f]|0)>>2]=p[h];var t=(r<<2)+p[f]|0,H=p[t>>2];p[t>>2]=p[h];t=a+16|0;e=p[t>>2];var v=a+32|0,P=p[v>>2]<<1,A=p[a+48>>2],J=r=f=0,G=((P|1)<<2)+e|0;e=(P<<2)+e|0;e>>=2;var I=H;a:for(;;){var M=A,H=f,O=D,N=J,P=G;d=P>>2;var Q=I;b:for(;;){var $=(Q|0)<(s|0);do{if(!$){var ha=M-1|0;if(0<=(ha|0)){for(M=p[g];;){var ba=(N|0)<(q|0);if(!ba){break}if(n[M+N+Q|0]<<24>>24!=n[B+N+o|0]<<24>>24){break}N=N+1|0}var $=p[h]-Q|0,R=y&(O|0)<(N|0);c:do{if(R){for(var Sa=$-1|0,fa=O;;){if(fa=fa+1|0,p[(fa<<2>>2)+i]=Sa,(fa|0)==(N|0)){var U=N;break c}}}else{U=O}}while(0);O=x[t>>2];R=p[v>>2];R=R-$+((R|0)<($|0)?p[u>>2]:0)<<1;$=(R<<2)+O|0;if(!ba){p[e]=p[$>>2];p[d]=p[O+((R|1)<<2)>>2];var qa=U;break a}if((w[M+N+Q|0]&255)<(w[B+N+o|0]&255)){p[e]=Q;e=((R|1)<<2)+O|0;d=p[e>>2];if((H|0)>=(N|0)){A=ha;f=H;D=U;J=r=N;G=P;e>>=2;I=d;continue a}A=ha;f=H;D=U;r=N;J=H;G=P;e>>=2;I=d;continue a}p[d]=Q;Q=p[$>>2];if((r|0)>=(N|0)){M=ha;H=N;O=U;P=$;d=P>>2;continue b}M=ha;H=N;O=U;N=r;P=$;d=P>>2;continue b}}}while(0);p[d]=-1;p[e]=-1;qa=O;break a}}y&&(u=c+12|0,g=p[u>>2],s=p[i+4],u=(g|0)>(s|0)?p[u>>2]=s:g,g=c+8|0,(p[g>>2]|0)>(u|0)&&(p[g>>2]=u));u=qa}}while(0);return u}Ad.X=1;function Bd(a,c,d,e){var f=d-2|0,g=a|0;8>(f|0)?(Cd(c,g,0),Dd(c,(e<<5)+a+8|0,f,3)):(Cd(c,g,1),g=a+4|0,16>(f|0)?(Cd(c,g,0),Dd(c,(e<<5)+a+136|0,d-10|0,3)):(Cd(c,g,1),Dd(c,a+264|0,d-18|0,8)));c=(e<<2)+a+5644|0;d=p[c>>2]-1|0;p[c>>2]=d;1>(d|0)&&Ed(a,e)}function Cd(a,c,d){var e;e=(a+24|0)>>2;var f=x[e],c=(c|0)>>2,g=(f>>>11)*p[c]|0;if(0==(d|0)){p[e]=g,f=x[c],f=((2048-f|0)>>>5)+f|0}else{var d=(a|0)>>2,h=p[d],i=p[d+1],j=(h>>>0)+4294967296*(i|0)+(g>>>0)+0>>>0,h=Math.min(Math.floor(((h>>>0)+4294967296*(i|0)+(g>>>0)+0)/4294967296),4294967295);p[d]=j;p[d+1]=h;p[e]=f-g|0;f=x[c];f=f-(f>>>5)|0}p[c]=f;c=x[e];16777216>c>>>0&&(p[e]=c<<8,Fd(a))}function Dd(a,c,d,e){var f=0<(e|0);a:do{if(f){for(var g=1<<e-1,h=1,i=e;;){var j=g&d;Cd(a,(h<<2)+c|0,j);h=0!=(j|0)&1|h<<1;i=i-1|0;if(0>=(i|0)){break a}g>>=1}}}while(0)}function Ed(a,c){var d,e=a>>2,f=a|0,g=Gd(p[f>>2]);d=(a+5640|0)>>2;for(var h=(c<<5)+a+8|0,i=0;8>(i|0);){if((i|0)>=(p[d]|0)){break}p[((i<<2)+1288>>2)+e+(272*c|0)]=Hd(h,i,3)+g|0;i=i+1|0}f=Qd(p[f>>2]);h=(c<<5)+a+136|0;for(g=a+4|0;;){var j=p[d],o=(i|0)<(j|0);if(!(16>(i|0)&o)){break}p[((i<<2)+1288>>2)+e+(272*c|0)]=Gd(p[g>>2])+f+Hd(h,i-8|0,3)|0;i=i+1|0}a:do{if(o){for(var h=a+264|0,u=i;;){var q=Qd(p[g>>2])+f+Hd(h,u-16|0,8)|0;p[((u<<2)+1288>>2)+e]=q;p[((u<<2)+2376>>2)+e]=q;p[((u<<2)+3464>>2)+e]=q;p[((u<<2)+4552>>2)+e]=q;u=u+1|0;q=p[d];if((u|0)>=(q|0)){var t=q;break a}}}else{t=j}}while(0);p[((c<<2)+5644>>2)+e]=t}Ed.X=1;function Rd(a){var c=a>>2,a=a+2068|0;p[c+43305]=Sd(a,0,4);p[c+43306]=Sd(a,1,4);p[c+43307]=Sd(a,2,4);p[c+43308]=Sd(a,3,4);p[c+43309]=Sd(a,4,4);p[c+43310]=Sd(a,5,4);p[c+43311]=Sd(a,6,4);p[c+43312]=Sd(a,7,4);p[c+43313]=Sd(a,8,4);p[c+43314]=Sd(a,9,4);p[c+43315]=Sd(a,10,4);p[c+43316]=Sd(a,11,4);p[c+43317]=Sd(a,12,4);p[c+43318]=Sd(a,13,4);p[c+43319]=Sd(a,14,4);p[c+43320]=Sd(a,15,4);p[c+43321]=16}Rd.X=1;function Sd(a,c,d){var e=0<(d|0);a:do{if(e){for(var f=0,g=1,h=c,i=d;;){var j=h&1,h=h>>1,f=Td((g<<2)+a|0,j)+f|0,i=i-1|0;if(0>=(i|0)){var o=f;break a}g=j|g<<1}}else{o=0}}while(0);return o}function Ud(a){for(var c=a>>2,d=4;;){var e=n[V+d|0]&255,f=(e>>>1)-1|0,g=(e&1|2)<<f,e=Sd((g-e<<2)+a+1608|0,d-g|0,f);p[((d<<2)+171172>>2)+c]=e;p[((d<<2)+171684>>2)+c]=e;p[((d<<2)+172196>>2)+c]=e;p[((d<<2)+172708>>2)+c]=e;d=d+1|0;if(128==(d|0)){break}}d=a+38072|0;for(e=0;;){f=(e<<8)+a+584|0;for(g=0;;){var h=(g|0)<(p[d>>2]|0);if(!(14>(g|0)&h)){break}p[((g<<2)+170244>>2)+c+(58*e|0)]=Hd(f,g,6);g=g+1|0}a:do{if(h){for(var i=g;;){if(p[((i<<2)+170244>>2)+c+(58*e|0)]=Hd(f,i,6)+((i<<5)-320&-64)|0,i=i+1|0,(i|0)>=(p[d>>2]|0)){break a}}}}while(0);p[((e<<9)+171172>>2)+c]=p[c+(58*e|0)+42561];p[((e<<9)+171176>>2)+c]=p[c+(58*e|0)+42562];p[((e<<9)+171180>>2)+c]=p[c+(58*e|0)+42563];p[((e<<9)+171184>>2)+c]=p[c+(58*e|0)+42564];for(f=4;!(g=(e<<9)+(f<<2)+a+171172|0,p[g>>2]=p[g>>2]+p[(((n[V+f|0]&255)<<2)+170244>>2)+c+(58*e|0)]|0,f=f+1|0,128==(f|0));){}e=e+1|0;if(4==(e|0)){break}}}Ud.X=1;function Hd(a,c,d){c|=1<<d;d=1<(c|0);a:do{if(d){for(var e=c,f=0;;){var g=e>>1,f=Td((g<<2)+a|0,e&1)+f|0;if(1>=(g|0)){var h=f;break a}e=g}}else{h=0}}while(0);return h}function Vd(a){var c;c=(a+20|0)>>2;var d=p[c];if(0<(d|0)){var e=p[a+32>>2],f=-1<(e|0);do{if(f){var g=Rc(e,p[a+16>>2],d),h=p[c];if((g|0)==(h|0)){g=h;break}g=nc(4);p[g>>2]=K.W|0;vd(g,wd,0);b("Reached an unreachable!")}g=d}while(0);d=g;e=0>(g|0)?-1:0;a=(a+8|0)>>2;g=p[a];h=p[a+1];f=(g>>>0)+4294967296*(h|0)+(d>>>0)+4294967296*(e|0)>>>0;d=Math.min(Math.floor(((g>>>0)+4294967296*(h|0)+(d>>>0)+4294967296*(e|0))/4294967296),4294967295);p[a]=f;p[a+1]=d;p[c]=0}}function Wd(a,c,d){var e=0>(d|0)?-1:0,f=(d>>>0)+4294967296*(e|0)+(a>>>0)+4294967296*(c|0)>>>0,a=Math.min(Math.floor(((d>>>0)+4294967296*(e|0)+(a>>>0)+4294967296*(c|0))/4294967296),4294967295);return[f,a]}function Xd(a,c,d,e){var f=a+12|0;(p[f>>2]|0)>(e|0)&&(p[a+4>>2]=c,p[a+8>>2]=d,p[f>>2]=e)}function Yd(a,c,d){return p[((c-2<<2)+a+1288>>2)+(272*d|0)]}function Zd(a,c){var d=(c<<5)+a+39176|0,e=0<(c|0);a:do{if(e){for(var f=c;;){var g=p[a+(f<<5)+39180>>2];p[((g<<5)+a+39184|0)>>2]=f-g|0;var f=p[d>>2],h=(g<<5)+a+39176|0;p[d>>2]=p[h>>2];p[h>>2]=f;if(0>=(g|0)){break a}f=g}}}while(0)}function $d(a,c){var d=c>>2,e=3<(a|0);do{if(e){var f=c+8|0;p[d+3]=p[f>>2];var g=c+4|0;p[f>>2]=p[g>>2];p[g>>2]=p[d];p[d]=a-4|0}else{if(0<(a|0)){f=p[(a<<2>>2)+d];for(g=a;;){var h=g-1|0;p[(g<<2>>2)+d]=p[(h<<2>>2)+d];if(0>=(h|0)){break}g=h}p[d]=f}}}while(0)}function ae(a,c,d){var e,f,g,h,i,j=a>>2,o=m;m+=16;i=o>>2;h=(a|0)>>2;var u=p[h];if(0<(u|0)){p[h]=0;var q=u}else{q=be(a)}g=(a+2132|0)>>2;var t=x[g];f=t>>2;var s=x[c>>2],B=x[f+2],v=x[f+7],y=x[f+9],A=ce(B,v,y,0,s+1|0,273);p[i]=A;var r=c+4|0,D=ce(B,v,y,0,p[r>>2]+1|0,273);p[i+1]=D;var L=(D|0)>(A|0)&1,H=c+8|0,P=ce(B,v,y,0,p[H>>2]+1|0,273);p[i+2]=P;var J=(P|0)>(p[(L<<2>>2)+i]|0)?2:L,G=c+12|0,I=ce(B,v,y,0,p[G>>2]+1|0,273);p[i+3]=I;var M=(I|0)>(p[(J<<2>>2)+i]|0)?3:J,O=x[(M<<2>>2)+i],N=p[f+11],Q=(O|0)<(N|0);a:do{if(Q){if((q|0)<(N|0)){var $=t|0,ha=Wd(p[$>>2],p[$+4>>2],v)[0],ba=n[B+v+ -1|0],R=n[B+v+0|0],Sa=n[B+v+(s^-1)|0],fa=d|0;n[a+39172|0]=n[fa];p[j+9797]=p[c>>2];p[j+9798]=p[r>>2];p[j+9799]=p[H>>2];p[j+9800]=p[G>>2];var U=ha&3,qa=a+39204|0,Aa=a+39208|0;p[Aa>>2]=-1;p[j+9803]=0;var da=Gd(p[(((n[fa]&255)<<4)+(U<<2)+8>>2)+j]),Ea=a+39216|0;p[Ea>>2]=da;var ra=a+13496|0;p[Ea>>2]=(7>(n[fa]&255)?Hd(ra+3072*((ba&255)>>>5)|0,R&255,8):de(ra+3072*((ba&255)>>>5)|0,R&255,Sa&255))+da|0;var pb=w[fa],bb=pb&255,Eb=Qd(p[((bb<<4)+(U<<2)+8>>2)+j]),sa=Qd(p[((bb<<2)+200>>2)+j])+Eb|0;Sa<<24>>24==R<<24>>24&&Xd(qa,0,0,ee(a,pb,U)+sa|0);if(2>(q|0)){p[j+9794]=p[Aa>>2];p[j+9796]=1;xd(p[g]);var Fa=1}else{var Zb=(q|0)>(O|0);b:do{if(Zb){for(var ga=Gd(p[(((n[fa]&255)<<2)+200>>2)+j])+Eb|0,ta=q+1|0,ia=2;;){var La=(ia<<2)+a+38076|0;p[((ia<<5)+39176>>2)+j]=p[La>>2]+4|0;p[((ia<<5)+39180>>2)+j]=0;p[((ia<<5)+39184>>2)+j]=ga+(3>(ia|0)&127<(p[La>>2]|0)?268435455:fe(a,p[La>>2],ld(ia))+Yd(a+2176|0,ia,U)|0)|0;var cb=ia+1|0;if((cb|0)==(ta|0)){var db=q;break b}ia=cb}}else{if(2>(O|0)){db=O}else{for(var Fb=O+1|0,ja=2;;){p[((ja<<5)+39184>>2)+j]=268435455;var rb=ja+1|0;if((rb|0)==(Fb|0)){db=O;break b}ja=rb}}}}while(0);var Ga=a+7836|0,sb=2>(A|0);b:do{if(!sb){for(var tb=ge(a,0,n[fa],U)+sa|0,Ta=2;;){Xd((Ta<<5)+a+39172|0,0,0,tb+Yd(Ga,Ta,U)|0);var Ma=Ta+1|0;if((Ma|0)>(A|0)){break b}Ta=Ma}}}while(0);var Ua=2>(D|0);b:do{if(!Ua){for(var ub=ge(a,1,n[fa],U)+sa|0,eb=2;;){Xd((eb<<5)+a+39172|0,1,0,ub+Yd(Ga,eb,U)|0);var vb=eb+1|0;if((vb|0)>(D|0)){break b}eb=vb}}}while(0);var Na=2>(P|0);b:do{if(!Na){for(var Va=ge(a,2,n[fa],U)+sa|0,Nb=2;;){Xd((Nb<<5)+a+39172|0,2,0,Va+Yd(Ga,Nb,U)|0);var Gb=Nb+1|0;if((Gb|0)>(P|0)){break b}Nb=Gb}}}while(0);var Hb=2>(I|0);b:do{if(!Hb){for(var Ib=ge(a,3,n[fa],U)+sa|0,Wa=2;;){Xd((Wa<<5)+a+39172|0,3,0,Ib+Yd(Ga,Wa,U)|0);var Y=Wa+1|0;if((Y|0)>(I|0)){break b}Wa=Y}}}while(0);xd(p[g]);var na=a+38084|0,ka=a+2176|0,ua=db,va=0;b:for(;;){for(var fb=va+1|0,Oa=va,gb=fb,Ob=0;;){var S=Oa+1|0;if((S|0)>=(ua|0)){Zd(a,S);Fa=S;break a}var oa=be(a);if((oa|0)>=(p[p[g]+44>>2]|0)){p[h]=oa;Zd(a,S);Fa=S;break a}var Xa=(S<<5)+a+39172|0,la=p[((S<<5)+39180>>2)+j],wa=Xa|0;n[wa]=n[(la<<5)+a+39172|0];var ma=(S<<5)+a+39188|0;p[ma>>2]=p[((la<<5)+39188>>2)+j];p[((S<<5)+39192>>2)+j]=p[((la<<5)+39192>>2)+j];p[((S<<5)+39196>>2)+j]=p[((la<<5)+39196>>2)+j];p[((S<<5)+39200>>2)+j]=p[((la<<5)+39200>>2)+j];var Ya=Xa|0,Jb=(S<<5)+a+39176|0,wb=p[Jb>>2];(la|0)==(Oa|0)?0==(wb|0)?id(Ya):hd(Ya):(4>(wb|0)?jd(Ya):od(Ya),$d(p[Jb>>2],ma));var Za=x[g],Ha=Za|0,Ia=p[Za+28>>2],Pa=Wd(p[Ha>>2],p[Ha+4>>2],Ia)[0]&3,hb=p[Za+8>>2],ib=n[hb+Ia+ -1|0],Qa=n[hb+Ia+0|0],xa=n[hb+Ia+(p[ma>>2]^-1)|0],Ja=(S<<5)+a+39184|0,jb=w[wa],Ba=Gd(p[(((jb&255)<<4)+(Pa<<2)+8>>2)+j])+p[Ja>>2]+(7>(jb&255)?Hd(ra+3072*((ib&255)>>>5)|0,Qa&255,8):de(ra+3072*((ib&255)>>>5)|0,Qa&255,xa&255))|0;xd(Za);var $a=Oa+2|0,xb=($a<<5)+a+39172|0;Xd(xb,-1,S,Ba);var kb=w[wa],yb=kb&255,Kb=Qd(p[((yb<<4)+(Pa<<2)+8>>2)+j])+p[Ja>>2]|0,Lb=Kb+Qd(p[((yb<<2)+200>>2)+j])|0;xa<<24>>24==Qa<<24>>24&&0!=(p[(($a<<5)+39176>>2)+j]|0)&&Xd(xb,0,S,ee(a,kb,Pa)+Lb|0);var Pb=4094-Oa|0,Qb=p[g];e=Qb>>2;var Ka=p[e+7],gc=p[e+9]-Ka|0,Tb=(Pb|0)<(gc|0)?Pb:gc,lb=p[e+11],hc=(Tb|0)<(lb|0)?Tb:lb;if(2<=(hc|0)){var mb=ua,Mb=0,lc=Qb,$b=Ka;break}Oa=S;gb=gb+1|0;Ob=Ob+1|0}for(;;){for(var mc=p[lc+8>>2]+$b|0,cd=-2-p[((S<<5)+(Mb<<2)+39188>>2)+j]|0,Ab=0;(Ab|0)<(hc|0);){if(n[mc+(Ab-1)|0]<<24>>24!=n[mc+cd+Ab|0]<<24>>24){break}Ab=Ab+1|0}var fg=1<(Ab|0);c:do{if(fg){var gg=ge(a,Mb,n[wa],Pa),hg=(mb|0)<(Ab+S|0);d:do{if(hg){for(var Ze=Ob+fb+Ab|0,$e=mb;;){var Id=$e+1|0;p[((Id<<5)+39184>>2)+j]=268435455;if((Id|0)==(Ze|0)){var af=Ze;break d}$e=Id}}else{af=mb}}while(0);for(var ig=gg+Lb|0,dd=Ab;;){Xd((dd+S<<5)+a+39172|0,Mb,S,ig+Yd(Ga,dd,Pa)|0);var bf=dd-1|0;if(1>=(bf|0)){var ic=af;break c}dd=bf}}else{ic=mb}}while(0);var cf=Mb+1|0;if(4==(cf|0)){break}var df=x[g],mb=ic,Mb=cf,lc=df,$b=p[df+28>>2]}if((oa|0)>(hc|0)){ua=ic,va=S}else{if(2>=(oa|0)){if(2!=(oa|0)){ua=ic;va=S;continue}if(128<=(p[na>>2]|0)){ua=ic;va=S;continue}}var ef=Gd(p[(((n[wa]&255)<<2)+200>>2)+j])+Kb|0,jg=(ic|0)<(oa+S|0);c:do{if(jg){for(var ff=oa+gb|0,gf=ic;;){var Jd=gf+1|0;p[((Jd<<5)+39184>>2)+j]=268435455;if((Jd|0)==(ff|0)){var Kd=ff;break c}gf=Jd}}else{Kd=ic}}while(0);var ed=x[na>>2],hf=ld(2);128>(ed|0)&&Xd((Oa+3<<5)+a+39172|0,ed+4|0,S,p[((hf<<9)+(ed<<2)+171172>>2)+j]+ef+Yd(ka,2,Pa)|0);if(3>(oa|0)){ua=Kd,va=S}else{for(var kg=oa+1|0,Ld=ed,Md=hf,jf=268435455,zc=3;;){var Nd=p[((zc<<2)+38076>>2)+j];if((Ld|0)!=(Nd|0)|3>(Md|0)){var kf=ld(zc),Od=fe(a,Nd,kf),lf=kf,Pd=Nd}else{Od=jf,lf=Md,Pd=Ld}Xd((zc+S<<5)+a+39172|0,Pd+4|0,S,Od+ef+Yd(ka,zc,Pa)|0);var mf=zc+1|0;if((mf|0)==(kg|0)){ua=Kd;va=S;continue b}Ld=Pd;Md=lf;jf=Od;zc=mf}}}}}}else{p[j+9794]=p[((N<<2)+38076>>2)+j]+4|0,p[j+9796]=q,he(a,q,1),Fa=q}}else{p[j+9794]=M,p[j+9796]=O,he(a,O,1),Fa=O}}while(0);m=o;return Fa}ae.X=1;function be(a){var c;c=a+2132|0;var d=Ad(p[c>>2],a+38076|0);c=p[c>>2]>>2;return(d|0)==(p[c+11]|0)?ce(p[c+2],p[c+7],p[c+9],d,p[a+(d<<2)+38076>>2]+1|0,273-d|0)+d|0:d}function ce(a,c,d,e,f,g){d=d-c|0;g=(g+e|0)>(d|0)?d-e|0:g;c=c+e|0;f=c-f|0;for(e=0;(e|0)<(g|0);){if(n[a+f+e|0]<<24>>24!=n[a+e+c|0]<<24>>24){break}e=e+1|0}return e}function he(a,c,d){var e=0<(c|0);a:do{if(e){for(var f=a+2132|0,g=d&1,h=c;;){if(h=h-1|0,0==(g&1)<<24>>24?Ad(p[f>>2],0):g=0,xd(p[f>>2]),0>=(h|0)){break a}}}}while(0)}function Qd(a){return Gd(2048-a|0)}function ee(a,c,d){c&=255;return Gd(p[a+(c<<4)+(d<<2)+392>>2])+Gd(p[a+(c<<2)+248>>2])|0}function ge(a,c,d,e){var d=d&255,f=x[a+(d<<2)+248>>2];0==(c|0)?a=Qd(p[a+(d<<4)+(e<<2)+392>>2])+Gd(f)|0:(e=Qd(f),f=p[a+(d<<2)+296>>2],a=1==(c|0)?Gd(f)+e|0:Qd(f)+e+Td((d<<2)+a+344|0,c-2|0)|0);return a}function ie(a,c,d,e){var f=0>(d|0)?-1:0,g=0>(e|0)?-1:0,h=(d>>>0)+4294967296*(f|0)+(a>>>0)+4294967296*(c|0)>>>0,c=Math.min(Math.floor(((d>>>0)+4294967296*(f|0)+(a>>>0)+4294967296*(c|0))/4294967296),4294967295),a=(h>>>0)+4294967296*(c|0)+(e>>>0)+4294967296*(g|0)>>>0,e=Math.min(Math.floor(((h>>>0)+4294967296*(c|0)+(e>>>0)+4294967296*(g|0))/4294967296),4294967295);return[a,e]}function je(a){for(var c=1,d=0,e=1;;){var f=0==(e&a|0)?d:c,c=c+1|0;if(32==(c|0)){break}d=f;e<<=1}return f}function ke(a){return 0==(n[a+56|0]&1)<<24>>24?0:(p[a+28>>2]|0)>=(p[a+36>>2]|0)}function le(a,c){var d=x[a>>2];p[a>>2]=p[Kc+((d&255^c&255)<<2)>>2]^d>>>8}function fe(a,c,d){return 128>(c|0)?p[a+(d<<9)+(c<<2)+171172>>2]:p[a+((c&15)<<2)+173220>>2]+p[((me(c)<<2)+a+170244>>2)+(58*d|0)]|0}function ne(a,c){var d=m;m+=20;var e=a+2132|0,f=p[e>>2],g=f|0,g=Wd(p[g>>2],p[g+4>>2],p[f+28>>2])[0]&3,f=a+2136|0,h=c|0;Cd(f,((n[h]&255)<<4)+(g<<2)+a+8|0,1);Cd(f,((n[h]&255)<<2)+a+200|0,0);oe(a,-1,2,g);Fd(f);Fd(f);Fd(f);Fd(f);Fd(f);g=p[a+4>>2]^-1;n[d|0]=g&255;n[d+1|0]=g>>>8&255;n[d+2|0]=g>>>16&255;n[d+3|0]=g>>>24&255;e=p[e>>2];g=e|0;g=Wd(p[g>>2],p[g+4>>2],p[e+28>>2]);e=g[0];g=g[1];n[d+4|0]=e&255;n[d+5|0]=(e>>>8|g<<24)&255;n[d+6|0]=(e>>>16|g<<16)&255;n[d+7|0]=(e>>>24|g<<8)&255;n[d+8|0]=g&255;n[d+9|0]=(g>>>8|0)&255;n[d+10|0]=(g>>>16|0)&255;n[d+11|0]=(g>>>24|0)&255;e=a+2144|0;g=ie(p[e>>2],p[e+4>>2],p[a+2156>>2],p[a+2164>>2]);e=g[0];h=g[1];g=20+(e>>>0)+4294967296*(h|0)>>>0;e=Math.min(Math.floor((20+(e>>>0)+4294967296*(h|0))/4294967296),4294967295);Lc(d,g,e);a:do{for(e=0;;){if(pe(f,n[d+e|0]),e=e+1|0,20==(e|0)){break a}}}while(0);Vd(f);m=d}ne.X=1;function pe(a,c){var d;d=(a+20|0)>>2;n[p[a+16>>2]+p[d]|0]=c;var e=p[d]+1|0;p[d]=e;65535<(e|0)&&Vd(a)}function qe(a,c,d,e){var f;p[a>>2]=0;p[a+4>>2]=-1;f=a+200|0;for(var g=a+8|0;!(T(g),g=g+4|0,(g|0)==(f|0));){}T(a+200|0);T(a+204|0);T(a+208|0);T(a+212|0);T(a+216|0);T(a+220|0);T(a+224|0);T(a+228|0);T(a+232|0);T(a+236|0);T(a+240|0);T(a+244|0);T(a+248|0);T(a+252|0);T(a+256|0);T(a+260|0);T(a+264|0);T(a+268|0);T(a+272|0);T(a+276|0);T(a+280|0);T(a+284|0);T(a+288|0);T(a+292|0);T(a+296|0);T(a+300|0);T(a+304|0);T(a+308|0);T(a+312|0);T(a+316|0);T(a+320|0);T(a+324|0);T(a+328|0);T(a+332|0);T(a+336|0);T(a+340|0);T(a+344|0);T(a+348|0);T(a+352|0);T(a+356|0);T(a+360|0);T(a+364|0);T(a+368|0);T(a+372|0);T(a+376|0);T(a+380|0);T(a+384|0);T(a+388|0);f=a+584|0;for(g=a+392|0;!(T(g),g=g+4|0,(g|0)==(f|0));){}f=a+1608|0;for(g=a+584|0;!(T(g),g=g+4|0,(g|0)==(f|0));){}f=a+2068|0;for(g=a+1608|0;!(T(g),g=g+4|0,(g|0)==(f|0));){}T(a+2068|0);T(a+2072|0);T(a+2076|0);T(a+2080|0);T(a+2084|0);T(a+2088|0);T(a+2092|0);T(a+2096|0);T(a+2100|0);T(a+2104|0);T(a+2108|0);T(a+2112|0);T(a+2116|0);T(a+2120|0);T(a+2124|0);T(a+2128|0);f=(a+2132|0)>>2;p[f]=c;c=a+2136|0;g=c|0;p[g>>2]=0;p[g+4>>2]=0;g=c+8|0;p[g>>2]=0;p[g+4>>2]=0;var g=c+16|0,h=sd(65536);p[g>>2]=h;p[c+20>>2]=0;p[c+24>>2]=-1;p[c+28>>2]=0;p[c+32>>2]=e;n[c+36|0]=0;re(a+2176|0,p[p[f]+44>>2]);re(a+7836|0,p[p[f]+44>>2]);g=a+13496|0;e=g+24576|0;for(g|=0;!(T(g),g=g+4|0,(g|0)==(e|0));){}p[(a+38072|0)>>2]=je(p[p[f]+20>>2]-1|0)<<1;e=a+170244|0;for(f=a+39172|0;!(n[f|0]=0,f=f+32|0,(f|0)==(e|0));){}Rd(a);for(a=0;6>(a|0);){pe(c,n[d+a|0]);a=a+1|0}}qe.X=1;function se(a,c,d){var e,f,g,h=m;m+=16;g=h>>2;var i=m;m+=1;m=m+3>>2<<2;var j=(c>>>0)+4294967296*(d|0)+ -16>>>0,o=Math.min(Math.floor(((c>>>0)+4294967296*(d|0)+ -16)/4294967296),4294967295),c=(a+2132|0)>>2,d=12<(p[p[c]+44>>2]|0);n[i|0]=0;p[g]=0;p[g+1]=0;p[g+2]=0;p[g+3]=0;g=(j>>>0)+4294967296*(o|0)-20>>>0;j=Math.min(Math.floor(((j>>>0)+4294967296*(o|0)-20)/4294967296),4294967295);d=d?512:2048;o=p[c];f=o|0;var u=p[o+28>>2];f=Wd(p[f>>2],p[f+4>>2],u);var q=0==f[0]&&0==f[1];a:do{if(q){var t=a+2136|0;f=(a+2144|0)>>2;var s=a+2156|0,B=a+2164|0,v=ie(p[f],p[f+1],p[s>>2],p[B>>2]);if(6==v[0]&&0==v[1]){if(ke(o)){var v=a+4|0,y=a+13496|0,A=i|0}else{v=n[p[o+8>>2]+u+0|0];A=i|0;Cd(t,((n[A]&255)<<4)+a+8|0,0);y=a+13496|0;Dd(t,y+0|0,v&255,8);var r=a+4|0;le(r,v);he(a,1,0);v=r}var r=h|0,D=a+7836|0,L=0;b:for(;;){if(ke(p[c])){ne(a,i);R=1;break a}1>(L|0)&&(Ud(a),L=d);var H=ae(a,r,i);if(1>(H|0)){R=0;break a}for(var L=L-H|0,P=0;;){var J=p[c],G=J|0,G=Wd(p[G>>2],p[G+4>>2],p[J+28>>2]),J=G[0],G=G[1],I=H,M=(J>>>0)+4294967296*(G|0)-((I>>>0)+0)>>>0;Math.min(Math.floor(((J>>>0)+4294967296*(G|0)-((I>>>0)+0))/4294967296),4294967295);var I=M&3,M=x[a+(P<<5)+39176>>2],J=x[a+(P<<5)+39184>>2],O=1==(J|0),N=0>(M|0)&O,G=w[A],Q=G&255;Cd(t,(Q<<4)+(I<<2)+a+8|0,N&1^1);e=x[c]>>2;if(N){O=H^-1;M=p[e+2];Q=p[e+7];I=n[M+Q+O|0];M=n[M+Q+(-H|0)|0];le(v,M);if(7>(G&255)){Dd(t,y+3072*((I&255)>>>5)|0,M&255,8)}else{Q=p[c];G=t;I=y+3072*((I&255)>>>5)|0;M&=255;e=n[p[Q+8>>2]+p[Q+28>>2]+(O-p[r>>2]|0)|0]&255;O=aa;Q=7;for(N=1;;){if(-1>=(Q|0)){O=7;break}var $=e>>>(Q>>>0)&1,ha=M>>>(Q>>>0)&1;Cd(G,(($<<8)+N+256<<2)+I|0,ha);var ba=ha|N<<1;if(($|0)!=(ha|0)){O=4;break}Q=Q-1|0;N=ba}c:do{if(4==O&&0<(Q|0)){e=ba;for(N=Q;;){N=N-1|0;$=M>>>(N>>>0)&1;Cd(G,(e<<2)+I|0,$);if(0>=(N|0)){break c}e=$|e<<1}}}while(0)}hd(i)}else{Jc(v,(p[e+2]+p[e+7]|0)+ -H|0,J),$d(M,r),G=4>(M|0),Cd(t,(Q<<2)+a+200|0,G&1),G?(G=0==(M|0),Cd(t,(Q<<2)+a+248|0,G&1^1),G?Cd(t,(Q<<4)+(I<<2)+a+392|0,1<(J|0)&1):(G=1<(M|0),Cd(t,(Q<<2)+a+296|0,G&1),G&&Cd(t,(Q<<2)+a+344|0,2<(M|0)&1)),O?id(i):(Bd(D,t,J,I),jd(i))):(oe(a,M-4|0,J,I),od(i))}G=H-J|0;H=ie(p[f],p[f+1],p[s>>2],p[B>>2]);I=H[1];if(!((I|0)<(j|0)||(I|0)==(j|0)&&H[0]>>>0<g>>>0)){break}if(1>(G|0)){continue b}P=J+P|0;H=G}ba=p[c];R=G;c=aa;0>(R|0)?ba=0:(c=ba+28|0,g=p[c>>2],(g|0)<(R|0)?ba=0:(p[c>>2]=g-R|0,c=(ba+32|0)>>2,R=p[c]-R|0,p[c]=R,0>(R|0)&&(p[c]=p[ba+20>>2]+R|0),ba=1));if(!ba){R=0;break a}ne(a,i);R=1;break a}}else{var R=0}}else{R=0}}while(0);m=h;return R}se.X=1;function oe(a,c,d,e){var f=a+2136|0;Bd(a+2176|0,f,d,e);e=me(c);Dd(f,(ld(d)<<8)+a+584|0,e,6);if(3<(e|0)){var d=e>>1,g=d-1|0,h=(e&1|2)<<g,c=c-h|0;if(14>(e|0)){te(f,(h-e<<2)+a+1608|0,c,g)}else{var e=c>>>4,d=d-5|0,i=0<(d|0);a:do{if(i){for(var h=(f+24|0)>>2,g=(f|0)>>2,j=d;;){var j=j-1|0,o=x[h],u=o>>>1;p[h]=u;if(0!=(1<<j&e|0)){var q=u,t=p[g],s=p[g+1],u=(t>>>0)+4294967296*(s|0)+(q>>>0)+0>>>0,q=Math.min(Math.floor(((t>>>0)+4294967296*(s|0)+(q>>>0)+0)/4294967296),4294967295);p[g]=u;p[g+1]=q}33554432>o>>>0&&(p[h]=o<<7&-256,Fd(f));if(0>=(j|0)){break a}}}}while(0);te(f,a+2068|0,c,4);f=a+173284|0;c=p[f>>2]-1|0;p[f>>2]=c;1>(c|0)&&Rd(a)}}}function me(a){return 4096>a>>>0?w[V+a|0]&255:8388608>a>>>0?(w[V+(a>>>11)|0]&255)+22|0:(w[V+(a>>>22)|0]&255)+44|0}function Gd(a){return p[ue+(a>>2<<2)>>2]}function re(a,c){T(a|0);T(a+4|0);T(a+8|0);T(a+12|0);T(a+16|0);T(a+20|0);T(a+24|0);T(a+28|0);T(a+32|0);T(a+36|0);T(a+40|0);T(a+44|0);T(a+48|0);T(a+52|0);T(a+56|0);T(a+60|0);T(a+64|0);T(a+68|0);T(a+72|0);T(a+76|0);T(a+80|0);T(a+84|0);T(a+88|0);T(a+92|0);T(a+96|0);T(a+100|0);T(a+104|0);T(a+108|0);T(a+112|0);T(a+116|0);T(a+120|0);T(a+124|0);T(a+128|0);T(a+132|0);T(a+136|0);T(a+140|0);T(a+144|0);T(a+148|0);T(a+152|0);T(a+156|0);T(a+160|0);T(a+164|0);T(a+168|0);T(a+172|0);T(a+176|0);T(a+180|0);T(a+184|0);T(a+188|0);T(a+192|0);T(a+196|0);T(a+200|0);T(a+204|0);T(a+208|0);T(a+212|0);T(a+216|0);T(a+220|0);T(a+224|0);T(a+228|0);T(a+232|0);T(a+236|0);T(a+240|0);T(a+244|0);T(a+248|0);T(a+252|0);T(a+256|0);T(a+260|0);for(var d=a+1288|0,e=a+264|0;!(T(e),e=e+4|0,(e|0)==(d|0));){}p[a+5640>>2]=c-1|0;Ed(a,0);Ed(a,1);Ed(a,2);Ed(a,3)}re.X=1;function Fd(a){var c,d;d=(a|0)>>2;var e=p[d],f=x[d+1];if((0>f>>>0||0==f>>>0&&4278190080>e>>>0)|1==(f|0)){e=a+36|0;pe(a,(w[e]&255)+f&255);c=(a+28|0)>>2;var g=0<(p[c]|0);a:do{if(g){for(var h=f+255&255;;){pe(a,h);var i=p[c]-1|0;p[c]=i;if(0>=(i|0)){break a}}}}while(0);f=x[d];a=x[d+1];n[e]=(f>>>24|a<<8)&255}else{a=a+28|0,p[a>>2]=p[a>>2]+1|0,a=f,f=e}p[d]=(f<<8|0)&-256;p[d+1]=(a<<8|f>>>24)&0}Fd.X=1;function te(a,c,d,e){var f=0<(e|0);a:do{if(f){for(var g=d,h=1,i=e;;){var j=g&1;Cd(a,(h<<2)+c|0,j);h=h<<1|j;i=i-1|0;if(0>=(i|0)){break a}g>>=1}}}while(0)}function Td(a,c){var d=p[a>>2];return 0==(c|0)?Gd(d):Qd(d)}function de(a,c,d){for(var e,f=7,g=1,h=0;;){if(-1>=(f|0)){var i=h;e=7;break}var j=d>>>(f>>>0)&1,o=c>>>(f>>>0)&1,u=Td(((j<<8)+g+256<<2)+a|0,o)+h|0,q=o|g<<1;if((j|0)!=(o|0)){e=4;break}f=f-1|0;g=q;h=u}a:do{if(4==e){if(0<(f|0)){g=u;d=q;for(h=f;;){h=h-1|0;j=c>>>(h>>>0)&1;g=Td((d<<2)+a|0,j)+g|0;if(0>=(h|0)){i=g;break a}d=j|d<<1}}else{i=u}}}while(0);return i}function Yc(a){0!=(a|0)&&Sc(p[p[ve>>2]+12>>2],a,Dc(a))}function we(a,c,d){if(-1<(p[xe>>2]|0)){if(0!=(a|0)&&0!=n[a]<<24>>24){ye(p[p[ve>>2]+12>>2],K.sa|0,(z=m,m+=8,p[z>>2]=K.i|0,p[z+4>>2]=a,z));if(0<(c|0)){var a=p[p[ve>>2]+12>>2],e;ze||(ze=nc(256));e=ze;if(c in Ae){if(255<Ae[c].length){W(Be)}else{for(var c=Ae[c],f=0;f<c.length;f++){n[e+f]=c.charCodeAt(f)}n[e+f]=0}}else{W(Ce)}e=ze;ye(a,K.S|0,(z=m,m+=4,p[z>>2]=e,z))}De(p[p[ve>>2]+12>>2])}a=p[Ee>>2];0!=(a|0)&d&&0!=n[a]<<24>>24&&ye(p[p[ve>>2]+12>>2],K.na|0,(z=m,m+=4,p[z>>2]=a,z))}}function yd(a){-1<(p[xe>>2]|0)&&ye(p[p[ve>>2]+12>>2],K.oa|0,(z=m,m+=8,p[z>>2]=K.i|0,p[z+4>>2]=a,z));Uc(3)}function Fe(a,c){var d=m;m+=8;p[d>>2]=8388608;p[d+4>>2]=36;p[Ee>>2]=p[c>>2];var e=1,f=0;a:for(;;){if((e|0)>=(a|0)){if(e=2==(f|0)){n[Ge]=0}else{if(0==(f|0)){n[V|0]=0;n[V+1|0]=1;n[V+2|0]=2;n[V+3|0]=3;C=1028;n[V+4|0]=C&255;C>>=8;n[(V+4|0)+1]=C&255;C=1285;n[V+6|0]=C&255;C>>=8;n[(V+6|0)+1]=C&255;C=101058054;n[V+8|0]=C&255;C>>=8;n[(V+8|0)+1]=C&255;C>>=8;n[(V+8|0)+2]=C&255;C>>=8;n[(V+8|0)+3]=C&255;C=117901063;n[V+12|0]=C&255;C>>=8;n[(V+12|0)+1]=C&255;C>>=8;n[(V+12|0)+2]=C&255;C>>=8;n[(V+12|0)+3]=C&255;var g=V+16|0,h=g|0;C=134744072;n[h]=C&255;C>>=8;n[h+1]=C&255;C>>=8;n[h+2]=C&255;C>>=8;n[h+3]=C&255;g=g+4|0;C=134744072;n[g]=C&255;C>>=8;n[g+1]=C&255;C>>=8;n[g+2]=C&255;C>>=8;n[g+3]=C&255;g=V+24|0;h=g|0;C=151587081;n[h]=C&255;C>>=8;n[h+1]=C&255;C>>=8;n[h+2]=C&255;C>>=8;n[h+3]=C&255;g=g+4|0;C=151587081;n[g]=C&255;C>>=8;n[g+1]=C&255;C>>=8;n[g+2]=C&255;C>>=8;n[g+3]=C&255;g=V+32|0;for(h=g+16;g<h;g++){n[g]=10}g=V+48|0;for(h=g+16;g<h;g++){n[g]=11}oc(V+64|0,12,32);oc(V+96|0,13,32);oc(V+128|0,14,64);oc(V+192|0,15,64);oc(V+256|0,16,128);oc(V+384|0,17,128);oc(V+512|0,18,256);oc(V+768|0,19,256);oc(V+1024|0,20,512);oc(V+1536|0,21,512);oc(V+2048|0,22,1024);oc(V+3072|0,23,1024);p[ue>>2]=704;for(var g=1,h=2,i=8;;){var j=(g|0)<(h|0);b:do{if(j){for(var o=i<<6,u=8-i|0,q=g;;){if(p[ue+(q<<2)>>2]=(h-q<<6>>u)+o|0,q=q+1|0,(q|0)==(h|0)){var t=h;break b}}}else{t=g}}while(0);if(0>=(i|0)){break}g=t;h<<=1;i=i-1|0}}}n[Ge]=1;t=f;g=aa;if(0==(t|0)&w[Ge]){if(0==(He(2)|0)){g=4}else{we(K.ha|0,0,1);var s=0,g=7}}else{g=4}4==g&&(2>(t-1|0)>>>0?0==(He(1)|0)?s=1:(we(K.ia|0,0,1),s=0):s=1);if(!s){g=1;break}f=0==(f|0)?Ie(d):Je(e);f=0<(f|0)?f:0;if(!w[Ge]){g=f;break}Ke[2]?(Ke[2].bb&&Le(Ke[2].bb),delete Ke[2],s=0):(W(Me),s=-1);if(0==(s|0)){g=f;break}we(K.ua|0,p[Pc>>2],0);if(1<=(f|0)){g=f;break}g=1;break}h=n[p[c+(e<<2)>>2]+1|0]<<24>>24;do{if(99==(h|0)||107==(h|0)){i=f}else{if(100==(h|0)){i=1}else{if(104==(h|0)){f=m;Ne(K.qa|0,(z=m,m+=4,p[z>>2]=K.p|0,z));Oe(K.ya|0);s=p[Ee>>2];Ne(K.ra|0,(z=m,m+=4,p[z>>2]=s,z));Oe(K.za|0);Oe(K.Ka|0);Oe(K.Ta|0);Oe(K.Ua|0);Oe(K.Va|0);Oe(K.Wa|0);Oe(K.Xa|0);Oe(K.Ya|0);Oe(K.Za|0);Oe(K.Aa|0);Oe(K.Ba|0);Oe(K.Ca|0);Oe(K.Da|0);Oe(K.Ea|0);Oe(K.Fa|0);Oe(K.Ga|0);Oe(K.Ha|0);Oe(K.Ia|0);Oe(K.Ja|0);Ne(K.va|0,(z=m,m+=4,p[z>>2]=K.i|0,z));Oe(K.La|0);Oe(K.Ma|0);Oe(K.Na|0);Oe(K.Oa|0);Oe(K.Pa|0);m=f;g=0;break a}else{if(113==(h|0)){p[xe>>2]=-1,i=f}else{if(118==(h|0)){i=p[xe>>2],4>(i|0)&&(p[xe>>2]=i+1|0),i=f}else{if(86==(h|0)){f=m;Ne(K.ja|0,(z=m,m+=8,p[z>>2]=K.p|0,p[z+4>>2]=K.ka|0,z));Ne(K.la|0,(z=m,m+=4,p[z>>2]=K.pa|0,z));Oe(K.Qa|0);Oe(K.Ra|0);Oe(K.Sa|0);m=f;g=0;break a}else{yd(K.ta|0),i=f}}}}}}}while(0);e=e+1|0;f=i}m=d;return g}Module._main=Fe;Fe.X=1;function Ie(a){var c=m;m+=173356;var d,e=c+8,f=c+68;C=1346984524;n[c]=C&255;C>>=8;n[c+1]=C&255;C>>=8;n[c+2]=C&255;C>>=8;n[c+3]=C&255;n[c+4|0]=1;d=Pe(c,p[a>>2]);a=a+4|0;if(d){if(d=x[a>>2],268<(d-5|0)>>>0){d=3}else{var g=d;d=4}}else{d=3}3==d&&(yd(K.ca|0),g=p[a>>2]);rd(e,Qe(n[c+5|0]),g,1);Pe(c,p[e+20>>2]);for(var g=e|0,a=e+28|0,h=0,i=0,j=0,o=0,u=0,q=0;;){qe(f,e,c,w[Ge]?2:-1);d=4294967295+2147483647*4294967296-((i>>>0)+4294967296*(h|0))>>>0;var t=Math.min(Math.floor((4294967295+2147483647*4294967296-((i>>>0)+4294967296*(h|0)))/4294967296),4294967295);if(!se(f,d,t)){Yc(K.da|0);var s=j,B=o,v=u,y=q,A=1;break}d=Wd(p[g>>2],p[g+4>>2],p[a>>2]);var t=d[0],r=d[1];d=(t>>>0)+4294967296*(r|0)+(q>>>0)+4294967296*(u|0)>>>0;u=Math.min(Math.floor(((t>>>0)+4294967296*(r|0)+(q>>>0)+4294967296*(u|0))/4294967296),4294967295);q=f+2144|0;q=ie(p[q>>2],p[q+4>>2],p[f+2156>>2],p[f+2164>>2]);q=[q[0],q[1]];t=q[0];r=q[1];q=(t>>>0)+4294967296*(r|0)+(o>>>0)+4294967296*(j|0)>>>0;j=Math.min(Math.floor(((t>>>0)+4294967296*(r|0)+(o>>>0)+4294967296*(j|0))/4294967296),4294967295);if(ke(e)){s=j;B=q;v=u;y=d;A=0;break}var o=(t>>>0)+4294967296*(r|0)+(i>>>0)+4294967296*(h|0)>>>0,h=Math.min(Math.floor(((t>>>0)+4294967296*(r|0)+(i>>>0)+4294967296*(h|0))/4294967296),4294967295),i=e,r=t=aa,r=(i+36|0)>>2,D=p[r],t=(i+28|0)>>2,L=p[t],H=D-L|0;0<(H|0)&&(D=p[i+8>>2],zd(D,D+L|0,H),L=p[t],D=p[r]);H=i|0;p[H>>2]=0;p[H+4>>2]=0;p[r]=D-L|0;p[t]=0;p[i+32>>2]=0;t=i+12|0;for(r=0;!(p[((r<<2)+p[t>>2]|0)>>2]=-1,r=r+1|0,1376256==(r|0));){}td(i);o=(i=2147483647<(h|0)||2147483647==(h|0)&&4294963198<o>>>0)?0:o;h=i?0:h;i=p[f+2152>>2];0!=(i|0)&&Re(i);i=o;o=q;q=d}f=p[f+2152>>2];0!=(f|0)&&Re(f);0==(A|0)&0<(p[xe>>2]|0)&&(f=p[p[ve>>2]+12>>2],(0>(v|0)||0==(v|0)&&1>y>>>0)|(0>(s|0)||0==(s|0)&&1>B>>>0)?Se(K.fa|0,20,1,f):(g=y+4294967296*v,a=B+4294967296*s,ye(f,K.ga|0,(z=m,m+=40,fc[0]=g/a,p[z>>2]=jc[0],p[z+4>>2]=jc[1],fc[0]=8*a/g,p[z+8>>2]=jc[0],p[z+12>>2]=jc[1],fc[0]=100*(1-a/g),p[z+16>>2]=jc[0],p[z+20>>2]=jc[1],p[z+24>>2]=y,p[z+28>>2]=v,p[z+32>>2]=B,p[z+36>>2]=s,z))));s=p[e+16>>2];0!=(s|0)&&Re(s);s=p[e+12>>2];0!=(s|0)&&Re(s);Le(p[e+8>>2]);m=c;return A}Ie.X=1;function Qe(a){var a=a&255,c=1<<(a&31);return 536866816>(c-4097|0)>>>0?c-c/16*(a>>>5)|0:c}function Te(a,c,d){var e=a+16|0,f=p[e>>2];0==(f|0)?(p[e>>2]=c,p[a+24>>2]=d,p[a+36>>2]=1):(f|0)==(c|0)?(a=a+24|0,2==(p[a>>2]|0)&&(p[a>>2]=d)):(d=a+36|0,p[d>>2]=p[d>>2]+1|0,p[a+24>>2]=2,n[a+54|0]=1)}function Ue(a,c,d,e){var f=a>>2;n[a+53|0]=1;d=(p[f+1]|0)==(d|0);do{if(d){n[a+52|0]=1;var g=a+16|0,h=p[g>>2];if(0==(h|0)){if(p[g>>2]=c,p[f+6]=e,p[f+9]=1,!(1==(p[f+12]|0)&1==(e|0))){break}}else{if((h|0)==(c|0)){if(g=a+24|0,h=p[g>>2],g=2==(h|0)?p[g>>2]=e:h,!(1==(p[f+12]|0)&1==(g|0))){break}}else{g=a+36|0,p[g>>2]=p[g>>2]+1|0}}n[a+54|0]=1}}while(0)}Ue.X=1;function Ve(a,c,d){(p[a+4>>2]|0)==(c|0)&&(a=a+28|0,1!=(p[a>>2]|0)&&(p[a>>2]=d))}function Je(a){var c=m;m+=88;var d,e=c+36,f=c+44,g=c>>2,h=c|0;p[h>>2]=0;p[h+4>>2]=0;var h=c+8|0,i=sd(16384);p[h>>2]=i;p[g+3]=0;p[g+4]=0;p[g+5]=0;p[g+6]=-1;p[g+7]=1;n[c+32|0]=0;for(var h=e+4|0,i=e+5|0,j=c|0,o=c+12|0,g=f+16|0,u=0,q=0,t=1;;){d=-p[c+12>>2]|0;var s=0>(d|0)?-1:0,B=c|0;p[B>>2]=d;p[B+4>>2]=s;for(d=0;6>(d|0);){if(Wc(c)){break}s=Xc(c);n[e+d|0]=s;d=d+1|0}if(Wc(c)){if(!t){d=41;break}Yc(K.wa|0);var v=1;d=45;break}a:{d=K.z|0;for(s=0;4>s;s++){var B=n[(e|0)+s],y=n[d+s];if(B!=y){d=B>y?1:-1;break a}}d=0}if(0!=(d|0)){if(!t){d=41;break}Yc(K.xa|0);v=2;d=45;break}s=w[h];if(2<=(s&255)){if(-1>=(p[xe>>2]|0)){v=2;d=45;break}Yc(0);v=s&255;ye(p[p[ve>>2]+12>>2],K.M|0,(z=m,m+=4,p[z>>2]=v,z));v=2;d=45;break}y=Qe(n[i]);if(536866816<(y-4096|0)>>>0){Yc(K.N|0);v=2;d=45;break}d=p[xe>>2];d=1<(d|0)?25:1!=(d|0)|t^1?27:25;if(25==d&&(Yc(0),1<(p[xe>>2]|0))){for(var t=p[p[ve>>2]+12>>2],B=0>(y|0)?-1:0,A=We|0,r=0;8>(r|0);){var D=-1<(B|0)||-1==(B|0)&&4294967295<y>>>0,L=0-((y>>>0)+4294967296*(B|0))>>>0,H=Math.min(Math.floor((0-((y>>>0)+4294967296*(B|0)))/4294967296),4294967295),L=D?y:L,D=D?B:H;if(!(0<(D|0)||0==(D|0)&&9999<L>>>0)){if(!((0<(D|0)||0==(D|0)&&1023<L>>>0)&(0==(y&1023)&&0==(B&0)))){break}}A=(Yb=((y>>>0)+4294967296*(B|0))/1024,0<=Yb?Math.floor(Yb):Math.ceil(Yb))>>>0;B=Math.min(Math.floor((Yb=((y>>>0)+4294967296*(B|0))/1024,0<=Yb?Math.floor(Yb):Math.ceil(Yb))/4294967296),4294967295);y=A;A=p[Xe+(r<<2)>>2];r=r+1|0}r=Ye|0;B=(z=m,m+=12,p[z>>2]=y,p[z+4>>2]=B,p[z+8>>2]=A,z);B=nf(K.ba|0,B);y=Math.min(B.length,15);for(A=0;A<y;A++){n[r+A]=B[A]}n[r+A]=0;s&=255;ye(t,K.P|0,(z=m,m+=8,p[z>>2]=s,p[z+4>>2]=Ye|0,z))}t=f;s=e;B=c;y=w[Ge]?2:-1;A=t>>2;r=t|0;p[r>>2]=0;p[r+4>>2]=0;D=Qe(n[s+5|0]);p[(t+8|0)>>2]=D;r=t+12|0;H=65536>(D|0)?65536:D;p[r>>2]=H;D=t+16|0;H=sd(-1<(H|0)?H:-1);p[D>>2]=H;p[A+5]=0;p[A+6]=0;p[A+7]=-1;p[A+8]=y;p[(t+36|0)>>2]=n[s+4|0]&255;p[A+10]=B;n[H+(p[r>>2]-1)|0]=0;s=Zc(f);t=Hc(p[j>>2],p[j+4>>2],p[o>>2]);B=t[0];y=t[1];t=(B>>>0)+4294967296*(y|0)+(q>>>0)+4294967296*(u|0)>>>0;u=Math.min(Math.floor(((B>>>0)+4294967296*(y|0)+(q>>>0)+4294967296*(u|0))/4294967296),4294967295);q=x[xe>>2];if(0!=(s|0)){-1<(q|0)&3>(s|0)&&(Yc(0),v=p[p[ve>>2]+12>>2],2==(s|0)?ye(v,K.Q|0,(z=m,m+=8,p[z>>2]=t,p[z+4>>2]=u,z)):ye(v,K.R|0,(z=m,m+=8,p[z>>2]=t,p[z+4>>2]=u,z)));v=p[g>>2];0!=(v|0)&&Re(v);v=2;d=45;break}1<(q|0)&&(q=p[p[ve>>2]+12>>2],a?Se(K.n|0,3,1,q):Se(K.o|0,5,1,q));q=p[g>>2];0!=(q|0)&&Re(q);q=t;t=0}41==d&&(1==(p[xe>>2]|0)&&(v=p[p[ve>>2]+12>>2],a?Se(K.n|0,3,1,v):Se(K.o|0,5,1,v)),v=0);a=p[c+8>>2];0!=(a|0)&&Re(a);m=c;return v}Je.X=1;function Pe(a,c){var d=536866817>(c-4096|0)>>>0;a:do{if(d){var e=je(c-1|0),f=a+5|0;n[f]=e&255;if(4096<(c|0)){for(var g=1<<(e&255),h=g/16|0,i=7;;){if(0>=(i|0)){e=1;break a}if((g-i*h|0)>=(c|0)){break}i=i-1|0}n[f]=(e|i<<5)&255}e=1}else{e=0}}while(0);return e}function of(a){pf(a|0)}function qf(a,c){var d,e=m;m+=56;d=e>>2;var f=p[a>>2],g=a+p[f-8>>2]|0,f=p[f-4>>2];p[d]=c;p[d+1]=a;p[d+2]=rf;p[d+3]=-1;for(var h=e+16|0,i=e+20|0,j=e+24|0,o=e+28|0,u=e+32|0,q=e+40|0,t=(f|0)==(c|0),s=h>>2,B=s+9;s<B;s++){p[s]=0}Rb[h+36>>1]=0;n[h+38]=0;do{if(t){p[d+12]=1,pc[p[p[f>>2]+12>>2]](f,e,g,g,1),s=1!=(p[j>>2]|0)?0:g}else{if(s=e+36|0,pc[p[p[f>>2]+16>>2]](f,e,g,1),s=p[s>>2],0==(s|0)){s=1!=(p[q>>2]|0)?0:1!=(p[o>>2]|0)?0:1!=(p[u>>2]|0)?0:p[i>>2]}else{if(1==(s|0)){if(1!=(p[j>>2]|0)){if(0!=(p[q>>2]|0)){s=0;break}if(1!=(p[o>>2]|0)){s=0;break}if(1!=(p[u>>2]|0)){s=0;break}}s=p[h>>2]}else{s=0}}}}while(0);m=e;return s}qf.X=1;function sf(a,c,d,e){var f=c>>2,g=a|0,h=(g|0)==(p[f+2]|0);a:do{if(h){Ve(c,d,e)}else{if((g|0)==(p[f]|0)){var i=(p[f+4]|0)==(d|0);do{if(!i){var j=c+20|0;if((p[j>>2]|0)!=(d|0)){p[f+8]=e;e=(c+44|0)>>2;if(4==(p[e]|0)){break a}g=c+52|0;n[g]=0;h=c+53|0;n[h]=0;a=p[a+8>>2];pc[p[p[a>>2]+12>>2]](a,c,d,d,1);if(0==(n[h]&1)<<24>>24){var o=0,a=11}else{0==(n[g]&1)<<24>>24?(o=1,a=11):a=15}b:do{if(11==a){p[j>>2]=d;a=c+40|0;p[a>>2]=p[a>>2]+1|0;g=1==(p[f+9]|0);do{if(g){if(2!=(p[f+6]|0)){a=14}else{n[c+54|0]=1;if(o){break b}a=16}}else{a=14}}while(0);if(!(14==a&&o)){p[e]=4;break a}}}while(0);p[e]=3;break a}}}while(0);1==(e|0)&&(p[f+8]=1)}else{j=p[a+8>>2],pc[p[p[j>>2]+16>>2]](j,c,d,e)}}}while(0)}sf.X=1;function nc(a){var c,d=245>a>>>0;do{if(d){var e=11>a>>>0?16:a+11&-8,f=e>>>3;c=x[X>>2];var g=c>>>(f>>>0);if(0!=(g&3|0)){var a=(g&1^1)+f|0,e=a<<1,d=(e<<2)+X+40|0,f=(e+2<<2)+X+40|0,h=x[f>>2],e=h+8|0,g=x[e>>2];(d|0)==(g|0)?p[X>>2]=c&(1<<a^-1):(g>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!")),p[f>>2]=g,p[g+12>>2]=d);c=a<<3;p[h+4>>2]=c|3;c=h+(c|4)|0;p[c>>2]|=1;h=e;c=38;break}if(e>>>0<=x[X+8>>2]>>>0){var i=e;c=30;break}if(0!=(g|0)){var a=2<<f,a=g<<f&(a|-a),d=(a&-a)-1|0,a=d>>>12&16,h=d>>>(a>>>0),d=h>>>5&8,f=h>>>(d>>>0),h=f>>>2&4,g=f>>>(h>>>0),f=g>>>1&2,g=g>>>(f>>>0),j=g>>>1&1,h=(d|a|h|f|j)+(g>>>(j>>>0))|0,a=h<<1,f=(a<<2)+X+40|0,g=(a+2<<2)+X+40|0,d=x[g>>2],a=d+8|0,j=x[a>>2];(f|0)==(j|0)?p[X>>2]=c&(1<<h^-1):(j>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!")),p[g>>2]=j,p[j+12>>2]=f);h<<=3;c=h-e|0;p[d+4>>2]=e|3;f=d;d=f+e|0;p[f+(e|4)>>2]=c|1;p[f+h>>2]=c;j=x[X+8>>2];0!=(j|0)&&(e=p[X+20>>2],f=j>>>2&1073741822,h=(f<<2)+X+40|0,g=x[X>>2],j=1<<(j>>>3),0==(g&j|0)?(p[X>>2]=g|j,g=h,f=(f+2<<2)+X+40|0):(f=(f+2<<2)+X+40|0,g=x[f>>2],g>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!"))),p[f>>2]=e,p[g+12>>2]=e,p[(e+8|0)>>2]=g,p[(e+12|0)>>2]=h);p[X+8>>2]=c;p[X+20>>2]=d;h=a;c=38;break}if(0==(p[X+4>>2]|0)){i=e;c=30;break}c=tf(e);if(0==(c|0)){i=e;c=30;break}h=c}else{if(4294967231<a>>>0){i=-1;c=30;break}c=a+11&-8;if(0==(p[X+4>>2]|0)){i=c;c=30;break}e=uf(c);if(0==(e|0)){i=c;c=30;break}h=e}c=38}while(0);30==c&&(e=x[X+8>>2],i>>>0>e>>>0?(c=x[X+12>>2],i>>>0<c>>>0?(c=c-i|0,p[X+12>>2]=c,e=x[X+24>>2],p[X+24>>2]=e+i|0,p[i+(e+4)>>2]=c|1,p[e+4>>2]=i|3,h=e+8|0):h=vf(i)):(a=e-i|0,c=x[X+20>>2],15<a>>>0?(p[X+20>>2]=c+i|0,p[X+8>>2]=a,p[i+(c+4)>>2]=a|1,p[c+e>>2]=a,p[c+4>>2]=i|3):(p[X+8>>2]=0,p[X+20>>2]=0,p[c+4>>2]=e|3,i=e+(c+4)|0,p[i>>2]|=1),h=c+8|0));return h}Module._malloc=nc;nc.X=1;function tf(a){var c,d,e=p[X+4>>2],f=(e&-e)-1|0,e=f>>>12&16,g=f>>>(e>>>0),f=g>>>5&8;d=g>>>(f>>>0);var g=d>>>2&4,h=d>>>(g>>>0);d=h>>>1&2;var h=h>>>(d>>>0),i=h>>>1&1,e=f=x[X+((f|e|g|d|i)+(h>>>(i>>>0))<<2)+304>>2];d=e>>2;f=(p[f+4>>2]&-8)-a|0;a:for(;;){for(g=e;;){h=p[g+16>>2];if(0==(h|0)){if(g=p[g+20>>2],0==(g|0)){break a}}else{g=h}h=(p[g+4>>2]&-8)-a|0;if(h>>>0<f>>>0){e=g;d=e>>2;f=h;continue a}}}var h=e,j=x[X+16>>2],i=h>>>0<j>>>0;do{if(!i){var o=h+a|0,g=o;if(h>>>0<o>>>0){var i=x[d+6],o=x[d+3],u=(o|0)==(e|0);do{if(u){c=e+20|0;var q=p[c>>2];if(0==(q|0)&&(c=e+16|0,q=p[c>>2],0==(q|0))){q=0;c=q>>2;break}for(;;){var t=q+20|0,s=p[t>>2];if(0==(s|0)&&(t=q+16|0,s=x[t>>2],0==(s|0))){break}c=t;q=s}c>>>0<j>>>0&&(Z(),b("Reached an unreachable!"));p[c>>2]=0}else{c=x[d+2],c>>>0<j>>>0&&(Z(),b("Reached an unreachable!")),p[c+12>>2]=o,p[o+8>>2]=c,q=o}c=q>>2}while(0);j=0==(i|0);a:do{if(!j){o=e+28|0;u=(p[o>>2]<<2)+X+304|0;t=(e|0)==(p[u>>2]|0);do{if(t){p[u>>2]=q;if(0!=(q|0)){break}p[X+4>>2]&=1<<p[o>>2]^-1;break a}i>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!"));s=i+16|0;(p[s>>2]|0)==(e|0)?p[s>>2]=q:p[i+20>>2]=q;if(0==(q|0)){break a}}while(0);q>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!"));p[c+6]=i;o=x[d+4];0!=(o|0)&&(o>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!")),p[c+4]=o,p[o+24>>2]=q);o=x[d+5];0!=(o|0)&&(o>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!")),p[c+5]=o,p[o+24>>2]=q)}}while(0);16>f>>>0?(a=f+a|0,p[d+1]=a|3,a=a+(h+4)|0,p[a>>2]|=1):(p[d+1]=a|3,p[a+(h+4)>>2]=f|1,p[h+f+a>>2]=f,j=x[X+8>>2],0!=(j|0)&&(a=x[X+20>>2],h=j>>>2&1073741822,d=(h<<2)+X+40|0,i=x[X>>2],j=1<<(j>>>3),0==(i&j|0)?(p[X>>2]=i|j,i=d,h=(h+2<<2)+X+40|0):(h=(h+2<<2)+X+40|0,i=x[h>>2],i>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!"))),p[h>>2]=a,p[i+12>>2]=a,p[a+8>>2]=i,p[a+12>>2]=d),p[X+8>>2]=f,p[X+20>>2]=g);return e+8|0}}}while(0);Z();b("Reached an unreachable!")}tf.X=1;function vf(a){var c,d;0==(p[wf>>2]|0)&&xf();var e=0==(p[X+440>>2]&4|0);do{if(e){d=p[X+24>>2];if(0==(d|0)){d=6}else{if(d=yf(d),0==(d|0)){d=6}else{var f=p[wf+8>>2],f=a+47-p[X+12>>2]+f&-f;if(2147483647>f>>>0){var g=zf(f);if((g|0)==(p[d>>2]+p[d+4>>2]|0)){var h=g,i=f;c=g;d=13}else{var j=g,o=f;d=15}}else{d=14}}}if(6==d){if(d=zf(0),-1==(d|0)){d=14}else{var f=p[wf+8>>2],f=f+(a+47)&-f,g=d,u=p[wf+4>>2],q=u-1|0,f=0==(q&g|0)?f:f-g+(q+g&-u)|0;2147483647>f>>>0?(g=zf(f),(g|0)==(d|0)?(h=d,i=f,c=g,d=13):(j=g,o=f,d=15)):d=14}}if(13==d){if(-1!=(h|0)){var t=i,s=h;d=26;break}j=c;o=i}else{if(14==d){p[X+440>>2]|=4;d=23;break}}d=-o|0;if(-1!=(j|0)&2147483647>o>>>0){if(o>>>0<(a+48|0)>>>0){f=p[wf+8>>2],f=a+47-o+f&-f,2147483647>f>>>0?-1==(zf(f)|0)?(zf(d),d=22):(B=f+o|0,d=21):(B=o,d=21)}else{var B=o;d=21}}else{B=o,d=21}21==d&&-1!=(j|0)?(t=B,s=j,d=26):(p[X+440>>2]|=4,d=23)}else{d=23}}while(0);23==d&&(e=p[wf+8>>2],e=e+(a+47)&-e,2147483647>e>>>0?(e=zf(e),h=zf(0),-1!=(h|0)&-1!=(e|0)&e>>>0<h>>>0?(h=h-e|0,h>>>0<=(a+40|0)>>>0|-1==(e|0)?d=49:(t=h,s=e,d=26)):d=49):d=49);a:do{if(26==d){e=p[X+432>>2]+t|0;p[X+432>>2]=e;e>>>0>x[X+436>>2]>>>0&&(p[X+436>>2]=e);e=x[X+24>>2];h=0==(e|0);b:do{if(h){i=x[X+16>>2];0==(i|0)|s>>>0<i>>>0&&(p[X+16>>2]=s);p[X+444>>2]=s;p[X+448>>2]=t;p[X+456>>2]=0;p[X+36>>2]=p[wf>>2];p[X+32>>2]=-1;for(i=0;!(c=i<<1,j=(c<<2)+X+40|0,p[X+(c+3<<2)+40>>2]=j,p[X+(c+2<<2)+40>>2]=j,i=i+1|0,32==(i|0));){}Af(s,t-40|0)}else{j=X+444|0;for(c=j>>2;0!=(j|0);){i=x[c];j=j+4|0;o=x[j>>2];B=i+o|0;if((s|0)==(B|0)){if(0!=(p[c+3]&8|0)){break}c=e;if(!(c>>>0>=i>>>0&c>>>0<B>>>0)){break}p[j>>2]=o+t|0;Af(p[X+24>>2],p[X+12>>2]+t|0);break b}j=p[c+2];c=j>>2}s>>>0<x[X+16>>2]>>>0&&(p[X+16>>2]=s);c=s+t|0;for(j=X+444|0;0!=(j|0);){o=j|0;i=x[o>>2];if((i|0)==(c|0)){if(0!=(p[j+12>>2]&8|0)){break}p[o>>2]=s;var v=j+4|0;p[v>>2]=p[v>>2]+t|0;v=Bf(s,i,a);d=50;break a}j=p[j+8>>2]}Cf(s,t)}}while(0);e=x[X+12>>2];e>>>0>a>>>0?(v=e-a|0,p[X+12>>2]=v,h=e=x[X+24>>2],p[X+24>>2]=h+a|0,p[a+(h+4)>>2]=v|1,p[e+4>>2]=a|3,v=e+8|0,d=50):d=49}}while(0);49==d&&(p[Pc>>2]=12,v=0);return v}vf.X=1;function uf(a){var c,d,e,f,g,h=a>>2,i=-a|0,j=a>>>8;if(0==(j|0)){var o=0}else{if(16777215<a>>>0){o=31}else{var u=(j+1048320|0)>>>16&8,q=j<<u,t=(q+520192|0)>>>16&4,s=q<<t,B=(s+245760|0)>>>16&2,v=14-(t|u|B)+(s<<B>>>15)|0,o=a>>>((v+7|0)>>>0)&1|v<<1}}var y=x[X+(o<<2)+304>>2],A=0==(y|0);a:do{if(A){var r=0,D=i,L=0}else{var H=31==(o|0)?0:25-(o>>>1)|0,P=0,J=i,G=y;g=G>>2;for(var I=a<<H,M=0;;){var O=p[g+1]&-8,N=O-a|0;if(N>>>0<J>>>0){if((O|0)==(a|0)){r=G;D=N;L=G;break a}var Q=G,$=N}else{Q=P,$=J}var ha=x[g+5],ba=x[((I>>>31<<2)+16>>2)+g],R=0==(ha|0)|(ha|0)==(ba|0)?M:ha;if(0==(ba|0)){r=Q;D=$;L=R;break a}P=Q;J=$;G=ba;g=G>>2;I<<=1;M=R}}}while(0);if(0==(L|0)&0==(r|0)){var Sa=2<<o,fa=p[X+4>>2]&(Sa|-Sa);if(0==(fa|0)){var U=L}else{var qa=(fa&-fa)-1|0,Aa=qa>>>12&16,da=qa>>>(Aa>>>0),Ea=da>>>5&8,ra=da>>>(Ea>>>0),pb=ra>>>2&4,bb=ra>>>(pb>>>0),Eb=bb>>>1&2,sa=bb>>>(Eb>>>0),Fa=sa>>>1&1,U=p[X+((Ea|Aa|pb|Eb|Fa)+(sa>>>(Fa>>>0))<<2)+304>>2]}}else{U=L}var Zb=0==(U|0);a:do{if(Zb){var ga=D,ta=r;f=ta>>2}else{var ia=U;e=ia>>2;for(var La=D,cb=r;;){var db=(p[e+1]&-8)-a|0,Fb=db>>>0<La>>>0,ja=Fb?db:La,rb=Fb?ia:cb,Ga=x[e+4];if(0!=(Ga|0)){ia=Ga}else{var sb=x[e+5];if(0==(sb|0)){ga=ja;ta=rb;f=ta>>2;break a}ia=sb}e=ia>>2;La=ja;cb=rb}}}while(0);var tb=0==(ta|0);a:do{if(tb){var Ta=0}else{if(ga>>>0<(p[X+8>>2]-a|0)>>>0){var Ma=ta;d=Ma>>2;var Ua=x[X+16>>2],ub=Ma>>>0<Ua>>>0;do{if(!ub){var eb=Ma+a|0,vb=eb;if(Ma>>>0<eb>>>0){var Na=x[f+6],Va=x[f+3],Nb=(Va|0)==(ta|0);do{if(Nb){var Gb=ta+20|0,Hb=p[Gb>>2];if(0==(Hb|0)){var Ib=ta+16|0,Wa=p[Ib>>2];if(0==(Wa|0)){var Y=0;c=Y>>2;break}var na=Ib,ka=Wa}else{na=Gb,ka=Hb}for(;;){var ua=ka+20|0,va=p[ua>>2];if(0!=(va|0)){na=ua,ka=va}else{var fb=ka+16|0,Oa=x[fb>>2];if(0==(Oa|0)){break}na=fb;ka=Oa}}na>>>0<Ua>>>0&&(Z(),b("Reached an unreachable!"));p[na>>2]=0;Y=ka}else{var gb=x[f+2];gb>>>0<Ua>>>0&&(Z(),b("Reached an unreachable!"));p[gb+12>>2]=Va;p[Va+8>>2]=gb;Y=Va}c=Y>>2}while(0);var Ob=0==(Na|0);b:do{if(!Ob){var S=ta+28|0,oa=(p[S>>2]<<2)+X+304|0,Xa=(ta|0)==(p[oa>>2]|0);do{if(Xa){p[oa>>2]=Y;if(0!=(Y|0)){break}p[X+4>>2]&=1<<p[S>>2]^-1;break b}Na>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!"));var la=Na+16|0;(p[la>>2]|0)==(ta|0)?p[la>>2]=Y:p[Na+20>>2]=Y;if(0==(Y|0)){break b}}while(0);Y>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!"));p[c+6]=Na;var wa=x[f+4];0!=(wa|0)&&(wa>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!")),p[c+4]=wa,p[wa+24>>2]=Y);var ma=x[f+5];0!=(ma|0)&&(ma>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!")),p[c+5]=ma,p[ma+24>>2]=Y)}}while(0);var Ya=16>ga>>>0;b:do{if(Ya){var Jb=ga+a|0;p[f+1]=Jb|3;var wb=Jb+(Ma+4)|0;p[wb>>2]|=1}else{if(p[f+1]=a|3,p[h+(d+1)]=ga|1,p[(ga>>2)+d+h]=ga,256>ga>>>0){var Za=ga>>>2&1073741822,Ha=(Za<<2)+X+40|0,Ia=x[X>>2],Pa=1<<(ga>>>3);if(0==(Ia&Pa|0)){p[X>>2]=Ia|Pa;var hb=Ha,ib=(Za+2<<2)+X+40|0}else{var Qa=(Za+2<<2)+X+40|0,xa=x[Qa>>2];xa>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!"));hb=xa;ib=Qa}p[ib>>2]=vb;p[hb+12>>2]=vb;p[h+(d+2)]=hb;p[h+(d+3)]=Ha}else{var Ja=eb,jb=ga>>>8;if(0==(jb|0)){var Ba=0}else{if(16777215<ga>>>0){Ba=31}else{var $a=(jb+1048320|0)>>>16&8,xb=jb<<$a,kb=(xb+520192|0)>>>16&4,yb=xb<<kb,Kb=(yb+245760|0)>>>16&2,Lb=14-(kb|$a|Kb)+(yb<<Kb>>>15)|0,Ba=ga>>>((Lb+7|0)>>>0)&1|Lb<<1}}var Pb=(Ba<<2)+X+304|0;p[h+(d+7)]=Ba;var Qb=a+(Ma+16)|0;p[h+(d+5)]=0;p[Qb>>2]=0;var Ka=p[X+4>>2],gc=1<<Ba;if(0==(Ka&gc|0)){p[X+4>>2]=Ka|gc,p[Pb>>2]=Ja,p[h+(d+6)]=Pb,p[h+(d+3)]=Ja,p[h+(d+2)]=Ja}else{for(var Tb=ga<<(31==(Ba|0)?0:25-(Ba>>>1)|0),lb=p[Pb>>2];;){if((p[lb+4>>2]&-8|0)==(ga|0)){var hc=lb+8|0,mb=x[hc>>2],Mb=x[X+16>>2],lc=lb>>>0<Mb>>>0;do{if(!lc&&mb>>>0>=Mb>>>0){p[mb+12>>2]=Ja;p[hc>>2]=Ja;p[h+(d+2)]=mb;p[h+(d+3)]=lb;p[h+(d+6)]=0;break b}}while(0);Z();b("Reached an unreachable!")}var $b=(Tb>>>31<<2)+lb+16|0,mc=x[$b>>2];if(0==(mc|0)){if($b>>>0>=x[X+16>>2]>>>0){p[$b>>2]=Ja;p[h+(d+6)]=lb;p[h+(d+3)]=Ja;p[h+(d+2)]=Ja;break b}Z();b("Reached an unreachable!")}Tb<<=1;lb=mc}}}}}while(0);Ta=ta+8|0;break a}}}while(0);Z();b("Reached an unreachable!")}Ta=0}}while(0);return Ta}uf.X=1;function Df(){var a;0==(p[wf>>2]|0)&&xf();var c=x[X+24>>2],d=0==(c|0);a:do{if(!d){var e=x[X+12>>2],f=40<e>>>0;do{if(f){var g=x[wf+8>>2],h=(Math.floor(((e-41+g|0)>>>0)/(g>>>0))-1)*g|0,i=yf(c);if(0==(p[i+12>>2]&8|0)){var j=zf(0);a=(i+4|0)>>2;if((j|0)==(p[i>>2]+p[a]|0)&&(h=zf(-(2147483646<h>>>0?-2147483648-g|0:h)|0),g=zf(0),-1!=(h|0)&g>>>0<j>>>0&&(h=j-g|0,(j|0)!=(g|0)))){p[a]=p[a]-h|0;p[X+432>>2]=p[X+432>>2]-h|0;Af(p[X+24>>2],p[X+12>>2]-h|0);break a}}}}while(0);x[X+12>>2]>>>0>x[X+28>>2]>>>0&&(p[X+28>>2]=-1)}}while(0)}Df.X=1;function Le(a){var c,d,e,f,g,h,i=a>>2,j,o=0==(a|0);a:do{if(!o){var u=a-8|0,q=u,t=x[X+16>>2],s=u>>>0<t>>>0;b:do{if(!s){var B=x[a-4>>2],v=B&3;if(1!=(v|0)){var y=B&-8;h=y>>2;var A=a+(y-8)|0,r=A,D=0==(B&1|0);c:do{if(D){var L=x[u>>2];if(0==(v|0)){break a}var H=-8-L|0;g=H>>2;var P=a+H|0,J=P,G=L+y|0;if(P>>>0<t>>>0){break b}if((J|0)==(p[X+20>>2]|0)){f=(a+(y-4)|0)>>2;if(3!=(p[f]&3|0)){var I=J;e=I>>2;var M=G;break}p[X+8>>2]=G;p[f]&=-2;p[g+(i+1)]=G|1;p[A>>2]=G;break a}if(256>L>>>0){var O=x[g+(i+2)],N=x[g+(i+3)];if((O|0)==(N|0)){p[X>>2]&=1<<(L>>>3)^-1,I=J,e=I>>2,M=G}else{var Q=((L>>>2&1073741822)<<2)+X+40|0,$=(O|0)!=(Q|0)&O>>>0<t>>>0;do{if(!$&&(N|0)==(Q|0)|N>>>0>=t>>>0){p[O+12>>2]=N;p[N+8>>2]=O;I=J;e=I>>2;M=G;break c}}while(0);Z();b("Reached an unreachable!")}}else{var ha=P,ba=x[g+(i+6)],R=x[g+(i+3)],Sa=(R|0)==(ha|0);do{if(Sa){var fa=H+(a+20)|0,U=p[fa>>2];if(0==(U|0)){var qa=H+(a+16)|0,Aa=p[qa>>2];if(0==(Aa|0)){var da=0;d=da>>2;break}var Ea=qa,ra=Aa}else{Ea=fa,ra=U,j=21}for(;;){var pb=ra+20|0,bb=p[pb>>2];if(0!=(bb|0)){Ea=pb,ra=bb}else{var Eb=ra+16|0,sa=x[Eb>>2];if(0==(sa|0)){break}Ea=Eb;ra=sa}}Ea>>>0<t>>>0&&(Z(),b("Reached an unreachable!"));p[Ea>>2]=0;da=ra}else{var Fa=x[g+(i+2)];Fa>>>0<t>>>0&&(Z(),b("Reached an unreachable!"));p[Fa+12>>2]=R;p[R+8>>2]=Fa;da=R}d=da>>2}while(0);if(0!=(ba|0)){var Zb=H+(a+28)|0,ga=(p[Zb>>2]<<2)+X+304|0,ta=(ha|0)==(p[ga>>2]|0);do{if(ta){p[ga>>2]=da;if(0!=(da|0)){break}p[X+4>>2]&=1<<p[Zb>>2]^-1;I=J;e=I>>2;M=G;break c}ba>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!"));var ia=ba+16|0;(p[ia>>2]|0)==(ha|0)?p[ia>>2]=da:p[ba+20>>2]=da;if(0==(da|0)){I=J;e=I>>2;M=G;break c}}while(0);da>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!"));p[d+6]=ba;var La=x[g+(i+4)];0!=(La|0)&&(La>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!")),p[d+4]=La,p[La+24>>2]=da);var cb=x[g+(i+5)];0!=(cb|0)&&(cb>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!")),p[d+5]=cb,p[cb+24>>2]=da)}I=J;e=I>>2;M=G}}else{I=q,e=I>>2,M=y}}while(0);var db=I;if(db>>>0<A>>>0){var Fb=a+(y-4)|0,ja=x[Fb>>2];if(0!=(ja&1|0)){var rb=0==(ja&2|0);do{if(rb){if((r|0)==(p[X+24>>2]|0)){var Ga=p[X+12>>2]+M|0;p[X+12>>2]=Ga;p[X+24>>2]=I;p[e+1]=Ga|1;(I|0)==(p[X+20>>2]|0)&&(p[X+20>>2]=0,p[X+8>>2]=0);if(Ga>>>0<=x[X+28>>2]>>>0){break a}Df();break a}if((r|0)==(p[X+20>>2]|0)){var sb=p[X+8>>2]+M|0;p[X+8>>2]=sb;p[X+20>>2]=I;p[e+1]=sb|1;p[(db+sb|0)>>2]=sb;break a}var tb=(ja&-8)+M|0,Ta=ja>>>3,Ma=256>ja>>>0;c:do{if(Ma){var Ua=x[i+h],ub=x[((y|4)>>2)+i];if((Ua|0)==(ub|0)){p[X>>2]&=1<<Ta^-1}else{var eb=((ja>>>2&1073741822)<<2)+X+40|0;j=(Ua|0)==(eb|0)?63:Ua>>>0<x[X+16>>2]>>>0?66:63;do{if(63==j&&!((ub|0)!=(eb|0)&&ub>>>0<x[X+16>>2]>>>0)){p[Ua+12>>2]=ub;p[ub+8>>2]=Ua;break c}}while(0);Z();b("Reached an unreachable!")}}else{var vb=A,Na=x[h+(i+4)],Va=x[((y|4)>>2)+i],Nb=(Va|0)==(vb|0);do{if(Nb){var Gb=y+(a+12)|0,Hb=p[Gb>>2];if(0==(Hb|0)){var Ib=y+(a+8)|0,Wa=p[Ib>>2];if(0==(Wa|0)){var Y=0;c=Y>>2;break}var na=Ib,ka=Wa}else{na=Gb,ka=Hb,j=73}for(;;){var ua=ka+20|0,va=p[ua>>2];if(0!=(va|0)){na=ua,ka=va}else{var fb=ka+16|0,Oa=x[fb>>2];if(0==(Oa|0)){break}na=fb;ka=Oa}}na>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!"));p[na>>2]=0;Y=ka}else{var gb=x[i+h];gb>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!"));p[gb+12>>2]=Va;p[Va+8>>2]=gb;Y=Va}c=Y>>2}while(0);if(0!=(Na|0)){var Ob=y+(a+20)|0,S=(p[Ob>>2]<<2)+X+304|0,oa=(vb|0)==(p[S>>2]|0);do{if(oa){p[S>>2]=Y;if(0!=(Y|0)){break}p[X+4>>2]&=1<<p[Ob>>2]^-1;break c}Na>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!"));var Xa=Na+16|0;(p[Xa>>2]|0)==(vb|0)?p[Xa>>2]=Y:p[Na+20>>2]=Y;if(0==(Y|0)){break c}}while(0);Y>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!"));p[c+6]=Na;var la=x[h+(i+2)];0!=(la|0)&&(la>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!")),p[c+4]=la,p[la+24>>2]=Y);var wa=x[h+(i+3)];0!=(wa|0)&&(wa>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!")),p[c+5]=wa,p[wa+24>>2]=Y)}}}while(0);p[e+1]=tb|1;p[db+tb>>2]=tb;if((I|0)!=(p[X+20>>2]|0)){var ma=tb}else{p[X+8>>2]=tb;break a}}else{p[Fb>>2]=ja&-2,p[e+1]=M|1,ma=p[db+M>>2]=M}}while(0);if(256>ma>>>0){var Ya=ma>>>2&1073741822,Jb=(Ya<<2)+X+40|0,wb=x[X>>2],Za=1<<(ma>>>3);if(0==(wb&Za|0)){p[X>>2]=wb|Za;var Ha=Jb,Ia=(Ya+2<<2)+X+40|0}else{var Pa=(Ya+2<<2)+X+40|0,hb=x[Pa>>2];hb>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!"));Ha=hb;Ia=Pa}p[Ia>>2]=I;p[Ha+12>>2]=I;p[e+2]=Ha;p[e+3]=Jb;break a}var ib=I,Qa=ma>>>8;if(0==(Qa|0)){var xa=0}else{if(16777215<ma>>>0){xa=31}else{var Ja=(Qa+1048320|0)>>>16&8,jb=Qa<<Ja,Ba=(jb+520192|0)>>>16&4,$a=jb<<Ba,xb=($a+245760|0)>>>16&2,kb=14-(Ba|Ja|xb)+($a<<xb>>>15)|0,xa=ma>>>((kb+7|0)>>>0)&1|kb<<1}}var yb=(xa<<2)+X+304|0;p[e+7]=xa;p[e+5]=0;p[e+4]=0;var Kb=p[X+4>>2],Lb=1<<xa,Pb=0==(Kb&Lb|0);c:do{if(Pb){p[X+4>>2]=Kb|Lb,p[yb>>2]=ib,p[e+6]=yb,p[e+3]=I,p[e+2]=I}else{for(var Qb=ma<<(31==(xa|0)?0:25-(xa>>>1)|0),Ka=p[yb>>2];;){if((p[Ka+4>>2]&-8|0)==(ma|0)){var gc=Ka+8|0,Tb=x[gc>>2],lb=x[X+16>>2],hc=Ka>>>0<lb>>>0;do{if(!hc&&Tb>>>0>=lb>>>0){p[Tb+12>>2]=ib;p[gc>>2]=ib;p[e+2]=Tb;p[e+3]=Ka;p[e+6]=0;break c}}while(0);Z();b("Reached an unreachable!")}var mb=(Qb>>>31<<2)+Ka+16|0,Mb=x[mb>>2];if(0==(Mb|0)){if(mb>>>0>=x[X+16>>2]>>>0){p[mb>>2]=ib;p[e+6]=Ka;p[e+3]=I;p[e+2]=I;break c}Z();b("Reached an unreachable!")}Qb<<=1;Ka=Mb}}}while(0);var lc=p[X+32>>2]-1|0;p[X+32>>2]=lc;if(0!=(lc|0)){break a}var $b=p[X+452>>2],mc=0==($b|0);c:do{if(!mc){for(var cd=$b;;){var Ab=p[cd+8>>2];if(0==(Ab|0)){break c}cd=Ab}}}while(0);p[X+32>>2]=-1;break a}}}}}while(0);Z();b("Reached an unreachable!")}}while(0)}Module._free=Le;Le.X=1;function yf(a){var c,d=X+444|0;for(c=d>>2;;){var e=x[c];if(e>>>0<=a>>>0&&(e+p[c+1]|0)>>>0>a>>>0){var f=d;break}c=x[c+2];if(0==(c|0)){f=0;break}d=c;c=d>>2}return f}function Af(a,c){var d=a+8|0,d=0==(d&7|0)?0:-d&7,e=c-d|0;p[X+24>>2]=a+d|0;p[X+12>>2]=e;p[d+(a+4)>>2]=e|1;p[c+(a+4)>>2]=40;p[X+28>>2]=p[wf+16>>2]}function ud(a,c){var d,e,f,g=4294967231<c>>>0;a:do{if(g){p[Pc>>2]=12;var h=0}else{f=d=a-8|0;e=(a-4|0)>>2;var i=x[e],j=i&-8,o=j-8|0,u=a+o|0,q=d>>>0<x[X+16>>2]>>>0;do{if(!q){var t=i&3;if(1!=(t|0)&-8<(o|0)&&(d=(a+(j-4)|0)>>2,0!=(p[d]&1|0))){g=11>c>>>0?16:c+11&-8;if(0==(t|0)){var s=0,B,i=p[f+4>>2]&-8;B=256>g>>>0?0:i>>>0>=(g+4|0)>>>0&&(i-g|0)>>>0<=p[wf+8>>2]<<1>>>0?f:0;f=17}else{j>>>0<g>>>0?(u|0)!=(p[X+24>>2]|0)?f=21:(d=p[X+12>>2]+j|0,d>>>0>g>>>0?(s=d-g|0,B=a+(g-8)|0,p[e]=g|i&1|2,p[a+(g-4)>>2]=s|1,p[X+24>>2]=B,p[X+12>>2]=s,s=0,B=f,f=17):f=21):(s=j-g|0,15<s>>>0?(p[e]=g|i&1|2,p[a+(g-4)>>2]=s|3,p[d]|=1,s=a+g|0):s=0,B=f,f=17)}do{if(17==f&&0!=(B|0)){0!=(s|0)&&Le(s);h=B+8|0;break a}}while(0);f=nc(c);if(0==(f|0)){h=0;break a}e=j-(0==(p[e]&3|0)?8:4)|0;qd(f,a,e>>>0<c>>>0?e:c);Le(a);h=f;break a}}}while(0);Z();b("Reached an unreachable!")}}while(0);return h}ud.X=1;function xf(){if(0==(p[wf>>2]|0)){var a=Ef();0==(a-1&a|0)?(p[wf+8>>2]=a,p[wf+4>>2]=a,p[wf+12>>2]=-1,p[wf+16>>2]=2097152,p[wf+20>>2]=0,p[X+440>>2]=0,p[wf>>2]=Math.floor(Date.now()/1e3)&-16^1431655768):(Z(),b("Reached an unreachable!"))}}function Bf(a,c,d){var e,f,g,h=c>>2,i=a>>2,j,o=a+8|0,o=0==(o&7|0)?0:-o&7;f=c+8|0;var u=0==(f&7|0)?0:-f&7;g=u>>2;var q=c+u|0,t=o+d|0;f=t>>2;var s=a+t|0,B=q-(a+o)-d|0;p[(o+4>>2)+i]=d|3;d=(q|0)==(p[X+24>>2]|0);a:do{if(d){var v=p[X+12>>2]+B|0;p[X+12>>2]=v;p[X+24>>2]=s;p[f+(i+1)]=v|1}else{if((q|0)==(p[X+20>>2]|0)){v=p[X+8>>2]+B|0,p[X+8>>2]=v,p[X+20>>2]=s,p[f+(i+1)]=v|1,p[(a+v+t|0)>>2]=v}else{var y=x[g+(h+1)];if(1==(y&3|0)){var v=y&-8,A=y>>>3,r=256>y>>>0;b:do{if(r){var D=x[((u|8)>>2)+h],L=x[g+(h+3)];if((D|0)==(L|0)){p[X>>2]&=1<<A^-1}else{var H=((y>>>2&1073741822)<<2)+X+40|0;j=(D|0)==(H|0)?15:D>>>0<x[X+16>>2]>>>0?18:15;do{if(15==j&&!((L|0)!=(H|0)&&L>>>0<x[X+16>>2]>>>0)){p[D+12>>2]=L;p[L+8>>2]=D;break b}}while(0);Z();b("Reached an unreachable!")}}else{j=q;D=x[((u|24)>>2)+h];L=x[g+(h+3)];H=(L|0)==(j|0);do{if(H){e=u|16;var P=e+(c+4)|0,J=p[P>>2];if(0==(J|0)){if(e=c+e|0,J=p[e>>2],0==(J|0)){J=0;e=J>>2;break}}else{e=P}for(;;){var P=J+20|0,G=p[P>>2];if(0==(G|0)&&(P=J+16|0,G=x[P>>2],0==(G|0))){break}e=P;J=G}e>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!"));p[e>>2]=0}else{e=x[((u|8)>>2)+h],e>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!")),p[e+12>>2]=L,p[L+8>>2]=e,J=L}e=J>>2}while(0);if(0!=(D|0)){L=u+(c+28)|0;H=(p[L>>2]<<2)+X+304|0;P=(j|0)==(p[H>>2]|0);do{if(P){p[H>>2]=J;if(0!=(J|0)){break}p[X+4>>2]&=1<<p[L>>2]^-1;break b}D>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!"));G=D+16|0;(p[G>>2]|0)==(j|0)?p[G>>2]=J:p[D+20>>2]=J;if(0==(J|0)){break b}}while(0);J>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!"));p[e+6]=D;j=u|16;D=x[(j>>2)+h];0!=(D|0)&&(D>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!")),p[e+4]=D,p[D+24>>2]=J);j=x[(j+4>>2)+h];0!=(j|0)&&(j>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!")),p[e+5]=j,p[j+24>>2]=J)}}}while(0);y=c+(v|u)|0;v=v+B|0}else{y=q,v=B}y=y+4|0;p[y>>2]&=-2;p[f+(i+1)]=v|1;p[(v>>2)+i+f]=v;if(256>v>>>0){A=v>>>2&1073741822,y=(A<<2)+X+40|0,r=x[X>>2],v=1<<(v>>>3),0==(r&v|0)?(p[X>>2]=r|v,v=y,A=(A+2<<2)+X+40|0):(A=(A+2<<2)+X+40|0,v=x[A>>2],v>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!"))),p[A>>2]=s,p[v+12>>2]=s,p[f+(i+2)]=v,p[f+(i+3)]=y}else{if(y=s,r=v>>>8,0==(r|0)?A=0:16777215<v>>>0?A=31:(A=(r+1048320|0)>>>16&8,j=r<<A,r=(j+520192|0)>>>16&4,j<<=r,D=(j+245760|0)>>>16&2,A=14-(r|A|D)+(j<<D>>>15)|0,A=v>>>((A+7|0)>>>0)&1|A<<1),r=(A<<2)+X+304|0,p[f+(i+7)]=A,j=t+(a+16)|0,p[f+(i+5)]=0,p[j>>2]=0,j=p[X+4>>2],D=1<<A,0==(j&D|0)){p[X+4>>2]=j|D,p[r>>2]=y,p[f+(i+6)]=r,p[f+(i+3)]=y,p[f+(i+2)]=y}else{A=v<<(31==(A|0)?0:25-(A>>>1)|0);for(r=p[r>>2];;){if((p[r+4>>2]&-8|0)==(v|0)){j=r+8|0;D=x[j>>2];L=x[X+16>>2];H=r>>>0<L>>>0;do{if(!H&&D>>>0>=L>>>0){p[D+12>>2]=y;p[j>>2]=y;p[f+(i+2)]=D;p[f+(i+3)]=r;p[f+(i+6)]=0;break a}}while(0);Z();b("Reached an unreachable!")}j=(A>>>31<<2)+r+16|0;D=x[j>>2];if(0==(D|0)){if(j>>>0>=x[X+16>>2]>>>0){p[j>>2]=y;p[f+(i+6)]=r;p[f+(i+3)]=y;p[f+(i+2)]=y;break a}Z();b("Reached an unreachable!")}A<<=1;r=D}}}}}}while(0);return a+(o|8)|0}Bf.X=1;function Re(a){0!=(a|0)&&Le(a)}function Ff(a){Gf(a|0)}function Cf(a,c){var d,e,f=x[X+24>>2];e=f>>2;var g=yf(f),h=p[g>>2];d=p[g+4>>2];var g=h+d|0,i=h+(d-39)|0,h=h+(d-47)+(0==(i&7|0)?0:-i&7)|0,h=h>>>0<(f+16|0)>>>0?f:h,i=h+8|0;d=i>>2;Af(a,c-40|0);p[(h+4|0)>>2]=27;p[d]=p[X+444>>2];p[d+1]=p[X+448>>2];p[d+2]=p[X+452>>2];p[d+3]=p[X+456>>2];p[X+444>>2]=a;p[X+448>>2]=c;p[X+456>>2]=0;p[X+452>>2]=i;d=h+28|0;p[d>>2]=7;i=(h+32|0)>>>0<g>>>0;a:do{if(i){for(var j=d;;){var o=j+4|0;p[o>>2]=7;if((j+8|0)>>>0>=g>>>0){break a}j=o}}}while(0);g=(h|0)==(f|0);a:do{if(!g){if(d=h-f|0,i=f+d|0,j=d+(f+4)|0,p[j>>2]&=-2,p[e+1]=d|1,p[i>>2]=d,256>d>>>0){j=d>>>2&1073741822,i=(j<<2)+X+40|0,o=x[X>>2],d=1<<(d>>>3),0==(o&d|0)?(p[X>>2]=o|d,d=i,j=(j+2<<2)+X+40|0):(j=(j+2<<2)+X+40|0,d=x[j>>2],d>>>0<x[X+16>>2]>>>0&&(Z(),b("Reached an unreachable!"))),p[j>>2]=f,p[d+12>>2]=f,p[e+2]=d,p[e+3]=i}else{i=f;o=d>>>8;if(0==(o|0)){j=0}else{if(16777215<d>>>0){j=31}else{var j=(o+1048320|0)>>>16&8,u=o<<j,o=(u+520192|0)>>>16&4,u=u<<o,q=(u+245760|0)>>>16&2,j=14-(o|j|q)+(u<<q>>>15)|0,j=d>>>((j+7|0)>>>0)&1|j<<1}}o=(j<<2)+X+304|0;p[e+7]=j;p[e+5]=0;p[e+4]=0;u=p[X+4>>2];q=1<<j;if(0==(u&q|0)){p[X+4>>2]=u|q,p[o>>2]=i,p[e+6]=o,p[e+3]=f,p[e+2]=f}else{j=d<<(31==(j|0)?0:25-(j>>>1)|0);for(o=p[o>>2];;){if((p[o+4>>2]&-8|0)==(d|0)){var u=o+8|0,q=x[u>>2],t=x[X+16>>2],s=o>>>0<t>>>0;do{if(!s&&q>>>0>=t>>>0){p[q+12>>2]=i;p[u>>2]=i;p[e+2]=q;p[e+3]=o;p[e+6]=0;break a}}while(0);Z();b("Reached an unreachable!")}u=(j>>>31<<2)+o+16|0;q=x[u>>2];if(0==(q|0)){if(u>>>0>=x[X+16>>2]>>>0){p[u>>2]=i;p[e+6]=o;p[e+3]=f;p[e+2]=f;break a}Z();b("Reached an unreachable!")}j<<=1;o=q}}}}}while(0)}Cf.X=1;function sd(a){for(a=0==(a|0)?1:a;;){var c=nc(a);if(0==(c|0)){c=(Xb=p[Hf>>2],p[Hf>>2]=Xb,Xb);if(0==(c|0)){var d=nc(4);p[d>>2]=If+8|0;vd(d,Jf,2);b("Reached an unreachable!")}pc[c]()}else{return c}}return ca}function W(a){Pc||(Pc=F([0],"i32",E));p[Pc>>2]=a}var Pc,Kf=13,Me=9,Ce=22,Lf=5,Mf=21,Nf=25,Of=6,Be=34,Pf=0,Qf=0,Rf=0,ve=0,Sf=2,Ke=[ca],Tf=k;function Uf(a,c){if("string"!==typeof a){return ca}c===aa&&(c="/");a&&"/"==a[0]&&(c="");for(var d=(c+"/"+a).split("/").reverse(),e=[""];d.length;){var f=d.pop();""==f||"."==f||(".."==f?1<e.length&&e.pop():e.push(f))}return 1==e.length?"/":e.join("/")}function Vf(a,c,d){var e={eb:l,k:l,error:0,name:ca,path:ca,object:ca,s:l,u:ca,t:ca},a=Uf(a);if("/"==a){e.eb=k,e.k=e.s=k,e.name="/",e.path=e.u="/",e.object=e.t=Wf}else{if(a!==ca){for(var d=d||0,a=a.slice(1).split("/"),f=Wf,g=[""];a.length;){1==a.length&&f.c&&(e.s=k,e.u=1==g.length?"/":g.join("/"),e.t=f,e.name=a[0]);var h=a.shift();if(f.c){if(f.v){if(!f.a.hasOwnProperty(h)){e.error=2;break}}else{e.error=Kf;break}}else{e.error=20;break}f=f.a[h];if(f.link&&!(c&&0==a.length)){if(40<d){e.error=40;break}e=Uf(f.link,g.join("/"));return Vf([e].concat(a).join("/"),c,d+1)}g.push(h);0==a.length&&(e.k=k,e.path=g.join("/"),e.object=f)}}}return e}function Xf(a){Yf();a=Vf(a,aa);if(a.k){return a.object}W(a.error);return ca}function Zf(a,c,d,e,f){a||(a="/");"string"===typeof a&&(a=Xf(a));a||(W(Kf),b(Error("Parent path must exist.")));a.c||(W(20),b(Error("Parent must be a folder.")));!a.write&&!Tf&&(W(Kf),b(Error("Parent folder must be writeable.")));if(!c||"."==c||".."==c){W(2),b(Error("Name must not be empty."))}a.a.hasOwnProperty(c)&&(W(17),b(Error("Can't overwrite object.")));a.a[c]={v:e===aa?k:e,write:f===aa?l:f,timestamp:Date.now(),cb:Sf++};for(var g in d){d.hasOwnProperty(g)&&(a.a[c][g]=d[g])}return a.a[c]}function $f(a,c){return Zf(a,c,{c:k,d:l,a:{}},k,k)}function ag(){var a="dev/shm/tmp",c=Xf("/");c===ca&&b(Error("Invalid parent."));for(a=a.split("/").reverse();a.length;){var d=a.pop();d&&(c.a.hasOwnProperty(d)||$f(c,d),c=c.a[d])}}function bg(a,c,d,e){!d&&!e&&b(Error("A device must have at least one callback defined."));var f={d:k,input:d,e:e};f.c=l;return Zf(a,c,f,Boolean(d),Boolean(e))}function Yf(){Wf||(Wf={v:k,write:k,c:k,d:l,timestamp:Date.now(),cb:1,a:{}})}function cg(){var a,c,d;function e(a){a===ca||10===a?(c.h(c.buffer.join("")),c.buffer=[]):c.buffer.push(String.fromCharCode(a))}qb(!dg,"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)");dg=k;Yf();a=a||Module.stdin;c=c||Module.stdout;d=d||Module.stderr;var f=k,g=k,h=k;a||(f=l,a=(function(){if(!a.j||!a.j.length){var c;"undefined"!=typeof window&&"function"==typeof window.prompt?c=window.prompt("Input: "):"function"==typeof readline&&(c=readline());c||(c="");a.j=uc(c+"\n",k)}return a.j.shift()}));c||(g=l,c=e);c.h||(c.h=print);c.buffer||(c.buffer=[]);d||(h=l,d=e);d.h||(d.h=print);d.buffer||(d.buffer=[]);$f("/","tmp");var i=$f("/","dev"),j=bg(i,"stdin",a),o=bg(i,"stdout",ca,c);d=bg(i,"stderr",ca,d);bg(i,"tty",a,c);Ke[1]={path:"/dev/stdin",object:j,position:0,f:k,g:l,r:l,m:!f,error:l,q:l,b:[]};Ke[2]={path:"/dev/stdout",object:o,position:0,f:l,g:k,r:l,m:!g,error:l,q:l,b:[]};Ke[3]={path:"/dev/stderr",object:d,position:0,f:l,g:k,r:l,m:!h,error:l,q:l,b:[]};Pf=F([1],"void*",E);Qf=F([2],"void*",E);Rf=F([3],"void*",E);ag();Ke[Pf]=Ke[1];Ke[Qf]=Ke[2];Ke[Rf]=Ke[3];ve=F([F([0,0,0,0,Pf,0,0,0,Qf,0,0,0,Rf,0,0,0],"void*",E)],"void*",E)}var dg,Wf;function eg(a,c,d,e){var f=Ke[a];if(!f||f.object.d){return W(Me),-1}if(f.f){if(f.object.c){return W(Mf),-1}if(0>d||0>e){return W(Ce),-1}for(a=0;f.b.length&&0<d;){n[c++]=f.b.pop(),d--,a++}for(var f=f.object.a,d=Math.min(f.length-e,d),g=0;g<d;g++){n[c+g]=f[e+g],a++}return a}W(Kf);return-1}function Qc(a,c,d){var e=Ke[a];if(e){if(e.f){if(0>d){return W(Ce),-1}if(e.object.d){if(e.object.input){for(a=0;e.b.length&&0<d;){n[c++]=e.b.pop(),d--,a++}for(var f=0;f<d;f++){try{var g=e.object.input()}catch(h){return W(Lf),-1}if(g===ca||g===aa){break}a++;n[c+f]=g}return a}W(Of);return-1}g=e.b.length;a=eg(a,c,d,e.position);-1!=a&&(e.position+=e.b.length-g+a);return a}W(Kf);return-1}W(Me);return-1}function Sc(a,c,d){var e=Ke[a];if(e){if(e.g){if(0>d){return W(Ce),-1}if(e.object.d){if(e.object.e){for(var f=0;f<d;f++){try{e.object.e(n[c+f])}catch(g){return W(Lf),-1}}e.object.timestamp=Date.now();return f}W(Of);return-1}f=e.position;a=Ke[a];if(!a||a.object.d){W(Me),c=-1}else{if(a.g){if(a.object.c){W(Mf),c=-1}else{if(0>d||0>f){W(Ce),c=-1}else{for(var h=a.object.a;h.length<f;){h.push(0)}for(var i=0;i<d;i++){h[f+i]=w[c+i]}a.object.timestamp=Date.now();c=i}}}else{W(Kf),c=-1}}-1!=c&&(e.position+=c);return c}W(Kf);return-1}W(Me);return-1}function Uc(a){yc(Bc);b("exit("+a+") called, at "+Error().stack)}function qd(a,c,d){if(20<=d&&c%2==a%2){if(c%4==a%4){for(d=c+d;c%4;){n[a++]=n[c++]}for(var c=c>>2,a=a>>2,e=d>>2;c<e;){p[a++]=p[c++]}c<<=2;for(a<<=2;c<d;){n[a++]=n[c++]}}else{d=c+d;c%2&&(n[a++]=n[c++]);c>>=1;a>>=1;for(e=d>>1;c<e;){Rb[a++]=Rb[c++]}c<<=1;a<<=1;c<d&&(n[a++]=n[c++])}}else{for(;d--;){n[a++]=n[c++]}}}function lg(){return!!lg.w}function vd(a,c,d){if(!mg){try{p[__ZTVN10__cxxabiv119__pointer_type_infoE>>2]=0}catch(e){}try{p[ng>>2]=1}catch(f){}try{p[og>>2]=2}catch(g){}mg=k}print("Compiled code throwing an exception, "+[a,c,d]+", at "+Error().stack);p[pg>>2]=a;p[pg+4>>2]=c;p[pg+8>>2]=d;"uncaught_exception"in lg?lg.w++:lg.w=1;b(a)}var mg;function zd(a,c,d){if(c<a&&a<c+d){c+=d;for(a+=d;d--;){a--,c--,n[a]=n[c]}}else{qd(a,c,d)}}function Se(a,c,d,e){c*=d;0!=c&&-1==Sc(e,a,c)&&Ke[e]&&(Ke[e].error=k)}function nf(a,c){function d(a){var d;"double"===a?d=(jc[0]=p[c+f>>2],jc[1]=p[c+f+4>>2],fc[0]):"i64"==a?d=[p[c+f>>2],p[c+f+4>>2]]:(a="i32",d=p[c+f>>2]);f+=Math.max(nb(a),ob);return d}for(var e=a,f=0,g=[],h,i;;){var j=e;h=n[e];if(0===h){break}i=n[e+1];if(37==h){var o=l,u=l,q=l,t=l;a:for(;;){switch(i){case 43:o=k;break;case 45:u=k;break;case 35:q=k;break;case 48:if(t){break a}else{t=k;break};default:break a}e++;i=n[e+1]}var s=0;if(42==i){s=d("i32"),e++,i=n[e+1]}else{for(;48<=i&&57>=i;){s=10*s+(i-48),e++,i=n[e+1]}}var B=l;if(46==i){var v=0,B=k;e++;i=n[e+1];if(42==i){v=d("i32"),e++}else{for(;;){i=n[e+1];if(48>i||57<i){break}v=10*v+(i-48);e++}}i=n[e+1]}else{v=6}var y;switch(String.fromCharCode(i)){case"h":i=n[e+2];104==i?(e++,y=1):y=2;break;case"l":i=n[e+2];108==i?(e++,y=8):y=4;break;case"L":case"q":case"j":y=8;break;case"z":case"t":case"I":y=4;break;default:y=ca}y&&e++;i=n[e+1];if(-1!="d,i,u,o,x,X,p".split(",").indexOf(String.fromCharCode(i))){j=100==i||105==i;y=y||4;h=d("i"+8*y);8==y&&(h=117==i?(h[0]>>>0)+4294967296*(h[1]>>>0):(h[0]>>>0)+4294967296*(h[1]|0));4>=y&&(h=(j?Gc:Fc)(h&Math.pow(256,y)-1,8*y));var A=Math.abs(h),r,j="";if(100==i||105==i){r=Gc(h,8*y).toString(10)}else{if(117==i){r=Fc(h,8*y).toString(10),h=Math.abs(h)}else{if(111==i){r=(q?"0":"")+A.toString(8)}else{if(120==i||88==i){j=q?"0x":"";if(0>h){h=-h;r=(A-1).toString(16);q=[];for(A=0;A<r.length;A++){q.push((15-parseInt(r[A],16)).toString(16))}for(r=q.join("");r.length<2*y;){r="f"+r}}else{r=A.toString(16)}88==i&&(j=j.toUpperCase(),r=r.toUpperCase())}else{112==i&&(0===A?r="(nil)":(j="0x",r=A.toString(16)))}}}}if(B){for(;r.length<v;){r="0"+r}}for(o&&(j=0>h?"-"+j:"+"+j);j.length+r.length<s;){u?r+=" ":t?r="0"+r:j=" "+j}r=j+r;r.split("").forEach((function(a){g.push(a.charCodeAt(0))}))}else{if(-1!="f,F,e,E,g,G".split(",").indexOf(String.fromCharCode(i))){h=d("double");if(isNaN(h)){r="nan",t=l}else{if(isFinite(h)){B=l;y=Math.min(v,20);if(103==i||71==i){B=k,v=v||1,y=parseInt(h.toExponential(y).split("e")[1],10),v>y&&-4<=y?(i=(103==i?"f":"F").charCodeAt(0),v-=y+1):(i=(103==i?"e":"E").charCodeAt(0),v--),y=Math.min(v,20)}if(101==i||69==i){r=h.toExponential(y),/[eE][-+]\d$/.test(r)&&(r=r.slice(0,-1)+"0"+r.slice(-1))}else{if(102==i||70==i){r=h.toFixed(y)}}j=r.split("e");if(B&&!q){for(;1<j[0].length&&-1!=j[0].indexOf(".")&&("0"==j[0].slice(-1)||"."==j[0].slice(-1));){j[0]=j[0].slice(0,-1)}}else{for(q&&-1==r.indexOf(".")&&(j[0]+=".");v>y++;){j[0]+="0"}}r=j[0]+(1<j.length?"e"+j[1]:"");69==i&&(r=r.toUpperCase());o&&0<=h&&(r="+"+r)}else{r=(0>h?"-":"")+"inf",t=l}}for(;r.length<s;){r=u?r+" ":t&&("-"==r[0]||"+"==r[0])?r[0]+"0"+r.slice(1):(t?"0":" ")+r}97>i&&(r=r.toUpperCase());r.split("").forEach((function(a){g.push(a.charCodeAt(0))}))}else{if(115==i){(o=d("i8*"))?(o=Ec(o),B&&o.length>v&&(o=o.slice(0,v))):o=uc("(null)",k);if(!u){for(;o.length<s--;){g.push(32)}}g=g.concat(o);if(u){for(;o.length<s--;){g.push(32)}}}else{if(99==i){for(u&&g.push(d("i8"));0<--s;){g.push(32)}u||g.push(d("i8"))}else{if(110==i){u=d("i32*"),p[u>>2]=g.length}else{if(37==i){g.push(h)}else{for(A=j;A<e+2;A++){g.push(n[A])}}}}}}}e+=2}else{g.push(h),e+=1}}return g}function ye(a,c,d){c=nf(c,d);d=m;Se(F(c,"i8",kc),1,c.length,a);m=d}var Ae={1:"Operation not permitted",2:"No such file or directory",3:"No such process",4:"Interrupted system call",5:"Input/output error",6:"No such device or address",8:"Exec format error",9:"Bad file descriptor",10:"No child processes",11:"Resource temporarily unavailable",12:"Cannot allocate memory",13:"Permission denied",14:"Bad address",16:"Device or resource busy",17:"File exists",18:"Invalid cross-device link",19:"No such device",20:"Not a directory",21:"Is a directory",22:"Invalid argument",23:"Too many open files in system",24:"Too many open files",25:"Inappropriate ioctl for device",26:"Text file busy",27:"File too large",28:"No space left on device",29:"Illegal seek",30:"Read-only file system",31:"Too many links",32:"Broken pipe",33:"Numerical argument out of domain",34:"Numerical result out of range",35:"Resource deadlock avoided",36:"File name too long",37:"No locks available",38:"Function not implemented",39:"Directory not empty",40:"Too many levels of symbolic links",42:"No message of desired type",43:"Identifier removed",60:"Device not a stream",61:"No data available",62:"Timer expired",63:"Out of streams resources",67:"Link has been severed",71:"Protocol error",72:"Multihop attempted",74:"Bad message",75:"Value too large for defined data type",84:"Invalid or incomplete multibyte or wide character",88:"Socket operation on non-socket",89:"Destination address required",90:"Message too long",91:"Protocol wrong type for socket",92:"Protocol not available",93:"Protocol not supported",95:"Operation not supported",97:"Address family not supported by protocol",98:"Address already in use",99:"Cannot assign requested address",100:"Network is down",101:"Network is unreachable",102:"Network dropped connection on reset",103:"Software caused connection abort",104:"Connection reset by peer",105:"No buffer space available",106:"Transport endpoint is already connected",107:"Transport endpoint is not connected",110:"Connection timed out",111:"Connection refused",113:"No route to host",114:"Operation already in progress",115:"Operation now in progress",116:"Stale NFS file handle",122:"Disk quota exceeded",125:"Operation canceled",130:"Owner died",131:"State not recoverable"},ze;function He(a){if(!Ke[a]){return W(Me),0}if(Ke[a].m){return 1}W(Nf);return 0}function oc(a,c,d){if(20<=d){for(d=a+d;a%4;){n[a++]=c}0>c&&(c+=256);for(var a=a>>2,e=d>>2,f=c|c<<8|c<<16|c<<24;a<e;){p[a++]=f}for(a<<=2;a<d;){n[a++]=c}}else{for(;d--;){n[a++]=c}}}function Ne(a,c){ye(p[Qf>>2],a,c)}var pf;function Z(){b("ABORT: undefined, at "+Error().stack)}function Ef(){switch(8){case 8:return qc;case 54:case 56:case 21:case 61:case 63:case 22:case 67:case 23:case 24:case 25:case 26:case 27:case 69:case 28:case 101:case 70:case 71:case 29:case 30:case 199:case 75:case 76:case 32:case 43:case 44:case 80:case 46:case 47:case 45:case 48:case 49:case 42:case 82:case 33:case 7:case 108:case 109:case 107:case 112:case 119:case 121:return 200809;case 13:case 104:case 94:case 95:case 34:case 35:case 77:case 81:case 83:case 84:case 85:case 86:case 87:case 88:case 89:case 90:case 91:case 94:case 95:case 110:case 111:case 113:case 114:case 115:case 116:case 117:case 118:case 120:case 40:case 16:case 79:case 19:return-1;case 92:case 93:case 5:case 72:case 6:case 74:case 92:case 93:case 96:case 97:case 98:case 99:case 102:case 103:case 105:return 1;case 38:case 66:case 50:case 51:case 4:return 1024;case 15:case 64:case 41:return 32;case 55:case 37:case 17:return 2147483647;case 18:case 1:return 47839;case 59:case 57:return 99;case 68:case 58:return 2048;case 0:return 2097152;case 3:return 65536;case 14:return 32768;case 73:return 32767;case 39:return 16384;case 60:return 1e3;case 106:return 700;case 52:return 256;case 62:return 255;case 2:return 100;case 65:return 64;case 36:return 20;case 100:return 16;case 20:return 6;case 53:return 4}W(Ce);return-1}function zf(a){qg||(Cb=Cb+4095>>12<<12,qg=k);var c=Cb;0!=a&&Bb(a);return c}var qg,Gf;function De(a){n[rg]=Fc(10);-1==Sc(a,rg,1)&&a in Ke&&(Ke[a].error=k)}function Oe(a){var c=p[Qf>>2];0>Sc(c,a,Dc(a))||De(c)}W(0);Ac.unshift({l:(function(){Tf=l;dg||cg()})});Bc.push({l:(function(){dg&&(Ke[2]&&0<Ke[2].object.e.buffer.length&&Ke[2].object.e(10),Ke[3]&&0<Ke[3].object.e.buffer.length&&Ke[3].object.e(10))})});var pg=F(12,"void*",E),rg=F([0],"i8",E);Module.ab=(function(a){function c(){for(var a=0;3>a;a++){e.push(0)}}var d=a.length+1,e=[F(uc("/bin/this.program"),"i8",E)];c();for(var f=0;f<d-1;f+=1){e.push(F(uc(a[f]),"i8",E)),c()}e.push(0);e=F(e,"i32",E);return Fe(d,e)});var Kc,Ac=Ac.concat([{l:(function(){for(var a=0;;){var c=a>>>1,c=0==(a&1|0)?c:c^-306674912,d=c>>>1,c=0==(c&1|0)?d:d^-306674912,d=c>>>1,c=0==(c&1|0)?d:d^-306674912,d=c>>>1,c=0==(c&1|0)?d:d^-306674912,d=c>>>1,c=0==(c&1|0)?d:d^-306674912,d=c>>>1,c=0==(c&1|0)?d:d^-306674912,d=c>>>1,c=0==(c&1|0)?d:d^-306674912,d=c>>>1;p[Kc+(a<<2)>>2]=0==(c&1|0)?d:d^-306674912;a=a+1|0;if(256==(a|0)){break}}})}]),V,ue,wd,xe,Ee,Ge,Xe,Ye,We,rf,sg,ng,og,tg,X,wf,Hf,If,Jf;Kc=F(1024,"i32",E);K.L=F([82,97,110,103,101,32,100,101,99,111,100,101,114,32,102,105,110,97,108,32,99,111,100,101,32,105,115,32,110,111,116,32,122,101,114,111,0],"i8",E);K.K=F([7,7,7,7,7,7,7,10,10,10,10,10],"i8",E);K.I=F([8,8,8,8,8,8,8,11,11,11,11,11],"i8",E);K.H=F([9,9,9,9,9,9,9,11,11,11,11,11],"i8",E);K.J=F([0,0,0,0,1,2,3,4,5,6,4,5],"i8",E);V=F(4096,"i8",E);ue=F(2048,"i32",E);K.A=F([53,69,114,114,111,114,0],"i8",E);wd=F(8,"*",E);K.O=F([112,111,115,32,62,32,115,116,114,101,97,109,95,112,111,115,32,105,110,32,77,97,116,99,104,102,105,110,100,101,114,58,58,109,111,118,101,95,112,111,115,0],"i8",E);K.W=F([87,114,105,116,101,32,101,114,114,111,114,0],"i8",E);K.ea=F([82,101,97,100,32,101,114,114,111,114,0],"i8",E);xe=F(1,"i32",E);K.sa=F([37,115,58,32,37,115,0],"i8",E);K.S=F([58,32,37,115,0],"i8",E);Ee=F(1,"i8*",E);K.na=F([84,114,121,32,96,37,115,32,45,45,104,101,108,112,39,32,102,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,46,10,0],"i8",E);K.oa=F([37,115,58,32,105,110,116,101,114,110,97,108,32,101,114,114,111,114,58,32,37,115,46,10,0],"i8",E);K.ta=F([117,110,99,97,117,103,104,116,32,111,112,116,105,111,110,0],"i8",E);Ge=F(1,"i1",E);K.ua=F([67,97,110,39,116,32,99,108,111,115,101,32,115,116,100,111,117,116,0],"i8",E);K.wa=F([69,114,114,111,114,32,114,101,97,100,105,110,103,32,109,101,109,98,101,114,32,104,101,97,100,101,114,0],"i8",E);K.xa=F([66,97,100,32,109,97,103,105,99,32,110,117,109,98,101,114,32,40,102,105,108,101,32,110,111,116,32,105,110,32,108,122,105,112,32,102,111,114,109,97,116,41,0],"i8",E);K.M=F([86,101,114,115,105,111,110,32,37,100,32,109,101,109,98,101,114,32,102,111,114,109,97,116,32,110,111,116,32,115,117,112,112,111,114,116,101,100,46,10,0],"i8",E);K.N=F([73,110,118,97,108,105,100,32,100,105,99,116,105,111,110,97,114,121,32,115,105,122,101,32,105,110,32,109,101,109,98,101,114,32,104,101,97,100,101,114,0],"i8",E);K.P=F([118,101,114,115,105,111,110,32,37,100,44,32,100,105,99,116,105,111,110,97,114,121,32,115,105,122,101,32,37,55,115,66,46,32,32,0],"i8",E);K.Q=F([70,105,108,101,32,101,110,100,115,32,117,110,101,120,112,101,99,116,101,100,108,121,32,97,116,32,112,111,115,32,37,108,108,100,10,0],"i8",E);K.R=F([68,101,99,111,100,101,114,32,101,114,114,111,114,32,97,116,32,112,111,115,32,37,108,108,100,10,0],"i8",E);K.n=F([111,107,10,0],"i8",E);K.o=F([100,111,110,101,10,0],"i8",E);Xe=F(32,"*",E);K.T=F([75,105,0],"i8",E);K.U=F([77,105,0],"i8",E);K.V=F([71,105,0],"i8",E);K.Y=F([84,105,0],"i8",E);K.Z=F([69,105,0],"i8",E);K.$=F([90,105,0],"i8",E);K.aa=F([89,105,0],"i8",E);Ye=F(16,"i8",E);We=F(1,"i8",E);K.ba=F([37,108,108,100,32,37,115,0],"i8",E);K.z=F([76,90,73,80],"i8",E);K.ca=F([105,110,118,97,108,105,100,32,97,114,103,117,109,101,110,116,32,116,111,32,101,110,99,111,100,101,114,0],"i8",E);K.da=F([69,110,99,111,100,101,114,32,101,114,114,111,114,0],"i8",E);K.fa=F([78,111,32,100,97,116,97,32,99,111,109,112,114,101,115,115,101,100,46,10,0],"i8",E);K.ga=F([37,54,46,51,102,58,49,44,32,37,54,46,51,102,32,98,105,116,115,47,98,121,116,101,44,32,37,53,46,50,102,37,37,32,115,97,118,101,100,44,32,37,108,108,100,32,105,110,44,32,37,108,108,100,32,111,117,116,46,10,0],"i8",E);K.ha=F([73,32,119,111,110,39,116,32,119,114,105,116,101,32,99,111,109,112,114,101,115,115,101,100,32,100,97,116,97,32,116,111,32,97,32,116,101,114,109,105,110,97,108,46,0],"i8",E);K.ia=F([73,32,119,111,110,39,116,32,114,101,97,100,32,99,111,109,112,114,101,115,115,101,100,32,100,97,116,97,32,102,114,111,109,32,97,32,116,101,114,109,105,110,97,108,46,0],"i8",E);K.ja=F([37,115,32,37,115,10,0],"i8",E);K.ka=F([49,46,49,50,0],"i8",E);K.la=F([67,111,112,121,114,105,103,104,116,32,40,67,41,32,37,115,32,65,110,116,111,110,105,111,32,68,105,97,122,32,68,105,97,122,46,10,0],"i8",E);K.pa=F([50,48,49,49,0],"i8",E);K.p=F([76,122,105,112,0],"i8",E);K.qa=F([37,115,32,45,32,68,97,116,97,32,99,111,109,112,114,101,115,115,111,114,32,98,97,115,101,100,32,111,110,32,116,104,101,32,76,90,77,65,32,97,108,103,111,114,105,116,104,109,46,10,0],"i8",E);K.ra=F([10,85,115,97,103,101,58,32,37,115,32,91,111,112,116,105,111,110,115,93,32,91,102,105,108,101,115,93,10,0],"i8",E);K.va=F([73,102,32,110,111,32,102,105,108,101,32,110,97,109,101,115,32,97,114,101,32,103,105,118,101,110,44,32,37,115,32,99,111,109,112,114,101,115,115,101,115,32,111,114,32,100,101,99,111,109,112,114,101,115,115,101,115,10,0],"i8",E);K.i=F([108,122,105,112,0],"i8",E);K.B=F([78,49,48,95,95,99,120,120,97,98,105,118,49,49,54,95,95,115,104,105,109,95,116,121,112,101,95,105,110,102,111,69,0],"i8",E);rf=F(12,"*",E);K.C=F([78,49,48,95,95,99,120,120,97,98,105,118,49,49,55,95,95,99,108,97,115,115,95,116,121,112,101,95,105,110,102,111,69,0],"i8",E);sg=F(12,"*",E);ng=F([0,0,0,0,0,0,0,0,4,0,0,0,6,0,0,0,8,0,0,0,10,0,0,0,12,0,0,0,14,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],E);F(1,"void*",E);K.F=F([80,105,0],"i8",E);og=F([0,0,0,0,0,0,0,0,4,0,0,0,16,0,0,0,8,0,0,0,18,0,0,0,20,0,0,0,22,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],E);F(1,"void*",E);K.D=F([78,49,48,95,95,99,120,120,97,98,105,118,49,50,48,95,95,115,105,95,99,108,97,115,115,95,116,121,112,101,95,105,110,102,111,69,0],"i8",E);tg=F(12,"*",E);X=F(468,["i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"*",0,0,0,"i32",0,0,0,"*",0,0,0,"i32",0,0,0,"*",0,0,0,"i32",0,0,0],E);wf=F(24,"i32",E);Hf=F(1,"void ()*",E);If=F([0,0,0,0,0,0,0,0,2,0,0,0,24,0,0,0,26,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],E);F(1,"void*",E);K.ma=F([115,116,100,58,58,98,97,100,95,97,108,108,111,99,0],"i8",E);K.G=F([83,116,57,98,97,100,95,97,108,108,111,99,0],"i8",E);Jf=F(12,"*",E);K.ya=F([60,60,32,77,111,115,116,32,111,102,32,116,104,101,115,101,32,97,114,101,32,117,110,115,117,112,112,111,114,116,101,100,46,32,67,111,109,112,114,101,115,115,105,110,103,47,100,101,99,111,109,112,114,101,115,115,105,110,103,32,102,114,111,109,32,115,116,100,105,110,32,116,111,32,115,116,100,111,117,116,32,105,115,32,116,104,101,32,114,105,103,104,116,32,119,97,121,33,32,62,62,0],"i8",E);K.za=F([10,79,112,116,105,111,110,115,58,0],"i8",E);K.Ka=F([32,32,45,104,44,32,45,45,104,101,108,112,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,100,105,115,112,108,97,121,32,116,104,105,115,32,104,101,108,112,32,97,110,100,32,101,120,105,116,0],"i8",E);K.Ta=F([32,32,45,86,44,32,45,45,118,101,114,115,105,111,110,32,32,32,32,32,32,32,32,32,32,32,32,32,32,111,117,116,112,117,116,32,118,101,114,115,105,111,110,32,105,110,102,111,114,109,97,116,105,111,110,32,97,110,100,32,101,120,105,116,0],"i8",E);K.Ua=F([32,32,45,98,44,32,45,45,109,101,109,98,101,114,45,115,105,122,101,61,60,110,62,32,32,32,32,32,32,115,101,116,32,109,101,109,98,101,114,32,115,105,122,101,32,108,105,109,105,116,32,105,110,32,98,121,116,101,115,0],"i8",E);K.Va=F([32,32,45,99,44,32,45,45,115,116,100,111,117,116,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,115,101,110,100,32,111,117,116,112,117,116,32,116,111,32,115,116,97,110,100,97,114,100,32,111,117,116,112,117,116,0],"i8",E);K.Wa=F([32,32,45,100,44,32,45,45,100,101,99,111,109,112,114,101,115,115,32,32,32,32,32,32,32,32,32,32,32,100,101,99,111,109,112,114,101,115,115,0],"i8",E);K.Xa=F([32,32,45,102,44,32,45,45,102,111,114,99,101,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,111,118,101,114,119,114,105,116,101,32,101,120,105,115,116,105,110,103,32,111,117,116,112,117,116,32,102,105,108,101,115,0],"i8",E);K.Ya=F([32,32,45,70,44,32,45,45,114,101,99,111,109,112,114,101,115,115,32,32,32,32,32,32,32,32,32,32,32,102,111,114,99,101,32,114,101,99,111,109,112,114,101,115,115,105,111,110,32,111,102,32,99,111,109,112,114,101,115,115,101,100,32,102,105,108,101,115,0],"i8",E);K.Za=F([32,32,45,107,44,32,45,45,107,101,101,112,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,107,101,101,112,32,40,100,111,110,39,116,32,100,101,108,101,116,101,41,32,105,110,112,117,116,32,102,105,108,101,115,0],"i8",E);K.Aa=F([32,32,45,109,44,32,45,45,109,97,116,99,104,45,108,101,110,103,116,104,61,60,110,62,32,32,32,32,32,115,101,116,32,109,97,116,99,104,32,108,101,110,103,116,104,32,108,105,109,105,116,32,105,110,32,98,121,116,101,115,32,91,51,54,93,0],"i8",E);K.Ba=F([32,32,45,111,44,32,45,45,111,117,116,112,117,116,61,60,102,105,108,101,62,32,32,32,32,32,32,32,32,105,102,32,114,101,97,100,105,110,103,32,115,116,100,105,110,44,32,112,108,97,99,101,32,116,104,101,32,111,117,116,112,117,116,32,105,110,116,111,32,60,102,105,108,101,62,0],"i8",E);K.Ca=F([32,32,45,113,44,32,45,45,113,117,105,101,116,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,115,117,112,112,114,101,115,115,32,97,108,108,32,109,101,115,115,97,103,101,115,0],"i8",E);K.Da=F([32,32,45,115,44,32,45,45,100,105,99,116,105,111,110,97,114,121,45,115,105,122,101,61,60,110,62,32,32,115,101,116,32,100,105,99,116,105,111,110,97,114,121,32,115,105,122,101,32,108,105,109,105,116,32,105,110,32,98,121,116,101,115,32,91,56,77,105,66,93,0],"i8",E);K.Ea=F([32,32,45,83,44,32,45,45,118,111,108,117,109,101,45,115,105,122,101,61,60,110,62,32,32,32,32,32,32,115,101,116,32,118,111,108,117,109,101,32,115,105,122,101,32,108,105,109,105,116,32,105,110,32,98,121,116,101,115,0],"i8",E);K.Fa=F([32,32,45,116,44,32,45,45,116,101,115,116,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,116,101,115,116,32,99,111,109,112,114,101,115,115,101,100,32,102,105,108,101,32,105,110,116,101,103,114,105,116,121,0],"i8",E);K.Ga=F([32,32,45,118,44,32,45,45,118,101,114,98,111,115,101,32,32,32,32,32,32,32,32,32,32,32,32,32,32,98,101,32,118,101,114,98,111,115,101,32,40,97,32,50,110,100,32,45,118,32,103,105,118,101,115,32,109,111,114,101,41,0],"i8",E);K.Ha=F([32,32,45,48,32,46,46,32,45,57,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,115,101,116,32,99,111,109,112,114,101,115,115,105,111,110,32,108,101,118,101,108,32,91,100,101,102,97,117,108,116,32,54,93,0],"i8",E);K.Ia=F([32,32,32,32,32,32,45,45,102,97,115,116,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,97,108,105,97,115,32,102,111,114,32,45,48,0],"i8",E);K.Ja=F([32,32,32,32,32,32,45,45,98,101,115,116,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,97,108,105,97,115,32,102,111,114,32,45,57,0],"i8",E);K.La=F([102,114,111,109,32,115,116,97,110,100,97,114,100,32,105,110,112,117,116,32,116,111,32,115,116,97,110,100,97,114,100,32,111,117,116,112,117,116,46,0],"i8",E);K.Ma=F([78,117,109,98,101,114,115,32,109,97,121,32,98,101,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,109,117,108,116,105,112,108,105,101,114,58,32,107,32,61,32,107,66,32,61,32,49,48,94,51,32,61,32,49,48,48,48,44,0],"i8",E);K.Na=F([75,105,32,61,32,75,105,66,32,61,32,50,94,49,48,32,61,32,49,48,50,52,44,32,77,32,61,32,49,48,94,54,44,32,77,105,32,61,32,50,94,50,48,44,32,71,32,61,32,49,48,94,57,44,32,71,105,32,61,32,50,94,51,48,44,32,101,116,99,46,46,46,0],"i8",E);K.Oa=F([10,82,101,112,111,114,116,32,98,117,103,115,32,116,111,32,108,122,105,112,45,98,117,103,64,110,111,110,103,110,117,46,111,114,103,0],"i8",E);K.Pa=F([76,122,105,112,32,104,111,109,101,32,112,97,103,101,58,32,104,116,116,112,58,47,47,119,119,119,46,110,111,110,103,110,117,46,111,114,103,47,108,122,105,112,47,108,122,105,112,46,104,116,109,108,0],"i8",E);K.Qa=F([76,105,99,101,110,115,101,32,71,80,76,118,51,43,58,32,71,78,85,32,71,80,76,32,118,101,114,115,105,111,110,32,51,32,111,114,32,108,97,116,101,114,32,60,104,116,116,112,58,47,47,103,110,117,46,111,114,103,47,108,105,99,101,110,115,101,115,47,103,112,108,46,104,116,109,108,62,0],"i8",E);K.Ra=F([84,104,105,115,32,105,115,32,102,114,101,101,32,115,111,102,116,119,97,114,101,58,32,121,111,117,32,97,114,101,32,102,114,101,101,32,116,111,32,99,104,97,110,103,101,32,97,110,100,32,114,101,100,105,115,116,114,105,98,117,116,101,32,105,116,46,0],"i8",E);K.Sa=F([84,104,101,114,101,32,105,115,32,78,79,32,87,65,82,82,65,78,84,89,44,32,116,111,32,116,104,101,32,101,120,116,101,110,116,32,112,101,114,109,105,116,116,101,100,32,98,121,32,108,97,119,46,0],"i8",E);p[wd>>2]=ng+8|0;p[wd+4>>2]=K.A|0;p[Xe>>2]=K.T|0;p[Xe+4>>2]=K.U|0;p[Xe+8>>2]=K.V|0;p[Xe+12>>2]=K.Y|0;p[Xe+16>>2]=K.F|0;p[Xe+20>>2]=K.Z|0;p[Xe+24>>2]=K.$|0;p[Xe+28>>2]=K.aa|0;p[rf>>2]=og+8|0;p[rf+4>>2]=K.B|0;p[rf+8>>2]=aa;p[sg>>2]=og+8|0;p[sg+4>>2]=K.C|0;p[sg+8>>2]=rf;p[ng+4>>2]=sg;p[og+4>>2]=tg;p[tg>>2]=og+8|0;p[tg+4>>2]=K.D|0;p[tg+8>>2]=sg;p[If+4>>2]=Jf;p[Jf>>2]=og+8|0;p[Jf+4>>2]=K.G|0;p[Jf+8>>2]=aa;pc=[0,0,Ff,0,of,0,(function(a){of(a|0);Re(a)}),0,(function(a,c,d){var e,f=m;m+=56;e=f>>2;if((a|0)==(c|0)){a=1}else{if(0==(c|0)){a=0}else{if(c=qf(c,sg),0==(c|0)){a=0}else{for(var g=f>>2,h=g+14;g<h;g++){p[g]=0}p[e]=c;p[e+2]=a;p[e+3]=-1;p[e+12]=1;pc[p[p[c>>2]+20>>2]](c,f,p[d>>2],1);1!=(p[e+6]|0)?a=0:(p[d>>2]=p[e+4],a=1)}}}m=f;return a}),0,(function(a,c,d,e,f){(p[c+8>>2]|0)==(a|0)&&Ue(c,d,e,f)}),0,(function(a,c,d,e){var f=c>>2,g=(p[f+2]|0)==(a|0);a:do{if(g){Ve(c,d,e)}else{if((p[f]|0)==(a|0)){var h=(p[f+4]|0)==(d|0);do{if(!h){var i=c+20|0;if((p[i>>2]|0)!=(d|0)){p[f+8]=e;p[i>>2]=d;a=c+40|0;p[a>>2]=p[a>>2]+1|0;1==(p[f+9]|0)&&2==(p[f+6]|0)&&(n[c+54|0]=1);p[f+11]=4;break a}}}while(0);1==(e|0)&&(p[f+8]=1)}}}while(0)}),0,(function(a,c,d,e){(p[c+8>>2]|0)==(a|0)&&Te(c,d,e)}),0,(function(a){of(a|0);Re(a)}),0,(function(a,c,d,e,f){(a|0)==(p[c+8>>2]|0)?Ue(c,d,e,f):(a=p[a+8>>2],pc[p[p[a>>2]+12>>2]](a,c,d,e,f))}),0,sf,0,(function(a,c,d,e){(a|0)==(p[c+8>>2]|0)?Te(c,d,e):(a=p[a+8>>2],pc[p[p[a>>2]+20>>2]](a,c,d,e))}),0,(function(a){Ff(a);Re(a)}),0,(function(){return K.ma|0}),0];Module.FUNCTION_TABLE=pc;function ug(a){a=a||Module.arguments;yc(Ac);var c=ca;Module._main&&(c=Module.ab(a),Module.noExitRuntime||yc(Bc));return c}Module.run=ug;Module.preRun&&Module.preRun();ug();Module.postRun&&Module.postRun() + + return returnValue; + }, + + compress: function(data) { + return this.run(data); + }, + + decompress: function(data) { + return this.run(data, true); + } +}; + diff --git a/third_party/lzma.js/native_test.sh b/third_party/lzma.js/native_test.sh new file mode 100755 index 00000000..63652340 --- /dev/null +++ b/third_party/lzma.js/native_test.sh @@ -0,0 +1,5 @@ +./lzma-native < lzma-native > lzma-native.lz +./lzma-native -d < lzma-native.lz > lzma-native.post +ls -al lzma-native* +diff lzma-native lzma-native.post + diff --git a/third_party/lzma.js/post.js b/third_party/lzma.js/post.js new file mode 100644 index 00000000..c000e810 --- /dev/null +++ b/third_party/lzma.js/post.js @@ -0,0 +1,13 @@ + + return returnValue; + }, + + compress: function(data) { + return this.run(data); + }, + + decompress: function(data) { + return this.run(data, true); + } +}; + diff --git a/third_party/lzma.js/pre.js b/third_party/lzma.js/pre.js new file mode 100644 index 00000000..c2ec08c6 --- /dev/null +++ b/third_party/lzma.js/pre.js @@ -0,0 +1,13 @@ + +// This is lzma.js, powered by lzip (which is GPL, source code at https://github.com/kripken/lzma.js) +var LZMA = { + run: function(data, decompress) { + var inputIndex = 0; + var returnValue = []; + var Module = { + arguments: ['-q'].concat(decompress ? ['-d'] : []), + stdin: function() { return inputIndex < data.length ? data[inputIndex++] : null }, + stdout: function(x) { if (x !== null) returnValue.push(x) } + }; + + diff --git a/third_party/lzma.js/test-decoder.js b/third_party/lzma.js/test-decoder.js new file mode 100644 index 00000000..4860c3de --- /dev/null +++ b/third_party/lzma.js/test-decoder.js @@ -0,0 +1,39 @@ +// js -m -n -e "load('lzma-decoder.js')" test-decoder.js + +function assertEq(a, b) { + if (a !== b) { + throw 'Should have been equal: ' + a + ' : ' + b; + } + return false; +} + +function assertNeq(a, b) { + try { + assertEq(a, b); + } catch(e) { + return; + } + throw 'Should have not been equal: ' + a + ' : ' + b; +} + +function byteCompare(a, b) { + assertEq(JSON.stringify(new Uint8Array(a)), JSON.stringify(new Uint8Array(b))); +} + +function testSimple() { + print('testing simple..'); + var data = [100, 200, 200, 200, 200, 200, 200, 100, 100, 200, 200, 200, 200, 0, 1]; + var compressed = [76,90,73,80,1,12,0,50,50,28,-1,-1,-1,-1,-16,0,0,0,-34,-10,-9,-43,2,0,0,0,0,0,0,0,38,0,0,0,0,0, + 0,0,76,90,73,80,1,12,0,100,105,61,-1,-1,-1,-1,-32,0,0,0,-46,66,-98,-91,5,0,0,0,0,0,0,0,38, + 0,0,0,0,0,0,0,76,90,73,80,1,12,0,50,100,27,-1,-1,-1,-2,0,0,0,29,25,-105,10,2,0,0,0,0,0,0,0, + 37,0,0,0,0,0,0,0,76,90,73,80,1,12,0,100,104,-67,-1,-1,-1,-1,-32,0,0,0,-55,-55,-99,-101,4,0,0,0, + 0,0,0,0,38,0,0,0,0,0,0,0,76,90,73,80,1,12,0,0,0,121,-128,-83,-1,-1,-20,-57,0,0,105,34,-34,54,2, + 0,0,0,0,0,0,0,38,0,0,0,0,0,0,0]; + var decompressed = LZMA.decompress(compressed); + byteCompare(data, decompressed); +} + +testSimple(); + +print('ok.'); + diff --git a/third_party/lzma.js/test-full.html b/third_party/lzma.js/test-full.html new file mode 100644 index 00000000..64d2be60 --- /dev/null +++ b/third_party/lzma.js/test-full.html @@ -0,0 +1,9 @@ +<body> +<script> + var print = function(x) { console.log(x) }; +</script> +<script src="lzma-full.js"></script> +<script src="test-full.js"></script> +See web console.. +</body> + diff --git a/third_party/lzma.js/test-full.js b/third_party/lzma.js/test-full.js new file mode 100644 index 00000000..c31e6e3a --- /dev/null +++ b/third_party/lzma.js/test-full.js @@ -0,0 +1,78 @@ +// js -m -n -e "load('lzma-full.js')" test-full.js + +function assertEq(a, b) { + if (a !== b) { + throw 'Should have been equal: ' + a + ' : ' + b; + } + return false; +} + +function assertNeq(a, b) { + try { + assertEq(a, b); + } catch(e) { + return; + } + throw 'Should have not been equal: ' + a + ' : ' + b; +} + +function byteCompare(a, b) { + assertEq(a.length, b.length); + for (var i = 0; i < a.length; i++) { + assertEq(a[i]&255, b[i]&255); + } +} + +function testSimple() { + print('testing simple..'); + var data = [100, 200, 200, 200, 200, 200, 200, 100, 100, 200, 200, 200, 200, 0, 1]; + var compressed = LZMA.compress(data); + var decompressed = LZMA.decompress(compressed); + + byteCompare(data, decompressed); + assertNeq(data.length, compressed.length); +} + +function testBig() { + print('testing big..'); + var seed1 = 100; + var seed2 = 200; + var last = 255; + function fakeRandom() { + // numbers from http://triptico.com/docs/sp_random.html + seed1 = ((seed1 * 58321) + 11113) | 0; + var ret = (seed1 >> 16) & 255; + seed2 = ((seed2 * 58321) + 11113) | 0; + if (seed2 % 5) { + return last; + } + last = ret; + return last; + } + print(' ..generating data..'); + var size = 1*1024*1024; + var data = new Array(size); + for (var i = 0; i < size; i++) { + data[i] = fakeRandom(); + } + + print(' ..compressing ' + data.length + ' bytes..'); + var t = Date.now(); + var compressed = LZMA.compress(data); + print(' ..took ' + ((Date.now() - t)/1000).toFixed(2) + ' secs'); + print(' ..decompressing ' + compressed.length + ' bytes..'); + t = Date.now(); + var decompressed = LZMA.decompress(compressed); + print(' ..took ' + ((Date.now() - t)/1000).toFixed(2) + ' secs'); + print(' ..got ' + decompressed.length + ' bytes..'); + + byteCompare(data, decompressed); + assertNeq(data.length, compressed.length); + print(' ..decompressed == original'); +} + +testSimple(); +testBig(); + +print('ok.'); + diff --git a/tools/autodebugger.py b/tools/autodebugger.py index 65ddc641..943ff043 100644 --- a/tools/autodebugger.py +++ b/tools/autodebugger.py @@ -11,17 +11,21 @@ Warning: You probably want to compile with SKIP_STACK_IN_SMALL=0! Otherwise import os, sys, re ALLOW_POINTERS = False +ALLOW_MISC = True MEMCPY = False POSTAMBLE = ''' @.emscripten.autodebug.str = private constant [10 x i8] c"AD:%d,%d\\0A\\00", align 1 ; [#uses=1] @.emscripten.autodebug.str.f = private constant [11 x i8] c"AD:%d,%lf\\0A\\00", align 1 ; [#uses=1] +@.emscripten.autodebug.str.64 = private constant [13 x i8] c"AD:%d,%d,%d\\0A\\00", align 1 ; [#uses=1] ; [#uses=1] define void @emscripten_autodebug_i64(i32 %line, i64 %value) { entry: - %0 = sitofp i64 %value to double ; [#uses=1] - %1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([11 x i8]* @.emscripten.autodebug.str.f, i32 0, i32 0), i32 %line, double %0) ; [#uses=0] + %0 = trunc i64 %value to i32 + %1 = lshr i64 %value, 32 + %2 = trunc i64 %1 to i32 + %3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([13 x i8]* @.emscripten.autodebug.str.64, i32 0, i32 0), i32 %line, i32 %0, i32 %2) ; [#uses=0] br label %return return: ; preds = %entry @@ -239,6 +243,23 @@ for i in range(len(lines)): index = i+1+lines_added lines[i] += '\n call void @emscripten_autodebug_%s(i32 %d, %s %%%s)' % (m.group('type'), index, m.group('type'), m.group('var')) lines_added += 1 + continue + if ALLOW_MISC: + m = re.match(' %(?P<var>[\w_.]+) = (call|mul|add) (nsw )?(?P<type>i64|i32|i16|i8|float|double+) .*', lines[i]) + if m: + index = i+1+lines_added + lines[i] += '\n call void @emscripten_autodebug_%s(i32 %d, %s %%%s)' % (m.group('type'), index, m.group('type'), m.group('var')) + lines_added += 1 + continue + m = re.match(' call void @llvm\.memcpy\.p0i8\.p0i8\.i32\(i8\* %(?P<dst>[\w_.]+), i8\* %(?P<src>[\w_.]+), i32 8, i32 (?P<align>\d+),.*', lines[i]) + if m: + index = i+1+lines_added + lines[i] += '\n %%adpretemp%d = bitcast i8* %%%s to i64*' % (index, m.group('src')) + \ + '\n %%adtemp%d = load i64* %%adpretemp%d, align %s' % (index, index, m.group('align')) + \ + '\n call void @emscripten_autodebug_%s(i32 %d, %s %%adtemp%d)' % ('i64', index, 'i64', index) + lines_added += 3 + continue + finally: if len(pre) > 0: lines[i] = pre + '\n' + lines[i] diff --git a/tools/bindings_generator.py b/tools/bindings_generator.py index 4731abf3..3fbff13d 100755 --- a/tools/bindings_generator.py +++ b/tools/bindings_generator.py @@ -42,8 +42,26 @@ bindings, and to prevent DFE from removing the code we care about. The JS bindings do more serious work, creating class structures in JS and linking them to the C bindings. -NOTE: ammo.js is currently the biggest consumer of this code. For some - more docs you can see that project's README +Notes: + * ammo.js is currently the biggest consumer of this code. For some + more docs you can see that project's README, + + https://github.com/kripken/ammo.js + + Another project using these bindings is box2d.js, + + https://github.com/kripken/box2d.js + + * Functions implemented inline in classes may not be actually + compiled into bitcode, unless they are actually used. That may + confuse the bindings generator. + + * C strings (char *) passed to functions are treated in a special way. + If you pass in a pointer, it is assumed to be a pointer and left as + is. Otherwise it must be a JS string, and we convert it to a C + string on the *stack*. The C string will live for the current + function call. If you need it for longer, you need to create a copy + in your C++ code. ''' import os, sys, glob, re @@ -507,6 +525,12 @@ function customizeVTable(object, replacementPairs) { return object; } Module['customizeVTable'] = customizeVTable; + +// Converts a value into a C-style string. +function ensureString(value) { + if (typeof value == 'number') return value; + return allocate(intArrayFromString(value), 'i8', ALLOC_STACK); +} ''') def generate_wrapping_code(classname): @@ -645,17 +669,25 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge #print 'zz types:', map(lambda arg: arg['type'], args) + has_string_convs = False + # We can assume that NULL is passed for null pointers, so object arguments can always # have .ptr done on them - def justargs_fixed(args): - ret = justargs(args)[:] - for i in range(len(args)): - arg = args[i] - if clean_type(arg['type']) in classes: - ret[i] += '.ptr' - return ret + justargs_fixed = justargs(args)[:] + for i in range(len(args)): + arg = args[i] + clean = clean_type(arg['type']) + if clean in classes: + justargs_fixed[i] += '.ptr' + elif arg['type'].replace(' ', '').endswith('char*'): + justargs_fixed[i] = 'ensureString(' + justargs_fixed[i] + ')' + has_string_convs = True calls = '' + if has_string_convs: + calls += 'var stack = Runtime.stackSave();\n'; + calls += 'try {\n' + #print 'js loopin', params, '|', len(args)#, args for args in params: i = len(args) @@ -667,12 +699,12 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge if constructor: if not dupe: calls += '''this.ptr = _%s_p%d(%s); -''' % (fullname, i, ', '.join(justargs_fixed(args)[:i])) +''' % (fullname, i, ', '.join(justargs_fixed[:i])) else: calls += '''this.ptr = _%s_p%d(%s); -''' % (fullname, i, ', '.join(justargs_fixed(args)[:i])) +''' % (fullname, i, ', '.join(justargs_fixed[:i])) else: - return_value = '''_%s_p%d(%s)''' % (fullname, i, ', '.join((['this.ptr'] if need_self else []) + justargs_fixed(args)[:i])) + return_value = '''_%s_p%d(%s)''' % (fullname, i, ', '.join((['this.ptr'] if need_self else []) + justargs_fixed[:i])) print 'zz making return', classname, method['name'], method['returns'], return_value if method['returns'] in classes: # Generate a wrapper @@ -682,6 +714,9 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge calls += ('return ' if ret != 'void' else '') + return_value + ';' calls += '\n' + if has_string_convs: + calls += '} finally { Runtime.stackRestore(stack) }\n'; + print 'Maekin:', classname, generating_classname, mname, mname_suffixed if constructor: calls += ''' diff --git a/tools/clean_webconsole.py b/tools/clean_webconsole.py new file mode 100644 index 00000000..56bd9e2b --- /dev/null +++ b/tools/clean_webconsole.py @@ -0,0 +1,17 @@ +''' +Removes timestamp and line info from a webgl log +''' + +import os, sys + +lines = sys.stdin.read().split('\n') + +for line in lines: + if line.startswith('['): + line = line[15:] + line = line.split(' @ ')[0] + print line + +for i in range(100): + print + diff --git a/tools/eliminator/eliminator.coffee b/tools/eliminator/eliminator.coffee index ba91aa89..a4c98930 100644 --- a/tools/eliminator/eliminator.coffee +++ b/tools/eliminator/eliminator.coffee @@ -19,6 +19,7 @@ # Imports. uglify = require 'uglify-js' fs = require 'fs' +os = require 'os' # Functions which have been generated by Emscripten. We optimize only those. generatedFunctions = [] @@ -369,7 +370,14 @@ class ExpressionOptimizer # function, then writes the optimized result to stdout. main = -> # Get the parse tree. - src = fs.readFileSync('/dev/stdin').toString() + if os.platform().substr(0, 3) != 'win' + src = fs.readFileSync('/dev/stdin').toString() + else + # The following seems to work on windows, but fails on linux.. + src = '' + size = fs.fstatSync(process.stdin.fd).size + if size > 0 + src = fs.readSync(process.stdin.fd, size)[0] throw 'Cannot identify generated functions' if GENERATED_FUNCTIONS_MARKER in src generatedFunctionsLine = src.split('\n').filter (line) -> diff --git a/tools/eliminator/node_modules/coffee-script/lib/command.js b/tools/eliminator/node_modules/coffee-script/lib/command.js index ca255020..39813201 100644 --- a/tools/eliminator/node_modules/coffee-script/lib/command.js +++ b/tools/eliminator/node_modules/coffee-script/lib/command.js @@ -12,7 +12,7 @@ return process.stdout.write(line + '\n'); }; printWarn = function(line) { - return process.binding('stdio').writeError(line + '\n'); + return process.stderr.write(line + '\n'); }; BANNER = 'Usage: coffee [options] path/to/script.coffee'; SWITCHES = [['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-o', '--output [DIR]', 'set the directory for compiled JavaScript'], ['-j', '--join [FILE]', 'concatenate the scripts before compiling'], ['-w', '--watch', 'watch scripts for changes, and recompile'], ['-p', '--print', 'print the compiled JavaScript to stdout'], ['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-e', '--eval', 'compile a string from the command line'], ['-r', '--require [FILE*]', 'require a library before executing your script'], ['-b', '--bare', 'compile without the top-level function wrapper'], ['-t', '--tokens', 'print the tokens that the lexer produces'], ['-n', '--nodes', 'print the parse tree that Jison produces'], ['--nodejs [ARGS]', 'pass options through to the "node" binary'], ['-v', '--version', 'display CoffeeScript version'], ['-h', '--help', 'display this help message']]; diff --git a/tools/emmaken.py b/tools/emmaken.py index 8e1bfdc8..ae4794f0 100755 --- a/tools/emmaken.py +++ b/tools/emmaken.py @@ -113,7 +113,7 @@ if CONFIGURE_CONFIG or CMAKE_CONFIG: compiler = 'g++' if 'CXXCompiler' in ' '.join(sys.argv) or os.environ.get('EMMAKEN_CXX') else 'gcc' cmd = [compiler] + EMSDK_OPTS + sys.argv[1:] print >> sys.stderr, 'emmaken.py, just configuring: ', cmd - exit(os.execvp(compiler, cmd)) + exit(subprocess.call(cmd)) try: #f=open('/dev/shm/tmp/waka.txt', 'a') @@ -223,7 +223,7 @@ try: print >> sys.stderr, "Running:", call, ' '.join(newargs) - os.execvp(call, [call] + newargs) + subprocess.call([call] + newargs) except Exception, e: print 'Error in emmaken.py. (Is the config file %s set up properly?) Error:' % EM_CONFIG, e raise diff --git a/tools/emmakenxx.py b/tools/emmakenxx.py index c9ab4ef4..1c31f3c2 100755 --- a/tools/emmakenxx.py +++ b/tools/emmakenxx.py @@ -4,7 +4,7 @@ see emmaken.py ''' -import os, sys +import os, subprocess, sys __rootpath__ = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) def path_from_root(*pathelems): @@ -14,5 +14,5 @@ from tools.shared import * emmaken = path_from_root('tools', 'emmaken.py') os.environ['EMMAKEN_CXX'] = '1' -exit(os.execvp('python', ['python', emmaken] + sys.argv[1:])) +exit(subprocess.call(['python', emmaken] + sys.argv[1:])) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 213e2257..b51fe22e 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -24,11 +24,14 @@ if (ENVIRONMENT_IS_NODE) { }; var nodeFS = require('fs'); + var nodePath = require('path'); read = function(filename) { + filename = nodePath['normalize'](filename); var ret = nodeFS['readFileSync'](filename).toString(); - if (!ret && filename[0] != '/') { - filename = __dirname.split('/').slice(0, -1).join('/') + '/src/' + filename; + // The path is absolute if the normalized version is the same as the resolved. + if (!ret && filename != nodePath['resolve'](filename)) { + filename = path.join(__dirname, '..', 'src', filename); ret = nodeFS['readFileSync'](filename).toString(); } return ret; @@ -46,9 +49,9 @@ if (ENVIRONMENT_IS_NODE) { this['read'] = function(f) { snarf(f) }; } - if (!this['arguments']) { + if (typeof scriptArgs != 'undefined') { arguments_ = scriptArgs; - } else { + } else if (typeof arguments != 'undefined') { arguments_ = arguments; } @@ -97,12 +100,15 @@ if (typeof print === 'undefined') { // Fix read for our location read = function(filename) { - if (filename[0] != '/') filename = __dirname.split('/').slice(0, -1).join('/') + '/src/' + filename; + // The path is absolute if the normalized version is the same as the resolved. + filename = path.normalize(filename); + if (filename != path.resolve(filename)) filename = path.join(__dirname, '..', 'src', filename); return fs.readFileSync(filename).toString(); } var uglify = require('../tools/eliminator/node_modules/uglify-js'); var fs = require('fs'); +var path = require('path'); // Load some modules @@ -382,7 +388,7 @@ function simplifyExpressionsPre(ast) { function simplifyBitops(ast) { var USEFUL_BINARY_OPS = set('<<', '>>', '|', '&', '^'); - var SAFE_BINARY_OPS = set('+', '-', '*', '/', '%'); + var SAFE_BINARY_OPS = set('+', '-', '*', '%'); // division is unsafe as it creates non-ints in JS var ZERO = ['num', 0]; var rerun = true; while (rerun) { diff --git a/tools/ll-strip.py b/tools/ll-strip.py new file mode 100755 index 00000000..b03e4f3a --- /dev/null +++ b/tools/ll-strip.py @@ -0,0 +1,56 @@ +#!/usr/bin/python + +import sys, re + +def print_usage(): + print >> sys.stderr, "Usage: ll-strip.py file from to" + print >> sys.stderr, "\tStrip function bodies in all ll file in the [from, to] range" + sys.exit(1) + +try: + range_from = int(sys.argv[2]) + range_to = int(sys.argv[3]) + if range_from >= range_to: + raise "error" + file = open(sys.argv[1]) +except: + print_usage() + +func_start = re.compile("^define\s") +func_end = re.compile("^}$") + +function_counter = 0 +in_function = False +line_number = 0 +skip = False +dummy_stmt = "unreachable" +for orig_line in file: + line = orig_line.strip() + if func_start.match(line): + if in_function: + print >> sys.stderr, "Discovered a function inside another function!" + sys.exit(1) + in_function = True + line_number = 0 + skip = False + function_counter = function_counter + 1 + elif func_end.match(line): + if not in_function: + print >> sys.stderr, "Discovered a function end without a matching beginning!" + sys.exit(1) + in_function = False + line_number = 0 + skip = False + elif in_function: + line_number = line_number + 1 + if not skip and line_number == 1: + if line == dummy_stmt: + function_counter = function_counter - 1 + if range_from <= function_counter <= range_to and line_number == 1: + #import pdb;pdb.set_trace() + if line != dummy_stmt: + skip = True + print dummy_stmt + if not skip: + print orig_line.rstrip("\n") + diff --git a/tools/make_minigzip.py b/tools/make_minigzip.py index cdd9c2ab..60177318 100644 --- a/tools/make_minigzip.py +++ b/tools/make_minigzip.py @@ -9,5 +9,5 @@ zlib = shared.Building.build_library('zlib', shared.EMSCRIPTEN_TEMP_DIR, shared. print 'Building minigzip' -Popen([shared.EMCC, '-O2', shared.path_from_root('tests', 'zlib', 'minigzip.c'), zlib, '-o', shared.path_from_root('tools', 'minigzip.js')]).communicate() +Popen(['python', shared.EMCC, '-O2', shared.path_from_root('tests', 'zlib', 'minigzip.c'), zlib, '-o', shared.path_from_root('tools', 'minigzip.js')]).communicate() diff --git a/tools/nativize_llvm.py b/tools/nativize_llvm.py index de78dce2..de78dce2 100644..100755 --- a/tools/nativize_llvm.py +++ b/tools/nativize_llvm.py diff --git a/tools/scan_js.py b/tools/scan_js.py new file mode 100644 index 00000000..eeff7c7c --- /dev/null +++ b/tools/scan_js.py @@ -0,0 +1,20 @@ +''' +Finds why a .js file is large by printing functions by size +''' + +import os, sys + +funcs = [] +i = 0 +inside = None +for line in open(sys.argv[1]): + i += 1 + if line.startswith('function _'): + inside = line.replace('function ', '').replace('\n', '') + start = i + elif inside and line.startswith('}'): + funcs.append((inside, i-start)) + inside = None + +print '\n'.join(map(lambda func: str(func[1]) + ':' + func[0], sorted(funcs, key=lambda func: -func[1]))) + diff --git a/tools/scan_ll.py b/tools/scan_ll.py new file mode 100644 index 00000000..d7d42057 --- /dev/null +++ b/tools/scan_ll.py @@ -0,0 +1,18 @@ +''' +Finds why an .ll file is large by printing functions by size +''' + +import os, sys + +funcs = [] +i = 0 +for line in open(sys.argv[1]): + i += 1 + if line.startswith('define '): + inside = line.replace('define ', '').replace('\n', '') + start = i + elif line.startswith('}'): + funcs.append((inside, i-start)) + +print '\n'.join(map(lambda func: str(func[1]) + ':' + func[0], sorted(funcs, key=lambda func: -func[1]))) + diff --git a/tools/scons/site_scons/site_tools/emscripten/__init__.py b/tools/scons/site_scons/site_tools/emscripten/__init__.py new file mode 100644 index 00000000..8ae2288e --- /dev/null +++ b/tools/scons/site_scons/site_tools/emscripten/__init__.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python + +from emscripten import exists, generate diff --git a/tools/scons/site_scons/site_tools/emscripten/emscripten.py b/tools/scons/site_scons/site_tools/emscripten/emscripten.py new file mode 100644 index 00000000..cb14b58e --- /dev/null +++ b/tools/scons/site_scons/site_tools/emscripten/emscripten.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python + +import os + +def generate(env, emscripten_path=None, **kw): + """ SCons tool entry point """ + + if emscripten_path is None: + # Try to find emscripten + # Use same method as Emscripten's shared.py + EM_CONFIG = os.environ.get('EM_CONFIG') + if not EM_CONFIG: + EM_CONFIG = '~/.emscripten' + + CONFIG_FILE = os.path.expanduser(EM_CONFIG) + try: + exec(open(CONFIG_FILE, 'r').read()) + except Exception, e: + print >> sys.stderr, 'Error in evaluating %s (at %s): %s' % (EM_CONFIG, CONFIG_FILE, str(e)) + sys.exit(1) + + emscripten_path = EMSCRIPTEN_ROOT + + try: + emscPath = emscripten_path.abspath + except: + emscPath = emscripten_path + + env.Replace(CC = os.path.join(emscPath, "emcc" )) + env.Replace(CXX = os.path.join(emscPath, "em++" )) + env.Replace(LINK = os.path.join(emscPath, "emld" )) + # SHLINK and LDMODULE should use LINK so no + # need to change them here + + env.Replace(AR = os.path.join(emscPath, "emar" )) + env.Replace(RANLIB = os.path.join(emscPath, "emranlib")) + + env.Replace(OBJSUFFIX = [".js", ".bc", ".o"][2]) + env.Replace(LIBSUFFIX = [".js", ".bc", ".o"][2]) + env.Replace(PROGSUFFIX = [".html", ".js" ][1]) + +def exists(env): + """ NOOP method required by SCons """ + return 1 diff --git a/tools/shared.py b/tools/shared.py index fd51282b..fb41f7ee 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -1,4 +1,4 @@ -import shutil, time, os, sys, json, tempfile, copy +import shutil, time, os, sys, json, tempfile, copy, shlex, atexit from subprocess import Popen, PIPE, STDOUT from tempfile import mkstemp @@ -6,15 +6,22 @@ __rootpath__ = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) def path_from_root(*pathelems): return os.path.join(__rootpath__, *pathelems) -# Config file +# Emscripten configuration is done through the EM_CONFIG environment variable. +# If the string value contained in this environment variable contains newline +# separated definitions, then these definitions will be used to configure +# Emscripten. Otherwise, the string is understood to be a path to a settings +# file that contains the required definitions. EM_CONFIG = os.environ.get('EM_CONFIG') if not EM_CONFIG: EM_CONFIG = '~/.emscripten' -CONFIG_FILE = os.path.expanduser(EM_CONFIG) -if not os.path.exists(CONFIG_FILE): - shutil.copy(path_from_root('settings.py'), CONFIG_FILE) - print >> sys.stderr, ''' +if '\n' in EM_CONFIG: + CONFIG_FILE = None +else: + CONFIG_FILE = os.path.expanduser(EM_CONFIG) + if not os.path.exists(CONFIG_FILE): + shutil.copy(path_from_root('settings.py'), CONFIG_FILE) + print >> sys.stderr, ''' ============================================================================== Welcome to Emscripten! @@ -28,9 +35,9 @@ make sure LLVM_ROOT and NODE_JS are correct. This command will now exit. When you are done editing those paths, re-run it. ============================================================================== ''' % (EM_CONFIG, CONFIG_FILE) - sys.exit(0) + sys.exit(0) try: - exec(open(CONFIG_FILE, 'r').read()) + exec(open(CONFIG_FILE, 'r').read() if CONFIG_FILE else EM_CONFIG) except Exception, e: print >> sys.stderr, 'Error in evaluating %s (at %s): %s' % (EM_CONFIG, CONFIG_FILE, str(e)) sys.exit(1) @@ -43,6 +50,8 @@ except Exception, e: def check_sanity(force=False): try: if not force: + if not CONFIG_FILE: + return # config stored directly in EM_CONFIG => skip sanity checks settings_mtime = os.stat(CONFIG_FILE).st_mtime sanity_file = CONFIG_FILE + '_sanity' try: @@ -115,18 +124,30 @@ EXEC_LLVM = path_from_root('tools', 'exec_llvm.py') VARIABLE_ELIMINATOR = path_from_root('tools', 'eliminator', 'eliminator.coffee') JS_OPTIMIZER = path_from_root('tools', 'js-optimizer.js') -# Temp dir +# Temp dir. Create a random one, unless EMCC_DEBUG is set, in which case use TEMP_DIR/emscripten_temp try: - EMSCRIPTEN_TEMP_DIR = os.path.join(TEMP_DIR, 'emscripten_temp') - if not os.path.exists(EMSCRIPTEN_TEMP_DIR): - try: - os.makedirs(EMSCRIPTEN_TEMP_DIR) - except Exception, e: - print >> sys.stderr, 'Warning: Could not create temp dir (%s): %s' % (EMSCRIPTEN_TEMP_DIR, str(e)) + TEMP_DIR except: + print >> sys.stderr, 'TEMP_DIR not defined in ~/.emscripten, using /tmp' + TEMP_DIR = '/tmp' + +CANONICAL_TEMP_DIR = os.path.join(TEMP_DIR, 'emscripten_temp') +EMSCRIPTEN_TEMP_DIR = None + +if os.environ.get('EMCC_DEBUG'): + try: + EMSCRIPTEN_TEMP_DIR = CANONICAL_TEMP_DIR + if not os.path.exists(EMSCRIPTEN_TEMP_DIR): + os.makedirs(EMSCRIPTEN_TEMP_DIR) + except: + print >> sys.stderr, 'Could not create canonical temp dir. Check definition of TEMP_DIR in ~/.emscripten' + +if not EMSCRIPTEN_TEMP_DIR: EMSCRIPTEN_TEMP_DIR = tempfile.mkdtemp(prefix='emscripten_temp_') - print >> sys.stderr, 'Warning: TEMP_DIR not defined in %s, using %s' % (EM_CONFIG, EMSCRIPTEN_TEMP_DIR) + def clean_temp(): + try_delete(EMSCRIPTEN_TEMP_DIR) + atexit.register(clean_temp) # EM_CONFIG stuff @@ -139,6 +160,11 @@ except: print 'ERROR: %s does not seem to have JS_ENGINES or JS_ENGINE set up' % EM_CONFIG raise +try: + CLOSURE_COMPILER +except: + CLOSURE_COMPILER = path_from_root('third_party', 'closure-compiler', 'compiler.jar') + # Additional compiler options try: @@ -176,8 +202,13 @@ else: #if 'strict' not in str(SPIDERMONKEY_ENGINE): # XXX temporarily disable strict mode until we sort out some stuff # SPIDERMONKEY_ENGINE += ['-e', "options('strict')"] # Strict mode in SpiderMonkey. With V8 we check that fallback to non-strict works too -if 'gcparam' not in str(SPIDERMONKEY_ENGINE): - SPIDERMONKEY_ENGINE += ['-e', "gcparam('maxBytes', 1024*1024*1024);"] # Our very large files need lots of gc heap +try: + if 'gcparam' not in str(SPIDERMONKEY_ENGINE): + SPIDERMONKEY_ENGINE += ['-e', "gcparam('maxBytes', 1024*1024*1024);"] # Our very large files need lots of gc heap +except NameError: + pass + +WINDOWS = sys.platform.startswith ('win') # Temp file utilities @@ -185,7 +216,10 @@ def try_delete(filename): try: os.unlink(filename) except: - pass + try: + shutil.rmtree(filename) + except: + pass class TempFiles: def __init__(self): @@ -216,12 +250,14 @@ class TempFiles: def check_engine(engine): # TODO: we call this several times, perhaps cache the results? try: + if not CONFIG_FILE: + return True # config stored directly in EM_CONFIG => skip engine check return 'hello, world!' in run_js(path_from_root('tests', 'hello_world.js'), engine) except Exception, e: print 'Checking JS engine %s failed. Check %s. Details: %s' % (str(engine), EM_CONFIG, str(e)) return False -def timeout_run(proc, timeout, note): +def timeout_run(proc, timeout, note='unnamed process'): start = time.time() if timeout is not None: while time.time() - start < timeout and proc.poll() is None: @@ -231,11 +267,14 @@ def timeout_run(proc, timeout, note): raise Exception("Timed out: " + note) return proc.communicate()[0] +EM_DEBUG = os.environ.get('EM_DEBUG') + def run_js(filename, engine=None, args=[], check_timeout=False, stdout=PIPE, stderr=None, cwd=None): if engine is None: engine = JS_ENGINES[0] if type(engine) is not list: engine = [engine] - return timeout_run(Popen(engine + [filename] + (['--'] if 'd8' in engine[0] else []) + args, - stdout=stdout, stderr=stderr, cwd=cwd), 15*60 if check_timeout else None, 'Execution') + command = engine + [filename] + (['--'] if 'd8' in engine[0] else []) + args + if EM_DEBUG: print >> sys.stderr, 'run_js: ' + ' '.join(command) + return timeout_run(Popen(command, stdout=stdout, stderr=stderr, cwd=cwd), 15*60 if check_timeout else None, 'Execution') def to_cc(cxx): # By default, LLVM_GCC and CLANG are really the C++ versions. This gets an explicit C version @@ -267,7 +306,7 @@ def read_pgo_data(filename): ''' signs_lines = [] overflows_lines = [] - + for line in open(filename, 'r'): try: if line.rstrip() == '': continue @@ -334,6 +373,7 @@ class Settings: Settings.CORRECT_OVERFLOWS = 0 Settings.CORRECT_ROUNDINGS = 0 Settings.DOUBLE_MODE = 0 + Settings.PRECISE_I64_MATH = 0 if noisy: print >> sys.stderr, 'Warning: Applying some potentially unsafe optimizations! (Use -O2 if this fails.)' global Settings @@ -352,11 +392,11 @@ class Building: @staticmethod def get_building_env(): env = os.environ.copy() - env['CC'] = EMCC - env['CXX'] = EMXX - env['AR'] = EMAR - env['RANLIB'] = EMRANLIB - env['LIBTOOL'] = EMLIBTOOL + env['CC'] = EMCC if not WINDOWS else 'python %r' % EMCC + env['CXX'] = EMXX if not WINDOWS else 'python %r' % EMXX + env['AR'] = EMAR if not WINDOWS else 'python %r' % EMAR + env['RANLIB'] = EMRANLIB if not WINDOWS else 'python %r' % EMRANLIB + env['LIBTOOL'] = EMLIBTOOL if not WINDOWS else 'python %r' % EMLIBTOOL env['EMMAKEN_COMPILER'] = Building.COMPILER env['EMSCRIPTEN_TOOLS'] = path_from_root('tools') env['CFLAGS'] = env['EMMAKEN_CFLAGS'] = ' '.join(Building.COMPILER_TEST_OPTS) @@ -368,14 +408,14 @@ class Building: @staticmethod def handle_CMake_toolchain(args, env): - CMakeToolchain = '''# the name of the target operating system + CMakeToolchain = ('''# the name of the target operating system SET(CMAKE_SYSTEM_NAME Linux) # which C and C++ compiler to use -SET(CMAKE_C_COMPILER $EMSCRIPTEN_ROOT/emcc) -SET(CMAKE_CXX_COMPILER $EMSCRIPTEN_ROOT/em++) -SET(CMAKE_AR $EMSCRIPTEN_ROOT/emar) -SET(CMAKE_RANLIB $EMSCRIPTEN_ROOT/emranlib) +SET(CMAKE_C_COMPILER %(winfix)s$EMSCRIPTEN_ROOT/emcc) +SET(CMAKE_CXX_COMPILER %(winfix)s$EMSCRIPTEN_ROOT/em++) +SET(CMAKE_AR %(winfix)s$EMSCRIPTEN_ROOT/emar) +SET(CMAKE_RANLIB %(winfix)s$EMSCRIPTEN_ROOT/emranlib) SET(CMAKE_C_FLAGS $CFLAGS) SET(CMAKE_CXX_FLAGS $CXXFLAGS) @@ -388,8 +428,8 @@ SET(CMAKE_FIND_ROOT_PATH $EMSCRIPTEN_ROOT/system/include ) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \ - .replace('$EMSCRIPTEN_ROOT', path_from_root('')) \ +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS else 'python ' }) \ + .replace('$EMSCRIPTEN_ROOT', path_from_root('').replace('\\', '/')) \ .replace('$CFLAGS', env['CFLAGS']) \ .replace('$CXXFLAGS', env['CFLAGS']) toolchainFile = mkstemp(suffix='.txt')[1] @@ -404,17 +444,17 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \ env['EMMAKEN_JUST_CONFIGURE'] = '1' if 'cmake' in args[0]: args = Building.handle_CMake_toolchain(args, env) - Popen(args, stdout=stdout, stderr=stderr, env=env).communicate()[0] + Popen(args, stdout=stdout, stderr=stderr, env=env).communicate() del env['EMMAKEN_JUST_CONFIGURE'] @staticmethod def make(args, stdout=None, stderr=None, env=None): if env is None: env = Building.get_building_env() - Popen(args, stdout=stdout, stderr=stderr, env=env).communicate()[0] + Popen(args, stdout=stdout, stderr=stderr, env=env).communicate() @staticmethod - def build_library(name, build_dir, output_dir, generated_libs, configure=['./configure'], configure_args=[], make=['make'], make_args=['-j', '2'], cache=None, cache_name=None, copy_project=False, env_init={}, source_dir=None): + def build_library(name, build_dir, output_dir, generated_libs, configure=['sh', './configure'], configure_args=[], make=['make'], make_args=['-j', '2'], cache=None, cache_name=None, copy_project=False, env_init={}, source_dir=None): ''' Build a library into a .bc file. We build the .bc file once and cache it for all our tests. (We cache in memory since the test directory is destroyed and recreated for each test. Note that we cache separately for different compilers). @@ -462,7 +502,9 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \ @staticmethod def link(files, target): try_delete(target) - output = Popen([LLVM_LD, '-disable-opt'] + files + ['-b', target], stdout=PIPE).communicate()[0] + stub = os.path.join(EMSCRIPTEN_TEMP_DIR, 'stub_deleteme') + ('.exe' if WINDOWS else '') + output = Popen([LLVM_LD, '-disable-opt'] + files + ['-b', target, '-o', stub], stdout=PIPE).communicate()[0] + try_delete(stub) # clean up stub left by the linker assert os.path.exists(target) and (output is None or 'Could not open input file' not in output), 'Linking error: ' + output # Emscripten optimizations that we run on the .ll file @@ -550,13 +592,13 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \ if output_filename is None: output_filename = filename + '.o' try_delete(output_filename) - Popen([EMCC, filename] + args + ['-o', output_filename], stdout=stdout, stderr=stderr, env=env).communicate() + Popen(['python', EMCC, filename] + args + ['-o', output_filename], stdout=stdout, stderr=stderr, env=env).communicate() assert os.path.exists(output_filename), 'emcc could not create output file' @staticmethod def emar(action, output_filename, filenames, stdout=None, stderr=None, env=None): try_delete(output_filename) - Popen([EMAR, action, output_filename] + filenames, stdout=stdout, stderr=stderr, env=env).communicate() + Popen(['python', EMAR, action, output_filename] + filenames, stdout=stdout, stderr=stderr, env=env).communicate() if 'c' in action: assert os.path.exists(output_filename), 'emar could not create output file' @@ -729,13 +771,19 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \ # Something like this (adjust memory as needed): # java -Xmx1024m -jar CLOSURE_COMPILER --compilation_level ADVANCED_OPTIMIZATIONS --variable_map_output_file src.cpp.o.js.vars --js src.cpp.o.js --js_output_file src.cpp.o.cc.js - cc_output = Popen(['java', '-jar', CLOSURE_COMPILER, - '--compilation_level', 'ADVANCED_OPTIMIZATIONS', - '--formatting', 'PRETTY_PRINT', - #'--variable_map_output_file', filename + '.vars', - '--js', filename, '--js_output_file', filename + '.cc.js'], stdout=PIPE, stderr=STDOUT).communicate()[0] - if 'ERROR' in cc_output or not os.path.exists(filename + '.cc.js'): - raise Exception('closure compiler error: ' + cc_output) + args = ['java', + '-Xmx1024m', + '-jar', CLOSURE_COMPILER, + '--compilation_level', 'ADVANCED_OPTIMIZATIONS', + '--formatting', 'PRETTY_PRINT', + #'--variable_map_output_file', filename + '.vars', + '--js', filename, '--js_output_file', filename + '.cc.js'] + if os.environ.get('EMCC_CLOSURE_ARGS'): + args += shlex.split(os.environ.get('EMCC_CLOSURE_ARGS')) + process = Popen(args, stdout=PIPE, stderr=STDOUT) + cc_output = process.communicate()[0] + if process.returncode != 0 or not os.path.exists(filename + '.cc.js'): + raise Exception('closure compiler error: ' + cc_output + ' (rc: %d)' % process.returncode) return filename + '.cc.js' @@ -784,12 +832,14 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \ elif ord(b[0]) == 222 and ord(b[1]) == 192 and ord(b[2]) == 23 and ord(b[3]) == 11: b = open(filename, 'r').read(24) return b[20] == 'B' and b[21] == 'C' - + return False # Permanent cache for dlmalloc and stdlibc++ class Cache: - dirname = os.path.expanduser(os.path.join('~', '.emscripten_cache')) + dirname = os.environ.get('EM_CACHE') + if not dirname: + dirname = os.path.expanduser(os.path.join('~', '.emscripten_cache')) @staticmethod def erase(): diff --git a/tools/test-js-optimizer-output.js b/tools/test-js-optimizer-output.js index ca76cae1..a312296d 100644 --- a/tools/test-js-optimizer-output.js +++ b/tools/test-js-optimizer-output.js @@ -86,7 +86,7 @@ function bits() { z($f << 2); z($f * 100 << 2); z($f % 2 | 255); - z($f / 55 & 255); + z(($f | 0) / 55 & 255); z($f - 22 ^ 1); z($f + 15 << 2); } @@ -311,4 +311,7 @@ function notComps() { shoo(); } } -// EMSCRIPTEN_GENERATED_FUNCTIONS: ["abc", "xyz", "xyz2", "expr", "loopy", "bits", "maths", "hoisting", "demangle", "lua", "moreLabels", "notComps"] +function tricky() { + var $conv642 = $conv6374 - (($132 << 16 >> 16 | 0) / 2 & -1) & 65535; +} +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["abc", "xyz", "xyz2", "expr", "loopy", "bits", "maths", "hoisting", "demangle", "lua", "moreLabels", "notComps", "tricky"] diff --git a/tools/test-js-optimizer.js b/tools/test-js-optimizer.js index 18c9ac75..e9d973dd 100644 --- a/tools/test-js-optimizer.js +++ b/tools/test-js-optimizer.js @@ -422,4 +422,8 @@ function notComps() { shoo(); } } -// EMSCRIPTEN_GENERATED_FUNCTIONS: ["abc", "xyz", "xyz2", "expr", "loopy", "bits", "maths", "hoisting", "demangle", "lua", "moreLabels", "notComps"] +function tricky() { + // The &-1 is a rounding correction, and must not be removed + var $conv642 = ($conv6374 - (($132 << 16 >> 16 | 0) / 2 & -1) | 0) & 65535; +} +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["abc", "xyz", "xyz2", "expr", "loopy", "bits", "maths", "hoisting", "demangle", "lua", "moreLabels", "notComps", "tricky"] |