Skip to content

Instantly share code, notes, and snippets.

@deathcap
Last active August 25, 2022 18:11
Show Gist options
  • Save deathcap/77bbe28924948e86529468f43b837ba6 to your computer and use it in GitHub Desktop.
Save deathcap/77bbe28924948e86529468f43b837ba6 to your computer and use it in GitHub Desktop.
example of transpiling FreeBSD bin/ls/ls.c to JS using https://github.com/deathcap/transpile-c-to-js
function xo_emit_hvp(xop, fmt, vap)
{
return xo_emit_hv(xop, fmt, vap);
}
function xo_emit_hp(xop, fmt, ...args)
{
let vap;
__builtin_va_start(vap);
let rc = xo_emit_hv(xop, fmt, vap);
;
return rc;
}
function xo_emit_p(fmt, ...args)
{
let vap;
__builtin_va_start(vap);
let rc = xo_emit_hv(0, fmt, vap);
;
return rc;
}
function xo_emit_warn_hcvp(xop, as_warning, code, fmt, vap)
{
xo_emit_warn_hcv(xop, as_warning, code, fmt, vap);
}
function xo_emit_warn_hcp(xop, code, fmt, ...args)
{
let vap;
__builtin_va_start(vap);
xo_emit_warn_hcv(xop, 1, code, fmt, vap);
;
}
function xo_emit_warn_cp(code, fmt, ...args)
{
let vap;
__builtin_va_start(vap);
xo_emit_warn_hcv(0, 1, code, fmt, vap);
;
}
function xo_emit_warn_p(fmt, ...args)
{
let code = errno;
let vap;
__builtin_va_start(vap);
xo_emit_warn_hcv(0, 1, code, fmt, vap);
;
}
function xo_emit_warnx_p(fmt, ...args)
{
let vap;
__builtin_va_start(vap);
xo_emit_warn_hcv(0, 1, -1, fmt, vap);
;
}
function xo_emit_err_p(eval, fmt, ...args)
{
let code = errno;
let vap;
__builtin_va_start(vap);
xo_emit_warn_hcv(0, 0, code, fmt, vap);
;
exit(eval);
}
function xo_emit_errx_p(eval, fmt, ...args)
{
let vap;
__builtin_va_start(vap);
xo_emit_warn_hcv(0, 0, -1, fmt, vap);
;
exit(eval);
}
function xo_emit_errc_p(eval, code, fmt, ...args)
{
let vap;
__builtin_va_start(vap);
xo_emit_warn_hcv(0, 0, code, fmt, vap);
;
exit(eval);
}
function main(argc, argv)
{
let dot = ".";
let dotav = [dot, 0];
let win;
let ch;
let fts_options;
let notused;
let p;
let errstr = 0;
setlocale(LC_ALL, "");
if (isatty(STDOUT_FILENO))
{
termwidth = 80;
if (((p = getenv("COLUMNS")) !== 0) && ((p) !== '\0'))
termwidth = strtonum(p, 0, 0x7fffffff, errstr);
else
if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, win) !== (-1)) && (win.ws_col > 0))
termwidth = win.ws_col;
f_nonprint = 1;
}
else
{
f_singlecol = 1;
p = getenv("COLUMNS");
if (p)
termwidth = strtonum(p, 0, 0x7fffffff, errstr);
}
if (errstr)
termwidth = 80;
fts_options = 0x010;
if (getenv("LS_SAMESORT"))
f_samesort = 1;
argc = xo_parse_args(argc, argv);
if (argc < 0)
return 1;
xo_set_flags(0, (1) << 21);
xo_set_version("1");
while ((ch = getopt(argc, argv, "1ABCD:FGHILPRSTUWXZabcdfghiklmnopqrstuwxy,")) !== (-1))
{
switch (ch)
{
case '1':
f_singlecol = 1;
f_longform = 0;
f_stream = 0;
break;
case 'C':
f_sortacross = (f_longform = (f_singlecol = 0));
break;
case 'l':
f_longform = 1;
f_singlecol = 0;
f_stream = 0;
break;
case 'x':
f_sortacross = 1;
f_longform = 0;
f_singlecol = 0;
break;
case 'c':
f_statustime = 1;
f_accesstime = 0;
f_birthtime = 0;
break;
case 'u':
f_accesstime = 1;
f_statustime = 0;
f_birthtime = 0;
break;
case 'U':
f_birthtime = 1;
f_accesstime = 0;
f_statustime = 0;
break;
case 'f':
f_nosort = 1;
case 'a':
fts_options |= 0x020;
case 'A':
f_listdot = 1;
break;
case 'S':
f_sizesort = 1;
f_timesort = 0;
break;
case 't':
f_timesort = 1;
f_sizesort = 0;
break;
case ',':
f_thousands = 1;
break;
case 'B':
f_nonprint = 0;
f_octal = 1;
f_octal_escape = 0;
break;
case 'D':
f_timeformat = optarg;
break;
case 'F':
f_type = 1;
f_slash = 0;
break;
case 'G':
setenv("CLICOLOR", "", 1);
break;
case 'H':
fts_options |= 0x001;
f_nofollow = 0;
break;
case 'I':
f_noautodot = 1;
break;
case 'L':
fts_options &= ~0x010;
fts_options |= 0x002;
f_nofollow = 0;
break;
case 'P':
fts_options &= ~0x001;
fts_options &= ~0x002;
fts_options |= 0x010;
f_nofollow = 1;
break;
case 'R':
f_recursive = 1;
break;
case 'T':
f_sectime = 1;
break;
case 'W':
f_whiteout = 1;
break;
case 'Z':
f_label = 1;
break;
case 'b':
f_nonprint = 0;
f_octal = 0;
f_octal_escape = 1;
break;
case 'd':
f_listdir = 1;
f_recursive = 0;
break;
case 'g':
break;
case 'h':
f_humanval = 1;
break;
case 'i':
f_inode = 1;
break;
case 'k':
f_humanval = 0;
f_kblocks = 1;
break;
case 'm':
f_stream = 1;
f_singlecol = 0;
f_longform = 0;
break;
case 'n':
f_numericonly = 1;
break;
case 'o':
f_flags = 1;
break;
case 'p':
f_slash = 1;
f_type = 1;
break;
case 'q':
f_nonprint = 1;
f_octal = 0;
f_octal_escape = 0;
break;
case 'r':
f_reversesort = 1;
break;
case 's':
f_size = 1;
break;
case 'w':
f_nonprint = 0;
f_octal = 0;
f_octal_escape = 0;
break;
case 'y':
f_samesort = 1;
break;
default:
case '?':
usage();
}
}
argc -= optind;
argv += optind;
if (((!f_listdot) && (getuid() === (0))) && (!f_noautodot))
f_listdot = 1;
if (getenv("CLICOLOR") && (isatty(STDOUT_FILENO) || getenv("CLICOLOR_FORCE")))
xo_warnx("color support not compiled in");
if ((((((!f_inode) && (!f_longform)) && (!f_size)) && (!f_timesort)) && (!f_sizesort)) && (!f_type))
fts_options |= 0x008;
if ((((!f_nofollow) && (!f_longform)) && (!f_listdir)) && ((!f_type) || f_slash))
fts_options |= 0x001;
if (f_whiteout)
fts_options |= 0x080;
if ((f_inode || f_longform) || f_size)
{
if (f_kblocks)
blocksize = 2;
else
{
getbsize(notused, blocksize);
blocksize /= 512;
}
}
if (f_reversesort)
{
if ((!f_timesort) && (!f_sizesort))
sortfcn = revnamecmp;
else
if (f_sizesort)
sortfcn = revsizecmp;
else
if (f_accesstime)
sortfcn = revacccmp;
else
if (f_birthtime)
sortfcn = revbirthcmp;
else
if (f_statustime)
sortfcn = revstatcmp;
else
sortfcn = revmodcmp;
}
else
{
if ((!f_timesort) && (!f_sizesort))
sortfcn = namecmp;
else
if (f_sizesort)
sortfcn = sizecmp;
else
if (f_accesstime)
sortfcn = acccmp;
else
if (f_birthtime)
sortfcn = birthcmp;
else
if (f_statustime)
sortfcn = statcmp;
else
sortfcn = modcmp;
}
if (f_singlecol)
printfcn = printscol;
else
if (f_longform)
printfcn = printlong;
else
if (f_stream)
printfcn = printstream;
else
printfcn = printcol;
xo_open_container("file-information");
if (argc)
traverse(argc, argv, fts_options);
else
traverse(1, dotav, fts_options);
xo_close_container("file-information");
xo_finish();
exit(rval);
}
function traverse(argc, argv, options)
{
let ftsp;
let p;
let chp;
let ch_options;
let first = 1;
if ((ftsp = fts_open(argv, options, f_nosort ? 0 : mastercmp)) === 0)
xo_err(1, "fts_open");
chp = fts_children(ftsp, 0);
if (chp !== 0)
display(0, chp, options);
if (f_listdir)
return;
ch_options = ((!f_recursive) && (!f_label)) && (options & 0x008) ? 0x100 : 0;
while ((p = fts_read(ftsp)) !== 0)
switch (p.fts_info)
{
case 2:
xo_warnx("%s: directory causes a cycle", p.fts_name);
break;
case 4:
case 7:
xo_warnx("%s: %s", p.fts_path, strerror(p.fts_errno));
rval = 1;
break;
case 1:
if (((p.fts_level !== 0) && (p.fts_name[0] === '.')) && (!f_listdot))
break;
if (first)
{
first = 0;
xo_open_list("directory");
}
xo_open_instance("directory");
if (output)
{
xo_emit("\n");
printname("path", p.fts_path);
xo_emit(":\n");
}
else
if (argc > 1)
{
printname("path", p.fts_path);
xo_emit(":\n");
output = 1;
}
chp = fts_children(ftsp, ch_options);
display(p, chp, options);
xo_close_instance("directory");
if ((!f_recursive) && (chp !== 0))
fts_set(ftsp, p, 4);
break;
default:
break;
}
if (!first)
xo_close_list("directory");
if (errno)
xo_err(1, "fts_read");
}
function display(p, list, options)
{
let sp;
let d;
let cur;
let np;
let maxsize;
let maxblock;
let maxinode;
let btotal;
let labelstrlen;
let maxlen;
let maxnlink;
let maxlabelstr;
let sizelen;
let maxflags;
let maxgroup;
let maxuser;
let flen;
let ulen;
let glen;
let initmax;
let entries;
let needstats;
let user;
let group;
let flags;
let labelstr = 0;
let ngroup;
let nuser;
needstats = (f_inode || f_longform) || f_size;
flen = 0;
btotal = 0;
initmax = getenv("LS_COLWIDTHS");
maxlabelstr = (maxblock = (maxlen = (maxnlink = 0)));
maxuser = (maxgroup = (maxflags = (maxsize = 0)));
maxinode = 0;
if ((initmax !== 0) && ((initmax) !== '\0'))
{
let initmax2;
let jinitmax;
let ninitmax;
jinitmax = malloc((strlen(initmax) * 2) + 2);
if (jinitmax === 0)
xo_err(1, "malloc");
initmax2 = jinitmax;
if ((initmax) === ':')
strcpy(initmax2, "0:"), initmax2 += 2;
else
/* FIXME: (initmax2++) = initmax */0, initmax2 = '\0';
for (initmax++; (initmax) !== '\0'; initmax++)
{
if ((initmax[-1] === ':') && (initmax[0] === ':'))
{
/* FIXME: (initmax2++) = '0' */0;
/* FIXME: (initmax2++) = initmax[0] */0;
initmax2[1] = '\0';
}
else
{
/* FIXME: (initmax2++) = initmax[0] */0;
initmax2[1] = '\0';
}
}
if (initmax2[-1] === ':')
strcpy(initmax2, "0");
ninitmax = sscanf(jinitmax, " %ju : %ld : %lu : %u : %u : %i : %jd : %lu : %lu ", maxinode, maxblock, maxnlink, maxuser, maxgroup, maxflags, maxsize, maxlen, maxlabelstr);
f_notabs = 1;
switch (ninitmax)
{
case 0:
maxinode = 0;
case 1:
maxblock = 0;
case 2:
maxnlink = 0;
case 3:
maxuser = 0;
case 4:
maxgroup = 0;
case 5:
maxflags = 0;
case 6:
maxsize = 0;
case 7:
maxlen = 0;
case 8:
maxlabelstr = 0;
f_notabs = 0;
default:
break;
}
do
{
let i;
for (i = 1; maxinode > 0; i *= 10)
maxinode--;
maxinode = i - 1;
}
while (0);
do
{
let i;
for (i = 1; maxblock > 0; i *= 10)
maxblock--;
maxblock = i - 1;
}
while (0);
do
{
let i;
for (i = 1; maxnlink > 0; i *= 10)
maxnlink--;
maxnlink = i - 1;
}
while (0);
do
{
let i;
for (i = 1; maxsize > 0; i *= 10)
maxsize--;
maxsize = i - 1;
}
while (0);
free(jinitmax);
}
d.s_size = 0;
sizelen = 0;
flags = 0;
for (cur = list, entries = 0; cur; cur = cur.fts_link)
{
if ((cur.fts_info === 7) || (cur.fts_info === 10))
{
xo_warnx("%s: %s", cur.fts_name, strerror(cur.fts_errno));
cur.fts_number = 1;
rval = 1;
continue;
}
if (p === 0)
{
if ((cur.fts_info === 1) && (!f_listdir))
{
cur.fts_number = 1;
continue;
}
}
else
{
if ((cur.fts_name[0] === '.') && (!f_listdot))
{
cur.fts_number = 1;
continue;
}
}
if (cur.fts_namelen > maxlen)
maxlen = cur.fts_namelen;
if (f_octal || f_octal_escape)
{
let t = len_octal(cur.fts_name, cur.fts_namelen);
if (t > maxlen)
maxlen = t;
}
if (needstats)
{
sp = cur.fts_statp;
if (sp.st_blocks > maxblock)
maxblock = sp.st_blocks;
if (sp.st_ino > maxinode)
maxinode = sp.st_ino;
if (sp.st_nlink > maxnlink)
maxnlink = sp.st_nlink;
if (sp.st_size > maxsize)
maxsize = sp.st_size;
btotal += sp.st_blocks;
if (f_longform)
{
if (f_numericonly)
{
snprintf(nuser, sizeof(nuser), "%u", sp.st_uid);
snprintf(ngroup, sizeof(ngroup), "%u", sp.st_gid);
user = nuser;
group = ngroup;
}
else
{
user = user_from_uid(sp.st_uid, 0);
group = group_from_gid(sp.st_gid, 0);
}
if ((ulen = strlen(user)) > maxuser)
maxuser = ulen;
if ((glen = strlen(group)) > maxgroup)
maxgroup = glen;
if (f_flags)
{
flags = fflagstostr(sp.st_flags);
if ((flags !== 0) && ((flags) === '\0'))
{
free(flags);
flags = strdup("-");
}
if (flags === 0)
xo_err(1, "fflagstostr");
flen = strlen(flags);
if (flen > (maxflags))
maxflags = flen;
}
else
flen = 0;
labelstr = 0;
if (f_label)
{
let name;
let label;
let error;
error = mac_prepare_file_label(label);
if (error === (-1))
{
xo_warn("MAC label for %s/%s", cur.fts_parent.fts_path, cur.fts_name);
// FIXME: goto label_out;
}
if (cur.fts_level === 0)
snprintf(name, sizeof(name), "%s", cur.fts_name);
else
snprintf(name, sizeof(name), "%s/%s", cur.fts_parent.fts_accpath, cur.fts_name);
if (options & 0x002)
error = mac_get_file(name, label);
else
error = mac_get_link(name, label);
if (error === (-1))
{
xo_warn("MAC label for %s/%s", cur.fts_parent.fts_path, cur.fts_name);
mac_free(label);
// FIXME: goto label_out;
}
error = mac_to_text(label, labelstr);
if (error === (-1))
{
xo_warn("MAC label for %s/%s", cur.fts_parent.fts_path, cur.fts_name);
mac_free(label);
// FIXME: goto label_out;
}
mac_free(label);
label_out:
if (labelstr === 0)
labelstr = strdup("-");
labelstrlen = strlen(labelstr);
if (labelstrlen > maxlabelstr)
maxlabelstr = labelstrlen;
}
else
labelstrlen = 0;
if ((np = malloc((((((sizeof(NAMES)) + labelstrlen) + ulen) + glen) + flen) + 4)) === 0)
xo_err(1, "malloc");
np.user = np.data[0];
strcpy(np.user, user);
np.group = np.data[ulen + 1];
strcpy(np.group, group);
if (S_ISCHR(sp.st_mode) || S_ISBLK(sp.st_mode))
{
sizelen = snprintf(0, 0, "%#jx", sp.st_rdev);
if (d.s_size < sizelen)
d.s_size = sizelen;
}
if (f_flags)
{
np.flags = np.data[(ulen + glen) + 2];
strcpy(np.flags, flags);
free(flags);
}
if (f_label)
{
np.label = np.data[((ulen + glen) + 2) + (f_flags ? flen + 1 : 0)];
strcpy(np.label, labelstr);
free(labelstr);
}
cur.fts_pointer = np;
}
}
++entries;
}
if ((!entries) && ((!(f_longform || f_size)) || (p === 0)))
return;
d.list = list;
d.entries = entries;
d.maxlen = maxlen;
if (needstats)
{
d.btotal = btotal;
d.s_block = snprintf(0, 0, "%lu", (maxblock + (blocksize - 1)) / blocksize);
d.s_flags = maxflags;
d.s_label = maxlabelstr;
d.s_group = maxgroup;
d.s_inode = snprintf(0, 0, "%ju", maxinode);
d.s_nlink = snprintf(0, 0, "%lu", maxnlink);
sizelen = f_humanval ? 5 : snprintf(0, 0, "%ju", maxsize);
if (d.s_size < sizelen)
d.s_size = sizelen;
d.s_user = maxuser;
}
if (f_thousands)
d.s_size += (d.s_size - 1) / 3;
printfcn(d);
output = 1;
if (f_longform)
for (cur = list; cur; cur = cur.fts_link)
free(cur.fts_pointer);
}
function mastercmp(a, b)
{
let a_info;
let b_info;
a_info = (a).fts_info;
if (a_info === 7)
return 0;
b_info = (b).fts_info;
if (b_info === 7)
return 0;
if ((a_info === 10) || (b_info === 10))
return namecmp(a, b);
if (((a_info !== b_info) && ((a).fts_level === 0)) && (!f_listdir))
{
if (a_info === 1)
return 1;
if (b_info === 1)
return -1;
}
return sortfcn(a, b);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment