X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=make_cmd.c;h=d17b4d81dea7cfe62780b27581ee570a349f7c8f;hb=ccc6cda312fea9f0468ee65b8f368e9653e1380b;hp=85eb3d59efe7e1bb4248ade23d3594f63d4c8a61;hpb=726f63884db0132f01745f1fb4465e6621088ccf;p=platform%2Fupstream%2Fbash.git diff --git a/make_cmd.c b/make_cmd.c index 85eb3d5..d17b4d8 100644 --- a/make_cmd.c +++ b/make_cmd.c @@ -1,5 +1,5 @@ -/* make_cmd.c -- - Functions for making instances of the various parser constructs. */ +/* make_cmd.c -- Functions for making instances of the various + parser constructs. */ /* Copyright (C) 1989 Free Software Foundation, Inc. @@ -19,17 +19,23 @@ You should have received a copy of the GNU General Public License along with Bash; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "config.h" + #include #include "bashtypes.h" #include #include "filecntl.h" #include "bashansi.h" -#include "config.h" +#if defined (HAVE_UNISTD_H) +# include +#endif + #include "command.h" #include "general.h" #include "error.h" #include "flags.h" #include "make_cmd.h" +#include "variables.h" #include "subst.h" #include "input.h" #include "externs.h" @@ -42,47 +48,59 @@ extern int line_number, current_command_line_count; extern int disallow_filename_globbing; WORD_DESC * -make_word (string) +make_bare_word (string) char *string; { WORD_DESC *temp; temp = (WORD_DESC *)xmalloc (sizeof (WORD_DESC)); - temp->word = savestring (string); - temp->quoted = temp->dollar_present = temp->assignment = 0; - - while (*string) + if (*string) + temp->word = savestring (string); + else { - if (*string == '$') temp->dollar_present = 1; - -#ifdef OLDCODE - if (member (*string, "'`\\\"")) - { - temp->quoted = 1; - if (*string == '\\') - string++; - } -#else - switch (*string) - { - case '\\': - string++; - /*FALLTHROUGH*/ - case '\'': - case '`': - case '"': - temp->quoted = 1; - break; - } -#endif - - if (*string) - (string++); + temp->word = xmalloc (1); + temp->word[0] = '\0'; } + + temp->flags = 0; return (temp); } WORD_DESC * +make_word_flags (w, string) + WORD_DESC *w; + char *string; +{ + register char *s; + + for (s = string; *s; s++) + switch (*s) + { + case '$': + w->flags |= W_HASDOLLAR; + break; + case '\\': + break; /* continue the loop */ + case '\'': + case '`': + case '"': + w->flags |= W_QUOTED; + break; + } + return (w); +} + +WORD_DESC * +make_word (string) + char *string; +{ + WORD_DESC *temp; + + temp = make_bare_word (string); + return (make_word_flags (temp, string)); +} + +WORD_DESC * make_word_from_token (token) int token; { @@ -112,24 +130,14 @@ add_string_to_list (string, list) char *string; WORD_LIST *list; { - WORD_LIST *temp = (WORD_LIST *)xmalloc (sizeof (WORD_LIST)); + WORD_LIST *temp; + + temp = (WORD_LIST *)xmalloc (sizeof (WORD_LIST)); temp->word = make_word (string); temp->next = list; return (temp); } -#if 0 -WORD_DESC * -coerce_to_word (number) - int number; -{ - char string[24]; - - sprintf (string, "%d", number); - return (make_word (string)); -} -#endif - COMMAND * make_command (type, pointer) enum command_type type; @@ -140,8 +148,7 @@ make_command (type, pointer) temp = (COMMAND *)xmalloc (sizeof (COMMAND)); temp->type = type; temp->value.Simple = pointer; - temp->value.Simple->flags = 0; - temp->flags = 0; + temp->value.Simple->flags = temp->flags = 0; temp->redirects = (REDIRECT *)NULL; return (temp); } @@ -160,44 +167,50 @@ command_connect (com1, com2, connector) return (make_command (cm_connection, (SIMPLE_COM *)temp)); } -COMMAND * -make_for_command (name, map_list, action) +static COMMAND * +make_for_or_select (type, name, map_list, action) + enum command_type type; WORD_DESC *name; WORD_LIST *map_list; COMMAND *action; { - FOR_COM *temp = (FOR_COM *)xmalloc (sizeof (FOR_COM)); + FOR_COM *temp; + temp = (FOR_COM *)xmalloc (sizeof (FOR_COM)); temp->flags = 0; temp->name = name; temp->map_list = map_list; temp->action = action; - return (make_command (cm_for, (SIMPLE_COM *)temp)); + return (make_command (type, (SIMPLE_COM *)temp)); } -#if defined (SELECT_COMMAND) COMMAND * -make_select_command (name, map_list, action) +make_for_command (name, map_list, action) WORD_DESC *name; WORD_LIST *map_list; COMMAND *action; { - SELECT_COM *temp = (SELECT_COM *)xmalloc (sizeof (SELECT_COM)); - - temp->flags = 0; - temp->name = name; - temp->map_list = map_list; - temp->action = action; - return (make_command (cm_select, (SIMPLE_COM *)temp)); + return (make_for_or_select (cm_for, name, map_list, action)); } + +COMMAND * +make_select_command (name, map_list, action) + WORD_DESC *name; + WORD_LIST *map_list; + COMMAND *action; +{ +#if defined (SELECT_COMMAND) + return (make_for_or_select (cm_select, name, map_list, action)); #endif +} COMMAND * make_group_command (command) COMMAND *command; { - GROUP_COM *temp = (GROUP_COM *)xmalloc (sizeof (GROUP_COM)); + GROUP_COM *temp; + temp = (GROUP_COM *)xmalloc (sizeof (GROUP_COM)); temp->command = command; return (make_command (cm_group, (SIMPLE_COM *)temp)); } @@ -245,9 +258,9 @@ make_if_command (test, true_case, false_case) } static COMMAND * -make_until_or_while (test, action, which) - COMMAND *test, *action; +make_until_or_while (which, test, action) enum command_type which; + COMMAND *test, *action; { WHILE_COM *temp; @@ -262,31 +275,34 @@ COMMAND * make_while_command (test, action) COMMAND *test, *action; { - return (make_until_or_while (test, action, cm_while)); + return (make_until_or_while (cm_while, test, action)); } COMMAND * make_until_command (test, action) COMMAND *test, *action; { - return (make_until_or_while (test, action, cm_until)); + return (make_until_or_while (cm_until, test, action)); } COMMAND * make_bare_simple_command () { COMMAND *command; - SIMPLE_COM *temp = (SIMPLE_COM *)xmalloc (sizeof (SIMPLE_COM)); + SIMPLE_COM *temp; + + command = (COMMAND *)xmalloc (sizeof (COMMAND)); + command->value.Simple = temp = (SIMPLE_COM *)xmalloc (sizeof (SIMPLE_COM)); temp->flags = 0; temp->line = line_number; temp->words = (WORD_LIST *)NULL; temp->redirects = (REDIRECT *)NULL; - command = (COMMAND *)xmalloc (sizeof (COMMAND)); + command->type = cm_simple; command->redirects = (REDIRECT *)NULL; command->flags = 0; - command->value.Simple = temp; + return (command); } @@ -302,7 +318,7 @@ make_simple_command (element, command) malloc doesn't return zeroed space. */ if (!command) command = make_bare_simple_command (); - + if (element.word) { WORD_LIST *tw = (WORD_LIST *)xmalloc (sizeof (WORD_LIST)); @@ -324,127 +340,112 @@ make_simple_command (element, command) return (command); } -#define POSIX_HERE_DOCUMENTS +/* Because we are Bourne compatible, we read the input for this + << or <<- redirection now, from wherever input is coming from. + We store the input read into a WORD_DESC. Replace the text of + the redirectee.word with the new input text. If <<- is on, + then remove leading TABS from each line. */ void make_here_document (temp) REDIRECT *temp; { - int kill_leading = 0; + int kill_leading, redir_len; + char *redir_word, *document, *full_line; + int document_index, document_size, delim_unquoted; + + if (temp->instruction != r_deblank_reading_until && + temp->instruction != r_reading_until) + { + internal_error ("make_here_document: bad instruction type %d", temp->instruction); + return; + } + + kill_leading = temp->instruction == r_deblank_reading_until; + + document = (char *)NULL; + document_index = document_size = 0; + + /* Quote removal is the only expansion performed on the delimiter + for here documents, making it an extremely special case. */ + redir_word = string_quote_removal (temp->redirectee.filename->word, 0); + + /* redirection_expand will return NULL if the expansion results in + multiple words or no words. Check for that here, and just abort + this here document if it does. */ + if (redir_word) + redir_len = strlen (redir_word); + else + { + temp->here_doc_eof = xmalloc (1); + temp->here_doc_eof[0] = '\0'; + goto document_done; + } - switch (temp->instruction) + free (temp->redirectee.filename->word); + temp->here_doc_eof = redir_word; + + /* Read lines from wherever lines are coming from. + For each line read, if kill_leading, then kill the + leading tab characters. + If the line matches redir_word exactly, then we have + manufactured the document. Otherwise, add the line to the + list of lines in the document. */ + + /* If the here-document delimiter was quoted, the lines should + be read verbatim from the input. If it was not quoted, we + need to perform backslash-quoted newline removal. */ + delim_unquoted = (temp->redirectee.filename->flags & W_QUOTED) == 0; + while (full_line = read_secondary_line (delim_unquoted)) { - /* Because we are Bourne compatible, we read the input for this - << or <<- redirection now, from wherever input is coming from. - We store the input read into a WORD_DESC. Replace the text of - the redirectee.word with the new input text. If <<- is on, - then remove leading TABS from each line. */ - - case r_deblank_reading_until: /* <<-foo */ - kill_leading++; - /* FALLTHROUGH */ - case r_reading_until: /* <= document_size) { - char *redir_word; - int redir_len; - char *full_line; - char *document = (char *)NULL; - int document_index = 0, document_size = 0; - -#if !defined (POSIX_HERE_DOCUMENTS) - /* Because of Bourne shell semantics, we turn off globbing, but - only for this style of redirection. I feel a little ill. */ - { - int old_value = disallow_filename_globbing; - disallow_filename_globbing = 1; - - redir_word = redirection_expand (temp->redirectee.filename); - - disallow_filename_globbing = old_value; - } -#else /* POSIX_HERE_DOCUMENTS */ - /* Quote removal is the only expansion performed on the delimiter - for here documents, making it an extremely special case. I - still feel ill. */ - redir_word = string_quote_removal (temp->redirectee.filename->word, 0); -#endif /* POSIX_HERE_DOCUMENTS */ - - /* redirection_expand will return NULL if the expansion results in - multiple words or no words. Check for that here, and just abort - this here document if it does. */ - if (redir_word) - redir_len = strlen (redir_word); - else - { - temp->here_doc_eof = savestring (""); - goto document_done; - } - - free (temp->redirectee.filename->word); - temp->here_doc_eof = redir_word; - - /* Read lines from wherever lines are coming from. - For each line read, if kill_leading, then kill the - leading tab characters. - If the line matches redir_word exactly, then we have - manufactured the document. Otherwise, add the line to the - list of lines in the document. */ - - /* If the here-document delimiter was quoted, the lines should - be read verbatim from the input. If it was not quoted, we - need to perform backslash-quoted newline removal. */ - while (full_line = read_secondary_line - (temp->redirectee.filename->quoted == 0)) - { - register char *line = full_line; - int len; - - line_number++; - - if (kill_leading && *line) - { - /* Hack: To be compatible with some Bourne shells, we - check the word before stripping the whitespace. This - is a hack, though. */ - if (STREQN (line, redir_word, redir_len) && - line[redir_len] == '\n') - goto document_done; - - while (*line == '\t') - line++; - } - - if (!*line) - continue; - - if (STREQN (line, redir_word, redir_len) && - line[redir_len] == '\n') - goto document_done; - - len = strlen (line); - if (len + document_index >= document_size) - { - document_size = document_size ? 2 * (document_size + len) - : 1000; /* XXX */ - document = xrealloc (document, document_size); - } - - /* len is guaranteed to be > 0 because of the check for line - being an empty string before the call to strlen. */ - FASTCOPY (line, document + document_index, len); - document_index += len; - } - - document_done: - if (document) - document[document_index] = '\0'; - else - document = savestring (""); - temp->redirectee.filename->word = document; + document_size = document_size ? 2 * (document_size + len) : 1000; + document = xrealloc (document, document_size); } + + /* len is guaranteed to be > 0 because of the check for line + being an empty string before the call to strlen. */ + FASTCOPY (line, document + document_index, len); + document_index += len; + } + +document_done: + if (document) + document[document_index] = '\0'; + else + { + document = xmalloc (1); + document[0] = '\0'; } + temp->redirectee.filename->word = document; } - -/* Generate a REDIRECT from SOURCE, DEST, and INSTRUCTION. + +/* Generate a REDIRECT from SOURCE, DEST, and INSTRUCTION. INSTRUCTION is the instruction type, SOURCE is a file descriptor, and DEST is a file descriptor or a WORD_DESC *. */ REDIRECT * @@ -483,13 +484,13 @@ make_redirection (source, instruction, dest_and_filename) case r_reading_until: /* << foo */ break; + case r_close_this: /* <&- */ case r_duplicating_input: /* 1<&2 */ case r_duplicating_output: /* 1>&2 */ - case r_close_this: /* <&- */ case r_duplicating_input_word: /* 1<&$foo */ case r_duplicating_output_word: /* 1>&$foo */ break; - + case r_err_and_out: /* command &>filename */ temp->flags = O_TRUNC | O_WRONLY | O_CREAT; break; @@ -499,8 +500,7 @@ make_redirection (source, instruction, dest_and_filename) break; default: - programming_error ("Redirection instruction from yyparse () '%d' is\n\ -out of range in make_redirection ().", instruction); + programming_error ("make_redirection: redirection instruction `%d' out of range", instruction); abort (); break; } @@ -508,16 +508,19 @@ out of range in make_redirection ().", instruction); } COMMAND * -make_function_def (name, command) +make_function_def (name, command, lineno, lstart) WORD_DESC *name; COMMAND *command; + int lineno, lstart; { FUNCTION_DEF *temp; temp = (FUNCTION_DEF *)xmalloc (sizeof (FUNCTION_DEF)); temp->command = command; temp->name = name; - command->line = line_number - current_command_line_count + 1; + temp->line = lineno; + temp->ignore = 0; + command->line = lstart; return (make_command (cm_function_def, (SIMPLE_COM *)temp)); } @@ -529,42 +532,18 @@ clean_simple_command (command) COMMAND *command; { if (command->type != cm_simple) - { - programming_error - ("clean_simple_command () got a command with type %d.", command->type); - } + programming_error ("clean_simple_command: bad command type `%d'", command->type); else { command->value.Simple->words = REVERSE_LIST (command->value.Simple->words, WORD_LIST *); - command->value.Simple->redirects = + command->value.Simple->redirects = REVERSE_LIST (command->value.Simple->redirects, REDIRECT *); } return (command); } -/* Cons up a new array of words. The words are taken from LIST, - which is a WORD_LIST *. Absolutely everything is malloc'ed, - so you should free everything in this array when you are done. - The array is NULL terminated. */ -char ** -make_word_array (list) - WORD_LIST *list; -{ - int count = list_length (list); - char **array = (char **)xmalloc ((1 + count) * sizeof (char *)); - - for (count = 0; list; count++) - { - array[count] = xmalloc (1 + strlen (list->word->word)); - strcpy (array[count], list->word->word); - list = list->next; - } - array[count] = (char *)NULL; - return (array); -} - /* The Yacc grammar productions have a problem, in that they take a list followed by an ampersand (`&') and do a simple command connection, making the entire list effectively asynchronous, instead of just