mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
slightly changed block format
- small change in block format - added config in blockchain explorer - bugfixes
This commit is contained in:
parent
7f3a22a217
commit
090e0c16eb
82 changed files with 1852 additions and 391 deletions
|
@ -1013,6 +1013,8 @@ x{FB00} @Defop SENDRAWMSG
|
|||
x{FB02} @Defop RAWRESERVE
|
||||
x{FB03} @Defop RAWRESERVEX
|
||||
x{FB04} @Defop SETCODE
|
||||
x{FB06} @Defop SETLIBCODE
|
||||
x{FB07} @Defop CHANGELIB
|
||||
|
||||
//
|
||||
// debug primitives
|
||||
|
|
|
@ -111,3 +111,4 @@ variable base
|
|||
{ true (atom) drop } : atom
|
||||
{ bl word atom 1 'nop } ::_ `
|
||||
{ hole dup 1 { @ execute } does create } : recursive
|
||||
{ 0 { 1+ dup 1 ' $() does over (.) "$" swap $+ 0 (create) } rot times drop } : :$1..n
|
||||
|
|
92
crypto/fift/lib/GetOpt.fif
Normal file
92
crypto/fift/lib/GetOpt.fif
Normal file
|
@ -0,0 +1,92 @@
|
|||
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?
|
||||
// ( l -- s i or 0 ) finds first string in l beginning with '-'
|
||||
{ 0 { 1+ over null? { 2drop 0 true } {
|
||||
swap uncons over is-opt? { 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
|
||||
// ( s t -- ? ) checks whether short/long option s matches description t
|
||||
{ third $= } : short-option-matches
|
||||
' second : get-opt-flags
|
||||
' first : get-opt-exec
|
||||
{ dup get-opt-flags 4 and 0= 3 + [] $=
|
||||
} : long-option-matches
|
||||
// ( 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 -- i or 0 )
|
||||
// parses command line arguments according to option description list l
|
||||
// and returns index i of first incorrect option
|
||||
{ { first-opt dup 0= { true } {
|
||||
swap dup "--" $pfx? { // l i s
|
||||
dup $len 2 = { drop dup 1 $*del.. 0 true } {
|
||||
split-longopt swap 3 pick
|
||||
lookup-long-option not { drop true } { // l i s' t f
|
||||
dup get-opt-exec swap get-opt-flags 3 and // l i s' e f'
|
||||
2 pick null? { dup 1 = } { dup 0= negate } cond // l 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 } { // l i s
|
||||
1 $| nip {
|
||||
dup $len 0= { drop 1 $*del.. false true } {
|
||||
1 $| swap 3 pick // l i s' s l
|
||||
lookup-short-option not { drop true true } { // l i s' t
|
||||
dup get-opt-exec swap get-opt-flags 3 and // l i s' e f'
|
||||
?dup 0= { execute false } {
|
||||
2 pick $len { drop execute "" false } {
|
||||
2 = { nip null swap execute "" false } { // l i e
|
||||
nip over 1+ $() swap execute 2 $*del.. false true
|
||||
} cond } cond } cond } cond } cond } until
|
||||
} cond
|
||||
} cond } until nip
|
||||
} : getopt
|
||||
// ( l -- ) Parses options and throws an error on failure
|
||||
{ getopt ?dup { $() "cannot parse command line options near `" swap $+ +"`" 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
|
|
@ -46,6 +46,9 @@ td::Result<std::string> load_Lists_fif(std::string dir = "") {
|
|||
td::Result<std::string> load_Lisp_fif(std::string dir = "") {
|
||||
return load_source("Lisp.fif", dir);
|
||||
}
|
||||
td::Result<std::string> load_GetOpt_fif(std::string dir = "") {
|
||||
return load_source("GetOpt.fif", dir);
|
||||
}
|
||||
|
||||
class MemoryFileLoader : public fift::FileLoader {
|
||||
public:
|
||||
|
@ -115,6 +118,10 @@ td::Result<fift::SourceLookup> create_source_lookup(std::string main, bool need_
|
|||
TRY_RESULT(f, load_TonUtil_fif(dir));
|
||||
loader->add_file("/TonUtil.fif", std::move(f));
|
||||
}
|
||||
{
|
||||
TRY_RESULT(f, load_GetOpt_fif(dir));
|
||||
loader->add_file("/GetOpt.fif", std::move(f));
|
||||
}
|
||||
}
|
||||
if (need_lisp) {
|
||||
TRY_RESULT(f, load_Lisp_fif(dir));
|
||||
|
|
|
@ -604,6 +604,12 @@ void interpret_str_split(vm::Stack& stack) {
|
|||
stack.push_string(std::string{str, sz});
|
||||
}
|
||||
|
||||
void interpret_str_pos(vm::Stack& stack) {
|
||||
auto s2 = stack.pop_string(), s1 = stack.pop_string();
|
||||
auto pos = s1.find(s2);
|
||||
stack.push_smallint(pos == std::string::npos ? -1 : pos);
|
||||
}
|
||||
|
||||
void interpret_str_reverse(vm::Stack& stack) {
|
||||
std::string s = stack.pop_string();
|
||||
auto it = s.begin();
|
||||
|
@ -659,6 +665,20 @@ void interpret_utf8_str_split(vm::Stack& stack) {
|
|||
}
|
||||
}
|
||||
|
||||
void interpret_utf8_str_pos(vm::Stack& stack) {
|
||||
auto s2 = stack.pop_string(), s1 = stack.pop_string();
|
||||
auto pos = s1.find(s2);
|
||||
if (pos == std::string::npos) {
|
||||
stack.push_smallint(-1);
|
||||
return;
|
||||
}
|
||||
int cnt = 0;
|
||||
for (std::size_t i = 0; i < pos; i++) {
|
||||
cnt += ((s1[i] & 0xc0) != 0x80);
|
||||
}
|
||||
stack.push_smallint(cnt);
|
||||
}
|
||||
|
||||
void interpret_str_remove_trailing_int(vm::Stack& stack, int arg) {
|
||||
char x = (char)(arg ? arg : stack.pop_long_range(127));
|
||||
std::string s = stack.pop_string();
|
||||
|
@ -2336,12 +2356,38 @@ void interpret_db_run_vm_parallel(IntCtx& ctx) {
|
|||
do_interpret_db_run_vm_parallel(ctx.error_stream, ctx.stack, ctx.ton_db, threads_n, tasks_n);
|
||||
}
|
||||
|
||||
Ref<vm::Box> cmdline_args{true};
|
||||
|
||||
void interpret_get_fixed_cmdline_arg(vm::Stack& stack, int n) {
|
||||
if (!n) {
|
||||
return;
|
||||
}
|
||||
auto v = cmdline_args->get();
|
||||
while (true) {
|
||||
if (v.empty()) {
|
||||
stack.push(vm::StackEntry{});
|
||||
return;
|
||||
}
|
||||
auto t = v.as_tuple_range(2, 2);
|
||||
if (t.is_null()) {
|
||||
throw IntError{"invalid cmdline arg list"};
|
||||
}
|
||||
if (!--n) {
|
||||
stack.push(t->at(0));
|
||||
return;
|
||||
}
|
||||
v = t->at(1);
|
||||
}
|
||||
}
|
||||
|
||||
// n -- executes $n
|
||||
void interpret_get_cmdline_arg(IntCtx& ctx) {
|
||||
int n = ctx.stack.pop_smallint_range(999999);
|
||||
char buffer[14];
|
||||
sprintf(buffer, "$%d ", n);
|
||||
auto entry = ctx.dictionary->lookup(std::string{buffer});
|
||||
if (n) {
|
||||
interpret_get_fixed_cmdline_arg(ctx.stack, n);
|
||||
return;
|
||||
}
|
||||
auto entry = ctx.dictionary->lookup("$0 ");
|
||||
if (!entry) {
|
||||
throw IntError{"-?"};
|
||||
} else {
|
||||
|
@ -2349,6 +2395,19 @@ void interpret_get_cmdline_arg(IntCtx& ctx) {
|
|||
}
|
||||
}
|
||||
|
||||
void interpret_get_cmdline_arg_count(vm::Stack& stack) {
|
||||
auto v = cmdline_args->get();
|
||||
int cnt;
|
||||
for (cnt = 0; !v.empty(); cnt++) {
|
||||
auto t = v.as_tuple_range(2, 2);
|
||||
if (t.is_null()) {
|
||||
throw IntError{"invalid cmdline arg list"};
|
||||
}
|
||||
v = t->at(1);
|
||||
}
|
||||
stack.push_smallint(cnt);
|
||||
}
|
||||
|
||||
void interpret_getenv(vm::Stack& stack) {
|
||||
auto str = stack.pop_string();
|
||||
auto value = str.size() < 1024 ? getenv(str.c_str()) : nullptr;
|
||||
|
@ -2568,6 +2627,7 @@ void init_words_common(Dictionary& d) {
|
|||
d.def_stack_word("$= ", interpret_str_equal);
|
||||
d.def_stack_word("$cmp ", interpret_str_cmp);
|
||||
d.def_stack_word("$reverse ", interpret_str_reverse);
|
||||
d.def_stack_word("$pos ", interpret_str_pos);
|
||||
d.def_stack_word("(-trailing) ", std::bind(interpret_str_remove_trailing_int, _1, 0));
|
||||
d.def_stack_word("-trailing ", std::bind(interpret_str_remove_trailing_int, _1, ' '));
|
||||
d.def_stack_word("-trailing0 ", std::bind(interpret_str_remove_trailing_int, _1, '0'));
|
||||
|
@ -2575,6 +2635,7 @@ void init_words_common(Dictionary& d) {
|
|||
d.def_stack_word("Blen ", interpret_bytes_len);
|
||||
d.def_stack_word("$Len ", interpret_utf8_str_len);
|
||||
d.def_stack_word("$Split ", interpret_utf8_str_split);
|
||||
d.def_stack_word("$Pos ", interpret_utf8_str_pos);
|
||||
d.def_ctx_word("Bx. ", std::bind(interpret_bytes_hex_print_raw, _1, true));
|
||||
d.def_stack_word("B>X ", std::bind(interpret_bytes_to_hex, _1, true));
|
||||
d.def_stack_word("B>x ", std::bind(interpret_bytes_to_hex, _1, false));
|
||||
|
@ -2766,6 +2827,10 @@ void init_words_common(Dictionary& d) {
|
|||
d.def_ctx_word("quit ", interpret_quit);
|
||||
d.def_ctx_word("bye ", interpret_bye);
|
||||
d.def_stack_word("halt ", interpret_halt);
|
||||
// cmdline args
|
||||
d.def_stack_word("$* ", std::bind(interpret_literal, _1, vm::StackEntry{cmdline_args}));
|
||||
d.def_stack_word("$# ", interpret_get_cmdline_arg_count);
|
||||
d.def_ctx_word("$() ", interpret_get_cmdline_arg);
|
||||
}
|
||||
|
||||
void init_words_ton(Dictionary& d) {
|
||||
|
@ -2799,13 +2864,16 @@ void import_cmdline_args(Dictionary& d, std::string arg0, int n, const char* con
|
|||
using namespace std::placeholders;
|
||||
LOG(DEBUG) << "import_cmdlist_args(" << arg0 << "," << n << ")";
|
||||
d.def_stack_word("$0 ", std::bind(interpret_literal, _1, vm::StackEntry{arg0}));
|
||||
for (int i = 0; i < n; i++) {
|
||||
char buffer[14];
|
||||
sprintf(buffer, "$%d ", i + 1);
|
||||
d.def_stack_word(buffer, std::bind(interpret_literal, _1, vm::StackEntry{argv[i]}));
|
||||
vm::StackEntry list;
|
||||
for (int i = n - 1; i >= 0; i--) {
|
||||
list = vm::StackEntry::cons(vm::StackEntry{argv[i]}, list);
|
||||
}
|
||||
cmdline_args->set(std::move(list));
|
||||
for (int i = 1; i <= n; i++) {
|
||||
char buffer[14];
|
||||
sprintf(buffer, "$%d ", i);
|
||||
d.def_stack_word(buffer, std::bind(interpret_get_fixed_cmdline_arg, _1, i));
|
||||
}
|
||||
d.def_stack_word("$# ", std::bind(interpret_const, _1, n));
|
||||
d.def_ctx_word("$() ", interpret_get_cmdline_arg);
|
||||
}
|
||||
|
||||
std::pair<td::RefInt256, td::RefInt256> numeric_value_ext(std::string s, bool allow_frac = true) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue