aboutsummaryrefslogtreecommitdiffhomepage
path: root/builtin.cpp
diff options
context:
space:
mode:
authorGravatar ridiculousfish <corydoras@ridiculousfish.com>2014-03-02 13:11:17 -0800
committerGravatar ridiculousfish <corydoras@ridiculousfish.com>2014-03-02 13:11:17 -0800
commit6b3a37c59785872eb62112e9045e7cc2b2e2406e (patch)
treef1d6ef0ac083f4ba319bc34d1b17bf9ec35e244f /builtin.cpp
parentb187125b636c14253d626e4c2470f89e192168cf (diff)
Remove obviated builtins and additional cleanup of old parser
Diffstat (limited to 'builtin.cpp')
-rw-r--r--builtin.cpp619
1 files changed, 7 insertions, 612 deletions
diff --git a/builtin.cpp b/builtin.cpp
index 8b8b8d5c..930d10be 100644
--- a/builtin.cpp
+++ b/builtin.cpp
@@ -1728,7 +1728,7 @@ 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) */
+/** Adds a function to the function set. It calls into function.cpp to perform any heavy lifting. */
int define_function(parser_t &parser, const wcstring_list_t &c_args, const wcstring &contents, wcstring *out_err)
{
assert(out_err != NULL);
@@ -2035,338 +2035,6 @@ int define_function(parser_t &parser, const wcstring_list_t &c_args, const wcstr
}
/**
- The function builtin, used for providing subroutines.
- It calls various functions from function.c to perform any heavy lifting.
-*/
-static int builtin_function(parser_t &parser, wchar_t **argv)
-{
- /* Hack hack hack - with the new parser, this is only invoked for help */
- if (parser_use_ast())
- {
- builtin_print_help(parser, argv[0], stdout_buffer);
- return STATUS_BUILTIN_OK;
- }
-
- 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;
-
- function_def_block_t * const fdb = new function_def_block_t();
- parser.push_block(fdb);
-
- 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(stderr_buffer,
- 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(stderr_buffer,
- _(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(stderr_buffer,
- _(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(stderr_buffer,
- _(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(stderr_buffer,
- _(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':
- parser.pop_block();
- parser.push_block(new fake_block_t());
- 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(stderr_buffer,
- _(L"%ls: Expected function name\n"),
- argv[0]);
- res=1;
- }
- else if (wcsfuncname(argv[woptind]))
- {
- append_format(stderr_buffer,
- _(L"%ls: Illegal function name '%ls'\n"),
- argv[0],
- argv[woptind]);
-
- res=1;
- }
- else if (parser_keywords_is_reserved(argv[woptind]))
- {
-
- append_format(stderr_buffer,
- _(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(stderr_buffer, _(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(stderr_buffer,
- _(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(stderr_buffer,
- _(L"%ls: Expected one argument, got %d\n"),
- argv[0],
- argc);
- res=1;
-
- }
- }
- }
-
- if (res)
- {
- size_t i;
- size_t chars=0;
-
- builtin_print_help(parser, argv[0], stderr_buffer);
- const wchar_t *cfa = _(L"Current functions are: ");
- stderr_buffer.append(cfa);
- chars += wcslen(cfa);
-
- wcstring_list_t names = function_get_names(0);
- sort(names.begin(), names.end());
-
- for (i=0; i<names.size(); i++)
- {
- const wchar_t *nxt = names.at(i).c_str();
- size_t l = wcslen(nxt + 2);
- if (chars+l > (size_t)common_get_width())
- {
- chars = 0;
- stderr_buffer.push_back(L'\n');
- }
-
- stderr_buffer.append(nxt);
- stderr_buffer.append(L" ");
- }
- stderr_buffer.push_back(L'\n');
-
- parser.pop_block();
- parser.push_block(new fake_block_t());
- }
- else
- {
- function_data_t &d = fdb->function_data;
-
- 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;
- }
- }
-
- parser.current_block()->tok_pos = parser.get_pos();
- parser.current_block()->skip = 1;
-
- return STATUS_BUILTIN_OK;
-}
-
-/**
The random builtin. For generating random numbers.
*/
static int builtin_random(parser_t &parser, wchar_t **argv)
@@ -3714,195 +3382,6 @@ static int builtin_for(parser_t &parser, wchar_t **argv)
}
/**
- The begin builtin. Creates a new block.
-*/
-static int builtin_begin(parser_t &parser, wchar_t **argv)
-{
- parser.push_block(new scope_block_t(BEGIN));
- parser.current_block()->tok_pos = parser.get_pos();
- return proc_get_last_status();
-}
-
-
-/**
- Builtin for ending a block of code, such as a for-loop or an if statement.
-
- The end command is whare a lot of the block-level magic happens.
-*/
-static int builtin_end(parser_t &parser, wchar_t **argv)
-{
- if (! parser.block_at_index(1))
- {
- append_format(stderr_buffer,
- _(L"%ls: Not inside of block\n"),
- argv[0]);
-
- builtin_print_help(parser, argv[0], stderr_buffer);
- return STATUS_BUILTIN_ERROR;
- }
- else
- {
- /**
- By default, 'end' kills the current block scope. But if we
- are rewinding a loop, this should be set to false, so that
- variables in the current loop scope won't die between laps.
- */
- bool kill_block = true;
-
- block_t * const current_block = parser.current_block();
- switch (current_block->type())
- {
- case WHILE:
- {
- /*
- If this is a while loop, we rewind the loop unless
- it's the last lap, in which case we continue.
- */
- if (!(current_block->skip && (current_block->loop_status != LOOP_CONTINUE)))
- {
- current_block->loop_status = LOOP_NORMAL;
- current_block->skip = 0;
- kill_block = false;
- parser.set_pos(current_block->tok_pos);
- while_block_t *blk = static_cast<while_block_t *>(current_block);
- blk->status = WHILE_TEST_AGAIN;
- }
-
- break;
- }
-
- case IF:
- /* Always return success (#1061) */
- proc_set_last_status(0);
- break;
-
- case SUBST:
- case BEGIN:
- case SWITCH:
- case FAKE:
- /*
- Nothing special happens at the end of these commands. The scope just ends.
- */
-
- break;
-
- case FOR:
- {
- /*
- set loop variable to next element, and rewind to the beginning of the block.
- */
- for_block_t *fb = static_cast<for_block_t *>(current_block);
- wcstring_list_t &for_vars = fb->sequence;
- if (current_block->loop_status == LOOP_BREAK)
- {
- for_vars.clear();
- }
-
- if (! for_vars.empty())
- {
- const wcstring val = for_vars.back();
- for_vars.pop_back();
- const wcstring &for_variable = fb->variable;
- env_set(for_variable, val.c_str(), ENV_LOCAL);
- current_block->loop_status = LOOP_NORMAL;
- current_block->skip = 0;
-
- kill_block = false;
- parser.set_pos(current_block->tok_pos);
- }
- break;
- }
-
- case FUNCTION_DEF:
- {
- function_def_block_t *fdb = static_cast<function_def_block_t *>(current_block);
- function_data_t &d = fdb->function_data;
-
- if (d.name.empty())
- {
- /* Disallow empty function names */
- append_format(stderr_buffer, _(L"%ls: No function name given\n"), argv[0]);
-
- /* Return an error via a crummy way. Don't just return here, since we need to pop the block. */
- proc_set_last_status(STATUS_BUILTIN_ERROR);
- }
- else
- {
- /**
- Copy the text from the beginning of the function
- until the end command and use as the new definition
- for the specified function
- */
-
- wchar_t *def = wcsndup(parser.get_buffer()+current_block->tok_pos,
- parser.get_job_pos()-current_block->tok_pos);
- d.definition = def;
-
- function_add(d, parser);
- free(def);
- }
- }
- break;
-
- default:
- assert(false); //should never get here
- break;
-
- }
- if (kill_block)
- {
- parser.pop_block();
- }
-
- /*
- If everything goes ok, return status of last command to execute.
- */
- return proc_get_last_status();
- }
-}
-
-/**
- Builtin for executing commands if an if statement is false
-*/
-static int builtin_else(parser_t &parser, wchar_t **argv)
-{
- bool block_ok = false;
- if_block_t *if_block = NULL;
- if (parser.current_block() != NULL && parser.current_block()->type() == IF)
- {
- if_block = static_cast<if_block_t *>(parser.current_block());
- /* Ensure that we're past IF but not up to an ELSE */
- if (if_block->if_expr_evaluated && ! if_block->else_evaluated)
- {
- block_ok = true;
- }
- }
-
- if (! block_ok)
- {
- append_format(stderr_buffer,
- _(L"%ls: Not inside of 'if' block\n"),
- argv[0]);
- builtin_print_help(parser, argv[0], stderr_buffer);
- return STATUS_BUILTIN_ERROR;
- }
- else
- {
- /* Run the else block if the IF expression was false and so were all the ELSEIF expressions (if any) */
- bool run_else = ! if_block->any_branch_taken;
- if_block->skip = ! run_else;
- if_block->else_evaluated = true;
- env_pop();
- env_push(false);
- }
-
- /*
- If everything goes ok, return status of last command to execute.
- */
- return proc_get_last_status();
-}
-
-/**
This function handles both the 'continue' and the 'break' builtins
that are used for loop control.
*/
@@ -4038,90 +3517,6 @@ static int builtin_return(parser_t &parser, wchar_t **argv)
}
/**
- Builtin for executing one of several blocks of commands depending
- on the value of an argument.
-*/
-static int builtin_switch(parser_t &parser, wchar_t **argv)
-{
- int res=STATUS_BUILTIN_OK;
- int argc = builtin_count_args(argv);
-
- /* Hackish - if we have no arguments other than the command, we are a "naked invocation" and we just print help */
- if (argc == 1)
- {
- builtin_print_help(parser, argv[0], stdout_buffer);
- return STATUS_BUILTIN_ERROR;
- }
-
- if (argc != 2)
- {
- append_format(stderr_buffer,
- _(L"%ls: Expected exactly one argument, got %d\n"),
- argv[0],
- argc-1);
-
- builtin_print_help(parser, argv[0], stderr_buffer);
- res=1;
- parser.push_block(new fake_block_t());
- }
- else
- {
- parser.push_block(new switch_block_t(argv[1]));
- parser.current_block()->skip=1;
- res = proc_get_last_status();
- }
-
- return res;
-}
-
-/**
- Builtin used together with the switch builtin for conditional
- execution
-*/
-static int builtin_case(parser_t &parser, wchar_t **argv)
-{
- int argc = builtin_count_args(argv);
- int i;
- wchar_t *unescaped=0;
-
- if (parser.current_block()->type() != SWITCH)
- {
- append_format(stderr_buffer,
- _(L"%ls: 'case' command while not in switch block\n"),
- argv[0]);
- builtin_print_help(parser, argv[0], stderr_buffer);
- return STATUS_BUILTIN_ERROR;
- }
-
- parser.current_block()->skip = 1;
- switch_block_t *sb = static_cast<switch_block_t *>(parser.current_block());
- if (sb->switch_taken)
- {
- return proc_get_last_status();
- }
-
- const wcstring &switch_value = sb->switch_value;
- for (i=1; i<argc; i++)
- {
- int match;
-
- unescaped = parse_util_unescape_wildcards(argv[i]);
- match = wildcard_match(switch_value, unescaped);
- free(unescaped);
-
- if (match)
- {
- parser.current_block()->skip = 0;
- sb->switch_taken = true;
- break;
- }
- }
-
- return proc_get_last_status();
-}
-
-
-/**
History of commands executed by user
*/
static int builtin_history(parser_t &parser, wchar_t **argv)
@@ -4317,14 +3712,14 @@ static const builtin_data_t builtin_datas[]=
{ L"[", &builtin_test, N_(L"Test a condition") },
{ L"__fish_parse", &builtin_parse, N_(L"Try out the new parser") },
{ L"and", &builtin_generic, N_(L"Execute command if previous command suceeded") },
- { L"begin", &builtin_begin, N_(L"Create a block of code") },
+ { L"begin", &builtin_generic, N_(L"Create a block of code") },
{ L"bg", &builtin_bg, N_(L"Send job to background") },
{ L"bind", &builtin_bind, N_(L"Handle fish key bindings") },
{ L"block", &builtin_block, N_(L"Temporarily block delivery of events") },
{ L"break", &builtin_break_continue, N_(L"Stop the innermost loop") },
{ L"breakpoint", &builtin_breakpoint, N_(L"Temporarily halt execution of a script and launch an interactive debug prompt") },
{ L"builtin", &builtin_builtin, N_(L"Run a builtin command instead of a function") },
- { L"case", &builtin_case, N_(L"Conditionally execute a block of commands") },
+ { L"case", &builtin_generic, N_(L"Conditionally execute a block of commands") },
{ L"cd", &builtin_cd, N_(L"Change working directory") },
{ L"command", &builtin_generic, N_(L"Run a program instead of a function or builtin") },
{ L"commandline", &builtin_commandline, N_(L"Set or get the commandline") },
@@ -4333,14 +3728,14 @@ static const builtin_data_t builtin_datas[]=
{ L"continue", &builtin_break_continue, N_(L"Skip the rest of the current lap of the innermost loop") },
{ L"count", &builtin_count, N_(L"Count the number of arguments") },
{ L"echo", &builtin_echo, N_(L"Print arguments") },
- { L"else", &builtin_else, N_(L"Evaluate block if condition is false") },
+ { L"else", &builtin_generic, N_(L"Evaluate block if condition is false") },
{ L"emit", &builtin_emit, N_(L"Emit an event") },
- { L"end", &builtin_end, N_(L"End a block of commands") },
+ { L"end", &builtin_generic, N_(L"End a block of commands") },
{ L"exec", &builtin_generic, N_(L"Run command in current process") },
{ L"exit", &builtin_exit, N_(L"Exit the shell") },
{ L"fg", &builtin_fg, N_(L"Send job to foreground") },
{ L"for", &builtin_for, N_(L"Perform a set of commands multiple times") },
- { L"function", &builtin_function, N_(L"Define a new function") },
+ { L"function", &builtin_generic, N_(L"Define a new function") },
{ L"functions", &builtin_functions, N_(L"List or remove functions") },
{ L"history", &builtin_history, N_(L"History of commands executed by user") },
{ L"if", &builtin_generic, N_(L"Evaluate block if condition is true") },
@@ -4356,7 +3751,7 @@ static const builtin_data_t builtin_datas[]=
{ L"set_color", &builtin_set_color, N_(L"Set the terminal color") },
{ L"source", &builtin_source, N_(L"Evaluate contents of file") },
{ L"status", &builtin_status, N_(L"Return status information about fish") },
- { L"switch", &builtin_switch, N_(L"Conditionally execute a block of commands") },
+ { L"switch", &builtin_generic, N_(L"Conditionally execute a block of commands") },
{ L"test", &builtin_test, N_(L"Test a condition") },
{ L"ulimit", &builtin_ulimit, N_(L"Set or get the shells resource usage limits") },
{ L"while", &builtin_generic, N_(L"Perform a command multiple times") }