From: Chet Ramey Date: Sun, 4 Dec 2011 03:48:33 +0000 (-0500) Subject: commit bash-20060517 snapshot X-Git-Tag: bash-3.2-alpha~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ccb43410f3c5291bd3283ea676ce0a0068ef639e;p=thirdparty%2Fbash.git commit bash-20060517 snapshot --- diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 3bf355c2d..543128612 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -13384,3 +13384,38 @@ subst.c doc/{bash.1,bashref.texi} - clarifed `trap' description to make it clear that trapped signals that are not set to SIG_IGN are reset when a subshell is created + + 5/18 + ---- +locale.c + - change reset_locale_vars to call setlocale (LC_ALL, "") if LANG + is unset or NULL + - if LANG is unset or NULL, reset the export environment before + calling setlocale in reset_locale_vars, and trust that it will + change the environment setlocale() inspects + + 5/21 + ---- +lib/readline/history.c + - new function, HIST_ENTRY *alloc_history_entry (char *string, char *ts); + creates a new history entry with text STRING and timestamp TS (both + of which may be NULL) + - new function, HIST_ENTRY *copy_history_entry (HIST_ENTRY *hist), + which copies the line and timestamp entries to new memory but just + copies the data member, since that's an opaque pointer + - new function, void replace_history_data (int which, histdata_t *old, histdata_t *new) + which replaces the `data' member of specified history entries with + NEW, as long as it is OLD. WHICH says which history entries to + modify + - add calls to replace_history_data in rl_free_undo_list and + rl_do_undo + +lib/readline/undo.c + - new function, alloc_undo_entry (enum undo_code what, int start, int end, char *text) + takes care of allocating and populating a struct for an individual + undo list entry + - new function: _rl_copy_undo_entry(UNDO_LIST *entry) + - new function: _rl_copy_undo_list(UNDO_LIST *head) + +lib/readline/rlprivate.h + - new extern declarations for _rl_copy_undo_{entry,list} diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~ index d70563dc5..9bb6c1de7 100644 --- a/CWRU/CWRU.chlog~ +++ b/CWRU/CWRU.chlog~ @@ -13372,3 +13372,48 @@ arrayfunc.c arrayfunc.h - new extern declarations for expand_compound_array_assignment and assign_compound_array_list + +subst.c + - in do_compound_assignment, call expand_compound_array_assignment + before creating the local variable so a previous inherited + value can be used when expanding the rhs of the compound assignment + statement + + 5/11 + ---- +doc/{bash.1,bashref.texi} + - clarifed `trap' description to make it clear that trapped signals + that are not set to SIG_IGN are reset when a subshell is created + + 5/18 + ---- +locale.c + - change reset_locale_vars to call setlocale (LC_ALL, "") if LANG + is unset or NULL + - if LANG is unset or NULL, reset the export environment before + calling setlocale in reset_locale_vars, and trust that it will + change the environment setlocale() inspects + + 5/21 + ---- +lib/readline/history.c + - new function, HIST_ENTRY *alloc_history_entry (char *string, char *ts); + creates a new history entry with text STRING and timestamp TS (both + of which may be NULL) + - new function, HIST_ENTRY *copy_history_entry (HIST_ENTRY *hist), + which copies the line and timestamp entries to new memory but just + copies the data member, since that's an opaque pointer + - new function, void replace_history_data (int which, histdata_t *old, histdata_t *new) + which replaces the `data' member of specified history entries with + NEW, as long as it is OLD. WHICH says which history entries to + modify + - add calls to replace_history_data in rl_free_undo_list and + rl_do_undo + +lib/readline/undo.c + - new function, alloc_undo_entry (enum undo_code what, int start, int end, char *text) + takes care of allocating and populating a struct for an individual + undo list entry + + + diff --git a/execute_cmd.c b/execute_cmd.c index e52905d54..38833e3bf 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -2503,6 +2503,7 @@ execute_cond_node (cond) } else if (cond->type == COND_BINARY) { + rmatch = 0; patmatch = ((cond->op->word[1] == '=') && (cond->op->word[2] == '\0') && (cond->op->word[0] == '!' || cond->op->word[0] == '=') || (cond->op->word[0] == '=' && cond->op->word[1] == '\0')); @@ -2514,7 +2515,7 @@ execute_cond_node (cond) arg1 = cond_expand_word (cond->left->op, 0); if (arg1 == 0) arg1 = nullstr; - arg2 = cond_expand_word (cond->right->op, patmatch); + arg2 = cond_expand_word (cond->right->op, patmatch||rmatch); if (arg2 == 0) arg2 = nullstr; diff --git a/execute_cmd.c~ b/execute_cmd.c~ index 57e9d1136..e52905d54 100644 --- a/execute_cmd.c~ +++ b/execute_cmd.c~ @@ -214,6 +214,8 @@ static int special_builtin_failed; report the correct line number. Kind of a hack. */ static int showing_function_line; +static int line_number_for_err_trap; + /* For catching RETURN in a function. */ int return_catch_flag; int return_catch_value; @@ -665,7 +667,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, if (command->flags & CMD_STDIN_REDIR) command->value.Simple->flags |= CMD_STDIN_REDIR; - line_number = command->value.Simple->line; + line_number_for_err_trap = line_number = command->value.Simple->line; exec_result = execute_simple_command (command->value.Simple, pipe_in, pipe_out, asynchronous, fds_to_close); diff --git a/lib/readline/history.c b/lib/readline/history.c index a538f91c0..1ccf4db78 100644 --- a/lib/readline/history.c +++ b/lib/readline/history.c @@ -209,6 +209,22 @@ history_get (offset) : the_history[local_index]; } +HIST_ENTRY * +alloc_history_entry (string, ts) + char *string; + char *ts; +{ + HIST_ENTRY *temp; + + temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); + + temp->line = string ? savestring (string) : string; + temp->data = (char *)NULL; + temp->timestamp = ts; + + return temp; +} + time_t history_get_time (hist) HIST_ENTRY *hist; @@ -290,11 +306,7 @@ add_history (string) } } - temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); - temp->line = savestring (string); - temp->data = (char *)NULL; - - temp->timestamp = hist_inittime (); + temp = alloc_history_entry (string, hist_inittime ()); the_history[history_length] = (HIST_ENTRY *)NULL; the_history[history_length - 1] = temp; @@ -328,6 +340,26 @@ free_history_entry (hist) free (hist); return (x); } + +HIST_ENTRY * +copy_history_entry (hist) + HIST_ENTRY *hist; +{ + HIST_ENTRY *ret; + char *ts; + + if (hist == 0) + return hist; + + ret = alloc_history_entry (hist->line, (char *)NULL); + + ts = hist->timestamp ? savestring (hist->timestamp) : hist->timestamp; + ret->timestamp = ts; + + ret->data = hist->data; + + return ret; +} /* Make the history entry at WHICH have LINE and DATA. This returns the old entry so you can dispose of the data. In the case of an @@ -354,6 +386,51 @@ replace_history_entry (which, line, data) return (old_value); } +/* Replace the DATA in the specified history entries, replacing OLD with + NEW. WHICH says which one(s) to replace: WHICH == -1 means to replace + all of the history entries where entry->data == OLD; WHICH == -2 means + to replace the `newest' history entry where entry->data == OLD; and + WHICH >= 0 means to replace that particular history entry's data, as + long as it matches OLD. */ +void +replace_history_data (which,old, new) + int which; + histdata_t *old, *new; +{ + HIST_ENTRY *entry; + register int i, last; + + if (which < -2 || which >= history_length || history_length == 0 || the_history == 0) + return; + + if (which >= 0) + { + entry = the_history[which]; + if (entry && entry->data == old) + entry->data = new; + return; + } + + last = -1; + for (i = 0; i < history_length; i++) + { + entry = the_history[i]; + if (entry == 0) + continue; + if (entry->data == old) + { + last = i; + if (which == -1) + entry->data = new; + } + } + if (which == -2 && last >= 0) + { + entry = the_history[last]; + entry->data = new; /* XXX - we don't check entry->old */ + } +} + /* Remove history element WHICH from the history. The removed element is returned to you so you can free the line, data, and containing structure. */ diff --git a/lib/readline/history.c~ b/lib/readline/history.c~ new file mode 100644 index 000000000..e18b410a6 --- /dev/null +++ b/lib/readline/history.c~ @@ -0,0 +1,486 @@ +/* history.c -- standalone history library */ + +/* Copyright (C) 1989-2005 Free Software Foundation, Inc. + + This file contains the GNU History Library (the Library), a set of + routines for managing the text of previously typed lines. + + The Library 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 2, or (at your option) + any later version. + + The Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +/* The goal is to make the implementation transparent, so that you + don't have to know what data types are used, just what functions + you can call. I think I have done that. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif +# include +#endif + +#include "history.h" +#include "histlib.h" + +#include "xmalloc.h" + +/* The number of slots to increase the_history by. */ +#define DEFAULT_HISTORY_GROW_SIZE 50 + +static char *hist_inittime PARAMS((void)); + +/* **************************************************************** */ +/* */ +/* History Functions */ +/* */ +/* **************************************************************** */ + +/* An array of HIST_ENTRY. This is where we store the history. */ +static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL; + +/* Non-zero means that we have enforced a limit on the amount of + history that we save. */ +static int history_stifled; + +/* The current number of slots allocated to the input_history. */ +static int history_size; + +/* If HISTORY_STIFLED is non-zero, then this is the maximum number of + entries to remember. */ +int history_max_entries; +int max_input_history; /* backwards compatibility */ + +/* The current location of the interactive history pointer. Just makes + life easier for outside callers. */ +int history_offset; + +/* The number of strings currently stored in the history list. */ +int history_length; + +/* The logical `base' of the history array. It defaults to 1. */ +int history_base = 1; + +/* Return the current HISTORY_STATE of the history. */ +HISTORY_STATE * +history_get_history_state () +{ + HISTORY_STATE *state; + + state = (HISTORY_STATE *)xmalloc (sizeof (HISTORY_STATE)); + state->entries = the_history; + state->offset = history_offset; + state->length = history_length; + state->size = history_size; + state->flags = 0; + if (history_stifled) + state->flags |= HS_STIFLED; + + return (state); +} + +/* Set the state of the current history array to STATE. */ +void +history_set_history_state (state) + HISTORY_STATE *state; +{ + the_history = state->entries; + history_offset = state->offset; + history_length = state->length; + history_size = state->size; + if (state->flags & HS_STIFLED) + history_stifled = 1; +} + +/* Begin a session in which the history functions might be used. This + initializes interactive variables. */ +void +using_history () +{ + history_offset = history_length; +} + +/* Return the number of bytes that the primary history entries are using. + This just adds up the lengths of the_history->lines and the associated + timestamps. */ +int +history_total_bytes () +{ + register int i, result; + + for (i = result = 0; the_history && the_history[i]; i++) + result += HISTENT_BYTES (the_history[i]); + + return (result); +} + +/* Returns the magic number which says what history element we are + looking at now. In this implementation, it returns history_offset. */ +int +where_history () +{ + return (history_offset); +} + +/* Make the current history item be the one at POS, an absolute index. + Returns zero if POS is out of range, else non-zero. */ +int +history_set_pos (pos) + int pos; +{ + if (pos > history_length || pos < 0 || !the_history) + return (0); + history_offset = pos; + return (1); +} + +/* Return the current history array. The caller has to be carefull, since this + is the actual array of data, and could be bashed or made corrupt easily. + The array is terminated with a NULL pointer. */ +HIST_ENTRY ** +history_list () +{ + return (the_history); +} + +/* Return the history entry at the current position, as determined by + history_offset. If there is no entry there, return a NULL pointer. */ +HIST_ENTRY * +current_history () +{ + return ((history_offset == history_length) || the_history == 0) + ? (HIST_ENTRY *)NULL + : the_history[history_offset]; +} + +/* Back up history_offset to the previous history entry, and return + a pointer to that entry. If there is no previous entry then return + a NULL pointer. */ +HIST_ENTRY * +previous_history () +{ + return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL; +} + +/* Move history_offset forward to the next history entry, and return + a pointer to that entry. If there is no next entry then return a + NULL pointer. */ +HIST_ENTRY * +next_history () +{ + return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset]; +} + +/* Return the history entry which is logically at OFFSET in the history array. + OFFSET is relative to history_base. */ +HIST_ENTRY * +history_get (offset) + int offset; +{ + int local_index; + + local_index = offset - history_base; + return (local_index >= history_length || local_index < 0 || the_history == 0) + ? (HIST_ENTRY *)NULL + : the_history[local_index]; +} + +time_t +history_get_time (hist) + HIST_ENTRY *hist; +{ + char *ts; + time_t t; + + if (hist == 0 || hist->timestamp == 0) + return 0; + ts = hist->timestamp; + if (ts[0] != history_comment_char) + return 0; + t = (time_t) atol (ts + 1); /* XXX - should use strtol() here */ + return t; +} + +static char * +hist_inittime () +{ + time_t t; + char ts[64], *ret; + + t = (time_t) time ((time_t *)0); +#if defined (HAVE_VSNPRINTF) /* assume snprintf if vsnprintf exists */ + snprintf (ts, sizeof (ts) - 1, "X%lu", (unsigned long) t); +#else + sprintf (ts, "X%lu", (unsigned long) t); +#endif + ret = savestring (ts); + ret[0] = history_comment_char; + + return ret; +} + +/* Place STRING at the end of the history list. The data field + is set to NULL. */ +void +add_history (string) + const char *string; +{ + HIST_ENTRY *temp; + + if (history_stifled && (history_length == history_max_entries)) + { + register int i; + + /* If the history is stifled, and history_length is zero, + and it equals history_max_entries, we don't save items. */ + if (history_length == 0) + return; + + /* If there is something in the slot, then remove it. */ + if (the_history[0]) + (void) free_history_entry (the_history[0]); + + /* Copy the rest of the entries, moving down one slot. */ + for (i = 0; i < history_length; i++) + the_history[i] = the_history[i + 1]; + + history_base++; + } + else + { + if (history_size == 0) + { + history_size = DEFAULT_HISTORY_GROW_SIZE; + the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *)); + history_length = 1; + } + else + { + if (history_length == (history_size - 1)) + { + history_size += DEFAULT_HISTORY_GROW_SIZE; + the_history = (HIST_ENTRY **) + xrealloc (the_history, history_size * sizeof (HIST_ENTRY *)); + } + history_length++; + } + } + + temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); + temp->line = savestring (string); + temp->data = (char *)NULL; + + temp->timestamp = hist_inittime (); + + the_history[history_length] = (HIST_ENTRY *)NULL; + the_history[history_length - 1] = temp; +} + +/* Change the time stamp of the most recent history entry to STRING. */ +void +add_history_time (string) + const char *string; +{ + HIST_ENTRY *hs; + + hs = the_history[history_length - 1]; + FREE (hs->timestamp); + hs->timestamp = savestring (string); +} + +/* Free HIST and return the data so the calling application can free it + if necessary and desired. */ +histdata_t +free_history_entry (hist) + HIST_ENTRY *hist; +{ + histdata_t x; + + if (hist == 0) + return ((histdata_t) 0); + FREE (hist->line); + FREE (hist->timestamp); + x = hist->data; + free (hist); + return (x); +} + +/* Make the history entry at WHICH have LINE and DATA. This returns + the old entry so you can dispose of the data. In the case of an + invalid WHICH, a NULL pointer is returned. */ +HIST_ENTRY * +replace_history_entry (which, line, data) + int which; + const char *line; + histdata_t data; +{ + HIST_ENTRY *temp, *old_value; + + if (which < 0 || which >= history_length) + return ((HIST_ENTRY *)NULL); + + temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); + old_value = the_history[which]; + + temp->line = savestring (line); + temp->data = data; + temp->timestamp = savestring (old_value->timestamp); + the_history[which] = temp; + + return (old_value); +} + +/* Replace the DATA in the specified history entries, replacing OLD with + NEW. WHICH says which one(s) to replace: WHICH == -1 means to replace + all of the history entries where entry->data == OLD; WHICH == -2 means + to replace the `newest' history entry where entry->data == OLD; and + WHICH >= 0 means to replace that particular history entry's data, as + long as it matches OLD. */ +void +replace_history_data (which,old, new) + int which; + histdata_t *old, *new; +{ + HIST_ENTRY *entry; + register int i, last; + + if (which < -2 || which >= history_length || history_length == 0 || the_history == 0) + return; + + if (which >= 0) + { + entry = the_history[which]; + if (entry && entry->data == old) + entry->data = new; + return; + } + + last = -1; + for (i = 0; i < history_length; i++) + { + entry = the_history[i]; + if (entry == 0) + continue; + if (entry->data == old) + { + last = i; + if (which == -1) + entry->data = new; + } + } + if (which == -2 && last >= 0) + { + entry = the_history[last]; + entry->data = new; /* XXX - we don't check entry->old */ + } +} + +/* Remove history element WHICH from the history. The removed + element is returned to you so you can free the line, data, + and containing structure. */ +HIST_ENTRY * +remove_history (which) + int which; +{ + HIST_ENTRY *return_value; + register int i; + + if (which < 0 || which >= history_length || history_length == 0 || the_history == 0) + return ((HIST_ENTRY *)NULL); + + return_value = the_history[which]; + + for (i = which; i < history_length; i++) + the_history[i] = the_history[i + 1]; + + history_length--; + + return (return_value); +} + +/* Stifle the history list, remembering only MAX number of lines. */ +void +stifle_history (max) + int max; +{ + register int i, j; + + if (max < 0) + max = 0; + + if (history_length > max) + { + /* This loses because we cannot free the data. */ + for (i = 0, j = history_length - max; i < j; i++) + free_history_entry (the_history[i]); + + history_base = i; + for (j = 0, i = history_length - max; j < max; i++, j++) + the_history[j] = the_history[i]; + the_history[j] = (HIST_ENTRY *)NULL; + history_length = j; + } + + history_stifled = 1; + max_input_history = history_max_entries = max; +} + +/* Stop stifling the history. This returns the previous maximum + number of history entries. The value is positive if the history + was stifled, negative if it wasn't. */ +int +unstifle_history () +{ + if (history_stifled) + { + history_stifled = 0; + return (history_max_entries); + } + else + return (-history_max_entries); +} + +int +history_is_stifled () +{ + return (history_stifled); +} + +void +clear_history () +{ + register int i; + + /* This loses because we cannot free the data. */ + for (i = 0; i < history_length; i++) + { + free_history_entry (the_history[i]); + the_history[i] = (HIST_ENTRY *)NULL; + } + + history_offset = history_length = 0; +} diff --git a/lib/readline/rlprivate.h b/lib/readline/rlprivate.h index 1c216ead1..d85fa9f9a 100644 --- a/lib/readline/rlprivate.h +++ b/lib/readline/rlprivate.h @@ -309,6 +309,10 @@ extern int _rl_char_search_internal PARAMS((int, int, int)); #endif extern int _rl_set_mark_at_pos PARAMS((int)); +/* undo.c */ +extern UNDO_LIST *_rl_copy_undo_entry PARAMS((UNDO_LIST *)); +extern UNDO_LIST *_rl_copy_undo_list PARAMS((UNDO_LIST *)); + /* util.c */ extern int _rl_abort_internal PARAMS((void)); extern char *_rl_strindex PARAMS((const char *, const char *)); diff --git a/lib/readline/rlprivate.h~ b/lib/readline/rlprivate.h~ new file mode 100644 index 000000000..1c216ead1 --- /dev/null +++ b/lib/readline/rlprivate.h~ @@ -0,0 +1,420 @@ +/* rlprivate.h -- functions and variables global to the readline library, + but not intended for use by applications. */ + +/* Copyright (C) 1999-2005 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library 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 2, or + (at your option) any later version. + + The GNU Readline Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if !defined (_RL_PRIVATE_H_) +#define _RL_PRIVATE_H_ + +#include "rlconf.h" /* for VISIBLE_STATS */ +#include "rlstdc.h" +#include "posixjmp.h" /* defines procenv_t */ + +/************************************************************************* + * * + * Global structs undocumented in texinfo manual and not in readline.h * + * * + *************************************************************************/ +/* search types */ +#define RL_SEARCH_ISEARCH 0x01 /* incremental search */ +#define RL_SEARCH_NSEARCH 0x02 /* non-incremental search */ +#define RL_SEARCH_CSEARCH 0x04 /* intra-line char search */ + +/* search flags */ +#define SF_REVERSE 0x01 +#define SF_FOUND 0x02 +#define SF_FAILED 0x04 + +typedef struct __rl_search_context +{ + int type; + int sflags; + + char *search_string; + int search_string_index; + int search_string_size; + + char **lines; + char *allocated_line; + int hlen; + int hindex; + + int save_point; + int save_mark; + int save_line; + int last_found_line; + char *prev_line_found; + + UNDO_LIST *save_undo_list; + + int history_pos; + int direction; + + int lastc; +#if defined (HANDLE_MULTIBYTE) + char mb[MB_LEN_MAX]; +#endif + + char *sline; + int sline_len; + int sline_index; + + char *search_terminators; +} _rl_search_cxt; + +/* Callback data for reading numeric arguments */ +#define NUM_SAWMINUS 0x01 +#define NUM_SAWDIGITS 0x02 +#define NUM_READONE 0x04 + +typedef int _rl_arg_cxt; + +/* A context for reading key sequences longer than a single character when + using the callback interface. */ +#define KSEQ_DISPATCHED 0x01 +#define KSEQ_SUBSEQ 0x02 +#define KSEQ_RECURSIVE 0x04 + +typedef struct __rl_keyseq_context +{ + int flags; + int subseq_arg; + int subseq_retval; /* XXX */ + Keymap dmap; + + Keymap oldmap; + int okey; + struct __rl_keyseq_context *ocxt; + int childval; +} _rl_keyseq_cxt; + + /* fill in more as needed */ +/* `Generic' callback data and functions */ +typedef struct __rl_callback_generic_arg +{ + int count; + int i1, i2; + /* add here as needed */ +} _rl_callback_generic_arg; + +typedef int _rl_callback_func_t PARAMS((_rl_callback_generic_arg *)); + +/************************************************************************* + * * + * Global functions undocumented in texinfo manual and not in readline.h * + * * + *************************************************************************/ + +/************************************************************************* + * * + * Global variables undocumented in texinfo manual and not in readline.h * + * * + *************************************************************************/ + +/* complete.c */ +extern int rl_complete_with_tilde_expansion; +#if defined (VISIBLE_STATS) +extern int rl_visible_stats; +#endif /* VISIBLE_STATS */ + +/* readline.c */ +extern int rl_line_buffer_len; +extern int rl_arg_sign; +extern int rl_visible_prompt_length; +extern int readline_echoing_p; +extern int rl_key_sequence_length; +extern int rl_byte_oriented; + +extern _rl_keyseq_cxt *_rl_kscxt; + +/* display.c */ +extern int rl_display_fixed; + +/* parens.c */ +extern int rl_blink_matching_paren; + +/************************************************************************* + * * + * Global functions and variables unsed and undocumented * + * * + *************************************************************************/ + +/* kill.c */ +extern int rl_set_retained_kills PARAMS((int)); + +/* terminal.c */ +extern void _rl_set_screen_size PARAMS((int, int)); + +/* undo.c */ +extern int _rl_fix_last_undo_of_type PARAMS((int, int, int)); + +/* util.c */ +extern char *_rl_savestring PARAMS((const char *)); + +/************************************************************************* + * * + * Functions and variables private to the readline library * + * * + *************************************************************************/ + +/* NOTE: Functions and variables prefixed with `_rl_' are + pseudo-global: they are global so they can be shared + between files in the readline library, but are not intended + to be visible to readline callers. */ + +/************************************************************************* + * Undocumented private functions * + *************************************************************************/ + +#if defined(READLINE_CALLBACKS) + +/* readline.c */ +extern void readline_internal_setup PARAMS((void)); +extern char *readline_internal_teardown PARAMS((int)); +extern int readline_internal_char PARAMS((void)); + +extern _rl_keyseq_cxt *_rl_keyseq_cxt_alloc PARAMS((void)); +extern void _rl_keyseq_cxt_dispose PARAMS((_rl_keyseq_cxt *)); +extern void _rl_keyseq_chain_dispose PARAMS((void)); + +extern int _rl_dispatch_callback PARAMS((_rl_keyseq_cxt *)); + +/* callback.c */ +extern _rl_callback_generic_arg *_rl_callback_data_alloc PARAMS((int)); +extern void _rl_callback_data_dispose PARAMS((_rl_callback_generic_arg *)); + +#endif /* READLINE_CALLBACKS */ + +/* bind.c */ + +/* complete.c */ +extern char _rl_find_completion_word PARAMS((int *, int *)); +extern void _rl_free_match_list PARAMS((char **)); + +/* display.c */ +extern char *_rl_strip_prompt PARAMS((char *)); +extern void _rl_move_cursor_relative PARAMS((int, const char *)); +extern void _rl_move_vert PARAMS((int)); +extern void _rl_save_prompt PARAMS((void)); +extern void _rl_restore_prompt PARAMS((void)); +extern char *_rl_make_prompt_for_search PARAMS((int)); +extern void _rl_erase_at_end_of_line PARAMS((int)); +extern void _rl_clear_to_eol PARAMS((int)); +extern void _rl_clear_screen PARAMS((void)); +extern void _rl_update_final PARAMS((void)); +extern void _rl_redisplay_after_sigwinch PARAMS((void)); +extern void _rl_clean_up_for_exit PARAMS((void)); +extern void _rl_erase_entire_line PARAMS((void)); +extern int _rl_current_display_line PARAMS((void)); + +/* input.c */ +extern int _rl_any_typein PARAMS((void)); +extern int _rl_input_available PARAMS((void)); +extern int _rl_input_queued PARAMS((int)); +extern void _rl_insert_typein PARAMS((int)); +extern int _rl_unget_char PARAMS((int)); +extern int _rl_pushed_input_available PARAMS((void)); + +/* isearch.c */ +extern _rl_search_cxt *_rl_scxt_alloc PARAMS((int, int)); +extern void _rl_scxt_dispose PARAMS((_rl_search_cxt *, int)); + +extern int _rl_isearch_dispatch PARAMS((_rl_search_cxt *, int)); +extern int _rl_isearch_callback PARAMS((_rl_search_cxt *)); + +extern int _rl_search_getchar PARAMS((_rl_search_cxt *)); + +/* macro.c */ +extern void _rl_with_macro_input PARAMS((char *)); +extern int _rl_next_macro_key PARAMS((void)); +extern void _rl_push_executing_macro PARAMS((void)); +extern void _rl_pop_executing_macro PARAMS((void)); +extern void _rl_add_macro_char PARAMS((int)); +extern void _rl_kill_kbd_macro PARAMS((void)); + +/* misc.c */ +extern int _rl_arg_overflow PARAMS((void)); +extern void _rl_arg_init PARAMS((void)); +extern int _rl_arg_getchar PARAMS((void)); +extern int _rl_arg_callback PARAMS((_rl_arg_cxt)); +extern void _rl_reset_argument PARAMS((void)); + +extern void _rl_start_using_history PARAMS((void)); +extern int _rl_free_saved_history_line PARAMS((void)); +extern void _rl_set_insert_mode PARAMS((int, int)); + +/* nls.c */ +extern int _rl_init_eightbit PARAMS((void)); + +/* parens.c */ +extern void _rl_enable_paren_matching PARAMS((int)); + +/* readline.c */ +extern void _rl_init_line_state PARAMS((void)); +extern void _rl_set_the_line PARAMS((void)); +extern int _rl_dispatch PARAMS((int, Keymap)); +extern int _rl_dispatch_subseq PARAMS((int, Keymap, int)); +extern void _rl_internal_char_cleanup PARAMS((void)); + +/* rltty.c */ +extern int _rl_disable_tty_signals PARAMS((void)); +extern int _rl_restore_tty_signals PARAMS((void)); + +/* search.c */ +extern int _rl_nsearch_callback PARAMS((_rl_search_cxt *)); + +/* terminal.c */ +extern void _rl_get_screen_size PARAMS((int, int)); +extern int _rl_init_terminal_io PARAMS((const char *)); +#ifdef _MINIX +extern void _rl_output_character_function PARAMS((int)); +#else +extern int _rl_output_character_function PARAMS((int)); +#endif +extern void _rl_output_some_chars PARAMS((const char *, int)); +extern int _rl_backspace PARAMS((int)); +extern void _rl_enable_meta_key PARAMS((void)); +extern void _rl_control_keypad PARAMS((int)); +extern void _rl_set_cursor PARAMS((int, int)); + +/* text.c */ +extern void _rl_fix_point PARAMS((int)); +extern int _rl_replace_text PARAMS((const char *, int, int)); +extern int _rl_insert_char PARAMS((int, int)); +extern int _rl_overwrite_char PARAMS((int, int)); +extern int _rl_overwrite_rubout PARAMS((int, int)); +extern int _rl_rubout_char PARAMS((int, int)); +#if defined (HANDLE_MULTIBYTE) +extern int _rl_char_search_internal PARAMS((int, int, char *, int)); +#else +extern int _rl_char_search_internal PARAMS((int, int, int)); +#endif +extern int _rl_set_mark_at_pos PARAMS((int)); + +/* util.c */ +extern int _rl_abort_internal PARAMS((void)); +extern char *_rl_strindex PARAMS((const char *, const char *)); +extern int _rl_qsort_string_compare PARAMS((char **, char **)); +extern int (_rl_uppercase_p) PARAMS((int)); +extern int (_rl_lowercase_p) PARAMS((int)); +extern int (_rl_pure_alphabetic) PARAMS((int)); +extern int (_rl_digit_p) PARAMS((int)); +extern int (_rl_to_lower) PARAMS((int)); +extern int (_rl_to_upper) PARAMS((int)); +extern int (_rl_digit_value) PARAMS((int)); + +/* vi_mode.c */ +extern void _rl_vi_initialize_line PARAMS((void)); +extern void _rl_vi_reset_last PARAMS((void)); +extern void _rl_vi_set_last PARAMS((int, int, int)); +extern int _rl_vi_textmod_command PARAMS((int)); +extern void _rl_vi_done_inserting PARAMS((void)); + +/************************************************************************* + * Undocumented private variables * + *************************************************************************/ + +/* bind.c */ +extern const char *_rl_possible_control_prefixes[]; +extern const char *_rl_possible_meta_prefixes[]; + +/* callback.c */ +extern _rl_callback_func_t *_rl_callback_func; +extern _rl_callback_generic_arg *_rl_callback_data; + +/* complete.c */ +extern int _rl_complete_show_all; +extern int _rl_complete_show_unmodified; +extern int _rl_complete_mark_directories; +extern int _rl_complete_mark_symlink_dirs; +extern int _rl_print_completions_horizontally; +extern int _rl_completion_case_fold; +extern int _rl_match_hidden_files; +extern int _rl_page_completions; + +/* display.c */ +extern int _rl_vis_botlin; +extern int _rl_last_c_pos; +extern int _rl_suppress_redisplay; +extern int _rl_want_redisplay; +extern char *rl_display_prompt; + +/* isearch.c */ +extern char *_rl_isearch_terminators; + +extern _rl_search_cxt *_rl_iscxt; + +/* macro.c */ +extern char *_rl_executing_macro; + +/* misc.c */ +extern int _rl_history_preserve_point; +extern int _rl_history_saved_point; + +extern _rl_arg_cxt _rl_argcxt; + +/* readline.c */ +extern int _rl_horizontal_scroll_mode; +extern int _rl_mark_modified_lines; +extern int _rl_bell_preference; +extern int _rl_meta_flag; +extern int _rl_convert_meta_chars_to_ascii; +extern int _rl_output_meta_chars; +extern int _rl_bind_stty_chars; +extern char *_rl_comment_begin; +extern unsigned char _rl_parsing_conditionalized_out; +extern Keymap _rl_keymap; +extern FILE *_rl_in_stream; +extern FILE *_rl_out_stream; +extern int _rl_last_command_was_kill; +extern int _rl_eof_char; +extern procenv_t readline_top_level; + +/* search.c */ +extern _rl_search_cxt *_rl_nscxt; + +/* terminal.c */ +extern int _rl_enable_keypad; +extern int _rl_enable_meta; +extern char *_rl_term_clreol; +extern char *_rl_term_clrpag; +extern char *_rl_term_im; +extern char *_rl_term_ic; +extern char *_rl_term_ei; +extern char *_rl_term_DC; +extern char *_rl_term_up; +extern char *_rl_term_dc; +extern char *_rl_term_cr; +extern char *_rl_term_IC; +extern int _rl_screenheight; +extern int _rl_screenwidth; +extern int _rl_screenchars; +extern int _rl_terminal_can_insert; +extern int _rl_term_autowrap; + +/* undo.c */ +extern int _rl_doing_an_undo; +extern int _rl_undo_group_level; + +/* vi_mode.c */ +extern int _rl_vi_last_command; + +#endif /* _RL_PRIVATE_H_ */ diff --git a/lib/readline/undo.c b/lib/readline/undo.c index fedfa121f..9d9bd25ba 100644 --- a/lib/readline/undo.c +++ b/lib/readline/undo.c @@ -1,7 +1,7 @@ /* readline.c -- a general facility for reading lines of input with emacs style editing and completion. */ -/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. +/* Copyright (C) 1987, 1989, 1992, 2006 Free Software Foundation, Inc. This file is part of the GNU Readline Library, a library for reading lines of text with interactive input and history editing. @@ -50,6 +50,8 @@ #include "rlprivate.h" #include "xmalloc.h" +extern void replace_history_data PARAMS((int, histdata_t *, histdata_t *)); + /* Non-zero tells rl_delete_text and rl_insert_text to not add to the undo list. */ int _rl_doing_an_undo = 0; @@ -66,19 +68,35 @@ UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL; /* */ /* **************************************************************** */ -/* Remember how to undo something. Concatenate some undos if that - seems right. */ -void -rl_add_undo (what, start, end, text) +static UNDO_LIST * +alloc_undo_entry (what, start, end, text) enum undo_code what; int start, end; char *text; { - UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST)); + UNDO_LIST *temp; + + temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST)); temp->what = what; temp->start = start; temp->end = end; temp->text = text; + + temp->next = (UNDO_LIST *)NULL; + return temp; +} + +/* Remember how to undo something. Concatenate some undos if that + seems right. */ +void +rl_add_undo (what, start, end, text) + enum undo_code what; + int start, end; + char *text; +{ + UNDO_LIST *temp; + + temp = alloc_undo_entry (what, start, end, text); temp->next = rl_undo_list; rl_undo_list = temp; } @@ -87,9 +105,12 @@ rl_add_undo (what, start, end, text) void rl_free_undo_list () { + UNDO_LIST *release, *orig_list; + + orig_list = rl_undo_list; while (rl_undo_list) { - UNDO_LIST *release = rl_undo_list; + release = rl_undo_list; rl_undo_list = rl_undo_list->next; if (release->what == UNDO_DELETE) @@ -98,6 +119,43 @@ rl_free_undo_list () free (release); } rl_undo_list = (UNDO_LIST *)NULL; + replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL); +} + +UNDO_LIST * +_rl_copy_undo_entry (entry) + UNDO_LIST *entry; +{ + UNDO_LIST *new; + + new = alloc_undo_entry (entry->what, entry->start, entry->end, (char *)NULL); + new->text = entry->text ? savestring (entry->text) : 0; + return new; +} + +UNDO_LIST * +_rl_copy_undo_list (head) + UNDO_LIST *head; +{ + UNDO_LIST *list, *new, *roving, *c; + + list = head; + new = 0; + while (list) + { + c = _rl_copy_undo_entry (list); + if (new == 0) + roving = new = c; + else + { + roving->next = c; + roving = roving->next; + } + list = list->next; + } + + roving->next = 0; + return new; } /* Undo the next thing in the list. Return 0 if there @@ -161,6 +219,8 @@ rl_do_undo () release = rl_undo_list; rl_undo_list = rl_undo_list->next; + replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list); + free (release); } while (waiting_for_begin); diff --git a/lib/readline/undo.c~ b/lib/readline/undo.c~ new file mode 100644 index 000000000..a27089a26 --- /dev/null +++ b/lib/readline/undo.c~ @@ -0,0 +1,292 @@ +/* readline.c -- a general facility for reading lines of input + with emacs style editing and completion. */ + +/* Copyright (C) 1987, 1989, 1992, 2006 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library 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 2, or + (at your option) any later version. + + The GNU Readline Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include + +#if defined (HAVE_UNISTD_H) +# include /* for _POSIX_VERSION */ +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" + +/* Some standard library routines. */ +#include "readline.h" +#include "history.h" + +#include "rlprivate.h" +#include "xmalloc.h" + +extern void replace_history_data PARAMS((int, histdata_t *, histdata_t *)); + +/* Non-zero tells rl_delete_text and rl_insert_text to not add to + the undo list. */ +int _rl_doing_an_undo = 0; + +/* How many unclosed undo groups we currently have. */ +int _rl_undo_group_level = 0; + +/* The current undo list for THE_LINE. */ +UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL; + +/* **************************************************************** */ +/* */ +/* Undo, and Undoing */ +/* */ +/* **************************************************************** */ + +static UNDO_LIST * +alloc_undo_entry (what, start, end, text) + enum undo_code what; + int start, end; + char *text; +{ + UNDO_LIST *temp; + + temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST)); + temp->what = what; + temp->start = start; + temp->end = end; + temp->text = text; + + temp->next = (UNDO_LIST *)NULL; + return temp; +} + +/* Remember how to undo something. Concatenate some undos if that + seems right. */ +void +rl_add_undo (what, start, end, text) + enum undo_code what; + int start, end; + char *text; +{ + UNDO_LIST *temp; + + temp = alloc_undo_entry (what, start, end, text); + temp->next = rl_undo_list; + rl_undo_list = temp; +} + +/* Free the existing undo list. */ +void +rl_free_undo_list () +{ + UNDO_LIST *release, *orig_list; + + orig_list = rl_undo_list; + while (rl_undo_list) + { + release = rl_undo_list; + rl_undo_list = rl_undo_list->next; + + if (release->what == UNDO_DELETE) + free (release->text); + + free (release); + } + rl_undo_list = (UNDO_LIST *)NULL; + replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL); +} + +/* Undo the next thing in the list. Return 0 if there + is nothing to undo, or non-zero if there was. */ +int +rl_do_undo () +{ + UNDO_LIST *release; + int waiting_for_begin, start, end; + +#define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i))) + + start = end = waiting_for_begin = 0; + do + { + if (!rl_undo_list) + return (0); + + _rl_doing_an_undo = 1; + RL_SETSTATE(RL_STATE_UNDOING); + + /* To better support vi-mode, a start or end value of -1 means + rl_point, and a value of -2 means rl_end. */ + if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT) + { + start = TRANS (rl_undo_list->start); + end = TRANS (rl_undo_list->end); + } + + switch (rl_undo_list->what) + { + /* Undoing deletes means inserting some text. */ + case UNDO_DELETE: + rl_point = start; + rl_insert_text (rl_undo_list->text); + free (rl_undo_list->text); + break; + + /* Undoing inserts means deleting some text. */ + case UNDO_INSERT: + rl_delete_text (start, end); + rl_point = start; + break; + + /* Undoing an END means undoing everything 'til we get to a BEGIN. */ + case UNDO_END: + waiting_for_begin++; + break; + + /* Undoing a BEGIN means that we are done with this group. */ + case UNDO_BEGIN: + if (waiting_for_begin) + waiting_for_begin--; + else + rl_ding (); + break; + } + + _rl_doing_an_undo = 0; + RL_UNSETSTATE(RL_STATE_UNDOING); + + release = rl_undo_list; + rl_undo_list = rl_undo_list->next; + replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list); + + free (release); + } + while (waiting_for_begin); + + return (1); +} +#undef TRANS + +int +_rl_fix_last_undo_of_type (type, start, end) + int type, start, end; +{ + UNDO_LIST *rl; + + for (rl = rl_undo_list; rl; rl = rl->next) + { + if (rl->what == type) + { + rl->start = start; + rl->end = end; + return 0; + } + } + return 1; +} + +/* Begin a group. Subsequent undos are undone as an atomic operation. */ +int +rl_begin_undo_group () +{ + rl_add_undo (UNDO_BEGIN, 0, 0, 0); + _rl_undo_group_level++; + return 0; +} + +/* End an undo group started with rl_begin_undo_group (). */ +int +rl_end_undo_group () +{ + rl_add_undo (UNDO_END, 0, 0, 0); + _rl_undo_group_level--; + return 0; +} + +/* Save an undo entry for the text from START to END. */ +int +rl_modifying (start, end) + int start, end; +{ + if (start > end) + { + SWAP (start, end); + } + + if (start != end) + { + char *temp = rl_copy_text (start, end); + rl_begin_undo_group (); + rl_add_undo (UNDO_DELETE, start, end, temp); + rl_add_undo (UNDO_INSERT, start, end, (char *)NULL); + rl_end_undo_group (); + } + return 0; +} + +/* Revert the current line to its previous state. */ +int +rl_revert_line (count, key) + int count, key; +{ + if (!rl_undo_list) + rl_ding (); + else + { + while (rl_undo_list) + rl_do_undo (); +#if defined (VI_MODE) + if (rl_editing_mode == vi_mode) + rl_point = rl_mark = 0; /* rl_end should be set correctly */ +#endif + } + + return 0; +} + +/* Do some undoing of things that were done. */ +int +rl_undo_command (count, key) + int count, key; +{ + if (count < 0) + return 0; /* Nothing to do. */ + + while (count) + { + if (rl_do_undo ()) + count--; + else + { + rl_ding (); + break; + } + } + return 0; +} diff --git a/locale.c b/locale.c index 48e44ec48..3d0061768 100644 --- a/locale.c +++ b/locale.c @@ -251,6 +251,20 @@ set_lang (var, value) return ((lc_all == 0 || *lc_all == 0) ? reset_locale_vars () : 0); } +/* Set default values for LANG and LC_ALL. Default values for all other + locale-related variables depend on these. */ +void +set_default_lang () +{ + char *v; + + v = get_string_value ("LC_ALL"); + set_locale_var ("LC_ALL", v); + + v = get_string_value ("LANG"); + set_lang ("LANG", v); +} + /* Get the value of one of the locale variables (LC_MESSAGES, LC_CTYPE). The precedence is as POSIX.2 specifies: LC_ALL has precedence over the specific locale variables, and LANG, if set, is used as the default. */ @@ -267,7 +281,7 @@ get_locale_var (var) if (locale == 0 || *locale == 0) locale = lang; if (locale == 0 || *locale == 0) - locale = default_locale; /* system-dependent; not really portable */ + locale = default_locale; /* system-dependent; not really portable. should it be "C"? */ return (locale); } @@ -279,12 +293,9 @@ static int reset_locale_vars () { #if defined (HAVE_SETLOCALE) - char *locale; - - locale = lang; - if (locale == 0 || *locale == '\0') - locale = default_locale; - if (setlocale (LC_ALL, locale) == 0) + if (lang == 0 || *lang == '\0') + maybe_make_export_env (); /* trust that this will change environment for setlocale */ + if (setlocale (LC_ALL, lang ? lang : "") == 0) return 0; # if defined (LC_CTYPE) diff --git a/locale.c~ b/locale.c~ new file mode 100644 index 000000000..bce101769 --- /dev/null +++ b/locale.c~ @@ -0,0 +1,514 @@ +/* locale.c - Miscellaneous internationalization functions. */ + +/* Copyright (C) 1996-2004 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 2, 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#include "config.h" + +#include "bashtypes.h" + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include "bashintl.h" +#include "bashansi.h" +#include +#include "chartypes.h" + +#include "shell.h" +#include "input.h" /* For bash_input */ + +extern int dump_translatable_strings, dump_po_strings; + +/* The current locale when the program begins */ +static char *default_locale; + +/* The current domain for textdomain(3). */ +static char *default_domain; +static char *default_dir; + +/* tracks the value of LC_ALL; used to override values for other locale + categories */ +static char *lc_all; + +/* tracks the value of LC_ALL; used to provide defaults for locale + categories */ +static char *lang; + +/* Called to reset all of the locale variables to their appropriate values + if (and only if) LC_ALL has not been assigned a value. */ +static int reset_locale_vars __P((void)); + +static void locale_setblanks __P((void)); + +/* Set the value of default_locale and make the current locale the + system default locale. This should be called very early in main(). */ +void +set_default_locale () +{ +#if defined (HAVE_SETLOCALE) + default_locale = setlocale (LC_ALL, ""); + if (default_locale) + default_locale = savestring (default_locale); +itrace("default locale = %s", default_locale ? default_locale : "NULL"); +#endif /* HAVE_SETLOCALE */ + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); +} + +/* Set default values for LC_CTYPE, LC_COLLATE, LC_MESSAGES, LC_NUMERIC and + LC_TIME if they are not specified in the environment, but LC_ALL is. This + should be called from main() after parsing the environment. */ +void +set_default_locale_vars () +{ + char *val; + int r; + +#if defined (HAVE_SETLOCALE) + +# if defined (LC_CTYPE) + val = get_string_value ("LC_CTYPE"); + if (val == 0 && lc_all && *lc_all) + { + setlocale (LC_CTYPE, lc_all); + locale_setblanks (); + } +# endif + +# if defined (LC_COLLATE) + val = get_string_value ("LC_COLLATE"); + if (val == 0 && lc_all && *lc_all) + setlocale (LC_COLLATE, lc_all); +# endif /* LC_COLLATE */ + +# if defined (LC_MESSAGES) + val = get_string_value ("LC_MESSAGES"); + if (val == 0 && lc_all && *lc_all) + setlocale (LC_MESSAGES, lc_all); +# endif /* LC_MESSAGES */ + +# if defined (LC_NUMERIC) + val = get_string_value ("LC_NUMERIC"); + if (val == 0 && lc_all && *lc_all) + setlocale (LC_NUMERIC, lc_all); +# endif /* LC_NUMERIC */ + +# if defined (LC_TIME) + val = get_string_value ("LC_TIME"); + if (val == 0 && lc_all && *lc_all) + setlocale (LC_TIME, lc_all); +# endif /* LC_TIME */ + +#endif /* HAVE_SETLOCALE */ + + val = get_string_value ("TEXTDOMAIN"); + if (val && *val) + { + FREE (default_domain); + default_domain = savestring (val); +#if 0 + /* Don't want to override the shell's textdomain as the default */ + textdomain (default_domain); +#endif + } + + val = get_string_value ("TEXTDOMAINDIR"); + if (val && *val) + { + FREE (default_dir); + default_dir = savestring (val); + if (default_domain && *default_domain) + bindtextdomain (default_domain, default_dir); + } +} + +/* Set one of the locale categories (specified by VAR) to VALUE. Returns 1 + if successful, 0 otherwise. */ +int +set_locale_var (var, value) + char *var, *value; +{ + int r; + + if (var[0] == 'T' && var[10] == 0) /* TEXTDOMAIN */ + { + FREE (default_domain); + default_domain = value ? savestring (value) : (char *)NULL; +#if 0 + /* Don't want to override the shell's textdomain as the default */ + textdomain (default_domain); +#endif + return (1); + } + else if (var[0] == 'T') /* TEXTDOMAINDIR */ + { + FREE (default_dir); + default_dir = value ? savestring (value) : (char *)NULL; + if (default_domain && *default_domain) + bindtextdomain (default_domain, default_dir); + return (1); + } + + /* var[0] == 'L' && var[1] == 'C' && var[2] == '_' */ + + else if (var[3] == 'A') /* LC_ALL */ + { + FREE (lc_all); + if (value) + lc_all = savestring (value); + else + { + lc_all = (char *)xmalloc (1); + lc_all[0] = '\0'; + } +#if defined (HAVE_SETLOCALE) + r = *lc_all ? (setlocale (LC_ALL, lc_all) != 0) : reset_locale_vars (); + locale_setblanks (); + return r; +#else + return (1); +#endif + } + +#if defined (HAVE_SETLOCALE) + else if (var[3] == 'C' && var[4] == 'T') /* LC_CTYPE */ + { +# if defined (LC_CTYPE) + if (lc_all == 0 || *lc_all == '\0') + { + r = (setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE")) != 0); + locale_setblanks (); + return r; + } +# endif + } + else if (var[3] == 'C' && var[4] == 'O') /* LC_COLLATE */ + { +# if defined (LC_COLLATE) + if (lc_all == 0 || *lc_all == '\0') + return (setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE")) != 0); +# endif /* LC_COLLATE */ + } + else if (var[3] == 'M' && var[4] == 'E') /* LC_MESSAGES */ + { +# if defined (LC_MESSAGES) + if (lc_all == 0 || *lc_all == '\0') + return (setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES")) != 0); +# endif /* LC_MESSAGES */ + } + else if (var[3] == 'N' && var[4] == 'U') /* LC_NUMERIC */ + { +# if defined (LC_NUMERIC) + if (lc_all == 0 || *lc_all == '\0') + return (setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC")) != 0); +# endif /* LC_NUMERIC */ + } + else if (var[3] == 'T' && var[4] == 'I') /* LC_TIME */ + { +# if defined (LC_TIME) + if (lc_all == 0 || *lc_all == '\0') + return (setlocale (LC_TIME, get_locale_var ("LC_TIME")) != 0); +# endif /* LC_TIME */ + } +#endif /* HAVE_SETLOCALE */ + + + return (0); +} + +/* Called when LANG is assigned a value. Tracks value in `lang'. Calls + reset_locale_vars() to reset any default values if LC_ALL is unset or + null. */ +int +set_lang (var, value) + char *var, *value; +{ + FREE (lang); + if (value) + lang = savestring (value); + else + { + lang = (char *)xmalloc (1); + lang[0] = '\0'; + } + + return ((lc_all == 0 || *lc_all == 0) ? reset_locale_vars () : 0); +} + +/* Set default values for LANG and LC_ALL. Default values for all other + locale-related variables depend on these. */ +void +set_default_lang () +{ + char *v; + + v = get_string_value ("LC_ALL"); + set_locale_var ("LC_ALL", v); + + v = get_string_value ("LANG"); + set_lang ("LANG", v); +} + +/* Get the value of one of the locale variables (LC_MESSAGES, LC_CTYPE). + The precedence is as POSIX.2 specifies: LC_ALL has precedence over + the specific locale variables, and LANG, if set, is used as the default. */ +char * +get_locale_var (var) + char *var; +{ + char *locale; + + locale = lc_all; + + if (locale == 0 || *locale == 0) + locale = get_string_value (var); + if (locale == 0 || *locale == 0) + locale = lang; + if (locale == 0 || *locale == 0) + locale = default_locale; /* system-dependent; not really portable. should it be "C"? */ + + return (locale); +} + +/* Called to reset all of the locale variables to their appropriate values + if (and only if) LC_ALL has not been assigned a value. DO NOT CALL THIS + IF LC_ALL HAS BEEN ASSIGNED A VALUE. */ +static int +reset_locale_vars () +{ +#if defined (HAVE_SETLOCALE) + char *locale; + + if (lang == 0 || *lang == '\0') + maybe_make_export_env (); /* trust that this will change environment for setlocale */ + if (setlocale (LC_ALL, lang ? lang : "") == 0) + return 0; + +itrace("setlocale(LC_ALL, \"%s\")", lang ? lang : ""); +locale = setlocale(LC_ALL, (char *)NULL); +itrace("current locale = %s", locale ? locale : "NULL"); + +# if defined (LC_CTYPE) + setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE")); +# endif +# if defined (LC_COLLATE) + setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE")); +# endif +# if defined (LC_MESSAGES) + setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES")); +# endif +# if defined (LC_NUMERIC) + setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC")); +# endif +# if defined (LC_TIME) + setlocale (LC_TIME, get_locale_var ("LC_TIME")); +# endif + + locale_setblanks (); + +#endif + return 1; +} + +/* Translate the contents of STRING, a $"..." quoted string, according + to the current locale. In the `C' or `POSIX' locale, or if gettext() + is not available, the passed string is returned unchanged. The + length of the translated string is returned in LENP, if non-null. */ +char * +localetrans (string, len, lenp) + char *string; + int len, *lenp; +{ + char *locale, *t; + char *translated; + int tlen; + + /* Don't try to translate null strings. */ + if (string == 0 || *string == 0) + { + if (lenp) + *lenp = 0; + return ((char *)NULL); + } + + locale = get_locale_var ("LC_MESSAGES"); + + /* If we don't have setlocale() or the current locale is `C' or `POSIX', + just return the string. If we don't have gettext(), there's no use + doing anything else. */ + if (locale == 0 || locale[0] == '\0' || + (locale[0] == 'C' && locale[1] == '\0') || STREQ (locale, "POSIX")) + { + t = (char *)xmalloc (len + 1); + strcpy (t, string); + if (lenp) + *lenp = len; + return (t); + } + + /* Now try to translate it. */ + if (default_domain && *default_domain) + translated = dgettext (default_domain, string); + else + translated = string; + + if (translated == string) /* gettext returns its argument if untranslatable */ + { + t = (char *)xmalloc (len + 1); + strcpy (t, string); + if (lenp) + *lenp = len; + } + else + { + tlen = strlen (translated); + t = (char *)xmalloc (tlen + 1); + strcpy (t, translated); + if (lenp) + *lenp = tlen; + } + return (t); +} + +/* Change a bash string into a string suitable for inclusion in a `po' file. + This backslash-escapes `"' and `\' and changes newlines into \\\n"\n". */ +char * +mk_msgstr (string, foundnlp) + char *string; + int *foundnlp; +{ + register int c, len; + char *result, *r, *s; + + for (len = 0, s = string; s && *s; s++) + { + len++; + if (*s == '"' || *s == '\\') + len++; + else if (*s == '\n') + len += 5; + } + + r = result = (char *)xmalloc (len + 3); + *r++ = '"'; + + for (s = string; s && (c = *s); s++) + { + if (c == '\n') /* -> \n"" */ + { + *r++ = '\\'; + *r++ = 'n'; + *r++ = '"'; + *r++ = '\n'; + *r++ = '"'; + if (foundnlp) + *foundnlp = 1; + continue; + } + if (c == '"' || c == '\\') + *r++ = '\\'; + *r++ = c; + } + + *r++ = '"'; + *r++ = '\0'; + + return result; +} + +/* $"..." -- Translate the portion of STRING between START and END + according to current locale using gettext (if available) and return + the result. The caller will take care of leaving the quotes intact. + The string will be left without the leading `$' by the caller. + If translation is performed, the translated string will be double-quoted + by the caller. The length of the translated string is returned in LENP, + if non-null. */ +char * +localeexpand (string, start, end, lineno, lenp) + char *string; + int start, end, lineno, *lenp; +{ + int len, tlen, foundnl; + char *temp, *t, *t2; + + temp = (char *)xmalloc (end - start + 1); + for (tlen = 0, len = start; len < end; ) + temp[tlen++] = string[len++]; + temp[tlen] = '\0'; + + /* If we're just dumping translatable strings, don't do anything with the + string itself, but if we're dumping in `po' file format, convert it into + a form more palatable to gettext(3) and friends by quoting `"' and `\' + with backslashes and converting into `\n""'. If we find a + newline in TEMP, we first output a `msgid ""' line and then the + translated string; otherwise we output the `msgid' and translated + string all on one line. */ + if (dump_translatable_strings) + { + if (dump_po_strings) + { + foundnl = 0; + t = mk_msgstr (temp, &foundnl); + t2 = foundnl ? "\"\"\n" : ""; + + printf ("#: %s:%d\nmsgid %s%s\nmsgstr \"\"\n", + yy_input_name (), lineno, t2, t); + free (t); + } + else + printf ("\"%s\"\n", temp); + + if (lenp) + *lenp = tlen; + return (temp); + } + else if (*temp) + { + t = localetrans (temp, tlen, &len); + free (temp); + if (lenp) + *lenp = len; + return (t); + } + else + { + if (lenp) + *lenp = 0; + return (temp); + } +} + +/* Set every character in the character class to be a shell break + character for the lexical analyzer when the locale changes. */ +static void +locale_setblanks () +{ + int x; + + for (x = 0; x < sh_syntabsiz; x++) + { + if (isblank (x)) + sh_syntaxtab[x] |= CSHBRK; + else if (member (x, shell_break_chars)) + sh_syntaxtab[x] |= CSHBRK; + else + sh_syntaxtab[x] &= ~CSHBRK; + } +} diff --git a/shell.c b/shell.c index a28442c95..6693f852e 100644 --- a/shell.c +++ b/shell.c @@ -532,6 +532,7 @@ main (argc, argv, env) Variables from the environment are expected to be set, etc. */ shell_initialize (); + set_default_lang (); set_default_locale_vars (); if (interactive_shell) diff --git a/variables.c~ b/variables.c~ index d54f10a21..449975e06 100644 --- a/variables.c~ +++ b/variables.c~ @@ -346,6 +346,8 @@ initialize_shell_variables (env, privmode) else { temp_var = bind_variable (name, string, 0); +if (strcmp(name,"LANG") == 0) + itrace("bound LANG to %s", string); VSETATTR (temp_var, (att_exported | att_imported)); array_needs_making = 1; } @@ -440,7 +442,7 @@ initialize_shell_variables (env, privmode) bind_variable ("OPTERR", "1", 0); sh_opterr = 1; - if (login_shell == 1) + if (login_shell == 1 && posixly_correct == 0) set_home_var (); /* Get the full pathname to THIS shell, and set the BASH variable @@ -1359,7 +1361,7 @@ get_dirstack (self) ARRAY *a; WORD_LIST *l; - l = get_directory_stack (); + l = get_directory_stack (0); a = array_from_word_list (l); array_dispose (array_cell (self)); dispose_words (l);