Commit e5df4d6b authored by 大地缸's avatar 大地缸
Browse files

some usefull script

parent f9761115
#!/usr/bin/env -S awk -f
# POSIX awk
# -----------
# About awk distribution:
# [[Name, Compatible]; [oawk, "x ?"] [mawk, ✓] ["gawk(gnu awk)", ✓] [nawk, "✓ ?"] ["busybox awk", ✓]]
#
# ╭───┬───────────────┬────────────╮
# │ # │ Name │ Compatible │
# ├───┼───────────────┼────────────┤
# │ 0 │ oawk │ x ? │
# │ 1 │ mawk │ ✓ │
# │ 2 │ gawk(gnu awk) │ ✓ │
# │ 3 │ nawk │ ✓ ? │
# │ 4 │ busybox awk │ ✓ │
# ╰───┴───────────────┴────────────╯
#
# On some systems, awk refers to oawk(1977).
# In fact, awk in the 1980s was very different from the 1970s.
# In this case, you should call (mawk, nawk, gawk or busybox awk) manually, e.g. nawk -f this-file.awk
# Or you can modify the shebang(line: 1)
#
# For compatibility, no gawk extensions have been introduced here.
#
# Although it is tested with mawk(1.3.4 20200120), theoretically any awk compatible with the new POSIX will work.
# Unfortunately, this version of mawk has some bugs.
# Even busybox awk doesn't have those bugs.
# Fortunately, you can still run it.
#
# Due to the special local variable declaration syntax of awk, if you find "_," in the declaration of a function, then don't panic.
# After this, the parameters(variables) are local.
# If the norm is followed, it should not be "_", but some spaces.
# -----------
function main() {
set_const()
get_system_info()
add_repo()
run_old_edition()
}
# -----------
#[test]
function test() {
set_const()
# test_cmd_exists()
# test_check_cmd()
# test_alice_s_fruit()
test_file_existence()
}
# -----------
# Get system information.
#
# In this world, there exist are many operating systems.
# For example:
# [[OS]; ["Microsoft Windows"], ["Apple MacOS"], ["Linux distros"], ["*BSD$"], ["Redox"]]
#
# Q: Windows?
# Are you serious?
# A: Yes, windows can also run awk.
# As windows 8.1/10/11(22000.856) do not have `awk` pre-installed, it may be better to use other methods.
#
# Note: windows and mac are not supported at this time.
# But maybe one day I'll get it to support mac.
#
# ╭───┬───────────────╮
# │ # │ OS │
# ├───┼───────────────┤
# │ 0 │ Windows │
# │ 1 │ MacOS │
# │ 2 │ Linux distros │
# │ 3 │ *BSD$ │
# │ 4 │ Redox │
# ╰───┴───────────────╯
#
function get_system_info() {
uname_cmd = check_uname_cmd()
kernel_name = get_cmd_out(uname_cmd ",-s")
# get os name and set OS["name"], OS["family"], etc.
get_os_name(uname_cmd, kernel_name)
# set I18N["lang"], I18N["region"], etc.
get_os_language()
# set ARCH["deb"] and ARCH["llvm"]
# To be honest, there is little use in getting the architecture before the edition 2022 is completed.
# There is always a need to look ahead and there is nothing wrong with being prepared in advance.
get_architecture(uname_cmd)
}
# -----------
function check_uname_cmd(_, uname_cmd) {
uname_cmd = (check_cmd("uname"))? "uname": (check_cmd("busybox", "uname,-s"))? "busybox uname": NONE
# [[OS, pkg]; ["Debian GNU/Linux", coreutils] [Windows, busybox]]
if (is_empty(uname_cmd)) {
print sty["cyan"]
print "╭───┬──────────────────┬───────────╮"
print "│ # │ OS │ pkg │"
print "├───┼──────────────────┼───────────┤"
print "│ 0 │ Debian GNU/Linux │ coreutils │"
print "│ 1 │ Windows │ busybox │"
print "╰───┴──────────────────┴───────────╯" sty[0]
print sty["green"] "`uname`", sty["yellow"] "is used to detect kernel information.\n",
sty["blue"] "For Linux distros such as", sty["magenta"] "Debian GNU/Linux" sty[0] ",", sty["cyan"] "you can install", sty["green"] "`coreutils`.\n",
sty["yellow"] "For", sty["blue"] "Windows" sty[0] ",", sty["cyan"] "you can use", sty["green"] "busybox.\n" sty[0]
exit 127
}
return uname_cmd
}
# -----------
# Get OS name
#
# Example
#
# ```awk
# uu = "uname"
#
# kernel = get_cmd_out(uu ",-s")
# get_os_name(uu, kernel)
#
# print OS["name"], OS["family"]
# ```
#
function get_os_name(uname_cmd, kernel_name, _, k, os_name) {
# [[OS, "uname -a"]; ["Windows", "Windows_NT MOE 10.0 22000 x86_64 MS/Windows"] ["Debian GNU/Linux", "Linux nuc 5.18.0-3-amd64 #1 SMP PREEMPT_DYNAMIC Debian 5.18.14-1 (2022-07-23) x86_64 GNU/Linux"]]
#
# ╭───┬──────────────────┬────────────────────────────────────╮
# │ # │ OS │ uname -a │
# ├───┼──────────────────┼────────────────────────────────────┤
# │ 0 │ Windows │ Windows_NT MOE 10.0 22000 x86_64 │
# │ │ │ MS/Windows │
# │ 1 │ Debian GNU/Linux │ Linux nuc 5.18.0-3-amd64 #1 SMP │
# │ │ │ PREEMPT_DYNAMIC Debian 5.18.14-1 │
# │ │ │ (2022-07-23) x86_64 GNU/Linux │
# ╰───┴──────────────────┴────────────────────────────────────╯
#
# [[OS,"Kernel Name"]; [linux, Linux] [mac, Darwin] [win, "Windows_NT|MINGW.*|MSYS.*|CYGWIN.*"] [freebsd, FreeBSD] [netbsd, NetBSD] [dragonfly, DragonFly] [sunos, SunOS]]
#
# ╭───┬───────────┬────────────────────────────────────╮
# │ # │ OS │ Kernel Name │
# ├───┼───────────┼────────────────────────────────────┤
# │ 0 │ linux │ Linux │
# │ 1 │ mac │ Darwin │
# │ 2 │ win │ Windows_NT|MINGW.*|MSYS.*|CYGWIN.* │
# │ 3 │ freebsd │ FreeBSD │
# │ 4 │ netbsd │ NetBSD │
# │ 5 │ dragonfly │ DragonFly │
# │ 6 │ sunos │ SunOS │
# ╰───┴───────────┴────────────────────────────────────╯
#
# to lower case
k = tolower(kernel_name)
# os_name = (k ~ /linux/)?
# "linux":
# (k ~ /darwin/)?
# "mac":
# (k ~ /windows_nt|cygwin|m(ingw|sys)/)?
# "win":
# (k ~ /dragonfly|(net|free)bsd|sunos/)?
# k:
# NONE
# Warning: mawk(1.3.4 20200120) uses the above statement with a "syntax error at or near :", but busybox awk does not.
# It needs to be combined into one line.
if (k ~ /linux/)
os_name = "linux"
else if (k ~ /darwin/)
os_name = "mac"
else if (k ~ /windows_nt|cygwin|m(ingw|sys)/)
os_name = "win"
else if (k ~ /dragonfly|(net|free)bsd|sunos/)
os_name = k
if (is_empty(os_name)) {
print sty["red"] "Unfortunately,", sty["yellow"] "it does", sty["magenta"] "not support", sty["blue"] "your system.", "\n",
sty["cyan"] "kernel name:", sty["green"] kernel_name, "\n",
sty["blue"] "Welcome to report this issue" sty[0]
exit 1
}
# OS["family"] = "ubuntu"
# OS["family2"] = "debian"
# OS["env"] = gnu / musl
OS["target-family"] = (os_name == "win")? "windows": "unix"
OS["kernel"] = kernel_name
OS["name"] = OS["family0"] = os_name
parse_os_name(uname_cmd, os_name, OS)
#[test]
# for (i in OS)
# print "debug::get_os_name, key:", i, "v:", OS[i]
}
# -----------
# parse_os_name(os_name: string, os: array)
function parse_os_name(uname_cmd, os_name, os, _, os_lower, release, release_file) {
# TODO: set OS["version"] & OS["code"]
# debian: OS["version"] = 12, OS["code"] = "bookworm"
# windows: OS["version"] = 11, OS["full_version"] = "22000.856"
if (os_name ~ /sunos|linux/) {
release_file = "/etc/os-release"
os_lower = tolower(get_cmd_out(uname_cmd ",-o"))
os["name"] = (os_lower == "android")? "android": (os_lower == "illumos")? "illum": os_name
}
if (os_name == "linux" && is_file_exists(release_file)) {
collect_to_arr(release_file, "=", release)
#[test]
# for (i in release)
# print "k:", i, "v:", release[i]
# print dequotes(release["PRETTY_NAME"])
if ("ID" in release)
os["name"] = os["family"] = dequotes(release["ID"])
# [["OS", ID_LIKE]; [kali, debian] [mint, ubuntu] [lmde, debian]]
#
# ╭───┬──────┬─────────╮
# │ # │ OS │ ID_LIKE │
# ├───┼──────┼─────────┤
# │ 0 │ kali │ debian │
# │ 1 │ mint │ ubuntu │
# │ 2 │ lmde │ debian │
# ╰───┴──────┴─────────╯
#
if ("ID_LIKE" in release)
os["family2"] = dequotes(release["ID_LIKE"])
}
}
# -----------
# Please do not declare `lang` local variables in this function
# It comes from the user passed in `-v lang=xx-yy`
#
function get_os_language(_, cmd, full, language) {
cmd = "getprop"
# Default locale: en_us
I18N["lang"] = "en"
I18N["region"] = "us"
# `lang` from user incoming data
# awk -f a.awk -v lang=en_us
if (!is_empty(lang) && lang ~ /[_-]/)
full = lang
else if (OS["name"] == "android" && check_cmd(cmd))
full = get_cmd_out(cmd ",persist.sys.locale")
else if (OS["name"] == "win")
full = get_cmd_out("powershell,-NoProfile,'Get-UICulture|select -ExpandProperty Name'")
else
full = ENVIRON["LANG"]
language = trim(tolower(full))
if (!is_empty(language))
parse_os_language(language, I18N)
#[test]
# key: lang v: en
# key: region v: us
# key: encoding v: utf-8
# a.awk -v lang=zh-cmn_hans_cn.utf-8
# key: script v: hans
# key: ext v: cmn
# key: lang v: zh
# key: region v: cn
# key: encoding v: utf-8
#
# for (i in I18N) {
# # print "debug::get_os_language",
# print "key:", i, "\tv:", I18N[i]
# }
}
# -----------
#
# [[src, result]; ["en_us.utf-8", 'lang: en, region: us, encoding: utf-8'], ["en_us", 'lang: en, region: us'], ["en-US", 'lang: en, region: us'], ["zh-Hans-CN", 'lang: zh, script: hans, region: cn'] ["zh-yue-Hant_hk", 'lang: zh, ext: yue, script: hant, region: hk']]
#
# ╭───┬────────────────┬──────────────────────────────────────────────╮
# │ # │ src │ result │
# ├───┼────────────────┼──────────────────────────────────────────────┤
# │ 0 │ en_us.utf-8 │ lang: en, region: us, encoding: utf-8 │
# │ 1 │ en_us │ lang: en, region: us │
# │ 2 │ en-US │ lang: en, region: us │
# │ 3 │ zh-Hans-CN │ lang: zh, script: hans, region: cn │
# │ 4 │ zh-yue-Hant_hk │ lang: zh, ext: yue, script: hant, region: hk │
# ╰───┴────────────────┴──────────────────────────────────────────────╯
#
# parse_os_language(lang: string, i18n: array)
function parse_os_language(lang, i18n, _, lang_arr1, lang_arr1_len, lang_arr2, lang_arr2_len, lang_spec, v) {
lang_arr1_len = split(lang, lang_arr1, ".")
if (lang_arr1_len == 2)
i18n["encoding"] = lang_arr1[2]
lang_arr2_len = split(lang_arr1[1], lang_arr2, /[_-]/)
i18n["lang"] = lang_arr2[1]
# language-extlang-script-region-variant-extension-privateuse
# [[Type, Construction, Standard]; [language, "(2 or 3) alpha[a-z]", "ISO639-[1,2,3,5]"], [extlang, "3 alpha", ISO639-3], [script, "4 alpha[A-Z]{1}[a-z]{3}", ISO15924], [region, "2 alpha[A-Z] or 3 digit", "ISO3166-1_alpha-2 or UNM.49"], [variant, "([5-8] alphanum) or (1 digit 3 alphanum)", "IANA language subtag registry?"]]
# https://www.rfc-editor.org/info/bcp47
# https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
#
# ╭───┬──────────┬──────────────────────────┬─────────────────────────╮
# │ # │ Type │ Construction │ Standard │
# ├───┼──────────┼──────────────────────────┼─────────────────────────┤
# │ 0 │ language │ (2 or 3) alpha │ ISO639-[1,2,3,5] │
# │ 1 │ extlang │ 3 alpha │ ISO639-3 │
# │ 2 │ script │ 4 alpha │ ISO15924 │
# │ 3 │ region │ 2 alpha or 3 digit │ ISO3166-1_alpha-2 or │
# │ │ │ │ UNM.49 │
# │ 4 │ variant │ ([5-8] alphanum) or (1 │ IANA language subtag │
# │ │ │ digit 3 alphanum) │ registry? │
# ╰───┴──────────┴──────────────────────────┴─────────────────────────╯
# Language specification array
split("lang,ext,script,region,variant,extension,privateuse", lang_spec, ",")
# Note: Only the first 4 types are parsed. Since the first one is always lang, only [ext, script, region] are parsed next.
# The hashmap or array of region code(UNM.49) is not defined in this awk program, so it does not automatically convert "UNM.49" to "ISO3166-1_alpha-2"
for (i = 2; i <= lang_arr2_len; ++i) {
v = lang_arr2[i]
is_i18n_extlang(v, i18n) || is_i18n_script(v, i18n) || is_i18n_region(v, i18n)
}
# Do not use `(! "script" in i18n)`
if (("region" in i18n) && (i18n["lang"] == "zh") && (is_empty(i18n["script"])))
i18n["script"] = (i18n["region"] ~ /cn|sg|my/)? "hans": "hant"
}
# -----------
# Warning: mawk (1.3.4 20200120) uses such regular expression (/[0-9a-z]{5,8}/) with error
function is_i18n_region(two_a_or_3d, a_map) {
# [a-z]{2} | [0-9]{3}
if (two_a_or_3d ~ /^[a-z][a-z]$|^[0-9][0-9][0-9]$/){
a_map["region"] = two_a_or_3d
return true
}
return false
}
function is_i18n_script(four_a, a_map){
# [a-z]{4}
if (four_a ~ /^[a-z][a-z][a-z][a-z]$/){
a_map["script"] = four_a
return true
}
return false
}
function is_i18n_extlang(three_a, a_map){
# [a-z]{3}
if (three_a ~ /^[a-z][a-z][a-z]$/){
a_map["ext"] = three_a
return true
}
return false
}
# -----------
function add_repo(_, gpgv_version) {
if ((OS["family2"] ~ /debian|ubuntu/ || OS["family" == "debian"]) && check_cmd("gpgv")) {
# [[sysver, "gpgv version"]; [bionic, "2.2.4-1ubuntu1.6"] [buster, "2.2.12-1+deb10u2"]]
#
# ╭───┬────────┬──────────────────╮
# │ # │ sysver │ gpgv version │
# ├───┼────────┼──────────────────┤
# │ 0 │ bionic │ 2.2.4-1ubuntu1.6 │
# │ 1 │ buster │ 2.2.12-1+deb10u2 │
# ╰───┴────────┴──────────────────╯
#
gpgv_version = parse_cmd_out("dpkg-query,-s,gpgv", "^Version", ":" SPACE)
if (semver_comparator(gpgv_version, "<", "2.0.0")) {
# TODO: if I18N["lang"] == "zh", then print Chinese
print sty["cyan"] "gpgv version :", sty["green"] gpgv_version,
sty["red"] "\nSorry,", sty["blue"] "the gpgv version is lower than", sty["yellow"] "2.0",
sty["cyan"] "\nSupport for", sty["underline"] sty["yellow"] "Curve25519/Ed25519",sty["not underlined"] sty["magenta"] "may not be perfect" sty[0] "\n"
print "Warning! Your system will not be able to add the related repo" > STDERR
}
}
# TODO: download deb file and install pkg
# [[Step, Command]; ["download deb", "curl -LO https://l.tmoe.me/neko.deb"] ["install deb as root", "sudo apt install ./neko.deb"] ["update index", "sudo apt update"] ["install tmm", "sudo apt install tmm"]]
#
# ╭───┬─────────────────────┬─────────────────────────────────────╮
# │ # │ Step │ Command │
# ├───┼─────────────────────┼─────────────────────────────────────┤
# │ 0 │ download deb │ curl -LO https://l.tmoe.me/neko.deb │
# │ 1 │ install deb as root │ sudo apt install ./neko.deb │
# │ 2 │ update index │ sudo apt update │
# ╰───┴─────────────────────┴─────────────────────────────────────╯
}
# -----------
# Comparison of version numbers.
#
# Example
# ```awk
# a = "1.10.0"
# b = "1.9.2"
# op = ">"
# aa = semver_comparator(a, op, b)
# print_bool(aa)
# # stdout: true
# bb = semver_comparator("1.5.12-alpha.2", "<", "1.5.12-beta.1")
# if (bb)
# print "1.5.12-alpha.2 is lower than 1.5.12-beta.1"
# ```
# semver_comparator(lhs: string, op: string, rhs: string) -> bool
function semver_comparator(lhs, op, rhs, _, m_arr, m_arr_len, arr_len, n_arr, n_arr_len, i) {
m_arr_len = split(lhs , m_arr, "[-.]")
n_arr_len = split(rhs, n_arr, "[-.]")
arr_len = (m_arr_len > n_arr_len)? m_arr_len: n_arr_len
for (i = 1; i <= arr_len; ++i) {
m_arr["op"] = (m_arr[i] > n_arr[i])? ">": (m_arr[i] < n_arr[i])? "<": "="
if (m_arr["op"] != "=")
break
}
op_clone = op
sub("=", NONE, op_clone)
#[test]
# print a_arr["op"], op, op_clone
return (op == m_arr["op"])? true: (op_clone == m_arr["op"])? true: false
}
# -----------
function set_git_uri(git, uri, _, a_map, opt) {
git["hub"] = "2moe/tmoe"
git["ee"] = "mo2/linux"
git["branch"] = "master"
git["manager_file"] = "share/old-version/share/app/manager"
uri["branch"] = git["branch"] "/"
uri["protocol"] = "https://"
uri["ee_base"] = "gitee.com/"
uri["ee_raw"] = "/raw/"
uri["gh_raw"] = "raw.githubusercontent.com/"
uri["js_gh_base"] = "gcore.jsdelivr.net/gh/"
uri["gitee"] = uri["protocol"] uri["ee_base"] git["ee"] uri["ee_raw"] uri["branch"] git["manager_file"]
uri["github"] = uri["protocol"] uri["gh_raw"] git["hub"] "/" uri["branch"] git["manager_file"]
uri["jscdn"] = uri["protocol"] uri["js_gh_base"] git["hub"] "@" uri["branch"] git["manager_file"]
y_n = coloured_y_n(true)
# mawk -f ./a.awk -v net_node=gh => net_node
if (is_empty(net_node)) {
# print I18N["region"]
print sty["_"] "gitee" sty["/_"] " or " sty["_"] "github" sty["/_"] ":"
if (I18N["region"] ~ /cn|tw|hk|mo/) {
a_map["ext", "zh"] = "script"
a_map["fallback", "zh"] = "hans"
a_map["choose_gitee", "zh" "hans"] = "直接按回车键选择 gitee"
a_map["choose_gitee", "zh" "hant"] = "直接按回車鍵選擇 gitee"
a_map["choose_github", "zh" "hans"] = "输入n 再按回车选择 github"
a_map["choose_github", "zh" "hant"] = "輸入n 再按回車選擇 github"
# get_i18n("choose_gitee", a_map)
# ╭───┬───────┬────────┬───────────────────────────╮
# │ # │ Opt │ Src │ Description │
# ├───┼───────┼────────┼───────────────────────────┤
# │ 0 │ y │ gitee │ 直接按回車鍵選擇 gitee │
# │ 1 │ n │ github │ 輸入n 再按回車選擇 github │
# ╰───┴───────┴────────┴───────────────────────────╯
# 地區: hk/mo/tw
# 是否從 gitee 獲取相關檔案? [Y/n]
# ╭───┬───────┬────────┬───────────────────────────╮
# │ # │ Opt │ Src │ Description │
# ├───┼───────┼────────┼───────────────────────────┤
# │ 0 │ y │ gitee │ 直接按回车键选择 gitee │
# │ 1 │ n │ github │ 输入n 再按回车选择 github │
# ╰───┴───────┴────────┴───────────────────────────╯
# 地区: cn
# 是否从 gitee 获取相关文件? [Y/n]
print sty["cyan"] "╭───┬" sty["blue"] "──────" sty ["cyan"] "─┬─" sty["cyan"] "──────" sty["cyan"] "─┬" sty["yellow"] "───────────────────────────" sty["yellow"] "╮"
print sty["cyan"] "│ # │" sty["blue"] " Opt " sty ["cyan"] " │ " sty["cyan"] " Src " sty["cyan"] " │" sty["yellow"] " Description " sty["yellow"] "│"
print sty["cyan"] "├───┼" sty["blue"] "──────" sty ["cyan"] "─┼─" sty["cyan"] "──────" sty["cyan"] "─┼" sty["yellow"] "───────────────────────────" sty["yellow"] "┤"
print sty["cyan"] "│ 0 │" sty["green"] " y " sty ["cyan"] " │ " sty["green"] "gitee " sty["cyan"] " │" sty["green"] " "get_i18n("choose_gitee", a_map)" " sty["yellow"] "│"
print sty["cyan"] "│ 1 │" sty["magenta"] " n " sty ["cyan"] " │ " sty["magenta"] "github" sty["cyan"] " │" sty["magenta"] " "get_i18n("choose_github", a_map)" " sty["yellow"] "│"
print sty["cyan"] "╰───┴" sty["blue"] "──────" sty ["cyan"] "─┴─" sty["cyan"] "──────" sty["cyan"] "─┴" sty["yellow"] "───────────────────────────" sty["yellow"] "╯"
print sty[0]
a_map["region", "zh" "hans"] = "地区"
a_map["region", "zh" "hant"] = "地區"
a_map["from", "zh" "hans"] = "是否从"
a_map["from", "zh" "hant"] = "是否從"
a_map["get_file", "zh" "hans"] = "获取相关文件"
a_map["get_file", "zh" "hant"] = "獲取相關檔案"
# print get_i18n("region", a_map)
print sty["yl"] get_i18n("region", a_map) ": " sty["b"] sty["green"] I18N["region"] sty["/b"]
print sty["bu"] get_i18n("from", a_map) SPACE sty["u"] sty["cyan"] "gitee" sty[0] sty["yellow"] SPACE get_i18n("get_file", a_map) sty["default"] "?", y_n
print sty["bu"] "Do you want to" sty["yl"] " get it" sty["bu"] " from " sty["u"] sty["cyan"]"gitee" sty[0] "?", y_n
opt = tolower(read_to_string(STDIN))
uri["current"] = (opt ~ /^n/)? uri["github"]: uri["gitee"]
} else {
# [[Input, Src, Description]; ["y", github, "Press Enter or type y to choose github"] ["n", gitee, "Type n to choose gitee"]]
# ╭───┬───────┬────────┬────────────────────────────────────────╮
# │ # │ Opt │ Src │ Description │
# ├───┼───────┼────────┼────────────────────────────────────────┤
# │ 0 │ y │ github │ Press Enter or type y to choose github │
# │ 1 │ n │ gitee │ Type n to choose gitee │
# ╰───┴───────┴────────┴────────────────────────────────────────╯
#
print sty["cyan"] "╭───┬" sty["blue"] "───────" sty["cyan"] "┬" sty["cyan"] "────────" sty["yellow"] "┬" sty["yellow"] "────────────────────────────────────────" sty["yellow"] "╮"
print sty["cyan"] "│ # │" sty["blue"] " Opt " sty["cyan"] "│" sty["cyan"] " Src " sty["yellow"] "│" sty["yellow"] " Description " sty["yellow"] "│"
print sty["cyan"] "├───┼" sty["blue"] "───────" sty["cyan"] "┼" sty["cyan"] "────────" sty["yellow"] "┼" sty["yellow"] "────────────────────────────────────────" sty["yellow"] "┤"
print sty["cyan"] "│ 0 │" sty["green"] " y " sty["cyan"] "│" sty["green"] " github " sty["yellow"] "│" sty["green"] " Press Enter or type y to choose github " sty["yellow"] "│"
print sty["cyan"] "│ 1 │" sty["magenta"] " n " sty["cyan"] "│" sty["magenta"] " gitee " sty["yellow"] "│"sty["magenta"] " Type n to choose gitee " sty["yellow"] "│"
print sty["cyan"] "╰───┴" sty["blue"] "───────" sty["cyan"] "┴" sty["cyan"] "────────" sty["yellow"] "┴" sty["yellow"] "────────────────────────────────────────" sty["yellow"] "╯"
print sty[0] "Do you want to" sty["yellow"] " get it" sty["blue"] " from " sty["underline"] sty["cyan"]"github" sty[0] "?", y_n
opt = read_to_string(STDIN)
uri["current"] = (opt ~ /^n/)? uri["gitee"]: uri["github"]
}
} else {
uri["current"] = (net_node ~ /github|hub|gh/)? uri["github"]: uri["gitee"]
}
# uri["num_of_fallback"] = 1
uri["fallback"] = uri["jscdn"]
}
# -----------
# This function was written before I wrote `get_i18n()`.
# To rewrite it, call `get_i18n()`
function about_y_or_n(_, amap) {
# Not yet ready to support i18n, so only `en` and `zh` are available.
#
# amap["option", "en"] = "Options"
amap["option", "zh", "hans"] = "选项"
amap["option", "zh", "hant"] = "選項"
# amap["desc", "en"] = "Description"
amap["desc", "zh", "hans"] = amap["desc", "zh", "hant"] = "描述"
# amap["default_is_yes", "en"] = "Default is yes"
# amap["default_is_no", "en"] = "Default is no"
amap["default_is_yes", "zh", "hans"] = "默认为yes"
amap["default_is_yes", "zh", "hant"] = "默認爲yes"
amap["default_is_no", "zh", "hans"] = "默认为no"
amap["default_is_no", "zh", "hant"] = "默認爲no"
# amap["press_enter", "en"] = "Press Enter"
# amap["type_n_press_enter", "en"] = "Type n and press Enter"
# amap["type_y_press_enter", "en"] = "Type y and press Enter"
amap["press_enter", "zh", "hans"] = "直接按回车键"
amap["type_n_press_enter", "zh", "hans"] = "先输入n,再按回车"
amap["type_y_press_enter", "zh", "hans"] = "先输入y,再按回车"
amap["press_enter", "zh", "hant"] = "直接按回車鍵"
amap["type_n_press_enter", "zh", "hant"] = "先輸入n,再按回車"
amap["type_y_press_enter", "zh", "hant"] = "先輸入y,再按回車"
# style:
# [[index, A, B, C] [cn, blue, cyan, yellow]]
# [[Option, Description, yes, no]; ["[Y/n]","Default is yes", "Press Enter", "Type n and press Enter" ] , ["[y/N]","Default is no", "Type y and press Enter", "Press Enter"]]
# [[选项, 描述, yes, no]; ["[Y/n]","默认是yes", "直接按回车键", "先输入n,再按回车" ] , ["[y/N]","默认是no", "先输入y,再按回车", "直接按回车键"]]
# amap["type_n_press_enter", I18N["lang"], I18N["script"]]
#
# ╭───┬────────┬────────────────┬────────────────────────┬────────────────────────╮
# │ # │ Options│ Description │ yes │ no │
# ├───┼────────┼────────────────┼────────────────────────┼────────────────────────┤
# │ 0 │ [Y/n] │ Default is yes │ Press Enter │ Type n and press Enter │
# │ 1 │ [y/N] │ Default is no │ Type y and press Enter │ Press Enter │
# ╰───┴────────┴────────────────┴────────────────────────┴────────────────────────╯
#
if (I18N["lang"] == "zh") {
print sty["blue"] "关于 " coloured_y_n(true) ":"
print sty["blue"] "關於 " coloured_y_n(false) ":"
print sty["cn"] "╭───┬" sty["bu"] "───────┬" sty["yl"] "───────────┬" sty["cn"] "──────────────────┬" sty["mn"] "───────────────────╮"
print sty["cn"] "│ # │" sty["bu"] " "amap["option", I18N["lang"], I18N["script"]]" │" sty["yl"] " " amap["desc", I18N["lang"], I18N["script"]]" │" sty["cn"] " yes │" sty["mn"] " no │"
print sty["cn"] "├───┼" sty["bu"] "───────┼" sty["yl"] "───────────┼" sty["cn"] "──────────────────┼" sty["mn"] "───────────────────┤"
print sty["cn"] "│ 0 │" sty["bu"] " " coloured_y_n(true) " │" sty["gn"] " " amap["default_is_yes", I18N["lang"], I18N["script"]] sty["yl"] " │" sty["gn"] " " amap["press_enter", I18N["lang"], I18N["script"]] sty["cn"]" │" sty["mn"] " " amap["type_n_press_enter", I18N["lang"], I18N["script"]] " │"
print sty["cn"] "│ 1 │" sty["bu"] " " coloured_y_n(false) " │" sty["yl"] " " amap["default_is_no", I18N["lang"], I18N["script"]] sty["yl"] " │" sty["mn"] " " amap["type_y_press_enter", I18N["lang"], I18N["script"]] sty["cn"]" │" sty["gn"] " " amap["press_enter", I18N["lang"], I18N["script"]] sty["mn"]" │"
print sty["cn"] "╰───┴" sty["bu"] "───────┴" sty["yl"] "───────────┴" sty["cn"] "──────────────────┴" sty["mn"] "───────────────────╯"
} else {
print sty["cyan"] "About " coloured_y_n(true) " & " coloured_y_n(false) ":"
print sty["cn"] "╭───┬" sty["bu"] "────────┬" sty["yl"] "───────────────┬" sty["cn"] "───────────────┬" sty["mn"] "──────────────╮"
print sty["cn"] "│ # │" sty["bu"] " Options│" sty["yl"] " Description │" sty["cn"] " yes │" sty["mn"] " no │"
print sty["cn"] "├───┼" sty["bu"] "────────┼" sty["yl"] "───────────────┼" sty["cn"] "───────────────┼" sty["mn"] "──────────────┤"
print sty["cn"] "│ 0 │" sty["bu"] " " coloured_y_n(true) " │" sty["gn"] " Default is │" sty["gn"] " Press Enter │" sty["mn"] " Type n and │"
print sty["cn"] "│ │" sty["bu"] " │" sty["gn"] " yes │" sty["cn"] " │" sty["mn"] " press Enter │"
print sty["cn"] "│ 1 │" sty["bu"] " " coloured_y_n(false) " │" sty["yl"] " Default is no │" sty["mn"] " Type y and │" sty["gn"] " Press Enter │"
print sty["cn"] "│ │" sty["bu"] " │" sty["yl"] " │" sty["mn"] " press Enter │" sty["mn"] " │"
print sty["cn"] "╰───┴" sty["bu"] "────────┴" sty["yl"] "───────────────┴" sty["cn"] "───────────────┴" sty["mn"] "──────────────╯"
}
}
function coloured_y_n(y) {
if (y)
return sty["0"] sty["cn"] "[" sty["gn"] sty["b"] sty["u"] "Y" sty["/u"] sty["/b"] sty["bu"] sty["faint"] "/" sty["/b"] sty["_"] sty["mn"] "n" sty["/_"] sty["cn"] "]" sty["0"]
else
return sty["0"] sty["cn"] "[" sty["mn"] sty["_"] "y" sty["/_"] sty["bu"] sty["faint"] "/" sty["/b"] sty["gn"] sty["b"] sty["u"] "N" sty["/u"] sty["/b"] sty["cn"] "]" sty["0"]
}
# -----------
function run_old_edition(_, home_dir, dl_status, file1, file2) {
# net_node: gitee, github
# -v lang=zh-cn \
# -v net_node="gh" \
# -v tmp_dir="/tmp" \
home_dir = ENVIRON["HOME"]
if (is_empty(home_dir))
home_dir = ENVIRON["HOMEPATH"]
GIT["manager_file"] = "share/old-version/share/app/manager"
GIT["dir"] = home_dir "/.local/share/tmoe-linux/git"
GIT["dir2"] = "/usr/local/etc/tmoe-linux/git"
file1 = GIT["dir"] "/" GIT["manager_file"]
file2 = GIT["dir2"] "/" GIT["manager_file"]
run_old_file(file1, file2)
print_sys_info()
about_y_or_n()
if (!do_you_want_to_continue(true))
exit 0
about_new_and_old_edition()
set_git_uri(GIT, URI)
#[test]
# print "debug::run_old_version,", URI["gitee"], "\n", URI["github"], "\n", URI["jscdn"], "\n"
# print net_node, tmp_dir
# default
TMP["file"] = NONE
set_tmp_dir(TMP, home_dir)
print sty["yl"] TMP["file"] "\n"
dl_status = get_file(URI["current"], URI["fallback"], TMP["file"])
# print_bool(dl_status())
if (dl_status) {
run_old_file(TMP["file"], file1)
exit 0
} else {
exit 1
}
}
# -----------
function about_new_and_old_edition() {
# [[Step, Command]; ["download neko repo", "wget https://l.tmoe.me/neko.deb"] ["install deb as root", "sudo apt install ./neko.deb"] ["update index", "sudo apt update"] ["install tmm", "sudo apt install tmm"] ["remove deb file", "rm neko.deb"] ]
print sty["de"] sty[1] "Perphaps one day, the new edition will be installed by the following steps below:" sty[0]
print sty["cn"] "╭───┬─"sty["cn"] "───────────────────" sty["cn"] "─┬" sty["yl"] "─────────────────────────────────" sty["yl"]"╮"
print sty["cn"] "│ # │ "sty["cn"] " Step " sty["cn"] " │" sty["yl"] " Command " sty["yl"]"│"
print sty["cn"] "├───┼─"sty["cn"] "───────────────────" sty["cn"] "─┼" sty["yl"] "─────────────────────────────────" sty["yl"]"┤"
print sty["cn"] "│ 0 │ "sty["gn"] "download neko repo " sty["cn"] " │" sty["gn"] " wget https://l.tmoe.me/neko.deb " sty["yl"]"│"
print sty["cn"] "│ 1 │ "sty["mn"] "install deb as root" sty["cn"] " │" sty["mn"] " sudo apt install ./neko.deb " sty["yl"]"│"
print sty["cn"] "│ 2 │ "sty["bu"] "update index " sty["cn"] " │" sty["bu"] " sudo apt update " sty["yl"]"│"
print sty["cn"] "│ 3 │ "sty["yl"] "install tmm " sty["cn"] " │" sty["yl"] " sudo apt install tmm " sty["yl"]"│"
print sty["cn"] "│ 4 │ "sty["de"] "remove deb file " sty["cn"] " │" sty["de"] " rm neko.deb " sty["yl"]"│"
print sty["cn"] "╰───┴─"sty["cn"] "───────────────────" sty["cn"] "─┴" sty["yl"] "─────────────────────────────────" sty["yl"]"╯"
print sty[0]
print "However, it is still " sty["rd"] "the old edition." sty[0]
print "There are many, many illogical designs in the old edition. To be honest, I don't particularly recommend it."
print "You may have heard of it before, and I will rewrite it."
print "Before, you probably installed it with `master/debian.sh` or `2/2`. Now it's `2/2.awk`."
print "What you see now is written in awk."
print "This file is just used to guide you through the installation of tmm."
print "For the other tools, I should write it in another language."
print "To be honest, I really like rust."
print "But due to my poor knowledge of the underlying operating system, and my lack of familiarity with rust asynchronous and unsafe. So I'm not ready yet."
print sty["~"]"Perhaps I should rewrite it quickly in `nu` and then rewrite it again in `rust`." sty["/~"]
print "In fact, I don't have that much time."
print "I am sorry that I did not fulfil your expectations."
print "\n"
print "Enough about the new edition, let's get to know", sty["yl"]"the old one!"
print sty["bu"] sty["_"]"Section:", sty[0] "admin"
print sty["bu"] sty["_"]"Depends:", sty[0] "aria2 (>= 1.30.0), binutils (>= 2.28-5), coreutils (>= 8.26-3), curl (>= 7.52.1-5), findutils (>= 4.6.0), git (>= 1:2.11.0-3), grep, lsof (>= 4.89), micro (>= 2.0.6-2) | nano (>= 2.7.4-1), proot (>= 5.1.0), procps (>= 2:3.3.12), sed, sudo (>= 1.8.19p1-2.1), tar (>= 1.29b-1.1), util-linux (>= 2.29.2-1), whiptail (>= 0.52.19), xz-utils (>= 5.2.2), zstd (>= 1.1.2)"
print sty["bu"] sty["_"]"Recommends:", sty[0] "bat, debootstrap, eatmydata, gzip, less, lz4, pulseaudio, pv, qemu-user-static, systemd-container"
print sty["bu"] sty["_"]"Suggests:", sty[0] " busybox, zsh"
print sty["bu"] sty["_"]"Homepage:", sty[0] " https://github.com/2moe/tmoe"
print sty["bu"] sty["_"]"Tag:", sty[0] "interface::TODO, interface::text-mode, system::cloud, system::virtual, role::program, works-with::archive, works-with::software:package, works-with::text"
print sty["bu"] sty["_"]"Description:", sty[0] "Easily manage containers and system. Just type `tmoe` to enjoy it."
print "\n"
print sty["gn"] "With this, I offer my " sty["bu"]"best wishes."
print sty["yl"] "Thank you for your choice and for running it."
print sty["yl"] "Thank you for being kind and lovely." sty["0"]
# print "\n"
print "I wish I could offer you a better service but unfortunately there are some current problems."
print "You can choose " sty["gn"] sty["u"]"no"sty[0] ", and I look forward to seeing you next time."
if (!do_you_want_to_continue(false)) {
print sty["cn"] "See you next time" sty[0]
exit 0
}
}
function print_sys_info() {
print sty["b"] sty["cn"] "OS info:" sty[0]
for (i in OS) {
if (!is_empty(OS[i]))
print sty["_"] sty["bu"] i ":", sty["/_"] sty["yl"] OS[i]
}
print "\n" sty["b"] sty["cn"] "Architecture:" sty[0]
for (i in ARCH)
print sty["_"] sty["gn"] i ":", sty["/_"] sty["yl"] ARCH[i]
print "\n" sty["b"] sty["cn"] "Locale:" sty[0]
for (i in I18N)
print sty["_"] sty["mn"] i ":", sty["/_"] sty["yl"] I18N[i]
print "\n"
}
# -----------
# do_you_want_to_continue(b: bool) -> bool
function do_you_want_to_continue(b, _, opt, a_map, y_n, language) {
language = I18N["lang"]
a_map["ext", language] = NONE
# English
a_map["do_you", "en"] = "Do you want to" SPACE
a_map["cont", "en"] = "continue?"
# Español
a_map["do_you", "es"] = "¿Quieres "
a_map["cont", "es"] = "continuar?"
# Português
a_map["ext", "pt"] = "region"
a_map["fallback", "pt"] = "pt"
# Portugal
a_map["do_you", "pt" "pt"] = "Quer "
a_map["cont", "pt" "pt"] = "continuar?"
# Brasil
a_map["do_you", "pt" "br"] = "Você quer "
# Deutsch
a_map["do_you", "de"] = "Möchten Sie "
a_map["cont", "de"] = "fortfahren?"
# polski
a_map["do_you", "pl"] = "Czy chcesz "
a_map["cont", "pl"] = "kontynuować?"
# 日本語
a_map["cont", "ja"] = "継続"
a_map["do_you", "ja"] = "しますか?"
# 한국어
a_map["cont", "ko"] = "계속하"
a_map["do_you", "ko"] = "시겠습니까?"
# čeština
a_map["do_you", "cs"] = "Chcete "
a_map["cont", "cs"] = "pokračovat?"
# eesti
a_map["do_you", "et"] = "Kas soovite "
a_map["cont", "et"] = "jätkata?"
# български
a_map["do_you", "bg"] = "Искате ли да "
a_map["cont", "bg"] = "продължите?"
# dansk
a_map["do_you", "da"] = "Ønsker du at "
a_map["cont", "da"] = "fortsætte?"
# latviešu
a_map["do_you", "lv"] = "Vai vēlaties "
a_map["cont", "lv"] = "turpināt?"
# română
a_map["do_you", "ro"] = "Vrei să "
a_map["cont", "ro"] = "continui?"
# magyar
a_map["do_you", "hu"] = "Akarod "
a_map["cont", "hu"] = "folytatni?"
# Tiếng Việt
a_map["do_you", "vi"] = "Bạn có muốn "
a_map["cont", "vi"] = "tiếp tục?"
# Indonesia
a_map["do_you", "id"] = "Apakah Anda ingin "
a_map["cont", "id"] = "melanjutkan?"
# українська
a_map["do_you", "uk"] = "Ви хочете "
a_map["cont", "uk"] = "продовжити?"
# ру́сский язы́к
a_map["do_you", "ru"] = "Вы хотите "
a_map["cont", "ru"] = "продолжить?"
# français
a_map["do_you", "fr"] = "Voulez-vous "
a_map["cont", "fr"] = "continuer?"
# বাংলা
a_map["do_you", "bn"] = "আপনি কি "
a_map["cont", "bn"] = "অবিরত করতে চান?"
# italiano
a_map["do_you", "it"] = "Vuoi "
a_map["cont", "it"] = "continuare?"
# svenska
a_map["do_you", "sv"] = "Vill du "
a_map["cont", "sv"] = "fortsätta?"
# suomi
a_map["do_you", "fi"] = "Haluatko "
a_map["cont", "fi"] = "jatkaa?"
# Nederlands
a_map["do_you", "nl"] = "Wil je "
a_map["cont", "nl"] = "doorgaan?"
# slovenčina
a_map["do_you", "sk"] = "Chcete "
a_map["cont", "sk"] = "pokračovať?"
# slovenščina
a_map["do_you", "sl"] = "Ali želite "
a_map["cont", "sl"] = "nadaljevati?"
# Türkçe
a_map["cont", "tr"] = "Devam "
a_map["do_you", "tr"] = "etmek istiyor musun?"
# Ελληνικά
a_map["do_you", "el"] = "Θέλετε να "
a_map["cont", "el"] = "συνεχίσετε;"
# 中文
a_map["ext", "zh"] = "script"
a_map["fallback", "zh"] = "hans"
a_map["do_you", "zh" "hans"] = "您要"
a_map["cont", "zh" "hant"] = "繼續嗎?"
a_map["cont", "zh" "hans"] = "继续吗?"
y_n = coloured_y_n(b)
# This message should not be printed in i18n, but in English.
# print sty["bu"] a_map["do_you", "en"] sty["yl"] a_map["cont", "en"], y_n
# print i18n data
# if (language != "en" && (!is_empty(get_i18n("do_you", a_map))))
# Now, if the relevant data does not exist, it will automatically fallback
if (language ~ /ja|ko|tr/)
print sty["yl"] get_i18n("cont", a_map) sty["bu"] get_i18n("do_you", a_map), y_n
else
print sty["bu"] get_i18n("do_you", a_map) sty["yl"] get_i18n("cont", a_map), y_n
opt = read_to_string(STDIN)
if (b)
return (opt ~ /^n|^N/)? false: true
else
return (opt ~ /^y|^Y/)? true: false
}
# -----------
# Get i18n data
#
# Example
#
# ```awk
# # set lang ext, of course, it can be empty.
# # You can set it to "region" or "script"
# a_map["ext", "en"] = "region"
#
# # Basic structure: [key, language ext]
# a_map["clr", "en" "gb"] = "colour"
# a_map["clr", "en" "us"] = "color"
# # Great, we've set up gb and us.
#
# # Let's see how get_i18n() works!
# key = "clr"
# value = get_i18n(key, a_map)
# print value
# # If your region is the GB, then it will print the word "colour"
#
# # Q: But my region is au, and we haven't set it up yet.
# # What should I do?
# # A: You need to set the fallback.
#
# # More commonly, you can think of it as having a default value stored inside.
# a_map["fallback", "en"] = "us"
#
# # If a_map["clr", "en" "au"] is empty, then it will get a_map["clr", "en" "us"]
# # Note: Prerequisite is a call to the get_i18n()
#
# # We can set a fallback for each language
# # e.g. a_map["fallback", "de"] = "de"
#
# # You can even set fallback for specific regional languages
# # e.g. Fallback for ca is us, and fallback for hk is gb
# a_map["fallback", "en" "ca"] = "us"
# a_map["fallback", "en" "hk"] = "gb"
# ```
#
function get_i18n(key, a_map, _, ext, language, value, fallback, region, fallback2, fallback0, map_ext) {
language = I18N["lang"]
map_ext = a_map["ext", language]
ext = a_map["ext"] = is_empty(map_ext)? NONE: I18N[map_ext]
value = a_map[key, language ext]
# Priority: fallback2 > fallback > fallback0
# [[fallback2, fallback, fallback0]; ["zh my => zh sg", "zh => zh cn", "zh cn => en"], ["If the key is pineapple. MY cannot find the value corresponding to this key, then it will fall back to SG. If found, return '黄梨'. If not found, fallback2 => fallback", "If fallback is cn for the zh language. hk => cn, mo => cn, tw => cn. If fallback2 has no value, then it is '菠萝' in fallback. If fallback has no value, fallback => fallback0", "At fallback0 there is no way back. Here, it is neither '黄梨' nor '菠萝', but pineapple"] ]
#
# ╭───┬─────────────────────┬────────────────────┬────────────────────╮
# │ # │ fallback2 │ fallback │ fallback0 │
# ├───┼─────────────────────┼────────────────────┼────────────────────┤
# │ 0 │ zh my => zh sg │ zh => zh cn │ zh cn => en │
# │ 1 │ If the key is │ If fallback is cn │ At fallback0 there │
# │ │ pineapple. MY │ for the zh │ is no way back. │
# │ │ cannot find the │ language. hk => │ Here, it is │
# │ │ value corresponding │ cn, mo => cn, tw │ neither '黄梨' nor │
# │ │ to this key, then │ => cn. If │ '菠萝', but │
# │ │ it will fall back │ fallback2 has no │ pineapple │
# │ │ to SG. If found, │ value, then it is │ │
# │ │ return '黄梨'. If │ '菠萝' in │ │
# │ │ not found, │ fallback. If │ │
# │ │ fallback2 => │ fallback has no │ │
# │ │ fallback │ value, fallback => │ │
# │ │ │ fallback0 │ │
# ╰───┴─────────────────────┴────────────────────┴────────────────────╯
#
if (is_empty(value)) {
fallback = a_map["fallback", language]
region = I18N["region"]
fallback2 = a_map["fallback", language region]
fallback0 = a_map["fallback"]
if (!is_empty(fallback2)) {
value = a_map[key, language fallback2]
if (!is_empty(value))
return value
}
if (!is_empty(fallback)) {
value = a_map[key, language fallback]
if (!is_empty(value))
return value
}
if (is_empty(fallback0))
fallback0 = "en"
return a_map[key, fallback0]
}
return value
}
# -----------
function run_old_file(file1, file2) {
if (!check_cmd("bash")) {
print sty["mn"] "Unfortunately, the new edition is not out yet.\n",
sty["yl"] "The old edition depends on bash, which I think was a mistake.\n",
sty["gn"] "Let's look forward to the new edition! See you soon."
exit 1
}
# print "debug::run_old_file" file1, file2
if (is_file_exists(file1)) {
if (!(match(read_to_string(file1), /TUI_BIN/))) {
git_dir = GIT["dir"]
if (match(git_dir, "/tmoe-linux/git") && is_file_exists(git_dir)) {
print "You have already installed an older version, which has serious problems and will be removed automatically. You will need to re-run this awk file."
print "Press enter to remove the old git dir"
rm_cmd = "rm -rfv" SPACE git_dir
print sty["rd"] rm_cmd sty[0]
if (do_you_want_to_continue(true)) {
system(rm_cmd)
print sty["mn"] "Please re-run this awk file" sty[0]
}
exit 1
}
}
if (system("bash" SPACE file1))
exit 1
else
exit 0
}
if (is_file_exists(file2)) {
if (system("bash" SPACE file2))
exit 1
else
exit 0
}
}
# -----------
function set_tmp_dir(tmp, home, _, tmp_env, cache_dir, tmp_arr, tmp_arr_len) {
if (check_cmd("mktemp")) {
tmp["file"] = get_cmd_out("mktemp")
tmp_arr_len = split(tmp["file"], tmp_arr, "/")
tmp["file0"] = tmp_arr[tmp_arr_len]
for (i = 2; i<= (tmp_arr_len - 1); ++i)
tmp["dir"] = (i == 2)? "/" tmp_arr[i]: tmp["dir"] "/" tmp_arr[i]
} else {
tmp_env = ENVIRON["TMPDIR"]
cache_dir = home "/.cache"
tmp["dir"] = (!is_empty(tmp_env))? tmp_env: (is_file_exists("/tmp"))? "/tmp": cache_dir
if (tmp["dir"] == cache_dir && (!is_file_exists(cache_dir))) {
if (system("mkdir -p" SPACE cache_dir)) {
print sty["red"] "Error!", sty["yellow"] "Since the", sty["blue"] "TMPDIR" sty["yellow"] "environment variable does not exist, the temporary directory is", sty["green"] cache_dir sty["magenta"] ", but it failed to be created." sty[0]
exit 1
}
}
tmp["file0"] = ".tmoe-old-version.sh"
tmp["file"] = tmp["dir"] "/" tmp["file0"]
}
# awk -f ./a.awk -v tmp_dir=/tmp
# `tmp_dir` from `-v` arg
if (!is_empty(tmp_dir) && tmp_dir ~ "/") {
tmp["dir"] = tmp_dir
tmp["file"] = (tmp_dir ~ "/$")? tmp["dir"] tmp["file0"]: tmp["dir"] "/" tmp["file0"]
# print "tmp_file:" tmp["file"]
}
}
# -----------
function get_file(uri, fallback, file) {
if (is_empty(DOWNLOADER)) {
print sty["red"] "Error!" sty["mn"] "No compatible downloader found" > STDERR
print sty["bu"] "Unfortunately, we did not find curl or wget on your system."
exit 1
}
if (DOWNLOADER == "curl") {
# If the exit status of the program is true, the loop is exited.
for (i = 0; i < 30; ++i) {
# !system => !(0) => true
if (!system("curl --compressed -L" SPACE uri SPACE "-o" SPACE file) > 0) {
return true
# break
} else {
print sty["red"] "Unknown curl Error! " > STDERR
print sty["yl"] "Trying again..." sty[0]
uri = fallback
}
}
}
if (DOWNLOADER == "wget") {
# !system => !(0) => true
for (i = 0; i < 20; ++i) {
if (!system("wget" SPACE uri SPACE "-O" SPACE file) > 0) {
return true
# break
} else {
print sty["red"] "wget is downloading files with errors, please check your ca-certificates." > STDERR
print sty["blue"] "The manual fix is a better solution than `-no-check-certificate`."
print sty["yl"] "Trying again..." sty[0]
uri = fallback
}
}
}
# (is_empty(downloader)):
return false
}
# -----------
# Check if the command exists with `WHICH_CMD`.
#
# [["Cmd Name", Usage, Result]; [uname, 'check_cmd("uname")', "true or false"]]
#
# ╭───┬──────────┬────────────────────┬───────────────╮
# │ # │ Cmd Name │ Usage │ Result │
# ├───┼──────────┼────────────────────┼───────────────┤
# │ 0 │ uname │ check_cmd("uname") │ true or false │
# ╰───┴──────────┴────────────────────┴───────────────╯
#
# What is the difference between check_cmd() and is_cmd_exists()?
#
# `A` and `B` are the former and `C` is the latter.
# A: check_cmd(n) => is_cmd_exists("command", ["-v", n]) -> bool
# B: check_cmd(n) => is_cmd_exists("which", [n]) -> bool
# C: is_cmd_exists(cmd, arg) -> bool
#
# Example
#
# ```awk
# WHICH_CMD = get_which_cmd()
# s = check_cmd("uname")
# if (s)
# print "Congratulations, `uname` already exists in your system"
#
# u = check_cmd("unknown_cmd", "--help")
# print_bool(u)
# # stdout: false
# ```
#
# opt_arg is optional, and it is not an array, but a string
# If the value is "-d,2,-b,3", and it will automatically slice into an array:
# ["-d", "2", "-b", "3"]
# i.e. arg[1] = "-d", arg[2] = "2"
# Note: It starts at 1, not 0
#
# check_cmd(cmd: string, opt_arg: string) -> bool
function check_cmd(cmd_name, opt_arg, _, cmd, arr_len, arg) {
# Is there a constant `WHICH_CMD`?
# cmd =
# No => cmd_name (it comes from the parameter)
# Yes, but opt_arg is not empty => cmd_name
# Yes => WHICH_CMD (and cmd_name => arg)
cmd = (is_empty(WHICH_CMD))? cmd_name: WHICH_CMD
# [[Cmd, Arg]; [command, "-v cmd_name"] [which, cmd_name] [type, cmd_name] [cmd_name, opt_arg]]
#
# ╭───┬──────────┬─────────────╮
# │ # │ Cmd │ Arg │
# ├───┼──────────┼─────────────┤
# │ 0 │ command │ -v cmd_name │
# │ 1 │ which │ cmd_name │
# │ 2 │ type │ cmd_name │
# │ 3 │ cmd_name │ opt_arg │
# ╰───┴──────────┴─────────────╯
#
arr_len = 0
# If opt_arg is empty and WHICH_CMD is not empty, then set the arg. e.g. (command, ["-v", cmd_name]), (type, [cmd_name])
if (is_empty(opt_arg)) {
opt_arg = "--help"
# set arg(array).
if (WHICH_CMD == "command")
arr_len = split("-v" SPACE cmd_name, arg, SPACE)
else if (WHICH_CMD ~ /type|which/)
arr_len = split(cmd_name, arg, ",")
}
# An implicit condition is included here (!is_empty(opt_arg))
# i.e. opt_arg is not empty and arr_len is 0
# [[Var, Value, Empty]; [arr_len, 0, false] [opt_arg, "?", false]]
# ╭───┬─────────┬───────┬───────╮
# │ # │ Var │ Value │ Empty │
# ├───┼─────────┼───────┼───────┤
# │ 0 │ arr_len │ 0 │ false │
# │ 1 │ opt_arg │ ? │ false │
# ╰───┴─────────┴───────┴───────╯
#
if (arr_len == 0) {
# The cmd variable will be forced to be overwritten.
cmd = cmd_name
arr_len = split(opt_arg, arg, ",")
}
# if arr_len is still 0, then there is an error.
if (arr_len == 0) {
print sty["red"] "Error!\n",
sty["yellow"] "{\n",
sty["magenta"] "Name:", sty["cyan"] "check_cmd()\n",
sty["magenta"] "Reason:", sty["cyan"] "The arr_len is 0.\n",
sty["magenta"] "Analysis:", sty["cyan"] "When you call check_cmd(), you may have passed in the wrong arguments.\n",
sty["yellow"] "}" sty[0] > STDERR
exit 1
}
# print "debug::check_cmd", "cmd_name:", cmd_name, "opt_arg:", opt_arg
# print "debug::check_cmd", "cmd:", cmd, "arg[1]:", arg[1], "arg[2]", arg[2]
return is_cmd_exists(cmd, arg, arr_len)
}
# -----------
# Use `!system()` to determine if the command exists.
#
# Compared to `check_cmd()`, `is_cmd_exists()` is more low-level.
#
# Some special awk distributions do not have `length(array)`
# So, `arr_len` is used here.
#
# is_cmd_exists(cmd: string, arg: array, arg_len: usize) -> bool
function is_cmd_exists(cmd, arg, arr_len, _, i) {
if (arr_len >= 1) {
# Since `split()` is used, it starts at 1 instead of 0 (i = 0; i < arg_len)
for (i = 1; i <= arr_len; ++i) {
# print "debug::is_cmd_exists, cmd: ", cmd, "arg: ", arg[i]
cmd = cmd SPACE arg[i]
}
}
# It's (!system()) not (system())
return (!system(cmd TO_NULL))
}
# -----------
# [[Name]; [command] [type] [which]]
#
# ╭───┬─────────╮
# │ # │ Name │
# ├───┼─────────┤
# │ 0 │ command │
# │ 1 │ type │
# │ 2 │ which │
# ╰───┴─────────╯
#
function get_which_cmd(_, i, cmd, arg, arr_len, cmd_arr1, cmd_arr1_len, cmd_arr2) {
cmd_arr1_len = split("command,type,which", cmd_arr1, ",")
# The value of cmd_arr1 becomes the key of cmd_arr2. This is an intentional design.
cmd_arr2[cmd_arr1[1]] = "-v,command"
# Assign value to cmd_arr2
for (i = 2; i <= cmd_arr1_len; ++i)
cmd_arr2[cmd_arr1[i]] = cmd_arr1[i]
# Generate a new array based on cmd_arr2 and call `is_cmd_exists()`
# [[Cmd, Arg]; [command, "-v command"] [type, type] [which, which]]
#
# ╭───┬─────────┬────────────╮
# │ # │ Cmd │ Arg │
# ├───┼─────────┼────────────┤
# │ 0 │ command │ -v command │
# │ 1 │ type │ type │
# │ 2 │ which │ which │
# ╰───┴─────────┴────────────╯
#
# Note: if (command -v command) has no errors, then return `command`, otherwise check `type` and `which`
#
for (i = 1; i <= cmd_arr1_len; ++i) {
cmd = cmd_arr1[i]
arr_len = split(cmd_arr2[cmd], arg, ",")
# print "debug::get_which_cmd, cmd: ", cmd, "arg[1]: ", arg[1]
if (is_cmd_exists(cmd, arg, arr_len)) {
return cmd
# break
}
}
# !(command|type|which):
return NONE
}
# -----------
# Use the output of the command as the return value
#
# Example
#
# ```awk
# b = get_cmd_out("mawk,-W,version")
# print b
# # stdout: mawk 1.3.4 20200120
# ```
#
# get_cmd_out(full_cmd: string) -> string
function get_cmd_out(full_cmd, _, arr, arr_len, out, cmd, i, v) {
arr_len = split(full_cmd, arr, ",")
for (i = 1; i <= arr_len; ++i)
cmd = cmd SPACE arr[i]
for (i = 0; (cmd | getline v) > 0; ++i)
out = (i != 0)? out "\n" v: v
close(cmd)
return out
}
# -----------
# Match the output of the command, and parse
#
# This is read on a row-by-row basis and if a match is made, subsequent content is not parsed further.
# If you want to parse all rows, use `collect_to_arr()`.
# Note: `parse_cmd_out()` will return a string, but `collect_to_arr()` will collect the parsed contents into an array.
#
# Example
#
# ```awk
# # arg1: full_cmd(comma separated), arg2: regex_str, arg3: field_separator
#
# ver = parse_cmd_out("dpkg-query,-s,gpgv", "^(V|v)er.*ion", ":" SPACE)
# print ver
# # stdout: 2.2.35-3
# # The source data are as follows:
# # Package: gpgv
# # Status: install ok installed
# # Section: utils
# # Source: gnupg2
# # Version: 2.2.35-3
# ```
#
# parse_cmd_out(full_cmd: string, regex_str: string, field_separator: string) -> string
function parse_cmd_out(full_cmd, regex_str, field_separator, _, arr, arr_len, out, cmd, i) {
# print "debug::parse_cmd_out,", "regex:", regex_str
arr_len = split(full_cmd, arr, ",")
for (i = 1; i <= arr_len; ++i)
cmd = cmd SPACE arr[i]
# Set FS, and `getline` will use it
old_fs = FS
FS = field_separator
while ((cmd | getline) > 0) {
if ($1 ~ regex_str) {
out = $2
break
}
}
FS = old_fs
close(cmd)
return out
}
# -----------
# Get data from stdin or text, and return string.
#
# If `f` is standard input (stdin) data, then this fn will automatically trim the extra spaces on the left and right sides, and return it.
# If `f` is a file, then this fn will collect it to a string.
#
# Example
#
# ```awk
# b = read_to_string("/etc/os-release")
# print b
# ```
#
# input(from stdin/file) -> output(string)
function read_to_string(f, _, v, i, out) {
if (f == STDIN) {
# print "Please input a string"
if ((getline out < f) <= 0) {
print "IO Error, unknown input data" > STDERR
exit 1
}
} else {
for (i = 0; (getline v < f) > 0; ++i)
out = (i != 0)? out "\n" v: v
# Do not `close("/dev/null")` manually. In mawk(1.3.4 20200120), it gets a segmentation fault.
close(f)
}
return (f == STDIN)? trim(out): out
}
# -----------
# Parsing text data and collecting data into array.
#
# If "a.txt" has "Key" = "Value", "aa" = "bb".
# After using `collect_to_arr("a.txt", "=", a_map)`
# array: a_map["Key"] = "Value", a_map["aa"] = "bb"
#
# opt_ignore_str (regex str) is an optional argument.
# You can exclude specific string.
# Excluded string will not be parsed.
#
# Example
#
# ```awk
# collect_to_arr("/etc/os-release", "=", release)
#
# for (i in release)
# print "k:", i, "v:", release[i]
# ```
#
function collect_to_arr(file, field_separator, arr, opt_ignore_str, _, i) {
# Set FS, and `getline` will use it.
old_fs = FS
FS = field_separator
for (i = 0; (getline < file) > 0; ++i) {
if (!is_empty(opt_ignore_str) && match($0, opt_ignore_str))
""
else if (match($0, FS))
arr[$1] = $2
else
arr[i] = $0
}
FS = old_fs
#[test]
# for (i in arr) {
# print "k =", i
# print "v =", arr[i]
# print "------------"
# }
close(file)
}
# -----------
# Set ANSI escape code
#
# For outputting fancy text to the terminal.
# When you call `print()` or `printf()`, you can print coloured text or special effects
#
# [[Colour, Foregroud, Backgroud]; [black,30,40] [red, 31, 41] [green, 32, 42] [yellow, 33, 43] [blue, 34, 44] [magenta, 35, 45] [cyan, 36, 46] [white, 37, 47] [default, 39, 49]]
#
# ╭───┬─────────┬───────────┬───────────╮
# │ # │ Colour │ Foregroud │ Backgroud │
# ├───┼─────────┼───────────┼───────────┤
# │ 0 │ black │ 30 │ 40 │
# │ 1 │ red │ 31 │ 41 │
# │ 2 │ green │ 32 │ 42 │
# │ 3 │ yellow │ 33 │ 43 │
# │ 4 │ blue │ 34 │ 44 │
# │ 5 │ magenta │ 35 │ 45 │
# │ 6 │ cyan │ 36 │ 46 │
# │ 7 │ white │ 37 │ 47 │
# │ 8 │ default │ 39 │ 49 │
# ╰───┴─────────┴───────────┴───────────╯
#
# Example
#
# ```awk
# set_ansi_style()
# print sty["green"] sty["~"] "hello", sty[0] sty["_"] sty["u"] sty["red"] "world" sty[0]
# ```
#
function set_ansi_style(_, colour_arr1, colour_arr1_len, i, colour_arr2) {
colour_arr1_len = split("black,red,green,yellow,blue,magenta,cyan,white", colour_arr1, ",")
# "black,red,green,yellow,blue,magenta,cyan,white"
# "bk,rd,gn,yl,bu,mn,cn,wh"
# [[Colour, Abbr]; [black, bk],[red, rd] [green, gn], [yellow, yl],[blue, bu], [magenta, mn], [cyan, cn], [white, wh]]
#
# ╭───┬─────────┬──────╮
# │ # │ Colour │ Abbr │
# ├───┼─────────┼──────┤
# │ 0 │ black │ bk │
# │ 1 │ red │ rd │
# │ 2 │ green │ gn │
# │ 3 │ yellow │ yl │
# │ 4 │ blue │ bu │
# │ 5 │ magenta │ mn │
# │ 6 │ cyan │ cn │
# │ 7 │ white │ wh │
# ╰───┴─────────┴──────╯
#
# note: sty["bk"] = sty["black"]
split("bk,rd,gn,yl,bu,mn,cn,wh", colour_arr2, ",")
for (i = 1; i <= colour_arr1_len; ++i) {
# note: Since i starts at 1, this is 29, not 30.
# print "debug::set_ansi_style", "\33[" (29 + i) "m"
sty[colour_arr1[i]] = sty[colour_arr2[i]] = "\33[" (29 + i) "m"
}
# default foreground colour
sty["default"] = sty["de"] = "\33[39m"
# reset
sty[0] = "\33[0m"
# increased intensity
sty[1] = sty["bold"] = sty["b"] = "\33[1m"
# decreased intensity
sty[2] = sty["faint"] = "\33[2m"
# neither bold nor faint
sty["/b"] ="\33[22m"
sty["italic"] = sty["_"] = "\33[3m"
# Neither italic, nor blackletter
sty["/_"] = "\33[23m"
sty["strike"] = sty["~"] = "\33[9m"
# Not striked(crossed out)
sty["/~"] = "\33[29m"
sty["underline"] = sty["u"] = "\33[4m"
sty["not underlined"] = sty["/u"] = "\33[24m"
sty["background"] = sty["bg"] = "\33[7m"
sty["foreground"] = sty["fg"] = "\33[27m"
}
# -----------
# Set constants
#
# About stdin:
# Some systems do not have "/dev/tty" or "/proc/self/fd/0"
# Some awk distros do not support "-"
# Interestingly, for busybox awk on windows (busybox: v1.36.0-FRP-4621-gf3c5e8bc3 (2022-02-28 07:17:58 GMT)), it automatically converts "/dev/stdin" to the windows interface, but neither "/dev/tty" or "-" will work.
# In mawk(1.3.4 20200120), an explicit call to `close("/dev/stdin")` will result in a segmentation fault.
#
function set_const() {
STDIN = "/dev/stdin"
NONE = ""
SPACE = " "
TO_NULL = " >/dev/null"
STDERR = "/dev/stderr"
# true and false are not keywords in the current awk
false = 0
true = 1
# for outputting fancy text to the terminal
set_ansi_style()
# Get constant at runtime
WHICH_CMD = get_which_cmd()
# set downloader
DOWNLOADER = (check_cmd("curl"))? "curl": (check_cmd("wget"))? "wget": NONE
}
# -----------
# Print true or else , instead of 1 or 0
#
# ╭───┬──────┬───────╮
# │ # │ Ok │ Err │
# ├───┼──────┼───────┤
# │ │ true │ false │
# ╰───┴──────┴───────╯
#
# Example
#
# ```awk
# m = 1
# print_bool(m)
# # stdout: true
#
# n = 0
# print_bool(n)
# # stdout: false
# # note: this is stdout, not stderr
# ```
#
# print_bool(b: bool)
function print_bool(b) {
print (b)? "true": "false"
}
# -----------
# If the string is empty -> true
# If not empty -> false
#
# Note: If you want to remove spaces or other invisible characters, you need to call `trim()` first
#
# [[s_type, Usage, Result]; ["string", "is_empty(s)", "true or false"]]
#
# ╭───┬────────┬─────────────┬───────────────╮
# │ # │ s_type │ Usage │ Result │
# ├───┼────────┼─────────────┼───────────────┤
# │ 0 │ string │ is_empty(s) │ true or false │
# ╰───┴────────┴─────────────┴───────────────╯
#
# Example
#
# ```awk
# s = ""
#
# if (is_empty(s))
# print "Ok, s is empty"
# ```
#
# is_empty(s: string) -> bool
function is_empty(s) {
# Unfortunately, busybox awk(1.35.0-1) does not have `typeof()`
## type: "array", "number", "regexp", "string", "strnum", "unassigned", or "undefined".
# (typeof(s) ~ /unassigned|undefined/)? true: ...
# The `length()` of some awk distributions may only support the string type.
# gawk and mawk also support the array and number types. i.e. They can use `length(array)`
return (length(s) == 0 || s == NONE)? true : false
}
# -----------
# Trim off whitespace characters on the left and right sides of the string.
# whitespace chars: [ \t\n\r\f\v]
#
# [[Usage, Trim, "Result(a new str)"]; ["trim(\" aa bb \")", "whitespace chars(left and right)", "\"aa bb\""]]
#
# ╭───┬───────────────────┬──────────────────────────────────┬───────────────────╮
# │ # │ Usage │ Trim │ Result(a new str) │
# ├───┼───────────────────┼──────────────────────────────────┼───────────────────┤
# │ 0 │ trim(" aa bb ") │ whitespace chars(left and right) │ "aa bb" │
# ╰───┴───────────────────┴──────────────────────────────────┴───────────────────╯
#
# Example
#
# ```awk
# s = " \t \t foo"
#
# n = trim(s)
# print n
# # stdout: foo
#
# print s
# # This will output spaces, tabs and foo
# ```
#
# trim(s: string) -> string
function trim(s) {
gsub(/^[[:space:]]+|[[:space:]]+$/, "", s)
return s
}
# -----------
# Remove the quotation marks on the left and right sides.
#
# Example
#
# ```awk
# s = "\"\"awk\"\""
#
# print s
# # stdout: ""awk""
#
# print dequotes(s)
# # stdout: awk
# ```
#
# dequotes(s: string) -> string
function dequotes(s) {
gsub(/^("|')+|("|')+$/, NONE, s)
return s
}
# -----------
# If the file exists -> true
# Otherwise -> false
#
# [[Arg, Usage, Result]; [file, "is_file_exists(file)", "true or false"]]
#
# ╭───┬──────┬──────────────────────┬───────────────╮
# │ # │ Arg │ Usage │ Result │
# ├───┼──────┼──────────────────────┼───────────────┤
# │ 0 │ file │ is_file_exists(file) │ true or false │
# ╰───┴──────┴──────────────────────┴───────────────╯
#
# Example
#
# ```awk
# file = "/usr/lib/os-release"
#
# if (is_file_exists(file))
# printf("Ok, %s exists\n", file)"
#
#
# f = "/tmp/a_non-existent_file.txt"
# b = is_file_exists(f)
#
# print_bool(b)
# # stdout: false
# ```
#
# is_file_exists(f: string) -> bool
function is_file_exists(f) {
# it's (!system()), not (system())
return !system("test -e" SPACE f)
}
# -----------
#[test]
function test_cmd_exists(_, cmd, arg, arr_len, i) {
cmd = "command"
arr_len= split("-v type aa bb cc dd 1.2e-3 ff 0x09", arg, SPACE)
print "arr.len(): " arr_len
for (i in arg)
print i, ":", arg[i]
status = is_cmd_exists(cmd, arg, arr_len)
print_bool(status)
}
# -----------
#[test]
function test_check_cmd() {
WHICH_CMD = get_which_cmd()
print "WHICH_CMD:", WHICH_CMD
s = check_cmd("uname", "-m")
print_bool(s)
}
# -----------
#[test]
function test_alice_s_fruit(_, s, fruit, my, alice) {
s = ""
fruit = "lychees"
if (is_empty(s)) {
print "s is empty\n",
"OK, I knew there was nothing there."
}
# note: my[fruit] is my["lychees"], not my["fruit"]
my[fruit] = 2
if (is_empty(my[fruit])) {
printf("Since the value of `my[fruit]` has already been defined earlier, don't be too sad.\n",
"The `if` will not go through this branch.\n")
} else {
printf("Please note that there is a difference between a variable that is empty and has the value \"\" and a variable that is not empty and has the value 0.\n",
"But in awk, if an int variable is uninitialized, it will automatically be set to 0.\n",
"Fortunately, mawk/gawk can call `typeof()` to check the type of a variable. We can determine (unassigned|undefined). Unfortunately, some awk distros do not have `typeof()`\n")
print (my[fruit] == 0)? "The sad thing is that I don't have any " fruit: (my[fruit] == 1)? "Only one, but no bad": "Woo-hoo! It's so exciting. I have many many", fruit
}
alice[fruit] = 5
# note: (!false) = (true)
if (!is_empty(alice[fruit]) && alice[fruit] > my[fruit])
printf("Oh, no! Alice has %d %s.\nThis is unfair.\n", alice[fruit], fruit)
}
# -----------
#[test]
function test_file_existence() {
if (is_file_exists("/usr/lib/os-release"))
print "Ok, it exists."
if (!is_file_exists("/etc/lib-release"))
print "Oh no, it doesn't exist"
}
# -----------
function get_architecture(uname, _, a) {
if (check_cmd("apt-cache") && check_cmd("dpkg-query"))
a = get_cmd_out("dpkg,--print-architecture")
else
a = get_cmd_out(uname ",-m")
# global
# Key: "llvm", Value: "x86_64"
# Key: "deb", Value: "amd64"
ARCH["llvm"] = "x86_64"
parse_architecture(a, ARCH)
#[test]
# print "debug::get_architecture,\n", sty["green"] "llvm_arch:", sty["yellow"], arch["llvm"] "\n",
# sty["blue"] "deb_arch:", sty["cyan"] arch["deb"]
}
# -----------
function parse_architecture(a, arch) {
# While gawk supports `switch case` statements, some other `awk` distributions do not.
# [[llvm_arch, deb_arch]; [x86_64, amd64], [aarch64, arm64], [armv7, "armhf or armel"], [arm, "armel"], [armv5te, armel], [i686, i386], [riscv64gc, riscv64], [powerpc64le, ppc64el], [s390x, s390x], [mips64el, mips64el], [mipsel, mipsel]]
# note: It doesn't support all architectures.
# `x86_64` must precede `i386`
# x86_64|amd64|x64
if (a ~ /(x(86_)?|amd)64/) {
arch["deb"] = "amd64"
arch["llvm"] = "x86_64"
# aarch64|armv8a|armv9|arm64
} else if (a ~ /a(arch64|rm(v(8a|9)|64))/) {
# aarch64-apple-darwin
# aarch64-linux-android
# aarch64-pc-windows-msvc
# aarch64-unknown-linux-musl
# aarch64-unknown-linux-gnu
arch["llvm"] = "aarch64"
arch["deb"] = "arm64"
# armv7|armv8l|armhf|^arm$
} else if (a ~ /arm(v(7|8l)|hf)|^arm$/) {
# armv7-unknown-linux-gnueabihf
# armv7-unknown-linux-musleabihf
# android abi: https://developer.android.com/ndk/guides/abis.html
# armv7-linux-androideabi, armeabi-v7a
# https://developer.android.com/ndk/guides/cpu-arm-neon
# thumbv7neon-linux-androideabi, Thumb2-mode ARMv7a Android with NEON
arch["llvm"] = "armv7"
arch["deb"] = "armhf"
# armel|armv6
} else if (a ~ /arm(el|v6)/) {
arch["llvm"] = "arm"
# On some systems, arm-unknown-linux-gnueabihf might be "armhf"
# note: arm-unknown-linux-gnueabi and arm-unknown-linux-musleabi are "armel"
arch["deb"] = "armel"
# To be honest, I don't want to support the armv6 and v5 architectures.
# Maybe one day I will remove or comment out these `else if`
} else if (a ~ /arm(el|v5)/) {
arch["llvm"] = "armv5te"
arch["deb"] = "armel"
} else if (a ~ /arm/) {
# armv4 or older architectures are not supported, if none of the above arm architectures are matched then the default will be to fall back to arm64
arch["llvm"] = "aarch64"
arch["deb"] = "arm64"
# i386 i486 i586 x86 x32 x86_32
} else if (a ~ /x((86_)?32|86)|i[3-5]86/) {
# note: On some systems it will output i386 even if it is i686.
print "It does not support i386 and i486, only i586 and i686"
arch["llvm"] = "i586"
arch["deb"] = "i386"
} else if (a ~ /i686/) {
arch["llvm"] = "i686"
arch["deb"] = "i386"
} else if (a ~ /riscv64/) {
arch["llvm"] = "riscv64gc"
arch["deb"] = "riscv64"
} else if (a ~ /powerpc64(el|le)?|ppc64(el|le)?/) {
print "It does not support ppc64, only ppc64el"
arch["llvm"] = "powerpc64le"
arch["deb"] = "ppc64el"
} else if (a ~ /s390/) {
# regex: Use /s390/, not /s390x/
arch["llvm"] = arch["deb"] = "s390x"
} else if (a ~ /mips64/) {
arch["llvm"] = arch["deb"] = "mips64el"
} else if (a ~ /mips/) {
# note: On mipsel devices, the output of `uname -m` may not be mipsle/mispel, but mips
arch["llvm"] = arch["deb"] = "mipsel"
} else {
print sty["cyan"]
print "╭────┬─────────────┬────────────────╮"
print "│ # │ llvm_arch │ deb_arch │"
print "├────┼─────────────┼────────────────┤"
print "│ 0 │ x86_64 │ amd64 │"
print "│ 1 │ aarch64 │ arm64 │"
print "│ 2 │ armv7 │ armhf or armel │"
print "│ 3 │ arm │ armel │"
print "│ 4 │ armv5te │ armel │"
print "│ 5 │ i686 │ i386 │"
print "│ 6 │ riscv64gc │ riscv64 │"
print "│ 7 │ powerpc64le │ ppc64el │"
print "│ 8 │ s390x │ s390x │"
print "│ 9 │ mips64el │ mips64el │"
print "│ 10 │ mipsel │ mipsel │"
print "╰────┴─────────────┴────────────────╯"
print sty["green"] "Note: There is a difference between", sty["blue"] "arm-unknown-linux-gnueabi", sty["cyan"] "and", sty["yellow"] "arm-unknown-linux-gnueabihf." sty[0]
print "On some systems, the latter may be", sty["yellow"] "armhf", sty[0] "instead of", sty["blue"] "armel."
print sty["yellow"] "---------------------"
# print "Adapting to different architectures is hard work. To be honest, I don't want to be that tired."
print sty["red"] "Unfortunately!\n",
sty["blue"] "It does not support the", sty["magenta"] a, sty["cyan"] "architecture." sty[0] > STDERR
exit 1
}
}
# -----------
# Please do not remove the test function.
BEGIN {
main()
# test()
}
# -----------
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment