mirror of
https://github.com/rizinorg/jsdec.git
synced 2026-11-07 14:58:12 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8180b60b9a | ||
|
|
1903c99b3a | ||
|
|
65821969c1 | ||
|
|
ac88882529 | ||
|
|
055f537948 | ||
|
|
0d559b8bb6 | ||
|
|
b63ab4b190 | ||
|
|
394628eaad | ||
|
|
02f34ad351 | ||
|
|
9a567c14a6 | ||
|
|
c35c9a20f9 | ||
|
|
7676831b3b | ||
|
|
d958b56f64 | ||
|
|
f53ad7a2a1 | ||
|
|
068f799e5e | ||
|
|
123fca01f8 | ||
|
|
092ea99273 | ||
|
|
efeea7d750 | ||
|
|
ccbbd071c4 | ||
|
|
1576b650c1 | ||
|
|
3890f3f4c4 | ||
|
|
b16bff8263 | ||
|
|
9a721bfbdf | ||
|
|
b6f29a6a91 | ||
|
|
f07b5b8c06 | ||
|
|
c299b1823e | ||
|
|
58e1adf0ed | ||
|
|
21a9b20c09 | ||
|
|
9bbd0fb2e3 | ||
|
|
906664e1fd |
No files matched your search
@@ -3,7 +3,14 @@ set -e
|
||||
|
||||
CI_BRANCH="$1"
|
||||
CI_JSDEC="$PWD"
|
||||
CI_RZ_VERSION=$(curl -s GET https://api.github.com/repos/rizinorg/rizin/tags\?per_page\=1 | jq -r '.[].name')
|
||||
CI_RZ_VERSION=$2
|
||||
|
||||
if [ "$CI_BRANCH" != "dev" ]; then
|
||||
# stable branch always build against latest release of rizin
|
||||
CI_RZ_VERSION=$(curl -s GET https://api.github.com/repos/rizinorg/rizin/tags\?per_page\=1 | jq -r '.[].name')
|
||||
else
|
||||
CI_RZ_VERSION="$CI_BRANCH"
|
||||
fi
|
||||
|
||||
echo "CI_BRANCH: $CI_BRANCH"
|
||||
echo "CI_RZ_VERSION: $CI_RZ_VERSION"
|
||||
@@ -12,11 +19,19 @@ echo "CI_JSDEC: $CI_JSDEC"
|
||||
# avoid placing rizin in the same folder.
|
||||
cd ..
|
||||
|
||||
# download the latest tagged rizin version and install it
|
||||
wget -O "rizin.tar.xz" "https://github.com/rizinorg/rizin/releases/download/$CI_RZ_VERSION/rizin-src-$CI_RZ_VERSION.tar.xz"
|
||||
tar xf "rizin.tar.xz"
|
||||
cd "rizin-$CI_RZ_VERSION"
|
||||
# download rizin
|
||||
if [ "$CI_BRANCH" == "dev" ]; then
|
||||
# dev branch always build against latest commit of rizin
|
||||
wget -O "rizin.tar.gz" "https://github.com/rizinorg/rizin/archive/refs/heads/dev.tar.gz"
|
||||
tar xf "rizin.tar.gz"
|
||||
else
|
||||
# stable branch always build against latest release of rizin
|
||||
wget -O "rizin.tar.xz" "https://github.com/rizinorg/rizin/releases/download/$CI_RZ_VERSION/rizin-src-$CI_RZ_VERSION.tar.xz"
|
||||
tar xf "rizin.tar.xz"
|
||||
fi
|
||||
|
||||
# build rizin and install it.
|
||||
cd "rizin-$CI_RZ_VERSION"
|
||||
meson setup --buildtype=release -Denable_tests=false build
|
||||
sudo ninja -C build install
|
||||
|
||||
@@ -28,18 +43,19 @@ rm -rf "rizin-*"
|
||||
cd "$CI_JSDEC"
|
||||
|
||||
# build jsdec and install in the rizin dir.
|
||||
meson setup --buildtype=release -Dstandalone=false build
|
||||
sudo ninja -C build install
|
||||
meson setup --buildtype=release -Dbuild_type=rizin --prefix=~/.local build
|
||||
sudo ninja -C build install || sleep 0
|
||||
|
||||
# check if it was installed correctly and try to run it.
|
||||
HAS_JSDEC=$(rizin -Qc "Lc" | grep jsdec)
|
||||
HAS_JSDEC=$(rizin -qc "Lc" | grep jsdec)
|
||||
if [ -z "$HAS_JSDEC" ]; then
|
||||
echo "rizin failed to load jsdec."
|
||||
rizin -e log.level=2 -Qc "Lc" | grep jsdec || sleep 0
|
||||
rizin -e log.level=0 -qc "Lc"
|
||||
rizin -hh
|
||||
exit 1
|
||||
fi
|
||||
|
||||
OUTPUT=$(rizin -Qc 'af ; pdd' /bin/ls)
|
||||
OUTPUT=$(rizin -qc 'af ; pdd' /bin/ls)
|
||||
CHECK=$(echo -e "$OUTPUT" | grep "jsdec pseudo code output")
|
||||
echo -e "$OUTPUT"
|
||||
if [ -z "$CHECK" ]; then
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
echo off
|
||||
set ARCH="%1"
|
||||
set PKG_CONFIG_PATH=%CD%\..\rizin\lib\pkgconfig
|
||||
set CFLAGS="-I%CD%\..\rizin\include\librz -I%CD%\..\rizin\include\librz\sdb"
|
||||
set LDFLAGS=-L%CD%\..\rizin\lib
|
||||
set PATH=%CD%\..\rizin\bin;%PATH%
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" "%ARCH%"
|
||||
meson --buildtype=release --prefix="%CD%\..\rizin" build || exit /b 666
|
||||
ninja -C build install || exit /b 666
|
||||
rizin.exe -e log.level=2 -Qc "Lc" || exit /b 0
|
||||
rizin.exe -Qc "af ; pdd" "%CD%\..\rizin\bin\rizin.exe" || exit /b 0
|
||||
@@ -0,0 +1,33 @@
|
||||
.ci-scripts\vsdevenv.ps1 64
|
||||
|
||||
function Invoke-NativeCommand() {
|
||||
if ($args.Count -eq 0) {
|
||||
throw "Must supply some arguments."
|
||||
}
|
||||
|
||||
$command = $args[0]
|
||||
$commandArgs = @()
|
||||
if ($args.Count -gt 1) {
|
||||
$commandArgs = $args[1..($args.Count - 1)]
|
||||
}
|
||||
|
||||
& $command $commandArgs
|
||||
$result = $LASTEXITCODE
|
||||
|
||||
if ($result -ne 0) {
|
||||
throw "$command $commandArgs exited with code $result."
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$rizin_path = "C:$env:HOMEPATH\AppData\Local\Programs\rizin"
|
||||
$env:PATH = "$env:PATH;C:$env:HOMEPATH\AppData\Local\Programs\rizin\bin"
|
||||
$env:PKG_CONFIG_PATH = "C:$env:HOMEPATH\AppData\Local\Programs\rizin\lib\pkgconfig"
|
||||
$env:CFLAGS = "-IC:$env:HOMEPATH\AppData\Local\Programs\rizin\include\librz -IC:$env:HOMEPATH\AppData\Local\Programs\rizin\include\librz\sdb"
|
||||
$env:LDFLAGS = "-LC:$env:HOMEPATH\AppData\Local\Programs\rizin\lib"
|
||||
|
||||
|
||||
Invoke-NativeCommand meson setup --buildtype=release --prefix="$rizin_path" build
|
||||
Invoke-NativeCommand ninja -C build install
|
||||
rizin.exe -e log.level=2 -qc "Lc"
|
||||
rizin.exe -qc "af ; pdd" "C:\Windows\System32\calc.exe"
|
||||
@@ -2,7 +2,7 @@
|
||||
set -e
|
||||
|
||||
## NPM eslint
|
||||
npm install -s eslint
|
||||
npm install --save-dev eslint
|
||||
|
||||
## NPM test
|
||||
find ./js -type f -name "*.js" | xargs node_modules/.bin/eslint -c ./.eslintrc.json
|
||||
find ./js -type f -name "*.js" | xargs node_modules/.bin/eslint --stats -c ./.eslint.config.js
|
||||
+13
-11
@@ -3,20 +3,22 @@ import json
|
||||
import sys
|
||||
import os
|
||||
|
||||
file_name = sys.argv[1]
|
||||
_, file_extension = os.path.splitext(file_name)
|
||||
out_file = f"rizin{file_extension}"
|
||||
print(file_name, out_file)
|
||||
out_file = "rizin.zip"
|
||||
|
||||
tags = None
|
||||
with urllib.request.urlopen('https://api.github.com/repos/rizinorg/rizin/tags?per_page=1') as f:
|
||||
tags = json.load(f)
|
||||
latest = tags[0]['name']
|
||||
latest = "stable" if len(sys.argv) < 1 else sys.argv[1]
|
||||
|
||||
url = f"https://github.com/rizinorg/rizin/releases/download/{latest}/{file_name}"
|
||||
url = url.format(version=latest)
|
||||
if latest != "dev":
|
||||
# stable branch always build against latest release of rizin
|
||||
tags = None
|
||||
with urllib.request.urlopen('https://api.github.com/repos/rizinorg/rizin/tags?per_page=1') as f:
|
||||
tags = json.load(f)
|
||||
latest = tags[0]['name']
|
||||
url = f"https://github.com/rizinorg/rizin/archive/refs/tags/{latest}.zip"
|
||||
else:
|
||||
# dev branch always build against latest commit of rizin
|
||||
url = "https://github.com/rizinorg/rizin/archive/refs/heads/dev.zip"
|
||||
|
||||
print(f"Latest rizin tag: {latest}")
|
||||
print(f"Using rizin branch: {latest}")
|
||||
print(f"{url} as {out_file}")
|
||||
|
||||
urllib.request.urlretrieve(url, out_file)
|
||||
@@ -1,7 +1,10 @@
|
||||
$bits = $args[0]
|
||||
$installationPath = vswhere.exe -latest -property installationPath
|
||||
if ($installationPath -and (test-path "$installationPath\Common7\Tools\vsdevcmd.bat")) {
|
||||
& "${env:COMSPEC}" /s /c "`"$installationPath\Common7\Tools\vsdevcmd.bat`" -no_logo && set" | foreach-object {
|
||||
$name, $value = $_ -split '=', 2
|
||||
set-content env:\"$name" $value
|
||||
if (-not $installationPath -or -not (test-path "$installationPath\VC\Auxiliary\Build\vcvars$bits.bat")) {
|
||||
throw "vcvars$bits.bat file not found"
|
||||
}
|
||||
& "${env:COMSPEC}" /s /c "`"$installationPath\VC\Auxiliary\Build\vcvars$bits.bat`" > nul 2>&1 && set" | . { process {
|
||||
if ($_ -match '^([^=]+)=(.*)') {
|
||||
[System.Environment]::SetEnvironmentVariable($matches[1], $matches[2])
|
||||
}
|
||||
}
|
||||
}}
|
||||
@@ -1,10 +1,22 @@
|
||||
{
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {}
|
||||
module.exports = {
|
||||
"languageOptions": {
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {}
|
||||
},
|
||||
"globals": {
|
||||
"process": true,
|
||||
"BigInt": true,
|
||||
"Global": true,
|
||||
"Limits": true,
|
||||
"rizin": true,
|
||||
"atob": true,
|
||||
"btoa": true,
|
||||
"unit": true,
|
||||
"console": true
|
||||
}
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"rules": {
|
||||
"semi": [2, "always"],
|
||||
"no-console": ["error", {
|
||||
@@ -18,6 +30,7 @@
|
||||
}],
|
||||
"no-unused-vars": ["error", {
|
||||
"varsIgnorePattern": "jsdec_|\\binclude\\b",
|
||||
"caughtErrors": "none",
|
||||
"args": "none"
|
||||
}],
|
||||
"curly": "error",
|
||||
@@ -26,17 +39,6 @@
|
||||
"no-constant-condition": ["error", {
|
||||
"checkLoops": false
|
||||
}],
|
||||
"no-control-regex": "warn"
|
||||
},
|
||||
"globals": {
|
||||
"process": true,
|
||||
"BigInt": true,
|
||||
"Global": true,
|
||||
"Limits": true,
|
||||
"rizin": true,
|
||||
"atob": true,
|
||||
"btoa": true,
|
||||
"unit": true,
|
||||
"console": true
|
||||
"no-control-regex": "warn"
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
version: 2
|
||||
|
||||
updates:
|
||||
- package-ecosystem: github-actions
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
@@ -3,7 +3,7 @@ name: build-plugin
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- stable
|
||||
- dev
|
||||
pull_request:
|
||||
|
||||
@@ -17,24 +17,24 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout commit
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
- name: Install dependencies
|
||||
run: sudo apt -y install meson ninja-build
|
||||
- name: Build & run the plugin
|
||||
run: bash .ci-scripts/ci-build-linux.sh "${{ github.ref_name }}"
|
||||
- name: Build & run jsdec as rizin plugin
|
||||
run: bash .ci-scripts/ci-build-linux.sh "${{ github.event.pull_request.base.ref || github.ref_name }}"
|
||||
|
||||
windows-64:
|
||||
runs-on: windows-latest
|
||||
name: ${{ matrix.release }}
|
||||
windows-latest:
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
release:
|
||||
- "windows-static"
|
||||
- "windows-shared64"
|
||||
os:
|
||||
- "windows-latest"
|
||||
- "windows-2022"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.9.x
|
||||
- name: Preparing msvc toolchain
|
||||
@@ -44,19 +44,23 @@ jobs:
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
pip install ninja meson
|
||||
pip install ninja meson PyYAML
|
||||
choco install pkgconfiglite
|
||||
choco install zip
|
||||
- name: Install rizin
|
||||
- name: Fetch & build rizin
|
||||
shell: bash
|
||||
run: |
|
||||
WORKDIR="$PWD"
|
||||
cd ..
|
||||
python "$WORKDIR/.ci-scripts/ci-rizin-dl.py" 'rizin-${{ matrix.release }}-{version}.zip'
|
||||
unzip rizin.zip
|
||||
python "$WORKDIR/.ci-scripts/ci-rizin-dl.py" '${{ github.event.pull_request.base.ref || github.ref_name }}'
|
||||
unzip -q rizin.zip
|
||||
rm *.zip
|
||||
mv rizin* rizin
|
||||
mv rizin* rizin-build
|
||||
cd rizin-build
|
||||
powershell.exe ".\dist\windows\build_windows_installer.ps1 vs2019_static 64 --default-library=shared -Dportable=true"
|
||||
ls ./dist/windows/Output
|
||||
powershell.exe '.\dist\windows\Output\rizin.exe /SP- /SILENT /CURRENTUSER'
|
||||
cd "$WORKDIR"
|
||||
- name: Build & run the plugin
|
||||
shell: cmd
|
||||
run: .ci-scripts/ci-build-win.bat x64
|
||||
- name: Build & run jsdec as rizin plugin
|
||||
shell: pwsh
|
||||
run: .ci-scripts\ci-build-win.ps1 64
|
||||
@@ -2,9 +2,9 @@ name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["master"]
|
||||
branches: ["stable", "dev"]
|
||||
pull_request:
|
||||
branches: ["master"]
|
||||
branches: ["stable", "dev"]
|
||||
schedule:
|
||||
- cron: "1 14 * * 5"
|
||||
|
||||
@@ -24,18 +24,18 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
queries: +security-and-quality
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
uses: github/codeql-action/autobuild@v4
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@v4
|
||||
with:
|
||||
category: "/language:${{ matrix.language }}"
|
||||
@@ -2,7 +2,7 @@ name: continuous-tests
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- stable
|
||||
- dev
|
||||
pull_request:
|
||||
|
||||
@@ -11,10 +11,10 @@ jobs:
|
||||
name: eslint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: "16"
|
||||
node-version: "21"
|
||||
- name: eslint
|
||||
run: chmod +x .ci-scripts/ci-eslint.sh && .ci-scripts/ci-eslint.sh
|
||||
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
name: tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- name: tests
|
||||
run: chmod +x .ci-scripts/ci-tests.sh && .ci-scripts/ci-tests.sh "${{ github.ref_name }}"
|
||||
|
||||
@@ -30,8 +30,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
- name: Reuse Compliance Check
|
||||
uses: fsfe/reuse-action@v2
|
||||
uses: fsfe/reuse-action@v6
|
||||
with:
|
||||
args: --suppress-deprecation lint
|
||||
@@ -1,2 +1,5 @@
|
||||
build*/
|
||||
subprojects/libquick*/
|
||||
node_modules/
|
||||
package.json
|
||||
package-lock.json
|
||||
+5
-1
@@ -15,7 +15,7 @@ Files: .github/**/*
|
||||
Copyright: 2018-2021 Giovanni Dante Grazioli <[email protected]>
|
||||
License: BSD-3-Clause
|
||||
|
||||
Files: .eslintrc.json
|
||||
Files: .eslint.config.js
|
||||
Copyright: 2018-2021 Giovanni Dante Grazioli <[email protected]>
|
||||
License: BSD-3-Clause
|
||||
|
||||
@@ -46,3 +46,7 @@ License: BSD-3-Clause
|
||||
Files: .clang-format
|
||||
Copyright: 2021 Giovanni Dante Grazioli <[email protected]>
|
||||
License: BSD-3-Clause
|
||||
|
||||
Files: cutter-plugin/CMakeLists.txt
|
||||
Copyright: 2024 Giovanni Dante Grazioli <[email protected]>
|
||||
License: BSD-3-Clause
|
||||
@@ -1,9 +1,6 @@
|
||||

|
||||
[](https://lgtm.com/projects/g/rizinorg/jsdec/context:javascript)
|
||||
[](https://lgtm.com/projects/g/rizinorg/jsdec/alerts/)
|
||||
[](https://opensource.org/licenses/BSD-3-Clause)
|
||||
|
||||

|
||||

|
||||
|
||||
Converts asm to pseudo-C code.
|
||||
|
||||
@@ -90,5 +87,5 @@ e scr.color | enables syntax colors.
|
||||
|
||||
# Developing on jsdec
|
||||
|
||||
[Read DEVELOPERS.md](https://github.com/rizinorg/jsdec/blob/master/DEVELOPERS.md)
|
||||
[Read DEVELOPERS.md](https://github.com/rizinorg/jsdec/blob/dev/DEVELOPERS.md)
|
||||
|
||||
@@ -0,0 +1,375 @@
|
||||
// SPDX-FileCopyrightText: 2024 Giovanni Dante Grazioli <[email protected]>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <rz_types.h>
|
||||
#include <rz_lib.h>
|
||||
#include <rz_cmd.h>
|
||||
#include <rz_core.h>
|
||||
#include <rz_cons.h>
|
||||
#include <rz_analysis.h>
|
||||
|
||||
#include "jsdec.h"
|
||||
#include "jsdec-cutter.h"
|
||||
|
||||
typedef struct rz_core_t RzCore;
|
||||
|
||||
typedef struct exec_context_t {
|
||||
RzCore *core;
|
||||
void *bed;
|
||||
RzStrBuf *anno;
|
||||
JSValue shared;
|
||||
} ExecContext;
|
||||
|
||||
static JSValue js_analysis_bytes(JSContext *ctx, RzCore *core, RzCoreDecodedBytes *cdb) {
|
||||
RzAnalysisOp *aop = &cdb->an_op;
|
||||
JSValue op = JS_NewObject(ctx);
|
||||
JS_SetPropertyStr(ctx, op, "offset", JS_NewBigUint64(ctx, aop->addr));
|
||||
if (aop->ptr != UT64_MAX) {
|
||||
JS_SetPropertyStr(ctx, op, "ptr", JS_NewBigUint64(ctx, aop->ptr));
|
||||
}
|
||||
if (aop->val != UT64_MAX) {
|
||||
JS_SetPropertyStr(ctx, op, "val", JS_NewBigUint64(ctx, aop->val));
|
||||
}
|
||||
JS_SetPropertyStr(ctx, op, "opcode", JS_NewString(ctx, rz_str_get_null(cdb->opcode)));
|
||||
JS_SetPropertyStr(ctx, op, "disasm", JS_NewString(ctx, rz_str_get_null(cdb->disasm)));
|
||||
JS_SetPropertyStr(ctx, op, "type", JS_NewString(ctx, rz_analysis_optype_to_string(aop->type)));
|
||||
if (aop->jump != UT64_MAX) {
|
||||
JS_SetPropertyStr(ctx, op, "jump", JS_NewBigInt64(ctx, aop->jump));
|
||||
}
|
||||
if (aop->fail != UT64_MAX) {
|
||||
JS_SetPropertyStr(ctx, op, "fail", JS_NewBigUint64(ctx, aop->fail));
|
||||
}
|
||||
const char *comment = rz_meta_get_string(core->analysis, RZ_META_TYPE_COMMENT, aop->addr);
|
||||
if (RZ_STR_ISNOTEMPTY(comment)) {
|
||||
JS_SetPropertyStr(ctx, op, "comment", JS_NewString(ctx, comment));
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
static JSValue js_analysis_opcodes(JSContext *ctx, RzCore *core) {
|
||||
RzCoreDecodedBytes *cdb;
|
||||
JSValue ops = JS_NewArray(ctx);
|
||||
st64 op_idx = 0;
|
||||
|
||||
RzIterator *iter = rz_core_analysis_bytes(core, core->offset, core->block, core->blocksize, 0);
|
||||
if (!iter) {
|
||||
return ops;
|
||||
}
|
||||
rz_iterator_foreach(iter, cdb) {
|
||||
if (!cdb || !strcmp(cdb->opcode, "nop")) {
|
||||
continue;
|
||||
}
|
||||
JSValue op = js_analysis_bytes(ctx, core, cdb);
|
||||
JS_SetPropertyInt64(ctx, ops, op_idx, op);
|
||||
op_idx++;
|
||||
}
|
||||
rz_iterator_free(iter);
|
||||
return ops;
|
||||
}
|
||||
|
||||
static JSValue js_function_bbs(JSContext *ctx, RzCore *core, RzAnalysisFunction *fcn) {
|
||||
JSValue bbs = JS_NewArray(ctx);
|
||||
RzAnalysisBlock *bbi;
|
||||
void **iter;
|
||||
st64 bbs_idx = 0;
|
||||
ut64 old_offset = core->offset;
|
||||
ut64 old_bsize = core->blocksize;
|
||||
rz_pvector_foreach (fcn->bbs, iter) {
|
||||
bbi = (RzAnalysisBlock *)*iter;
|
||||
rz_core_block_size(core, bbi->size);
|
||||
rz_core_seek(core, bbi->addr, true);
|
||||
|
||||
JSValue bb = JS_NewObject(ctx);
|
||||
JS_SetPropertyStr(ctx, bb, "address", JS_NewBigUint64(ctx, bbi->addr));
|
||||
if (bbi->jump != UT64_MAX) {
|
||||
JS_SetPropertyStr(ctx, bb, "jump", JS_NewBigUint64(ctx, bbi->jump));
|
||||
}
|
||||
if (bbi->fail != UT64_MAX) {
|
||||
JS_SetPropertyStr(ctx, bb, "fail", JS_NewBigUint64(ctx, bbi->fail));
|
||||
}
|
||||
JSValue ops = js_analysis_opcodes(ctx, core);
|
||||
JS_SetPropertyStr(ctx, bb, "ops", ops);
|
||||
JS_SetPropertyInt64(ctx, bbs, bbs_idx, bb);
|
||||
bbs_idx++;
|
||||
}
|
||||
rz_core_block_size(core, old_bsize);
|
||||
rz_core_seek(core, old_offset, true);
|
||||
return bbs;
|
||||
}
|
||||
|
||||
static JSValue js_command(JSContext *ctx, JSValueConst jsThis, int argc, JSValueConst *argv) {
|
||||
if (argc != 1) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
const char *command = JS_ToCString(ctx, argv[0]);
|
||||
if (!command) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
ExecContext *ectx = (ExecContext *)JS_GetContextOpaque(ctx);
|
||||
RzCore *core = ectx->core;
|
||||
rz_cons_sleep_end(ectx->bed);
|
||||
|
||||
char *output = rz_core_cmd_str(core, command);
|
||||
JS_FreeCString(ctx, command);
|
||||
JSValue result = JS_NewString(ctx, output ? output : "");
|
||||
free(output);
|
||||
|
||||
ectx->bed = rz_cons_sleep_begin();
|
||||
return result;
|
||||
}
|
||||
|
||||
static JSValue js_graph(JSContext *ctx, JSValueConst jsThis, int argc, JSValueConst *argv) {
|
||||
if (argc != 0) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
ExecContext *ectx = (ExecContext *)JS_GetContextOpaque(ctx);
|
||||
RzCore *core = ectx->core;
|
||||
rz_cons_sleep_end(ectx->bed);
|
||||
|
||||
RzAnalysisFunction *fcn = rz_analysis_get_fcn_in(core->analysis, core->offset, -1);
|
||||
if (!fcn) {
|
||||
ectx->bed = rz_cons_sleep_begin();
|
||||
return JS_ThrowInternalError(ctx, "Cannot find function at 0x%08" PFMT64x, core->offset);
|
||||
}
|
||||
|
||||
JSValue graph = JS_NewArray(ctx);
|
||||
JSValue object = JS_NewObject(ctx);
|
||||
JS_SetPropertyInt64(ctx, graph, 0, object);
|
||||
JS_SetPropertyStr(ctx, object, "name", JS_NewString(ctx, rz_str_get_null(fcn->name)));
|
||||
JSValue blocks = js_function_bbs(ctx, core, fcn);
|
||||
JS_SetPropertyStr(ctx, object, "blocks", blocks);
|
||||
ectx->bed = rz_cons_sleep_begin();
|
||||
return graph;
|
||||
}
|
||||
|
||||
static JSValue js_console_log(JSContext *ctx, JSValueConst jsThis, int argc, JSValueConst *argv) {
|
||||
ExecContext *ectx = (ExecContext *)JS_GetContextOpaque(ctx);
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
if (i != 0) {
|
||||
rz_strbuf_append_n(ectx->anno, " ", 1);
|
||||
}
|
||||
const char *str = JS_ToCString(ctx, argv[i]);
|
||||
if (!str) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
rz_strbuf_append(ectx->anno, str);
|
||||
JS_FreeCString(ctx, str);
|
||||
}
|
||||
rz_strbuf_append_n(ectx->anno, "\n", 1);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_get_global(JSContext *ctx, JSValueConst jsThis, int argc, JSValueConst *argv) {
|
||||
ExecContext *ectx = (ExecContext *)JS_GetContextOpaque(ctx);
|
||||
return JS_GetPropertyStr(ctx, ectx->shared, "Shared");
|
||||
}
|
||||
|
||||
static jsdec_t *jsdec_create(ExecContext *ec) {
|
||||
jsdec_t *dec = jsdec_new();
|
||||
if (!dec) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSContext *ctx = jsdec_context(dec);
|
||||
JS_SetContextOpaque(ctx, ec);
|
||||
ec->shared = JS_NewObject(ctx);
|
||||
JS_SetPropertyStr(ctx, ec->shared, "Shared", JS_NewObject(ctx));
|
||||
|
||||
JSValue global = JS_GetGlobalObject(ctx);
|
||||
JS_SetPropertyStr(ctx, global, "Global", JS_NewCFunction(ctx, js_get_global, "Global", 1));
|
||||
|
||||
JSValue console = JS_NewObject(ctx);
|
||||
JS_SetPropertyStr(ctx, global, "console", console);
|
||||
JS_SetPropertyStr(ctx, console, "log", JS_NewCFunction(ctx, js_console_log, "log", 1));
|
||||
|
||||
JSValue rizin = JS_NewObject(ctx);
|
||||
JS_SetPropertyStr(ctx, global, "rizin", rizin);
|
||||
JS_SetPropertyStr(ctx, rizin, "command", JS_NewCFunction(ctx, js_command, "command", 1));
|
||||
JS_SetPropertyStr(ctx, rizin, "graph", JS_NewCFunction(ctx, js_graph, "graph", 1));
|
||||
|
||||
JSValue process = JS_NewObject(ctx);
|
||||
JS_SetPropertyStr(ctx, global, "process", process);
|
||||
JSValue args = JS_NewArray(ctx);
|
||||
JS_SetPropertyInt64(ctx, args, 0, JS_NewString(ctx, "--annotation"));
|
||||
JS_SetPropertyStr(ctx, process, "args", args);
|
||||
|
||||
JS_FreeValue(ctx, global);
|
||||
return dec;
|
||||
}
|
||||
|
||||
static void jsdec_destroy(jsdec_t *dec, ExecContext *ec) {
|
||||
JSContext *ctx = jsdec_context(dec);
|
||||
JS_FreeValue(ctx, ec->shared);
|
||||
jsdec_free(dec);
|
||||
}
|
||||
|
||||
static char *json_to_strdup(const RzJson *object, const char *key) {
|
||||
const RzJson *j = rz_json_get(object, key);
|
||||
if (!j || j->type != RZ_JSON_STRING) {
|
||||
return NULL;
|
||||
}
|
||||
return rz_str_dup(j->str_value);
|
||||
}
|
||||
|
||||
static const char *json_as_string(const RzJson *object, const char *key) {
|
||||
const RzJson *j = rz_json_get(object, key);
|
||||
if (!j || j->type != RZ_JSON_STRING) {
|
||||
return NULL;
|
||||
}
|
||||
return j->str_value;
|
||||
}
|
||||
|
||||
static ut64 json_as_ut64(const RzJson *object, const char *key) {
|
||||
const RzJson *j = rz_json_get(object, key);
|
||||
if (!j || (j->type != RZ_JSON_STRING && j->type != RZ_JSON_INTEGER)) {
|
||||
return 0;
|
||||
}
|
||||
if (j->type == RZ_JSON_INTEGER) {
|
||||
return j->num.u_value;
|
||||
} else if (rz_num_is_valid_input(NULL, j->str_value)) {
|
||||
return rz_num_get_input_value(NULL, j->str_value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static RzAnnotatedCode *parse_json(RzStrBuf *sb) {
|
||||
char *text = rz_strbuf_drain(sb);
|
||||
if (RZ_STR_ISEMPTY(text)) {
|
||||
free(text);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// text is modified by rz_json_parse and
|
||||
// is freed by rz_json_free
|
||||
RzJson *json = rz_json_parse(text);
|
||||
if (!json) {
|
||||
RZ_LOG_ERROR("failed to parse from json string\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *raw_code = json_to_strdup(json, "code");
|
||||
if (!raw_code) {
|
||||
rz_json_free(json);
|
||||
RZ_LOG_ERROR("failed to dup code\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RzAnnotatedCode *code = rz_annotated_code_new(raw_code);
|
||||
if (!code) {
|
||||
rz_json_free(json);
|
||||
RZ_LOG_ERROR("failed to create RzAnnotatedCode\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const RzJson *annotations = rz_json_get(json, "annotations");
|
||||
const RzJson *element = NULL;
|
||||
for (size_t idx = 0; annotations && (element = rz_json_item(annotations, idx)); idx++) {
|
||||
RzCodeAnnotation annotation = { 0 };
|
||||
annotation.start = json_as_ut64(element, "start");
|
||||
annotation.end = json_as_ut64(element, "end");
|
||||
const char *type = json_as_string(element, "type");
|
||||
if (!strcmp(type, "offset")) {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_OFFSET;
|
||||
annotation.offset.offset = json_as_ut64(element, "offset");
|
||||
} else if (!strcmp(type, "function_name")) {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_FUNCTION_NAME;
|
||||
annotation.reference.name = json_to_strdup(element, "name");
|
||||
annotation.reference.offset = json_as_ut64(element, "offset");
|
||||
} else if (!strcmp(type, "global_variable")) {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE;
|
||||
annotation.reference.offset = json_as_ut64(element, "offset");
|
||||
} else if (!strcmp(type, "constant_variable")) {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE;
|
||||
annotation.reference.offset = json_as_ut64(element, "offset");
|
||||
} else if (!strcmp(type, "local_variable")) {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_LOCAL_VARIABLE;
|
||||
annotation.variable.name = json_to_strdup(element, "name");
|
||||
} else if (!strcmp(type, "function_parameter")) {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_FUNCTION_PARAMETER;
|
||||
annotation.variable.name = json_to_strdup(element, "name");
|
||||
} else if (!strcmp(type, "syntax_highlight")) {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_SYNTAX_HIGHLIGHT;
|
||||
const char *highlightType = json_as_string(element, "syntax_highlight");
|
||||
if (!strcmp(highlightType, "keyword")) {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_KEYWORD;
|
||||
} else if (!strcmp(highlightType, "comment")) {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_COMMENT;
|
||||
} else if (!strcmp(highlightType, "datatype")) {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_DATATYPE;
|
||||
} else if (!strcmp(highlightType, "function_name")) {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_FUNCTION_NAME;
|
||||
} else if (!strcmp(highlightType, "function_parameter")) {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_FUNCTION_PARAMETER;
|
||||
} else if (!strcmp(highlightType, "local_variable")) {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_LOCAL_VARIABLE;
|
||||
} else if (!strcmp(highlightType, "constant_variable")) {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_CONSTANT_VARIABLE;
|
||||
} else if (!strcmp(highlightType, "global_variable")) {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_GLOBAL_VARIABLE;
|
||||
}
|
||||
}
|
||||
rz_annotated_code_add_annotation(code, &annotation);
|
||||
}
|
||||
|
||||
rz_json_free(json);
|
||||
return code;
|
||||
}
|
||||
|
||||
RZ_API void jsdec_init_config(RzCore *core) {
|
||||
RzConfig *cfg = core->config;
|
||||
|
||||
rz_config_lock(cfg, false);
|
||||
SETPREF("jsdec.asm", "false", "if true, shows pseudo next to the assembly.");
|
||||
SETPREF("jsdec.blocks", "false", "if true, shows only scopes blocks.");
|
||||
SETPREF("jsdec.casts", "false", "if false, hides all casts in the pseudo code.");
|
||||
SETPREF("jsdec.debug", "false", "do not catch exceptions in jsdec.");
|
||||
SETPREF("jsdec.highlight", "default", "highlights the current address.");
|
||||
SETPREF("jsdec.paddr", "false", "if true, all xrefs uses physical addresses compare.");
|
||||
SETPREF("jsdec.slow", "false", "load all the data before to avoid multirequests to rizin.");
|
||||
SETPREF("jsdec.xrefs", "false", "if true, shows all xrefs in the pseudo code.");
|
||||
rz_config_lock(cfg, true);
|
||||
}
|
||||
|
||||
RZ_API RzAnnotatedCode *jsdec_as_annotation(RzCore *core, ut64 addr) {
|
||||
ExecContext ectx;
|
||||
ectx.core = core;
|
||||
ectx.anno = rz_strbuf_new("");
|
||||
if (!ectx.anno) {
|
||||
rz_strbuf_free(ectx.anno);
|
||||
RZ_LOG_ERROR("failed to create RzStrBuf\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jsdec_t *dec = jsdec_create(&ectx);
|
||||
if (!dec) {
|
||||
rz_strbuf_free(ectx.anno);
|
||||
RZ_LOG_ERROR("failed to create jsdec_t\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ut64 offset = core->offset;
|
||||
if (offset != addr) {
|
||||
rz_core_seek(core, addr, true);
|
||||
}
|
||||
|
||||
ectx.bed = rz_cons_sleep_begin();
|
||||
bool ret = jsdec_run(dec);
|
||||
rz_cons_sleep_end(ectx.bed);
|
||||
|
||||
if (offset != addr) {
|
||||
rz_core_seek(core, offset, true);
|
||||
}
|
||||
|
||||
jsdec_destroy(dec, &ectx);
|
||||
if (!ret) {
|
||||
rz_strbuf_free(ectx.anno);
|
||||
RZ_LOG_ERROR("jsdec_run returned false\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return parse_json(ectx.anno);
|
||||
}
|
||||
+16
-13
@@ -49,8 +49,8 @@ typedef struct exec_context_t {
|
||||
#define rz_cmd_desc_argv_new_warn(rcmd, root, cmd) \
|
||||
rz_warn_if_fail(rz_cmd_desc_argv_new(rcmd, root, #cmd, name_handler(cmd), &name_help(cmd)))
|
||||
|
||||
static JSValue js_analysis_bytes(JSContext *ctx, RzCore *core, RzAnalysisBytes *ab) {
|
||||
RzAnalysisOp *aop = ab->op;
|
||||
static JSValue js_analysis_bytes(JSContext *ctx, RzCore *core, RzCoreDecodedBytes *cdb) {
|
||||
RzAnalysisOp *aop = &cdb->an_op;
|
||||
JSValue op = JS_NewObject(ctx);
|
||||
JS_SetPropertyStr(ctx, op, "offset", JS_NewBigUint64(ctx, aop->addr));
|
||||
if (aop->ptr != UT64_MAX) {
|
||||
@@ -59,8 +59,8 @@ static JSValue js_analysis_bytes(JSContext *ctx, RzCore *core, RzAnalysisBytes *
|
||||
if (aop->val != UT64_MAX) {
|
||||
JS_SetPropertyStr(ctx, op, "val", JS_NewBigUint64(ctx, aop->val));
|
||||
}
|
||||
JS_SetPropertyStr(ctx, op, "opcode", JS_NewString(ctx, rz_str_get_null(ab->opcode)));
|
||||
JS_SetPropertyStr(ctx, op, "disasm", JS_NewString(ctx, rz_str_get_null(ab->disasm)));
|
||||
JS_SetPropertyStr(ctx, op, "opcode", JS_NewString(ctx, rz_str_get_null(cdb->opcode)));
|
||||
JS_SetPropertyStr(ctx, op, "disasm", JS_NewString(ctx, rz_str_get_null(cdb->disasm)));
|
||||
JS_SetPropertyStr(ctx, op, "type", JS_NewString(ctx, rz_analysis_optype_to_string(aop->type)));
|
||||
if (aop->jump != UT64_MAX) {
|
||||
JS_SetPropertyStr(ctx, op, "jump", JS_NewBigInt64(ctx, aop->jump));
|
||||
@@ -76,7 +76,7 @@ static JSValue js_analysis_bytes(JSContext *ctx, RzCore *core, RzAnalysisBytes *
|
||||
}
|
||||
|
||||
static JSValue js_analysis_opcodes(JSContext *ctx, RzCore *core) {
|
||||
RzAnalysisBytes *ab;
|
||||
RzCoreDecodedBytes *cdb;
|
||||
JSValue ops = JS_NewArray(ctx);
|
||||
st64 op_idx = 0;
|
||||
|
||||
@@ -84,11 +84,11 @@ static JSValue js_analysis_opcodes(JSContext *ctx, RzCore *core) {
|
||||
if (!iter) {
|
||||
return ops;
|
||||
}
|
||||
rz_iterator_foreach (iter, ab) {
|
||||
if (!ab || !ab->op || !strcmp(ab->opcode, "nop")) {
|
||||
rz_iterator_foreach (iter, cdb) {
|
||||
if (!cdb || !strcmp(cdb->opcode, "nop")) {
|
||||
continue;
|
||||
}
|
||||
JSValue op = js_analysis_bytes(ctx, core, ab);
|
||||
JSValue op = js_analysis_bytes(ctx, core, cdb);
|
||||
JS_SetPropertyInt64(ctx, ops, op_idx, op);
|
||||
op_idx++;
|
||||
}
|
||||
@@ -99,11 +99,12 @@ static JSValue js_analysis_opcodes(JSContext *ctx, RzCore *core) {
|
||||
static JSValue js_function_bbs(JSContext *ctx, RzCore *core, RzAnalysisFunction *fcn) {
|
||||
JSValue bbs = JS_NewArray(ctx);
|
||||
RzAnalysisBlock *bbi;
|
||||
RzListIter *iter;
|
||||
void **iter;
|
||||
st64 bbs_idx = 0;
|
||||
ut64 old_offset = core->offset;
|
||||
ut64 old_bsize = core->blocksize;
|
||||
rz_list_foreach (fcn->bbs, iter, bbi) {
|
||||
rz_pvector_foreach (fcn->bbs, iter) {
|
||||
bbi = (RzAnalysisBlock *)*iter;
|
||||
rz_core_block_size(core, bbi->size);
|
||||
rz_core_seek(core, bbi->addr, true);
|
||||
|
||||
@@ -279,7 +280,8 @@ command_handler(pddi, "--issue");
|
||||
command_handler(pddj, "--as-json");
|
||||
command_handler(pddo, "--offsets");
|
||||
|
||||
static bool rz_cmd_pdd_init(RzCore *core) {
|
||||
static bool rz_cmd_pdd_init(RzCore *core, void **user) {
|
||||
(void)user;
|
||||
RzCmd *rcmd = core->rcmd;
|
||||
RzConfig *cfg = core->config;
|
||||
RzCmdDesc *root_cd = rz_cmd_get_desc(rcmd, "pd");
|
||||
@@ -318,7 +320,8 @@ static bool rz_cmd_pdd_init(RzCore *core) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool rz_cmd_pdd_fini(RzCore *core) {
|
||||
static bool rz_cmd_pdd_fini(RzCore *core, void *user) {
|
||||
(void)user;
|
||||
RzCmd *rcmd = core->rcmd;
|
||||
RzCmdDesc *cd = rz_cmd_get_desc(rcmd, "pdd");
|
||||
return rz_cmd_desc_remove(rcmd, cd);
|
||||
@@ -336,7 +339,7 @@ RzCorePlugin rz_core_plugin_jsdec = {
|
||||
#ifdef _MSC_VER
|
||||
#define _RZ_API __declspec(dllexport)
|
||||
#else
|
||||
#define _RZ_API
|
||||
#define _RZ_API __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
#ifndef CORELIB
|
||||
|
||||
@@ -51,10 +51,6 @@ static void print_jsval(JSValue val) {
|
||||
errorf("JS_IsNumber\n");
|
||||
} else if(JS_IsBigInt(NULL, val)) {
|
||||
errorf("JS_IsBigInt\n");
|
||||
} else if(JS_IsBigFloat(val)) {
|
||||
errorf("JS_IsBigFloat\n");
|
||||
} else if(JS_IsBigDecimal(val)) {
|
||||
errorf("JS_IsBigDecimal\n");
|
||||
} else if(JS_IsBool(val)) {
|
||||
errorf("JS_IsBool\n");
|
||||
} else if(JS_IsNull(val)) {
|
||||
@@ -104,8 +100,10 @@ static int js_load_module(JSContext *ctx, const uint8_t *bytes, const uint32_t s
|
||||
return 0;
|
||||
}
|
||||
|
||||
//print_jsval(obj);
|
||||
JSValue val = JS_EvalFunction(ctx, obj);
|
||||
if (JS_IsException(val)) {
|
||||
errorf("Error: jsdec thrown an exception when loading a module\n");
|
||||
jsdec_handle_exception(ctx);
|
||||
return 0;
|
||||
}
|
||||
@@ -194,17 +192,15 @@ jsdec_t *jsdec_new() {
|
||||
|
||||
// initialize all intrisic
|
||||
JS_AddIntrinsicBaseObjects(ctx);
|
||||
JS_AddIntrinsicDate(ctx);
|
||||
JS_AddIntrinsicEval(ctx);
|
||||
JS_AddIntrinsicRegExpCompiler(ctx);
|
||||
JS_AddIntrinsicRegExp(ctx);
|
||||
JS_AddIntrinsicJSON(ctx);
|
||||
JS_AddIntrinsicMapSet(ctx);
|
||||
JS_AddIntrinsicTypedArrays(ctx);
|
||||
JS_AddIntrinsicPromise(ctx);
|
||||
JS_AddIntrinsicBigInt(ctx);
|
||||
JS_AddIntrinsicBigFloat(ctx);
|
||||
JS_AddIntrinsicBigDecimal(ctx);
|
||||
JS_AddIntrinsicOperators(ctx);
|
||||
JS_AddIntrinsicEval(ctx);
|
||||
JS_EnableBignumExt(ctx, 1);
|
||||
JS_AddIntrinsicDate(ctx);
|
||||
|
||||
|
||||
// Setup global objects.
|
||||
JSValue global = JS_GetGlobalObject(ctx);
|
||||
@@ -223,6 +219,7 @@ jsdec_t *jsdec_new() {
|
||||
JS_FreeValue(ctx, global);
|
||||
|
||||
if (!js_load_all_modules(ctx)) {
|
||||
errorf("Error: failed to load modules\n");
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
return NULL;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
project(cutter-jsdec-plugin)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
set(CUTTER_INSTALL_PLUGDIR "share/rizin/cutter/plugins/native" CACHE STRING "Directory to install Cutter plugin into")
|
||||
set(JSDEC_BUILD_DIR "../build" CACHE STRING "Directory where to find libjsdec.a")
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_INSTALL_PREFIX}/lib/cmake/Cutter")
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
add_library(jsdec_cutter MODULE
|
||||
JSDecPlugin.h
|
||||
JSDecPlugin.cpp
|
||||
JSDecDecompiler.h
|
||||
JSDecDecompiler.cpp
|
||||
)
|
||||
|
||||
find_library(libjsdec NAMES jsdec PATHS "${JSDEC_BUILD_DIR}")
|
||||
include_directories("../include")
|
||||
|
||||
find_package(Cutter REQUIRED)
|
||||
|
||||
target_link_libraries(jsdec_cutter PRIVATE Cutter::Cutter "${libjsdec}")
|
||||
install(TARGETS jsdec_cutter DESTINATION "${CUTTER_INSTALL_PLUGDIR}")
|
||||
@@ -0,0 +1,40 @@
|
||||
// SPDX-FileCopyrightText: 2024 Giovanni Dante Grazioli <[email protected]>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#include "JSDecDecompiler.h"
|
||||
#include <Cutter.h>
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
|
||||
#include "jsdec-cutter.h"
|
||||
|
||||
JSDecDecompiler::JSDecDecompiler(CutterCore *core)
|
||||
: Decompiler("jsdec", "jsdec", core) {
|
||||
task = nullptr;
|
||||
RzCoreLocked c = core->core();
|
||||
jsdec_init_config(c);
|
||||
}
|
||||
|
||||
void JSDecDecompiler::decompileAt(RVA addr) {
|
||||
if (task) {
|
||||
return;
|
||||
}
|
||||
|
||||
task = new RizinFunctionTask([addr](RzCore *core) {
|
||||
return jsdec_as_annotation(core, addr);
|
||||
});
|
||||
|
||||
connect(task, &RizinFunctionTask::finished, this, [this]() {
|
||||
auto res = reinterpret_cast<RzAnnotatedCode *>(task->getResult());
|
||||
delete task;
|
||||
task = nullptr;
|
||||
if (!res) {
|
||||
res = Decompiler::makeWarning(tr("Failed to parse JSON from jsdec"));
|
||||
}
|
||||
emit finished(res);
|
||||
});
|
||||
|
||||
task->startTask();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// SPDX-FileCopyrightText: 2024 Giovanni Dante Grazioli <[email protected]>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#ifndef JSDEC_DECOMPILER_H
|
||||
#define JSDEC_DECOMPILER_H
|
||||
|
||||
#include "Decompiler.h"
|
||||
#include "RizinTask.h"
|
||||
|
||||
class JSDecDecompiler: public Decompiler
|
||||
{
|
||||
private:
|
||||
RizinFunctionTask *task;
|
||||
|
||||
public:
|
||||
JSDecDecompiler(CutterCore *core = nullptr);
|
||||
virtual void decompileAt(RVA addr) override;
|
||||
virtual bool isRunning() override { return task != nullptr; }
|
||||
};
|
||||
|
||||
#endif // JSDEC_DECOMPILER_H
|
||||
@@ -0,0 +1,18 @@
|
||||
// SPDX-FileCopyrightText: 2024 Giovanni Dante Grazioli <[email protected]>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#include "JSDecDecompiler.h"
|
||||
#include "JSDecPlugin.h"
|
||||
|
||||
void JSDecPlugin::setupPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
void JSDecPlugin::setupInterface(MainWindow *)
|
||||
{
|
||||
}
|
||||
|
||||
void JSDecPlugin::registerDecompilers()
|
||||
{
|
||||
Core()->registerDecompiler(new JSDecDecompiler(Core()));
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// SPDX-FileCopyrightText: 2024 Giovanni Dante Grazioli <[email protected]>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#ifndef JSDEC_CUTTER_PLUGIN_H
|
||||
#define JSDEC_CUTTER_PLUGIN_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QtPlugin>
|
||||
#include <plugins/CutterPlugin.h>
|
||||
|
||||
class JSDecPlugin : public QObject, CutterPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "re.rizin.cutter.plugins.jsdec")
|
||||
Q_INTERFACES(CutterPlugin)
|
||||
|
||||
public:
|
||||
void setupPlugin() override;
|
||||
void setupInterface(MainWindow *main) override;
|
||||
void registerDecompilers() override;
|
||||
|
||||
QString getName() const override { return "JsDec Decompiler (jsdec)"; }
|
||||
QString getAuthor() const override { return "deroad"; }
|
||||
QString getDescription() const override { return "GUI Integration of jsdec."; }
|
||||
QString getVersion() const override { return "1.0"; }
|
||||
};
|
||||
|
||||
|
||||
#endif // JSDEC_CUTTER_PLUGIN_H
|
||||
@@ -0,0 +1,20 @@
|
||||
// SPDX-FileCopyrightText: 2024 Giovanni Dante Grazioli <[email protected]>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#ifndef JSDEC_CUTTER_H
|
||||
#define JSDEC_CUTTER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rz_util/rz_annotated_code.h>
|
||||
|
||||
RZ_API void jsdec_init_config(RzCore *core);
|
||||
RZ_API RzAnnotatedCode *jsdec_as_annotation(RzCore *core, ut64 addr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JSDEC_CUTTER_H */
|
||||
@@ -917,6 +917,11 @@ var _arm = {
|
||||
cmp: _compare,
|
||||
cmn: _compare,
|
||||
fcmp: _compare,
|
||||
ccmp: function(instr, context) {
|
||||
context.cond.a = instr.parsed.opd[0];
|
||||
context.cond.b = instr.parsed.opd[1];
|
||||
return _conditional(instr, context, instr.parsed.opd[3].toUpperCase());
|
||||
},
|
||||
cbz: function(instr, context, instructions) {
|
||||
context.cond.a = instr.parsed.opd[0];
|
||||
context.cond.b = '0';
|
||||
@@ -1356,6 +1361,17 @@ var _arm = {
|
||||
}
|
||||
return Base.conditional_assign(opds[0], context.cond.a, context.cond.b, cond, '1', '0');
|
||||
},
|
||||
cneg: function(instr, context) {
|
||||
var opds = instr.parsed.opd;
|
||||
var cond = 'EQ';
|
||||
for (var i = 0; i < _conditional_list.length; i++) {
|
||||
if (_conditional_list[i].ext == opds[1]) {
|
||||
cond = _conditional_list[i].type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Base.conditional_assign(opds[0], context.cond.a, context.cond.b, cond, '-' + opds[1], opds[0]);
|
||||
},
|
||||
fcset: function(instr, context) {
|
||||
var opds = instr.parsed.opd;
|
||||
var cond = 'EQ';
|
||||
@@ -1537,6 +1553,9 @@ var _arm = {
|
||||
fcvt: function(instr) {
|
||||
return Base.cast(instr.parsed.opd[0], instr.parsed.opd[1], instr.parsed.opd[0][0] == 's' ? 'float' : 'double');
|
||||
},
|
||||
udf: function() {
|
||||
return Base.nop();
|
||||
},
|
||||
invalid: function() {
|
||||
return Base.nop();
|
||||
}
|
||||
@@ -1547,6 +1566,8 @@ var _arm = {
|
||||
asm = orig;
|
||||
} else if (asm.match(/aav\.[\da-fA-F]+/)) {
|
||||
asm = orig;
|
||||
} else if (asm.match(/data\.[\da-fA-F]+/)) {
|
||||
asm = orig;
|
||||
}
|
||||
var ret = asm.replace(/(\[|\])/g, ' $1 ').replace(/,/g, ' ');
|
||||
ret = ret.replace(/\{|\}/g, ' ').replace(/#/g, ' ');
|
||||
|
||||
+4
-2
@@ -79,7 +79,7 @@ export default (function() {
|
||||
var functions = rz_sanitize(rzpipe.string('aflj'), '[]');
|
||||
var classes = rz_sanitize(rzpipe.string('icj'), '[]');
|
||||
var data = JSONex.stringify(rizin.graph());
|
||||
var farguments = rz_sanitize(rzpipe.string('afvj', true), '{"sp":[],"bp":[],"reg":[]}');
|
||||
var farguments = rz_sanitize(rzpipe.string('afvlj', true), '{"stack":[],"reg":[]}');
|
||||
var arch = rz_sanitize(rzpipe.string('e asm.arch'), '');
|
||||
var archbits = rz_sanitize(rzpipe.string('e asm.bits'), '32');
|
||||
var database = rz_sanitize(rzpipe.custom('afsj @@i', null, merge_arrays), '[]');
|
||||
@@ -216,11 +216,13 @@ export default (function() {
|
||||
strings: (isfast ? [] : rzpipe.json('Cslj', [])),
|
||||
functions: (isfast ? [] : rzpipe.json('aflj', [])),
|
||||
classes: rzpipe.json('icj', []),
|
||||
arguments: rzpipe.json('afvj', {
|
||||
arguments: rzpipe.json('afvlj', {
|
||||
"stack": [],
|
||||
"reg": []
|
||||
})
|
||||
};
|
||||
this.xrefs.arguments.stack = this.xrefs.arguments.stack || [];
|
||||
this.xrefs.arguments.reg = this.xrefs.arguments.reg || [];
|
||||
this.graph = rizin.graph();
|
||||
this.argdb = rzpipe.custom('afsj @@i', null, merge_arrays_json);
|
||||
},
|
||||
|
||||
@@ -52,7 +52,7 @@ function _new_data(issue) {
|
||||
// to override this is required to be converted to just an integer.
|
||||
bits = parseInt(bits.toString());
|
||||
}
|
||||
return {
|
||||
var testdata = {
|
||||
arch: issue.arch,
|
||||
bits: bits,
|
||||
graph: issue.agj ? _fixup_old_graph(issue.agj) : (issue.graph || []),
|
||||
@@ -68,6 +68,9 @@ function _new_data(issue) {
|
||||
},
|
||||
argdb: issue.afcfj
|
||||
};
|
||||
testdata.xrefs.arguments.stack = testdata.xrefs.arguments.stack || [];
|
||||
testdata.xrefs.arguments.reg = testdata.xrefs.arguments.reg || [];
|
||||
return testdata;
|
||||
}
|
||||
|
||||
export default function(filename) {
|
||||
|
||||
+3
-3
@@ -4,13 +4,13 @@
|
||||
jsdec_plugin = 'jsdec-plugin.js'
|
||||
jsdec_testsuite = 'jsdec-testsuite.js'
|
||||
|
||||
if get_option('standalone')
|
||||
if get_option('build_type') == 'standalone'
|
||||
bytecode_h = custom_target(
|
||||
'bytecode.h',
|
||||
build_always_stale: true,
|
||||
output : 'bytecode.h',
|
||||
input : jsdec_testsuite,
|
||||
command : [qjsc, '-m', '-N', 'main_bytecode', '-c', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
command : [qjsc, '-m', '-N', 'main_bytecode', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
else
|
||||
bytecode_h = custom_target(
|
||||
@@ -18,7 +18,7 @@ else
|
||||
build_always_stale: true,
|
||||
output : 'bytecode.h',
|
||||
input : jsdec_plugin,
|
||||
command : [qjsc, '-m', '-N', 'main_bytecode', '-c', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
command : [qjsc, '-m', '-N', 'main_bytecode', '-o', '@OUTPUT@', '@INPUT@'],
|
||||
)
|
||||
endif
|
||||
|
||||
|
||||
+80
-15
@@ -1,23 +1,27 @@
|
||||
# SPDX-FileCopyrightText: 2023 Giovanni Dante Grazioli <[email protected]>
|
||||
# SPDX-FileCopyrightText: 2023-2024 Giovanni Dante Grazioli <[email protected]>
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
project('jsdec', 'c', meson_version: '>=0.55.0')
|
||||
project('jsdec', 'c', meson_version: '>=0.56.0',
|
||||
default_options: [
|
||||
'buildtype=release',
|
||||
'b_vscrt=from_buildtype',
|
||||
'warning_level=1',
|
||||
'c_std=c11'
|
||||
])
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
libquickjs_proj = subproject('libquickjs', default_options: ['default_library=static'])
|
||||
libquickjs_dep = libquickjs_proj.get_variable('quickjs_dep')
|
||||
qjsc = libquickjs_proj.get_variable('qjsc')
|
||||
|
||||
jsdec_incs = ['.', 'c']
|
||||
jsdec_incs = ['.', 'c', 'include']
|
||||
jsdec_c_args = []
|
||||
jsdec_src = [
|
||||
'c' / 'jsdec.c',
|
||||
'c' / 'base64.c',
|
||||
]
|
||||
jsdec_deps = [
|
||||
libquickjs_dep,
|
||||
]
|
||||
|
||||
libquickjs_proj = subproject('libquickjs', default_options: ['default_library=static'])
|
||||
libquickjs_dep = libquickjs_proj.get_variable('quickjs_dep')
|
||||
|
||||
jsdec_deps = [ libquickjs_dep ]
|
||||
|
||||
modjs_gen = executable('modjs_gen', 'tools' / 'modjs_gen.c',
|
||||
dependencies: [],
|
||||
@@ -26,10 +30,27 @@ modjs_gen = executable('modjs_gen', 'tools' / 'modjs_gen.c',
|
||||
install: false,
|
||||
)
|
||||
|
||||
qjsc = executable('qjsc', 'tools' / 'qjsc_mod.c',
|
||||
dependencies: libquickjs_dep,
|
||||
c_args: ['-D_GNU_SOURCE=1'],
|
||||
include_directories: [],
|
||||
implicit_include_directories: false,
|
||||
install: false,
|
||||
)
|
||||
|
||||
subdir('js')
|
||||
|
||||
if get_option('standalone')
|
||||
jsdec_link_args = []
|
||||
foreach flag: [
|
||||
'-Wl,--exclude-libs,ALL',
|
||||
]
|
||||
if cc.has_link_argument(flag)
|
||||
jsdec_link_args += flag
|
||||
endif
|
||||
endforeach
|
||||
|
||||
build_type = get_option('build_type')
|
||||
if build_type == 'standalone'
|
||||
jsdec_src += [
|
||||
bytecode_h,
|
||||
bytecode_mod_h,
|
||||
@@ -39,11 +60,47 @@ if get_option('standalone')
|
||||
jsdec_standalone = executable('jsdec-standalone', jsdec_src,
|
||||
c_args : jsdec_c_args,
|
||||
dependencies: jsdec_deps,
|
||||
link_args: jsdec_link_args,
|
||||
gnu_symbol_visibility: 'hidden',
|
||||
include_directories: include_directories(jsdec_incs),
|
||||
implicit_include_directories: false,
|
||||
install: false,
|
||||
)
|
||||
else
|
||||
elif build_type == 'cutter'
|
||||
jsdec_deps = [ libquickjs_dep.as_link_whole() ]
|
||||
jsdec_deps += dependency('rz_core')
|
||||
jsdec_deps += dependency('rz_util')
|
||||
jsdec_deps += dependency('rz_cons')
|
||||
jsdec_deps += dependency('rz_config')
|
||||
jsdec_deps += dependency('rz_io')
|
||||
|
||||
jsdec_src += [
|
||||
bytecode_h,
|
||||
bytecode_mod_h,
|
||||
'c' / 'jsdec-cutter.c'
|
||||
]
|
||||
|
||||
if cc.has_argument('-fvisibility=hidden')
|
||||
jsdec_c_args += '-fvisibility=hidden'
|
||||
endif
|
||||
if cc.has_argument('-flto')
|
||||
jsdec_c_args += '-flto'
|
||||
endif
|
||||
|
||||
libjsdec = static_library('jsdec', jsdec_src,
|
||||
c_args : jsdec_c_args,
|
||||
dependencies: jsdec_deps,
|
||||
include_directories: include_directories(jsdec_incs),
|
||||
link_args: jsdec_link_args,
|
||||
gnu_symbol_visibility: 'hidden',
|
||||
implicit_include_directories: false,
|
||||
install: false,
|
||||
)
|
||||
libjsdec_dep = declare_dependency(
|
||||
link_with: libjsdec,
|
||||
include_directories: include_directories(['include']),
|
||||
)
|
||||
elif build_type == 'rizin'
|
||||
# build plugin for Rizin
|
||||
rz_core_dep = dependency('rz_core')
|
||||
jsdec_deps += rz_core_dep
|
||||
@@ -54,9 +111,6 @@ else
|
||||
rizin_plugdir = get_option('rizin_plugdir')
|
||||
if rizin_plugdir == ''
|
||||
rizin_plugdir = rz_core_dep.get_variable(pkgconfig: 'plugindir', cmake: 'rz_core_PLUGINDIR')
|
||||
plugin_jsdec_dir = join_paths(get_option('prefix'), rizin_plugdir, 'jsdec')
|
||||
else
|
||||
plugin_jsdec_dir = join_paths(rizin_plugdir, 'jsdec')
|
||||
endif
|
||||
|
||||
jsdec_src += [
|
||||
@@ -65,12 +119,23 @@ else
|
||||
'c' / 'jsdec-plugin.c'
|
||||
]
|
||||
|
||||
if cc.has_argument('-fvisibility=hidden')
|
||||
jsdec_c_args += '-fvisibility=hidden'
|
||||
endif
|
||||
if cc.has_argument('-flto')
|
||||
jsdec_c_args += '-flto'
|
||||
endif
|
||||
|
||||
shared_library('core_pdd', jsdec_src,
|
||||
c_args : jsdec_c_args,
|
||||
dependencies: jsdec_deps,
|
||||
include_directories: include_directories(jsdec_incs),
|
||||
link_args: jsdec_link_args,
|
||||
gnu_symbol_visibility: 'hidden',
|
||||
implicit_include_directories: false,
|
||||
install: true,
|
||||
install_dir: rizin_plugdir
|
||||
)
|
||||
else
|
||||
error('Invalid `build_type`.')
|
||||
endif
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
option('rizin_plugdir', type: 'string', value: '', description: 'rizin install directory')
|
||||
option('standalone', type: 'boolean', value: false, description: 'enables/disables building only the standalone executable for testing purposes')
|
||||
option('build_type', type: 'combo', choices: ['rizin', 'cutter', 'standalone'], value: 'rizin', description: 'build type; `standalone` for tests, `rizin` as rizin native plugin and `cutter` as cutter native plugin')
|
||||
@@ -1,4 +1,6 @@
|
||||
[wrap-git]
|
||||
url = https://github.com/frida/quickjs.git
|
||||
revision = c81f05c9859cea5f83a80057416a0c7affe9b876
|
||||
patch_directory = libquickjs
|
||||
url = https://github.com/quickjs-ng/quickjs.git
|
||||
revision = v0.8.0
|
||||
directory = libquickjs
|
||||
patch_directory = libquickjs
|
||||
depth = 1
|
||||
@@ -1,104 +1,88 @@
|
||||
project('quickjs', 'c',
|
||||
version: '2021-03-27-frida',
|
||||
project('quickjs-ng', 'c',
|
||||
version: 'v0.8.0',
|
||||
default_options: [
|
||||
'buildtype=release',
|
||||
'b_vscrt=from_buildtype',
|
||||
'warning_level=1',
|
||||
'c_std=c11'
|
||||
]
|
||||
)
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
have_msvc = cc.get_id() == 'msvc'
|
||||
|
||||
threads_dep = dependency('threads')
|
||||
atomic_dep = cc.find_library('atomic', required: false)
|
||||
dl_dep = cc.find_library('dl', required: false)
|
||||
m_dep = cc.find_library('m', required: false)
|
||||
|
||||
headers = [
|
||||
'quickjs.h',
|
||||
]
|
||||
|
||||
sources = [
|
||||
'quickjs.c',
|
||||
'libregexp.c',
|
||||
'libunicode.c',
|
||||
'cutils.c',
|
||||
'libbf.c',
|
||||
'libregexp.c',
|
||||
'libunicode.c',
|
||||
'quickjs.c',
|
||||
]
|
||||
|
||||
cdata = configuration_data()
|
||||
cdata.set_quoted('CONFIG_VERSION', meson.project_version())
|
||||
compiler_flags = [
|
||||
'-fvisibility=hidden',
|
||||
'-fvisibility-inlines-hidden',
|
||||
'-Wno-implicit-fallthrough',
|
||||
'-Wno-sign-compare',
|
||||
'-Wno-missing-field-initializers',
|
||||
'-Wno-unused-parameter',
|
||||
'-Wno-unused-but-set-variable',
|
||||
'-Wno-array-bounds',
|
||||
'-Wno-format-truncation',
|
||||
'-Wno-format-zero-length',
|
||||
'-funsigned-char',
|
||||
]
|
||||
|
||||
if host_machine.endian() == 'big'
|
||||
cdata.set('WORDS_BIGENDIAN', 1)
|
||||
if cc.get_id() == 'msvc'
|
||||
compiler_flags += '-Wno-unsafe-buffer-usage'
|
||||
compiler_flags += '-Wno-sign-conversion'
|
||||
compiler_flags += '-Wno-nonportable-system-include-path'
|
||||
compiler_flags += '-Wno-implicit-int-conversion'
|
||||
compiler_flags += '-Wno-shorten-64-to-32'
|
||||
compiler_flags += '-Wno-reserved-macro-identifier'
|
||||
compiler_flags += '-Wno-reserved-identifier'
|
||||
compiler_flags += '-Wdeprecated-declarations'
|
||||
compiler_flags += '/experimental:c11atomics'
|
||||
compiler_flags += '/wd4018' # -Wno-sign-conversion
|
||||
compiler_flags += '/wd4061' # -Wno-implicit-fallthrough
|
||||
compiler_flags += '/wd4100' # -Wno-unused-parameter
|
||||
compiler_flags += '/wd4200' # -Wno-zero-length-array
|
||||
compiler_flags += '/wd4242' # -Wno-shorten-64-to-32
|
||||
compiler_flags += '/wd4244' # -Wno-shorten-64-to-32
|
||||
compiler_flags += '/wd4245' # -Wno-sign-compare
|
||||
compiler_flags += '/wd4267' # -Wno-shorten-64-to-32
|
||||
compiler_flags += '/wd4388' # -Wno-sign-compare
|
||||
compiler_flags += '/wd4389' # -Wno-sign-compare
|
||||
compiler_flags += '/wd4710' # Function not inlined
|
||||
compiler_flags += '/wd4711' # Function was inlined
|
||||
compiler_flags += '/wd4820' # Padding added after construct
|
||||
compiler_flags += '/wd4996' # -Wdeprecated-declarations
|
||||
compiler_flags += '/wd5045' # Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified
|
||||
endif
|
||||
|
||||
if cc.has_header('unistd.h')
|
||||
cdata.set('HAVE_UNISTD_H', 1)
|
||||
endif
|
||||
# required on linux, but ignored by windows
|
||||
quickjs_c_args = ['-D_GNU_SOURCE=1']
|
||||
|
||||
if cc.has_function('malloc_usable_size')
|
||||
cdata.set('HAVE_MALLOC_USABLE_SIZE', 1)
|
||||
endif
|
||||
|
||||
if get_option('libc')
|
||||
headers += 'quickjs-libc.h'
|
||||
sources += 'quickjs-libc.c'
|
||||
endif
|
||||
|
||||
cdata.set('CONFIG_BIGNUM', get_option('bignum'))
|
||||
|
||||
atomics = false
|
||||
opt = get_option('atomics')
|
||||
if not opt.disabled()
|
||||
if opt.auto()
|
||||
atomics = not have_msvc
|
||||
elif not have_msvc
|
||||
atomics = true
|
||||
else
|
||||
error('Atomics support was requested but is not available')
|
||||
foreach flag: compiler_flags
|
||||
if cc.has_argument(flag)
|
||||
quickjs_c_args += flag
|
||||
endif
|
||||
endif
|
||||
cdata.set('CONFIG_ATOMICS', atomics)
|
||||
|
||||
stack_check = false
|
||||
opt = get_option('stack_check')
|
||||
if not opt.disabled()
|
||||
if opt.auto()
|
||||
stack_check = not have_msvc
|
||||
elif not have_msvc
|
||||
stack_check = true
|
||||
else
|
||||
error('Stack limitation was requested but is not available')
|
||||
endif
|
||||
endif
|
||||
cdata.set('CONFIG_STACK_CHECK', stack_check)
|
||||
|
||||
configure_file(
|
||||
output: 'config.h',
|
||||
configuration: cdata,
|
||||
)
|
||||
|
||||
add_project_arguments(
|
||||
have_msvc ? '/FI' : '-include', meson.current_build_dir() / 'config.h',
|
||||
'-D_GNU_SOURCE=1',
|
||||
language: 'c',
|
||||
)
|
||||
endforeach
|
||||
|
||||
quickjs = static_library('quickjs', sources,
|
||||
dependencies: [threads_dep, dl_dep, m_dep],
|
||||
dependencies: [atomic_dep, threads_dep, dl_dep, m_dep],
|
||||
c_args: quickjs_c_args,
|
||||
pic: true,
|
||||
gnu_symbol_visibility: 'hidden',
|
||||
implicit_include_directories: false,
|
||||
install: false,
|
||||
install: false
|
||||
)
|
||||
|
||||
quickjs_dep = declare_dependency(
|
||||
link_with: quickjs,
|
||||
include_directories: include_directories('.'),
|
||||
)
|
||||
|
||||
qjsc_sources = [
|
||||
'qjsc.c',
|
||||
'quickjs-libc.c',
|
||||
]
|
||||
|
||||
qjsc = executable('qjsc', qjsc_sources,
|
||||
dependencies: quickjs_dep,
|
||||
include_directories: include_directories('.'),
|
||||
implicit_include_directories: false,
|
||||
install: false,
|
||||
)
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,917 +0,0 @@
|
||||
/*
|
||||
* Dirent interface for Microsoft Visual Studio
|
||||
* Version 1.21
|
||||
*
|
||||
* Copyright (C) 2006-2012 Toni Ronkko
|
||||
* This file is part of dirent. Dirent may be freely distributed
|
||||
* under the MIT license. For all details and documentation, see
|
||||
* https://github.com/tronkko/dirent
|
||||
*/
|
||||
#ifndef DIRENT_H
|
||||
#define DIRENT_H
|
||||
|
||||
/*
|
||||
* Define architecture flags so we don't need to include windows.h.
|
||||
* Avoiding windows.h makes it simpler to use windows sockets in conjunction
|
||||
* with dirent.h.
|
||||
*/
|
||||
#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86)
|
||||
# define _X86_
|
||||
#endif
|
||||
#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_AMD64)
|
||||
#define _AMD64_
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <wchar.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Indicates that d_type field is available in dirent structure */
|
||||
#define _DIRENT_HAVE_D_TYPE
|
||||
|
||||
/* Indicates that d_namlen field is available in dirent structure */
|
||||
#define _DIRENT_HAVE_D_NAMLEN
|
||||
|
||||
/* Entries missing from MSVC 6.0 */
|
||||
#if !defined(FILE_ATTRIBUTE_DEVICE)
|
||||
# define FILE_ATTRIBUTE_DEVICE 0x40
|
||||
#endif
|
||||
|
||||
/* File type and permission flags for stat(), general mask */
|
||||
#if !defined(S_IFMT)
|
||||
# define S_IFMT _S_IFMT
|
||||
#endif
|
||||
|
||||
/* Directory bit */
|
||||
#if !defined(S_IFDIR)
|
||||
# define S_IFDIR _S_IFDIR
|
||||
#endif
|
||||
|
||||
/* Character device bit */
|
||||
#if !defined(S_IFCHR)
|
||||
# define S_IFCHR _S_IFCHR
|
||||
#endif
|
||||
|
||||
/* Pipe bit */
|
||||
#if !defined(S_IFFIFO)
|
||||
# define S_IFFIFO _S_IFFIFO
|
||||
#endif
|
||||
|
||||
/* Regular file bit */
|
||||
#if !defined(S_IFREG)
|
||||
# define S_IFREG _S_IFREG
|
||||
#endif
|
||||
|
||||
/* Read permission */
|
||||
#if !defined(S_IREAD)
|
||||
# define S_IREAD _S_IREAD
|
||||
#endif
|
||||
|
||||
/* Write permission */
|
||||
#if !defined(S_IWRITE)
|
||||
# define S_IWRITE _S_IWRITE
|
||||
#endif
|
||||
|
||||
/* Execute permission */
|
||||
#if !defined(S_IEXEC)
|
||||
# define S_IEXEC _S_IEXEC
|
||||
#endif
|
||||
|
||||
/* Pipe */
|
||||
#if !defined(S_IFIFO)
|
||||
# define S_IFIFO _S_IFIFO
|
||||
#endif
|
||||
|
||||
/* Block device */
|
||||
#if !defined(S_IFBLK)
|
||||
# define S_IFBLK 0
|
||||
#endif
|
||||
|
||||
/* Link */
|
||||
#if !defined(S_IFLNK)
|
||||
# define S_IFLNK 0
|
||||
#endif
|
||||
|
||||
/* Socket */
|
||||
#if !defined(S_IFSOCK)
|
||||
# define S_IFSOCK 0
|
||||
#endif
|
||||
|
||||
/* Read user permission */
|
||||
#if !defined(S_IRUSR)
|
||||
# define S_IRUSR S_IREAD
|
||||
#endif
|
||||
|
||||
/* Write user permission */
|
||||
#if !defined(S_IWUSR)
|
||||
# define S_IWUSR S_IWRITE
|
||||
#endif
|
||||
|
||||
/* Execute user permission */
|
||||
#if !defined(S_IXUSR)
|
||||
# define S_IXUSR 0
|
||||
#endif
|
||||
|
||||
/* Read group permission */
|
||||
#if !defined(S_IRGRP)
|
||||
# define S_IRGRP 0
|
||||
#endif
|
||||
|
||||
/* Write group permission */
|
||||
#if !defined(S_IWGRP)
|
||||
# define S_IWGRP 0
|
||||
#endif
|
||||
|
||||
/* Execute group permission */
|
||||
#if !defined(S_IXGRP)
|
||||
# define S_IXGRP 0
|
||||
#endif
|
||||
|
||||
/* Read others permission */
|
||||
#if !defined(S_IROTH)
|
||||
# define S_IROTH 0
|
||||
#endif
|
||||
|
||||
/* Write others permission */
|
||||
#if !defined(S_IWOTH)
|
||||
# define S_IWOTH 0
|
||||
#endif
|
||||
|
||||
/* Execute others permission */
|
||||
#if !defined(S_IXOTH)
|
||||
# define S_IXOTH 0
|
||||
#endif
|
||||
|
||||
/* Maximum length of file name */
|
||||
#if !defined(PATH_MAX)
|
||||
# define PATH_MAX MAX_PATH
|
||||
#endif
|
||||
#if !defined(FILENAME_MAX)
|
||||
# define FILENAME_MAX MAX_PATH
|
||||
#endif
|
||||
#if !defined(NAME_MAX)
|
||||
# define NAME_MAX FILENAME_MAX
|
||||
#endif
|
||||
|
||||
/* File type flags for d_type */
|
||||
#define DT_UNKNOWN 0
|
||||
#define DT_REG S_IFREG
|
||||
#define DT_DIR S_IFDIR
|
||||
#define DT_FIFO S_IFIFO
|
||||
#define DT_SOCK S_IFSOCK
|
||||
#define DT_CHR S_IFCHR
|
||||
#define DT_BLK S_IFBLK
|
||||
#define DT_LNK S_IFLNK
|
||||
|
||||
/* Macros for converting between st_mode and d_type */
|
||||
#define IFTODT(mode) ((mode) & S_IFMT)
|
||||
#define DTTOIF(type) (type)
|
||||
|
||||
/*
|
||||
* File type macros. Note that block devices, sockets and links cannot be
|
||||
* distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
|
||||
* only defined for compatibility. These macros should always return false
|
||||
* on Windows.
|
||||
*/
|
||||
#if !defined(S_ISFIFO)
|
||||
# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
|
||||
#endif
|
||||
#if !defined(S_ISDIR)
|
||||
# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
#if !defined(S_ISREG)
|
||||
# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
#if !defined(S_ISLNK)
|
||||
# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
|
||||
#endif
|
||||
#if !defined(S_ISSOCK)
|
||||
# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
|
||||
#endif
|
||||
#if !defined(S_ISCHR)
|
||||
# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
|
||||
#endif
|
||||
#if !defined(S_ISBLK)
|
||||
# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
|
||||
#endif
|
||||
|
||||
/* Return the exact length of d_namlen without zero terminator */
|
||||
#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
|
||||
|
||||
/* Return number of bytes needed to store d_namlen */
|
||||
#define _D_ALLOC_NAMLEN(p) (PATH_MAX)
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Wide-character version */
|
||||
struct _wdirent {
|
||||
/* Always zero */
|
||||
long d_ino;
|
||||
|
||||
/* Structure size */
|
||||
unsigned short d_reclen;
|
||||
|
||||
/* Length of name without \0 */
|
||||
size_t d_namlen;
|
||||
|
||||
/* File type */
|
||||
int d_type;
|
||||
|
||||
/* File name */
|
||||
wchar_t d_name[PATH_MAX];
|
||||
};
|
||||
typedef struct _wdirent _wdirent;
|
||||
|
||||
struct _WDIR {
|
||||
/* Current directory entry */
|
||||
struct _wdirent ent;
|
||||
|
||||
/* Private file data */
|
||||
WIN32_FIND_DATAW data;
|
||||
|
||||
/* True if data is valid */
|
||||
int cached;
|
||||
|
||||
/* Win32 search handle */
|
||||
HANDLE handle;
|
||||
|
||||
/* Initial directory name */
|
||||
wchar_t *patt;
|
||||
};
|
||||
typedef struct _WDIR _WDIR;
|
||||
|
||||
static _WDIR *_wopendir (const wchar_t *dirname);
|
||||
static struct _wdirent *_wreaddir (_WDIR *dirp);
|
||||
static int _wclosedir (_WDIR *dirp);
|
||||
static void _wrewinddir (_WDIR* dirp);
|
||||
|
||||
|
||||
/* For compatibility with Symbian */
|
||||
#define wdirent _wdirent
|
||||
#define WDIR _WDIR
|
||||
#define wopendir _wopendir
|
||||
#define wreaddir _wreaddir
|
||||
#define wclosedir _wclosedir
|
||||
#define wrewinddir _wrewinddir
|
||||
|
||||
|
||||
/* Multi-byte character versions */
|
||||
struct dirent {
|
||||
/* Always zero */
|
||||
long d_ino;
|
||||
|
||||
/* Structure size */
|
||||
unsigned short d_reclen;
|
||||
|
||||
/* Length of name without \0 */
|
||||
size_t d_namlen;
|
||||
|
||||
/* File type */
|
||||
int d_type;
|
||||
|
||||
/* File name */
|
||||
char d_name[PATH_MAX];
|
||||
};
|
||||
typedef struct dirent dirent;
|
||||
|
||||
struct DIR {
|
||||
struct dirent ent;
|
||||
struct _WDIR *wdirp;
|
||||
};
|
||||
typedef struct DIR DIR;
|
||||
|
||||
static DIR *opendir (const char *dirname);
|
||||
static struct dirent *readdir (DIR *dirp);
|
||||
static int closedir (DIR *dirp);
|
||||
static void rewinddir (DIR* dirp);
|
||||
|
||||
|
||||
/* Internal utility functions */
|
||||
static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
|
||||
static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
|
||||
|
||||
static int dirent_mbstowcs_s(
|
||||
size_t *pReturnValue,
|
||||
wchar_t *wcstr,
|
||||
size_t sizeInWords,
|
||||
const char *mbstr,
|
||||
size_t count);
|
||||
|
||||
static int dirent_wcstombs_s(
|
||||
size_t *pReturnValue,
|
||||
char *mbstr,
|
||||
size_t sizeInBytes,
|
||||
const wchar_t *wcstr,
|
||||
size_t count);
|
||||
|
||||
static void dirent_set_errno (int error);
|
||||
|
||||
/*
|
||||
* Open directory stream DIRNAME for read and return a pointer to the
|
||||
* internal working area that is used to retrieve individual directory
|
||||
* entries.
|
||||
*/
|
||||
static _WDIR*
|
||||
_wopendir(
|
||||
const wchar_t *dirname)
|
||||
{
|
||||
_WDIR *dirp = NULL;
|
||||
int error;
|
||||
|
||||
/* Must have directory name */
|
||||
if (dirname == NULL || dirname[0] == '\0') {
|
||||
dirent_set_errno (ENOENT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate new _WDIR structure */
|
||||
dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
|
||||
if (dirp != NULL) {
|
||||
DWORD n;
|
||||
|
||||
/* Reset _WDIR structure */
|
||||
dirp->handle = INVALID_HANDLE_VALUE;
|
||||
dirp->patt = NULL;
|
||||
dirp->cached = 0;
|
||||
|
||||
/* Compute the length of full path plus zero terminator */
|
||||
n = GetFullPathNameW (dirname, 0, NULL, NULL);
|
||||
|
||||
/* Allocate room for absolute directory name and search pattern */
|
||||
dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
|
||||
if (dirp->patt) {
|
||||
|
||||
/*
|
||||
* Convert relative directory name to an absolute one. This
|
||||
* allows rewinddir() to function correctly even when current
|
||||
* working directory is changed between opendir() and rewinddir().
|
||||
*/
|
||||
n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
|
||||
if (n > 0) {
|
||||
wchar_t *p;
|
||||
|
||||
/* Append search pattern \* to the directory name */
|
||||
p = dirp->patt + n;
|
||||
if (dirp->patt < p) {
|
||||
switch (p[-1]) {
|
||||
case '\\':
|
||||
case '/':
|
||||
case ':':
|
||||
/* Directory ends in path separator, e.g. c:\temp\ */
|
||||
/*NOP*/;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Directory name doesn't end in path separator */
|
||||
*p++ = '\\';
|
||||
}
|
||||
}
|
||||
*p++ = '*';
|
||||
*p = '\0';
|
||||
|
||||
/* Open directory stream and retrieve the first entry */
|
||||
if (dirent_first (dirp)) {
|
||||
/* Directory stream opened successfully */
|
||||
error = 0;
|
||||
} else {
|
||||
/* Cannot retrieve first entry */
|
||||
error = 1;
|
||||
dirent_set_errno (ENOENT);
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Cannot retrieve full path name */
|
||||
dirent_set_errno (ENOENT);
|
||||
error = 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Cannot allocate memory for search pattern */
|
||||
error = 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Cannot allocate _WDIR structure */
|
||||
error = 1;
|
||||
}
|
||||
|
||||
/* Clean up in case of error */
|
||||
if (error && dirp) {
|
||||
_wclosedir (dirp);
|
||||
dirp = NULL;
|
||||
}
|
||||
|
||||
return dirp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read next directory entry. The directory entry is returned in dirent
|
||||
* structure in the d_name field. Individual directory entries returned by
|
||||
* this function include regular files, sub-directories, pseudo-directories
|
||||
* "." and ".." as well as volume labels, hidden files and system files.
|
||||
*/
|
||||
static struct _wdirent*
|
||||
_wreaddir(
|
||||
_WDIR *dirp)
|
||||
{
|
||||
WIN32_FIND_DATAW *datap;
|
||||
struct _wdirent *entp;
|
||||
|
||||
/* Read next directory entry */
|
||||
datap = dirent_next (dirp);
|
||||
if (datap) {
|
||||
size_t n;
|
||||
DWORD attr;
|
||||
|
||||
/* Pointer to directory entry to return */
|
||||
entp = &dirp->ent;
|
||||
|
||||
/*
|
||||
* Copy file name as wide-character string. If the file name is too
|
||||
* long to fit in to the destination buffer, then truncate file name
|
||||
* to PATH_MAX characters and zero-terminate the buffer.
|
||||
*/
|
||||
n = 0;
|
||||
while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) {
|
||||
entp->d_name[n] = datap->cFileName[n];
|
||||
n++;
|
||||
}
|
||||
dirp->ent.d_name[n] = 0;
|
||||
|
||||
/* Length of file name excluding zero terminator */
|
||||
entp->d_namlen = n;
|
||||
|
||||
/* File type */
|
||||
attr = datap->dwFileAttributes;
|
||||
if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
|
||||
entp->d_type = DT_CHR;
|
||||
} else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
|
||||
entp->d_type = DT_DIR;
|
||||
} else {
|
||||
entp->d_type = DT_REG;
|
||||
}
|
||||
|
||||
/* Reset dummy fields */
|
||||
entp->d_ino = 0;
|
||||
entp->d_reclen = sizeof (struct _wdirent);
|
||||
|
||||
} else {
|
||||
|
||||
/* Last directory entry read */
|
||||
entp = NULL;
|
||||
|
||||
}
|
||||
|
||||
return entp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Close directory stream opened by opendir() function. This invalidates the
|
||||
* DIR structure as well as any directory entry read previously by
|
||||
* _wreaddir().
|
||||
*/
|
||||
static int
|
||||
_wclosedir(
|
||||
_WDIR *dirp)
|
||||
{
|
||||
int ok;
|
||||
if (dirp) {
|
||||
|
||||
/* Release search handle */
|
||||
if (dirp->handle != INVALID_HANDLE_VALUE) {
|
||||
FindClose (dirp->handle);
|
||||
dirp->handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
/* Release search pattern */
|
||||
if (dirp->patt) {
|
||||
free (dirp->patt);
|
||||
dirp->patt = NULL;
|
||||
}
|
||||
|
||||
/* Release directory structure */
|
||||
free (dirp);
|
||||
ok = /*success*/0;
|
||||
|
||||
} else {
|
||||
/* Invalid directory stream */
|
||||
dirent_set_errno (EBADF);
|
||||
ok = /*failure*/-1;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rewind directory stream such that _wreaddir() returns the very first
|
||||
* file name again.
|
||||
*/
|
||||
static void
|
||||
_wrewinddir(
|
||||
_WDIR* dirp)
|
||||
{
|
||||
if (dirp) {
|
||||
/* Release existing search handle */
|
||||
if (dirp->handle != INVALID_HANDLE_VALUE) {
|
||||
FindClose (dirp->handle);
|
||||
}
|
||||
|
||||
/* Open new search handle */
|
||||
dirent_first (dirp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get first directory entry (internal) */
|
||||
static WIN32_FIND_DATAW*
|
||||
dirent_first(
|
||||
_WDIR *dirp)
|
||||
{
|
||||
WIN32_FIND_DATAW *datap;
|
||||
|
||||
/* Open directory and retrieve the first entry */
|
||||
dirp->handle = FindFirstFileW (dirp->patt, &dirp->data);
|
||||
if (dirp->handle != INVALID_HANDLE_VALUE) {
|
||||
|
||||
/* a directory entry is now waiting in memory */
|
||||
datap = &dirp->data;
|
||||
dirp->cached = 1;
|
||||
|
||||
} else {
|
||||
|
||||
/* Failed to re-open directory: no directory entry in memory */
|
||||
dirp->cached = 0;
|
||||
datap = NULL;
|
||||
|
||||
}
|
||||
return datap;
|
||||
}
|
||||
|
||||
/* Get next directory entry (internal) */
|
||||
static WIN32_FIND_DATAW*
|
||||
dirent_next(
|
||||
_WDIR *dirp)
|
||||
{
|
||||
WIN32_FIND_DATAW *p;
|
||||
|
||||
/* Get next directory entry */
|
||||
if (dirp->cached != 0) {
|
||||
|
||||
/* A valid directory entry already in memory */
|
||||
p = &dirp->data;
|
||||
dirp->cached = 0;
|
||||
|
||||
} else if (dirp->handle != INVALID_HANDLE_VALUE) {
|
||||
|
||||
/* Get the next directory entry from stream */
|
||||
if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
|
||||
/* Got a file */
|
||||
p = &dirp->data;
|
||||
} else {
|
||||
/* The very last entry has been processed or an error occured */
|
||||
FindClose (dirp->handle);
|
||||
dirp->handle = INVALID_HANDLE_VALUE;
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* End of directory stream reached */
|
||||
p = NULL;
|
||||
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open directory stream using plain old C-string.
|
||||
*/
|
||||
static DIR*
|
||||
opendir(
|
||||
const char *dirname)
|
||||
{
|
||||
struct DIR *dirp;
|
||||
int error;
|
||||
|
||||
/* Must have directory name */
|
||||
if (dirname == NULL || dirname[0] == '\0') {
|
||||
dirent_set_errno (ENOENT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate memory for DIR structure */
|
||||
dirp = (DIR*) malloc (sizeof (struct DIR));
|
||||
if (dirp) {
|
||||
wchar_t wname[PATH_MAX];
|
||||
size_t n;
|
||||
|
||||
/* Convert directory name to wide-character string */
|
||||
error = dirent_mbstowcs_s (&n, wname, PATH_MAX, dirname, PATH_MAX);
|
||||
if (!error) {
|
||||
|
||||
/* Open directory stream using wide-character name */
|
||||
dirp->wdirp = _wopendir (wname);
|
||||
if (dirp->wdirp) {
|
||||
/* Directory stream opened */
|
||||
error = 0;
|
||||
} else {
|
||||
/* Failed to open directory stream */
|
||||
error = 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
/*
|
||||
* Cannot convert file name to wide-character string. This
|
||||
* occurs if the string contains invalid multi-byte sequences or
|
||||
* the output buffer is too small to contain the resulting
|
||||
* string.
|
||||
*/
|
||||
error = 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Cannot allocate DIR structure */
|
||||
error = 1;
|
||||
}
|
||||
|
||||
/* Clean up in case of error */
|
||||
if (error && dirp) {
|
||||
free (dirp);
|
||||
dirp = NULL;
|
||||
}
|
||||
|
||||
return dirp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read next directory entry.
|
||||
*
|
||||
* When working with text consoles, please note that file names returned by
|
||||
* readdir() are represented in the default ANSI code page while any output to
|
||||
* console is typically formatted on another code page. Thus, non-ASCII
|
||||
* characters in file names will not usually display correctly on console. The
|
||||
* problem can be fixed in two ways: (1) change the character set of console
|
||||
* to 1252 using chcp utility and use Lucida Console font, or (2) use
|
||||
* _cprintf function when writing to console. The _cprinf() will re-encode
|
||||
* ANSI strings to the console code page so many non-ASCII characters will
|
||||
* display correcly.
|
||||
*/
|
||||
static struct dirent*
|
||||
readdir(
|
||||
DIR *dirp)
|
||||
{
|
||||
WIN32_FIND_DATAW *datap;
|
||||
struct dirent *entp;
|
||||
|
||||
/* Read next directory entry */
|
||||
datap = dirent_next (dirp->wdirp);
|
||||
if (datap) {
|
||||
size_t n;
|
||||
int error;
|
||||
|
||||
/* Attempt to convert file name to multi-byte string */
|
||||
error = dirent_wcstombs_s(
|
||||
&n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX);
|
||||
|
||||
/*
|
||||
* If the file name cannot be represented by a multi-byte string,
|
||||
* then attempt to use old 8+3 file name. This allows traditional
|
||||
* Unix-code to access some file names despite of unicode
|
||||
* characters, although file names may seem unfamiliar to the user.
|
||||
*
|
||||
* Be ware that the code below cannot come up with a short file
|
||||
* name unless the file system provides one. At least
|
||||
* VirtualBox shared folders fail to do this.
|
||||
*/
|
||||
if (error && datap->cAlternateFileName[0] != '\0') {
|
||||
error = dirent_wcstombs_s(
|
||||
&n, dirp->ent.d_name, PATH_MAX,
|
||||
datap->cAlternateFileName, PATH_MAX);
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
DWORD attr;
|
||||
|
||||
/* Initialize directory entry for return */
|
||||
entp = &dirp->ent;
|
||||
|
||||
/* Length of file name excluding zero terminator */
|
||||
entp->d_namlen = n - 1;
|
||||
|
||||
/* File attributes */
|
||||
attr = datap->dwFileAttributes;
|
||||
if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
|
||||
entp->d_type = DT_CHR;
|
||||
} else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
|
||||
entp->d_type = DT_DIR;
|
||||
} else {
|
||||
entp->d_type = DT_REG;
|
||||
}
|
||||
|
||||
/* Reset dummy fields */
|
||||
entp->d_ino = 0;
|
||||
entp->d_reclen = sizeof (struct dirent);
|
||||
|
||||
} else {
|
||||
/*
|
||||
* Cannot convert file name to multi-byte string so construct
|
||||
* an errornous directory entry and return that. Note that
|
||||
* we cannot return NULL as that would stop the processing
|
||||
* of directory entries completely.
|
||||
*/
|
||||
entp = &dirp->ent;
|
||||
entp->d_name[0] = '?';
|
||||
entp->d_name[1] = '\0';
|
||||
entp->d_namlen = 1;
|
||||
entp->d_type = DT_UNKNOWN;
|
||||
entp->d_ino = 0;
|
||||
entp->d_reclen = 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* No more directory entries */
|
||||
entp = NULL;
|
||||
}
|
||||
|
||||
return entp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Close directory stream.
|
||||
*/
|
||||
static int
|
||||
closedir(
|
||||
DIR *dirp)
|
||||
{
|
||||
int ok;
|
||||
if (dirp) {
|
||||
|
||||
/* Close wide-character directory stream */
|
||||
ok = _wclosedir (dirp->wdirp);
|
||||
dirp->wdirp = NULL;
|
||||
|
||||
/* Release multi-byte character version */
|
||||
free (dirp);
|
||||
|
||||
} else {
|
||||
|
||||
/* Invalid directory stream */
|
||||
dirent_set_errno (EBADF);
|
||||
ok = /*failure*/-1;
|
||||
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rewind directory stream to beginning.
|
||||
*/
|
||||
static void
|
||||
rewinddir(
|
||||
DIR* dirp)
|
||||
{
|
||||
/* Rewind wide-character string directory stream */
|
||||
_wrewinddir (dirp->wdirp);
|
||||
}
|
||||
|
||||
/* Convert multi-byte string to wide character string */
|
||||
static int
|
||||
dirent_mbstowcs_s(
|
||||
size_t *pReturnValue,
|
||||
wchar_t *wcstr,
|
||||
size_t sizeInWords,
|
||||
const char *mbstr,
|
||||
size_t count)
|
||||
{
|
||||
int error;
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
|
||||
/* Microsoft Visual Studio 2005 or later */
|
||||
error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
|
||||
|
||||
#else
|
||||
|
||||
/* Older Visual Studio or non-Microsoft compiler */
|
||||
size_t n;
|
||||
|
||||
/* Convert to wide-character string (or count characters) */
|
||||
n = mbstowcs (wcstr, mbstr, sizeInWords);
|
||||
if (!wcstr || n < count) {
|
||||
|
||||
/* Zero-terminate output buffer */
|
||||
if (wcstr && sizeInWords) {
|
||||
if (n >= sizeInWords) {
|
||||
n = sizeInWords - 1;
|
||||
}
|
||||
wcstr[n] = 0;
|
||||
}
|
||||
|
||||
/* Length of resuting multi-byte string WITH zero terminator */
|
||||
if (pReturnValue) {
|
||||
*pReturnValue = n + 1;
|
||||
}
|
||||
|
||||
/* Success */
|
||||
error = 0;
|
||||
|
||||
} else {
|
||||
|
||||
/* Could not convert string */
|
||||
error = 1;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Convert wide-character string to multi-byte string */
|
||||
static int
|
||||
dirent_wcstombs_s(
|
||||
size_t *pReturnValue,
|
||||
char *mbstr,
|
||||
size_t sizeInBytes, /* max size of mbstr */
|
||||
const wchar_t *wcstr,
|
||||
size_t count)
|
||||
{
|
||||
int error;
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
|
||||
/* Microsoft Visual Studio 2005 or later */
|
||||
error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
|
||||
|
||||
#else
|
||||
|
||||
/* Older Visual Studio or non-Microsoft compiler */
|
||||
size_t n;
|
||||
|
||||
/* Convert to multi-byte string (or count the number of bytes needed) */
|
||||
n = wcstombs (mbstr, wcstr, sizeInBytes);
|
||||
if (!mbstr || n < count) {
|
||||
|
||||
/* Zero-terminate output buffer */
|
||||
if (mbstr && sizeInBytes) {
|
||||
if (n >= sizeInBytes) {
|
||||
n = sizeInBytes - 1;
|
||||
}
|
||||
mbstr[n] = '\0';
|
||||
}
|
||||
|
||||
/* Lenght of resulting multi-bytes string WITH zero-terminator */
|
||||
if (pReturnValue) {
|
||||
*pReturnValue = n + 1;
|
||||
}
|
||||
|
||||
/* Success */
|
||||
error = 0;
|
||||
|
||||
} else {
|
||||
|
||||
/* Cannot convert string */
|
||||
error = 1;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Set errno variable */
|
||||
static void
|
||||
dirent_set_errno(
|
||||
int error)
|
||||
{
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
|
||||
/* Microsoft Visual Studio 2005 and later */
|
||||
_set_errno (error);
|
||||
|
||||
#else
|
||||
|
||||
/* Non-Microsoft compiler or older Microsoft compiler */
|
||||
errno = error;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /*DIRENT_H*/
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
#ifndef WINGETOPT_H
|
||||
#define WINGETOPT_H
|
||||
|
||||
/*
|
||||
* Copyright (c) 1987, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int opterr = 1, /* if error message should be printed */
|
||||
optind = 1, /* index into parent argv vector */
|
||||
optopt, /* character checked for validity */
|
||||
optreset; /* reset getopt */
|
||||
char *optarg; /* argument associated with option */
|
||||
|
||||
#define BADCH (int)'?'
|
||||
#define BADARG (int)':'
|
||||
#define EMSG ""
|
||||
|
||||
/*
|
||||
* getopt --
|
||||
* Parse argc/argv argument vector.
|
||||
*/
|
||||
static int getopt(int nargc, char * const nargv[], const char *ostr)
|
||||
{
|
||||
static char *place = EMSG; /* option letter processing */
|
||||
const char *oli; /* option letter list index */
|
||||
|
||||
if (optreset || !*place) { /* update scanning pointer */
|
||||
optreset = 0;
|
||||
if (optind >= nargc || *(place = nargv[optind]) != '-') {
|
||||
place = EMSG;
|
||||
return (-1);
|
||||
}
|
||||
if (place[1] && *++place == '-') { /* found "--" */
|
||||
++optind;
|
||||
place = EMSG;
|
||||
return (-1);
|
||||
}
|
||||
} /* option letter okay? */
|
||||
if ((optopt = (int)*place++) == (int)':' ||
|
||||
!(oli = strchr(ostr, optopt))) {
|
||||
/*
|
||||
* if the user didn't specify '-' as an option,
|
||||
* assume it means -1.
|
||||
*/
|
||||
if (optopt == (int)'-')
|
||||
return (-1);
|
||||
if (!*place)
|
||||
++optind;
|
||||
if (opterr && *ostr != ':')
|
||||
(void)printf("illegal option -- %c\n", optopt);
|
||||
return (BADCH);
|
||||
}
|
||||
if (*++oli != ':') { /* don't need argument */
|
||||
optarg = NULL;
|
||||
if (!*place)
|
||||
++optind;
|
||||
}
|
||||
else { /* need an argument */
|
||||
if (*place) /* no white space */
|
||||
optarg = place;
|
||||
else if (nargc <= ++optind) { /* no arg */
|
||||
place = EMSG;
|
||||
if (*ostr == ':')
|
||||
return (BADARG);
|
||||
if (opterr)
|
||||
(void)printf("option requires an argument -- %c\n", optopt);
|
||||
return (BADCH);
|
||||
}
|
||||
else /* white space */
|
||||
optarg = nargv[optind];
|
||||
place = EMSG;
|
||||
++optind;
|
||||
}
|
||||
return (optopt); /* dump back option letter */
|
||||
}
|
||||
|
||||
#endif /* WINGETOPT_H */
|
||||
@@ -1,7 +1,15 @@
|
||||
// SPDX-FileCopyrightText: 2024-2025 Giovanni Dante Grazioli <[email protected]>
|
||||
// SPDX-FileCopyrightText: 2018-2021 Fabrice Bellard
|
||||
// SPDX-FileCopyrightText: 2023 Ben Noordhuis
|
||||
// SPDX-FileCopyrightText: 2023 Saúl Ibarra Corretgé
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/*
|
||||
* QuickJS command line compiler
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2018-2021 Fabrice Bellard
|
||||
* Copyright (c) 2023 Ben Noordhuis
|
||||
* Copyright (c) 2023 Saúl Ibarra Corretgé
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -27,16 +35,24 @@
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#if !defined(_WIN32)
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include "getopt_compat.h"
|
||||
#else
|
||||
#include "wingetopt.h"
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "cutils.h"
|
||||
#include "quickjs-libc.h"
|
||||
#include <quickjs.h>
|
||||
#include <cutils.h>
|
||||
|
||||
typedef enum {
|
||||
OUTPUT_C,
|
||||
OUTPUT_C_MAIN,
|
||||
OUTPUT_RAW,
|
||||
} OutputTypeEnum;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
@@ -50,38 +66,13 @@ typedef struct namelist_t {
|
||||
int size;
|
||||
} namelist_t;
|
||||
|
||||
typedef struct {
|
||||
const char *option_name;
|
||||
const char *init_name;
|
||||
} FeatureEntry;
|
||||
|
||||
static namelist_t cname_list;
|
||||
static namelist_t cmodule_list;
|
||||
static namelist_t init_module_list;
|
||||
static uint64_t feature_bitmap;
|
||||
static OutputTypeEnum output_type;
|
||||
static FILE *outfile;
|
||||
static BOOL byte_swap;
|
||||
static BOOL dynamic_export;
|
||||
static const char *c_ident_prefix = "qjsc_";
|
||||
|
||||
#define FE_ALL (-1)
|
||||
|
||||
static const FeatureEntry feature_list[] = {
|
||||
{ "date", "Date" },
|
||||
{ "eval", "Eval" },
|
||||
{ "string-normalize", "StringNormalize" },
|
||||
{ "regexp", "RegExp" },
|
||||
{ "json", "JSON" },
|
||||
{ "proxy", "Proxy" },
|
||||
{ "map", "MapSet" },
|
||||
{ "typedarray", "TypedArrays" },
|
||||
{ "promise", "Promise" },
|
||||
#define FE_MODULE_LOADER 9
|
||||
{ "module-loader", NULL },
|
||||
#ifdef CONFIG_BIGNUM
|
||||
{ "bigint", "BigInt" },
|
||||
#endif
|
||||
};
|
||||
static int strip;
|
||||
|
||||
void namelist_add(namelist_t *lp, const char *name, const char *short_name,
|
||||
int flags)
|
||||
@@ -133,7 +124,7 @@ static void get_c_name(char *buf, size_t buf_size, const char *file)
|
||||
size_t len, i;
|
||||
int c;
|
||||
char *q;
|
||||
|
||||
|
||||
p = strrchr(file, '/');
|
||||
if (!p)
|
||||
p = file;
|
||||
@@ -144,7 +135,7 @@ static void get_c_name(char *buf, size_t buf_size, const char *file)
|
||||
len = strlen(p);
|
||||
else
|
||||
len = r - p;
|
||||
pstrcpy(buf, buf_size, c_ident_prefix);
|
||||
js__pstrcpy(buf, buf_size, c_ident_prefix);
|
||||
q = buf + strlen(buf);
|
||||
for(i = 0; i < len; i++) {
|
||||
c = p[i];
|
||||
@@ -174,30 +165,76 @@ static void dump_hex(FILE *f, const uint8_t *buf, size_t len)
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
static void qjsc_dump_obj(JSContext *ctx, FILE *f, JSValue val)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
str = JS_ToCString(ctx, val);
|
||||
if (str) {
|
||||
fprintf(f, "%s\n", str);
|
||||
JS_FreeCString(ctx, str);
|
||||
} else {
|
||||
fprintf(f, "[exception]\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void qjsc_dump_error1(JSContext *ctx, JSValue exception_val)
|
||||
{
|
||||
JSValue val;
|
||||
BOOL is_error;
|
||||
|
||||
is_error = JS_IsError(ctx, exception_val);
|
||||
qjsc_dump_obj(ctx, stderr, exception_val);
|
||||
if (is_error) {
|
||||
val = JS_GetPropertyStr(ctx, exception_val, "stack");
|
||||
if (!JS_IsUndefined(val)) {
|
||||
qjsc_dump_obj(ctx, stderr, val);
|
||||
}
|
||||
JS_FreeValue(ctx, val);
|
||||
}
|
||||
}
|
||||
|
||||
static void qjsc_dump_error(JSContext *ctx)
|
||||
{
|
||||
JSValue exception_val;
|
||||
|
||||
exception_val = JS_GetException(ctx);
|
||||
qjsc_dump_error1(ctx, exception_val);
|
||||
JS_FreeValue(ctx, exception_val);
|
||||
}
|
||||
|
||||
static void output_object_code(JSContext *ctx,
|
||||
FILE *fo, JSValueConst obj, const char *c_name,
|
||||
FILE *fo, JSValue obj, const char *c_name,
|
||||
BOOL load_only)
|
||||
{
|
||||
uint8_t *out_buf;
|
||||
size_t out_buf_len;
|
||||
int flags;
|
||||
flags = JS_WRITE_OBJ_BYTECODE;
|
||||
if (byte_swap)
|
||||
flags |= JS_WRITE_OBJ_BSWAP;
|
||||
int flags = JS_WRITE_OBJ_BYTECODE;
|
||||
|
||||
if (strip) {
|
||||
flags |= JS_WRITE_OBJ_STRIP_SOURCE;
|
||||
if (strip > 1)
|
||||
flags |= JS_WRITE_OBJ_STRIP_DEBUG;
|
||||
}
|
||||
|
||||
out_buf = JS_WriteObject(ctx, &out_buf_len, obj, flags);
|
||||
if (!out_buf) {
|
||||
js_std_dump_error(ctx);
|
||||
qjsc_dump_error(ctx);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
namelist_add(&cname_list, c_name, NULL, load_only);
|
||||
|
||||
fprintf(fo, "const uint32_t %s_size = %u;\n\n",
|
||||
c_name, (unsigned int)out_buf_len);
|
||||
fprintf(fo, "const uint8_t %s[%u] = {\n",
|
||||
c_name, (unsigned int)out_buf_len);
|
||||
dump_hex(fo, out_buf, out_buf_len);
|
||||
fprintf(fo, "};\n\n");
|
||||
|
||||
if (output_type == OUTPUT_RAW) {
|
||||
fwrite(out_buf, 1, out_buf_len, fo);
|
||||
} else {
|
||||
fprintf(fo, "const uint32_t %s_size = %u;\n\n",
|
||||
c_name, (unsigned int)out_buf_len);
|
||||
fprintf(fo, "const uint8_t %s[%u] = {\n",
|
||||
c_name, (unsigned int)out_buf_len);
|
||||
dump_hex(fo, out_buf, out_buf_len);
|
||||
fprintf(fo, "};\n\n");
|
||||
}
|
||||
|
||||
js_free(ctx, out_buf);
|
||||
}
|
||||
@@ -206,6 +243,7 @@ static int js_module_dummy_init(JSContext *ctx, JSModuleDef *m)
|
||||
{
|
||||
/* should never be called when compiling JS code */
|
||||
abort();
|
||||
return -1; // pacify compiler
|
||||
}
|
||||
|
||||
static void find_unique_cname(char *cname, size_t cname_size)
|
||||
@@ -227,7 +265,52 @@ static void find_unique_cname(char *cname, size_t cname_size)
|
||||
break;
|
||||
suffix_num++;
|
||||
}
|
||||
pstrcpy(cname, cname_size, cname1);
|
||||
js__pstrcpy(cname, cname_size, cname1);
|
||||
}
|
||||
|
||||
static uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
uint8_t *buf;
|
||||
size_t buf_len;
|
||||
long lret;
|
||||
|
||||
f = fopen(filename, "rb");
|
||||
if (!f)
|
||||
return NULL;
|
||||
if (fseek(f, 0, SEEK_END) < 0)
|
||||
goto fail;
|
||||
lret = ftell(f);
|
||||
if (lret < 0)
|
||||
goto fail;
|
||||
/* XXX: on Linux, ftell() return LONG_MAX for directories */
|
||||
if (lret == LONG_MAX) {
|
||||
errno = EISDIR;
|
||||
goto fail;
|
||||
}
|
||||
buf_len = lret;
|
||||
if (fseek(f, 0, SEEK_SET) < 0)
|
||||
goto fail;
|
||||
if (ctx)
|
||||
buf = js_malloc(ctx, buf_len + 1);
|
||||
else
|
||||
buf = malloc(buf_len + 1);
|
||||
if (!buf)
|
||||
goto fail;
|
||||
if (fread(buf, 1, buf_len, f) != buf_len) {
|
||||
errno = EIO;
|
||||
if (ctx)
|
||||
js_free(ctx, buf);
|
||||
else
|
||||
free(buf);
|
||||
fail:
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
buf[buf_len] = '\0';
|
||||
fclose(f);
|
||||
*pbuf_len = buf_len;
|
||||
return buf;
|
||||
}
|
||||
|
||||
JSModuleDef *jsc_module_loader(JSContext *ctx,
|
||||
@@ -243,26 +326,23 @@ JSModuleDef *jsc_module_loader(JSContext *ctx,
|
||||
namelist_add(&init_module_list, e->name, e->short_name, 0);
|
||||
/* create a dummy module */
|
||||
m = JS_NewCModule(ctx, module_name, js_module_dummy_init);
|
||||
} else if (has_suffix(module_name, ".so")) {
|
||||
fprintf(stderr, "Warning: binary module '%s' will be dynamically loaded\n", module_name);
|
||||
/* create a dummy module */
|
||||
m = JS_NewCModule(ctx, module_name, js_module_dummy_init);
|
||||
/* the resulting executable will export its symbols for the
|
||||
dynamic library */
|
||||
dynamic_export = TRUE;
|
||||
} else if (js__has_suffix(module_name, ".so")) {
|
||||
JS_ThrowReferenceError(ctx, "%s: dynamically linking to shared libraries not supported",
|
||||
module_name);
|
||||
return NULL;
|
||||
} else {
|
||||
size_t buf_len;
|
||||
uint8_t *buf;
|
||||
JSValue func_val;
|
||||
char cname[1024];
|
||||
|
||||
|
||||
buf = js_load_file(ctx, &buf_len, module_name);
|
||||
if (!buf) {
|
||||
JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
|
||||
module_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* compile the module */
|
||||
func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
|
||||
JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
|
||||
@@ -274,7 +354,7 @@ JSModuleDef *jsc_module_loader(JSContext *ctx,
|
||||
find_unique_cname(cname, sizeof(cname));
|
||||
}
|
||||
output_object_code(ctx, outfile, func_val, cname, TRUE);
|
||||
|
||||
|
||||
/* the module is already referenced, so we must free it */
|
||||
m = JS_VALUE_GET_PTR(func_val);
|
||||
JS_FreeValue(ctx, func_val);
|
||||
@@ -284,6 +364,7 @@ JSModuleDef *jsc_module_loader(JSContext *ctx,
|
||||
|
||||
static void compile_file(JSContext *ctx, FILE *fo,
|
||||
const char *filename,
|
||||
const char *script_name,
|
||||
const char *c_name1,
|
||||
int module)
|
||||
{
|
||||
@@ -292,7 +373,7 @@ static void compile_file(JSContext *ctx, FILE *fo,
|
||||
int eval_flags;
|
||||
JSValue obj;
|
||||
size_t buf_len;
|
||||
|
||||
|
||||
buf = js_load_file(ctx, &buf_len, filename);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Could not load '%s'\n", filename);
|
||||
@@ -300,21 +381,21 @@ static void compile_file(JSContext *ctx, FILE *fo,
|
||||
}
|
||||
eval_flags = JS_EVAL_FLAG_COMPILE_ONLY;
|
||||
if (module < 0) {
|
||||
module = (has_suffix(filename, ".mjs") ||
|
||||
module = (js__has_suffix(filename, ".mjs") ||
|
||||
JS_DetectModule((const char *)buf, buf_len));
|
||||
}
|
||||
if (module)
|
||||
eval_flags |= JS_EVAL_TYPE_MODULE;
|
||||
else
|
||||
eval_flags |= JS_EVAL_TYPE_GLOBAL;
|
||||
obj = JS_Eval(ctx, (const char *)buf, buf_len, filename, eval_flags);
|
||||
obj = JS_Eval(ctx, (const char *)buf, buf_len, script_name ? script_name : filename, eval_flags);
|
||||
if (JS_IsException(obj)) {
|
||||
js_std_dump_error(ctx);
|
||||
qjsc_dump_error(ctx);
|
||||
exit(1);
|
||||
}
|
||||
js_free(ctx, buf);
|
||||
if (c_name1) {
|
||||
pstrcpy(c_name, sizeof(c_name), c_name1);
|
||||
js__pstrcpy(c_name, sizeof(c_name), c_name1);
|
||||
} else {
|
||||
get_c_name(c_name, sizeof(c_name), filename);
|
||||
}
|
||||
@@ -335,6 +416,7 @@ static const char main_c_template1[] =
|
||||
static const char main_c_template2[] =
|
||||
" js_std_loop(ctx);\n"
|
||||
" JS_FreeContext(ctx);\n"
|
||||
" js_std_free_handlers(rt);\n"
|
||||
" JS_FreeRuntime(rt);\n"
|
||||
" return 0;\n"
|
||||
"}\n";
|
||||
@@ -343,226 +425,74 @@ static const char main_c_template2[] =
|
||||
|
||||
void help(void)
|
||||
{
|
||||
printf("QuickJS Compiler version " CONFIG_VERSION "\n"
|
||||
printf("QuickJS-ng Compiler version %s\n"
|
||||
"usage: " PROG_NAME " [options] [files]\n"
|
||||
"\n"
|
||||
"options are:\n"
|
||||
"-c only output bytecode in a C file\n"
|
||||
"-e output main() and bytecode in a C file (default = executable output)\n"
|
||||
"-b output raw bytecode instead of C code\n"
|
||||
"-e output main() and bytecode in a C file\n"
|
||||
"-o output set the output filename\n"
|
||||
"-n script_name set the script name (as used in stack traces)\n"
|
||||
"-N cname set the C name of the generated data\n"
|
||||
"-m compile as Javascript module (default=autodetect)\n"
|
||||
"-D module_name compile a dynamically loaded module or worker\n"
|
||||
"-M module_name[,cname] add initialization code for an external C module\n"
|
||||
"-x byte swapped output\n"
|
||||
"-p prefix set the prefix of the generated C names\n"
|
||||
"-s strip the source code, specify twice to also strip debug info\n"
|
||||
"-S n set the maximum stack size to 'n' bytes (default=%d)\n",
|
||||
JS_GetVersion(),
|
||||
JS_DEFAULT_STACK_SIZE);
|
||||
#ifdef CONFIG_LTO
|
||||
{
|
||||
int i;
|
||||
printf("-flto use link time optimization\n");
|
||||
printf("-fbignum enable bignum extensions\n");
|
||||
printf("-fno-[");
|
||||
for(i = 0; i < countof(feature_list); i++) {
|
||||
if (i != 0)
|
||||
printf("|");
|
||||
printf("%s", feature_list[i].option_name);
|
||||
}
|
||||
printf("]\n"
|
||||
" disable selected language features (smaller code size)\n");
|
||||
}
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CC) && !defined(_WIN32)
|
||||
|
||||
int exec_cmd(char **argv)
|
||||
{
|
||||
int pid, status, ret;
|
||||
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
execvp(argv[0], argv);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
ret = waitpid(pid, &status, 0);
|
||||
if (ret == pid && WIFEXITED(status))
|
||||
break;
|
||||
}
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
|
||||
static int output_executable(const char *out_filename, const char *cfilename,
|
||||
BOOL use_lto, BOOL verbose, const char *exename)
|
||||
{
|
||||
const char *argv[64];
|
||||
const char **arg, *bn_suffix, *lto_suffix;
|
||||
char libjsname[1024];
|
||||
char exe_dir[1024], inc_dir[1024], lib_dir[1024], buf[1024], *p;
|
||||
int ret;
|
||||
|
||||
/* get the directory of the executable */
|
||||
pstrcpy(exe_dir, sizeof(exe_dir), exename);
|
||||
p = strrchr(exe_dir, '/');
|
||||
if (p) {
|
||||
*p = '\0';
|
||||
} else {
|
||||
pstrcpy(exe_dir, sizeof(exe_dir), ".");
|
||||
}
|
||||
|
||||
/* if 'quickjs.h' is present at the same path as the executable, we
|
||||
use it as include and lib directory */
|
||||
snprintf(buf, sizeof(buf), "%s/quickjs.h", exe_dir);
|
||||
if (access(buf, R_OK) == 0) {
|
||||
pstrcpy(inc_dir, sizeof(inc_dir), exe_dir);
|
||||
pstrcpy(lib_dir, sizeof(lib_dir), exe_dir);
|
||||
} else {
|
||||
snprintf(inc_dir, sizeof(inc_dir), "%s/include/quickjs", CONFIG_PREFIX);
|
||||
snprintf(lib_dir, sizeof(lib_dir), "%s/lib/quickjs", CONFIG_PREFIX);
|
||||
}
|
||||
|
||||
lto_suffix = "";
|
||||
bn_suffix = "";
|
||||
|
||||
arg = argv;
|
||||
*arg++ = CONFIG_CC;
|
||||
*arg++ = "-O2";
|
||||
#ifdef CONFIG_LTO
|
||||
if (use_lto) {
|
||||
*arg++ = "-flto";
|
||||
lto_suffix = ".lto";
|
||||
}
|
||||
#endif
|
||||
/* XXX: use the executable path to find the includes files and
|
||||
libraries */
|
||||
*arg++ = "-D";
|
||||
*arg++ = "_GNU_SOURCE";
|
||||
*arg++ = "-I";
|
||||
*arg++ = inc_dir;
|
||||
*arg++ = "-o";
|
||||
*arg++ = out_filename;
|
||||
if (dynamic_export)
|
||||
*arg++ = "-rdynamic";
|
||||
*arg++ = cfilename;
|
||||
snprintf(libjsname, sizeof(libjsname), "%s/libquickjs%s%s.a",
|
||||
lib_dir, bn_suffix, lto_suffix);
|
||||
*arg++ = libjsname;
|
||||
*arg++ = "-lm";
|
||||
*arg++ = "-ldl";
|
||||
*arg++ = "-lpthread";
|
||||
*arg = NULL;
|
||||
|
||||
if (verbose) {
|
||||
for(arg = argv; *arg != NULL; arg++)
|
||||
printf("%s ", *arg);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
ret = exec_cmd((char **)argv);
|
||||
unlink(cfilename);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static int output_executable(const char *out_filename, const char *cfilename,
|
||||
BOOL use_lto, BOOL verbose, const char *exename)
|
||||
{
|
||||
fprintf(stderr, "Executable output is not supported for this target\n");
|
||||
exit(1);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum {
|
||||
OUTPUT_C,
|
||||
OUTPUT_C_MAIN,
|
||||
OUTPUT_EXECUTABLE,
|
||||
} OutputTypeEnum;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int c, i, verbose;
|
||||
const char *out_filename, *cname;
|
||||
int c, i;
|
||||
const char *out_filename, *cname, *script_name;
|
||||
char cfilename[1024];
|
||||
FILE *fo;
|
||||
JSRuntime *rt;
|
||||
JSContext *ctx;
|
||||
BOOL use_lto;
|
||||
int module;
|
||||
OutputTypeEnum output_type;
|
||||
size_t stack_size;
|
||||
#ifdef CONFIG_BIGNUM
|
||||
BOOL bignum_ext = FALSE;
|
||||
#endif
|
||||
namelist_t dynamic_module_list;
|
||||
|
||||
|
||||
out_filename = NULL;
|
||||
output_type = OUTPUT_EXECUTABLE;
|
||||
script_name = NULL;
|
||||
output_type = OUTPUT_C;
|
||||
cname = NULL;
|
||||
feature_bitmap = FE_ALL;
|
||||
module = -1;
|
||||
byte_swap = FALSE;
|
||||
verbose = 0;
|
||||
use_lto = FALSE;
|
||||
strip = 0;
|
||||
stack_size = 0;
|
||||
memset(&dynamic_module_list, 0, sizeof(dynamic_module_list));
|
||||
|
||||
|
||||
/* add system modules */
|
||||
namelist_add(&cmodule_list, "std", "std", 0);
|
||||
namelist_add(&cmodule_list, "os", "os", 0);
|
||||
namelist_add(&cmodule_list, "bjson", "bjson", 0);
|
||||
|
||||
for(;;) {
|
||||
c = getopt(argc, argv, "ho:cN:f:mxevM:p:S:D:");
|
||||
c = getopt(argc, argv, "ho:N:mn:bxesvM:p:S:D:");
|
||||
if (c == -1)
|
||||
break;
|
||||
switch(c) {
|
||||
case 'h':
|
||||
help();
|
||||
case 'b':
|
||||
output_type = OUTPUT_RAW;
|
||||
break;
|
||||
case 'o':
|
||||
out_filename = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
output_type = OUTPUT_C;
|
||||
break;
|
||||
case 'e':
|
||||
output_type = OUTPUT_C_MAIN;
|
||||
break;
|
||||
case 'n':
|
||||
script_name = optarg;
|
||||
break;
|
||||
case 'N':
|
||||
cname = optarg;
|
||||
break;
|
||||
case 'f':
|
||||
{
|
||||
const char *p;
|
||||
p = optarg;
|
||||
if (!strcmp(optarg, "lto")) {
|
||||
use_lto = TRUE;
|
||||
} else if (strstart(p, "no-", &p)) {
|
||||
use_lto = TRUE;
|
||||
for(i = 0; i < countof(feature_list); i++) {
|
||||
if (!strcmp(p, feature_list[i].option_name)) {
|
||||
feature_bitmap &= ~((uint64_t)1 << i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == countof(feature_list))
|
||||
goto bad_feature;
|
||||
} else
|
||||
#ifdef CONFIG_BIGNUM
|
||||
if (!strcmp(optarg, "bignum")) {
|
||||
bignum_ext = TRUE;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
bad_feature:
|
||||
fprintf(stderr, "unsupported feature: %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
module = 1;
|
||||
break;
|
||||
@@ -571,11 +501,11 @@ int main(int argc, char **argv)
|
||||
char *p;
|
||||
char path[1024];
|
||||
char cname[1024];
|
||||
pstrcpy(path, sizeof(path), optarg);
|
||||
js__pstrcpy(path, sizeof(path), optarg);
|
||||
p = strchr(path, ',');
|
||||
if (p) {
|
||||
*p = '\0';
|
||||
pstrcpy(cname, sizeof(cname), p + 1);
|
||||
js__pstrcpy(cname, sizeof(cname), p + 1);
|
||||
} else {
|
||||
get_c_name(cname, sizeof(cname), path);
|
||||
}
|
||||
@@ -585,11 +515,8 @@ int main(int argc, char **argv)
|
||||
case 'D':
|
||||
namelist_add(&dynamic_module_list, optarg, NULL, 0);
|
||||
break;
|
||||
case 'x':
|
||||
byte_swap = TRUE;
|
||||
break;
|
||||
case 'v':
|
||||
verbose++;
|
||||
case 's':
|
||||
strip++;
|
||||
break;
|
||||
case 'p':
|
||||
c_ident_prefix = optarg;
|
||||
@@ -605,55 +532,39 @@ int main(int argc, char **argv)
|
||||
if (optind >= argc)
|
||||
help();
|
||||
|
||||
if (!out_filename) {
|
||||
if (output_type == OUTPUT_EXECUTABLE) {
|
||||
out_filename = "a.out";
|
||||
} else {
|
||||
out_filename = "out.c";
|
||||
}
|
||||
}
|
||||
if (!out_filename)
|
||||
out_filename = "out.c";
|
||||
|
||||
js__pstrcpy(cfilename, sizeof(cfilename), out_filename);
|
||||
|
||||
if (output_type == OUTPUT_RAW)
|
||||
fo = fopen(cfilename, "wb");
|
||||
else
|
||||
fo = fopen(cfilename, "w");
|
||||
|
||||
if (output_type == OUTPUT_EXECUTABLE) {
|
||||
#if defined(_WIN32) || defined(__ANDROID__)
|
||||
/* XXX: find a /tmp directory ? */
|
||||
snprintf(cfilename, sizeof(cfilename), "out%d.c", getpid());
|
||||
#else
|
||||
snprintf(cfilename, sizeof(cfilename), "/tmp/out%d.c", getpid());
|
||||
#endif
|
||||
} else {
|
||||
pstrcpy(cfilename, sizeof(cfilename), out_filename);
|
||||
}
|
||||
|
||||
fo = fopen(cfilename, "w");
|
||||
if (!fo) {
|
||||
perror(cfilename);
|
||||
exit(1);
|
||||
}
|
||||
outfile = fo;
|
||||
|
||||
|
||||
rt = JS_NewRuntime();
|
||||
ctx = JS_NewContext(rt);
|
||||
#ifdef CONFIG_BIGNUM
|
||||
if (bignum_ext) {
|
||||
JS_AddIntrinsicBigFloat(ctx);
|
||||
JS_AddIntrinsicBigDecimal(ctx);
|
||||
JS_AddIntrinsicOperators(ctx);
|
||||
JS_EnableBignumExt(ctx, TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* loader for ES6 modules */
|
||||
JS_SetModuleLoaderFunc(rt, NULL, jsc_module_loader, NULL);
|
||||
|
||||
fprintf(fo, "/* File generated automatically by the QuickJS compiler. */\n"
|
||||
"\n"
|
||||
);
|
||||
|
||||
if (output_type != OUTPUT_C) {
|
||||
if (output_type != OUTPUT_RAW) {
|
||||
fprintf(fo, "/* File generated automatically by the QuickJS-ng compiler. */\n"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
||||
if (output_type == OUTPUT_C_MAIN) {
|
||||
fprintf(fo, "#include \"quickjs-libc.h\"\n"
|
||||
"\n"
|
||||
);
|
||||
} else {
|
||||
} else if (output_type == OUTPUT_C) {
|
||||
fprintf(fo, "#include <inttypes.h>\n"
|
||||
"\n"
|
||||
);
|
||||
@@ -661,7 +572,7 @@ int main(int argc, char **argv)
|
||||
|
||||
for(i = optind; i < argc; i++) {
|
||||
const char *filename = argv[i];
|
||||
compile_file(ctx, fo, filename, cname, module);
|
||||
compile_file(ctx, fo, filename, script_name, cname, module);
|
||||
cname = NULL;
|
||||
}
|
||||
|
||||
@@ -672,38 +583,20 @@ int main(int argc, char **argv)
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (output_type != OUTPUT_C) {
|
||||
|
||||
if (output_type == OUTPUT_C_MAIN) {
|
||||
fprintf(fo,
|
||||
"static JSContext *JS_NewCustomContext(JSRuntime *rt)\n"
|
||||
"{\n"
|
||||
" JSContext *ctx = JS_NewContextRaw(rt);\n"
|
||||
" JSContext *ctx = JS_NewContext(rt);\n"
|
||||
" if (!ctx)\n"
|
||||
" return NULL;\n");
|
||||
/* add the basic objects */
|
||||
fprintf(fo, " JS_AddIntrinsicBaseObjects(ctx);\n");
|
||||
for(i = 0; i < countof(feature_list); i++) {
|
||||
if ((feature_bitmap & ((uint64_t)1 << i)) &&
|
||||
feature_list[i].init_name) {
|
||||
fprintf(fo, " JS_AddIntrinsic%s(ctx);\n",
|
||||
feature_list[i].init_name);
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_BIGNUM
|
||||
if (bignum_ext) {
|
||||
fprintf(fo,
|
||||
" JS_AddIntrinsicBigFloat(ctx);\n"
|
||||
" JS_AddIntrinsicBigDecimal(ctx);\n"
|
||||
" JS_AddIntrinsicOperators(ctx);\n"
|
||||
" JS_EnableBignumExt(ctx, 1);\n");
|
||||
}
|
||||
#endif
|
||||
/* add the precompiled modules (XXX: could modify the module
|
||||
loader instead) */
|
||||
for(i = 0; i < init_module_list.count; i++) {
|
||||
namelist_entry_t *e = &init_module_list.array[i];
|
||||
/* initialize the static C modules */
|
||||
|
||||
|
||||
fprintf(fo,
|
||||
" {\n"
|
||||
" extern JSModuleDef *js_init_module_%s(JSContext *ctx, const char *name);\n"
|
||||
@@ -721,19 +614,17 @@ int main(int argc, char **argv)
|
||||
fprintf(fo,
|
||||
" return ctx;\n"
|
||||
"}\n\n");
|
||||
|
||||
|
||||
fputs(main_c_template1, fo);
|
||||
|
||||
if (stack_size != 0) {
|
||||
fprintf(fo, " JS_SetMaxStackSize(rt, %u);\n",
|
||||
(unsigned int)stack_size);
|
||||
}
|
||||
|
||||
/* add the module loader if necessary */
|
||||
if (feature_bitmap & (1 << FE_MODULE_LOADER)) {
|
||||
fprintf(fo, " JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n");
|
||||
}
|
||||
|
||||
|
||||
/* add the module loader */
|
||||
fprintf(fo, " JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n");
|
||||
|
||||
fprintf(fo,
|
||||
" ctx = JS_NewCustomContext(rt);\n"
|
||||
" js_std_add_helpers(ctx, argc, argv);\n");
|
||||
@@ -747,16 +638,12 @@ int main(int argc, char **argv)
|
||||
}
|
||||
fputs(main_c_template2, fo);
|
||||
}
|
||||
|
||||
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
|
||||
fclose(fo);
|
||||
|
||||
if (output_type == OUTPUT_EXECUTABLE) {
|
||||
return output_executable(out_filename, cfilename, use_lto, verbose,
|
||||
argv[0]);
|
||||
}
|
||||
namelist_free(&cname_list);
|
||||
namelist_free(&cmodule_list);
|
||||
namelist_free(&init_module_list);
|
||||
Reference in new issue
Block a user