Init with the basics
This commit is contained in:
commit
800161fd6d
6 files changed
+3919
No files matched your search
+299
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* A port of xxd as distributed with Vim 8.2 (on Ubuntu 22.04 LTS).
|
||||
*
|
||||
* That utility's source code is distributed with the following notice:
|
||||
*
|
||||
* (c) 1990-1998 by Juergen Weigert (jnweiger@gmail.com)
|
||||
*
|
||||
* I hereby grant permission to distribute and use xxd
|
||||
* under X11-MIT or GPL-2.0 (at the user's choice).
|
||||
*
|
||||
* Contributions by Bram Moolenaar et al.
|
||||
*
|
||||
* Only the defaults are supported at this time. The argument processing
|
||||
* logic is mostly absent.
|
||||
*
|
||||
* The choices made here (and there are few--we primarily aim for the source
|
||||
* to correspond to the routines just as they appear in xxd-8.2.3995.c) are
|
||||
* done with the main aim being to reconcile the impedance mismatch between
|
||||
* the C implementation and the dialect used here for the programming
|
||||
* environment we are targeting. Modifications have been made where necessary
|
||||
* with the foremost goal being to get the code to work. It is not meant to
|
||||
* be efficient nor to satisfy some other measure of good. This is bad code.
|
||||
*
|
||||
* This class doesn't actually output anything (or read anything, for that
|
||||
* matter). It does its work with the `input` and `output` buffers. There is
|
||||
* a `toString` implementation to reify the completed dump as a string.
|
||||
*/
|
||||
|
||||
export
|
||||
class XXD {
|
||||
exec() {
|
||||
const _static = new XXD.Keeps;
|
||||
|
||||
const { EOF } = XXD;
|
||||
|
||||
const { HEX_NORMAL } = XXD;
|
||||
const { HEX_POSTSCRIPT } = XXD;
|
||||
const { HEX_CINCLUDE } = XXD;
|
||||
const { HEX_BITS } = XXD;
|
||||
const { HEX_LITTLEENDIAN } = XXD;
|
||||
|
||||
const { COLS } = XXD;
|
||||
const { LLEN } = XXD;
|
||||
|
||||
const $ = ((c) => (c.charCodeAt(0)));
|
||||
const $$ = ((s) => (Uint8Array.from(s, $)));
|
||||
const $puts = ((...args) => (this._putOrDie(...args)));
|
||||
const $exit = ((...args) => (this._exit(...args)));
|
||||
|
||||
const hexx = $$("0123456789abcdef0123456789ABCDEF");
|
||||
|
||||
let fp = this.input;
|
||||
let fpo = this.output;
|
||||
|
||||
let c, e, p = 0;
|
||||
|
||||
let relseek = 1;
|
||||
let negseek = 0;
|
||||
let revert = 0;
|
||||
|
||||
let cols = 0;
|
||||
let nonzero = 0;
|
||||
let autoskip = 0;
|
||||
let hextype = HEX_NORMAL;
|
||||
|
||||
let capitalize, decimaloff = 0;
|
||||
let ebcdic = 0;
|
||||
let octspergrp = -1;
|
||||
let grplen;
|
||||
let length = -1, n = 0, seekoff = 0;
|
||||
let displayoff = 0;
|
||||
|
||||
let l = new Uint8Array(LLEN + 1);
|
||||
|
||||
let pp;
|
||||
let addrlen = 9;
|
||||
|
||||
if (!cols) {
|
||||
switch (hextype) {
|
||||
case HEX_POSTSCRIPT: cols = 30; break;
|
||||
case HEX_CINCLUDE: cols = 12; break;
|
||||
case HEX_BITS: cols = 6; break;
|
||||
case HEX_NORMAL:
|
||||
case HEX_LITTLENDIAN:
|
||||
default: cols = 16; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (octspergrp < 0) {
|
||||
switch (hextype) {
|
||||
case HEX_BITS: octspergrp = 1; break;
|
||||
case HEX_NORMAL: octspergrp = 2; break;
|
||||
case HEX_LITTLENDIAN: octspergrp = 4; break;
|
||||
case HEX_POSTSCRIPT:
|
||||
case HEX_CINCLUDE:
|
||||
default: octspergrp = 0; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cols < 1 || ((hextype == HEX_NORMAL || hextype == HEX_BITS ||
|
||||
hextype == HEX_LITTLEENDIAN) && (cols > COLS))) {
|
||||
return void this._exit(
|
||||
1, null, pname + ": invalid number of columns (max. " + COLS + ")"
|
||||
);
|
||||
}
|
||||
|
||||
if (octspergrp < 1 || octspergrp > cols) {
|
||||
octspergrp = cols;
|
||||
} else if (hextype == HEX_LITTLEENDIAN) {
|
||||
if (octspergrp & (octspergrp - 1)) {
|
||||
return void this._exit(
|
||||
1, "number of octets per group must be a power of 2 with -e."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (revert) {
|
||||
if (hextype && hextype != HEX_POSTSCRIPT) {
|
||||
return void this._exit(-1, "Sorry, cannot revert this type of hexdump");
|
||||
}
|
||||
return void this._exit(XXD.UNIMPLEMENTED); // XXX
|
||||
}
|
||||
|
||||
if (seekoff || negseek || !relseek) {
|
||||
if (relseek) {
|
||||
e = _fseek(fp, (negseek) ? -seekoff : seekoff, SEEK_CUR);
|
||||
} else {
|
||||
e = _fseek(fp, (negseek) ? -seekoff : seekoff,
|
||||
(negseek) ? SEEK_END : SEEK_SET);
|
||||
}
|
||||
|
||||
if (e < 0 && negseek) {
|
||||
return void this._exit(4, "Sorry, cannot seek.");
|
||||
} else if (e >= 0) {
|
||||
seekoff = _ftell(fp);
|
||||
} else {
|
||||
let s = seekoff;
|
||||
while (s--) {
|
||||
let e = this._getOrDie(fp);
|
||||
if (e == EOF) return void this._exit(4, "Sorry, cannot seek.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hextype == HEX_CINCLUDE) {
|
||||
return void this._exit(XXD.UNIMPLEMENTED); // XXX
|
||||
} else if (hextype == HEX_POSTSCRIPT) {
|
||||
return void this._exit(XXD.UNIMPLEMENTED); // XXX
|
||||
}
|
||||
|
||||
if (hextype != HEX_BITS) {
|
||||
grplen = octspergrp + octspergrp + 1;
|
||||
} else {
|
||||
grplen = 8 * octspergrp + 1;
|
||||
}
|
||||
|
||||
while (length < 0 || n < length) {
|
||||
e = this._getOrDie(fp);
|
||||
if (e == EOF) break;
|
||||
|
||||
let x;
|
||||
|
||||
if (p == 0) {
|
||||
addrlen = _sprintf(
|
||||
l, (decimaloff) ? "%08ld:" : "%08lx:",
|
||||
n + seekoff + displayoff
|
||||
);
|
||||
|
||||
for (c = addrlen; c < LLEN; l[c++] = $(' '));
|
||||
}
|
||||
x = (hextype == HEX_LITTLEENDIAN) ? (p ^ (octspergrp - 1)) : p;
|
||||
c = addrlen + 1 + ~~((grplen * x) / octspergrp);
|
||||
if (hextype == HEX_NORMAL || hextype == HEX_LITTLEENDIAN) {
|
||||
l[c+0] = hexx[(e >> 4) & 0x0F];
|
||||
l[++c] = hexx[(e >> 0) & 0x0F];
|
||||
} else { // HEX_BITS
|
||||
for (let i = 7; i >= 0; --i) {
|
||||
l[c++] = (e & (1 << i)) ? $('1') : $('0');
|
||||
}
|
||||
}
|
||||
|
||||
if (e) nonzero++;
|
||||
|
||||
if (ebcdic) return void this._exit(XXD.UNIMPLEMENTED); // XXX
|
||||
|
||||
c = addrlen + 3 + ~~((grplen * cols - 1) / octspergrp) + p;
|
||||
|
||||
if (31 < e && e < 127) {
|
||||
l[c++] = e;
|
||||
} else {
|
||||
l[c++] = $('.');
|
||||
}
|
||||
|
||||
++n;
|
||||
|
||||
if (++p == cols) {
|
||||
l[c+0] = $('\n');
|
||||
l[++c] = $('\0');
|
||||
_xxdline(fpo, l , (autoskip) ? nonzero : 1);
|
||||
nonzero = 0;
|
||||
p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (p) {
|
||||
l[c+0] = $('\n');
|
||||
l[++c] = $('\0');
|
||||
_xxdline(fpo, l, 1);
|
||||
} else if (autoskip) {
|
||||
_xxdline(fpo, l, -1);
|
||||
}
|
||||
|
||||
function _xxdline(fp, l, nz, _ = _static) {
|
||||
if (!nz && _.s == 1) {
|
||||
_strcpy(_.z, l);
|
||||
}
|
||||
|
||||
if (nz || !_.s++) {
|
||||
if (nz) {
|
||||
if (nz < 0) _.s--;
|
||||
if (_.s == 2) $puts(_.z, fp);
|
||||
if (_.s > 2) $puts($$("*\n"), fp);
|
||||
}
|
||||
if (nz >= 0 || _.s > 0) $puts(l, fp);
|
||||
if (nz) _.s = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function _strcpy(dest, src) {
|
||||
let stop = src.indexOf(0);
|
||||
if (stop >= 0) {
|
||||
dest.set(new Uint8Array(src.buffer, 0, stop));
|
||||
} else {
|
||||
return void $exit(XXD.IMPLEMENTATION_ERROR); // XXX
|
||||
}
|
||||
}
|
||||
|
||||
function _sprintf(bytes, format, ...args) {
|
||||
if (args.length == 1 && format == "%08lx:") {
|
||||
let what = args[0].toString(16).padStart(8, "0") + ":";
|
||||
bytes.set($$(what));
|
||||
return what.length;
|
||||
}
|
||||
return void $exit(XXD.UNIMPLEMENTED); // XXX
|
||||
}
|
||||
}
|
||||
|
||||
constructor(input, output = []) {
|
||||
this.input = input;
|
||||
this.output = output;
|
||||
|
||||
this._place = 0;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.output.map((x) => (String.fromCharCode(x))).join("");
|
||||
}
|
||||
|
||||
_getOrDie(fp) {
|
||||
if (fp == this.input) {
|
||||
if (this._place < this.input.length) {
|
||||
return this.input[this._place++];
|
||||
}
|
||||
return XXD.EOF;
|
||||
}
|
||||
return void this._exit(XXD.UNIMPLEMENTED); // XXX
|
||||
}
|
||||
|
||||
_putOrDie(bytes, fp) {
|
||||
if (fp == this.output) {
|
||||
for (let i = 0, n = bytes.length; i < n; ++i) {
|
||||
if (bytes[i] == 0) return;
|
||||
this.output.push(bytes[i]);
|
||||
}
|
||||
}
|
||||
return void this._exit(XXD.UNIMPLEMENTED); // XXX
|
||||
}
|
||||
}
|
||||
|
||||
XXD.Keeps = class {
|
||||
constructor() {
|
||||
this.s = 0; // was `zero_seen` in C
|
||||
this.z = new Uint8Array(XXD.LLEN + 1);
|
||||
}
|
||||
}
|
||||
|
||||
XXD.HEX_NORMAL = 0;
|
||||
XXD.HEX_POSTSCRIPT = 1;
|
||||
XXD.HEX_CINCLUDE = 2;
|
||||
XXD.HEX_BITS = 3;
|
||||
XXD.HEX_LITTLEENDIAN = 4;
|
||||
|
||||
XXD.COLS = 256;
|
||||
XXD.LLEN = 2573; // XXX (2 * 4) + 4 + (9 * COLS - 1) + COLS + 2
|
||||
|
||||
XXD.EOF = -1;
|
||||
|
||||
XXD.UNIMPLEMENTED = 90;
|
||||
XXD.IMPLEMENTATION_ERROR = 91;
|
||||
Reference in new issue
Block a user