mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-23 03:32:27 +08:00
split builtin random into its own module
This commit is contained in:
parent
e7f87c08e1
commit
1c91ec9dfa
49
Makefile.in
49
Makefile.in
|
@ -101,6 +101,7 @@ HAVE_DOXYGEN=@HAVE_DOXYGEN@
|
|||
FISH_OBJS := obj/autoload.o obj/builtin.o obj/builtin_bind.o obj/builtin_block.o \
|
||||
obj/builtin_commandline.o obj/builtin_emit.o obj/builtin_functions.o \
|
||||
obj/builtin_history.o obj/builtin_status.o obj/builtin_read.o \
|
||||
obj/builtin_random.o \
|
||||
obj/builtin_complete.o obj/builtin_jobs.o obj/builtin_printf.o \
|
||||
obj/builtin_set.o obj/builtin_set_color.o obj/builtin_string.o \
|
||||
obj/builtin_test.o obj/builtin_ulimit.o obj/color.o obj/common.o \
|
||||
|
@ -946,17 +947,18 @@ v = $(V$(V))
|
|||
obj/autoload.o: config.h src/autoload.h src/common.h src/fallback.h
|
||||
obj/autoload.o: src/signal.h src/lru.h src/env.h src/exec.h src/wutil.h
|
||||
obj/builtin.o: config.h src/signal.h src/builtin.h src/common.h
|
||||
obj/builtin.o: src/fallback.h src/builtin_bind.h src/builtin_block.h src/builtin_functions.h
|
||||
obj/builtin.o: src/builtin_commandline.h src/builtin_complete.h src/builtin_history.h
|
||||
obj/builtin.o: src/builtin_emit.h src/builtin_jobs.h src/builtin_printf.h
|
||||
obj/builtin.o: src/builtin_set.h src/builtin_set_color.h src/builtin_string.h
|
||||
obj/builtin.o: src/builtin_test.h src/builtin_ulimit.h src/complete.h
|
||||
obj/builtin.o: src/env.h src/event.h src/exec.h src/expand.h
|
||||
obj/builtin.o: src/parse_constants.h src/function.h src/highlight.h
|
||||
obj/builtin.o: src/color.h src/history.h src/wutil.h src/intern.h src/io.h
|
||||
obj/builtin.o: src/parse_util.h src/tokenizer.h src/parser.h src/parse_tree.h
|
||||
obj/builtin.o: src/fallback.h src/builtin_bind.h src/builtin_block.h
|
||||
obj/builtin.o: src/builtin_commandline.h src/builtin_complete.h
|
||||
obj/builtin.o: src/builtin_emit.h src/builtin_functions.h
|
||||
obj/builtin.o: src/builtin_history.h src/builtin_jobs.h src/builtin_printf.h
|
||||
obj/builtin.o: src/builtin_random.h src/builtin_read.h src/builtin_set.h
|
||||
obj/builtin.o: src/builtin_set_color.h src/builtin_status.h
|
||||
obj/builtin.o: src/builtin_string.h src/builtin_test.h src/builtin_ulimit.h
|
||||
obj/builtin.o: src/complete.h src/env.h src/event.h src/exec.h src/function.h
|
||||
obj/builtin.o: src/intern.h src/io.h src/parse_constants.h src/parse_util.h
|
||||
obj/builtin.o: src/tokenizer.h src/parser.h src/expand.h src/parse_tree.h
|
||||
obj/builtin.o: src/proc.h src/parser_keywords.h src/path.h src/reader.h
|
||||
obj/builtin.o: src/wcstringutil.h src/wgetopt.h
|
||||
obj/builtin.o: src/highlight.h src/color.h src/wgetopt.h src/wutil.h
|
||||
obj/builtin_bind.o: config.h src/builtin.h src/common.h src/fallback.h
|
||||
obj/builtin_bind.o: src/signal.h src/builtin_bind.h src/input.h src/env.h
|
||||
obj/builtin_bind.o: src/io.h src/wgetopt.h src/wutil.h
|
||||
|
@ -980,15 +982,33 @@ obj/builtin_complete.o: src/parse_tree.h src/proc.h src/reader.h
|
|||
obj/builtin_complete.o: src/highlight.h src/color.h src/wgetopt.h src/wutil.h
|
||||
obj/builtin_emit.o: config.h src/builtin.h src/common.h src/fallback.h
|
||||
obj/builtin_emit.o: src/signal.h src/builtin_emit.h src/event.h src/io.h
|
||||
obj/builtin_emit.o: src/parser.h src/expand.h src/parse_constants.h
|
||||
obj/builtin_emit.o: src/parse_tree.h src/tokenizer.h src/proc.h
|
||||
obj/builtin_emit.o: src/wgetopt.h src/wutil.h
|
||||
obj/builtin_functions.o: config.h src/builtin.h src/common.h src/fallback.h
|
||||
obj/builtin_functions.o: src/signal.h src/builtin_functions.h src/env.h
|
||||
obj/builtin_functions.o: src/event.h src/function.h src/io.h
|
||||
obj/builtin_functions.o: src/parser_keywords.h src/proc.h src/parse_tree.h
|
||||
obj/builtin_functions.o: src/parse_constants.h src/tokenizer.h src/wgetopt.h
|
||||
obj/builtin_functions.o: src/wutil.h
|
||||
obj/builtin_history.o: config.h src/builtin.h src/common.h src/fallback.h
|
||||
obj/builtin_history.o: src/signal.h src/builtin_history.h src/history.h
|
||||
obj/builtin_history.o: src/wutil.h src/io.h src/reader.h src/complete.h
|
||||
obj/builtin_history.o: src/highlight.h src/color.h src/env.h
|
||||
obj/builtin_history.o: src/parse_constants.h src/wgetopt.h
|
||||
obj/builtin_jobs.o: config.h src/builtin.h src/common.h src/fallback.h
|
||||
obj/builtin_jobs.o: src/signal.h src/io.h src/proc.h src/parse_tree.h
|
||||
obj/builtin_jobs.o: src/parse_constants.h src/tokenizer.h src/wgetopt.h
|
||||
obj/builtin_jobs.o: src/wutil.h
|
||||
obj/builtin_printf.o: config.h src/builtin.h src/common.h src/fallback.h
|
||||
obj/builtin_printf.o: src/signal.h src/io.h src/wutil.h
|
||||
obj/builtin_random.o: config.h src/builtin.h src/common.h src/fallback.h
|
||||
obj/builtin_random.o: src/signal.h src/builtin_random.h src/io.h
|
||||
obj/builtin_random.o: src/wgetopt.h src/wutil.h
|
||||
obj/builtin_read.o: config.h src/builtin.h src/common.h src/fallback.h
|
||||
obj/builtin_read.o: src/signal.h src/builtin_read.h src/complete.h src/env.h
|
||||
obj/builtin_read.o: src/event.h src/expand.h src/parse_constants.h
|
||||
obj/builtin_read.o: src/highlight.h src/color.h src/io.h src/proc.h
|
||||
obj/builtin_read.o: src/parse_tree.h src/tokenizer.h src/reader.h
|
||||
obj/builtin_read.o: src/wcstringutil.h src/wgetopt.h src/wutil.h
|
||||
obj/builtin_set.o: config.h src/builtin.h src/common.h src/fallback.h
|
||||
obj/builtin_set.o: src/signal.h src/env.h src/expand.h src/parse_constants.h
|
||||
obj/builtin_set.o: src/io.h src/proc.h src/parse_tree.h src/tokenizer.h
|
||||
|
@ -996,6 +1016,11 @@ obj/builtin_set.o: src/wgetopt.h src/wutil.h
|
|||
obj/builtin_set_color.o: config.h src/builtin.h src/common.h src/fallback.h
|
||||
obj/builtin_set_color.o: src/signal.h src/color.h src/env.h src/io.h
|
||||
obj/builtin_set_color.o: src/output.h src/wgetopt.h src/wutil.h
|
||||
obj/builtin_status.o: config.h src/builtin.h src/common.h src/fallback.h
|
||||
obj/builtin_status.o: src/signal.h src/builtin_status.h src/io.h src/parser.h
|
||||
obj/builtin_status.o: src/event.h src/expand.h src/parse_constants.h
|
||||
obj/builtin_status.o: src/parse_tree.h src/tokenizer.h src/proc.h
|
||||
obj/builtin_status.o: src/wgetopt.h src/wutil.h
|
||||
obj/builtin_string.o: config.h src/builtin.h src/common.h src/fallback.h
|
||||
obj/builtin_string.o: src/signal.h src/io.h src/parse_util.h
|
||||
obj/builtin_string.o: src/parse_constants.h src/tokenizer.h src/wgetopt.h
|
||||
|
|
154
src/builtin.cpp
154
src/builtin.cpp
|
@ -21,7 +21,6 @@
|
|||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -31,7 +30,6 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
|
@ -45,6 +43,7 @@
|
|||
#include "builtin_history.h"
|
||||
#include "builtin_jobs.h"
|
||||
#include "builtin_printf.h"
|
||||
#include "builtin_random.h"
|
||||
#include "builtin_read.h"
|
||||
#include "builtin_set.h"
|
||||
#include "builtin_set_color.h"
|
||||
|
@ -897,157 +896,6 @@ int builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_lis
|
|||
return STATUS_CMD_OK;
|
||||
}
|
||||
|
||||
/// The random builtin generates random numbers.
|
||||
static int builtin_random(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
||||
int argc = builtin_count_args(argv);
|
||||
|
||||
static bool seeded = false;
|
||||
static std::minstd_rand engine;
|
||||
if (!seeded) {
|
||||
// seed engine with 2*32 bits of random data
|
||||
// for the 64 bits of internal state of minstd_rand
|
||||
std::random_device rd;
|
||||
std::seed_seq seed{rd(), rd()};
|
||||
engine.seed(seed);
|
||||
seeded = true;
|
||||
}
|
||||
|
||||
static const wchar_t *short_options = L"h";
|
||||
static const struct woption long_options[] = {{L"help", no_argument, NULL, 'h'},
|
||||
{NULL, 0, NULL, 0}};
|
||||
|
||||
int opt;
|
||||
wgetopter_t w;
|
||||
while ((opt = w.wgetopt_long(argc, argv, short_options, long_options, NULL)) != -1) {
|
||||
switch (opt) { //!OCLINT(too few branches)
|
||||
case 'h': {
|
||||
builtin_print_help(parser, streams, argv[0], streams.out);
|
||||
return STATUS_CMD_OK;
|
||||
}
|
||||
case '?': {
|
||||
builtin_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]);
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
default: {
|
||||
DIE("unexpected retval from wgetopt_long");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int arg_count = argc - w.woptind;
|
||||
long long start, end;
|
||||
unsigned long long step;
|
||||
bool choice = false;
|
||||
if (arg_count >= 1 && !wcscmp(argv[w.woptind], L"choice")) {
|
||||
if (arg_count == 1) {
|
||||
streams.err.append_format(L"%ls: nothing to choose from\n", argv[0]);
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
choice = true;
|
||||
start = 1;
|
||||
step = 1;
|
||||
end = arg_count - 1;
|
||||
} else {
|
||||
bool parse_error = false;
|
||||
auto parse_ll = [&](const wchar_t *str) {
|
||||
long long ll = fish_wcstoll(str);
|
||||
if (errno) {
|
||||
streams.err.append_format(L"%ls: %ls is not a valid integer\n", argv[0], str);
|
||||
parse_error = true;
|
||||
}
|
||||
return ll;
|
||||
};
|
||||
auto parse_ull = [&](const wchar_t *str) {
|
||||
unsigned long long ull = fish_wcstoull(str);
|
||||
if (errno) {
|
||||
streams.err.append_format(L"%ls: %ls is not a valid integer\n", argv[0], str);
|
||||
parse_error = true;
|
||||
}
|
||||
return ull;
|
||||
};
|
||||
if (arg_count == 0) {
|
||||
start = 0;
|
||||
end = 32767;
|
||||
step = 1;
|
||||
} else if (arg_count == 1) {
|
||||
long long seed = parse_ll(argv[w.woptind]);
|
||||
if (parse_error) return STATUS_INVALID_ARGS;
|
||||
engine.seed(static_cast<uint32_t>(seed));
|
||||
return STATUS_CMD_OK;
|
||||
} else if (arg_count == 2) {
|
||||
start = parse_ll(argv[w.woptind]);
|
||||
step = 1;
|
||||
end = parse_ll(argv[w.woptind + 1]);
|
||||
} else if (arg_count == 3) {
|
||||
start = parse_ll(argv[w.woptind]);
|
||||
step = parse_ull(argv[w.woptind + 1]);
|
||||
end = parse_ll(argv[w.woptind + 2]);
|
||||
} else {
|
||||
streams.err.append_format(BUILTIN_ERR_TOO_MANY_ARGUMENTS, argv[0]);
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (parse_error) {
|
||||
return STATUS_INVALID_ARGS;
|
||||
} else if (start >= end) {
|
||||
streams.err.append_format(L"%ls: END must be greater than START\n", argv[0]);
|
||||
return STATUS_INVALID_ARGS;
|
||||
} else if (step == 0) {
|
||||
streams.err.append_format(L"%ls: STEP must be a positive integer\n", argv[0]);
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
}
|
||||
|
||||
// only for negative argument
|
||||
auto safe_abs = [](long long ll) -> unsigned long long {
|
||||
return -static_cast<unsigned long long>(ll);
|
||||
};
|
||||
long long real_end;
|
||||
if (start >= 0 || end < 0) {
|
||||
// 0 <= start <= end
|
||||
long long diff = end - start;
|
||||
// 0 <= diff <= LL_MAX
|
||||
real_end = start + static_cast<long long>(diff / step);
|
||||
} else {
|
||||
// start < 0 <= end
|
||||
unsigned long long abs_start = safe_abs(start);
|
||||
unsigned long long diff = (end + abs_start);
|
||||
real_end = diff / step - abs_start;
|
||||
}
|
||||
|
||||
if (!choice && start == real_end) {
|
||||
streams.err.append_format(L"%ls: range contains only one possible value\n", argv[0]);
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
|
||||
std::uniform_int_distribution<long long> dist(start, real_end);
|
||||
long long random = dist(engine);
|
||||
long long result;
|
||||
if (start >= 0) {
|
||||
// 0 <= start <= random <= end
|
||||
long long diff = random - start;
|
||||
// 0 < step * diff <= end - start <= LL_MAX
|
||||
result = start + static_cast<long long>(diff * step);
|
||||
} else if (random < 0) {
|
||||
// start <= random < 0
|
||||
long long diff = random - start;
|
||||
result = diff * step - safe_abs(start);
|
||||
} else {
|
||||
// start < 0 <= random
|
||||
unsigned long long abs_start = safe_abs(start);
|
||||
unsigned long long diff = (random + abs_start);
|
||||
result = diff * step - abs_start;
|
||||
}
|
||||
|
||||
if (choice) {
|
||||
streams.out.append_format(L"%ls\n", argv[w.woptind + result]);
|
||||
} else {
|
||||
streams.out.append_format(L"%lld\n", result);
|
||||
}
|
||||
return STATUS_CMD_OK;
|
||||
}
|
||||
|
||||
/// The exit builtin. Calls reader_exit to exit and returns the value specified.
|
||||
static int builtin_exit(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
||||
int argc = builtin_count_args(argv);
|
||||
|
|
191
src/builtin_random.cpp
Normal file
191
src/builtin_random.cpp
Normal file
|
@ -0,0 +1,191 @@
|
|||
// Implementation of the random builtin.
|
||||
#include "config.h" // IWYU pragma: keep
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
|
||||
#include "builtin.h"
|
||||
#include "builtin_random.h"
|
||||
#include "common.h"
|
||||
#include "fallback.h" // IWYU pragma: keep
|
||||
#include "io.h"
|
||||
#include "wgetopt.h"
|
||||
#include "wutil.h" // IWYU pragma: keep
|
||||
|
||||
struct random_opts {
|
||||
bool print_help = false;
|
||||
};
|
||||
|
||||
static const wchar_t *short_options = L"h";
|
||||
static const struct woption long_options[] = {{L"help", no_argument, NULL, 'h'},
|
||||
{NULL, 0, NULL, 0}};
|
||||
|
||||
static int parse_random_opts(struct random_opts *opts, int *optind, //!OCLINT(high ncss method)
|
||||
int argc, wchar_t **argv, parser_t &parser, io_streams_t &streams) {
|
||||
wchar_t *cmd = argv[0];
|
||||
int opt;
|
||||
wgetopter_t w;
|
||||
while ((opt = w.wgetopt_long(argc, argv, short_options, long_options, NULL)) != -1) {
|
||||
switch (opt) { //!OCLINT(too few branches)
|
||||
case 'h': {
|
||||
opts->print_help = true;
|
||||
return STATUS_CMD_OK;
|
||||
}
|
||||
case '?': {
|
||||
builtin_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]);
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
default: {
|
||||
DIE("unexpected retval from wgetopt_long");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*optind = w.woptind;
|
||||
return STATUS_CMD_OK;
|
||||
}
|
||||
|
||||
/// The random builtin generates random numbers.
|
||||
int builtin_random(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
||||
wchar_t *cmd = argv[0];
|
||||
int argc = builtin_count_args(argv);
|
||||
struct random_opts opts;
|
||||
|
||||
int optind;
|
||||
int retval = parse_random_opts(&opts, &optind, argc, argv, parser, streams);
|
||||
if (retval != STATUS_CMD_OK) return retval;
|
||||
|
||||
if (opts.print_help) {
|
||||
builtin_print_help(parser, streams, cmd, streams.out);
|
||||
return STATUS_CMD_OK;
|
||||
}
|
||||
|
||||
static bool seeded = false;
|
||||
static std::minstd_rand engine;
|
||||
if (!seeded) {
|
||||
// seed engine with 2*32 bits of random data
|
||||
// for the 64 bits of internal state of minstd_rand
|
||||
std::random_device rd;
|
||||
std::seed_seq seed{rd(), rd()};
|
||||
engine.seed(seed);
|
||||
seeded = true;
|
||||
}
|
||||
|
||||
int arg_count = argc - optind;
|
||||
long long start, end;
|
||||
unsigned long long step;
|
||||
bool choice = false;
|
||||
if (arg_count >= 1 && !wcscmp(argv[optind], L"choice")) {
|
||||
if (arg_count == 1) {
|
||||
streams.err.append_format(L"%ls: nothing to choose from\n", cmd);
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
choice = true;
|
||||
start = 1;
|
||||
step = 1;
|
||||
end = arg_count - 1;
|
||||
} else {
|
||||
bool parse_error = false;
|
||||
auto parse_ll = [&](const wchar_t *str) {
|
||||
long long ll = fish_wcstoll(str);
|
||||
if (errno) {
|
||||
streams.err.append_format(L"%ls: %ls is not a valid integer\n", cmd, str);
|
||||
parse_error = true;
|
||||
}
|
||||
return ll;
|
||||
};
|
||||
auto parse_ull = [&](const wchar_t *str) {
|
||||
unsigned long long ull = fish_wcstoull(str);
|
||||
if (errno) {
|
||||
streams.err.append_format(L"%ls: %ls is not a valid integer\n", cmd, str);
|
||||
parse_error = true;
|
||||
}
|
||||
return ull;
|
||||
};
|
||||
if (arg_count == 0) {
|
||||
start = 0;
|
||||
end = 32767;
|
||||
step = 1;
|
||||
} else if (arg_count == 1) {
|
||||
long long seed = parse_ll(argv[optind]);
|
||||
if (parse_error) return STATUS_INVALID_ARGS;
|
||||
engine.seed(static_cast<uint32_t>(seed));
|
||||
return STATUS_CMD_OK;
|
||||
} else if (arg_count == 2) {
|
||||
start = parse_ll(argv[optind]);
|
||||
step = 1;
|
||||
end = parse_ll(argv[optind + 1]);
|
||||
} else if (arg_count == 3) {
|
||||
start = parse_ll(argv[optind]);
|
||||
step = parse_ull(argv[optind + 1]);
|
||||
end = parse_ll(argv[optind + 2]);
|
||||
} else {
|
||||
streams.err.append_format(BUILTIN_ERR_TOO_MANY_ARGUMENTS, cmd);
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (parse_error) {
|
||||
return STATUS_INVALID_ARGS;
|
||||
} else if (start >= end) {
|
||||
streams.err.append_format(L"%ls: END must be greater than START\n", cmd);
|
||||
return STATUS_INVALID_ARGS;
|
||||
} else if (step == 0) {
|
||||
streams.err.append_format(L"%ls: STEP must be a positive integer\n", cmd);
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
}
|
||||
|
||||
// only for negative argument
|
||||
auto safe_abs = [](long long ll) -> unsigned long long {
|
||||
return -static_cast<unsigned long long>(ll);
|
||||
};
|
||||
long long real_end;
|
||||
if (start >= 0 || end < 0) {
|
||||
// 0 <= start <= end
|
||||
long long diff = end - start;
|
||||
// 0 <= diff <= LL_MAX
|
||||
real_end = start + static_cast<long long>(diff / step);
|
||||
} else {
|
||||
// start < 0 <= end
|
||||
unsigned long long abs_start = safe_abs(start);
|
||||
unsigned long long diff = (end + abs_start);
|
||||
real_end = diff / step - abs_start;
|
||||
}
|
||||
|
||||
if (!choice && start == real_end) {
|
||||
streams.err.append_format(L"%ls: range contains only one possible value\n", cmd);
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
|
||||
std::uniform_int_distribution<long long> dist(start, real_end);
|
||||
long long random = dist(engine);
|
||||
long long result;
|
||||
if (start >= 0) {
|
||||
// 0 <= start <= random <= end
|
||||
long long diff = random - start;
|
||||
// 0 < step * diff <= end - start <= LL_MAX
|
||||
result = start + static_cast<long long>(diff * step);
|
||||
} else if (random < 0) {
|
||||
// start <= random < 0
|
||||
long long diff = random - start;
|
||||
result = diff * step - safe_abs(start);
|
||||
} else {
|
||||
// start < 0 <= random
|
||||
unsigned long long abs_start = safe_abs(start);
|
||||
unsigned long long diff = (random + abs_start);
|
||||
result = diff * step - abs_start;
|
||||
}
|
||||
|
||||
if (choice) {
|
||||
streams.out.append_format(L"%ls\n", argv[optind + result]);
|
||||
} else {
|
||||
streams.out.append_format(L"%lld\n", result);
|
||||
}
|
||||
return STATUS_CMD_OK;
|
||||
}
|
9
src/builtin_random.h
Normal file
9
src/builtin_random.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
// Prototypes for executing builtin_random function.
|
||||
#ifndef FISH_BUILTIN_RANDOM_H
|
||||
#define FISH_BUILTIN_RANDOM_H
|
||||
|
||||
class parser_t;
|
||||
struct io_streams_t;
|
||||
|
||||
int builtin_random(parser_t &parser, io_streams_t &streams, wchar_t **argv);
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user