home *** CD-ROM | disk | FTP | other *** search
- /* alias.c -- Not a full alias, but just the kind that we use in the
- shell. Csh style alias is somewhere else. */
-
- /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-
- Bash is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 1, or (at your option) any later
- version.
-
- Bash is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- 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 "general.h"
- #include "alias.h"
-
- /* The number of slots to allocate when we need new slots. */
- #define alias_list_grow_amount 50
-
- /* Non-zero means expand all words on the line. Otherwise, expand
- after first expansion if the expansion ends in a space. */
- int alias_expand_all = 0;
-
- /* The list of aliases that we have. */
- ASSOC **aliases = (ASSOC **)NULL;
-
- /* The number of slots in the above list. */
- static int aliases_size = 0;
-
- /* The number of aliases that are in existence. */
- static int aliases_length = 0;
-
- /* The last alias index found with find_alias (). */
- static int last_alias_index = 0;
-
- /* Scan the list of aliases looking for one with NAME. Return NULL
- if the alias doesn't exist, else a pointer to the assoc. */
- ASSOC *
- find_alias (name)
- char *name;
- {
- register int i;
-
- for (i = 0; i < aliases_length; i++)
- if (strcmp (name, aliases[i]->name) == 0)
- return (aliases[last_alias_index = i]);
-
- return ((ASSOC *)NULL);
- }
-
- /* Return the value of the alias for NAME, or NULL if there is none. */
- char *
- get_alias_value (name)
- char *name;
- {
- ASSOC *alias = find_alias (name);
- if (alias)
- return (alias->value);
- else
- return ((char *)NULL);
- }
-
- /* Make a new alias from NAME and VALUE. If NAME can be found,
- then replace its value. */
- void
- add_alias (name, value)
- char *name, *value;
- {
- ASSOC *temp = find_alias (name);
-
- if (temp)
- {
- free (temp->value);
- temp->value = savestring (value);
- }
- else
- {
- temp = (ASSOC *)xmalloc (sizeof (ASSOC));
- temp->name = savestring (name);
- temp->value = savestring (value);
-
- if ((aliases_length + 1) >= aliases_size)
- {
- if (!aliases)
- aliases =
- (ASSOC **)xmalloc ((aliases_size = alias_list_grow_amount)
- * sizeof (ASSOC *));
- else
- aliases =
- (ASSOC **)xrealloc (aliases,
- (aliases_size += alias_list_grow_amount)
- * sizeof (ASSOC *));
- }
- aliases[aliases_length++] = temp;
- aliases[aliases_length] = (ASSOC *)NULL;
- }
- }
-
- /* Remove the alias with name NAME from the alias list. Returns
- the index of the removed alias, or -1 if the alias didn't exist. */
- int
- remove_alias (name)
- char *name;
- {
- register int i;
-
- if (!find_alias (name))
- return (-1);
-
- i = last_alias_index;
- free (aliases[i]->name);
- free (aliases[i]->value);
- free (aliases[i]);
-
- for (; i < aliases_length; i++)
- aliases[i] = aliases[i + 1];
-
- aliases_length--;
- aliases[aliases_length] = (ASSOC *)NULL;
-
- return (last_alias_index);
- }
-
- /* Delete all aliases. */
- delete_all_aliases ()
- {
- register int i;
-
- for (i = 0; i < aliases_length; i++)
- {
- free (aliases[i]->name);
- free (aliases[i]->value);
- free (aliases[i]);
- aliases[i] = (ASSOC *)NULL;
- }
-
- aliases_length = 0;
- }
-
- /* Return non-zero if CHARACTER is a member of the class of characters
- that are self-delimiting in the shell. */
- self_delimiting (character)
- int character;
- {
- return (member (character, " \t\n\r;|&("));
- }
-
- /* Return a new line, with any aliases substituted. */
- char *
- alias_expand (string)
- char *string;
- {
- int line_len = 1 + strlen (string);
- char *line = (char *)xmalloc (line_len);
- register int i, j, start, delimiter;
- char *token = (char *)alloca (line_len);
- int tl, real_start, in_command_position;
- int expand_next = 1;
- ASSOC *alias;
-
- line[0] = i = 0;
-
- /* Find the next word in line. If it has an alias, substitute
- the alias value. If the value ends in ` ', then try again
- with the next word. Else, if there is no value, or if
- the value does not end in space, we are done. */
-
- next_word:
-
- token[0] = 0;
- /* Skip leading whitespace (or separator characters).
- But save it in the output. */
- for (start = i; string[i]; i++)
- {
- if (whitespace (string[i]))
- continue;
-
- if (self_delimiting (string[i]))
- {
- expand_next++;
- continue;
- }
- break;
- }
-
- if (start == i && string[i] == '\0')
- return (line);
-
- j = strlen (line);
- if (1 + j + (i - start) >= line_len)
- line = (char *)xrealloc (line, line_len += (50 + (i - start)));
- strncpy (line + j, string + start, i - start);
- line[j + (i - start)] = '\0';
-
- real_start = i;
-
- in_command_position = (self_delimiting (string[i]) || expand_next);
- expand_next = 0;
-
- /* From here to next separator character is a token. */
- delimiter = 0;
-
- for (start = i; string[i]; i++)
- {
- switch (string[i])
- {
- case '\\':
- if (string[i + 1])
- {
- i++;
- continue;
- }
- break;
-
- case '"':
- case '\'':
- if (!delimiter)
- delimiter = string[i];
- else if (delimiter == string[i])
- delimiter = 0;
- break;
- }
-
- if (!delimiter &&
- (whitespace (string[i]) || self_delimiting (string[i])))
- break;
- }
-
- tl = strlen (token);
- strncpy (token + tl, string + start, i - start);
- token [tl += (i - start)] = '\0';
-
- /* See if this word has a substitution. If it does, do the expansion,
- but only if we are expanding all words, or if we are in a location
- where an expansion is supposed to take place. */
- alias = find_alias (token);
-
- if (alias && (in_command_position || alias_expand_all))
- {
- char *v = alias->value;
- int l = strlen (v);
-
- /* +3 because we possibly add one more character below. */
- if ((l + 3) > line_len - strlen (line))
- line = (char *)xrealloc (line, line_len += (50 + l));
-
- strcat (line, v);
-
- if ((l && whitespace (v[l - 1])) || alias_expand_all)
- {
- if (l && whitespace (v[l -1]))
- line[strlen (line) - 1] = '\0';
-
- expand_next = 1;
- }
- }
- else
- {
- int ll = strlen (line), tl = i - real_start;
- /* int tl = strlen (token); */
-
- if (ll + tl + 2 > line_len)
- line = (char *)xrealloc (line, line_len += 50 + ll + tl);
-
- strncpy (line + ll, string + real_start, tl);
- line[ll + tl] = '\0';
- /* strcat (line, token); */
- }
- goto next_word;
- }
-