From e0cd2c4078c5dbaecda881c9258f01d5069a1d02 Mon Sep 17 00:00:00 2001 From: ngld Date: Mon, 16 Sep 2013 01:55:55 +0200 Subject: Started work on #1554 Added a script to extract struct sizes and field offsets as well as constant (#define) values. --- AUTHORS | 2 +- tools/gen_struct_info.py | 368 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 369 insertions(+), 1 deletion(-) create mode 100644 tools/gen_struct_info.py diff --git a/AUTHORS b/AUTHORS index a0475661..23325a7d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -96,4 +96,4 @@ a license to everyone to use it as detailed in LICENSE.) * Aidan Hobson Sayers * Charlie Birks * Ranger Harke (copyright owned by Autodesk, Inc.) - +* Tobias Vrinssen diff --git a/tools/gen_struct_info.py b/tools/gen_struct_info.py new file mode 100644 index 00000000..563b4fa1 --- /dev/null +++ b/tools/gen_struct_info.py @@ -0,0 +1,368 @@ +# -*- encoding: utf8 -*- + +''' +This tool extracts information about structs and defines from the C headers. +You can pass either the raw header files or JSON files to this script. + +The JSON input format is as follows: +[ + { + 'file': 'some/header.h', + 'structs': { + 'struct_name': [ + 'field1', + 'field2', + 'field3', + { + 'field4': [ + 'nested1', + 'nested2', + { + 'nested3': [ + 'deep_nested1', + ... + ] + } + ... + ] + }, + 'field5' + ], + 'other_struct': [ + 'field1', + 'field2', + ... + ] + }, + 'defines': [ + 'DEFINE_1', + 'DEFINE_2', + ['f', 'FLOAT_DEFINE'], + 'DEFINE_3', + ... + ] + }, + { + 'file': 'some/other/header.h', + ... + } +] + +Please note that the 'f' for 'FLOAT_DEFINE' is just the format passed to printf(), you can put anything printf() understands. +If you call this script with the flag "-f" and pass a header file, it will create an automated boilerplate for you. + +The JSON output format is based on the return value of Runtime.generateStructInfo(). +{ + 'structs': { + 'struct_name': { + '__size__': , + 'field1': , + 'field2': , + 'field3': , + 'field4': { + '__size__': , + 'nested1': , + ... + }, + ... + } + }, + 'defines': { + 'DEFINE_1': , + ... + } +} + +''' + +import sys +import os +import json +import argparse +import tempfile +import subprocess +import shared + +# Try to load pycparser. +try: + import pycparser +except ImportError: + # The import failed, warn the user. + sys.stderr.write('WARN: pycparser isn\'t available. I won\'t be able to parse C files, only .json files.\n') + + def parse_header(path, cpp_opts): + # Tell the user how to get pycparser, if he tries to parse a C file. + sys.stderr.write('ERR: I need pycparser to process C files. \n') + sys.stderr.write(' Use "pip install pycparser" or go to "https://github.com/eliben/pycparser" to install it.\n') + sys.exit(1) +else: + # We successfully imported pycparser, the script will be completely functional. + + class FieldVisitor(pycparser.c_ast.NodeVisitor): + def __init__(self): + self._name = None + self.structs = {} + self.named_structs = {} + + def visit_Struct(self, node): + if node.decls == None: + # Skip empty struct declarations. + return + + fields = [] + for decl in node.decls: + # Look for nested structs. + subwalk = FieldVisitor() + subwalk.visit(decl) + + if subwalk.named_structs: + # Store the nested fields. + fields.append(subwalk.named_structs) + else: + # Just store the field name. + fields.append(decl.name) + + if node.name != None: + self.structs[node.name] = fields + + self.named_structs[self._name] = fields + + def visit_Union(self, node): + self.visit_Struct(node) + + def visit_TypeDecl(self, node): + # Remember the name of this typedef, so we can access it later in visit_Struct(). + old_name = self._name + self._name = node.declname + self.generic_visit(node) + self._name = old_name + + def parse_header(path, cpp_opts): + sys.stderr.write('Parsing header "' + path + '"...\n') + + # Use clang -E as the preprocessor for pycparser. + ast = pycparser.parse_file(path, True, cpp_path=shared.CLANG_CC, cpp_args=['-E'] + cpp_opts) + + # Walk the parsed AST and filter out all the declared structs and their fields. + walker = FieldVisitor() + walker.visit(ast) + return walker.structs + +# The following three functions generate C code. The output of the compiled code will be +# parsed later on and then put back together into a dict structure by parse_c_output(). +def c_set(name, type_, value, code): + code.append('printf("K' + name + '\\n");') + code.append('printf("V' + type_ + '\\n", ' + value + ');') + +def c_descent(name, code): + code.append('printf("D' + name + '\\n");') + +def c_ascent(code): + code.append('printf("A\\n");') + +def parse_c_output(lines): + result = {} + cur_level = result + parent = [] + key = None + + for line in lines: + arg = line[1:].strip() + if line[0] == 'K': + # This is a key + key = arg + elif line[0] == 'V': + # A value + cur_level[key] = int(arg) + elif line[0] == 'D': + # Remember the current level as the last parent. + parent.append(cur_level) + + # We descend one level. + cur_level[arg] = {} + cur_level = cur_level[arg] + elif line[0] == 'A': + # We return to the parent dict. (One level up.) + cur_level = parent.pop() + + return result + +def gen_inspect_code(path, struct, code): + c_descent(path[-1], code) + if len(path) == 1: + c_set('__size__', '%lu', 'sizeof (struct ' + path[0] + ')', code) + else: + c_set('__size__', '%lu', 'sizeof ((struct ' + path[0] + ' *)0)->' + '.'.join(path[1:]), code) + + for field in struct: + if isinstance(field, dict): + # We have to recurse to inspect the nested dict. + fname = field.keys()[0] + gen_inspect_code(path + [fname], field[fname], code) + else: + c_set(field, '%u', 'offsetof(struct ' + path[0] + ', ' + '.'.join(path[1:] + [field]) + ')', code) + + c_ascent(code) + +def inspect_code(headers, cpp_opts, structs, defines): + sys.stderr.write('Generating C code...\n') + + code = ['#include ', '#include '] + # Include all the needed headers. + for path in headers: + code.append('#include "' + path + '"') + + code.append('int main() {') + c_descent('structs', code) + for name, struct in structs.items(): + gen_inspect_code([name], struct, code) + + c_ascent(code) + c_descent('defines', code) + for name in defines: + if isinstance(name, list): + type_, name = name + else: + type_ = 'i' + c_set(name, '%' + type_, name, code) + + code.append('return 0;') + code.append('}') + + # Write the source code to a temporary file. + src_file = tempfile.mkstemp('.c') + bin_file = tempfile.mkstemp() + + os.write(src_file[0], '\n'.join(code)) + + # Close all unneeded FDs. + os.close(src_file[0]) + os.close(bin_file[0]) + + info = [] + try: + # Compile the program. + sys.stderr.write('Compiling generated code...\n') + subprocess.check_call([shared.CLANG_CC] + cpp_opts + ['-o', bin_file[1], src_file[1]]) + + # Run the compiled program. + sys.stderr.write('Calling generated program...\n') + info = subprocess.check_output([bin_file[1]]).splitlines() + except subprocess.CalledProcessError: + if os.path.isfile(bin_file[1]): + sys.stderr.write('FAIL: Running the generated program failed!\n') + else: + sys.stderr.write('FAIL: Compilation failed!\n') + + sys.exit(1) + finally: + # Remove all temporary files. + os.unlink(src_file[1]) + + if os.path.exists(bin_file[1]): + os.unlink(bin_file[1]) + + # Parse the output of the program into a dict. + data = parse_c_output(info) + + # Convert all the define's values into the appropriate python types (based on the type passed to printf). + for name in defines: + if isinstance(name, list): + type_, name = name + else: + type_ = 'i' + + if type_[-1] in ('d', 'i', 'u'): + # Integer + data['defines'][name] = int(data['defines'][name]) + elif type_[-1] in ('x', 'X', 'a', 'A'): + # Hexadecimal + data['defines'][name] = float.fromhex(data['defines'][name]) + elif type_[-1] in ('f', 'F', 'e', 'E', 'g', 'G'): + # Float + data['defines'][name] = float(data['defines'][name]) + # Leave everything else untouched. + + return data + +def main(): + parser = argparse.ArgumentParser(description='Generate JSON infos for structs.') + parser.add_argument('headers', nargs='+', help='A header (.h) file or a JSON file with a list of structs and their fields') + parser.add_argument('-f', dest='list_fields', action='store_true', default=False, help='Output a list of structs and fields for the first header.') + parser.add_argument('-p', dest='pretty_print', action='store_true', default=False, help='Pretty print the outputted JSON.') + parser.add_argument('-o', dest='output', metavar='path', default=None, help='Path to the JSON file that will be written. If omitted, the generated data will be printed to stdout.') + parser.add_argument('-I', dest='includes', metavar='dir', action='append', default=[], help='Add directory to include search path') + parser.add_argument('-D', dest='defines', metavar='define', action='append', default=[], help='Pass a define to the preprocessor') + parser.add_argument('-U', dest='undefines', metavar='undefine', action='append', default=[], help='Pass an undefine to the preprocessor') + args = parser.parse_args() + + # Avoid parsing problems due to gcc specifc syntax. + cpp_opts = ['-U__GNUC__'] + + # Only apply compiler options regarding syntax, includes and defines. + # We have to compile for the current system, we aren't compiling to bitcode after all. + for flag in shared.COMPILER_OPTS: + if flag[:2] in ('-f', '-I', '-i', '-D', '-U'): + cpp_opts.append(flag) + + # Add the user options to the list as well. + for path in args.includes: + cpp_opts.append('-I' + path) + + for arg in args.defines: + cpp_opts.append('-D' + arg) + + for arg in args.undefines: + cpp_opts.append('-U' + arg) + + if args.list_fields: + # Just parse the first header and output the result. + structs = parse_header(args.headers[0], cpp_opts) + data = { + 'file': args.headers[0], + 'structs': structs, + 'defines': [] + } + + if args.output == None: + sys.stdout.write(json.dumps(data, indent=4 if args.pretty_print else None)) + else: + with open(args.output, 'w') as stream: + json.dump(data, stream, indent=4 if args.pretty_print else None) + + sys.exit(0) + + # Look for structs in all passed headers. + header_files = [] + structs = {} + defines = {} + + for header in args.headers: + if header[-5:] == '.json': + # This is a JSON file, simply load it. + with open(header, 'r') as stream: + data = json.load(stream) + + if not isinstance(data, list): + data = [ data ] + + for item in data: + header_files.append(item['file']) + structs.update(item['structs']) + defines.update(item['defines']) + else: + # If the passed file isn't a JSON file, assume it's a header. + header_files.append(header) + structs.update(parse_header(header, cpp_opts)) + + # Inspect all collected structs. + struct_info = inspect_code(header_files, cpp_opts, structs, defines) + + if args.output == None: + sys.stdout.write(json.dumps(struct_info, indent=4 if args.pretty_print else None)) + else: + with open(args.output, 'w') as stream: + json.dump(struct_info, stream, indent=4 if args.pretty_print else None) + +if __name__ == '__main__': + main() \ No newline at end of file -- cgit v1.2.3-18-g5258 From 1600df2e360d0bbfd9195b3523dd3d0b440fe62a Mon Sep 17 00:00:00 2001 From: ngld Date: Mon, 16 Sep 2013 23:49:19 +0200 Subject: Integrate the new tool into emscripten Automatically compile struct_info.json and save the compiled version in the emscripten cache. --- emscripten.py | 9 +- src/compiler.js | 6 + src/library.js | 593 ++++++++++++---------------------- src/parseTools.js | 3 +- src/struct_info.json | 822 +++++++++++++++++++++++++++++++++++++++++++++++ tools/gen_struct_info.py | 335 +++++++++++++------ tools/shared.py | 12 +- 7 files changed, 1298 insertions(+), 482 deletions(-) create mode 100644 src/struct_info.json diff --git a/emscripten.py b/emscripten.py index 4d744fdd..e6a6e124 100755 --- a/emscripten.py +++ b/emscripten.py @@ -709,7 +709,14 @@ def main(args, compiler_engine, cache, jcache, relooper, temp_files, DEBUG, DEBU if not os.path.exists(relooper): from tools import shared shared.Building.ensure_relooper(relooper) - + + settings.setdefault('STRUCT_INFO', cache.get_path('struct_info.compiled.json')) + struct_info = settings.get('STRUCT_INFO') + + if not os.path.exists(struct_info): + from tools import shared + shared.Building.ensure_struct_info(struct_info) + emscript(args.infile, settings, args.outfile, libraries, compiler_engine=compiler_engine, jcache=jcache, temp_files=temp_files, DEBUG=DEBUG, DEBUG_CACHE=DEBUG_CACHE) diff --git a/src/compiler.js b/src/compiler.js index f2b0dcbd..69824035 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -204,6 +204,12 @@ if (phase == 'pre') { if (VERBOSE) printErr('VERBOSE is on, this generates a lot of output and can slow down compilation'); +// Load struct and define information. +var temp = JSON.parse(read(STRUCT_INFO)); +C_STRUCTS = temp.structs; +// NOTE: This overwrites C_DEFINES from settings.js, should this be fixed or will C_DEFINES in settings.js be deprecated? +C_DEFINES = temp.defines; + // Load compiler code load('framework.js'); diff --git a/src/library.js b/src/library.js index aac5a9da..b45dd8f5 100644 --- a/src/library.js +++ b/src/library.js @@ -28,13 +28,7 @@ LibraryManager.library = { // dirent.h // ========================================================================== - __dirent_struct_layout: Runtime.generateStructInfo([ - ['i32', 'd_ino'], - ['i32', 'd_off'], - ['i16', 'd_reclen'], - ['i8', 'd_type'], - ['b256', 'd_name']]), - opendir__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', '__dirent_struct_layout', 'open'], + opendir__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'open'], opendir: function(dirname) { // DIR *opendir(const char *dirname); // http://pubs.opengroup.org/onlinepubs/007908799/xsh/opendir.html @@ -90,7 +84,7 @@ LibraryManager.library = { // http://pubs.opengroup.org/onlinepubs/007908799/xsh/rewinddir.html _seekdir(dirp, 0); }, - readdir_r__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', '__dirent_struct_layout'], + readdir_r__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'], readdir_r: function(dirp, entry, result) { // int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); // http://pubs.opengroup.org/onlinepubs/007908799/xsh/readdir_r.html @@ -123,14 +117,14 @@ LibraryManager.library = { FS.isLink(child.mode) ? 10 : // DT_LNK, symbolic link. 8; // DT_REG, regular file. } - {{{ makeSetValue('entry', '___dirent_struct_layout.d_ino', 'id', 'i32') }}} - {{{ makeSetValue('entry', '___dirent_struct_layout.d_off', 'offset', 'i32') }}} - {{{ makeSetValue('entry', '___dirent_struct_layout.d_reclen', 'name.length + 1', 'i32') }}} + {{{ makeSetValue('entry', C_STRUCTS.dirent.d_ino, 'id', 'i32') }}} + {{{ makeSetValue('entry', C_STRUCTS.dirent.d_off, 'offset', 'i32') }}} + {{{ makeSetValue('entry', C_STRUCTS.dirent.d_reclen, 'name.length + 1', 'i32') }}} for (var i = 0; i < name.length; i++) { - {{{ makeSetValue('entry + ___dirent_struct_layout.d_name', 'i', 'name.charCodeAt(i)', 'i8') }}} + {{{ makeSetValue('entry + ' + C_STRUCTS.dirent.d_name, 'i', 'name.charCodeAt(i)', 'i8') }}} } - {{{ makeSetValue('entry + ___dirent_struct_layout.d_name', 'i', '0', 'i8') }}} - {{{ makeSetValue('entry', '___dirent_struct_layout.d_type', 'type', 'i8') }}} + {{{ makeSetValue('entry + ' + C_STRUCTS.dirent.d_name, 'i', '0', 'i8') }}} + {{{ makeSetValue('entry', C_STRUCTS.dirent.d_type, 'type', 'i8') }}} {{{ makeSetValue('result', '0', 'entry', 'i8*') }}} stream.position++; return 0; @@ -145,7 +139,7 @@ LibraryManager.library = { return 0; } // TODO Is it supposed to be safe to execute multiple readdirs? - if (!_readdir.entry) _readdir.entry = _malloc(___dirent_struct_layout.__size__); + if (!_readdir.entry) _readdir.entry = _malloc({{{ C_STRUCTS.dirent.__size__ }}}); if (!_readdir.result) _readdir.result = _malloc(4); var err = _readdir_r(dirp, _readdir.entry, _readdir.result); if (err) { @@ -161,17 +155,14 @@ LibraryManager.library = { // utime.h // ========================================================================== - __utimbuf_struct_layout: Runtime.generateStructInfo([ - ['i32', 'actime'], - ['i32', 'modtime']]), - utime__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', '__utimbuf_struct_layout'], + utime__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'], utime: function(path, times) { // int utime(const char *path, const struct utimbuf *times); // http://pubs.opengroup.org/onlinepubs/009695399/basedefs/utime.h.html var time; if (times) { // NOTE: We don't keep track of access timestamps. - var offset = ___utimbuf_struct_layout.modtime; + var offset = {{{ C_STRUCTS.utimbuf.modtime }}}; time = {{{ makeGetValue('times', 'offset', 'i32') }}} time *= 1000; } else { @@ -253,27 +244,7 @@ LibraryManager.library = { // sys/stat.h // ========================================================================== - __stat_struct_layout: Runtime.generateStructInfo([ - ['i32', 'st_dev'], - ['i32', '__st_dev_padding'], - ['i32', '__st_ino_truncated'], - ['i32', 'st_mode'], - ['i32', 'st_nlink'], - ['i32', 'st_uid'], - ['i32', 'st_gid'], - ['i32', 'st_rdev'], - ['i32', '__st_rdev_padding'], - ['i32', 'st_size'], - ['i32', 'st_blksize'], - ['i32', 'st_blocks'], - ['i32', 'st_atim_secs'], - ['i32', 'st_atim_nsecs'], - ['i32', 'st_mtim_secs'], - ['i32', 'st_mtim_nsecs'], - ['i32', 'st_ctim_secs'], - ['i32', 'st_ctim_nsecs'], - ['i32', 'st_ino']]), - stat__deps: ['$FS', '__stat_struct_layout'], + stat__deps: ['$FS'], stat: function(path, buf, dontResolveLastLink) { // http://pubs.opengroup.org/onlinepubs/7908799/xsh/stat.html // int stat(const char *path, struct stat *buf); @@ -282,25 +253,25 @@ LibraryManager.library = { path = typeof path !== 'string' ? Pointer_stringify(path) : path; try { var stat = dontResolveLastLink ? FS.lstat(path) : FS.stat(path); - {{{ makeSetValue('buf', '___stat_struct_layout.st_dev', 'stat.dev', 'i32') }}}; - {{{ makeSetValue('buf', '___stat_struct_layout.__st_dev_padding', '0', 'i32') }}}; - {{{ makeSetValue('buf', '___stat_struct_layout.__st_ino_truncated', 'stat.ino', 'i32') }}}; - {{{ makeSetValue('buf', '___stat_struct_layout.st_mode', 'stat.mode', 'i32') }}} - {{{ makeSetValue('buf', '___stat_struct_layout.st_nlink', 'stat.nlink', 'i32') }}} - {{{ makeSetValue('buf', '___stat_struct_layout.st_uid', 'stat.uid', 'i32') }}} - {{{ makeSetValue('buf', '___stat_struct_layout.st_gid', 'stat.gid', 'i32') }}} - {{{ makeSetValue('buf', '___stat_struct_layout.st_rdev', 'stat.rdev', 'i32') }}} - {{{ makeSetValue('buf', '___stat_struct_layout.__st_rdev_padding', '0', 'i32') }}}; - {{{ makeSetValue('buf', '___stat_struct_layout.st_size', 'stat.size', 'i32') }}} - {{{ makeSetValue('buf', '___stat_struct_layout.st_blksize', '4096', 'i32') }}} - {{{ makeSetValue('buf', '___stat_struct_layout.st_blocks', 'stat.blocks', 'i32') }}} - {{{ makeSetValue('buf', '___stat_struct_layout.st_atim_secs', 'Math.floor(stat.atime.getTime() / 1000)', 'i32') }}} - {{{ makeSetValue('buf', '___stat_struct_layout.st_atim_nsecs', '0', 'i32') }}} - {{{ makeSetValue('buf', '___stat_struct_layout.st_mtim_secs', 'Math.floor(stat.mtime.getTime() / 1000)', 'i32') }}} - {{{ makeSetValue('buf', '___stat_struct_layout.st_mtim_nsecs', '0', 'i32') }}} - {{{ makeSetValue('buf', '___stat_struct_layout.st_ctim_secs', 'Math.floor(stat.ctime.getTime() / 1000)', 'i32') }}} - {{{ makeSetValue('buf', '___stat_struct_layout.st_ctim_nsecs', '0', 'i32') }}} - {{{ makeSetValue('buf', '___stat_struct_layout.st_ino', 'stat.ino', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.stat.st_dev, 'stat.dev', 'i32') }}}; + {{{ makeSetValue('buf', C_STRUCTS.stat.__st_dev_padding, '0', 'i32') }}}; + {{{ makeSetValue('buf', C_STRUCTS.stat.__st_ino_truncated, 'stat.ino', 'i32') }}}; + {{{ makeSetValue('buf', C_STRUCTS.stat.st_mode, 'stat.mode', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.stat.st_nlink, 'stat.nlink', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.stat.st_uid, 'stat.uid', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.stat.st_gid, 'stat.gid', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.stat.st_rdev, 'stat.rdev', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.stat.__st_rdev_padding, '0', 'i32') }}}; + {{{ makeSetValue('buf', C_STRUCTS.stat.st_size, 'stat.size', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.stat.st_blksize, '4096', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.stat.st_blocks, 'stat.blocks', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.stat.st_atim.tv_sec, 'Math.floor(stat.atime.getTime() / 1000)', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.stat.st_atim.tv_nsec, '0', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.stat.st_mtim.tv_sec, 'Math.floor(stat.mtime.getTime() / 1000)', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.stat.st_mtim.tv_nsec, '0', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.stat.st_ctim.tv_sec, 'Math.floor(stat.ctime.getTime() / 1000)', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.stat.st_ctim.tv_nsec, '0', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.stat.st_ino, 'stat.ino', 'i32') }}} return 0; } catch (e) { FS.handleFSError(e); @@ -436,43 +407,23 @@ LibraryManager.library = { // sys/statvfs.h // ========================================================================== - __statvfs_struct_layout: Runtime.generateStructInfo([ - ['i32', 'f_bsize'], - ['i32', 'f_frsize'], - ['i32', 'f_blocks'], - ['i32', 'f_bfree'], - ['i32', 'f_bavail'], - ['i32', 'f_files'], - ['i32', 'f_ffree'], - ['i32', 'f_favail'], - ['i32', 'f_fsid'], - ['i32', '__padding'], - ['i32', 'f_flag'], - ['i32', 'f_namemax'], - ['i32', '__reserved_1'], - ['i32', '__reserved_2'], - ['i32', '__reserved_3'], - ['i32', '__reserved_4'], - ['i32', '__reserved_5'], - ['i32', '__reserved_6']]), - statvfs__deps: ['$FS', '__statvfs_struct_layout'], + statvfs__deps: ['$FS'], statvfs: function(path, buf) { // http://pubs.opengroup.org/onlinepubs/009695399/functions/statvfs.html // int statvfs(const char *restrict path, struct statvfs *restrict buf); - var offsets = ___statvfs_struct_layout; // NOTE: None of the constants here are true. We're just returning safe and // sane values. - {{{ makeSetValue('buf', 'offsets.f_bsize', '4096', 'i32') }}} - {{{ makeSetValue('buf', 'offsets.f_frsize', '4096', 'i32') }}} - {{{ makeSetValue('buf', 'offsets.f_blocks', '1000000', 'i32') }}} - {{{ makeSetValue('buf', 'offsets.f_bfree', '500000', 'i32') }}} - {{{ makeSetValue('buf', 'offsets.f_bavail', '500000', 'i32') }}} - {{{ makeSetValue('buf', 'offsets.f_files', 'FS.nextInode', 'i32') }}} - {{{ makeSetValue('buf', 'offsets.f_ffree', '1000000', 'i32') }}} - {{{ makeSetValue('buf', 'offsets.f_favail', '1000000', 'i32') }}} - {{{ makeSetValue('buf', 'offsets.f_fsid', '42', 'i32') }}} - {{{ makeSetValue('buf', 'offsets.f_flag', '2', 'i32') }}} // ST_NOSUID - {{{ makeSetValue('buf', 'offsets.f_namemax', '255', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.statvfs.f_bsize, '4096', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.statvfs.f_frsize, '4096', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.statvfs.f_blocks, '1000000', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.statvfs.f_bfree, '500000', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.statvfs.f_bavail, '500000', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.statvfs.f_files, 'FS.nextInode', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.statvfs.f_ffree, '1000000', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.statvfs.f_favail, '1000000', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.statvfs.f_fsid, '42', 'i32') }}} + {{{ makeSetValue('buf', C_STRUCTS.statvfs.f_flag, '2', 'i32') }}} // ST_NOSUID + {{{ makeSetValue('buf', C_STRUCTS.statvfs.f_namemax, '255', 'i32') }}} return 0; }, fstatvfs__deps: ['statvfs'], @@ -488,13 +439,7 @@ LibraryManager.library = { // fcntl.h // ========================================================================== - __flock_struct_layout: Runtime.generateStructInfo([ - ['i16', 'l_type'], - ['i16', 'l_whence'], - ['i32', 'l_start'], - ['i32', 'l_len'], - ['i16', 'l_pid']]), - open__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', '__dirent_struct_layout'], + open__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'], open: function(path, oflag, varargs) { // int open(const char *path, int oflag, ...); // http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html @@ -523,7 +468,7 @@ LibraryManager.library = { writeArrayToMemory(intArrayFromString(c), template + Pointer_stringify(template).indexOf(rep)); return _creat(template, 0600); }, - fcntl__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', '__flock_struct_layout'], + fcntl__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'], fcntl: function(fildes, cmd, varargs, dup2) { // int fcntl(int fildes, int cmd, ...); // http://pubs.opengroup.org/onlinepubs/009695399/functions/fcntl.html @@ -559,7 +504,7 @@ LibraryManager.library = { case {{{ cDefine('F_GETLK') }}}: case {{{ cDefine('F_GETLK64') }}}: var arg = {{{ makeGetValue('varargs', 0, 'i32') }}}; - var offset = ___flock_struct_layout.l_type; + var offset = {{{ C_STRUCTS.flock.l_type }}}; // We're always unlocked. {{{ makeSetValue('arg', 'offset', cDefine('F_UNLCK'), 'i16') }}} return 0; @@ -621,20 +566,15 @@ LibraryManager.library = { // ========================================================================== __DEFAULT_POLLMASK: {{{ cDefine('POLLIN') }}} | {{{ cDefine('POLLOUT') }}}, - __pollfd_struct_layout: Runtime.generateStructInfo([ - ['i32', 'fd'], - ['i16', 'events'], - ['i16', 'revents']]), - poll__deps: ['$FS', '__DEFAULT_POLLMASK', '__pollfd_struct_layout'], + poll__deps: ['$FS', '__DEFAULT_POLLMASK'], poll: function(fds, nfds, timeout) { // int poll(struct pollfd fds[], nfds_t nfds, int timeout); // http://pubs.opengroup.org/onlinepubs/009695399/functions/poll.html - var offsets = ___pollfd_struct_layout; var nonzero = 0; for (var i = 0; i < nfds; i++) { - var pollfd = fds + ___pollfd_struct_layout.__size__ * i; - var fd = {{{ makeGetValue('pollfd', 'offsets.fd', 'i32') }}}; - var events = {{{ makeGetValue('pollfd', 'offsets.events', 'i16') }}}; + var pollfd = fds + {{{ C_STRUCTS.pollfd.__size__ }}} * i; + var fd = {{{ makeGetValue('pollfd', C_STRUCTS.pollfd.fd, 'i32') }}}; + var events = {{{ makeGetValue('pollfd', C_STRUCTS.pollfd.events, 'i16') }}}; var mask = {{{ cDefine('POLLNVAL') }}}; var stream = FS.getStream(fd); if (stream) { @@ -645,7 +585,7 @@ LibraryManager.library = { } mask &= events | {{{ cDefine('POLLERR') }}} | {{{ cDefine('POLLHUP') }}}; if (mask) nonzero++; - {{{ makeSetValue('pollfd', 'offsets.revents', 'mask', 'i16') }}} + {{{ makeSetValue('pollfd', C_STRUCTS.pollfd.revents, 'mask', 'i16') }}} } return nonzero; }, @@ -5010,17 +4950,11 @@ LibraryManager.library = { {{{ makeSetValue('cosine', '0', 'cosineVal', 'float') }}}; }, - __div_t_struct_layout: Runtime.generateStructInfo([ - ['i32', 'quot'], - ['i32', 'rem'], - ]), - div__deps: ['__div_t_struct_layout'], div: function(divt, numer, denom) { var quot = Math.floor(numer / denom); var rem = numer - quot * denom; - var offset = ___div_t_struct_layout.rem; - {{{ makeSetValue('divt', '0', 'quot', 'i32') }}}; - {{{ makeSetValue('divt', 'offset', 'rem', 'i32') }}}; + {{{ makeSetValue('divt', C_STRUCTS.div_t.quot, 'quot', 'i32') }}}; + {{{ makeSetValue('divt', C_STRUCTS.div_t.rem, 'rem', 'i32') }}}; return divt; }, @@ -5039,19 +4973,12 @@ LibraryManager.library = { // sys/utsname.h // ========================================================================== - __utsname_struct_layout: Runtime.generateStructInfo([ - ['b65', 'sysname'], - ['b65', 'nodename'], - ['b65', 'release'], - ['b65', 'version'], - ['b65', 'machine'], - ['b65', 'domainname']]), - uname__deps: ['__utsname_struct_layout'], uname: function(name) { // int uname(struct utsname *name); // http://pubs.opengroup.org/onlinepubs/009695399/functions/uname.html + var layout = {{{ JSON.stringify(C_STRUCTS.utsname) }}}; function copyString(element, value) { - var offset = ___utsname_struct_layout[element]; + var offset = layout[element]; for (var i = 0; i < value.length; i++) { {{{ makeSetValue('name', 'offset + i', 'value.charCodeAt(i)', 'i8') }}} } @@ -5347,62 +5274,48 @@ LibraryManager.library = { return time1 - time0; }, - __tm_struct_layout: Runtime.generateStructInfo([ - ['i32', 'tm_sec'], - ['i32', 'tm_min'], - ['i32', 'tm_hour'], - ['i32', 'tm_mday'], - ['i32', 'tm_mon'], - ['i32', 'tm_year'], - ['i32', 'tm_wday'], - ['i32', 'tm_yday'], - ['i32', 'tm_isdst'], - ['i32', 'tm_gmtoff'], - ['i8*', 'tm_zone']]), - // Statically allocated time struct. + // Statically allocated time struct. (TODO: Shouldn't C_STRUCTS.tm.__size__ be used here?) __tm_current: 'allocate({{{ Runtime.QUANTUM_SIZE }}}*26, "i8", ALLOC_STATIC)', // Statically allocated timezone string. We only use GMT as a timezone. __tm_timezone: 'allocate(intArrayFromString("GMT"), "i8", ALLOC_STATIC)', // Statically allocated time strings. __tm_formatted: 'allocate({{{ Runtime.QUANTUM_SIZE }}}*26, "i8", ALLOC_STATIC)', - mktime__deps: ['__tm_struct_layout', 'tzset'], + mktime__deps: ['tzset'], mktime: function(tmPtr) { _tzset(); - var offsets = ___tm_struct_layout; - var year = {{{ makeGetValue('tmPtr', 'offsets.tm_year', 'i32') }}}; + var year = {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_year, 'i32') }}}; var timestamp = new Date(year >= 1900 ? year : year + 1900, - {{{ makeGetValue('tmPtr', 'offsets.tm_mon', 'i32') }}}, - {{{ makeGetValue('tmPtr', 'offsets.tm_mday', 'i32') }}}, - {{{ makeGetValue('tmPtr', 'offsets.tm_hour', 'i32') }}}, - {{{ makeGetValue('tmPtr', 'offsets.tm_min', 'i32') }}}, - {{{ makeGetValue('tmPtr', 'offsets.tm_sec', 'i32') }}}, + {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_mon, 'i32') }}}, + {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_mday, 'i32') }}}, + {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_hour, 'i32') }}}, + {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_min, 'i32') }}}, + {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_sec, 'i32') }}}, 0).getTime() / 1000; - {{{ makeSetValue('tmPtr', 'offsets.tm_wday', 'new Date(timestamp).getDay()', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_wday, 'new Date(timestamp).getDay()', 'i32') }}} var yday = Math.round((timestamp - (new Date(year, 0, 1)).getTime()) / (1000 * 60 * 60 * 24)); - {{{ makeSetValue('tmPtr', 'offsets.tm_yday', 'yday', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_yday, 'yday', 'i32') }}} return timestamp; }, timelocal: 'mktime', - gmtime__deps: ['malloc', '__tm_struct_layout', '__tm_current', 'gmtime_r'], + gmtime__deps: ['malloc', '__tm_current', 'gmtime_r'], gmtime: function(time) { return _gmtime_r(time, ___tm_current); }, - gmtime_r__deps: ['__tm_struct_layout', '__tm_timezone'], + gmtime_r__deps: ['__tm_timezone'], gmtime_r: function(time, tmPtr) { var date = new Date({{{ makeGetValue('time', 0, 'i32') }}}*1000); - var offsets = ___tm_struct_layout; - {{{ makeSetValue('tmPtr', 'offsets.tm_sec', 'date.getUTCSeconds()', 'i32') }}} - {{{ makeSetValue('tmPtr', 'offsets.tm_min', 'date.getUTCMinutes()', 'i32') }}} - {{{ makeSetValue('tmPtr', 'offsets.tm_hour', 'date.getUTCHours()', 'i32') }}} - {{{ makeSetValue('tmPtr', 'offsets.tm_mday', 'date.getUTCDate()', 'i32') }}} - {{{ makeSetValue('tmPtr', 'offsets.tm_mon', 'date.getUTCMonth()', 'i32') }}} - {{{ makeSetValue('tmPtr', 'offsets.tm_year', 'date.getUTCFullYear()-1900', 'i32') }}} - {{{ makeSetValue('tmPtr', 'offsets.tm_wday', 'date.getUTCDay()', 'i32') }}} - {{{ makeSetValue('tmPtr', 'offsets.tm_gmtoff', '0', 'i32') }}} - {{{ makeSetValue('tmPtr', 'offsets.tm_isdst', '0', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_sec, 'date.getUTCSeconds()', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_min, 'date.getUTCMinutes()', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_hour, 'date.getUTCHours()', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_mday, 'date.getUTCDate()', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_mon, 'date.getUTCMonth()', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_year, 'date.getUTCFullYear()-1900', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_wday, 'date.getUTCDay()', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_gmtoff, '0', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_isdst, '0', 'i32') }}} var start = new Date(date); // define date using UTC, start from Jan 01 00:00:00 UTC start.setUTCDate(1); start.setUTCMonth(0); @@ -5411,8 +5324,8 @@ LibraryManager.library = { start.setUTCSeconds(0); start.setUTCMilliseconds(0); var yday = Math.floor((date.getTime() - start.getTime()) / (1000 * 60 * 60 * 24)); - {{{ makeSetValue('tmPtr', 'offsets.tm_yday', 'yday', 'i32') }}} - {{{ makeSetValue('tmPtr', 'offsets.tm_zone', '___tm_timezone', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_yday, 'yday', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_zone, '___tm_timezone', 'i32') }}} return tmPtr; }, @@ -5426,33 +5339,32 @@ LibraryManager.library = { return ret; }, - localtime__deps: ['malloc', '__tm_struct_layout', '__tm_current', 'localtime_r'], + localtime__deps: ['malloc', '__tm_current', 'localtime_r'], localtime: function(time) { return _localtime_r(time, ___tm_current); }, - localtime_r__deps: ['__tm_struct_layout', '__tm_timezone', 'tzset'], + localtime_r__deps: ['__tm_timezone', 'tzset'], localtime_r: function(time, tmPtr) { _tzset(); - var offsets = ___tm_struct_layout; var date = new Date({{{ makeGetValue('time', 0, 'i32') }}}*1000); - {{{ makeSetValue('tmPtr', 'offsets.tm_sec', 'date.getSeconds()', 'i32') }}} - {{{ makeSetValue('tmPtr', 'offsets.tm_min', 'date.getMinutes()', 'i32') }}} - {{{ makeSetValue('tmPtr', 'offsets.tm_hour', 'date.getHours()', 'i32') }}} - {{{ makeSetValue('tmPtr', 'offsets.tm_mday', 'date.getDate()', 'i32') }}} - {{{ makeSetValue('tmPtr', 'offsets.tm_mon', 'date.getMonth()', 'i32') }}} - {{{ makeSetValue('tmPtr', 'offsets.tm_year', 'date.getFullYear()-1900', 'i32') }}} - {{{ makeSetValue('tmPtr', 'offsets.tm_wday', 'date.getDay()', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_sec, 'date.getSeconds()', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_min, 'date.getMinutes()', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_hour, 'date.getHours()', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_mday, 'date.getDate()', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_mon, 'date.getMonth()', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_year, 'date.getFullYear()-1900', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_wday, 'date.getDay()', 'i32') }}} var start = new Date(date.getFullYear(), 0, 1); var yday = Math.floor((date.getTime() - start.getTime()) / (1000 * 60 * 60 * 24)); - {{{ makeSetValue('tmPtr', 'offsets.tm_yday', 'yday', 'i32') }}} - {{{ makeSetValue('tmPtr', 'offsets.tm_gmtoff', 'start.getTimezoneOffset() * 60', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_yday, 'yday', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_gmtoff, 'start.getTimezoneOffset() * 60', 'i32') }}} var dst = Number(start.getTimezoneOffset() != date.getTimezoneOffset()); - {{{ makeSetValue('tmPtr', 'offsets.tm_isdst', 'dst', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_isdst, 'dst', 'i32') }}} - {{{ makeSetValue('tmPtr', 'offsets.tm_zone', '___tm_timezone', 'i32') }}} + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_zone, '___tm_timezone', 'i32') }}} return tmPtr; }, @@ -5563,21 +5475,21 @@ LibraryManager.library = { return newDate; }, - strftime__deps: ['__tm_struct_layout', '_isLeapYear', '_arraySum', '_addDays', '_MONTH_DAYS_REGULAR', '_MONTH_DAYS_LEAP'], + strftime__deps: ['_isLeapYear', '_arraySum', '_addDays', '_MONTH_DAYS_REGULAR', '_MONTH_DAYS_LEAP'], strftime: function(s, maxsize, format, tm) { // size_t strftime(char *restrict s, size_t maxsize, const char *restrict format, const struct tm *restrict timeptr); // http://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html var date = { - tm_sec: {{{ makeGetValue('tm', '___tm_struct_layout.tm_sec', 'i32') }}}, - tm_min: {{{ makeGetValue('tm', '___tm_struct_layout.tm_min', 'i32') }}}, - tm_hour: {{{ makeGetValue('tm', '___tm_struct_layout.tm_hour', 'i32') }}}, - tm_mday: {{{ makeGetValue('tm', '___tm_struct_layout.tm_mday', 'i32') }}}, - tm_mon: {{{ makeGetValue('tm', '___tm_struct_layout.tm_mon', 'i32') }}}, - tm_year: {{{ makeGetValue('tm', '___tm_struct_layout.tm_year', 'i32') }}}, - tm_wday: {{{ makeGetValue('tm', '___tm_struct_layout.tm_wday', 'i32') }}}, - tm_yday: {{{ makeGetValue('tm', '___tm_struct_layout.tm_yday', 'i32') }}}, - tm_isdst: {{{ makeGetValue('tm', '___tm_struct_layout.tm_isdst', 'i32') }}} + tm_sec: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_sec, 'i32') }}}, + tm_min: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_min, 'i32') }}}, + tm_hour: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_hour, 'i32') }}}, + tm_mday: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_mday, 'i32') }}}, + tm_mon: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_mon, 'i32') }}}, + tm_year: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_year, 'i32') }}}, + tm_wday: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_wday, 'i32') }}}, + tm_yday: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_yday, 'i32') }}}, + tm_isdst: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_isdst, 'i32') }}} }; var pattern = Pointer_stringify(format); @@ -5860,7 +5772,7 @@ LibraryManager.library = { }, strftime_l: 'strftime', // no locale support yet - strptime__deps: ['__tm_struct_layout', '_isLeapYear', '_arraySum', '_addDays', '_MONTH_DAYS_REGULAR', '_MONTH_DAYS_LEAP'], + strptime__deps: ['_isLeapYear', '_arraySum', '_addDays', '_MONTH_DAYS_REGULAR', '_MONTH_DAYS_LEAP'], strptime: function(buf, format, tm) { // char *strptime(const char *restrict buf, const char *restrict format, struct tm *restrict tm); // http://pubs.opengroup.org/onlinepubs/009695399/functions/strptime.html @@ -5938,12 +5850,12 @@ LibraryManager.library = { return (typeof value !== 'number' || isNaN(value)) ? min : (value>=min ? (value<=max ? value: max): min); }; return { - year: fixup({{{ makeGetValue('tm', '___tm_struct_layout.tm_year', 'i32', 0, 0, 1) }}} + 1900 , 1970, 9999), - month: fixup({{{ makeGetValue('tm', '___tm_struct_layout.tm_mon', 'i32', 0, 0, 1) }}}, 0, 11), - day: fixup({{{ makeGetValue('tm', '___tm_struct_layout.tm_mday', 'i32', 0, 0, 1) }}}, 1, 31), - hour: fixup({{{ makeGetValue('tm', '___tm_struct_layout.tm_hour', 'i32', 0, 0, 1) }}}, 0, 23), - min: fixup({{{ makeGetValue('tm', '___tm_struct_layout.tm_min', 'i32', 0, 0, 1) }}}, 0, 59), - sec: fixup({{{ makeGetValue('tm', '___tm_struct_layout.tm_sec', 'i32', 0, 0, 1) }}}, 0, 59) + year: fixup({{{ makeGetValue('tm', C_STRUCTS.tm.tm_year, 'i32', 0, 0, 1) }}} + 1900 , 1970, 9999), + month: fixup({{{ makeGetValue('tm', C_STRUCTS.tm.tm_mon, 'i32', 0, 0, 1) }}}, 0, 11), + day: fixup({{{ makeGetValue('tm', C_STRUCTS.tm.tm_mday, 'i32', 0, 0, 1) }}}, 1, 31), + hour: fixup({{{ makeGetValue('tm', C_STRUCTS.tm.tm_hour, 'i32', 0, 0, 1) }}}, 0, 23), + min: fixup({{{ makeGetValue('tm', C_STRUCTS.tm.tm_min, 'i32', 0, 0, 1) }}}, 0, 59), + sec: fixup({{{ makeGetValue('tm', C_STRUCTS.tm.tm_sec, 'i32', 0, 0, 1) }}}, 0, 59) }; }; @@ -6083,15 +5995,15 @@ LibraryManager.library = { */ var fullDate = new Date(date.year, date.month, date.day, date.hour, date.min, date.sec, 0); - {{{ makeSetValue('tm', '___tm_struct_layout.tm_sec', 'fullDate.getSeconds()', 'i32') }}} - {{{ makeSetValue('tm', '___tm_struct_layout.tm_min', 'fullDate.getMinutes()', 'i32') }}} - {{{ makeSetValue('tm', '___tm_struct_layout.tm_hour', 'fullDate.getHours()', 'i32') }}} - {{{ makeSetValue('tm', '___tm_struct_layout.tm_mday', 'fullDate.getDate()', 'i32') }}} - {{{ makeSetValue('tm', '___tm_struct_layout.tm_mon', 'fullDate.getMonth()', 'i32') }}} - {{{ makeSetValue('tm', '___tm_struct_layout.tm_year', 'fullDate.getFullYear()-1900', 'i32') }}} - {{{ makeSetValue('tm', '___tm_struct_layout.tm_wday', 'fullDate.getDay()', 'i32') }}} - {{{ makeSetValue('tm', '___tm_struct_layout.tm_yday', '__arraySum(__isLeapYear(fullDate.getFullYear()) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, fullDate.getMonth()-1)+fullDate.getDate()-1', 'i32') }}} - {{{ makeSetValue('tm', '___tm_struct_layout.tm_isdst', '0', 'i32') }}} + {{{ makeSetValue('tm', C_STRUCTS.tm.tm_sec, 'fullDate.getSeconds()', 'i32') }}} + {{{ makeSetValue('tm', C_STRUCTS.tm.tm_min, 'fullDate.getMinutes()', 'i32') }}} + {{{ makeSetValue('tm', C_STRUCTS.tm.tm_hour, 'fullDate.getHours()', 'i32') }}} + {{{ makeSetValue('tm', C_STRUCTS.tm.tm_mday, 'fullDate.getDate()', 'i32') }}} + {{{ makeSetValue('tm', C_STRUCTS.tm.tm_mon, 'fullDate.getMonth()', 'i32') }}} + {{{ makeSetValue('tm', C_STRUCTS.tm.tm_year, 'fullDate.getFullYear()-1900', 'i32') }}} + {{{ makeSetValue('tm', C_STRUCTS.tm.tm_wday, 'fullDate.getDay()', 'i32') }}} + {{{ makeSetValue('tm', C_STRUCTS.tm.tm_yday, '__arraySum(__isLeapYear(fullDate.getFullYear()) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, fullDate.getMonth()-1)+fullDate.getDate()-1', 'i32') }}} + {{{ makeSetValue('tm', C_STRUCTS.tm.tm_isdst, '0', 'i32') }}} // we need to convert the matched sequence into an integer array to take care of UTF-8 characters > 0x7F // TODO: not sure that intArrayFromString handles all unicode characters correctly @@ -6116,25 +6028,21 @@ LibraryManager.library = { // sys/time.h // ========================================================================== - __timespec_struct_layout: Runtime.generateStructInfo([ - ['i32', 'tv_sec'], - ['i32', 'tv_nsec']]), - nanosleep__deps: ['usleep', '__timespec_struct_layout'], + nanosleep__deps: ['usleep'], nanosleep: function(rqtp, rmtp) { // int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); - var seconds = {{{ makeGetValue('rqtp', '___timespec_struct_layout.tv_sec', 'i32') }}}; - var nanoseconds = {{{ makeGetValue('rqtp', '___timespec_struct_layout.tv_nsec', 'i32') }}}; - {{{ makeSetValue('rmtp', '___timespec_struct_layout.tv_sec', '0', 'i32') }}} - {{{ makeSetValue('rmtp', '___timespec_struct_layout.tv_nsec', '0', 'i32') }}} + var seconds = {{{ makeGetValue('rqtp', C_STRUCTS.timespec.tv_sec, 'i32') }}}; + var nanoseconds = {{{ makeGetValue('rqtp', C_STRUCTS.timespec.tv_nsec, 'i32') }}}; + {{{ makeSetValue('rmtp', C_STRUCTS.timespec.tv_sec, '0', 'i32') }}} + {{{ makeSetValue('rmtp', C_STRUCTS.timespec.tv_nsec, '0', 'i32') }}} return _usleep((seconds * 1e6) + (nanoseconds / 1000)); }, // TODO: Implement these for real. - clock_gettime__deps: ['__timespec_struct_layout'], clock_gettime: function(clk_id, tp) { // int clock_gettime(clockid_t clk_id, struct timespec *tp); var now = Date.now(); - {{{ makeSetValue('tp', '___timespec_struct_layout.tv_sec', 'Math.floor(now/1000)', 'i32') }}}; // seconds - {{{ makeSetValue('tp', '___timespec_struct_layout.tv_nsec', '(now % 1000) * 1000 * 1000', 'i32') }}}; // nanoseconds (really milliseconds) + {{{ makeSetValue('tp', C_STRUCTS.timespec.tv_sec, 'Math.floor(now/1000)', 'i32') }}}; // seconds + {{{ makeSetValue('tp', C_STRUCTS.timespec.tv_nsec, '(now % 1000) * 1000 * 1000', 'i32') }}}; // nanoseconds (really milliseconds) return 0; }, clock_settime: function(clk_id, tp) { @@ -6142,28 +6050,26 @@ LibraryManager.library = { // Nothing. return 0; }, - clock_getres__deps: ['__timespec_struct_layout'], clock_getres: function(clk_id, res) { // int clock_getres(clockid_t clk_id, struct timespec *res); - {{{ makeSetValue('res', '___timespec_struct_layout.tv_sec', '1', 'i32') }}} - {{{ makeSetValue('res', '___timespec_struct_layout.tv_nsec', '1000 * 1000', 'i32') }}} // resolution is milliseconds + {{{ makeSetValue('res', C_STRUCTS.timespec.tv_sec, '1', 'i32') }}} + {{{ makeSetValue('res', C_STRUCTS.timespec.tv_nsec, '1000 * 1000', 'i32') }}} // resolution is milliseconds return 0; }, // http://pubs.opengroup.org/onlinepubs/000095399/basedefs/sys/time.h.html gettimeofday: function(ptr) { - // %struct.timeval = type { i32, i32 } - {{{ (LibraryManager.structs.gettimeofday = Runtime.calculateStructAlignment({ fields: ['i32', 'i32'] }), null) }}} var now = Date.now(); - {{{ makeSetValue('ptr', LibraryManager.structs.gettimeofday[0], 'Math.floor(now/1000)', 'i32') }}}; // seconds - {{{ makeSetValue('ptr', LibraryManager.structs.gettimeofday[1], 'Math.floor((now-1000*Math.floor(now/1000))*1000)', 'i32') }}}; // microseconds + {{{ makeSetValue('ptr', C_STRUCTS.timeval.tv_sec, 'Math.floor(now/1000)', 'i32') }}}; // seconds + {{{ makeSetValue('ptr', C_STRUCTS.timeval.tv_usec, 'Math.floor((now-1000*Math.floor(now/1000))*1000)', 'i32') }}}; // microseconds return 0; }, // ========================================================================== // sys/timeb.h // ========================================================================== - + + // TODO: Where did this header go? __timeb_struct_layout: Runtime.generateStructInfo([ ['i32', 'time'], ['i16', 'millitm'], @@ -6184,18 +6090,13 @@ LibraryManager.library = { // sys/times.h // ========================================================================== - __tms_struct_layout: Runtime.generateStructInfo([ - ['i32', 'tms_utime'], - ['i32', 'tms_stime'], - ['i32', 'tms_cutime'], - ['i32', 'tms_cstime']]), - times__deps: ['__tms_struct_layout', 'memset'], + times__deps: ['memset'], times: function(buffer) { // clock_t times(struct tms *buffer); // http://pubs.opengroup.org/onlinepubs/009695399/functions/times.html // NOTE: This is fake, since we can't calculate real CPU time usage in JS. if (buffer !== 0) { - _memset(buffer, 0, ___tms_struct_layout.__size__); + _memset(buffer, 0, {{{ C_STRUCTS.tms.__size__ }}}); } return 0; }, @@ -6853,14 +6754,10 @@ LibraryManager.library = { // ========================================================================== // TODO: Implement for real. - __rlimit_struct_layout: Runtime.generateStructInfo([ - ['i32', 'rlim_cur'], - ['i32', 'rlim_max']]), - getrlimit__deps: ['__rlimit_struct_layout'], getrlimit: function(resource, rlp) { // int getrlimit(int resource, struct rlimit *rlp); - {{{ makeSetValue('rlp', '___rlimit_struct_layout.rlim_cur', '-1', 'i32') }}} // RLIM_INFINITY - {{{ makeSetValue('rlp', '___rlimit_struct_layout.rlim_max', '-1', 'i32') }}} // RLIM_INFINITY + {{{ makeSetValue('rlp', C_STRUCTS.rlimit.rlim_cur, '-1', 'i32') }}} // RLIM_INFINITY + {{{ makeSetValue('rlp', C_STRUCTS.rlimit.rlim_max, '-1', 'i32') }}} // RLIM_INFINITY return 0; }, setrlimit: function(resource, rlp) { @@ -6870,33 +6767,12 @@ LibraryManager.library = { __01getrlimit64_: 'getrlimit', // TODO: Implement for real. We just do time used, and no useful data - __rusage_struct_layout: Runtime.generateStructInfo([ - ['i64', 'ru_utime'], - ['i64', 'ru_stime'], - ['i32', 'ru_maxrss'], - ['i32', 'ru_ixrss'], - ['i32', 'ru_idrss'], - ['i32', 'ru_isrss'], - ['i32', 'ru_minflt'], - ['i32', 'ru_majflt'], - ['i32', 'ru_nswap'], - ['i32', 'ru_inblock'], - ['i32', 'ru_oublock'], - ['i32', 'ru_msgsnd'], - ['i32', 'ru_msgrcv'], - ['i32', 'ru_nsignals'], - ['i32', 'ru_nvcsw'], - ['i32', 'ru_nivcsw']]), - getrusage__deps: ['__rusage_struct_layout'], getrusage: function(resource, rlp) { - // %struct.timeval = type { i32, i32 } - var timeval = Runtime.calculateStructAlignment({ fields: ['i32', 'i32'] }); - // int getrusage(int resource, struct rusage *rlp); - {{{ makeSetValue('rlp', '___rusage_struct_layout.ru_utime+timeval[0]', '1', 'i32') }}} - {{{ makeSetValue('rlp', '___rusage_struct_layout.ru_utime+timeval[1]', '2', 'i32') }}} - {{{ makeSetValue('rlp', '___rusage_struct_layout.ru_stime+timeval[0]', '3', 'i32') }}} - {{{ makeSetValue('rlp', '___rusage_struct_layout.ru_stime+timeval[1]', '4', 'i32') }}} + {{{ makeSetValue('rlp', C_STRUCTS.rusage.ru_utime.tv_sec, '1', 'i32') }}} + {{{ makeSetValue('rlp', C_STRUCTS.rusage.ru_utime.tv_usec, '2', 'i32') }}} + {{{ makeSetValue('rlp', C_STRUCTS.rusage.ru_stime.tv_sec, '3', 'i32') }}} + {{{ makeSetValue('rlp', C_STRUCTS.rusage.ru_stime.tv_usec, '4', 'i32') }}} return 0; }, @@ -7404,25 +7280,6 @@ LibraryManager.library = { }, // note: lots of leaking here! - __hostent_struct_layout: Runtime.generateStructInfo([ - ['i8*', 'h_name'], - ['i8**', 'h_aliases'], - ['i32', 'h_addrtype'], - ['i32', 'h_length'], - ['i8**', 'h_addr_list'], - ]), - - _addrinfo_layout: Runtime.generateStructInfo([ - ['i32', 'ai_flags'], - ['i32', 'ai_family'], - ['i32', 'ai_socktype'], - ['i32', 'ai_protocol'], - ['i32', 'ai_addrlen'], - ['*', 'ai_addr'], - ['*', 'ai_canonname'], - ['*', 'ai_next'] - ]), - gethostbyaddr__deps: ['$DNS', 'gethostbyname', '_inet_ntop4_raw'], gethostbyaddr: function (addr, addrlen, type) { if (type !== {{{ cDefine('AF_INET') }}}) { @@ -7439,40 +7296,40 @@ LibraryManager.library = { return _gethostbyname(hostp); }, - gethostbyname__deps: ['$DNS', '__hostent_struct_layout', '_inet_pton4_raw'], + gethostbyname__deps: ['$DNS', '_inet_pton4_raw'], gethostbyname: function(name) { name = Pointer_stringify(name); // generate hostent - var ret = _malloc(___hostent_struct_layout.__size__); // XXX possibly leaked, as are others here + var ret = _malloc({{{ C_STRUCTS.hostent.__size__ }}}); // XXX possibly leaked, as are others here var nameBuf = _malloc(name.length+1); writeStringToMemory(name, nameBuf); - {{{ makeSetValue('ret', '___hostent_struct_layout.h_name', 'nameBuf', 'i8*') }}} + {{{ makeSetValue('ret', C_STRUCTS.hostent.h_name, 'nameBuf', 'i8*') }}} var aliasesBuf = _malloc(4); {{{ makeSetValue('aliasesBuf', '0', '0', 'i8*') }}} - {{{ makeSetValue('ret', '___hostent_struct_layout.h_aliases', 'aliasesBuf', 'i8**') }}} + {{{ makeSetValue('ret', C_STRUCTS.hostent.h_aliases, 'aliasesBuf', 'i8**') }}} var afinet = {{{ cDefine('AF_INET') }}}; - {{{ makeSetValue('ret', '___hostent_struct_layout.h_addrtype', 'afinet', 'i32') }}} - {{{ makeSetValue('ret', '___hostent_struct_layout.h_length', '4', 'i32') }}} + {{{ makeSetValue('ret', C_STRUCTS.hostent.h_addrtype, 'afinet', 'i32') }}} + {{{ makeSetValue('ret', C_STRUCTS.hostent.h_length, '4', 'i32') }}} var addrListBuf = _malloc(12); {{{ makeSetValue('addrListBuf', '0', 'addrListBuf+8', 'i32*') }}} {{{ makeSetValue('addrListBuf', '4', '0', 'i32*') }}} {{{ makeSetValue('addrListBuf', '8', '__inet_pton4_raw(DNS.lookup_name(name))', 'i32') }}} - {{{ makeSetValue('ret', '___hostent_struct_layout.h_addr_list', 'addrListBuf', 'i8**') }}} + {{{ makeSetValue('ret', C_STRUCTS.hostent.h_addr_list, 'addrListBuf', 'i8**') }}} return ret; }, gethostbyname_r__deps: ['gethostbyname'], gethostbyname_r: function(name, ret, buf, buflen, out, err) { var data = _gethostbyname(name); - _memcpy(ret, data, ___hostent_struct_layout.__size__); + _memcpy(ret, data, {{{ C_STRUCTS.hostent.__size__ }}}); _free(data); {{{ makeSetValue('err', '0', '0', 'i32') }}}; {{{ makeSetValue('out', '0', 'ret', '*') }}}; return 0; }, - getaddrinfo__deps: ['$Sockets', '$DNS', '_addrinfo_layout', '_inet_pton4_raw', '_inet_ntop4_raw', '_inet_pton6_raw', '_inet_ntop6_raw', '_write_sockaddr', 'htonl'], + getaddrinfo__deps: ['$Sockets', '$DNS', '_inet_pton4_raw', '_inet_ntop4_raw', '_inet_pton6_raw', '_inet_ntop6_raw', '_write_sockaddr', 'htonl'], getaddrinfo: function(node, service, hint, out) { var addrs = []; var canon = null; @@ -7489,8 +7346,8 @@ LibraryManager.library = { var res; salen = family === {{{ cDefine('AF_INET6') }}} ? - Sockets.sockaddr_in6_layout.__size__ : - Sockets.sockaddr_in_layout.__size__; + {{{ C_STRUCTS.sockaddr_in6.__size__ }}} : + {{{ C_STRUCTS.sockaddr_in.__size__ }}}; addr = family === {{{ cDefine('AF_INET6') }}} ? __inet_ntop6_raw(addr) : __inet_ntop4_raw(addr); @@ -7498,28 +7355,28 @@ LibraryManager.library = { res = __write_sockaddr(sa, family, addr, port); assert(!res.errno); - ai = _malloc(__addrinfo_layout.__size__); - {{{ makeSetValue('ai', '__addrinfo_layout.ai_family', 'family', 'i32') }}}; - {{{ makeSetValue('ai', '__addrinfo_layout.ai_socktype', 'type', 'i32') }}}; - {{{ makeSetValue('ai', '__addrinfo_layout.ai_protocol', 'proto', 'i32') }}}; + ai = _malloc({{{ C_STRUCTS.addrinfo.__size__ }}}); + {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_family, 'family', 'i32') }}}; + {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_socktype, 'type', 'i32') }}}; + {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_protocol, 'proto', 'i32') }}}; if (canon) { - {{{ makeSetValue('ai', '__addrinfo_layout.ai_canonname', 'canon', 'i32') }}}; + {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_canonname, 'canon', 'i32') }}}; } - {{{ makeSetValue('ai', '__addrinfo_layout.ai_addr', 'sa', '*') }}}; + {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_addr, 'sa', '*') }}}; if (family === {{{ cDefine('AF_INET6') }}}) { - {{{ makeSetValue('ai', '__addrinfo_layout.ai_addrlen', 'Sockets.sockaddr_in6_layout.__size__', 'i32') }}}; + {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_addrlen, C_STRUCTS.sockaddr_in6.__size__, 'i32') }}}; } else { - {{{ makeSetValue('ai', '__addrinfo_layout.ai_addrlen', 'Sockets.sockaddr_in_layout.__size__', 'i32') }}}; + {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_addrlen, C_STRUCTS.sockaddr_in.__size__, 'i32') }}}; } return ai; } if (hint) { - flags = {{{ makeGetValue('hint', '__addrinfo_layout.ai_flags', 'i32') }}}; - family = {{{ makeGetValue('hint', '__addrinfo_layout.ai_family', 'i32') }}}; - type = {{{ makeGetValue('hint', '__addrinfo_layout.ai_socktype', 'i32') }}}; - proto = {{{ makeGetValue('hint', '__addrinfo_layout.ai_protocol', 'i32') }}}; + flags = {{{ makeGetValue('hint', C_STRUCTS.addrinfo.ai_flags, 'i32') }}}; + family = {{{ makeGetValue('hint', C_STRUCTS.addrinfo.ai_family, 'i32') }}}; + type = {{{ makeGetValue('hint', C_STRUCTS.addrinfo.ai_socktype, 'i32') }}}; + proto = {{{ makeGetValue('hint', C_STRUCTS.addrinfo.ai_protocol, 'i32') }}}; } if (type && !proto) { proto = type === {{{ cDefine('SOCK_DGRAM') }}} ? {{{ cDefine('IPPROTO_UDP') }}} : {{{ cDefine('IPPROTO_TCP') }}}; @@ -7535,7 +7392,7 @@ LibraryManager.library = { {{{ cDefine('AI_NUMERICSERV') }}}|{{{ cDefine('AI_V4MAPPED') }}}|{{{ cDefine('AI_ALL') }}}|{{{ cDefine('AI_ADDRCONFIG') }}})) { return {{{ cDefine('EAI_BADFLAGS') }}}; } - if (({{{ makeGetValue('hint', '__addrinfo_layout.ai_flags', 'i32') }}} & {{{ cDefine('AI_CANONNAME') }}}) && !node) { + if (({{{ makeGetValue('hint', C_STRUCTS.addrinfo.ai_flags, 'i32') }}} & {{{ cDefine('AI_CANONNAME') }}}) && !node) { return {{{ cDefine('EAI_BADFLAGS') }}}; } if (flags & {{{ cDefine('AI_ADDRCONFIG') }}}) { @@ -7631,14 +7488,14 @@ LibraryManager.library = { return 0; }, - freeaddrinfo__deps: ['$Sockets', '_addrinfo_layout'], + freeaddrinfo__deps: ['$Sockets'], freeaddrinfo: function(ai) { - var sa = {{{ makeGetValue('ai', '__addrinfo_layout.ai_addr', '*') }}}; + var sa = {{{ makeGetValue('ai', C_STRUCTS.addrinfo.ai_addr, '*') }}}; _free(sa); _free(ai); }, - getnameinfo__deps: ['$Sockets', '$DNS', '__hostent_struct_layout', '_read_sockaddr'], + getnameinfo__deps: ['$Sockets', '$DNS', '_read_sockaddr'], getnameinfo: function (sa, salen, node, nodelen, serv, servlen, flags) { var info = __read_sockaddr(sa, salen); if (info.errno) { @@ -7705,33 +7562,7 @@ LibraryManager.library = { localAddr: 0xfe00000a, // Local address is always 10.0.0.254 addrPool: [ 0x0200000a, 0x0300000a, 0x0400000a, 0x0500000a, 0x0600000a, 0x0700000a, 0x0800000a, 0x0900000a, 0x0a00000a, - 0x0b00000a, 0x0c00000a, 0x0d00000a, 0x0e00000a], /* 0x0100000a is reserved */ - sockaddr_in_layout: Runtime.generateStructInfo([ - ['i16', 'sin_family'], - ['i16', 'sin_port'], - ['i32', 'sin_addr'], - ['b8', 'sin_zero'], - ]), - sockaddr_in6_layout: Runtime.generateStructInfo([ - ['i16', 'sin6_family'], - ['i16', 'sin6_port'], - ['i32', 'sin6_flowinfo'], - ['b16', 'sin6_addr'], - ['i32', 'sin6_scope_id'] - ]), - msghdr_layout: Runtime.generateStructInfo([ - ['*', 'msg_name'], - ['i32', 'msg_namelen'], - ['*', 'msg_iov'], - ['i32', 'msg_iovlen'], - ['*', 'msg_control'], - ['i32', 'msg_controllen'], - ['i32', 'msg_flags'], - ]), - iovec_layout: Runtime.generateStructInfo([ - ['i8*', 'iov_base'], - ['i32', 'iov_len'] - ]) + 0x0b00000a, 0x0c00000a, 0x0d00000a, 0x0e00000a] /* 0x0100000a is reserved */ }, #if SOCKET_WEBRTC @@ -7895,8 +7726,8 @@ LibraryManager.library = { var info = FS.getStream(fd); if (!info) return -1; if (addr) { - info.port = _ntohs(getValue(addr + Sockets.sockaddr_in_layout.sin_port, 'i16')); - // info.addr = getValue(addr + Sockets.sockaddr_in_layout.sin_addr, 'i32'); + info.port = _ntohs(getValue(addr + {{{ C_STRUCTS.sockaddr_in.sin_port }}}, 'i16')); + // info.addr = getValue(addr + {{{ C_STRUCTS.sockaddr_in.sin_addr.s_addr }}}, 'i32'); } if (!info.port) { info.port = _mkport(); @@ -7920,10 +7751,10 @@ LibraryManager.library = { _bind(fd); } - var name = {{{ makeGetValue('msg', 'Sockets.msghdr_layout.msg_name', '*') }}}; + var name = {{{ makeGetValue('msg', C_STRUCTS.msghdr.msg_name, '*') }}}; assert(name, 'sendmsg on non-connected socket, and no name/address in the message'); - var port = _ntohs(getValue(name + Sockets.sockaddr_in_layout.sin_port, 'i16')); - var addr = getValue(name + Sockets.sockaddr_in_layout.sin_addr, 'i32'); + var port = _ntohs(getValue(name + {{{ C_STRUCTS.sockaddr_in.sin_port }}}, 'i16')); + var addr = getValue(name + {{{ C_STRUCTS.sockaddr_in.sin_addr.s_addr }}}, 'i32'); var connection = Sockets.connections[addr]; // var host = __inet_ntop4_raw(addr); @@ -7932,8 +7763,8 @@ LibraryManager.library = { return -1; } - var iov = {{{ makeGetValue('msg', 'Sockets.msghdr_layout.msg_iov', 'i8*') }}}; - var num = {{{ makeGetValue('msg', 'Sockets.msghdr_layout.msg_iovlen', 'i32') }}}; + var iov = {{{ makeGetValue('msg', C_STRUCTS.msghdr.msg_iov, 'i8*') }}}; + var num = {{{ makeGetValue('msg', C_STRUCTS.msghdr.msg_iovlen, 'i32') }}}; #if SOCKET_DEBUG Module.print('sendmsg vecs: ' + num); #endif @@ -7994,13 +7825,13 @@ LibraryManager.library = { Module.print('recvmsg bytes: ' + bytes + ' | ' + Array.prototype.slice.call(buffer)); #endif // write source - var name = {{{ makeGetValue('msg', 'Sockets.msghdr_layout.msg_name', '*') }}}; - {{{ makeSetValue('name', 'Sockets.sockaddr_in_layout.sin_addr', 'addr', 'i32') }}}; - {{{ makeSetValue('name', 'Sockets.sockaddr_in_layout.sin_port', '_htons(header[0])', 'i16') }}}; + var name = {{{ makeGetValue('msg', C_STRUCTS.msghdr.msg_name, '*') }}}; + {{{ makeSetValue('name', C_STRUCTS.sockaddr_in.sin_addr.s_addr, 'addr', 'i32') }}}; + {{{ makeSetValue('name', C_STRUCTS.sockaddr_in.sin_port, '_htons(header[0])', 'i16') }}}; // write data var ret = bytes; - var iov = {{{ makeGetValue('msg', 'Sockets.msghdr_layout.msg_iov', 'i8*') }}}; - var num = {{{ makeGetValue('msg', 'Sockets.msghdr_layout.msg_iovlen', 'i32') }}}; + var iov = {{{ makeGetValue('msg', C_STRUCTS.msghdr.msg_iov, 'i8*') }}}; + var num = {{{ makeGetValue('msg', C_STRUCTS.msghdr.msg_iovlen, 'i32') }}}; var bufferPos = 0; for (var i = 0; i < num && bytes > 0; i++) { var currNum = {{{ makeGetValue('iov', '8*i + 4', 'i32') }}}; @@ -8054,9 +7885,9 @@ LibraryManager.library = { var info = FS.getStream(fd); if (!info) return -1; if (addr) { - setValue(addr + Sockets.sockaddr_in_layout.sin_addr, info.addr, 'i32'); - setValue(addr + Sockets.sockaddr_in_layout.sin_port, info.port, 'i32'); - setValue(addrlen, Sockets.sockaddr_in_layout.__size__, 'i32'); + setValue(addr + {{{ C_STRUCTS.sockaddr_in.sin_addr.s_addr }}}, info.addr, 'i32'); + setValue(addr + {{{ C_STRUCTS.sockaddr_in.sin_port }}}, info.port, 'i32'); + setValue(addrlen, {{{ C_STRUCTS.sockaddr_in.__size__ }}}, 'i32'); } return fd; }, @@ -8122,27 +7953,27 @@ LibraryManager.library = { _read_sockaddr__deps: ['$Sockets', '_inet_ntop4_raw', '_inet_ntop6_raw'], _read_sockaddr: function (sa, salen) { // family / port offsets are common to both sockaddr_in and sockaddr_in6 - var family = {{{ makeGetValue('sa', 'Sockets.sockaddr_in_layout.sin_family', 'i16') }}}; - var port = _ntohs({{{ makeGetValue('sa', 'Sockets.sockaddr_in_layout.sin_port', 'i16') }}}); + var family = {{{ makeGetValue('sa', C_STRUCTS.sockaddr_in.sin_family, 'i16') }}}; + var port = _ntohs({{{ makeGetValue('sa', C_STRUCTS.sockaddr_in.sin_port, 'i16') }}}); var addr; switch (family) { case {{{ cDefine('AF_INET') }}}: - if (salen !== Sockets.sockaddr_in_layout.__size__) { + if (salen !== {{{ C_STRUCTS.sockaddr_in.__size__ }}}) { return { errno: ERRNO_CODES.EINVAL }; } - addr = {{{ makeGetValue('sa', 'Sockets.sockaddr_in_layout.sin_addr', 'i32') }}}; + addr = {{{ makeGetValue('sa', C_STRUCTS.sockaddr_in.sin_addr.s_addr, 'i32') }}}; addr = __inet_ntop4_raw(addr); break; case {{{ cDefine('AF_INET6') }}}: - if (salen !== Sockets.sockaddr_in6_layout.__size__) { + if (salen !== {{{ C_STRUCTS.sockaddr_in6.__size__ }}}) { return { errno: ERRNO_CODES.EINVAL }; } addr = [ - {{{ makeGetValue('sa', 'Sockets.sockaddr_in6_layout.sin6_addr+0', 'i32') }}}, - {{{ makeGetValue('sa', 'Sockets.sockaddr_in6_layout.sin6_addr+4', 'i32') }}}, - {{{ makeGetValue('sa', 'Sockets.sockaddr_in6_layout.sin6_addr+8', 'i32') }}}, - {{{ makeGetValue('sa', 'Sockets.sockaddr_in6_layout.sin6_addr+12', 'i32') }}} + {{{ makeGetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+0, 'i32') }}}, + {{{ makeGetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+4, 'i32') }}}, + {{{ makeGetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+8, 'i32') }}}, + {{{ makeGetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+12, 'i32') }}} ]; addr = __inet_ntop6_raw(addr); break; @@ -8157,18 +7988,18 @@ LibraryManager.library = { switch (family) { case {{{ cDefine('AF_INET') }}}: addr = __inet_pton4_raw(addr); - {{{ makeSetValue('sa', 'Sockets.sockaddr_in_layout.sin_family', 'family', 'i16') }}}; - {{{ makeSetValue('sa', 'Sockets.sockaddr_in_layout.sin_addr', 'addr', 'i32') }}}; - {{{ makeSetValue('sa', 'Sockets.sockaddr_in_layout.sin_port', '_htons(port)', 'i16') }}}; + {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in.sin_family, 'family', 'i16') }}}; + {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in.sin_addr.s_addr, 'addr', 'i32') }}}; + {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in.sin_port, '_htons(port)', 'i16') }}}; break; case {{{ cDefine('AF_INET6') }}}: addr = __inet_pton6_raw(addr); - {{{ makeSetValue('sa', 'Sockets.sockaddr_in6_layout.sin6_family', 'family', 'i32') }}}; - {{{ makeSetValue('sa', 'Sockets.sockaddr_in6_layout.sin6_addr+0', 'addr[0]', 'i32') }}}; - {{{ makeSetValue('sa', 'Sockets.sockaddr_in6_layout.sin6_addr+4', 'addr[1]', 'i32') }}}; - {{{ makeSetValue('sa', 'Sockets.sockaddr_in6_layout.sin6_addr+8', 'addr[2]', 'i32') }}}; - {{{ makeSetValue('sa', 'Sockets.sockaddr_in6_layout.sin6_addr+12', 'addr[3]', 'i32') }}}; - {{{ makeSetValue('sa', 'Sockets.sockaddr_in6_layout.sin6_port', '_htons(port)', 'i16') }}}; + {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_family, 'family', 'i32') }}}; + {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+0, 'addr[0]', 'i32') }}}; + {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+4, 'addr[1]', 'i32') }}}; + {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+8, 'addr[2]', 'i32') }}}; + {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+12, 'addr[3]', 'i32') }}}; + {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_port, '_htons(port)', 'i16') }}}; break; default: return { errno: ERRNO_CODES.EAFNOSUPPORT }; @@ -8414,14 +8245,14 @@ LibraryManager.library = { return -1; } - var iov = {{{ makeGetValue('message', 'Sockets.msghdr_layout.msg_iov', '*') }}}; - var num = {{{ makeGetValue('message', 'Sockets.msghdr_layout.msg_iovlen', 'i32') }}}; + var iov = {{{ makeGetValue('message', C_STRUCTS.msghdr.msg_iov, '*') }}}; + var num = {{{ makeGetValue('message', C_STRUCTS.msghdr.msg_iovlen, 'i32') }}}; // read the address and port to send to var addr; var port; - var name = {{{ makeGetValue('message', 'Sockets.msghdr_layout.msg_name', '*') }}}; - var namelen = {{{ makeGetValue('message', 'Sockets.msghdr_layout.msg_namelen', 'i32') }}}; + var name = {{{ makeGetValue('message', C_STRUCTS.msghdr.msg_name, '*') }}}; + var namelen = {{{ makeGetValue('message', C_STRUCTS.msghdr.msg_namelen, 'i32') }}}; if (name) { var info = __read_sockaddr(name, namelen); if (info.errno) { @@ -8435,13 +8266,13 @@ LibraryManager.library = { // concatenate scatter-gather arrays into one message buffer var total = 0; for (var i = 0; i < num; i++) { - total += {{{ makeGetValue('iov', '(Sockets.iovec_layout.__size__ * i) + Sockets.iovec_layout.iov_len', 'i32') }}}; + total += {{{ makeGetValue('iov', '(' + C_STRUCTS.iovec.__size__ + ' * i) + ' + C_STRUCTS.iovec.iov_len, 'i32') }}}; } var view = new Uint8Array(total); var offset = 0; for (var i = 0; i < num; i++) { - var iovbase = {{{ makeGetValue('iov', '(Sockets.iovec_layout.__size__ * i) + Sockets.iovec_layout.iov_base', 'i8*') }}}; - var iovlen = {{{ makeGetValue('iov', '(Sockets.iovec_layout.__size__ * i) + Sockets.iovec_layout.iov_len', 'i32') }}}; + var iovbase = {{{ makeGetValue('iov', '(' + C_STRUCTS.iovec.__size__ + ' * i) + ' + C_STRUCTS.iovec.iov_base, 'i8*') }}}; + var iovlen = {{{ makeGetValue('iov', '(' + C_STRUCTS.iovec.__size__ + ' * i) + ' + C_STRUCTS.iovec.iov_len, 'i32') }}}; for (var j = 0; j < iovlen; j++) { view[offset++] = {{{ makeGetValue('iovbase', 'j', 'i8') }}}; } @@ -8464,13 +8295,13 @@ LibraryManager.library = { return -1; } - var iov = {{{ makeGetValue('message', 'Sockets.msghdr_layout.msg_iov', 'i8*') }}}; - var num = {{{ makeGetValue('message', 'Sockets.msghdr_layout.msg_iovlen', 'i32') }}}; + var iov = {{{ makeGetValue('message', C_STRUCTS.msghdr.msg_iov, 'i8*') }}}; + var num = {{{ makeGetValue('message', C_STRUCTS.msghdr.msg_iovlen, 'i32') }}}; // get the total amount of data we can read across all arrays var total = 0; for (var i = 0; i < num; i++) { - total += {{{ makeGetValue('iov', '(Sockets.iovec_layout.__size__ * i) + Sockets.iovec_layout.iov_len', 'i32') }}}; + total += {{{ makeGetValue('iov', '(' + C_STRUCTS.iovec.__size__ + ' * i) + ' + C_STRUCTS.iovec.iov_len, 'i32') }}}; } // try to read total data @@ -8496,7 +8327,7 @@ LibraryManager.library = { // Requests that the function block until the full amount of data requested can be returned. The function may return a smaller amount of data if a signal is caught, if the connection is terminated, if MSG_PEEK was specified, or if an error is pending for the socket. // write the source address out - var name = {{{ makeGetValue('message', 'Sockets.msghdr_layout.msg_name', '*') }}}; + var name = {{{ makeGetValue('message', C_STRUCTS.msghdr.msg_name, '*') }}}; if (name) { var res = __write_sockaddr(name, sock.family, DNS.lookup_name(msg.addr), msg.port); assert(!res.errno); @@ -8506,8 +8337,8 @@ LibraryManager.library = { var bytesRemaining = msg.buffer.byteLength; for (var i = 0; bytesRemaining > 0 && i < num; i++) { - var iovbase = {{{ makeGetValue('iov', '(Sockets.iovec_layout.__size__ * i) + Sockets.iovec_layout.iov_base', 'i8*') }}}; - var iovlen = {{{ makeGetValue('iov', '(Sockets.iovec_layout.__size__ * i) + Sockets.iovec_layout.iov_len', 'i32') }}}; + var iovbase = {{{ makeGetValue('iov', '(' + C_STRUCTS.iovec.__size__ + ' * i) + ' + C_STRUCTS.iovec.iov_base, 'i8*') }}}; + var iovlen = {{{ makeGetValue('iov', '(' + C_STRUCTS.iovec.__size__ + ' * i) + ' + C_STRUCTS.iovec.iov_len, 'i32') }}}; if (!iovlen) { continue; } diff --git a/src/parseTools.js b/src/parseTools.js index 90c5acab..2ccf0179 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -5,11 +5,12 @@ // Does simple 'macro' substitution, using Django-like syntax, // {{{ code }}} will be replaced with |eval(code)|. +// NOTE: Be careful with that ret check. If ret is |0|, |ret ? ret.toString() : ''| would result in ''! function processMacros(text) { return text.replace(/{{{([^}]|}(?!}))+}}}/g, function(str) { str = str.substr(3, str.length-6); var ret = eval(str); - return ret ? ret.toString() : ''; + return ret !== null ? ret.toString() : ''; }); } diff --git a/src/struct_info.json b/src/struct_info.json new file mode 100644 index 00000000..5b969603 --- /dev/null +++ b/src/struct_info.json @@ -0,0 +1,822 @@ +[ + { + "file": "libc/dirent.h", + "defines": [], + "structs": { + "dirent": [ + "d_ino", + "d_off", + "d_reclen", + "d_type", + "d_name" + ] + } + }, + { + "file": "libc/utime.h", + "defines": [], + "structs": { + "utimbuf": [ + "actime", + "modtime" + ] + } + }, + { + "file": "libc/sys/stat.h", + "defines": [ + "S_IFDIR", + "S_IFREG", + "S_IFMT", + "S_IFIFO", + "S_IFSOCK", + "S_IFBLK", + "S_IFLNK", + "S_IFCHR" + ], + "structs": { + "stat": [ + "st_dev", + "__st_dev_padding", + "__st_ino_truncated", + "st_mode", + "st_nlink", + "st_uid", + "st_gid", + "st_rdev", + "__st_rdev_padding", + "st_size", + "st_blksize", + "st_blocks", + { + "st_atim": [ + "tv_sec", + "tv_nsec" + ] + }, + { + "st_mtim": [ + "tv_sec", + "tv_nsec" + ] + }, + { + "st_ctim": [ + "tv_sec", + "tv_nsec" + ] + }, + "st_ino" + ] + } + }, + { + "file": "libc/sys/statvfs.h", + "defines": [], + "structs": { + "statvfs": [ + "f_bsize", + "f_frsize", + "f_blocks", + "f_bfree", + "f_bavail", + "f_files", + "f_ffree", + "f_favail", + "f_fsid", + "f_flag", + "f_namemax" + ] + } + }, + { + "file": "libc/fcntl.h", + "defines": [ + "F_UNLCK", + "O_RDWR", + "S_IRWXO", + "F_GETLK64", + "F_SETLKW64", + "F_SETLKW", + "F_SETLK64", + "F_GETLK", + "S_ISVTX", + "O_RDONLY", + "O_ACCMODE", + "F_DUPFD", + "F_SETLK", + "O_WRONLY" + ], + "structs": { + "flock": [ + "l_type", + "l_whence", + "l_start", + "l_len", + "l_pid" + ] + } + }, + { + "file": "libc/poll.h", + "defines": [ + "POLLHUP", + "POLLERR", + "POLLRDNORM", + "POLLPRI", + "POLLIN", + "POLLOUT", + "POLLNVAL" + ], + "structs": { + "pollfd": [ + "fd", + "events", + "revents" + ] + } + }, + { + "file": "libc/stdlib.h", + "defines": [], + "structs": { + // NOTE: The hash sign at the end of this name is a hint to the processor that it mustn't prefix "struct " to the name to reference this struct. + // It will be stripped away when writing the compiled JSON file. You can just refer to it as C_STRUCTS.div_t when using it in the JS code. + // For more information see gen_inspect_code() in tools/gen_struct_info.py . + "div_t#": [ + "quot", + "rem" + ] + } + }, + { + "file": "libc/sys/utsname.h", + "defines": [], + "structs": { + "utsname": [ + "sysname", + "nodename", + "release", + "version", + "machine", + "domainname" + ] + } + }, + { + "file": "libc/time.h", + "defines": [ + ["li", "CLOCKS_PER_SEC"] + ], + "structs": { + "timezone": [ + "tz_minuteswest", + "tz_dsttime" + ], + "tm": [ + "tm_sec", + "tm_min", + "tm_hour", + "tm_mday", + "tm_mon", + "tm_year", + "tm_wday", + "tm_yday", + "tm_isdst", + "tm_gmtoff", + "tm_zone" + ], + "itimerspec": [ + { + "it_interval": [ + "tv_sec", + "tv_nsec" + ] + }, + { + "it_value": [ + "tv_sec", + "tv_nsec" + ] + } + ], + "timespec": [ + "tv_sec", + "tv_nsec" + ], + "timeval": [ + "tv_sec", + "tv_usec" + ] + } + }, + { + "file": "libc/sys/times.h", + "defines": [], + "structs": { + "tms": [ + "tms_utime", + "tms_stime", + "tms_cutime", + "tms_cstime" + ] + } + }, + { + "file": "libc/sys/resource.h", + "defines": [], + "structs": { + "rlimit": [ + "rlim_cur", + "rlim_max" + ], + "rusage": [ + { + "ru_utime": [ + "tv_sec", + "tv_usec" + ] + }, + { + "ru_stime": [ + "tv_sec", + "tv_usec" + ] + }, + "ru_maxrss", + "ru_ixrss", + "ru_idrss", + "ru_isrss", + "ru_minflt", + "ru_majflt", + "ru_nswap", + "ru_inblock", + "ru_oublock", + "ru_msgsnd", + "ru_msgrcv", + "ru_nsignals", + "ru_nvcsw", + "ru_nivcsw" + ] + } + }, + { + "file": "libc/netdb.h", + "defines": [ + "AI_V4MAPPED", + "EAI_SERVICE", + "EAI_FAMILY", + "AI_ALL", + "AI_ADDRCONFIG", + "AI_NUMERICSERV", + "NI_NUMERICHOST", + "EAI_OVERFLOW", + "AI_NUMERICHOST", + "AI_CANONNAME", + "AI_PASSIVE", + "NI_NAMEREQD", + "EAI_NONAME", + "EAI_SOCKTYPE", + "EAI_BADFLAGS" + ], + "structs": { + "sockaddr": [ + "sa_family", + "sa_data" + ], + "hostent": [ + "h_name", + "h_aliases", + "h_addrtype", + "h_length", + "h_addr_list" + ], + "addrinfo": [ + "ai_flags", + "ai_family", + "ai_socktype", + "ai_protocol", + "ai_addrlen", + "ai_addr", + "ai_canonname", + "ai_next" + ], + "in_addr": [ + "s_addr" + ], + "linger": [ + "l_onoff", + "l_linger" + ], + "protoent": [ + "p_name", + "p_aliases", + "p_proto" + ], + "sockaddr_in": [ + "sin_family", + "sin_port", + { + "sin_addr": [ + "s_addr" + ] + }, + "sin_zero" + ], + "iovec": [ + "iov_base", + "iov_len" + ], + "cmsghdr": [ + "cmsg_len", + "cmsg_level", + "cmsg_type" + ], + "sockaddr_in6": [ + "sin6_family", + "sin6_port", + "sin6_flowinfo", + { + "sin6_addr": [ + { + "__in6_union": [ + "__s6_addr", + "__s6_addr16", + "__s6_addr32" + ] + } + ] + }, + "sin6_scope_id" + ], + "msghdr": [ + "msg_name", + "msg_namelen", + "msg_iov", + "msg_iovlen", + "msg_control", + "msg_controllen", + "msg_flags" + ], + "in6_addr": [ + { + "__in6_union": [ + "__s6_addr", + "__s6_addr16", + "__s6_addr32" + ] + } + ], + "netent": [ + "n_name", + "n_aliases", + "n_addrtype", + "n_net" + ] + } + }, + { + "file": "libc/netinet/in.h", + "defines": [ + "IPPROTO_UDP", + "IPPROTO_TCP", + "INADDR_LOOPBACK" + ], + "structs": {} + }, + { + "file": "libc/math.h", + "defines": [ + "FP_ZERO", + "FP_NAN", + "FP_INFINITE", + "FP_NORMAL" + ], + "structs": {} + }, + { + "file": "libc/bits/fcntl.h", + "defines": [ + "O_CREAT", + "O_SYNC", + "F_GETFD", + "F_SETFL", + "O_NOFOLLOW", + "O_APPEND", + "F_SETOWN", + "O_TRUNC", + "F_GETOWN", + "F_SETFD", + "O_EXCL", + "F_GETFL" + ], + "structs": {} + }, + { + "file": "libc/sys/socket.h", + "defines": [ + "SOCK_DGRAM", + "SOCK_STREAM", + "AF_INET", + "AF_UNSPEC", + "AF_INET6" + ], + "structs": {} + }, + { + "file": "libc/bits/ioctl.h", + "defines": [ + "FIONREAD" + ], + "structs": {} + }, + { + "file": "libc/unistd.h", + "defines": [ + "_SC_XOPEN_LEGACY", + "_SC_XOPEN_VERSION", + "_SC_BC_DIM_MAX", + "_CS_POSIX_V6_LP64_OFF64_LIBS", + "_PC_REC_MIN_XFER_SIZE", + "_SC_V6_ILP32_OFFBIG", + "_SC_MEMLOCK", + "_SC_THREADS", + "_PC_SOCK_MAXBUF", + "_SC_THREAD_KEYS_MAX", + "_SC_2_PBS", + "_SC_TRACE_INHERIT", + "_SC_REGEXP", + "_CS_POSIX_V6_LP64_OFF64_CFLAGS", + "_SC_VERSION", + "_PC_CHOWN_RESTRICTED", + "_SC_MQ_PRIO_MAX", + "_SC_PAGE_SIZE", + "_SC_BARRIERS", + "_SC_2_LOCALEDEF", + "_SC_STREAM_MAX", + "_SC_TIMERS", + "_PC_PATH_MAX", + "_SC_SPORADIC_SERVER", + "_SC_NPROCESSORS_ONLN", + "_CS_POSIX_V6_LPBIG_OFFBIG_LIBS", + "_PC_MAX_INPUT", + "_SC_CLK_TCK", + "_SC_AIO_MAX", + "_SC_THREAD_PRIO_INHERIT", + "_PC_2_SYMLINKS", + "_SC_SPAWN", + "_CS_POSIX_V6_ILP32_OFF32_LDFLAGS", + "_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS", + "_SC_TRACE_SYS_MAX", + "_CS_POSIX_V6_WIDTH_RESTRICTED_ENVS", + "_SC_AIO_PRIO_DELTA_MAX", + "_SC_MONOTONIC_CLOCK", + "_SC_XOPEN_ENH_I18N", + "_SC_SPIN_LOCKS", + "_SC_XOPEN_SHM", + "_PC_LINK_MAX", + "_SC_FSYNC", + "_SC_GETGR_R_SIZE_MAX", + "_SC_TRACE_NAME_MAX", + "_SC_BC_BASE_MAX", + "_SC_XOPEN_STREAMS", + "_SC_GETPW_R_SIZE_MAX", + "_SC_CPUTIME", + "_SC_XBS5_ILP32_OFFBIG", + "_SC_TRACE_EVENT_FILTER", + "_SC_OPEN_MAX", + "_SC_2_FORT_RUN", + "_SC_RE_DUP_MAX", + "_SC_THREAD_PRIO_PROTECT", + "_SC_2_PBS_CHECKPOINT", + "_SC_XBS5_LPBIG_OFFBIG", + "_SC_SHARED_MEMORY_OBJECTS", + "_PC_ALLOC_SIZE_MIN", + "_SC_READER_WRITER_LOCKS", + "_SC_MEMLOCK_RANGE", + "_SC_PRIORITY_SCHEDULING", + "_PC_VDISABLE", + "_SC_MESSAGE_PASSING", + "_SC_THREAD_ATTR_STACKADDR", + "_SC_THREAD_THREADS_MAX", + "_SC_LOGIN_NAME_MAX", + "_SC_2_C_BIND", + "_PC_NO_TRUNC", + "_SC_SHELL", + "_SC_V6_LP64_OFF64", + "_CS_GNU_LIBC_VERSION", + "_SC_SEM_VALUE_MAX", + "_SC_MQ_OPEN_MAX", + "_SC_HOST_NAME_MAX", + "_SC_THREAD_STACK_MIN", + "_SC_TIMEOUTS", + "_SC_CHILD_MAX", + "_SC_2_PBS_MESSAGE", + "_SC_2_C_DEV", + "_SC_TIMER_MAX", + "_SC_SYMLOOP_MAX", + "_PC_REC_XFER_ALIGN", + "_SC_REALTIME_SIGNALS", + "_PC_ASYNC_IO", + "_SC_MAPPED_FILES", + "_SC_NGROUPS_MAX", + "_SC_SEMAPHORES", + "_SC_TRACE_LOG", + "_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS", + "_CS_POSIX_V6_LP64_OFF64_LDFLAGS", + "_SC_THREAD_DESTRUCTOR_ITERATIONS", + "_SC_TRACE_EVENT_NAME_MAX", + "_SC_BC_STRING_MAX", + "_SC_2_SW_DEV", + "_SC_ARG_MAX", + "_SC_THREAD_PRIORITY_SCHEDULING", + "_SC_THREAD_CPUTIME", + "_CS_POSIX_V6_ILP32_OFF32_LIBS", + "_SC_SYNCHRONIZED_IO", + "_CS_POSIX_V6_ILP32_OFF32_CFLAGS", + "_SC_MEMORY_PROTECTION", + "_PC_PRIO_IO", + "_SC_V6_LPBIG_OFFBIG", + "_SC_EXPR_NEST_MAX", + "_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS", + "_PC_REC_MAX_XFER_SIZE", + "_SC_DELAYTIMER_MAX", + "W_OK", + "R_OK", + "_SC_XOPEN_CRYPT", + "_SC_XBS5_LP64_OFF64", + "_SC_SIGQUEUE_MAX", + "_SC_TZNAME_MAX", + "_CS_PATH", + "_PC_MAX_CANON", + "_SC_THREAD_SAFE_FUNCTIONS", + "_PC_NAME_MAX", + "_SC_TRACE_USER_EVENT_MAX", + "_SC_RAW_SOCKETS", + "_SC_RTSIG_MAX", + "_SC_PRIORITIZED_IO", + "_SC_XOPEN_UNIX", + "_PC_REC_INCR_XFER_SIZE", + "_PC_FILESIZEBITS", + "_SC_XBS5_ILP32_OFF32", + "_CS_GNU_LIBPTHREAD_VERSION", + "_SC_2_PBS_LOCATE", + "_SC_V6_ILP32_OFF32", + "_PC_SYNC_IO", + "_SC_2_UPE", + "_SC_SEM_NSEMS_MAX", + "_SC_IOV_MAX", + "_SC_TRACE", + "_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS", + "_SC_LINE_MAX", + "_CS_POSIX_V6_ILP32_OFFBIG_LIBS", + "_SC_2_FORT_DEV", + "_SC_ATEXIT_MAX", + "_SC_SAVED_IDS", + "_SC_2_PBS_TRACK", + "_SC_THREAD_PROCESS_SHARED", + "_SC_JOB_CONTROL", + "_SC_IPV6", + "_SC_ADVISORY_INFO", + "_SC_XOPEN_REALTIME_THREADS", + "_PC_SYMLINK_MAX", + "X_OK", + "_SC_COLL_WEIGHTS_MAX", + "_SC_CLOCK_SELECTION", + "_SC_XOPEN_REALTIME", + "_PC_PIPE_BUF", + "_SC_2_PBS_ACCOUNTING", + "_SC_THREAD_SPORADIC_SERVER", + "_SC_THREAD_ATTR_STACKSIZE", + "_SC_2_VERSION", + "_SC_TYPED_MEMORY_OBJECTS", + "_SC_ASYNCHRONOUS_IO", + "_SC_2_CHAR_TERM", + "_SC_AIO_LISTIO_MAX", + "_SC_BC_SCALE_MAX", + "_SC_TTY_NAME_MAX" + ], + "structs": {} + }, + { + "file": "libc/bits/errno.h", + "defines": [ + "ETXTBSY", + "ETOOMANYREFS", + "ENAMETOOLONG", + "ENOPKG", + "EL3HLT", + "EINPROGRESS", + "ENOTSOCK", + "ENOTSUP", + "EFBIG", + "ENOLINK", + "EL3RST", + "ENOTUNIQ", + "ELNRNG", + "ENOANO", + "ENOPROTOOPT", + "E2BIG", + "EHOSTDOWN", + "EBFONT", + "ENOTEMPTY", + "EBUSY", + "EADDRINUSE", + "ELIBACC", + "EDQUOT", + "ENOENT", + "ECOMM", + "EXFULL", + "ENOTDIR", + "ENETRESET", + "EAFNOSUPPORT", + "EINVAL", + "ENODEV", + "ENOCSI", + "EPROTONOSUPPORT", + "ETIME", + "ENOTTY", + "EAGAIN", + "EMSGSIZE", + "ELIBEXEC", + "EMLINK", + "ECANCELED", + "EDESTADDRREQ", + "EADDRNOTAVAIL", + "EPERM", + "EPROTOTYPE", + "ENOMEDIUM", + "ELOOP", + "EREMOTE", + "ELIBMAX", + "EMULTIHOP", + "ECONNABORTED", + "EFAULT", + "EBADMSG", + "EDOM", + "EILSEQ", + "EPFNOSUPPORT", + "ENONET", + "ECHRNG", + "ESRCH", + "EHOSTUNREACH", + "EL2HLT", + "EL2NSYNC", + "ENOMSG", + "EISDIR", + "EDEADLOCK", + "ECONNRESET", + "ESTRPIPE", + "ESHUTDOWN", + "EDEADLK", + "EBADRQC", + "EUNATCH", + "ECHILD", + "ETIMEDOUT", + "EALREADY", + "ENXIO", + "EMFILE", + "ENFILE", + "EREMCHG", + "ENOMEM", + "ENOSR", + "EOWNERDEAD", + "ELIBSCN", + "EPIPE", + "EBADSLT", + "ENOSTR", + "EIO", + "EWOULDBLOCK", + "EBADE", + "ENODATA", + "ESOCKTNOSUPPORT", + "ENOLCK", + "EPROTO", + "ESRMNT", + "EXDEV", + "ENOSPC", + "ELIBBAD", + "ERANGE", + "ESTALE", + "ENOTRECOVERABLE", + "ENOBUFS", + "EIDRM", + "EINTR", + "EADV", + "ENOSYS", + "EUSERS", + "EOPNOTSUPP", + "ENOTCONN", + "ENETUNREACH", + "ESPIPE", + "EROFS", + "ECONNREFUSED", + "ENETDOWN", + "ENOEXEC", + "EBADF", + "EDOTDOT", + "EBADFD", + "EBADR", + "EISCONN", + "ENOTBLK", + "EOVERFLOW" + ], + "structs": {} + }, + { + "file": "libc/langinfo.h", + "defines": [ + "ABDAY_7", + "ABDAY_6", + "ABDAY_5", + "ABDAY_4", + "ABDAY_3", + "ABDAY_2", + "ABDAY_1", + "ABMON_1", + "RADIXCHAR", + "ABMON_3", + "AM_STR", + "ALT_DIGITS", + "PM_STR", + "ABMON_9", + "YESEXPR", + "ABMON_2", + "ABMON_7", + "ABMON_6", + "ABMON_5", + "ABMON_4", + "ABMON_8", + "ERA", + "MON_2", + "MON_3", + "MON_1", + "MON_6", + "MON_7", + "MON_4", + "MON_5", + "MON_8", + "MON_9", + "NOEXPR", + "T_FMT_AMPM", + "MON_10", + "MON_11", + "MON_12", + "T_FMT", + "THOUSEP", + "ERA_T_FMT", + "ERA_D_T_FMT", + "D_FMT", + "DAY_2", + "DAY_3", + "DAY_1", + "DAY_6", + "DAY_7", + "DAY_4", + "DAY_5", + "ERA_D_FMT", + "CODESET", + "D_T_FMT", + "CRNCYSTR", + "ABMON_12", + "ABMON_11", + "ABMON_10" + ], + "structs": {} + }, + { + "file": "libc/stdio.h", + "defines": [ + "EOF", + "SEEK_END", + "SEEK_SET" + ], + "structs": {} + }, + { + "file": "libc/arpa/tftp.h", + "defines": [ + "EACCES", + "EEXIST" + ], + "structs": {} + }, + { + "file": "compat/sys/stat.h", + "defines": [ + "S_IALLUGO", + "S_IWUGO", + "S_IRUGO", + "S_IRWXUGO", + "S_IXUGO" + ], + "structs": {} + }, + { + "file": "libc/bits/mman.h", + "defines": [ + "MAP_PRIVATE" + ], + "structs": {} + } +] diff --git a/tools/gen_struct_info.py b/tools/gen_struct_info.py index 563b4fa1..203a18ec 100644 --- a/tools/gen_struct_info.py +++ b/tools/gen_struct_info.py @@ -75,29 +75,38 @@ The JSON output format is based on the return value of Runtime.generateStructInf ''' -import sys -import os -import json -import argparse -import tempfile -import subprocess +import sys, os, re, json, argparse, tempfile, subprocess import shared +QUIET = (__name__ != '__main__') + +def show(msg): + global QUIET + if not QUIET: + sys.stderr.write(msg + '\n') # Try to load pycparser. try: import pycparser except ImportError: # The import failed, warn the user. - sys.stderr.write('WARN: pycparser isn\'t available. I won\'t be able to parse C files, only .json files.\n') + show('WARN: pycparser isn\'t available. I won\'t be able to parse C files, only .json files.') def parse_header(path, cpp_opts): # Tell the user how to get pycparser, if he tries to parse a C file. sys.stderr.write('ERR: I need pycparser to process C files. \n') - sys.stderr.write(' Use "pip install pycparser" or go to "https://github.com/eliben/pycparser" to install it.\n') + sys.stderr.write(' Use "pip install pycparser" to install or download it from "https://github.com/eliben/pycparser".\n') sys.exit(1) else: # We successfully imported pycparser, the script will be completely functional. + class DelayedRef(object): + def __init__(self, dest): + self.dest = dest + + def __str__(self): + return self.dest + + # For a list of node types and their fields, look here: https://github.com/eliben/pycparser/blob/master/pycparser/_c_ast.cfg class FieldVisitor(pycparser.c_ast.NodeVisitor): def __init__(self): self._name = None @@ -106,21 +115,30 @@ else: def visit_Struct(self, node): if node.decls == None: - # Skip empty struct declarations. + self.named_structs[self._name] = DelayedRef(node.name) return + fields = [] for decl in node.decls: - # Look for nested structs. - subwalk = FieldVisitor() - subwalk.visit(decl) + if decl.name == None: + # Well, this field doesn't have a name. + continue - if subwalk.named_structs: - # Store the nested fields. - fields.append(subwalk.named_structs) - else: - # Just store the field name. + if decl.type != None and isinstance(decl.type, pycparser.c_ast.PtrDecl): + # This field is a pointer, there's no point in looking for nested structs. fields.append(decl.name) + else: + # Look for nested structs. + subwalk = FieldVisitor() + subwalk.visit(decl) + + if subwalk.named_structs: + # Store the nested fields. + fields.append(subwalk.named_structs) + else: + # Just store the field name. + fields.append(decl.name) if node.name != None: self.structs[node.name] = fields @@ -136,9 +154,68 @@ else: self._name = node.declname self.generic_visit(node) self._name = old_name - + + # The first parameter is a structure, the second is a path (a list containing all the keys, needed to reach the destination). + # The last parameter is an item to look for. This function will try to follow the path into the given object and then look there for this key. + # As long as the nested object doesn't have the given key, it will descent into the next higher object till it finds the given key. + # + # Example: + # + # res = look_through({ + # 'la1': { + # 'lb1': { + # 'lc1': 99, + # 'lc2': { 'ld1': 11 } + # 'lc2': 200 + # }, + # 'nice': 100 + # }, + # 'nice': 300 + # }, ['la1', 'lb1', 'lc2'], 'nice') + # + # print(res) # Prints 100 . + # + # In this case the function looked inside obj['la1']['lb1']['lc2']['nice'], then obj['la1']['lb1']['nice'] and found the value + # in obj['la1']['nice']. As soon as it finds a value it returns it and stops looking. + def look_through(obj, path, name): + cur_level = obj + path = path[:] + for i, p in enumerate(path): + cur_level = cur_level[p] + path[i] = cur_level + + path = [ obj ] + path + + while len(path) > 0: + if name in path[-1]: + return path[-1][name] + else: + path.pop() + + return None + + # Use the above function to resolve all DelayedRef() inside a list or dict recursively. + def resolve_delayed(item, root=None, path=[]): + if root == None: + root = item + + if isinstance(item, DelayedRef): + if item.dest in path: + show('WARN: Circular reference found! Field "' + path[-1] + '" references "' + item.dest + '"! (Path = ' + '/'.join([str(part) for part in path]) + ')') + return { '__ref__': item.dest } + else: + return look_through(root, path[:-1], item.dest) + elif isinstance(item, dict): + for name, val in item.items(): + item[name] = resolve_delayed(val, root, path + [ name ]) + elif isinstance(item, list): + for i, val in enumerate(item): + item[i] = resolve_delayed(val, root, path + [ i ]) + + return item + def parse_header(path, cpp_opts): - sys.stderr.write('Parsing header "' + path + '"...\n') + show('Parsing header "' + path + '"...') # Use clang -E as the preprocessor for pycparser. ast = pycparser.parse_file(path, True, cpp_path=shared.CLANG_CC, cpp_args=['-E'] + cpp_opts) @@ -146,10 +223,37 @@ else: # Walk the parsed AST and filter out all the declared structs and their fields. walker = FieldVisitor() walker.visit(ast) - return walker.structs + + walker.structs = resolve_delayed(walker.structs) + with open(path, 'r') as stream: + defines = re.findall(r'(?:^|\n)#define\s+([A-Z|_]+)\s.*', stream.read()) + + return { + 'file': path, + 'defines': defines, + 'structs': walker.structs + } # The following three functions generate C code. The output of the compiled code will be # parsed later on and then put back together into a dict structure by parse_c_output(). +# +# Example: +# c_descent('test1', code) +# c_set('item', 'i%i', '111', code) +# c_set('item2', 'i%i', '9', code) +# c_set('item3', 's%s', '"Hello"', code) +# c_ascent(code) +# c_set('outer', 'f%f', '0.999', code) +# +# Will result in: +# { +# 'test1': { +# 'item': 111, +# 'item2': 9, +# 'item3': 'Hello', +# }, +# 'outer': 0.999 +# } def c_set(name, type_, value, code): code.append('printf("K' + name + '\\n");') code.append('printf("V' + type_ + '\\n", ' + value + ');') @@ -173,7 +277,14 @@ def parse_c_output(lines): key = arg elif line[0] == 'V': # A value - cur_level[key] = int(arg) + if arg[0] == 'i': + arg = int(arg[1:]) + elif arg[0] == 'f': + arg = float(arg[1:]) + elif arg[0] == 's': + arg = arg[1:] + + cur_level[key] = arg elif line[0] == 'D': # Remember the current level as the last parent. parent.append(cur_level) @@ -188,11 +299,19 @@ def parse_c_output(lines): return result def gen_inspect_code(path, struct, code): + if path[0][-1] == '#': + path[0] = path[0][:-1] + prefix = '' + else: + prefix = 'struct ' + c_descent(path[-1], code) + if len(path) == 1: - c_set('__size__', '%lu', 'sizeof (struct ' + path[0] + ')', code) + c_set('__size__', 'i%u', 'sizeof (' + prefix + path[0] + ')', code) else: - c_set('__size__', '%lu', 'sizeof ((struct ' + path[0] + ' *)0)->' + '.'.join(path[1:]), code) + c_set('__size__', 'i%u', 'sizeof ((' + prefix + path[0] + ' *)0)->' + '.'.join(path[1:]), code) + #c_set('__offset__', 'i%u', 'offsetof(' + prefix + path[0] + ', ' + '.'.join(path[1:]) + ')', code) for field in struct: if isinstance(field, dict): @@ -200,12 +319,12 @@ def gen_inspect_code(path, struct, code): fname = field.keys()[0] gen_inspect_code(path + [fname], field[fname], code) else: - c_set(field, '%u', 'offsetof(struct ' + path[0] + ', ' + '.'.join(path[1:] + [field]) + ')', code) + c_set(field, 'i%u', 'offsetof(' + prefix + path[0] + ', ' + '.'.join(path[1:] + [field]) + ')', code) c_ascent(code) def inspect_code(headers, cpp_opts, structs, defines): - sys.stderr.write('Generating C code...\n') + show('Generating C code...') code = ['#include ', '#include '] # Include all the needed headers. @@ -219,19 +338,27 @@ def inspect_code(headers, cpp_opts, structs, defines): c_ascent(code) c_descent('defines', code) - for name in defines: - if isinstance(name, list): - type_, name = name - else: - type_ = 'i' - c_set(name, '%' + type_, name, code) + for name, type_ in defines.items(): + # Add the necessary python type, if missing. + if '%' not in type_: + if type_[-1] in ('d', 'i', 'u'): + # integer + type_ = 'i%' + type_ + elif type_[-1] in ('f', 'F', 'e', 'E', 'g', 'G'): + # float + type_ = 'f%' + type_ + elif type_[-1] in ('x', 'X', 'a', 'A', 'c', 's'): + # hexadecimal or string + type_ = 's%' + type_ + + c_set(name, type_, name, code) code.append('return 0;') code.append('}') # Write the source code to a temporary file. src_file = tempfile.mkstemp('.c') - bin_file = tempfile.mkstemp() + bin_file = tempfile.mkstemp('.ll') os.write(src_file[0], '\n'.join(code)) @@ -239,15 +366,18 @@ def inspect_code(headers, cpp_opts, structs, defines): os.close(src_file[0]) os.close(bin_file[0]) + # NOTE: We can't generate an executable in the next step because it won't run on the current system without changing the target. + # If we change the target, some type sizes will change resulting in wrong data. As a workaround, we will be generating bitcode and + # run that with the LLVM interpreter. That way we can use the default target and still run the code. info = [] try: # Compile the program. - sys.stderr.write('Compiling generated code...\n') - subprocess.check_call([shared.CLANG_CC] + cpp_opts + ['-o', bin_file[1], src_file[1]]) + show('Compiling generated code...') + subprocess.check_call([shared.CLANG_CC, '-emit-llvm', '-S'] + cpp_opts + ['-o', bin_file[1], src_file[1]]) # Run the compiled program. - sys.stderr.write('Calling generated program...\n') - info = subprocess.check_output([bin_file[1]]).splitlines() + show('Calling generated program...') + info = subprocess.check_output([shared.LLVM_INTERPRETER, bin_file[1]]).splitlines() except subprocess.CalledProcessError: if os.path.isfile(bin_file[1]): sys.stderr.write('FAIL: Running the generated program failed!\n') @@ -263,47 +393,75 @@ def inspect_code(headers, cpp_opts, structs, defines): os.unlink(bin_file[1]) # Parse the output of the program into a dict. - data = parse_c_output(info) + return parse_c_output(info) + +def parse_json(path, header_files, structs, defines): + with open(path, 'r') as stream: + # Remove comments before loading the JSON. + data = json.loads(re.sub(r'//.*\n', '', stream.read())) - # Convert all the define's values into the appropriate python types (based on the type passed to printf). - for name in defines: - if isinstance(name, list): - type_, name = name - else: - type_ = 'i' + if not isinstance(data, list): + data = [ data ] + + for item in data: + header_files.append(item['file']) + for name, data in item['structs'].items(): + if name in structs: + show('WARN: Description of struct "' + name + '" in file "' + item['file'] + '" replaces an existing description!') + + structs[name] = data - if type_[-1] in ('d', 'i', 'u'): - # Integer - data['defines'][name] = int(data['defines'][name]) - elif type_[-1] in ('x', 'X', 'a', 'A'): - # Hexadecimal - data['defines'][name] = float.fromhex(data['defines'][name]) - elif type_[-1] in ('f', 'F', 'e', 'E', 'g', 'G'): - # Float - data['defines'][name] = float(data['defines'][name]) - # Leave everything else untouched. - - return data + for part in item['defines']: + if not isinstance(part, list): + # If no type is specified, assume integer. + part = ['i', part] + + if part[1] in defines: + show('WARN: Description of define "' + part[1] + '" in file "' + item['file'] + '" replaces an existing description!') + + defines[part[1]] = part[0] + +def output_json(obj, compressed=True, stream=None): + if stream == None: + stream = sys.stdout + elif isinstance(stream, str): + stream = open(stream, 'w') + + if compressed: + json.dump(obj, stream, separators=(',', ':')) + else: + json.dump(obj, stream, indent=4, sort_keys=True) + + stream.close() + +def filter_opts(opts): + # Only apply compiler options regarding syntax, includes and defines. + # We have to compile for the current system, we aren't compiling to bitcode after all. + out = [] + for flag in opts: + if flag[:2] in ('-f', '-I', '-i', '-D', '-U'): + out.append(flag) + + return out -def main(): +def main(args): + global QUIET + parser = argparse.ArgumentParser(description='Generate JSON infos for structs.') parser.add_argument('headers', nargs='+', help='A header (.h) file or a JSON file with a list of structs and their fields') - parser.add_argument('-f', dest='list_fields', action='store_true', default=False, help='Output a list of structs and fields for the first header.') + parser.add_argument('-q', dest='quiet', action='store_true', default=False, help='Don\'t output anything besides error messages.') + parser.add_argument('-f', dest='list_fields', action='store_true', default=False, help='Output a list of structs and fields for the given headers.') parser.add_argument('-p', dest='pretty_print', action='store_true', default=False, help='Pretty print the outputted JSON.') parser.add_argument('-o', dest='output', metavar='path', default=None, help='Path to the JSON file that will be written. If omitted, the generated data will be printed to stdout.') parser.add_argument('-I', dest='includes', metavar='dir', action='append', default=[], help='Add directory to include search path') parser.add_argument('-D', dest='defines', metavar='define', action='append', default=[], help='Pass a define to the preprocessor') parser.add_argument('-U', dest='undefines', metavar='undefine', action='append', default=[], help='Pass an undefine to the preprocessor') - args = parser.parse_args() + args = parser.parse_args(args) - # Avoid parsing problems due to gcc specifc syntax. - cpp_opts = ['-U__GNUC__'] + QUIET = args.quiet - # Only apply compiler options regarding syntax, includes and defines. - # We have to compile for the current system, we aren't compiling to bitcode after all. - for flag in shared.COMPILER_OPTS: - if flag[:2] in ('-f', '-I', '-i', '-D', '-U'): - cpp_opts.append(flag) + # Avoid parsing problems due to gcc specifc syntax. + cpp_opts = ['-U__GNUC__', '-D_GNU_SOURCE'] + shared.COMPILER_OPTS # Add the user options to the list as well. for path in args.includes: @@ -316,20 +474,15 @@ def main(): cpp_opts.append('-U' + arg) if args.list_fields: - # Just parse the first header and output the result. - structs = parse_header(args.headers[0], cpp_opts) - data = { - 'file': args.headers[0], - 'structs': structs, - 'defines': [] - } - - if args.output == None: - sys.stdout.write(json.dumps(data, indent=4 if args.pretty_print else None)) - else: - with open(args.output, 'w') as stream: - json.dump(data, stream, indent=4 if args.pretty_print else None) + # Just parse the given headers and output the result. + data = [] + for path in args.headers: + if path[-5:] == '.json': + show('WARN: Skipping "' + path + '" because it\'s already a JSON file!') + else: + data.append(parse_header(path, cpp_opts)) + output_json(data, not args.pretty_print, args.output) sys.exit(0) # Look for structs in all passed headers. @@ -339,30 +492,18 @@ def main(): for header in args.headers: if header[-5:] == '.json': - # This is a JSON file, simply load it. - with open(header, 'r') as stream: - data = json.load(stream) - - if not isinstance(data, list): - data = [ data ] - - for item in data: - header_files.append(item['file']) - structs.update(item['structs']) - defines.update(item['defines']) + # This is a JSON file, parse it. + parse_json(header, header_files, structs, defines) else: # If the passed file isn't a JSON file, assume it's a header. header_files.append(header) - structs.update(parse_header(header, cpp_opts)) + data = parse_header(header, cpp_opts) + structs.update(data['structs']) + defines.extend(data['defines']) # Inspect all collected structs. struct_info = inspect_code(header_files, cpp_opts, structs, defines) - - if args.output == None: - sys.stdout.write(json.dumps(struct_info, indent=4 if args.pretty_print else None)) - else: - with open(args.output, 'w') as stream: - json.dump(struct_info, stream, indent=4 if args.pretty_print else None) + output_json(struct_info, not args.pretty_print, args.output) if __name__ == '__main__': - main() \ No newline at end of file + main(sys.argv[1:]) \ No newline at end of file diff --git a/tools/shared.py b/tools/shared.py index a07bdeaf..76802eaa 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -354,7 +354,7 @@ def check_sanity(force=False): logging.critical('Node.js (%s) does not seem to work, check the paths in %s' % (NODE_JS, EM_CONFIG)) sys.exit(1) - for cmd in [CLANG, LINK_CMD[0], LLVM_AR, LLVM_OPT, LLVM_AS, LLVM_DIS, LLVM_NM]: + for cmd in [CLANG, LINK_CMD[0], LLVM_AR, LLVM_OPT, LLVM_AS, LLVM_DIS, LLVM_NM, LLVM_INTERPRETER]: if not os.path.exists(cmd) and not os.path.exists(cmd + '.exe'): # .exe extension required for Windows logging.critical('Cannot find %s, check the paths in %s' % (cmd, EM_CONFIG)) sys.exit(1) @@ -1445,7 +1445,15 @@ class Building: if not ok: logging.error('bootstrapping relooper failed. You may need to manually create relooper.js by compiling it, see src/relooper/emscripten') 1/0 - + + @staticmethod + def ensure_struct_info(info_path): + if os.path.exists(info_path): return + Cache.ensure() + + import gen_struct_info + gen_struct_info.main(['-o', info_path, path_from_root('src/struct_info.json')]) + @staticmethod def preprocess(infile, outfile): ''' -- cgit v1.2.3-18-g5258 From 29a62bd92e056800c7bf8f91fbe4c9fc948bf035 Mon Sep 17 00:00:00 2001 From: ngld Date: Tue, 17 Sep 2013 00:44:38 +0200 Subject: Updated library_sdl.js --- src/library_sdl.js | 187 ++++++--------------- src/settings.js | 428 +---------------------------------------------- src/struct_info.json | 191 +++++++++++++++++++++ tools/gen_struct_info.py | 2 +- tools/shared.py | 2 +- 5 files changed, 255 insertions(+), 555 deletions(-) diff --git a/src/library_sdl.js b/src/library_sdl.js index 116bf547..e9d5a1d9 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -35,7 +35,7 @@ var LibrarySDL = { volume: 1.0 }, mixerFrequency: 22050, - mixerFormat: 0x8010, // AUDIO_S16LSB + mixerFormat: {{{ cDefine('AUDIO_S16LSB') }}}, //0x8010, // AUDIO_S16LSB mixerNumChannels: 2, mixerChunkSize: 1024, channelMinimumNumber: 0, @@ -151,89 +151,12 @@ var LibrarySDL = { 305: 224, // ctrl 308: 226, // alt }, - - structs: { - Rect: Runtime.generateStructInfo([ - ['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'] - ]), - KeyboardEvent: Runtime.generateStructInfo([ - ['i32', 'type'], - ['i32', 'windowID'], - ['i8', 'state'], - ['i8', 'repeat'], - ['i8', 'padding2'], - ['i8', 'padding3'], - ['i32', 'keysym'] - ]), - keysym: Runtime.generateStructInfo([ - ['i32', 'scancode'], - ['i32', 'sym'], - ['i16', 'mod'], - ['i32', 'unicode'] - ]), - TextInputEvent: Runtime.generateStructInfo([ - ['i32', 'type'], - ['i32', 'windowID'], - ['b256', 'text'], - ]), - 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'] - ]), - ResizeEvent: Runtime.generateStructInfo([ - ['i32', 'type'], - ['i32', 'w'], - ['i32', 'h'] - ]), - AudioSpec: Runtime.generateStructInfo([ - ['i32', 'freq'], - ['i16', 'format'], - ['i8', 'channels'], - ['i8', 'silence'], - ['i16', 'samples'], - ['i32', 'size'], - ['void*', 'callback'], - ['void*', 'userdata'] - ]), - version: Runtime.generateStructInfo([ - ['i8', 'major'], - ['i8', 'minor'], - ['i8', 'patch'] - ]) - }, - 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') }}} + x: {{{ makeGetValue('rect + ' + C_STRUCTS.SDL_Rect.x, '0', 'i32') }}}, + y: {{{ makeGetValue('rect + ' + C_STRUCTS.SDL_Rect.y, '0', 'i32') }}}, + w: {{{ makeGetValue('rect + ' + C_STRUCTS.SDL_Rect.w, '0', 'i32') }}}, + h: {{{ makeGetValue('rect + ' + C_STRUCTS.SDL_Rect.h, '0', 'i32') }}} }; }, @@ -281,15 +204,15 @@ var LibrarySDL = { {{{ makeSetValue('surf+Runtime.QUANTUM_SIZE*14', '0', '1', 'i32') }}} - {{{ 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', 'bpp * 8', 'i8') }}} - {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.BytesPerPixel', '0', 'bpp', 'i8') }}} + {{{ makeSetValue('pixelFormat + ' + C_STRUCTS.SDL_PixelFormat.format, '0', '-2042224636', 'i32') }}} // SDL_PIXELFORMAT_RGBA8888 + {{{ makeSetValue('pixelFormat + ' + C_STRUCTS.SDL_PixelFormat.palette, '0', '0', 'i32') }}} // TODO + {{{ makeSetValue('pixelFormat + ' + C_STRUCTS.SDL_PixelFormat.BitsPerPixel, '0', 'bpp * 8', 'i8') }}} + {{{ makeSetValue('pixelFormat + ' + C_STRUCTS.SDL_PixelFormat.BytesPerPixel, '0', 'bpp', 'i8') }}} - {{{ 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') }}} + {{{ makeSetValue('pixelFormat + ' + C_STRUCTS.SDL_PixelFormat.Rmask, '0', 'rmask || 0x000000ff', 'i32') }}} + {{{ makeSetValue('pixelFormat + ' + C_STRUCTS.SDL_PixelFormat.Gmask, '0', 'gmask || 0x0000ff00', 'i32') }}} + {{{ makeSetValue('pixelFormat + ' + C_STRUCTS.SDL_PixelFormat.Bmask, '0', 'bmask || 0x00ff0000', 'i32') }}} + {{{ makeSetValue('pixelFormat + ' + C_STRUCTS.SDL_PixelFormat.Amask, '0', 'amask || 0xff000000', 'i32') }}} // Decide if we want to use WebGL or not var useWebGL = (flags & 0x04000000) != 0; // SDL_OPENGL @@ -608,7 +531,7 @@ var LibrarySDL = { 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__); // XXX + _memcpy(ptr, event, {{{ C_STRUCTS.SDL_KeyboardEvent.__size__ }}}); // XXX return; } @@ -631,52 +554,52 @@ var LibrarySDL = { scan = SDL.scanCodes[key] || key; } - {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.type', 'SDL.DOMEventToSDLEvent[event.type]', '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', 'scan', 'i32') }}} - {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.sym', 'key', 'i32') }}} - {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.mod', 'SDL.modState', 'i16') }}} + {{{ makeSetValue('ptr', C_STRUCTS.SDL_KeyboardEvent.type, 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}} + {{{ makeSetValue('ptr', C_STRUCTS.SDL_KeyboardEvent.state, 'down ? 1 : 0', 'i8') }}} + {{{ makeSetValue('ptr', C_STRUCTS.SDL_KeyboardEvent.repeat, '0', 'i8') }}} // TODO + {{{ makeSetValue('ptr', C_STRUCTS.SDL_KeyboardEvent.keysym + C_STRUCTS.SDL_Keysym.scancode, 'scan', 'i32') }}} + {{{ makeSetValue('ptr', C_STRUCTS.SDL_KeyboardEvent.keysym + C_STRUCTS.SDL_Keysym.sym, 'key', 'i32') }}} + {{{ makeSetValue('ptr', C_STRUCTS.SDL_KeyboardEvent.keysym + C_STRUCTS.SDL_Keysym.mod, 'SDL.modState', 'i16') }}} // some non-character keys (e.g. backspace and tab) won't have keypressCharCode set, fill in with the keyCode. - {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.unicode', 'event.keypressCharCode || key', 'i32') }}} + {{{ makeSetValue('ptr', C_STRUCTS.SDL_KeyboardEvent.keysym + C_STRUCTS.SDL_Keysym.unicode, 'event.keypressCharCode || key', 'i32') }}} break; } case 'keypress': { - {{{ makeSetValue('ptr', 'SDL.structs.TextInputEvent.type', 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}} + {{{ makeSetValue('ptr', C_STRUCTS.SDL_TextInputEvent.type, 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}} // Not filling in windowID for now var cStr = intArrayFromString(String.fromCharCode(event.charCode)); for (var i = 0; i < cStr.length; ++i) { - {{{ makeSetValue('ptr', 'SDL.structs.TextInputEvent.text + i', 'cStr[i]', 'i8') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_TextInputEvent.text + ' + i', 'cStr[i]', 'i8') }}}; } break; } case 'mousedown': case 'mouseup': case 'mousemove': { 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', 'Browser.mouseX', 'i32') }}}; - {{{ makeSetValue('ptr', 'SDL.structs.MouseButtonEvent.y', 'Browser.mouseY', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseButtonEvent.type, 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseButtonEvent.button, 'event.button+1', 'i8') }}}; // DOM buttons are 0-2, SDL 1-3 + {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseButtonEvent.state, 'down ? 1 : 0', 'i8') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseButtonEvent.x, 'Browser.mouseX', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseButtonEvent.y, 'Browser.mouseY', 'i32') }}}; } else { - {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.type', 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}}; - {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.state', 'SDL.buttonState', 'i8') }}}; - {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.x', 'Browser.mouseX', 'i32') }}}; - {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.y', 'Browser.mouseY', 'i32') }}}; - {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.xrel', 'Browser.mouseMovementX', 'i32') }}}; - {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.yrel', 'Browser.mouseMovementY', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseMotionEvent.type, 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseMotionEvent.state, 'SDL.buttonState', 'i8') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseMotionEvent.x, 'Browser.mouseX', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseMotionEvent.y, 'Browser.mouseY', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseMotionEvent.xrel, 'Browser.mouseMovementX', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseMotionEvent.yrel, 'Browser.mouseMovementY', 'i32') }}}; } break; } case 'unload': { - {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.type', 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_KeyboardEvent.type, 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}}; break; } case 'resize': { - {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.type', 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}}; - {{{ makeSetValue('ptr', 'SDL.structs.ResizeEvent.w', 'event.w', 'i32') }}}; - {{{ makeSetValue('ptr', 'SDL.structs.ResizeEvent.h', 'event.h', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_KeyboardEvent.type, 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_ResizeEvent.w, 'event.w', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_ResizeEvent.h, 'event.h', 'i32') }}}; break; } default: throw 'Unhandled SDL event: ' + event.type; @@ -740,10 +663,10 @@ var LibrarySDL = { 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') }}} + SDL.version = _malloc({{{ C_STRUCTS.SDL_version.__size__ }}}); + {{{ makeSetValue('SDL.version + ' + C_STRUCTS.SDL_version.major, '0', '1', 'i8') }}} + {{{ makeSetValue('SDL.version + ' + C_STRUCTS.SDL_version.minor, '0', '3', 'i8') }}} + {{{ makeSetValue('SDL.version + ' + C_STRUCTS.SDL_version.patch, '0', '0', 'i8') }}} } return SDL.version; }, @@ -1459,24 +1382,24 @@ var LibrarySDL = { SDL.allocateChannels(32); SDL.audio = { - freq: {{{ makeGetValue('desired', 'SDL.structs.AudioSpec.freq', 'i32', 0, 1) }}}, - format: {{{ makeGetValue('desired', 'SDL.structs.AudioSpec.format', 'i16', 0, 1) }}}, - channels: {{{ makeGetValue('desired', 'SDL.structs.AudioSpec.channels', 'i8', 0, 1) }}}, - samples: {{{ makeGetValue('desired', 'SDL.structs.AudioSpec.samples', 'i16', 0, 1) }}}, - callback: {{{ makeGetValue('desired', 'SDL.structs.AudioSpec.callback', 'void*', 0, 1) }}}, - userdata: {{{ makeGetValue('desired', 'SDL.structs.AudioSpec.userdata', 'void*', 0, 1) }}}, + freq: {{{ makeGetValue('desired', C_STRUCTS.SDL_AudioSpec.freq, 'i32', 0, 1) }}}, + format: {{{ makeGetValue('desired', C_STRUCTS.SDL_AudioSpec.format, 'i16', 0, 1) }}}, + channels: {{{ makeGetValue('desired', C_STRUCTS.SDL_AudioSpec.channels, 'i8', 0, 1) }}}, + samples: {{{ makeGetValue('desired', C_STRUCTS.SDL_AudioSpec.samples, 'i16', 0, 1) }}}, + callback: {{{ makeGetValue('desired', C_STRUCTS.SDL_AudioSpec.callback, 'void*', 0, 1) }}}, + userdata: {{{ makeGetValue('desired', C_STRUCTS.SDL_AudioSpec.userdata, 'void*', 0, 1) }}}, paused: true, timer: null }; if (obtained) { - {{{ makeSetValue('obtained', 'SDL.structs.AudioSpec.freq', 'SDL.audio.freq', 'i32') }}}; // no good way for us to know if the browser can really handle this - {{{ makeSetValue('obtained', 'SDL.structs.AudioSpec.format', 33040, 'i16') }}}; // float, signed, 16-bit - {{{ makeSetValue('obtained', 'SDL.structs.AudioSpec.channels', 'SDL.audio.channels', 'i8') }}}; - {{{ makeSetValue('obtained', 'SDL.structs.AudioSpec.silence', makeGetValue('desired', 'SDL.structs.AudioSpec.silence', 'i8', 0, 1), 'i8') }}}; // unclear if browsers can provide this - {{{ makeSetValue('obtained', 'SDL.structs.AudioSpec.samples', 'SDL.audio.samples', 'i16') }}}; - {{{ makeSetValue('obtained', 'SDL.structs.AudioSpec.callback', 'SDL.audio.callback', '*') }}}; - {{{ makeSetValue('obtained', 'SDL.structs.AudioSpec.userdata', 'SDL.audio.userdata', '*') }}}; + {{{ makeSetValue('obtained', C_STRUCTS.SDL_AudioSpec.freq, 'SDL.audio.freq', 'i32') }}}; // no good way for us to know if the browser can really handle this + {{{ makeSetValue('obtained', C_STRUCTS.SDL_AudioSpec.format, 33040, 'i16') }}}; // float, signed, 16-bit + {{{ makeSetValue('obtained', C_STRUCTS.SDL_AudioSpec.channels, 'SDL.audio.channels', 'i8') }}}; + {{{ makeSetValue('obtained', C_STRUCTS.SDL_AudioSpec.silence, makeGetValue('desired', C_STRUCTS.SDL_AudioSpec.silence, 'i8', 0, 1), 'i8') }}}; // unclear if browsers can provide this + {{{ makeSetValue('obtained', C_STRUCTS.SDL_AudioSpec.samples, 'SDL.audio.samples', 'i16') }}}; + {{{ makeSetValue('obtained', C_STRUCTS.SDL_AudioSpec.callback, 'SDL.audio.callback', '*') }}}; + {{{ makeSetValue('obtained', C_STRUCTS.SDL_AudioSpec.userdata, 'SDL.audio.userdata', '*') }}}; } var totalSamples = SDL.audio.samples*SDL.audio.channels; diff --git a/src/settings.js b/src/settings.js index 15bca4db..8d9d4634 100644 --- a/src/settings.js +++ b/src/settings.js @@ -440,425 +440,11 @@ var DEBUG_TAGS_SHOWING = []; // A cached set of defines, generated from the header files. This // lets the emscripten libc (library.js) see the right values. -// If you modify the headers or use different ones, you will need -// to override this. -var C_DEFINES = { - 'ABDAY_1': '131072', - 'ABDAY_2': '131073', - 'ABDAY_3': '131074', - 'ABDAY_4': '131075', - 'ABDAY_5': '131076', - 'ABDAY_6': '131077', - 'ABDAY_7': '131078', - 'ABMON_1': '131086', - 'ABMON_10': '131095', - 'ABMON_11': '131096', - 'ABMON_12': '131097', - 'ABMON_2': '131087', - 'ABMON_3': '131088', - 'ABMON_4': '131089', - 'ABMON_5': '131090', - 'ABMON_6': '131091', - 'ABMON_7': '131092', - 'ABMON_8': '131093', - 'ABMON_9': '131094', - 'AF_INET': '2', - 'AF_INET6': '10', - 'AF_UNSPEC': '0', - 'AI_ADDRCONFIG': '32', - 'AI_ALL': '16', - 'AI_CANONNAME': '2', - 'AI_NUMERICHOST': '4', - 'AI_NUMERICSERV': '1024', - 'AI_PASSIVE': '1', - 'AI_V4MAPPED': '8', - 'ALT_DIGITS': '131119', - 'AM_STR': '131110', - 'CLOCKS_PER_SEC': '1000000', - 'CODESET': '14', - 'CRNCYSTR': '262159', - 'DAY_1': '131079', - 'DAY_2': '131080', - 'DAY_3': '131081', - 'DAY_4': '131082', - 'DAY_5': '131083', - 'DAY_6': '131084', - 'DAY_7': '131085', - 'D_FMT': '131113', - 'D_T_FMT': '131112', - 'E2BIG': '7', - 'EACCES': '13', - 'EADDRINUSE': '98', - 'EADDRNOTAVAIL': '99', - 'EADV': '68', - 'EAFNOSUPPORT': '97', - 'EAGAIN': '11', - 'EAI_BADFLAGS': '-1', - 'EAI_FAMILY': '-6', - 'EAI_NONAME': '-2', - 'EAI_OVERFLOW': '-12', - 'EAI_SERVICE': '-8', - 'EAI_SOCKTYPE': '-7', - 'EALREADY': '114', - 'EBADE': '52', - 'EBADF': '9', - 'EBADFD': '77', - 'EBADMSG': '74', - 'EBADR': '53', - 'EBADRQC': '56', - 'EBADSLT': '57', - 'EBFONT': '59', - 'EBUSY': '16', - 'ECANCELED': '125', - 'ECHILD': '10', - 'ECHRNG': '44', - 'ECOMM': '70', - 'ECONNABORTED': '103', - 'ECONNREFUSED': '111', - 'ECONNRESET': '104', - 'EDEADLK': '35', - 'EDEADLOCK': '35', - 'EDESTADDRREQ': '89', - 'EDOM': '33', - 'EDOTDOT': '73', - 'EDQUOT': '122', - 'EEXIST': '17', - 'EFAULT': '14', - 'EFBIG': '27', - 'EHOSTDOWN': '112', - 'EHOSTUNREACH': '113', - 'EIDRM': '43', - 'EILSEQ': '84', - 'EINPROGRESS': '115', - 'EINTR': '4', - 'EINVAL': '22', - 'EIO': '5', - 'EISCONN': '106', - 'EISDIR': '21', - 'EL2HLT': '51', - 'EL2NSYNC': '45', - 'EL3HLT': '46', - 'EL3RST': '47', - 'ELIBACC': '79', - 'ELIBBAD': '80', - 'ELIBEXEC': '83', - 'ELIBMAX': '82', - 'ELIBSCN': '81', - 'ELNRNG': '48', - 'ELOOP': '40', - 'EMFILE': '24', - 'EMLINK': '31', - 'EMSGSIZE': '90', - 'EMULTIHOP': '72', - 'ENAMETOOLONG': '36', - 'ENETDOWN': '100', - 'ENETRESET': '102', - 'ENETUNREACH': '101', - 'ENFILE': '23', - 'ENOANO': '55', - 'ENOBUFS': '105', - 'ENOCSI': '50', - 'ENODATA': '61', - 'ENODEV': '19', - 'ENOENT': '2', - 'ENOEXEC': '8', - 'ENOLCK': '37', - 'ENOLINK': '67', - 'ENOMEDIUM': '123', - 'ENOMEM': '12', - 'ENOMSG': '42', - 'ENONET': '64', - 'ENOPKG': '65', - 'ENOPROTOOPT': '92', - 'ENOSPC': '28', - 'ENOSR': '63', - 'ENOSTR': '60', - 'ENOSYS': '38', - 'ENOTBLK': '15', - 'ENOTCONN': '107', - 'ENOTDIR': '20', - 'ENOTEMPTY': '39', - 'ENOTRECOVERABLE': '131', - 'ENOTSOCK': '88', - 'ENOTSUP': '95', - 'ENOTTY': '25', - 'ENOTUNIQ': '76', - 'ENXIO': '6', - 'EOF': '-1', - 'EOPNOTSUPP': '95', - 'EOVERFLOW': '75', - 'EOWNERDEAD': '130', - 'EPERM': '1', - 'EPFNOSUPPORT': '96', - 'EPIPE': '32', - 'EPROTO': '71', - 'EPROTONOSUPPORT': '93', - 'EPROTOTYPE': '91', - 'ERA': '131116', - 'ERANGE': '34', - 'ERA_D_FMT': '131118', - 'ERA_D_T_FMT': '131120', - 'ERA_T_FMT': '131121', - 'EREMCHG': '78', - 'EREMOTE': '66', - 'EROFS': '30', - 'ESHUTDOWN': '108', - 'ESOCKTNOSUPPORT': '94', - 'ESPIPE': '29', - 'ESRCH': '3', - 'ESRMNT': '69', - 'ESTALE': '116', - 'ESTRPIPE': '86', - 'ETIME': '62', - 'ETIMEDOUT': '110', - 'ETOOMANYREFS': '109', - 'ETXTBSY': '26', - 'EUNATCH': '49', - 'EUSERS': '87', - 'EWOULDBLOCK': '11', - 'EXDEV': '18', - 'EXFULL': '54', - 'FIONREAD': '21531', - 'FP_INFINITE': '1', - 'FP_NAN': '0', - 'FP_NORMAL': '4', - 'FP_ZERO': '2', - 'F_DUPFD': '0', - 'F_GETFD': '1', - 'F_GETFL': '3', - 'F_GETLK': '12', - 'F_GETLK64': '12', - 'F_GETOWN': '9', - 'F_SETFD': '2', - 'F_SETFL': '4', - 'F_SETLK': '13', - 'F_SETLK64': '13', - 'F_SETLKW': '14', - 'F_SETLKW64': '14', - 'F_SETOWN': '8', - 'F_UNLCK': '2', - 'INADDR_LOOPBACK': '2130706433', - 'IPPROTO_TCP': '6', - 'IPPROTO_UDP': '17', - 'MAP_PRIVATE': '2', - 'MON_1': '131098', - 'MON_10': '131107', - 'MON_11': '131108', - 'MON_12': '131109', - 'MON_2': '131099', - 'MON_3': '131100', - 'MON_4': '131101', - 'MON_5': '131102', - 'MON_6': '131103', - 'MON_7': '131104', - 'MON_8': '131105', - 'MON_9': '131106', - 'NI_NAMEREQD': '8', - 'NI_NUMERICHOST': '1', - 'NOEXPR': '327681', - 'O_ACCMODE': '2097155', - 'O_APPEND': '1024', - 'O_CREAT': '64', - 'O_EXCL': '128', - 'O_NOFOLLOW': '131072', - 'O_RDONLY': '0', - 'O_RDWR': '2', - 'O_SYNC': '1052672', - 'O_TRUNC': '512', - 'O_WRONLY': '1', - 'PM_STR': '131111', - 'POLLERR': '8', - 'POLLHUP': '16', - 'POLLIN': '1', - 'POLLNVAL': '32', - 'POLLOUT': '4', - 'POLLPRI': '2', - 'POLLRDNORM': '64', - 'RADIXCHAR': '65536', - 'R_OK': '4', - 'SEEK_END': '2', - 'SEEK_SET': '0', - 'SOCK_DGRAM': '2', - 'SOCK_STREAM': '1', - 'S_IALLUGO': '4095', - 'S_IFBLK': '24576', - 'S_IFCHR': '8192', - 'S_IFDIR': '16384', - 'S_IFIFO': '4096', - 'S_IFLNK': '40960', - 'S_IFMT': '61440', - 'S_IFREG': '32768', - 'S_IFSOCK': '49152', - 'S_IRUGO': '292', - 'S_IRWXO': '7', - 'S_IRWXUGO': '511', - 'S_ISVTX': '512', - 'S_IWUGO': '146', - 'S_IXUGO': '73', - 'THOUSEP': '65537', - 'T_FMT': '131114', - 'T_FMT_AMPM': '131115', - 'W_OK': '2', - 'X_OK': '1', - 'YESEXPR': '327680', - '_CS_GNU_LIBC_VERSION': '2', - '_CS_GNU_LIBPTHREAD_VERSION': '3', - '_CS_PATH': '0', - '_CS_POSIX_V6_ILP32_OFF32_CFLAGS': '1116', - '_CS_POSIX_V6_ILP32_OFF32_LDFLAGS': '1117', - '_CS_POSIX_V6_ILP32_OFF32_LIBS': '1118', - '_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS': '1120', - '_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS': '1121', - '_CS_POSIX_V6_ILP32_OFFBIG_LIBS': '1122', - '_CS_POSIX_V6_LP64_OFF64_CFLAGS': '1124', - '_CS_POSIX_V6_LP64_OFF64_LDFLAGS': '1125', - '_CS_POSIX_V6_LP64_OFF64_LIBS': '1126', - '_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS': '1128', - '_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS': '1129', - '_CS_POSIX_V6_LPBIG_OFFBIG_LIBS': '1130', - '_CS_POSIX_V6_WIDTH_RESTRICTED_ENVS': '1', - '_PC_2_SYMLINKS': '20', - '_PC_ALLOC_SIZE_MIN': '18', - '_PC_ASYNC_IO': '10', - '_PC_CHOWN_RESTRICTED': '6', - '_PC_FILESIZEBITS': '13', - '_PC_LINK_MAX': '0', - '_PC_MAX_CANON': '1', - '_PC_MAX_INPUT': '2', - '_PC_NAME_MAX': '3', - '_PC_NO_TRUNC': '7', - '_PC_PATH_MAX': '4', - '_PC_PIPE_BUF': '5', - '_PC_PRIO_IO': '11', - '_PC_REC_INCR_XFER_SIZE': '14', - '_PC_REC_MAX_XFER_SIZE': '15', - '_PC_REC_MIN_XFER_SIZE': '16', - '_PC_REC_XFER_ALIGN': '17', - '_PC_SOCK_MAXBUF': '12', - '_PC_SYMLINK_MAX': '19', - '_PC_SYNC_IO': '9', - '_PC_VDISABLE': '8', - '_SC_2_CHAR_TERM': '95', - '_SC_2_C_BIND': '47', - '_SC_2_C_DEV': '48', - '_SC_2_FORT_DEV': '49', - '_SC_2_FORT_RUN': '50', - '_SC_2_LOCALEDEF': '52', - '_SC_2_PBS': '168', - '_SC_2_PBS_ACCOUNTING': '169', - '_SC_2_PBS_CHECKPOINT': '175', - '_SC_2_PBS_LOCATE': '170', - '_SC_2_PBS_MESSAGE': '171', - '_SC_2_PBS_TRACK': '172', - '_SC_2_SW_DEV': '51', - '_SC_2_UPE': '97', - '_SC_2_VERSION': '46', - '_SC_ADVISORY_INFO': '132', - '_SC_AIO_LISTIO_MAX': '23', - '_SC_AIO_MAX': '24', - '_SC_AIO_PRIO_DELTA_MAX': '25', - '_SC_ARG_MAX': '0', - '_SC_ASYNCHRONOUS_IO': '12', - '_SC_ATEXIT_MAX': '87', - '_SC_BARRIERS': '133', - '_SC_BC_BASE_MAX': '36', - '_SC_BC_DIM_MAX': '37', - '_SC_BC_SCALE_MAX': '38', - '_SC_BC_STRING_MAX': '39', - '_SC_CHILD_MAX': '1', - '_SC_CLK_TCK': '2', - '_SC_CLOCK_SELECTION': '137', - '_SC_COLL_WEIGHTS_MAX': '40', - '_SC_CPUTIME': '138', - '_SC_DELAYTIMER_MAX': '26', - '_SC_EXPR_NEST_MAX': '42', - '_SC_FSYNC': '15', - '_SC_GETGR_R_SIZE_MAX': '69', - '_SC_GETPW_R_SIZE_MAX': '70', - '_SC_HOST_NAME_MAX': '180', - '_SC_IOV_MAX': '60', - '_SC_IPV6': '235', - '_SC_JOB_CONTROL': '7', - '_SC_LINE_MAX': '43', - '_SC_LOGIN_NAME_MAX': '71', - '_SC_MAPPED_FILES': '16', - '_SC_MEMLOCK': '17', - '_SC_MEMLOCK_RANGE': '18', - '_SC_MEMORY_PROTECTION': '19', - '_SC_MESSAGE_PASSING': '20', - '_SC_MONOTONIC_CLOCK': '149', - '_SC_MQ_OPEN_MAX': '27', - '_SC_MQ_PRIO_MAX': '28', - '_SC_NGROUPS_MAX': '3', - '_SC_NPROCESSORS_ONLN': '84', - '_SC_OPEN_MAX': '4', - '_SC_PAGE_SIZE': '30', - '_SC_PRIORITIZED_IO': '13', - '_SC_PRIORITY_SCHEDULING': '10', - '_SC_RAW_SOCKETS': '236', - '_SC_READER_WRITER_LOCKS': '153', - '_SC_REALTIME_SIGNALS': '9', - '_SC_REGEXP': '155', - '_SC_RE_DUP_MAX': '44', - '_SC_RTSIG_MAX': '31', - '_SC_SAVED_IDS': '8', - '_SC_SEMAPHORES': '21', - '_SC_SEM_NSEMS_MAX': '32', - '_SC_SEM_VALUE_MAX': '33', - '_SC_SHARED_MEMORY_OBJECTS': '22', - '_SC_SHELL': '157', - '_SC_SIGQUEUE_MAX': '34', - '_SC_SPAWN': '159', - '_SC_SPIN_LOCKS': '154', - '_SC_SPORADIC_SERVER': '160', - '_SC_STREAM_MAX': '5', - '_SC_SYMLOOP_MAX': '173', - '_SC_SYNCHRONIZED_IO': '14', - '_SC_THREADS': '67', - '_SC_THREAD_ATTR_STACKADDR': '77', - '_SC_THREAD_ATTR_STACKSIZE': '78', - '_SC_THREAD_CPUTIME': '139', - '_SC_THREAD_DESTRUCTOR_ITERATIONS': '73', - '_SC_THREAD_KEYS_MAX': '74', - '_SC_THREAD_PRIORITY_SCHEDULING': '79', - '_SC_THREAD_PRIO_INHERIT': '80', - '_SC_THREAD_PRIO_PROTECT': '81', - '_SC_THREAD_PROCESS_SHARED': '82', - '_SC_THREAD_SAFE_FUNCTIONS': '68', - '_SC_THREAD_SPORADIC_SERVER': '161', - '_SC_THREAD_STACK_MIN': '75', - '_SC_THREAD_THREADS_MAX': '76', - '_SC_TIMEOUTS': '164', - '_SC_TIMERS': '11', - '_SC_TIMER_MAX': '35', - '_SC_TRACE': '181', - '_SC_TRACE_EVENT_FILTER': '182', - '_SC_TRACE_EVENT_NAME_MAX': '242', - '_SC_TRACE_INHERIT': '183', - '_SC_TRACE_LOG': '184', - '_SC_TRACE_NAME_MAX': '243', - '_SC_TRACE_SYS_MAX': '244', - '_SC_TRACE_USER_EVENT_MAX': '245', - '_SC_TTY_NAME_MAX': '72', - '_SC_TYPED_MEMORY_OBJECTS': '165', - '_SC_TZNAME_MAX': '6', - '_SC_V6_ILP32_OFF32': '176', - '_SC_V6_ILP32_OFFBIG': '177', - '_SC_V6_LP64_OFF64': '178', - '_SC_V6_LPBIG_OFFBIG': '179', - '_SC_VERSION': '29', - '_SC_XBS5_ILP32_OFF32': '125', - '_SC_XBS5_ILP32_OFFBIG': '126', - '_SC_XBS5_LP64_OFF64': '127', - '_SC_XBS5_LPBIG_OFFBIG': '128', - '_SC_XOPEN_CRYPT': '92', - '_SC_XOPEN_ENH_I18N': '93', - '_SC_XOPEN_LEGACY': '129', - '_SC_XOPEN_REALTIME': '130', - '_SC_XOPEN_REALTIME_THREADS': '131', - '_SC_XOPEN_SHM': '94', - '_SC_XOPEN_STREAMS': '246', - '_SC_XOPEN_UNIX': '91', - '_SC_XOPEN_VERSION': '89' -}; +// The list of defines was moved into struct_info.json in the same directory. +// That file is automatically parsed by tools/gen_struct_info.py. +// If you modify the headers, just clear your cache and emscripten libc should see +// the new values. +// NOTE: Right now this value is ignored. +// TODO: See compiler.js (Should this var be deprecated?) +var C_DEFINES = {}; diff --git a/src/struct_info.json b/src/struct_info.json index 5b969603..2b095a8c 100644 --- a/src/struct_info.json +++ b/src/struct_info.json @@ -1,4 +1,7 @@ [ + // =========================================== + // libc + // =========================================== { "file": "libc/dirent.h", "defines": [], @@ -818,5 +821,193 @@ "MAP_PRIVATE" ], "structs": {} + }, + + // =========================================== + // SDL + // =========================================== + { + "file": "SDL/SDL_rect.h", + "defines": [], + "structs": { + "SDL_Rect": [ + "x", + "y", + "w", + "h" + ] + } + }, + { + "file": "SDL/SDL_keyboard.h", + "defines": [], + "structs": { + "SDL_Keysym": [ + "scancode", + "sym", + "mod", + "unicode" + ] + } + }, + { + "file": "SDL/SDL_pixels.h", + "defines": [], + "structs": { + "SDL_Palette": [ + "ncolors", + "colors", + "version", + "refcount" + ], + "SDL_PixelFormat": [ + "format", + "palette", + "BitsPerPixel", + "BytesPerPixel", + "padding", + "Rmask", + "Gmask", + "Bmask", + "Amask", + "Rloss", + "Gloss", + "Bloss", + "Aloss", + "Rshift", + "Gshift", + "Bshift", + "Ashift", + "refcount", + "next" + ], + "SDL_Color": [ + "r", + "g", + "b", + "unused" + ] + } + }, + { + "file": "SDL/SDL_events.h", + "defines": [], + "structs": { + "SDL_KeyboardEvent": [ + "type", + "windowID", + "state", + "repeat", + "padding2", + "padding3", + "keysym" + ], + "SDL_TextInputEvent": [ + "type", + "windowID", + "text" + ], + "SDL_MouseMotionEvent": [ + "type", + "windowID", + "state", + "padding1", + "padding2", + "padding3", + "x", + "y", + "xrel", + "yrel" + ], + "SDL_MouseButtonEvent": [ + "type", + "windowID", + "button", + "state", + "padding1", + "padding2", + "x", + "y" + ], + "SDL_ResizeEvent": [ + "type", + "w", + "h" + ] + } + }, + { + "file": "SDL_audio.h", + "defines": [ + "SDL_AUDIO_MASK_BITSIZE", + "SDL_AUDIO_MASK_DATATYPE", + "SDL_AUDIO_MASK_ENDIAN", + "SDL_AUDIO_MASK_SIGNED", + "AUDIO_U8", + "AUDIO_S8", + "AUDIO_U16LSB", + "AUDIO_S16LSB", + "AUDIO_U16MSB", + "AUDIO_S16MSB", + "AUDIO_U16", + "AUDIO_S16", + "AUDIO_S32LSB", + "AUDIO_S32MSB", + "AUDIO_S32", + "AUDIO_F32LSB", + "AUDIO_F32MSB", + "AUDIO_F32", + "AUDIO_U16SYS", + "AUDIO_S16SYS", + "AUDIO_S32SYS", + "AUDIO_F32SYS", + "SDL_AUDIO_ALLOW_FREQUENCY_CHANGE", + "SDL_AUDIO_ALLOW_FORMAT_CHANGE", + "SDL_AUDIO_ALLOW_CHANNELS_CHANGE", + "SDL_AUDIO_ALLOW_ANY_CHANGE", + "SDL_MIX_MAXVOLUME" + ], + "structs": { + "SDL_AudioCVT": [ + "needed", + "src_format", + "dst_format", + "rate_incr", + "buf", + "len", + "len_cvt", + "len_mult", + "len_ratio", + "filters", + "filter_index" + ], + "SDL_AudioSpec": [ + "freq", + "format", + "channels", + "silence", + "samples", + "padding", + "size", + "callback", + "userdata" + ] + } + }, + { + "file": "SDL_version.h", + "defines": [ + "SDL_MAJOR_VERSION", + "SDL_MINOR_VERSION", + "SDL_PATCHLEVEL", + "SDL_COMPILEDVERSION" + ], + "structs": { + "SDL_version": [ + "major", + "minor", + "patch" + ] + } } ] diff --git a/tools/gen_struct_info.py b/tools/gen_struct_info.py index 203a18ec..ccc4aee6 100644 --- a/tools/gen_struct_info.py +++ b/tools/gen_struct_info.py @@ -226,7 +226,7 @@ else: walker.structs = resolve_delayed(walker.structs) with open(path, 'r') as stream: - defines = re.findall(r'(?:^|\n)#define\s+([A-Z|_]+)\s.*', stream.read()) + defines = re.findall(r'(?:^|\n)\s*#define\s+([A-Z|_|0-9]+)\s.*', stream.read()) return { 'file': path, diff --git a/tools/shared.py b/tools/shared.py index 76802eaa..554813ee 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -1452,7 +1452,7 @@ class Building: Cache.ensure() import gen_struct_info - gen_struct_info.main(['-o', info_path, path_from_root('src/struct_info.json')]) + gen_struct_info.main(['-qo', info_path, path_from_root('src/struct_info.json')]) @staticmethod def preprocess(infile, outfile): -- cgit v1.2.3-18-g5258 From 43ed0e83b8f387eb4ca2eb8e491a4c810d74e56b Mon Sep 17 00:00:00 2001 From: ngld Date: Sun, 22 Sep 2013 03:00:39 +0200 Subject: Remove "-U__GNUC__" flag to avoid incorrect measurements. --- tools/gen_struct_info.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/gen_struct_info.py b/tools/gen_struct_info.py index ccc4aee6..6c479747 100644 --- a/tools/gen_struct_info.py +++ b/tools/gen_struct_info.py @@ -37,7 +37,7 @@ The JSON input format is as follows: 'defines': [ 'DEFINE_1', 'DEFINE_2', - ['f', 'FLOAT_DEFINE'], + ['li', 'FLOAT_DEFINE'], 'DEFINE_3', ... ] @@ -461,7 +461,7 @@ def main(args): QUIET = args.quiet # Avoid parsing problems due to gcc specifc syntax. - cpp_opts = ['-U__GNUC__', '-D_GNU_SOURCE'] + shared.COMPILER_OPTS + cpp_opts = ['-D_GNU_SOURCE'] + shared.COMPILER_OPTS # Add the user options to the list as well. for path in args.includes: @@ -506,4 +506,4 @@ def main(args): output_json(struct_info, not args.pretty_print, args.output) if __name__ == '__main__': - main(sys.argv[1:]) \ No newline at end of file + main(sys.argv[1:]) -- cgit v1.2.3-18-g5258 From e9705b2fcb179fd16b60ab35c31bff87a5704743 Mon Sep 17 00:00:00 2001 From: ngld Date: Wed, 25 Sep 2013 16:41:40 +0200 Subject: Add timeb.h to struct_info.json --- src/library.js | 16 ++++------------ src/struct_info.json | 14 +++++++++++++- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/library.js b/src/library.js index b45dd8f5..2e2298ec 100644 --- a/src/library.js +++ b/src/library.js @@ -6069,20 +6069,12 @@ LibraryManager.library = { // sys/timeb.h // ========================================================================== - // TODO: Where did this header go? - __timeb_struct_layout: Runtime.generateStructInfo([ - ['i32', 'time'], - ['i16', 'millitm'], - ['i16', 'timezone'], - ['i16', 'dstflag'] - ]), - ftime__deps: ['__timeb_struct_layout'], ftime: function(p) { var millis = Date.now(); - {{{ makeSetValue('p', '___timeb_struct_layout.time', 'Math.floor(millis/1000)', 'i32') }}}; - {{{ makeSetValue('p', '___timeb_struct_layout.millitm', 'millis % 1000', 'i16') }}}; - {{{ makeSetValue('p', '___timeb_struct_layout.timezone', '0', 'i16') }}}; // TODO - {{{ makeSetValue('p', '___timeb_struct_layout.dstflag', '0', 'i16') }}}; // TODO + {{{ makeSetValue('p', C_STRUCTS.timeb.time, 'Math.floor(millis/1000)', 'i32') }}}; + {{{ makeSetValue('p', C_STRUCTS.timeb.millitm, 'millis % 1000', 'i16') }}}; + {{{ makeSetValue('p', C_STRUCTS.timeb.timezone, '0', 'i16') }}}; // TODO + {{{ makeSetValue('p', C_STRUCTS.timeb.dstflag, '0', 'i16') }}}; // TODO return 0; }, diff --git a/src/struct_info.json b/src/struct_info.json index 2b095a8c..28d24279 100644 --- a/src/struct_info.json +++ b/src/struct_info.json @@ -224,7 +224,19 @@ "tms_cstime" ] } - }, + }, + { + "defines": [], + "file": "compat/sys/timeb.h", + "structs": { + "timeb": [ + "time", + "millitm", + "timezone", + "dstflag" + ] + } + }, { "file": "libc/sys/resource.h", "defines": [], -- cgit v1.2.3-18-g5258 From 8481d3023417529839067af4dca9c5484b69c309 Mon Sep 17 00:00:00 2001 From: ngld Date: Wed, 25 Sep 2013 17:33:52 +0200 Subject: Replace references to QUANTUM_SIZE with C_STRUCTS equivalents. --- src/library.js | 6 +++--- src/library_sdl.js | 40 ++++++++++++++++++++-------------------- src/struct_info.json | 24 ++++++++++++++++++++++-- 3 files changed, 45 insertions(+), 25 deletions(-) diff --git a/src/library.js b/src/library.js index 2e2298ec..7a144951 100644 --- a/src/library.js +++ b/src/library.js @@ -5274,12 +5274,12 @@ LibraryManager.library = { return time1 - time0; }, - // Statically allocated time struct. (TODO: Shouldn't C_STRUCTS.tm.__size__ be used here?) - __tm_current: 'allocate({{{ Runtime.QUANTUM_SIZE }}}*26, "i8", ALLOC_STATIC)', + // Statically allocated time struct. + __tm_current: 'allocate({{{ C_STRUCTS.tm.__size__ }}}, "i8", ALLOC_STATIC)', // Statically allocated timezone string. We only use GMT as a timezone. __tm_timezone: 'allocate(intArrayFromString("GMT"), "i8", ALLOC_STATIC)', // Statically allocated time strings. - __tm_formatted: 'allocate({{{ Runtime.QUANTUM_SIZE }}}*26, "i8", ALLOC_STATIC)', + __tm_formatted: 'allocate({{{ C_STRUCTS.tm.__size__ }}}, "i8", ALLOC_STATIC)', mktime__deps: ['tzset'], mktime: function(tmPtr) { diff --git a/src/library_sdl.js b/src/library_sdl.js index e9d5a1d9..656b5a02 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -184,35 +184,35 @@ var LibrarySDL = { makeSurface: function(width, height, flags, usePageCanvas, source, rmask, gmask, bmask, amask) { flags = flags || 0; - var surf = _malloc(15*Runtime.QUANTUM_SIZE); // SDL_Surface has 15 fields of quantum size + var surf = _malloc({{{ C_STRUCTS.SDL_Surface.__size__ }}}); // SDL_Surface has 15 fields of quantum size var buffer = _malloc(width*height*4); // TODO: only allocate when locked the first time - var pixelFormat = _malloc(18*Runtime.QUANTUM_SIZE); + var pixelFormat = _malloc({{{ C_STRUCTS.SDL_PixelFormat.__size__ }}}); flags |= 1; // SDL_HWSURFACE - this tells SDL_MUSTLOCK that this needs to be locked //surface with SDL_HWPALETTE flag is 8bpp surface (1 byte) var is_SDL_HWPALETTE = flags & 0x00200000; var bpp = is_SDL_HWPALETTE ? 1 : 4; - {{{ makeSetValue('surf+Runtime.QUANTUM_SIZE*0', '0', 'flags', 'i32') }}} // SDL_Surface.flags - {{{ 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 * bpp', 'i32') }}} // SDL_Surface.pitch, assuming RGBA or indexed for now, + {{{ makeSetValue('surf', C_STRUCTS.SDL_Surface.flags, 'flags', 'i32') }}} // SDL_Surface.flags + {{{ makeSetValue('surf', C_STRUCTS.SDL_Surface.format, 'pixelFormat', 'void*') }}} // SDL_Surface.format TODO + {{{ makeSetValue('surf', C_STRUCTS.SDL_Surface.w, 'width', 'i32') }}} // SDL_Surface.w + {{{ makeSetValue('surf', C_STRUCTS.SDL_Surface.h, 'height', 'i32') }}} // SDL_Surface.h + {{{ makeSetValue('surf', C_STRUCTS.SDL_Surface.pitch, 'width * bpp', 'i32') }}} // SDL_Surface.pitch, assuming RGBA or indexed 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('surf', C_STRUCTS.SDL_Surface.pixels, 'buffer', 'void*') }}} // SDL_Surface.pixels + {{{ makeSetValue('surf', C_STRUCTS.SDL_Surface.clip_rect, '0', 'i32*') }}} // SDL_Surface.offset - {{{ makeSetValue('surf+Runtime.QUANTUM_SIZE*14', '0', '1', 'i32') }}} + {{{ makeSetValue('surf', C_STRUCTS.SDL_Surface.refcount, '1', 'i32') }}} - {{{ makeSetValue('pixelFormat + ' + C_STRUCTS.SDL_PixelFormat.format, '0', '-2042224636', 'i32') }}} // SDL_PIXELFORMAT_RGBA8888 - {{{ makeSetValue('pixelFormat + ' + C_STRUCTS.SDL_PixelFormat.palette, '0', '0', 'i32') }}} // TODO - {{{ makeSetValue('pixelFormat + ' + C_STRUCTS.SDL_PixelFormat.BitsPerPixel, '0', 'bpp * 8', 'i8') }}} - {{{ makeSetValue('pixelFormat + ' + C_STRUCTS.SDL_PixelFormat.BytesPerPixel, '0', 'bpp', 'i8') }}} + {{{ makeSetValue('pixelFormat', C_STRUCTS.SDL_PixelFormat.format, cDefine('SDL_PIXELFORMAT_RGBA8888'), 'i32') }}} // SDL_PIXELFORMAT_RGBA8888 + {{{ makeSetValue('pixelFormat', C_STRUCTS.SDL_PixelFormat.palette, '0', 'i32') }}} // TODO + {{{ makeSetValue('pixelFormat', C_STRUCTS.SDL_PixelFormat.BitsPerPixel, 'bpp * 8', 'i8') }}} + {{{ makeSetValue('pixelFormat', C_STRUCTS.SDL_PixelFormat.BytesPerPixel, 'bpp', 'i8') }}} - {{{ makeSetValue('pixelFormat + ' + C_STRUCTS.SDL_PixelFormat.Rmask, '0', 'rmask || 0x000000ff', 'i32') }}} - {{{ makeSetValue('pixelFormat + ' + C_STRUCTS.SDL_PixelFormat.Gmask, '0', 'gmask || 0x0000ff00', 'i32') }}} - {{{ makeSetValue('pixelFormat + ' + C_STRUCTS.SDL_PixelFormat.Bmask, '0', 'bmask || 0x00ff0000', 'i32') }}} - {{{ makeSetValue('pixelFormat + ' + C_STRUCTS.SDL_PixelFormat.Amask, '0', 'amask || 0xff000000', 'i32') }}} + {{{ makeSetValue('pixelFormat', C_STRUCTS.SDL_PixelFormat.Rmask, 'rmask || 0x000000ff', 'i32') }}} + {{{ makeSetValue('pixelFormat', C_STRUCTS.SDL_PixelFormat.Gmask, 'gmask || 0x0000ff00', 'i32') }}} + {{{ makeSetValue('pixelFormat', C_STRUCTS.SDL_PixelFormat.Bmask, 'bmask || 0x00ff0000', 'i32') }}} + {{{ makeSetValue('pixelFormat', C_STRUCTS.SDL_PixelFormat.Amask, 'amask || 0xff000000', 'i32') }}} // Decide if we want to use WebGL or not var useWebGL = (flags & 0x04000000) != 0; // SDL_OPENGL @@ -290,7 +290,7 @@ var LibrarySDL = { }, freeSurface: function(surf) { - var refcountPointer = surf + Runtime.QUANTUM_SIZE * 14; + var refcountPointer = surf + {{{ C_STRUCTS.SDL_Surface.refcount }}}; var refcount = {{{ makeGetValue('refcountPointer', '0', 'i32') }}}; if (refcount > 1) { {{{ makeSetValue('refcountPointer', '0', 'refcount - 1', 'i32') }}}; @@ -810,7 +810,7 @@ var LibrarySDL = { // 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*') }}}; + {{{ makeSetValue('surf', C_STRUCTS.SDL_Surface.pixels, 'surfData.buffer', 'void*') }}}; if (surf == SDL.screen && Module.screenIsReadOnly && surfData.image) return 0; diff --git a/src/struct_info.json b/src/struct_info.json index 28d24279..5b4726e8 100644 --- a/src/struct_info.json +++ b/src/struct_info.json @@ -901,6 +901,26 @@ ] } }, + { + "file": "SDL/SDL_surface.h", + "defines": [], + "structs": { + "SDL_Surface": [ + "flags", + "format", + "w", + "h", + "pitch", + "pixels", + "userdata", + "locked", + "lock_data", + "clip_rect", + "map", + "refcount" + ] + } + }, { "file": "SDL/SDL_events.h", "defines": [], @@ -949,7 +969,7 @@ } }, { - "file": "SDL_audio.h", + "file": "SDL/SDL_audio.h", "defines": [ "SDL_AUDIO_MASK_BITSIZE", "SDL_AUDIO_MASK_DATATYPE", @@ -1007,7 +1027,7 @@ } }, { - "file": "SDL_version.h", + "file": "SDL/SDL_version.h", "defines": [ "SDL_MAJOR_VERSION", "SDL_MINOR_VERSION", -- cgit v1.2.3-18-g5258 From 2370dd4b6f32b9be38c736b3060ba690a720483f Mon Sep 17 00:00:00 2001 From: ngld Date: Wed, 25 Sep 2013 17:44:57 +0200 Subject: Fix some comments and bump EMSCRIPTEN_VERSION --- src/compiler.js | 1 - src/settings.js | 8 +------- tools/gen_struct_info.py | 4 ++-- tools/shared.py | 2 +- 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/compiler.js b/src/compiler.js index 69824035..f7c6dd59 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -207,7 +207,6 @@ if (VERBOSE) printErr('VERBOSE is on, this generates a lot of output and can slo // Load struct and define information. var temp = JSON.parse(read(STRUCT_INFO)); C_STRUCTS = temp.structs; -// NOTE: This overwrites C_DEFINES from settings.js, should this be fixed or will C_DEFINES in settings.js be deprecated? C_DEFINES = temp.defines; // Load compiler code diff --git a/src/settings.js b/src/settings.js index 8d9d4634..8cdf420c 100644 --- a/src/settings.js +++ b/src/settings.js @@ -438,13 +438,7 @@ var DEBUG_TAGS_SHOWING = []; // metadata // legalizer -// A cached set of defines, generated from the header files. This -// lets the emscripten libc (library.js) see the right values. -// The list of defines was moved into struct_info.json in the same directory. +// The list of defines (C_DEFINES) was moved into struct_info.json in the same directory. // That file is automatically parsed by tools/gen_struct_info.py. // If you modify the headers, just clear your cache and emscripten libc should see // the new values. -// NOTE: Right now this value is ignored. -// TODO: See compiler.js (Should this var be deprecated?) -var C_DEFINES = {}; - diff --git a/tools/gen_struct_info.py b/tools/gen_struct_info.py index 6c479747..aab128eb 100644 --- a/tools/gen_struct_info.py +++ b/tools/gen_struct_info.py @@ -37,7 +37,7 @@ The JSON input format is as follows: 'defines': [ 'DEFINE_1', 'DEFINE_2', - ['li', 'FLOAT_DEFINE'], + ['f', 'FLOAT_DEFINE'], 'DEFINE_3', ... ] @@ -92,7 +92,7 @@ except ImportError: show('WARN: pycparser isn\'t available. I won\'t be able to parse C files, only .json files.') def parse_header(path, cpp_opts): - # Tell the user how to get pycparser, if he tries to parse a C file. + # Tell the user how to get pycparser, if he or she tries to parse a C file. sys.stderr.write('ERR: I need pycparser to process C files. \n') sys.stderr.write(' Use "pip install pycparser" to install or download it from "https://github.com/eliben/pycparser".\n') sys.exit(1) diff --git a/tools/shared.py b/tools/shared.py index 554813ee..53f83185 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -304,7 +304,7 @@ def find_temp_directory(): # we re-check sanity when the settings are changed) # We also re-check sanity and clear the cache when the version changes -EMSCRIPTEN_VERSION = '1.5.9' +EMSCRIPTEN_VERSION = '1.5.10' def generate_sanity(): return EMSCRIPTEN_VERSION + '|' + get_llvm_target() + '|' + LLVM_ROOT -- cgit v1.2.3-18-g5258