mirror of
https://github.com/ton-blockchain/ton
synced 2025-02-13 11:42:18 +00:00
131 lines
5.4 KiB
Text
131 lines
5.4 KiB
Text
library GetOpt // Simple command-line options parser
|
|
"Lists.fif" include
|
|
|
|
// May be used as follows:
|
|
// begin-options
|
|
// "h" { ."Help Message" 0 halt } short-option
|
|
// "v" { parse-int =: verbosity } short-option-arg
|
|
// "i" "--interactive" { true =: interactive } short-long-option
|
|
// parse-options
|
|
|
|
// ( l -- l') computes tail of list l if non-empty; else ()
|
|
{ dup null? ' cdr ifnot } : safe-cdr
|
|
// ( l c -- l') deletes first c elements from list l
|
|
{ ' safe-cdr swap times } : list-delete-first
|
|
// ( l n c -- l' ) deletes c elements starting from n-th in list l
|
|
recursive list-delete-range {
|
|
dup 0<= { 2drop } {
|
|
over 0<= { nip list-delete-first } {
|
|
swap 1- swap rot uncons 2swap list-delete-range cons
|
|
} cond } cond
|
|
} swap !
|
|
// ( n c -- ) deletes $n .. $(n+c-1) from the argument list $*
|
|
{ swap 1- $* @ swap rot list-delete-range $* ! } : $*del..
|
|
// ( s s' -- ? ) checks whether s' is a prefix of s
|
|
{ tuck $len over $len over >= { $| drop $= } { 2drop drop false } cond
|
|
} : $pfx?
|
|
// ( s -- ? ) checks whether s is an option (a string beginning with '-')
|
|
{ dup $len 1 > { "-" $pfx? } { drop false } cond } : is-opt?
|
|
// ( s -- ? ) checks whether s is a digit option
|
|
{ 2 $| drop 1 $| nip $>B 8 B>u@ dup 57 <= swap 48 >= and } : is-digit-opt?
|
|
0 box constant disable-digit-opts
|
|
// ( l -- s i or 0 ) finds first string in l beginning with '-'
|
|
{ 0 { 1+ over null? { 2drop 0 true } {
|
|
swap uncons over is-opt?
|
|
{ disable-digit-opts @ { over is-digit-opt? not } { true } cond } { false } cond
|
|
{ drop swap true } { nip swap false } cond
|
|
} cond } until
|
|
} : list-find-opt
|
|
// ( -- s i or 0 ) finds first option in cmdline args
|
|
{ $* @ list-find-opt } : first-opt
|
|
' second : get-opt-flags
|
|
' first : get-opt-exec
|
|
// ( s t -- ? ) checks whether short/long option s matches description t
|
|
{ third $= } : short-option-matches
|
|
{ dup get-opt-flags 4 and 0= 3 + [] $=
|
|
} : long-option-matches
|
|
// ( t -- s -1 or 0 ) extracts help message from description
|
|
{ dup get-opt-flags 4 and 0= 4 + over count over >
|
|
{ [] true } { 2drop false } cond
|
|
} : get-opt-help
|
|
// ( s l -- t -1 or 0 ) finds short/long option s in list l
|
|
{ swap 1 { swap short-option-matches } does assoc-gen
|
|
} : lookup-short-option
|
|
{ swap 1 { swap long-option-matches } does assoc-gen
|
|
} : lookup-long-option
|
|
// ( s -- s' null or s' s'' ) Splits long option --opt=arg at '='
|
|
{ dup "=" $pos 1+ ?dup { tuck $| swap rot 1- $| drop swap } { null } cond
|
|
} : split-longopt
|
|
// ( l -- f or 0 ) Extracts global option flags from first entry of l
|
|
{ dup null? { drop 0 } { car get-opt-flags -256 and } cond
|
|
} : get-global-option-flags
|
|
variable options-list
|
|
// ( l -- i or 0 )
|
|
// parses command line arguments according to option description list l
|
|
// and returns index i of first incorrect option
|
|
{ dup options-list ! get-global-option-flags
|
|
256 and disable-digit-opts !
|
|
{ first-opt dup 0= { true } {
|
|
swap dup "--" $pfx? { // i s
|
|
dup $len 2 = { drop dup 1 $*del.. 0 true } {
|
|
split-longopt swap options-list @
|
|
lookup-long-option not { drop true } { // i s' t f
|
|
dup get-opt-exec swap get-opt-flags 3 and // i s' e f'
|
|
2 pick null? { dup 1 = } { dup 0= negate } cond // i s' e f' f''
|
|
dup 1 = { 2drop 2drop true } {
|
|
{ drop nip over 1+ $() swap execute 2 $*del.. false } {
|
|
' nip ifnot execute 1 $*del.. false
|
|
} cond } cond } cond } cond } { // i s
|
|
1 $| nip {
|
|
dup $len 0= { drop 1 $*del.. false true } {
|
|
1 $| swap options-list @ // i s' s l
|
|
lookup-short-option not { drop true true } { // i s' t
|
|
dup get-opt-exec swap get-opt-flags 3 and // i s' e f'
|
|
?dup 0= { execute false } {
|
|
2 pick $len { drop execute "" false } {
|
|
2 = { nip null swap execute "" false } { // i e
|
|
nip over 1+ $() swap execute 2 $*del.. false true
|
|
} cond } cond } cond } cond } cond } until
|
|
} cond
|
|
} cond } until
|
|
} : getopt
|
|
// ( t -- ) Displays help message for one option
|
|
{ dup get-opt-flags dup 4 and 2 pick third swap {
|
|
."-" type ."/" over 3 [] type } {
|
|
dup $len { dup "--" $pfx? { ."-" } ifnot type } {
|
|
drop ."usage: " $0 type
|
|
} cond } cond
|
|
dup 3 and ?dup {
|
|
2 = { ."[=<optarg>]" } { ."=<optarg>" } cond
|
|
} if
|
|
8 and { 9 emit } ifnot
|
|
get-opt-help { type } { ."No help available" } cond cr
|
|
} : show-opt-help
|
|
// ( -- ) Displays options help message according to options-list
|
|
{ options-list @ { dup null? not } {
|
|
uncons swap show-opt-help
|
|
} while drop
|
|
} : show-options-help
|
|
// ( l -- ) Parses options and throws an error on failure
|
|
{ getopt ?dup {
|
|
$() "cannot parse command line options near `" swap $+ +"`"
|
|
show-options-help abort } if
|
|
} : run-getopt
|
|
anon constant opt-list-marker
|
|
' opt-list-marker : begin-options
|
|
{ opt-list-marker list-until-marker } : end-options
|
|
{ end-options run-getopt } : parse-options
|
|
// ( s e -- o ) Creates short/long option s with execution token e
|
|
{ 0 rot triple } dup : short-option : long-option
|
|
// ( s s' e -- o ) Creates a combined short option s and long option s' with execution token e
|
|
{ 4 2swap 4 tuple } : short-long-option
|
|
{ 1 rot triple } dup : short-option-arg : long-option-arg
|
|
{ 2 rot triple } dup : short-option-?arg : long-option-?arg
|
|
{ 5 2swap 4 tuple } : short-long-option-arg
|
|
{ 6 2swap 4 tuple } : short-long-option-?arg
|
|
// ( o s -- s' ) Adds help message to option
|
|
' , : option-help
|
|
// ( s f -- o ) Creates a generic help message
|
|
{ swap 'nop rot "" 3 roll 4 tuple } : generic-help-setopt
|
|
{ 0 generic-help-setopt } : generic-help
|
|
256 constant disable-digit-options
|