Last active
August 25, 2022 18:11
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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