aboutsummaryrefslogtreecommitdiffhomepage
path: root/builtin.cpp
diff options
context:
space:
mode:
authorGravatar ridiculousfish <corydoras@ridiculousfish.com>2013-12-27 01:38:43 -0800
committerGravatar ridiculousfish <corydoras@ridiculousfish.com>2013-12-27 01:38:43 -0800
commit6ce4b344e45baaa06bf593a5c0983da7a22eb64e (patch)
tree2358b60e771c42d29aeb26a03dd95f22cbd8ca15 /builtin.cpp
parenta6ca809a4e4873f3fd16e4a763001a109afc2185 (diff)
Hook up for statements, if statements, and function definition in new
parser
Diffstat (limited to 'builtin.cpp')
-rw-r--r--builtin.cpp307
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
{