Files

188 lines
5.7 KiB
JavaScript

// SPDX-FileCopyrightText: 2018-2023 Giovanni Dante Grazioli <[email protected]>
// SPDX-License-Identifier: BSD-3-Clause
import JSONex from './JSONex.js';
import Long from './long.js';
import Anno from './annotation.js';
import ColorsAnsi from './colors/ansi.js';
import ColorsInvalid from './colors/invalid.js';
function initializeColors() {
const config = {};
if (rizin) {
const raw = rizin.command("ecj");
const colors = JSON.parse(raw || "{}");
if (colors && typeof colors === 'object' && !Array.isArray(colors)) {
Object.keys(colors).forEach(function(key) {
config[key] = colors[key];
});
}
}
return {
"callname": config['call'] || 'gray',
"integers": config['num'] || 'cyan',
"comment": config['comment'] || 'red',
"labels": config['flag'] || 'green',
"types": config['func_var_type'] || 'green',
"macro": config['cjmp'] || 'yellow',
"flow": config['flow'] || 'magenta',
"text": config['usrcmt'] || 'yellow',
};
}
//const _autoregex = /(\bif\b|\belse\b|\bwhile\b|\bfor\b|\bdo\b|\breturn\b|[ui]+nt[123468]+\_t|\bvoid\b|\bconst\b|\bsizeof\b|\bfloat\b|\bdouble\b|0x[0-9A-Fa-f]+|\b\d+\b)/g
/**
* Contains the regex used to colorize a given string.
* @type {Object}
*/
const _autotheme = {
controlflow: /\bif\b|\belse\b|\bwhile\b|\bfor\b|\bdo\b|\breturn\b|\bthrow\b/g,
definebits: /[ui]+nt[123468]+_t|\bvoid\b|\bconst\b|\bsizeof\b|\bfloat\b|\bdouble\b|\bchar\b|\bwchar_t\b|\bextern\b|\bstruct\b|\bsize_t\b|\btime_t\b|\bboolean\b/g,
numbers: /0x[0-9a-fA-F]+|\b(?![;[])\d+(?![;m])\b/g,
string: /("[^"]+")/,
};
const defaulttheme = initializeColors();
/**
* Color types (ansi, nocolor)
* @type {Object}
*/
const Colors = {
ansi: ColorsAnsi,
text: ColorsInvalid,
};
var _theme_colors = Colors.text.make(defaulttheme);
/**
* Applies colors to the string given a certain regex
* @param {String} input - Input string
* @param {String} type - Color name (ansi, text)
* @param {String} regex - Regex to apply
* @return {String} - Result string
*/
var _apply_regex = function(input, type, regex) {
var x = input.split(regex);
var p = input.match(regex);
var s = '';
if (!p) {
return s;
}
var i = 0;
for (i = 0; i < p.length; i++) {
if (p[i].length > 0) {
s += x[i] + _theme_colors[type](p[i]);
} else {
s += x[i] + p[i];
}
}
for (; i < x.length; i++) {
s += x[i];
}
return s;
};
/**
* Colorize the input string via ansi converters
* @param {String} input - Input string
* @return {String} - Result string
*/
var _colorize_text = function(input) {
if (!input || input.length < 1) {
return '';
}
if (!Global().evars.honor.color) {
return input;
}
/* control flow (if, else, while, do, etc..) */
var x = input.split(_autotheme.controlflow);
if (x.length > 1) {
input = _apply_regex(input, 'flow', _autotheme.controlflow);
}
/* numbers */
x = input.split(_autotheme.numbers);
if (x.length == 1 && x == '') {
input = this.theme.integers(input);
} else if (x.length > 1) {
input = _apply_regex(input, 'integers', _autotheme.numbers);
}
/* uint32_t, etc.. */
x = input.split(_autotheme.definebits);
if (x.length == 1 && x == '') {
input = this.theme.types(input);
} else if (input.split(_autotheme.definebits).length > 1) {
input = _apply_regex(input, 'types', _autotheme.definebits);
}
return input;
};
/**
* Applies all the colors options (theme/colors).
*/
var _get_theme = function(evars) {
if (evars.honor && evars.honor.color) {
return Colors.ansi.make(defaulttheme);
}
return Colors.text.make(defaulttheme);
};
/**
* Prints the final jsdec output
* @param useJSON - boolean whether to print as json
*/
var _flush_output = function(lines, errors, log) {
if (Global().evars.extra.annotation && lines) {
var actx = Anno.context();
var res = {
code: "",
annotations: []
};
lines.forEach(function(x) {
var parsed = Anno.parse(res.code.length, x, actx);
res.annotations = res.annotations.concat(parsed);
res.code += x.str + '\n';
});
console.log(JSONex.stringify(res));
} else if (Global().evars.extra.json) {
var jdata = {};
if (lines && lines.length > 0) {
jdata.lines = lines;
}
if (errors && errors.length > 0) {
jdata.errors = errors;
}
if (log && log.length > 0) {
jdata.log = log;
}
console.log(JSONex.stringify(jdata));
} else {
var prefix = Global().evars.extra.allfunctions ? "// " : "";
if (lines && lines.length > 0) {
for (var i = 0; i < lines.length; i++) {
if (Global().evars.extra.highlights && Global().evars.extra.offset.eq(lines[i].offset || Long.ZERO)) {
console.log('\u001b[7m' + lines[i].str + '\u001b[49m\u001b[0m');
} else {
console.log(lines[i].str);
}
}
}
if (errors && errors.length > 0) {
console.log(prefix + errors.join("\n").replace(/\n/g, '\n' + prefix));
}
if (log && log.length > 0) {
console.log(prefix + log.join("\n").replace(/\n/g, '\n' + prefix));
}
}
};
/**
* Printer Object
* @return {Function} - Printer object (to be called via `new Printer()`)
*/
export default function() {
this.theme = _get_theme(Global().evars);
this.auto = _colorize_text;
this.flushOutput = _flush_output;
}