diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2823e3b --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.nyc_output +build +coverage +node_modules +package-lock.json +vcd_parser.* diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..671e54c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,18 @@ +language: node_js +node_js: + - "12" + - "11" + - "10" + - "9" + - "8" + - "6" +os: + - linux + - osx +# - windows +sudo: false +install: + - npm --version + - npm install +script: + - npm test diff --git a/README.md b/README.md index 1d4a4d1..577bf32 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,14 @@ # :construction: Work In Progress :construction: Value Change Dump ([VCD](https://en.wikipedia.org/wiki/Value_change_dump)) parser using [llparse](https://github.com/nodejs/llparse) + +## Test + +``` +npm i +npm test +``` + +## License + +MIT [LICENSE](LICENSE) diff --git a/bin/build.js b/bin/build.js new file mode 100755 index 0000000..8099184 --- /dev/null +++ b/bin/build.js @@ -0,0 +1,35 @@ +#!/usr/bin/env node +'use strict'; + +const fs = require('fs'); +const llparse = require('llparse'); +const llparseDot = require('llparse-dot'); + +const prj = 'vcd_parser'; + +const p = new llparse.LLParse(prj); + +const start = p.node('start'); +const stop = p.node('stop'); + +start + .match('stop', stop) + .otherwise(p.error(1, 'Expected start')); + +stop + .match('start', start) + .otherwise(p.error(2, 'Expected start')); + +// Build + +const artifacts = p.build(start); + +fs.writeFileSync(prj + '.h', artifacts.header); +// fs.writeFileSync('verilog_preprocessor.bc', artifacts.bitcode); +fs.writeFileSync(prj + '.c', artifacts.c); + +const dot = new llparseDot.Dot(); + +fs.writeFileSync(prj + '.dot', dot.build(start)); + +/* eslint camelcase: 0 */ diff --git a/binding.gyp b/binding.gyp new file mode 100644 index 0000000..4dc3222 --- /dev/null +++ b/binding.gyp @@ -0,0 +1,11 @@ +{ + "targets": [ + { + "target_name": "vcd_parser", + "sources": [ + "vcd_parser.c", + "vcd.c" + ] + } + ] +} diff --git a/index.js b/index.js new file mode 100644 index 0000000..437b854 --- /dev/null +++ b/index.js @@ -0,0 +1,8 @@ +'use strict'; + +const pkg = require('./package.json'); + +let lib = require('bindings')('vpreproc.node'); +lib.version = pkg.version; + +module.exports = lib; diff --git a/package.json b/package.json new file mode 100644 index 0000000..8010532 --- /dev/null +++ b/package.json @@ -0,0 +1,39 @@ +{ + "name": "vcd", + "version": "0.1.0", + "description": "Value Change Dump (VCD) parser", + "main": "lib/index.js", + "scripts": { + "test": "eslint bin && nyc --reporter=lcov mocha", + "install": "node bin/build.js && node-gyp rebuild" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/wavedrom/vcd.git" + }, + "keywords": [ + "VCD" + ], + "author": "Aliaksei Chapyzhenka", + "license": "MIT", + "bugs": { + "url": "https://github.com/wavedrom/vcd/issues" + }, + "homepage": "https://github.com/wavedrom/vcd#readme", + "dependencies": { + "bindings": "^1.5.0", + "llparse": "^6.1.1" + }, + "devDependencies": { + "@drom/eslint-config": "^0.10.0", + "chai": "^4.2.0", + "eslint": "^5.16.0", + "llparse-dot": "^1.0.1", + "llparse-test-fixture": "^3.3.1", + "mocha": "^6.1.4", + "nyc": "^14.1.1" + }, + "eslintConfig": { + "extends": "@drom/eslint-config/eslint4/node8" + } +} diff --git a/vcd.c b/vcd.c new file mode 100644 index 0000000..a6adc2c --- /dev/null +++ b/vcd.c @@ -0,0 +1,100 @@ +#include +#include +#include "vcd_parser.h" +#include + +#define DECLARE_NAPI_METHOD(name, func) { \ + napi_property_descriptor desc = { name, 0, func, 0, 0, 0, napi_default, 0 }; \ + if (napi_define_properties(env, exports, 1, &desc) != napi_ok) { \ + napi_throw_error(env, 0, "Error"); \ + } \ +} + +#define METHOD(name) \ + napi_value name(napi_env env, napi_callback_info info) + +#define ASSERT(val, expr) \ + if (expr != napi_ok) { \ + napi_throw(env, val); \ + } + +#define ASSERT_ARGC(count) \ + napi_value args[count]; \ + { \ + size_t argc = count; \ + if (napi_get_cb_info(env, info, &argc, args, 0, 0) != napi_ok) { \ + napi_throw_error(env, 0, "Error"); \ + return 0; \ + } \ + if (argc < count) { \ + napi_throw_type_error(env, 0, "Wrong number of arguments"); \ + return 0; \ + } \ + } + +#define ASSERT_STRING(name, var) \ + char var[256]; \ + { \ + napi_value tmp; \ + if (napi_coerce_to_string(env, name, &tmp) != napi_ok) { \ + napi_throw(env, name); \ + return 0; \ + } \ + size_t result; \ + if (napi_get_value_string_latin1(env, tmp, var, 256, &result) != napi_ok) { \ + napi_throw(env, name); \ + return 0; \ + } \ + } + +#define ASSERT_EXTERNAL(name, var) { \ + napi_valuetype valuetype; \ + if (napi_typeof(env, name, &valuetype) != napi_ok) { \ + napi_throw(env, name); \ + return 0; \ + } \ + if (valuetype != napi_external) { \ + napi_throw_type_error(env, 0, "Wrong arguments"); \ + return 0; \ + } \ + if (napi_get_value_external(env, name, (void **)(&var)) != napi_ok) { \ + napi_throw(env, name); \ + return 0; \ + } \ +} + +METHOD(init) { + struct vcd_parser_s *state = malloc(sizeof *state); + + const int32_t error = vcd_parser_init(state); + + napi_value res; + if (error) { + ASSERT(res, napi_create_int32(env, error, &res)) + } else { + ASSERT(res, napi_create_external(env, state, 0, 0, &res)) + } + return res; +} + +METHOD(execute) { + ASSERT_ARGC(3) + struct vcd_parser_s *state; + ASSERT_EXTERNAL(args[0], state) + ASSERT_STRING(args[1], p) + ASSERT_STRING(args[2], endp) + + const int32_t error = vcd_parser_execute(state, p, endp); + + napi_value res; + ASSERT(res, napi_create_int32(env, error, &res)) + return res; +} + +napi_value Init(napi_env env, napi_value exports) { + DECLARE_NAPI_METHOD("init", init) + DECLARE_NAPI_METHOD("execute", execute) + return exports; +} + +NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)