diff options
author | 2013-12-27 01:38:43 -0800 | |
---|---|---|
committer | 2013-12-27 01:38:43 -0800 | |
commit | 6ce4b344e45baaa06bf593a5c0983da7a22eb64e (patch) | |
tree | 2358b60e771c42d29aeb26a03dd95f22cbd8ca15 /builtin.cpp | |
parent | a6ca809a4e4873f3fd16e4a763001a109afc2185 (diff) |
Hook up for statements, if statements, and function definition in new
parser
Diffstat (limited to 'builtin.cpp')
-rw-r--r-- | builtin.cpp | 307 |
1 files changed, 306 insertions, 1 deletions
diff --git a/builtin.cpp b/builtin.cpp index a97efdbf..11036e37 100644 --- a/builtin.cpp +++ b/builtin.cpp @@ -165,7 +165,7 @@ static const io_chain_t *real_io; /** Counts the number of non null pointers in the specified array */ -static int builtin_count_args(wchar_t **argv) +static int builtin_count_args(const wchar_t * const * argv) { int argc = 1; while (argv[argc] != NULL) @@ -1752,6 +1752,307 @@ static int builtin_pwd(parser_t &parser, wchar_t **argv) } } +/* This is nearly identical to builtin_function, and is intended to be the successor (with no block manipulation, no function/end split) */ +int define_function(parser_t &parser, const wcstring_list_t &args, const wcstring &contents, wcstring *out_err) +{ + assert(out_err != NULL); + + /* Hackish const_cast matches the one in builtin_run */ + const null_terminated_array_t<wchar_t> argv_array(args); + wchar_t **argv = const_cast<wchar_t **>(argv_array.get()); + + int argc = builtin_count_args(argv); + int res=STATUS_BUILTIN_OK; + wchar_t *desc=0; + std::vector<event_t> events; + std::auto_ptr<wcstring_list_t> named_arguments(NULL); + + wchar_t *name = 0; + bool shadows = true; + + woptind=0; + + const struct woption long_options[] = + { + { L"description", required_argument, 0, 'd' }, + { L"on-signal", required_argument, 0, 's' }, + { L"on-job-exit", required_argument, 0, 'j' }, + { L"on-process-exit", required_argument, 0, 'p' }, + { L"on-variable", required_argument, 0, 'v' }, + { L"on-event", required_argument, 0, 'e' }, + { L"help", no_argument, 0, 'h' }, + { L"argument-names", no_argument, 0, 'a' }, + { L"no-scope-shadowing", no_argument, 0, 'S' }, + { 0, 0, 0, 0 } + }; + + while (1 && (!res)) + { + int opt_index = 0; + + int opt = wgetopt_long(argc, + argv, + L"d:s:j:p:v:e:haS", + long_options, + &opt_index); + if (opt == -1) + break; + + switch (opt) + { + case 0: + if (long_options[opt_index].flag != 0) + break; + + + + append_format(*out_err, + BUILTIN_ERR_UNKNOWN, + argv[0], + long_options[opt_index].name); + + res = 1; + break; + + case 'd': + desc=woptarg; + break; + + case 's': + { + int sig = wcs2sig(woptarg); + + if (sig < 0) + { + append_format(*out_err, + _(L"%ls: Unknown signal '%ls'\n"), + argv[0], + woptarg); + res=1; + break; + } + events.push_back(event_t::signal_event(sig)); + break; + } + + case 'v': + { + if (wcsvarname(woptarg)) + { + append_format(*out_err, + _(L"%ls: Invalid variable name '%ls'\n"), + argv[0], + woptarg); + res=STATUS_BUILTIN_ERROR; + break; + } + + events.push_back(event_t::variable_event(woptarg)); + break; + } + + + case 'e': + { + events.push_back(event_t::generic_event(woptarg)); + break; + } + + case 'j': + case 'p': + { + pid_t pid; + wchar_t *end; + event_t e(EVENT_ANY); + + if ((opt == 'j') && + (wcscasecmp(woptarg, L"caller") == 0)) + { + int job_id = -1; + + if (is_subshell) + { + size_t block_idx = 0; + + /* Find the outermost substitution block */ + for (block_idx = 0; ; block_idx++) + { + const block_t *b = parser.block_at_index(block_idx); + if (b == NULL || b->type() == SUBST) + break; + } + + /* Go one step beyond that, to get to the caller */ + const block_t *caller_block = parser.block_at_index(block_idx + 1); + if (caller_block != NULL && caller_block->job != NULL) + { + job_id = caller_block->job->job_id; + } + } + + if (job_id == -1) + { + append_format(*out_err, + _(L"%ls: Cannot find calling job for event handler\n"), + argv[0]); + res=1; + } + else + { + e.type = EVENT_JOB_ID; + e.param1.job_id = job_id; + } + + } + else + { + errno = 0; + pid = fish_wcstoi(woptarg, &end, 10); + if (errno || !end || *end) + { + append_format(*out_err, + _(L"%ls: Invalid process id %ls\n"), + argv[0], + woptarg); + res=1; + break; + } + + + e.type = EVENT_EXIT; + e.param1.pid = (opt=='j'?-1:1)*abs(pid); + } + if (res) + { + /* nothing */ + } + else + { + events.push_back(e); + } + break; + } + + case 'a': + if (named_arguments.get() == NULL) + named_arguments.reset(new wcstring_list_t); + break; + + case 'S': + shadows = 0; + break; + + case 'h': + builtin_print_help(parser, argv[0], stdout_buffer); + return STATUS_BUILTIN_OK; + + case '?': + builtin_unknown_option(parser, argv[0], argv[woptind-1]); + res = 1; + break; + + } + + } + + if (!res) + { + + if (argc == woptind) + { + append_format(*out_err, + _(L"%ls: Expected function name\n"), + argv[0]); + res=1; + } + else if (wcsfuncname(argv[woptind])) + { + append_format(*out_err, + _(L"%ls: Illegal function name '%ls'\n"), + argv[0], + argv[woptind]); + + res=1; + } + else if (parser_keywords_is_reserved(argv[woptind])) + { + + append_format(*out_err, + _(L"%ls: The name '%ls' is reserved,\nand can not be used as a function name\n"), + argv[0], + argv[woptind]); + + res=1; + } + else if (! wcslen(argv[woptind])) + { + append_format(*out_err, _(L"%ls: No function name given\n"), argv[0]); + } + else + { + + name = argv[woptind++]; + + if (named_arguments.get()) + { + while (woptind < argc) + { + if (wcsvarname(argv[woptind])) + { + append_format(*out_err, + _(L"%ls: Invalid variable name '%ls'\n"), + argv[0], + argv[woptind]); + res = STATUS_BUILTIN_ERROR; + break; + } + + named_arguments->push_back(argv[woptind++]); + } + } + else if (woptind != argc) + { + append_format(*out_err, + _(L"%ls: Expected one argument, got %d\n"), + argv[0], + argc); + res=1; + + } + } + } + + if (res) + { + builtin_print_help(parser, argv[0], *out_err); + } + else + { + function_data_t d; + + d.name = name; + if (desc) + d.description = desc; + d.events.swap(events); + d.shadows = shadows; + if (named_arguments.get()) + d.named_arguments.swap(*named_arguments); + + for (size_t i=0; i<d.events.size(); i++) + { + event_t &e = d.events.at(i); + e.function_name = d.name; + } + + d.definition = contents.c_str(); + + // TODO: fix def_offset inside function_add + function_add(d, parser); + } + + return res; +} + /** The function builtin, used for providing subroutines. It calls various functions from function.c to perform any heavy lifting. @@ -1983,6 +2284,10 @@ static int builtin_function(parser_t &parser, wchar_t **argv) res=1; } + else if (! wcslen(argv[woptind])) + { + append_format(stderr_buffer, _(L"%ls: No function name given\n"), argv[0]); + } else { |