From c81300691327066b954fb34116f6d1f88e0d49d6 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Oct 2002 22:59:29 +0300 Subject: [PATCH 01/89] fixed update with subselect (FOR REVIEW) mysql-test/r/subselect.result: update with subselect test mysql-test/t/subselect.test: update with subselect test sql/mysql_priv.h: fixed update with subselect sql/sql_base.cc: fixed update with subselect sql/sql_lex.cc: fixed update with subselect sql/sql_select.cc: fixed update with subselect sql/sql_update.cc: fixed update with subselect sql/sql_yacc.yy: fixed update with subselect --- mysql-test/r/subselect.result | 16 ++++++++++++++++ mysql-test/t/subselect.test | 13 ++++++++++++- sql/mysql_priv.h | 3 ++- sql/sql_base.cc | 16 ++++++++++++---- sql/sql_lex.cc | 4 +++- sql/sql_select.cc | 3 +++ sql/sql_update.cc | 18 ++++++++++++------ sql/sql_yacc.yy | 5 +++-- 8 files changed, 63 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 3f89f546ca3..60312ca46a3 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -205,3 +205,19 @@ SELECT (SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03') (SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03') 2002-08-03 drop table searchconthardwarefr3; +create table t1 (a int NOT NULL, b int, primary key (a)); +create table t2 (a int NOT NULL, b int, primary key (a)); +insert into t1 values (0, 10),(1, 11),(2, 12); +insert into t2 values (1, 21),(2, 22),(3, 23); +select * from t1; +a b +0 10 +1 11 +2 12 +update t1 set b= (select b from t2 where t1.a = t2.a); +select * from t1; +a b +0 NULL +1 21 +2 22 +drop table t1, t2; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 6e585883f1c..a2c9d4dbb7b 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -110,4 +110,15 @@ EXPLAIN SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03'; EXPLAIN SELECT (SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03'); SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03'; SELECT (SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03'); -drop table searchconthardwarefr3; \ No newline at end of file +drop table searchconthardwarefr3; + +#update with subselects +create table t1 (a int NOT NULL, b int, primary key (a)); +create table t2 (a int NOT NULL, b int, primary key (a)); +insert into t1 values (0, 10),(1, 11),(2, 12); +insert into t2 values (1, 21),(2, 22),(3, 23); +select * from t1; +update t1 set b= (select b from t2 where t1.a = t2.a); +select * from t1; +drop table t1, t2; + diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index d1a3c7e235a..f81d8ce7af6 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -444,7 +444,8 @@ void kill_delayed_threads(void); int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, ORDER *order, ha_rows rows, thr_lock_type lock_type, ulong options); int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok=0); -TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update); +TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update, + bool multiopen= 0); TABLE *open_table(THD *thd,const char *db,const char *table,const char *alias, bool *refresh); TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 46afddf0967..425784dada2 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1567,16 +1567,24 @@ int open_tables(THD *thd,TABLE_LIST *start) } -TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) +TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type, + bool multiopen) { TABLE *table; bool refresh; DBUG_ENTER("open_ltable"); thd->proc_info="Opening table"; - while (!(table=open_table(thd,table_list->db, - table_list->real_name,table_list->alias, - &refresh)) && refresh) ; + if (table_list->next && multiopen) + { + while (open_tables(thd,table_list) && refresh) ; + table= table_list->table; + } + else + while (!(table= open_table(thd,table_list->db, + table_list->real_name,table_list->alias, + &refresh)) && refresh) ; + if (table) { int error; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 9f09afc78a6..132c760267f 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -148,6 +148,7 @@ LEX *lex_start(THD *thd, uchar *buf,uint length) lex->select_lex.expr_list.empty(); lex->select_lex.ftfunc_list_alloc.empty(); lex->select_lex.ftfunc_list= &lex->select->ftfunc_list_alloc; + lex->select= &lex->select_lex; lex->convert_set= (lex->thd= thd)->variables.convert_set; lex->yacc_yyss=lex->yacc_yyvs=0; lex->ignore_space=test(thd->sql_mode & MODE_IGNORE_SPACE); @@ -956,6 +957,7 @@ void st_select_lex::init_query() table_list.next= (byte**) &table_list.first; item_list.empty(); join= 0; + having_fix_field= 0; } void st_select_lex::init_select() @@ -973,7 +975,7 @@ void st_select_lex::init_select() ftfunc_list_alloc.empty(); ftfunc_list= &ftfunc_list_alloc; linkage= UNSPECIFIED_TYPE; - depended= having_fix_field= 0; + depended= 0; } /* diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6a48f56443c..c3cc4c1041c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5641,6 +5641,9 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table) static Item * part_of_refkey(TABLE *table,Field *field) { + if (!table->reginfo.join_tab) + return (Item*) 0; // field from outer non-select (UPDATE,...) + uint ref_parts=table->reginfo.join_tab->ref.key_parts; if (ref_parts) { diff --git a/sql/sql_update.cc b/sql/sql_update.cc index c146b07284f..d47e539f610 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -62,12 +62,17 @@ int mysql_update(THD *thd, TABLE *table; SQL_SELECT *select; READ_RECORD info; + TABLE_LIST *update_table_list= (TABLE_LIST*) + thd->lex.select_lex.table_list.first; DBUG_ENTER("mysql_update"); LINT_INIT(used_index); LINT_INIT(timestamp_query_id); - if (!(table = open_ltable(thd,table_list,lock_type))) - DBUG_RETURN(-1); /* purecov: inspected */ + table_list->lock_type= lock_type; + if (!(table = open_ltable(thd,table_list,lock_type, 1))) + DBUG_RETURN(-1); + fix_tables_pointers(&thd->lex.select_lex); + save_time_stamp=table->time_stamp; table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); thd->proc_info="init"; @@ -77,8 +82,9 @@ int mysql_update(THD *thd, table->quick_keys=0; want_privilege=table->grant.want_privilege; table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege); - if (setup_tables(table_list) || setup_conds(thd,table_list,&conds) - || setup_ftfuncs(thd)) + if (setup_tables(update_table_list) || + setup_conds(thd,update_table_list,&conds) + || setup_ftfuncs(thd)) DBUG_RETURN(-1); /* purecov: inspected */ old_used_keys=table->used_keys; // Keys used in WHERE @@ -94,7 +100,7 @@ int mysql_update(THD *thd, /* Check the fields we are going to modify */ table->grant.want_privilege=want_privilege; - if (setup_fields(thd,table_list,fields,1,0,0)) + if (setup_fields(thd,update_table_list,fields,1,0,0)) DBUG_RETURN(-1); /* purecov: inspected */ if (table->timestamp_field) { @@ -107,7 +113,7 @@ int mysql_update(THD *thd, /* Check values */ table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege); - if (setup_fields(thd,table_list,values,0,0,0)) + if (setup_fields(thd,update_table_list,values,0,0,0)) { table->time_stamp=save_time_stamp; // Restore timestamp pointer DBUG_RETURN(-1); /* purecov: inspected */ diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index f5b8c6e4b24..a6bfbafe46a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1572,8 +1572,9 @@ select_init: select_part2: { LEX *lex=Lex; - lex->lock_option=TL_READ; - mysql_init_select(lex); + if (lex->select == &lex->select_lex) + lex->lock_option= TL_READ; /* Only for global SELECT */ + mysql_init_select(lex); } select_options select_item_list select_into select_lock_type; From 0241d64b643ea0440d86b84196ae4df44b83978a Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 27 Oct 2002 23:27:00 +0200 Subject: [PATCH 02/89] IN subselect mysql-test/r/subselect.result: IN subselect test mysql-test/t/subselect.test: IN subselect test sql/item.cc: Item wrappers for IN subselect sql/item.h: Item wrappers for IN subselect --- mysql-test/r/subselect.result | 11 ++++++ mysql-test/t/subselect.test | 6 +++ sql/item.cc | 47 ++++++++++++++++++++++ sql/item.h | 49 +++++++++++++++++++++++ sql/item_subselect.cc | 74 ++++++++++++++++++++++++++++++++--- sql/item_subselect.h | 21 ++++++++-- sql/sql_yacc.yy | 37 ++++++++++++++++-- 7 files changed, 232 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 5c5b8984102..b232061585d 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -96,6 +96,17 @@ select * from t3 where not exists (select * from t2 where t2.b=t3.a); a 6 3 +select * from t3 where a in (select b from t2); +a +7 +select * from t3 where a not in (select b from t2); +a +6 +3 +select * from t3 where a in (select a,b from t2); +Subselect returns more than 1 field +select * from t3 where a in (select * from t2); +Subselect returns more than 1 field insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9); select b,max(a) as ma from t4 group by b having b < (select max(t2.a) from t2 where t2.b=t4.b); diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index c74922d3d9e..83c81fbbfc5 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -34,6 +34,12 @@ select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2 explain select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4; select * from t3 where exists (select * from t2 where t2.b=t3.a); select * from t3 where not exists (select * from t2 where t2.b=t3.a); +select * from t3 where a in (select b from t2); +select * from t3 where a not in (select b from t2); +-- error 1239 +select * from t3 where a in (select a,b from t2); +-- error 1239 +select * from t3 where a in (select * from t2); insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9); select b,max(a) as ma from t4 group by b having b < (select max(t2.a) from t2 where t2.b=t4.b); diff --git a/sql/item.cc b/sql/item.cc index f8404f40421..97c09207e38 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -424,6 +424,53 @@ bool Item::fix_fields(THD *thd, return 0; } +bool Item_outer_select_context_saver::fix_fields(THD *thd, + struct st_table_list *list, + Item ** ref) +{ + DBUG_ENTER("Item_outer_select_context_saver::fix_fields"); + bool res= item->fix_fields(thd, + 0, // do not show current subselect fields + &item); + *ref= item; + DBUG_RETURN(res); +} + +bool Item_asterisk_remover::fix_fields(THD *thd, + struct st_table_list *list, + Item ** ref) +{ + DBUG_ENTER("Item_asterisk_remover::fix_fields"); + + bool res; + if (item) + if (item->type() == Item::FIELD_ITEM && + ((Item_field*) item)->field_name[0] == '*') + { + List fields; + fields.push_back(item); + List_iterator it(fields); + it++; + uint elem=fields.elements; + if (insert_fields(thd, list, ((Item_field*) item)->db_name, + ((Item_field*) item)->table_name, &it)) + res= -1; + else + if (fields.elements > 1) + { + my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0)); + res= -1; + } + } + else + res= item->fix_fields(thd, list, &item); + else + res= -1; + *ref= item; + DBUG_RETURN(res); +} + + bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { if (!field) // If field is not checked diff --git a/sql/item.h b/sql/item.h index fc36148e443..2b92d7c9ed8 100644 --- a/sql/item.h +++ b/sql/item.h @@ -90,6 +90,55 @@ public: }; +/* + Wrapper base class +*/ + +class Item_wrapper :public Item +{ +protected: + Item *item; +public: + /* + Following methods should not be used, because fix_fields exclude this + item (it assign '*ref' with field 'item' in derived classes) + */ + enum Type type() const { return item->type(); } + double val() { return item->val(); } + longlong val_int() { return item->val_int(); } + String* val_str(String* s) { return item->val_str(s); } + void make_field(Send_field* f) { item->make_field(f); } +}; + + +/* + Save context of name resolution for Item, used in subselect transformer. +*/ +class Item_outer_select_context_saver :public Item_wrapper +{ + Item *item; +public: + Item_outer_select_context_saver(Item *i): + item(i) + { + } + bool fix_fields(THD *, struct st_table_list *, Item ** ref); +}; + +/* + To resolve '*' field moved to condition +*/ +class Item_asterisk_remover :public Item_wrapper +{ + Item *item; +public: + Item_asterisk_remover(Item *i): + item(i) + { + } + bool fix_fields(THD *, struct st_table_list *, Item ** ref); +}; + class st_select_lex; class Item_ident :public Item { diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 456ce5f22ba..66238934e29 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -44,12 +44,13 @@ Item_subselect::Item_subselect(): } void Item_subselect::init(THD *thd, st_select_lex *select_lex, - select_subselect *result) + select_subselect *result, Item *left_expr) { DBUG_ENTER("Item_subselect::init"); - DBUG_PRINT("subs", ("select_lex 0x%xl", (long) select_lex)); + DBUG_PRINT("subs", ("select_lex 0x%xl", (ulong) select_lex)); + select_transformer(select_lex, left_expr); if (select_lex->next_select()) engine= new subselect_union_engine(thd, select_lex->master_unit(), result, this); @@ -65,6 +66,14 @@ Item_subselect::~Item_subselect() delete engine; } +void Item_subselect::select_transformer(st_select_lex *select_lex, + Item *left_expr) +{ + DBUG_ENTER("Item_subselect::select_transformer"); + DBUG_VOID_RETURN; +} + + void Item_subselect::make_field (Send_field *tmp_field) { if (null_value) @@ -109,9 +118,11 @@ Item_singleval_subselect::Item_singleval_subselect(THD *thd, st_select_lex *select_lex): Item_subselect() { - init(thd, select_lex, new select_singleval_subselect(this)); + DBUG_ENTER("Item_singleval_subselect::Item_singleval_subselect"); + init(thd, select_lex, new select_singleval_subselect(this), 0); max_columns= 1; maybe_null= 1; + DBUG_VOID_RETURN; } void Item_singleval_subselect::fix_length_and_dec() @@ -156,17 +167,37 @@ String *Item_singleval_subselect::val_str (String *str) } Item_exists_subselect::Item_exists_subselect(THD *thd, - st_select_lex *select_lex): + st_select_lex *select_lex, + Item *left_expr): Item_subselect() { - init(thd, select_lex, new select_exists_subselect(this)); + DBUG_ENTER("Item_exists_subselect::Item_exists_subselect"); + init(thd, select_lex, new select_exists_subselect(this), left_expr); max_columns= UINT_MAX; null_value= 0; //can't be NULL maybe_null= 0; //can't be NULL value= 0; - select_lex->select_limit= 1; // we need only 1 row to determinate existence + // We need only 1 row to determinate existence + select_lex->master_unit()->global_parameters->select_limit= 1; + DBUG_VOID_RETURN; } +Item_in_subselect::Item_in_subselect(THD *thd, Item * left_expr, + st_select_lex *select_lex): + Item_exists_subselect() +{ + DBUG_ENTER("Item_in_subselect::Item_in_subselect"); + init(thd, select_lex, new select_exists_subselect(this), left_expr); + max_columns= UINT_MAX; + null_value= 0; //can't be NULL + maybe_null= 0; //can't be NULL + value= 0; + // We need only 1 row to determinate existence + select_lex->master_unit()->global_parameters->select_limit= 1; + DBUG_VOID_RETURN; +} + + void Item_exists_subselect::fix_length_and_dec() { max_length= 1; @@ -204,6 +235,37 @@ String *Item_exists_subselect::val_str(String *str) return str; } +Item_in_subselect::Item_in_subselect(Item_in_subselect *item): + Item_exists_subselect(item) +{ +} + +void Item_in_subselect::select_transformer(st_select_lex *select_lex, + Item *left_expr) +{ + DBUG_ENTER("Item_in_subselect::select_transformer"); + for(SELECT_LEX * sl= select_lex; sl; sl= sl->next_select()) + { + Item *item; + if (sl->item_list.elements > 1) + { + my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0)); + item= 0; // Item_asterisk_remover mast fail + } + else + item= (Item*) sl->item_list.pop(); + sl->item_list.empty(); + sl->item_list.push_back(new Item_int(1)); + left_expr= new Item_outer_select_context_saver(left_expr); + item= new Item_asterisk_remover(item); + if (sl->where) + sl->where= new Item_cond_and(sl->where, + new Item_func_eq(item, left_expr)); + else + sl->where= new Item_func_eq(item, left_expr); + } + DBUG_VOID_RETURN; +} subselect_single_select_engine::subselect_single_select_engine(THD *thd, st_select_lex *select, diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 33f82982708..5a5f7bd58d8 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -55,13 +55,16 @@ public: pointer in constructor initialization list, but we need pass pointer to subselect Item class to select_subselect classes constructor. */ - void init (THD *thd, st_select_lex *select_lex, select_subselect *result); + virtual void init (THD *thd, st_select_lex *select_lex, + select_subselect *result, + Item *left_expr= 0); ~Item_subselect(); virtual void assign_null() { null_value= 1; } + virtual void select_transformer(st_select_lex *select_lex, Item *left_expr); bool assigned() { return value_assigned; } void assigned(bool a) { value_assigned= a; } enum Type type() const; @@ -74,7 +77,6 @@ public: friend class select_subselect; }; - /* single value subselect */ class Item_singleval_subselect :public Item_subselect @@ -127,12 +129,15 @@ protected: longlong value; /* value of this item (boolean: exists/not-exists) */ public: - Item_exists_subselect(THD *thd, st_select_lex *select_lex); + Item_exists_subselect(THD *thd, st_select_lex *select_lex, + Item *left_expr= 0); Item_exists_subselect(Item_exists_subselect *item): Item_subselect(item) { value= item->value; } + Item_exists_subselect(): Item_subselect() {} + virtual void assign_null() { value= 0; @@ -147,6 +152,16 @@ public: friend class select_exists_subselect; }; +/* IN subselect */ + +class Item_in_subselect :public Item_exists_subselect +{ +public: + Item_in_subselect(THD *thd, Item * left_expr, st_select_lex *select_lex); + Item_in_subselect(Item_in_subselect *item); + virtual void select_transformer(st_select_lex *select_lex, Item *left_exp); +}; + class subselect_engine { protected: diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 7d68278e39f..81ee899cfd4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -70,6 +70,7 @@ inline Item *or_or_concat(Item* A, Item* B) enum Item_udftype udf_type; CHARSET_INFO *charset; interval_type interval; + st_select_lex *select_lex; } %{ @@ -528,7 +529,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %type IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME - ULONGLONG_NUM field_ident select_alias ident ident_or_text UNDERSCORE_CHARSET + ULONGLONG_NUM field_ident select_alias ident ident_or_text + UNDERSCORE_CHARSET %type opt_table_alias @@ -610,6 +612,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %type internal_variable_name +%type in_subselect in_subselect_init + %type query verb_clause create change select do drop insert replace insert2 insert_values update delete truncate rename @@ -1706,10 +1710,16 @@ expr: expr_expr { $$= $1; } /* expressions that begin with 'expr' */ expr_expr: - expr IN_SYM '(' expr_list ')' + expr IN_SYM '(' expr_list ')' { $$= new Item_func_in($1,*$4); } | expr NOT IN_SYM '(' expr_list ')' { $$= new Item_func_not(new Item_func_in($1,*$5)); } + | expr IN_SYM in_subselect + { $$= new Item_in_subselect(current_thd, $1, $3); } + | expr NOT IN_SYM in_subselect + { + $$= new Item_func_not(new Item_in_subselect(current_thd, $1, $4)); + } | expr BETWEEN_SYM no_and_expr AND expr { $$= new Item_func_between($1,$3,$5); } | expr NOT BETWEEN_SYM no_and_expr AND expr @@ -1789,10 +1799,16 @@ no_in_expr: /* expressions that begin with 'expr' that does NOT follow AND */ no_and_expr: - no_and_expr IN_SYM '(' expr_list ')' - { $$= new Item_func_in($1,*$4); } + no_and_expr IN_SYM '(' expr_list ')' + { $$= new Item_func_in($1,*$4); } | no_and_expr NOT IN_SYM '(' expr_list ')' { $$= new Item_func_not(new Item_func_in($1,*$5)); } + | no_and_expr IN_SYM in_subselect + { $$= new Item_in_subselect(current_thd, $1, $3); } + | no_and_expr NOT IN_SYM in_subselect + { + $$= new Item_func_not(new Item_in_subselect(current_thd, $1, $4)); + } | no_and_expr BETWEEN_SYM no_and_expr AND expr { $$= new Item_func_between($1,$3,$5); } | no_and_expr NOT BETWEEN_SYM no_and_expr AND expr @@ -4180,6 +4196,19 @@ exists_subselect_init: Lex->select->master_unit()->first_select()); }; +in_subselect: + subselect_start in_subselect_init + subselect_end + { + $$= $2; + }; + +in_subselect_init: + select_init + { + $$= Lex->select->master_unit()->first_select(); + }; + subselect_start: '(' { From ceb73645c19128cfef13d517f003a9ba2f4028c2 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 31 Oct 2002 02:11:59 +0200 Subject: [PATCH 03/89] IN subselect with ORDER BY, HAVING & sum functions mysql-test/r/subselect.result: IN subselect with ORDER BY, HAVING & sum functions test mysql-test/t/subselect.test: IN subselect with ORDER BY, HAVING & sum functions test sql/item.h: removed field, because parent class has same field --- mysql-test/r/subselect.result | 11 +++++++++++ mysql-test/t/subselect.test | 5 +++++ sql/item.h | 10 ++++------ sql/item_subselect.cc | 29 ++++++++++++++++++++++------- sql/item_sum.cc | 7 +++++-- sql/item_sum.h | 11 ++++++++--- sql/sql_lex.cc | 3 ++- sql/sql_lex.h | 1 + 8 files changed, 58 insertions(+), 19 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index cccdd05f9bf..1bbc652426a 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -230,4 +230,15 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY searchconthardwarefr3 index NULL topic 3 NULL 2 Using index 2 SUBSELECT No tables used 3 UNION No tables used +SELECT 1 IN (SELECT 1 FROM searchconthardwarefr3 HAVING a); +Unknown column 'a' in 'having clause' +SELECT * from searchconthardwarefr3 where topic IN (SELECT topic FROM searchconthardwarefr3 GROUP BY date); +topic date pseudo +40143 2002-08-03 joce +43506 2002-10-02 joce +SELECT * from searchconthardwarefr3 where topic IN (SELECT topic FROM searchconthardwarefr3 GROUP BY date HAVING topic < 4100); +topic date pseudo +43506 2002-10-02 joce +SELECT * from searchconthardwarefr3 where topic IN (SELECT SUM(topic) FROM searchconthardwarefr3); +topic date pseudo drop table searchconthardwarefr3; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 0cf976b4bec..5e868aaa67f 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -120,4 +120,9 @@ SELECT 1 FROM searchconthardwarefr3 WHERE 1=(SELECT 1 UNION SELECT 1) UNION ALL -- error 1240 SELECT 1 FROM searchconthardwarefr3 WHERE 1=(SELECT 1 UNION ALL SELECT 1) UNION SELECT 1; EXPLAIN SELECT 1 FROM searchconthardwarefr3 WHERE 1=(SELECT 1 UNION SELECT 1); +-- error 1054 +SELECT 1 IN (SELECT 1 FROM searchconthardwarefr3 HAVING a); +SELECT * from searchconthardwarefr3 where topic IN (SELECT topic FROM searchconthardwarefr3 GROUP BY date); +SELECT * from searchconthardwarefr3 where topic IN (SELECT topic FROM searchconthardwarefr3 GROUP BY date HAVING topic < 4100); +SELECT * from searchconthardwarefr3 where topic IN (SELECT SUM(topic) FROM searchconthardwarefr3); drop table searchconthardwarefr3; \ No newline at end of file diff --git a/sql/item.h b/sql/item.h index 2b92d7c9ed8..391ec347b78 100644 --- a/sql/item.h +++ b/sql/item.h @@ -116,11 +116,10 @@ public: */ class Item_outer_select_context_saver :public Item_wrapper { - Item *item; public: - Item_outer_select_context_saver(Item *i): - item(i) + Item_outer_select_context_saver(Item *i) { + item= i; } bool fix_fields(THD *, struct st_table_list *, Item ** ref); }; @@ -130,11 +129,10 @@ public: */ class Item_asterisk_remover :public Item_wrapper { - Item *item; public: - Item_asterisk_remover(Item *i): - item(i) + Item_asterisk_remover(Item *i) { + item= i; } bool fix_fields(THD *, struct st_table_list *, Item ** ref); }; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index f68af3079d2..2f7c7aad9a1 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -254,15 +254,30 @@ void Item_in_subselect::select_transformer(st_select_lex *select_lex, } else item= (Item*) sl->item_list.pop(); - sl->item_list.empty(); - sl->item_list.push_back(new Item_int(1)); + left_expr= new Item_outer_select_context_saver(left_expr); - item= new Item_asterisk_remover(item); - if (sl->where) - sl->where= new Item_cond_and(sl->where, - new Item_func_eq(item, left_expr)); + + if (sl->having || sl->with_sum_func || sl->group_list.first) + { + sl->item_list.push_back(item); + item= new Item_ref(sl->item_list.head_ref(), 0, ""); + if (sl->having) + sl->having= new Item_cond_and(sl->having, + new Item_func_eq(item, left_expr)); + else + sl->having= new Item_func_eq(item, left_expr); + } else - sl->where= new Item_func_eq(item, left_expr); + { + sl->item_list.empty(); + sl->item_list.push_back(new Item_int(1)); + item= new Item_asterisk_remover(item); + if (sl->where) + sl->where= new Item_cond_and(sl->where, + new Item_func_eq(item, left_expr)); + else + sl->where= new Item_func_eq(item, left_expr); + } } DBUG_VOID_RETURN; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index ae1a86845bf..0b1150cb697 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -23,7 +23,6 @@ #include "mysql_priv.h" - Item_sum::Item_sum(List &list) { arg_count=list.elements; @@ -38,10 +37,14 @@ Item_sum::Item_sum(List &list) args[i++]= item; } } - with_sum_func=1; + mark_as_sum_func(); list.empty(); // Fields are used } +void Item_sum::mark_as_sum_func() +{ + current_thd->lex.select->with_sum_func= with_sum_func= 1; +} void Item_sum::make_field(Send_field *tmp_field) { diff --git a/sql/item_sum.h b/sql/item_sum.h index 3e67f1e3624..a169a0ee562 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -34,23 +34,28 @@ public: uint arg_count; bool quick_group; /* If incremental update of fields */ - Item_sum() : arg_count(0),quick_group(1) { with_sum_func=1; } + Item_sum() : arg_count(0),quick_group(1) + { + mark_as_sum_func(); + } Item_sum(Item *a) :quick_group(1) { arg_count=1; args=tmp_args; args[0]=a; - with_sum_func = 1; + mark_as_sum_func(); } Item_sum( Item *a, Item *b ) :quick_group(1) { arg_count=2; args=tmp_args; args[0]=a; args[1]=b; - with_sum_func=1; + mark_as_sum_func(); } Item_sum(List &list); ~Item_sum() { result_field=0; } + inline void mark_as_sum_func(); + enum Type type() const { return SUM_FUNC_ITEM; } virtual enum Sumfunctype sum_func () const=0; virtual void reset()=0; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 52f1be6bddf..31f7e99a2b6 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -934,7 +934,8 @@ void st_select_lex_node::init_select() order_list.first= 0; order_list.next= (byte**) &order_list.first; select_limit= HA_POS_ERROR; - offset_limit= 0; + offset_limit= 0; + with_sum_func= 0; } void st_select_lex_unit::init_query() diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 50bff7c7f63..64186fb49ea 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -196,6 +196,7 @@ public: enum sub_select_type linkage; SQL_LIST order_list; /* ORDER clause */ ha_rows select_limit, offset_limit; /* LIMIT clause parameters */ + bool with_sum_func; void init_query(); void init_select(); void include_down(st_select_lex_node *upper); From 646ae53f8a8715c1a8d66de4696a101df7bc3924 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 2 Nov 2002 16:10:53 +0200 Subject: [PATCH 04/89] Added test case for the last fix --- mysql-test/r/func_test.result | 4 ++++ mysql-test/t/func_test.test | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result index 586e345ea10..da82567db4d 100644 --- a/mysql-test/r/func_test.result +++ b/mysql-test/r/func_test.result @@ -26,6 +26,10 @@ 1 1 1 -1.49 or -1.49 0.6 or 0.6 1 1 +start ctime1 ctime2 +2002-11-04 00:00:00 20021029165106 20021105164731 +start ctime1 ctime2 +2002-11-04 00:00:00 20021029165106 20021105164731 5 between 0 and 10 between 0 and 1 (5 between 0 and 10) between 0 and 1 0 1 1 and 2 between 2 and 10 2 between 2 and 10 and 1 diff --git a/mysql-test/t/func_test.test b/mysql-test/t/func_test.test index ec44009b1a6..ccbb531e2e6 100644 --- a/mysql-test/t/func_test.test +++ b/mysql-test/t/func_test.test @@ -15,6 +15,16 @@ select 2 between 1 and 3, "monty" between "max" and "my",2=2 and "monty" between select 'b' between 'a' and 'c', 'B' between 'a' and 'c'; select 2 in (3,2,5,9,5,1),"monty" in ("david","monty","allan"), 1.2 in (1.4,1.2,1.0); select -1.49 or -1.49,0.6 or 0.6; +drop table if exists t1,t2; +CREATE TABLE t1 ( start datetime default NULL) TYPE=MyISAM; +INSERT INTO t1 VALUES ('2002-10-21 00:00:00'); +INSERT INTO t1 VALUES ('2002-10-28 00:00:00'); +INSERT INTO t1 VALUES ('2002-11-04 00:00:00'); +CREATE TABLE t2 ( ctime1 timestamp(14) NOT NULL, ctime2 timestamp(14) NOT NULL) TYPE=MyISAM; +INSERT INTO t2 VALUES (20021029165106,20021105164731); +select * from t1, t2 where t1.start between t2.ctime1 and t2.ctime2; +select * from t1, t2 where t1.start >= t2.ctime1 and t1.start <= t2.ctime2; +drop table if exists t1,t2; # # Wrong usage of functions From e2f4a07b4f5638bef041f9705188b4af691f56bb Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Nov 2002 11:59:18 +0200 Subject: [PATCH 05/89] after merging fix --- sql/item_sum.cc | 2 +- sql/sql_yacc.yy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/item_sum.cc b/sql/item_sum.cc index ff20acdfc37..7aa7e13c7f7 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -43,7 +43,7 @@ Item_sum::Item_sum(List &list) void Item_sum::mark_as_sum_func() { - current_thd->lex.select->with_sum_func= with_sum_func= 1; + current_thd->lex.current_select->with_sum_func= with_sum_func= 1; } void Item_sum::make_field(Send_field *tmp_field) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 063f449f117..5f2ef13a35a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4258,7 +4258,7 @@ in_subselect: in_subselect_init: select_init { - $$= Lex->select->master_unit()->first_select(); + $$= Lex->current_select->master_unit()->first_select(); }; subselect_start: From 1448ba4ee9b9bc4176d7368709de98288b0e1310 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Nov 2002 21:47:20 +0200 Subject: [PATCH 06/89] test of join_free bug sql/sql_lex.cc: possible bug fixed sql/sql_select.cc: fixed join_free bug --- mysql-test/r/subselect.result | 12 ++++++++++-- mysql-test/t/subselect.test | 12 ++++++++++-- sql/sql_lex.cc | 3 ++- sql/sql_select.cc | 9 ++++++--- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 1bbc652426a..572834bd742 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -195,7 +195,7 @@ joce SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo LIKE '%joce%'); Subselect returns more than 1 record drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit; -drop table if exists searchconthardwarefr3; +drop table if exists searchconthardwarefr3, forumconthardwarefr7; CREATE TABLE `searchconthardwarefr3` ( `topic` mediumint(8) unsigned NOT NULL default '0', `date` date NOT NULL default '0000-00-00', @@ -241,4 +241,12 @@ topic date pseudo 43506 2002-10-02 joce SELECT * from searchconthardwarefr3 where topic IN (SELECT SUM(topic) FROM searchconthardwarefr3); topic date pseudo -drop table searchconthardwarefr3; +CREATE TABLE `forumconthardwarefr7` ( +`numeropost` mediumint(8) unsigned NOT NULL auto_increment, +`maxnumrep` int(10) unsigned NOT NULL default '0', +PRIMARY KEY (`numeropost`), +UNIQUE KEY `maxnumrep` (`maxnumrep`)) TYPE=MyISAM ROW_FORMAT=FIXED; +INSERT INTO forumconthardwarefr7 (numeropost,maxnumrep) VALUES (40143,1),(43506,2); +SELECT SQL_CALC_FOUND_ROWS numeropost,maxnumrep FROM forumconthardwarefr7 WHERE numeropost IN (SELECT topic FROM searchconthardwarefr3 WHERE pseudo='joce' AND date >= '2002-10-06') ORDER BY maxnumrep DESC LIMIT 0,20; +numeropost maxnumrep +drop table searchconthardwarefr3, forumconthardwarefr7; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 5e868aaa67f..f86ce7e0429 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -102,7 +102,7 @@ SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit; -drop table if exists searchconthardwarefr3; +drop table if exists searchconthardwarefr3, forumconthardwarefr7; CREATE TABLE `searchconthardwarefr3` ( `topic` mediumint(8) unsigned NOT NULL default '0', `date` date NOT NULL default '0000-00-00', @@ -125,4 +125,12 @@ SELECT 1 IN (SELECT 1 FROM searchconthardwarefr3 HAVING a); SELECT * from searchconthardwarefr3 where topic IN (SELECT topic FROM searchconthardwarefr3 GROUP BY date); SELECT * from searchconthardwarefr3 where topic IN (SELECT topic FROM searchconthardwarefr3 GROUP BY date HAVING topic < 4100); SELECT * from searchconthardwarefr3 where topic IN (SELECT SUM(topic) FROM searchconthardwarefr3); -drop table searchconthardwarefr3; \ No newline at end of file +CREATE TABLE `forumconthardwarefr7` ( + `numeropost` mediumint(8) unsigned NOT NULL auto_increment, + `maxnumrep` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`numeropost`), + UNIQUE KEY `maxnumrep` (`maxnumrep`)) TYPE=MyISAM ROW_FORMAT=FIXED; + +INSERT INTO forumconthardwarefr7 (numeropost,maxnumrep) VALUES (40143,1),(43506,2); +SELECT SQL_CALC_FOUND_ROWS numeropost,maxnumrep FROM forumconthardwarefr7 WHERE numeropost IN (SELECT topic FROM searchconthardwarefr3 WHERE pseudo='joce' AND date >= '2002-10-06') ORDER BY maxnumrep DESC LIMIT 0,20; +drop table searchconthardwarefr3, forumconthardwarefr7; \ No newline at end of file diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 24fea111bdd..8c49680189d 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -927,6 +927,7 @@ void st_select_lex_node::init_query() { next= master= slave= link_next= 0; prev= link_prev= 0; + dependent= 0; } void st_select_lex_node::init_select() @@ -937,7 +938,7 @@ void st_select_lex_node::init_select() select_limit= HA_POS_ERROR; offset_limit= 0; with_sum_func= 0; - create_refs= dependent= 0; + create_refs= 0; } void st_select_lex_unit::init_query() diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 93d48e3e1e0..a1c25eb88e2 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2915,9 +2915,12 @@ join_free(JOIN *join) free_io_cache(join->table[join->const_tables]); for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++) { - delete tab->select; - delete tab->quick; - x_free(tab->cache.buff); + if (!join->select_lex->dependent) + { + delete tab->select; + delete tab->quick; + x_free(tab->cache.buff); + } if (tab->table) { if (tab->table->key_read) From 6987b41456dff437195beb6b6974e48fd0fcf633 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Nov 2002 23:45:19 +0200 Subject: [PATCH 07/89] ALL/ANY/SOME decreasing number of rules in sql_yacc.yy to satisfy bison limitation fixed subselect Items initializer methods mysql-test/r/subselect.result: tests of ALL/ANY/SOME mysql-test/t/subselect.test: tests of ALL/ANY/SOME sql/item_cmpfunc.cc: ALL/ANY/SOME sql/item_cmpfunc.h: ALL/ANY/SOME sql/item_subselect.cc: ALL/ANY/SOME fixed subselect Items initializer methods sql/item_subselect.h: ALL/ANY/SOME fixed subselect Items initializer methods sql/lex.h: ALL/ANY/SOME sql/mysql_priv.h: decreasing number of rules in sql_yacc.yy to satisfy bison limitation sql/sql_parse.cc: decreasing number of rules in sql_yacc.yy to satisfy bison limitation sql/sql_yacc.yy: ALL/ANY/SOME decreasing number of rules in sql_yacc.yy to satisfy bison limitation --- mysql-test/r/subselect.result | 50 ++++++++++++++++++++++ mysql-test/t/subselect.test | 17 ++++++++ sql/item_cmpfunc.cc | 24 +++++++++++ sql/item_cmpfunc.h | 7 ++++ sql/item_subselect.cc | 78 +++++++++++++++++++++++++---------- sql/item_subselect.h | 32 +++++++++++--- sql/lex.h | 2 + sql/mysql_priv.h | 9 ++++ sql/sql_parse.cc | 30 ++++++++++++++ sql/sql_yacc.yy | 74 ++++++++++++++++++++++----------- 10 files changed, 271 insertions(+), 52 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 572834bd742..cc907d33cc2 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -106,6 +106,36 @@ select * from t3 where a not in (select b from t2); a 6 3 +select * from t3 where a = some (select b from t2); +a +7 +select * from t3 where a <> any (select b from t2); +a +6 +3 +select * from t3 where a = all (select b from t2); +a +7 +select * from t3 where a <> all (select b from t2); +a +6 +3 +insert into t2 values (100, 5); +select * from t3 where a < any (select b from t2); +a +6 +3 +select * from t3 where a < all (select b from t2); +a +3 +select * from t3 where a >= any (select b from t2); +a +6 +7 +select * from t3 where a >= all (select b from t2); +a +7 +delete from t2 where a=100; select * from t3 where a in (select a,b from t2); Subselect returns more than 1 field select * from t3 where a in (select * from t2); @@ -241,6 +271,26 @@ topic date pseudo 43506 2002-10-02 joce SELECT * from searchconthardwarefr3 where topic IN (SELECT SUM(topic) FROM searchconthardwarefr3); topic date pseudo +SELECT * from searchconthardwarefr3 where topic = any (SELECT topic FROM searchconthardwarefr3 GROUP BY date); +topic date pseudo +40143 2002-08-03 joce +43506 2002-10-02 joce +SELECT * from searchconthardwarefr3 where topic = any (SELECT topic FROM searchconthardwarefr3 GROUP BY date HAVING topic < 4100); +topic date pseudo +43506 2002-10-02 joce +SELECT * from searchconthardwarefr3 where topic = any (SELECT SUM(topic) FROM searchconthardwarefr3); +topic date pseudo +SELECT * from searchconthardwarefr3 where topic = all (SELECT topic FROM searchconthardwarefr3 GROUP BY date); +topic date pseudo +SELECT * from searchconthardwarefr3 where topic = all (SELECT topic FROM searchconthardwarefr3 GROUP BY date HAVING topic < 4100); +topic date pseudo +40143 2002-08-03 joce +SELECT * from searchconthardwarefr3 where topic = all (SELECT SUM(topic) FROM searchconthardwarefr3); +topic date pseudo +SELECT * from searchconthardwarefr3 where topic <> any (SELECT SUM(topic) FROM searchconthardwarefr3); +topic date pseudo +40143 2002-08-03 joce +43506 2002-10-02 joce CREATE TABLE `forumconthardwarefr7` ( `numeropost` mediumint(8) unsigned NOT NULL auto_increment, `maxnumrep` int(10) unsigned NOT NULL default '0', diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index f86ce7e0429..10e73a7f971 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -36,6 +36,16 @@ select * from t3 where exists (select * from t2 where t2.b=t3.a); select * from t3 where not exists (select * from t2 where t2.b=t3.a); select * from t3 where a in (select b from t2); select * from t3 where a not in (select b from t2); +select * from t3 where a = some (select b from t2); +select * from t3 where a <> any (select b from t2); +select * from t3 where a = all (select b from t2); +select * from t3 where a <> all (select b from t2); +insert into t2 values (100, 5); +select * from t3 where a < any (select b from t2); +select * from t3 where a < all (select b from t2); +select * from t3 where a >= any (select b from t2); +select * from t3 where a >= all (select b from t2); +delete from t2 where a=100; -- error 1239 select * from t3 where a in (select a,b from t2); -- error 1239 @@ -125,6 +135,13 @@ SELECT 1 IN (SELECT 1 FROM searchconthardwarefr3 HAVING a); SELECT * from searchconthardwarefr3 where topic IN (SELECT topic FROM searchconthardwarefr3 GROUP BY date); SELECT * from searchconthardwarefr3 where topic IN (SELECT topic FROM searchconthardwarefr3 GROUP BY date HAVING topic < 4100); SELECT * from searchconthardwarefr3 where topic IN (SELECT SUM(topic) FROM searchconthardwarefr3); +SELECT * from searchconthardwarefr3 where topic = any (SELECT topic FROM searchconthardwarefr3 GROUP BY date); +SELECT * from searchconthardwarefr3 where topic = any (SELECT topic FROM searchconthardwarefr3 GROUP BY date HAVING topic < 4100); +SELECT * from searchconthardwarefr3 where topic = any (SELECT SUM(topic) FROM searchconthardwarefr3); +SELECT * from searchconthardwarefr3 where topic = all (SELECT topic FROM searchconthardwarefr3 GROUP BY date); +SELECT * from searchconthardwarefr3 where topic = all (SELECT topic FROM searchconthardwarefr3 GROUP BY date HAVING topic < 4100); +SELECT * from searchconthardwarefr3 where topic = all (SELECT SUM(topic) FROM searchconthardwarefr3); +SELECT * from searchconthardwarefr3 where topic <> any (SELECT SUM(topic) FROM searchconthardwarefr3); CREATE TABLE `forumconthardwarefr7` ( `numeropost` mediumint(8) unsigned NOT NULL auto_increment, `maxnumrep` int(10) unsigned NOT NULL default '0', diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index b6ea4beb339..1dfc5d86f5e 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -24,6 +24,30 @@ #include "mysql_priv.h" #include +Item_bool_func2* Item_bool_func2::eq_creator(Item *a, Item *b) +{ + return new Item_func_eq(a, b); +} +Item_bool_func2* Item_bool_func2::ne_creator(Item *a, Item *b) +{ + return new Item_func_ne(a, b); +} +Item_bool_func2* Item_bool_func2::gt_creator(Item *a, Item *b) +{ + return new Item_func_gt(a, b); +} +Item_bool_func2* Item_bool_func2::lt_creator(Item *a, Item *b) +{ + return new Item_func_lt(a, b); +} +Item_bool_func2* Item_bool_func2::ge_creator(Item *a, Item *b) +{ + return new Item_func_ge(a, b); +} +Item_bool_func2* Item_bool_func2::le_creator(Item *a, Item *b) +{ + return new Item_func_le(a, b); +} /* Test functions diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index c0dcc2bba8f..9976319740d 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -47,6 +47,13 @@ public: bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; } void print(String *str) { Item_func::print_op(str); } bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); } + + static Item_bool_func2* eq_creator(Item *a, Item *b); + static Item_bool_func2* ne_creator(Item *a, Item *b); + static Item_bool_func2* gt_creator(Item *a, Item *b); + static Item_bool_func2* lt_creator(Item *a, Item *b); + static Item_bool_func2* ge_creator(Item *a, Item *b); + static Item_bool_func2* le_creator(Item *a, Item *b); }; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 7fadd982594..d8e1fee2277 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -44,13 +44,13 @@ Item_subselect::Item_subselect(): } void Item_subselect::init(THD *thd, st_select_lex *select_lex, - select_subselect *result, Item *left_expr) + select_subselect *result) { DBUG_ENTER("Item_subselect::init"); DBUG_PRINT("subs", ("select_lex 0x%xl", (ulong) select_lex)); - select_transformer(select_lex, left_expr); + select_transformer(select_lex); if (select_lex->next_select()) engine= new subselect_union_engine(thd, select_lex->master_unit(), result, this); @@ -66,8 +66,7 @@ Item_subselect::~Item_subselect() delete engine; } -void Item_subselect::select_transformer(st_select_lex *select_lex, - Item *left_expr) +void Item_subselect::select_transformer(st_select_lex *select_lex) { DBUG_ENTER("Item_subselect::select_transformer"); DBUG_VOID_RETURN; @@ -119,7 +118,7 @@ Item_singleval_subselect::Item_singleval_subselect(THD *thd, Item_subselect() { DBUG_ENTER("Item_singleval_subselect::Item_singleval_subselect"); - init(thd, select_lex, new select_singleval_subselect(this), 0); + init(thd, select_lex, new select_singleval_subselect(this)); max_columns= 1; maybe_null= 1; DBUG_VOID_RETURN; @@ -167,12 +166,11 @@ String *Item_singleval_subselect::val_str (String *str) } Item_exists_subselect::Item_exists_subselect(THD *thd, - st_select_lex *select_lex, - Item *left_expr): + st_select_lex *select_lex): Item_subselect() { DBUG_ENTER("Item_exists_subselect::Item_exists_subselect"); - init(thd, select_lex, new select_exists_subselect(this), left_expr); + init(thd, select_lex, new select_exists_subselect(this)); max_columns= UINT_MAX; null_value= 0; //can't be NULL maybe_null= 0; //can't be NULL @@ -182,12 +180,31 @@ Item_exists_subselect::Item_exists_subselect(THD *thd, DBUG_VOID_RETURN; } -Item_in_subselect::Item_in_subselect(THD *thd, Item * left_expr, +Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp, st_select_lex *select_lex): Item_exists_subselect() { DBUG_ENTER("Item_in_subselect::Item_in_subselect"); - init(thd, select_lex, new select_exists_subselect(this), left_expr); + left_expr= left_exp; + init(thd, select_lex, new select_exists_subselect(this)); + max_columns= UINT_MAX; + null_value= 0; //can't be NULL + maybe_null= 0; //can't be NULL + value= 0; + // We need only 1 row to determinate existence + select_lex->master_unit()->global_parameters->select_limit= 1; + DBUG_VOID_RETURN; +} + +Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp, + compare_func_creator f, + st_select_lex *select_lex): + Item_in_subselect() +{ + DBUG_ENTER("Item_in_subselect::Item_in_subselect"); + left_expr= left_exp; + func= f; + init(thd, select_lex, new select_exists_subselect(this)); max_columns= UINT_MAX; null_value= 0; //can't be NULL maybe_null= 0; //can't be NULL @@ -201,7 +218,6 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_expr, void Item_exists_subselect::fix_length_and_dec() { max_length= 1; - } double Item_exists_subselect::val () @@ -238,12 +254,20 @@ String *Item_exists_subselect::val_str(String *str) Item_in_subselect::Item_in_subselect(Item_in_subselect *item): Item_exists_subselect(item) { + left_expr= item->left_expr; } -void Item_in_subselect::select_transformer(st_select_lex *select_lex, - Item *left_expr) +Item_allany_subselect::Item_allany_subselect(Item_allany_subselect *item): + Item_in_subselect(item) { - DBUG_ENTER("Item_in_subselect::select_transformer"); + func= item->func; +} + +void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, + Item *left_expr, + compare_func_creator func) +{ + DBUG_ENTER("Item_in_subselect::single_value_transformer"); for(SELECT_LEX * sl= select_lex; sl; sl= sl->next_select()) { Item *item; @@ -260,28 +284,38 @@ void Item_in_subselect::select_transformer(st_select_lex *select_lex, if (sl->having || sl->with_sum_func || sl->group_list.first) { sl->item_list.push_back(item); - item= new Item_ref(sl->item_list.head_ref(), 0, ""); + item= (*func)(left_expr, new Item_ref(sl->item_list.head_ref(), + 0, "")); if (sl->having) - sl->having= new Item_cond_and(sl->having, - new Item_func_eq(item, left_expr)); + sl->having= new Item_cond_and(sl->having, item); else - sl->having= new Item_func_eq(item, left_expr); + sl->having= item; } else { sl->item_list.empty(); sl->item_list.push_back(new Item_int(1)); - item= new Item_asterisk_remover(item); + item= (*func)(left_expr, new Item_asterisk_remover(item)); if (sl->where) - sl->where= new Item_cond_and(sl->where, - new Item_func_eq(item, left_expr)); + sl->where= new Item_cond_and(sl->where, item); else - sl->where= new Item_func_eq(item, left_expr); + sl->where= item; } } DBUG_VOID_RETURN; } +void Item_in_subselect::select_transformer(st_select_lex *select_lex) +{ + single_value_transformer(select_lex, left_expr, + &Item_bool_func2::eq_creator); +} + +void Item_allany_subselect::select_transformer(st_select_lex *select_lex) +{ + single_value_transformer(select_lex, left_expr, func); +} + subselect_single_select_engine::subselect_single_select_engine(THD *thd, st_select_lex *select, select_subselect *result, diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 5a5f7bd58d8..3d455b6decf 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -25,6 +25,9 @@ class st_select_lex_unit; class JOIN; class select_subselect; class subselect_engine; +class Item_bool_func2; + +typedef Item_bool_func2* (*compare_func_creator)(Item*, Item*); /* base class for subselects */ @@ -56,15 +59,14 @@ public: to subselect Item class to select_subselect classes constructor. */ virtual void init (THD *thd, st_select_lex *select_lex, - select_subselect *result, - Item *left_expr= 0); + select_subselect *result); ~Item_subselect(); virtual void assign_null() { null_value= 1; } - virtual void select_transformer(st_select_lex *select_lex, Item *left_expr); + virtual void select_transformer(st_select_lex *select_lex); bool assigned() { return value_assigned; } void assigned(bool a) { value_assigned= a; } enum Type type() const; @@ -129,8 +131,7 @@ protected: longlong value; /* value of this item (boolean: exists/not-exists) */ public: - Item_exists_subselect(THD *thd, st_select_lex *select_lex, - Item *left_expr= 0); + Item_exists_subselect(THD *thd, st_select_lex *select_lex); Item_exists_subselect(Item_exists_subselect *item): Item_subselect(item) { @@ -156,10 +157,29 @@ public: class Item_in_subselect :public Item_exists_subselect { +protected: + Item * left_expr; + public: Item_in_subselect(THD *thd, Item * left_expr, st_select_lex *select_lex); Item_in_subselect(Item_in_subselect *item); - virtual void select_transformer(st_select_lex *select_lex, Item *left_exp); + Item_in_subselect(): Item_exists_subselect() {} + virtual void select_transformer(st_select_lex *select_lex); + void single_value_transformer(st_select_lex *select_lex, + Item *left_expr, compare_func_creator func); +}; + +/* ALL/ANY/SOME subselect */ +class Item_allany_subselect :public Item_in_subselect +{ +protected: + compare_func_creator func; + +public: + Item_allany_subselect(THD *thd, Item * left_expr, compare_func_creator f, + st_select_lex *select_lex); + Item_allany_subselect(Item_allany_subselect *item); + virtual void select_transformer(st_select_lex *select_lex); }; class subselect_engine diff --git a/sql/lex.h b/sql/lex.h index 4b56eb4b5d8..744b4c9bf27 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -56,6 +56,7 @@ static SYMBOL symbols[] = { { "AGAINST", SYM(AGAINST),0,0}, { "ANALYZE", SYM(ANALYZE_SYM),0,0}, { "AND", SYM(AND),0,0}, + { "ANY", SYM(ANY_SYM),0,0}, { "AS", SYM(AS),0,0}, { "ASC", SYM(ASC),0,0}, { "AVG", SYM(AVG_SYM),0,0}, @@ -323,6 +324,7 @@ static SYMBOL symbols[] = { { "SHUTDOWN", SYM(SHUTDOWN),0,0}, { "SLAVE", SYM(SLAVE),0,0}, { "SMALLINT", SYM(SMALLINT),0,0}, + { "SOME", SYM(ANY_SYM),0,0}, { "SONAME", SYM(UDF_SONAME_SYM),0,0}, { "SPATIAL", SYM(SPATIAL_SYM),0,0}, { "SQL_BIG_RESULT", SYM(SQL_BIG_RESULT),0,0}, diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index c61621bf91d..457dbe7a73d 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -263,6 +263,7 @@ inline THD *_current_thd(void) #include "field.h" /* Field definitions */ #include "sql_udf.h" #include "item.h" +typedef compare_func_creator (*chooser_compare_func_creator)(bool invert); #include "sql_class.h" #include "opt_range.h" @@ -867,3 +868,11 @@ inline void mark_as_null_row(TABLE *table) table->status|=STATUS_NULL_ROW; bfill(table->null_flags,table->null_bytes,255); } + +compare_func_creator comp_eq_creator(bool invert); +compare_func_creator comp_ge_creator(bool invert); +compare_func_creator comp_gt_creator(bool invert); +compare_func_creator comp_le_creator(bool invert); +compare_func_creator comp_lt_creator(bool invert); +compare_func_creator comp_ne_creator(bool invert); + diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 57325ef19cf..28a2db61f6d 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3706,3 +3706,33 @@ bool check_simple_select() } return 0; } + +compare_func_creator comp_eq_creator(bool invert) +{ + return invert?&Item_bool_func2::ne_creator:&Item_bool_func2::eq_creator; +} + +compare_func_creator comp_ge_creator(bool invert) +{ + return invert?&Item_bool_func2::lt_creator:&Item_bool_func2::ge_creator; +} + +compare_func_creator comp_gt_creator(bool invert) +{ + return invert?&Item_bool_func2::le_creator:&Item_bool_func2::gt_creator; +} + +compare_func_creator comp_le_creator(bool invert) +{ + return invert?&Item_bool_func2::gt_creator:&Item_bool_func2::le_creator; +} + +compare_func_creator comp_lt_creator(bool invert) +{ + return invert?&Item_bool_func2::ge_creator:&Item_bool_func2::lt_creator; +} + +compare_func_creator comp_ne_creator(bool invert) +{ + return invert?&Item_bool_func2::eq_creator:&Item_bool_func2::ne_creator; +} diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 3ac15324ce6..e2e17d98f2c 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -71,6 +71,7 @@ inline Item *or_or_concat(Item* A, Item* B) CHARSET_INFO *charset; interval_type interval; st_select_lex *select_lex; + chooser_compare_func_creator boolfunc2creator; } %{ @@ -104,6 +105,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token AFTER_SYM %token ALTER %token ANALYZE_SYM +%token ANY_SYM %token AVG_SYM %token BEGIN_SYM %token BINLOG_SYM @@ -551,7 +553,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); type int_type real_type order_dir opt_field_spec lock_option udf_type if_exists opt_local opt_table_options table_options table_option opt_if_not_exists opt_var_type opt_var_ident_type - delete_option + delete_option all_or_any %type ULONG_NUM raid_types merge_insert_types @@ -616,6 +618,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %type in_subselect in_subselect_init +%type comp_op + %type query verb_clause create change select do drop insert replace insert2 insert_values update delete truncate rename @@ -641,7 +645,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); opt_mi_check_type opt_to mi_check_types normal_join table_to_table_list table_to_table opt_table_list opt_as handler_rkey_function handler_read_or_scan - single_multi table_wild_list table_wild_one opt_wild union union_list + single_multi table_wild_list table_wild_one opt_wild union precision union_option opt_on_delete_item subselect_start opt_and subselect_end select_var_list select_var_list_init help END_OF_INPUT @@ -1723,6 +1727,18 @@ optional_braces: expr: expr_expr { $$= $1; } | simple_expr { $$= $1; }; +comp_op: EQ { $$ = &comp_eq_creator; } + | GE { $$ = &comp_ge_creator; } + | GT_SYM { $$ = &comp_gt_creator; } + | LE { $$ = &comp_le_creator; } + | LT { $$ = &comp_lt_creator; } + | NE { $$ = &comp_ne_creator; } + ; + +all_or_any: ALL { $$ = 1; } + | ANY_SYM { $$ = 0; } + ; + /* expressions that begin with 'expr' */ expr_expr: expr IN_SYM '(' expr_list ')' @@ -1749,13 +1765,17 @@ expr_expr: | expr NOT REGEXP expr { $$= new Item_func_not(new Item_func_regex($1,$4)); } | expr IS NULL_SYM { $$= new Item_func_isnull($1); } | expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); } - | expr EQ expr { $$= new Item_func_eq($1,$3); } | expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); } - | expr GE expr { $$= new Item_func_ge($1,$3); } - | expr GT_SYM expr { $$= new Item_func_gt($1,$3); } - | expr LE expr { $$= new Item_func_le($1,$3); } - | expr LT expr { $$= new Item_func_lt($1,$3); } - | expr NE expr { $$= new Item_func_ne($1,$3); } + | expr comp_op expr %prec EQ { $$= (*((*$2)(0)))($1,$3); } + | expr comp_op all_or_any in_subselect %prec EQ + { + Item_allany_subselect *it= + new Item_allany_subselect(current_thd, $1, (*$2)($3), $4); + if ($3) + $$ = new Item_func_not(it); /* ALL */ + else + $$ = it; /* ANY/SOME */ + } | expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); } | expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); } | expr '+' expr { $$= new Item_func_plus($1,$3); } @@ -1789,13 +1809,17 @@ no_in_expr: | no_in_expr NOT REGEXP expr { $$= new Item_func_not(new Item_func_regex($1,$4)); } | no_in_expr IS NULL_SYM { $$= new Item_func_isnull($1); } | no_in_expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); } - | no_in_expr EQ expr { $$= new Item_func_eq($1,$3); } | no_in_expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); } - | no_in_expr GE expr { $$= new Item_func_ge($1,$3); } - | no_in_expr GT_SYM expr { $$= new Item_func_gt($1,$3); } - | no_in_expr LE expr { $$= new Item_func_le($1,$3); } - | no_in_expr LT expr { $$= new Item_func_lt($1,$3); } - | no_in_expr NE expr { $$= new Item_func_ne($1,$3); } + | no_in_expr comp_op expr %prec EQ { $$= (*((*$2)(0)))($1,$3); } + | no_in_expr comp_op all_or_any in_subselect %prec EQ + { + Item_allany_subselect *it= + new Item_allany_subselect(current_thd, $1, (*$2)($3), $4); + if ($3) + $$ = new Item_func_not(it); /* ALL */ + else + $$ = it; /* ANY/SOME */ + } | no_in_expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); } | no_in_expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); } | no_in_expr '+' expr { $$= new Item_func_plus($1,$3); } @@ -1837,13 +1861,17 @@ no_and_expr: | no_and_expr NOT REGEXP expr { $$= new Item_func_not(new Item_func_regex($1,$4)); } | no_and_expr IS NULL_SYM { $$= new Item_func_isnull($1); } | no_and_expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); } - | no_and_expr EQ expr { $$= new Item_func_eq($1,$3); } | no_and_expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); } - | no_and_expr GE expr { $$= new Item_func_ge($1,$3); } - | no_and_expr GT_SYM expr { $$= new Item_func_gt($1,$3); } - | no_and_expr LE expr { $$= new Item_func_le($1,$3); } - | no_and_expr LT expr { $$= new Item_func_lt($1,$3); } - | no_and_expr NE expr { $$= new Item_func_ne($1,$3); } + | no_and_expr comp_op expr %prec EQ { $$= (*((*$2)(0)))($1,$3); } + | no_and_expr comp_op all_or_any in_subselect %prec EQ + { + Item_allany_subselect *it= + new Item_allany_subselect(current_thd, $1, (*$2)($3), $4); + if ($3) + $$ = new Item_func_not(it); /* ALL */ + else + $$ = it; /* ANY/SOME */ + } | no_and_expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); } | no_and_expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); } | no_and_expr '+' expr { $$= new Item_func_plus($1,$3); } @@ -3495,6 +3523,7 @@ keyword: | AFTER_SYM {} | AGAINST {} | AGGREGATE_SYM {} + | ANY_SYM {} | AUTO_INC {} | AVG_ROW_LENGTH {} | AVG_SYM {} @@ -4173,10 +4202,7 @@ rollback: union: /* empty */ {} - | union_list; - -union_list: - UNION_SYM union_option + |UNION_SYM union_option { LEX *lex=Lex; if (lex->exchange) From 405fb9a5d4f972e6b5ed4e582bfd8b94a8511c75 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 13 Nov 2002 03:53:45 +0500 Subject: [PATCH 08/89] add functions for store keys to temporary file with variable length myisam/sort.c: add function for store keys to temporary files with variable length BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + myisam/sort.c | 207 +++++++++++++++++++++++++++++++++------ 2 files changed, 179 insertions(+), 29 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index aec1275d516..8134a08ea5e 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -90,6 +90,7 @@ venu@myvenu.com venu@work.mysql.com vva@genie.(none) walrus@mysql.com +wax@mysql.com worm@altair.is.lan zak@balfor.local zak@linux.local diff --git a/myisam/sort.c b/myisam/sort.c index 0e69e41ed5c..acf375a2bca 100644 --- a/myisam/sort.c +++ b/myisam/sort.c @@ -47,6 +47,18 @@ typedef struct st_buffpek { ulong max_keys; /* Max keys in buffert */ } BUFFPEK; + +/* + Pointers of functions for store and read keys from temp file +*/ +typedef struct st_key_store { + NEAR int (*write_keys)(struct st_mi_sort_param *, register uchar **, + uint , struct st_buffpek *, IO_CACHE *); + NEAR uint (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint); + NEAR int (*write_key)(struct st_mi_sort_param *, IO_CACHE *,char *, + uint, uint); +} KEY_STORE; + extern void print_error _VARARGS((const char *fmt,...)); /* Functions defined in this file */ @@ -55,8 +67,9 @@ static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info,uint keys, uchar **sort_keys, DYNAMIC_ARRAY *buffpek,int *maxbuffer, IO_CACHE *tempfile, - IO_CACHE *tempfile_for_exceptions); -static int NEAR_F write_keys(MI_SORT_PARAM *info,uchar * *sort_keys, + IO_CACHE *tempfile_for_exceptions, + KEY_STORE *key_store); +static int NEAR_F write_keys(MI_SORT_PARAM *info,uchar **sort_keys, uint count, BUFFPEK *buffpek,IO_CACHE *tempfile); static int NEAR_F write_key(MI_SORT_PARAM *info, uchar *key, IO_CACHE *tempfile); @@ -65,16 +78,25 @@ static int NEAR_F write_index(MI_SORT_PARAM *info,uchar * *sort_keys, static int NEAR_F merge_many_buff(MI_SORT_PARAM *info,uint keys, uchar * *sort_keys, BUFFPEK *buffpek,int *maxbuffer, - IO_CACHE *t_file); + IO_CACHE *t_file,KEY_STORE *key_store); static uint NEAR_F read_to_buffer(IO_CACHE *fromfile,BUFFPEK *buffpek, uint sort_length); static int NEAR_F merge_buffers(MI_SORT_PARAM *info,uint keys, IO_CACHE *from_file, IO_CACHE *to_file, uchar * *sort_keys, BUFFPEK *lastbuff, - BUFFPEK *Fb, BUFFPEK *Tb); + BUFFPEK *Fb, BUFFPEK *Tb, + KEY_STORE *key_store); static int NEAR_F merge_index(MI_SORT_PARAM *,uint,uchar **,BUFFPEK *, int, - IO_CACHE *); - + IO_CACHE *,KEY_STORE *); + +static int NEAR_F write_keys_varlen(MI_SORT_PARAM *info,uchar **sort_keys, + uint count, BUFFPEK *buffpek,IO_CACHE *tempfile); +static uint NEAR_F read_to_buffer_varlen(IO_CACHE *fromfile,BUFFPEK *buffpek, + uint sort_length); +static int NEAR_F write_merge_key(MI_SORT_PARAM *info, IO_CACHE *to_file,char* key, + uint sort_length, uint count) ; +static int NEAR_F write_merge_key_varlen(MI_SORT_PARAM *info, IO_CACHE *to_file,char* key, + uint sort_length, uint count); /* Creates a index of sorted keys @@ -99,9 +121,24 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ha_rows records; uchar **sort_keys; IO_CACHE tempfile, tempfile_for_exceptions; + KEY_STORE key_store; DBUG_ENTER("_create_index_by_sort"); DBUG_PRINT("enter",("sort_length: %d", info->key_length)); + if ((info->keyinfo->seg->type == HA_KEYTYPE_TEXT)|| + (info->keyinfo->seg->type == HA_KEYTYPE_VARTEXT)) + { + key_store.write_keys=write_keys_varlen; + key_store.read_to_buffer=read_to_buffer_varlen; + key_store.write_key=write_merge_key_varlen; + } + else + { + key_store.write_keys=write_keys; + key_store.read_to_buffer=read_to_buffer; + key_store.write_key=write_merge_key; + } + my_b_clear(&tempfile); my_b_clear(&tempfile_for_exceptions); bzero((char*) &buffpek,sizeof(buffpek)); @@ -157,7 +194,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, printf(" - Searching for keys, allocating buffer for %d keys\n",keys); if ((records=find_all_keys(info,keys,sort_keys,&buffpek,&maxbuffer, - &tempfile,&tempfile_for_exceptions)) + &tempfile,&tempfile_for_exceptions,&key_store)) == HA_POS_ERROR) goto err; /* purecov: tested */ if (maxbuffer == 0) @@ -175,7 +212,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, if (!no_messages) printf(" - Merging %lu keys\n",records); /* purecov: tested */ if (merge_many_buff(info,keys,sort_keys, - dynamic_element(&buffpek,0,BUFFPEK *),&maxbuffer,&tempfile)) + dynamic_element(&buffpek,0,BUFFPEK *),&maxbuffer,&tempfile,&key_store)) goto err; /* purecov: inspected */ } if (flush_io_cache(&tempfile) || @@ -184,7 +221,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, if (!no_messages) puts(" - Last merge and dumping keys\n"); /* purecov: tested */ if (merge_index(info,keys,sort_keys,dynamic_element(&buffpek,0,BUFFPEK *), - maxbuffer,&tempfile)) + maxbuffer,&tempfile,&key_store)) goto err; /* purecov: inspected */ } @@ -229,7 +266,8 @@ err: static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys, uchar **sort_keys, DYNAMIC_ARRAY *buffpek, int *maxbuffer, IO_CACHE *tempfile, - IO_CACHE *tempfile_for_exceptions) + IO_CACHE *tempfile_for_exceptions, + KEY_STORE *key_store) { int error; uint idx; @@ -249,7 +287,7 @@ static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys, if (++idx == keys) { - if (write_keys(info,sort_keys,idx-1,(BUFFPEK *)alloc_dynamic(buffpek), + if (key_store->write_keys(info,sort_keys,idx-1,(BUFFPEK *)alloc_dynamic(buffpek), tempfile)) DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */ @@ -263,7 +301,7 @@ static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys, DBUG_RETURN(HA_POS_ERROR); /* Aborted by get_key */ /* purecov: inspected */ if (buffpek->elements) { - if (write_keys(info,sort_keys,idx,(BUFFPEK *)alloc_dynamic(buffpek), + if (key_store->write_keys(info,sort_keys,idx,(BUFFPEK *)alloc_dynamic(buffpek), tempfile)) DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */ *maxbuffer=buffpek->elements-1; @@ -284,6 +322,7 @@ pthread_handler_decl(thr_find_all_keys,arg) uint memavl,old_memavl,keys,sort_length; uint idx, maxbuffer; uchar **sort_keys=0; + KEY_STORE key_store; error=1; @@ -292,6 +331,20 @@ pthread_handler_decl(thr_find_all_keys,arg) if (info->sort_info->got_error) goto err; + if ((info->keyinfo->seg->type == HA_KEYTYPE_TEXT)|| + (info->keyinfo->seg->type == HA_KEYTYPE_VARTEXT)) + { + key_store.write_keys=write_keys_varlen; + key_store.read_to_buffer=read_to_buffer_varlen; + key_store.write_key=write_merge_key_varlen; + } + else + { + key_store.write_keys=write_keys; + key_store.read_to_buffer=read_to_buffer; + key_store.write_key=write_merge_key; + } + my_b_clear(&info->tempfile); my_b_clear(&info->tempfile_for_exceptions); bzero((char*) &info->buffpek,sizeof(info->buffpek)); @@ -365,7 +418,7 @@ pthread_handler_decl(thr_find_all_keys,arg) if (++idx == keys) { - if (write_keys(info,sort_keys,idx-1, + if (key_store.write_keys(info,sort_keys,idx-1, (BUFFPEK *)alloc_dynamic(&info->buffpek), &info->tempfile)) goto err; @@ -379,7 +432,7 @@ pthread_handler_decl(thr_find_all_keys,arg) goto err; if (info->buffpek.elements) { - if (write_keys(info,sort_keys, idx, + if (key_store.write_keys(info,sort_keys, idx, (BUFFPEK *) alloc_dynamic(&info->buffpek), &info->tempfile)) goto err; info->keys=(info->buffpek.elements-1)*(keys-1)+idx; @@ -421,6 +474,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) MI_INFO *info=sort_info->info; MYISAM_SHARE *share=info->s; MI_SORT_PARAM *sinfo; + KEY_STORE key_store; byte *mergebuf=0; LINT_INIT(length); @@ -464,6 +518,19 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) { if (got_error) continue; + if ((sinfo->keyinfo->seg->type == HA_KEYTYPE_TEXT)|| + (sinfo->keyinfo->seg->type == HA_KEYTYPE_VARTEXT)) + { + key_store.write_keys=write_keys_varlen; + key_store.read_to_buffer=read_to_buffer_varlen; + key_store.write_key=write_merge_key_varlen; + } + else + { + key_store.write_keys=write_keys; + key_store.read_to_buffer=read_to_buffer; + key_store.write_key=write_merge_key; + } if (sinfo->buffpek.elements) { uint maxbuffer=sinfo->buffpek.elements-1; @@ -488,7 +555,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) printf("Key %d - Merging %u keys\n",sinfo->key+1, sinfo->keys); if (merge_many_buff(sinfo, keys, (uchar **)mergebuf, dynamic_element(&sinfo->buffpek, 0, BUFFPEK *), - &maxbuffer, &sinfo->tempfile)) + &maxbuffer, &sinfo->tempfile,&key_store)) { got_error=1; continue; @@ -504,7 +571,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) printf("Key %d - Last merge and dumping keys\n", sinfo->key+1); if (merge_index(sinfo, keys, (uchar **)mergebuf, dynamic_element(&sinfo->buffpek,0,BUFFPEK *), - maxbuffer,&sinfo->tempfile) || + maxbuffer,&sinfo->tempfile,&key_store) || flush_pending_blocks(sinfo)) { got_error=1; @@ -568,6 +635,32 @@ static int NEAR_F write_keys(MI_SORT_PARAM *info, register uchar **sort_keys, DBUG_RETURN(0); } /* write_keys */ +static int NEAR_F write_keys_varlen(MI_SORT_PARAM *info, register uchar **sort_keys, + uint count, BUFFPEK *buffpek, IO_CACHE *tempfile) +{ + uchar **end; + DBUG_ENTER("write_keys_varlen"); + + qsort2((byte*) sort_keys,count,sizeof(byte*),(qsort2_cmp) info->key_cmp, + info); + if (!my_b_inited(tempfile) && + open_cached_file(tempfile, my_tmpdir(info->tmpdir), "ST", + DISK_BUFFER_SIZE, info->sort_info->param->myf_rw)) + DBUG_RETURN(1); /* purecov: inspected */ + + buffpek->file_pos=my_b_tell(tempfile); + buffpek->count=count; + for (end=sort_keys+count ; sort_keys != end ; sort_keys++) + { + uint16 len = _mi_keylength(info->keyinfo,*sort_keys); + if (my_b_write(tempfile,(byte*)&len,sizeof(len))) + DBUG_RETURN(1); + if (my_b_write(tempfile,(byte*) *sort_keys,(uint) len)) + DBUG_RETURN(1); + } + DBUG_RETURN(0); +} /* write_keys_varlen */ + static int NEAR_F write_key(MI_SORT_PARAM *info, uchar *key, IO_CACHE *tempfile) @@ -609,7 +702,8 @@ static int NEAR_F write_index(MI_SORT_PARAM *info, register uchar **sort_keys, static int NEAR_F merge_many_buff(MI_SORT_PARAM *info, uint keys, uchar **sort_keys, BUFFPEK *buffpek, - int *maxbuffer, IO_CACHE *t_file) + int *maxbuffer, IO_CACHE *t_file, + KEY_STORE *key_store) { register int i; IO_CACHE t_file2, *from_file, *to_file, *temp; @@ -632,11 +726,11 @@ static int NEAR_F merge_many_buff(MI_SORT_PARAM *info, uint keys, for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF) { if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++, - buffpek+i,buffpek+i+MERGEBUFF-1)) + buffpek+i,buffpek+i+MERGEBUFF-1,key_store)) break; /* purecov: inspected */ } if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++, - buffpek+i,buffpek+ *maxbuffer)) + buffpek+i,buffpek+ *maxbuffer,key_store)) break; /* purecov: inspected */ if (flush_io_cache(to_file)) break; /* purecov: inspected */ @@ -683,6 +777,62 @@ static uint NEAR_F read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, return (count*sort_length); } /* read_to_buffer */ +static uint NEAR_F read_to_buffer_varlen(IO_CACHE *fromfile, BUFFPEK *buffpek, + uint sort_length) +{ + register uint count; + uint16 length_of_key = 0; + uint idx; + uchar *buffp; + + if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count))) + { + buffp = buffpek->base; + + for (idx=1;idx<=count;idx++) + { + if (my_pread(fromfile->file,(byte*)&length_of_key,sizeof(length_of_key), + buffpek->file_pos,MYF_RW)) + return((uint) -1); + buffpek->file_pos+=sizeof(length_of_key); + if (my_pread(fromfile->file,(byte*) buffp,length_of_key, + buffpek->file_pos,MYF_RW)) + return((uint) -1); + buffpek->file_pos+=length_of_key; + buffp = buffp + sort_length; + } + buffpek->key=buffpek->base; + buffpek->count-= count; + buffpek->mem_count= count; + } + return (count*sort_length); +} /* read_to_buffer_varlen */ + + +static int NEAR_F write_merge_key_varlen(MI_SORT_PARAM *info, IO_CACHE *to_file,char* key, + uint sort_length, uint count) +{ + uint idx; + int err; + + uchar *bufs = key; + for (idx=1;idx<=count;idx++) + { + uint16 len = _mi_keylength(info->keyinfo,bufs); + if (err=my_b_write(to_file,(byte*)&len,sizeof(len))) + return(err); + if (err=my_b_write(to_file,(byte*)bufs,(uint) len)) + return(err); + bufs=bufs+sort_length; + } + return(0); +} + +static int NEAR_F write_merge_key(MI_SORT_PARAM *info, IO_CACHE *to_file,char* key, + uint sort_length, uint count) +{ + return(my_b_write(to_file,(byte*) key,(uint) sort_length*count)); +} /* Merge buffers to one buffer @@ -692,7 +842,7 @@ static uint NEAR_F read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, static int NEAR_F merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, IO_CACHE *to_file, uchar **sort_keys, BUFFPEK *lastbuff, - BUFFPEK *Fb, BUFFPEK *Tb) + BUFFPEK *Fb, BUFFPEK *Tb, KEY_STORE *key_store) { int error; uint sort_length,maxcount; @@ -722,8 +872,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, count+= buffpek->count; buffpek->base= strpos; buffpek->max_keys=maxcount; - strpos+= (uint) (error=(int) read_to_buffer(from_file,buffpek, - sort_length)); + strpos+= (uint) (error=(int) key_store->read_to_buffer(from_file,buffpek,sort_length)); if (error == -1) goto err; /* purecov: inspected */ queue_insert(&queue,(char*) buffpek); @@ -740,7 +889,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, buffpek=(BUFFPEK*) queue_top(&queue); if (to_file) { - if (my_b_write(to_file,(byte*) buffpek->key,(uint) sort_length)) + if (key_store->write_key(info,to_file,(byte*) buffpek->key,(uint) sort_length,1)) { error=1; goto err; /* purecov: inspected */ } @@ -755,7 +904,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, buffpek->key+=sort_length; if (! --buffpek->mem_count) { - if (!(error=(int) read_to_buffer(from_file,buffpek,sort_length))) + if (!(error=(int) key_store->read_to_buffer(from_file,buffpek,sort_length))) { uchar *base=buffpek->base; uint max_keys=buffpek->max_keys; @@ -795,8 +944,8 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, { if (to_file) { - if (my_b_write(to_file,(byte*) buffpek->key, - (sort_length*buffpek->mem_count))) + if (key_store->write_key(info,to_file,(byte*) buffpek->key, + sort_length,buffpek->mem_count)) { error=1; goto err; /* purecov: inspected */ } @@ -816,7 +965,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, } } } - while ((error=(int) read_to_buffer(from_file,buffpek,sort_length)) != -1 && + while ((error=(int) key_store->read_to_buffer(from_file,buffpek,sort_length)) != -1 && error != 0); lastbuff->count=count; @@ -832,11 +981,11 @@ err: static int NEAR_F merge_index(MI_SORT_PARAM *info, uint keys, uchar **sort_keys, - BUFFPEK *buffpek, int maxbuffer, IO_CACHE *tempfile) + BUFFPEK *buffpek, int maxbuffer, IO_CACHE *tempfile,KEY_STORE *key_store) { DBUG_ENTER("merge_index"); if (merge_buffers(info,keys,tempfile,(IO_CACHE*) 0,sort_keys,buffpek,buffpek, - buffpek+maxbuffer)) + buffpek+maxbuffer,key_store)) DBUG_RETURN(1); /* purecov: inspected */ DBUG_RETURN(0); } /* merge_index */ From 3f742831211a4d53d97c5ac6ee402b4782de8776 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Nov 2002 20:32:09 +0200 Subject: [PATCH 09/89] basic row Items (SCRUM) include/mysql_com.h: basic row Items include/mysqld_error.h: more wide error mening libmysqld/Makefile.am: basic row Items mysql-test/r/subselect.result: more wide error mening sql/Makefile.am: basic row Items sql/filesort.cc: basic row Items sql/item.cc: basic row Items sql/item.h: basic row Items sql/item_cmpfunc.cc: basic row Items sql/item_cmpfunc.h: basic row Items sql/item_func.cc: basic row Items sql/item_func.h: basic row Items sql/item_strfunc.cc: basic row Items sql/item_strfunc.h: basic row Items sql/item_subselect.cc: basic row Items sql/item_sum.cc: basic row Items sql/share/czech/errmsg.txt: more wide error mening sql/share/danish/errmsg.txt: more wide error mening sql/share/dutch/errmsg.txt: more wide error mening sql/share/english/errmsg.txt: more wide error mening sql/share/estonian/errmsg.txt: more wide error mening sql/share/french/errmsg.txt: more wide error mening sql/share/german/errmsg.txt: more wide error mening sql/share/greek/errmsg.txt: more wide error mening sql/share/hungarian/errmsg.txt: more wide error mening sql/share/italian/errmsg.txt: more wide error mening sql/share/japanese/errmsg.txt: more wide error mening sql/share/korean/errmsg.txt: more wide error mening sql/share/norwegian-ny/errmsg.txt: more wide error mening sql/share/norwegian/errmsg.txt: more wide error mening sql/share/polish/errmsg.txt: more wide error mening sql/share/portuguese/errmsg.txt: more wide error mening sql/share/romanian/errmsg.txt: more wide error mening sql/share/russian/errmsg.txt: more wide error mening sql/share/serbian/errmsg.txt: more wide error mening sql/share/slovak/errmsg.txt: more wide error mening sql/share/spanish/errmsg.txt: more wide error mening sql/share/swedish/errmsg.txt: more wide error mening sql/share/ukrainian/errmsg.txt: more wide error mening sql/sql_base.cc: fix_fields error handling sql/sql_lex.cc: basic row Items sql/sql_select.cc: basic row Items sql/sql_yacc.yy: basic row Items --- include/mysql_com.h | 2 +- include/mysqld_error.h | 2 +- libmysqld/Makefile.am | 2 +- mysql-test/r/row_test.result | 45 ++++++++++ mysql-test/r/subselect.result | 4 +- mysql-test/t/row_test.test | 19 ++++ sql/Makefile.am | 6 +- sql/filesort.cc | 8 ++ sql/item.cc | 14 +++ sql/item.h | 13 ++- sql/item_cmpfunc.cc | 143 ++++++++++++++++++++---------- sql/item_cmpfunc.h | 105 ++++++++++++++++++---- sql/item_func.cc | 45 +++++++++- sql/item_func.h | 26 +++--- sql/item_row.cc | 66 ++++++++++++++ sql/item_row.h | 65 ++++++++++++++ sql/item_strfunc.cc | 4 +- sql/item_strfunc.h | 11 ++- sql/item_subselect.cc | 2 +- sql/item_sum.cc | 23 ++++- sql/share/czech/errmsg.txt | 4 +- sql/share/danish/errmsg.txt | 2 +- sql/share/dutch/errmsg.txt | 2 +- sql/share/english/errmsg.txt | 2 +- sql/share/estonian/errmsg.txt | 2 +- sql/share/french/errmsg.txt | 2 +- sql/share/german/errmsg.txt | 2 +- sql/share/greek/errmsg.txt | 2 +- sql/share/hungarian/errmsg.txt | 2 +- sql/share/italian/errmsg.txt | 2 +- sql/share/japanese/errmsg.txt | 2 +- sql/share/korean/errmsg.txt | 2 +- sql/share/norwegian-ny/errmsg.txt | 2 +- sql/share/norwegian/errmsg.txt | 2 +- sql/share/polish/errmsg.txt | 2 +- sql/share/portuguese/errmsg.txt | 2 +- sql/share/romanian/errmsg.txt | 2 +- sql/share/russian/errmsg.txt | 2 +- sql/share/serbian/errmsg.txt | 2 +- sql/share/slovak/errmsg.txt | 2 +- sql/share/spanish/errmsg.txt | 2 +- sql/share/swedish/errmsg.txt | 2 +- sql/share/ukrainian/errmsg.txt | 6 +- sql/sql_base.cc | 4 +- sql/sql_lex.cc | 4 + sql/sql_select.cc | 14 ++- sql/sql_yacc.yy | 5 ++ 47 files changed, 553 insertions(+), 131 deletions(-) create mode 100644 mysql-test/r/row_test.result create mode 100644 mysql-test/t/row_test.test create mode 100644 sql/item_row.cc create mode 100644 sql/item_row.h diff --git a/include/mysql_com.h b/include/mysql_com.h index 5bf0394c7b0..b2295d16ecd 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -241,7 +241,7 @@ struct rand_struct { /* The following is for user defined functions */ -enum Item_result {STRING_RESULT,REAL_RESULT,INT_RESULT}; +enum Item_result {STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT}; typedef struct st_udf_args { diff --git a/include/mysqld_error.h b/include/mysqld_error.h index 456d675a045..687fca0adae 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -255,7 +255,7 @@ #define ER_MASTER_FATAL_ERROR_READING_BINLOG 1236 #define ER_WRONG_FK_DEF 1237 #define ER_KEY_REF_DO_NOT_MATCH_TABLE_REF 1238 -#define ER_SUBSELECT_NO_1_COL 1239 +#define ER_CARDINALITY_COL 1239 #define ER_SUBSELECT_NO_1_ROW 1240 #define ER_UNKNOWN_STMT_HANDLER 1241 #define ER_CORRUPT_HELP_DB 1242 diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index 022a589e304..feb1da5871e 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -43,7 +43,7 @@ sqlsources = convert.cc derror.cc field.cc field_conv.cc filesort.cc \ hostname.cc init.cc \ item.cc item_buff.cc item_cmpfunc.cc item_create.cc \ item_func.cc item_strfunc.cc item_sum.cc item_timefunc.cc \ - item_uniq.cc item_subselect.cc \ + item_uniq.cc item_subselect.cc item_row.cc\ key.cc lock.cc log.cc log_event.cc mf_iocache.cc\ mini_client.cc net_pkg.cc net_serv.cc opt_ft.cc opt_range.cc \ opt_sum.cc procedure.cc records.cc sql_acl.cc \ diff --git a/mysql-test/r/row_test.result b/mysql-test/r/row_test.result new file mode 100644 index 00000000000..fa7739904d7 --- /dev/null +++ b/mysql-test/r/row_test.result @@ -0,0 +1,45 @@ +SELECT (1,2,3)=(1,2,3); +(1,2,3)=(1,2,3) +1 +SELECT (2,2,3)=(1+1,2,3); +(2,2,3)=(1+1,2,3) +1 +SELECT (1,2,3)=(1+1,2,3); +(1,2,3)=(1+1,2,3) +0 +SELECT (1,2,3)<(1+1,2,3); +(1,2,3)<(1+1,2,3) +1 +SELECT (1,2,3)>(1+1,2,3); +(1,2,3)>(1+1,2,3) +0 +SELECT (1,2,3)<=(1+1,2,3); +(1,2,3)<=(1+1,2,3) +1 +SELECT (1,2,3)>=(1+1,2,3); +(1,2,3)>=(1+1,2,3) +0 +SELECT (1,2,3)<>(1+1,2,3); +(1,2,3)<>(1+1,2,3) +1 +SELECT (1,2,(3,4,5))=(1,2,(3,4,5)); +(1,2,(3,4,5))=(1,2,(3,4,5)) +1 +SELECT ('test',2,3.33)=('test',2,3.33); +('test',2,3.33)=('test',2,3.33) +1 +SELECT ('test',2,3.33)=('test',2,3.33,4); +Cardinality error (more/less than 4 columns) +drop table if exists t1; +create table t1 ( a int, b int, c int); +insert into t1 values (1,2,3), (2,3,1), (3,2,1); +select * from t1 where (1,2,3)=(a,b,c); +a b c +1 2 3 +select * from t1 where (0,2,3)=(a,b,c); +a b c +select * from t1 where (1,2,3)<(a,b,c); +a b c +2 3 1 +3 2 1 +drop table t1; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index d1a3056d8e9..d3b9e1320f3 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -178,10 +178,10 @@ id select_type table type possible_keys key key_len ref rows Extra 3 SUBSELECT inscrit const PRIMARY PRIMARY 35 const 1 SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo,email FROM inscrit WHERE pseudo='joce'); -Subselect returns more than 1 field +Cardinality error (more/less than 1 columns) SELECT pseudo FROM inscrit WHERE pseudo=(SELECT * FROM inscrit WHERE pseudo='joce'); -Subselect returns more than 1 field +Cardinality error (more/less than 1 columns) SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo='joce'); pseudo joce diff --git a/mysql-test/t/row_test.test b/mysql-test/t/row_test.test new file mode 100644 index 00000000000..8be347cf5fc --- /dev/null +++ b/mysql-test/t/row_test.test @@ -0,0 +1,19 @@ +SELECT (1,2,3)=(1,2,3); +SELECT (2,2,3)=(1+1,2,3); +SELECT (1,2,3)=(1+1,2,3); +SELECT (1,2,3)<(1+1,2,3); +SELECT (1,2,3)>(1+1,2,3); +SELECT (1,2,3)<=(1+1,2,3); +SELECT (1,2,3)>=(1+1,2,3); +SELECT (1,2,3)<>(1+1,2,3); +SELECT (1,2,(3,4,5))=(1,2,(3,4,5)); +SELECT ('test',2,3.33)=('test',2,3.33); +-- error 1239 +SELECT ('test',2,3.33)=('test',2,3.33,4); +drop table if exists t1; +create table t1 ( a int, b int, c int); +insert into t1 values (1,2,3), (2,3,1), (3,2,1); +select * from t1 where (1,2,3)=(a,b,c); +select * from t1 where (0,2,3)=(a,b,c); +select * from t1 where (1,2,3)<(a,b,c); +drop table t1; \ No newline at end of file diff --git a/sql/Makefile.am b/sql/Makefile.am index 09fedd393c2..409613dbbbe 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -46,7 +46,8 @@ mysqld_LDADD = @MYSQLD_EXTRA_LDFLAGS@ \ $(LDADD) $(CXXLDFLAGS) $(WRAPLIBS) @LIBDL@ @openssl_libs@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ item_strfunc.h item_timefunc.h item_uniq.h \ - item_create.h item_subselect.h mysql_priv.h \ + item_create.h item_subselect.h item_row.h \ + mysql_priv.h \ procedure.h sql_class.h sql_lex.h sql_list.h \ sql_manager.h sql_map.h sql_string.h unireg.h \ field.h handler.h \ @@ -61,7 +62,8 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ mysqld_SOURCES = sql_lex.cc sql_handler.cc \ item.cc item_sum.cc item_buff.cc item_func.cc \ item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \ - thr_malloc.cc item_create.cc item_subselect.cc\ + thr_malloc.cc item_create.cc item_subselect.cc \ + item_row.cc \ field.cc key.cc sql_class.cc sql_list.cc \ net_serv.cc net_pkg.cc lock.cc my_lock.c \ sql_string.cc sql_manager.cc sql_map.cc \ diff --git a/sql/filesort.cc b/sql/filesort.cc index 53af60b0370..8247b52ad1b 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -23,6 +23,7 @@ #endif #include #include "sql_sort.h" +#include "assert.h" #ifndef THREAD #define SKIP_DBUG_IN_FILESORT @@ -579,6 +580,10 @@ static void make_sortkey(register SORTPARAM *param, change_double_for_sort(value,(byte*) to); break; } + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; } } if (sort_field->reverse) @@ -965,6 +970,9 @@ sortlength(SORT_FIELD *sortorder, uint s_length) case REAL_RESULT: sortorder->length=sizeof(double); break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); } if (sortorder->item->maybe_null) length++; // Place for NULL marker diff --git a/sql/item.cc b/sql/item.cc index 48ec11d02c2..91c4e70cc8f 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -58,6 +58,16 @@ bool Item::check_loop(uint id) DBUG_RETURN(0); } +bool Item::check_cols(uint c) +{ + if (c != 1) + { + my_error(ER_CARDINALITY_COL, MYF(0), 1); + return 1; + } + return 0; +} + void Item::set_name(const char *str,uint length) { if (!length) @@ -885,6 +895,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) maybe_null= (*ref)->maybe_null; decimals= (*ref)->decimals; } + if (ref && (*ref)->check_cols(1)) + return 1; return 0; } @@ -907,6 +919,8 @@ Item_result item_cmp_type(Item_result a,Item_result b) return STRING_RESULT; else if (a == INT_RESULT && b == INT_RESULT) return INT_RESULT; + else if (a == ROW_RESULT || b == ROW_RESULT) + return ROW_RESULT; else return REAL_RESULT; } diff --git a/sql/item.h b/sql/item.h index c67c16c50ad..192a908c347 100644 --- a/sql/item.h +++ b/sql/item.h @@ -34,7 +34,7 @@ public: INT_ITEM,REAL_ITEM,NULL_ITEM,VARBIN_ITEM, COPY_STR_ITEM,FIELD_AVG_ITEM, DEFAULT_ITEM, PROC_ITEM,COND_ITEM,REF_ITEM,FIELD_STD_ITEM, CONST_ITEM, - SUBSELECT_ITEM}; + SUBSELECT_ITEM, ROW_ITEM}; enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE }; String str_value; /* used to store value */ @@ -87,10 +87,18 @@ public: virtual bool is_null() { return 0; }; virtual CHARSET_INFO *thd_charset() const; virtual CHARSET_INFO *charset() const { return str_value.charset(); }; - virtual bool binary() const { return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; } + virtual bool binary() const + { + return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0; + } virtual void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); } virtual bool check_loop(uint id); + + // Row emulation + virtual uint cols() { return 1; } + virtual Item* el(uint i) { return this; } + virtual bool check_cols(uint c); }; @@ -469,6 +477,7 @@ public: #include "item_timefunc.h" #include "item_uniq.h" #include "item_subselect.h" +#include "item_row.h" class Item_copy_string :public Item { diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 744ed1bceca..5fca3566521 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -23,7 +23,7 @@ #include "mysql_priv.h" #include - +#include "assert.h" /* Test functions @@ -83,7 +83,7 @@ void Item_bool_func2::fix_length_and_dec() { if (convert_constant_item(field,&args[1])) { - cmp_func= &Item_bool_func2::compare_int; // Works for all types. + cmp_func= new Compare_func_int(this); // Works for all types. return; } } @@ -95,88 +95,115 @@ void Item_bool_func2::fix_length_and_dec() { if (convert_constant_item(field,&args[0])) { - cmp_func= &Item_bool_func2::compare_int; // Works for all types. + cmp_func= new Compare_func_int(this); // Works for all types. return; } } } - set_cmp_func(item_cmp_type(args[0]->result_type(),args[1]->result_type())); + set_cmp_func(args[0], args[1]); } - -void Item_bool_func2::set_cmp_func(Item_result type) +Compare_func* Compare_func::get_compare_func(Item_bool_func2 *owner, + Item *a, Item* b) { - switch (type) { + switch (item_cmp_type(a->result_type(), b->result_type())) + { case STRING_RESULT: - cmp_func=&Item_bool_func2::compare_string; - break; + return new Compare_func_string(owner); case REAL_RESULT: - cmp_func=&Item_bool_func2::compare_real; - break; + return new Compare_func_real(owner); case INT_RESULT: - cmp_func=&Item_bool_func2::compare_int; - break; + return new Compare_func_int(owner); + case ROW_RESULT: + return new Compare_func_row(owner, a, b); } + return 0; } +Compare_func_row::Compare_func_row(Item_bool_func2 *owner, Item *a, Item* b): + Compare_func(owner) +{ + uint n= a->cols(); + if (n != b->cols()) + { + my_error(ER_CARDINALITY_COL, MYF(0), n); + cmp_func= 0; + return; + } + cmp_func= (Compare_func **) sql_alloc(sizeof(Compare_func*)*n); + for(uint i=0; i < n; i++) + cmp_func[i]= Compare_func::get_compare_func(owner, a->el(i), b->el(i)); +} -int Item_bool_func2::compare_string() +int Compare_func_string::compare(Item *a, Item *b) { String *res1,*res2; - if ((res1=args[0]->val_str(&tmp_value1))) + if ((res1= a->val_str(&owner->tmp_value1))) { - if ((res2=args[1]->val_str(&tmp_value2))) + if ((res2= b->val_str(&owner->tmp_value2))) { - null_value=0; - return binary() ? stringcmp(res1,res2) : sortcmp(res1,res2); + owner->null_value= 0; + return owner->binary() ? stringcmp(res1,res2) : sortcmp(res1,res2); } } - null_value=1; + owner->null_value= 1; return -1; } -int Item_bool_func2::compare_real() +int Compare_func_real::compare(Item *a, Item *b) { - double val1=args[0]->val(); - if (!args[0]->null_value) + double val1= a->val(); + if (!a->null_value) { - double val2=args[1]->val(); - if (!args[1]->null_value) + double val2= b->val(); + if (!b->null_value) { - null_value=0; + owner->null_value= 0; if (val1 < val2) return -1; if (val1 == val2) return 0; return 1; } } - null_value=1; + owner->null_value= 1; return -1; } -int Item_bool_func2::compare_int() +int Compare_func_int::compare(Item *a, Item *b) { - longlong val1=args[0]->val_int(); - if (!args[0]->null_value) + longlong val1= a->val_int(); + if (!a->null_value) { - longlong val2=args[1]->val_int(); - if (!args[1]->null_value) + longlong val2= b->val_int(); + if (!b->null_value) { - null_value=0; + owner->null_value= 0; if (val1 < val2) return -1; if (val1 == val2) return 0; return 1; } } - null_value=1; + owner->null_value= 1; return -1; } - +int Compare_func_row::compare(Item *a, Item *b) +{ + int res= 0; + uint n= a->cols(); + for(uint i= 0; icompare(a->el(i), b->el(i)))) + return res; + if (owner->null_value) + return -1; + } + return res; +} longlong Item_func_eq::val_int() { - int value=(this->*cmp_func)(); + int value= cmp_func->compare(args[0], args[1]); return value == 0 ? 1 : 0; } @@ -218,6 +245,11 @@ longlong Item_func_equal::val_int() return test(args[0]->null_value && args[1]->null_value); return test(val1 == val2); } + case ROW_RESULT: + { + my_error(ER_WRONG_USAGE, MYF(0), "row", "<=>"); + return 0; + } } return 0; // Impossible } @@ -225,34 +257,34 @@ longlong Item_func_equal::val_int() longlong Item_func_ne::val_int() { - int value=(this->*cmp_func)(); + int value= cmp_func->compare(args[0], args[1]); return value != 0 && !null_value ? 1 : 0; } longlong Item_func_ge::val_int() { - int value=(this->*cmp_func)(); + int value= cmp_func->compare(args[0], args[1]); return value >= 0 ? 1 : 0; } longlong Item_func_gt::val_int() { - int value=(this->*cmp_func)(); + int value= cmp_func->compare(args[0], args[1]); return value > 0 ? 1 : 0; } longlong Item_func_le::val_int() { - int value=(this->*cmp_func)(); + int value= cmp_func->compare(args[0], args[1]); return value <= 0 && !null_value ? 1 : 0; } longlong Item_func_lt::val_int() { - int value=(this->*cmp_func)(); + int value= cmp_func->compare(args[0], args[1]); return value < 0 && !null_value ? 1 : 0; } @@ -595,7 +627,7 @@ double Item_func_nullif::val() { double value; - if (!(this->*cmp_func)() || null_value) + if (!cmp_func->compare(args[0], args[1]) || null_value) { null_value=1; return 0.0; @@ -609,7 +641,7 @@ longlong Item_func_nullif::val_int() { longlong value; - if (!(this->*cmp_func)() || null_value) + if (!cmp_func->compare(args[0], args[1]) || null_value) { null_value=1; return 0; @@ -623,7 +655,7 @@ String * Item_func_nullif::val_str(String *str) { String *res; - if (!(this->*cmp_func)() || null_value) + if (!cmp_func->compare(args[0], args[1]) || null_value) { null_value=1; return 0; @@ -702,6 +734,11 @@ Item *Item_func_case::find_item(String *str) } if (args[i]->val()==first_expr_real && !args[i]->null_value) return args[i+1]; + break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; } } // No, WHEN clauses all missed, return ELSE expression @@ -764,8 +801,10 @@ double Item_func_case::val() bool Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { - if (first_expr && first_expr->fix_fields(thd, tables, &first_expr) || - else_expr && else_expr->fix_fields(thd, tables, &else_expr)) + if (first_expr && (first_expr->check_cols(1) || + first_expr->fix_fields(thd, tables, &first_expr)) || + else_expr && (else_expr->check_cols(1) || + else_expr->fix_fields(thd, tables, &else_expr))) return 1; if (Item_func::fix_fields(thd, tables, ref)) return 1; @@ -1007,6 +1046,10 @@ void Item_func_in::fix_length_and_dec() case REAL_RESULT: array= new in_double(arg_count); break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; } uint j=0; for (uint i=0 ; i < arg_count ; i++) @@ -1033,6 +1076,10 @@ void Item_func_in::fix_length_and_dec() case REAL_RESULT: in_item= new cmp_item_real; break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; } } maybe_null= item->maybe_null; @@ -1141,7 +1188,7 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) #endif item= *li.ref(); // new current item } - if (item->fix_fields(thd, tables, li.ref())) + if (item->check_cols(1) || item->fix_fields(thd, tables, li.ref())) return 1; /* purecov: inspected */ used_tables_cache|=item->used_tables(); with_sum_func= with_sum_func || item->with_sum_func; @@ -1390,7 +1437,9 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref) bool Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { - if (args[0]->fix_fields(thd, tables, args) || + if (args[0]->check_cols(1) || + args[1]->check_cols(1) || + args[0]->fix_fields(thd, tables, args) || args[1]->fix_fields(thd,tables, args + 1)) return 1; /* purecov: inspected */ with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 489d54ae786..dd1cf8d6da6 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -30,6 +30,61 @@ public: void fix_length_and_dec() { decimals=0; max_length=1; } }; +class Item_bool_func2; + +class Compare_func +{ +protected: + Item_bool_func2 *owner; +public: + static void *operator new(size_t size) + { + return (void*) sql_alloc((uint) size); + } + static void operator delete(void *ptr,size_t size) {} + + Compare_func(Item_bool_func2 *o) { owner= o; } + virtual ~Compare_func() {}; + virtual int compare(Item *, Item*)= 0; + + static Compare_func* get_compare_func(Item_bool_func2 *owner, + Item* a, Item* b); +}; + +class Compare_func_string: public Compare_func +{ +public: + Compare_func_string(Item_bool_func2 *owner): Compare_func(owner) {}; + int compare(Item *, Item*); +}; + +class Compare_func_real: public Compare_func +{ +public: + Compare_func_real(Item_bool_func2 *owner): Compare_func(owner) {}; + int compare(Item *, Item*); +}; + +class Compare_func_int: public Compare_func +{ +public: + Compare_func_int(Item_bool_func2 *owner): Compare_func(owner) {}; + int compare(Item *, Item*); +}; + +class Compare_func_row: public Compare_func +{ + Compare_func **cmp_func; +public: + Compare_func_row(Item_bool_func2 *owner, Item* a, Item* b); + ~Compare_func_row() + { + if(cmp_func) + sql_element_free(cmp_func); + } + int compare(Item *, Item*); +}; + class Item_bool_func2 :public Item_int_func { /* Bool with 2 string args */ protected: @@ -37,18 +92,28 @@ protected: public: Item_bool_func2(Item *a,Item *b) :Item_int_func(a,b) {} void fix_length_and_dec(); - void set_cmp_func(Item_result type); - int (Item_bool_func2::*cmp_func)(); - int compare_string(); /* compare arg[0] & arg[1] */ - int compare_real(); /* compare arg[0] & arg[1] */ - int compare_int(); /* compare arg[0] & arg[1] */ + Compare_func *cmp_func; + void set_cmp_func(Item *a, Item *b) + { + cmp_func= Compare_func::get_compare_func(this, args[0], args[1]); + } optimize_type select_optimize() const { return OPTIMIZE_OP; } virtual enum Functype rev_functype() const { return UNKNOWN_FUNC; } bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; } void print(String *str) { Item_func::print_op(str); } bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); } + + friend class Compare_func_string; }; +class Item_bool_rowready_func2 :public Item_bool_func2 +{ +public: + Item_bool_rowready_func2(Item *a,Item *b) :Item_bool_func2(a,b) + { + allowed_arg_cols= a->cols(); + } +}; class Item_func_not :public Item_bool_func { @@ -58,10 +123,10 @@ public: const char *func_name() const { return "not"; } }; -class Item_func_eq :public Item_bool_func2 +class Item_func_eq :public Item_bool_rowready_func2 { public: - Item_func_eq(Item *a,Item *b) :Item_bool_func2(a,b) { }; + Item_func_eq(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { }; longlong val_int(); enum Functype functype() const { return EQ_FUNC; } enum Functype rev_functype() const { return EQ_FUNC; } @@ -83,10 +148,10 @@ public: }; -class Item_func_ge :public Item_bool_func2 +class Item_func_ge :public Item_bool_rowready_func2 { public: - Item_func_ge(Item *a,Item *b) :Item_bool_func2(a,b) { }; + Item_func_ge(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { }; longlong val_int(); enum Functype functype() const { return GE_FUNC; } enum Functype rev_functype() const { return LE_FUNC; } @@ -95,10 +160,10 @@ public: }; -class Item_func_gt :public Item_bool_func2 +class Item_func_gt :public Item_bool_rowready_func2 { public: - Item_func_gt(Item *a,Item *b) :Item_bool_func2(a,b) { }; + Item_func_gt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { }; longlong val_int(); enum Functype functype() const { return GT_FUNC; } enum Functype rev_functype() const { return LT_FUNC; } @@ -107,10 +172,10 @@ public: }; -class Item_func_le :public Item_bool_func2 +class Item_func_le :public Item_bool_rowready_func2 { public: - Item_func_le(Item *a,Item *b) :Item_bool_func2(a,b) { }; + Item_func_le(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { }; longlong val_int(); enum Functype functype() const { return LE_FUNC; } enum Functype rev_functype() const { return GE_FUNC; } @@ -119,10 +184,10 @@ public: }; -class Item_func_lt :public Item_bool_func2 +class Item_func_lt :public Item_bool_rowready_func2 { public: - Item_func_lt(Item *a,Item *b) :Item_bool_func2(a,b) { } + Item_func_lt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { } longlong val_int(); enum Functype functype() const { return LT_FUNC; } enum Functype rev_functype() const { return GT_FUNC; } @@ -131,10 +196,10 @@ public: }; -class Item_func_ne :public Item_bool_func2 +class Item_func_ne :public Item_bool_rowready_func2 { public: - Item_func_ne(Item *a,Item *b) :Item_bool_func2(a,b) { } + Item_func_ne(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { } longlong val_int(); enum Functype functype() const { return NE_FUNC; } cond_result eq_cmp_result() const { return COND_FALSE; } @@ -179,7 +244,8 @@ public: longlong val_int(); bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref) { - return (item->fix_fields(thd, tlist, &item) || + return (item->check_cols(1) || + item->fix_fields(thd, tlist, &item) || Item_func::fix_fields(thd, tlist, ref)); } void fix_length_and_dec(); @@ -414,7 +480,8 @@ class Item_func_in :public Item_int_func longlong val_int(); bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref) { - return (item->fix_fields(thd, tlist, &item) || + return (item->check_cols(1) || + item->fix_fields(thd, tlist, &item) || Item_func::fix_fields(thd, tlist, ref)); } void fix_length_and_dec(); diff --git a/sql/item_func.cc b/sql/item_func.cc index aa39b3cc857..36a804e600c 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -39,7 +39,8 @@ eval_const_cond(COND *cond) } -Item_func::Item_func(List &list) +Item_func::Item_func(List &list): + allowed_arg_cols(1) { arg_count=list.elements; if ((args=(Item**) sql_alloc(sizeof(Item*)*arg_count))) @@ -111,7 +112,8 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) set_charset((*args)->charset()); for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++) { - if ((*arg)->fix_fields(thd, tables, arg)) + if ((*arg)->check_cols(allowed_arg_cols) || + (*arg)->fix_fields(thd, tables, arg)) return 1; /* purecov: inspected */ if ((*arg)->maybe_null) maybe_null=1; @@ -248,6 +250,10 @@ Field *Item_func::tmp_table_field(TABLE *t_arg) else res= new Field_string(max_length, maybe_null, name, t_arg, charset()); break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; } return res; } @@ -869,6 +875,11 @@ String *Item_func_min_max::val_str(String *str) } return res; } + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + return 0; + } return 0; // Keep compiler happy } @@ -1276,7 +1287,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func, arg != arg_end ; arg++,i++) { - if ((*arg)->fix_fields(thd, tables, arg)) + if ((*arg)->check_cols(1) || (*arg)->fix_fields(thd, tables, arg)) return 1; if ((*arg)->binary()) func->set_charset(my_charset_bin); @@ -1405,6 +1416,10 @@ bool udf_handler::get_arguments() to+= ALIGN_SIZE(sizeof(double)); } break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + ; } } return 0; @@ -1857,6 +1872,10 @@ longlong Item_func_benchmark::val_int() case STRING_RESULT: (void) args[0]->val_str(&tmp); break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + return 0; } } return 0; @@ -1983,11 +2002,17 @@ Item_func_set_user_var::update() (void) val_int(); break; case STRING_RESULT: + { char buffer[MAX_FIELD_WIDTH]; String tmp(buffer,sizeof(buffer),default_charset_info); (void) val_str(&tmp); break; } + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; + } return current_thd->fatal_error; } @@ -2062,6 +2087,10 @@ Item_func_get_user_var::val_str(String *str) return NULL; } break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; } return str; } @@ -2079,6 +2108,10 @@ double Item_func_get_user_var::val() return (double) *(longlong*) entry->value; case STRING_RESULT: return atof(entry->value); // This is null terminated + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + return 0; } return 0.0; // Impossible } @@ -2096,6 +2129,10 @@ longlong Item_func_get_user_var::val_int() return *(longlong*) entry->value; case STRING_RESULT: return strtoull(entry->value,NULL,10); // String is null terminated + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + return 0; } return LL(0); // Impossible } @@ -2256,7 +2293,7 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) while ((item=li++)) { - if (item->fix_fields(thd, tlist, li.ref())) + if (item->check_cols(1) || item->fix_fields(thd, tlist, li.ref())) return 1; if (item->type() == Item::REF_ITEM) li.replace(item= *((Item_ref *)item)->ref); diff --git a/sql/item_func.h b/sql/item_func.h index 581809fc9cb..ce05eb0d1d8 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -32,6 +32,7 @@ class Item_func :public Item_result_field { protected: Item **args,*tmp_arg[2]; + uint allowed_arg_cols; public: uint arg_count; table_map used_tables_cache; @@ -49,25 +50,27 @@ public: enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL }; enum Type type() const { return FUNC_ITEM; } virtual enum Functype functype() const { return UNKNOWN_FUNC; } - Item_func(void) + Item_func(void): + allowed_arg_cols(1), arg_count(0) { - arg_count=0; with_sum_func=0; + with_sum_func=0; } - Item_func(Item *a) + Item_func(Item *a): + allowed_arg_cols(1), arg_count(1) { - arg_count=1; args=tmp_arg; args[0]=a; with_sum_func=a->with_sum_func; } - Item_func(Item *a,Item *b) + Item_func(Item *a,Item *b): + allowed_arg_cols(1), arg_count(2) { - arg_count=2; args=tmp_arg; args[0]=a; args[1]=b; with_sum_func=a->with_sum_func || b->with_sum_func; } - Item_func(Item *a,Item *b,Item *c) + Item_func(Item *a,Item *b,Item *c): + allowed_arg_cols(1) { arg_count=0; if ((args=(Item**) sql_alloc(sizeof(Item*)*3))) @@ -77,7 +80,8 @@ public: with_sum_func=a->with_sum_func || b->with_sum_func || c->with_sum_func; } } - Item_func(Item *a,Item *b,Item *c,Item *d) + Item_func(Item *a,Item *b,Item *c,Item *d): + allowed_arg_cols(1) { arg_count=0; if ((args=(Item**) sql_alloc(sizeof(Item*)*4))) @@ -88,7 +92,8 @@ public: d->with_sum_func; } } - Item_func(Item *a,Item *b,Item *c,Item *d,Item* e) + Item_func(Item *a,Item *b,Item *c,Item *d,Item* e): + allowed_arg_cols(1) { arg_count=5; if ((args=(Item**) sql_alloc(sizeof(Item*)*5))) @@ -590,7 +595,8 @@ public: longlong val_int(); bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref) { - return (item->fix_fields(thd, tlist, &item) || + return (item->check_cols(1) || + item->fix_fields(thd, tlist, &item) || Item_func::fix_fields(thd, tlist, ref)); } void update_used_tables() diff --git a/sql/item_row.cc b/sql/item_row.cc new file mode 100644 index 00000000000..95da4f5901e --- /dev/null +++ b/sql/item_row.cc @@ -0,0 +1,66 @@ +/* Copyright (C) 2000 MySQL AB + + This program 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 of the License, or + (at your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "mysql_priv.h" +#include "assert.h" + +Item_row::Item_row(List &arg): + Item(), array_holder(1) +{ + if ((arg_count= arg.elements)) + items= (Item**) sql_alloc(sizeof(Item*)*arg_count); + else + items= 0; + List_iterator li(arg); + uint i= 0; + Item *item; + while ((item= li++)) + { + items[i]= item; + i++; + } +} + +void Item_row::illegal_method_call(const char *method) +{ + DBUG_ENTER("Item_row::illegal_method_call"); + DBUG_PRINT("error", ("!!! %s method was called for row item", method)); + DBUG_ASSERT(0); + my_error(ER_CARDINALITY_COL, MYF(0), arg_count); + DBUG_VOID_RETURN; +} + +bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref) +{ + tables= 0; + for (uint i= 0; i < arg_count; i++) + { + if (items[i]->fix_fields(thd, tabl, items+i)) + return 1; + tables |= items[i]->used_tables(); + } + return 0; +} + +bool Item_row::check_cols(uint c) +{ + if (c != arg_count) + { + my_error(ER_CARDINALITY_COL, MYF(0), arg_count); + return 1; + } + return 0; +} diff --git a/sql/item_row.h b/sql/item_row.h new file mode 100644 index 00000000000..6970b240b31 --- /dev/null +++ b/sql/item_row.h @@ -0,0 +1,65 @@ +/* Copyright (C) 2000 MySQL AB + + This program 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 of the License, or + (at your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +class Item_row: public Item +{ + bool array_holder; + table_map tables; + uint arg_count; + Item **items; +public: + Item_row(List &); + Item_row(Item_row *item): + Item(), array_holder(0), tables(item->tables), arg_count(item->arg_count), + items(item->items) + {} + + ~Item_row() + { + if(array_holder && items) + sql_element_free(items); + } + + enum Type type() const { return ROW_ITEM; }; + void illegal_method_call(const char *); + bool is_null() { return null_value; } + void make_field(Send_field *) + { + illegal_method_call((const char*)"make_field"); + }; + double val() + { + illegal_method_call((const char*)"val"); + return 0; + }; + longlong val_int() + { + illegal_method_call((const char*)"val_int"); + return 0; + }; + String *val_str(String *) + { + illegal_method_call((const char*)"val_str"); + return 0; + }; + bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref); + table_map used_tables() const { return tables; }; + enum Item_result result_type() const { return ROW_RESULT; } + + virtual uint cols() { return arg_count; } + virtual Item* el(uint i) { return items[i]; } + virtual bool check_cols(uint c); +}; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 1a561c9eb34..01958f81deb 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2059,7 +2059,7 @@ bool Item_func_conv_charset::fix_fields(THD *thd,struct st_table_list *tables, I if (thd && check_stack_overrun(thd,buff)) return 0; // Fatal error if flag is set! - if (args[0]->fix_fields(thd, tables, args)) + if (args[0]->check_cols(1) || args[0]->fix_fields(thd, tables, args)) return 1; maybe_null=args[0]->maybe_null; const_item_cache=args[0]->const_item(); @@ -2091,7 +2091,7 @@ bool Item_func_set_collation::fix_fields(THD *thd,struct st_table_list *tables, if (thd && check_stack_overrun(thd,buff)) return 0; // Fatal error if flag is set! - if (args[0]->fix_fields(thd, tables, args)) + if (args[0]->check_cols(1) || args[0]->fix_fields(thd, tables, args)) return 1; maybe_null=args[0]->maybe_null; set_charset(set_collation); diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 2b308630b48..60462621630 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -101,8 +101,9 @@ public: void update_used_tables(); bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { - return (separator->fix_fields(thd, tlist, &separator) - || Item_func::fix_fields(thd, tlist, ref)); + return (separator->check_cols(1) || + separator->fix_fields(thd, tlist, &separator) || + Item_func::fix_fields(thd, tlist, ref)); } const char *func_name() const { return "concat_ws"; } bool check_loop(uint id) @@ -362,7 +363,8 @@ public: String *val_str(String *str); bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { - return (item->fix_fields(thd, tlist, &item) || + return (item->check_cols(1) || + item->fix_fields(thd, tlist, &item) || Item_func::fix_fields(thd, tlist, ref)); } void fix_length_and_dec(); @@ -389,7 +391,8 @@ public: String *val_str(String *str); bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { - return (item->fix_fields(thd, tlist, &item) || + return (item->check_cols(1) || + item->fix_fields(thd, tlist, &item) || Item_func::fix_fields(thd, tlist, ref)); } void fix_length_and_dec(); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 1f1944026ef..0d7f77fb283 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -87,7 +87,7 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) // Is it one field subselect? if (engine->cols() > max_columns) { - my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0)); + my_error(ER_CARDINALITY_COL, MYF(0), 1); return 1; } fix_length_and_dec(); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index db4c45fc412..5e1b30dfddf 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -22,7 +22,7 @@ #endif #include "mysql_priv.h" - +#include "assert.h" Item_sum::Item_sum(List &list) { @@ -124,7 +124,7 @@ Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) maybe_null=0; for (uint i=0 ; i < arg_count ; i++) { - if (args[i]->fix_fields(thd, tables, args + i)) + if (args[i]->check_cols(1) || args[i]->fix_fields(thd, tables, args + i)) return 1; if (decimals < args[i]->decimals) decimals=args[i]->decimals; @@ -149,7 +149,7 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) return 1; } thd->allow_sum_func=0; // No included group funcs - if (item->fix_fields(thd, tables, args)) + if (item->check_cols(1) || item->fix_fields(thd, tables, args)) return 1; hybrid_type=item->result_type(); if (hybrid_type == INT_RESULT) @@ -336,6 +336,10 @@ double Item_sum_hybrid::val() return (double) sum_int; case REAL_RESULT: return sum; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + return 0; } return 0; // Keep compiler happy } @@ -367,6 +371,10 @@ Item_sum_hybrid::val_str(String *str) else str->set((longlong) sum_int,thd_charset()); break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; } return str; // Keep compiler happy } @@ -409,6 +417,10 @@ bool Item_sum_min::add() } } break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; } return 0; } @@ -452,6 +464,11 @@ bool Item_sum_max::add() } } break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; + } return 0; } diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index d43a433da06..2ef5dc43180 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -1,4 +1,4 @@ -/* +v/* Modifikoval Petr -B╘najdr, snajdr@pvt.net, snajdr@cpress.cz v.0.01 -A ISO LATIN-8852-2 Dal-B╧М verze Jan Pazdziora, adelton@fi.muni.cz-A @@ -249,7 +249,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 3a947bcbe38..74d8dadaf72 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -243,7 +243,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 1cb81849be1..5c8261fc07d 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -251,7 +251,7 @@ "Kreeg fatale fout %d: '%-.128s' van master tijdens lezen van data uit binaire log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 6e96fdb393e..89789669612 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -240,7 +240,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 394c40c5778..f1716831b2a 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -245,7 +245,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index b18d3f8fb38..ab07311aa5e 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -240,7 +240,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 49ea31dd05b..028297531fa 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -243,7 +243,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect return more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect return more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index b203c63949b..240a0119f84 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -240,7 +240,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 07081e689ad..63f61a3ca5a 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -242,7 +242,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 0a380e2b48f..569e6d1cacb 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -240,7 +240,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 2e0a083ca06..96eb983cc5d 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -242,7 +242,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 19fcf98e3c7..4f68c071d58 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -240,7 +240,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 810aaf38f74..cda119773d9 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -242,7 +242,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index a74a0a910b8..11f2cffd896 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -242,7 +242,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index efde31ff4c9..63079565d83 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -244,7 +244,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index e90d5844b9b..64eee8c525f 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -240,7 +240,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 18f0bf7f79d..3461df87734 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -244,7 +244,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 790d738031c..06e44722cf5 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -243,7 +243,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Подзапрос возвращает более одного поля", +"Ошибка мощьности множества (больше/меньше %d колонок)", "Подзапрос возвращает более одной записи", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index e8186d38a5b..f7438457660 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -236,7 +236,7 @@ "User '%-.64s' has exceeded the '%s' resource (current value: %ld)", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 216d46fcd3a..8db9dd7770b 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -248,7 +248,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 5076b1b6679..19377803257 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -241,7 +241,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index a3bb40fb4f5..e12a30ed422 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -240,7 +240,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 426c2a14e3b..a824fd1cdd8 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -245,8 +245,8 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Пiдзапит поверта╓ бiльш нiж 1 стовбець", -"Пiдзапит поверта╓ бiльш нiж 1 запис", +"Cardinality error (б╕льше/меньше н╕ж %d стовбц╕в)", +"П╕дзапит поверта╓ б╕льш нiж 1 запис", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", -"Циклiчне посилання на пiдзапит", +"Цикл╕чне посилання на п╕дзапит", diff --git a/sql/sql_base.cc b/sql/sql_base.cc index fd6c2c48020..c50298292ac 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2027,7 +2027,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List &fields, thd->used_tables|=item->used_tables(); } } - DBUG_RETURN(test(thd->fatal_error)); + DBUG_RETURN(test(thd->fatal_error || thd->net.report_error)); } @@ -2239,7 +2239,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) table->on_expr=and_conds(table->on_expr,cond_and); } } - DBUG_RETURN(test(thd->fatal_error)); + DBUG_RETURN(test(thd->fatal_error || thd->net.report_error)); } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 0865e6da05f..5da2066cfb9 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -191,6 +191,10 @@ static int find_keyword(LEX *lex, uint len, bool function) return (udf->type == UDFTYPE_FUNCTION) ? UDF_FLOAT_FUNC : UDA_FLOAT_SUM; case INT_RESULT: return (udf->type == UDFTYPE_FUNCTION) ? UDF_INT_FUNC : UDA_INT_SUM; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + return 0; } } #endif diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b3838628d35..a3672e47d42 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3317,8 +3317,7 @@ change_cond_ref_to_const(I_List *save_list,Item *and_father, if ((tmp2=new COND_CMP(and_father,func))) save_list->push_back(tmp2); } - func->set_cmp_func(item_cmp_type(func->arguments()[0]->result_type(), - func->arguments()[1]->result_type())); + func->set_cmp_func(func->arguments()[0],func->arguments()[1]); } } else if (left_item->eq(field,0) && right_item != value) @@ -3338,8 +3337,7 @@ change_cond_ref_to_const(I_List *save_list,Item *and_father, if ((tmp2=new COND_CMP(and_father,func))) save_list->push_back(tmp2); } - func->set_cmp_func(item_cmp_type(func->arguments()[0]->result_type(), - func->arguments()[1]->result_type())); + func->set_cmp_func(func->arguments()[0], func->arguments()[1]); } } } @@ -3679,6 +3677,10 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, item->name,table,item->charset()); return new Field_string(item_sum->max_length,maybe_null, item->name,table,item->charset()); + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + return 0; } } thd->fatal_error=1; @@ -3735,6 +3737,10 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, new_field= new Field_string(item->max_length,maybe_null, item->name,table,item->str_value.charset()); break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; } if (copy_func) *((*copy_func)++) = (Item_result_field*) item; // Save for copy_funcs diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d432a76770d..1a2a3e9f37e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1873,6 +1873,11 @@ simple_expr: | NOT expr %prec NEG { $$= new Item_func_not($2); } | '!' expr %prec NEG { $$= new Item_func_not($2); } | '(' expr ')' { $$= $2; } + | '(' expr ',' expr_list ')' + { + $4->push_front($2); + $$= new Item_row(*$4); + } | EXISTS exists_subselect { $$= $2; } | singleval_subselect { $$= $1; } | '{' ident expr '}' { $$= $3; } From b9a431c41ca843805ac630d0cf521d2c19083e01 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 17 Nov 2002 05:41:42 +0500 Subject: [PATCH 10/89] Move MI_SORT_PARAM and BUFFPEK to myisamdef.h, delete KEY_STORE, change functions of store keys to temp. file include/myisam.h: move MI_SORT_PARAM to myisamdef.h myisam/myisamdef.h: Move MI_SORT_PARAM and BUFFPEK. Change MI_SORT_PARAM myisam/sort.c: Delete KEY_STORE, change functions of store keys to temp. file --- include/myisam.h | 27 -------- myisam/myisamdef.h | 37 +++++++++++ myisam/sort.c | 151 ++++++++++++++++++++------------------------- 3 files changed, 104 insertions(+), 111 deletions(-) diff --git a/include/myisam.h b/include/myisam.h index acaf8bb7618..74ba0501f9f 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -360,31 +360,6 @@ typedef struct st_sort_info pthread_cond_t cond; } SORT_INFO; - -typedef struct st_mi_sort_param -{ - pthread_t thr; - IO_CACHE read_cache, tempfile, tempfile_for_exceptions; - DYNAMIC_ARRAY buffpek; - ulonglong unique[MI_MAX_KEY_SEG+1]; - my_off_t pos,max_pos,filepos,start_recpos; - uint key, key_length,real_key_length,sortbuff_size; - uint maxbuffers, keys, find_length, sort_keys_length; - my_bool fix_datafile, master; - MI_KEYDEF *keyinfo; - SORT_INFO *sort_info; - uchar **sort_keys; - byte *rec_buff; - void *wordlist, *wordptr; - char *record; - MY_TMPDIR *tmpdir; - int (*key_cmp)(struct st_mi_sort_param *, const void *, const void *); - int (*key_read)(struct st_mi_sort_param *,void *); - int (*key_write)(struct st_mi_sort_param *, const void *); - void (*lock_in_memory)(MI_CHECK *); -} MI_SORT_PARAM; - - /* functions in mi_check */ void myisamchk_init(MI_CHECK *param); int chk_status(MI_CHECK *param, MI_INFO *info); @@ -415,9 +390,7 @@ int filecopy(MI_CHECK *param, File to,File from,my_off_t start, my_off_t length, const char *type); int movepoint(MI_INFO *info,byte *record,my_off_t oldpos, my_off_t newpos, uint prot_key); -int sort_write_record(MI_SORT_PARAM *sort_param); int write_data_suffix(SORT_INFO *sort_info, my_bool fix_datafile); -int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ulong); int test_if_almost_full(MI_INFO *info); int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename); void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows); diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index 6499021861e..5bd63fd8cf6 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -275,7 +275,41 @@ struct st_myisam_info { int rtree_recursion_depth; }; +typedef struct st_buffpek { + my_off_t file_pos; /* Where we are in the sort file */ + uchar *base,*key; /* Key pointers */ + ha_rows count; /* Number of rows in table */ + ulong mem_count; /* numbers of keys in memory */ + ulong max_keys; /* Max keys in buffert */ +} BUFFPEK; +typedef struct st_mi_sort_param +{ + pthread_t thr; + IO_CACHE read_cache, tempfile, tempfile_for_exceptions; + DYNAMIC_ARRAY buffpek; + ulonglong unique[MI_MAX_KEY_SEG+1]; + my_off_t pos,max_pos,filepos,start_recpos; + uint key, key_length,real_key_length,sortbuff_size; + uint maxbuffers, keys, find_length, sort_keys_length; + my_bool fix_datafile, master; + MI_KEYDEF *keyinfo; + SORT_INFO *sort_info; + uchar **sort_keys; + byte *rec_buff; + void *wordlist, *wordptr; + char *record; + MY_TMPDIR *tmpdir; + int (*key_cmp)(struct st_mi_sort_param *, const void *, const void *); + int (*key_read)(struct st_mi_sort_param *,void *); + int (*key_write)(struct st_mi_sort_param *, const void *); + void (*lock_in_memory)(MI_CHECK *); + NEAR int (*write_keys)(struct st_mi_sort_param *, register uchar **, + uint , struct st_buffpek *, IO_CACHE *); + NEAR uint (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint); + NEAR int (*write_key)(struct st_mi_sort_param *, IO_CACHE *,char *, + uint, uint); +} MI_SORT_PARAM; /* Some defines used by isam-funktions */ #define USE_WHOLE_KEY MI_MAX_KEY_BUFF*2 /* Use whole key in _mi_search() */ @@ -658,6 +692,9 @@ int thr_write_keys(MI_SORT_PARAM *sort_param); pthread_handler_decl(thr_find_all_keys,arg); #endif +int sort_write_record(MI_SORT_PARAM *sort_param); +int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ulong); + #ifdef __cplusplus } #endif diff --git a/myisam/sort.c b/myisam/sort.c index acf375a2bca..7152855a54b 100644 --- a/myisam/sort.c +++ b/myisam/sort.c @@ -39,25 +39,10 @@ #define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL) #define DISK_BUFFER_SIZE (IO_SIZE*16) -typedef struct st_buffpek { - my_off_t file_pos; /* Where we are in the sort file */ - uchar *base,*key; /* Key pointers */ - ha_rows count; /* Number of rows in table */ - ulong mem_count; /* numbers of keys in memory */ - ulong max_keys; /* Max keys in buffert */ -} BUFFPEK; - /* Pointers of functions for store and read keys from temp file */ -typedef struct st_key_store { - NEAR int (*write_keys)(struct st_mi_sort_param *, register uchar **, - uint , struct st_buffpek *, IO_CACHE *); - NEAR uint (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint); - NEAR int (*write_key)(struct st_mi_sort_param *, IO_CACHE *,char *, - uint, uint); -} KEY_STORE; extern void print_error _VARARGS((const char *fmt,...)); @@ -67,8 +52,7 @@ static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info,uint keys, uchar **sort_keys, DYNAMIC_ARRAY *buffpek,int *maxbuffer, IO_CACHE *tempfile, - IO_CACHE *tempfile_for_exceptions, - KEY_STORE *key_store); + IO_CACHE *tempfile_for_exceptions); static int NEAR_F write_keys(MI_SORT_PARAM *info,uchar **sort_keys, uint count, BUFFPEK *buffpek,IO_CACHE *tempfile); static int NEAR_F write_key(MI_SORT_PARAM *info, uchar *key, @@ -78,16 +62,15 @@ static int NEAR_F write_index(MI_SORT_PARAM *info,uchar * *sort_keys, static int NEAR_F merge_many_buff(MI_SORT_PARAM *info,uint keys, uchar * *sort_keys, BUFFPEK *buffpek,int *maxbuffer, - IO_CACHE *t_file,KEY_STORE *key_store); + IO_CACHE *t_file); static uint NEAR_F read_to_buffer(IO_CACHE *fromfile,BUFFPEK *buffpek, uint sort_length); static int NEAR_F merge_buffers(MI_SORT_PARAM *info,uint keys, IO_CACHE *from_file, IO_CACHE *to_file, uchar * *sort_keys, BUFFPEK *lastbuff, - BUFFPEK *Fb, BUFFPEK *Tb, - KEY_STORE *key_store); + BUFFPEK *Fb, BUFFPEK *Tb); static int NEAR_F merge_index(MI_SORT_PARAM *,uint,uchar **,BUFFPEK *, int, - IO_CACHE *,KEY_STORE *); + IO_CACHE *); static int NEAR_F write_keys_varlen(MI_SORT_PARAM *info,uchar **sort_keys, uint count, BUFFPEK *buffpek,IO_CACHE *tempfile); @@ -97,7 +80,7 @@ static int NEAR_F write_merge_key(MI_SORT_PARAM *info, IO_CACHE *to_file,char* k uint sort_length, uint count) ; static int NEAR_F write_merge_key_varlen(MI_SORT_PARAM *info, IO_CACHE *to_file,char* key, uint sort_length, uint count); - +inline int my_var_write(MI_SORT_PARAM *info,IO_CACHE *to_file,char *bufs); /* Creates a index of sorted keys @@ -121,22 +104,20 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ha_rows records; uchar **sort_keys; IO_CACHE tempfile, tempfile_for_exceptions; - KEY_STORE key_store; DBUG_ENTER("_create_index_by_sort"); DBUG_PRINT("enter",("sort_length: %d", info->key_length)); - if ((info->keyinfo->seg->type == HA_KEYTYPE_TEXT)|| - (info->keyinfo->seg->type == HA_KEYTYPE_VARTEXT)) + if (info->keyinfo->flag && HA_VAR_LENGTH_KEY) { - key_store.write_keys=write_keys_varlen; - key_store.read_to_buffer=read_to_buffer_varlen; - key_store.write_key=write_merge_key_varlen; + info->write_keys=write_keys_varlen; + info->read_to_buffer=read_to_buffer_varlen; + info->write_key=write_merge_key_varlen; } else { - key_store.write_keys=write_keys; - key_store.read_to_buffer=read_to_buffer; - key_store.write_key=write_merge_key; + info->write_keys=write_keys; + info->read_to_buffer=read_to_buffer; + info->write_key=write_merge_key; } my_b_clear(&tempfile); @@ -194,7 +175,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, printf(" - Searching for keys, allocating buffer for %d keys\n",keys); if ((records=find_all_keys(info,keys,sort_keys,&buffpek,&maxbuffer, - &tempfile,&tempfile_for_exceptions,&key_store)) + &tempfile,&tempfile_for_exceptions)) == HA_POS_ERROR) goto err; /* purecov: tested */ if (maxbuffer == 0) @@ -212,7 +193,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, if (!no_messages) printf(" - Merging %lu keys\n",records); /* purecov: tested */ if (merge_many_buff(info,keys,sort_keys, - dynamic_element(&buffpek,0,BUFFPEK *),&maxbuffer,&tempfile,&key_store)) + dynamic_element(&buffpek,0,BUFFPEK *),&maxbuffer,&tempfile)) goto err; /* purecov: inspected */ } if (flush_io_cache(&tempfile) || @@ -221,7 +202,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, if (!no_messages) puts(" - Last merge and dumping keys\n"); /* purecov: tested */ if (merge_index(info,keys,sort_keys,dynamic_element(&buffpek,0,BUFFPEK *), - maxbuffer,&tempfile,&key_store)) + maxbuffer,&tempfile)) goto err; /* purecov: inspected */ } @@ -266,8 +247,7 @@ err: static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys, uchar **sort_keys, DYNAMIC_ARRAY *buffpek, int *maxbuffer, IO_CACHE *tempfile, - IO_CACHE *tempfile_for_exceptions, - KEY_STORE *key_store) + IO_CACHE *tempfile_for_exceptions) { int error; uint idx; @@ -287,7 +267,7 @@ static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys, if (++idx == keys) { - if (key_store->write_keys(info,sort_keys,idx-1,(BUFFPEK *)alloc_dynamic(buffpek), + if (info->write_keys(info,sort_keys,idx-1,(BUFFPEK *)alloc_dynamic(buffpek), tempfile)) DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */ @@ -301,7 +281,7 @@ static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys, DBUG_RETURN(HA_POS_ERROR); /* Aborted by get_key */ /* purecov: inspected */ if (buffpek->elements) { - if (key_store->write_keys(info,sort_keys,idx,(BUFFPEK *)alloc_dynamic(buffpek), + if (info->write_keys(info,sort_keys,idx,(BUFFPEK *)alloc_dynamic(buffpek), tempfile)) DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */ *maxbuffer=buffpek->elements-1; @@ -322,7 +302,6 @@ pthread_handler_decl(thr_find_all_keys,arg) uint memavl,old_memavl,keys,sort_length; uint idx, maxbuffer; uchar **sort_keys=0; - KEY_STORE key_store; error=1; @@ -331,18 +310,17 @@ pthread_handler_decl(thr_find_all_keys,arg) if (info->sort_info->got_error) goto err; - if ((info->keyinfo->seg->type == HA_KEYTYPE_TEXT)|| - (info->keyinfo->seg->type == HA_KEYTYPE_VARTEXT)) + if (info->keyinfo->flag && HA_VAR_LENGTH_KEY) { - key_store.write_keys=write_keys_varlen; - key_store.read_to_buffer=read_to_buffer_varlen; - key_store.write_key=write_merge_key_varlen; + info->write_keys=write_keys_varlen; + info->read_to_buffer=read_to_buffer_varlen; + info->write_key=write_merge_key_varlen; } else { - key_store.write_keys=write_keys; - key_store.read_to_buffer=read_to_buffer; - key_store.write_key=write_merge_key; + info->write_keys=write_keys; + info->read_to_buffer=read_to_buffer; + info->write_key=write_merge_key; } my_b_clear(&info->tempfile); @@ -418,7 +396,7 @@ pthread_handler_decl(thr_find_all_keys,arg) if (++idx == keys) { - if (key_store.write_keys(info,sort_keys,idx-1, + if (info->write_keys(info,sort_keys,idx-1, (BUFFPEK *)alloc_dynamic(&info->buffpek), &info->tempfile)) goto err; @@ -432,7 +410,7 @@ pthread_handler_decl(thr_find_all_keys,arg) goto err; if (info->buffpek.elements) { - if (key_store.write_keys(info,sort_keys, idx, + if (info->write_keys(info,sort_keys, idx, (BUFFPEK *) alloc_dynamic(&info->buffpek), &info->tempfile)) goto err; info->keys=(info->buffpek.elements-1)*(keys-1)+idx; @@ -474,7 +452,6 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) MI_INFO *info=sort_info->info; MYISAM_SHARE *share=info->s; MI_SORT_PARAM *sinfo; - KEY_STORE key_store; byte *mergebuf=0; LINT_INIT(length); @@ -518,18 +495,17 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) { if (got_error) continue; - if ((sinfo->keyinfo->seg->type == HA_KEYTYPE_TEXT)|| - (sinfo->keyinfo->seg->type == HA_KEYTYPE_VARTEXT)) + if (sinfo->keyinfo->flag && HA_VAR_LENGTH_KEY) { - key_store.write_keys=write_keys_varlen; - key_store.read_to_buffer=read_to_buffer_varlen; - key_store.write_key=write_merge_key_varlen; + sinfo->write_keys=write_keys_varlen; + sinfo->read_to_buffer=read_to_buffer_varlen; + sinfo->write_key=write_merge_key_varlen; } else { - key_store.write_keys=write_keys; - key_store.read_to_buffer=read_to_buffer; - key_store.write_key=write_merge_key; + sinfo->write_keys=write_keys; + sinfo->read_to_buffer=read_to_buffer; + sinfo->write_key=write_merge_key; } if (sinfo->buffpek.elements) { @@ -555,7 +531,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) printf("Key %d - Merging %u keys\n",sinfo->key+1, sinfo->keys); if (merge_many_buff(sinfo, keys, (uchar **)mergebuf, dynamic_element(&sinfo->buffpek, 0, BUFFPEK *), - &maxbuffer, &sinfo->tempfile,&key_store)) + &maxbuffer, &sinfo->tempfile)) { got_error=1; continue; @@ -571,7 +547,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) printf("Key %d - Last merge and dumping keys\n", sinfo->key+1); if (merge_index(sinfo, keys, (uchar **)mergebuf, dynamic_element(&sinfo->buffpek,0,BUFFPEK *), - maxbuffer,&sinfo->tempfile,&key_store) || + maxbuffer,&sinfo->tempfile) || flush_pending_blocks(sinfo)) { got_error=1; @@ -635,10 +611,24 @@ static int NEAR_F write_keys(MI_SORT_PARAM *info, register uchar **sort_keys, DBUG_RETURN(0); } /* write_keys */ +inline int my_var_write(MI_SORT_PARAM *info,IO_CACHE *to_file,char *bufs) +{ + int err; + uint16 len = _mi_keylength(info->keyinfo,bufs); + + if (err=my_b_write(to_file,(byte*)&len,sizeof(len))) + return(err); + if (err=my_b_write(to_file,(byte*)bufs,(uint) len)) + return(err); + return(0); +} + + static int NEAR_F write_keys_varlen(MI_SORT_PARAM *info, register uchar **sort_keys, uint count, BUFFPEK *buffpek, IO_CACHE *tempfile) { uchar **end; + int err; DBUG_ENTER("write_keys_varlen"); qsort2((byte*) sort_keys,count,sizeof(byte*),(qsort2_cmp) info->key_cmp, @@ -652,11 +642,8 @@ static int NEAR_F write_keys_varlen(MI_SORT_PARAM *info, register uchar **sort_k buffpek->count=count; for (end=sort_keys+count ; sort_keys != end ; sort_keys++) { - uint16 len = _mi_keylength(info->keyinfo,*sort_keys); - if (my_b_write(tempfile,(byte*)&len,sizeof(len))) - DBUG_RETURN(1); - if (my_b_write(tempfile,(byte*) *sort_keys,(uint) len)) - DBUG_RETURN(1); + if (err=my_var_write(info,tempfile,*sort_keys)) + DBUG_RETURN(err); } DBUG_RETURN(0); } /* write_keys_varlen */ @@ -702,8 +689,7 @@ static int NEAR_F write_index(MI_SORT_PARAM *info, register uchar **sort_keys, static int NEAR_F merge_many_buff(MI_SORT_PARAM *info, uint keys, uchar **sort_keys, BUFFPEK *buffpek, - int *maxbuffer, IO_CACHE *t_file, - KEY_STORE *key_store) + int *maxbuffer, IO_CACHE *t_file) { register int i; IO_CACHE t_file2, *from_file, *to_file, *temp; @@ -726,11 +712,11 @@ static int NEAR_F merge_many_buff(MI_SORT_PARAM *info, uint keys, for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF) { if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++, - buffpek+i,buffpek+i+MERGEBUFF-1,key_store)) + buffpek+i,buffpek+i+MERGEBUFF-1)) break; /* purecov: inspected */ } if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++, - buffpek+i,buffpek+ *maxbuffer,key_store)) + buffpek+i,buffpek+ *maxbuffer)) break; /* purecov: inspected */ if (flush_io_cache(to_file)) break; /* purecov: inspected */ @@ -813,16 +799,13 @@ static int NEAR_F write_merge_key_varlen(MI_SORT_PARAM *info, IO_CACHE *to_file, uint sort_length, uint count) { uint idx; - int err; - uchar *bufs = key; + char *bufs = key; for (idx=1;idx<=count;idx++) { - uint16 len = _mi_keylength(info->keyinfo,bufs); - if (err=my_b_write(to_file,(byte*)&len,sizeof(len))) - return(err); - if (err=my_b_write(to_file,(byte*)bufs,(uint) len)) - return(err); + int err; + if (err = my_var_write(info,to_file,bufs)) + return(err); bufs=bufs+sort_length; } return(0); @@ -842,7 +825,7 @@ static int NEAR_F write_merge_key(MI_SORT_PARAM *info, IO_CACHE *to_file,char* k static int NEAR_F merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, IO_CACHE *to_file, uchar **sort_keys, BUFFPEK *lastbuff, - BUFFPEK *Fb, BUFFPEK *Tb, KEY_STORE *key_store) + BUFFPEK *Fb, BUFFPEK *Tb) { int error; uint sort_length,maxcount; @@ -872,7 +855,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, count+= buffpek->count; buffpek->base= strpos; buffpek->max_keys=maxcount; - strpos+= (uint) (error=(int) key_store->read_to_buffer(from_file,buffpek,sort_length)); + strpos+= (uint) (error=(int) info->read_to_buffer(from_file,buffpek,sort_length)); if (error == -1) goto err; /* purecov: inspected */ queue_insert(&queue,(char*) buffpek); @@ -889,7 +872,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, buffpek=(BUFFPEK*) queue_top(&queue); if (to_file) { - if (key_store->write_key(info,to_file,(byte*) buffpek->key,(uint) sort_length,1)) + if (info->write_key(info,to_file,(byte*) buffpek->key,(uint) sort_length,1)) { error=1; goto err; /* purecov: inspected */ } @@ -904,7 +887,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, buffpek->key+=sort_length; if (! --buffpek->mem_count) { - if (!(error=(int) key_store->read_to_buffer(from_file,buffpek,sort_length))) + if (!(error=(int) info->read_to_buffer(from_file,buffpek,sort_length))) { uchar *base=buffpek->base; uint max_keys=buffpek->max_keys; @@ -944,7 +927,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, { if (to_file) { - if (key_store->write_key(info,to_file,(byte*) buffpek->key, + if (info->write_key(info,to_file,(byte*) buffpek->key, sort_length,buffpek->mem_count)) { error=1; goto err; /* purecov: inspected */ @@ -965,7 +948,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, } } } - while ((error=(int) key_store->read_to_buffer(from_file,buffpek,sort_length)) != -1 && + while ((error=(int) info->read_to_buffer(from_file,buffpek,sort_length)) != -1 && error != 0); lastbuff->count=count; @@ -981,11 +964,11 @@ err: static int NEAR_F merge_index(MI_SORT_PARAM *info, uint keys, uchar **sort_keys, - BUFFPEK *buffpek, int maxbuffer, IO_CACHE *tempfile,KEY_STORE *key_store) + BUFFPEK *buffpek, int maxbuffer, IO_CACHE *tempfile) { DBUG_ENTER("merge_index"); if (merge_buffers(info,keys,tempfile,(IO_CACHE*) 0,sort_keys,buffpek,buffpek, - buffpek+maxbuffer,key_store)) + buffpek+maxbuffer)) DBUG_RETURN(1); /* purecov: inspected */ DBUG_RETURN(0); } /* merge_index */ From 8e9a5a4f10a04ce793e76c91bd47b4ed146406b5 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Nov 2002 13:45:51 +0100 Subject: [PATCH 11/89] - applied patch for AMD x86-64 (thanks to Gwenole Beauchesne bdb/dist/aclocal/mutex.m4: - applied patch for AMD x86-64 --- bdb/dist/aclocal/mutex.m4 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bdb/dist/aclocal/mutex.m4 b/bdb/dist/aclocal/mutex.m4 index a6b1fa1a053..5c9218da163 100644 --- a/bdb/dist/aclocal/mutex.m4 +++ b/bdb/dist/aclocal/mutex.m4 @@ -403,5 +403,7 @@ UTS/cc-assembly) ADDITIONAL_OBJS="$ADDITIONAL_OBJS uts4.cc${o}" AC_DEFINE(HAVE_MUTEX_UTS_CC_ASSEMBLY);; x86/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" AC_DEFINE(HAVE_MUTEX_X86_GCC_ASSEMBLY);; +x86_64/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + AC_DEFINE(HAVE_MUTEX_X86_64_GCC_ASSEMBLY);; esac ])dnl From 953f6c51fed3478cc3905d2ce15728e5c3e7f00c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Nov 2002 18:26:53 +0400 Subject: [PATCH 12/89] upgrade readline to version 4.3 client/completion_hash.cc: correct headers of functions for readline 4.3 (add const modifier to char*) client/completion_hash.h: correct headers of functions for readline 4.3 (add const modifier to char*) client/mysql.cc: correct functions for readline 4.3 --- client/completion_hash.cc | 6 +- client/completion_hash.h | 4 +- client/mysql.cc | 18 +- readline/COPYING | 4 +- readline/INSTALL | 277 +- readline/Makefile.am | 2 +- readline/README | 37 +- readline/ansi_stdlib.h | 21 +- readline/bind.c | 734 +++-- readline/callback.c | 64 +- readline/chardefs.h | 95 +- readline/complete.c | 644 ++-- readline/configure | 6170 +++++++++++++++++++++++++++---------- readline/configure.in | 105 +- readline/display.c | 1222 ++++++-- readline/emacs_keymap.c | 1292 ++++---- readline/funmap.c | 55 +- readline/histexpand.c | 263 +- readline/histfile.c | 249 +- readline/histlib.h | 28 +- readline/history.c | 59 +- readline/history.h | 88 +- readline/histsearch.c | 25 +- readline/input.c | 365 ++- readline/isearch.c | 265 +- readline/keymaps.c | 16 +- readline/keymaps.h | 45 +- readline/kill.c | 141 +- readline/macro.c | 86 +- readline/mbutil.c | 337 ++ readline/misc.c | 496 +++ readline/nls.c | 37 +- readline/parens.c | 67 +- readline/posixdir.h | 12 +- readline/posixjmp.h | 18 + readline/posixstat.h | 4 +- readline/readline.c | 1776 ++--------- readline/readline.h | 684 ++-- readline/rlconf.h | 11 +- readline/rldefs.h | 43 +- readline/rlmbutil.h | 108 + readline/rlprivate.h | 284 ++ readline/rlshell.h | 34 + readline/rlstdc.h | 64 +- readline/rltty.c | 322 +- readline/rltty.h | 25 +- readline/rltypedefs.h | 88 + readline/rlwinsize.h | 5 +- readline/search.c | 282 +- readline/shell.c | 96 +- readline/signals.c | 68 +- readline/tcap.h | 4 +- readline/terminal.c | 496 +-- readline/text.c | 1540 +++++++++ readline/tilde.c | 124 +- readline/tilde.h | 45 +- readline/undo.c | 33 +- readline/util.c | 163 +- readline/vi_keymap.c | 1284 ++++---- readline/vi_mode.c | 400 ++- readline/xmalloc.c | 67 +- readline/xmalloc.h | 46 + 62 files changed, 14264 insertions(+), 7179 deletions(-) create mode 100644 readline/mbutil.c create mode 100644 readline/misc.c create mode 100644 readline/rlmbutil.h create mode 100644 readline/rlprivate.h create mode 100644 readline/rlshell.h create mode 100644 readline/rltypedefs.h create mode 100644 readline/text.c create mode 100644 readline/xmalloc.h diff --git a/client/completion_hash.cc b/client/completion_hash.cc index ff5d0b28e41..536e7f9373a 100644 --- a/client/completion_hash.cc +++ b/client/completion_hash.cc @@ -27,7 +27,7 @@ #include #include "completion_hash.h" -uint hashpjw(char *arKey, uint nKeyLength) +uint hashpjw(const char *arKey, uint nKeyLength) { uint h = 0, g, i; @@ -111,7 +111,7 @@ int completion_hash_update(HashTable *ht, char *arKey, uint nKeyLength, return SUCCESS; } -static Bucket *completion_hash_find(HashTable *ht, char *arKey, +static Bucket *completion_hash_find(HashTable *ht, const char *arKey, uint nKeyLength) { uint h, nIndex; @@ -156,7 +156,7 @@ int completion_hash_exists(HashTable *ht, char *arKey, uint nKeyLength) return 0; } -Bucket *find_all_matches(HashTable *ht, char *str, uint length, +Bucket *find_all_matches(HashTable *ht, const char *str, uint length, uint *res_length) { Bucket *b; diff --git a/client/completion_hash.h b/client/completion_hash.h index c0853fddfe7..2595a445c9d 100644 --- a/client/completion_hash.h +++ b/client/completion_hash.h @@ -43,14 +43,14 @@ typedef struct hashtable { uint nTableSize; uint initialized; MEM_ROOT mem_root; - uint(*pHashFunction) (char *arKey, uint nKeyLength); + uint(*pHashFunction) (const char *arKey, uint nKeyLength); Bucket **arBuckets; } HashTable; extern int completion_hash_init(HashTable *ht, uint nSize); extern int completion_hash_update(HashTable *ht, char *arKey, uint nKeyLength, char *str); extern int hash_exists(HashTable *ht, char *arKey); -extern Bucket *find_all_matches(HashTable *ht, char *str, uint length, uint *res_length); +extern Bucket *find_all_matches(HashTable *ht, const char *str, uint length, uint *res_length); extern Bucket *find_longest_match(HashTable *ht, char *str, uint length, uint *res_length); extern void add_word(HashTable *ht,char *str); extern void completion_hash_clean(HashTable *ht); diff --git a/client/mysql.cc b/client/mysql.cc index 241f4cf7ecc..391779ef801 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1049,8 +1049,8 @@ static bool add_line(String &buffer,char *line,char *in_string) #ifdef HAVE_READLINE -static char *new_command_generator(char *text, int); -static char **new_mysql_completion (char *text, int start, int end); +static char *new_command_generator(const char *text, int); +static char **new_mysql_completion (const char *text, int start, int end); /* Tell the GNU Readline library how to complete. We want to try to complete @@ -1058,8 +1058,8 @@ static char **new_mysql_completion (char *text, int start, int end); if not. */ -char **no_completion (char *text __attribute__ ((unused)), - char *word __attribute__ ((unused))) +char *no_completion (const char *text __attribute__ ((unused)), + int ) { return 0; /* No filename completion */ } @@ -1071,8 +1071,8 @@ static void initialize_readline (char *name) /* Tell the completer that we want a crack first. */ /* rl_attempted_completion_function = (CPPFunction *)mysql_completion;*/ - rl_attempted_completion_function = (CPPFunction *) new_mysql_completion; - rl_completion_entry_function=(Function *) no_completion; + rl_attempted_completion_function = &new_mysql_completion; + rl_completion_entry_function= &no_completion; } /* @@ -1082,17 +1082,17 @@ static void initialize_readline (char *name) array of matches, or NULL if there aren't any. */ -static char **new_mysql_completion (char *text, +static char **new_mysql_completion (const char *text, int start __attribute__((unused)), int end __attribute__((unused))) { if (!status.batch && !quick) - return completion_matches(text, (CPFunction*) new_command_generator); + return rl_completion_matches(text, new_command_generator); else return (char**) 0; } -static char *new_command_generator(char *text,int state) +static char *new_command_generator(const char *text,int state) { static int textlen; char *ptr; diff --git a/readline/COPYING b/readline/COPYING index a43ea2126fb..1bf15263878 100644 --- a/readline/COPYING +++ b/readline/COPYING @@ -2,7 +2,7 @@ Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA + 59 Temple Place, Suite 330, Boston, MA 02111 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -305,7 +305,7 @@ the "copyright" line and a pointer to where the full notice is found. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. diff --git a/readline/INSTALL b/readline/INSTALL index 95d84c820fb..adb27a9f222 100644 --- a/readline/INSTALL +++ b/readline/INSTALL @@ -1,73 +1,81 @@ Basic Installation ================== - These are generic installation instructions. +These are installation instructions for Readline-4.3. - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, a file -`config.cache' that saves the results of its tests to speed up -reconfiguring, and a file `config.log' containing compiler output -(useful mainly for debugging `configure'). +The simplest way to compile readline is: - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If at some point `config.cache' -contains results you don't want to keep, you may remove or edit it. - - The file `configure.in' is used to create `configure' by a program -called `autoconf'. You only need `configure.in' if you want to change -it or regenerate `configure' using a newer version of `autoconf'. - -The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. If you're + 1. `cd' to the directory containing the readline source code and type + `./configure' to configure readline for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. - Running `configure' takes awhile. While running, it prints some + Running `configure' takes some time. While running, it prints some messages telling which features it is checking for. - 2. Type `make' to compile the package. + 2. Type `make' to compile readline and build the static readline + and history libraries. If supported, the shared readline and history + libraries will be built also. See below for instructions on compiling + the other parts of the distribution. Typing `make everything' will + cause the static and shared libraries (if supported) and the example + programs to be built. - 3. Optionally, type `make check' to run any self-tests that come with - the package. + 3. Type `make install' to install the static readline and history + libraries, the readline include files, the documentation, and, if + supported, the shared readline and history libraries. - 4. Type `make install' to install the programs and any data files and - documentation. - - 5. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for + 4. You can remove the created libraries and object files from the + build directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile readline for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. + for the readline developers, and should be used with care. + +The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It +uses those values to create a `Makefile' in the build directory, +and Makefiles in the `doc', `shlib', and `examples' +subdirectories. It also creates a `config.h' file containing +system-dependent definitions. Finally, it creates a shell script +`config.status' that you can run in the future to recreate the +current configuration, a file `config.cache' that saves the +results of its tests to speed up reconfiguring, and a file +`config.log' containing compiler output (useful mainly for +debugging `configure'). + +If you need to do unusual things to compile readline, please try +to figure out how `configure' could check whether to do them, and +mail diffs or instructions to so they can +be considered for the next release. If at some point +`config.cache' contains results you don't want to keep, you may +remove or edit it. + +The file `configure.in' is used to create `configure' by a +program called `autoconf'. You only need `configure.in' if you +want to change it or regenerate `configure' using a newer version +of `autoconf'. The readline `configure.in' requires autoconf +version 2.50 or newer. Compilers and Options ===================== - Some systems require unusual options for compilation or linking that +Some systems require unusual options for compilation or linking that the `configure' script does not know about. You can give `configure' initial values for variables by setting them in the environment. Using a Bourne-compatible shell, you can do that on the command line like this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure Compiling For Multiple Architectures ==================================== - You can compile the package for more than one kind of computer at the +You can compile readline for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the @@ -75,80 +83,59 @@ directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. - If you have to use a `make' that does not supports the `VPATH' -variable, you have to compile the package for one architecture at a time -in the source code directory. After you have installed the package for -one architecture, use `make distclean' before reconfiguring for another -architecture. +If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile readline for one architecture at a +time in the source code directory. After you have installed +readline for one architecture, use `make distclean' before +reconfiguring for another architecture. Installation Names ================== - By default, `make install' will install the package's files in -`/usr/local/bin', `/usr/local/man', etc. You can specify an -installation prefix other than `/usr/local' by giving `configure' the -option `--prefix=PATH'. +By default, `make install' will install the readline libraries in +`/usr/local/lib', the include files in +`/usr/local/include/readline', the man pages in `/usr/local/man', +and the info files in `/usr/local/info'. You can specify an +installation prefix other than `/usr/local' by giving `configure' +the option `--prefix=PATH' or by supplying a value for the +DESTDIR variable when running `make install'. - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -give `configure' the option `--exec-prefix=PATH', the package will use -PATH as the prefix for installing programs and libraries. -Documentation and other data files will still use the regular prefix. - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - -Optional Features -================= - - Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. +You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. +If you give `configure' the option `--exec-prefix=PATH', the +readline Makefiles will use PATH as the prefix for installing the +libraries. Documentation and other data files will still use the +regular prefix. Specifying the System Type ========================== - There may be some features `configure' can not figure out -automatically, but needs to determine by the type of host the package -will run on. Usually `configure' can figure that out, but if it prints -a message saying it can not guess the host type, give it the -`--host=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name with three fields: - CPU-COMPANY-SYSTEM +There may be some features `configure' can not figure out +automatically, but need to determine by the type of host readline +will run on. Usually `configure' can figure that out, but if it +prints a message saying it can not guess the host type, give it +the `--host=TYPE' option. TYPE can either be a short name for +the system type, such as `sun4', or a canonical name with three +fields: CPU-COMPANY-SYSTEM (e.g., i386-unknown-freebsd4.2). -See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the host type. - - If you are building compiler tools for cross-compiling, you can also -use the `--target=TYPE' option to select the type of system they will -produce code for and the `--build=TYPE' option to select the type of -system on which you are compiling the package. +See the file `config.sub' for the possible values of each field. Sharing Defaults ================ - If you want to set default values for `configure' scripts to share, +If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. +A warning: the readline `configure' looks for a site script, but not +all `configure' scripts do. Operation Controls ================== - `configure' recognizes the following options to control how it +`configure' recognizes the following options to control how it operates. `--cache-file=FILE' @@ -174,3 +161,113 @@ operates. `configure' also accepts some other, not widely useful, options. +Optional Features +================= + +The readline `configure' recognizes a single `--with-PACKAGE' option: + +`--with-curses' + This tells readline that it can find the termcap library functions + (tgetent, et al.) in the curses library, rather than a separate + termcap library. Readline uses the termcap functions, but does not + link with the termcap or curses library itself, allowing applications + which link with readline the to choose an appropriate library. + This option tells readline to link the example programs with the + curses library rather than libtermcap. + +`configure' also recognizes two `--enable-FEATURE' options: + +`--enable-shared' + Build the shared libraries by default on supported platforms. The + default is `yes'. + +`--enable-static' + Build the static libraries by default. The default is `yes'. + +Shared Libraries +================ + +There is support for building shared versions of the readline and +history libraries. The configure script creates a Makefile in +the `shlib' subdirectory, and typing `make shared' will cause +shared versions of the readline and history libraries to be built +on supported platforms. + +If `configure' is given the `--enable-shared' option, it will attempt +to build the shared libraries by default on supported platforms. + +Configure calls the script support/shobj-conf to test whether or +not shared library creation is supported and to generate the values +of variables that are substituted into shlib/Makefile. If you +try to build shared libraries on an unsupported platform, `make' +will display a message asking you to update support/shobj-conf for +your platform. + +If you need to update support/shobj-conf, you will need to create +a `stanza' for your operating system and compiler. The script uses +the value of host_os and ${CC} as determined by configure. For +instance, FreeBSD 4.2 with any version of gcc is identified as +`freebsd4.2-gcc*'. + +In the stanza for your operating system-compiler pair, you will need to +define several variables. They are: + +SHOBJ_CC The C compiler used to compile source files into shareable + object files. This is normally set to the value of ${CC} + by configure, and should not need to be changed. + +SHOBJ_CFLAGS Flags to pass to the C compiler ($SHOBJ_CC) to create + position-independent code. If you are using gcc, this + should probably be set to `-fpic'. + +SHOBJ_LD The link editor to be used to create the shared library from + the object files created by $SHOBJ_CC. If you are using + gcc, a value of `gcc' will probably work. + +SHOBJ_LDFLAGS Flags to pass to SHOBJ_LD to enable shared object creation. + If you are using gcc, `-shared' may be all that is necessary. + These should be the flags needed for generic shared object + creation. + +SHLIB_XLDFLAGS Additional flags to pass to SHOBJ_LD for shared library + creation. Many systems use the -R option to the link + editor to embed a path within the library for run-time + library searches. A reasonable value for such systems would + be `-R$(libdir)'. + +SHLIB_LIBS Any additional libraries that shared libraries should be + linked against when they are created. + +SHLIB_LIBSUFF The suffix to add to `libreadline' and `libhistory' when + generating the filename of the shared library. Many systems + use `so'; HP-UX uses `sl'. + +SHLIB_LIBVERSION The string to append to the filename to indicate the version + of the shared library. It should begin with $(SHLIB_LIBSUFF), + and possibly include version information that allows the + run-time loader to load the version of the shared library + appropriate for a particular program. Systems using shared + libraries similar to SunOS 4.x use major and minor library + version numbers; for those systems a value of + `$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)$(SHLIB_MINOR)' is appropriate. + Systems based on System V Release 4 don't use minor version + numbers; use `$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' on those systems. + Other Unix versions use different schemes. + +SHLIB_STATUS Set this to `supported' when you have defined the other + necessary variables. Make uses this to determine whether + or not shared library creation should be attempted. If + shared libraries are not supported, this will be set to + `unsupported'. + +You should look at the existing stanzas in support/shobj-conf for ideas. + +Once you have updated support/shobj-conf, re-run configure and type +`make shared' or `make'. The shared libraries will be created in the +shlib subdirectory. + +If shared libraries are created, `make install' will install them. +You may install only the shared libraries by running `make +install-shared' from the top-level build directory. Running `make +install' in the shlib subdirectory will also work. If you don't want +to install any created shared libraries, run `make install-static'. diff --git a/readline/Makefile.am b/readline/Makefile.am index 37e97289e6b..e9c6b3b8d58 100644 --- a/readline/Makefile.am +++ b/readline/Makefile.am @@ -15,7 +15,7 @@ libreadline_a_SOURCES = readline.c funmap.c keymaps.c \ callback.c terminal.c xmalloc.c \ history.c histsearch.c histexpand.c \ histfile.c nls.c search.c \ - shell.c tilde.c + shell.c tilde.c misc.c text.c mbutil.c pkginclude_HEADERS = readline.h chardefs.h keymaps.h history.h tilde.h diff --git a/readline/README b/readline/README index 56565b2fb80..7aa939452fb 100644 --- a/readline/README +++ b/readline/README @@ -1,7 +1,7 @@ Introduction ============ -This is the Gnu Readline library, version 4.0. +This is the Gnu Readline library, version 4.3. The Readline library provides a set of functions for use by applications that allow users to edit command lines as they are typed in. Both @@ -16,8 +16,8 @@ may be used without Readline in applications which desire its capabilities. The Readline library is free software, distributed under the terms of -the GNU Public License, version 2. For more information, see the file -COPYING. +the [GNU] General Public License, version 2. For more information, see +the file COPYING. To build the library, try typing `./configure', then `make'. The configuration process is automated, so no further intervention should @@ -37,6 +37,9 @@ to customize and control the build process. The file rlconf.h contains C preprocessor defines that enable and disable certain Readline features. +The special make target `everything' will build the static and shared +libraries (if the target platform supports them) and the examples. + Examples ======== @@ -54,6 +57,9 @@ a Makefile in the `shlib' subdirectory, and typing `make shared' will cause shared versions of the Readline and History libraries to be built on supported platforms. +If `configure' is given the `--enable-shared' option, it will attempt +to build the shared libraries by default on supported platforms. + Configure calls the script support/shobj-conf to test whether or not shared library creation is supported and to generate the values of variables that are substituted into shlib/Makefile. If you @@ -64,8 +70,8 @@ your platform. If you need to update support/shobj-conf, you will need to create a `stanza' for your operating system and compiler. The script uses the value of host_os and ${CC} as determined by configure. For -instance, FreeBSD 2.2.5 with any version of gcc is identified as -`freebsd2.2.5-gcc*'. +instance, FreeBSD 4.2 with any version of gcc is identified as +`freebsd4.2-gcc*'. In the stanza for your operating system-compiler pair, you will need to define several variables. They are: @@ -122,18 +128,21 @@ Once you have updated support/shobj-conf, re-run configure and type `make shared'. The shared libraries will be created in the shlib subdirectory. -Since shared libraries are not created on all platforms, `make install' -will not automatically install the shared libraries. To install them, -change the current directory to shlib and type `make install'. Running -`make install-shared' from the top-level build directory will also work. +If shared libraries are created, `make install' will install them. +You may install only the shared libraries by running `make +install-shared' from the top-level build directory. Running `make +install' in the shlib subdirectory will also work. If you don't want +to install any created shared libraries, run `make install-static'. Documentation ============= -The documentation for the Readline and History libraries appears in the -`doc' subdirectory. There are two texinfo files and a Unix-style manual -page describing the programming facilities available in the Readline -library. The texinfo files include both user and programmer's manuals. +The documentation for the Readline and History libraries appears in +the `doc' subdirectory. There are three texinfo files and a +Unix-style manual page describing the facilities available in the +Readline library. The texinfo files include both user and +programmer's manuals. HTML versions of the manuals appear in the +`doc' subdirectory as well. Reporting Bugs ============== @@ -144,7 +153,7 @@ Bug reports for Readline should be sent to: When reporting a bug, please include the following information: - * the version number and release status of Readline (e.g., 4.0-release) + * the version number and release status of Readline (e.g., 4.2-release) * the machine and OS that it is running on * a list of the compilation flags or the contents of `config.h', if appropriate diff --git a/readline/ansi_stdlib.h b/readline/ansi_stdlib.h index 52339da5d33..db13cd234bd 100644 --- a/readline/ansi_stdlib.h +++ b/readline/ansi_stdlib.h @@ -18,18 +18,31 @@ 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. */ + Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #if !defined (_STDLIB_H_) #define _STDLIB_H_ 1 /* String conversion functions. */ extern int atoi (); -extern long int atol (); + +extern double atof (); +extern double strtod (); /* Memory allocation functions. */ -extern char *malloc (); -extern char *realloc (); +/* Generic pointer type. */ +#ifndef PTR_T + +#if defined (__STDC__) +# define PTR_T void * +#else +# define PTR_T char * +#endif + +#endif /* PTR_T */ + +extern PTR_T malloc (); +extern PTR_T realloc (); extern void free (); /* Other miscellaneous functions. */ diff --git a/readline/bind.c b/readline/bind.c index f122bdf4860..324499acf8f 100644 --- a/readline/bind.c +++ b/readline/bind.c @@ -7,7 +7,7 @@ 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 1, or + 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 @@ -18,7 +18,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) @@ -42,7 +42,6 @@ # include "ansi_stdlib.h" #endif /* HAVE_STDLIB_H */ -#include #include #if !defined (errno) @@ -58,61 +57,27 @@ extern int errno; #include "readline.h" #include "history.h" +#include "rlprivate.h" +#include "rlshell.h" +#include "xmalloc.h" + #if !defined (strchr) && !defined (__STDC__) extern char *strchr (), *strrchr (); #endif /* !strchr && !__STDC__ */ -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_complete_show_all; -extern int _rl_complete_mark_directories; -extern int _rl_print_completions_horizontally; -extern int _rl_completion_case_fold; -extern int _rl_enable_keypad; -#if defined (PAREN_MATCHING) -extern int rl_blink_matching_paren; -#endif /* PAREN_MATCHING */ -#if defined (VISIBLE_STATS) -extern int rl_visible_stats; -#endif /* VISIBLE_STATS */ -extern int rl_complete_with_tilde_expansion; -extern int rl_completion_query_items; -extern int rl_inhibit_completion; -extern char *_rl_comment_begin; -extern unsigned char *_rl_isearch_terminators; - -extern int rl_explicit_arg; -extern int rl_editing_mode; -extern unsigned char _rl_parsing_conditionalized_out; -extern Keymap _rl_keymap; - -extern char *possible_control_prefixes[], *possible_meta_prefixes[]; - -/* Functions imported from funmap.c */ -extern char **rl_funmap_names (); -extern int rl_add_funmap_entry (); - -/* Functions imported from util.c */ -extern char *_rl_strindex (); - -/* Functions imported from shell.c */ -extern char *get_env_value (); - /* Variables exported by this file. */ Keymap rl_binding_keymap; -/* Forward declarations */ -void rl_set_keymap_from_edit_mode (); +static char *_rl_read_file PARAMS((char *, size_t *)); +static void _rl_init_file_error PARAMS((const char *)); +static int _rl_read_init_file PARAMS((const char *, int)); +static int glean_key_from_name PARAMS((char *)); +static int substring_member_of_array PARAMS((char *, const char **)); -static int _rl_read_init_file (const char *filename, int include_level); -static int glean_key_from_name (); -static int substring_member_of_array (); +static int currently_reading_init_file; -extern char *xmalloc (), *xrealloc (); +/* used only in this file */ +static int _rl_prefer_visible_bell = 1; /* **************************************************************** */ /* */ @@ -120,13 +85,13 @@ extern char *xmalloc (), *xrealloc (); /* */ /* **************************************************************** */ -/* rl_add_defun (char *name, Function *function, int key) +/* rl_add_defun (char *name, rl_command_func_t *function, int key) Add NAME to the list of named functions. Make FUNCTION be the function that gets called. If KEY is not -1, then bind it. */ int rl_add_defun (name, function, key) - char *name; - Function *function; + const char *name; + rl_command_func_t *function; int key; { if (key != -1) @@ -139,7 +104,7 @@ rl_add_defun (name, function, key) int rl_bind_key (key, function) int key; - Function *function; + rl_command_func_t *function; { if (key < 0) return (key); @@ -170,7 +135,7 @@ rl_bind_key (key, function) int rl_bind_key_in_map (key, function, map) int key; - Function *function; + rl_command_func_t *function; Keymap map; { int result; @@ -189,7 +154,7 @@ int rl_unbind_key (key) int key; { - return (rl_bind_key (key, (Function *)NULL)); + return (rl_bind_key (key, (rl_command_func_t *)NULL)); } /* Make KEY do nothing in MAP. @@ -199,13 +164,13 @@ rl_unbind_key_in_map (key, map) int key; Keymap map; { - return (rl_bind_key_in_map (key, (Function *)NULL, map)); + return (rl_bind_key_in_map (key, (rl_command_func_t *)NULL, map)); } /* Unbind all keys bound to FUNCTION in MAP. */ int rl_unbind_function_in_map (func, map) - Function *func; + rl_command_func_t *func; Keymap map; { register int i, rval; @@ -214,7 +179,7 @@ rl_unbind_function_in_map (func, map) { if (map[i].type == ISFUNC && map[i].function == func) { - map[i].function = (Function *)NULL; + map[i].function = (rl_command_func_t *)NULL; rval = 1; } } @@ -223,10 +188,10 @@ rl_unbind_function_in_map (func, map) int rl_unbind_command_in_map (command, map) - char *command; + const char *command; Keymap map; { - Function *func; + rl_command_func_t *func; func = rl_named_function (command); if (func == 0) @@ -239,8 +204,8 @@ rl_unbind_command_in_map (command, map) place to do bindings is in MAP. */ int rl_set_key (keyseq, function, map) - char *keyseq; - Function *function; + const char *keyseq; + rl_command_func_t *function; Keymap map; { return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map)); @@ -251,7 +216,7 @@ rl_set_key (keyseq, function, map) necessary. The initial place to do bindings is in MAP. */ int rl_macro_bind (keyseq, macro, map) - char *keyseq, *macro; + const char *keyseq, *macro; Keymap map; { char *macro_keys; @@ -276,12 +241,16 @@ rl_macro_bind (keyseq, macro, map) int rl_generic_bind (type, keyseq, data, map) int type; - char *keyseq, *data; + const char *keyseq; + char *data; Keymap map; { char *keys; int keys_len; register int i; + KEYMAP_ENTRY k; + + k.function = 0; /* If no keys to bind to, exit right away. */ if (!keyseq || !*keyseq) @@ -291,7 +260,7 @@ rl_generic_bind (type, keyseq, data, map) return -1; } - keys = xmalloc (1 + (2 * strlen (keyseq))); + keys = (char *)xmalloc (1 + (2 * strlen (keyseq))); /* Translate the ASCII representation of KEYSEQ into an array of characters. Stuff the characters into KEYS, and the length of @@ -305,7 +274,12 @@ rl_generic_bind (type, keyseq, data, map) /* Bind keys, making new keymaps as necessary. */ for (i = 0; i < keys_len; i++) { - int ic = (int) ((unsigned char)keys[i]); + unsigned char uc = keys[i]; + int ic; + + ic = uc; + if (ic < 0 || ic >= KEYMAP_SIZE) + return -1; if (_rl_convert_meta_chars_to_ascii && META_CHAR (ic)) { @@ -318,18 +292,40 @@ rl_generic_bind (type, keyseq, data, map) { if (map[ic].type != ISKMAP) { - if (map[ic].type == ISMACR) - free ((char *)map[ic].function); + /* We allow subsequences of keys. If a keymap is being + created that will `shadow' an existing function or macro + key binding, we save that keybinding into the ANYOTHERKEY + index in the new map. The dispatch code will look there + to find the function to execute if the subsequence is not + matched. ANYOTHERKEY was chosen to be greater than + UCHAR_MAX. */ + k = map[ic]; map[ic].type = ISKMAP; map[ic].function = KEYMAP_TO_FUNCTION (rl_make_bare_keymap()); } map = FUNCTION_TO_KEYMAP (map, ic); + /* The dispatch code will return this function if no matching + key sequence is found in the keymap. This (with a little + help from the dispatch code in readline.c) allows `a' to be + mapped to something, `abc' to be mapped to something else, + and the function bound to `a' to be executed when the user + types `abx', leaving `bx' in the input queue. */ + if (k.function /* && k.type == ISFUNC */) + { + map[ANYOTHERKEY] = k; + k.function = 0; + } } else { if (map[ic].type == ISMACR) free ((char *)map[ic].function); + else if (map[ic].type == ISKMAP) + { + map = FUNCTION_TO_KEYMAP (map, ic); + ic = ANYOTHERKEY; + } map[ic].function = KEYMAP_TO_FUNCTION (data); map[ic].type = type; @@ -346,7 +342,8 @@ rl_generic_bind (type, keyseq, data, map) non-zero if there was an error parsing SEQ. */ int rl_translate_keyseq (seq, array, len) - char *seq, *array; + const char *seq; + char *array; int *len; { register int i, c, l, temp; @@ -366,7 +363,7 @@ rl_translate_keyseq (seq, array, len) /* Handle special case of backwards define. */ if (strncmp (&seq[i], "C-\\M-", 5) == 0) { - array[l++] = ESC; + array[l++] = ESC; /* ESC is meta-prefix */ i += 5; array[l++] = CTRL (_rl_to_upper (seq[i])); if (seq[i] == '\0') @@ -375,7 +372,7 @@ rl_translate_keyseq (seq, array, len) else if (c == 'M') { i++; - array[l++] = ESC; /* XXX */ + array[l++] = ESC; /* ESC is meta-prefix */ } else if (c == 'C') { @@ -428,16 +425,16 @@ rl_translate_keyseq (seq, array, len) for (temp = 2, c -= '0'; ISOCTAL (seq[i]) && temp--; i++) c = (c * 8) + OCTVALUE (seq[i]); i--; /* auto-increment in for loop */ - array[l++] = c % (largest_char + 1); + array[l++] = c & largest_char; break; case 'x': i++; - for (temp = 3, c = 0; isxdigit (seq[i]) && temp--; i++) + for (temp = 2, c = 0; ISXDIGIT ((unsigned char)seq[i]) && temp--; i++) c = (c * 16) + HEXVALUE (seq[i]); - if (temp == 3) + if (temp == 2) c = 'x'; i--; /* auto-increment in for loop */ - array[l++] = c % (largest_char + 1); + array[l++] = c & largest_char; break; default: /* backslashes before non-special chars just add the char */ array[l++] = c; @@ -507,7 +504,7 @@ _rl_untranslate_macro_value (seq) char *ret, *r, *s; int c; - r = ret = xmalloc (7 * strlen (seq) + 1); + r = ret = (char *)xmalloc (7 * strlen (seq) + 1); for (s = seq; *s; s++) { c = *s; @@ -550,9 +547,9 @@ _rl_untranslate_macro_value (seq) /* Return a pointer to the function that STRING represents. If STRING doesn't have a matching function, then a NULL pointer is returned. */ -Function * +rl_command_func_t * rl_named_function (string) - char *string; + const char *string; { register int i; @@ -561,7 +558,7 @@ rl_named_function (string) for (i = 0; funmap[i]; i++) if (_rl_stricmp (funmap[i]->name, string) == 0) return (funmap[i]->function); - return ((Function *)NULL); + return ((rl_command_func_t *)NULL); } /* Return the function (or macro) definition which would be invoked via @@ -569,8 +566,11 @@ rl_named_function (string) used. TYPE, if non-NULL, is a pointer to an int which will receive the type of the object pointed to. One of ISFUNC (function), ISKMAP (keymap), or ISMACR (macro). */ -Function * -rl_function_of_keyseq (const char *keyseq, Keymap map, int *type) +rl_command_func_t * +rl_function_of_keyseq (keyseq, map, type) + const char *keyseq; + Keymap map; + int *type; { register int i; @@ -579,7 +579,7 @@ rl_function_of_keyseq (const char *keyseq, Keymap map, int *type) for (i = 0; keyseq && keyseq[i]; i++) { - int ic = keyseq[i]; + unsigned char ic = keyseq[i]; if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii) { @@ -619,7 +619,7 @@ rl_function_of_keyseq (const char *keyseq, Keymap map, int *type) return (map[ic].function); } } - return ((Function *) NULL); + return ((rl_command_func_t *) NULL); } /* The last key bindings file read. */ @@ -664,29 +664,26 @@ _rl_read_file (filename, sizep) i = read (file, buffer, file_size); close (file); -#if 0 - if (i < file_size) -#else if (i < 0) -#endif { free (buffer); return ((char *)NULL); } - buffer[file_size] = '\0'; + buffer[i] = '\0'; if (sizep) - *sizep = file_size; + *sizep = i; + return (buffer); } /* Re-read the current keybindings file. */ int -rl_re_read_init_file (int count __attribute__((unused)), - int ignore __attribute__((unused))) +rl_re_read_init_file (count, ignore) + int count __attribute__((unused)), ignore __attribute__((unused)); { int r; - r = rl_read_init_file ((char *)NULL); + r = rl_read_init_file ((const char *)NULL); rl_set_keymap_from_edit_mode (); return r; } @@ -699,14 +696,15 @@ rl_re_read_init_file (int count __attribute__((unused)), If the file existed and could be opened and read, 0 is returned, otherwise errno is returned. */ int -rl_read_init_file (const char *filename) +rl_read_init_file (filename) + const char *filename; { /* Default the filename. */ if (filename == 0) { filename = last_readline_init_file; if (filename == 0) - filename = get_env_value ("INPUTRC"); + filename = sh_get_env_value ("INPUTRC"); if (filename == 0) filename = DEFAULT_INPUTRC; } @@ -714,11 +712,18 @@ rl_read_init_file (const char *filename) if (*filename == 0) filename = DEFAULT_INPUTRC; +#if defined (__MSDOS__) + if (_rl_read_init_file (filename, 0) == 0) + return 0; + filename = "~/_inputrc"; +#endif return (_rl_read_init_file (filename, 0)); } static int -_rl_read_init_file (const char *filename, int include_level) +_rl_read_init_file (filename, include_level) + const char *filename; + int include_level; { register int i; char *buffer, *openname, *line, *end; @@ -733,13 +738,15 @@ _rl_read_init_file (const char *filename, int include_level) if (buffer == 0) return (errno); - + if (include_level == 0 && filename != last_readline_init_file) { FREE (last_readline_init_file); last_readline_init_file = savestring (filename); } + currently_reading_init_file = 1; + /* Loop over the lines in the file. Lines that start with `#' are comments; all other lines are commands for readline initialization. */ current_readline_init_lineno = 1; @@ -750,6 +757,12 @@ _rl_read_init_file (const char *filename, int include_level) /* Find the end of this line. */ for (i = 0; line + i != end && line[i] != '\n'; i++); +#if defined (__CYGWIN__) + /* ``Be liberal in what you accept.'' */ + if (line[i] == '\n' && line[i-1] == '\r') + line[i - 1] = '\0'; +#endif + /* Mark end of line. */ line[i] = '\0'; @@ -770,16 +783,19 @@ _rl_read_init_file (const char *filename, int include_level) } free (buffer); + currently_reading_init_file = 0; return (0); } static void _rl_init_file_error (msg) - char *msg; + const char *msg; { - fprintf (stderr, "readline: %s: line %d: %s\n", current_readline_init_file, - current_readline_init_lineno, - msg); + if (currently_reading_init_file) + fprintf (stderr, "readline: %s: line %d: %s\n", current_readline_init_file, + current_readline_init_lineno, msg); + else + fprintf (stderr, "readline: %s\n", msg); } /* **************************************************************** */ @@ -788,6 +804,17 @@ _rl_init_file_error (msg) /* */ /* **************************************************************** */ +typedef int _rl_parser_func_t PARAMS((char *)); + +/* Things that mean `Control'. */ +const char *_rl_possible_control_prefixes[] = { + "Control-", "C-", "CTRL-", (const char *)NULL +}; + +const char *_rl_possible_meta_prefixes[] = { + "Meta", "M-", (const char *)NULL +}; + /* Conditionals. */ /* Calling programs set this to have their argv[0]. */ @@ -875,7 +902,7 @@ parser_if (args) /* Invert the current parser state if there is anything on the stack. */ static int parser_else (args) -char *args __attribute__((unused)); + char *args __attribute__((unused)); { register int i; @@ -900,7 +927,7 @@ char *args __attribute__((unused)); _rl_parsing_conditionalized_out from the stack. */ static int parser_endif (args) -char *args __attribute__((unused)); + char *args __attribute__((unused)); { if (if_stack_depth) _rl_parsing_conditionalized_out = if_stack[--if_stack_depth]; @@ -927,7 +954,7 @@ parser_include (args) e = strchr (args, '\n'); if (e) *e = '\0'; - r = _rl_read_init_file (args, old_include_level + 1); + r = _rl_read_init_file ((const char *)args, old_include_level + 1); current_readline_init_file = old_init_file; current_readline_init_lineno = old_line_number; @@ -935,17 +962,17 @@ parser_include (args) return r; } - + /* Associate textual names with actual functions. */ static struct { const char *name; - Function *function; + _rl_parser_func_t *function; } parser_directives [] = { { "if", parser_if }, { "endif", parser_endif }, { "else", parser_else }, { "include", parser_include }, - { (char *)0x0, (Function *)0x0 } + { (char *)0x0, (_rl_parser_func_t *)0x0 } }; /* Handle a parser directive. STATEMENT is the line of the directive @@ -1070,7 +1097,7 @@ rl_parse_and_bind (string) /* Make VAR point to start of variable name. */ while (*var && whitespace (*var)) var++; - /* Make value point to start of value string. */ + /* Make VALUE point to start of value string. */ value = var; while (*value && !whitespace (*value)) value++; if (*value) @@ -1140,7 +1167,7 @@ rl_parse_and_bind (string) char *seq; register int j, k, passc; - seq = xmalloc (1 + strlen (string)); + seq = (char *)xmalloc (1 + strlen (string)); for (j = 1, k = passc = 0; string[j]; j++) { /* Allow backslash to quote characters, but leave them in place. @@ -1189,23 +1216,23 @@ rl_parse_and_bind (string) key = glean_key_from_name (kname); /* Add in control and meta bits. */ - if (substring_member_of_array (string, possible_control_prefixes)) + if (substring_member_of_array (string, _rl_possible_control_prefixes)) key = CTRL (_rl_to_upper (key)); - if (substring_member_of_array (string, possible_meta_prefixes)) + if (substring_member_of_array (string, _rl_possible_meta_prefixes)) key = META (key); /* Temporary. Handle old-style keyname with macro-binding. */ if (*funname == '\'' || *funname == '"') { - unsigned char useq[2]; + char useq[2]; int fl = strlen (funname); useq[0] = key; useq[1] = '\0'; if (fl && funname[fl - 1] == *funname) funname[fl - 1] = '\0'; - rl_macro_bind ((char*) useq, &funname[1], _rl_keymap); + rl_macro_bind (useq, &funname[1], _rl_keymap); } #if defined (PREFIX_META_HACK) /* Ugly, but working hack to keep prefix-meta around. */ @@ -1227,154 +1254,278 @@ rl_parse_and_bind (string) have one of two values; either "On" or 1 for truth, or "Off" or 0 for false. */ +#define V_SPECIAL 0x1 + static struct { const char *name; int *value; + int flags; } boolean_varlist [] = { -#if defined (PAREN_MATCHING) - { "blink-matching-paren", &rl_blink_matching_paren }, -#endif - { "completion-ignore-case", &_rl_completion_case_fold }, - { "convert-meta", &_rl_convert_meta_chars_to_ascii }, - { "disable-completion", &rl_inhibit_completion }, - { "enable-keypad", &_rl_enable_keypad }, - { "expand-tilde", &rl_complete_with_tilde_expansion }, - { "horizontal-scroll-mode", &_rl_horizontal_scroll_mode }, - { "input-meta", &_rl_meta_flag }, - { "mark-directories", &_rl_complete_mark_directories }, - { "mark-modified-lines", &_rl_mark_modified_lines }, - { "meta-flag", &_rl_meta_flag }, - { "output-meta", &_rl_output_meta_chars }, - { "print-completions-horizontally", &_rl_print_completions_horizontally }, - { "show-all-if-ambiguous", &_rl_complete_show_all }, + { "blink-matching-paren", &rl_blink_matching_paren, V_SPECIAL }, + { "byte-oriented", &rl_byte_oriented, 0 }, + { "completion-ignore-case", &_rl_completion_case_fold, 0 }, + { "convert-meta", &_rl_convert_meta_chars_to_ascii, 0 }, + { "disable-completion", &rl_inhibit_completion, 0 }, + { "enable-keypad", &_rl_enable_keypad, 0 }, + { "expand-tilde", &rl_complete_with_tilde_expansion, 0 }, + { "history-preserve-point", &_rl_history_preserve_point, 0 }, + { "horizontal-scroll-mode", &_rl_horizontal_scroll_mode, 0 }, + { "input-meta", &_rl_meta_flag, 0 }, + { "mark-directories", &_rl_complete_mark_directories, 0 }, + { "mark-modified-lines", &_rl_mark_modified_lines, 0 }, + { "mark-symlinked-directories", &_rl_complete_mark_symlink_dirs, 0 }, + { "match-hidden-files", &_rl_match_hidden_files, 0 }, + { "meta-flag", &_rl_meta_flag, 0 }, + { "output-meta", &_rl_output_meta_chars, 0 }, + { "page-completions", &_rl_page_completions, 0 }, + { "prefer-visible-bell", &_rl_prefer_visible_bell, V_SPECIAL }, + { "print-completions-horizontally", &_rl_print_completions_horizontally, 0 }, + { "show-all-if-ambiguous", &_rl_complete_show_all, 0 }, #if defined (VISIBLE_STATS) - { "visible-stats", &rl_visible_stats }, + { "visible-stats", &rl_visible_stats, 0 }, #endif /* VISIBLE_STATS */ - { (char *)NULL, (int *)NULL } + { (char *)NULL, (int *)NULL, 0 } }; -int -rl_variable_bind (name, value) - char *name, *value; +static int +find_boolean_var (name) + const char *name; { register int i; - /* Check for simple variables first. */ for (i = 0; boolean_varlist[i].name; i++) - { - if (_rl_stricmp (name, boolean_varlist[i].name) == 0) - { - /* A variable is TRUE if the "value" is "on", "1" or "". */ - *boolean_varlist[i].value = *value == 0 || - _rl_stricmp (value, "on") == 0 || - (value[0] == '1' && value[1] == '\0'); - return 0; - } - } + if (_rl_stricmp (name, boolean_varlist[i].name) == 0) + return i; + return -1; +} - /* Not a boolean variable, so check for specials. */ +/* Hooks for handling special boolean variables, where a + function needs to be called or another variable needs + to be changed when they're changed. */ +static void +hack_special_boolean_var (i) + int i; +{ + const char *name; - /* Editing mode change? */ - if (_rl_stricmp (name, "editing-mode") == 0) - { - if (_rl_strnicmp (value, "vi", 2) == 0) - { -#if defined (VI_MODE) - _rl_keymap = vi_insertion_keymap; - rl_editing_mode = vi_mode; -#endif /* VI_MODE */ - } - else if (_rl_strnicmp (value, "emacs", 5) == 0) - { - _rl_keymap = emacs_standard_keymap; - rl_editing_mode = emacs_mode; - } - } + name = boolean_varlist[i].name; - /* Comment string change? */ - else if (_rl_stricmp (name, "comment-begin") == 0) - { - if (*value) - { - if (_rl_comment_begin) - free (_rl_comment_begin); - - _rl_comment_begin = savestring (value); - } - } - else if (_rl_stricmp (name, "completion-query-items") == 0) - { - int nval = 100; - if (*value) - { - nval = atoi (value); - if (nval < 0) - nval = 0; - } - rl_completion_query_items = nval; - } - else if (_rl_stricmp (name, "keymap") == 0) - { - Keymap kmap; - kmap = rl_get_keymap_by_name (value); - if (kmap) - rl_set_keymap (kmap); - } - else if (_rl_stricmp (name, "bell-style") == 0) - { - if (!*value) - _rl_bell_preference = AUDIBLE_BELL; - else - { - if (_rl_stricmp (value, "none") == 0 || _rl_stricmp (value, "off") == 0) - _rl_bell_preference = NO_BELL; - else if (_rl_stricmp (value, "audible") == 0 || _rl_stricmp (value, "on") == 0) - _rl_bell_preference = AUDIBLE_BELL; - else if (_rl_stricmp (value, "visible") == 0) - _rl_bell_preference = VISIBLE_BELL; - } - } + if (_rl_stricmp (name, "blink-matching-paren") == 0) + _rl_enable_paren_matching (rl_blink_matching_paren); else if (_rl_stricmp (name, "prefer-visible-bell") == 0) { - /* Backwards compatibility. */ - if (*value && (_rl_stricmp (value, "on") == 0 || - (*value == '1' && !value[1]))) - _rl_bell_preference = VISIBLE_BELL; + if (_rl_prefer_visible_bell) + _rl_bell_preference = VISIBLE_BELL; else - _rl_bell_preference = AUDIBLE_BELL; + _rl_bell_preference = AUDIBLE_BELL; } - else if (_rl_stricmp (name, "isearch-terminators") == 0) +} + +typedef int _rl_sv_func_t PARAMS((const char *)); + +/* These *must* correspond to the array indices for the appropriate + string variable. (Though they're not used right now.) */ +#define V_BELLSTYLE 0 +#define V_COMBEGIN 1 +#define V_EDITMODE 2 +#define V_ISRCHTERM 3 +#define V_KEYMAP 4 + +#define V_STRING 1 +#define V_INT 2 + +/* Forward declarations */ +static int sv_bell_style PARAMS((const char *)); +static int sv_combegin PARAMS((const char *)); +static int sv_compquery PARAMS((const char *)); +static int sv_editmode PARAMS((const char *)); +static int sv_isrchterm PARAMS((const char *)); +static int sv_keymap PARAMS((const char *)); + +static struct { + const char *name; + int flags; + _rl_sv_func_t *set_func; +} string_varlist[] = { + { "bell-style", V_STRING, sv_bell_style }, + { "comment-begin", V_STRING, sv_combegin }, + { "completion-query-items", V_INT, sv_compquery }, + { "editing-mode", V_STRING, sv_editmode }, + { "isearch-terminators", V_STRING, sv_isrchterm }, + { "keymap", V_STRING, sv_keymap }, + { (char *)NULL, 0, 0 } +}; + +static int +find_string_var (name) + const char *name; +{ + register int i; + + for (i = 0; string_varlist[i].name; i++) + if (_rl_stricmp (name, string_varlist[i].name) == 0) + return i; + return -1; +} + +/* A boolean value that can appear in a `set variable' command is true if + the value is null or empty, `on' (case-insenstive), or "1". Any other + values result in 0 (false). */ +static int +bool_to_int (value) + char *value; +{ + return (value == 0 || *value == '\0' || + (_rl_stricmp (value, "on") == 0) || + (value[0] == '1' && value[1] == '\0')); +} + +int +rl_variable_bind (name, value) + const char *name, *value; +{ + register int i; + int v; + + /* Check for simple variables first. */ + i = find_boolean_var (name); + if (i >= 0) { - /* Isolate the value and translate it into a character string. */ - int beg, end; - char *v; - - v = savestring (value); - FREE (_rl_isearch_terminators); - if (v[0] == '"' || v[0] == '\'') - { - int delim = v[0]; - for (beg = end = 1; v[end] && v[end] != delim; end++) - ; - } - else - { - for (beg = end = 0; whitespace (v[end]) == 0; end++) - ; - } - - v[end] = '\0'; - /* The value starts at v + beg. Translate it into a character string. */ - _rl_isearch_terminators = (unsigned char *)xmalloc (2 * strlen (v) + 1); - rl_translate_keyseq (v + beg, (char*) _rl_isearch_terminators, &end); - _rl_isearch_terminators[end] = '\0'; - free (v); + *boolean_varlist[i].value = bool_to_int (value); + if (boolean_varlist[i].flags & V_SPECIAL) + hack_special_boolean_var (i); + return 0; } - /* For the time being, unknown variable names are simply ignored. */ + i = find_string_var (name); + + /* For the time being, unknown variable names or string names without a + handler function are simply ignored. */ + if (i < 0 || string_varlist[i].set_func == 0) + return 0; + + v = (*string_varlist[i].set_func) (value); + return v; +} + +static int +sv_editmode (value) + const char *value; +{ + if (_rl_strnicmp (value, "vi", 2) == 0) + { +#if defined (VI_MODE) + _rl_keymap = vi_insertion_keymap; + rl_editing_mode = vi_mode; +#endif /* VI_MODE */ + return 0; + } + else if (_rl_strnicmp (value, "emacs", 5) == 0) + { + _rl_keymap = emacs_standard_keymap; + rl_editing_mode = emacs_mode; + return 0; + } + return 1; +} + +static int +sv_combegin (value) + const char *value; +{ + if (value && *value) + { + FREE (_rl_comment_begin); + _rl_comment_begin = savestring (value); + return 0; + } + return 1; +} + +static int +sv_compquery (value) + const char *value; +{ + int nval = 100; + + if (value && *value) + { + nval = atoi (value); + if (nval < 0) + nval = 0; + } + rl_completion_query_items = nval; return 0; } +static int +sv_keymap (value) + const char *value; +{ + Keymap kmap; + + kmap = rl_get_keymap_by_name (value); + if (kmap) + { + rl_set_keymap (kmap); + return 0; + } + return 1; +} + +static int +sv_bell_style (value) + const char *value; +{ + if (value == 0 || *value == '\0') + _rl_bell_preference = AUDIBLE_BELL; + else if (_rl_stricmp (value, "none") == 0 || _rl_stricmp (value, "off") == 0) + _rl_bell_preference = NO_BELL; + else if (_rl_stricmp (value, "audible") == 0 || _rl_stricmp (value, "on") == 0) + _rl_bell_preference = AUDIBLE_BELL; + else if (_rl_stricmp (value, "visible") == 0) + _rl_bell_preference = VISIBLE_BELL; + else + return 1; + return 0; +} + +static int +sv_isrchterm (value) + const char *value; +{ + int beg, end, delim; + char *v; + + if (value == 0) + return 1; + + /* Isolate the value and translate it into a character string. */ + v = savestring (value); + FREE (_rl_isearch_terminators); + if (v[0] == '"' || v[0] == '\'') + { + delim = v[0]; + for (beg = end = 1; v[end] && v[end] != delim; end++) + ; + } + else + { + for (beg = end = 0; whitespace (v[end]) == 0; end++) + ; + } + + v[end] = '\0'; + + /* The value starts at v + beg. Translate it into a character string. */ + _rl_isearch_terminators = (char *)xmalloc (2 * strlen (v) + 1); + rl_translate_keyseq (v + beg, _rl_isearch_terminators, &end); + _rl_isearch_terminators[end] = '\0'; + + free (v); + return 0; +} + /* Return the character which matches NAME. For example, `Space' returns ' '. */ @@ -1431,27 +1582,27 @@ static struct { Keymap rl_get_keymap_by_name (name) - char *name; + const char *name; { register int i; for (i = 0; keymap_names[i].name; i++) - if (strcmp (name, keymap_names[i].name) == 0) + if (_rl_stricmp (name, keymap_names[i].name) == 0) return (keymap_names[i].map); return ((Keymap) NULL); } -const char * +char * rl_get_keymap_name (map) Keymap map; { register int i; for (i = 0; keymap_names[i].name; i++) if (map == keymap_names[i].map) - return (keymap_names[i].name); + return ((char *)keymap_names[i].name); return ((char *)NULL); } - + void rl_set_keymap (map) Keymap map; @@ -1477,17 +1628,18 @@ rl_set_keymap_from_edit_mode () #endif /* VI_MODE */ } -const char * + +char * rl_get_keymap_name_from_edit_mode () { if (rl_editing_mode == emacs_mode) - return "emacs"; + return (char*)"emacs"; #if defined (VI_MODE) else if (rl_editing_mode == vi_mode) - return "vi"; + return (char*)"vi"; #endif /* VI_MODE */ else - return "none"; + return (char*)"nope"; } /* **************************************************************** */ @@ -1506,7 +1658,7 @@ void rl_list_funmap_names () { register int i; - char **funmap_names; + const char **funmap_names; funmap_names = rl_funmap_names (); @@ -1533,17 +1685,18 @@ _rl_get_keyname (key) pairs for possible inclusion in an inputrc file, we don't want to do any special meta processing on KEY. */ -#if 0 +#if 1 + /* XXX - Experimental */ /* We might want to do this, but the old version of the code did not. */ /* If this is an escape character, we don't want to do any more processing. Just add the special ESC key sequence and return. */ if (c == ESC) { - keyseq[0] = '\\'; - keyseq[1] = 'e'; - keyseq[2] = '\0'; - return keyseq; + keyname[0] = '\\'; + keyname[1] = 'e'; + keyname[2] = '\0'; + return keyname; } #endif @@ -1596,7 +1749,7 @@ _rl_get_keyname (key) sequences that are used to invoke FUNCTION in MAP. */ char ** rl_invoking_keyseqs_in_map (function, map) - Function *function; + rl_command_func_t *function; Keymap map; { register int key; @@ -1625,7 +1778,7 @@ rl_invoking_keyseqs_in_map (function, map) if (result_index + 2 > result_size) { result_size += 10; - result = (char **) xrealloc (result, result_size * sizeof (char *)); + result = (char **)xrealloc (result, result_size * sizeof (char *)); } result[result_index++] = keyname; @@ -1654,7 +1807,12 @@ rl_invoking_keyseqs_in_map (function, map) char *keyname = (char *)xmalloc (6 + strlen (seqs[i])); if (key == ESC) +#if 0 sprintf (keyname, "\\e"); +#else + /* XXX - experimental */ + sprintf (keyname, "\\M-"); +#endif else if (CTRL_CHAR (key)) sprintf (keyname, "\\C-%c", _rl_to_lower (UNCTRL (key))); else if (key == RUBOUT) @@ -1670,14 +1828,14 @@ rl_invoking_keyseqs_in_map (function, map) keyname[0] = (char) key; keyname[1] = '\0'; } - + strcat (keyname, seqs[i]); free (seqs[i]); if (result_index + 2 > result_size) { result_size += 10; - result = (char **) xrealloc (result, result_size * sizeof (char *)); + result = (char **)xrealloc (result, result_size * sizeof (char *)); } result[result_index++] = keyname; @@ -1696,7 +1854,7 @@ rl_invoking_keyseqs_in_map (function, map) sequences that can be used to invoke FUNCTION using the current keymap. */ char ** rl_invoking_keyseqs (function) - Function *function; + rl_command_func_t *function; { return (rl_invoking_keyseqs_in_map (function, _rl_keymap)); } @@ -1709,8 +1867,8 @@ rl_function_dumper (print_readably) int print_readably; { register int i; - char **names; - char *name; + const char **names; + const char *name; names = rl_funmap_names (); @@ -1718,7 +1876,7 @@ rl_function_dumper (print_readably) for (i = 0; (name = names[i]); i++) { - Function *function; + rl_command_func_t *function; char **invokers; function = rl_named_function (name); @@ -1775,8 +1933,8 @@ rl_function_dumper (print_readably) rl_outstream. If an explicit argument is given, then print the output in such a way that it can be read back in. */ int -rl_dump_functions (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_dump_functions (count, key) + int count __attribute__((unused)), key __attribute__((unused)); { if (rl_dispatching) fprintf (rl_outstream, "\r\n"); @@ -1801,11 +1959,8 @@ _rl_macro_dumper_internal (print_readably, map, prefix) { case ISMACR: keyname = _rl_get_keyname (key); -#if 0 - out = (char *)map[key].function; -#else out = _rl_untranslate_macro_value ((char *)map[key].function); -#endif + if (print_readably) fprintf (rl_outstream, "\"%s%s\": \"%s\"\n", prefix ? prefix : "", keyname, @@ -1815,9 +1970,7 @@ _rl_macro_dumper_internal (print_readably, map, prefix) keyname, out ? out : ""); free (keyname); -#if 1 free (out); -#endif break; case ISFUNC: break; @@ -1825,7 +1978,7 @@ _rl_macro_dumper_internal (print_readably, map, prefix) prefix_len = prefix ? strlen (prefix) : 0; if (key == ESC) { - keyname = xmalloc (3 + prefix_len); + keyname = (char *)xmalloc (3 + prefix_len); if (prefix) strcpy (keyname, prefix); keyname[prefix_len] = '\\'; @@ -1837,7 +1990,7 @@ _rl_macro_dumper_internal (print_readably, map, prefix) keyname = _rl_get_keyname (key); if (prefix) { - out = xmalloc (strlen (keyname) + prefix_len + 1); + out = (char *)xmalloc (strlen (keyname) + prefix_len + 1); strcpy (out, prefix); strcpy (out + prefix_len, keyname); free (keyname); @@ -1860,8 +2013,8 @@ rl_macro_dumper (print_readably) } int -rl_dump_macros (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_dump_macros (count, key) + int count __attribute__((unused)), key __attribute__((unused)); { if (rl_dispatching) fprintf (rl_outstream, "\r\n"); @@ -1907,7 +2060,7 @@ rl_variable_dumper (print_readably) if (print_readably) fprintf (rl_outstream, "set comment-begin %s\n", _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT); else - fprintf (rl_outstream, "comment-begin is set to `%s'\n", _rl_comment_begin ? _rl_comment_begin : ""); + fprintf (rl_outstream, "comment-begin is set to `%s'\n", _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT); /* completion-query-items */ if (print_readably) @@ -1921,15 +2074,6 @@ rl_variable_dumper (print_readably) else fprintf (rl_outstream, "editing-mode is set to `%s'\n", (rl_editing_mode == emacs_mode) ? "emacs" : "vi"); - /* keymap */ - kname = rl_get_keymap_name (_rl_keymap); - if (kname == 0) - kname = rl_get_keymap_name_from_edit_mode (); - if (print_readably) - fprintf (rl_outstream, "set keymap %s\n", kname ? kname : "none"); - else - fprintf (rl_outstream, "keymap is set to `%s'\n", kname ? kname : "none"); - /* isearch-terminators */ if (_rl_isearch_terminators) { @@ -1944,14 +2088,23 @@ rl_variable_dumper (print_readably) free (disp); } + + /* keymap */ + kname = rl_get_keymap_name (_rl_keymap); + if (kname == 0) + kname = rl_get_keymap_name_from_edit_mode (); + if (print_readably) + fprintf (rl_outstream, "set keymap %s\n", kname ? kname : "none"); + else + fprintf (rl_outstream, "keymap is set to `%s'\n", kname ? kname : "none"); } /* Print all of the current variables and their values to rl_outstream. If an explicit argument is given, then print the output in such a way that it can be read back in. */ int -rl_dump_variables (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_dump_variables (count, key) + int count __attribute__((unused)), key __attribute__((unused)); { if (rl_dispatching) fprintf (rl_outstream, "\r\n"); @@ -1960,18 +2113,24 @@ rl_dump_variables (int count __attribute__((unused)), return (0); } -/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound. */ +/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound. Right + now, this is always used to attempt to bind the arrow keys, hence the + check for rl_vi_movement_mode. */ void _rl_bind_if_unbound (keyseq, default_func) - char *keyseq; - Function *default_func; + const char *keyseq; + rl_command_func_t *default_func; { - Function *func; + rl_command_func_t *func; if (keyseq) { func = rl_function_of_keyseq (keyseq, _rl_keymap, (int *)NULL); +#if defined (VI_MODE) + if (!func || func == rl_do_lowercase_version || func == rl_vi_movement_mode) +#else if (!func || func == rl_do_lowercase_version) +#endif rl_set_key (keyseq, default_func, _rl_keymap); } } @@ -1979,7 +2138,8 @@ _rl_bind_if_unbound (keyseq, default_func) /* Return non-zero if any members of ARRAY are a substring in STRING. */ static int substring_member_of_array (string, array) - char *string, **array; + char *string; + const char **array; { while (*array) { diff --git a/readline/callback.c b/readline/callback.c index 200f3cc37f9..a8f4323c929 100644 --- a/readline/callback.c +++ b/readline/callback.c @@ -7,7 +7,7 @@ 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 1, or + 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 @@ -18,7 +18,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) @@ -29,22 +29,20 @@ #if defined (READLINE_CALLBACKS) -#include #include + +#ifdef HAVE_STDLIB_H +# include +#else +# include "ansi_stdlib.h" +#endif + #include /* System-specific feature definitions and include files. */ #include "rldefs.h" #include "readline.h" - -extern void readline_internal_setup (); -extern char *readline_internal_teardown (); -extern int readline_internal_char (); -extern void _rl_init_line_state (); - -extern int _rl_meta_flag; -extern char *rl_prompt; -extern int rl_visible_prompt_length; +#include "rlprivate.h" /* **************************************************************** */ /* */ @@ -61,7 +59,7 @@ extern int rl_visible_prompt_length; text read in at each end of line. The terminal is kept prepped and signals handled all the time, except during calls to the user's function. */ -VFunction *rl_linefunc; /* user callback function */ +rl_vcpfunc_t *rl_linefunc; /* user callback function */ static int in_handler; /* terminal_prepped and signals set? */ /* Make sure the terminal is set up, initialize readline, and prompt. */ @@ -87,11 +85,10 @@ _rl_callback_newline () /* Install a readline handler, set up the terminal, and issue the prompt. */ void rl_callback_handler_install (prompt, linefunc) - char *prompt; - VFunction *linefunc; + const char *prompt; + rl_vcpfunc_t *linefunc; { - rl_prompt = prompt; - rl_visible_prompt_length = rl_prompt ? rl_expand_prompt (rl_prompt) : 0; + rl_set_prompt (prompt); rl_linefunc = linefunc; _rl_callback_newline (); } @@ -111,24 +108,33 @@ rl_callback_read_char () eof = readline_internal_char (); - if (rl_done) + /* We loop in case some function has pushed input back with rl_execute_next. */ + for (;;) { - line = readline_internal_teardown (eof); + if (rl_done) + { + line = readline_internal_teardown (eof); - (*rl_deprep_term_function) (); + (*rl_deprep_term_function) (); #if defined (HANDLE_SIGNALS) - rl_clear_signals (); + rl_clear_signals (); #endif - in_handler = 0; - (*rl_linefunc) (line); + in_handler = 0; + (*rl_linefunc) (line); - /* If the user did not clear out the line, do it for him. */ - if (rl_line_buffer[0]) - _rl_init_line_state (); + /* If the user did not clear out the line, do it for him. */ + if (rl_line_buffer[0]) + _rl_init_line_state (); - /* Redisplay the prompt if readline_handler_{install,remove} not called. */ - if (in_handler == 0 && rl_linefunc) - _rl_callback_newline (); + /* Redisplay the prompt if readline_handler_{install,remove} + not called. */ + if (in_handler == 0 && rl_linefunc) + _rl_callback_newline (); + } + if (rl_pending_input) + eof = readline_internal_char (); + else + break; } } diff --git a/readline/chardefs.h b/readline/chardefs.h index 740f14b185b..a537be220b0 100644 --- a/readline/chardefs.h +++ b/readline/chardefs.h @@ -7,7 +7,7 @@ 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 1, or + 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 @@ -18,21 +18,23 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #ifndef _CHARDEFS_H_ #define _CHARDEFS_H_ -#ifndef _m_ctype_h #include -#endif #if defined (HAVE_CONFIG_H) # if defined (HAVE_STRING_H) +# if ! defined (STDC_HEADERS) && defined (HAVE_MEMORY_H) +# include +# endif # include -# else -# include # endif /* HAVE_STRING_H */ +# if defined (HAVE_STRINGS_H) +# include +# endif /* HAVE_STRINGS_H */ #else # include #endif /* !HAVE_CONFIG_H */ @@ -42,7 +44,10 @@ #endif #ifdef CTRL -#undef CTRL +# undef CTRL +#endif +#ifdef UNCTRL +# undef UNCTRL #endif /* Some character stuff. */ @@ -53,7 +58,7 @@ #define meta_character_bit 0x080 /* x0000000, must be on. */ #define largest_char 255 /* Largest character value. */ -#define CTRL_CHAR(c) ((c) < control_character_threshold && (c) >= 0) +#define CTRL_CHAR(c) ((c) < control_character_threshold && (((c) & 0x80) == 0)) #define META_CHAR(c) ((c) > meta_character_threshold && (c) <= largest_char) #define CTRL(c) ((c) & control_character_mask) @@ -62,33 +67,59 @@ #define UNMETA(c) ((c) & (~meta_character_bit)) #define UNCTRL(c) _rl_to_upper(((c)|control_character_bit)) -/* Old versions -#define _rl_lowercase_p(c) (((c) > ('a' - 1) && (c) < ('z' + 1))) -#define _rl_uppercase_p(c) (((c) > ('A' - 1) && (c) < ('Z' + 1))) -#define _rl_digit_p(c) ((c) >= '0' && (c) <= '9') -*/ +#if defined STDC_HEADERS || (!defined (isascii) && !defined (HAVE_ISASCII)) +# define IN_CTYPE_DOMAIN(c) 1 +#else +# define IN_CTYPE_DOMAIN(c) isascii(c) +#endif -#define _rl_lowercase_p(c) (islower(c)) -#define _rl_uppercase_p(c) (isupper(c)) -#define _rl_digit_p(x) (isdigit (x)) +#if !defined (isxdigit) && !defined (HAVE_ISXDIGIT) +# define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) +#endif -#define _rl_pure_alphabetic(c) (_rl_lowercase_p(c) || _rl_uppercase_p(c)) -#define ALPHABETIC(c) (_rl_lowercase_p(c) || _rl_uppercase_p(c) || _rl_digit_p(c)) +#define NON_NEGATIVE(c) ((unsigned char)(c) == (c)) -/* Old versions -# define _rl_to_upper(c) (_rl_lowercase_p(c) ? ((c) - 32) : (c)) -# define _rl_to_lower(c) (_rl_uppercase_p(c) ? ((c) + 32) : (c)) -*/ +/* Some systems define these; we want our definitions. */ +#undef ISPRINT + +#define ISALNUM(c) (IN_CTYPE_DOMAIN (c) && isalnum (c)) +#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c)) +#define ISDIGIT(c) (IN_CTYPE_DOMAIN (c) && isdigit (c)) +#define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (c)) +#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c)) +#define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c)) +#define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit (c)) + +#define _rl_lowercase_p(c) (NON_NEGATIVE(c) && ISLOWER(c)) +#define _rl_uppercase_p(c) (NON_NEGATIVE(c) && ISUPPER(c)) +#define _rl_digit_p(c) ((c) >= '0' && (c) <= '9') + +#define _rl_pure_alphabetic(c) (NON_NEGATIVE(c) && ISALPHA(c)) +#define ALPHABETIC(c) (NON_NEGATIVE(c) && ISALNUM(c)) #ifndef _rl_to_upper -# define _rl_to_upper(c) (islower(c) ? toupper(c) : (c)) -# define _rl_to_lower(c) (isupper(c) ? tolower(c) : (c)) +# define _rl_to_upper(c) (_rl_lowercase_p(c) ? toupper((unsigned char)c) : (c)) +# define _rl_to_lower(c) (_rl_uppercase_p(c) ? tolower((unsigned char)c) : (c)) #endif #ifndef _rl_digit_value -#define _rl_digit_value(x) ((x) - '0') +# define _rl_digit_value(x) ((x) - '0') #endif +#ifndef _rl_isident +# define _rl_isident(c) (ISALNUM(c) || (c) == '_') +#endif + +#ifndef ISOCTAL +# define ISOCTAL(c) ((c) >= '0' && (c) <= '7') +#endif +#define OCTVALUE(c) ((c) - '0') + +#define HEXVALUE(c) \ + (((c) >= 'a' && (c) <= 'f') \ + ? (c)-'a'+10 \ + : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0') + #ifndef NEWLINE #define NEWLINE '\n' #endif @@ -125,18 +156,4 @@ #endif #define ESC CTRL('[') -#ifndef ISOCTAL -#define ISOCTAL(c) ((c) >= '0' && (c) <= '7') -#endif -#define OCTVALUE(c) ((c) - '0') - -#ifndef isxdigit -# define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) -#endif - -#define HEXVALUE(c) \ - (((c) >= 'a' && (c) <= 'f') \ - ? (c)-'a'+10 \ - : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0') - #endif /* _CHARDEFS_H_ */ diff --git a/readline/complete.c b/readline/complete.c index 8810ca06d5f..693550c9945 100644 --- a/readline/complete.c +++ b/readline/complete.c @@ -7,7 +7,7 @@ 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 1, or + 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 @@ -18,7 +18,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) @@ -49,41 +49,39 @@ extern int errno; #endif /* !errno */ #include -#if !defined (HAVE_GETPW_DECLS) -extern struct passwd *getpwent (); -#endif /* USG && !HAVE_GETPW_DECLS */ - -/* ISC systems don't define getpwent() if _POSIX_SOURCE is defined. */ -#if defined (isc386) && defined (_POSIX_SOURCE) -# if defined (__STDC__) -extern struct passwd *getpwent (void); -# else -extern struct passwd *getpwent (); -# endif /* !__STDC__ */ -#endif /* isc386 && _POSIX_SOURCE */ #include "posixdir.h" #include "posixstat.h" /* System-specific feature definitions and include files. */ #include "rldefs.h" +#include "rlmbutil.h" /* Some standard library routines. */ #include "readline.h" +#include "xmalloc.h" +#include "rlprivate.h" -extern char *tilde_expand (); -extern char *rl_copy_text (); -extern void _rl_abort_internal (); -extern int _rl_qsort_string_compare (); -extern void _rl_replace_text (); +#ifdef __STDC__ +typedef int QSFUNC (const void *, const void *); +#else +typedef int QSFUNC (); +#endif -extern Function *rl_last_func; -extern int rl_editing_mode; -extern int screenwidth; +#ifdef HAVE_LSTAT +# define LSTAT lstat +#else +# define LSTAT stat +#endif -extern void _rl_move_vert (); -extern int _rl_vis_botlin; -extern int rl_display_fixed; +/* Unix version of a hidden file. Could be different on other systems. */ +#define HIDDEN_FILE(fname) ((fname)[0] == '.') + +/* Most systems don't declare getpwent in if _POSIX_SOURCE is + defined. */ +#if !defined (HAVE_GETPW_DECLS) || defined (_POSIX_SOURCE) +extern struct passwd *getpwent PARAMS((void)); +#endif /* !HAVE_GETPW_DECLS || _POSIX_SOURCE */ /* If non-zero, then this is the address of a function to call when completing a word would normally display the list of possible matches. @@ -92,30 +90,34 @@ extern int rl_display_fixed; where MATCHES is the array of strings that matched, NUM_MATCHES is the number of strings in that array, and MAX_LENGTH is the length of the longest string in that array. */ -VFunction *rl_completion_display_matches_hook = (VFunction *)NULL; - -/* Forward declarations for functions defined and used in this file. */ -char *filename_completion_function (const char *text, int state); -char **completion_matches (); +rl_compdisp_func_t *rl_completion_display_matches_hook = (rl_compdisp_func_t *)NULL; #if defined (VISIBLE_STATS) # if !defined (X_OK) # define X_OK 1 # endif -static int stat_char (); +static int stat_char PARAMS((char *)); #endif -static char *rl_quote_filename (); -static char *rl_strpbrk (); +static char *rl_quote_filename PARAMS((char *, int, char *)); -static char **remove_duplicate_matches (); -static void insert_match (); -static int append_to_match (); -static void insert_all_matches (); -static void display_matches (); -static int compute_lcd_of_matches (); +static void set_completion_defaults PARAMS((int)); +static int get_y_or_n PARAMS((int)); +static int _rl_internal_pager PARAMS((int)); +static char *printable_part PARAMS((char *)); +static int print_filename PARAMS((char *, char *)); -extern char *xmalloc (), *xrealloc (); +static char **gen_completion_matches PARAMS((char *, int, int, rl_compentry_func_t *, int, int)); + +static char **remove_duplicate_matches PARAMS((char **)); +static void insert_match PARAMS((char *, int, int, char *)); +static int append_to_match PARAMS((char *, int, int, int)); +static void insert_all_matches PARAMS((char **, int, char *)); +static void display_matches PARAMS((char **)); +static int compute_lcd_of_matches PARAMS((char **, int, const char *)); +static int postprocess_matches PARAMS((char ***, int)); + +static char *make_quoted_replacement PARAMS((char *, int, char *)); /* **************************************************************** */ /* */ @@ -131,12 +133,26 @@ int _rl_complete_show_all = 0; /* If non-zero, completed directory names have a slash appended. */ int _rl_complete_mark_directories = 1; +/* If non-zero, the symlinked directory completion behavior introduced in + readline-4.2a is disabled, and symlinks that point to directories have + a slash appended (subject to the value of _rl_complete_mark_directories). + This is user-settable via the mark-symlinked-directories variable. */ +int _rl_complete_mark_symlink_dirs = 0; + /* If non-zero, completions are printed horizontally in alphabetical order, like `ls -x'. */ int _rl_print_completions_horizontally; /* Non-zero means that case is not significant in filename completion. */ +#if defined (__MSDOS__) && !defined (__DJGPP__) +int _rl_completion_case_fold = 1; +#else int _rl_completion_case_fold; +#endif + +/* If non-zero, don't match hidden files (filenames beginning with a `.' on + Unix) when doing filename completion. */ +int _rl_match_hidden_files = 1; /* Global variables available to applications using readline. */ @@ -150,15 +166,17 @@ int rl_visible_stats = 0; /* If non-zero, then this is the address of a function to call when completing on a directory name. The function is called with the address of a string (the current directory name) as an arg. */ -Function *rl_directory_completion_hook = (Function *)NULL; +rl_icppfunc_t *rl_directory_completion_hook = (rl_icppfunc_t *)NULL; + +rl_icppfunc_t *rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL; /* Non-zero means readline completion functions perform tilde expansion. */ int rl_complete_with_tilde_expansion = 0; /* Pointer to the generator function for completion_matches (). - NULL means to use filename_completion_function (), the default filename + NULL means to use rl_filename_completion_function (), the default filename completer. */ -Function *rl_completion_entry_function = (Function *)NULL; +rl_compentry_func_t *rl_completion_entry_function = (rl_compentry_func_t *)NULL; /* Pointer to alternative function to create matches. Function is called with TEXT, START, and END. @@ -167,7 +185,7 @@ Function *rl_completion_entry_function = (Function *)NULL; If this function exists and returns NULL then call the value of rl_completion_entry_function to try to match, otherwise use the array of strings returned. */ -CPPFunction *rl_attempted_completion_function = (CPPFunction *)NULL; +rl_completion_func_t *rl_attempted_completion_function = (rl_completion_func_t *)NULL; /* Non-zero means to suppress normal filename completion after the user-specified completion function has been called. */ @@ -183,10 +201,12 @@ int rl_completion_type = 0; she is sure she wants to see them all. */ int rl_completion_query_items = 100; +int _rl_page_completions = 1; + /* The basic list of characters that signal a break between words for the completer routine. The contents of this variable is what breaks words in the shell, i.e. " \t\n\"\\'`@$><=" */ -const char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{("; +const char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{("; /* }) */ /* List of basic quoting characters. */ const char *rl_basic_quote_characters = "\"'"; @@ -194,21 +214,21 @@ const char *rl_basic_quote_characters = "\"'"; /* The list of characters that signal a break between words for rl_complete_internal. The default list is the contents of rl_basic_word_break_characters. */ -const char *rl_completer_word_break_characters = (char *)NULL; +const char *rl_completer_word_break_characters = (const char *)NULL; /* List of characters which can be used to quote a substring of the line. Completion occurs on the entire substring, and within the substring rl_completer_word_break_characters are treated as any other character, unless they also appear within this list. */ -char *rl_completer_quote_characters = (char *)NULL; +const char *rl_completer_quote_characters = (const char *)NULL; /* List of characters that should be quoted in filenames by the completer. */ -char *rl_filename_quote_characters = (char *)NULL; +const char *rl_filename_quote_characters = (const char *)NULL; /* List of characters that are word break characters, but should be left in TEXT when it is passed to the completion function. The shell uses this to help determine what kind of completing to do. */ -char *rl_special_prefixes = (char *)NULL; +const char *rl_special_prefixes = (const char *)NULL; /* If non-zero, then disallow duplicates in the matches. */ int rl_ignore_completion_duplicates = 1; @@ -234,29 +254,45 @@ int rl_filename_quoting_desired = 1; the list of matches as required, but all elements of the array must be free()'d if they are deleted. The main intent of this function is to implement FIGNORE a la SunOS csh. */ -Function *rl_ignore_some_completions_function = (Function *)NULL; +rl_compignore_func_t *rl_ignore_some_completions_function = (rl_compignore_func_t *)NULL; /* Set to a function to quote a filename in an application-specific fashion. Called with the text to quote, the type of match found (single or multiple) and a pointer to the quoting character to be used, which the function can reset if desired. */ -CPFunction *rl_filename_quoting_function = rl_quote_filename; - +rl_quote_func_t *rl_filename_quoting_function = rl_quote_filename; + /* Function to call to remove quoting characters from a filename. Called before completion is attempted, so the embedded quotes do not interfere with matching names in the file system. Readline doesn't do anything with this; it's set only by applications. */ -CPFunction *rl_filename_dequoting_function = (CPFunction *)NULL; +rl_dequote_func_t *rl_filename_dequoting_function = (rl_dequote_func_t *)NULL; /* Function to call to decide whether or not a word break character is quoted. If a character is quoted, it does not break words for the completer. */ -Function *rl_char_is_quoted_p = (Function *)NULL; +rl_linebuf_func_t *rl_char_is_quoted_p = (rl_linebuf_func_t *)NULL; + +/* If non-zero, the completion functions don't append anything except a + possible closing quote. This is set to 0 by rl_complete_internal and + may be changed by an application-specific completion function. */ +int rl_completion_suppress_append = 0; /* Character appended to completed words when at the end of the line. The default is a space. */ int rl_completion_append_character = ' '; +/* If non-zero, a slash will be appended to completed filenames that are + symbolic links to directory names, subject to the value of the + mark-directories variable (which is user-settable). This exists so + that application completion functions can override the user's preference + (set via the mark-symlinked-directories variable) if appropriate. + It's set to the value of _rl_complete_mark_symlink_dirs in + rl_complete_internal before any application-specific completion + function is called, so without that function doing anything, the user's + preferences are honored. */ +int rl_completion_mark_symlink_dirs; + /* If non-zero, inhibit completion (temporarily). */ int rl_inhibit_completion; @@ -273,13 +309,13 @@ static int completion_changed_buffer; /* Complete the word at or before point. You have supplied the function that does the initial simple matching selection algorithm (see - completion_matches ()). The default is to do filename completion. */ + rl_completion_matches ()). The default is to do filename completion. */ int rl_complete (ignore, invoking_key) int ignore, invoking_key; { if (rl_inhibit_completion) - return (rl_insert (ignore, invoking_key)); + return (_rl_insert_char (ignore, invoking_key)); else if (rl_last_func == rl_complete && !completion_changed_buffer) return (rl_complete_internal ('?')); else if (_rl_complete_show_all) @@ -303,52 +339,90 @@ rl_insert_completions (ignore, invoking_key) return (rl_complete_internal ('*')); } +/* Return the correct value to pass to rl_complete_internal performing + the same tests as rl_complete. This allows consecutive calls to an + application's completion function to list possible completions and for + an application-specific completion function to honor the + show-all-if-ambiguous readline variable. */ +int +rl_completion_mode (cfunc) + rl_command_func_t *cfunc; +{ + if (rl_last_func == cfunc && !completion_changed_buffer) + return '?'; + else if (_rl_complete_show_all) + return '!'; + else + return TAB; +} + /************************************/ /* */ /* Completion utility functions */ /* */ /************************************/ -/* Find the first occurrence in STRING1 of any character from STRING2. - Return a pointer to the character in STRING1. */ -static char * -rl_strpbrk (string1, string2) - char *string1, *string2; +/* Set default values for readline word completion. These are the variables + that application completion functions can change or inspect. */ +static void +set_completion_defaults (what_to_do) + int what_to_do; { - register char *scan; + /* Only the completion entry function can change these. */ + rl_filename_completion_desired = 0; + rl_filename_quoting_desired = 1; + rl_completion_type = what_to_do; + rl_completion_suppress_append = 0; - for (; *string1; string1++) - { - for (scan = string2; *scan; scan++) - { - if (*string1 == *scan) - { - return (string1); - } - } - } - return ((char *)NULL); + /* The completion entry function may optionally change this. */ + rl_completion_mark_symlink_dirs = _rl_complete_mark_symlink_dirs; } /* The user must press "y" or "n". Non-zero return means "y" pressed. */ static int -get_y_or_n () +get_y_or_n (for_pager) + int for_pager; { int c; for (;;) { + RL_SETSTATE(RL_STATE_MOREINPUT); c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + if (c == 'y' || c == 'Y' || c == ' ') return (1); if (c == 'n' || c == 'N' || c == RUBOUT) return (0); if (c == ABORT_CHAR) _rl_abort_internal (); - ding (); + if (for_pager && (c == NEWLINE || c == RETURN)) + return (2); + if (for_pager && (c == 'q' || c == 'Q')) + return (0); + rl_ding (); } } +static int +_rl_internal_pager (lines) + int lines; +{ + int i; + + fprintf (rl_outstream, "--More--"); + fflush (rl_outstream); + i = get_y_or_n (1); + _rl_erase_entire_line (); + if (i == 0) + return -1; + else if (i == 2) + return (lines - 1); + else + return 0; +} + #if defined (VISIBLE_STATS) /* Return the character which best describes FILENAME. `@' for symbolic links @@ -409,15 +483,41 @@ stat_char (filename) /* Return the portion of PATHNAME that should be output when listing possible completions. If we are hacking filename completion, we are only interested in the basename, the portion following the - final slash. Otherwise, we return what we were passed. */ + final slash. Otherwise, we return what we were passed. Since + printing empty strings is not very informative, if we're doing + filename completion, and the basename is the empty string, we look + for the previous slash and return the portion following that. If + there's no previous slash, we just return what we were passed. */ static char * printable_part (pathname) char *pathname; { - char *temp; + char *temp, *x; - temp = rl_filename_completion_desired ? strrchr (pathname, '/') : (char *)NULL; - return (temp ? ++temp : pathname); + if (rl_filename_completion_desired == 0) /* don't need to do anything */ + return (pathname); + + temp = strrchr (pathname, '/'); +#if defined (__MSDOS__) + if (temp == 0 && ISALPHA ((unsigned char)pathname[0]) && pathname[1] == ':') + temp = pathname + 1; +#endif + + if (temp == 0 || *temp == '\0') + return (pathname); + /* If the basename is NULL, we might have a pathname like '/usr/src/'. + Look for a previous slash and, if one is found, return the portion + following that slash. If there's no previous slash, just return the + pathname we were passed. */ + else if (temp[1] == '\0') + { + for (x = temp - 1; x > pathname; x--) + if (*x == '/') + break; + return ((*x == '/') ? x + 1 : pathname); + } + else + return ++temp; } /* Output TO_PRINT to rl_outstream. If VISIBLE_STATS is defined and we @@ -477,13 +577,18 @@ print_filename (to_print, full_pathname) c = to_print[-1]; to_print[-1] = '\0'; - s = tilde_expand (full_pathname); + /* If setting the last slash in full_pathname to a NUL results in + full_pathname being the empty string, we are trying to complete + files in the root directory. If we pass a null string to the + bash directory completion hook, for example, it will expand it + to the current directory. We just want the `/'. */ + s = tilde_expand (full_pathname && *full_pathname ? full_pathname : "/"); if (rl_directory_completion_hook) (*rl_directory_completion_hook) (&s); slen = strlen (s); tlen = strlen (to_print); - new_full_pathname = xmalloc (slen + tlen + 2); + new_full_pathname = (char *)xmalloc (slen + tlen + 2); strcpy (new_full_pathname, s); new_full_pathname[slen] = '/'; strcpy (new_full_pathname + slen + 1, to_print); @@ -518,7 +623,7 @@ rl_quote_filename (s, rtype, qcp) { char *r; - r = xmalloc (strlen (s) + 2); + r = (char *)xmalloc (strlen (s) + 2); *r = *rl_completer_quote_characters; strcpy (r + 1, s); if (qcp) @@ -529,7 +634,7 @@ rl_quote_filename (s, rtype, qcp) /* Find the bounds of the current word for completion purposes, and leave rl_point set to the end of the word. This function skips quoted substrings (characters between matched pairs of characters in - rl_completer_quote_characters. First we try to find an unclosed + rl_completer_quote_characters). First we try to find an unclosed quoted substring on which to do matching. If one is not found, we use the word break characters to find the boundaries of the current word. We call an application-specific function to decide whether or not a @@ -541,8 +646,8 @@ rl_quote_filename (s, rtype, qcp) quote, or backslash) anywhere in the string. DP, if non-null, is set to the value of the delimiter character that caused a word break. */ -static char -find_completion_word (fp, dp) +char +_rl_find_completion_word (fp, dp) int *fp, *dp; { int scan, end, found_quote, delimiter, pass_next, isbrk; @@ -566,7 +671,11 @@ find_completion_word (fp, dp) continue; } - if (rl_line_buffer[scan] == '\\') + /* Shell-like semantics for single quotes -- don't allow backslash + to quote anything in single quotes, especially not the closing + quote. If you don't like this, take out the check on the value + of quote_char. */ + if (quote_char != '\'' && rl_line_buffer[scan] == '\\') { pass_next = 1; found_quote |= RL_QF_BACKSLASH; @@ -593,6 +702,8 @@ find_completion_word (fp, dp) found_quote |= RL_QF_SINGLE_QUOTE; else if (quote_char == '"') found_quote |= RL_QF_DOUBLE_QUOTE; + else + found_quote |= RL_QF_OTHER_QUOTE; } } } @@ -602,7 +713,11 @@ find_completion_word (fp, dp) /* We didn't find an unclosed quoted substring upon which to do completion, so use the word break characters to find the substring on which to complete. */ +#if defined (HANDLE_MULTIBYTE) + while (rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_ANY)) +#else while (--rl_point) +#endif { scan = rl_line_buffer[rl_point]; @@ -627,25 +742,31 @@ find_completion_word (fp, dp) /* If there is an application-specific function to say whether or not a character is quoted and we found a quote character, let that function decide whether or not a character is a word break, even - if it is found in rl_completer_word_break_characters. */ - if (rl_char_is_quoted_p) - isbrk = (found_quote == 0 || - (*rl_char_is_quoted_p) (rl_line_buffer, rl_point) == 0) && - strchr (rl_completer_word_break_characters, scan) != 0; - else - isbrk = strchr (rl_completer_word_break_characters, scan) != 0; - - if (isbrk) + if it is found in rl_completer_word_break_characters. Don't bother + if we're at the end of the line, though. */ + if (scan) { - /* If the character that caused the word break was a quoting - character, then remember it as the delimiter. */ - if (rl_basic_quote_characters && strchr (rl_basic_quote_characters, scan) && (end - rl_point) > 1) - delimiter = scan; + if (rl_char_is_quoted_p) + isbrk = (found_quote == 0 || + (*rl_char_is_quoted_p) (rl_line_buffer, rl_point) == 0) && + strchr (rl_completer_word_break_characters, scan) != 0; + else + isbrk = strchr (rl_completer_word_break_characters, scan) != 0; - /* If the character isn't needed to determine something special - about what kind of completion to perform, then advance past it. */ - if (rl_special_prefixes == 0 || strchr (rl_special_prefixes, scan) == 0) - rl_point++; + if (isbrk) + { + /* If the character that caused the word break was a quoting + character, then remember it as the delimiter. */ + if (rl_basic_quote_characters && + strchr (rl_basic_quote_characters, scan) && + (end - rl_point) > 1) + delimiter = scan; + + /* If the character isn't needed to determine something special + about what kind of completion to perform, then advance past it. */ + if (rl_special_prefixes == 0 || strchr (rl_special_prefixes, scan) == 0) + rl_point++; + } } if (fp) @@ -660,7 +781,7 @@ static char ** gen_completion_matches (text, start, end, our_func, found_quote, quote_char) char *text; int start, end; - Function *our_func; + rl_compentry_func_t *our_func; int found_quote, quote_char; { char **matches, *temp; @@ -684,7 +805,7 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char) filename dequoting function. */ temp = (char *)NULL; - if (found_quote && our_func == (Function *)filename_completion_function && + if (found_quote && our_func == rl_filename_completion_function && rl_filename_dequoting_function) { /* delete single and double quotes */ @@ -692,7 +813,7 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char) text = temp; /* not freeing text is not a memory leak */ } - matches = completion_matches (text, (CPFunction *)our_func); + matches = rl_completion_matches (text, our_func); FREE (temp); return matches; } @@ -715,7 +836,7 @@ remove_duplicate_matches (matches) /* Sort the array without matches[0], since we need it to stay in place no matter what. */ if (i) - qsort (matches+1, i-1, sizeof (char *), _rl_qsort_string_compare); + qsort (matches+1, i-1, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare); /* Remember the lowest common denominator for it may be unique. */ lowest_common = savestring (matches[0]); @@ -764,10 +885,15 @@ static int compute_lcd_of_matches (match_list, matches, text) char **match_list; int matches; - char *text; + const char *text; { register int i, c1, c2, si; int low; /* Count of max-matched characters. */ +#if defined (HANDLE_MULTIBYTE) + int v; + mbstate_t ps1, ps2; + wchar_t wc1, wc2; +#endif /* If only one match, just use that. Otherwise, compare each member of the list with the next, finding out where they @@ -781,12 +907,33 @@ compute_lcd_of_matches (match_list, matches, text) for (i = 1, low = 100000; i < matches; i++) { +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + memset (&ps1, 0, sizeof (mbstate_t)); + memset (&ps2, 0, sizeof (mbstate_t)); + } +#endif if (_rl_completion_case_fold) { for (si = 0; (c1 = _rl_to_lower(match_list[i][si])) && (c2 = _rl_to_lower(match_list[i + 1][si])); si++) +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + v = mbrtowc (&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1); + mbrtowc (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2); + wc1 = towlower (wc1); + wc2 = towlower (wc2); + if (wc1 != wc2) + break; + else if (v > 1) + si += v - 1; + } + else +#endif if (c1 != c2) break; } @@ -796,6 +943,17 @@ compute_lcd_of_matches (match_list, matches, text) (c1 = match_list[i][si]) && (c2 = match_list[i + 1][si]); si++) +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + mbstate_t ps_back = ps1; + if (!_rl_compare_chars (match_list[i], si, &ps1, match_list[i+1], si, &ps2)) + break; + else if ((v = _rl_get_char_len (&match_list[i][si], &ps_back)) > 1) + si += v - 1; + } + else +#endif if (c1 != c2) break; } @@ -809,13 +967,42 @@ compute_lcd_of_matches (match_list, matches, text) value of matches[0]. */ if (low == 0 && text && *text) { - match_list[0] = xmalloc (strlen (text) + 1); + match_list[0] = (char *)xmalloc (strlen (text) + 1); strcpy (match_list[0], text); } else { - match_list[0] = xmalloc (low + 1); - strncpy (match_list[0], match_list[1], low); + match_list[0] = (char *)xmalloc (low + 1); + + /* XXX - this might need changes in the presence of multibyte chars */ + + /* If we are ignoring case, try to preserve the case of the string + the user typed in the face of multiple matches differing in case. */ + if (_rl_completion_case_fold) + { + /* sort the list to get consistent answers. */ + qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare); + + si = strlen (text); + if (si <= low) + { + for (i = 1; i <= matches; i++) + if (strncmp (match_list[i], text, si) == 0) + { + strncpy (match_list[0], match_list[i], low); + break; + } + /* no casematch, use first entry */ + if (i > matches) + strncpy (match_list[0], match_list[1], low); + } + else + /* otherwise, just use the text the user typed. */ + strncpy (match_list[0], text, low); + } + else + strncpy (match_list[0], match_list[1], low); + match_list[0][low] = '\0'; } @@ -832,6 +1019,9 @@ postprocess_matches (matchesp, matching_filenames) matches = *matchesp; + if (matches == 0) + return 0; + /* It seems to me that in all the cases we handle we would like to ignore duplicate possiblilities. Scan for the text to insert being identical to the other completions. */ @@ -884,17 +1074,17 @@ rl_display_match_list (matches, len, max) char **matches; int len, max; { - int count, limit, printed_len; + int count, limit, printed_len, lines; int i, j, k, l; char *temp; /* How many items of MAX length can we fit in the screen window? */ max += 2; - limit = screenwidth / max; - if (limit != 1 && (limit * max == screenwidth)) + limit = _rl_screenwidth / max; + if (limit != 1 && (limit * max == _rl_screenwidth)) limit--; - /* Avoid a possible floating exception. If max > screenwidth, + /* Avoid a possible floating exception. If max > _rl_screenwidth, limit will be 0 and a divide-by-zero fault will result. */ if (limit == 0) limit = 1; @@ -908,10 +1098,11 @@ rl_display_match_list (matches, len, max) /* Sort the items if they are not already sorted. */ if (rl_ignore_completion_duplicates == 0) - qsort (matches + 1, len, sizeof (char *), _rl_qsort_string_compare); + qsort (matches + 1, len, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare); - crlf (); + rl_crlf (); + lines = 0; if (_rl_print_completions_horizontally == 0) { /* Print the sorted items, up-and-down alphabetically, like ls. */ @@ -932,7 +1123,14 @@ rl_display_match_list (matches, len, max) } l += count; } - crlf (); + rl_crlf (); + lines++; + if (_rl_page_completions && lines >= (_rl_screenheight - 1) && i < count) + { + lines = _rl_internal_pager (lines); + if (lines < 0) + return; + } } } else @@ -946,13 +1144,22 @@ rl_display_match_list (matches, len, max) if (matches[i+1]) { if (i && (limit > 1) && (i % limit) == 0) - crlf (); + { + rl_crlf (); + lines++; + if (_rl_page_completions && lines >= _rl_screenheight - 1) + { + lines = _rl_internal_pager (lines); + if (lines < 0) + return; + } + } else for (k = 0; k < max - printed_len; k++) putc (' ', rl_outstream); } } - crlf (); + rl_crlf (); } } @@ -981,9 +1188,9 @@ display_matches (matches) if (matches[1] == 0) { temp = printable_part (matches[0]); - crlf (); + rl_crlf (); print_filename (temp, matches[0]); - crlf (); + rl_crlf (); rl_forced_update_display (); rl_display_fixed = 1; @@ -1010,17 +1217,17 @@ display_matches (matches) (*rl_completion_display_matches_hook) (matches, len, max); return; } - + /* If there are many items, then ask the user if she really wants to see them all. */ if (len >= rl_completion_query_items) { - crlf (); + rl_crlf (); fprintf (rl_outstream, "Display all %d possibilities? (y or n)", len); fflush (rl_outstream); - if (get_y_or_n () == 0) + if (get_y_or_n (0) == 0) { - crlf (); + rl_crlf (); rl_forced_update_display (); rl_display_fixed = 1; @@ -1068,7 +1275,7 @@ make_quoted_replacement (match, mtype, qc) This also checks whether the common prefix of several matches needs to be quoted. */ should_quote = rl_filename_quote_characters - ? (rl_strpbrk (match, rl_filename_quote_characters) != 0) + ? (_rl_strpbrk (match, rl_filename_quote_characters) != 0) : 0; do_replace = should_quote ? mtype : NO_MATCH; @@ -1114,14 +1321,20 @@ insert_match (match, start, mtype, qc) just-inserted match. If the user has specified that directories should be marked by a trailing `/', append one of those instead. The default trailing character is a space. Returns the number of characters - appended. */ + appended. If NONTRIVIAL_MATCH is set, we test for a symlink (if the OS + has them) and don't add a suffix for a symlink to a directory. A + nontrivial match is one that actually adds to the word being completed. + The variable rl_completion_mark_symlink_dirs controls this behavior + (it's initially set to the what the user has chosen, indicated by the + value of _rl_complete_mark_symlink_dirs, but may be modified by an + application's completion function). */ static int -append_to_match (text, delimiter, quote_char) +append_to_match (text, delimiter, quote_char, nontrivial_match) char *text; - int delimiter, quote_char; + int delimiter, quote_char, nontrivial_match; { char temp_string[4], *filename; - int temp_string_index; + int temp_string_index, s; struct stat finfo; temp_string_index = 0; @@ -1130,7 +1343,7 @@ append_to_match (text, delimiter, quote_char) if (delimiter) temp_string[temp_string_index++] = delimiter; - else if (rl_completion_append_character) + else if (rl_completion_suppress_append == 0 && rl_completion_append_character) temp_string[temp_string_index++] = rl_completion_append_character; temp_string[temp_string_index++] = '\0'; @@ -1138,21 +1351,39 @@ append_to_match (text, delimiter, quote_char) if (rl_filename_completion_desired) { filename = tilde_expand (text); - if (stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode)) + s = (nontrivial_match && rl_completion_mark_symlink_dirs == 0) + ? LSTAT (filename, &finfo) + : stat (filename, &finfo); + if (s == 0 && S_ISDIR (finfo.st_mode)) { - if (_rl_complete_mark_directories && rl_line_buffer[rl_point] != '/') - rl_insert_text ("/"); + if (_rl_complete_mark_directories) + { + /* This is clumsy. Avoid putting in a double slash if point + is at the end of the line and the previous character is a + slash. */ + if (rl_point && rl_line_buffer[rl_point] == '\0' && rl_line_buffer[rl_point - 1] == '/') + ; + else if (rl_line_buffer[rl_point] != '/') + rl_insert_text ("/"); + } } +#ifdef S_ISLNK + /* Don't add anything if the filename is a symlink and resolves to a + directory. */ + else if (s == 0 && S_ISLNK (finfo.st_mode) && + stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode)) + ; +#endif else { - if (rl_point == rl_end) + if (rl_point == rl_end && temp_string_index) rl_insert_text (temp_string); } free (filename); } else { - if (rl_point == rl_end) + if (rl_point == rl_end && temp_string_index) rl_insert_text (temp_string); } @@ -1198,12 +1429,15 @@ insert_all_matches (matches, point, qc) rl_end_undo_group (); } -static void -free_match_list (matches) +void +_rl_free_match_list (matches) char **matches; { register int i; + if (matches == 0) + return; + for (i = 0; matches[i]; i++) free (matches[i]); free (matches); @@ -1221,20 +1455,19 @@ rl_complete_internal (what_to_do) int what_to_do; { char **matches; - Function *our_func; - int start, end, delimiter, found_quote, i; + rl_compentry_func_t *our_func; + int start, end, delimiter, found_quote, i, nontrivial_lcd; char *text, *saved_line_buffer; char quote_char; - /* Only the completion entry function can change these. */ - rl_filename_completion_desired = 0; - rl_filename_quoting_desired = 1; - rl_completion_type = what_to_do; + RL_SETSTATE(RL_STATE_COMPLETING); + + set_completion_defaults (what_to_do); saved_line_buffer = rl_line_buffer ? savestring (rl_line_buffer) : (char *)NULL; our_func = rl_completion_entry_function ? rl_completion_entry_function - : (Function *)filename_completion_function; + : rl_filename_completion_function; /* We now look backwards for the start of a filename/variable word. */ end = rl_point; @@ -1244,38 +1477,38 @@ rl_complete_internal (what_to_do) if (rl_point) /* This (possibly) changes rl_point. If it returns a non-zero char, we know we have an open quote. */ - quote_char = find_completion_word (&found_quote, &delimiter); + quote_char = _rl_find_completion_word (&found_quote, &delimiter); start = rl_point; rl_point = end; text = rl_copy_text (start, end); matches = gen_completion_matches (text, start, end, our_func, found_quote, quote_char); + /* nontrivial_lcd is set if the common prefix adds something to the word + being completed. */ + nontrivial_lcd = matches && strcmp (text, matches[0]) != 0; free (text); if (matches == 0) { - ding (); + rl_ding (); FREE (saved_line_buffer); + completion_changed_buffer = 0; + RL_UNSETSTATE(RL_STATE_COMPLETING); return (0); } -#if 0 - /* If we are matching filenames, our_func will have been set to - filename_completion_function */ - i = our_func == (Function *)filename_completion_function; -#else /* If we are matching filenames, the attempted completion function will have set rl_filename_completion_desired to a non-zero value. The basic - filename_completion_function does this. */ + rl_filename_completion_function does this. */ i = rl_filename_completion_desired; -#endif if (postprocess_matches (&matches, i) == 0) { - ding (); + rl_ding (); FREE (saved_line_buffer); completion_changed_buffer = 0; + RL_UNSETSTATE(RL_STATE_COMPLETING); return (0); } @@ -1303,10 +1536,10 @@ rl_complete_internal (what_to_do) break; } else if (rl_editing_mode != vi_mode) - ding (); /* There are other matches remaining. */ + rl_ding (); /* There are other matches remaining. */ } else - append_to_match (matches[0], delimiter, quote_char); + append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd); break; @@ -1320,12 +1553,13 @@ rl_complete_internal (what_to_do) default: fprintf (stderr, "\r\nreadline: bad value %d for what_to_do in rl_complete\n", what_to_do); - ding (); + rl_ding (); FREE (saved_line_buffer); + RL_UNSETSTATE(RL_STATE_COMPLETING); return 1; } - free_match_list (matches); + _rl_free_match_list (matches); /* Check to see if the line has changed through all of this manipulation. */ if (saved_line_buffer) @@ -1334,6 +1568,7 @@ rl_complete_internal (what_to_do) free (saved_line_buffer); } + RL_UNSETSTATE(RL_STATE_COMPLETING); return 0; } @@ -1356,7 +1591,9 @@ rl_complete_internal (what_to_do) when there are no more matches. */ char ** -completion_matches (const char *text, CPFunction *entry_function) +rl_completion_matches (text, entry_function) + const char *text; + rl_compentry_func_t *entry_function; { /* Number of slots in match_list. */ int match_list_size; @@ -1401,11 +1638,13 @@ completion_matches (const char *text, CPFunction *entry_function) TEXT contains a partial username preceded by a random character (usually `~'). */ char * -username_completion_function (const char *text, int state) +rl_username_completion_function (text, state) + const char *text; + int state; { -#if defined (__GO32__) || defined (__WIN__) || defined (__OPENNT) +#if defined (__WIN32__) || defined (__OPENNT) return (char *)NULL; -#else /* !__GO32__ */ +#else /* !__WIN32__ && !__OPENNT) */ static char *username = (char *)NULL; static struct passwd *entry; static int namelen, first_char, first_char_loc; @@ -1437,7 +1676,7 @@ username_completion_function (const char *text, int state) } else { - value = xmalloc (2 + strlen (entry->pw_name)); + value = (char *)xmalloc (2 + strlen (entry->pw_name)); *value = *text; @@ -1448,7 +1687,7 @@ username_completion_function (const char *text, int state) return (value); } -#endif /* !__GO32__ */ +#endif /* !__WIN32__ && !__OPENNT */ } /* Okay, now we write the entry_function for filename completion. In the @@ -1456,7 +1695,9 @@ username_completion_function (const char *text, int state) because of all the pathnames that must be followed when looking up the completion for a command. */ char * -filename_completion_function (const char *text, int state) +rl_filename_completion_function (text, state) + const char *text; + int state; { static DIR *directory = (DIR *)NULL; static char *filename = (char *)NULL; @@ -1488,11 +1729,25 @@ filename_completion_function (const char *text, int state) temp = strrchr (dirname, '/'); +#if defined (__MSDOS__) + /* special hack for //X/... */ + if (dirname[0] == '/' && dirname[1] == '/' && ISALPHA ((unsigned char)dirname[2]) && dirname[3] == '/') + temp = strrchr (dirname + 3, '/'); +#endif + if (temp) { strcpy (filename, ++temp); *temp = '\0'; } +#if defined (__MSDOS__) + /* searches from current directory on the drive */ + else if (ISALPHA ((unsigned char)dirname[0]) && dirname[1] == ':') + { + strcpy (filename, dirname + 2); + dirname[2] = '\0'; + } +#endif else { dirname[0] = '.'; @@ -1511,6 +1766,9 @@ filename_completion_function (const char *text, int state) dirname = temp; } + if (rl_directory_rewrite_hook) + (*rl_directory_rewrite_hook) (&dirname); + if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&dirname)) { free (users_dirname); @@ -1534,10 +1792,14 @@ filename_completion_function (const char *text, int state) entry = (struct dirent *)NULL; while (directory && (entry = readdir (directory))) { - /* Special case for no filename. - All entries except "." and ".." match. */ + /* Special case for no filename. If the user has disabled the + `match-hidden-files' variable, skip filenames beginning with `.'. + All other entries except "." and ".." match. */ if (filename_len == 0) { + if (_rl_match_hidden_files == 0 && HIDDEN_FILE (entry->d_name)) + continue; + if (entry->d_name[0] != '.' || (entry->d_name[1] && (entry->d_name[1] != '.' || entry->d_name[2]))) @@ -1597,7 +1859,7 @@ filename_completion_function (const char *text, int state) if (rl_complete_with_tilde_expansion && *users_dirname == '~') { dirlen = strlen (dirname); - temp = xmalloc (2 + dirlen + D_NAMLEN (entry)); + temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry)); strcpy (temp, dirname); /* Canonicalization cuts off any final slash present. We may need to add it back. */ @@ -1610,8 +1872,11 @@ filename_completion_function (const char *text, int state) else { dirlen = strlen (users_dirname); - temp = xmalloc (1 + dirlen + D_NAMLEN (entry)); + temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry)); strcpy (temp, users_dirname); + /* Make sure that temp has a trailing slash here. */ + if (users_dirname[dirlen - 1] != '/') + temp[dirlen++] = '/'; } strcpy (temp + dirlen, entry->d_name); @@ -1633,9 +1898,10 @@ filename_completion_function (const char *text, int state) hit the end of the match list, we restore the original unmatched text, ring the bell, and reset the counter to zero. */ int -rl_menu_complete (int count, int ignore __attribute__((unused))) +rl_menu_complete (count, ignore) + int count, ignore __attribute__((unused)); { - Function *our_func; + rl_compentry_func_t *our_func; int matching_filenames, found_quote; static char *orig_text; @@ -1653,23 +1919,17 @@ rl_menu_complete (int count, int ignore __attribute__((unused))) /* Clean up from previous call, if any. */ FREE (orig_text); if (matches) - { - for (match_list_index = 0; matches[match_list_index]; match_list_index++) - free (matches[match_list_index]); - free (matches); - } + _rl_free_match_list (matches); match_list_index = match_list_size = 0; matches = (char **)NULL; /* Only the completion entry function can change these. */ - rl_filename_completion_desired = 0; - rl_filename_quoting_desired = 1; - rl_completion_type = '%'; + set_completion_defaults ('%'); our_func = rl_completion_entry_function ? rl_completion_entry_function - : (Function *)filename_completion_function; + : rl_filename_completion_function; /* We now look backwards for the start of a filename/variable word. */ orig_end = rl_point; @@ -1679,7 +1939,7 @@ rl_menu_complete (int count, int ignore __attribute__((unused))) if (rl_point) /* This (possibly) changes rl_point. If it returns a non-zero char, we know we have an open quote. */ - quote_char = find_completion_word (&found_quote, &delimiter); + quote_char = _rl_find_completion_word (&found_quote, &delimiter); orig_start = rl_point; rl_point = orig_end; @@ -1688,19 +1948,14 @@ rl_menu_complete (int count, int ignore __attribute__((unused))) matches = gen_completion_matches (orig_text, orig_start, orig_end, our_func, found_quote, quote_char); -#if 0 - /* If we are matching filenames, our_func will have been set to - filename_completion_function */ - matching_filenames = our_func == (Function *)filename_completion_function; -#else /* If we are matching filenames, the attempted completion function will have set rl_filename_completion_desired to a non-zero value. The basic - filename_completion_function does this. */ + rl_filename_completion_function does this. */ matching_filenames = rl_filename_completion_desired; -#endif + if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0) { - ding (); + rl_ding (); FREE (matches); matches = (char **)0; FREE (orig_text); @@ -1721,7 +1976,7 @@ rl_menu_complete (int count, int ignore __attribute__((unused))) if (matches == 0 || match_list_size == 0) { - ding (); + rl_ding (); FREE (matches); matches = (char **)0; completion_changed_buffer = 0; @@ -1734,13 +1989,14 @@ rl_menu_complete (int count, int ignore __attribute__((unused))) if (match_list_index == 0 && match_list_size > 1) { - ding (); + rl_ding (); insert_match (orig_text, orig_start, MULT_MATCH, "e_char); } else { insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, "e_char); - append_to_match (matches[match_list_index], delimiter, quote_char); + append_to_match (matches[match_list_index], delimiter, quote_char, + strcmp (orig_text, matches[match_list_index])); } completion_changed_buffer = 1; diff --git a/readline/configure b/readline/configure index 454a177e35d..fc3769f50e8 100755 --- a/readline/configure +++ b/readline/configure @@ -1,119 +1,158 @@ #! /bin/sh - -# From configure.in for Readline 4.0, version 2.14, from autoconf version 2.12 -LIBVERSION=4.0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# From configure.in for Readline 4.3, version 2.45, from autoconf version 2.52. # Guess values for system-dependent variables and create Makefiles. -# Generated automatically using autoconf version 2.12 -# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# Generated by Autoconf 2.52 for readline 4.3. # +# Report bugs to . +# +# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. -# Defaults: -ac_help= +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# Name of the executable. +as_me=`echo "$0" |sed 's,.*[\\/],,'` + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +as_executable_p="test -f" + +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + +# NLS nuisances. +$as_unset LANG || test "${LANG+set}" != set || { LANG=C; export LANG; } +$as_unset LC_ALL || test "${LC_ALL+set}" != set || { LC_ALL=C; export LC_ALL; } +$as_unset LC_TIME || test "${LC_TIME+set}" != set || { LC_TIME=C; export LC_TIME; } +$as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set || { LC_CTYPE=C; export LC_CTYPE; } +$as_unset LANGUAGE || test "${LANGUAGE+set}" != set || { LANGUAGE=C; export LANGUAGE; } +$as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set || { LC_COLLATE=C; export LC_COLLATE; } +$as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set || { LC_NUMERIC=C; export LC_NUMERIC; } +$as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set || { LC_MESSAGES=C; export LC_MESSAGES; } + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=:; export CDPATH; } + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# ac_default_prefix=/usr/local -# Any additions from configure.in: -ac_help="$ac_help ---with-curses use the curses library instead of the termcap library" +cross_compiling=no +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +ac_unique_file="readline.h" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif +#if HAVE_UNISTD_H +# include +#endif" # Initialize some variables set by options. +ac_init_help= +ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. -build=NONE -cache_file=./config.cache +cache_file=/dev/null exec_prefix=NONE -host=NONE no_create= -nonopt=NONE no_recursion= prefix=NONE program_prefix=NONE @@ -122,10 +161,15 @@ program_transform_name=s,x,x, silent= site= srcdir= -target=NONE verbose= x_includes=NONE x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' @@ -139,16 +183,16 @@ oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' -# Initialize some other variables. -subdirs= -MFLAGS= MAKEFLAGS= -# Maximum number of lines to put in a shell here document. -ac_max_here_lines=12 +# Identity of this package. +PACKAGE_NAME='readline' +PACKAGE_TARNAME='readline' +PACKAGE_VERSION='4.3' +PACKAGE_STRING='readline 4.3' +PACKAGE_BUGREPORT='bug-readline@gnu.org' ac_prev= for ac_option do - # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" @@ -156,59 +200,59 @@ do continue fi - case "$ac_option" in - -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; - *) ac_optarg= ;; - esac + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` # Accept the important Cygnus configure options, so we can diagnose typos. - case "$ac_option" in + case $ac_option in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir="$ac_optarg" ;; + bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) - ac_prev=build ;; + ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build="$ac_optarg" ;; + build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file="$ac_optarg" ;; + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) - datadir="$ac_optarg" ;; + datadir=$ac_optarg ;; -disable-* | --disable-*) - ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. - if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then - { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } - fi - ac_feature=`echo $ac_feature| sed 's/-/_/g'` - eval "enable_${ac_feature}=no" ;; + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; -enable-* | --enable-*) - ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. - if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then - { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } - fi - ac_feature=`echo $ac_feature| sed 's/-/_/g'` - case "$ac_option" in - *=*) ;; + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac - eval "enable_${ac_feature}='$ac_optarg'" ;; + eval "enable_$ac_feature='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ @@ -217,95 +261,47 @@ do -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) - exec_prefix="$ac_optarg" ;; + exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; - -help | --help | --hel | --he) - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat << EOF -Usage: configure [options] [host] -Options: [defaults in brackets after descriptions] -Configuration: - --cache-file=FILE cache test results in FILE - --help print this message - --no-create do not create output files - --quiet, --silent do not print \`checking...' messages - --version print the version of autoconf that created configure -Directory and file names: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [same as prefix] - --bindir=DIR user executables in DIR [EPREFIX/bin] - --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] - --libexecdir=DIR program executables in DIR [EPREFIX/libexec] - --datadir=DIR read-only architecture-independent data in DIR - [PREFIX/share] - --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data in DIR - [PREFIX/com] - --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] - --libdir=DIR object code libraries in DIR [EPREFIX/lib] - --includedir=DIR C header files in DIR [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] - --infodir=DIR info documentation in DIR [PREFIX/info] - --mandir=DIR man documentation in DIR [PREFIX/man] - --srcdir=DIR find the sources in DIR [configure dir or ..] - --program-prefix=PREFIX prepend PREFIX to installed program names - --program-suffix=SUFFIX append SUFFIX to installed program names - --program-transform-name=PROGRAM - run sed PROGRAM on installed program names -EOF - cat << EOF -Host type: - --build=BUILD configure for building on BUILD [BUILD=HOST] - --host=HOST configure for HOST [guessed] - --target=TARGET configure for TARGET [TARGET=HOST] -Features and packages: - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --x-includes=DIR X include files are in DIR - --x-libraries=DIR X library files are in DIR -EOF - if test -n "$ac_help"; then - echo "--enable and --with options recognized:$ac_help" - fi - exit 0 ;; + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; -host | --host | --hos | --ho) - ac_prev=host ;; + ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) - host="$ac_optarg" ;; + host_alias=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir="$ac_optarg" ;; + includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir="$ac_optarg" ;; + infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir="$ac_optarg" ;; + libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) - libexecdir="$ac_optarg" ;; + libexecdir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ @@ -314,12 +310,12 @@ EOF -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) - localstatedir="$ac_optarg" ;; + localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir="$ac_optarg" ;; + mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. @@ -340,26 +336,26 @@ EOF -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir="$ac_optarg" ;; + oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix="$ac_optarg" ;; + prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix="$ac_optarg" ;; + program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix="$ac_optarg" ;; + program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ @@ -376,7 +372,7 @@ EOF | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name="$ac_optarg" ;; + program_transform_name=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) @@ -386,7 +382,7 @@ EOF ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) - sbindir="$ac_optarg" ;; + sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ @@ -397,58 +393,57 @@ EOF | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) - sharedstatedir="$ac_optarg" ;; + sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) - site="$ac_optarg" ;; + site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir="$ac_optarg" ;; + srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir="$ac_optarg" ;; + sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target ;; + ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target="$ac_optarg" ;; + target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; - -version | --version | --versio | --versi | --vers) - echo "configure generated by autoconf version 2.12" - exit 0 ;; + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; -with-* | --with-*) - ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. - if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then - { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } - fi + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } ac_package=`echo $ac_package| sed 's/-/_/g'` - case "$ac_option" in - *=*) ;; + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac - eval "with_${ac_package}='$ac_optarg'" ;; + eval "with_$ac_package='$ac_optarg'" ;; -without-* | --without-*) - ac_package=`echo $ac_option|sed -e 's/-*without-//'` + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. - if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then - { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } - fi - ac_package=`echo $ac_package| sed 's/-/_/g'` - eval "with_${ac_package}=no" ;; + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; --x) # Obsolete; use --with-x. @@ -459,98 +454,98 @@ EOF ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes="$ac_optarg" ;; + x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries="$ac_optarg" ;; + x_libraries=$ac_optarg ;; - -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } ;; + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + *) - if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then - echo "configure: warning: $ac_option: invalid host type" 1>&2 - fi - if test "x$nonopt" != xNONE; then - { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } - fi - nonopt="$ac_option" + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then - { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } fi -trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 - -# File descriptor usage: -# 0 standard input -# 1 file creation -# 2 errors and warnings -# 3 some systems may open it to /dev/tty -# 4 used on the Kubota Titan -# 6 checking for... messages and results -# 5 compiler messages saved in config.log -if test "$silent" = yes; then - exec 6>/dev/null -else - exec 6>&1 -fi -exec 5>./config.log - -echo "\ -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. -" 1>&5 - -# Strip out --no-create and --no-recursion so they do not pile up. -# Also quote any args containing shell metacharacters. -ac_configure_args= -for ac_arg +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix do - case "$ac_arg" in - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c) ;; - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) - ac_configure_args="$ac_configure_args '$ac_arg'" ;; - *) ac_configure_args="$ac_configure_args $ac_arg" ;; + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute path for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; esac done -# NLS nuisances. -# Only set these to C if already set. These must not be set unconditionally -# because not all systems understand e.g. LANG=C (notably SCO). -# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! -# Non-C LC_CTYPE values break the ctype check. -if test "${LANG+set}" = set; then LANG=C; export LANG; fi -if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi -if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi -if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute path for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -rf conftest* confdefs.h -# AIX cpp loses on an empty file, so make sure it contains at least a newline. -echo > confdefs.h +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +build=$build_alias +host=$host_alias +target=$target_alias -# A filename unique to this package, relative to the directory that -# configure is in, which we can look for to find out if srcdir is correct. -ac_unique_file=readline.h +# FIXME: should be removed in autoconf 3.0. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_prog=$0 - ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + ac_confdir=`echo "$ac_prog" | sed 's%[\\/][^\\/][^\\/]*$%%'` test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then @@ -561,13 +556,316 @@ else fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then - { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + { echo "$as_me: error: cannot find sources in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } else - { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + { echo "$as_me: error: cannot find sources in $srcdir" >&2 + { (exit 1); exit 1; }; } fi fi -srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat < if you have libraries in a + nonstandard directory + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +EOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_subdir in : $ac_subdirs_all; do test "x$ac_subdir" = x: && continue + cd $ac_subdir + # A "../" for each directory in /$ac_subdir. + ac_dots=`echo $ac_subdir | + sed 's,^\./,,;s,[^/]$,&/,;s,[^/]*/,../,g'` + + case $srcdir in + .) # No --srcdir option. We are building in place. + ac_sub_srcdir=$srcdir ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_sub_srcdir=$srcdir/$ac_subdir ;; + *) # Relative path. + ac_sub_srcdir=$ac_dots$srcdir/$ac_subdir ;; + esac + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_sub_srcdir/configure.gnu; then + echo + $SHELL $ac_sub_srcdir/configure.gnu --help=recursive + elif test -f $ac_sub_srcdir/configure; then + echo + $SHELL $ac_sub_srcdir/configure --help=recursive + elif test -f $ac_sub_srcdir/configure.ac || + test -f $ac_sub_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_subdir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\EOF +readline configure 4.3 +generated by GNU Autoconf 2.52 + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +EOF + exit 0 +fi +exec 5>config.log +cat >&5 </dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +PATH = $PATH + +_ASUNAME +} >&5 + +cat >&5 <\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + ac_sep=" " ;; + *) ac_configure_args="$ac_configure_args$ac_sep$ac_arg" + ac_sep=" " ;; + esac + # Get rid of the leading space. +done + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + echo >&5 + echo "## ----------------- ##" >&5 + echo "## Cache variables. ##" >&5 + echo "## ----------------- ##" >&5 + echo >&5 + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} >&5 + sed "/^$/d" confdefs.h >conftest.log + if test -s conftest.log; then + echo >&5 + echo "## ------------ ##" >&5 + echo "## confdefs.h. ##" >&5 + echo "## ------------ ##" >&5 + echo >&5 + cat conftest.log >&5 + fi + (echo; echo) >&5 + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" >&5 + echo "$as_me: exit $exit_status" >&5 + rm -rf conftest* confdefs* core core.* *.core conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then @@ -578,42 +876,107 @@ if test -z "$CONFIG_SITE"; then fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then - echo "loading site script $ac_site_file" + { echo "$as_me:879: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + cat "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then - echo "loading cache $cache_file" - . $cache_file + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:890: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi else - echo "creating cache $cache_file" - > $cache_file + { echo "$as_me:898: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:914: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:918: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:924: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:926: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:928: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. It doesn't matter if + # we pass some twice (in addition to the command line arguments). + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` + ac_configure_args="$ac_configure_args '$ac_arg'" + ;; + *) ac_configure_args="$ac_configure_args $ac_var=$ac_new_val" + ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:947: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:949: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } fi ac_ext=c -# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -cross_compiling=$ac_cv_prog_cc_cross +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu -if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then - # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. - if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then - ac_n= ac_c=' -' ac_t=' ' - else - ac_n=-n ac_c= ac_t= - fi +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac +echo "#! $SHELL" >conftest.sh +echo "exit 0" >>conftest.sh +chmod +x conftest.sh +if { (echo "$as_me:969: PATH=\".;.\"; conftest.sh") >&5 + (PATH=".;."; conftest.sh) 2>&5 + ac_status=$? + echo "$as_me:972: \$? = $ac_status" >&5 + (exit $ac_status); }; then + ac_path_separator=';' else - ac_n= ac_c='\c' ac_t= + ac_path_separator=: fi - - - - - +PATH_SEPARATOR="$ac_path_separator" +rm -f conftest.sh ac_aux_dir= for ac_dir in ./support $srcdir/./support; do @@ -625,387 +988,1135 @@ for ac_dir in ./support $srcdir/./support; do ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break fi done if test -z "$ac_aux_dir"; then - { echo "configure: error: can not find install-sh or install.sh in ./support $srcdir/./support" 1>&2; exit 1; } + { { echo "$as_me:998: error: cannot find install-sh or install.sh in ./support $srcdir/./support" >&5 +echo "$as_me: error: cannot find install-sh or install.sh in ./support $srcdir/./support" >&2;} + { (exit 1); exit 1; }; } fi -ac_config_guess=$ac_aux_dir/config.guess -ac_config_sub=$ac_aux_dir/config.sub -ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. +ac_config_headers="$ac_config_headers config.h" +LIBVERSION=4.3 # Make sure we can run config.sub. -if $ac_config_sub sun4 >/dev/null 2>&1; then : -else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +$ac_config_sub sun4 >/dev/null 2>&1 || + { { echo "$as_me:1012: error: cannot run $ac_config_sub" >&5 +echo "$as_me: error: cannot run $ac_config_sub" >&2;} + { (exit 1); exit 1; }; } + +echo "$as_me:1016: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6 +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_build_alias=$build_alias +test -z "$ac_cv_build_alias" && + ac_cv_build_alias=`$ac_config_guess` +test -z "$ac_cv_build_alias" && + { { echo "$as_me:1025: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || + { { echo "$as_me:1029: error: $ac_config_sub $ac_cv_build_alias failed." >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed." >&2;} + { (exit 1); exit 1; }; } + fi +echo "$as_me:1034: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6 +build=$ac_cv_build +build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` -echo $ac_n "checking host system type""... $ac_c" 1>&6 -echo "configure:646: checking host system type" >&5 - -host_alias=$host -case "$host_alias" in -NONE) - case $nonopt in - NONE) - if host_alias=`$ac_config_guess`; then : - else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } - fi ;; - *) host_alias=$nonopt ;; - esac ;; -esac - -host=`$ac_config_sub $host_alias` -host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` -echo "$ac_t""$host" 1>&6 +echo "$as_me:1041: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6 +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_host_alias=$host_alias +test -z "$ac_cv_host_alias" && + ac_cv_host_alias=$ac_cv_build_alias +ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || + { { echo "$as_me:1050: error: $ac_config_sub $ac_cv_host_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} + { (exit 1); exit 1; }; } +fi +echo "$as_me:1055: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6 +host=$ac_cv_host +host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` opt_curses=no -opt_shared=no # Check whether --with-curses or --without-curses was given. if test "${with_curses+set}" = set; then withval="$with_curses" opt_curses=$withval -fi - +fi; if test "$opt_curses" = "yes"; then prefer_curses=yes fi +opt_static_libs=yes +opt_shared_libs=yes + +# Check whether --enable-shared or --disable-shared was given. +if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + opt_shared_libs=$enableval +fi; +# Check whether --enable-static or --disable-static was given. +if test "${enable_static+set}" = set; then + enableval="$enable_static" + opt_static_libs=$enableval +fi; + +echo "" +echo "Beginning configuration for readline-$LIBVERSION for ${host_cpu}-${host_vendor}-${host_os}" +echo "" + # We want these before the checks, so the checks can modify their values. test -z "$CFLAGS" && CFLAGS=-g auto_cflags=1 -# Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:687: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +echo "$as_me:1095: checking whether ${MAKE-make} sets \${MAKE}" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \${MAKE}... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:1115: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:1119: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:1132: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_prog_CC="gcc" - break - fi - done - IFS="$ac_save_ifs" + ac_save_IFS=$IFS; IFS=$ac_path_separator +ac_dummy="$PATH" +for ac_dir in $ac_dummy; do + IFS=$ac_save_IFS + test -z "$ac_dir" && ac_dir=. + $as_executable_p "$ac_dir/$ac_word" || continue +ac_cv_prog_CC="${ac_tool_prefix}gcc" +echo "$as_me:1147: found $ac_dir/$ac_word" >&5 +break +done + fi fi -CC="$ac_cv_prog_CC" +CC=$ac_cv_prog_CC if test -n "$CC"; then - echo "$ac_t""$CC" 1>&6 + echo "$as_me:1155: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 else - echo "$ac_t""no" 1>&6 + echo "$as_me:1158: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:1167: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else + ac_save_IFS=$IFS; IFS=$ac_path_separator +ac_dummy="$PATH" +for ac_dir in $ac_dummy; do + IFS=$ac_save_IFS + test -z "$ac_dir" && ac_dir=. + $as_executable_p "$ac_dir/$ac_word" || continue +ac_cv_prog_ac_ct_CC="gcc" +echo "$as_me:1182: found $ac_dir/$ac_word" >&5 +break +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:1190: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:1193: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" fi if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:716: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:1206: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_save_IFS=$IFS; IFS=$ac_path_separator +ac_dummy="$PATH" +for ac_dir in $ac_dummy; do + IFS=$ac_save_IFS + test -z "$ac_dir" && ac_dir=. + $as_executable_p "$ac_dir/$ac_word" || continue +ac_cv_prog_CC="${ac_tool_prefix}cc" +echo "$as_me:1221: found $ac_dir/$ac_word" >&5 +break +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:1229: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:1232: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:1241: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else + ac_save_IFS=$IFS; IFS=$ac_path_separator +ac_dummy="$PATH" +for ac_dir in $ac_dummy; do + IFS=$ac_save_IFS + test -z "$ac_dir" && ac_dir=. + $as_executable_p "$ac_dir/$ac_word" || continue +ac_cv_prog_ac_ct_CC="cc" +echo "$as_me:1256: found $ac_dir/$ac_word" >&5 +break +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:1264: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:1267: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:1280: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" ac_prog_rejected=no - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - break - fi - done - IFS="$ac_save_ifs" + ac_save_IFS=$IFS; IFS=$ac_path_separator +ac_dummy="$PATH" +for ac_dir in $ac_dummy; do + IFS=$ac_save_IFS + test -z "$ac_dir" && ac_dir=. + $as_executable_p "$ac_dir/$ac_word" || continue +if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue +fi +ac_cv_prog_CC="cc" +echo "$as_me:1300: found $ac_dir/$ac_word" >&5 +break +done + if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift - if test $# -gt 0; then + if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift - set dummy "$ac_dir/$ac_word" "$@" + set dummy "$ac_dir/$ac_word" ${1+"$@"} shift ac_cv_prog_CC="$@" fi fi fi fi -CC="$ac_cv_prog_CC" +CC=$ac_cv_prog_CC if test -n "$CC"; then - echo "$ac_t""$CC" 1>&6 + echo "$as_me:1322: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 else - echo "$ac_t""no" 1>&6 + echo "$as_me:1325: result: no" >&5 +echo "${ECHO_T}no" >&6 fi - test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:1336: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_save_IFS=$IFS; IFS=$ac_path_separator +ac_dummy="$PATH" +for ac_dir in $ac_dummy; do + IFS=$ac_save_IFS + test -z "$ac_dir" && ac_dir=. + $as_executable_p "$ac_dir/$ac_word" || continue +ac_cv_prog_CC="$ac_tool_prefix$ac_prog" +echo "$as_me:1351: found $ac_dir/$ac_word" >&5 +break +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:1359: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:1362: result: no" >&5 +echo "${ECHO_T}no" >&6 fi -echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:764: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:1375: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else + ac_save_IFS=$IFS; IFS=$ac_path_separator +ac_dummy="$PATH" +for ac_dir in $ac_dummy; do + IFS=$ac_save_IFS + test -z "$ac_dir" && ac_dir=. + $as_executable_p "$ac_dir/$ac_word" || continue +ac_cv_prog_ac_ct_CC="$ac_prog" +echo "$as_me:1390: found $ac_dir/$ac_word" >&5 +break +done -ac_ext=c -# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. -ac_cpp='$CPP $CPPFLAGS' -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -cross_compiling=$ac_cv_prog_cc_cross +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:1398: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:1401: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi -cat > conftest.$ac_ext <&5 +echo "$as_me: error: no acceptable cc found in \$PATH" >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:1418:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:1421: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:1424: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:1426: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:1429: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:1431: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:1434: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +#line 1438 "configure" #include "confdefs.h" -main(){return(0);} -EOF -if { (eval echo configure:778: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - ac_cv_prog_cc_works=yes - # If we can't run a trivial program, we are probably using a cross compiler. - if (./conftest; exit) 2>/dev/null; then - ac_cv_prog_cc_cross=no + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:1454: checking for C compiler default output" >&5 +echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:1457: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:1460: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. +for ac_file in `ls a.exe conftest.exe 2>/dev/null; + ls a.out conftest 2>/dev/null; + ls a.* conftest.* 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb ) ;; + a.out ) # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool --akim. + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +{ { echo "$as_me:1483: error: C compiler cannot create executables" >&5 +echo "$as_me: error: C compiler cannot create executables" >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:1489: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:1494: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:1500: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:1503: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no else - ac_cv_prog_cc_cross=yes + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:1510: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'." >&2;} + { (exit 1); exit 1; }; } + fi fi -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - ac_cv_prog_cc_works=no fi -rm -fr conftest* +echo "$as_me:1518: result: yes" >&5 +echo "${ECHO_T}yes" >&6 -echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 -if test $ac_cv_prog_cc_works = no; then - { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } -fi -echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:798: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 -echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 -cross_compiling=$ac_cv_prog_cc_cross +rm -f a.out a.exe conftest$ac_cv_exeext +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:1525: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:1527: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 -echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:803: checking whether we are using GNU C" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +echo "$as_me:1530: checking for executable suffix" >&5 +echo $ECHO_N "checking for executable suffix... $ECHO_C" >&6 +if { (eval echo "$as_me:1532: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:1535: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in `(ls conftest.exe; ls conftest; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done else - cat > conftest.c <&5 +echo "$as_me: error: cannot compute EXEEXT: cannot compile and link" >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:1557: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:1563: checking for object suffix" >&5 +echo $ECHO_N "checking for object suffix... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 1569 "configure" +#include "confdefs.h" + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:1581: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:1584: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +{ { echo "$as_me:1596: error: cannot compute OBJEXT: cannot compile" >&5 +echo "$as_me: error: cannot compute OBJEXT: cannot compile" >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:1603: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:1607: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 1613 "configure" +#include "confdefs.h" + +int +main () +{ +#ifndef __GNUC__ + choke me #endif -EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:812: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then - ac_cv_prog_gcc=yes -else - ac_cv_prog_gcc=no -fi -fi -echo "$ac_t""$ac_cv_prog_gcc" 1>&6 - -if test $ac_cv_prog_gcc = yes; then - GCC=yes - ac_test_CFLAGS="${CFLAGS+set}" - ac_save_CFLAGS="$CFLAGS" - CFLAGS= - echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:827: checking whether ${CC-cc} accepts -g" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:1628: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:1631: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:1634: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:1637: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes else - echo 'void f(){}' > conftest.c -if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_compiler_gnu=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:1649: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:1655: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 1661 "configure" +#include "confdefs.h" + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:1673: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:1676: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:1679: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:1682: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then ac_cv_prog_cc_g=yes else - ac_cv_prog_cc_g=no + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_prog_cc_g=no fi -rm -f conftest* - +rm -f conftest.$ac_objext conftest.$ac_ext fi - -echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 - if test "$ac_test_CFLAGS" = set; then - CFLAGS="$ac_save_CFLAGS" - elif test $ac_cv_prog_cc_g = yes; then +echo "$as_me:1692: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then CFLAGS="-g -O2" else - CFLAGS="-O2" + CFLAGS="-g" fi else - GCC= - test "${CFLAGS+set}" = set || CFLAGS="-g" + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:1719: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:1722: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:1725: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:1728: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + ''\ + '#include ' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +#line 1740 "configure" +#include "confdefs.h" +#include +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:1753: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:1756: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:1759: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:1762: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +continue +fi +rm -f conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +#line 1772 "configure" +#include "confdefs.h" +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:1784: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:1787: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:1790: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:1793: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +fi +rm -f conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h fi -echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:855: checking how to run the C preprocessor" >&5 +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +echo "$as_me:1825: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then -if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - # This must be in double quotes, not single quotes, because CPP may get - # substituted into the Makefile and "${CC-cc}" will confuse make. - CPP="${CC-cc} -E" + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 1846 "configure" #include "confdefs.h" #include -Syntax Error -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:876: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out` -if test -z "$ac_err"; then + Syntax error +_ACEOF +if { (eval echo "$as_me:1851: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:1857: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then : else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 + echo "$as_me: failed program was:" >&5 cat conftest.$ac_ext >&5 - rm -rf conftest* - CPP="${CC-cc} -E -traditional-cpp" - cat > conftest.$ac_ext < -Syntax Error -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:893: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out` -if test -z "$ac_err"; then - : -else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - CPP=/lib/cpp + # Broken: fails on valid input. +continue fi -rm -f conftest* -fi -rm -f conftest* - ac_cv_prog_CPP="$CPP" -fi - CPP="$ac_cv_prog_CPP" -else - ac_cv_prog_CPP="$CPP" -fi -echo "$ac_t""$CPP" 1>&6 +rm -f conftest.err conftest.$ac_ext -ac_safe=`echo "minix/config.h" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6 -echo "configure:917: checking for minix/config.h" >&5 -if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line 1880 "configure" +#include "confdefs.h" +#include +_ACEOF +if { (eval echo "$as_me:1884: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:1890: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi else - cat > conftest.$ac_ext <&5 + cat conftest.$ac_ext >&5 + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:1927: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line 1937 "configure" +#include "confdefs.h" +#include + Syntax error +_ACEOF +if { (eval echo "$as_me:1942: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:1948: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line 1971 "configure" +#include "confdefs.h" +#include +_ACEOF +if { (eval echo "$as_me:1975: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:1981: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:2009: error: C preprocessor \"$CPP\" fails sanity check" >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +echo "$as_me:2020: checking for minix/config.h" >&5 +echo $ECHO_N "checking for minix/config.h... $ECHO_C" >&6 +if test "${ac_cv_header_minix_config_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 2026 "configure" #include "confdefs.h" #include -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:927: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out` -if test -z "$ac_err"; then - rm -rf conftest* - eval "ac_cv_header_$ac_safe=yes" +_ACEOF +if { (eval echo "$as_me:2030: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:2036: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_cv_header_minix_config_h=yes +else + echo "$as_me: failed program was:" >&5 cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" + ac_cv_header_minix_config_h=no fi -rm -f conftest* +rm -f conftest.err conftest.$ac_ext fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 +echo "$as_me:2055: result: $ac_cv_header_minix_config_h" >&5 +echo "${ECHO_T}$ac_cv_header_minix_config_h" >&6 +if test $ac_cv_header_minix_config_h = yes; then MINIX=yes else - echo "$ac_t""no" 1>&6 -MINIX= + MINIX= fi if test "$MINIX" = yes; then - cat >> confdefs.h <<\EOF + +cat >>confdefs.h <<\EOF #define _POSIX_SOURCE 1 EOF - cat >> confdefs.h <<\EOF +cat >>confdefs.h <<\EOF #define _POSIX_1_SOURCE 2 EOF - cat >> confdefs.h <<\EOF +cat >>confdefs.h <<\EOF #define _MINIX 1 EOF fi - # If we're using gcc and the user hasn't specified CFLAGS, add -O to CFLAGS. test -n "$GCC" && test -n "$auto_cflags" && CFLAGS="$CFLAGS -O" -if test $ac_cv_prog_gcc = yes; then - echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6 -echo "configure:970: checking whether ${CC-cc} needs -traditional" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +if test $ac_cv_c_compiler_gnu = yes; then + echo "$as_me:2083: checking whether $CC needs -traditional" >&5 +echo $ECHO_N "checking whether $CC needs -traditional... $ECHO_C" >&6 +if test "${ac_cv_prog_gcc_traditional+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_pattern="Autoconf.*'x'" - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 2090 "configure" #include "confdefs.h" #include Autoconf TIOCGETP -EOF +_ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "$ac_pattern" >/dev/null 2>&1; then - rm -rf conftest* ac_cv_prog_gcc_traditional=yes else - rm -rf conftest* ac_cv_prog_gcc_traditional=no fi rm -f conftest* - if test $ac_cv_prog_gcc_traditional = no; then - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 2105 "configure" #include "confdefs.h" #include Autoconf TCGETA -EOF +_ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "$ac_pattern" >/dev/null 2>&1; then - rm -rf conftest* ac_cv_prog_gcc_traditional=yes fi rm -f conftest* fi fi - -echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6 +echo "$as_me:2118: result: $ac_cv_prog_gcc_traditional" >&5 +echo "${ECHO_T}$ac_cv_prog_gcc_traditional" >&6 if test $ac_cv_prog_gcc_traditional = yes; then CC="$CC -traditional" fi @@ -1018,28 +2129,38 @@ fi # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. -echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:1026: checking for a BSD compatible install" >&5 +echo "$as_me:2137: checking for a BSD compatible install" >&5 +echo $ECHO_N "checking for a BSD compatible install... $ECHO_C" >&6 if test -z "$INSTALL"; then -if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:" + ac_save_IFS=$IFS; IFS=$ac_path_separator for ac_dir in $PATH; do + IFS=$ac_save_IFS # Account for people who put trailing slashes in PATH elements. - case "$ac_dir/" in - /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + case $ac_dir/ in + / | ./ | .// | /cC/* \ + | /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* \ + | /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. - for ac_prog in ginstall installbsd scoinst install; do - if test -f $ac_dir/$ac_prog; then + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if $as_executable_p "$ac_dir/$ac_prog"; then if test $ac_prog = install && - grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + grep dspmsg "$ac_dir/$ac_prog" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. - # OSF/1 installbsd also uses dspmsg, but is usable. + : + elif test $ac_prog = install && + grep pwplus "$ac_dir/$ac_prog" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. : else ac_cv_path_install="$ac_dir/$ac_prog -c" @@ -1050,101 +2171,581 @@ else ;; esac done - IFS="$ac_save_IFS" fi if test "${ac_cv_path_install+set}" = set; then - INSTALL="$ac_cv_path_install" + INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. We don't cache a # path for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the path is relative. - INSTALL="$ac_install_sh" + INSTALL=$ac_install_sh fi fi -echo "$ac_t""$INSTALL" 1>&6 +echo "$as_me:2186: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1078: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +echo "$as_me:2199: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_prog_AR="ar" - break - fi - done - IFS="$ac_save_ifs" + ac_save_IFS=$IFS; IFS=$ac_path_separator +ac_dummy="$PATH" +for ac_dir in $ac_dummy; do + IFS=$ac_save_IFS + test -z "$ac_dir" && ac_dir=. + $as_executable_p "$ac_dir/$ac_word" || continue +ac_cv_prog_AR="" +echo "$as_me:2214: found $ac_dir/$ac_word" >&5 +break +done + + test -z "$ac_cv_prog_AR" && ac_cv_prog_AR="ar" fi fi -AR="$ac_cv_prog_AR" +AR=$ac_cv_prog_AR if test -n "$AR"; then - echo "$ac_t""$AR" 1>&6 + echo "$as_me:2223: result: $AR" >&5 +echo "${ECHO_T}$AR" >&6 else - echo "$ac_t""no" 1>&6 + echo "$as_me:2226: result: no" >&5 +echo "${ECHO_T}no" >&6 fi test -n "$ARFLAGS" || ARFLAGS="cr" -# Extract the first word of "ranlib", so it can be a program name with args. -set dummy ranlib; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1107: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +echo "$as_me:2234: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_prog_RANLIB="ranlib" - break - fi - done - IFS="$ac_save_ifs" - test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" + ac_save_IFS=$IFS; IFS=$ac_path_separator +ac_dummy="$PATH" +for ac_dir in $ac_dummy; do + IFS=$ac_save_IFS + test -z "$ac_dir" && ac_dir=. + $as_executable_p "$ac_dir/$ac_word" || continue +ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" +echo "$as_me:2249: found $ac_dir/$ac_word" >&5 +break +done + fi fi -RANLIB="$ac_cv_prog_RANLIB" +RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then - echo "$ac_t""$RANLIB" 1>&6 + echo "$as_me:2257: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6 else - echo "$ac_t""no" 1>&6 + echo "$as_me:2260: result: no" >&5 +echo "${ECHO_T}no" >&6 fi +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo "$as_me:2269: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else + ac_save_IFS=$IFS; IFS=$ac_path_separator +ac_dummy="$PATH" +for ac_dir in $ac_dummy; do + IFS=$ac_save_IFS + test -z "$ac_dir" && ac_dir=. + $as_executable_p "$ac_dir/$ac_word" || continue +ac_cv_prog_ac_ct_RANLIB="ranlib" +echo "$as_me:2284: found $ac_dir/$ac_word" >&5 +break +done + + test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + echo "$as_me:2293: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6 +else + echo "$as_me:2296: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + RANLIB=$ac_ct_RANLIB +else + RANLIB="$ac_cv_prog_RANLIB" +fi MAKE_SHELL=/bin/sh - -echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 -echo "configure:1138: checking return type of signal handlers" >&5 -if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +echo "$as_me:2307: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 2315 "configure" +#include "confdefs.h" +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:2364: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:2367: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:2370: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:2373: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +fi +rm -f conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:2390: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:2393: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +echo "$as_me:2398: checking for an ANSI C-conforming const" >&5 +echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6 +if test "${ac_cv_c_const+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 2404 "configure" +#include "confdefs.h" + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset x; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *ccp; + char **p; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + ccp = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++ccp; + p = (char**) ccp; + ccp = (char const *const *) p; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + } +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:2462: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:2465: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:2468: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:2471: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_const=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_c_const=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:2481: result: $ac_cv_c_const" >&5 +echo "${ECHO_T}$ac_cv_c_const" >&6 +if test $ac_cv_c_const = no; then + +cat >>confdefs.h <<\EOF +#define const +EOF + +fi + +echo "$as_me:2491: checking for function prototypes" >&5 +echo $ECHO_N "checking for function prototypes... $ECHO_C" >&6 +if test "$ac_cv_prog_cc_stdc" != no; then + echo "$as_me:2494: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +cat >>confdefs.h <<\EOF +#define PROTOTYPES 1 +EOF + +else + echo "$as_me:2502: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +echo "$as_me:2506: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 2512 "configure" +#include "confdefs.h" +#include +#include +#include +#include + +_ACEOF +if { (eval echo "$as_me:2520: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:2526: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +#line 2548 "configure" +#include "confdefs.h" +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +#line 2566 "configure" +#include "confdefs.h" +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +#line 2587 "configure" +#include "confdefs.h" +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:2613: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:2616: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:2618: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:2621: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_header_stdc=no +fi +rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:2634: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:2650: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 2656 "configure" +#include "confdefs.h" +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:2662: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:2665: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:2668: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:2671: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +eval "$as_ac_Header=no" +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:2681: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <&5 +echo $ECHO_N "checking whether char is unsigned... $ECHO_C" >&6 +if test "${ac_cv_c_char_unsigned+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 2697 "configure" +#include "confdefs.h" +$ac_includes_default +int +main () +{ +int _array_ [1 - 2 * !(((char) -1) < 0)] + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:2709: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:2712: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:2715: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:2718: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_char_unsigned=no +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_c_char_unsigned=yes +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:2728: result: $ac_cv_c_char_unsigned" >&5 +echo "${ECHO_T}$ac_cv_c_char_unsigned" >&6 +if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then + cat >>confdefs.h <<\EOF +#define __CHAR_UNSIGNED__ 1 +EOF + +fi + +echo "$as_me:2737: checking return type of signal handlers" >&5 +echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6 +if test "${ac_cv_type_signal+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 2743 "configure" #include "confdefs.h" #include #include #ifdef signal -#undef signal +# undef signal #endif #ifdef __cplusplus extern "C" void (*signal (int, void (*)(int)))(int); @@ -1152,36 +2753,152 @@ extern "C" void (*signal (int, void (*)(int)))(int); void (*signal ()) (); #endif -int main() { +int +main () +{ int i; -; return 0; } -EOF -if { (eval echo configure:1160: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:2765: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:2768: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:2771: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:2774: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then ac_cv_type_signal=void else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - ac_cv_type_signal=int + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_type_signal=int fi -rm -f conftest* +rm -f conftest.$ac_objext conftest.$ac_ext fi +echo "$as_me:2784: result: $ac_cv_type_signal" >&5 +echo "${ECHO_T}$ac_cv_type_signal" >&6 -echo "$ac_t""$ac_cv_type_signal" 1>&6 -cat >> confdefs.h <>confdefs.h <&6 -echo "configure:1180: checking whether stat file-mode macros are broken" >&5 -if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +echo "$as_me:2791: checking for size_t" >&5 +echo $ECHO_N "checking for size_t... $ECHO_C" >&6 +if test "${ac_cv_type_size_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 2797 "configure" +#include "confdefs.h" +$ac_includes_default +int +main () +{ +if ((size_t *) 0) + return 0; +if (sizeof (size_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:2812: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:2815: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:2818: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:2821: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_size_t=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_type_size_t=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:2831: result: $ac_cv_type_size_t" >&5 +echo "${ECHO_T}$ac_cv_type_size_t" >&6 +if test $ac_cv_type_size_t = yes; then + : +else + +cat >>confdefs.h <&5 +echo $ECHO_N "checking for ssize_t... $ECHO_C" >&6 +if test "${ac_cv_type_ssize_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 2849 "configure" +#include "confdefs.h" +$ac_includes_default +int +main () +{ +if ((ssize_t *) 0) + return 0; +if (sizeof (ssize_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:2864: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:2867: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:2870: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:2873: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_ssize_t=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_type_ssize_t=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:2883: result: $ac_cv_type_ssize_t" >&5 +echo "${ECHO_T}$ac_cv_type_ssize_t" >&6 +if test $ac_cv_type_ssize_t = yes; then + : +else + +cat >>confdefs.h <&5 +echo $ECHO_N "checking whether stat file-mode macros are broken... $ECHO_C" >&6 +if test "${ac_cv_header_stat_broken+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 2901 "configure" #include "confdefs.h" #include #include @@ -1210,408 +2927,516 @@ You lose. # endif #endif -EOF +_ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "You lose" >/dev/null 2>&1; then - rm -rf conftest* ac_cv_header_stat_broken=yes else - rm -rf conftest* ac_cv_header_stat_broken=no fi rm -f conftest* fi - -echo "$ac_t""$ac_cv_header_stat_broken" 1>&6 +echo "$as_me:2940: result: $ac_cv_header_stat_broken" >&5 +echo "${ECHO_T}$ac_cv_header_stat_broken" >&6 if test $ac_cv_header_stat_broken = yes; then - cat >> confdefs.h <<\EOF + +cat >>confdefs.h <<\EOF #define STAT_MACROS_BROKEN 1 EOF fi ac_header_dirent=no -for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h -do -ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6 -echo "configure:1240: checking for $ac_hdr that defines DIR" >&5 -if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +echo "$as_me:2953: checking for $ac_hdr that defines DIR" >&5 +echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 2959 "configure" #include "confdefs.h" #include #include <$ac_hdr> -int main() { -DIR *dirp = 0; -; return 0; } -EOF -if { (eval echo configure:1253: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* - eval "ac_cv_header_dirent_$ac_safe=yes" + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:2974: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:2977: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:2980: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:2983: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_header_dirent_$ac_safe=no" + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +eval "$as_ac_Header=no" fi -rm -f conftest* +rm -f conftest.$ac_objext conftest.$ac_ext fi -if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` - cat >> confdefs.h <&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <&6 + +ac_header_dirent=$ac_hdr; break fi + done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then -echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6 -echo "configure:1278: checking for opendir in -ldir" >&5 -ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 + echo "$as_me:3006: checking for opendir in -ldir" >&5 +echo $ECHO_N "checking for opendir in -ldir... $ECHO_C" >&6 +if test "${ac_cv_lib_dir_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - ac_save_LIBS="$LIBS" + ac_check_lib_save_LIBS=$LIBS LIBS="-ldir $LIBS" -cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 3014 "configure" #include "confdefs.h" + /* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif /* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char opendir(); - -int main() { -opendir() -; return 0; } -EOF -if { (eval echo configure:1297: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" + builtin and then its argument prototype would still apply. */ +char opendir (); +int +main () +{ +opendir (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:3033: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:3036: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:3039: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:3042: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dir_opendir=yes else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_lib_dir_opendir=no fi -rm -f conftest* -LIBS="$ac_save_LIBS" - +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 +echo "$as_me:3053: result: $ac_cv_lib_dir_opendir" >&5 +echo "${ECHO_T}$ac_cv_lib_dir_opendir" >&6 +if test $ac_cv_lib_dir_opendir = yes; then LIBS="$LIBS -ldir" -else - echo "$ac_t""no" 1>&6 fi else -echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6 -echo "configure:1319: checking for opendir in -lx" >&5 -ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 + echo "$as_me:3060: checking for opendir in -lx" >&5 +echo $ECHO_N "checking for opendir in -lx... $ECHO_C" >&6 +if test "${ac_cv_lib_x_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - ac_save_LIBS="$LIBS" + ac_check_lib_save_LIBS=$LIBS LIBS="-lx $LIBS" -cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 3068 "configure" #include "confdefs.h" + /* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif /* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char opendir(); - -int main() { -opendir() -; return 0; } -EOF -if { (eval echo configure:1338: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" + builtin and then its argument prototype would still apply. */ +char opendir (); +int +main () +{ +opendir (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:3087: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:3090: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:3093: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:3096: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_x_opendir=yes else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_lib_x_opendir=no fi -rm -f conftest* -LIBS="$ac_save_LIBS" - +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 +echo "$as_me:3107: result: $ac_cv_lib_x_opendir" >&5 +echo "${ECHO_T}$ac_cv_lib_x_opendir" >&6 +if test $ac_cv_lib_x_opendir = yes; then LIBS="$LIBS -lx" -else - echo "$ac_t""no" 1>&6 fi fi - -for ac_func in strcasecmp select setenv putenv tcgetattr setlocale lstat +for ac_func in lstat memmove putenv select setenv setlocale \ + strcasecmp strpbrk tcgetattr vsnprintf isascii isxdigit do -echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1364: checking for $ac_func" >&5 -if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:3119: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 3125 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func(); below. */ + which can conflict with char $ac_func (); below. */ #include /* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif /* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char $ac_func(); - -int main() { + builtin and then its argument prototype would still apply. */ +char $ac_func (); +char (*f) (); +int +main () +{ /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else -$ac_func(); +f = $ac_func; #endif -; return 0; } -EOF -if { (eval echo configure:1392: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - rm -rf conftest* - eval "ac_cv_func_$ac_func=yes" + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:3156: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:3159: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:3162: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:3165: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_func_$ac_func=no" + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +eval "$as_ac_var=no" fi -rm -f conftest* +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext fi +echo "$as_me:3175: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <&6 - ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` - cat >> confdefs.h <&6 fi done - -echo $ac_n "checking for working strcoll""... $ac_c" 1>&6 -echo "configure:1418: checking for working strcoll" >&5 -if eval "test \"`echo '$''{'ac_cv_func_strcoll_works'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +echo "$as_me:3185: checking for working strcoll" >&5 +echo $ECHO_N "checking for working strcoll... $ECHO_C" >&6 +if test "${ac_cv_func_strcoll_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then ac_cv_func_strcoll_works=no else - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 3194 "configure" #include "confdefs.h" -#include +$ac_includes_default +int main () { - exit (strcoll ("abc", "def") >= 0 || - strcoll ("ABC", "DEF") >= 0 || - strcoll ("123", "456") >= 0); +exit (strcoll ("abc", "def") >= 0 || + strcoll ("ABC", "DEF") >= 0 || + strcoll ("123", "456") >= 0) + ; + return 0; } -EOF -if { (eval echo configure:1436: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null -then +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:3208: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:3211: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:3213: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:3216: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then ac_cv_func_strcoll_works=yes else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - ac_cv_func_strcoll_works=no + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_func_strcoll_works=no fi -rm -fr conftest* +rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi - fi - -echo "$ac_t""$ac_cv_func_strcoll_works" 1>&6 +echo "$as_me:3228: result: $ac_cv_func_strcoll_works" >&5 +echo "${ECHO_T}$ac_cv_func_strcoll_works" >&6 if test $ac_cv_func_strcoll_works = yes; then - cat >> confdefs.h <<\EOF + +cat >>confdefs.h <<\EOF #define HAVE_STRCOLL 1 EOF fi - -for ac_hdr in unistd.h stdlib.h varargs.h stdarg.h string.h \ - sys/ptem.h sys/pte.h sys/stream.h sys/select.h \ - termcap.h termios.h termio.h sys/file.h locale.h +for ac_header in unistd.h stdlib.h varargs.h stdarg.h string.h strings.h \ + limits.h sys/ptem.h sys/pte.h sys/stream.h sys/select.h \ + termcap.h termios.h termio.h sys/file.h locale.h memory.h do -ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1465: checking for $ac_hdr" >&5 -if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:3243: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 3249 "configure" #include "confdefs.h" -#include <$ac_hdr> -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1475: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out` -if test -z "$ac_err"; then - rm -rf conftest* - eval "ac_cv_header_$ac_safe=yes" +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:3253: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:3259: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" + eval "$as_ac_Header=no" fi -rm -f conftest* +rm -f conftest.err conftest.$ac_ext fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` - cat >> confdefs.h <&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <&6 + fi done - - -echo $ac_n "checking for type of signal functions""... $ac_c" 1>&6 -echo "configure:1504: checking for type of signal functions" >&5 -if eval "test \"`echo '$''{'bash_cv_signal_vintage'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +echo "$as_me:3288: checking for type of signal functions" >&5 +echo $ECHO_N "checking for type of signal functions... $ECHO_C" >&6 +if test "${bash_cv_signal_vintage+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 3295 "configure" #include "confdefs.h" #include -int main() { +int +main () +{ sigset_t ss; struct sigaction sa; sigemptyset(&ss); sigsuspend(&ss); sigaction(SIGINT, &sa, (struct sigaction *) 0); sigprocmask(SIG_BLOCK, &ss, (sigset_t *) 0); - -; return 0; } -EOF -if { (eval echo configure:1523: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - rm -rf conftest* + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:3313: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:3316: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:3319: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:3322: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then bash_cv_signal_vintage=posix else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - - cat > conftest.$ac_ext <&5 +cat conftest.$ac_ext >&5 + + cat >conftest.$ac_ext <<_ACEOF +#line 3330 "configure" #include "confdefs.h" #include -int main() { +int +main () +{ int mask = sigmask(SIGINT); sigsetmask(mask); sigblock(mask); sigpause(mask); - -; return 0; } -EOF -if { (eval echo configure:1542: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - rm -rf conftest* + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:3345: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:3348: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:3351: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:3354: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then bash_cv_signal_vintage=4.2bsd else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - - cat > conftest.$ac_ext <&5 +cat conftest.$ac_ext >&5 + + cat >conftest.$ac_ext <<_ACEOF +#line 3362 "configure" #include "confdefs.h" #include RETSIGTYPE foo() { } -int main() { +int +main () +{ int mask = sigmask(SIGINT); sigset(SIGINT, foo); sigrelse(SIGINT); sighold(SIGINT); sigpause(SIGINT); - -; return 0; } -EOF -if { (eval echo configure:1564: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - rm -rf conftest* + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:3380: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:3383: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:3386: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:3389: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then bash_cv_signal_vintage=svr3 else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - bash_cv_signal_vintage=v7 - -fi -rm -f conftest* - -fi -rm -f conftest* + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +bash_cv_signal_vintage=v7 fi -rm -f conftest* +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext + +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext + +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext fi -echo "$ac_t""$bash_cv_signal_vintage" 1>&6 +echo "$as_me:3408: result: $bash_cv_signal_vintage" >&5 +echo "${ECHO_T}$bash_cv_signal_vintage" >&6 if test "$bash_cv_signal_vintage" = posix; then -cat >> confdefs.h <<\EOF +cat >>confdefs.h <<\EOF #define HAVE_POSIX_SIGNALS 1 EOF elif test "$bash_cv_signal_vintage" = "4.2bsd"; then -cat >> confdefs.h <<\EOF +cat >>confdefs.h <<\EOF #define HAVE_BSD_SIGNALS 1 EOF elif test "$bash_cv_signal_vintage" = svr3; then -cat >> confdefs.h <<\EOF +cat >>confdefs.h <<\EOF #define HAVE_USG_SIGHOLD 1 EOF fi - - -echo $ac_n "checking if signal handlers must be reinstalled when invoked""... $ac_c" 1>&6 -echo "configure:1605: checking if signal handlers must be reinstalled when invoked" >&5 -if eval "test \"`echo '$''{'bash_cv_must_reinstall_sighandlers'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +echo "$as_me:3427: checking if signal handlers must be reinstalled when invoked" >&5 +echo $ECHO_N "checking if signal handlers must be reinstalled when invoked... $ECHO_C" >&6 +if test "${bash_cv_must_reinstall_sighandlers+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then - echo "configure: warning: cannot check signal handling if cross compiling -- defaulting to no" 1>&2 + { echo "$as_me:3433: WARNING: cannot check signal handling if cross compiling -- defaulting to no" >&5 +echo "$as_me: WARNING: cannot check signal handling if cross compiling -- defaulting to no" >&2;} bash_cv_must_reinstall_sighandlers=no else - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 3439 "configure" #include "confdefs.h" #include @@ -1657,43 +3482,51 @@ main() exit(nsigint != 2); } -EOF -if { (eval echo configure:1662: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null -then +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:3487: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:3490: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:3492: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:3495: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then bash_cv_must_reinstall_sighandlers=no else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - bash_cv_must_reinstall_sighandlers=yes + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +bash_cv_must_reinstall_sighandlers=yes +fi +rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi -rm -fr conftest* fi -fi - -echo "$ac_t""$bash_cv_must_reinstall_sighandlers" 1>&6 +echo "$as_me:3508: result: $bash_cv_must_reinstall_sighandlers" >&5 +echo "${ECHO_T}$bash_cv_must_reinstall_sighandlers" >&6 if test $bash_cv_must_reinstall_sighandlers = yes; then -cat >> confdefs.h <<\EOF +cat >>confdefs.h <<\EOF #define MUST_REINSTALL_SIGHANDLERS 1 EOF fi - - -echo $ac_n "checking for presence of POSIX-style sigsetjmp/siglongjmp""... $ac_c" 1>&6 -echo "configure:1687: checking for presence of POSIX-style sigsetjmp/siglongjmp" >&5 -if eval "test \"`echo '$''{'bash_cv_func_sigsetjmp'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +echo "$as_me:3517: checking for presence of POSIX-style sigsetjmp/siglongjmp" >&5 +echo $ECHO_N "checking for presence of POSIX-style sigsetjmp/siglongjmp... $ECHO_C" >&6 +if test "${bash_cv_func_sigsetjmp+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then - echo "configure: warning: cannot check for sigsetjmp/siglongjmp if cross-compiling -- defaulting to missing" 1>&2 + { echo "$as_me:3523: WARNING: cannot check for sigsetjmp/siglongjmp if cross-compiling -- defaulting to missing" >&5 +echo "$as_me: WARNING: cannot check for sigsetjmp/siglongjmp if cross-compiling -- defaulting to missing" >&2;} bash_cv_func_sigsetjmp=missing else - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 3529 "configure" #include "confdefs.h" #ifdef HAVE_UNISTD_H @@ -1733,115 +3566,100 @@ siglongjmp(xx, 10); exit(1); #endif } -EOF -if { (eval echo configure:1738: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null -then +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:3571: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:3574: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:3576: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:3579: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then bash_cv_func_sigsetjmp=present else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - bash_cv_func_sigsetjmp=missing + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +bash_cv_func_sigsetjmp=missing +fi +rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi -rm -fr conftest* fi -fi - -echo "$ac_t""$bash_cv_func_sigsetjmp" 1>&6 +echo "$as_me:3592: result: $bash_cv_func_sigsetjmp" >&5 +echo "${ECHO_T}$bash_cv_func_sigsetjmp" >&6 if test $bash_cv_func_sigsetjmp = present; then -cat >> confdefs.h <<\EOF +cat >>confdefs.h <<\EOF #define HAVE_POSIX_SIGSETJMP 1 EOF fi -echo $ac_n "checking for lstat""... $ac_c" 1>&6 -echo "configure:1761: checking for lstat" >&5 -if eval "test \"`echo '$''{'bash_cv_func_lstat'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +echo "$as_me:3601: checking for lstat" >&5 +echo $ECHO_N "checking for lstat... $ECHO_C" >&6 +if test "${bash_cv_func_lstat+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 3607 "configure" #include "confdefs.h" #include #include -int main() { - lstat(".",(struct stat *)0); -; return 0; } -EOF -if { (eval echo configure:1776: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - rm -rf conftest* +int +main () +{ + lstat(".",(struct stat *)0); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:3622: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:3625: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:3628: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:3631: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then bash_cv_func_lstat=yes else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - bash_cv_func_lstat=no + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +bash_cv_func_lstat=no fi -rm -f conftest* +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext fi - -echo "$ac_t""$bash_cv_func_lstat" 1>&6 +echo "$as_me:3641: result: $bash_cv_func_lstat" >&5 +echo "${ECHO_T}$bash_cv_func_lstat" >&6 if test $bash_cv_func_lstat = yes; then - cat >> confdefs.h <<\EOF + cat >>confdefs.h <<\EOF #define HAVE_LSTAT 1 EOF fi -echo $ac_n "checking whether programs are able to redeclare getpw functions""... $ac_c" 1>&6 -echo "configure:1797: checking whether programs are able to redeclare getpw functions" >&5 -if eval "test \"`echo '$''{'bash_cv_can_redecl_getpw'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -#include -extern struct passwd *getpwent(); -extern struct passwd *getpwuid(); -extern struct passwd *getpwnam(); -int main() { -struct passwd *z; z = getpwent(); z = getpwuid(0); z = getpwnam("root"); -; return 0; } -EOF -if { (eval echo configure:1813: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* - bash_cv_can_redecl_getpw=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - bash_cv_can_redecl_getpw=no -fi -rm -f conftest* -fi - -echo "$ac_t""$bash_cv_can_redecl_getpw" 1>&6 -if test $bash_cv_can_redecl_getpw = no; then -cat >> confdefs.h <<\EOF -#define HAVE_GETPW_DECLS 1 -EOF - -fi - - -echo $ac_n "checking whether or not strcoll and strcmp differ""... $ac_c" 1>&6 -echo "configure:1835: checking whether or not strcoll and strcmp differ" >&5 -if eval "test \"`echo '$''{'bash_cv_func_strcoll_broken'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +echo "$as_me:3650: checking whether or not strcoll and strcmp differ" >&5 +echo $ECHO_N "checking whether or not strcoll and strcmp differ... $ECHO_C" >&6 +if test "${bash_cv_func_strcoll_broken+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then - echo "configure: warning: cannot check strcoll if cross compiling -- defaulting to no" 1>&2 + { echo "$as_me:3656: WARNING: cannot check strcoll if cross compiling -- defaulting to no" >&5 +echo "$as_me: WARNING: cannot check strcoll if cross compiling -- defaulting to no" >&2;} bash_cv_func_strcoll_broken=no else - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 3662 "configure" #include "confdefs.h" #include @@ -1879,37 +3697,189 @@ char *v[]; exit (r1 > 0 && r2 > 0); } -EOF -if { (eval echo configure:1884: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null -then +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:3702: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:3705: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:3707: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:3710: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then bash_cv_func_strcoll_broken=yes else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - bash_cv_func_strcoll_broken=no + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +bash_cv_func_strcoll_broken=no +fi +rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi -rm -fr conftest* fi -fi - -echo "$ac_t""$bash_cv_func_strcoll_broken" 1>&6 +echo "$as_me:3723: result: $bash_cv_func_strcoll_broken" >&5 +echo "${ECHO_T}$bash_cv_func_strcoll_broken" >&6 if test $bash_cv_func_strcoll_broken = yes; then -cat >> confdefs.h <<\EOF +cat >>confdefs.h <<\EOF #define STRCOLL_BROKEN 1 EOF fi - -echo $ac_n "checking whether signal handlers are of type void""... $ac_c" 1>&6 -echo "configure:1908: checking whether signal handlers are of type void" >&5 -if eval "test \"`echo '$''{'bash_cv_void_sighandler'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +echo "$as_me:3732: checking whether getpw functions are declared in pwd.h" >&5 +echo $ECHO_N "checking whether getpw functions are declared in pwd.h... $ECHO_C" >&6 +if test "${bash_cv_getpw_declared+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 3738 "configure" +#include "confdefs.h" + +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "getpwuid" >/dev/null 2>&1; then + bash_cv_getpw_declared=yes +else + bash_cv_getpw_declared=no +fi +rm -f conftest* + +fi + +echo "$as_me:3758: result: $bash_cv_getpw_declared" >&5 +echo "${ECHO_T}$bash_cv_getpw_declared" >&6 +if test $bash_cv_getpw_declared = yes; then +cat >>confdefs.h <<\EOF +#define HAVE_GETPW_DECLS 1 +EOF + +fi + +echo "$as_me:3767: checking POSIX termios" >&5 +echo $ECHO_N "checking POSIX termios... $ECHO_C" >&6 +if test "${ac_cv_sys_posix_termios+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 3773 "configure" +#include "confdefs.h" +#include +#include +#include +int +main () +{ +/* SunOS 4.0.3 has termios.h but not the library calls. */ + tcgetattr(0, 0); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:3788: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:3791: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:3794: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:3797: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sys_posix_termios=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_sys_posix_termios=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:3807: result: $ac_cv_sys_posix_termios" >&5 +echo "${ECHO_T}$ac_cv_sys_posix_termios" >&6 + +if test $ac_cv_sys_posix_termios = yes; then + echo "$as_me:3811: checking whether termios.h defines TIOCGWINSZ" >&5 +echo $ECHO_N "checking whether termios.h defines TIOCGWINSZ... $ECHO_C" >&6 +if test "${ac_cv_sys_tiocgwinsz_in_termios_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 3817 "configure" +#include "confdefs.h" +#include +#include +#ifdef TIOCGWINSZ + yes +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "yes" >/dev/null 2>&1; then + ac_cv_sys_tiocgwinsz_in_termios_h=yes +else + ac_cv_sys_tiocgwinsz_in_termios_h=no +fi +rm -f conftest* + +fi +echo "$as_me:3835: result: $ac_cv_sys_tiocgwinsz_in_termios_h" >&5 +echo "${ECHO_T}$ac_cv_sys_tiocgwinsz_in_termios_h" >&6 + +fi +if test $ac_cv_sys_tiocgwinsz_in_termios_h != yes; then + echo "$as_me:3840: checking whether sys/ioctl.h defines TIOCGWINSZ" >&5 +echo $ECHO_N "checking whether sys/ioctl.h defines TIOCGWINSZ... $ECHO_C" >&6 +if test "${ac_cv_sys_tiocgwinsz_in_sys_ioctl_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 3846 "configure" +#include "confdefs.h" +#include +#include +#ifdef TIOCGWINSZ + yes +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "yes" >/dev/null 2>&1; then + ac_cv_sys_tiocgwinsz_in_sys_ioctl_h=yes +else + ac_cv_sys_tiocgwinsz_in_sys_ioctl_h=no +fi +rm -f conftest* + +fi +echo "$as_me:3864: result: $ac_cv_sys_tiocgwinsz_in_sys_ioctl_h" >&5 +echo "${ECHO_T}$ac_cv_sys_tiocgwinsz_in_sys_ioctl_h" >&6 + + if test $ac_cv_sys_tiocgwinsz_in_sys_ioctl_h = yes; then + +cat >>confdefs.h <<\EOF +#define GWINSZ_IN_SYS_IOCTL 1 +EOF + + fi +fi + +echo "$as_me:3876: checking whether signal handlers are of type void" >&5 +echo $ECHO_N "checking whether signal handlers are of type void... $ECHO_C" >&6 +if test "${bash_cv_void_sighandler+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 3882 "configure" #include "confdefs.h" #include #include @@ -1920,233 +3890,283 @@ else extern "C" #endif void (*signal ()) (); -int main() { +int +main () +{ int i; -; return 0; } -EOF -if { (eval echo configure:1928: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:3902: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:3905: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:3908: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:3911: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then bash_cv_void_sighandler=yes else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - bash_cv_void_sighandler=no + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +bash_cv_void_sighandler=no fi -rm -f conftest* +rm -f conftest.$ac_objext conftest.$ac_ext fi -echo "$ac_t""$bash_cv_void_sighandler" 1>&6 +echo "$as_me:3921: result: $bash_cv_void_sighandler" >&5 +echo "${ECHO_T}$bash_cv_void_sighandler" >&6 if test $bash_cv_void_sighandler = yes; then -cat >> confdefs.h <<\EOF +cat >>confdefs.h <<\EOF #define VOID_SIGHANDLER 1 EOF fi -echo $ac_n "checking for TIOCGWINSZ in sys/ioctl.h""... $ac_c" 1>&6 -echo "configure:1948: checking for TIOCGWINSZ in sys/ioctl.h" >&5 -if eval "test \"`echo '$''{'bash_cv_tiocgwinsz_in_ioctl'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +echo "$as_me:3930: checking for TIOCSTAT in sys/ioctl.h" >&5 +echo $ECHO_N "checking for TIOCSTAT in sys/ioctl.h... $ECHO_C" >&6 +if test "${bash_cv_tiocstat_in_ioctl+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 3936 "configure" #include "confdefs.h" #include #include -int main() { -int x = TIOCGWINSZ; -; return 0; } -EOF -if { (eval echo configure:1961: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* - bash_cv_tiocgwinsz_in_ioctl=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - bash_cv_tiocgwinsz_in_ioctl=no -fi -rm -f conftest* -fi - -echo "$ac_t""$bash_cv_tiocgwinsz_in_ioctl" 1>&6 -if test $bash_cv_tiocgwinsz_in_ioctl = yes; then -cat >> confdefs.h <<\EOF -#define GWINSZ_IN_SYS_IOCTL 1 -EOF - -fi - -echo $ac_n "checking for TIOCSTAT in sys/ioctl.h""... $ac_c" 1>&6 -echo "configure:1982: checking for TIOCSTAT in sys/ioctl.h" >&5 -if eval "test \"`echo '$''{'bash_cv_tiocstat_in_ioctl'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -#include -int main() { +int +main () +{ int x = TIOCSTAT; -; return 0; } -EOF -if { (eval echo configure:1995: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:3949: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:3952: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:3955: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:3958: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then bash_cv_tiocstat_in_ioctl=yes else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - bash_cv_tiocstat_in_ioctl=no + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +bash_cv_tiocstat_in_ioctl=no fi -rm -f conftest* +rm -f conftest.$ac_objext conftest.$ac_ext fi -echo "$ac_t""$bash_cv_tiocstat_in_ioctl" 1>&6 -if test $bash_cv_tiocstat_in_ioctl = yes; then -cat >> confdefs.h <<\EOF +echo "$as_me:3969: result: $bash_cv_tiocstat_in_ioctl" >&5 +echo "${ECHO_T}$bash_cv_tiocstat_in_ioctl" >&6 +if test $bash_cv_tiocstat_in_ioctl = yes; then +cat >>confdefs.h <<\EOF #define TIOCSTAT_IN_SYS_IOCTL 1 EOF fi -echo $ac_n "checking for FIONREAD in sys/ioctl.h""... $ac_c" 1>&6 -echo "configure:2016: checking for FIONREAD in sys/ioctl.h" >&5 -if eval "test \"`echo '$''{'bash_cv_fionread_in_ioctl'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +echo "$as_me:3978: checking for FIONREAD in sys/ioctl.h" >&5 +echo $ECHO_N "checking for FIONREAD in sys/ioctl.h... $ECHO_C" >&6 +if test "${bash_cv_fionread_in_ioctl+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 3984 "configure" #include "confdefs.h" #include #include -int main() { +int +main () +{ int x = FIONREAD; -; return 0; } -EOF -if { (eval echo configure:2029: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:3997: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:4000: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:4003: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:4006: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then bash_cv_fionread_in_ioctl=yes else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - bash_cv_fionread_in_ioctl=no + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +bash_cv_fionread_in_ioctl=no fi -rm -f conftest* +rm -f conftest.$ac_objext conftest.$ac_ext fi -echo "$ac_t""$bash_cv_fionread_in_ioctl" 1>&6 -if test $bash_cv_fionread_in_ioctl = yes; then -cat >> confdefs.h <<\EOF +echo "$as_me:4017: result: $bash_cv_fionread_in_ioctl" >&5 +echo "${ECHO_T}$bash_cv_fionread_in_ioctl" >&6 +if test $bash_cv_fionread_in_ioctl = yes; then +cat >>confdefs.h <<\EOF #define FIONREAD_IN_SYS_IOCTL 1 EOF fi -echo $ac_n "checking for speed_t in sys/types.h""... $ac_c" 1>&6 -echo "configure:2050: checking for speed_t in sys/types.h" >&5 -if eval "test \"`echo '$''{'bash_cv_speed_t_in_sys_types'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +echo "$as_me:4026: checking for speed_t in sys/types.h" >&5 +echo $ECHO_N "checking for speed_t in sys/types.h... $ECHO_C" >&6 +if test "${bash_cv_speed_t_in_sys_types+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 4032 "configure" #include "confdefs.h" #include -int main() { +int +main () +{ speed_t x; -; return 0; } -EOF -if { (eval echo configure:2062: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:4044: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:4047: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:4050: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:4053: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then bash_cv_speed_t_in_sys_types=yes else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - bash_cv_speed_t_in_sys_types=no + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +bash_cv_speed_t_in_sys_types=no fi -rm -f conftest* +rm -f conftest.$ac_objext conftest.$ac_ext fi -echo "$ac_t""$bash_cv_speed_t_in_sys_types" 1>&6 -if test $bash_cv_speed_t_in_sys_types = yes; then -cat >> confdefs.h <<\EOF +echo "$as_me:4064: result: $bash_cv_speed_t_in_sys_types" >&5 +echo "${ECHO_T}$bash_cv_speed_t_in_sys_types" >&6 +if test $bash_cv_speed_t_in_sys_types = yes; then +cat >>confdefs.h <<\EOF #define SPEED_T_IN_SYS_TYPES 1 EOF fi -echo $ac_n "checking for struct winsize in sys/ioctl.h and termios.h""... $ac_c" 1>&6 -echo "configure:2083: checking for struct winsize in sys/ioctl.h and termios.h" >&5 -if eval "test \"`echo '$''{'bash_cv_struct_winsize_header'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +echo "$as_me:4073: checking for struct winsize in sys/ioctl.h and termios.h" >&5 +echo $ECHO_N "checking for struct winsize in sys/ioctl.h and termios.h... $ECHO_C" >&6 +if test "${bash_cv_struct_winsize_header+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 4079 "configure" #include "confdefs.h" #include #include -int main() { +int +main () +{ struct winsize x; -; return 0; } -EOF -if { (eval echo configure:2096: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:4092: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:4095: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:4098: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:4101: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then bash_cv_struct_winsize_header=ioctl_h else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - cat > conftest.$ac_ext <&5 +cat conftest.$ac_ext >&5 +cat >conftest.$ac_ext <<_ACEOF +#line 4108 "configure" #include "confdefs.h" #include #include -int main() { +int +main () +{ struct winsize x; -; return 0; } -EOF -if { (eval echo configure:2112: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:4121: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:4124: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:4127: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:4130: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then bash_cv_struct_winsize_header=termios_h else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - bash_cv_struct_winsize_header=other + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +bash_cv_struct_winsize_header=other fi -rm -f conftest* +rm -f conftest.$ac_objext conftest.$ac_ext fi -rm -f conftest* +rm -f conftest.$ac_objext conftest.$ac_ext fi if test $bash_cv_struct_winsize_header = ioctl_h; then - echo "$ac_t""sys/ioctl.h" 1>&6 - cat >> confdefs.h <<\EOF + echo "$as_me:4145: result: sys/ioctl.h" >&5 +echo "${ECHO_T}sys/ioctl.h" >&6 + cat >>confdefs.h <<\EOF #define STRUCT_WINSIZE_IN_SYS_IOCTL 1 EOF elif test $bash_cv_struct_winsize_header = termios_h; then - echo "$ac_t""termios.h" 1>&6 - cat >> confdefs.h <<\EOF + echo "$as_me:4152: result: termios.h" >&5 +echo "${ECHO_T}termios.h" >&6 + cat >>confdefs.h <<\EOF #define STRUCT_WINSIZE_IN_TERMIOS 1 EOF else - echo "$ac_t""not found" 1>&6 + echo "$as_me:4159: result: not found" >&5 +echo "${ECHO_T}not found" >&6 fi - -echo $ac_n "checking if struct dirent has a d_ino member""... $ac_c" 1>&6 -echo "configure:2145: checking if struct dirent has a d_ino member" >&5 -if eval "test \"`echo '$''{'bash_cv_dirent_has_dino'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +echo "$as_me:4163: checking if struct dirent has a d_ino member" >&5 +echo $ECHO_N "checking if struct dirent has a d_ino member... $ECHO_C" >&6 +if test "${bash_cv_dirent_has_dino+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 4169 "configure" #include "confdefs.h" #include @@ -2169,40 +4189,53 @@ else # endif #endif /* HAVE_DIRENT_H */ -int main() { +int +main () +{ struct dirent d; int z; z = d.d_ino; -; return 0; } -EOF -if { (eval echo configure:2179: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:4203: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:4206: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:4209: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:4212: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then bash_cv_dirent_has_dino=yes else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - bash_cv_dirent_has_dino=no + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +bash_cv_dirent_has_dino=no fi -rm -f conftest* +rm -f conftest.$ac_objext conftest.$ac_ext fi -echo "$ac_t""$bash_cv_dirent_has_dino" 1>&6 +echo "$as_me:4223: result: $bash_cv_dirent_has_dino" >&5 +echo "${ECHO_T}$bash_cv_dirent_has_dino" >&6 if test $bash_cv_dirent_has_dino = yes; then -cat >> confdefs.h <<\EOF +cat >>confdefs.h <<\EOF #define STRUCT_DIRENT_HAS_D_INO 1 EOF fi - -echo $ac_n "checking if struct dirent has a d_fileno member""... $ac_c" 1>&6 -echo "configure:2201: checking if struct dirent has a d_fileno member" >&5 -if eval "test \"`echo '$''{'bash_cv_dirent_has_d_fileno'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +echo "$as_me:4232: checking if struct dirent has a d_fileno member" >&5 +echo $ECHO_N "checking if struct dirent has a d_fileno member... $ECHO_C" >&6 +if test "${bash_cv_dirent_has_d_fileno+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 4238 "configure" #include "confdefs.h" #include @@ -2225,33 +4258,46 @@ else # endif #endif /* HAVE_DIRENT_H */ -int main() { +int +main () +{ struct dirent d; int z; z = d.d_fileno; -; return 0; } -EOF -if { (eval echo configure:2235: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then - rm -rf conftest* + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:4272: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:4275: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:4278: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:4281: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then bash_cv_dirent_has_d_fileno=yes else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - bash_cv_dirent_has_d_fileno=no + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +bash_cv_dirent_has_d_fileno=no fi -rm -f conftest* +rm -f conftest.$ac_objext conftest.$ac_ext fi -echo "$ac_t""$bash_cv_dirent_has_d_fileno" 1>&6 +echo "$as_me:4292: result: $bash_cv_dirent_has_d_fileno" >&5 +echo "${ECHO_T}$bash_cv_dirent_has_d_fileno" >&6 if test $bash_cv_dirent_has_d_fileno = yes; then -cat >> confdefs.h <<\EOF +cat >>confdefs.h <<\EOF #define STRUCT_DIRENT_HAS_D_FILENO 1 EOF fi - case "$host_os" in aix*) prefer_curses=yes ;; esac @@ -2259,128 +4305,224 @@ esac if test "X$bash_cv_termcap_lib" = "X"; then _bash_needmsg=yes else -echo $ac_n "checking which library has the termcap functions""... $ac_c" 1>&6 -echo "configure:2264: checking which library has the termcap functions" >&5 +echo "$as_me:4308: checking which library has the termcap functions" >&5 +echo $ECHO_N "checking which library has the termcap functions... $ECHO_C" >&6 _bash_needmsg= fi -if eval "test \"`echo '$''{'bash_cv_termcap_lib'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 +if test "${bash_cv_termcap_lib+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - echo $ac_n "checking for tgetent in -ltermcap""... $ac_c" 1>&6 -echo "configure:2271: checking for tgetent in -ltermcap" >&5 -ac_lib_var=`echo termcap'_'tgetent | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 + echo "$as_me:4315: checking for tgetent in -ltermcap" >&5 +echo $ECHO_N "checking for tgetent in -ltermcap... $ECHO_C" >&6 +if test "${ac_cv_lib_termcap_tgetent+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - ac_save_LIBS="$LIBS" + ac_check_lib_save_LIBS=$LIBS LIBS="-ltermcap $LIBS" -cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 4323 "configure" #include "confdefs.h" + /* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif /* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char tgetent(); - -int main() { -tgetent() -; return 0; } -EOF -if { (eval echo configure:2290: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" + builtin and then its argument prototype would still apply. */ +char tgetent (); +int +main () +{ +tgetent (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:4342: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:4345: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:4348: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:4351: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_termcap_tgetent=yes else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_lib_termcap_tgetent=no fi -rm -f conftest* -LIBS="$ac_save_LIBS" - +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 +echo "$as_me:4362: result: $ac_cv_lib_termcap_tgetent" >&5 +echo "${ECHO_T}$ac_cv_lib_termcap_tgetent" >&6 +if test $ac_cv_lib_termcap_tgetent = yes; then bash_cv_termcap_lib=libtermcap else - echo "$ac_t""no" 1>&6 -echo $ac_n "checking for tgetent in -lcurses""... $ac_c" 1>&6 -echo "configure:2309: checking for tgetent in -lcurses" >&5 -ac_lib_var=`echo curses'_'tgetent | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 + echo "$as_me:4367: checking for tgetent in -ltinfo" >&5 +echo $ECHO_N "checking for tgetent in -ltinfo... $ECHO_C" >&6 +if test "${ac_cv_lib_tinfo_tgetent+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - ac_save_LIBS="$LIBS" -LIBS="-lcurses $LIBS" -cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 4375 "configure" #include "confdefs.h" + /* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif /* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char tgetent(); - -int main() { -tgetent() -; return 0; } -EOF -if { (eval echo configure:2328: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" + builtin and then its argument prototype would still apply. */ +char tgetent (); +int +main () +{ +tgetent (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:4394: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:4397: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:4400: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:4403: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_tinfo_tgetent=yes else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_lib_tinfo_tgetent=no fi -rm -f conftest* -LIBS="$ac_save_LIBS" +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:4414: result: $ac_cv_lib_tinfo_tgetent" >&5 +echo "${ECHO_T}$ac_cv_lib_tinfo_tgetent" >&6 +if test $ac_cv_lib_tinfo_tgetent = yes; then + bash_cv_termcap_lib=libtinfo +else + echo "$as_me:4419: checking for tgetent in -lcurses" >&5 +echo $ECHO_N "checking for tgetent in -lcurses... $ECHO_C" >&6 +if test "${ac_cv_lib_curses_tgetent+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcurses $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line 4427 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char tgetent (); +int +main () +{ +tgetent (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:4446: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:4449: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:4452: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:4455: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_curses_tgetent=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_lib_curses_tgetent=no fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:4466: result: $ac_cv_lib_curses_tgetent" >&5 +echo "${ECHO_T}$ac_cv_lib_curses_tgetent" >&6 +if test $ac_cv_lib_curses_tgetent = yes; then bash_cv_termcap_lib=libcurses else - echo "$ac_t""no" 1>&6 -echo $ac_n "checking for tgetent in -lncurses""... $ac_c" 1>&6 -echo "configure:2347: checking for tgetent in -lncurses" >&5 -ac_lib_var=`echo ncurses'_'tgetent | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 + echo "$as_me:4471: checking for tgetent in -lncurses" >&5 +echo $ECHO_N "checking for tgetent in -lncurses... $ECHO_C" >&6 +if test "${ac_cv_lib_ncurses_tgetent+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 else - ac_save_LIBS="$LIBS" + ac_check_lib_save_LIBS=$LIBS LIBS="-lncurses $LIBS" -cat > conftest.$ac_ext <conftest.$ac_ext <<_ACEOF +#line 4479 "configure" #include "confdefs.h" + /* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif /* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char tgetent(); - -int main() { -tgetent() -; return 0; } -EOF -if { (eval echo configure:2366: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" + builtin and then its argument prototype would still apply. */ +char tgetent (); +int +main () +{ +tgetent (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:4498: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:4501: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:4504: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:4507: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_ncurses_tgetent=yes else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_lib_ncurses_tgetent=no fi -rm -f conftest* -LIBS="$ac_save_LIBS" - +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 +echo "$as_me:4518: result: $ac_cv_lib_ncurses_tgetent" >&5 +echo "${ECHO_T}$ac_cv_lib_ncurses_tgetent" >&6 +if test $ac_cv_lib_ncurses_tgetent = yes; then bash_cv_termcap_lib=libncurses else - echo "$ac_t""no" 1>&6 -bash_cv_termcap_lib=gnutermcap + bash_cv_termcap_lib=gnutermcap +fi + fi fi @@ -2390,10 +4532,11 @@ fi fi if test "X$_bash_needmsg" = "Xyes"; then -echo $ac_n "checking which library has the termcap functions""... $ac_c" 1>&6 -echo "configure:2395: checking which library has the termcap functions" >&5 +echo "$as_me:4535: checking which library has the termcap functions" >&5 +echo $ECHO_N "checking which library has the termcap functions... $ECHO_C" >&6 fi -echo "$ac_t""using $bash_cv_termcap_lib" 1>&6 +echo "$as_me:4538: result: using $bash_cv_termcap_lib" >&5 +echo "${ECHO_T}using $bash_cv_termcap_lib" >&6 if test $bash_cv_termcap_lib = gnutermcap && test -z "$prefer_curses"; then LDFLAGS="$LDFLAGS -L./lib/termcap" TERMCAP_LIB="./lib/termcap/libtermcap.a" @@ -2401,6 +4544,9 @@ TERMCAP_DEP="./lib/termcap/libtermcap.a" elif test $bash_cv_termcap_lib = libtermcap && test -z "$prefer_curses"; then TERMCAP_LIB=-ltermcap TERMCAP_DEP= +elif test $bash_cv_termcap_lib = libtinfo; then +TERMCAP_LIB=-ltinfo +TERMCAP_DEP= elif test $bash_cv_termcap_lib = libncurses; then TERMCAP_LIB=-lncurses TERMCAP_DEP= @@ -2410,11 +4556,388 @@ TERMCAP_DEP= fi if test "$TERMCAP_LIB" = "./lib/termcap/libtermcap.a"; then - TERMCAP_LIB=-ltermcap #default + if test "$prefer_curses" = yes; then + TERMCAP_LIB=-lcurses + else + TERMCAP_LIB=-ltermcap #default + fi +fi + +for ac_header in wctype.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:4569: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 4575 "configure" +#include "confdefs.h" +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:4579: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:4585: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_ext +fi +echo "$as_me:4604: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 4623 "configure" +#include "confdefs.h" +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:4627: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:4633: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_ext +fi +echo "$as_me:4652: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 4671 "configure" +#include "confdefs.h" +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:4675: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:4681: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_ext +fi +echo "$as_me:4700: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <&5 +echo $ECHO_N "checking for mbsrtowcs... $ECHO_C" >&6 +if test "${ac_cv_func_mbsrtowcs+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 4716 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char mbsrtowcs (); below. */ +#include +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char mbsrtowcs (); +char (*f) (); + +int +main () +{ +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_mbsrtowcs) || defined (__stub___mbsrtowcs) +choke me +#else +f = mbsrtowcs; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:4747: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:4750: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:4753: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:4756: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_mbsrtowcs=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_func_mbsrtowcs=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:4766: result: $ac_cv_func_mbsrtowcs" >&5 +echo "${ECHO_T}$ac_cv_func_mbsrtowcs" >&6 +if test $ac_cv_func_mbsrtowcs = yes; then + cat >>confdefs.h <<\EOF +#define HAVE_MBSRTOWCS 1 +EOF + +fi + +echo "$as_me:4775: checking for wcwidth" >&5 +echo $ECHO_N "checking for wcwidth... $ECHO_C" >&6 +if test "${ac_cv_func_wcwidth+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 4781 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char wcwidth (); below. */ +#include +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char wcwidth (); +char (*f) (); + +int +main () +{ +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_wcwidth) || defined (__stub___wcwidth) +choke me +#else +f = wcwidth; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:4812: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:4815: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:4818: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:4821: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_wcwidth=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_func_wcwidth=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:4831: result: $ac_cv_func_wcwidth" >&5 +echo "${ECHO_T}$ac_cv_func_wcwidth" >&6 +if test $ac_cv_func_wcwidth = yes; then + cat >>confdefs.h <<\EOF +#define HAVE_WCWIDTH 1 +EOF + +fi + +echo "$as_me:4840: checking for mbstate_t" >&5 +echo $ECHO_N "checking for mbstate_t... $ECHO_C" >&6 +if test "${bash_cv_have_mbstate_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:4846: error: cannot run test program while cross compiling" >&5 +echo "$as_me: error: cannot run test program while cross compiling" >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +#line 4851 "configure" +#include "confdefs.h" + +#include +int +main () +{ + mbstate_t ps; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:4863: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:4866: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:4868: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:4871: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + bash_cv_have_mbstate_t=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +bash_cv_have_mbstate_t=no +fi +rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +echo "$as_me:4883: result: $bash_cv_have_mbstate_t" >&5 +echo "${ECHO_T}$bash_cv_have_mbstate_t" >&6 +if test $bash_cv_have_mbstate_t = yes; then + cat >>confdefs.h <<\EOF +#define HAVE_MBSTATE_T 1 +EOF + +fi + +echo "$as_me:4892: checking for nl_langinfo and CODESET" >&5 +echo $ECHO_N "checking for nl_langinfo and CODESET... $ECHO_C" >&6 +if test "${bash_cv_langinfo_codeset+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line 4898 "configure" +#include "confdefs.h" +#include +int +main () +{ +char* cs = nl_langinfo(CODESET); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:4910: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:4913: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:4916: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:4919: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + bash_cv_langinfo_codeset=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +bash_cv_langinfo_codeset=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:4929: result: $bash_cv_langinfo_codeset" >&5 +echo "${ECHO_T}$bash_cv_langinfo_codeset" >&6 +if test $bash_cv_langinfo_codeset = yes; then + cat >>confdefs.h <<\EOF +#define HAVE_LANGINFO_CODESET 1 +EOF + fi case "$host_cpu" in *cray*) LOCAL_CFLAGS=-DCRAY ;; +*s390*) LOCAL_CFLAGS=-fsigned-char ;; esac case "$host_os" in @@ -2427,423 +4950,916 @@ esac # ${srcdir}/support/shobj-conf # if test -f ${srcdir}/support/shobj-conf; then - echo $ac_n "checking configuration for building shared libraries""... $ac_c" 1>&6 -echo "configure:2432: checking configuration for building shared libraries" >&5 - eval `${CONFIG_SHELL-/bin/sh} ${srcdir}/support/shobj-conf -C ${CC} -c ${host_cpu} -o ${host_os} -v ${host_vendor}` - - - - - - - - - - - - - echo "$ac_t""$SHLIB_STATUS" 1>&6 + echo "$as_me:4953: checking configuration for building shared libraries" >&5 +echo $ECHO_N "checking configuration for building shared libraries... $ECHO_C" >&6 + eval `${CONFIG_SHELL-/bin/sh} ${srcdir}/support/shobj-conf -C "${CC}" -c ${host_cpu} -o ${host_os} -v ${host_vendor}` + + echo "$as_me:4957: result: $SHLIB_STATUS" >&5 +echo "${ECHO_T}$SHLIB_STATUS" >&6 + + # SHLIB_STATUS is either `supported' or `unsupported'. If it's + # `unsupported', turn off any default shared library building + if test "$SHLIB_STATUS" = 'unsupported'; then + opt_shared_libs=no + fi + + # shared library versioning + # quoted for m4 so I can use character classes + SHLIB_MAJOR=`expr "$LIBVERSION" : '\([0-9]\)\..*'` + SHLIB_MINOR=`expr "$LIBVERSION" : '[0-9]\.\([0-9]\).*'` + fi -BUILD_DIR=`pwd` +if test "$opt_static_libs" = "yes"; then + STATIC_TARGET=static + STATIC_INSTALL_TARGET=install-static +fi +if test "$opt_shared_libs" = "yes"; then + SHARED_TARGET=shared + SHARED_INSTALL_TARGET=install-shared +fi +case "$host_os" in +msdosdjgpp*) BUILD_DIR=`pwd.exe` ;; # to prevent //d/path/file +*) BUILD_DIR=`pwd` ;; +esac - - - - - - - - - - - - - - - -trap '' 1 2 15 -cat > confcache <<\EOF +ac_config_files="$ac_config_files Makefile doc/Makefile examples/Makefile shlib/Makefile" +ac_config_commands="$ac_config_commands default" +cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure -# scripts and configure runs. It is not useful on other systems. -# If it contains results you don't want to keep, you may remove or edit it. +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. # -# By default, configure uses ./config.cache as the cache file, -# creating it if it does not exist already. You can give configure -# the --cache-file=FILE option to use a different cache file; that is -# what configure does when it calls configure scripts in -# subdirectories, so they share the cache. -# Giving --cache-file=/dev/null disables caching, for debugging configure. -# config.status only pays attention to the cache file if you give it the -# --recheck option to rerun configure. +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. # -EOF +# `ac_cv_env_foo' variables (set or unset) will be overriden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. -(set) 2>&1 | - case `(ac_space=' '; set) 2>&1` in - *ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote substitution - # turns \\\\ into \\, and sed turns \\ into \). - sed -n \ - -e "s/'/'\\\\''/g" \ - -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" - ;; - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' - ;; - esac >> confcache -if cmp -s $cache_file confcache; then - : -else +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if cmp -s $cache_file confcache; then :; else if test -w $cache_file; then - echo "updating cache $cache_file" - cat confcache > $cache_file + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache -trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 - test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' -# Any assignment to VPATH causes Sun make to only execute -# the first set of double-colon rules, so remove it if not needed. -# If there is a colon in the path, we need to keep it. +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' fi -trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 - DEFS=-DHAVE_CONFIG_H -# Without the "./", some shells look in PATH for config.status. : ${CONFIG_STATUS=./config.status} - -echo creating $CONFIG_STATUS -rm -f $CONFIG_STATUS -cat > $CONFIG_STATUS <&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL # Generated automatically by configure. # Run this file to recreate the current configuration. -# This directory was configured as follows, -# on host `(hostname || uname -n) 2>/dev/null | sed 1q`: -# -# $0 $ac_configure_args -# # Compiler output produced by configure, useful for debugging -# configure, is in ./config.log if it exists. +# configure, is in config.log if it exists. -ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" -for ac_option -do - case "\$ac_option" in - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" - exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; - -version | --version | --versio | --versi | --vers | --ver | --ve | --v) - echo "$CONFIG_STATUS generated by autoconf version 2.12" - exit 0 ;; - -help | --help | --hel | --he | --h) - echo "\$ac_cs_usage"; exit 0 ;; - *) echo "\$ac_cs_usage"; exit 1 ;; - esac -done +debug=false +SHELL=\${CONFIG_SHELL-$SHELL} +ac_cs_invocation="\$0 \$@" -ac_given_srcdir=$srcdir -ac_given_INSTALL="$INSTALL" +_ACEOF -trap 'rm -fr `echo "Makefile doc/Makefile examples/Makefile shlib/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 -EOF -cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF -$ac_vpsub -$extrasub -s%@CFLAGS@%$CFLAGS%g -s%@CPPFLAGS@%$CPPFLAGS%g -s%@CXXFLAGS@%$CXXFLAGS%g -s%@DEFS@%$DEFS%g -s%@LDFLAGS@%$LDFLAGS%g -s%@LIBS@%$LIBS%g -s%@exec_prefix@%$exec_prefix%g -s%@prefix@%$prefix%g -s%@program_transform_name@%$program_transform_name%g -s%@bindir@%$bindir%g -s%@sbindir@%$sbindir%g -s%@libexecdir@%$libexecdir%g -s%@datadir@%$datadir%g -s%@sysconfdir@%$sysconfdir%g -s%@sharedstatedir@%$sharedstatedir%g -s%@localstatedir@%$localstatedir%g -s%@libdir@%$libdir%g -s%@includedir@%$includedir%g -s%@oldincludedir@%$oldincludedir%g -s%@infodir@%$infodir%g -s%@mandir@%$mandir%g -s%@host@%$host%g -s%@host_alias@%$host_alias%g -s%@host_cpu@%$host_cpu%g -s%@host_vendor@%$host_vendor%g -s%@host_os@%$host_os%g -s%@CC@%$CC%g -s%@CPP@%$CPP%g -s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g -s%@INSTALL_DATA@%$INSTALL_DATA%g -s%@AR@%$AR%g -s%@RANLIB@%$RANLIB%g -s%@MAKE_SHELL@%$MAKE_SHELL%g -s%@SHOBJ_CC@%$SHOBJ_CC%g -s%@SHOBJ_CFLAGS@%$SHOBJ_CFLAGS%g -s%@SHOBJ_LD@%$SHOBJ_LD%g -s%@SHOBJ_LDFLAGS@%$SHOBJ_LDFLAGS%g -s%@SHOBJ_XLDFLAGS@%$SHOBJ_XLDFLAGS%g -s%@SHOBJ_LIBS@%$SHOBJ_LIBS%g -s%@SHOBJ_STATUS@%$SHOBJ_STATUS%g -s%@SHLIB_STATUS@%$SHLIB_STATUS%g -s%@SHLIB_XLDFLAGS@%$SHLIB_XLDFLAGS%g -s%@SHLIB_LIBSUFF@%$SHLIB_LIBSUFF%g -s%@SHLIB_LIBVERSION@%$SHLIB_LIBVERSION%g -s%@SHLIB_LIBS@%$SHLIB_LIBS%g -s%@BUILD_DIR@%$BUILD_DIR%g -s%@LOCAL_CFLAGS@%$LOCAL_CFLAGS%g -s%@LOCAL_LDFLAGS@%$LOCAL_LDFLAGS%g -s%@LOCAL_DEFS@%$LOCAL_DEFS%g -s%@ARFLAGS@%$ARFLAGS%g -s%@LIBVERSION@%$LIBVERSION%g -s%@TERMCAP_LIB@%$TERMCAP_LIB%g - -CEOF -EOF - -cat >> $CONFIG_STATUS <<\EOF - -# Split the substitutions into bite-sized pieces for seds with -# small command number limits, like on Digital OSF/1 and HP-UX. -ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. -ac_file=1 # Number of current file. -ac_beg=1 # First line for current file. -ac_end=$ac_max_sed_cmds # Line after last line for current file. -ac_more_lines=: -ac_sed_cmds="" -while $ac_more_lines; do - if test $ac_beg -gt 1; then - sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file - else - sed "${ac_end}q" conftest.subs > conftest.s$ac_file - fi - if test ! -s conftest.s$ac_file; then - ac_more_lines=false - rm -f conftest.s$ac_file - else - if test -z "$ac_sed_cmds"; then - ac_sed_cmds="sed -f conftest.s$ac_file" - else - ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" - fi - ac_file=`expr $ac_file + 1` - ac_beg=$ac_end - ac_end=`expr $ac_end + $ac_max_sed_cmds` - fi -done -if test -z "$ac_sed_cmds"; then - ac_sed_cmds=cat +cat >>$CONFIG_STATUS <<\_ACEOF +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix fi + +# Name of the executable. +as_me=`echo "$0" |sed 's,.*[\\/],,'` + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +as_executable_p="test -f" + +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + +# NLS nuisances. +$as_unset LANG || test "${LANG+set}" != set || { LANG=C; export LANG; } +$as_unset LC_ALL || test "${LC_ALL+set}" != set || { LC_ALL=C; export LC_ALL; } +$as_unset LC_TIME || test "${LC_TIME+set}" != set || { LC_TIME=C; export LC_TIME; } +$as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set || { LC_CTYPE=C; export LC_CTYPE; } +$as_unset LANGUAGE || test "${LANGUAGE+set}" != set || { LANGUAGE=C; export LANGUAGE; } +$as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set || { LC_COLLATE=C; export LC_COLLATE; } +$as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set || { LC_NUMERIC=C; export LC_NUMERIC; } +$as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set || { LC_MESSAGES=C; export LC_MESSAGES; } + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=:; export CDPATH; } + +exec 6>&1 + +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\EOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." EOF -cat >> $CONFIG_STATUS <>$CONFIG_STATUS <> $CONFIG_STATUS <<\EOF -for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then - # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". - case "$ac_file" in - *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` - ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; - *) ac_file_in="${ac_file}.in" ;; + +cat >>$CONFIG_STATUS <<\EOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + shift + set dummy "$ac_option" "$ac_optarg" ${1+"$@"} + shift + ;; + -*);; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_need_defaults=false;; esac - # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + case $1 in + # Handling of the options. +EOF +cat >>$CONFIG_STATUS <>$CONFIG_STATUS <<\EOF + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:5244: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + shift + CONFIG_FILES="$CONFIG_FILES $1" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + shift + CONFIG_HEADERS="$CONFIG_HEADERS $1" + ac_need_defaults=false;; - # Remove last slash and all that follows it. Not all systems have dirname. - ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + # This is an error. + -*) { { echo "$as_me:5263: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +exec 5>>config.log +cat >&5 << _ACEOF + +## ----------------------- ## +## Running config.status. ## +## ----------------------- ## + +This file was extended by $as_me (readline 4.3) 2.52, executed with + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + > $ac_cs_invocation +on `(hostname || uname -n) 2>/dev/null | sed 1q` + +_ACEOF +EOF + +cat >>$CONFIG_STATUS <<\EOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "doc/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + "examples/Makefile" ) CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;; + "shlib/Makefile" ) CONFIG_FILES="$CONFIG_FILES shlib/Makefile" ;; + "default" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;; + "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + *) { { echo "$as_me:5304: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. +: ${TMPDIR=/tmp} +{ + tmp=`(umask 077 && mktemp -d -q "$TMPDIR/csXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=$TMPDIR/cs$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in $TMPDIR" >&2 + { (exit 1); exit 1; } +} + +EOF + +cat >>$CONFIG_STATUS <\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@DEFS@,$DEFS,;t t +s,@LIBS@,$LIBS,;t t +s,@build@,$build,;t t +s,@build_cpu@,$build_cpu,;t t +s,@build_vendor@,$build_vendor,;t t +s,@build_os@,$build_os,;t t +s,@host@,$host,;t t +s,@host_cpu@,$host_cpu,;t t +s,@host_vendor@,$host_vendor,;t t +s,@host_os@,$host_os,;t t +s,@SET_MAKE@,$SET_MAKE,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@CPP@,$CPP,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@AR@,$AR,;t t +s,@RANLIB@,$RANLIB,;t t +s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t +s,@MAKE_SHELL@,$MAKE_SHELL,;t t +s,@SHOBJ_CC@,$SHOBJ_CC,;t t +s,@SHOBJ_CFLAGS@,$SHOBJ_CFLAGS,;t t +s,@SHOBJ_LD@,$SHOBJ_LD,;t t +s,@SHOBJ_LDFLAGS@,$SHOBJ_LDFLAGS,;t t +s,@SHOBJ_XLDFLAGS@,$SHOBJ_XLDFLAGS,;t t +s,@SHOBJ_LIBS@,$SHOBJ_LIBS,;t t +s,@SHOBJ_STATUS@,$SHOBJ_STATUS,;t t +s,@SHLIB_STATUS@,$SHLIB_STATUS,;t t +s,@SHLIB_XLDFLAGS@,$SHLIB_XLDFLAGS,;t t +s,@SHLIB_LIBSUFF@,$SHLIB_LIBSUFF,;t t +s,@SHLIB_LIBVERSION@,$SHLIB_LIBVERSION,;t t +s,@SHLIB_LIBS@,$SHLIB_LIBS,;t t +s,@SHLIB_MAJOR@,$SHLIB_MAJOR,;t t +s,@SHLIB_MINOR@,$SHLIB_MINOR,;t t +s,@STATIC_TARGET@,$STATIC_TARGET,;t t +s,@SHARED_TARGET@,$SHARED_TARGET,;t t +s,@STATIC_INSTALL_TARGET@,$STATIC_INSTALL_TARGET,;t t +s,@SHARED_INSTALL_TARGET@,$SHARED_INSTALL_TARGET,;t t +s,@BUILD_DIR@,$BUILD_DIR,;t t +s,@LOCAL_CFLAGS@,$LOCAL_CFLAGS,;t t +s,@LOCAL_LDFLAGS@,$LOCAL_LDFLAGS,;t t +s,@LOCAL_DEFS@,$LOCAL_DEFS,;t t +s,@ARFLAGS@,$ARFLAGS,;t t +s,@LIBVERSION@,$LIBVERSION,;t t +s,@TERMCAP_LIB@,$TERMCAP_LIB,;t t +CEOF + +EOF + + cat >>$CONFIG_STATUS <<\EOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +EOF +cat >>$CONFIG_STATUS <<\EOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then - # The file is in a subdirectory. - test ! -d "$ac_dir" && mkdir "$ac_dir" - ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + { case "$ac_dir" in + [\\/]* | ?:[\\/]* ) as_incr_dir=;; + *) as_incr_dir=.;; +esac +as_dummy="$ac_dir" +for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do + case $as_mkdir_dir in + # Skip DOS drivespec + ?:) as_incr_dir=$as_mkdir_dir ;; + *) + as_incr_dir=$as_incr_dir/$as_mkdir_dir + test -d "$as_incr_dir" || mkdir "$as_incr_dir" + ;; + esac +done; } + + ac_dir_suffix="/`echo $ac_dir|sed 's,^\./,,'`" # A "../" for each directory in $ac_dir_suffix. - ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + ac_dots=`echo "$ac_dir_suffix" | sed 's,/[^/]*,../,g'` else ac_dir_suffix= ac_dots= fi - case "$ac_given_srcdir" in - .) srcdir=. - if test -z "$ac_dots"; then top_srcdir=. - else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; - /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + case $srcdir in + .) ac_srcdir=. + if test -z "$ac_dots"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_dots | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; *) # Relative path. - srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" - top_srcdir="$ac_dots$ac_given_srcdir" ;; + ac_srcdir=$ac_dots$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_dots$srcdir ;; esac - case "$ac_given_INSTALL" in - [/$]*) INSTALL="$ac_given_INSTALL" ;; - *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_dots$INSTALL ;; esac - echo creating "$ac_file" - rm -f "$ac_file" - configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." - case "$ac_file" in - *Makefile*) ac_comsub="1i\\ -# $configure_input" ;; - *) ac_comsub= ;; - esac + if test x"$ac_file" != x-; then + { echo "$as_me:5549: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated automatically by config.status. */ + configure_input="Generated automatically from `echo $ac_file_in | + sed 's,.*/,,'` by configure." - ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` - sed -e "$ac_comsub -s%@configure_input@%$configure_input%g -s%@srcdir@%$srcdir%g -s%@top_srcdir@%$top_srcdir%g -s%@INSTALL@%$INSTALL%g -" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file -fi; done -rm -f conftest.s* + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:5567: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo $f;; + *) # Relative + if test -f "$f"; then + # Build tree + echo $f + elif test -f "$srcdir/$f"; then + # Source tree + echo $srcdir/$f + else + # /dev/null tree + { { echo "$as_me:5580: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +EOF +cat >>$CONFIG_STATUS <>$CONFIG_STATUS <<\EOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +EOF +cat >>$CONFIG_STATUS <<\EOF + +# +# CONFIG_HEADER section. +# # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where # NAME is the cpp macro being defined and VALUE is the value it is being given. # # ac_d sets the value in "#define NAME VALUE" lines. -ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' -ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' -ac_dC='\3' -ac_dD='%g' -# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". -ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' -ac_uB='\([ ]\)%\1#\2define\3' +ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='[ ].*$,\1#\2' +ac_dC=' ' +ac_dD=',;t' +# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='$,\1#\2define\3' ac_uC=' ' -ac_uD='\4%g' -# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". -ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' -ac_eB='$%\1#\2define\3' -ac_eC=' ' -ac_eD='%g' +ac_uD=',;t' -if test "${CONFIG_HEADERS+set}" != set; then -EOF -cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF -fi -for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then +for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". - case "$ac_file" in - *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` - ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; - *) ac_file_in="${ac_file}.in" ;; + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; esac - echo creating $ac_file + test x"$ac_file" != x- && { echo "$as_me:5641: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} - rm -f conftest.frag conftest.in conftest.out - ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` - cat $ac_file_inputs > conftest.in + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:5652: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo $f;; + *) # Relative + if test -f "$f"; then + # Build tree + echo $f + elif test -f "$srcdir/$f"; then + # Source tree + echo $srcdir/$f + else + # /dev/null tree + { { echo "$as_me:5665: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + # Remove the trailing spaces. + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in EOF -# Transform confdefs.h into a sed script conftest.vals that substitutes -# the proper values into config.h.in to produce config.h. And first: -# Protect against being on the right side of a sed subst in config.status. -# Protect against being in an unquoted here document in config.status. -rm -f conftest.vals -cat > conftest.hdr <<\EOF -s/[\\&%]/\\&/g -s%[\\$`]%\\&%g -s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp -s%ac_d%ac_u%gp -s%ac_u%ac_e%gp +# Transform confdefs.h into two sed scripts, `conftest.defines' and +# `conftest.undefs', that substitutes the proper values into +# config.h.in to produce config.h. The first handles `#define' +# templates, and the second `#undef' templates. +# And first: Protect against being on the right side of a sed subst in +# config.status. Protect against being in an unquoted here document +# in config.status. +rm -f conftest.defines conftest.undefs +# Using a here document instead of a string reduces the quoting nightmare. +# Putting comments in sed scripts is not portable. +# +# `end' is used to avoid that the second main sed command (meant for +# 0-ary CPP macros) applies to n-ary macro definitions. +# See the Autoconf documentation for `clear'. +cat >confdef2sed.sed <<\EOF +s/[\\&,]/\\&/g +s,[\\$`],\\&,g +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\(\([^ (][^ (]*\)([^)]*)\)[ ]*\(.*\)$,${ac_dA}\2${ac_dB}\1${ac_dC}\3${ac_dD},gp +t end +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp +: end EOF -sed -n -f conftest.hdr confdefs.h > conftest.vals -rm -f conftest.hdr +# If some macros were called several times there might be several times +# the same #defines, which is useless. Nevertheless, we may not want to +# sort them, since we want the *last* AC-DEFINE to be honored. +uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines +sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs +rm -f confdef2sed.sed # This sed command replaces #undef with comments. This is necessary, for # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. -cat >> conftest.vals <<\EOF -s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +cat >>conftest.undefs <<\EOF +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, EOF -# Break up conftest.vals because some shells have a limit on -# the size of here documents, and old seds have small limits too. - +# Break up conftest.defines because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS +echo ' if egrep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS +echo ' :' >>$CONFIG_STATUS rm -f conftest.tail -while : +while grep . conftest.defines >/dev/null do - ac_lines=`grep -c . conftest.vals` - # grep -c gives empty output for an empty file on some AIX systems. - if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi - # Write a limited-size here document to conftest.frag. - echo ' cat > conftest.frag <> $CONFIG_STATUS - sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + # Write a limited-size here document to $tmp/defines.sed. + echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#define' lines. + echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS echo 'CEOF - sed -f conftest.frag conftest.in > conftest.out - rm -f conftest.in - mv conftest.out conftest.in -' >> $CONFIG_STATUS - sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail - rm -f conftest.vals - mv conftest.tail conftest.vals + sed -f $tmp/defines.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail + rm -f conftest.defines + mv conftest.tail conftest.defines done -rm -f conftest.vals +rm -f conftest.defines +echo ' fi # egrep' >>$CONFIG_STATUS +echo >>$CONFIG_STATUS -cat >> $CONFIG_STATUS <<\EOF - rm -f conftest.frag conftest.h - echo "/* $ac_file. Generated automatically by configure. */" > conftest.h - cat conftest.in >> conftest.h - rm -f conftest.in - if cmp -s $ac_file conftest.h 2>/dev/null; then - echo "$ac_file is unchanged" - rm -f conftest.h +# Break up conftest.undefs because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #undef templates' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.undefs >/dev/null +do + # Write a limited-size here document to $tmp/undefs.sed. + echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#undef' + echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/undefs.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail + rm -f conftest.undefs + mv conftest.tail conftest.undefs +done +rm -f conftest.undefs + +cat >>$CONFIG_STATUS <<\EOF + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated automatically by config.status. */ + if test x"$ac_file" = x-; then + echo "/* Generated automatically by configure. */" >$tmp/config.h else - # Remove last slash and all that follows it. Not all systems have dirname. - ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` - if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then - # The file is in a subdirectory. - test ! -d "$ac_dir" && mkdir "$ac_dir" - fi - rm -f $ac_file - mv conftest.h $ac_file + echo "/* $ac_file. Generated automatically by configure. */" >$tmp/config.h fi -fi; done + cat $tmp/in >>$tmp/config.h + rm -f $tmp/in + if test x"$ac_file" != x-; then + if cmp -s $ac_file $tmp/config.h 2>/dev/null; then + { echo "$as_me:5782: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + ac_dir=`$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + { case "$ac_dir" in + [\\/]* | ?:[\\/]* ) as_incr_dir=;; + *) as_incr_dir=.;; +esac +as_dummy="$ac_dir" +for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do + case $as_mkdir_dir in + # Skip DOS drivespec + ?:) as_incr_dir=$as_mkdir_dir ;; + *) + as_incr_dir=$as_incr_dir/$as_mkdir_dir + test -d "$as_incr_dir" || mkdir "$as_incr_dir" + ;; + esac +done; } + fi + rm -f $ac_file + mv $tmp/config.h $ac_file + fi + else + cat $tmp/config.h + rm -f $tmp/config.h + fi +done EOF -cat >> $CONFIG_STATUS <>$CONFIG_STATUS <<\EOF -EOF -cat >> $CONFIG_STATUS <<\EOF +# +# CONFIG_COMMANDS section. +# +for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue + ac_dest=`echo "$ac_file" | sed 's,:.*,,'` + ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` + case $ac_dest in + default ) # Makefile uses this timestamp file to record whether config.h is up to date. echo > stamp-h + ;; + esac +done +EOF -exit 0 +cat >>$CONFIG_STATUS <<\EOF + +{ (exit 0); exit 0; } EOF chmod +x $CONFIG_STATUS -rm -fr confdefs* $ac_clean_files -test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 +ac_clean_files=$ac_clean_files_save + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + exec 5>/dev/null + $SHELL $CONFIG_STATUS || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi diff --git a/readline/configure.in b/readline/configure.in index 240a3addc45..bc78f8a0f60 100644 --- a/readline/configure.in +++ b/readline/configure.in @@ -4,34 +4,49 @@ dnl dnl report bugs to chet@po.cwru.edu dnl dnl Process this file with autoconf to produce a configure script. -AC_REVISION([for Readline 4.0, version 2.14, from autoconf version] AC_ACVERSION) -LIBVERSION=4.0 +AC_REVISION([for Readline 4.3, version 2.45, from autoconf version] AC_ACVERSION) -AC_INIT(readline.h) -AC_CONFIG_HEADER(config.h) +AC_INIT(readline, 4.3, bug-readline@gnu.org) dnl make sure we are using a recent autoconf version -AC_PREREQ(2.10) +AC_PREREQ(2.50) +AC_CONFIG_SRCDIR(readline.h) AC_CONFIG_AUX_DIR(./support) +AC_CONFIG_HEADERS(config.h) + +dnl update the value of RL_READLINE_VERSION in readline.h when this changes +LIBVERSION=4.3 AC_CANONICAL_HOST dnl configure defaults opt_curses=no -opt_shared=no dnl arguments to configure -AC_ARG_WITH(curses, --with-curses use the curses library instead of the termcap library,opt_curses=$withval) +AC_ARG_WITH(curses, AC_HELP_STRING([--with-curses], [use the curses library instead of the termcap library]), opt_curses=$withval) if test "$opt_curses" = "yes"; then prefer_curses=yes fi +dnl option parsing for optional features +opt_static_libs=yes +opt_shared_libs=yes + +AC_ARG_ENABLE(shared, AC_HELP_STRING([--enable-shared], [build shared libraries [[default=YES]]]), opt_shared_libs=$enableval) +AC_ARG_ENABLE(static, AC_HELP_STRING([--enable-static], [build static libraries [[default=YES]]]), opt_static_libs=$enableval) + +echo "" +echo "Beginning configuration for readline-$LIBVERSION for ${host_cpu}-${host_vendor}-${host_os}" +echo "" + # We want these before the checks, so the checks can modify their values. test -z "$CFLAGS" && CFLAGS=-g auto_cflags=1 +AC_PROG_MAKE_SET AC_PROG_CC +dnl AC_AIX AC_MINIX # If we're using gcc and the user hasn't specified CFLAGS, add -O to CFLAGS. @@ -39,7 +54,7 @@ test -n "$GCC" && test -n "$auto_cflags" && CFLAGS="$CFLAGS -O" AC_PROG_GCC_TRADITIONAL AC_PROG_INSTALL -AC_CHECK_PROG(AR, ar, ar) +AC_CHECK_PROG(AR, ar, , ar) dnl Set default for ARFLAGS, since autoconf does not have a macro for it. dnl This allows people to set it when running configure or make test -n "$ARFLAGS" || ARFLAGS="cr" @@ -48,32 +63,42 @@ AC_PROG_RANLIB MAKE_SHELL=/bin/sh AC_SUBST(MAKE_SHELL) -AC_RETSIGTYPE +AC_C_CONST +AC_C_PROTOTYPES +AC_C_CHAR_UNSIGNED + +AC_TYPE_SIGNAL + +AC_TYPE_SIZE_T +AC_CHECK_TYPE(ssize_t, int) AC_HEADER_STAT AC_HEADER_DIRENT -AC_CHECK_FUNCS(strcasecmp select setenv putenv tcgetattr setlocale lstat) +AC_CHECK_FUNCS(lstat memmove putenv select setenv setlocale \ + strcasecmp strpbrk tcgetattr vsnprintf isascii isxdigit) AC_FUNC_STRCOLL -AC_CHECK_HEADERS(unistd.h stdlib.h varargs.h stdarg.h string.h \ - sys/ptem.h sys/pte.h sys/stream.h sys/select.h \ - termcap.h termios.h termio.h sys/file.h locale.h) +AC_CHECK_HEADERS(unistd.h stdlib.h varargs.h stdarg.h string.h strings.h \ + limits.h sys/ptem.h sys/pte.h sys/stream.h sys/select.h \ + termcap.h termios.h termio.h sys/file.h locale.h memory.h ) -BASH_SIGNAL_CHECK -BASH_REINSTALL_SIGHANDLERS +BASH_SYS_SIGNAL_VINTAGE +BASH_SYS_REINSTALL_SIGHANDLERS BASH_FUNC_POSIX_SETJMP BASH_FUNC_LSTAT -BASH_CHECK_GETPW_FUNCS BASH_FUNC_STRCOLL +BASH_CHECK_GETPW_FUNCS + +AC_HEADER_TIOCGWINSZ + BASH_TYPE_SIGHANDLER -BASH_HAVE_TIOCGWINSZ BASH_HAVE_TIOCSTAT BASH_HAVE_FIONREAD -BASH_MISC_SPEED_T +BASH_CHECK_SPEED_T BASH_STRUCT_WINSIZE BASH_STRUCT_DIRENT_D_INO BASH_STRUCT_DIRENT_D_FILENO @@ -84,11 +109,18 @@ aix*) prefer_curses=yes ;; esac BASH_CHECK_LIB_TERMCAP if test "$TERMCAP_LIB" = "./lib/termcap/libtermcap.a"; then - TERMCAP_LIB=-ltermcap #default + if test "$prefer_curses" = yes; then + TERMCAP_LIB=-lcurses + else + TERMCAP_LIB=-ltermcap #default + fi fi +BASH_CHECK_MULTIBYTE + case "$host_cpu" in *cray*) LOCAL_CFLAGS=-DCRAY ;; +*s390*) LOCAL_CFLAGS=-fsigned-char ;; esac case "$host_os" in @@ -102,7 +134,7 @@ esac # if test -f ${srcdir}/support/shobj-conf; then AC_MSG_CHECKING(configuration for building shared libraries) - eval `${CONFIG_SHELL-/bin/sh} ${srcdir}/support/shobj-conf -C ${CC} -c ${host_cpu} -o ${host_os} -v ${host_vendor}` + eval `${CONFIG_SHELL-/bin/sh} ${srcdir}/support/shobj-conf -C "${CC}" -c ${host_cpu} -o ${host_os} -v ${host_vendor}` AC_SUBST(SHOBJ_CC) AC_SUBST(SHOBJ_CFLAGS) AC_SUBST(SHOBJ_LD) @@ -116,9 +148,40 @@ if test -f ${srcdir}/support/shobj-conf; then AC_SUBST(SHLIB_LIBVERSION) AC_SUBST(SHLIB_LIBS) AC_MSG_RESULT($SHLIB_STATUS) + + # SHLIB_STATUS is either `supported' or `unsupported'. If it's + # `unsupported', turn off any default shared library building + if test "$SHLIB_STATUS" = 'unsupported'; then + opt_shared_libs=no + fi + + # shared library versioning + # quoted for m4 so I can use character classes + SHLIB_MAJOR=[`expr "$LIBVERSION" : '\([0-9]\)\..*'`] + SHLIB_MINOR=[`expr "$LIBVERSION" : '[0-9]\.\([0-9]\).*'`] + AC_SUBST(SHLIB_MAJOR) + AC_SUBST(SHLIB_MINOR) fi -BUILD_DIR=`pwd` +if test "$opt_static_libs" = "yes"; then + STATIC_TARGET=static + STATIC_INSTALL_TARGET=install-static +fi +if test "$opt_shared_libs" = "yes"; then + SHARED_TARGET=shared + SHARED_INSTALL_TARGET=install-shared +fi + +AC_SUBST(STATIC_TARGET) +AC_SUBST(SHARED_TARGET) +AC_SUBST(STATIC_INSTALL_TARGET) +AC_SUBST(SHARED_INSTALL_TARGET) + +case "$host_os" in +msdosdjgpp*) BUILD_DIR=`pwd.exe` ;; # to prevent //d/path/file +*) BUILD_DIR=`pwd` ;; +esac + AC_SUBST(BUILD_DIR) AC_SUBST(CFLAGS) diff --git a/readline/display.c b/readline/display.c index df9e212ac0c..180061b29ae 100644 --- a/readline/display.c +++ b/readline/display.c @@ -7,7 +7,7 @@ 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 1, or + 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 @@ -18,7 +18,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) @@ -41,13 +41,9 @@ #include -#if defined (__GO32__) -# include -# include -#endif /* __GO32__ */ - /* System-specific feature definitions and include files. */ #include "rldefs.h" +#include "rlmbutil.h" /* Termcap library stuff. */ #include "tcap.h" @@ -56,48 +52,32 @@ #include "readline.h" #include "history.h" +#include "rlprivate.h" +#include "xmalloc.h" + #if !defined (strchr) && !defined (__STDC__) extern char *strchr (), *strrchr (); #endif /* !strchr && !__STDC__ */ -/* Global and pseudo-global variables and functions - imported from readline.c. */ -extern char *rl_prompt; -extern int readline_echoing_p; - -extern int _rl_output_meta_chars; -extern int _rl_horizontal_scroll_mode; -extern int _rl_mark_modified_lines; -extern int _rl_prefer_visible_bell; - -/* Variables and functions imported from terminal.c */ -extern void _rl_output_some_chars (); -#ifdef _MINIX -extern void _rl_output_character_function (); -#else -extern int _rl_output_character_function (); +#if defined (HACK_TERMCAP_MOTION) +extern char *_rl_term_forward_char; #endif -extern int _rl_backspace (); -extern const char *term_clreol, *term_clrpag; -extern const char *term_im, *term_ic, *term_ei, *term_DC; -extern const char *term_up, *term_dc, *term_cr, *term_IC; -extern int screenheight, screenwidth, screenchars; -extern int terminal_can_insert, _rl_term_autowrap; +static void update_line PARAMS((char *, char *, int, int, int, int)); +static void space_to_eol PARAMS((int)); +static void delete_chars PARAMS((int)); +static void insert_some_chars PARAMS((char *, int, int)); +static void cr PARAMS((void)); -/* Pseudo-global functions (local to the readline library) exported - by this file. */ -void _rl_move_cursor_relative (), _rl_output_some_chars (); -void _rl_move_vert (); -void _rl_clear_to_eol (), _rl_clear_screen (); - -static void update_line (), space_to_eol (); -static void delete_chars (), insert_some_chars (); -static void cr (); +#if defined (HANDLE_MULTIBYTE) +static int _rl_col_width PARAMS((char *, int, int)); +static int *_rl_wrapped_line; +#else +# define _rl_col_width(l, s, e) (((e) <= (s)) ? 0 : (e) - (s)) +#endif static int *inv_lbreaks, *vis_lbreaks; - -extern char *xmalloc (), *xrealloc (); +static int inv_lbsize, vis_lbsize; /* Heuristic used to decide whether it is faster to move from CUR to NEW by backing up or outputting a carriage return and moving forward. */ @@ -131,7 +111,7 @@ extern char *xmalloc (), *xrealloc (); RL_DISPLAY_FIXED variable. This is good for efficiency. */ /* Application-specific redisplay function. */ -VFunction *rl_redisplay_function = rl_redisplay; +rl_voidfunc_t *rl_redisplay_function = rl_redisplay; /* Global variables declared here. */ /* What YOU turn on when you have handled all redisplay yourself. */ @@ -141,7 +121,7 @@ int _rl_suppress_redisplay = 0; /* The stuff that gets printed out before the actual text of the line. This is usually pointing to rl_prompt. */ -const char *rl_display_prompt = (char *)NULL; +char *rl_display_prompt = (char *)NULL; /* Pseudo-global variables declared here. */ /* The visible cursor position. If you print some text, adjust this. */ @@ -170,27 +150,40 @@ static int forced_display; /* Default and initial buffer size. Can grow. */ static int line_size = 1024; +/* Variables to keep track of the expanded prompt string, which may + include invisible characters. */ + static char *local_prompt, *local_prompt_prefix; -static int visible_length, prefix_length; +static int prompt_visible_length, prompt_prefix_length; /* The number of invisible characters in the line currently being displayed on the screen. */ static int visible_wrap_offset; -/* static so it can be shared between rl_redisplay and update_line */ +/* The number of invisible characters in the prompt string. Static so it + can be shared between rl_redisplay and update_line */ static int wrap_offset; -/* The index of the last invisible_character in the prompt string. */ -static int last_invisible; +/* The index of the last invisible character in the prompt string. */ +static int prompt_last_invisible; /* The length (buffer offset) of the first line of the last (possibly multi-line) buffer displayed on the screen. */ static int visible_first_line_len; +/* Number of invisible characters on the first physical line of the prompt. + Only valid when the number of physical characters in the prompt exceeds + (or is equal to) _rl_screenwidth. */ +static int prompt_invis_chars_first_line; + +static int prompt_last_screen_line; + /* Expand the prompt string S and return the number of visible characters in *LP, if LP is not null. This is currently more-or-less a placeholder for expansion. LIP, if non-null is a place to store the - index of the last invisible character in ther eturned string. */ + index of the last invisible character in the returned string. NIFLP, + if non-zero, is a place to store the number of invisible characters in + the first prompt line. */ /* Current implementation: \001 (^A) start non-visible characters @@ -200,12 +193,12 @@ static int visible_first_line_len; \002 are assumed to be `visible'. */ static char * -expand_prompt (pmt, lp, lip) +expand_prompt (pmt, lp, lip, niflp) char *pmt; - int *lp, *lip; + int *lp, *lip, *niflp; { char *r, *ret, *p; - int l, rl, last, ignoring; + int l, rl, last, ignoring, ninvis, invfl; /* Short-circuit if we can. */ if (strchr (pmt, RL_PROMPT_START_IGNORE) == 0) @@ -217,9 +210,11 @@ expand_prompt (pmt, lp, lip) } l = strlen (pmt); - r = ret = xmalloc (l + 1); + r = ret = (char *)xmalloc (l + 1); - for (rl = ignoring = last = 0, p = pmt; p && *p; p++) + invfl = 0; /* invisible chars in first line of prompt */ + + for (rl = ignoring = last = ninvis = 0, p = pmt; p && *p; p++) { /* This code strips the invisible character string markers RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */ @@ -239,14 +234,35 @@ expand_prompt (pmt, lp, lip) *r++ = *p; if (!ignoring) rl++; + else + ninvis++; + if (rl == _rl_screenwidth) + invfl = ninvis; } } + if (rl < _rl_screenwidth) + invfl = ninvis; + *r = '\0'; if (lp) *lp = rl; if (lip) *lip = last; + if (niflp) + *niflp = invfl; + return ret; +} + +/* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from + PMT and return the rest of PMT. */ +char * +_rl_strip_prompt (pmt) + char *pmt; +{ + char *ret; + + ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL); return ret; } @@ -258,8 +274,8 @@ expand_prompt (pmt, lp, lip) * (portion after the final newline) * local_prompt_prefix = portion before last newline of rl_display_prompt, * expanded via expand_prompt - * visible_length = number of visible characters in local_prompt - * prefix_length = number of visible characters in local_prompt_prefix + * prompt_visible_length = number of visible characters in local_prompt + * prompt_prefix_length = number of visible characters in local_prompt_prefix * * This function is called once per call to readline(). It may also be * called arbitrarily to expand the primary prompt. @@ -275,12 +291,11 @@ rl_expand_prompt (prompt) int c; /* Clear out any saved values. */ - if (local_prompt) - free (local_prompt); - if (local_prompt_prefix) - free (local_prompt_prefix); + FREE (local_prompt); + FREE (local_prompt_prefix); + local_prompt = local_prompt_prefix = (char *)0; - last_invisible = visible_length = 0; + prompt_last_invisible = prompt_visible_length = 0; if (prompt == 0 || *prompt == 0) return (0); @@ -288,25 +303,77 @@ rl_expand_prompt (prompt) p = strrchr (prompt, '\n'); if (!p) { - /* The prompt is only one line. */ - local_prompt = expand_prompt (prompt, &visible_length, &last_invisible); + /* The prompt is only one logical line, though it might wrap. */ + local_prompt = expand_prompt (prompt, &prompt_visible_length, + &prompt_last_invisible, + &prompt_invis_chars_first_line); local_prompt_prefix = (char *)0; - return (visible_length); + return (prompt_visible_length); } else { /* The prompt spans multiple lines. */ t = ++p; - local_prompt = expand_prompt (p, &visible_length, &last_invisible); + local_prompt = expand_prompt (p, &prompt_visible_length, + &prompt_last_invisible, + &prompt_invis_chars_first_line); c = *t; *t = '\0'; /* The portion of the prompt string up to and including the final newline is now null-terminated. */ - local_prompt_prefix = expand_prompt (prompt, &prefix_length, (int *)NULL); + local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length, + (int *)NULL, + &prompt_invis_chars_first_line); *t = c; - return (prefix_length); + return (prompt_prefix_length); } } +/* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated + arrays of line break markers. MINSIZE is the minimum size of VISIBLE_LINE + and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is + increased. If the lines have already been allocated, this ensures that + they can hold at least MINSIZE characters. */ +static void +init_line_structures (minsize) + int minsize; +{ + register int n; + + if (invisible_line == 0) /* initialize it */ + { + if (line_size < minsize) + line_size = minsize; + visible_line = (char *)xmalloc (line_size); + invisible_line = (char *)xmalloc (line_size); + } + else if (line_size < minsize) /* ensure it can hold MINSIZE chars */ + { + line_size *= 2; + if (line_size < minsize) + line_size = minsize; + visible_line = (char *)xrealloc (visible_line, line_size); + invisible_line = (char *)xrealloc (invisible_line, line_size); + } + + for (n = minsize; n < line_size; n++) + { + visible_line[n] = 0; + invisible_line[n] = 1; + } + + if (vis_lbreaks == 0) + { + /* should be enough. */ + inv_lbsize = vis_lbsize = 256; + inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int)); + vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int)); +#if defined (HANDLE_MULTIBYTE) + _rl_wrapped_line = (int *)xmalloc (vis_lbsize * sizeof (int)); +#endif + inv_lbreaks[0] = vis_lbreaks[0] = 0; + } +} + /* Basic redisplay algorithm. */ void rl_redisplay () @@ -315,29 +382,24 @@ rl_redisplay () register char *line; int c_pos, inv_botlin, lb_botlin, lb_linenum; int newlines, lpos, temp; - const char *prompt_this_line; + char *prompt_this_line; +#if defined (HANDLE_MULTIBYTE) + wchar_t wc; + size_t wc_bytes; + int wc_width; + mbstate_t ps; + int _rl_wrapped_multicolumn = 0; +#endif if (!readline_echoing_p) return; if (!rl_display_prompt) - rl_display_prompt = ""; + rl_display_prompt = (char*)""; if (invisible_line == 0) { - visible_line = xmalloc (line_size); - invisible_line = xmalloc (line_size); - for (in = 0; in < line_size; in++) - { - visible_line[in] = 0; - invisible_line[in] = 1; - } - - /* should be enough, but then again, this is just for testing. */ - inv_lbreaks = (int *)malloc (256 * sizeof (int)); - vis_lbreaks = (int *)malloc (256 * sizeof (int)); - inv_lbreaks[0] = vis_lbreaks[0] = 0; - + init_line_structures (0); rl_on_new_line (); } @@ -377,14 +439,14 @@ rl_redisplay () if (temp >= line_size) { line_size = (temp + 1024) - (temp % 1024); - visible_line = xrealloc (visible_line, line_size); - line = invisible_line = xrealloc (invisible_line, line_size); + visible_line = (char *)xrealloc (visible_line, line_size); + line = invisible_line = (char *)xrealloc (invisible_line, line_size); } strncpy (line + out, local_prompt, local_len); out += local_len; } line[out] = '\0'; - wrap_offset = local_len - visible_length; + wrap_offset = local_len - prompt_visible_length; } else { @@ -395,12 +457,13 @@ rl_redisplay () else { prompt_this_line++; + pmtlen = prompt_this_line - rl_display_prompt; /* temp var */ if (forced_display) { - _rl_output_some_chars (rl_display_prompt, prompt_this_line - rl_display_prompt); + _rl_output_some_chars (rl_display_prompt, pmtlen); /* Make sure we are at column zero even after a newline, regardless of the state of terminal output processing. */ - if (prompt_this_line[-2] != '\r') + if (pmtlen < 2 || prompt_this_line[-2] != '\r') cr (); } } @@ -410,55 +473,143 @@ rl_redisplay () if (temp >= line_size) { line_size = (temp + 1024) - (temp % 1024); - visible_line = xrealloc (visible_line, line_size); - line = invisible_line = xrealloc (invisible_line, line_size); + visible_line = (char *)xrealloc (visible_line, line_size); + line = invisible_line = (char *)xrealloc (invisible_line, line_size); } strncpy (line + out, prompt_this_line, pmtlen); out += pmtlen; line[out] = '\0'; - wrap_offset = 0; + wrap_offset = prompt_invis_chars_first_line = 0; } +#define CHECK_INV_LBREAKS() \ + do { \ + if (newlines >= (inv_lbsize - 2)) \ + { \ + inv_lbsize *= 2; \ + inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ + } \ + } while (0) + +#if defined (HANDLE_MULTIBYTE) #define CHECK_LPOS() \ do { \ lpos++; \ - if (lpos >= screenwidth) \ + if (lpos >= _rl_screenwidth) \ { \ + if (newlines >= (inv_lbsize - 2)) \ + { \ + inv_lbsize *= 2; \ + inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ + _rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \ + } \ + inv_lbreaks[++newlines] = out; \ + _rl_wrapped_line[newlines] = _rl_wrapped_multicolumn; \ + lpos = 0; \ + } \ + } while (0) +#else +#define CHECK_LPOS() \ + do { \ + lpos++; \ + if (lpos >= _rl_screenwidth) \ + { \ + if (newlines >= (inv_lbsize - 2)) \ + { \ + inv_lbsize *= 2; \ + inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ + } \ inv_lbreaks[++newlines] = out; \ lpos = 0; \ } \ } while (0) +#endif /* inv_lbreaks[i] is where line i starts in the buffer. */ inv_lbreaks[newlines = 0] = 0; lpos = out - wrap_offset; - - /* XXX - what if lpos is already >= screenwidth before we start drawing the - contents of the command line? */ - while (lpos >= screenwidth) - { -#if 0 - temp = ((newlines + 1) * screenwidth) - ((newlines == 0) ? wrap_offset : 0); -#else - /* XXX - possible fix from Darin Johnson for prompt - string with invisible characters that is longer than the screen - width. */ - temp = ((newlines + 1) * screenwidth) + ((newlines == 0) ? wrap_offset : 0); +#if defined (HANDLE_MULTIBYTE) + memset (_rl_wrapped_line, 0, vis_lbsize); #endif + + /* prompt_invis_chars_first_line is the number of invisible characters in + the first physical line of the prompt. + wrap_offset - prompt_invis_chars_first_line is the number of invis + chars on the second line. */ + + /* what if lpos is already >= _rl_screenwidth before we start drawing the + contents of the command line? */ + while (lpos >= _rl_screenwidth) + { + /* fix from Darin Johnson for prompt string with + invisible characters that is longer than the screen width. The + prompt_invis_chars_first_line variable could be made into an array + saying how many invisible characters there are per line, but that's + probably too much work for the benefit gained. How many people have + prompts that exceed two physical lines? */ + temp = ((newlines + 1) * _rl_screenwidth) + +#if 0 + ((newlines == 0) ? prompt_invis_chars_first_line : 0) + +#else + ((newlines == 0 && local_prompt_prefix == 0) ? prompt_invis_chars_first_line : 0) + +#endif + ((newlines == 1) ? wrap_offset : 0); + inv_lbreaks[++newlines] = temp; - lpos -= screenwidth; + lpos -= _rl_screenwidth; } + prompt_last_screen_line = newlines; + + /* Draw the rest of the line (after the prompt) into invisible_line, keeping + track of where the cursor is (c_pos), the number of the line containing + the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin). + It maintains an array of line breaks for display (inv_lbreaks). + This handles expanding tabs for display and displaying meta characters. */ lb_linenum = 0; +#if defined (HANDLE_MULTIBYTE) + in = 0; + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + memset (&ps, 0, sizeof (mbstate_t)); + wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps); + } + else + wc_bytes = 1; + while (in < rl_end) +#else for (in = 0; in < rl_end; in++) +#endif { c = (unsigned char)rl_line_buffer[in]; +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + if (wc_bytes == (size_t)-1 || wc_bytes == (size_t)-2) + { + /* Byte sequence is invalid or shortened. Assume that the + first byte represents a character. */ + wc_bytes = 1; + /* Assume that a character occupies a single column. */ + wc_width = 1; + memset (&ps, 0, sizeof (mbstate_t)); + } + else if (wc_bytes == (size_t)0) + break; /* Found '\0' */ + else + { + temp = wcwidth (wc); + wc_width = (temp < 0) ? 1 : temp; + } + } +#endif + if (out + 8 >= line_size) /* XXX - 8 for \t */ { line_size *= 2; - visible_line = xrealloc (visible_line, line_size); - invisible_line = xrealloc (invisible_line, line_size); + visible_line = (char *)xrealloc (visible_line, line_size); + invisible_line = (char *)xrealloc (invisible_line, line_size); line = invisible_line; } @@ -468,15 +619,20 @@ rl_redisplay () lb_linenum = newlines; } +#if defined (HANDLE_MULTIBYTE) + if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */ +#else if (META_CHAR (c)) +#endif { if (_rl_output_meta_chars == 0) { sprintf (line + out, "\\%o", c); - if (lpos + 4 >= screenwidth) + if (lpos + 4 >= _rl_screenwidth) { - temp = screenwidth - lpos; + temp = _rl_screenwidth - lpos; + CHECK_INV_LBREAKS (); inv_lbreaks[++newlines] = out + temp; lpos = 4 - temp; } @@ -494,7 +650,7 @@ rl_redisplay () #if defined (DISPLAY_TABS) else if (c == '\t') { - register int temp, newout; + register int newout; #if 0 newout = (out | (int)7) + 1; @@ -502,10 +658,11 @@ rl_redisplay () newout = out + 8 - lpos % 8; #endif temp = newout - out; - if (lpos + temp >= screenwidth) + if (lpos + temp >= _rl_screenwidth) { register int temp2; - temp2 = screenwidth - lpos; + temp2 = _rl_screenwidth - lpos; + CHECK_INV_LBREAKS (); inv_lbreaks[++newlines] = out + temp2; lpos = temp - temp2; while (out < newout) @@ -519,9 +676,10 @@ rl_redisplay () } } #endif - else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && term_up && *term_up) + else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up) { line[out++] = '\0'; /* XXX - sentinel */ + CHECK_INV_LBREAKS (); inv_lbreaks[++newlines] = out; lpos = 0; } @@ -534,9 +692,52 @@ rl_redisplay () } else { +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + register int i; + + _rl_wrapped_multicolumn = 0; + + if (_rl_screenwidth < lpos + wc_width) + for (i = lpos; i < _rl_screenwidth; i++) + { + /* The space will be removed in update_line() */ + line[out++] = ' '; + _rl_wrapped_multicolumn++; + CHECK_LPOS(); + } + if (in == rl_point) + { + c_pos = out; + lb_linenum = newlines; + } + for (i = in; i < in+wc_bytes; i++) + line[out++] = rl_line_buffer[i]; + for (i = 0; i < wc_width; i++) + CHECK_LPOS(); + } + else + { + line[out++] = c; + CHECK_LPOS(); + } +#else line[out++] = c; CHECK_LPOS(); +#endif } + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + in += wc_bytes; + wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps); + } + else + in++; +#endif + } line[out] = '\0'; if (c_pos < 0) @@ -546,10 +747,12 @@ rl_redisplay () } inv_botlin = lb_botlin = newlines; + CHECK_INV_LBREAKS (); inv_lbreaks[newlines+1] = out; cursor_linenum = lb_linenum; - /* C_POS == position in buffer where cursor should be placed. */ + /* C_POS == position in buffer where cursor should be placed. + CURSOR_LINENUM == line number where the cursor should be placed. */ /* PWP: now is when things get a bit hairy. The visible and invisible line buffers are really multiple lines, which would wrap every @@ -560,7 +763,7 @@ rl_redisplay () otherwise, let long lines display in a single terminal line, and horizontally scroll it. */ - if (_rl_horizontal_scroll_mode == 0 && term_up && *term_up) + if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up) { int nleft, pos, changed_screen_line; @@ -571,8 +774,13 @@ rl_redisplay () /* If we have more than a screenful of material to display, then only display a screenful. We should display the last screen, not the first. */ - if (out >= screenchars) - out = screenchars - 1; + if (out >= _rl_screenchars) + { + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY); + else + out = _rl_screenchars - 1; + } /* The first line is at character position 0 in the buffer. The second and subsequent lines start at inv_lbreaks[N], offset by @@ -582,7 +790,7 @@ rl_redisplay () #define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l])) #define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l]) #define VIS_CHARS(line) (visible_line + vis_lbreaks[line]) -#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line) +#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? (char*)"" : VIS_CHARS(line) #define INV_LINE(line) (invisible_line + inv_lbreaks[line]) /* For each line in the buffer, do the updating display. */ @@ -602,7 +810,7 @@ rl_redisplay () (wrap_offset > visible_wrap_offset) && (_rl_last_c_pos < visible_first_line_len)) { - nleft = screenwidth + wrap_offset - _rl_last_c_pos; + nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos; if (nleft) _rl_clear_to_eol (nleft); } @@ -623,7 +831,7 @@ rl_redisplay () _rl_move_vert (linenum); _rl_move_cursor_relative (0, tt); _rl_clear_to_eol - ((linenum == _rl_vis_botlin) ? (int) strlen (tt) : screenwidth); + ((linenum == _rl_vis_botlin) ? (int)strlen (tt) : _rl_screenwidth); } } _rl_vis_botlin = inv_botlin; @@ -634,7 +842,7 @@ rl_redisplay () if (changed_screen_line) { _rl_move_vert (cursor_linenum); - /* If we moved up to the line with the prompt using term_up, + /* If we moved up to the line with the prompt using _rl_term_up, the physical cursor position on the screen stays the same, but the buffer position needs to be adjusted to account for invisible characters. */ @@ -647,14 +855,21 @@ rl_redisplay () the characters from the current cursor position. But we only need to reprint it if the cursor is before the last invisible character in the prompt string. */ - nleft = visible_length + wrap_offset; + nleft = prompt_visible_length + wrap_offset; if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 && - _rl_last_c_pos <= last_invisible && local_prompt) + _rl_last_c_pos <= prompt_last_invisible && local_prompt) { - if (term_cr) - tputs (term_cr, 1, _rl_output_character_function); +#if defined (__MSDOS__) + putc ('\r', rl_outstream); +#else + if (_rl_term_cr) + tputs (_rl_term_cr, 1, _rl_output_character_function); +#endif _rl_output_some_chars (local_prompt, nleft); - _rl_last_c_pos = nleft; + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + _rl_last_c_pos = _rl_col_width(local_prompt, 0, nleft); + else + _rl_last_c_pos = nleft; } /* Where on that line? And where does that line start @@ -670,10 +885,15 @@ rl_redisplay () if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos) { _rl_backspace (_rl_last_c_pos - nleft); - _rl_last_c_pos = nleft; + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + _rl_last_c_pos = _rl_col_width (&visible_line[pos], 0, nleft); + else + _rl_last_c_pos = nleft; } - if (nleft != _rl_last_c_pos) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + _rl_move_cursor_relative (nleft, &invisible_line[pos]); + else if (nleft != _rl_last_c_pos) _rl_move_cursor_relative (nleft, &invisible_line[pos]); } } @@ -690,11 +910,11 @@ rl_redisplay () /* The number of characters that will be displayed before the cursor. */ ndisp = c_pos - wrap_offset; - nleft = visible_length + wrap_offset; + nleft = prompt_visible_length + wrap_offset; /* Where the new cursor position will be on the screen. This can be longer than SCREENWIDTH; if it is, lmargin will be adjusted. */ phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset); - t = screenwidth / 3; + t = _rl_screenwidth / 3; /* If the number of characters had already exceeded the screenwidth, last_lmargin will be > 0. */ @@ -702,7 +922,7 @@ rl_redisplay () /* If the number of characters to be displayed is more than the screen width, compute the starting offset so that the cursor is about two-thirds of the way across the screen. */ - if (phys_c_pos > screenwidth - 2) + if (phys_c_pos > _rl_screenwidth - 2) { lmargin = c_pos - (2 * t); if (lmargin < 0) @@ -712,7 +932,7 @@ rl_redisplay () if (wrap_offset && lmargin > 0 && lmargin < nleft) lmargin = nleft; } - else if (ndisp < screenwidth - 2) /* XXX - was -1 */ + else if (ndisp < _rl_screenwidth - 2) /* XXX - was -1 */ lmargin = 0; else if (phys_c_pos < 1) { @@ -734,7 +954,7 @@ rl_redisplay () the whole line, indicate that with a special character at the right edge of the screen. If LMARGIN is 0, we need to take the wrap offset into account. */ - t = lmargin + M_OFFSET (lmargin, wrap_offset) + screenwidth; + t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth; if (t < out) line[t - 1] = '>'; @@ -744,8 +964,8 @@ rl_redisplay () update_line (&visible_line[last_lmargin], &invisible_line[lmargin], 0, - screenwidth + visible_wrap_offset, - screenwidth + (lmargin ? 0 : wrap_offset), + _rl_screenwidth + visible_wrap_offset, + _rl_screenwidth + (lmargin ? 0 : wrap_offset), 0); /* If the visible new line is shorter than the old, but the number @@ -756,12 +976,12 @@ rl_redisplay () (_rl_last_c_pos == out) && t < visible_first_line_len) { - nleft = screenwidth - t; + nleft = _rl_screenwidth - t; _rl_clear_to_eol (nleft); } visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset); - if (visible_first_line_len > screenwidth) - visible_first_line_len = screenwidth; + if (visible_first_line_len > _rl_screenwidth) + visible_first_line_len = _rl_screenwidth; _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]); last_lmargin = lmargin; @@ -771,12 +991,18 @@ rl_redisplay () /* Swap visible and non-visible lines. */ { - char *temp = visible_line; - int *itemp = vis_lbreaks; + char *vtemp = visible_line; + int *itemp = vis_lbreaks, ntemp = vis_lbsize; + visible_line = invisible_line; - invisible_line = temp; + invisible_line = vtemp; + vis_lbreaks = inv_lbreaks; inv_lbreaks = itemp; + + vis_lbsize = inv_lbsize; + inv_lbsize = ntemp; + rl_display_fixed = 0; /* If we are displaying on a single line, and last_lmargin is > 0, we are not displaying any invisible characters, so set visible_wrap_offset @@ -812,6 +1038,11 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) register char *ofd, *ols, *oe, *nfd, *nls, *ne; int temp, lendiff, wsatend, od, nd; int current_invis_chars; + int col_lendiff, col_temp; +#if defined (HANDLE_MULTIBYTE) + mbstate_t ps_new, ps_old; + int new_offset, old_offset, tmp; +#endif /* If we're at the right edge of a terminal that supports xn, we're ready to wrap around, so do so. This fixes problems with knowing @@ -819,20 +1050,98 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) emulators. In this calculation, TEMP is the physical screen position of the cursor. */ temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset); - if (temp == screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode - && _rl_last_v_pos == current_line - 1) + if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode + && _rl_last_v_pos == current_line - 1) { - if (new[0]) - putc (new[0], rl_outstream); +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + wchar_t wc; + mbstate_t ps; + int tempwidth, bytes; + size_t ret; + + /* This fixes only double-column characters, but if the wrapped + character comsumes more than three columns, spaces will be + inserted in the string buffer. */ + if (_rl_wrapped_line[current_line] > 0) + _rl_clear_to_eol (_rl_wrapped_line[current_line]); + + memset (&ps, 0, sizeof (mbstate_t)); + ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps); + if (ret == (size_t)-1 || ret == (size_t)-2) + { + tempwidth = 1; + ret = 1; + } + else if (ret == 0) + tempwidth = 0; + else + tempwidth = wcwidth (wc); + + if (tempwidth > 0) + { + int count; + bytes = ret; + for (count = 0; count < bytes; count++) + putc (new[count], rl_outstream); + _rl_last_c_pos = tempwidth; + _rl_last_v_pos++; + memset (&ps, 0, sizeof (mbstate_t)); + ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps); + if (ret != 0 && bytes != 0) + { + if (ret == (size_t)-1 || ret == (size_t)-2) + memmove (old+bytes, old+1, strlen (old+1)); + else + memmove (old+bytes, old+ret, strlen (old+ret)); + memcpy (old, new, bytes); + } + } + else + { + putc (' ', rl_outstream); + _rl_last_c_pos = 1; + _rl_last_v_pos++; + if (old[0] && new[0]) + old[0] = new[0]; + } + } else - putc (' ', rl_outstream); - _rl_last_c_pos = 1; /* XXX */ - _rl_last_v_pos++; - if (old[0] && new[0]) - old[0] = new[0]; +#endif + { + if (new[0]) + putc (new[0], rl_outstream); + else + putc (' ', rl_outstream); + _rl_last_c_pos = 1; /* XXX */ + _rl_last_v_pos++; + if (old[0] && new[0]) + old[0] = new[0]; + } } + /* Find first difference. */ +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + memset (&ps_new, 0, sizeof(mbstate_t)); + memset (&ps_old, 0, sizeof(mbstate_t)); + + new_offset = old_offset = 0; + for (ofd = old, nfd = new; + (ofd - old < omax) && *ofd && + _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); ) + { + old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY); + new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY); + ofd = old + old_offset; + nfd = new + new_offset; + } + } + else +#endif for (ofd = old, nfd = new; (ofd - old < omax) && *ofd && (*ofd == *nfd); ofd++, nfd++) @@ -849,6 +1158,33 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) return; wsatend = 1; /* flag for trailing whitespace */ + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY); + nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY); + while ((ols > ofd) && (nls > nfd)) + { + memset (&ps_old, 0, sizeof (mbstate_t)); + memset (&ps_new, 0, sizeof (mbstate_t)); + + _rl_adjust_point (old, ols - old, &ps_old); + _rl_adjust_point (new, nls - new, &ps_new); + + if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0) + break; + + if (*ols == ' ') + wsatend = 0; + + ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY); + nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY); + } + } + else + { +#endif /* HANDLE_MULTIBYTE */ ols = oe - 1; /* find last same */ nls = ne - 1; while ((ols > ofd) && (nls > nfd) && (*ols == *nls)) @@ -858,18 +1194,38 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) ols--; nls--; } +#if defined (HANDLE_MULTIBYTE) + } +#endif if (wsatend) { ols = oe; nls = ne; } +#if defined (HANDLE_MULTIBYTE) + /* This may not work for stateful encoding, but who cares? To handle + stateful encoding properly, we have to scan each string from the + beginning and compare. */ + else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0) +#else else if (*ols != *nls) +#endif { if (*ols) /* don't step past the NUL */ - ols++; + { + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY); + else + ols++; + } if (*nls) - nls++; + { + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY); + else + nls++; + } } /* count of invisible characters in the current invisible line. */ @@ -896,29 +1252,59 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) lendiff = local_prompt ? strlen (local_prompt) : 0; od = ofd - old; /* index of first difference in visible line */ if (current_line == 0 && !_rl_horizontal_scroll_mode && - term_cr && lendiff > visible_length && _rl_last_c_pos > 0 && - od > lendiff && _rl_last_c_pos < last_invisible) + _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 && + od >= lendiff && _rl_last_c_pos <= prompt_last_invisible) { - tputs (term_cr, 1, _rl_output_character_function); +#if defined (__MSDOS__) + putc ('\r', rl_outstream); +#else + tputs (_rl_term_cr, 1, _rl_output_character_function); +#endif _rl_output_some_chars (local_prompt, lendiff); - _rl_last_c_pos = lendiff; + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff); + else + _rl_last_c_pos = lendiff; } _rl_move_cursor_relative (od, old); - /* if (len (new) > len (old)) */ + /* if (len (new) > len (old)) + lendiff == difference in buffer + col_lendiff == difference on screen + When not using multibyte characters, these are equal */ lendiff = (nls - nfd) - (ols - ofd); + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + col_lendiff = _rl_col_width (new, nfd - new, nls - new) - _rl_col_width (old, ofd - old, ols - old); + else + col_lendiff = lendiff; /* If we are changing the number of invisible characters in a line, and the spot of first difference is before the end of the invisible chars, lendiff needs to be adjusted. */ if (current_line == 0 && !_rl_horizontal_scroll_mode && current_invis_chars != visible_wrap_offset) - lendiff += visible_wrap_offset - current_invis_chars; + { + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + lendiff += visible_wrap_offset - current_invis_chars; + col_lendiff += visible_wrap_offset - current_invis_chars; + } + else + { + lendiff += visible_wrap_offset - current_invis_chars; + col_lendiff = lendiff; + } + } /* Insert (diff (len (old), len (new)) ch. */ temp = ne - nfd; - if (lendiff > 0) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + col_temp = _rl_col_width (new, nfd - new, ne - new); + else + col_temp = temp; + + if (col_lendiff > 0) /* XXX - was lendiff */ { /* Non-zero if we're increasing the number of lines. */ int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin; @@ -926,17 +1312,17 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) use the terminal's capabilities. If we're growing the number of lines, make sure we actually cause the new line to wrap around on auto-wrapping terminals. */ - if (terminal_can_insert && ((2 * temp) >= lendiff || term_IC) && (!_rl_term_autowrap || !gl)) + if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl)) { - /* If lendiff > visible_length and _rl_last_c_pos == 0 and + /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and _rl_horizontal_scroll_mode == 1, inserting the characters with - term_IC or term_ic will screw up the screen because of the + _rl_term_IC or _rl_term_ic will screw up the screen because of the invisible characters. We need to just draw them. */ if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 || - lendiff <= visible_length || !current_invis_chars)) + lendiff <= prompt_visible_length || !current_invis_chars)) { - insert_some_chars (nfd, lendiff); - _rl_last_c_pos += lendiff; + insert_some_chars (nfd, lendiff, col_lendiff); + _rl_last_c_pos += col_lendiff; } else if (*ols == 0) { @@ -945,7 +1331,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) /* However, this screws up the rest of this block, which assumes you've done the insert because you can. */ _rl_output_some_chars (nfd, lendiff); - _rl_last_c_pos += lendiff; + _rl_last_c_pos += col_lendiff; } else { @@ -953,7 +1339,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) the end. We have invisible characters in this line. This is a dumb update. */ _rl_output_some_chars (nfd, temp); - _rl_last_c_pos += temp; + _rl_last_c_pos += col_temp; return; } /* Copy (new) chars to screen from first diff to last match. */ @@ -961,37 +1347,41 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) if ((temp - lendiff) > 0) { _rl_output_some_chars (nfd + lendiff, temp - lendiff); - _rl_last_c_pos += temp - lendiff; +#if 0 + _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff) - col_lendiff; +#else + _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff); +#endif } } else { /* cannot insert chars, write to EOL */ _rl_output_some_chars (nfd, temp); - _rl_last_c_pos += temp; + _rl_last_c_pos += col_temp; } } else /* Delete characters from line. */ { /* If possible and inexpensive to use terminal deletion, then do so. */ - if (term_dc && (2 * temp) >= -lendiff) + if (_rl_term_dc && (2 * col_temp) >= -col_lendiff) { /* If all we're doing is erasing the invisible characters in the prompt string, don't bother. It screws up the assumptions about what's on the screen. */ if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 && -lendiff == visible_wrap_offset) - lendiff = 0; + col_lendiff = 0; - if (lendiff) - delete_chars (-lendiff); /* delete (diff) characters */ + if (col_lendiff) + delete_chars (-col_lendiff); /* delete (diff) characters */ /* Copy (new) chars to screen from first diff to last match */ temp = nls - nfd; if (temp > 0) { _rl_output_some_chars (nfd, temp); - _rl_last_c_pos += temp; + _rl_last_c_pos += _rl_col_width (nfd, 0, temp);; } } /* Otherwise, print over the existing material. */ @@ -1000,15 +1390,20 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) if (temp > 0) { _rl_output_some_chars (nfd, temp); - _rl_last_c_pos += temp; + _rl_last_c_pos += col_temp; } lendiff = (oe - old) - (ne - new); - if (lendiff) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + col_lendiff = _rl_col_width (old, 0, oe - old) - _rl_col_width (new, 0, ne - new); + else + col_lendiff = lendiff; + + if (col_lendiff) { if (_rl_term_autowrap && current_line < inv_botlin) - space_to_eol (lendiff); + space_to_eol (col_lendiff); else - _rl_clear_to_eol (lendiff); + _rl_clear_to_eol (col_lendiff); } } } @@ -1029,6 +1424,61 @@ rl_on_new_line () return 0; } +/* Tell the update routines that we have moved onto a new line with the + prompt already displayed. Code originally from the version of readline + distributed with CLISP. */ +int +rl_on_new_line_with_prompt () +{ + int prompt_size, i, l, real_screenwidth, newlines; + char *prompt_last_line; + + /* Initialize visible_line and invisible_line to ensure that they can hold + the already-displayed prompt. */ + prompt_size = strlen (rl_prompt) + 1; + init_line_structures (prompt_size); + + /* Make sure the line structures hold the already-displayed prompt for + redisplay. */ + strcpy (visible_line, rl_prompt); + strcpy (invisible_line, rl_prompt); + + /* If the prompt contains newlines, take the last tail. */ + prompt_last_line = strrchr (rl_prompt, '\n'); + if (!prompt_last_line) + prompt_last_line = rl_prompt; + + l = strlen (prompt_last_line); + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l); + else + _rl_last_c_pos = l; + + /* Dissect prompt_last_line into screen lines. Note that here we have + to use the real screenwidth. Readline's notion of screenwidth might be + one less, see terminal.c. */ + real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1); + _rl_last_v_pos = l / real_screenwidth; + /* If the prompt length is a multiple of real_screenwidth, we don't know + whether the cursor is at the end of the last line, or already at the + beginning of the next line. Output a newline just to be safe. */ + if (l > 0 && (l % real_screenwidth) == 0) + _rl_output_some_chars ("\n", 1); + last_lmargin = 0; + + newlines = 0; i = 0; + while (i <= l) + { + _rl_vis_botlin = newlines; + vis_lbreaks[newlines++] = i; + i += real_screenwidth; + } + vis_lbreaks[newlines] = l; + visible_wrap_offset = 0; + + return 0; +} + /* Actually update the display, period. */ int rl_forced_update_display () @@ -1052,24 +1502,31 @@ rl_forced_update_display () void _rl_move_cursor_relative (new, data) int new; - char *data; + const char *data; { register int i; /* If we don't have to do anything, then return. */ +#if defined (HANDLE_MULTIBYTE) + /* If we have multibyte characters, NEW is indexed by the buffer point in + a multibyte string, but _rl_last_c_pos is the display position. In + this case, NEW's display position is not obvious. */ + if ((MB_CUR_MAX == 1 || rl_byte_oriented ) && _rl_last_c_pos == new) return; +#else if (_rl_last_c_pos == new) return; +#endif /* It may be faster to output a CR, and then move forwards instead of moving backwards. */ /* i == current physical cursor position. */ i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset); if (new == 0 || CR_FASTER (new, _rl_last_c_pos) || - (_rl_term_autowrap && i == screenwidth)) + (_rl_term_autowrap && i == _rl_screenwidth)) { #if defined (__MSDOS__) putc ('\r', rl_outstream); #else - tputs (term_cr, 1, _rl_output_character_function); + tputs (_rl_term_cr, 1, _rl_output_character_function); #endif /* !__MSDOS__ */ _rl_last_c_pos = 0; } @@ -1086,22 +1543,70 @@ _rl_move_cursor_relative (new, data) That kind of control is for people who don't know what the data is underneath the cursor. */ #if defined (HACK_TERMCAP_MOTION) - extern char *term_forward_char; - - if (term_forward_char) - for (i = _rl_last_c_pos; i < new; i++) - tputs (term_forward_char, 1, _rl_output_character_function); + if (_rl_term_forward_char) + { + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + int width; + width = _rl_col_width (data, _rl_last_c_pos, new); + for (i = 0; i < width; i++) + tputs (_rl_term_forward_char, 1, _rl_output_character_function); + } + else + { + for (i = _rl_last_c_pos; i < new; i++) + tputs (_rl_term_forward_char, 1, _rl_output_character_function); + } + } + else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + tputs (_rl_term_cr, 1, _rl_output_character_function); + for (i = 0; i < new; i++) + putc (data[i], rl_outstream); + } else for (i = _rl_last_c_pos; i < new; i++) putc (data[i], rl_outstream); -#else - for (i = _rl_last_c_pos; i < new; i++) - putc (data[i], rl_outstream); -#endif /* HACK_TERMCAP_MOTION */ + +#else /* !HACK_TERMCAP_MOTION */ + + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + tputs (_rl_term_cr, 1, _rl_output_character_function); + for (i = 0; i < new; i++) + putc (data[i], rl_outstream); + } + else + for (i = _rl_last_c_pos; i < new; i++) + putc (data[i], rl_outstream); + +#endif /* !HACK_TERMCAP_MOTION */ + } +#if defined (HANDLE_MULTIBYTE) + /* NEW points to the buffer point, but _rl_last_c_pos is the display point. + The byte length of the string is probably bigger than the column width + of the string, which means that if NEW == _rl_last_c_pos, then NEW's + display point is less than _rl_last_c_pos. */ + else if (_rl_last_c_pos >= new) +#else else if (_rl_last_c_pos > new) - _rl_backspace (_rl_last_c_pos - new); - _rl_last_c_pos = new; +#endif + { + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + tputs (_rl_term_cr, 1, _rl_output_character_function); + for (i = 0; i < new; i++) + putc (data[i], rl_outstream); + } + else + _rl_backspace (_rl_last_c_pos - new); + } + + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + _rl_last_c_pos = _rl_col_width (data, 0, new); + else + _rl_last_c_pos = new; } /* PWP: move the cursor up or down. */ @@ -1111,32 +1616,27 @@ _rl_move_vert (to) { register int delta, i; - if (_rl_last_v_pos == to || to > screenheight) + if (_rl_last_v_pos == to || to > _rl_screenheight) return; -#if defined (__GO32__) - { - int row, col; - - ScreenGetCursor (&row, &col); - ScreenSetCursor ((row + to - _rl_last_v_pos), col); - } -#else /* !__GO32__ */ - if ((delta = to - _rl_last_v_pos) > 0) { for (i = 0; i < delta; i++) putc ('\n', rl_outstream); - tputs (term_cr, 1, _rl_output_character_function); +#if defined (__MSDOS__) + putc ('\r', rl_outstream); +#else + tputs (_rl_term_cr, 1, _rl_output_character_function); +#endif _rl_last_c_pos = 0; } else { /* delta < 0 */ - if (term_up && *term_up) + if (_rl_term_up && *_rl_term_up) for (i = 0; i < -delta; i++) - tputs (term_up, 1, _rl_output_character_function); + tputs (_rl_term_up, 1, _rl_output_character_function); } -#endif /* !__GO32__ */ + _rl_last_v_pos = to; /* Now TO is here */ } @@ -1193,7 +1693,7 @@ rl_character_len (c, pos) if (CTRL_CHAR (c) || c == RUBOUT) return (2); - return ((isprint (uc)) ? 1 : 2); + return ((ISPRINT (uc)) ? 1 : 2); } /* How to print things in the "echo-area". The prompt is treated as a @@ -1220,7 +1720,12 @@ rl_message (va_alist) format = va_arg (args, char *); #endif +#if defined (HAVE_VSNPRINTF) + vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args); +#else vsprintf (msg_buf, format, args); + msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */ +#endif va_end (args); rl_display_prompt = msg_buf; @@ -1229,9 +1734,12 @@ rl_message (va_alist) } #else /* !USE_VARARGS */ int -rl_message (char *format, void *arg1, void *arg2) +rl_message (format, arg1, arg2) + char *format; + int arg1, arg2; { sprintf (msg_buf, format, arg1, arg2); + msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */ rl_display_prompt = msg_buf; (*rl_redisplay_function) (); return 0; @@ -1252,7 +1760,7 @@ rl_reset_line_state () { rl_on_new_line (); - rl_display_prompt = rl_prompt ? rl_prompt : ""; + rl_display_prompt = (char*)(rl_prompt ? rl_prompt : ""); forced_display = 1; return 0; } @@ -1267,25 +1775,23 @@ rl_save_prompt () { saved_local_prompt = local_prompt; saved_local_prefix = local_prompt_prefix; - saved_last_invisible = last_invisible; - saved_visible_length = visible_length; + saved_last_invisible = prompt_last_invisible; + saved_visible_length = prompt_visible_length; local_prompt = local_prompt_prefix = (char *)0; - last_invisible = visible_length = 0; + prompt_last_invisible = prompt_visible_length = 0; } void rl_restore_prompt () { - if (local_prompt) - free (local_prompt); - if (local_prompt_prefix) - free (local_prompt_prefix); + FREE (local_prompt); + FREE (local_prompt_prefix); local_prompt = saved_local_prompt; local_prompt_prefix = saved_local_prefix; - last_invisible = saved_last_invisible; - visible_length = saved_visible_length; + prompt_last_invisible = saved_last_invisible; + prompt_visible_length = saved_visible_length; } char * @@ -1300,7 +1806,7 @@ _rl_make_prompt_for_search (pchar) if (saved_local_prompt == 0) { len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0; - pmt = xmalloc (len + 2); + pmt = (char *)xmalloc (len + 2); if (len) strcpy (pmt, rl_prompt); pmt[len] = pchar; @@ -1309,14 +1815,14 @@ _rl_make_prompt_for_search (pchar) else { len = *saved_local_prompt ? strlen (saved_local_prompt) : 0; - pmt = xmalloc (len + 2); + pmt = (char *)xmalloc (len + 2); if (len) strcpy (pmt, saved_local_prompt); pmt[len] = pchar; pmt[len+1] = '\0'; local_prompt = savestring (pmt); - last_invisible = saved_last_invisible; - visible_length = saved_visible_length + 1; + prompt_last_invisible = saved_last_invisible; + prompt_visible_length = saved_visible_length + 1; } return pmt; } @@ -1343,11 +1849,9 @@ void _rl_clear_to_eol (count) int count; { -#if !defined (__GO32__) - if (term_clreol) - tputs (term_clreol, 1, _rl_output_character_function); + if (_rl_term_clreol) + tputs (_rl_term_clreol, 1, _rl_output_character_function); else if (count) -#endif /* !__GO32__ */ space_to_eol (count); } @@ -1368,39 +1872,29 @@ space_to_eol (count) void _rl_clear_screen () { -#if !defined (__GO32__) - if (term_clrpag) - tputs (term_clrpag, 1, _rl_output_character_function); + if (_rl_term_clrpag) + tputs (_rl_term_clrpag, 1, _rl_output_character_function); else -#endif /* !__GO32__ */ - crlf (); + rl_crlf (); } -/* Insert COUNT characters from STRING to the output stream. */ +/* Insert COUNT characters from STRING to the output stream at column COL. */ static void -insert_some_chars (string, count) +insert_some_chars (string, count, col) char *string; - int count; + int count, col; { -#if defined (__GO32__) - int row, col, width; - char *row_start; - - ScreenGetCursor (&row, &col); - width = ScreenCols (); - row_start = ScreenPrimary + (row * width); - - memcpy (row_start + col + count, row_start + col, width - col - count); - - /* Place the text on the screen. */ - _rl_output_some_chars (string, count); -#else /* !_GO32 */ + /* DEBUGGING */ + if (MB_CUR_MAX == 1 || rl_byte_oriented) + if (count != col) + fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col); /* If IC is defined, then we do not have to "enter" insert mode. */ - if (term_IC) + if (_rl_term_IC) { char *buffer; - buffer = tgoto (term_IC, 0, count); + + buffer = tgoto (_rl_term_IC, 0, col); tputs (buffer, 1, _rl_output_character_function); _rl_output_some_chars (string, count); } @@ -1409,15 +1903,15 @@ insert_some_chars (string, count) register int i; /* If we have to turn on insert-mode, then do so. */ - if (term_im && *term_im) - tputs (term_im, 1, _rl_output_character_function); + if (_rl_term_im && *_rl_term_im) + tputs (_rl_term_im, 1, _rl_output_character_function); /* If there is a special command for inserting characters, then use that first to open up the space. */ - if (term_ic && *term_ic) + if (_rl_term_ic && *_rl_term_ic) { - for (i = count; i--; ) - tputs (term_ic, 1, _rl_output_character_function); + for (i = col; i--; ) + tputs (_rl_term_ic, 1, _rl_output_character_function); } /* Print the text. */ @@ -1425,10 +1919,9 @@ insert_some_chars (string, count) /* If there is a string to turn off insert mode, we had best use it now. */ - if (term_ei && *term_ei) - tputs (term_ei, 1, _rl_output_character_function); + if (_rl_term_ei && *_rl_term_ei) + tputs (_rl_term_ei, 1, _rl_output_character_function); } -#endif /* !__GO32__ */ } /* Delete COUNT characters from the display line. */ @@ -1436,34 +1929,21 @@ static void delete_chars (count) int count; { -#if defined (__GO32__) - int row, col, width; - char *row_start; - - ScreenGetCursor (&row, &col); - width = ScreenCols (); - row_start = ScreenPrimary + (row * width); - - memcpy (row_start + col, row_start + col + count, width - col - count); - memset (row_start + width - count, 0, count * 2); -#else /* !_GO32 */ - - if (count > screenwidth) /* XXX */ + if (count > _rl_screenwidth) /* XXX */ return; - if (term_DC && *term_DC) + if (_rl_term_DC && *_rl_term_DC) { char *buffer; - buffer = tgoto (term_DC, count, count); + buffer = tgoto (_rl_term_DC, count, count); tputs (buffer, count, _rl_output_character_function); } else { - if (term_dc && *term_dc) + if (_rl_term_dc && *_rl_term_dc) while (count--) - tputs (term_dc, 1, _rl_output_character_function); + tputs (_rl_term_dc, 1, _rl_output_character_function); } -#endif /* !__GO32__ */ } void @@ -1482,16 +1962,17 @@ _rl_update_final () } _rl_move_vert (_rl_vis_botlin); /* If we've wrapped lines, remove the final xterm line-wrap flag. */ - if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == screenwidth)) + if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth)) { char *last_line; - last_line = &visible_line[inv_lbreaks[_rl_vis_botlin]]; - _rl_move_cursor_relative (screenwidth - 1, last_line); + + last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; + _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); _rl_clear_to_eol (0); - putc (last_line[screenwidth - 1], rl_outstream); + putc (last_line[_rl_screenwidth - 1], rl_outstream); } _rl_vis_botlin = 0; - crlf (); + rl_crlf (); fflush (rl_outstream); rl_display_fixed++; } @@ -1500,53 +1981,90 @@ _rl_update_final () static void cr () { - if (term_cr) + if (_rl_term_cr) { - tputs (term_cr, 1, _rl_output_character_function); +#if defined (__MSDOS__) + putc ('\r', rl_outstream); +#else + tputs (_rl_term_cr, 1, _rl_output_character_function); +#endif _rl_last_c_pos = 0; } } +/* Redraw the last line of a multi-line prompt that may possibly contain + terminal escape sequences. Called with the cursor at column 0 of the + line to draw the prompt on. */ +static void +redraw_prompt (t) + char *t; +{ + char *oldp, *oldl, *oldlprefix; + int oldlen, oldlast, oldplen, oldninvis; + + /* Geez, I should make this a struct. */ + oldp = rl_display_prompt; + oldl = local_prompt; + oldlprefix = local_prompt_prefix; + oldlen = prompt_visible_length; + oldplen = prompt_prefix_length; + oldlast = prompt_last_invisible; + oldninvis = prompt_invis_chars_first_line; + + rl_display_prompt = t; + local_prompt = expand_prompt (t, &prompt_visible_length, + &prompt_last_invisible, + &prompt_invis_chars_first_line); + local_prompt_prefix = (char *)NULL; + rl_forced_update_display (); + + rl_display_prompt = oldp; + local_prompt = oldl; + local_prompt_prefix = oldlprefix; + prompt_visible_length = oldlen; + prompt_prefix_length = oldplen; + prompt_last_invisible = oldlast; + prompt_invis_chars_first_line = oldninvis; +} + /* Redisplay the current line after a SIGWINCH is received. */ void _rl_redisplay_after_sigwinch () { - char *t, *oldl, *oldlprefix; - const char *oldp; + char *t; /* Clear the current line and put the cursor at column 0. Make sure the right thing happens if we have wrapped to a new screen line. */ - if (term_cr) + if (_rl_term_cr) { - tputs (term_cr, 1, _rl_output_character_function); +#if defined (__MSDOS__) + putc ('\r', rl_outstream); +#else + tputs (_rl_term_cr, 1, _rl_output_character_function); +#endif _rl_last_c_pos = 0; - if (term_clreol) - tputs (term_clreol, 1, _rl_output_character_function); +#if defined (__MSDOS__) + space_to_eol (_rl_screenwidth); + putc ('\r', rl_outstream); +#else + if (_rl_term_clreol) + tputs (_rl_term_clreol, 1, _rl_output_character_function); else { - space_to_eol (screenwidth); - tputs (term_cr, 1, _rl_output_character_function); + space_to_eol (_rl_screenwidth); + tputs (_rl_term_cr, 1, _rl_output_character_function); } +#endif if (_rl_last_v_pos > 0) _rl_move_vert (0); } else - crlf (); + rl_crlf (); /* Redraw only the last line of a multi-line prompt. */ t = strrchr (rl_display_prompt, '\n'); if (t) - { - oldp = rl_display_prompt; - oldl = local_prompt; - oldlprefix = local_prompt_prefix; - rl_display_prompt = ++t; - local_prompt = local_prompt_prefix = (char *)NULL; - rl_forced_update_display (); - rl_display_prompt = oldp; - local_prompt = oldl; - local_prompt_prefix = oldlprefix; - } + redraw_prompt (++t); else rl_forced_update_display (); } @@ -1571,3 +2089,109 @@ _rl_erase_entire_line () cr (); fflush (rl_outstream); } + +/* return the `current display line' of the cursor -- the number of lines to + move up to get to the first screen line of the current readline line. */ +int +_rl_current_display_line () +{ + int ret, nleft; + + /* Find out whether or not there might be invisible characters in the + editing buffer. */ + if (rl_display_prompt == rl_prompt) + nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length; + else + nleft = _rl_last_c_pos - _rl_screenwidth; + + if (nleft > 0) + ret = 1 + nleft / _rl_screenwidth; + else + ret = 0; + + return ret; +} + +#if defined (HANDLE_MULTIBYTE) +/* Calculate the number of screen columns occupied by STR from START to END. + In the case of multibyte characters with stateful encoding, we have to + scan from the beginning of the string to take the state into account. */ +static int +_rl_col_width (str, start, end) + char *str; + int start, end; +{ + wchar_t wc; + mbstate_t ps = {0}; + int tmp, point, width, max; + + if (end <= start) + return 0; + + point = 0; + max = end; + + while (point < start) + { + tmp = mbrlen (str + point, max, &ps); + if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2) + { + /* In this case, the bytes are invalid or too short to compose a + multibyte character, so we assume that the first byte represents + a single character. */ + point++; + max--; + + /* Clear the state of the byte sequence, because in this case the + effect of mbstate is undefined. */ + memset (&ps, 0, sizeof (mbstate_t)); + } + else if (tmp == 0) + break; /* Found '\0' */ + else + { + point += tmp; + max -= tmp; + } + } + + /* If START is not a byte that starts a character, then POINT will be + greater than START. In this case, assume that (POINT - START) gives + a byte count that is the number of columns of difference. */ + width = point - start; + + while (point < end) + { + tmp = mbrtowc (&wc, str + point, max, &ps); + if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2) + { + /* In this case, the bytes are invalid or too short to compose a + multibyte character, so we assume that the first byte represents + a single character. */ + point++; + max--; + + /* and assume that the byte occupies a single column. */ + width++; + + /* Clear the state of the byte sequence, because in this case the + effect of mbstate is undefined. */ + memset (&ps, 0, sizeof (mbstate_t)); + } + else if (tmp == 0) + break; /* Found '\0' */ + else + { + point += tmp; + max -= tmp; + tmp = wcwidth(wc); + width += (tmp >= 0) ? tmp : 1; + } + } + + width += point - end; + + return width; +} +#endif /* HANDLE_MULTIBYTE */ + diff --git a/readline/emacs_keymap.c b/readline/emacs_keymap.c index 4ba385843f6..ca9d1343b65 100644 --- a/readline/emacs_keymap.c +++ b/readline/emacs_keymap.c @@ -7,7 +7,7 @@ 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 1, or + 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 @@ -18,7 +18,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #if !defined (BUFSIZ) #include @@ -33,197 +33,185 @@ KEYMAP_ENTRY_ARRAY emacs_standard_keymap = { /* Control keys. */ - { ISFUNC, rl_set_mark }, /* Control-@ */ - { ISFUNC, rl_beg_of_line }, /* Control-a */ - { ISFUNC, rl_backward }, /* Control-b */ - { ISFUNC, (Function *)0x0 }, /* Control-c */ - { ISFUNC, rl_delete }, /* Control-d */ - { ISFUNC, rl_end_of_line }, /* Control-e */ - { ISFUNC, rl_forward }, /* Control-f */ - { ISFUNC, rl_abort }, /* Control-g */ - { ISFUNC, rl_rubout }, /* Control-h */ - { ISFUNC, rl_complete }, /* Control-i */ - { ISFUNC, rl_newline }, /* Control-j */ - { ISFUNC, rl_kill_line }, /* Control-k */ - { ISFUNC, rl_clear_screen }, /* Control-l */ - { ISFUNC, rl_newline }, /* Control-m */ - { ISFUNC, rl_get_next_history }, /* Control-n */ - { ISFUNC, (Function *)0x0 }, /* Control-o */ - { ISFUNC, rl_get_previous_history }, /* Control-p */ - { ISFUNC, rl_quoted_insert }, /* Control-q */ - { ISFUNC, rl_reverse_search_history }, /* Control-r */ - { ISFUNC, rl_forward_search_history }, /* Control-s */ - { ISFUNC, rl_transpose_chars }, /* Control-t */ - { ISFUNC, rl_unix_line_discard }, /* Control-u */ - { ISFUNC, rl_quoted_insert }, /* Control-v */ - { ISFUNC, rl_unix_word_rubout }, /* Control-w */ - { ISKMAP, (Function *)emacs_ctlx_keymap }, /* Control-x */ - { ISFUNC, rl_yank }, /* Control-y */ - { ISFUNC, (Function *)0x0 }, /* Control-z */ - { ISKMAP, (Function *)emacs_meta_keymap }, /* Control-[ */ - { ISFUNC, (Function *)0x0 }, /* Control-\ */ - { ISFUNC, rl_char_search }, /* Control-] */ - { ISFUNC, (Function *)0x0 }, /* Control-^ */ - { ISFUNC, rl_undo_command }, /* Control-_ */ + { ISFUNC, rl_set_mark }, /* Control-@ */ + { ISFUNC, rl_beg_of_line }, /* Control-a */ + { ISFUNC, rl_backward_char }, /* Control-b */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-c */ + { ISFUNC, rl_delete }, /* Control-d */ + { ISFUNC, rl_end_of_line }, /* Control-e */ + { ISFUNC, rl_forward_char }, /* Control-f */ + { ISFUNC, rl_abort }, /* Control-g */ + { ISFUNC, rl_rubout }, /* Control-h */ + { ISFUNC, rl_complete }, /* Control-i */ + { ISFUNC, rl_newline }, /* Control-j */ + { ISFUNC, rl_kill_line }, /* Control-k */ + { ISFUNC, rl_clear_screen }, /* Control-l */ + { ISFUNC, rl_newline }, /* Control-m */ + { ISFUNC, rl_get_next_history }, /* Control-n */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-o */ + { ISFUNC, rl_get_previous_history }, /* Control-p */ + { ISFUNC, rl_quoted_insert }, /* Control-q */ + { ISFUNC, rl_reverse_search_history }, /* Control-r */ + { ISFUNC, rl_forward_search_history }, /* Control-s */ + { ISFUNC, rl_transpose_chars }, /* Control-t */ + { ISFUNC, rl_unix_line_discard }, /* Control-u */ + { ISFUNC, rl_quoted_insert }, /* Control-v */ + { ISFUNC, rl_unix_word_rubout }, /* Control-w */ + { ISKMAP, (rl_command_func_t *)emacs_ctlx_keymap }, /* Control-x */ + { ISFUNC, rl_yank }, /* Control-y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-z */ + { ISKMAP, (rl_command_func_t *)emacs_meta_keymap }, /* Control-[ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-\ */ + { ISFUNC, rl_char_search }, /* Control-] */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-^ */ + { ISFUNC, rl_undo_command }, /* Control-_ */ /* The start of printing characters. */ - { ISFUNC, rl_insert }, /* SPACE */ - { ISFUNC, rl_insert }, /* ! */ - { ISFUNC, rl_insert }, /* " */ - { ISFUNC, rl_insert }, /* # */ - { ISFUNC, rl_insert }, /* $ */ - { ISFUNC, rl_insert }, /* % */ - { ISFUNC, rl_insert }, /* & */ - { ISFUNC, rl_insert }, /* ' */ - { ISFUNC, rl_insert }, /* ( */ -#if defined (PAREN_MATCHING) - { ISFUNC, rl_insert_close }, /* ) */ -#else - { ISFUNC, rl_insert }, /* ) */ -#endif /* !PAREN_MATCHING */ - { ISFUNC, rl_insert }, /* * */ - { ISFUNC, rl_insert }, /* + */ - { ISFUNC, rl_insert }, /* , */ - { ISFUNC, rl_insert }, /* - */ - { ISFUNC, rl_insert }, /* . */ - { ISFUNC, rl_insert }, /* / */ - - /* Regular digits. */ - { ISFUNC, rl_insert }, /* 0 */ - { ISFUNC, rl_insert }, /* 1 */ - { ISFUNC, rl_insert }, /* 2 */ - { ISFUNC, rl_insert }, /* 3 */ - { ISFUNC, rl_insert }, /* 4 */ - { ISFUNC, rl_insert }, /* 5 */ - { ISFUNC, rl_insert }, /* 6 */ - { ISFUNC, rl_insert }, /* 7 */ - { ISFUNC, rl_insert }, /* 8 */ - { ISFUNC, rl_insert }, /* 9 */ + { ISFUNC, rl_insert }, /* SPACE */ + { ISFUNC, rl_insert }, /* ! */ + { ISFUNC, rl_insert }, /* " */ + { ISFUNC, rl_insert }, /* # */ + { ISFUNC, rl_insert }, /* $ */ + { ISFUNC, rl_insert }, /* % */ + { ISFUNC, rl_insert }, /* & */ + { ISFUNC, rl_insert }, /* ' */ + { ISFUNC, rl_insert }, /* ( */ + { ISFUNC, rl_insert }, /* ) */ + { ISFUNC, rl_insert }, /* * */ + { ISFUNC, rl_insert }, /* + */ + { ISFUNC, rl_insert }, /* , */ + { ISFUNC, rl_insert }, /* - */ + { ISFUNC, rl_insert }, /* . */ + { ISFUNC, rl_insert }, /* / */ + + /* Regular digits. */ + { ISFUNC, rl_insert }, /* 0 */ + { ISFUNC, rl_insert }, /* 1 */ + { ISFUNC, rl_insert }, /* 2 */ + { ISFUNC, rl_insert }, /* 3 */ + { ISFUNC, rl_insert }, /* 4 */ + { ISFUNC, rl_insert }, /* 5 */ + { ISFUNC, rl_insert }, /* 6 */ + { ISFUNC, rl_insert }, /* 7 */ + { ISFUNC, rl_insert }, /* 8 */ + { ISFUNC, rl_insert }, /* 9 */ /* A little more punctuation. */ - { ISFUNC, rl_insert }, /* : */ - { ISFUNC, rl_insert }, /* ; */ - { ISFUNC, rl_insert }, /* < */ - { ISFUNC, rl_insert }, /* = */ - { ISFUNC, rl_insert }, /* > */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* @ */ + { ISFUNC, rl_insert }, /* : */ + { ISFUNC, rl_insert }, /* ; */ + { ISFUNC, rl_insert }, /* < */ + { ISFUNC, rl_insert }, /* = */ + { ISFUNC, rl_insert }, /* > */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* @ */ /* Uppercase alphabet. */ - { ISFUNC, rl_insert }, /* A */ - { ISFUNC, rl_insert }, /* B */ - { ISFUNC, rl_insert }, /* C */ - { ISFUNC, rl_insert }, /* D */ - { ISFUNC, rl_insert }, /* E */ - { ISFUNC, rl_insert }, /* F */ - { ISFUNC, rl_insert }, /* G */ - { ISFUNC, rl_insert }, /* H */ - { ISFUNC, rl_insert }, /* I */ - { ISFUNC, rl_insert }, /* J */ - { ISFUNC, rl_insert }, /* K */ - { ISFUNC, rl_insert }, /* L */ - { ISFUNC, rl_insert }, /* M */ - { ISFUNC, rl_insert }, /* N */ - { ISFUNC, rl_insert }, /* O */ - { ISFUNC, rl_insert }, /* P */ - { ISFUNC, rl_insert }, /* Q */ - { ISFUNC, rl_insert }, /* R */ - { ISFUNC, rl_insert }, /* S */ - { ISFUNC, rl_insert }, /* T */ - { ISFUNC, rl_insert }, /* U */ - { ISFUNC, rl_insert }, /* V */ - { ISFUNC, rl_insert }, /* W */ - { ISFUNC, rl_insert }, /* X */ - { ISFUNC, rl_insert }, /* Y */ - { ISFUNC, rl_insert }, /* Z */ + { ISFUNC, rl_insert }, /* A */ + { ISFUNC, rl_insert }, /* B */ + { ISFUNC, rl_insert }, /* C */ + { ISFUNC, rl_insert }, /* D */ + { ISFUNC, rl_insert }, /* E */ + { ISFUNC, rl_insert }, /* F */ + { ISFUNC, rl_insert }, /* G */ + { ISFUNC, rl_insert }, /* H */ + { ISFUNC, rl_insert }, /* I */ + { ISFUNC, rl_insert }, /* J */ + { ISFUNC, rl_insert }, /* K */ + { ISFUNC, rl_insert }, /* L */ + { ISFUNC, rl_insert }, /* M */ + { ISFUNC, rl_insert }, /* N */ + { ISFUNC, rl_insert }, /* O */ + { ISFUNC, rl_insert }, /* P */ + { ISFUNC, rl_insert }, /* Q */ + { ISFUNC, rl_insert }, /* R */ + { ISFUNC, rl_insert }, /* S */ + { ISFUNC, rl_insert }, /* T */ + { ISFUNC, rl_insert }, /* U */ + { ISFUNC, rl_insert }, /* V */ + { ISFUNC, rl_insert }, /* W */ + { ISFUNC, rl_insert }, /* X */ + { ISFUNC, rl_insert }, /* Y */ + { ISFUNC, rl_insert }, /* Z */ /* Some more punctuation. */ - { ISFUNC, rl_insert }, /* [ */ - { ISFUNC, rl_insert }, /* \ */ -#if defined (PAREN_MATCHING) - { ISFUNC, rl_insert_close }, /* ] */ -#else - { ISFUNC, rl_insert }, /* ] */ -#endif /* !PAREN_MATCHING */ - { ISFUNC, rl_insert }, /* ^ */ - { ISFUNC, rl_insert }, /* _ */ - { ISFUNC, rl_insert }, /* ` */ + { ISFUNC, rl_insert }, /* [ */ + { ISFUNC, rl_insert }, /* \ */ + { ISFUNC, rl_insert }, /* ] */ + { ISFUNC, rl_insert }, /* ^ */ + { ISFUNC, rl_insert }, /* _ */ + { ISFUNC, rl_insert }, /* ` */ /* Lowercase alphabet. */ - { ISFUNC, rl_insert }, /* a */ - { ISFUNC, rl_insert }, /* b */ - { ISFUNC, rl_insert }, /* c */ - { ISFUNC, rl_insert }, /* d */ - { ISFUNC, rl_insert }, /* e */ - { ISFUNC, rl_insert }, /* f */ - { ISFUNC, rl_insert }, /* g */ - { ISFUNC, rl_insert }, /* h */ - { ISFUNC, rl_insert }, /* i */ - { ISFUNC, rl_insert }, /* j */ - { ISFUNC, rl_insert }, /* k */ - { ISFUNC, rl_insert }, /* l */ - { ISFUNC, rl_insert }, /* m */ - { ISFUNC, rl_insert }, /* n */ - { ISFUNC, rl_insert }, /* o */ - { ISFUNC, rl_insert }, /* p */ - { ISFUNC, rl_insert }, /* q */ - { ISFUNC, rl_insert }, /* r */ - { ISFUNC, rl_insert }, /* s */ - { ISFUNC, rl_insert }, /* t */ - { ISFUNC, rl_insert }, /* u */ - { ISFUNC, rl_insert }, /* v */ - { ISFUNC, rl_insert }, /* w */ - { ISFUNC, rl_insert }, /* x */ - { ISFUNC, rl_insert }, /* y */ - { ISFUNC, rl_insert }, /* z */ + { ISFUNC, rl_insert }, /* a */ + { ISFUNC, rl_insert }, /* b */ + { ISFUNC, rl_insert }, /* c */ + { ISFUNC, rl_insert }, /* d */ + { ISFUNC, rl_insert }, /* e */ + { ISFUNC, rl_insert }, /* f */ + { ISFUNC, rl_insert }, /* g */ + { ISFUNC, rl_insert }, /* h */ + { ISFUNC, rl_insert }, /* i */ + { ISFUNC, rl_insert }, /* j */ + { ISFUNC, rl_insert }, /* k */ + { ISFUNC, rl_insert }, /* l */ + { ISFUNC, rl_insert }, /* m */ + { ISFUNC, rl_insert }, /* n */ + { ISFUNC, rl_insert }, /* o */ + { ISFUNC, rl_insert }, /* p */ + { ISFUNC, rl_insert }, /* q */ + { ISFUNC, rl_insert }, /* r */ + { ISFUNC, rl_insert }, /* s */ + { ISFUNC, rl_insert }, /* t */ + { ISFUNC, rl_insert }, /* u */ + { ISFUNC, rl_insert }, /* v */ + { ISFUNC, rl_insert }, /* w */ + { ISFUNC, rl_insert }, /* x */ + { ISFUNC, rl_insert }, /* y */ + { ISFUNC, rl_insert }, /* z */ /* Final punctuation. */ - { ISFUNC, rl_insert }, /* { */ - { ISFUNC, rl_insert }, /* | */ -#if defined (PAREN_MATCHING) - { ISFUNC, rl_insert_close }, /* } */ -#else - { ISFUNC, rl_insert }, /* } */ -#endif /* !PAREN_MATCHING */ - { ISFUNC, rl_insert }, /* ~ */ - { ISFUNC, rl_rubout }, /* RUBOUT */ + { ISFUNC, rl_insert }, /* { */ + { ISFUNC, rl_insert }, /* | */ + { ISFUNC, rl_insert }, /* } */ + { ISFUNC, rl_insert }, /* ~ */ + { ISFUNC, rl_rubout }, /* RUBOUT */ #if KEYMAP_SIZE > 128 /* Pure 8-bit characters (128 - 159). These might be used in some character sets. */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ /* ISO Latin-1 characters (160 - 255) */ { ISFUNC, rl_insert }, /* No-break space */ @@ -328,78 +316,78 @@ KEYMAP_ENTRY_ARRAY emacs_standard_keymap = { KEYMAP_ENTRY_ARRAY emacs_meta_keymap = { /* Meta keys. Just like above, but the high bit is set. */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-@ */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-a */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-b */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-c */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-d */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-e */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-f */ - { ISFUNC, rl_abort }, /* Meta-Control-g */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-@ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-a */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-b */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-c */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-d */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-e */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-f */ + { ISFUNC, rl_abort }, /* Meta-Control-g */ { ISFUNC, rl_backward_kill_word }, /* Meta-Control-h */ - { ISFUNC, rl_tab_insert }, /* Meta-Control-i */ - { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-j */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-k */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-l */ - { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-m */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-n */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-o */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-p */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-q */ - { ISFUNC, rl_revert_line }, /* Meta-Control-r */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-s */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-t */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-u */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-v */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-w */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-x */ - { ISFUNC, rl_yank_nth_arg }, /* Meta-Control-y */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-z */ + { ISFUNC, rl_tab_insert }, /* Meta-Control-i */ + { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-j */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-k */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-l */ + { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-m */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-n */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-o */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-p */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-q */ + { ISFUNC, rl_revert_line }, /* Meta-Control-r */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-s */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-t */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-u */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-v */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-w */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-x */ + { ISFUNC, rl_yank_nth_arg }, /* Meta-Control-y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-z */ - { ISFUNC, rl_complete }, /* Meta-Control-[ */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-\ */ + { ISFUNC, rl_complete }, /* Meta-Control-[ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-\ */ { ISFUNC, rl_backward_char_search }, /* Meta-Control-] */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-^ */ - { ISFUNC, (Function *)0x0 }, /* Meta-Control-_ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-^ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-Control-_ */ /* The start of printing characters. */ - { ISFUNC, rl_set_mark }, /* Meta-SPACE */ - { ISFUNC, (Function *)0x0 }, /* Meta-! */ - { ISFUNC, (Function *)0x0 }, /* Meta-" */ - { ISFUNC, rl_insert_comment },/* Meta-# */ - { ISFUNC, (Function *)0x0 }, /* Meta-$ */ - { ISFUNC, (Function *)0x0 }, /* Meta-% */ - { ISFUNC, rl_tilde_expand }, /* Meta-& */ - { ISFUNC, (Function *)0x0 }, /* Meta-' */ - { ISFUNC, (Function *)0x0 }, /* Meta-( */ - { ISFUNC, (Function *)0x0 }, /* Meta-) */ + { ISFUNC, rl_set_mark }, /* Meta-SPACE */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-! */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-" */ + { ISFUNC, rl_insert_comment }, /* Meta-# */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-$ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-% */ + { ISFUNC, rl_tilde_expand }, /* Meta-& */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-' */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-( */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-) */ { ISFUNC, rl_insert_completions }, /* Meta-* */ - { ISFUNC, (Function *)0x0 }, /* Meta-+ */ - { ISFUNC, (Function *)0x0 }, /* Meta-, */ - { ISFUNC, rl_digit_argument }, /* Meta-- */ - { ISFUNC, rl_yank_last_arg}, /* Meta-. */ - { ISFUNC, (Function *)0x0 }, /* Meta-/ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-+ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-, */ + { ISFUNC, rl_digit_argument }, /* Meta-- */ + { ISFUNC, rl_yank_last_arg}, /* Meta-. */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-/ */ /* Regular digits. */ - { ISFUNC, rl_digit_argument }, /* Meta-0 */ - { ISFUNC, rl_digit_argument }, /* Meta-1 */ - { ISFUNC, rl_digit_argument }, /* Meta-2 */ - { ISFUNC, rl_digit_argument }, /* Meta-3 */ - { ISFUNC, rl_digit_argument }, /* Meta-4 */ - { ISFUNC, rl_digit_argument }, /* Meta-5 */ - { ISFUNC, rl_digit_argument }, /* Meta-6 */ - { ISFUNC, rl_digit_argument }, /* Meta-7 */ - { ISFUNC, rl_digit_argument }, /* Meta-8 */ - { ISFUNC, rl_digit_argument }, /* Meta-9 */ + { ISFUNC, rl_digit_argument }, /* Meta-0 */ + { ISFUNC, rl_digit_argument }, /* Meta-1 */ + { ISFUNC, rl_digit_argument }, /* Meta-2 */ + { ISFUNC, rl_digit_argument }, /* Meta-3 */ + { ISFUNC, rl_digit_argument }, /* Meta-4 */ + { ISFUNC, rl_digit_argument }, /* Meta-5 */ + { ISFUNC, rl_digit_argument }, /* Meta-6 */ + { ISFUNC, rl_digit_argument }, /* Meta-7 */ + { ISFUNC, rl_digit_argument }, /* Meta-8 */ + { ISFUNC, rl_digit_argument }, /* Meta-9 */ /* A little more punctuation. */ - { ISFUNC, (Function *)0x0 }, /* Meta-: */ - { ISFUNC, (Function *)0x0 }, /* Meta-; */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-: */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-; */ { ISFUNC, rl_beginning_of_history }, /* Meta-< */ { ISFUNC, rl_possible_completions }, /* Meta-= */ { ISFUNC, rl_end_of_history }, /* Meta-> */ { ISFUNC, rl_possible_completions }, /* Meta-? */ - { ISFUNC, (Function *)0x0 }, /* Meta-@ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-@ */ /* Uppercase alphabet. */ { ISFUNC, rl_do_lowercase_version }, /* Meta-A */ @@ -430,456 +418,456 @@ KEYMAP_ENTRY_ARRAY emacs_meta_keymap = { { ISFUNC, rl_do_lowercase_version }, /* Meta-Z */ /* Some more punctuation. */ - { ISFUNC, (Function *)0x0 }, /* Meta-[ */ /* was rl_arrow_keys */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-[ */ /* was rl_arrow_keys */ { ISFUNC, rl_delete_horizontal_space }, /* Meta-\ */ - { ISFUNC, (Function *)0x0 }, /* Meta-] */ - { ISFUNC, (Function *)0x0 }, /* Meta-^ */ - { ISFUNC, rl_yank_last_arg }, /* Meta-_ */ - { ISFUNC, (Function *)0x0 }, /* Meta-` */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-] */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-^ */ + { ISFUNC, rl_yank_last_arg }, /* Meta-_ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-` */ /* Lowercase alphabet. */ - { ISFUNC, (Function *)0x0 }, /* Meta-a */ - { ISFUNC, rl_backward_word }, /* Meta-b */ - { ISFUNC, rl_capitalize_word }, /* Meta-c */ - { ISFUNC, rl_kill_word }, /* Meta-d */ - { ISFUNC, (Function *)0x0 }, /* Meta-e */ - { ISFUNC, rl_forward_word }, /* Meta-f */ - { ISFUNC, (Function *)0x0 }, /* Meta-g */ - { ISFUNC, (Function *)0x0 }, /* Meta-h */ - { ISFUNC, (Function *)0x0 }, /* Meta-i */ - { ISFUNC, (Function *)0x0 }, /* Meta-j */ - { ISFUNC, (Function *)0x0 }, /* Meta-k */ - { ISFUNC, rl_downcase_word }, /* Meta-l */ - { ISFUNC, (Function *)0x0 }, /* Meta-m */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-a */ + { ISFUNC, rl_backward_word }, /* Meta-b */ + { ISFUNC, rl_capitalize_word }, /* Meta-c */ + { ISFUNC, rl_kill_word }, /* Meta-d */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-e */ + { ISFUNC, rl_forward_word }, /* Meta-f */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-g */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-h */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-i */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-j */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-k */ + { ISFUNC, rl_downcase_word }, /* Meta-l */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-m */ { ISFUNC, rl_noninc_forward_search }, /* Meta-n */ - { ISFUNC, (Function *)0x0 }, /* Meta-o */ /* was rl_arrow_keys */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-o */ /* was rl_arrow_keys */ { ISFUNC, rl_noninc_reverse_search }, /* Meta-p */ - { ISFUNC, (Function *)0x0 }, /* Meta-q */ - { ISFUNC, rl_revert_line }, /* Meta-r */ - { ISFUNC, (Function *)0x0 }, /* Meta-s */ - { ISFUNC, rl_transpose_words }, /* Meta-t */ - { ISFUNC, rl_upcase_word }, /* Meta-u */ - { ISFUNC, (Function *)0x0 }, /* Meta-v */ - { ISFUNC, (Function *)0x0 }, /* Meta-w */ - { ISFUNC, (Function *)0x0 }, /* Meta-x */ - { ISFUNC, rl_yank_pop }, /* Meta-y */ - { ISFUNC, (Function *)0x0 }, /* Meta-z */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-q */ + { ISFUNC, rl_revert_line }, /* Meta-r */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-s */ + { ISFUNC, rl_transpose_words }, /* Meta-t */ + { ISFUNC, rl_upcase_word }, /* Meta-u */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-v */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-w */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-x */ + { ISFUNC, rl_yank_pop }, /* Meta-y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-z */ /* Final punctuation. */ - { ISFUNC, (Function *)0x0 }, /* Meta-{ */ - { ISFUNC, (Function *)0x0 }, /* Meta-| */ - { ISFUNC, (Function *)0x0 }, /* Meta-} */ - { ISFUNC, rl_tilde_expand }, /* Meta-~ */ - { ISFUNC, rl_backward_kill_word }, /* Meta-rubout */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-{ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-| */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-} */ + { ISFUNC, rl_tilde_expand }, /* Meta-~ */ + { ISFUNC, rl_backward_kill_word }, /* Meta-rubout */ #if KEYMAP_SIZE > 128 /* Undefined keys. */ - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 } + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 } #endif /* KEYMAP_SIZE > 128 */ }; KEYMAP_ENTRY_ARRAY emacs_ctlx_keymap = { /* Control keys. */ - { ISFUNC, (Function *)0x0 }, /* Control-@ */ - { ISFUNC, (Function *)0x0 }, /* Control-a */ - { ISFUNC, (Function *)0x0 }, /* Control-b */ - { ISFUNC, (Function *)0x0 }, /* Control-c */ - { ISFUNC, (Function *)0x0 }, /* Control-d */ - { ISFUNC, (Function *)0x0 }, /* Control-e */ - { ISFUNC, (Function *)0x0 }, /* Control-f */ - { ISFUNC, rl_abort }, /* Control-g */ - { ISFUNC, (Function *)0x0 }, /* Control-h */ - { ISFUNC, (Function *)0x0 }, /* Control-i */ - { ISFUNC, (Function *)0x0 }, /* Control-j */ - { ISFUNC, (Function *)0x0 }, /* Control-k */ - { ISFUNC, (Function *)0x0 }, /* Control-l */ - { ISFUNC, (Function *)0x0 }, /* Control-m */ - { ISFUNC, (Function *)0x0 }, /* Control-n */ - { ISFUNC, (Function *)0x0 }, /* Control-o */ - { ISFUNC, (Function *)0x0 }, /* Control-p */ - { ISFUNC, (Function *)0x0 }, /* Control-q */ - { ISFUNC, rl_re_read_init_file }, /* Control-r */ - { ISFUNC, (Function *)0x0 }, /* Control-s */ - { ISFUNC, (Function *)0x0 }, /* Control-t */ - { ISFUNC, rl_undo_command }, /* Control-u */ - { ISFUNC, (Function *)0x0 }, /* Control-v */ - { ISFUNC, (Function *)0x0 }, /* Control-w */ - { ISFUNC, rl_exchange_point_and_mark },/* Control-x */ - { ISFUNC, (Function *)0x0 }, /* Control-y */ - { ISFUNC, (Function *)0x0 }, /* Control-z */ - { ISFUNC, (Function *)0x0 }, /* Control-[ */ - { ISFUNC, (Function *)0x0 }, /* Control-\ */ - { ISFUNC, (Function *)0x0 }, /* Control-] */ - { ISFUNC, (Function *)0x0 }, /* Control-^ */ - { ISFUNC, (Function *)0x0 }, /* Control-_ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-@ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-a */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-b */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-c */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-d */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-e */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-f */ + { ISFUNC, rl_abort }, /* Control-g */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-h */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-i */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-j */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-k */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-l */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-m */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-n */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-o */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-p */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-q */ + { ISFUNC, rl_re_read_init_file }, /* Control-r */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-s */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-t */ + { ISFUNC, rl_undo_command }, /* Control-u */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-v */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-w */ + { ISFUNC, rl_exchange_point_and_mark }, /* Control-x */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-z */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-[ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-\ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-] */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-^ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-_ */ /* The start of printing characters. */ - { ISFUNC, (Function *)0x0 }, /* SPACE */ - { ISFUNC, (Function *)0x0 }, /* ! */ - { ISFUNC, (Function *)0x0 }, /* " */ - { ISFUNC, (Function *)0x0 }, /* # */ - { ISFUNC, (Function *)0x0 }, /* $ */ - { ISFUNC, (Function *)0x0 }, /* % */ - { ISFUNC, (Function *)0x0 }, /* & */ - { ISFUNC, (Function *)0x0 }, /* ' */ - { ISFUNC, rl_start_kbd_macro }, /* ( */ - { ISFUNC, rl_end_kbd_macro }, /* ) */ - { ISFUNC, (Function *)0x0 }, /* * */ - { ISFUNC, (Function *)0x0 }, /* + */ - { ISFUNC, (Function *)0x0 }, /* , */ - { ISFUNC, (Function *)0x0 }, /* - */ - { ISFUNC, (Function *)0x0 }, /* . */ - { ISFUNC, (Function *)0x0 }, /* / */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* SPACE */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ! */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* " */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* # */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* $ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* % */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* & */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ' */ + { ISFUNC, rl_start_kbd_macro }, /* ( */ + { ISFUNC, rl_end_kbd_macro }, /* ) */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* * */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* + */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* , */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* - */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* . */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* / */ /* Regular digits. */ - { ISFUNC, (Function *)0x0 }, /* 0 */ - { ISFUNC, (Function *)0x0 }, /* 1 */ - { ISFUNC, (Function *)0x0 }, /* 2 */ - { ISFUNC, (Function *)0x0 }, /* 3 */ - { ISFUNC, (Function *)0x0 }, /* 4 */ - { ISFUNC, (Function *)0x0 }, /* 5 */ - { ISFUNC, (Function *)0x0 }, /* 6 */ - { ISFUNC, (Function *)0x0 }, /* 7 */ - { ISFUNC, (Function *)0x0 }, /* 8 */ - { ISFUNC, (Function *)0x0 }, /* 9 */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 0 */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 1 */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 2 */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 3 */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 4 */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 5 */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 6 */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 7 */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 8 */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* 9 */ /* A little more punctuation. */ - { ISFUNC, (Function *)0x0 }, /* : */ - { ISFUNC, (Function *)0x0 }, /* ; */ - { ISFUNC, (Function *)0x0 }, /* < */ - { ISFUNC, (Function *)0x0 }, /* = */ - { ISFUNC, (Function *)0x0 }, /* > */ - { ISFUNC, (Function *)0x0 }, /* ? */ - { ISFUNC, (Function *)0x0 }, /* @ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* : */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ; */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* < */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* = */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* > */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ? */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* @ */ /* Uppercase alphabet. */ - { ISFUNC, rl_do_lowercase_version }, /* A */ - { ISFUNC, rl_do_lowercase_version }, /* B */ - { ISFUNC, rl_do_lowercase_version }, /* C */ - { ISFUNC, rl_do_lowercase_version }, /* D */ - { ISFUNC, rl_do_lowercase_version }, /* E */ - { ISFUNC, rl_do_lowercase_version }, /* F */ - { ISFUNC, rl_do_lowercase_version }, /* G */ - { ISFUNC, rl_do_lowercase_version }, /* H */ - { ISFUNC, rl_do_lowercase_version }, /* I */ - { ISFUNC, rl_do_lowercase_version }, /* J */ - { ISFUNC, rl_do_lowercase_version }, /* K */ - { ISFUNC, rl_do_lowercase_version }, /* L */ - { ISFUNC, rl_do_lowercase_version }, /* M */ - { ISFUNC, rl_do_lowercase_version }, /* N */ - { ISFUNC, rl_do_lowercase_version }, /* O */ - { ISFUNC, rl_do_lowercase_version }, /* P */ - { ISFUNC, rl_do_lowercase_version }, /* Q */ - { ISFUNC, rl_do_lowercase_version }, /* R */ - { ISFUNC, rl_do_lowercase_version }, /* S */ - { ISFUNC, rl_do_lowercase_version }, /* T */ - { ISFUNC, rl_do_lowercase_version }, /* U */ - { ISFUNC, rl_do_lowercase_version }, /* V */ - { ISFUNC, rl_do_lowercase_version }, /* W */ - { ISFUNC, rl_do_lowercase_version }, /* X */ - { ISFUNC, rl_do_lowercase_version }, /* Y */ - { ISFUNC, rl_do_lowercase_version }, /* Z */ + { ISFUNC, rl_do_lowercase_version }, /* A */ + { ISFUNC, rl_do_lowercase_version }, /* B */ + { ISFUNC, rl_do_lowercase_version }, /* C */ + { ISFUNC, rl_do_lowercase_version }, /* D */ + { ISFUNC, rl_do_lowercase_version }, /* E */ + { ISFUNC, rl_do_lowercase_version }, /* F */ + { ISFUNC, rl_do_lowercase_version }, /* G */ + { ISFUNC, rl_do_lowercase_version }, /* H */ + { ISFUNC, rl_do_lowercase_version }, /* I */ + { ISFUNC, rl_do_lowercase_version }, /* J */ + { ISFUNC, rl_do_lowercase_version }, /* K */ + { ISFUNC, rl_do_lowercase_version }, /* L */ + { ISFUNC, rl_do_lowercase_version }, /* M */ + { ISFUNC, rl_do_lowercase_version }, /* N */ + { ISFUNC, rl_do_lowercase_version }, /* O */ + { ISFUNC, rl_do_lowercase_version }, /* P */ + { ISFUNC, rl_do_lowercase_version }, /* Q */ + { ISFUNC, rl_do_lowercase_version }, /* R */ + { ISFUNC, rl_do_lowercase_version }, /* S */ + { ISFUNC, rl_do_lowercase_version }, /* T */ + { ISFUNC, rl_do_lowercase_version }, /* U */ + { ISFUNC, rl_do_lowercase_version }, /* V */ + { ISFUNC, rl_do_lowercase_version }, /* W */ + { ISFUNC, rl_do_lowercase_version }, /* X */ + { ISFUNC, rl_do_lowercase_version }, /* Y */ + { ISFUNC, rl_do_lowercase_version }, /* Z */ /* Some more punctuation. */ - { ISFUNC, (Function *)0x0 }, /* [ */ - { ISFUNC, (Function *)0x0 }, /* \ */ - { ISFUNC, (Function *)0x0 }, /* ] */ - { ISFUNC, (Function *)0x0 }, /* ^ */ - { ISFUNC, (Function *)0x0 }, /* _ */ - { ISFUNC, (Function *)0x0 }, /* ` */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* [ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* \ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ] */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ^ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* _ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ` */ /* Lowercase alphabet. */ - { ISFUNC, (Function *)0x0 }, /* a */ - { ISFUNC, (Function *)0x0 }, /* b */ - { ISFUNC, (Function *)0x0 }, /* c */ - { ISFUNC, (Function *)0x0 }, /* d */ - { ISFUNC, rl_call_last_kbd_macro }, /* e */ - { ISFUNC, (Function *)0x0 }, /* f */ - { ISFUNC, (Function *)0x0 }, /* g */ - { ISFUNC, (Function *)0x0 }, /* h */ - { ISFUNC, (Function *)0x0 }, /* i */ - { ISFUNC, (Function *)0x0 }, /* j */ - { ISFUNC, (Function *)0x0 }, /* k */ - { ISFUNC, (Function *)0x0 }, /* l */ - { ISFUNC, (Function *)0x0 }, /* m */ - { ISFUNC, (Function *)0x0 }, /* n */ - { ISFUNC, (Function *)0x0 }, /* o */ - { ISFUNC, (Function *)0x0 }, /* p */ - { ISFUNC, (Function *)0x0 }, /* q */ - { ISFUNC, (Function *)0x0 }, /* r */ - { ISFUNC, (Function *)0x0 }, /* s */ - { ISFUNC, (Function *)0x0 }, /* t */ - { ISFUNC, (Function *)0x0 }, /* u */ - { ISFUNC, (Function *)0x0 }, /* v */ - { ISFUNC, (Function *)0x0 }, /* w */ - { ISFUNC, (Function *)0x0 }, /* x */ - { ISFUNC, (Function *)0x0 }, /* y */ - { ISFUNC, (Function *)0x0 }, /* z */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* a */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* b */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* c */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* d */ + { ISFUNC, rl_call_last_kbd_macro }, /* e */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* f */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* g */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* h */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* i */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* j */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* k */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* l */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* m */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* n */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* o */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* p */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* q */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* r */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* s */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* t */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* u */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* v */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* w */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* x */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* z */ /* Final punctuation. */ - { ISFUNC, (Function *)0x0 }, /* { */ - { ISFUNC, (Function *)0x0 }, /* | */ - { ISFUNC, (Function *)0x0 }, /* } */ - { ISFUNC, (Function *)0x0 }, /* ~ */ - { ISFUNC, rl_backward_kill_line }, /* RUBOUT */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* { */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* | */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* } */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ~ */ + { ISFUNC, rl_backward_kill_line }, /* RUBOUT */ #if KEYMAP_SIZE > 128 /* Undefined keys. */ - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 } + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 } #endif /* KEYMAP_SIZE > 128 */ }; diff --git a/readline/funmap.c b/readline/funmap.c index 472119bd80a..fe9a1da43d7 100644 --- a/readline/funmap.c +++ b/readline/funmap.c @@ -7,7 +7,7 @@ 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 1, or + 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 @@ -18,15 +18,13 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) # include #endif -extern char *xmalloc (), *xrealloc (); - #if !defined (BUFSIZ) #include #endif /* BUFSIZ */ @@ -40,7 +38,15 @@ extern char *xmalloc (), *xrealloc (); #include "rlconf.h" #include "readline.h" -extern int _rl_qsort_string_compare (); +#include "xmalloc.h" + +#ifdef __STDC__ +typedef int QSFUNC (const void *, const void *); +#else +typedef int QSFUNC (); +#endif + +extern int _rl_qsort_string_compare PARAMS((char **, char **)); FUNMAP **funmap; static int funmap_size; @@ -54,7 +60,8 @@ static FUNMAP default_funmap[] = { { "abort", rl_abort }, { "accept-line", rl_newline }, { "arrow-key-prefix", rl_arrow_keys }, - { "backward-char", rl_backward }, + { "backward-byte", rl_backward_byte }, + { "backward-char", rl_backward_char }, { "backward-delete-char", rl_rubout }, { "backward-kill-line", rl_backward_kill_line }, { "backward-kill-word", rl_backward_kill_word }, @@ -85,7 +92,8 @@ static FUNMAP default_funmap[] = { { "end-of-line", rl_end_of_line }, { "exchange-point-and-mark", rl_exchange_point_and_mark }, { "forward-backward-delete-char", rl_rubout_or_delete }, - { "forward-char", rl_forward }, + { "forward-byte", rl_forward_byte }, + { "forward-char", rl_forward_char }, { "forward-search-history", rl_forward_search_history }, { "forward-word", rl_forward_word }, { "history-search-backward", rl_history_search_backward }, @@ -102,7 +110,8 @@ static FUNMAP default_funmap[] = { { "non-incremental-reverse-search-history", rl_noninc_reverse_search }, { "non-incremental-forward-search-history-again", rl_noninc_forward_search_again }, { "non-incremental-reverse-search-history-again", rl_noninc_reverse_search_again }, -#ifdef __CYGWIN32__ + { "overwrite-mode", rl_overwrite_mode }, +#ifdef __CYGWIN__ { "paste-from-clipboard", rl_paste_from_clipboard }, #endif { "possible-completions", rl_possible_completions }, @@ -136,7 +145,6 @@ static FUNMAP default_funmap[] = { { "vi-arg-digit", rl_vi_arg_digit }, { "vi-back-to-indent", rl_vi_back_to_indent }, { "vi-bWord", rl_vi_bWord }, - { "vi-bracktype", rl_vi_bracktype }, { "vi-bword", rl_vi_bword }, { "vi-change-case", rl_vi_change_case }, { "vi-change-char", rl_vi_change_char }, @@ -176,18 +184,20 @@ static FUNMAP default_funmap[] = { { "vi-yank-to", rl_vi_yank_to }, #endif /* VI_MODE */ - {(char *)NULL, (Function *)NULL } + {(char *)NULL, (rl_command_func_t *)NULL } }; int -rl_add_funmap_entry (const char *name, Function *function) +rl_add_funmap_entry (name, function) + const char *name; + rl_command_func_t *function; { if (funmap_entry + 2 >= funmap_size) { funmap_size += 64; funmap = (FUNMAP **)xrealloc (funmap, funmap_size * sizeof (FUNMAP *)); } - + funmap[funmap_entry] = (FUNMAP *)xmalloc (sizeof (FUNMAP)); funmap[funmap_entry]->name = name; funmap[funmap_entry]->function = function; @@ -217,36 +227,27 @@ rl_initialize_funmap () /* Produce a NULL terminated array of known function names. The array is sorted. The array itself is allocated, but not the strings inside. You should free () the array when you done, but not the pointrs. */ -char ** +const char ** rl_funmap_names () { - char **result; + const char **result; int result_size, result_index; /* Make sure that the function map has been initialized. */ rl_initialize_funmap (); - for (result_index = result_size = 0, result = (char **)NULL; funmap[result_index]; result_index++) + for (result_index = result_size = 0, result = (const char **)NULL; funmap[result_index]; result_index++) { if (result_index + 2 > result_size) { result_size += 20; - result = (char **)xrealloc (result, result_size * sizeof (char *)); + result = (const char **)xrealloc (result, result_size * sizeof (char *)); } - result[result_index] = (char*) funmap[result_index]->name; + result[result_index] = funmap[result_index]->name; result[result_index + 1] = (char *)NULL; } - qsort (result, result_index, sizeof (char *), _rl_qsort_string_compare); + qsort (result, result_index, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare); return (result); } - -/* Things that mean `Control'. */ -const char *possible_control_prefixes[] = { - "Control-", "C-", "CTRL-", (char *)NULL -}; - -const char *possible_meta_prefixes[] = { - "Meta", "M-", (char *)NULL -}; diff --git a/readline/histexpand.c b/readline/histexpand.c index f78838ef2ba..a98067956c2 100644 --- a/readline/histexpand.c +++ b/readline/histexpand.c @@ -7,7 +7,7 @@ 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 1, or (at your option) + 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 @@ -18,7 +18,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY @@ -41,18 +41,21 @@ # include #endif -#if defined (HAVE_STRING_H) -# include -#else -# include -#endif /* !HAVE_STRING_H */ +#include "rlmbutil.h" #include "history.h" #include "histlib.h" +#include "rlshell.h" +#include "xmalloc.h" + #define HISTORY_WORD_DELIMITERS " \t\n;&()|<>" #define HISTORY_QUOTE_CHARACTERS "\"'`" +typedef int _hist_search_func_t PARAMS((const char *, int)); + +extern int rl_byte_oriented; /* declared in mbutil.c */ + static char error_pointer; static char *subst_lhs; @@ -60,15 +63,10 @@ static char *subst_rhs; static int subst_lhs_len; static int subst_rhs_len; -static char *get_history_word_specifier (); -static char *history_find_word (); +static char *get_history_word_specifier PARAMS((char *, char *, int *)); +static char *history_find_word PARAMS((char *, int)); -extern int history_offset; - -extern char *single_quote (); -static char *quote_breaks (); - -extern char *xmalloc (), *xrealloc (); +static char *quote_breaks PARAMS((char *)); /* Variables exported by this file. */ /* The character that represents the start of a history expansion @@ -87,15 +85,18 @@ char history_comment_char = '\0'; /* The list of characters which inhibit the expansion of text if found immediately following history_expansion_char. */ -const char *history_no_expand_chars = " \t\n\r="; +char *history_no_expand_chars = (char*)" \t\n\r="; /* If set to a non-zero value, single quotes inhibit history expansion. The default is 0. */ int history_quotes_inhibit_expansion = 0; +/* Used to split words by history_tokenize_internal. */ +char *history_word_delimiters = (char*)HISTORY_WORD_DELIMITERS; + /* If set, this points to a function that is called to verify that a particular history expansion should be performed. */ -Function *history_inhibit_expansion_function; +rl_linebuf_func_t *history_inhibit_expansion_function; /* **************************************************************** */ /* */ @@ -124,7 +125,7 @@ static char *search_match; line = get_history_event ("!echo:p", &index, 0); */ char * get_history_event (string, caller_index, delimiting_quote) - char *string; + const char *string; int *caller_index; int delimiting_quote; { @@ -132,7 +133,7 @@ get_history_event (string, caller_index, delimiting_quote) register char c; HIST_ENTRY *entry; int which, sign, local_index, substring_okay; - Function *search_func; + _hist_search_func_t *search_func; char *temp; /* The event can be specified in a number of ways. @@ -201,15 +202,33 @@ get_history_event (string, caller_index, delimiting_quote) /* Only a closing `?' or a newline delimit a substring search string. */ for (local_index = i; (c = string[i]); i++) - if ((!substring_okay && (whitespace (c) || c == ':' || - (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) || - string[i] == delimiting_quote)) || - string[i] == '\n' || - (substring_okay && string[i] == '?')) - break; +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + int v; + mbstate_t ps; + + memset (&ps, 0, sizeof (mbstate_t)); + /* These produce warnings because we're passing a const string to a + function that takes a non-const string. */ + _rl_adjust_point (string, i, &ps); + if ((v = _rl_get_char_len (string + i, &ps)) > 1) + { + i += v - 1; + continue; + } + } + else +#endif /* HANDLE_MULTIBYTE */ + if ((!substring_okay && (whitespace (c) || c == ':' || + (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) || + string[i] == delimiting_quote)) || + string[i] == '\n' || + (substring_okay && string[i] == '?')) + break; which = i - local_index; - temp = xmalloc (1 + which); + temp = (char *)xmalloc (1 + which); if (which) strncpy (temp, string + local_index, which); temp[which] = '\0'; @@ -249,7 +268,7 @@ get_history_event (string, caller_index, delimiting_quote) { entry = current_history (); history_offset = history_length; - + /* If this was a substring search, then remember the string that we matched for word substitution. */ if (substring_okay) @@ -311,7 +330,7 @@ quote_breaks (s) len += 2; } - r = ret = xmalloc (len); + r = ret = (char *)xmalloc (len); *r++ = '\''; for (p = s; p && *p; ) { @@ -376,7 +395,7 @@ hist_error(s, start, current, errtype) break; } - temp = xmalloc (ll + elen + 3); + temp = (char *)xmalloc (ll + elen + 3); strncpy (temp, s + start, ll); temp[ll] = ':'; temp[ll + 1] = ' '; @@ -402,17 +421,37 @@ get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr) int *iptr, delimiter, is_rhs, *lenptr; { register int si, i, j, k; - char *s = (char *) NULL; + char *s; +#if defined (HANDLE_MULTIBYTE) + mbstate_t ps; +#endif + s = (char *)NULL; i = *iptr; +#if defined (HANDLE_MULTIBYTE) + memset (&ps, 0, sizeof (mbstate_t)); + _rl_adjust_point (str, i, &ps); +#endif + for (si = i; str[si] && str[si] != delimiter; si++) - if (str[si] == '\\' && str[si + 1] == delimiter) - si++; +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + int v; + if ((v = _rl_get_char_len (str + si, &ps)) > 1) + si += v - 1; + else if (str[si] == '\\' && str[si + 1] == delimiter) + si++; + } + else +#endif /* HANDLE_MULTIBYTE */ + if (str[si] == '\\' && str[si + 1] == delimiter) + si++; if (si > i || is_rhs) { - s = xmalloc (si - i + 1); + s = (char *)xmalloc (si - i + 1); for (j = 0, k = i; k < si; j++, k++) { /* Remove a backslash quoting the search string delimiter. */ @@ -439,13 +478,13 @@ postproc_subst_rhs () char *new; int i, j, new_size; - new = xmalloc (new_size = subst_rhs_len + subst_lhs_len); + new = (char *)xmalloc (new_size = subst_rhs_len + subst_lhs_len); for (i = j = 0; i < subst_rhs_len; i++) { if (subst_rhs[i] == '&') { if (j + subst_lhs_len >= new_size) - new = xrealloc (new, (new_size = new_size * 2 + subst_lhs_len)); + new = (char *)xrealloc (new, (new_size = new_size * 2 + subst_lhs_len)); strcpy (new + j, subst_lhs); j += subst_lhs_len; } @@ -455,7 +494,7 @@ postproc_subst_rhs () if (subst_rhs[i] == '\\' && subst_rhs[i + 1] == '&') i++; if (j >= new_size) - new = xrealloc (new, new_size *= 2); + new = (char *)xrealloc (new, new_size *= 2); new[j++] = subst_rhs[i]; } } @@ -481,8 +520,13 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line) int substitute_globally, want_quotes, print_only; char *event, *temp, *result, *tstr, *t, c, *word_spec; int result_len; +#if defined (HANDLE_MULTIBYTE) + mbstate_t ps; - result = xmalloc (result_len = 128); + memset (&ps, 0, sizeof (mbstate_t)); +#endif + + result = (char *)xmalloc (result_len = 128); i = start; @@ -511,11 +555,24 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line) quote, then this expansion takes place inside of the quoted string. If we have to search for some text ("!foo"), allow the delimiter to end the search string. */ - if (i && (string[i - 1] == '\'' || string[i - 1] == '"')) - quoted_search_delimiter = string[i - 1]; +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + int c, l; + l = _rl_find_prev_mbchar (string, i, MB_FIND_ANY); + c = string[l]; + /* XXX - original patch had i - 1 ??? If i == 0 it would fail. */ + if (i && (c == '\'' || c == '"')) + quoted_search_delimiter = c; + } + else +#endif /* HANDLE_MULTIBYTE */ + if (i && (string[i - 1] == '\'' || string[i - 1] == '"')) + quoted_search_delimiter = string[i - 1]; + event = get_history_event (string, &i, quoted_search_delimiter); } - + if (event == 0) { *ret_string = hist_error (string, start, i, EVENT_NOT_FOUND); @@ -625,13 +682,26 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line) case '&': case 's': { - char *new_event, *t; + char *new_event; int delimiter, failed, si, l_temp; if (c == 's') { if (i + 2 < (int)strlen (string)) - delimiter = string[i + 2]; + { +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + _rl_adjust_point (string, i + 2, &ps); + if (_rl_get_char_len (string + i + 2, &ps) > 1) + delimiter = 0; + else + delimiter = string[i + 2]; + } + else +#endif /* HANDLE_MULTIBYTE */ + delimiter = string[i + 2]; + } else break; /* no search delimiter */ @@ -695,7 +765,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line) if (STREQN (temp+si, subst_lhs, subst_lhs_len)) { int len = subst_rhs_len - subst_lhs_len + l_temp; - new_event = xmalloc (1 + len); + new_event = (char *)xmalloc (1 + len); strncpy (new_event, temp, si); strncpy (new_event + si, subst_rhs, subst_rhs_len); strncpy (new_event + si + subst_rhs_len, @@ -744,7 +814,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line) char *x; if (want_quotes == 'q') - x = single_quote (temp); + x = sh_single_quote (temp); else if (want_quotes == 'x') x = quote_breaks (temp); else @@ -756,7 +826,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line) n = strlen (temp); if (n >= result_len) - result = xrealloc (result, n + 2); + result = (char *)xrealloc (result, n + 2); strcpy (result, temp); free (temp); @@ -787,7 +857,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line) { \ while (j >= result_len) \ result_len += 128; \ - result = xrealloc (result, result_len); \ + result = (char *)xrealloc (result, result_len); \ } \ strcpy (result + j - sl, s); \ } \ @@ -797,7 +867,7 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line) do \ { \ if (j >= result_len - 1) \ - result = xrealloc (result, result_len += 64); \ + result = (char *)xrealloc (result, result_len += 64); \ result[j++] = c; \ result[j] = '\0'; \ } \ @@ -816,9 +886,17 @@ history_expand (hstring, output) int result_len; char *result; +#if defined (HANDLE_MULTIBYTE) + char mb[MB_LEN_MAX]; + mbstate_t ps; +#endif + /* Used when adding the string. */ char *temp; + if (output == 0) + return 0; + /* Setting the history expansion character to 0 inhibits all history expansion. */ if (history_expansion_char == 0) @@ -826,9 +904,9 @@ history_expand (hstring, output) *output = savestring (hstring); return (0); } - + /* Prepare the buffer for printing error messages. */ - result = xmalloc (result_len = 256); + result = (char *)xmalloc (result_len = 256); result[0] = '\0'; only_printing = modified = 0; @@ -845,7 +923,7 @@ history_expand (hstring, output) that is the substitution that we do. */ if (hstring[0] == history_subst_char) { - string = xmalloc (l + 5); + string = (char *)xmalloc (l + 5); string[0] = string[1] = history_expansion_char; string[2] = ':'; @@ -855,6 +933,10 @@ history_expand (hstring, output) } else { +#if defined (HANDLE_MULTIBYTE) + memset (&ps, 0, sizeof (mbstate_t)); +#endif + string = hstring; /* If not quick substitution, still maybe have to do expansion. */ @@ -862,13 +944,26 @@ history_expand (hstring, output) is NOT an expansion. */ for (i = 0; string[i]; i++) { +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + int v; + v = _rl_get_char_len (string + i, &ps); + if (v > 1) + { + i += v - 1; + continue; + } + } +#endif /* HANDLE_MULTIBYTE */ + cc = string[i + 1]; - /* The history_comment_char, if set, appearing that the beginning + /* The history_comment_char, if set, appearing at the beginning of a word signifies that the rest of the line should not have history expansion performed on it. Skip the rest of the line and break out of the loop. */ if (history_comment_char && string[i] == history_comment_char && - (i == 0 || member (string[i - 1], HISTORY_WORD_DELIMITERS))) + (i == 0 || member (string[i - 1], history_word_delimiters))) { while (string[i]) i++; @@ -905,7 +1000,7 @@ history_expand (hstring, output) i++; } } - + if (string[i] != history_expansion_char) { free (result); @@ -926,6 +1021,30 @@ history_expand (hstring, output) continue; } +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + int k, c; + + c = tchar; + memset (mb, 0, sizeof (mb)); + for (k = 0; k < MB_LEN_MAX; k++) + { + mb[k] = (char)c; + memset (&ps, 0, sizeof (mbstate_t)); + if (_rl_get_char_len (mb, &ps) == -2) + c = string[++i]; + else + break; + } + if (strlen (mb) > 1) + { + ADD_STRING (mb); + break; + } + } +#endif /* HANDLE_MULTIBYTE */ + if (tchar == history_expansion_char) tchar = -3; else if (tchar == history_comment_char) @@ -954,7 +1073,7 @@ history_expand (hstring, output) hist_string_extract_single_quoted (string, &i); slen = i - quote + 2; - temp = xmalloc (slen); + temp = (char *)xmalloc (slen); strncpy (temp, string + quote, slen); temp[slen - 1] = '\0'; ADD_STRING (temp); @@ -966,9 +1085,9 @@ history_expand (hstring, output) } case -2: /* history_comment_char */ - if (i == 0 || member (string[i - 1], HISTORY_WORD_DELIMITERS)) + if (i == 0 || member (string[i - 1], history_word_delimiters)) { - temp = xmalloc (l - i + 1); + temp = (char *)xmalloc (l - i + 1); strcpy (temp, string + i); ADD_STRING (temp); free (temp); @@ -1000,7 +1119,7 @@ history_expand (hstring, output) { if (result) { - temp = xmalloc (1 + strlen (result)); + temp = (char *)xmalloc (1 + strlen (result)); strcpy (temp, result); ADD_STRING (temp); free (temp); @@ -1134,7 +1253,14 @@ get_history_word_specifier (spec, from, caller_index) i++; last = '$'; } - else if (!spec[i] || spec[i] == ':') /* could be modifier separator */ +#if 0 + else if (!spec[i] || spec[i] == ':') + /* check against `:' because there could be a modifier separator */ +#else + else + /* csh seems to allow anything to terminate the word spec here, + leaving it as an abbreviation. */ +#endif last = -1; /* x- abbreviates x-$ omitting word `$' */ } @@ -1154,7 +1280,7 @@ get_history_word_specifier (spec, from, caller_index) char * history_arg_extract (first, last, string) int first, last; - char *string; + const char *string; { register int i, len; char *result; @@ -1190,7 +1316,7 @@ history_arg_extract (first, last, string) { for (size = 0, i = first; i < last; i++) size += strlen (list[i]) + 1; - result = xmalloc (size + 1); + result = (char *)xmalloc (size + 1); result[0] = '\0'; for (i = first, offset = 0; i < last; i++) @@ -1220,13 +1346,18 @@ history_arg_extract (first, last, string) *INDP. */ static char ** history_tokenize_internal (string, wind, indp) - char *string; + const char *string; int wind, *indp; { char **result; register int i, start, result_index, size; int len, delimiter; + /* If we're searching for a string that's not part of a word (e.g., " "), + make sure we set *INDP to a reasonable value. */ + if (indp && wind != -1) + *indp = -1; + /* Get a token, and stuff it into RESULT. The tokens are split exactly where the shell would split them. */ for (i = result_index = size = 0, result = (char **)NULL; string[i]; ) @@ -1240,7 +1371,7 @@ history_tokenize_internal (string, wind, indp) return (result); start = i; - + if (member (string[i], "()\n")) { i++; @@ -1301,7 +1432,7 @@ history_tokenize_internal (string, wind, indp) continue; } - if (!delimiter && (member (string[i], HISTORY_WORD_DELIMITERS))) + if (!delimiter && (member (string[i], history_word_delimiters))) break; if (!delimiter && member (string[i], HISTORY_QUOTE_CHARACTERS)) @@ -1318,7 +1449,7 @@ history_tokenize_internal (string, wind, indp) len = i - start; if (result_index + 2 >= size) result = (char **)xrealloc (result, ((size += 10) * sizeof (char *))); - result[result_index] = xmalloc (1 + len); + result[result_index] = (char *)xmalloc (1 + len); strncpy (result[result_index], string + start, len); result[result_index][len] = '\0'; result[++result_index] = (char *)NULL; @@ -1331,7 +1462,7 @@ history_tokenize_internal (string, wind, indp) parsed out of STRING. */ char ** history_tokenize (string) - char *string; + const char *string; { return (history_tokenize_internal (string, -1, (int *)NULL)); } @@ -1348,7 +1479,7 @@ history_find_word (line, ind) int i, wind; words = history_tokenize_internal (line, ind, &wind); - if (wind == -1) + if (wind == -1 || words == 0) return ((char *)NULL); s = words[wind]; for (i = 0; i < wind; i++) diff --git a/readline/histfile.c b/readline/histfile.c index 1da45b00b58..60a91251b7a 100644 --- a/readline/histfile.c +++ b/readline/histfile.c @@ -7,7 +7,7 @@ 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 1, or (at your option) + 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 @@ -18,7 +18,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 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 @@ -35,7 +35,7 @@ #ifndef _MINIX # include #endif -#include +#include "posixstat.h" #include #if defined (HAVE_STDLIB_H) @@ -48,21 +48,39 @@ # include #endif -#if defined (HAVE_STRING_H) -# include -#else -# include -#endif /* !HAVE_STRING_H */ +#if defined (__EMX__) || defined (__CYGWIN__) +# undef HAVE_MMAP +#endif -#if defined (__EMX__) +#ifdef HAVE_MMAP +# include + +# ifdef MAP_FILE +# define MAP_RFLAGS (MAP_FILE|MAP_PRIVATE) +# define MAP_WFLAGS (MAP_FILE|MAP_SHARED) +# else +# define MAP_RFLAGS MAP_PRIVATE +# define MAP_WFLAGS MAP_SHARED +# endif + +# ifndef MAP_FAILED +# define MAP_FAILED ((void *)-1) +# endif + +#endif /* HAVE_MMAP */ + +/* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment + on win 95/98/nt), we want to open files with O_BINARY mode so that there + is no \n -> \r\n conversion performed. On other systems, we don't want to + mess around with O_BINARY at all, so we ensure that it's defined to 0. */ +#if defined (__EMX__) || defined (__CYGWIN__) # ifndef O_BINARY # define O_BINARY 0 # endif -#else /* !__EMX__ */ - /* If we're not compiling for __EMX__, we don't want this at all. Ever. */ +#else /* !__EMX__ && !__CYGWIN__ */ # undef O_BINARY # define O_BINARY 0 -#endif /* !__EMX__ */ +#endif /* !__EMX__ && !__CYGWIN__ */ #include #if !defined (errno) @@ -72,17 +90,15 @@ extern int errno; #include "history.h" #include "histlib.h" -/* Functions imported from shell.c */ -extern char *get_env_value (); - -extern char *xmalloc (), *xrealloc (); +#include "rlshell.h" +#include "xmalloc.h" /* Return the string that should be used in the place of this filename. This only matters when you don't specify the filename to read_history (), or write_history (). */ static char * history_filename (filename) - char *filename; + const char *filename; { char *return_val; const char *home; @@ -92,8 +108,8 @@ history_filename (filename) if (return_val) return (return_val); - - home = get_env_value ("HOME"); + + home = sh_get_env_value ("HOME"); if (home == 0) { @@ -103,10 +119,14 @@ history_filename (filename) else home_len = strlen (home); - return_val = xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */ + return_val = (char *)xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */ strcpy (return_val, home); return_val[home_len] = '/'; +#if defined (__MSDOS__) + strcpy (return_val + home_len + 1, "_history"); +#else strcpy (return_val + home_len + 1, ".history"); +#endif return (return_val); } @@ -116,7 +136,7 @@ history_filename (filename) successful, or errno if not. */ int read_history (filename) - char *filename; + const char *filename; { return (read_history_range (filename, 0, -1)); } @@ -128,13 +148,14 @@ read_history (filename) ~/.history. Returns 0 if successful, or errno if not. */ int read_history_range (filename, from, to) - char *filename; + const char *filename; int from, to; { - char *input, *buffer; - int file, current_line; + register char *line_start, *line_end; + char *input, *buffer, *bufend; + int file, current_line, chars_read; struct stat finfo; - size_t line_start, line_end, file_size; + size_t file_size; buffer = (char *)NULL; input = history_filename (filename); @@ -150,57 +171,67 @@ read_history_range (filename, from, to) { #if defined (EFBIG) errno = EFBIG; +#elif defined (EOVERFLOW) + errno = EOVERFLOW; #endif goto error_and_exit; } - buffer = xmalloc (file_size + 1); -#if 0 - if (read (file, buffer, file_size) != file_size) +#ifdef HAVE_MMAP + /* We map read/write and private so we can change newlines to NULs without + affecting the underlying object. */ + buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE, MAP_RFLAGS, file, 0); + if ((void *)buffer == MAP_FAILED) + goto error_and_exit; + chars_read = file_size; #else - if (read (file, buffer, file_size) < 0) + buffer = (char *)malloc (file_size + 1); + if (buffer == 0) + goto error_and_exit; + + chars_read = read (file, buffer, file_size); #endif + if (chars_read < 0) { error_and_exit: + chars_read = errno; if (file >= 0) close (file); FREE (input); +#ifndef HAVE_MMAP FREE (buffer); +#endif - return (errno); + return (chars_read); } close (file); /* Set TO to larger than end of file if negative. */ if (to < 0) - to = file_size; + to = chars_read; /* Start at beginning of file, work to end. */ - line_start = line_end = current_line = 0; + bufend = buffer + chars_read; + current_line = 0; /* Skip lines until we are at FROM. */ - while (line_start < file_size && current_line < from) - { - for (line_end = line_start; line_end < file_size; line_end++) - if (buffer[line_end] == '\n') - { - current_line++; - line_start = line_end + 1; - if (current_line == from) - break; - } - } + for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++) + if (*line_end == '\n') + { + current_line++; + line_start = line_end + 1; + } /* If there are lines left to gobble, then gobble them now. */ - for (line_end = line_start; line_end < file_size; line_end++) - if (buffer[line_end] == '\n') + for (line_end = line_start; line_end < bufend; line_end++) + if (*line_end == '\n') { - buffer[line_end] = '\0'; + *line_end = '\0'; - if (buffer[line_start]) - add_history (buffer + line_start); + if (*line_start) + add_history (line_start); current_line++; @@ -211,30 +242,52 @@ read_history_range (filename, from, to) } FREE (input); +#ifndef HAVE_MMAP FREE (buffer); +#else + munmap (buffer, file_size); +#endif return (0); } /* Truncate the history file FNAME, leaving only LINES trailing lines. - If FNAME is NULL, then use ~/.history. */ + If FNAME is NULL, then use ~/.history. Returns 0 on success, errno + on failure. */ int history_truncate_file (fname, lines) - char *fname; + const char *fname; int lines; { - register int i; - int file, chars_read; - char *buffer, *filename; + char *buffer, *filename, *bp; + int file, chars_read, rv; struct stat finfo; size_t file_size; buffer = (char *)NULL; filename = history_filename (fname); file = open (filename, O_RDONLY|O_BINARY, 0666); + rv = 0; + /* Don't try to truncate non-regular files. */ if (file == -1 || fstat (file, &finfo) == -1) - goto truncate_exit; + { + rv = errno; + if (file != -1) + close (file); + goto truncate_exit; + } + + if (S_ISREG (finfo.st_mode) == 0) + { + close (file); +#ifdef EFTYPE + rv = EFTYPE; +#else + rv = EINVAL; +#endif + goto truncate_exit; + } file_size = (size_t)finfo.st_size; @@ -243,23 +296,36 @@ history_truncate_file (fname, lines) { close (file); #if defined (EFBIG) - errno = EFBIG; + rv = errno = EFBIG; +#elif defined (EOVERFLOW) + rv = errno = EOVERFLOW; +#else + rv = errno = EINVAL; #endif goto truncate_exit; } - buffer = xmalloc (file_size + 1); + buffer = (char *)malloc (file_size + 1); + if (buffer == 0) + { + close (file); + goto truncate_exit; + } + chars_read = read (file, buffer, file_size); close (file); if (chars_read <= 0) - goto truncate_exit; + { + rv = (chars_read < 0) ? errno : 0; + goto truncate_exit; + } /* Count backwards from the end of buffer until we have passed LINES lines. */ - for (i = chars_read - 1; lines && i; i--) + for (bp = buffer + chars_read - 1; lines && bp > buffer; bp--) { - if (buffer[i] == '\n') + if (*bp == '\n') lines--; } @@ -268,22 +334,22 @@ history_truncate_file (fname, lines) anything. It's the first line if we don't find a newline between the current value of i and 0. Otherwise, write from the start of this line until the end of the buffer. */ - for ( ; i; i--) - if (buffer[i] == '\n') + for ( ; bp > buffer; bp--) + if (*bp == '\n') { - i++; + bp++; break; } /* Write only if there are more lines in the file than we want to truncate to. */ - if (i && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1)) + if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1)) { - write (file, buffer + i, file_size - i); + write (file, bp, chars_read - (bp - buffer)); #if defined (__BEOS__) /* BeOS ignores O_TRUNC. */ - ftruncate (file, file_size - i); + ftruncate (file, chars_read - (bp - buffer)); #endif close (file); @@ -294,7 +360,7 @@ history_truncate_file (fname, lines) FREE (buffer); free (filename); - return 0; + return rv; } /* Workhorse function for writing history. Writes NELEMENT entries @@ -302,15 +368,21 @@ history_truncate_file (fname, lines) wish to replace FILENAME with the entries. */ static int history_do_write (filename, nelements, overwrite) - char *filename; + const char *filename; int nelements, overwrite; { register int i; char *output; - int file, mode; + int file, mode, rv; + size_t cursize; +#ifdef HAVE_MMAP + mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY; +#else mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY; +#endif output = history_filename (filename); + rv = 0; if ((file = open (output, mode, 0600)) == -1) { @@ -318,6 +390,10 @@ history_do_write (filename, nelements, overwrite) return (errno); } +#ifdef HAVE_MMAP + cursize = overwrite ? 0 : lseek (file, 0, SEEK_END); +#endif + if (nelements > history_length) nelements = history_length; @@ -335,7 +411,28 @@ history_do_write (filename, nelements, overwrite) buffer_size += 1 + strlen (the_history[i]->line); /* Allocate the buffer, and fill it. */ - buffer = xmalloc (buffer_size); +#ifdef HAVE_MMAP + if (ftruncate (file, buffer_size+cursize) == -1) + goto mmap_error; + buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize); + if ((void *)buffer == MAP_FAILED) + { +mmap_error: + rv = errno; + FREE (output); + close (file); + return rv; + } +#else + buffer = (char *)malloc (buffer_size); + if (buffer == 0) + { + rv = errno; + FREE (output); + close (file); + return rv; + } +#endif for (j = 0, i = history_length - nelements; i < history_length; i++) { @@ -344,15 +441,21 @@ history_do_write (filename, nelements, overwrite) buffer[j++] = '\n'; } - write (file, buffer, buffer_size); +#ifdef HAVE_MMAP + if (msync (buffer, buffer_size, 0) != 0 || munmap (buffer, buffer_size) != 0) + rv = errno; +#else + if (write (file, buffer, buffer_size) < 0) + rv = errno; free (buffer); +#endif } close (file); FREE (output); - return (0); + return (rv); } /* Append NELEMENT entries to FILENAME. The entries appended are from @@ -360,7 +463,7 @@ history_do_write (filename, nelements, overwrite) int append_history (nelements, filename) int nelements; - char *filename; + const char *filename; { return (history_do_write (filename, nelements, HISTORY_APPEND)); } @@ -370,7 +473,7 @@ append_history (nelements, filename) are as in read_history ().*/ int write_history (filename) - char *filename; + const char *filename; { return (history_do_write (filename, history_length, HISTORY_OVERWRITE)); } diff --git a/readline/histlib.h b/readline/histlib.h index 422cf5974db..c39af71814c 100644 --- a/readline/histlib.h +++ b/readline/histlib.h @@ -6,7 +6,7 @@ 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 1, or (at your option) + 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 @@ -17,27 +17,24 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #if !defined (_HISTLIB_H_) #define _HISTLIB_H_ -/* Function pointers can be declared as (Function *)foo. */ -#if !defined (_FUNCTION_DEF) -# define _FUNCTION_DEF -typedef int Function (); -typedef void VFunction (); -typedef char *CPFunction (); -typedef char **CPPFunction (); -#endif /* _FUNCTION_DEF */ +#if defined (HAVE_STRING_H) +# include +#else +# include +#endif /* !HAVE_STRING_H */ +#if !defined (STREQ) #define STREQ(a, b) (((a)[0] == (b)[0]) && (strcmp ((a), (b)) == 0)) -#define STREQN(a, b, n) (((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0)) +#define STREQN(a, b, n) (((n) == 0) ? (1) \ + : ((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0)) +#endif #ifndef savestring -# ifndef strcpy -extern char *strcpy (); -# endif #define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x)) #endif @@ -79,4 +76,7 @@ extern char *strchr (); #define HISTORY_APPEND 0 #define HISTORY_OVERWRITE 1 +/* Some variable definitions shared across history source files. */ +extern int history_offset; + #endif /* !_HISTLIB_H_ */ diff --git a/readline/history.c b/readline/history.c index 804ffddcd89..4242f33efe1 100644 --- a/readline/history.c +++ b/readline/history.c @@ -7,7 +7,7 @@ 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 1, or (at your option) + 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 @@ -18,7 +18,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 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 @@ -44,16 +44,10 @@ # include #endif -#if defined (HAVE_STRING_H) -# include -#else -# include -#endif /* !HAVE_STRING_H */ - #include "history.h" #include "histlib.h" -extern char *xmalloc (), *xrealloc (); +#include "xmalloc.h" /* The number of slots to increase the_history by. */ #define DEFAULT_HISTORY_GROW_SIZE 50 @@ -71,9 +65,13 @@ static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL; 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 max_input_history; +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. */ @@ -82,9 +80,6 @@ int history_offset; /* The number of strings currently stored in the history list. */ int history_length; -/* The current number of slots allocated to the input_history. */ -static int history_size; - /* The logical `base' of the history array. It defaults to 1. */ int history_base = 1; @@ -134,9 +129,7 @@ history_total_bytes () { register int i, result; - result = 0; - - for (i = 0; the_history && the_history[i]; i++) + for (i = result = 0; the_history && the_history[i]; i++) result += strlen (the_history[i]->line); return (result); @@ -161,7 +154,7 @@ history_set_pos (pos) 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. */ @@ -217,16 +210,16 @@ history_get (offset) is set to NULL. */ void add_history (string) - char *string; + const char *string; { HIST_ENTRY *temp; - if (history_stifled && (history_length == max_input_history)) + if (history_stifled && (history_length == history_max_entries)) { register int i; /* If the history is stifled, and history_length is zero, - and it equals max_input_history, we don't save items. */ + and it equals history_max_entries, we don't save items. */ if (history_length == 0) return; @@ -277,15 +270,15 @@ add_history (string) HIST_ENTRY * replace_history_entry (which, line, data) int which; - char *line; + const char *line; histdata_t data; { - HIST_ENTRY *temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); - HIST_ENTRY *old_value; + HIST_ENTRY *temp, *old_value; if (which >= history_length) return ((HIST_ENTRY *)NULL); + temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); old_value = the_history[which]; temp->line = savestring (line); @@ -303,12 +296,12 @@ remove_history (which) int which; { HIST_ENTRY *return_value; + register int i; if (which >= history_length || !history_length) return_value = (HIST_ENTRY *)NULL; else { - register int i; return_value = the_history[which]; for (i = which; i < history_length; i++) @@ -325,13 +318,13 @@ void stifle_history (max) int max; { + register int i, j; + if (max < 0) max = 0; if (history_length > max) { - register int i, j; - /* This loses because we cannot free the data. */ for (i = 0, j = history_length - max; i < j; i++) { @@ -347,22 +340,22 @@ stifle_history (max) } history_stifled = 1; - max_input_history = max; + max_input_history = history_max_entries = max; } -/* Stop stifling the history. This returns the previous amount the - history was stifled by. The value is positive if the history was - stifled, negative if it wasn't. */ +/* 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 (-max_input_history); + return (history_max_entries); } - - return (max_input_history); + else + return (-history_max_entries); } int diff --git a/readline/history.h b/readline/history.h index 88bf471bb62..58b5de4655f 100644 --- a/readline/history.h +++ b/readline/history.h @@ -6,7 +6,7 @@ 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 1, or (at your option) + 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 @@ -17,7 +17,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #ifndef _HISTORY_H_ #define _HISTORY_H_ @@ -28,16 +28,10 @@ extern "C" { #if defined READLINE_LIBRARY # include "rlstdc.h" +# include "rltypedefs.h" #else # include -#endif - -#if !defined (_FUNCTION_DEF) -# define _FUNCTION_DEF -typedef int Function (); -typedef void VFunction (); -typedef char *CPFunction (); -typedef char **CPPFunction (); +# include #endif #ifdef __STDC__ @@ -68,81 +62,81 @@ typedef struct _hist_state { /* Begin a session in which the history functions might be used. This just initializes the interactive variables. */ -extern void using_history __P((void)); +extern void using_history PARAMS((void)); /* Return the current HISTORY_STATE of the history. */ -extern HISTORY_STATE *history_get_history_state __P((void)); +extern HISTORY_STATE *history_get_history_state PARAMS((void)); /* Set the state of the current history array to STATE. */ -extern void history_set_history_state __P((HISTORY_STATE *)); +extern void history_set_history_state PARAMS((HISTORY_STATE *)); /* Manage the history list. */ /* Place STRING at the end of the history list. The associated data field (if any) is set to NULL. */ -extern void add_history __P((char *)); +extern void add_history PARAMS((const char *)); /* A reasonably useless function, only here for completeness. WHICH is the magic number that tells us which element to delete. The elements are numbered from 0. */ -extern HIST_ENTRY *remove_history __P((int)); +extern HIST_ENTRY *remove_history PARAMS((int)); /* 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. */ -extern HIST_ENTRY *replace_history_entry __P((int, char *, histdata_t)); +extern HIST_ENTRY *replace_history_entry PARAMS((int, const char *, histdata_t)); /* Clear the history list and start over. */ -extern void clear_history __P((void)); +extern void clear_history PARAMS((void)); /* Stifle the history list, remembering only MAX number of entries. */ -extern void stifle_history __P((int)); +extern void stifle_history PARAMS((int)); /* Stop stifling the history. This returns the previous amount the history was stifled by. The value is positive if the history was stifled, negative if it wasn't. */ -extern int unstifle_history __P((void)); +extern int unstifle_history PARAMS((void)); /* Return 1 if the history is stifled, 0 if it is not. */ -extern int history_is_stifled __P((void)); +extern int history_is_stifled PARAMS((void)); /* Information about the history list. */ /* Return a NULL terminated array of HIST_ENTRY which is the current input history. Element 0 of this list is the beginning of time. If there is no history, return NULL. */ -extern HIST_ENTRY **history_list __P((void)); +extern HIST_ENTRY **history_list PARAMS((void)); /* Returns the number which says what history element we are now looking at. */ -extern int where_history __P((void)); - +extern int where_history PARAMS((void)); + /* 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 __P((void)); +extern HIST_ENTRY *current_history PARAMS((void)); /* Return the history entry which is logically at OFFSET in the history array. OFFSET is relative to history_base. */ -extern HIST_ENTRY *history_get __P((int)); +extern HIST_ENTRY *history_get PARAMS((int)); /* Return the number of bytes that the primary history entries are using. This just adds up the lengths of the_history->lines. */ -extern int history_total_bytes __P((void)); +extern int history_total_bytes PARAMS((void)); /* Moving around the history list. */ /* Set the position in the history list to POS. */ -int history_set_pos __P((int)); +extern int history_set_pos PARAMS((int)); /* Back up history_offset to the previous history entry, and return a pointer to that entry. If there is no previous entry, return a NULL pointer. */ -extern HIST_ENTRY *previous_history __P((void)); +extern HIST_ENTRY *previous_history PARAMS((void)); /* Move history_offset forward to the next item in the input_history, and return the a pointer to that entry. If there is no next entry, return a NULL pointer. */ -extern HIST_ENTRY *next_history __P((void)); +extern HIST_ENTRY *next_history PARAMS((void)); /* Searching the history list. */ @@ -152,45 +146,45 @@ extern HIST_ENTRY *next_history __P((void)); current_history () is the history entry, and the value of this function is the offset in the line of that history entry that the string was found in. Otherwise, nothing is changed, and a -1 is returned. */ -extern int history_search __P((char *, int)); +extern int history_search PARAMS((const char *, int)); /* Search the history for STRING, starting at history_offset. The search is anchored: matching lines must begin with string. DIRECTION is as in history_search(). */ -extern int history_search_prefix __P((char *, int)); +extern int history_search_prefix PARAMS((const char *, int)); /* Search for STRING in the history list, starting at POS, an absolute index into the list. DIR, if negative, says to search backwards from POS, else forwards. Returns the absolute index of the history element where STRING was found, or -1 otherwise. */ -extern int history_search_pos __P((char *, int, int)); +extern int history_search_pos PARAMS((const char *, int, int)); /* Managing the history file. */ /* Add the contents of FILENAME to the history list, a line at a time. If FILENAME is NULL, then read from ~/.history. Returns 0 if successful, or errno if not. */ -extern int read_history __P((char *)); +extern int read_history PARAMS((const char *)); /* Read a range of lines from FILENAME, adding them to the history list. Start reading at the FROM'th line and end at the TO'th. If FROM is zero, start at the beginning. If TO is less than FROM, read until the end of the file. If FILENAME is NULL, then read from ~/.history. Returns 0 if successful, or errno if not. */ -extern int read_history_range __P((char *, int, int)); +extern int read_history_range PARAMS((const char *, int, int)); /* Write the current history to FILENAME. If FILENAME is NULL, then write the history list to ~/.history. Values returned are as in read_history (). */ -extern int write_history __P((char *)); +extern int write_history PARAMS((const char *)); /* Append NELEMENT entries to FILENAME. The entries appended are from the end of the list minus NELEMENTs up to the end of the list. */ -int append_history __P((int, char *)); +extern int append_history PARAMS((int, const char *)); /* Truncate the history file, leaving only the last NLINES lines. */ -extern int history_truncate_file __P((char *, int)); +extern int history_truncate_file PARAMS((const char *, int)); /* History expansion. */ @@ -206,12 +200,12 @@ extern int history_truncate_file __P((char *, int)); If an error ocurred in expansion, then OUTPUT contains a descriptive error message. */ -extern int history_expand __P((char *, char **)); +extern int history_expand PARAMS((char *, char **)); /* Extract a string segment consisting of the FIRST through LAST arguments present in STRING. Arguments are broken up as in the shell. */ -extern char *history_arg_extract __P((int, int, char *)); +extern char *history_arg_extract PARAMS((int, int, const char *)); /* Return the text of the history event beginning at the current offset into STRING. Pass STRING with *INDEX equal to the @@ -219,27 +213,31 @@ extern char *history_arg_extract __P((int, int, char *)); DELIMITING_QUOTE is a character that is allowed to end the string specification for what to search for in addition to the normal characters `:', ` ', `\t', `\n', and sometimes `?'. */ -extern char *get_history_event __P((char *, int *, int)); +extern char *get_history_event PARAMS((const char *, int *, int)); /* Return an array of tokens, much as the shell might. The tokens are parsed out of STRING. */ -extern char **history_tokenize __P((char *)); +extern char **history_tokenize PARAMS((const char *)); /* Exported history variables. */ extern int history_base; extern int history_length; -extern int max_input_history; +extern int history_max_entries; extern char history_expansion_char; extern char history_subst_char; +extern char *history_word_delimiters; extern char history_comment_char; -extern const char *history_no_expand_chars; -extern const char *history_search_delimiter_chars; +extern char *history_no_expand_chars; +extern char *history_search_delimiter_chars; extern int history_quotes_inhibit_expansion; +/* Backwards compatibility */ +extern int max_input_history; + /* If set, this function is called to decide whether or not a particular history expansion should be treated as a special case for the calling application and not expanded. */ -extern Function *history_inhibit_expansion_function; +extern rl_linebuf_func_t *history_inhibit_expansion_function; #ifdef __cplusplus } diff --git a/readline/histsearch.c b/readline/histsearch.c index eb17e9332e8..d94fd6cd9c6 100644 --- a/readline/histsearch.c +++ b/readline/histsearch.c @@ -7,7 +7,7 @@ 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 1, or (at your option) + 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 @@ -18,7 +18,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY @@ -32,27 +32,22 @@ #else # include "ansi_stdlib.h" #endif /* HAVE_STDLIB_H */ + #if defined (HAVE_UNISTD_H) # ifdef _MINIX # include # endif # include #endif -#if defined (HAVE_STRING_H) -# include -#else -# include -#endif /* !HAVE_STRING_H */ #include "history.h" #include "histlib.h" -/* Variables imported from other history library files. */ -extern int history_offset; - /* The list of alternate characters that can delimit a history search string. */ -const char *history_search_delimiter_chars = (char *)NULL; +char *history_search_delimiter_chars = (char *)NULL; + +static int history_search_internal PARAMS((const char *, int, int)); /* Search the history for STRING, starting at history_offset. If DIRECTION < 0, then the search is through previous entries, else @@ -66,7 +61,7 @@ const char *history_search_delimiter_chars = (char *)NULL; static int history_search_internal (string, direction, anchored) - char *string; + const char *string; int direction, anchored; { register int i, reverse; @@ -162,7 +157,7 @@ history_search_internal (string, direction, anchored) /* Do a non-anchored search for STRING through the history in DIRECTION. */ int history_search (string, direction) - char *string; + const char *string; int direction; { return (history_search_internal (string, direction, NON_ANCHORED_SEARCH)); @@ -171,7 +166,7 @@ history_search (string, direction) /* Do an anchored search for string through the history in DIRECTION. */ int history_search_prefix (string, direction) - char *string; + const char *string; int direction; { return (history_search_internal (string, direction, ANCHORED_SEARCH)); @@ -182,7 +177,7 @@ history_search_prefix (string, direction) which point to begin searching. */ int history_search_pos (string, dir, pos) - char *string; + const char *string; int dir, pos; { int ret, old; diff --git a/readline/input.c b/readline/input.c index ea1342969b0..1442c5ef155 100644 --- a/readline/input.c +++ b/readline/input.c @@ -18,7 +18,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) @@ -42,7 +42,7 @@ #endif /* HAVE_STDLIB_H */ #if defined (HAVE_SELECT) -# if !defined (HAVE_SYS_SELECT_H) || !defined (M_UNIX) || defined(TIME_WITH_SYS_TIME) +# if !defined (HAVE_SYS_SELECT_H) || !defined (M_UNIX) # include # endif #endif /* HAVE_SELECT */ @@ -63,48 +63,31 @@ extern int errno; /* System-specific feature definitions and include files. */ #include "rldefs.h" +#include "rlmbutil.h" /* Some standard library routines. */ #include "readline.h" +#include "rlprivate.h" +#include "rlshell.h" +#include "xmalloc.h" + /* What kind of non-blocking I/O do we have? */ #if !defined (O_NDELAY) && defined (O_NONBLOCK) # define O_NDELAY O_NONBLOCK /* Posix style */ #endif -/* Functions imported from other files in the library. */ -extern char *xmalloc (), *xrealloc (); - -/* Variables and functions from macro.c. */ -extern void _rl_add_macro_char (); -extern void _rl_with_macro_input (); -extern int _rl_next_macro_key (); -extern int _rl_defining_kbd_macro; - -#if defined (VI_MODE) -extern void _rl_vi_set_last (); -extern int _rl_vi_textmod_command (); -#endif /* VI_MODE */ - -extern FILE *rl_instream, *rl_outstream; -extern Function *rl_last_func; -extern int rl_key_sequence_length; -extern int rl_pending_input; -extern int rl_editing_mode; - -extern Keymap _rl_keymap; - -extern int _rl_convert_meta_chars_to_ascii; - -#if defined (__GO32__) -# include -#endif /* __GO32__ */ - /* Non-null means it is a pointer to a function to run while waiting for character input. */ -Function *rl_event_hook = (Function *)NULL; +rl_hook_func_t *rl_event_hook = (rl_hook_func_t *)NULL; -Function *rl_getc_function = rl_getc; +rl_getc_func_t *rl_getc_function = rl_getc; + +static int _keyboard_input_timeout = 100000; /* 0.1 seconds; it's in usec */ + +static int ibuffer_space PARAMS((void)); +static int rl_get_char PARAMS((int *)); +static int rl_gather_tyi PARAMS((void)); /* **************************************************************** */ /* */ @@ -156,8 +139,8 @@ rl_get_char (key) /* Stuff KEY into the *front* of the input buffer. Returns non-zero if successful, zero if there is no space left in the buffer. */ -static int -rl_unget_char (key) +int +_rl_unget_char (key) int key; { if (ibuffer_space ()) @@ -171,33 +154,12 @@ rl_unget_char (key) return (0); } -#if defined(__EMX__) -int waiting_char = -1; -#endif - -/* If a character is available to be read, then read it - and stuff it into IBUFFER. Otherwise, just return. */ -static void +/* If a character is available to be read, then read it and stuff it into + IBUFFER. Otherwise, just return. Returns number of characters read + (0 if none available) and -1 on error (EIO). */ +static int rl_gather_tyi () { -#if defined (__EMX__) - if (isatty (0) && (waiting_char = _read_kbd(0, 0, 0)) != -1 && ibuffer_space ()) - { - int i; - i = (*rl_getc_function) (rl_instream); - rl_stuff_char (i); - } -#elif defined (__GO32__) - char input; - - if (isatty (0) && kbhit () && ibuffer_space ()) - { - int i; - i = (*rl_getc_function) (rl_instream); - rl_stuff_char (i); - } -#else /* !__GO32__ */ - int tty; register int tem, result; int chars_avail; @@ -215,14 +177,18 @@ rl_gather_tyi () FD_SET (tty, &readfds); FD_SET (tty, &exceptfds); timeout.tv_sec = 0; - timeout.tv_usec = 100000; /* 0.1 seconds */ - if (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) <= 0) - return; /* Nothing to read. */ + timeout.tv_usec = _keyboard_input_timeout; + result = select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout); + if (result <= 0) + return 0; /* Nothing to read. */ #endif result = -1; #if defined (FIONREAD) + errno = 0; result = ioctl (tty, FIONREAD, &chars_avail); + if (result == -1 && errno == EIO) + return -1; #endif #if defined (O_NDELAY) @@ -235,14 +201,14 @@ rl_gather_tyi () fcntl (tty, F_SETFL, tem); if (chars_avail == -1 && errno == EAGAIN) - return; + return 0; } #endif /* O_NDELAY */ /* If there's nothing available, don't waste time trying to read something. */ if (chars_avail <= 0) - return; + return 0; tem = ibuffer_space (); @@ -266,23 +232,36 @@ rl_gather_tyi () if (chars_avail) rl_stuff_char (input); } -#endif /* !__GO32__ */ + + return 1; +} + +int +rl_set_keyboard_input_timeout (u) + int u; +{ + int o; + + o = _keyboard_input_timeout; + if (u > 0) + _keyboard_input_timeout = u; + return (o); } /* Is there input available to be read on the readline input file - descriptor? Only works if the system has select(2) or FIONREAD. */ + descriptor? Only works if the system has select(2) or FIONREAD. + Uses the value of _keyboard_input_timeout as the timeout; if another + readline function wants to specify a timeout and not leave it up to + the user, it should use _rl_input_queued(timeout_value_in_microseconds) + instead. */ int _rl_input_available () { -#if defined (__EMX__) - if (isatty (0) && (waiting_char = _read_kbd(0, 0, 0)) != -1) - return 1; -#else /* __EMX__ */ #if defined(HAVE_SELECT) fd_set readfds, exceptfds; struct timeval timeout; #endif -#if defined(FIONREAD) +#if !defined (HAVE_SELECT) && defined(FIONREAD) int chars_avail; #endif int tty; @@ -295,28 +274,41 @@ _rl_input_available () FD_SET (tty, &readfds); FD_SET (tty, &exceptfds); timeout.tv_sec = 0; - timeout.tv_usec = 100000; /* 0.1 seconds */ + timeout.tv_usec = _keyboard_input_timeout; return (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) > 0); -#endif +#else #if defined (FIONREAD) if (ioctl (tty, FIONREAD, &chars_avail) == 0) return (chars_avail); #endif -#endif /* !__EMX__ */ + +#endif return 0; } +int +_rl_input_queued (t) + int t; +{ + int old_timeout, r; + + old_timeout = rl_set_keyboard_input_timeout (t); + r = _rl_input_available (); + rl_set_keyboard_input_timeout (old_timeout); + return r; +} + void _rl_insert_typein (c) int c; -{ +{ int key, t, i; char *string; i = key = 0; - string = xmalloc (ibuffer_len + 1); + string = (char *)xmalloc (ibuffer_len + 1); string[i++] = (char) c; while ((t = rl_get_char (&key)) && @@ -325,7 +317,7 @@ _rl_insert_typein (c) string[i++] = key; if (t) - rl_unget_char (key); + _rl_unget_char (key); string[i] = '\0'; rl_insert_text (string); @@ -345,6 +337,7 @@ rl_stuff_char (key) { key = NEWLINE; rl_pending_input = EOF; + RL_SETSTATE (RL_STATE_INPUTPENDING); } ibuffer[push_index++] = key; if (push_index >= ibuffer_len) @@ -359,6 +352,16 @@ rl_execute_next (c) int c; { rl_pending_input = c; + RL_SETSTATE (RL_STATE_INPUTPENDING); + return 0; +} + +/* Clear any pending input pushed with rl_execute_next() */ +int +rl_clear_pending_input () +{ + rl_pending_input = 0; + RL_UNSETSTATE (RL_STATE_INPUTPENDING); return 0; } @@ -379,7 +382,7 @@ rl_read_key () if (rl_pending_input) { c = rl_pending_input; - rl_pending_input = 0; + rl_clear_pending_input (); } else { @@ -393,7 +396,13 @@ rl_read_key () while (rl_event_hook && rl_get_char (&c) == 0) { (*rl_event_hook) (); - rl_gather_tyi (); + if (rl_done) /* XXX - experimental */ + return ('\n'); + if (rl_gather_tyi () < 0) /* XXX - EIO */ + { + rl_done = 1; + return ('\n'); + } } } else @@ -410,96 +419,9 @@ int rl_getc (stream) FILE *stream; { - int result, flags; + int result; unsigned char c; -#if defined (__EMX__) - if (isatty (0)) - { - int key; - - if (waiting_char != -1) - { - key = waiting_char; - waiting_char = -1; - } - else - { -#ifdef __RSXNT__ - pc_flush(); -#endif - key = _read_kbd(0, 1, 0); - } - - while (key == 0) - { - key |= (_read_kbd(0, 1, 0) << 8); - /* printf("<%04X> ", key); - fflush(stdout); */ - - switch (key) - { - case 0x4B00: /* left arrow */ - key = 'B' - 64; - break; - case 0x4D00: /* right arrow */ - key = 'F' - 64; - break; - case 0x7300: /* ctrl left arrow */ - key = 27; - waiting_char = 'B'; - break; - case 0x7400: /* ctrl right arrow */ - key = 27; - waiting_char = 'F'; - break; - case 0x4800: /* up arrow */ - key = 'P' - 64; - break; - case 0x5000: /* down arrow */ - key = 'N' - 64; - break; - case 0x8D00: /* ctrl up arrow */ - key = 'R' - 64; - break; - case 0x9100: /* ctrl down arrow */ - key = 'S' - 64; - break; - case 0x4700: /* home key */ - key = 'A' - 64; - break; - case 0x4F00: /* end key */ - key = 'E' - 64; - break; - case 0x7700: /* ctrl home key */ - key = 27; - waiting_char = '<'; - break; - case 0x7500: /* ctrl end key */ - key = 27; - waiting_char = '>'; - break; - case 0x5300: /* delete key */ - key = 'D' - 64; - break; - case 0x5200: /* insert key */ - key = 'V' - 64; - break; - default: /* ignore all other special keys, read next */ - key = _read_kbd(0, 1, 0); - break; - } - } - - return (key & 0xFF); - } -#endif /* __EMX__ */ - -#if defined (__GO32__) - if (isatty (0)) - return (getkey () & 0x7F); -#endif /* __GO32__ */ - while (1) { result = read (fileno (stream), &c, sizeof (unsigned char)); @@ -518,40 +440,101 @@ rl_getc (stream) #endif #if defined (EWOULDBLOCK) - if (errno == EWOULDBLOCK) +# define X_EWOULDBLOCK EWOULDBLOCK +#else +# define X_EWOULDBLOCK -99 +#endif + +#if defined (EAGAIN) +# define X_EAGAIN EAGAIN +#else +# define X_EAGAIN -99 +#endif + + if (errno == X_EWOULDBLOCK || errno == X_EAGAIN) { - if ((flags = fcntl (fileno (stream), F_GETFL, 0)) < 0) + if (sh_unset_nodelay_mode (fileno (stream)) < 0) return (EOF); - if (flags & O_NDELAY) - { - flags &= ~O_NDELAY; - fcntl (fileno (stream), F_SETFL, flags); - continue; - } continue; } -#endif /* EWOULDBLOCK */ -#if defined (_POSIX_VERSION) && defined (EAGAIN) && defined (O_NONBLOCK) - if (errno == EAGAIN) - { - if ((flags = fcntl (fileno (stream), F_GETFL, 0)) < 0) - return (EOF); - if (flags & O_NONBLOCK) - { - flags &= ~O_NONBLOCK; - fcntl (fileno (stream), F_SETFL, flags); - continue; - } - } -#endif /* _POSIX_VERSION && EAGAIN && O_NONBLOCK */ +#undef X_EWOULDBLOCK +#undef X_EAGAIN -#if !defined (__GO32__) /* If the error that we received was SIGINT, then try again, this is simply an interrupted system call to read (). Otherwise, some error ocurred, also signifying EOF. */ if (errno != EINTR) return (EOF); -#endif /* !__GO32__ */ } } + +#if defined (HANDLE_MULTIBYTE) +/* read multibyte char */ +int +_rl_read_mbchar (mbchar, size) + char *mbchar; + int size; +{ + int mb_len = 0; + size_t mbchar_bytes_length; + wchar_t wc; + mbstate_t ps, ps_back; + + memset(&ps, 0, sizeof (mbstate_t)); + memset(&ps_back, 0, sizeof (mbstate_t)); + + while (mb_len < size) + { + RL_SETSTATE(RL_STATE_MOREINPUT); + mbchar[mb_len++] = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + mbchar_bytes_length = mbrtowc (&wc, mbchar, mb_len, &ps); + if (mbchar_bytes_length == (size_t)(-1)) + break; /* invalid byte sequence for the current locale */ + else if (mbchar_bytes_length == (size_t)(-2)) + { + /* shorted bytes */ + ps = ps_back; + continue; + } + else if (mbchar_bytes_length > (size_t)(0)) + break; + } + + return mb_len; +} + +/* Read a multibyte-character string whose first character is FIRST into + the buffer MB of length MBLEN. Returns the last character read, which + may be FIRST. Used by the search functions, among others. Very similar + to _rl_read_mbchar. */ +int +_rl_read_mbstring (first, mb, mblen) + int first; + char *mb; + int mblen; +{ + int i, c; + mbstate_t ps; + + c = first; + memset (mb, 0, mblen); + for (i = 0; i < mblen; i++) + { + mb[i] = (char)c; + memset (&ps, 0, sizeof (mbstate_t)); + if (_rl_get_char_len (mb, &ps) == -2) + { + /* Read more for multibyte character */ + RL_SETSTATE (RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE (RL_STATE_MOREINPUT); + } + else + break; + } + return c; +} +#endif /* HANDLE_MULTIBYTE */ diff --git a/readline/isearch.c b/readline/isearch.c index a4a294b6b20..c0604ce703c 100644 --- a/readline/isearch.c +++ b/readline/isearch.c @@ -4,7 +4,7 @@ /* */ /* **************************************************************** */ -/* Copyright (C) 1987,1989 Free Software Foundation, Inc. +/* Copyright (C) 1987-2002 Free Software Foundation, Inc. This file contains the Readline Library (the Library), a set of routines for providing Emacs style line input to programs that ask @@ -12,7 +12,7 @@ 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 1, or (at your option) + 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 @@ -23,7 +23,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) @@ -45,32 +45,33 @@ #endif #include "rldefs.h" +#include "rlmbutil.h" + #include "readline.h" #include "history.h" +#include "rlprivate.h" +#include "xmalloc.h" + /* Variables exported to other files in the readline library. */ -unsigned char *_rl_isearch_terminators = (unsigned char *)NULL; +char *_rl_isearch_terminators = (char *)NULL; /* Variables imported from other files in the readline library. */ -extern Keymap _rl_keymap; -extern HIST_ENTRY *saved_line_for_history; -extern int rl_line_buffer_len; -extern int rl_point, rl_end; -extern char *rl_line_buffer; +extern HIST_ENTRY *_rl_saved_line_for_history; -extern int rl_execute_next (); -extern void rl_extend_line_buffer (); - -extern int _rl_input_available (); - -extern char *xmalloc (), *xrealloc (); - -static int rl_search_history (); +/* Forward declarations */ +static int rl_search_history PARAMS((int, int)); /* Last line found by the current incremental search, so we don't `find' identical lines many times in a row. */ static char *prev_line_found; +/* Last search string and its length. */ +static char *last_isearch_string; +static int last_isearch_string_len; + +static char default_isearch_terminators[] = "\033\012"; + /* Search backwards through the history looking for a string which is typed interactively. Start with the current line. */ int @@ -97,15 +98,14 @@ rl_forward_search_history (sign, key) static void rl_display_search (search_string, reverse_p, where) char *search_string; - int reverse_p; - int where __attribute__((unused)); + int reverse_p, where __attribute__((unused)); { char *message; int msglen, searchlen; searchlen = (search_string && *search_string) ? strlen (search_string) : 0; - message = xmalloc (searchlen + 33); + message = (char *)xmalloc (searchlen + 33); msglen = 0; #if defined (NOTDEF) @@ -135,7 +135,7 @@ rl_display_search (search_string, reverse_p, where) strcpy (message + msglen, "': "); - rl_message ("%s", message, 0); + rl_message ("%s", message); free (message); (*rl_redisplay_function) (); } @@ -145,7 +145,8 @@ rl_display_search (search_string, reverse_p, where) DIRECTION is which direction to search; >= 0 means forward, < 0 means backwards. */ static int -rl_search_history (int direction, int invoking_key __attribute__((unused))) +rl_search_history (direction, invoking_key) + int direction, invoking_key __attribute__((unused)); { /* The string that the user types in to search for. */ char *search_string; @@ -166,8 +167,12 @@ rl_search_history (int direction, int invoking_key __attribute__((unused))) HIST_ENTRY **hlist; register int i; - int orig_point, orig_line, last_found_line; + int orig_point, orig_mark, orig_line, last_found_line; int c, found, failed, sline_len; + int n, wstart, wlen; +#if defined (HANDLE_MULTIBYTE) + char mb[MB_LEN_MAX]; +#endif /* The line currently being searched. */ char *sline; @@ -181,19 +186,21 @@ rl_search_history (int direction, int invoking_key __attribute__((unused))) /* The list of characters which terminate the search, but are not subsequently executed. If the variable isearch-terminators has been set, we use that value, otherwise we use ESC and C-J. */ - unsigned char *isearch_terminators; + char *isearch_terminators; + RL_SETSTATE(RL_STATE_ISEARCH); orig_point = rl_point; + orig_mark = rl_mark; last_found_line = orig_line = where_history (); reverse = direction < 0; hlist = history_list (); allocated_line = (char *)NULL; isearch_terminators = _rl_isearch_terminators ? _rl_isearch_terminators - : (unsigned char *)"\033\012"; + : default_isearch_terminators; /* Create an arrary of pointers to the lines that we want to search. */ - maybe_replace_line (); + rl_maybe_replace_line (); i = 0; if (hlist) for (i = 0; hlist[i]; i++); @@ -204,12 +211,12 @@ rl_search_history (int direction, int invoking_key __attribute__((unused))) for (i = 0; i < hlen; i++) lines[i] = hlist[i]->line; - if (saved_line_for_history) - lines[i] = saved_line_for_history->line; + if (_rl_saved_line_for_history) + lines[i] = _rl_saved_line_for_history->line; else { /* Keep track of this so we can free it. */ - allocated_line = xmalloc (1 + strlen (rl_line_buffer)); + allocated_line = (char *)xmalloc (1 + strlen (rl_line_buffer)); strcpy (allocated_line, &rl_line_buffer[0]); lines[i] = allocated_line; } @@ -222,7 +229,7 @@ rl_search_history (int direction, int invoking_key __attribute__((unused))) rl_save_prompt (); /* Initialize search parameters. */ - search_string = xmalloc (search_string_size = 128); + search_string = (char *)xmalloc (search_string_size = 128); *search_string = '\0'; search_string_index = 0; prev_line_found = (char *)0; /* XXX */ @@ -239,12 +246,20 @@ rl_search_history (int direction, int invoking_key __attribute__((unused))) found = failed = 0; for (;;) { - Function *f = (Function *)NULL; + rl_command_func_t *f = (rl_command_func_t *)NULL; /* Read a key and decide how to proceed. */ + RL_SETSTATE(RL_STATE_MOREINPUT); c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); - if (_rl_keymap[c].type == ISFUNC) +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + c = _rl_read_mbstring (c, mb, MB_LEN_MAX); +#endif + + /* Translate the keys we do something with to opcodes. */ + if (c >= 0 && _rl_keymap[c].type == ISFUNC) { f = _rl_keymap[c].function; @@ -252,34 +267,56 @@ rl_search_history (int direction, int invoking_key __attribute__((unused))) c = reverse ? -1 : -2; else if (f == rl_forward_search_history) c = !reverse ? -1 : -2; + else if (f == rl_rubout) + c = -3; + else if (c == CTRL ('G')) + c = -4; + else if (c == CTRL ('W')) /* XXX */ + c = -5; + else if (c == CTRL ('Y')) /* XXX */ + c = -6; } -#if 0 - /* Let NEWLINE (^J) terminate the search for people who don't like - using ESC. ^M can still be used to terminate the search and - immediately execute the command. */ - if (c == ESC || c == NEWLINE) -#else /* The characters in isearch_terminators (set from the user-settable variable isearch-terminators) are used to terminate the search but not subsequently execute the character as a command. The default value is "\033\012" (ESC and C-J). */ - if (strchr((char*) isearch_terminators, c)) -#endif + if (strchr (isearch_terminators, c)) { /* ESC still terminates the search, but if there is pending input or if input arrives within 0.1 seconds (on systems with select(2)) it is used as a prefix character with rl_execute_next. WATCH OUT FOR THIS! This is intended to allow the arrow keys to be used like ^F and ^B are used - to terminate the search and execute the movement command. */ - if (c == ESC && _rl_input_available ()) /* XXX */ + to terminate the search and execute the movement command. + XXX - since _rl_input_available depends on the application- + settable keyboard timeout value, this could alternatively + use _rl_input_queued(100000) */ + if (c == ESC && _rl_input_available ()) rl_execute_next (ESC); break; } - if (c >= 0 && (CTRL_CHAR (c) || META_CHAR (c) || c == RUBOUT) && c != CTRL ('G')) +#define ENDSRCH_CHAR(c) \ + ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G'))) + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { + if (c >= 0 && strlen (mb) == 1 && ENDSRCH_CHAR (c)) + { + /* This sets rl_pending_input to c; it will be picked up the next + time rl_read_key is called. */ + rl_execute_next (c); + break; + } + } + else +#endif + if (c >= 0 && ENDSRCH_CHAR (c)) + { + /* This sets rl_pending_input to c; it will be picked up the next + time rl_read_key is called. */ rl_execute_next (c); break; } @@ -288,13 +325,24 @@ rl_search_history (int direction, int invoking_key __attribute__((unused))) { case -1: if (search_string_index == 0) - continue; + { + if (last_isearch_string) + { + search_string_size = 64 + last_isearch_string_len; + search_string = (char *)xrealloc (search_string, search_string_size); + strcpy (search_string, last_isearch_string); + search_string_index = last_isearch_string_len; + rl_display_search (search_string, reverse, -1); + break; + } + continue; + } else if (reverse) --line_index; else if (line_index != sline_len) ++line_index; else - ding (); + rl_ding (); break; /* switch directions */ @@ -303,40 +351,96 @@ rl_search_history (int direction, int invoking_key __attribute__((unused))) reverse = direction < 0; break; - case CTRL ('G'): - strcpy (rl_line_buffer, lines[orig_line]); + /* delete character from search string. */ + case -3: /* C-H, DEL */ + /* This is tricky. To do this right, we need to keep a + stack of search positions for the current search, with + sentinels marking the beginning and end. But this will + do until we have a real isearch-undo. */ + if (search_string_index == 0) + rl_ding (); + else + search_string[--search_string_index] = '\0'; + + break; + + case -4: /* C-G */ + rl_replace_line (lines[orig_line], 0); rl_point = orig_point; - rl_end = strlen (rl_line_buffer); + rl_mark = orig_mark; rl_restore_prompt(); rl_clear_message (); if (allocated_line) free (allocated_line); free (lines); + RL_UNSETSTATE(RL_STATE_ISEARCH); return 0; -#if 0 - /* delete character from search string. */ - case -3: - if (search_string_index == 0) - ding (); - else + case -5: /* C-W */ + /* skip over portion of line we already matched */ + wstart = rl_point + search_string_index; + if (wstart >= rl_end) { - search_string[--search_string_index] = '\0'; - /* This is tricky. To do this right, we need to keep a - stack of search positions for the current search, with - sentinels marking the beginning and end. */ + rl_ding (); + break; } + + /* if not in a word, move to one. */ + if (rl_alphabetic(rl_line_buffer[wstart]) == 0) + { + rl_ding (); + break; + } + n = wstart; + while (n < rl_end && rl_alphabetic(rl_line_buffer[n])) + n++; + wlen = n - wstart + 1; + if (search_string_index + wlen + 1 >= search_string_size) + { + search_string_size += wlen + 1; + search_string = (char *)xrealloc (search_string, search_string_size); + } + for (; wstart < n; wstart++) + search_string[search_string_index++] = rl_line_buffer[wstart]; + search_string[search_string_index] = '\0'; + break; + + case -6: /* C-Y */ + /* skip over portion of line we already matched */ + wstart = rl_point + search_string_index; + if (wstart >= rl_end) + { + rl_ding (); + break; + } + n = rl_end - wstart + 1; + if (search_string_index + n + 1 >= search_string_size) + { + search_string_size += n + 1; + search_string = (char *)xrealloc (search_string, search_string_size); + } + for (n = wstart; n < rl_end; n++) + search_string[search_string_index++] = rl_line_buffer[n]; + search_string[search_string_index] = '\0'; break; -#endif default: /* Add character to search string and continue search. */ if (search_string_index + 2 >= search_string_size) { search_string_size += 128; - search_string = xrealloc (search_string, search_string_size); + search_string = (char *)xrealloc (search_string, search_string_size); } - search_string[search_string_index++] = c; +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + int j, l; + for (j = 0, l = strlen (mb); j < l; ) + search_string[search_string_index++] = mb[j++]; + } + else +#endif + search_string[search_string_index++] = c; search_string[search_string_index] = '\0'; break; } @@ -391,7 +495,7 @@ rl_search_history (int direction, int invoking_key __attribute__((unused))) if (failed) { /* We cannot find the search string. Ding the bell. */ - ding (); + rl_ding (); i = last_found_line; continue; /* XXX - was break */ } @@ -401,17 +505,9 @@ rl_search_history (int direction, int invoking_key __attribute__((unused))) the location. */ if (found) { - int line_len; - prev_line_found = lines[i]; - line_len = strlen (lines[i]); - - if (line_len >= rl_line_buffer_len) - rl_extend_line_buffer (line_len); - - strcpy (rl_line_buffer, lines[i]); + rl_replace_line (lines[i], 0); rl_point = line_index; - rl_end = line_len; last_found_line = i; rl_display_search (search_string, reverse, (i == orig_line) ? -1 : i); } @@ -427,23 +523,38 @@ rl_search_history (int direction, int invoking_key __attribute__((unused))) rl_restore_prompt (); - /* Free the search string. */ - free (search_string); + /* Save the search string for possible later use. */ + FREE (last_isearch_string); + last_isearch_string = search_string; + last_isearch_string_len = search_string_index; if (last_found_line < orig_line) rl_get_previous_history (orig_line - last_found_line, 0); else rl_get_next_history (last_found_line - orig_line, 0); - /* If the string was not found, put point at the end of the line. */ + /* If the string was not found, put point at the end of the last matching + line. If last_found_line == orig_line, we didn't find any matching + history lines at all, so put point back in its original position. */ if (line_index < 0) - line_index = strlen (rl_line_buffer); + { + if (last_found_line == orig_line) + line_index = orig_point; + else + line_index = strlen (rl_line_buffer); + rl_mark = orig_mark; + } + rl_point = line_index; + /* Don't worry about where to put the mark here; rl_get_previous_history + and rl_get_next_history take care of it. */ + rl_clear_message (); - if (allocated_line) - free (allocated_line); + FREE (allocated_line); free (lines); + RL_UNSETSTATE(RL_STATE_ISEARCH); + return 0; } diff --git a/readline/keymaps.c b/readline/keymaps.c index c73666bf273..12506d3aab2 100644 --- a/readline/keymaps.c +++ b/readline/keymaps.c @@ -7,7 +7,7 @@ Readline 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 + Free Software Foundation; either version 2, or (at your option) any later version. Readline is distributed in the hope that it will be useful, but @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with Readline; see the file COPYING. If not, write to the Free - Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) @@ -30,18 +30,18 @@ # include "ansi_stdlib.h" #endif /* HAVE_STDLIB_H */ +#include /* for FILE * definition for readline.h */ + +#include "readline.h" #include "rlconf.h" -#include "keymaps.h" + #include "emacs_keymap.c" #if defined (VI_MODE) #include "vi_keymap.c" #endif -extern int rl_do_lowercase_version (); -extern int rl_rubout (), rl_insert (); - -extern char *xmalloc (), *xrealloc (); +#include "xmalloc.h" /* **************************************************************** */ /* */ @@ -61,7 +61,7 @@ rl_make_bare_keymap () for (i = 0; i < KEYMAP_SIZE; i++) { keymap[i].type = ISFUNC; - keymap[i].function = (Function *)NULL; + keymap[i].function = (rl_command_func_t *)NULL; } for (i = 'A'; i < ('Z' + 1); i++) diff --git a/readline/keymaps.h b/readline/keymaps.h index 5dff46f56c2..66fa2a5ec14 100644 --- a/readline/keymaps.h +++ b/readline/keymaps.h @@ -7,7 +7,7 @@ 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 1, or + 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 @@ -18,25 +18,23 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #ifndef _KEYMAPS_H_ #define _KEYMAPS_H_ +#ifdef __cplusplus +extern "C" { +#endif + #if defined (READLINE_LIBRARY) # include "rlstdc.h" # include "chardefs.h" +# include "rltypedefs.h" #else # include # include -#endif - -#if !defined (_FUNCTION_DEF) -# define _FUNCTION_DEF -typedef int Function (); -typedef void VFunction (); -typedef char *CPFunction (); -typedef char **CPPFunction (); +# include #endif /* A keymap contains one entry for each key in the ASCII set. @@ -46,16 +44,17 @@ typedef char **CPPFunction (); TYPE says which kind of thing FUNCTION is. */ typedef struct _keymap_entry { char type; - Function *function; + rl_command_func_t *function; } KEYMAP_ENTRY; /* This must be large enough to hold bindings for all of the characters in a desired character set (e.g, 128 for ASCII, 256 for ISO Latin-x, - and so on). */ -#define KEYMAP_SIZE 256 + and so on) plus one for subsequence matching. */ +#define KEYMAP_SIZE 257 +#define ANYOTHERKEY KEYMAP_SIZE-1 /* I wanted to make the above structure contain a union of: - union { Function *function; struct _keymap_entry *keymap; } value; + union { rl_command_func_t *function; struct _keymap_entry *keymap; } value; but this made it impossible for me to create a static array. Maybe I need C lessons. */ @@ -72,29 +71,33 @@ extern KEYMAP_ENTRY_ARRAY vi_insertion_keymap, vi_movement_keymap; /* Return a new, empty keymap. Free it with free() when you are done. */ -extern Keymap rl_make_bare_keymap __P((void)); +extern Keymap rl_make_bare_keymap PARAMS((void)); /* Return a new keymap which is a copy of MAP. */ -extern Keymap rl_copy_keymap __P((Keymap)); +extern Keymap rl_copy_keymap PARAMS((Keymap)); /* Return a new keymap with the printing characters bound to rl_insert, the lowercase Meta characters bound to run their equivalents, and the Meta digits bound to produce numeric arguments. */ -extern Keymap rl_make_keymap __P((void)); +extern Keymap rl_make_keymap PARAMS((void)); /* Free the storage associated with a keymap. */ -extern void rl_discard_keymap __P((Keymap)); +extern void rl_discard_keymap PARAMS((Keymap)); /* These functions actually appear in bind.c */ /* Return the keymap corresponding to a given name. Names look like `emacs' or `emacs-meta' or `vi-insert'. */ -extern Keymap rl_get_keymap_by_name __P((char *)); +extern Keymap rl_get_keymap_by_name PARAMS((const char *)); /* Return the current keymap. */ -extern Keymap rl_get_keymap __P((void)); +extern Keymap rl_get_keymap PARAMS((void)); /* Set the current keymap to MAP. */ -extern void rl_set_keymap __P((Keymap)); +extern void rl_set_keymap PARAMS((Keymap)); + +#ifdef __cplusplus +} +#endif #endif /* _KEYMAPS_H_ */ diff --git a/readline/kill.c b/readline/kill.c index 78387e138c2..f8c6961bbd3 100644 --- a/readline/kill.c +++ b/readline/kill.c @@ -7,7 +7,7 @@ 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 1, or + 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 @@ -18,7 +18,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) @@ -46,17 +46,8 @@ #include "readline.h" #include "history.h" -extern int _rl_last_command_was_kill; -extern int rl_editing_mode; -extern int rl_explicit_arg; -extern Function *rl_last_func; - -extern void _rl_init_argument (); -extern int _rl_set_mark_at_pos (); -extern void _rl_fix_point (); -extern void _rl_abort_internal (); - -extern char *xmalloc (), *xrealloc (); +#include "rlprivate.h" +#include "xmalloc.h" /* **************************************************************** */ /* */ @@ -79,10 +70,16 @@ static int rl_kill_index; /* How many slots we have in the kill ring. */ static int rl_kill_ring_length; +static int _rl_copy_to_kill_ring PARAMS((char *, int)); +static int region_kill_internal PARAMS((int)); +static int _rl_copy_word_as_kill PARAMS((int, int)); +static int rl_yank_nth_arg_internal PARAMS((int, int, int)); + /* How to say that you only want to save a certain amount of kill material. */ int -rl_set_retained_kills (int num __attribute__((unused))) +rl_set_retained_kills (num) + int num __attribute__((unused)); { return 0; } @@ -137,7 +134,7 @@ _rl_copy_to_kill_ring (text, append) if (_rl_last_command_was_kill && rl_editing_mode != vi_mode) { old = rl_kill_ring[slot]; - new = xmalloc (1 + strlen (old) + strlen (text)); + new = (char *)xmalloc (1 + strlen (old) + strlen (text)); if (append) { @@ -204,18 +201,21 @@ int rl_kill_word (count, key) int count, key; { - int orig_point = rl_point; + int orig_point; if (count < 0) return (rl_backward_kill_word (-count, key)); else { + orig_point = rl_point; rl_forward_word (count, key); if (rl_point != orig_point) rl_kill_text (orig_point, rl_point); rl_point = orig_point; + if (rl_editing_mode == emacs_mode) + rl_mark = rl_point; } return 0; } @@ -225,16 +225,20 @@ int rl_backward_kill_word (count, ignore) int count, ignore; { - int orig_point = rl_point; + int orig_point; if (count < 0) return (rl_kill_word (-count, ignore)); else { + orig_point = rl_point; rl_backward_word (count, ignore); if (rl_point != orig_point) rl_kill_text (orig_point, rl_point); + + if (rl_editing_mode == emacs_mode) + rl_mark = rl_point; } return 0; } @@ -245,16 +249,19 @@ int rl_kill_line (direction, ignore) int direction, ignore; { - int orig_point = rl_point; + int orig_point; if (direction < 0) return (rl_backward_kill_line (1, ignore)); else { + orig_point = rl_point; rl_end_of_line (1, ignore); if (orig_point != rl_point) rl_kill_text (orig_point, rl_point); rl_point = orig_point; + if (rl_editing_mode == emacs_mode) + rl_mark = rl_point; } return 0; } @@ -265,18 +272,22 @@ int rl_backward_kill_line (direction, ignore) int direction, ignore; { - int orig_point = rl_point; + int orig_point; if (direction < 0) return (rl_kill_line (1, ignore)); else { if (!rl_point) - ding (); + rl_ding (); else { + orig_point = rl_point; rl_beg_of_line (1, ignore); - rl_kill_text (orig_point, rl_point); + if (rl_point != orig_point) + rl_kill_text (orig_point, rl_point); + if (rl_editing_mode == emacs_mode) + rl_mark = rl_point; } } return 0; @@ -284,12 +295,13 @@ rl_backward_kill_line (direction, ignore) /* Kill the whole line, no matter where point is. */ int -rl_kill_full_line (int count __attribute__((unused)), - int ignore __attribute__((unused))) +rl_kill_full_line (count, ignore) + int count __attribute__((unused)), ignore __attribute__((unused)); { rl_begin_undo_group (); rl_point = 0; rl_kill_text (rl_point, rl_end); + rl_mark = 0; rl_end_undo_group (); return 0; } @@ -301,12 +313,13 @@ rl_kill_full_line (int count __attribute__((unused)), /* This does what C-w does in Unix. We can't prevent people from using behaviour that they expect. */ int -rl_unix_word_rubout (int count, int key __attribute__((unused))) +rl_unix_word_rubout (count, key) + int count, key __attribute__((unused)); { int orig_point; if (rl_point == 0) - ding (); + rl_ding (); else { orig_point = rl_point; @@ -323,6 +336,8 @@ rl_unix_word_rubout (int count, int key __attribute__((unused))) } rl_kill_text (orig_point, rl_point); + if (rl_editing_mode == emacs_mode) + rl_mark = rl_point; } return 0; } @@ -334,15 +349,17 @@ rl_unix_word_rubout (int count, int key __attribute__((unused))) into the line at all, and if you aren't, then you know what you are doing. */ int -rl_unix_line_discard (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_unix_line_discard (count, key) + int count __attribute__((unused)), key __attribute__((unused)); { if (rl_point == 0) - ding (); + rl_ding (); else { rl_kill_text (rl_point, 0); rl_point = 0; + if (rl_editing_mode == emacs_mode) + rl_mark = rl_point; } return 0; } @@ -355,38 +372,37 @@ region_kill_internal (delete) { char *text; - if (rl_mark == rl_point) + if (rl_mark != rl_point) { - _rl_last_command_was_kill++; - return 0; + text = rl_copy_text (rl_point, rl_mark); + if (delete) + rl_delete_text (rl_point, rl_mark); + _rl_copy_to_kill_ring (text, rl_point < rl_mark); } - text = rl_copy_text (rl_point, rl_mark); - if (delete) - rl_delete_text (rl_point, rl_mark); - _rl_copy_to_kill_ring (text, rl_point < rl_mark); - _rl_last_command_was_kill++; return 0; } /* Copy the text in the region to the kill ring. */ int -rl_copy_region_to_kill (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_copy_region_to_kill (count, ignore) + int count __attribute__((unused)), ignore __attribute__((unused)); { return (region_kill_internal (0)); } /* Kill the text between the point and mark. */ int -rl_kill_region (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_kill_region (count, ignore) + int count __attribute__((unused)), ignore __attribute__((unused)); { - int r; + int r, npoint; + npoint = (rl_point < rl_mark) ? rl_point : rl_mark; r = region_kill_internal (1); _rl_fix_point (1); + rl_point = npoint; return r; } @@ -440,11 +456,11 @@ rl_copy_backward_word (count, key) return (_rl_copy_word_as_kill (count, -1)); } - + /* Yank back the last killed text. This ignores arguments. */ int -rl_yank (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_yank (count, ignore) + int count __attribute__((unused)), ignore __attribute__((unused)); { if (rl_kill_ring == 0) { @@ -462,8 +478,8 @@ rl_yank (int count __attribute__((unused)), delete that text from the line, rotate the index down, and yank back some other text. */ int -rl_yank_pop (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_yank_pop (count, key) + int count __attribute__((unused)), key __attribute__((unused)); { int l, n; @@ -501,7 +517,9 @@ rl_yank_nth_arg_internal (count, ignore, history_skip) { register HIST_ENTRY *entry; char *arg; - int i; + int i, pos; + + pos = where_history (); if (history_skip) { @@ -510,30 +528,26 @@ rl_yank_nth_arg_internal (count, ignore, history_skip) } entry = previous_history (); - if (entry) + + history_set_pos (pos); + + if (entry == 0) { - if (history_skip) - { - for (i = 0; i < history_skip; i++) - next_history (); - } - next_history (); - } - else - { - ding (); + rl_ding (); return -1; } arg = history_arg_extract (count, count, entry->line); if (!arg || !*arg) { - ding (); + rl_ding (); return -1; } rl_begin_undo_group (); + _rl_set_mark_at_pos (rl_point); + #if defined (VI_MODE) /* Vi mode always inserts a space before yanking the argument, and it inserts it right *after* rl_point. */ @@ -590,7 +604,7 @@ rl_yank_last_arg (count, key) if (history_skip < 0) history_skip = 0; } - + if (explicit_arg_p) retval = rl_yank_nth_arg_internal (count_passed, key, history_skip); else @@ -601,7 +615,7 @@ rl_yank_last_arg (count, key) } /* A special paste command for users of Cygnus's cygwin32. */ -#if defined (__CYGWIN32__) +#if defined (__CYGWIN__) #include int @@ -621,12 +635,13 @@ rl_paste_from_clipboard (count, key) if (ptr) { len = ptr - data; - ptr = xmalloc (len + 1); + ptr = (char *)xmalloc (len + 1); ptr[len] = '\0'; strncpy (ptr, data, len); } else ptr = data; + _rl_set_mark_at_pos (rl_point); rl_insert_text (ptr); if (ptr != data) free (ptr); @@ -634,4 +649,4 @@ rl_paste_from_clipboard (count, key) } return (0); } -#endif /* __CYGWIN32__ */ +#endif /* __CYGWIN__ */ diff --git a/readline/macro.c b/readline/macro.c index b4d7835c631..7ab4b6ca657 100644 --- a/readline/macro.c +++ b/readline/macro.c @@ -7,7 +7,7 @@ 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 1, or + 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 @@ -18,7 +18,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) @@ -46,19 +46,8 @@ #include "readline.h" #include "history.h" -#define SWAP(s, e) do { int t; t = s; s = e; e = t; } while (0) - -/* Forward definitions. */ -void _rl_push_executing_macro (), _rl_pop_executing_macro (); -void _rl_add_macro_char (); - -/* Extern declarations. */ -extern int rl_explicit_arg; -extern int rl_key_sequence_length; - -extern void _rl_abort_internal (); - -extern char *xmalloc (), *xrealloc (); +#include "rlprivate.h" +#include "xmalloc.h" /* **************************************************************** */ /* */ @@ -66,12 +55,9 @@ extern char *xmalloc (), *xrealloc (); /* */ /* **************************************************************** */ -/* Non-zero means to save keys that we dispatch on in a kbd macro. */ -int _rl_defining_kbd_macro = 0; - /* The currently executing macro string. If this is non-zero, then it is a malloc ()'ed string where input is coming from. */ -char *_rl_executing_macro = (char *)NULL; +char *rl_executing_macro = (char *)NULL; /* The offset in the above string to the next character to be read. */ static int executing_macro_index; @@ -90,7 +76,7 @@ static int current_macro_index; It is a linked list of string/index for each saved macro. */ struct saved_macro { struct saved_macro *next; - const char *string; + char *string; int sindex; }; @@ -100,11 +86,13 @@ static struct saved_macro *macro_list = (struct saved_macro *)NULL; /* Set up to read subsequent input from STRING. STRING is free ()'ed when we are done with it. */ void -_rl_with_macro_input (const char *string) +_rl_with_macro_input (string) + char *string; { _rl_push_executing_macro (); - _rl_executing_macro = (char*) string; + rl_executing_macro = string; executing_macro_index = 0; + RL_SETSTATE(RL_STATE_MACROINPUT); } /* Return the next character available from a macro, or 0 if @@ -112,16 +100,16 @@ _rl_with_macro_input (const char *string) int _rl_next_macro_key () { - if (_rl_executing_macro == 0) + if (rl_executing_macro == 0) return (0); - if (_rl_executing_macro[executing_macro_index] == 0) + if (rl_executing_macro[executing_macro_index] == 0) { _rl_pop_executing_macro (); return (_rl_next_macro_key ()); } - return (_rl_executing_macro[executing_macro_index++]); + return (rl_executing_macro[executing_macro_index++]); } /* Save the currently executing macro on a stack of saved macros. */ @@ -133,7 +121,7 @@ _rl_push_executing_macro () saver = (struct saved_macro *)xmalloc (sizeof (struct saved_macro)); saver->next = macro_list; saver->sindex = executing_macro_index; - saver->string = _rl_executing_macro; + saver->string = rl_executing_macro; macro_list = saver; } @@ -145,20 +133,21 @@ _rl_pop_executing_macro () { struct saved_macro *macro; - if (_rl_executing_macro) - free (_rl_executing_macro); - - _rl_executing_macro = (char *)NULL; + FREE (rl_executing_macro); + rl_executing_macro = (char *)NULL; executing_macro_index = 0; if (macro_list) { macro = macro_list; - _rl_executing_macro = (char*) macro_list->string; + rl_executing_macro = macro_list->string; executing_macro_index = macro_list->sindex; macro_list = macro_list->next; free (macro); } + + if (rl_executing_macro == 0) + RL_UNSETSTATE(RL_STATE_MACROINPUT); } /* Add a character to the macro being built. */ @@ -169,9 +158,9 @@ _rl_add_macro_char (c) if (current_macro_index + 1 >= current_macro_size) { if (current_macro == 0) - current_macro = xmalloc (current_macro_size = 25); + current_macro = (char *)xmalloc (current_macro_size = 25); else - current_macro = xrealloc (current_macro, current_macro_size += 25); + current_macro = (char *)xrealloc (current_macro, current_macro_size += 25); } current_macro[current_macro_index++] = c; @@ -188,14 +177,11 @@ _rl_kill_kbd_macro () } current_macro_size = current_macro_index = 0; - if (_rl_executing_macro) - { - free (_rl_executing_macro); - _rl_executing_macro = (char *) NULL; - } + FREE (rl_executing_macro); + rl_executing_macro = (char *) NULL; executing_macro_index = 0; - _rl_defining_kbd_macro = 0; + RL_UNSETSTATE(RL_STATE_MACRODEF); } /* Begin defining a keyboard macro. @@ -205,10 +191,10 @@ _rl_kill_kbd_macro () definition to the end of the existing macro, and start by re-executing the existing macro. */ int -rl_start_kbd_macro (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_start_kbd_macro (ignore1, ignore2) + int ignore1 __attribute__((unused)), ignore2 __attribute__((unused)); { - if (_rl_defining_kbd_macro) + if (RL_ISSTATE (RL_STATE_MACRODEF)) { _rl_abort_internal (); return -1; @@ -222,7 +208,7 @@ rl_start_kbd_macro (int count __attribute__((unused)), else current_macro_index = 0; - _rl_defining_kbd_macro = 1; + RL_SETSTATE(RL_STATE_MACRODEF); return 0; } @@ -230,9 +216,10 @@ rl_start_kbd_macro (int count __attribute__((unused)), A numeric argument says to execute the macro right now, that many times, counting the definition as the first time. */ int -rl_end_kbd_macro (int count, int ignore __attribute__((unused))) +rl_end_kbd_macro (count, ignore) + int count, ignore __attribute__((unused)); { - if (_rl_defining_kbd_macro == 0) + if (RL_ISSTATE (RL_STATE_MACRODEF) == 0) { _rl_abort_internal (); return -1; @@ -241,7 +228,7 @@ rl_end_kbd_macro (int count, int ignore __attribute__((unused))) current_macro_index -= rl_key_sequence_length - 1; current_macro[current_macro_index] = '\0'; - _rl_defining_kbd_macro = 0; + RL_UNSETSTATE(RL_STATE_MACRODEF); return (rl_call_last_kbd_macro (--count, 0)); } @@ -249,14 +236,15 @@ rl_end_kbd_macro (int count, int ignore __attribute__((unused))) /* Execute the most recently defined keyboard macro. COUNT says how many times to execute it. */ int -rl_call_last_kbd_macro (int count, int key __attribute__((unused))) +rl_call_last_kbd_macro (count, ignore) + int count, ignore __attribute__((unused)); { if (current_macro == 0) _rl_abort_internal (); - if (_rl_defining_kbd_macro) + if (RL_ISSTATE (RL_STATE_MACRODEF)) { - ding (); /* no recursive macros */ + rl_ding (); /* no recursive macros */ current_macro[--current_macro_index] = '\0'; /* erase this char */ return 0; } diff --git a/readline/mbutil.c b/readline/mbutil.c new file mode 100644 index 00000000000..1b7342bfc0b --- /dev/null +++ b/readline/mbutil.c @@ -0,0 +1,337 @@ +/* mbutil.c -- readline multibyte character utility functions */ + +/* Copyright (C) 2001 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 +#include +#include "posixjmp.h" + +#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 +#include + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" +#include "rlmbutil.h" + +#if defined (TIOCSTAT_IN_SYS_IOCTL) +# include +#endif /* TIOCSTAT_IN_SYS_IOCTL */ + +/* Some standard library routines. */ +#include "readline.h" + +#include "rlprivate.h" +#include "xmalloc.h" + +/* Declared here so it can be shared between the readline and history + libraries. */ +#if defined (HANDLE_MULTIBYTE) +int rl_byte_oriented = 0; +#else +int rl_byte_oriented = 1; +#endif + +/* **************************************************************** */ +/* */ +/* Multibyte Character Utility Functions */ +/* */ +/* **************************************************************** */ + +#if defined(HANDLE_MULTIBYTE) + +static int +_rl_find_next_mbchar_internal (string, seed, count, find_non_zero) + char *string; + int seed, count, find_non_zero; +{ + size_t tmp = 0; + mbstate_t ps; + int point = 0; + wchar_t wc; + + memset(&ps, 0, sizeof (mbstate_t)); + if (seed < 0) + seed = 0; + if (count <= 0) + return seed; + + point = seed + _rl_adjust_point(string, seed, &ps); + /* if this is true, means that seed was not pointed character + started byte. So correct the point and consume count */ + if (seed < point) + count --; + + while (count > 0) + { + tmp = mbrtowc (&wc, string+point, strlen(string + point), &ps); + if ((size_t)(tmp) == (size_t)-1 || (size_t)(tmp) == (size_t)-2) + { + /* invalid bytes. asume a byte represents a character */ + point++; + count--; + /* reset states. */ + memset(&ps, 0, sizeof(mbstate_t)); + } + else if (tmp == (size_t)0) + /* found '\0' char */ + break; + else + { + /* valid bytes */ + point += tmp; + if (find_non_zero) + { + if (wcwidth (wc) == 0) + continue; + else + count--; + } + else + count--; + } + } + + if (find_non_zero) + { + tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps); + while (wcwidth (wc) == 0) + { + point += tmp; + tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps); + if (tmp == (size_t)(0) || tmp == (size_t)(-1) || tmp == (size_t)(-2)) + break; + } + } + return point; +} + +static int +_rl_find_prev_mbchar_internal (string, seed, find_non_zero) + char *string; + int seed, find_non_zero; +{ + mbstate_t ps; + int prev, non_zero_prev, point, length; + size_t tmp; + wchar_t wc; + + memset(&ps, 0, sizeof(mbstate_t)); + length = strlen(string); + + if (seed < 0) + return 0; + else if (length < seed) + return length; + + prev = non_zero_prev = point = 0; + while (point < seed) + { + tmp = mbrtowc (&wc, string + point, length - point, &ps); + if ((size_t)(tmp) == (size_t)-1 || (size_t)(tmp) == (size_t)-2) + { + /* in this case, bytes are invalid or shorted to compose + multibyte char, so assume that the first byte represents + a single character anyway. */ + tmp = 1; + /* clear the state of the byte sequence, because + in this case effect of mbstate is undefined */ + memset(&ps, 0, sizeof (mbstate_t)); + } + else if (tmp == 0) + break; /* Found '\0' char. Can this happen? */ + else + { + if (find_non_zero) + { + if (wcwidth (wc) != 0) + prev = point; + } + else + prev = point; + } + + point += tmp; + } + + return prev; +} + +/* return the number of bytes parsed from the multibyte sequence starting + at src, if a non-L'\0' wide character was recognized. It returns 0, + if a L'\0' wide character was recognized. It returns (size_t)(-1), + if an invalid multibyte sequence was encountered. It returns (size_t)(-2) + if it couldn't parse a complete multibyte character. */ +int +_rl_get_char_len (src, ps) + char *src; + mbstate_t *ps; +{ + size_t tmp; + + tmp = mbrlen((const char *)src, (size_t)strlen (src), ps); + if (tmp == (size_t)(-2)) + { + /* shorted to compose multibyte char */ + memset (ps, 0, sizeof(mbstate_t)); + return -2; + } + else if (tmp == (size_t)(-1)) + { + /* invalid to compose multibyte char */ + /* initialize the conversion state */ + memset (ps, 0, sizeof(mbstate_t)); + return -1; + } + else if (tmp == (size_t)0) + return 0; + else + return (int)tmp; +} + +/* compare the specified two characters. If the characters matched, + return 1. Otherwise return 0. */ +int +_rl_compare_chars (buf1, pos1, ps1, buf2, pos2, ps2) + char *buf1, *buf2; + mbstate_t *ps1, *ps2; + int pos1, pos2; +{ + int i, w1, w2; + + if ((w1 = _rl_get_char_len (&buf1[pos1], ps1)) <= 0 || + (w2 = _rl_get_char_len (&buf2[pos2], ps2)) <= 0 || + (w1 != w2) || + (buf1[pos1] != buf2[pos2])) + return 0; + + for (i = 1; i < w1; i++) + if (buf1[pos1+i] != buf2[pos2+i]) + return 0; + + return 1; +} + +/* adjust pointed byte and find mbstate of the point of string. + adjusted point will be point <= adjusted_point, and returns + differences of the byte(adjusted_point - point). + if point is invalied (point < 0 || more than string length), + it returns -1 */ +int +_rl_adjust_point(string, point, ps) + char *string; + int point; + mbstate_t *ps; +{ + size_t tmp = 0; + int length; + int pos = 0; + + length = strlen(string); + if (point < 0) + return -1; + if (length < point) + return -1; + + while (pos < point) + { + tmp = mbrlen (string + pos, length - pos, ps); + if((size_t)(tmp) == (size_t)-1 || (size_t)(tmp) == (size_t)-2) + { + /* in this case, bytes are invalid or shorted to compose + multibyte char, so assume that the first byte represents + a single character anyway. */ + pos++; + /* clear the state of the byte sequence, because + in this case effect of mbstate is undefined */ + memset (ps, 0, sizeof (mbstate_t)); + } + else + pos += tmp; + } + + return (pos - point); +} + +int +_rl_is_mbchar_matched (string, seed, end, mbchar, length) + char *string; + int seed, end; + char *mbchar; + int length; +{ + int i; + + if ((end - seed) < length) + return 0; + + for (i = 0; i < length; i++) + if (string[seed + i] != mbchar[i]) + return 0; + return 1; +} +#endif /* HANDLE_MULTIBYTE */ + +/* Find next `count' characters started byte point of the specified seed. + If flags is MB_FIND_NONZERO, we look for non-zero-width multibyte + characters. */ +#undef _rl_find_next_mbchar +int +_rl_find_next_mbchar (string, seed, count, flags) + char *string __attribute__((unused)); + int seed, count, flags __attribute__((unused)); +{ +#if defined (HANDLE_MULTIBYTE) + return _rl_find_next_mbchar_internal (string, seed, count, flags); +#else + return (seed + count); +#endif +} + +/* Find previous character started byte point of the specified seed. + Returned point will be point <= seed. If flags is MB_FIND_NONZERO, + we look for non-zero-width multibyte characters. */ +#undef _rl_find_prev_mbchar +int +_rl_find_prev_mbchar (string, seed, flags) + char *string __attribute__((unused)); + int seed, flags __attribute__((unused)); +{ +#if defined (HANDLE_MULTIBYTE) + return _rl_find_prev_mbchar_internal (string, seed, flags); +#else + return ((seed == 0) ? seed : seed - 1); +#endif +} diff --git a/readline/misc.c b/readline/misc.c new file mode 100644 index 00000000000..94ad433473b --- /dev/null +++ b/readline/misc.c @@ -0,0 +1,496 @@ +/* misc.c -- miscellaneous bindable readline functions. */ + +/* Copyright (C) 1987-2002 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 + +#if defined (HAVE_UNISTD_H) +# include +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#if defined (HAVE_LOCALE_H) +# include +#endif + +#include + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" +#include "rlmbutil.h" + +/* Some standard library routines. */ +#include "readline.h" +#include "history.h" + +#include "rlprivate.h" +#include "rlshell.h" +#include "xmalloc.h" + +static int rl_digit_loop PARAMS((void)); +static void _rl_history_set_point PARAMS((void)); + +/* Forward declarations used in this file */ +void _rl_free_history_entry PARAMS((HIST_ENTRY *)); + +/* If non-zero, rl_get_previous_history and rl_get_next_history attempt + to preserve the value of rl_point from line to line. */ +int _rl_history_preserve_point = 0; + +/* Saved target point for when _rl_history_preserve_point is set. Special + value of -1 means that point is at the end of the line. */ +int _rl_history_saved_point = -1; + +/* **************************************************************** */ +/* */ +/* Numeric Arguments */ +/* */ +/* **************************************************************** */ + +/* Handle C-u style numeric args, as well as M--, and M-digits. */ +static int +rl_digit_loop () +{ + int key, c, sawminus, sawdigits; + + rl_save_prompt (); + + RL_SETSTATE(RL_STATE_NUMERICARG); + sawminus = sawdigits = 0; + while (1) + { + if (rl_numeric_arg > 1000000) + { + sawdigits = rl_explicit_arg = rl_numeric_arg = 0; + rl_ding (); + rl_restore_prompt (); + rl_clear_message (); + RL_UNSETSTATE(RL_STATE_NUMERICARG); + return 1; + } + rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); + RL_SETSTATE(RL_STATE_MOREINPUT); + key = c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (c < 0) + { + _rl_abort_internal (); + return -1; + } + + /* If we see a key bound to `universal-argument' after seeing digits, + it ends the argument but is otherwise ignored. */ + if (_rl_keymap[c].type == ISFUNC && + _rl_keymap[c].function == rl_universal_argument) + { + if (sawdigits == 0) + { + rl_numeric_arg *= 4; + continue; + } + else + { + RL_SETSTATE(RL_STATE_MOREINPUT); + key = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + rl_restore_prompt (); + rl_clear_message (); + RL_UNSETSTATE(RL_STATE_NUMERICARG); + return (_rl_dispatch (key, _rl_keymap)); + } + } + + c = UNMETA (c); + + if (_rl_digit_p (c)) + { + rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + c - '0' : c - '0'; + sawdigits = rl_explicit_arg = 1; + } + else if (c == '-' && rl_explicit_arg == 0) + { + rl_numeric_arg = sawminus = 1; + rl_arg_sign = -1; + } + else + { + /* Make M-- command equivalent to M--1 command. */ + if (sawminus && rl_numeric_arg == 1 && rl_explicit_arg == 0) + rl_explicit_arg = 1; + rl_restore_prompt (); + rl_clear_message (); + RL_UNSETSTATE(RL_STATE_NUMERICARG); + return (_rl_dispatch (key, _rl_keymap)); + } + } + + /*NOTREACHED*/ +} + +/* Add the current digit to the argument in progress. */ +int +rl_digit_argument (ignore, key) + int ignore __attribute__((unused)), key; +{ + rl_execute_next (key); + return (rl_digit_loop ()); +} + +/* What to do when you abort reading an argument. */ +int +rl_discard_argument () +{ + rl_ding (); + rl_clear_message (); + _rl_init_argument (); + return 0; +} + +/* Create a default argument. */ +int +_rl_init_argument () +{ + rl_numeric_arg = rl_arg_sign = 1; + rl_explicit_arg = 0; + return 0; +} + +/* C-u, universal argument. Multiply the current argument by 4. + Read a key. If the key has nothing to do with arguments, then + dispatch on it. If the key is the abort character then abort. */ +int +rl_universal_argument (count, key) + int count __attribute__((unused)), key __attribute__((unused)); +{ + rl_numeric_arg *= 4; + return (rl_digit_loop ()); +} + +/* **************************************************************** */ +/* */ +/* History Utilities */ +/* */ +/* **************************************************************** */ + +/* We already have a history library, and that is what we use to control + the history features of readline. This is our local interface to + the history mechanism. */ + +/* While we are editing the history, this is the saved + version of the original line. */ +HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL; + +/* Set the history pointer back to the last entry in the history. */ +void +_rl_start_using_history () +{ + using_history (); + if (_rl_saved_line_for_history) + _rl_free_history_entry (_rl_saved_line_for_history); + + _rl_saved_line_for_history = (HIST_ENTRY *)NULL; +} + +/* Free the contents (and containing structure) of a HIST_ENTRY. */ +void +_rl_free_history_entry (entry) + HIST_ENTRY *entry; +{ + if (entry == 0) + return; + if (entry->line) + free (entry->line); + free (entry); +} + +/* Perhaps put back the current line if it has changed. */ +int +rl_maybe_replace_line () +{ + HIST_ENTRY *temp; + + temp = current_history (); + /* If the current line has changed, save the changes. */ + if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list)) + { + temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list); + free (temp->line); + free (temp); + } + return 0; +} + +/* Restore the _rl_saved_line_for_history if there is one. */ +int +rl_maybe_unsave_line () +{ + if (_rl_saved_line_for_history) + { + rl_replace_line (_rl_saved_line_for_history->line, 0); + rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data; + _rl_free_history_entry (_rl_saved_line_for_history); + _rl_saved_line_for_history = (HIST_ENTRY *)NULL; + rl_point = rl_end; /* rl_replace_line sets rl_end */ + } + else + rl_ding (); + return 0; +} + +/* Save the current line in _rl_saved_line_for_history. */ +int +rl_maybe_save_line () +{ + if (_rl_saved_line_for_history == 0) + { + _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); + _rl_saved_line_for_history->line = savestring (rl_line_buffer); + _rl_saved_line_for_history->data = (char *)rl_undo_list; + } + return 0; +} + +int +_rl_free_saved_history_line () +{ + if (_rl_saved_line_for_history) + { + _rl_free_history_entry (_rl_saved_line_for_history); + _rl_saved_line_for_history = (HIST_ENTRY *)NULL; + } + return 0; +} + +static void +_rl_history_set_point () +{ + rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1) + ? _rl_history_saved_point + : rl_end; + if (rl_point > rl_end) + rl_point = rl_end; + +#if defined (VI_MODE) + if (rl_editing_mode == vi_mode) + rl_point = 0; +#endif /* VI_MODE */ + + if (rl_editing_mode == emacs_mode) + rl_mark = (rl_point == rl_end ? 0 : rl_end); +} + +void +rl_replace_from_history (entry, flags) + HIST_ENTRY *entry; + int flags __attribute__((unused)); /* currently unused */ +{ + rl_replace_line (entry->line, 0); + rl_undo_list = (UNDO_LIST *)entry->data; + rl_point = rl_end; + rl_mark = 0; + +#if defined (VI_MODE) + if (rl_editing_mode == vi_mode) + { + rl_point = 0; + rl_mark = rl_end; + } +#endif +} + +/* **************************************************************** */ +/* */ +/* History Commands */ +/* */ +/* **************************************************************** */ + +/* Meta-< goes to the start of the history. */ +int +rl_beginning_of_history (count, key) + int count __attribute__((unused)), key; +{ + return (rl_get_previous_history (1 + where_history (), key)); +} + +/* Meta-> goes to the end of the history. (The current line). */ +int +rl_end_of_history (count, key) + int count __attribute__((unused)), key __attribute__((unused)); +{ + rl_maybe_replace_line (); + using_history (); + rl_maybe_unsave_line (); + return 0; +} + +/* Move down to the next history line. */ +int +rl_get_next_history (count, key) + int count, key; +{ + HIST_ENTRY *temp; + + if (count < 0) + return (rl_get_previous_history (-count, key)); + + if (count == 0) + return 0; + + rl_maybe_replace_line (); + + /* either not saved by rl_newline or at end of line, so set appropriately. */ + if (_rl_history_saved_point == -1 && (rl_point || rl_end)) + _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; + + temp = (HIST_ENTRY *)NULL; + while (count) + { + temp = next_history (); + if (!temp) + break; + --count; + } + + if (temp == 0) + rl_maybe_unsave_line (); + else + { + rl_replace_from_history (temp, 0); + _rl_history_set_point (); + } + return 0; +} + +/* Get the previous item out of our interactive history, making it the current + line. If there is no previous history, just ding. */ +int +rl_get_previous_history (count, key) + int count, key; +{ + HIST_ENTRY *old_temp, *temp; + + if (count < 0) + return (rl_get_next_history (-count, key)); + + if (count == 0) + return 0; + + /* either not saved by rl_newline or at end of line, so set appropriately. */ + if (_rl_history_saved_point == -1 && (rl_point || rl_end)) + _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; + + /* If we don't have a line saved, then save this one. */ + rl_maybe_save_line (); + + /* If the current line has changed, save the changes. */ + rl_maybe_replace_line (); + + temp = old_temp = (HIST_ENTRY *)NULL; + while (count) + { + temp = previous_history (); + if (temp == 0) + break; + + old_temp = temp; + --count; + } + + /* If there was a large argument, and we moved back to the start of the + history, that is not an error. So use the last value found. */ + if (!temp && old_temp) + temp = old_temp; + + if (temp == 0) + rl_ding (); + else + { + rl_replace_from_history (temp, 0); + _rl_history_set_point (); + } + return 0; +} + +/* **************************************************************** */ +/* */ +/* Editing Modes */ +/* */ +/* **************************************************************** */ +/* How to toggle back and forth between editing modes. */ +int +rl_vi_editing_mode (count, key) + int count __attribute__((unused)), key; +{ +#if defined (VI_MODE) + _rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */ + rl_editing_mode = vi_mode; + rl_vi_insertion_mode (1, key); +#endif /* VI_MODE */ + + return 0; +} + +int +rl_emacs_editing_mode (count, key) + int count __attribute__((unused)), key __attribute__((unused)); +{ + rl_editing_mode = emacs_mode; + _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */ + _rl_keymap = emacs_standard_keymap; + return 0; +} + +/* Function for the rest of the library to use to set insert/overwrite mode. */ +void +_rl_set_insert_mode (im, force) + int im, force __attribute__((unused)); +{ +#ifdef CURSOR_MODE + _rl_set_cursor (im, force); +#endif + + rl_insert_mode = im; +} + +/* Toggle overwrite mode. A positive explicit argument selects overwrite + mode. A negative or zero explicit argument selects insert mode. */ +int +rl_overwrite_mode (count, key) + int count, key __attribute__((unused)); +{ + if (rl_explicit_arg == 0) + _rl_set_insert_mode (rl_insert_mode ^ 1, 0); + else if (count > 0) + _rl_set_insert_mode (RL_IM_OVERWRITE, 0); + else + _rl_set_insert_mode (RL_IM_INSERT, 0); + + return 0; +} diff --git a/readline/nls.c b/readline/nls.c index f2d413d59d5..706c8195c10 100644 --- a/readline/nls.c +++ b/readline/nls.c @@ -7,7 +7,7 @@ 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 1, or + 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 @@ -18,7 +18,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) @@ -27,6 +27,8 @@ #include +#include + #if defined (HAVE_UNISTD_H) # include #endif /* HAVE_UNISTD_H */ @@ -44,13 +46,9 @@ #include #include "rldefs.h" - -extern int _rl_convert_meta_chars_to_ascii; -extern int _rl_output_meta_chars; -extern int _rl_meta_flag; - -/* Functions imported from shell.c */ -extern char *get_env_value (); +#include "readline.h" +#include "rlshell.h" +#include "rlprivate.h" #if !defined (HAVE_SETLOCALE) /* A list of legal values for the LANG or LC_CTYPE environment variables. @@ -70,12 +68,11 @@ static char *legal_lang_values[] = "iso88599", "iso885910", "koi8r", - "koi8-r", 0 }; -static char *normalize_codeset (); -static char *find_codeset (); +static char *normalize_codeset PARAMS((char *)); +static char *find_codeset PARAMS((char *, size_t *)); #endif /* !HAVE_SETLOCALE */ /* Check for LC_ALL, LC_CTYPE, and LANG and use the first with a value @@ -108,9 +105,9 @@ _rl_init_eightbit () /* We don't have setlocale. Finesse it. Check the environment for the appropriate variables and set eight-bit mode if they have the right values. */ - lspec = get_env_value ("LC_ALL"); - if (lspec == 0) lspec = get_env_value ("LC_CTYPE"); - if (lspec == 0) lspec = get_env_value ("LANG"); + lspec = sh_get_env_value ("LC_ALL"); + if (lspec == 0) lspec = sh_get_env_value ("LC_CTYPE"); + if (lspec == 0) lspec = sh_get_env_value ("LANG"); if (lspec == 0 || (t = normalize_codeset (lspec)) == 0) return (0); for (i = 0; t && legal_lang_values[i]; i++) @@ -144,10 +141,10 @@ normalize_codeset (codeset) all_digits = 1; for (len = 0, i = 0; i < namelen; i++) { - if (isalnum (codeset[i])) + if (ISALNUM ((unsigned char)codeset[i])) { len++; - all_digits &= isdigit (codeset[i]); + all_digits &= _rl_digit_p (codeset[i]); } } @@ -165,9 +162,9 @@ normalize_codeset (codeset) } for (i = 0; i < namelen; i++) - if (isalpha (codeset[i])) - *wp++ = (isupper (codeset[i])) ? tolower (codeset[i]) : codeset[i]; - else if (isdigit (codeset[i])) + if (ISALPHA ((unsigned char)codeset[i])) + *wp++ = _rl_to_lower (codeset[i]); + else if (_rl_digit_p (codeset[i])) *wp++ = codeset[i]; *wp = '\0'; diff --git a/readline/parens.c b/readline/parens.c index a500c0afac7..54ef1f3695f 100644 --- a/readline/parens.c +++ b/readline/parens.c @@ -7,7 +7,7 @@ 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 1, or + 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 @@ -18,23 +18,11 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #include "rlconf.h" -#if !defined (PAREN_MATCHING) -extern int rl_insert (); - -int -rl_insert_close (count, invoking_key) - int count, invoking_key; -{ - return (rl_insert (count, invoking_key)); -} - -#else /* PAREN_MATCHING */ - #if defined (HAVE_CONFIG_H) # include #endif @@ -42,6 +30,10 @@ rl_insert_close (count, invoking_key) #include #include +#if defined (HAVE_UNISTD_H) +# include +#endif + #if defined (FD_SET) && !defined (HAVE_SELECT) # define HAVE_SELECT #endif @@ -64,8 +56,9 @@ extern char *strchr (), *strrchr (); #endif /* !strchr && !__STDC__ */ #include "readline.h" +#include "rlprivate.h" -extern int rl_explicit_arg; +static int find_matching_open PARAMS((char *, int, int)); /* Non-zero means try to blink the matching open parenthesis when the close parenthesis is inserted. */ @@ -75,14 +68,46 @@ int rl_blink_matching_paren = 1; int rl_blink_matching_paren = 0; #endif /* !HAVE_SELECT */ -static int find_matching_open (); +static int _paren_blink_usec = 500000; + +/* Change emacs_standard_keymap to have bindings for paren matching when + ON_OR_OFF is 1, change them back to self_insert when ON_OR_OFF == 0. */ +void +_rl_enable_paren_matching (on_or_off) + int on_or_off; +{ + if (on_or_off) + { /* ([{ */ + rl_bind_key_in_map (')', rl_insert_close, emacs_standard_keymap); + rl_bind_key_in_map (']', rl_insert_close, emacs_standard_keymap); + rl_bind_key_in_map ('}', rl_insert_close, emacs_standard_keymap); + } + else + { /* ([{ */ + rl_bind_key_in_map (')', rl_insert, emacs_standard_keymap); + rl_bind_key_in_map (']', rl_insert, emacs_standard_keymap); + rl_bind_key_in_map ('}', rl_insert, emacs_standard_keymap); + } +} + +int +rl_set_paren_blink_timeout (u) + int u; +{ + int o; + + o = _paren_blink_usec; + if (u > 0) + _paren_blink_usec = u; + return (o); +} int rl_insert_close (count, invoking_key) int count, invoking_key; { if (rl_explicit_arg || !rl_blink_matching_paren) - rl_insert (count, invoking_key); + _rl_insert_char (count, invoking_key); else { #if defined (HAVE_SELECT) @@ -90,7 +115,7 @@ rl_insert_close (count, invoking_key) struct timeval timer; fd_set readfds; - rl_insert (1, invoking_key); + _rl_insert_char (1, invoking_key); (*rl_redisplay_function) (); match_point = find_matching_open (rl_line_buffer, rl_point - 2, invoking_key); @@ -102,7 +127,7 @@ rl_insert_close (count, invoking_key) FD_ZERO (&readfds); FD_SET (fileno (rl_instream), &readfds); timer.tv_sec = 0; - timer.tv_usec = 500000; + timer.tv_usec = _paren_blink_usec; orig_point = rl_point; rl_point = match_point; @@ -110,7 +135,7 @@ rl_insert_close (count, invoking_key) ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer); rl_point = orig_point; #else /* !HAVE_SELECT */ - rl_insert (count, invoking_key); + _rl_insert_char (count, invoking_key); #endif /* !HAVE_SELECT */ } return 0; @@ -152,5 +177,3 @@ find_matching_open (string, from, closer) } return (i); } - -#endif /* PAREN_MATCHING */ diff --git a/readline/posixdir.h b/readline/posixdir.h index 7480a93d5db..505e27954f1 100644 --- a/readline/posixdir.h +++ b/readline/posixdir.h @@ -6,7 +6,7 @@ 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) + 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 @@ -16,7 +16,7 @@ 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. */ + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ /* This file should be included instead of or . */ @@ -46,4 +46,12 @@ # define d_fileno d_ino #endif +#if defined (_POSIX_SOURCE) && (!defined (STRUCT_DIRENT_HAS_D_INO) || defined (BROKEN_DIRENT_D_INO)) +/* Posix does not require that the d_ino field be present, and some + systems do not provide it. */ +# define REAL_DIR_ENTRY(dp) 1 +#else +# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) +#endif /* _POSIX_SOURCE */ + #endif /* !_POSIXDIR_H_ */ diff --git a/readline/posixjmp.h b/readline/posixjmp.h index 1347cc07ebc..b52aa00332b 100644 --- a/readline/posixjmp.h +++ b/readline/posixjmp.h @@ -1,5 +1,23 @@ /* posixjmp.h -- wrapper for setjmp.h with changes for POSIX systems. */ +/* Copyright (C) 1987,1991 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. */ + #ifndef _POSIXJMP_H_ #define _POSIXJMP_H_ diff --git a/readline/posixstat.h b/readline/posixstat.h index bfce8c04fef..c93b52887e9 100644 --- a/readline/posixstat.h +++ b/readline/posixstat.h @@ -7,7 +7,7 @@ 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) + 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 @@ -17,7 +17,7 @@ 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. */ + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ /* This file should be included instead of . It relies on the local sys/stat.h to work though. */ diff --git a/readline/readline.c b/readline/readline.c index 1da73250773..28801f19dfc 100644 --- a/readline/readline.c +++ b/readline/readline.c @@ -1,14 +1,14 @@ /* 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-2002 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 1, or + 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 @@ -19,7 +19,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) @@ -47,12 +47,12 @@ # include #endif -#include #include #include "posixjmp.h" /* System-specific feature definitions and include files. */ #include "rldefs.h" +#include "rlmbutil.h" #if defined (__EMX__) # define INCL_DOSPROCESS @@ -63,117 +63,28 @@ #include "readline.h" #include "history.h" +#include "rlprivate.h" +#include "rlshell.h" +#include "xmalloc.h" + #ifndef RL_LIBRARY_VERSION -# define RL_LIBRARY_VERSION "4.0" +# define RL_LIBRARY_VERSION "4.3" #endif -/* Evaluates its arguments multiple times. */ -#define SWAP(s, e) do { int t; t = s; s = e; e = t; } while (0) - -/* 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. */ - -/* Variables and functions imported from terminal.c */ -extern int _rl_init_terminal_io (); -extern void _rl_enable_meta_key (); -#ifdef _MINIX -extern void _rl_output_character_function (); -#else -extern int _rl_output_character_function (); +#ifndef RL_READLINE_VERSION +# define RL_READLINE_VERSION 0x0403 #endif -extern int _rl_enable_meta; -extern int _rl_term_autowrap; -extern int screenwidth, screenheight, screenchars; - -/* Variables and functions imported from rltty.c. */ -extern void rl_prep_terminal (), rl_deprep_terminal (); -extern void rltty_set_default_bindings (); - -/* Functions imported from util.c. */ -extern void _rl_abort_internal (); -extern void rl_extend_line_buffer (); -extern int alphabetic (); - -/* Functions imported from bind.c. */ -extern void _rl_bind_if_unbound (); - -/* Functions imported from input.c. */ -extern int _rl_any_typein (); -extern void _rl_insert_typein (); -extern int rl_read_key (); - -/* Functions imported from nls.c */ -extern int _rl_init_eightbit (); - -/* Functions imported from shell.c */ -extern char *get_env_value (); - -/* External redisplay functions and variables from display.c */ -extern void _rl_move_vert (); -extern void _rl_update_final (); -extern void _rl_clear_to_eol (); -extern void _rl_clear_screen (); -extern void _rl_erase_entire_line (); - -extern void _rl_erase_at_end_of_line (); -extern void _rl_move_cursor_relative (); - -extern int _rl_vis_botlin; -extern int _rl_last_c_pos; -extern int _rl_horizontal_scroll_mode; -extern int rl_display_fixed; -extern int _rl_suppress_redisplay; -extern char *rl_display_prompt; - -/* Variables imported from complete.c. */ -extern const char *rl_completer_word_break_characters; -extern const char *rl_basic_word_break_characters; -extern int rl_completion_query_items; -extern int rl_complete_with_tilde_expansion; - -/* Variables and functions from macro.c. */ -extern void _rl_add_macro_char (); -extern void _rl_with_macro_input (); -extern int _rl_next_macro_key (); -extern int _rl_defining_kbd_macro; - -#if defined (VI_MODE) -/* Functions imported from vi_mode.c. */ -extern void _rl_vi_set_last (); -extern void _rl_vi_reset_last (); -extern void _rl_vi_done_inserting (); -extern int _rl_vi_textmod_command (); -extern void _rl_vi_initialize_line (); -#endif /* VI_MODE */ - -extern UNDO_LIST *rl_undo_list; -extern int _rl_doing_an_undo; +extern void _rl_free_history_entry PARAMS((HIST_ENTRY *)); /* Forward declarations used in this file. */ -void _rl_free_history_entry (); +static char *readline_internal PARAMS((void)); +static void readline_initialize_everything PARAMS((void)); -int _rl_dispatch (); -int _rl_init_argument (); +static void bind_arrow_keys_internal PARAMS((Keymap)); +static void bind_arrow_keys PARAMS((void)); -static char *readline_internal (); -static void readline_initialize_everything (); -static void start_using_history (); -static void bind_arrow_keys (); - -#if !defined (__GO32__) -static void readline_default_bindings (); -#endif /* !__GO32__ */ - -#if defined (__GO32__) -# include -# include -# undef HANDLE_SIGNALS -#endif /* __GO32__ */ - -extern char *xmalloc (), *xrealloc (); +static void readline_default_bindings PARAMS((void)); /* **************************************************************** */ /* */ @@ -183,6 +94,11 @@ extern char *xmalloc (), *xrealloc (); const char *rl_library_version = RL_LIBRARY_VERSION; +int rl_readline_version = RL_READLINE_VERSION; + +/* True if this is `real' readline as opposed to some stub substitute. */ +int rl_gnu_readline_p = 1; + /* A pointer to the keymap that is currently in use. By default, it is the standard emacs keymap. */ Keymap _rl_keymap = emacs_standard_keymap; @@ -190,6 +106,9 @@ Keymap _rl_keymap = emacs_standard_keymap; /* The current style of editing. */ int rl_editing_mode = emacs_mode; +/* The current insert mode: input (the default) or overwrite */ +int rl_insert_mode = RL_IM_DEFAULT; + /* Non-zero if we called this function from _rl_dispatch(). It's present so functions can find out whether they were called from a key binding or directly from an application. */ @@ -210,8 +129,13 @@ int rl_arg_sign = 1; /* Non-zero means we have been called at least once before. */ static int rl_initialized; +#if 0 /* If non-zero, this program is running in an EMACS buffer. */ static int running_in_emacs; +#endif + +/* Flags word encapsulating the current readline state. */ +int rl_readline_state = RL_STATE_NONE; /* The current offset in the current input line. */ int rl_point; @@ -226,7 +150,7 @@ int rl_end; int rl_done; /* The last function executed by readline. */ -Function *rl_last_func = (Function *)NULL; +rl_command_func_t *rl_last_func = (rl_command_func_t *)NULL; /* Top level environment for readline_internal (). */ procenv_t readline_top_level; @@ -238,24 +162,31 @@ FILE *_rl_in_stream, *_rl_out_stream; FILE *rl_instream = (FILE *)NULL; FILE *rl_outstream = (FILE *)NULL; -/* Non-zero means echo characters as they are read. */ -int readline_echoing_p = 1; +/* Non-zero means echo characters as they are read. Defaults to no echo; + set to 1 if there is a controlling terminal, we can get its attributes, + and the attributes include `echo'. Look at rltty.c:prepare_terminal_settings + for the code that sets it. */ +int readline_echoing_p = 0; /* Current prompt. */ -char *rl_prompt; +char *rl_prompt = (char *)NULL; int rl_visible_prompt_length = 0; +/* Set to non-zero by calling application if it has already printed rl_prompt + and does not want readline to do it the first time. */ +int rl_already_prompted = 0; + /* The number of characters read in order to type this complete command. */ int rl_key_sequence_length = 0; /* If non-zero, then this is the address of a function to call just before readline_internal_setup () prints the first prompt. */ -Function *rl_startup_hook = (Function *)NULL; +rl_hook_func_t *rl_startup_hook = (rl_hook_func_t *)NULL; /* If non-zero, this is the address of a function to call just before readline_internal_setup () returns and readline_internal starts reading input characters. */ -Function *rl_pre_input_hook = (Function *)NULL; +rl_hook_func_t *rl_pre_input_hook = (rl_hook_func_t *)NULL; /* What we use internally. You should always refer to RL_LINE_BUFFER. */ static char *the_line; @@ -268,7 +199,7 @@ int _rl_eof_char = CTRL ('D'); int rl_pending_input = 0; /* Pointer to a useful terminal name. */ -char *rl_terminal_name = (char *)NULL; +const char *rl_terminal_name = (const char *)NULL; /* Non-zero means to always use horizontal scrolling in line display. */ int _rl_horizontal_scroll_mode = 0; @@ -280,7 +211,7 @@ int _rl_mark_modified_lines = 0; /* The style of `bell' notification preferred. This can be set to NO_BELL, AUDIBLE_BELL, or VISIBLE_BELL. */ int _rl_bell_preference = AUDIBLE_BELL; - + /* String inserted into the line by rl_insert_comment (). */ char *_rl_comment_begin; @@ -290,11 +221,15 @@ Keymap rl_executing_keymap; /* Non-zero means to erase entire line, including prompt, on empty input lines. */ int rl_erase_empty_line = 0; +/* Non-zero means to read only this many characters rather than up to a + character bound to accept-line. */ +int rl_num_chars_to_read; + /* Line buffer and maintenence. */ char *rl_line_buffer = (char *)NULL; int rl_line_buffer_len = 0; -/* Forward declarations used by the display and termcap code. */ +/* Forward declarations used by the display, termcap, and history code. */ /* **************************************************************** */ /* */ @@ -324,24 +259,35 @@ int _rl_output_meta_chars = 0; /* Non-zero means treat 0200 bit in terminal input as Meta bit. */ int _rl_meta_flag = 0; /* Forward declaration */ +/* Set up the prompt and expand it. Called from readline() and + rl_callback_handler_install (). */ +int +rl_set_prompt (prompt) + const char *prompt; +{ + FREE (rl_prompt); + rl_prompt = prompt ? savestring (prompt) : (char *)NULL; + + rl_visible_prompt_length = rl_expand_prompt (rl_prompt); + return 0; +} + /* Read a line of input. Prompt with PROMPT. An empty PROMPT means none. A return value of NULL means that EOF was encountered. */ char * readline (prompt) - char *prompt; + const char *prompt; { char *value; - rl_prompt = prompt; - /* If we are at EOF return a NULL string. */ if (rl_pending_input == EOF) { - rl_pending_input = 0; + rl_clear_pending_input (); return ((char *)NULL); } - rl_visible_prompt_length = rl_expand_prompt (rl_prompt); + rl_set_prompt (prompt); rl_initialize (); (*rl_prep_term_function) (_rl_meta_flag); @@ -369,30 +315,41 @@ readline (prompt) STATIC_CALLBACK void readline_internal_setup () { + char *nprompt; + _rl_in_stream = rl_instream; _rl_out_stream = rl_outstream; if (rl_startup_hook) (*rl_startup_hook) (); - if (readline_echoing_p == 0) + /* If we're not echoing, we still want to at least print a prompt, because + rl_redisplay will not do it for us. If the calling application has a + custom redisplay function, though, let that function handle it. */ + if (readline_echoing_p == 0 && rl_redisplay_function == rl_redisplay) { - if (rl_prompt) + if (rl_prompt && rl_already_prompted == 0) { - fprintf (_rl_out_stream, "%s", rl_prompt); + nprompt = _rl_strip_prompt (rl_prompt); + fprintf (_rl_out_stream, "%s", nprompt); fflush (_rl_out_stream); + free (nprompt); } } else { - rl_on_new_line (); + if (rl_prompt && rl_already_prompted) + rl_on_new_line_with_prompt (); + else + rl_on_new_line (); (*rl_redisplay_function) (); -#if defined (VI_MODE) - if (rl_editing_mode == vi_mode) - rl_vi_insertion_mode (1, 0); -#endif /* VI_MODE */ } +#if defined (VI_MODE) + if (rl_editing_mode == vi_mode) + rl_vi_insertion_mode (1, 0); +#endif /* VI_MODE */ + if (rl_pre_input_hook) (*rl_pre_input_hook) (); } @@ -422,7 +379,10 @@ readline_internal_teardown (eof) /* At any rate, it is highly likely that this line has an undo list. Get rid of it now. */ if (rl_undo_list) - free_undo_list (); + rl_free_undo_list (); + + /* Restore normal cursor, if available. */ + _rl_set_insert_mode (RL_IM_INSERT, 0); return (eof ? (char *)NULL : savestring (the_line)); } @@ -458,7 +418,9 @@ readline_internal_charloop () rl_key_sequence_length = 0; } + RL_SETSTATE(RL_STATE_READCMD); c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_READCMD); /* EOF typed to a non-blank line is a . */ if (c == EOF && rl_end) @@ -469,6 +431,7 @@ readline_internal_charloop () if (((c == _rl_eof_char && lastc != c) || c == EOF) && !rl_end) { #if defined (READLINE_CALLBACKS) + RL_SETSTATE(RL_STATE_DONE); return (rl_done = 1); #else eof_found = 1; @@ -477,7 +440,7 @@ readline_internal_charloop () } lastc = c; - _rl_dispatch (c, _rl_keymap); + _rl_dispatch ((unsigned char)c, _rl_keymap); /* If there was no change in _rl_last_command_was_kill, then no kill has taken place. Note that if input is pending we are reading @@ -492,6 +455,12 @@ readline_internal_charloop () rl_vi_check (); #endif /* VI_MODE */ + if (rl_num_chars_to_read && rl_end >= rl_num_chars_to_read) + { + (*rl_redisplay_function) (); + rl_newline (1, '\n'); + } + if (rl_done == 0) (*rl_redisplay_function) (); @@ -538,7 +507,7 @@ readline_internal () void _rl_init_line_state () { - rl_point = rl_end = 0; + rl_point = rl_end = rl_mark = 0; the_line = rl_line_buffer; the_line[0] = 0; } @@ -556,16 +525,25 @@ int _rl_dispatch (key, map) register int key; Keymap map; +{ + return _rl_dispatch_subseq (key, map, 0); +} + +int +_rl_dispatch_subseq (key, map, got_subseq) + register int key; + Keymap map; + int got_subseq; { int r, newkey; char *macro; - Function *func; + rl_command_func_t *func; if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii) { if (map[ESC].type == ISKMAP) { - if (_rl_defining_kbd_macro) + if (RL_ISSTATE (RL_STATE_MACRODEF)) _rl_add_macro_char (ESC); map = FUNCTION_TO_KEYMAP (map, ESC); key = UNMETA (key); @@ -573,11 +551,11 @@ _rl_dispatch (key, map) return (_rl_dispatch (key, map)); } else - ding (); + rl_ding (); return 0; } - if (_rl_defining_kbd_macro) + if (RL_ISSTATE (RL_STATE_MACRODEF)) _rl_add_macro_char (key); r = 0; @@ -585,7 +563,7 @@ _rl_dispatch (key, map) { case ISFUNC: func = map[key].function; - if (func != (Function *)NULL) + if (func) { /* Special case rl_do_lowercase_version (). */ if (func == rl_do_lowercase_version) @@ -598,15 +576,34 @@ _rl_dispatch (key, map) #endif rl_dispatching = 1; + RL_SETSTATE(RL_STATE_DISPATCHING); r = (*map[key].function)(rl_numeric_arg * rl_arg_sign, key); + RL_UNSETSTATE(RL_STATE_DISPATCHING); rl_dispatching = 0; /* If we have input pending, then the last command was a prefix command. Don't change the state of rl_last_func. Otherwise, remember the last command executed in this variable. */ - if (!rl_pending_input && map[key].function != rl_digit_argument) + if (rl_pending_input == 0 && map[key].function != rl_digit_argument) rl_last_func = map[key].function; } + else if (map[ANYOTHERKEY].function) + { + /* OK, there's no function bound in this map, but there is a + shadow function that was overridden when the current keymap + was created. Return -2 to note that. */ + _rl_unget_char (key); + return -2; + } + else if (got_subseq) + { + /* Return -1 to note that we're in a subsequence, but we don't + have a matching key, nor was one overridden. This means + we need to back up the recursion chain and find the last + subsequence that is bound to a function. */ + _rl_unget_char (key); + return -1; + } else { _rl_abort_internal (); @@ -615,11 +612,59 @@ _rl_dispatch (key, map) break; case ISKMAP: - if (map[key].function != (Function *)NULL) + if (map[key].function != 0) { +#if defined (VI_MODE) + /* The only way this test will be true is if a subsequence has been + bound starting with ESC, generally the arrow keys. What we do is + check whether there's input in the queue, which there generally + will be if an arrow key has been pressed, and, if there's not, + just dispatch to (what we assume is) rl_vi_movement_mode right + away. This is essentially an input test with a zero timeout. */ + if (rl_editing_mode == vi_mode && key == ESC && map == vi_insertion_keymap + && _rl_input_queued (0) == 0) + return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key))); +#endif + rl_key_sequence_length++; + + if (key == ESC) + RL_SETSTATE(RL_STATE_METANEXT); + RL_SETSTATE(RL_STATE_MOREINPUT); newkey = rl_read_key (); - r = _rl_dispatch (newkey, FUNCTION_TO_KEYMAP (map, key)); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + if (key == ESC) + RL_UNSETSTATE(RL_STATE_METANEXT); + + if (newkey < 0) + { + _rl_abort_internal (); + return -1; + } + + r = _rl_dispatch_subseq (newkey, FUNCTION_TO_KEYMAP (map, key), got_subseq || map[ANYOTHERKEY].function); + + if (r == -2) + /* We didn't match anything, and the keymap we're indexed into + shadowed a function previously bound to that prefix. Call + the function. The recursive call to _rl_dispatch_subseq has + already taken care of pushing any necessary input back onto + the input queue with _rl_unget_char. */ + r = _rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key)); + else if (r && map[ANYOTHERKEY].function) + { + /* We didn't match (r is probably -1), so return something to + tell the caller that it should try ANYOTHERKEY for an + overridden function. */ + _rl_unget_char (key); + return -2; + } + else if (r && got_subseq) + { + /* OK, back up the chain. */ + _rl_unget_char (key); + return -1; + } } else { @@ -629,7 +674,7 @@ _rl_dispatch (key, map) break; case ISMACR: - if (map[key].function != (Function *)NULL) + if (map[key].function != 0) { macro = savestring ((char *)map[key].function); _rl_with_macro_input (macro); @@ -659,8 +704,11 @@ rl_initialize () terminal and data structures. */ if (!rl_initialized) { + RL_SETSTATE(RL_STATE_INITIALIZING); readline_initialize_everything (); + RL_UNSETSTATE(RL_STATE_INITIALIZING); rl_initialized++; + RL_SETSTATE(RL_STATE_INITIALIZED); } /* Initalize the current line information. */ @@ -668,15 +716,16 @@ rl_initialize () /* We aren't done yet. We haven't even gotten started yet! */ rl_done = 0; + RL_UNSETSTATE(RL_STATE_DONE); /* Tell the history routines what is going on. */ - start_using_history (); + _rl_start_using_history (); /* Make the display buffer match the state of the line. */ rl_reset_line_state (); /* No such function typed yet. */ - rl_last_func = (Function *)NULL; + rl_last_func = (rl_command_func_t *)NULL; /* Parsing of key-bindings begins in an enabled state. */ _rl_parsing_conditionalized_out = 0; @@ -686,9 +735,13 @@ rl_initialize () _rl_vi_initialize_line (); #endif + /* Each line starts in insert mode (the default). */ + _rl_set_insert_mode (RL_IM_DEFAULT, 1); + return 0; } +#if 0 #if defined (__EMX__) static void _emx_build_environ () @@ -712,18 +765,23 @@ _emx_build_environ () *tp = 0; } #endif /* __EMX__ */ +#endif /* Initialize the entire state of the world. */ static void readline_initialize_everything () { +#if 0 #if defined (__EMX__) if (environ == 0) _emx_build_environ (); #endif +#endif - /* Find out if we are running in Emacs. */ - running_in_emacs = get_env_value ("EMACS") != (char *)0; +#if 0 + /* Find out if we are running in Emacs -- UNUSED. */ + running_in_emacs = sh_get_env_value ("EMACS") != (char *)0; +#endif /* Set up input and output if they are not already set up. */ if (!rl_instream) @@ -740,30 +798,30 @@ readline_initialize_everything () /* Allocate data structures. */ if (rl_line_buffer == 0) - rl_line_buffer = xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE); + rl_line_buffer = (char *)xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE); /* Initialize the terminal interface. */ - _rl_init_terminal_io ((char *)NULL); + if (rl_terminal_name == 0) + rl_terminal_name = sh_get_env_value ("TERM"); + _rl_init_terminal_io (rl_terminal_name); -#if !defined (__GO32__) /* Bind tty characters to readline functions. */ readline_default_bindings (); -#endif /* !__GO32__ */ /* Initialize the function names. */ rl_initialize_funmap (); /* Decide whether we should automatically go into eight-bit mode. */ _rl_init_eightbit (); - + /* Read in the init file. */ rl_read_init_file ((char *)NULL); /* XXX */ if (_rl_horizontal_scroll_mode && _rl_term_autowrap) { - screenwidth--; - screenchars -= screenheight; + _rl_screenwidth--; + _rl_screenchars -= _rl_screenheight; } /* Override the effect of any `set keymap' assignments in the @@ -789,1367 +847,127 @@ readline_initialize_everything () static void readline_default_bindings () { - rltty_set_default_bindings (_rl_keymap); + rl_tty_set_default_bindings (_rl_keymap); } +/* Bind some common arrow key sequences in MAP. */ static void -bind_arrow_keys_internal () +bind_arrow_keys_internal (map) + Keymap map; { - Function *f; + Keymap xkeymap; - f = rl_function_of_keyseq ("\033[A", _rl_keymap, (int *)NULL); - if (!f || f == rl_do_lowercase_version) - { - _rl_bind_if_unbound ("\033[A", rl_get_previous_history); - _rl_bind_if_unbound ("\033[B", rl_get_next_history); - _rl_bind_if_unbound ("\033[C", rl_forward); - _rl_bind_if_unbound ("\033[D", rl_backward); - } + xkeymap = _rl_keymap; + _rl_keymap = map; - f = rl_function_of_keyseq ("\033OA", _rl_keymap, (int *)NULL); - if (!f || f == rl_do_lowercase_version) - { - _rl_bind_if_unbound ("\033OA", rl_get_previous_history); - _rl_bind_if_unbound ("\033OB", rl_get_next_history); - _rl_bind_if_unbound ("\033OC", rl_forward); - _rl_bind_if_unbound ("\033OD", rl_backward); - } +#if defined (__MSDOS__) + _rl_bind_if_unbound ("\033[0A", rl_get_previous_history); + _rl_bind_if_unbound ("\033[0B", rl_backward_char); + _rl_bind_if_unbound ("\033[0C", rl_forward_char); + _rl_bind_if_unbound ("\033[0D", rl_get_next_history); +#endif + + _rl_bind_if_unbound ("\033[A", rl_get_previous_history); + _rl_bind_if_unbound ("\033[B", rl_get_next_history); + _rl_bind_if_unbound ("\033[C", rl_forward_char); + _rl_bind_if_unbound ("\033[D", rl_backward_char); + _rl_bind_if_unbound ("\033[H", rl_beg_of_line); + _rl_bind_if_unbound ("\033[F", rl_end_of_line); + + _rl_bind_if_unbound ("\033OA", rl_get_previous_history); + _rl_bind_if_unbound ("\033OB", rl_get_next_history); + _rl_bind_if_unbound ("\033OC", rl_forward_char); + _rl_bind_if_unbound ("\033OD", rl_backward_char); + _rl_bind_if_unbound ("\033OH", rl_beg_of_line); + _rl_bind_if_unbound ("\033OF", rl_end_of_line); + + _rl_keymap = xkeymap; } -/* Try and bind the common arrow key prefix after giving termcap and +/* Try and bind the common arrow key prefixes after giving termcap and the inputrc file a chance to bind them and create `real' keymaps for the arrow key prefix. */ static void bind_arrow_keys () { - Keymap xkeymap; - - xkeymap = _rl_keymap; - - _rl_keymap = emacs_standard_keymap; - bind_arrow_keys_internal (); + bind_arrow_keys_internal (emacs_standard_keymap); #if defined (VI_MODE) - _rl_keymap = vi_movement_keymap; - bind_arrow_keys_internal (); + bind_arrow_keys_internal (vi_movement_keymap); + bind_arrow_keys_internal (vi_insertion_keymap); #endif - - _rl_keymap = xkeymap; -} - - -/* **************************************************************** */ -/* */ -/* Numeric Arguments */ -/* */ -/* **************************************************************** */ - -/* Handle C-u style numeric args, as well as M--, and M-digits. */ -static int -rl_digit_loop () -{ - int key, c, sawminus, sawdigits; - - rl_save_prompt (); - - sawminus = sawdigits = 0; - while (1) - { - if (rl_numeric_arg > 1000000) - { - sawdigits = rl_explicit_arg = rl_numeric_arg = 0; - ding (); - rl_restore_prompt (); - rl_clear_message (); - return 1; - } - rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); - key = c = rl_read_key (); - - /* If we see a key bound to `universal-argument' after seeing digits, - it ends the argument but is otherwise ignored. */ - if (_rl_keymap[c].type == ISFUNC && - _rl_keymap[c].function == rl_universal_argument) - { - if (sawdigits == 0) - { - rl_numeric_arg *= 4; - continue; - } - else - { - key = rl_read_key (); - rl_restore_prompt (); - rl_clear_message (); - return (_rl_dispatch (key, _rl_keymap)); - } - } - - c = UNMETA (c); - - if (_rl_digit_p (c)) - { - rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + c - '0' : c - '0'; - sawdigits = rl_explicit_arg = 1; - } - else if (c == '-' && rl_explicit_arg == 0) - { - rl_numeric_arg = sawminus = 1; - rl_arg_sign = -1; - } - else - { - /* Make M-- command equivalent to M--1 command. */ - if (sawminus && rl_numeric_arg == 1 && rl_explicit_arg == 0) - rl_explicit_arg = 1; - rl_restore_prompt (); - rl_clear_message (); - return (_rl_dispatch (key, _rl_keymap)); - } - } - - return 0; -} - -/* Add the current digit to the argument in progress. */ -int -rl_digit_argument (ignore, key) - int ignore __attribute__((unused)), key; -{ - rl_pending_input = key; - return (rl_digit_loop ()); -} - -/* What to do when you abort reading an argument. */ -int -rl_discard_argument () -{ - ding (); - rl_clear_message (); - _rl_init_argument (); - return 0; -} - -/* Create a default argument. */ -int -_rl_init_argument () -{ - rl_numeric_arg = rl_arg_sign = 1; - rl_explicit_arg = 0; - return 0; -} - -/* C-u, universal argument. Multiply the current argument by 4. - Read a key. If the key has nothing to do with arguments, then - dispatch on it. If the key is the abort character then abort. */ -int -rl_universal_argument (count, key) - int count __attribute__((unused)), key __attribute__((unused)); -{ - rl_numeric_arg *= 4; - return (rl_digit_loop ()); } /* **************************************************************** */ /* */ -/* Insert and Delete */ -/* */ -/* **************************************************************** */ - -/* Insert a string of text into the line at point. This is the only - way that you should do insertion. rl_insert () calls this - function. */ -int -rl_insert_text (const char *string) -{ - register int i, l = strlen (string); - - if (rl_end + l >= rl_line_buffer_len) - rl_extend_line_buffer (rl_end + l); - - for (i = rl_end; i >= rl_point; i--) - the_line[i + l] = the_line[i]; - strncpy (the_line + rl_point, string, l); - - /* Remember how to undo this if we aren't undoing something. */ - if (!_rl_doing_an_undo) - { - /* If possible and desirable, concatenate the undos. */ - if ((l == 1) && - rl_undo_list && - (rl_undo_list->what == UNDO_INSERT) && - (rl_undo_list->end == rl_point) && - (rl_undo_list->end - rl_undo_list->start < 20)) - rl_undo_list->end++; - else - rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL); - } - rl_point += l; - rl_end += l; - the_line[rl_end] = '\0'; - return l; -} - -/* Delete the string between FROM and TO. FROM is - inclusive, TO is not. */ -int -rl_delete_text (from, to) - int from, to; -{ - register char *text; - register int diff, i; - - /* Fix it if the caller is confused. */ - if (from > to) - SWAP (from, to); - - /* fix boundaries */ - if (to > rl_end) - { - to = rl_end; - if (from > to) - from = to; - } - - text = rl_copy_text (from, to); - - /* Some versions of strncpy() can't handle overlapping arguments. */ - diff = to - from; - for (i = from; i < rl_end - diff; i++) - the_line[i] = the_line[i + diff]; - - /* Remember how to undo this delete. */ - if (_rl_doing_an_undo == 0) - rl_add_undo (UNDO_DELETE, from, to, text); - else - free (text); - - rl_end -= diff; - the_line[rl_end] = '\0'; - return (diff); -} - -/* Fix up point so that it is within the line boundaries after killing - text. If FIX_MARK_TOO is non-zero, the mark is forced within line - boundaries also. */ - -#define _RL_FIX_POINT(x) \ - do { \ - if (x > rl_end) \ - x = rl_end; \ - else if (x < 0) \ - x = 0; \ - } while (0) - -void -_rl_fix_point (fix_mark_too) - int fix_mark_too; -{ - _RL_FIX_POINT (rl_point); - if (fix_mark_too) - _RL_FIX_POINT (rl_mark); -} -#undef _RL_FIX_POINT - -void -_rl_replace_text (text, start, end) - char *text; - int start, end; -{ - rl_begin_undo_group (); - rl_delete_text (start, end + 1); - rl_point = start; - rl_insert_text (text); - rl_end_undo_group (); -} - -/* **************************************************************** */ -/* */ -/* Readline character functions */ -/* */ -/* **************************************************************** */ - -/* This is not a gap editor, just a stupid line input routine. No hair - is involved in writing any of the functions, and none should be. */ - -/* Note that: - - rl_end is the place in the string that we would place '\0'; - i.e., it is always safe to place '\0' there. - - rl_point is the place in the string where the cursor is. Sometimes - this is the same as rl_end. - - Any command that is called interactively receives two arguments. - The first is a count: the numeric arg pased to this command. - The second is the key which invoked this command. -*/ - -/* **************************************************************** */ -/* */ -/* Movement Commands */ -/* */ -/* **************************************************************** */ - -/* Note that if you `optimize' the display for these functions, you cannot - use said functions in other functions which do not do optimizing display. - I.e., you will have to update the data base for rl_redisplay, and you - might as well let rl_redisplay do that job. */ - -/* Move forward COUNT characters. */ -int -rl_forward (count, key) - int count, key; -{ - if (count < 0) - rl_backward (-count, key); - else if (count > 0) - { - int end = rl_point + count; -#if defined (VI_MODE) - int lend = rl_end - (rl_editing_mode == vi_mode); -#else - int lend = rl_end; -#endif - - if (end > lend) - { - rl_point = lend; - ding (); - } - else - rl_point = end; - } - return 0; -} - -/* Move backward COUNT characters. */ -int -rl_backward (count, key) - int count, key; -{ - if (count < 0) - rl_forward (-count, key); - else if (count > 0) - { - if (rl_point < count) - { - rl_point = 0; - ding (); - } - else - rl_point -= count; - } - return 0; -} - -/* Move to the beginning of the line. */ -int -rl_beg_of_line (count, key) - int count __attribute__((unused)), key __attribute__((unused)); -{ - rl_point = 0; - return 0; -} - -/* Move to the end of the line. */ -int -rl_end_of_line (count, key) - int count __attribute__((unused)), key __attribute__((unused)); -{ - rl_point = rl_end; - return 0; -} - -/* Move forward a word. We do what Emacs does. */ -int -rl_forward_word (count, key) - int count, key; -{ - int c; - - if (count < 0) - { - rl_backward_word (-count, key); - return 0; - } - - while (count) - { - if (rl_point == rl_end) - return 0; - - /* If we are not in a word, move forward until we are in one. - Then, move forward until we hit a non-alphabetic character. */ - c = the_line[rl_point]; - if (alphabetic (c) == 0) - { - while (++rl_point < rl_end) - { - c = the_line[rl_point]; - if (alphabetic (c)) - break; - } - } - if (rl_point == rl_end) - return 0; - while (++rl_point < rl_end) - { - c = the_line[rl_point]; - if (alphabetic (c) == 0) - break; - } - --count; - } - return 0; -} - -/* Move backward a word. We do what Emacs does. */ -int -rl_backward_word (count, key) - int count, key; -{ - int c; - - if (count < 0) - { - rl_forward_word (-count, key); - return 0; - } - - while (count) - { - if (!rl_point) - return 0; - - /* Like rl_forward_word (), except that we look at the characters - just before point. */ - - c = the_line[rl_point - 1]; - if (alphabetic (c) == 0) - { - while (--rl_point) - { - c = the_line[rl_point - 1]; - if (alphabetic (c)) - break; - } - } - - while (rl_point) - { - c = the_line[rl_point - 1]; - if (alphabetic (c) == 0) - break; - else - --rl_point; - } - --count; - } - return 0; -} - -/* Clear the current line. Numeric argument to C-l does this. */ -int -rl_refresh_line (ignore1, ignore2) - int ignore1 __attribute__((unused)), ignore2 __attribute__((unused)); -{ - int curr_line, nleft; - - /* Find out whether or not there might be invisible characters in the - editing buffer. */ - if (rl_display_prompt == rl_prompt) - nleft = _rl_last_c_pos - screenwidth - rl_visible_prompt_length; - else - nleft = _rl_last_c_pos - screenwidth; - - if (nleft > 0) - curr_line = 1 + nleft / screenwidth; - else - curr_line = 0; - - _rl_move_vert (curr_line); - _rl_move_cursor_relative (0, the_line); /* XXX is this right */ - -#if defined (__GO32__) - { - int row, col, width, row_start; - - ScreenGetCursor (&row, &col); - width = ScreenCols (); - row_start = ScreenPrimary + (row * width); - memset (row_start + col, 0, (width - col) * 2); - } -#else /* !__GO32__ */ - _rl_clear_to_eol (0); /* arg of 0 means to not use spaces */ -#endif /* !__GO32__ */ - - rl_forced_update_display (); - rl_display_fixed = 1; - - return 0; -} - -/* C-l typed to a line without quoting clears the screen, and then reprints - the prompt and the current input line. Given a numeric arg, redraw only - the current line. */ -int -rl_clear_screen (count, key) - int count, key; -{ - if (rl_explicit_arg) - { - rl_refresh_line (count, key); - return 0; - } - - _rl_clear_screen (); /* calls termcap function to clear screen */ - rl_forced_update_display (); - rl_display_fixed = 1; - - return 0; -} - -int -rl_arrow_keys (count, c) - int count, c __attribute__((unused)); -{ - int ch; - - ch = rl_read_key (); - - switch (_rl_to_upper (ch)) - { - case 'A': - rl_get_previous_history (count, ch); - break; - - case 'B': - rl_get_next_history (count, ch); - break; - - case 'C': - rl_forward (count, ch); - break; - - case 'D': - rl_backward (count, ch); - break; - - default: - ding (); - } - return 0; -} - - -/* **************************************************************** */ -/* */ -/* Text commands */ -/* */ -/* **************************************************************** */ - -/* Insert the character C at the current location, moving point forward. */ -int -rl_insert (count, c) - int count, c; -{ - register int i; - char *string; - - if (count <= 0) - return 0; - - /* If we can optimize, then do it. But don't let people crash - readline because of extra large arguments. */ - if (count > 1 && count <= 1024) - { - string = xmalloc (1 + count); - - for (i = 0; i < count; i++) - string[i] = c; - - string[i] = '\0'; - rl_insert_text (string); - free (string); - - return 0; - } - - if (count > 1024) - { - int decreaser; - char str[1024+1]; - - for (i = 0; i < 1024; i++) - str[i] = c; - - while (count) - { - decreaser = (count > 1024 ? 1024 : count); - str[decreaser] = '\0'; - rl_insert_text (str); - count -= decreaser; - } - - return 0; - } - - /* We are inserting a single character. - If there is pending input, then make a string of all of the - pending characters that are bound to rl_insert, and insert - them all. */ - if (_rl_any_typein ()) - _rl_insert_typein (c); - else - { - /* Inserting a single character. */ - char str[2]; - - str[1] = '\0'; - str[0] = c; - rl_insert_text (str); - } - return 0; -} - -/* Insert the next typed character verbatim. */ -int -rl_quoted_insert (count, key) - int count, key __attribute__((unused)); -{ - int c; - - c = rl_read_key (); - return (rl_insert (count, c)); -} - -/* Insert a tab character. */ -int -rl_tab_insert (count, key) - int count, key __attribute__((unused)); -{ - return (rl_insert (count, '\t')); -} - -/* What to do when a NEWLINE is pressed. We accept the whole line. - KEY is the key that invoked this command. I guess it could have - meaning in the future. */ -int -rl_newline (count, key) - int count __attribute__((unused)), key __attribute__((unused)); -{ - rl_done = 1; - -#if defined (VI_MODE) - if (rl_editing_mode == vi_mode) - { - _rl_vi_done_inserting (); - _rl_vi_reset_last (); - } -#endif /* VI_MODE */ - - /* If we've been asked to erase empty lines, suppress the final update, - since _rl_update_final calls crlf(). */ - if (rl_erase_empty_line && rl_point == 0 && rl_end == 0) - return 0; - - if (readline_echoing_p) - _rl_update_final (); - return 0; -} - -/* What to do for some uppercase characters, like meta characters, - and some characters appearing in emacs_ctlx_keymap. This function - is just a stub, you bind keys to it and the code in _rl_dispatch () - is special cased. */ -int -rl_do_lowercase_version (ignore1, ignore2) - int ignore1 __attribute__((unused)), ignore2 __attribute__((unused)); -{ - return 0; -} - -/* Rubout the character behind point. */ -int -rl_rubout (count, key) - int count, key; -{ - if (count < 0) - { - rl_delete (-count, key); - return 0; - } - - if (!rl_point) - { - ding (); - return -1; - } - - if (count > 1 || rl_explicit_arg) - { - int orig_point = rl_point; - rl_backward (count, key); - rl_kill_text (orig_point, rl_point); - } - else - { - int c = the_line[--rl_point]; - rl_delete_text (rl_point, rl_point + 1); - - if (rl_point == rl_end && isprint (c) && _rl_last_c_pos) - { - int l; - l = rl_character_len (c, rl_point); - _rl_erase_at_end_of_line (l); - } - } - return 0; -} - -/* Delete the character under the cursor. Given a numeric argument, - kill that many characters instead. */ -int -rl_delete (count, key) - int count, key; -{ - if (count < 0) - return (rl_rubout (-count, key)); - - if (rl_point == rl_end) - { - ding (); - return -1; - } - - if (count > 1 || rl_explicit_arg) - { - int orig_point = rl_point; - rl_forward (count, key); - rl_kill_text (orig_point, rl_point); - rl_point = orig_point; - return 0; - } - else - return (rl_delete_text (rl_point, rl_point + 1)); -} - -/* Delete the character under the cursor, unless the insertion - point is at the end of the line, in which case the character - behind the cursor is deleted. COUNT is obeyed and may be used - to delete forward or backward that many characters. */ -int -rl_rubout_or_delete (count, key) - int count, key; -{ - if (rl_end != 0 && rl_point == rl_end) - return (rl_rubout (count, key)); - else - return (rl_delete (count, key)); -} - -/* Delete all spaces and tabs around point. */ -int -rl_delete_horizontal_space (count, ignore) - int count __attribute__((unused)), ignore __attribute__((unused)); -{ - int start = rl_point; - - while (rl_point && whitespace (the_line[rl_point - 1])) - rl_point--; - - start = rl_point; - - while (rl_point < rl_end && whitespace (the_line[rl_point])) - rl_point++; - - if (start != rl_point) - { - rl_delete_text (start, rl_point); - rl_point = start; - } - return 0; -} - -/* Like the tcsh editing function delete-char-or-list. The eof character - is caught before this is invoked, so this really does the same thing as - delete-char-or-list-or-eof, as long as it's bound to the eof character. */ -int -rl_delete_or_show_completions (count, key) - int count, key; -{ - if (rl_end != 0 && rl_point == rl_end) - return (rl_possible_completions (count, key)); - else - return (rl_delete (count, key)); -} - -#ifndef RL_COMMENT_BEGIN_DEFAULT -#define RL_COMMENT_BEGIN_DEFAULT "#" -#endif - -/* Turn the current line into a comment in shell history. - A K*rn shell style function. */ -int -rl_insert_comment (count, key) - int count __attribute__((unused)), key; -{ - rl_beg_of_line (1, key); - rl_insert_text (_rl_comment_begin ? _rl_comment_begin - : RL_COMMENT_BEGIN_DEFAULT); - (*rl_redisplay_function) (); - rl_newline (1, '\n'); - return (0); -} - -/* **************************************************************** */ -/* */ -/* Changing Case */ -/* */ -/* **************************************************************** */ - -/* The three kinds of things that we know how to do. */ -#define UpCase 1 -#define DownCase 2 -#define CapCase 3 - -static int rl_change_case (); - -/* Uppercase the word at point. */ -int -rl_upcase_word (count, key) - int count, key __attribute__((unused)); -{ - return (rl_change_case (count, UpCase)); -} - -/* Lowercase the word at point. */ -int -rl_downcase_word (count, key) - int count, key __attribute__((unused)); -{ - return (rl_change_case (count, DownCase)); -} - -/* Upcase the first letter, downcase the rest. */ -int -rl_capitalize_word (count, key) - int count, key __attribute__((unused)); -{ - return (rl_change_case (count, CapCase)); -} - -/* The meaty function. - Change the case of COUNT words, performing OP on them. - OP is one of UpCase, DownCase, or CapCase. - If a negative argument is given, leave point where it started, - otherwise, leave it where it moves to. */ -static int -rl_change_case (count, op) - int count, op; -{ - register int start, end; - int inword, c; - - start = rl_point; - rl_forward_word (count, 0); - end = rl_point; - - if (count < 0) - SWAP (start, end); - - /* We are going to modify some text, so let's prepare to undo it. */ - rl_modifying (start, end); - - for (inword = 0; start < end; start++) - { - c = the_line[start]; - switch (op) - { - case UpCase: - the_line[start] = _rl_to_upper (c); - break; - - case DownCase: - the_line[start] = _rl_to_lower (c); - break; - - case CapCase: - the_line[start] = (inword == 0) ? _rl_to_upper (c) : _rl_to_lower (c); - inword = alphabetic (the_line[start]); - break; - - default: - ding (); - return -1; - } - } - rl_point = end; - return 0; -} - -/* **************************************************************** */ -/* */ -/* Transposition */ -/* */ -/* **************************************************************** */ - -/* Transpose the words at point. */ -int -rl_transpose_words (count, key) - int count, key; -{ - char *word1, *word2; - int w1_beg, w1_end, w2_beg, w2_end; - int orig_point = rl_point; - - if (!count) - return 0; - - /* Find the two words. */ - rl_forward_word (count, key); - w2_end = rl_point; - rl_backward_word (1, key); - w2_beg = rl_point; - rl_backward_word (count, key); - w1_beg = rl_point; - rl_forward_word (1, key); - w1_end = rl_point; - - /* Do some check to make sure that there really are two words. */ - if ((w1_beg == w2_beg) || (w2_beg < w1_end)) - { - ding (); - rl_point = orig_point; - return -1; - } - - /* Get the text of the words. */ - word1 = rl_copy_text (w1_beg, w1_end); - word2 = rl_copy_text (w2_beg, w2_end); - - /* We are about to do many insertions and deletions. Remember them - as one operation. */ - rl_begin_undo_group (); - - /* Do the stuff at word2 first, so that we don't have to worry - about word1 moving. */ - rl_point = w2_beg; - rl_delete_text (w2_beg, w2_end); - rl_insert_text (word1); - - rl_point = w1_beg; - rl_delete_text (w1_beg, w1_end); - rl_insert_text (word2); - - /* This is exactly correct since the text before this point has not - changed in length. */ - rl_point = w2_end; - - /* I think that does it. */ - rl_end_undo_group (); - free (word1); - free (word2); - - return 0; -} - -/* Transpose the characters at point. If point is at the end of the line, - then transpose the characters before point. */ -int -rl_transpose_chars (count, key) - int count, key __attribute__((unused)); -{ - char dummy[2]; - - if (!count) - return 0; - - if (!rl_point || rl_end < 2) - { - ding (); - return -1; - } - - rl_begin_undo_group (); - - if (rl_point == rl_end) - { - --rl_point; - count = 1; - } - rl_point--; - - dummy[0] = the_line[rl_point]; - dummy[1] = '\0'; - - rl_delete_text (rl_point, rl_point + 1); - - rl_point += count; - _rl_fix_point (0); - rl_insert_text (dummy); - - rl_end_undo_group (); - return 0; -} - -/* **************************************************************** */ -/* */ -/* Character Searching */ +/* Saving and Restoring Readline's state */ /* */ /* **************************************************************** */ int -_rl_char_search_internal (count, dir, schar) - int count, dir, schar; +rl_save_state (sp) + struct readline_state *sp; { - int pos, inc; - - pos = rl_point; - inc = (dir < 0) ? -1 : 1; - while (count) - { - if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end)) - { - ding (); - return -1; - } - - pos += inc; - do - { - if (rl_line_buffer[pos] == schar) - { - count--; - if (dir < 0) - rl_point = (dir == BTO) ? pos + 1 : pos; - else - rl_point = (dir == FTO) ? pos - 1 : pos; - break; - } - } - while ((dir < 0) ? pos-- : ++pos < rl_end); - } - return (0); -} - -/* Search COUNT times for a character read from the current input stream. - FDIR is the direction to search if COUNT is non-negative; otherwise - the search goes in BDIR. */ -static int -_rl_char_search (count, fdir, bdir) - int count, fdir, bdir; -{ - int c; - - c = rl_read_key (); - if (count < 0) - return (_rl_char_search_internal (-count, bdir, c)); - else - return (_rl_char_search_internal (count, fdir, c)); -} - -int -rl_char_search (count, key) - int count, key __attribute__((unused)); -{ - return (_rl_char_search (count, FFIND, BFIND)); -} - -int -rl_backward_char_search (count, key) - int count, key __attribute__((unused)); -{ - return (_rl_char_search (count, BFIND, FFIND)); -} - -/* **************************************************************** */ -/* */ -/* History Utilities */ -/* */ -/* **************************************************************** */ - -/* We already have a history library, and that is what we use to control - the history features of readline. This is our local interface to - the history mechanism. */ - -/* While we are editing the history, this is the saved - version of the original line. */ -HIST_ENTRY *saved_line_for_history = (HIST_ENTRY *)NULL; - -/* Set the history pointer back to the last entry in the history. */ -static void -start_using_history () -{ - using_history (); - if (saved_line_for_history) - _rl_free_history_entry (saved_line_for_history); - - saved_line_for_history = (HIST_ENTRY *)NULL; -} - -/* Free the contents (and containing structure) of a HIST_ENTRY. */ -void -_rl_free_history_entry (entry) - HIST_ENTRY *entry; -{ - if (entry == 0) - return; - if (entry->line) - free (entry->line); - free (entry); -} - -/* Perhaps put back the current line if it has changed. */ -int -maybe_replace_line () -{ - HIST_ENTRY *temp; - - temp = current_history (); - /* If the current line has changed, save the changes. */ - if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list)) - { - temp = replace_history_entry (where_history (), the_line, (histdata_t)rl_undo_list); - free (temp->line); - free (temp); - } - return 0; -} - -/* Put back the saved_line_for_history if there is one. */ -int -maybe_unsave_line () -{ - int line_len; - - if (saved_line_for_history) - { - line_len = strlen (saved_line_for_history->line); - - if (line_len >= rl_line_buffer_len) - rl_extend_line_buffer (line_len); - - strcpy (the_line, saved_line_for_history->line); - rl_undo_list = (UNDO_LIST *)saved_line_for_history->data; - _rl_free_history_entry (saved_line_for_history); - saved_line_for_history = (HIST_ENTRY *)NULL; - rl_end = rl_point = strlen (the_line); - } - else - ding (); - return 0; -} - -/* Save the current line in saved_line_for_history. */ -int -maybe_save_line () -{ - if (saved_line_for_history == 0) - { - saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); - saved_line_for_history->line = savestring (the_line); - saved_line_for_history->data = (char *)rl_undo_list; - } - return 0; -} - -/* **************************************************************** */ -/* */ -/* History Commands */ -/* */ -/* **************************************************************** */ - -/* Meta-< goes to the start of the history. */ -int -rl_beginning_of_history (count, key) - int count __attribute__((unused)), key; -{ - return (rl_get_previous_history (1 + where_history (), key)); -} - -/* Meta-> goes to the end of the history. (The current line). */ -int -rl_end_of_history (count, key) - int count __attribute__((unused)), key __attribute__((unused)); -{ - maybe_replace_line (); - using_history (); - maybe_unsave_line (); - return 0; -} - -/* Move down to the next history line. */ -int -rl_get_next_history (count, key) - int count, key; -{ - HIST_ENTRY *temp; - int line_len; - - if (count < 0) - return (rl_get_previous_history (-count, key)); - - if (count == 0) - return 0; - - maybe_replace_line (); - - temp = (HIST_ENTRY *)NULL; - while (count) - { - temp = next_history (); - if (!temp) - break; - --count; - } - - if (temp == 0) - maybe_unsave_line (); - else - { - line_len = strlen (temp->line); - - if (line_len >= rl_line_buffer_len) - rl_extend_line_buffer (line_len); - - strcpy (the_line, temp->line); - rl_undo_list = (UNDO_LIST *)temp->data; - rl_end = rl_point = strlen (the_line); -#if defined (VI_MODE) - if (rl_editing_mode == vi_mode) - rl_point = 0; -#endif /* VI_MODE */ - } - return 0; -} - -/* Get the previous item out of our interactive history, making it the current - line. If there is no previous history, just ding. */ -int -rl_get_previous_history (count, key) - int count, key; -{ - HIST_ENTRY *old_temp, *temp; - int line_len; - - if (count < 0) - return (rl_get_next_history (-count, key)); - - if (count == 0) - return 0; - - /* If we don't have a line saved, then save this one. */ - maybe_save_line (); - - /* If the current line has changed, save the changes. */ - maybe_replace_line (); - - temp = old_temp = (HIST_ENTRY *)NULL; - while (count) - { - temp = previous_history (); - if (temp == 0) - break; - - old_temp = temp; - --count; - } - - /* If there was a large argument, and we moved back to the start of the - history, that is not an error. So use the last value found. */ - if (!temp && old_temp) - temp = old_temp; - - if (temp == 0) - ding (); - else - { - line_len = strlen (temp->line); - - if (line_len >= rl_line_buffer_len) - rl_extend_line_buffer (line_len); - - strcpy (the_line, temp->line); - rl_undo_list = (UNDO_LIST *)temp->data; - rl_end = rl_point = line_len; - -#if defined (VI_MODE) - if (rl_editing_mode == vi_mode) - rl_point = 0; -#endif /* VI_MODE */ - } - return 0; -} - -/* **************************************************************** */ -/* */ -/* The Mark and the Region. */ -/* */ -/* **************************************************************** */ - -/* Set the mark at POSITION. */ -int -_rl_set_mark_at_pos (position) - int position; -{ - if (position > rl_end) + if (sp == 0) return -1; - rl_mark = position; - return 0; -} + sp->point = rl_point; + sp->end = rl_end; + sp->mark = rl_mark; + sp->buffer = rl_line_buffer; + sp->buflen = rl_line_buffer_len; + sp->ul = rl_undo_list; + sp->prompt = rl_prompt; -/* A bindable command to set the mark. */ -int -rl_set_mark (count, key) - int count, key __attribute__((unused)); -{ - return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point)); -} + sp->rlstate = rl_readline_state; + sp->done = rl_done; + sp->kmap = _rl_keymap; -/* Exchange the position of mark and point. */ -int -rl_exchange_point_and_mark (count, key) - int count __attribute__((unused)), key __attribute__((unused)); -{ - if (rl_mark > rl_end) - rl_mark = -1; + sp->lastfunc = rl_last_func; + sp->insmode = rl_insert_mode; + sp->edmode = rl_editing_mode; + sp->kseqlen = rl_key_sequence_length; + sp->inf = rl_instream; + sp->outf = rl_outstream; + sp->pendingin = rl_pending_input; + sp->macro = rl_executing_macro; - if (rl_mark == -1) - { - ding (); - return -1; - } - else - SWAP (rl_point, rl_mark); + sp->catchsigs = rl_catch_signals; + sp->catchsigwinch = rl_catch_sigwinch; - return 0; -} - -/* **************************************************************** */ -/* */ -/* Editing Modes */ -/* */ -/* **************************************************************** */ -/* How to toggle back and forth between editing modes. */ -int -rl_vi_editing_mode (count, key) - int count __attribute__((unused)), key; -{ -#if defined (VI_MODE) - rl_editing_mode = vi_mode; - rl_vi_insertion_mode (1, key); -#endif /* VI_MODE */ - return 0; + return (0); } int -rl_emacs_editing_mode (count, key) - int count __attribute__((unused)), key __attribute__((unused)); +rl_restore_state (sp) + struct readline_state *sp; { - rl_editing_mode = emacs_mode; - _rl_keymap = emacs_standard_keymap; - return 0; + if (sp == 0) + return -1; + + rl_point = sp->point; + rl_end = sp->end; + rl_mark = sp->mark; + the_line = rl_line_buffer = sp->buffer; + rl_line_buffer_len = sp->buflen; + rl_undo_list = sp->ul; + rl_prompt = sp->prompt; + + rl_readline_state = sp->rlstate; + rl_done = sp->done; + _rl_keymap = sp->kmap; + + rl_last_func = sp->lastfunc; + rl_insert_mode = sp->insmode; + rl_editing_mode = sp->edmode; + rl_key_sequence_length = sp->kseqlen; + rl_instream = sp->inf; + rl_outstream = sp->outf; + rl_pending_input = sp->pendingin; + rl_executing_macro = sp->macro; + + rl_catch_signals = sp->catchsigs; + rl_catch_sigwinch = sp->catchsigwinch; + + return (0); } diff --git a/readline/readline.h b/readline/readline.h index 7804d31efb1..f11b3d0357c 100644 --- a/readline/readline.h +++ b/readline/readline.h @@ -7,7 +7,7 @@ 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 1, or + 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 @@ -18,7 +18,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #if !defined (_READLINE_H_) #define _READLINE_H_ @@ -29,14 +29,21 @@ extern "C" { #if defined (READLINE_LIBRARY) # include "rlstdc.h" +# include "rltypedefs.h" # include "keymaps.h" # include "tilde.h" #else # include +# include # include # include #endif +/* Hex-encoded Readline version number. */ +#define RL_READLINE_VERSION 0x0403 /* Readline 4.3 */ +#define RL_VERSION_MAJOR 4 +#define RL_VERSION_MINOR 3 + /* Readline data structures. */ /* Maintaining the state of undo. We remember individual deletes and inserts @@ -61,7 +68,7 @@ extern UNDO_LIST *rl_undo_list; /* The data structure for mapping textual names to code addresses. */ typedef struct _funmap { const char *name; - Function *function; + rl_command_func_t *function; } FUNMAP; extern FUNMAP **funmap; @@ -73,184 +80,191 @@ extern FUNMAP **funmap; /* **************************************************************** */ /* Bindable commands for numeric arguments. */ -extern int rl_digit_argument __P((int, int)); -extern int rl_universal_argument __P((int, int)); +extern int rl_digit_argument PARAMS((int, int)); +extern int rl_universal_argument PARAMS((int, int)); /* Bindable commands for moving the cursor. */ -extern int rl_forward __P((int, int)); -extern int rl_backward __P((int, int)); -extern int rl_beg_of_line __P((int, int)); -extern int rl_end_of_line __P((int, int)); -extern int rl_forward_word __P((int, int)); -extern int rl_backward_word __P((int, int)); -extern int rl_refresh_line __P((int, int)); -extern int rl_clear_screen __P((int, int)); -extern int rl_arrow_keys __P((int, int)); +extern int rl_forward_byte PARAMS((int, int)); +extern int rl_forward_char PARAMS((int, int)); +extern int rl_forward PARAMS((int, int)); +extern int rl_backward_byte PARAMS((int, int)); +extern int rl_backward_char PARAMS((int, int)); +extern int rl_backward PARAMS((int, int)); +extern int rl_beg_of_line PARAMS((int, int)); +extern int rl_end_of_line PARAMS((int, int)); +extern int rl_forward_word PARAMS((int, int)); +extern int rl_backward_word PARAMS((int, int)); +extern int rl_refresh_line PARAMS((int, int)); +extern int rl_clear_screen PARAMS((int, int)); +extern int rl_arrow_keys PARAMS((int, int)); /* Bindable commands for inserting and deleting text. */ -extern int rl_insert __P((int, int)); -extern int rl_quoted_insert __P((int, int)); -extern int rl_tab_insert __P((int, int)); -extern int rl_newline __P((int, int)); -extern int rl_do_lowercase_version __P((int, int)); -extern int rl_rubout __P((int, int)); -extern int rl_delete __P((int, int)); -extern int rl_rubout_or_delete __P((int, int)); -extern int rl_delete_horizontal_space __P((int, int)); -extern int rl_delete_or_show_completions __P((int, int)); -extern int rl_insert_comment __P((int, int)); +extern int rl_insert PARAMS((int, int)); +extern int rl_quoted_insert PARAMS((int, int)); +extern int rl_tab_insert PARAMS((int, int)); +extern int rl_newline PARAMS((int, int)); +extern int rl_do_lowercase_version PARAMS((int, int)); +extern int rl_rubout PARAMS((int, int)); +extern int rl_delete PARAMS((int, int)); +extern int rl_rubout_or_delete PARAMS((int, int)); +extern int rl_delete_horizontal_space PARAMS((int, int)); +extern int rl_delete_or_show_completions PARAMS((int, int)); +extern int rl_insert_comment PARAMS((int, int)); /* Bindable commands for changing case. */ -extern int rl_upcase_word __P((int, int)); -extern int rl_downcase_word __P((int, int)); -extern int rl_capitalize_word __P((int, int)); +extern int rl_upcase_word PARAMS((int, int)); +extern int rl_downcase_word PARAMS((int, int)); +extern int rl_capitalize_word PARAMS((int, int)); /* Bindable commands for transposing characters and words. */ -extern int rl_transpose_words __P((int, int)); -extern int rl_transpose_chars __P((int, int)); +extern int rl_transpose_words PARAMS((int, int)); +extern int rl_transpose_chars PARAMS((int, int)); /* Bindable commands for searching within a line. */ -extern int rl_char_search __P((int, int)); -extern int rl_backward_char_search __P((int, int)); +extern int rl_char_search PARAMS((int, int)); +extern int rl_backward_char_search PARAMS((int, int)); /* Bindable commands for readline's interface to the command history. */ -extern int rl_beginning_of_history __P((int, int)); -extern int rl_end_of_history __P((int, int)); -extern int rl_get_next_history __P((int, int)); -extern int rl_get_previous_history __P((int, int)); +extern int rl_beginning_of_history PARAMS((int, int)); +extern int rl_end_of_history PARAMS((int, int)); +extern int rl_get_next_history PARAMS((int, int)); +extern int rl_get_previous_history PARAMS((int, int)); /* Bindable commands for managing the mark and region. */ -extern int rl_set_mark __P((int, int)); -extern int rl_exchange_point_and_mark __P((int, int)); +extern int rl_set_mark PARAMS((int, int)); +extern int rl_exchange_point_and_mark PARAMS((int, int)); /* Bindable commands to set the editing mode (emacs or vi). */ -extern int rl_vi_editing_mode __P((int, int)); -extern int rl_emacs_editing_mode __P((int, int)); +extern int rl_vi_editing_mode PARAMS((int, int)); +extern int rl_emacs_editing_mode PARAMS((int, int)); + +/* Bindable commands to change the insert mode (insert or overwrite) */ +extern int rl_overwrite_mode PARAMS((int, int)); /* Bindable commands for managing key bindings. */ -extern int rl_re_read_init_file __P((int, int)); -extern int rl_dump_functions __P((int, int)); -extern int rl_dump_macros __P((int, int)); -extern int rl_dump_variables __P((int, int)); +extern int rl_re_read_init_file PARAMS((int, int)); +extern int rl_dump_functions PARAMS((int, int)); +extern int rl_dump_macros PARAMS((int, int)); +extern int rl_dump_variables PARAMS((int, int)); /* Bindable commands for word completion. */ -extern int rl_complete __P((int, int)); -extern int rl_possible_completions __P((int, int)); -extern int rl_insert_completions __P((int, int)); -extern int rl_menu_complete __P((int, int)); +extern int rl_complete PARAMS((int, int)); +extern int rl_possible_completions PARAMS((int, int)); +extern int rl_insert_completions PARAMS((int, int)); +extern int rl_menu_complete PARAMS((int, int)); /* Bindable commands for killing and yanking text, and managing the kill ring. */ -extern int rl_kill_word __P((int, int)); -extern int rl_backward_kill_word __P((int, int)); -extern int rl_kill_line __P((int, int)); -extern int rl_backward_kill_line __P((int, int)); -extern int rl_kill_full_line __P((int, int)); -extern int rl_unix_word_rubout __P((int, int)); -extern int rl_unix_line_discard __P((int, int)); -extern int rl_copy_region_to_kill __P((int, int)); -extern int rl_kill_region __P((int, int)); -extern int rl_copy_forward_word __P((int, int)); -extern int rl_copy_backward_word __P((int, int)); -extern int rl_yank __P((int, int)); -extern int rl_yank_pop __P((int, int)); -extern int rl_yank_nth_arg __P((int, int)); -extern int rl_yank_last_arg __P((int, int)); -/* Not available unless __CYGWIN32__ is defined. */ -#ifdef __CYGWIN32__ -extern int rl_paste_from_clipboard __P((int, int)); +extern int rl_kill_word PARAMS((int, int)); +extern int rl_backward_kill_word PARAMS((int, int)); +extern int rl_kill_line PARAMS((int, int)); +extern int rl_backward_kill_line PARAMS((int, int)); +extern int rl_kill_full_line PARAMS((int, int)); +extern int rl_unix_word_rubout PARAMS((int, int)); +extern int rl_unix_line_discard PARAMS((int, int)); +extern int rl_copy_region_to_kill PARAMS((int, int)); +extern int rl_kill_region PARAMS((int, int)); +extern int rl_copy_forward_word PARAMS((int, int)); +extern int rl_copy_backward_word PARAMS((int, int)); +extern int rl_yank PARAMS((int, int)); +extern int rl_yank_pop PARAMS((int, int)); +extern int rl_yank_nth_arg PARAMS((int, int)); +extern int rl_yank_last_arg PARAMS((int, int)); +/* Not available unless __CYGWIN__ is defined. */ +#ifdef __CYGWIN__ +extern int rl_paste_from_clipboard PARAMS((int, int)); #endif /* Bindable commands for incremental searching. */ -extern int rl_reverse_search_history __P((int, int)); -extern int rl_forward_search_history __P((int, int)); +extern int rl_reverse_search_history PARAMS((int, int)); +extern int rl_forward_search_history PARAMS((int, int)); /* Bindable keyboard macro commands. */ -extern int rl_start_kbd_macro __P((int, int)); -extern int rl_end_kbd_macro __P((int, int)); -extern int rl_call_last_kbd_macro __P((int, int)); +extern int rl_start_kbd_macro PARAMS((int, int)); +extern int rl_end_kbd_macro PARAMS((int, int)); +extern int rl_call_last_kbd_macro PARAMS((int, int)); /* Bindable undo commands. */ -extern int rl_revert_line __P((int, int)); -extern int rl_undo_command __P((int, int)); +extern int rl_revert_line PARAMS((int, int)); +extern int rl_undo_command PARAMS((int, int)); /* Bindable tilde expansion commands. */ -extern int rl_tilde_expand __P((int, int)); +extern int rl_tilde_expand PARAMS((int, int)); /* Bindable terminal control commands. */ -extern int rl_restart_output __P((int, int)); -extern int rl_stop_output __P((int, int)); +extern int rl_restart_output PARAMS((int, int)); +extern int rl_stop_output PARAMS((int, int)); /* Miscellaneous bindable commands. */ -extern int rl_abort __P((int, int)); -extern int rl_tty_status __P((int, int)); +extern int rl_abort PARAMS((int, int)); +extern int rl_tty_status PARAMS((int, int)); /* Bindable commands for incremental and non-incremental history searching. */ -extern int rl_history_search_forward __P((int, int)); -extern int rl_history_search_backward __P((int, int)); -extern int rl_noninc_forward_search __P((int, int)); -extern int rl_noninc_reverse_search __P((int, int)); -extern int rl_noninc_forward_search_again __P((int, int)); -extern int rl_noninc_reverse_search_again __P((int, int)); +extern int rl_history_search_forward PARAMS((int, int)); +extern int rl_history_search_backward PARAMS((int, int)); +extern int rl_noninc_forward_search PARAMS((int, int)); +extern int rl_noninc_reverse_search PARAMS((int, int)); +extern int rl_noninc_forward_search_again PARAMS((int, int)); +extern int rl_noninc_reverse_search_again PARAMS((int, int)); -/* Not available unless readline is compiled -DPAREN_MATCHING. */ -extern int rl_insert_close __P((int, int)); +/* Bindable command used when inserting a matching close character. */ +extern int rl_insert_close PARAMS((int, int)); /* Not available unless READLINE_CALLBACKS is defined. */ -extern void rl_callback_handler_install __P((char *, VFunction *)); -extern void rl_callback_read_char __P((void)); -extern void rl_callback_handler_remove __P((void)); +extern void rl_callback_handler_install PARAMS((const char *, rl_vcpfunc_t *)); +extern void rl_callback_read_char PARAMS((void)); +extern void rl_callback_handler_remove PARAMS((void)); /* Things for vi mode. Not available unless readline is compiled -DVI_MODE. */ /* VI-mode bindable commands. */ -extern int rl_vi_redo __P((int, int)); -extern int rl_vi_undo __P((int, int)); -extern int rl_vi_yank_arg __P((int, int)); -extern int rl_vi_fetch_history __P((int, int)); -extern int rl_vi_search_again __P((int, int)); -extern int rl_vi_search __P((int, int)); -extern int rl_vi_complete __P((int, int)); -extern int rl_vi_tilde_expand __P((int, int)); -extern int rl_vi_prev_word __P((int, int)); -extern int rl_vi_next_word __P((int, int)); -extern int rl_vi_end_word __P((int, int)); -extern int rl_vi_insert_beg __P((int, int)); -extern int rl_vi_append_mode __P((int, int)); -extern int rl_vi_append_eol __P((int, int)); -extern int rl_vi_eof_maybe __P((int, int)); -extern int rl_vi_insertion_mode __P((int, int)); -extern int rl_vi_movement_mode __P((int, int)); -extern int rl_vi_arg_digit __P((int, int)); -extern int rl_vi_change_case __P((int, int)); -extern int rl_vi_put __P((int, int)); -extern int rl_vi_column __P((int, int)); -extern int rl_vi_delete_to __P((int, int)); -extern int rl_vi_change_to __P((int, int)); -extern int rl_vi_yank_to __P((int, int)); -extern int rl_vi_delete __P((int, int)); -extern int rl_vi_back_to_indent __P((int, int)); -extern int rl_vi_first_print __P((int, int)); -extern int rl_vi_char_search __P((int, int)); -extern int rl_vi_match __P((int, int)); -extern int rl_vi_change_char __P((int, int)); -extern int rl_vi_subst __P((int, int)); -extern int rl_vi_overstrike __P((int, int)); -extern int rl_vi_overstrike_delete __P((int, int)); -extern int rl_vi_replace __P((int, int)); -extern int rl_vi_set_mark __P((int, int)); -extern int rl_vi_goto_mark __P((int, int)); +extern int rl_vi_redo PARAMS((int, int)); +extern int rl_vi_undo PARAMS((int, int)); +extern int rl_vi_yank_arg PARAMS((int, int)); +extern int rl_vi_fetch_history PARAMS((int, int)); +extern int rl_vi_search_again PARAMS((int, int)); +extern int rl_vi_search PARAMS((int, int)); +extern int rl_vi_complete PARAMS((int, int)); +extern int rl_vi_tilde_expand PARAMS((int, int)); +extern int rl_vi_prev_word PARAMS((int, int)); +extern int rl_vi_next_word PARAMS((int, int)); +extern int rl_vi_end_word PARAMS((int, int)); +extern int rl_vi_insert_beg PARAMS((int, int)); +extern int rl_vi_append_mode PARAMS((int, int)); +extern int rl_vi_append_eol PARAMS((int, int)); +extern int rl_vi_eof_maybe PARAMS((int, int)); +extern int rl_vi_insertion_mode PARAMS((int, int)); +extern int rl_vi_movement_mode PARAMS((int, int)); +extern int rl_vi_arg_digit PARAMS((int, int)); +extern int rl_vi_change_case PARAMS((int, int)); +extern int rl_vi_put PARAMS((int, int)); +extern int rl_vi_column PARAMS((int, int)); +extern int rl_vi_delete_to PARAMS((int, int)); +extern int rl_vi_change_to PARAMS((int, int)); +extern int rl_vi_yank_to PARAMS((int, int)); +extern int rl_vi_delete PARAMS((int, int)); +extern int rl_vi_back_to_indent PARAMS((int, int)); +extern int rl_vi_first_print PARAMS((int, int)); +extern int rl_vi_char_search PARAMS((int, int)); +extern int rl_vi_match PARAMS((int, int)); +extern int rl_vi_change_char PARAMS((int, int)); +extern int rl_vi_subst PARAMS((int, int)); +extern int rl_vi_overstrike PARAMS((int, int)); +extern int rl_vi_overstrike_delete PARAMS((int, int)); +extern int rl_vi_replace PARAMS((int, int)); +extern int rl_vi_set_mark PARAMS((int, int)); +extern int rl_vi_goto_mark PARAMS((int, int)); /* VI-mode utility functions. */ -extern int rl_vi_check __P((void)); -extern int rl_vi_domove __P((int, int *)); -extern int rl_vi_bracktype __P((int)); +extern int rl_vi_check PARAMS((void)); +extern int rl_vi_domove PARAMS((int, int *)); +extern int rl_vi_bracktype PARAMS((int)); /* VI-mode pseudo-bindable commands, used as utility functions. */ -extern int rl_vi_fWord __P((int, int)); -extern int rl_vi_bWord __P((int, int)); -extern int rl_vi_eWord __P((int, int)); -extern int rl_vi_fword __P((int, int)); -extern int rl_vi_bword __P((int, int)); -extern int rl_vi_eword __P((int, int)); +extern int rl_vi_fWord PARAMS((int, int)); +extern int rl_vi_bWord PARAMS((int, int)); +extern int rl_vi_eWord PARAMS((int, int)); +extern int rl_vi_fword PARAMS((int, int)); +extern int rl_vi_bword PARAMS((int, int)); +extern int rl_vi_eword PARAMS((int, int)); /* **************************************************************** */ /* */ @@ -260,141 +274,176 @@ extern int rl_vi_eword __P((int, int)); /* Readline functions. */ /* Read a line of input. Prompt with PROMPT. A NULL PROMPT means none. */ -extern char *readline __P((char *)); +extern char *readline PARAMS((const char *)); -extern int rl_initialize __P((void)); +extern int rl_set_prompt PARAMS((const char *)); +extern int rl_expand_prompt PARAMS((char *)); -extern int rl_discard_argument __P((void)); +extern int rl_initialize PARAMS((void)); + +/* Undocumented; unused by readline */ +extern int rl_discard_argument PARAMS((void)); /* Utility functions to bind keys to readline commands. */ -extern int rl_add_defun __P((char *, Function *, int)); -extern int rl_bind_key __P((int, Function *)); -extern int rl_bind_key_in_map __P((int, Function *, Keymap)); -extern int rl_unbind_key __P((int)); -extern int rl_unbind_key_in_map __P((int, Keymap)); -extern int rl_unbind_function_in_map __P((Function *, Keymap)); -extern int rl_unbind_command_in_map __P((char *, Keymap)); -extern int rl_set_key __P((char *, Function *, Keymap)); -extern int rl_generic_bind __P((int, char *, char *, Keymap)); -extern int rl_variable_bind __P((char *, char *)); +extern int rl_add_defun PARAMS((const char *, rl_command_func_t *, int)); +extern int rl_bind_key PARAMS((int, rl_command_func_t *)); +extern int rl_bind_key_in_map PARAMS((int, rl_command_func_t *, Keymap)); +extern int rl_unbind_key PARAMS((int)); +extern int rl_unbind_key_in_map PARAMS((int, Keymap)); +extern int rl_unbind_function_in_map PARAMS((rl_command_func_t *, Keymap)); +extern int rl_unbind_command_in_map PARAMS((const char *, Keymap)); +extern int rl_set_key PARAMS((const char *, rl_command_func_t *, Keymap)); +extern int rl_generic_bind PARAMS((int, const char *, char *, Keymap)); +extern int rl_variable_bind PARAMS((const char *, const char *)); /* Backwards compatibility, use rl_generic_bind instead. */ -extern int rl_macro_bind __P((char *, char *, Keymap)); +extern int rl_macro_bind PARAMS((const char *, const char *, Keymap)); /* Undocumented in the texinfo manual; not really useful to programs. */ -extern int rl_translate_keyseq __P((char *, char *, int *)); -extern char *rl_untranslate_keyseq __P((int)); +extern int rl_translate_keyseq PARAMS((const char *, char *, int *)); +extern char *rl_untranslate_keyseq PARAMS((int)); -extern Function *rl_named_function __P((char *)); -extern Function *rl_function_of_keyseq __P((const char *, Keymap, int *)); +extern rl_command_func_t *rl_named_function PARAMS((const char *)); +extern rl_command_func_t *rl_function_of_keyseq PARAMS((const char *, Keymap, int *)); -extern void rl_list_funmap_names __P((void)); -extern char **rl_invoking_keyseqs_in_map __P((Function *, Keymap)); -extern char **rl_invoking_keyseqs __P((Function *)); +extern void rl_list_funmap_names PARAMS((void)); +extern char **rl_invoking_keyseqs_in_map PARAMS((rl_command_func_t *, Keymap)); +extern char **rl_invoking_keyseqs PARAMS((rl_command_func_t *)); + +extern void rl_function_dumper PARAMS((int)); +extern void rl_macro_dumper PARAMS((int)); +extern void rl_variable_dumper PARAMS((int)); -extern void rl_function_dumper __P((int)); -extern void rl_macro_dumper __P((int)); -extern void rl_variable_dumper __P((int)); - -extern int rl_read_init_file __P((const char *)); -extern int rl_parse_and_bind __P((char *)); +extern int rl_read_init_file PARAMS((const char *)); +extern int rl_parse_and_bind PARAMS((char *)); /* Functions for manipulating keymaps. */ -extern Keymap rl_make_bare_keymap __P((void)); -extern Keymap rl_copy_keymap __P((Keymap)); -extern Keymap rl_make_keymap __P((void)); -extern void rl_discard_keymap __P((Keymap)); +extern Keymap rl_make_bare_keymap PARAMS((void)); +extern Keymap rl_copy_keymap PARAMS((Keymap)); +extern Keymap rl_make_keymap PARAMS((void)); +extern void rl_discard_keymap PARAMS((Keymap)); -extern Keymap rl_get_keymap_by_name __P((char *)); -extern const char *rl_get_keymap_name __P((Keymap)); -extern void rl_set_keymap __P((Keymap)); -extern Keymap rl_get_keymap __P((void)); -extern void rl_set_keymap_from_edit_mode __P((void)); -extern const char *rl_get_keymap_name_from_edit_mode __P((void)); +extern Keymap rl_get_keymap_by_name PARAMS((const char *)); +extern char *rl_get_keymap_name PARAMS((Keymap)); +extern void rl_set_keymap PARAMS((Keymap)); +extern Keymap rl_get_keymap PARAMS((void)); +/* Undocumented; used internally only. */ +extern void rl_set_keymap_from_edit_mode PARAMS((void)); +extern char *rl_get_keymap_name_from_edit_mode PARAMS((void)); /* Functions for manipulating the funmap, which maps command names to functions. */ -extern int rl_add_funmap_entry __P((const char *, Function *)); -extern void rl_initialize_funmap __P((void)); -extern char **rl_funmap_names __P((void)); +extern int rl_add_funmap_entry PARAMS((const char *, rl_command_func_t *)); +extern const char **rl_funmap_names PARAMS((void)); +/* Undocumented, only used internally -- there is only one funmap, and this + function may be called only once. */ +extern void rl_initialize_funmap PARAMS((void)); /* Utility functions for managing keyboard macros. */ -extern void rl_push_macro_input __P((char *)); +extern void rl_push_macro_input PARAMS((char *)); /* Functions for undoing, from undo.c */ -extern void rl_add_undo __P((enum undo_code, int, int, char *)); -extern void free_undo_list __P((void)); -extern int rl_do_undo __P((void)); -extern int rl_begin_undo_group __P((void)); -extern int rl_end_undo_group __P((void)); -extern int rl_modifying __P((int, int)); +extern void rl_add_undo PARAMS((enum undo_code, int, int, char *)); +extern void rl_free_undo_list PARAMS((void)); +extern int rl_do_undo PARAMS((void)); +extern int rl_begin_undo_group PARAMS((void)); +extern int rl_end_undo_group PARAMS((void)); +extern int rl_modifying PARAMS((int, int)); /* Functions for redisplay. */ -extern void rl_redisplay __P((void)); -extern int rl_on_new_line __P((void)); -extern int rl_forced_update_display __P((void)); -extern int rl_clear_message __P((void)); -extern int rl_reset_line_state __P((void)); +extern void rl_redisplay PARAMS((void)); +extern int rl_on_new_line PARAMS((void)); +extern int rl_on_new_line_with_prompt PARAMS((void)); +extern int rl_forced_update_display PARAMS((void)); +extern int rl_clear_message PARAMS((void)); +extern int rl_reset_line_state PARAMS((void)); +extern int rl_crlf PARAMS((void)); -#if defined (__STDC__) && defined (USE_VARARGS) && defined (PREFER_STDARG) -extern int rl_message (const char *, ...); +#if (defined (__STDC__) || defined (__cplusplus)) && defined (USE_VARARGS) && defined (PREFER_STDARG) +extern int rl_message (const char *, ...) __attribute__((__format__ (printf, 1, 2))); #else extern int rl_message (); #endif +extern int rl_show_char PARAMS((int)); + /* Undocumented in texinfo manual. */ -extern int rl_show_char __P((int)); -extern int rl_character_len __P((int, int)); -extern int crlf __P((void)); +extern int rl_character_len PARAMS((int, int)); /* Save and restore internal prompt redisplay information. */ -extern void rl_save_prompt __P((void)); -extern void rl_restore_prompt __P((void)); +extern void rl_save_prompt PARAMS((void)); +extern void rl_restore_prompt PARAMS((void)); /* Modifying text. */ -extern int rl_insert_text __P((const char *)); -extern int rl_delete_text __P((int, int)); -extern int rl_kill_text __P((int, int)); -extern char *rl_copy_text __P((int, int)); +extern void rl_replace_line PARAMS((const char *, int)); +extern int rl_insert_text PARAMS((const char *)); +extern int rl_delete_text PARAMS((int, int)); +extern int rl_kill_text PARAMS((int, int)); +extern char *rl_copy_text PARAMS((int, int)); /* Terminal and tty mode management. */ -extern void rl_prep_terminal __P((int)); -extern void rl_deprep_terminal __P((void)); -extern void rltty_set_default_bindings __P((Keymap)); +extern void rl_prep_terminal PARAMS((int)); +extern void rl_deprep_terminal PARAMS((void)); +extern void rl_tty_set_default_bindings PARAMS((Keymap)); -extern int rl_reset_terminal __P((char *)); -extern void rl_resize_terminal __P((void)); +extern int rl_reset_terminal PARAMS((const char *)); +extern void rl_resize_terminal PARAMS((void)); +extern void rl_set_screen_size PARAMS((int, int)); +extern void rl_get_screen_size PARAMS((int *, int *)); -/* `Public' utility functions . */ -extern void rl_extend_line_buffer __P((int)); -extern int ding __P((void)); +extern char *rl_get_termcap PARAMS((const char *)); /* Functions for character input. */ -extern int rl_stuff_char __P((int)); -extern int rl_execute_next __P((int)); -extern int rl_read_key __P((void)); -extern int rl_getc __P((FILE *)); +extern int rl_stuff_char PARAMS((int)); +extern int rl_execute_next PARAMS((int)); +extern int rl_clear_pending_input PARAMS((void)); +extern int rl_read_key PARAMS((void)); +extern int rl_getc PARAMS((FILE *)); +extern int rl_set_keyboard_input_timeout PARAMS((int)); + +/* `Public' utility functions . */ +extern void rl_extend_line_buffer PARAMS((int)); +extern int rl_ding PARAMS((void)); +extern int rl_alphabetic PARAMS((int)); /* Readline signal handling, from signals.c */ -extern int rl_set_signals __P((void)); -extern int rl_clear_signals __P((void)); -extern void rl_cleanup_after_signal __P((void)); -extern void rl_reset_after_signal __P((void)); -extern void rl_free_line_state __P((void)); +extern int rl_set_signals PARAMS((void)); +extern int rl_clear_signals PARAMS((void)); +extern void rl_cleanup_after_signal PARAMS((void)); +extern void rl_reset_after_signal PARAMS((void)); +extern void rl_free_line_state PARAMS((void)); + +extern int rl_set_paren_blink_timeout PARAMS((int)); /* Undocumented. */ -extern int rl_expand_prompt __P((char *)); - -extern int maybe_save_line __P((void)); -extern int maybe_unsave_line __P((void)); -extern int maybe_replace_line __P((void)); +extern int rl_maybe_save_line PARAMS((void)); +extern int rl_maybe_unsave_line PARAMS((void)); +extern int rl_maybe_replace_line PARAMS((void)); /* Completion functions. */ -extern int rl_complete_internal __P((int)); -extern void rl_display_match_list __P((char **, int, int)); +extern int rl_complete_internal PARAMS((int)); +extern void rl_display_match_list PARAMS((char **, int, int)); -extern char **completion_matches __P((const char *, CPFunction *)); -extern char *username_completion_function __P((const char *, int)); -extern char *filename_completion_function __P((const char *, int)); +extern char **rl_completion_matches PARAMS((const char *, rl_compentry_func_t *)); +extern char *rl_username_completion_function PARAMS((const char *, int)); +extern char *rl_filename_completion_function PARAMS((const char *, int)); + +extern int rl_completion_mode PARAMS((rl_command_func_t *)); + +#if 0 +/* Backwards compatibility (compat.c). These will go away sometime. */ +extern void free_undo_list PARAMS((void)); +extern int maybe_save_line PARAMS((void)); +extern int maybe_unsave_line PARAMS((void)); +extern int maybe_replace_line PARAMS((void)); + +extern int ding PARAMS((void)); +extern int alphabetic PARAMS((int)); +extern int crlf PARAMS((void)); + +extern char **completion_matches PARAMS((char *, rl_compentry_func_t *)); +extern char *username_completion_function PARAMS((const char *, int)); +extern char *filename_completion_function PARAMS((const char *, int)); +#endif /* **************************************************************** */ /* */ @@ -403,7 +452,22 @@ extern char *filename_completion_function __P((const char *, int)); /* **************************************************************** */ /* The version of this incarnation of the readline library. */ -extern const char *rl_library_version; +extern const char *rl_library_version; /* e.g., "4.2" */ +extern int rl_readline_version; /* e.g., 0x0402 */ + +/* True if this is real GNU readline. */ +extern int rl_gnu_readline_p; + +/* Flags word encapsulating the current readline state. */ +extern int rl_readline_state; + +/* Says which editing mode readline is currently using. 1 means emacs mode; + 0 means vi mode. */ +extern int rl_editing_mode; + +/* Insert or overwrite mode for emacs mode. 1 means insert mode; 0 means + overwrite mode. Reset to insert mode on each input line. */ +extern int rl_insert_mode; /* The name of the calling program. You should initialize this to whatever was in argv[0]. It is used when parsing conditionals. */ @@ -417,7 +481,8 @@ extern char *rl_prompt; extern char *rl_line_buffer; /* The location of point, and end. */ -extern int rl_point, rl_end; +extern int rl_point; +extern int rl_end; /* The mark, or saved cursor position. */ extern int rl_mark; @@ -434,29 +499,44 @@ extern int rl_pending_input; or directly from an application. */ extern int rl_dispatching; +/* Non-zero if the user typed a numeric argument before executing the + current function. */ +extern int rl_explicit_arg; + +/* The current value of the numeric argument specified by the user. */ +extern int rl_numeric_arg; + +/* The address of the last command function Readline executed. */ +extern rl_command_func_t *rl_last_func; + /* The name of the terminal to use. */ -extern char *rl_terminal_name; +extern const char *rl_terminal_name; /* The input and output streams. */ -extern FILE *rl_instream, *rl_outstream; +extern FILE *rl_instream; +extern FILE *rl_outstream; /* If non-zero, then this is the address of a function to call just before readline_internal () prints the first prompt. */ -extern Function *rl_startup_hook; +extern rl_hook_func_t *rl_startup_hook; /* If non-zero, this is the address of a function to call just before readline_internal_setup () returns and readline_internal starts reading input characters. */ -extern Function *rl_pre_input_hook; - +extern rl_hook_func_t *rl_pre_input_hook; + /* The address of a function to call periodically while Readline is awaiting character input, or NULL, for no event handling. */ -extern Function *rl_event_hook; +extern rl_hook_func_t *rl_event_hook; -extern Function *rl_getc_function; -extern VFunction *rl_redisplay_function; -extern VFunction *rl_prep_term_function; -extern VFunction *rl_deprep_term_function; +/* The address of the function to call to fetch a character from the current + Readline input stream */ +extern rl_getc_func_t *rl_getc_function; + +extern rl_voidfunc_t *rl_redisplay_function; + +extern rl_vintfunc_t *rl_prep_term_function; +extern rl_voidfunc_t *rl_deprep_term_function; /* Dispatch variables. */ extern Keymap rl_executing_keymap; @@ -468,6 +548,18 @@ extern Keymap rl_binding_keymap; rl_newline. */ extern int rl_erase_empty_line; +/* If non-zero, the application has already printed the prompt (rl_prompt) + before calling readline, so readline should not output it the first time + redisplay is done. */ +extern int rl_already_prompted; + +/* A non-zero value means to read only this many characters rather than + up to a character bound to accept-line. */ +extern int rl_num_chars_to_read; + +/* The text of a currently-executing keyboard macro. */ +extern char *rl_executing_macro; + /* Variables to control readline signal handling. */ /* If non-zero, readline will install its own signal handlers for SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */ @@ -482,9 +574,9 @@ extern int rl_catch_sigwinch; /* Completion variables. */ /* Pointer to the generator function for completion_matches (). - NULL means to use filename_entry_function (), the default filename - completer. */ -extern Function *rl_completion_entry_function; + NULL means to use rl_filename_completion_function (), the default + filename completer. */ +extern rl_compentry_func_t *rl_completion_entry_function; /* If rl_ignore_some_completions_function is non-NULL it is the address of a function to call after all of the possible matches have been @@ -492,7 +584,7 @@ extern Function *rl_completion_entry_function; The function is called with one argument; a NULL terminated array of (char *). If your function removes any of the elements, they must be free()'ed. */ -extern Function *rl_ignore_some_completions_function; +extern rl_compignore_func_t *rl_ignore_some_completions_function; /* Pointer to alternative function to create matches. Function is called with TEXT, START, and END. @@ -501,7 +593,7 @@ extern Function *rl_ignore_some_completions_function; If this function exists and returns NULL then call the value of rl_completion_entry_function to try to match, otherwise use the array of strings returned. */ -extern CPPFunction *rl_attempted_completion_function; +extern rl_completion_func_t *rl_attempted_completion_function; /* The basic list of characters that signal a break between words for the completer routine. The initial contents of this variable is what @@ -517,23 +609,34 @@ extern const char *rl_completer_word_break_characters; Completion occurs on the entire substring, and within the substring rl_completer_word_break_characters are treated as any other character, unless they also appear within this list. */ -extern char *rl_completer_quote_characters; +extern const char *rl_completer_quote_characters; /* List of quote characters which cause a word break. */ extern const char *rl_basic_quote_characters; /* List of characters that need to be quoted in filenames by the completer. */ -extern char *rl_filename_quote_characters; +extern const char *rl_filename_quote_characters; /* List of characters that are word break characters, but should be left in TEXT when it is passed to the completion function. The shell uses this to help determine what kind of completing to do. */ -extern char *rl_special_prefixes; +extern const char *rl_special_prefixes; /* If non-zero, then this is the address of a function to call when completing on a directory name. The function is called with - the address of a string (the current directory name) as an arg. */ -extern Function *rl_directory_completion_hook; + the address of a string (the current directory name) as an arg. It + changes what is displayed when the possible completions are printed + or inserted. */ +extern rl_icppfunc_t *rl_directory_completion_hook; + +/* If non-zero, this is the address of a function to call when completing + a directory name. This function takes the address of the directory name + to be modified as an argument. Unlike rl_directory_completion_hook, it + only modifies the directory name used in opendir(2), not what is displayed + when the possible completions are printed or inserted. It is called + before rl_directory_completion_hook. I'm not happy with how this works + yet, so it's undocumented. */ +extern rl_icppfunc_t *rl_directory_rewrite_hook; /* Backwards compatibility with previous versions of readline. */ #define rl_symbolic_link_hook rl_directory_completion_hook @@ -545,7 +648,7 @@ extern Function *rl_directory_completion_hook; where MATCHES is the array of strings that matched, NUM_MATCHES is the number of strings in that array, and MAX_LENGTH is the length of the longest string in that array. */ -extern VFunction *rl_completion_display_matches_hook; +extern rl_compdisp_func_t *rl_completion_display_matches_hook; /* Non-zero means that the results of the matches are to be treated as filenames. This is ALWAYS zero on entry, and can only be changed @@ -563,17 +666,17 @@ extern int rl_filename_quoting_desired; Called with the text to quote, the type of match found (single or multiple) and a pointer to the quoting character to be used, which the function can reset if desired. */ -extern CPFunction *rl_filename_quoting_function; +extern rl_quote_func_t *rl_filename_quoting_function; /* Function to call to remove quoting characters from a filename. Called before completion is attempted, so the embedded quotes do not interfere with matching names in the file system. */ -extern CPFunction *rl_filename_dequoting_function; +extern rl_dequote_func_t *rl_filename_dequoting_function; /* Function to call to decide whether or not a word break character is quoted. If a character is quoted, it does not break words for the completer. */ -extern Function *rl_char_is_quoted_p; +extern rl_linebuf_func_t *rl_char_is_quoted_p; /* Non-zero means to suppress normal filename completion after the user-specified completion function has been called. */ @@ -588,11 +691,26 @@ extern int rl_completion_type; default is a space. Nothing is added if this is '\0'. */ extern int rl_completion_append_character; +/* If set to non-zero by an application completion function, + rl_completion_append_character will not be appended. */ +extern int rl_completion_suppress_append; + /* Up to this many items will be displayed in response to a possible-completions call. After that, we ask the user if she is sure she wants to see them all. The default value is 100. */ extern int rl_completion_query_items; +/* If non-zero, a slash will be appended to completed filenames that are + symbolic links to directory names, subject to the value of the + mark-directories variable (which is user-settable). This exists so + that application completion functions can override the user's preference + (set via the mark-symlinked-directories variable) if appropriate. + It's set to the value of _rl_complete_mark_symlink_dirs in + rl_complete_internal before any application-specific completion + function is called, so without that function doing anything, the user's + preferences are honored. */ +extern int rl_completion_mark_symlink_dirs; + /* If non-zero, then disallow duplicates in the matches. */ extern int rl_ignore_completion_duplicates; @@ -610,9 +728,69 @@ extern int rl_inhibit_completion; #define SINGLE_MATCH 1 #define MULT_MATCH 2 -#if !defined (savestring) -extern char *savestring (); /* XXX backwards compatibility */ -#endif +/* Possible state values for rl_readline_state */ +#define RL_STATE_NONE 0x00000 /* no state; before first call */ + +#define RL_STATE_INITIALIZING 0x00001 /* initializing */ +#define RL_STATE_INITIALIZED 0x00002 /* initialization done */ +#define RL_STATE_TERMPREPPED 0x00004 /* terminal is prepped */ +#define RL_STATE_READCMD 0x00008 /* reading a command key */ +#define RL_STATE_METANEXT 0x00010 /* reading input after ESC */ +#define RL_STATE_DISPATCHING 0x00020 /* dispatching to a command */ +#define RL_STATE_MOREINPUT 0x00040 /* reading more input in a command function */ +#define RL_STATE_ISEARCH 0x00080 /* doing incremental search */ +#define RL_STATE_NSEARCH 0x00100 /* doing non-inc search */ +#define RL_STATE_SEARCH 0x00200 /* doing a history search */ +#define RL_STATE_NUMERICARG 0x00400 /* reading numeric argument */ +#define RL_STATE_MACROINPUT 0x00800 /* getting input from a macro */ +#define RL_STATE_MACRODEF 0x01000 /* defining keyboard macro */ +#define RL_STATE_OVERWRITE 0x02000 /* overwrite mode */ +#define RL_STATE_COMPLETING 0x04000 /* doing completion */ +#define RL_STATE_SIGHANDLER 0x08000 /* in readline sighandler */ +#define RL_STATE_UNDOING 0x10000 /* doing an undo */ +#define RL_STATE_INPUTPENDING 0x20000 /* rl_execute_next called */ + +#define RL_STATE_DONE 0x80000 /* done; accepted line */ + +#define RL_SETSTATE(x) (rl_readline_state |= (x)) +#define RL_UNSETSTATE(x) (rl_readline_state &= ~(x)) +#define RL_ISSTATE(x) (rl_readline_state & (x)) + +struct readline_state { + /* line state */ + int point; + int end; + int mark; + char *buffer; + int buflen; + UNDO_LIST *ul; + char *prompt; + + /* global state */ + int rlstate; + int done; + Keymap kmap; + + /* input state */ + rl_command_func_t *lastfunc; + int insmode; + int edmode; + int kseqlen; + FILE *inf; + FILE *outf; + int pendingin; + char *macro; + + /* signal state */ + int catchsigs; + int catchsigwinch; + + /* reserved for future expansion, so the struct size doesn't change */ + char reserved[64]; +}; + +extern int rl_save_state PARAMS((struct readline_state *)); +extern int rl_restore_state PARAMS((struct readline_state *)); #ifdef __cplusplus } diff --git a/readline/rlconf.h b/readline/rlconf.h index 1356fd87924..c651fd8b41f 100644 --- a/readline/rlconf.h +++ b/readline/rlconf.h @@ -8,7 +8,7 @@ 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 1, or (at your option) + 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 @@ -19,7 +19,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #if !defined (_RLCONF_H_) #define _RLCONF_H_ @@ -30,10 +30,6 @@ /* Define this to get an indication of file type when listing completions. */ #define VISIBLE_STATS -/* If defined, readline shows opening parens and braces when closing - paren or brace entered. */ -/* #define PAREN_MATCHING */ - /* This definition is needed by readline.c, rltty.c, and signals.c. */ /* If on, then readline handles signals in a way that doesn't screw. */ #define HANDLE_SIGNALS @@ -58,4 +54,7 @@ X `callback' style. */ #define READLINE_CALLBACKS +/* Define this if you want the cursor to indicate insert or overwrite mode. */ +/* #define CURSOR_MODE */ + #endif /* _RLCONF_H_ */ diff --git a/readline/rldefs.h b/readline/rldefs.h index d4aced43e2a..4a28bd1e49c 100644 --- a/readline/rldefs.h +++ b/readline/rldefs.h @@ -10,7 +10,7 @@ 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 1, or (at your option) + 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 @@ -21,7 +21,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #if !defined (_RLDEFS_H_) #define _RLDEFS_H_ @@ -30,6 +30,8 @@ # include "config.h" #endif +#include "rlstdc.h" + #if defined (_POSIX_VERSION) && !defined (TERMIOS_MISSING) # define TERMIOS_TTY_DRIVER #else @@ -71,7 +73,14 @@ extern char *strchr (), *strrchr (); #define _rl_stricmp strcasecmp #define _rl_strnicmp strncasecmp #else -extern int _rl_stricmp (), _rl_strnicmp (); +extern int _rl_stricmp PARAMS((char *, char *)); +extern int _rl_strnicmp PARAMS((char *, char *, int)); +#endif + +#if defined (HAVE_STRPBRK) +# define _rl_strpbrk(a,b) strpbrk((a),(b)) +#else +extern char *_rl_strpbrk PARAMS((const char *, const char *)); #endif #if !defined (emacs_mode) @@ -80,6 +89,13 @@ extern int _rl_stricmp (), _rl_strnicmp (); # define emacs_mode 1 #endif +#if !defined (RL_IM_INSERT) +# define RL_IM_INSERT 1 +# define RL_IM_OVERWRITE 0 +# +# define RL_IM_DEFAULT RL_IM_INSERT +#endif + /* If you cast map[key].function to type (Keymap) on a Cray, the compiler takes the value of map[key].function and divides it by 4 to convert between pointer types (pointers @@ -87,15 +103,14 @@ extern int _rl_stricmp (), _rl_strnicmp (); This is not what is wanted. */ #if defined (CRAY) # define FUNCTION_TO_KEYMAP(map, key) (Keymap)((int)map[key].function) -# define KEYMAP_TO_FUNCTION(data) (Function *)((int)(data)) +# define KEYMAP_TO_FUNCTION(data) (rl_command_func_t *)((int)(data)) #else # define FUNCTION_TO_KEYMAP(map, key) (Keymap)(map[key].function) -# define KEYMAP_TO_FUNCTION(data) (Function *)(data) +# define KEYMAP_TO_FUNCTION(data) (rl_command_func_t *)(data) #endif #ifndef savestring -extern char *xmalloc (); -#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x)) +#define savestring(x) strcpy ((char *)xmalloc (1 + strlen (x)), (x)) #endif /* Possible values for _rl_bell_preference. */ @@ -113,22 +128,28 @@ extern char *xmalloc (); /* Possible values for the found_quote flags word used by the completion functions. It says what kind of (shell-like) quoting we found anywhere in the line. */ -#define RL_QF_SINGLE_QUOTE 0x1 -#define RL_QF_DOUBLE_QUOTE 0x2 -#define RL_QF_BACKSLASH 0x4 +#define RL_QF_SINGLE_QUOTE 0x01 +#define RL_QF_DOUBLE_QUOTE 0x02 +#define RL_QF_BACKSLASH 0x04 +#define RL_QF_OTHER_QUOTE 0x08 /* Default readline line buffer length. */ #define DEFAULT_BUFFER_SIZE 256 #if !defined (STREQ) #define STREQ(a, b) (((a)[0] == (b)[0]) && (strcmp ((a), (b)) == 0)) -#define STREQN(a, b, n) (((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0)) +#define STREQN(a, b, n) (((n) == 0) ? (1) \ + : ((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0)) #endif #if !defined (FREE) # define FREE(x) if (x) free (x) #endif +#if !defined (SWAP) +# define SWAP(s, e) do { int t; t = s; s = e; e = t; } while (0) +#endif + /* CONFIGURATION SECTION */ #include "rlconf.h" diff --git a/readline/rlmbutil.h b/readline/rlmbutil.h new file mode 100644 index 00000000000..27ca32bfc7d --- /dev/null +++ b/readline/rlmbutil.h @@ -0,0 +1,108 @@ +/* rlmbutil.h -- utility functions for multibyte characters. */ + +/* Copyright (C) 2001 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_MBUTIL_H_) +#define _RL_MBUTIL_H_ + +#include "rlstdc.h" + +/************************************************/ +/* check multibyte capability for I18N code */ +/************************************************/ + +/* For platforms which support the ISO C amendement 1 functionality we + support user defined character classes. */ + /* Solaris 2.5 has a bug: must be included before . */ +#if defined (HAVE_WCTYPE_H) && defined (HAVE_WCHAR_H) +# include +# include +# if defined (HAVE_MBSRTOWCS) /* system is supposed to support XPG5 */ +# define HANDLE_MULTIBYTE 1 +# endif +#endif + +/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */ +#if HANDLE_MULTIBYTE && !defined (HAVE_MBSTATE_T) +# define wcsrtombs(dest, src, len, ps) (wcsrtombs) (dest, src, len, 0) +# define mbsrtowcs(dest, src, len, ps) (mbsrtowcs) (dest, src, len, 0) +# define wcrtomb(s, wc, ps) (wcrtomb) (s, wc, 0) +# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0) +# define mbrlen(s, n, ps) (mbrlen) (s, n, 0) +# define mbstate_t int +#endif + +/* Make sure MB_LEN_MAX is at least 16 on systems that claim to be able to + handle multibyte chars (some systems define MB_LEN_MAX as 1) */ +#ifdef HANDLE_MULTIBYTE +# include +# if defined(MB_LEN_MAX) && (MB_LEN_MAX < 16) +# undef MB_LEN_MAX +# endif +# if !defined (MB_LEN_MAX) +# define MB_LEN_MAX 16 +# endif +#endif + +/************************************************/ +/* end of multibyte capability checks for I18N */ +/************************************************/ + +/* + * Flags for _rl_find_prev_mbchar and _rl_find_next_mbchar: + * + * MB_FIND_ANY find any multibyte character + * MB_FIND_NONZERO find a non-zero-width multibyte character + */ + +#define MB_FIND_ANY 0x00 +#define MB_FIND_NONZERO 0x01 + +extern int _rl_find_prev_mbchar PARAMS((char *, int, int)); +extern int _rl_find_next_mbchar PARAMS((char *, int, int, int)); + +#ifdef HANDLE_MULTIBYTE + +extern int _rl_compare_chars PARAMS((char *, int, mbstate_t *, char *, int, mbstate_t *)); +extern int _rl_get_char_len PARAMS((char *, mbstate_t *)); +extern int _rl_adjust_point PARAMS((char *, int, mbstate_t *)); + +extern int _rl_read_mbchar PARAMS((char *, int)); +extern int _rl_read_mbstring PARAMS((int, char *, int)); + +extern int _rl_is_mbchar_matched PARAMS((char *, int, int, char *, int)); + +#else /* !HANDLE_MULTIBYTE */ + +#undef MB_LEN_MAX +#undef MB_CUR_MAX + +#define MB_LEN_MAX 1 +#define MB_CUR_MAX 1 + +#define _rl_find_prev_mbchar(b, i, f) (((i) == 0) ? (i) : ((i) - 1)) +#define _rl_find_next_mbchar(b, i1, i2, f) ((i1) + (i2)) + +#endif /* !HANDLE_MULTIBYTE */ + +extern int rl_byte_oriented; + +#endif /* _RL_MBUTIL_H_ */ diff --git a/readline/rlprivate.h b/readline/rlprivate.h new file mode 100644 index 00000000000..78bee107dcd --- /dev/null +++ b/readline/rlprivate.h @@ -0,0 +1,284 @@ +/* rlprivate.h -- functions and variables global to the readline library, + but not intended for use by applications. */ + +/* Copyright (C) 1999 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 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; + +/* 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((unsigned 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)); + +#endif /* READLINE_CALLBACKS */ + +/* bind.c */ +extern void _rl_bind_if_unbound PARAMS((const char *, rl_command_func_t *)); + +/* 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)); + +/* 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_init_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)); + +/* rltty.c */ +extern int _rl_disable_tty_signals PARAMS((void)); +extern int _rl_restore_tty_signals PARAMS((void)); + +/* 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[]; + +/* complete.c */ +extern int _rl_complete_show_all; +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 char *rl_display_prompt; + +/* isearch.c */ +extern char *_rl_isearch_terminators; + +/* macro.c */ +extern char *_rl_executing_macro; + +/* misc.c */ +extern int _rl_history_preserve_point; +extern int _rl_history_saved_point; + +/* 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 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; + +/* 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; + +#endif /* _RL_PRIVATE_H_ */ diff --git a/readline/rlshell.h b/readline/rlshell.h new file mode 100644 index 00000000000..3c03fbad576 --- /dev/null +++ b/readline/rlshell.h @@ -0,0 +1,34 @@ +/* rlshell.h -- utility functions normally provided by bash. */ + +/* Copyright (C) 1999 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_SHELL_H_) +#define _RL_SHELL_H_ + +#include "rlstdc.h" + +extern char *sh_single_quote PARAMS((char *)); +extern void sh_set_lines_and_columns PARAMS((int, int)); +extern char *sh_get_env_value PARAMS((const char *)); +extern char *sh_get_home_dir PARAMS((void)); +extern int sh_unset_nodelay_mode PARAMS((int)); + +#endif /* _RL_SHELL_H_ */ diff --git a/readline/rlstdc.h b/readline/rlstdc.h index f79cf89fe76..d6a22b3742c 100644 --- a/readline/rlstdc.h +++ b/readline/rlstdc.h @@ -7,7 +7,7 @@ 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) + 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 @@ -17,7 +17,7 @@ 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. */ + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #if !defined (_RL_STDC_H_) #define _RL_STDC_H_ @@ -26,58 +26,20 @@ /* A function can be defined using prototypes and compile on both ANSI C and traditional C compilers with something like this: - extern char *func __P((char *, char *, int)); */ + extern char *func PARAMS((char *, char *, int)); */ -#if defined (__STDC__) || defined(__cplusplus) +#if !defined (PARAMS) +# if defined (__STDC__) || defined (__GNUC__) || defined (__cplusplus) +# define PARAMS(protos) protos +# else +# define PARAMS(protos) () +# endif +#endif -# if !defined (__P) -# define __P(protos) protos +#ifndef __attribute__ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ +# define __attribute__(x) # endif -# define __STRING(x) #x - -# if !defined (__GNUC__) && !defined(__cplusplus) && !defined(inline) -# define inline -# endif - -#else /* !__STDC__ */ - -# if !defined (__P) -# define __P(protos) () -# endif -# define __STRING(x) "x" - -#if defined (__GNUC__) /* gcc with -traditional */ -# if !defined (const) -# define const __const -# endif -# if !defined (inline) -# define inline __inline -# endif -# if !defined (signed) -# define signed __signed -# endif -# if !defined (volatile) -# define volatile __volatile -# endif -#else /* !__GNUC__ */ -# if !defined (const) -# define const -# endif -# if !defined (inline) -# define inline -# endif -# if !defined (signed) -# define signed -# endif -# if !defined (volatile) -# define volatile -# endif -#endif /* !__GNUC__ */ - -#endif /* !__STDC__ */ - -#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8) -#define __attribute__(A) #endif #endif /* !_RL_STDC_H_ */ diff --git a/readline/rltty.c b/readline/rltty.c index f87c1c9747f..09702e9e755 100644 --- a/readline/rltty.c +++ b/readline/rltty.c @@ -8,7 +8,7 @@ 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 1, or + 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 @@ -19,7 +19,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) @@ -43,28 +43,19 @@ #include "rltty.h" #include "readline.h" +#include "rlprivate.h" #if !defined (errno) extern int errno; #endif /* !errno */ -extern int readline_echoing_p; -extern int _rl_eof_char; +rl_vintfunc_t *rl_prep_term_function = rl_prep_terminal; +rl_voidfunc_t *rl_deprep_term_function = rl_deprep_terminal; -extern int _rl_enable_keypad, _rl_enable_meta; +static void block_sigint PARAMS((void)); +static void release_sigint PARAMS((void)); -extern void _rl_control_keypad (); - -#if defined (__GO32__) -# include -# undef HANDLE_SIGNALS -#endif /* __GO32__ */ - -/* Indirect functions to allow apps control over terminal management. */ -extern void rl_prep_terminal (), rl_deprep_terminal (); - -VFunction *rl_prep_term_function = rl_prep_terminal; -VFunction *rl_deprep_term_function = rl_deprep_terminal; +static void set_winsize PARAMS((int)); /* **************************************************************** */ /* */ @@ -104,6 +95,7 @@ block_sigint () # endif /* HAVE_USG_SIGHOLD */ # endif /* !HAVE_BSD_SIGNALS */ #endif /* !HAVE_POSIX_SIGNALS */ + sigint_blocked = 1; } @@ -111,7 +103,7 @@ block_sigint () static void release_sigint () { - if (!sigint_blocked) + if (sigint_blocked == 0) return; #if defined (HAVE_POSIX_SIGNALS) @@ -138,32 +130,27 @@ release_sigint () /* Non-zero means that the terminal is in a prepped state. */ static int terminal_prepped; +static _RL_TTY_CHARS _rl_tty_chars, _rl_last_tty_chars; + /* If non-zero, means that this process has called tcflow(fd, TCOOFF) and output is suspended. */ #if defined (__ksr1__) static int ksrflow; #endif -#if defined (TIOCGWINSZ) /* Dummy call to force a backgrounded readline to stop before it tries to get the tty settings. */ static void set_winsize (tty) int tty; { +#if defined (TIOCGWINSZ) struct winsize w; if (ioctl (tty, TIOCGWINSZ, &w) == 0) (void) ioctl (tty, TIOCSWINSZ, &w); -} -#else -static void -set_winsize (tty) - int tty; -{ -// dummy function, required by other code. What should be doing? -} #endif /* TIOCGWINSZ */ +} #if defined (NEW_TTY_DRIVER) @@ -191,6 +178,50 @@ struct bsdtty { static TIOTYPE otio; +static void save_tty_chars PARAMS((TIOTYPE *)); +static int _get_tty_settings PARAMS((int, TIOTYPE *)); +static int get_tty_settings PARAMS((int, TIOTYPE *)); +static int _set_tty_settings PARAMS((int, TIOTYPE *)); +static int set_tty_settings PARAMS((int, TIOTYPE *)); + +static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *)); + +static void +save_tty_chars (tiop) + TIOTYPE *tiop; +{ + _rl_last_tty_chars = _rl_tty_chars; + + if (tiop->flags & SGTTY_SET) + { + _rl_tty_chars.t_erase = tiop->sgttyb.sg_erase; + _rl_tty_chars.t_kill = tiop->sgttyb.sg_kill; + } + + if (tiop->flags & TCHARS_SET) + { + _rl_tty_chars.t_intr = tiop->tchars.t_intrc; + _rl_tty_chars.t_quit = tiop->tchars.t_quitc; + _rl_tty_chars.t_start = tiop->tchars.t_startc; + _rl_tty_chars.t_stop = tiop->tchars.t_stopc; + _rl_tty_chars.t_eof = tiop->tchars.t_eofc; + _rl_tty_chars.t_eol = '\n'; + _rl_tty_chars.t_eol2 = tiop->tchars.t_brkc; + } + + if (tiop->flags & LTCHARS_SET) + { + _rl_tty_chars.t_susp = tiop->ltchars.t_suspc; + _rl_tty_chars.t_dsusp = tiop->ltchars.t_dsuspc; + _rl_tty_chars.t_reprint = tiop->ltchars.t_rprntc; + _rl_tty_chars.t_flush = tiop->ltchars.t_flushc; + _rl_tty_chars.t_werase = tiop->ltchars.t_werasc; + _rl_tty_chars.t_lnext = tiop->ltchars.t_lnextc; + } + + _rl_tty_chars.t_status = -1; +} + static int get_tty_settings (tty, tiop) int tty; @@ -200,22 +231,23 @@ get_tty_settings (tty, tiop) tiop->flags = tiop->lflag = 0; - ioctl (tty, TIOCGETP, &(tiop->sgttyb)); + if (ioctl (tty, TIOCGETP, &(tiop->sgttyb)) < 0) + return -1; tiop->flags |= SGTTY_SET; #if defined (TIOCLGET) - ioctl (tty, TIOCLGET, &(tiop->lflag)); - tiop->flags |= LFLAG_SET; + if (ioctl (tty, TIOCLGET, &(tiop->lflag)) == 0) + tiop->flags |= LFLAG_SET; #endif #if defined (TIOCGETC) - ioctl (tty, TIOCGETC, &(tiop->tchars)); - tiop->flags |= TCHARS_SET; + if (ioctl (tty, TIOCGETC, &(tiop->tchars)) == 0) + tiop->flags |= TCHARS_SET; #endif #if defined (TIOCGLTC) - ioctl (tty, TIOCGLTC, &(tiop->ltchars)); - tiop->flags |= LTCHARS_SET; + if (ioctl (tty, TIOCGLTC, &(tiop->ltchars)) == 0) + tiop->flags |= LTCHARS_SET; #endif return 0; @@ -261,24 +293,23 @@ set_tty_settings (tty, tiop) } static void -prepare_terminal_settings (meta_flag, otio, tiop) +prepare_terminal_settings (meta_flag, oldtio, tiop) int meta_flag; - TIOTYPE otio, *tiop; + TIOTYPE oldtio, *tiop; { -#if !defined (__GO32__) - readline_echoing_p = (otio.sgttyb.sg_flags & ECHO); + readline_echoing_p = (oldtio.sgttyb.sg_flags & ECHO); /* Copy the original settings to the structure we're going to use for our settings. */ - tiop->sgttyb = otio.sgttyb; - tiop->lflag = otio.lflag; + tiop->sgttyb = oldtio.sgttyb; + tiop->lflag = oldtio.lflag; #if defined (TIOCGETC) - tiop->tchars = otio.tchars; + tiop->tchars = oldtio.tchars; #endif #if defined (TIOCGLTC) - tiop->ltchars = otio.ltchars; + tiop->ltchars = oldtio.ltchars; #endif - tiop->flags = otio.flags; + tiop->flags = oldtio.flags; /* First, the basic settings to put us into character-at-a-time, no-echo input mode. */ @@ -291,8 +322,8 @@ prepare_terminal_settings (meta_flag, otio, tiop) #if !defined (ANYP) # define ANYP (EVENP | ODDP) #endif - if (((otio.sgttyb.sg_flags & ANYP) == ANYP) || - ((otio.sgttyb.sg_flags & ANYP) == 0)) + if (((oldtio.sgttyb.sg_flags & ANYP) == ANYP) || + ((oldtio.sgttyb.sg_flags & ANYP) == 0)) { tiop->sgttyb.sg_flags |= ANYP; @@ -311,13 +342,13 @@ prepare_terminal_settings (meta_flag, otio, tiop) tiop->tchars.t_startc = -1; /* C-q */ /* If there is an XON character, bind it to restart the output. */ - if (otio.tchars.t_startc != -1) - rl_bind_key (otio.tchars.t_startc, rl_restart_output); + if (oldtio.tchars.t_startc != -1) + rl_bind_key (oldtio.tchars.t_startc, rl_restart_output); # endif /* USE_XON_XOFF */ /* If there is an EOF char, bind _rl_eof_char to it. */ - if (otio.tchars.t_eofc != -1) - _rl_eof_char = otio.tchars.t_eofc; + if (oldtio.tchars.t_eofc != -1) + _rl_eof_char = oldtio.tchars.t_eofc; # if defined (NO_KILL_INTR) /* Get rid of terminal-generated SIGQUIT and SIGINT. */ @@ -331,7 +362,6 @@ prepare_terminal_settings (meta_flag, otio, tiop) tiop->ltchars.t_dsuspc = -1; /* C-y */ tiop->ltchars.t_lnextc = -1; /* C-v */ #endif /* TIOCGLTC */ -#endif /* !__GO32__ */ } #else /* !defined (NEW_TTY_DRIVER) */ @@ -357,18 +387,71 @@ prepare_terminal_settings (meta_flag, otio, tiop) # define TIOTYPE struct termio # define DRAIN_OUTPUT(fd) # define GETATTR(tty, tiop) (ioctl (tty, TCGETA, tiop)) -# define SETATTR(tty, tiop) (ioctl (tty, TCSETA, tiop)) +# define SETATTR(tty, tiop) (ioctl (tty, TCSETAW, tiop)) #endif /* !TERMIOS_TTY_DRIVER */ static TIOTYPE otio; +static void save_tty_chars PARAMS((TIOTYPE *)); +static int _get_tty_settings PARAMS((int, TIOTYPE *)); +static int get_tty_settings PARAMS((int, TIOTYPE *)); +static int _set_tty_settings PARAMS((int, TIOTYPE *)); +static int set_tty_settings PARAMS((int, TIOTYPE *)); + +static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *)); + #if defined (FLUSHO) # define OUTPUT_BEING_FLUSHED(tp) (tp->c_lflag & FLUSHO) #else # define OUTPUT_BEING_FLUSHED(tp) 0 #endif -#if defined (_AIX) || (defined (FLUSHO) && defined (_AIX41)) +static void +save_tty_chars (tiop) + TIOTYPE *tiop; +{ + _rl_last_tty_chars = _rl_tty_chars; + + _rl_tty_chars.t_eof = tiop->c_cc[VEOF]; + _rl_tty_chars.t_eol = tiop->c_cc[VEOL]; +#ifdef VEOL2 + _rl_tty_chars.t_eol2 = tiop->c_cc[VEOL2]; +#endif + _rl_tty_chars.t_erase = tiop->c_cc[VERASE]; +#ifdef VWERASE + _rl_tty_chars.t_werase = tiop->c_cc[VWERASE]; +#endif + _rl_tty_chars.t_kill = tiop->c_cc[VKILL]; +#ifdef VREPRINT + _rl_tty_chars.t_reprint = tiop->c_cc[VREPRINT]; +#endif + _rl_tty_chars.t_intr = tiop->c_cc[VINTR]; + _rl_tty_chars.t_quit = tiop->c_cc[VQUIT]; +#ifdef VSUSP + _rl_tty_chars.t_susp = tiop->c_cc[VSUSP]; +#endif +#ifdef VDSUSP + _rl_tty_chars.t_dsusp = tiop->c_cc[VDSUSP]; +#endif +#ifdef VSTART + _rl_tty_chars.t_start = tiop->c_cc[VSTART]; +#endif +#ifdef VSTOP + _rl_tty_chars.t_stop = tiop->c_cc[VSTOP]; +#endif +#ifdef VLNEXT + _rl_tty_chars.t_lnext = tiop->c_cc[VLNEXT]; +#endif +#ifdef VDISCARD + _rl_tty_chars.t_flush = tiop->c_cc[VDISCARD]; +#endif +#ifdef VSTATUS + _rl_tty_chars.t_status = tiop->c_cc[VSTATUS]; +#endif +} + +#if defined (_AIX) || defined (_AIX41) +/* Currently this is only used on AIX */ static void rltty_warning (msg) char *msg; @@ -377,7 +460,6 @@ rltty_warning (msg) } #endif - #if defined (_AIX) void setopost(tp) @@ -392,14 +474,12 @@ TIOTYPE *tp; #endif static int -get_tty_settings (tty, tiop) +_get_tty_settings (tty, tiop) int tty; TIOTYPE *tiop; { int ioctl_ret; - set_winsize (tty); - while (1) { ioctl_ret = GETATTR (tty, tiop); @@ -423,6 +503,19 @@ get_tty_settings (tty, tiop) break; } + return 0; +} + +static int +get_tty_settings (tty, tiop) + int tty; + TIOTYPE *tiop; +{ + set_winsize (tty); + + if (_get_tty_settings (tty, tiop) < 0) + return -1; + #if defined (_AIX) setopost(tiop); #endif @@ -431,7 +524,7 @@ get_tty_settings (tty, tiop) } static int -set_tty_settings (tty, tiop) +_set_tty_settings (tty, tiop) int tty; TIOTYPE *tiop; { @@ -441,7 +534,17 @@ set_tty_settings (tty, tiop) return -1; errno = 0; } + return 0; +} +static int +set_tty_settings (tty, tiop) + int tty; + TIOTYPE *tiop; +{ + if (_set_tty_settings (tty, tiop) < 0) + return -1; + #if 0 #if defined (TERMIOS_TTY_DRIVER) @@ -458,22 +561,22 @@ set_tty_settings (tty, tiop) ioctl (tty, TCXONC, 1); /* Simulate a ^Q. */ #endif /* !TERMIOS_TTY_DRIVER */ -#endif +#endif /* 0 */ return 0; } static void -prepare_terminal_settings (meta_flag, otio, tiop) +prepare_terminal_settings (meta_flag, oldtio, tiop) int meta_flag; - TIOTYPE otio, *tiop; + TIOTYPE oldtio, *tiop; { - readline_echoing_p = (otio.c_lflag & ECHO); + readline_echoing_p = (oldtio.c_lflag & ECHO); tiop->c_lflag &= ~(ICANON | ECHO); - if ((unsigned char) otio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE) - _rl_eof_char = otio.c_cc[VEOF]; + if ((unsigned char) oldtio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE) + _rl_eof_char = oldtio.c_cc[VEOF]; #if defined (USE_XON_XOFF) #if defined (IXANY) @@ -504,7 +607,7 @@ prepare_terminal_settings (meta_flag, otio, tiop) if (OUTPUT_BEING_FLUSHED (tiop)) { tiop->c_lflag &= ~FLUSHO; - otio.c_lflag &= ~FLUSHO; + oldtio.c_lflag &= ~FLUSHO; } #endif @@ -530,7 +633,6 @@ void rl_prep_terminal (meta_flag) int meta_flag; { -#if !defined (__GO32__) int tty; TIOTYPE tio; @@ -550,6 +652,8 @@ rl_prep_terminal (meta_flag) otio = tio; + save_tty_chars (&otio); + prepare_terminal_settings (meta_flag, otio, &tio); if (set_tty_settings (tty, &tio) < 0) @@ -563,16 +667,15 @@ rl_prep_terminal (meta_flag) fflush (rl_outstream); terminal_prepped = 1; + RL_SETSTATE(RL_STATE_TERMPREPPED); release_sigint (); -#endif /* !__GO32__ */ } /* Restore the terminal's normal settings and modes. */ void rl_deprep_terminal () { -#if !defined (__GO32__) int tty; if (!terminal_prepped) @@ -595,9 +698,9 @@ rl_deprep_terminal () } terminal_prepped = 0; + RL_UNSETSTATE(RL_STATE_TERMPREPPED); release_sigint (); -#endif /* !__GO32__ */ } /* **************************************************************** */ @@ -607,8 +710,8 @@ rl_deprep_terminal () /* **************************************************************** */ int -rl_restart_output (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_restart_output (count, key) + int count __attribute__((unused)), key __attribute__((unused)); { int fildes = fileno (rl_outstream); #if defined (TIOCSTART) @@ -640,8 +743,8 @@ rl_restart_output (int count __attribute__((unused)), } int -rl_stop_output (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_stop_output (count, key) + int count __attribute__((unused)), key __attribute__((unused)); { int fildes = fileno (rl_instream); @@ -672,6 +775,9 @@ rl_stop_output (int count __attribute__((unused)), /* Default Key Bindings */ /* */ /* **************************************************************** */ + +/* Set the system's default editing characters to their readline equivalents + in KMAP. Should be static, now that we have rl_tty_set_default_bindings. */ void rltty_set_default_bindings (kmap) Keymap kmap; @@ -686,8 +792,8 @@ rltty_set_default_bindings (kmap) { \ int ic; \ ic = sc; \ - if (ic != -1 && kmap[ic].type == ISFUNC) \ - kmap[ic].function = func; \ + if (ic != -1 && kmap[(unsigned char)ic].type == ISFUNC) \ + kmap[(unsigned char)ic].function = func; \ } \ while (0) @@ -735,3 +841,71 @@ rltty_set_default_bindings (kmap) } #endif /* !NEW_TTY_DRIVER */ } + +/* New public way to set the system default editing chars to their readline + equivalents. */ +void +rl_tty_set_default_bindings (kmap) + Keymap kmap; +{ + rltty_set_default_bindings (kmap); +} + +#if defined (HANDLE_SIGNALS) + +#if defined (NEW_TTY_DRIVER) +int +_rl_disable_tty_signals () +{ + return 0; +} + +int +_rl_restore_tty_signals () +{ + return 0; +} +#else + +static TIOTYPE sigstty, nosigstty; +static int tty_sigs_disabled = 0; + +int +_rl_disable_tty_signals () +{ + if (tty_sigs_disabled) + return 0; + + if (_get_tty_settings (fileno (rl_instream), &sigstty) < 0) + return -1; + + nosigstty = sigstty; + + nosigstty.c_lflag &= ~ISIG; + nosigstty.c_iflag &= ~IXON; + + if (_set_tty_settings (fileno (rl_instream), &nosigstty) < 0) + return (_set_tty_settings (fileno (rl_instream), &sigstty)); + + tty_sigs_disabled = 1; + return 0; +} + +int +_rl_restore_tty_signals () +{ + int r; + + if (tty_sigs_disabled == 0) + return 0; + + r = _set_tty_settings (fileno (rl_instream), &sigstty); + + if (r == 0) + tty_sigs_disabled = 0; + + return r; +} +#endif /* !NEW_TTY_DRIVER */ + +#endif /* HANDLE_SIGNALS */ diff --git a/readline/rltty.h b/readline/rltty.h index fe783463f6a..029a3fbc0e1 100644 --- a/readline/rltty.h +++ b/readline/rltty.h @@ -8,7 +8,7 @@ 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 1, or (at your option) + 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 @@ -19,10 +19,10 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #if !defined (_RLTTY_H_) -#define _RLTTY_H +#define _RLTTY_H_ /* Posix systems use termios and the Posix signal functions. */ #if defined (TERMIOS_TTY_DRIVER) @@ -60,4 +60,23 @@ # endif /* !_SVR4_DISABLE */ #endif /* !NEW_TTY_DRIVER && !_POSIX_VDISABLE */ +typedef struct _rl_tty_chars { + char t_eof; + char t_eol; + char t_eol2; + char t_erase; + char t_werase; + char t_kill; + char t_reprint; + char t_intr; + char t_quit; + char t_susp; + char t_dsusp; + char t_start; + char t_stop; + char t_lnext; + char t_flush; + char t_status; +} _RL_TTY_CHARS; + #endif /* _RLTTY_H_ */ diff --git a/readline/rltypedefs.h b/readline/rltypedefs.h new file mode 100644 index 00000000000..f3280e9fce0 --- /dev/null +++ b/readline/rltypedefs.h @@ -0,0 +1,88 @@ +/* rltypedefs.h -- Type declarations for readline functions. */ + +/* Copyright (C) 2000 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. */ + +#ifndef _RL_TYPEDEFS_H_ +#define _RL_TYPEDEFS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Old-style */ + +#if !defined (_FUNCTION_DEF) +# define _FUNCTION_DEF + +typedef int Function (); +typedef void VFunction (); +typedef char *CPFunction (); +typedef char **CPPFunction (); + +#endif /* _FUNCTION_DEF */ + +/* New style. */ + +#if !defined (_RL_FUNCTION_TYPEDEF) +# define _RL_FUNCTION_TYPEDEF + +/* Bindable functions */ +typedef int rl_command_func_t PARAMS((int, int)); + +/* Typedefs for the completion system */ +typedef char *rl_compentry_func_t PARAMS((const char *, int)); +typedef char **rl_completion_func_t PARAMS((const char *, int, int)); + +typedef char *rl_quote_func_t PARAMS((char *, int, char *)); +typedef char *rl_dequote_func_t PARAMS((char *, int)); + +typedef int rl_compignore_func_t PARAMS((char **)); + +typedef void rl_compdisp_func_t PARAMS((char **, int, int)); + +/* Type for input and pre-read hook functions like rl_event_hook */ +typedef int rl_hook_func_t PARAMS((void)); + +/* Input function type */ +typedef int rl_getc_func_t PARAMS((FILE *)); + +/* Generic function that takes a character buffer (which could be the readline + line buffer) and an index into it (which could be rl_point) and returns + an int. */ +typedef int rl_linebuf_func_t PARAMS((char *, int)); + +/* `Generic' function pointer typedefs */ +typedef int rl_intfunc_t PARAMS((int)); +#define rl_ivoidfunc_t rl_hook_func_t +typedef int rl_icpfunc_t PARAMS((char *)); +typedef int rl_icppfunc_t PARAMS((char **)); + +typedef void rl_voidfunc_t PARAMS((void)); +typedef void rl_vintfunc_t PARAMS((int)); +typedef void rl_vcpfunc_t PARAMS((char *)); +typedef void rl_vcppfunc_t PARAMS((char **)); +#endif /* _RL_FUNCTION_TYPEDEF */ + +#ifdef __cplusplus +} +#endif + +#endif /* _RL_TYPEDEFS_H_ */ diff --git a/readline/rlwinsize.h b/readline/rlwinsize.h index 92b3de174bf..7838154d023 100644 --- a/readline/rlwinsize.h +++ b/readline/rlwinsize.h @@ -9,7 +9,7 @@ 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 1, or (at your option) + 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 @@ -20,7 +20,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #if !defined (_RLWINSIZE_H_) #define _RLWINSIZE_H_ @@ -55,4 +55,3 @@ #endif /* _RL_WINSIZE_H */ - diff --git a/readline/search.c b/readline/search.c index 0179d8da2f1..ac47596a3f8 100644 --- a/readline/search.c +++ b/readline/search.c @@ -8,7 +8,7 @@ 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 1, or (at your option) + 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 @@ -19,7 +19,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) @@ -40,33 +40,56 @@ #endif #include "rldefs.h" +#include "rlmbutil.h" + #include "readline.h" #include "history.h" +#include "rlprivate.h" +#include "xmalloc.h" + #ifdef abs # undef abs #endif #define abs(x) (((x) >= 0) ? (x) : -(x)) -extern char *xmalloc (), *xrealloc (); - -/* Variables imported from readline.c */ -extern int rl_point, rl_end, rl_line_buffer_len; -extern int rl_editing_mode; -extern char *rl_prompt; -extern char *rl_line_buffer; -extern HIST_ENTRY *saved_line_for_history; -extern Function *rl_last_func; +extern HIST_ENTRY *_rl_saved_line_for_history; /* Functions imported from the rest of the library. */ -extern int _rl_free_history_entry (); -extern char *_rl_make_prompt_for_search (); -extern void rl_extend_line_buffer (); +extern int _rl_free_history_entry PARAMS((HIST_ENTRY *)); static char *noninc_search_string = (char *) NULL; static int noninc_history_pos; + static char *prev_line_found = (char *) NULL; +static int rl_history_search_len; +static int rl_history_search_pos; +static char *history_search_string; +static int history_string_size; + +static void make_history_line_current PARAMS((HIST_ENTRY *)); +static int noninc_search_from_pos PARAMS((char *, int, int)); +static void noninc_dosearch PARAMS((char *, int)); +static void noninc_search PARAMS((int, int)); +static int rl_history_search_internal PARAMS((int, int)); +static void rl_history_search_reinit PARAMS((void)); + +/* Make the data from the history entry ENTRY be the contents of the + current line. This doesn't do anything with rl_point; the caller + must set it. */ +static void +make_history_line_current (entry) + HIST_ENTRY *entry; +{ + rl_replace_line (entry->line, 0); + rl_undo_list = (UNDO_LIST *)entry->data; + + if (_rl_saved_line_for_history) + _rl_free_history_entry (_rl_saved_line_for_history); + _rl_saved_line_for_history = (HIST_ENTRY *)NULL; +} + /* Search the history list for STRING starting at absolute history position POS. If STRING begins with `^', the search must match STRING at the beginning of a history line, otherwise a full substring match is performed @@ -79,13 +102,19 @@ noninc_search_from_pos (string, pos, dir) { int ret, old; - old = where_history (); - history_set_pos (pos); + if (pos < 0) + return -1; + old = where_history (); + if (history_set_pos (pos) == 0) + return -1; + + RL_SETSTATE(RL_STATE_SEARCH); if (*string == '^') ret = history_search_prefix (string + 1, dir); else ret = history_search (string, dir); + RL_UNSETSTATE(RL_STATE_SEARCH); if (ret != -1) ret = where_history (); @@ -102,12 +131,12 @@ noninc_dosearch (string, dir) char *string; int dir; { - int oldpos, pos, line_len; + int oldpos, pos; HIST_ENTRY *entry; if (string == 0 || *string == '\0' || noninc_history_pos < 0) { - ding (); + rl_ding (); return; } @@ -115,10 +144,10 @@ noninc_dosearch (string, dir) if (pos == -1) { /* Search failed, current history position unchanged. */ - maybe_unsave_line (); + rl_maybe_unsave_line (); rl_clear_message (); rl_point = 0; - ding (); + rl_ding (); return; } @@ -132,19 +161,12 @@ noninc_dosearch (string, dir) #endif history_set_pos (oldpos); - line_len = strlen (entry->line); - if (line_len >= rl_line_buffer_len) - rl_extend_line_buffer (line_len); - strcpy (rl_line_buffer, entry->line); + make_history_line_current (entry); - rl_undo_list = (UNDO_LIST *)entry->data; - rl_end = strlen (rl_line_buffer); rl_point = 0; - rl_clear_message (); + rl_mark = rl_end; - if (saved_line_for_history) - _rl_free_history_entry (saved_line_for_history); - saved_line_for_history = (HIST_ENTRY *)NULL; + rl_clear_message (); } /* Search non-interactively through the history list. DIR < 0 means to @@ -157,11 +179,15 @@ noninc_search (dir, pchar) int dir; int pchar; { - int saved_point, c; + int saved_point, saved_mark, c; char *p; +#if defined (HANDLE_MULTIBYTE) + char mb[MB_LEN_MAX]; +#endif - maybe_save_line (); + rl_maybe_save_line (); saved_point = rl_point; + saved_mark = rl_mark; /* Use the line buffer to read the search string. */ rl_line_buffer[0] = 0; @@ -171,23 +197,37 @@ noninc_search (dir, pchar) rl_message (p, 0, 0); free (p); -#define SEARCH_RETURN rl_restore_prompt (); return +#define SEARCH_RETURN rl_restore_prompt (); RL_UNSETSTATE(RL_STATE_NSEARCH); return + RL_SETSTATE(RL_STATE_NSEARCH); /* Read the search string. */ - while ((c = rl_read_key ())) + while (1) { + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + c = _rl_read_mbstring (c, mb, MB_LEN_MAX); +#endif + + if (c == 0) + break; + switch (c) { case CTRL('H'): case RUBOUT: if (rl_point == 0) { - maybe_unsave_line (); + rl_maybe_unsave_line (); rl_clear_message (); rl_point = saved_point; + rl_mark = saved_mark; SEARCH_RETURN; } - rl_rubout (1, c); + _rl_rubout_char (1, c); break; case CTRL('W'): @@ -206,20 +246,28 @@ noninc_search (dir, pchar) case CTRL('C'): case CTRL('G'): - maybe_unsave_line (); + rl_maybe_unsave_line (); rl_clear_message (); rl_point = saved_point; - ding (); + rl_mark = saved_mark; + rl_ding (); SEARCH_RETURN; default: - rl_insert (1, c); +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_insert_text (mb); + else +#endif + _rl_insert_char (1, c); break; } (*rl_redisplay_function) (); } dosearch: + rl_mark = saved_mark; + /* If rl_point == 0, we want to re-use the previous search string and start from the saved history position. If there's no previous search string, punt. */ @@ -227,7 +275,7 @@ noninc_search (dir, pchar) { if (!noninc_search_string) { - ding (); + rl_ding (); SEARCH_RETURN; } } @@ -235,19 +283,20 @@ noninc_search (dir, pchar) { /* We want to start the search from the current history position. */ noninc_history_pos = where_history (); - if (noninc_search_string) - free (noninc_search_string); + FREE (noninc_search_string); noninc_search_string = savestring (rl_line_buffer); } rl_restore_prompt (); noninc_dosearch (noninc_search_string, dir); + RL_UNSETSTATE(RL_STATE_NSEARCH); } /* Search forward through the history list for a string. If the vi-mode code calls this, KEY will be `?'. */ int -rl_noninc_forward_search (int count __attribute__((unused)), int key) +rl_noninc_forward_search (count, key) + int count __attribute__((unused)), key __attribute__((unused)); { noninc_search (1, (key == '?') ? '?' : 0); return 0; @@ -256,7 +305,8 @@ rl_noninc_forward_search (int count __attribute__((unused)), int key) /* Reverse search the history list for a string. If the vi-mode code calls this, KEY will be `/'. */ int -rl_noninc_reverse_search (int count __attribute__((unused)), int key) +rl_noninc_reverse_search (count, key) + int count __attribute__((unused)), key __attribute__((unused)); { noninc_search (-1, (key == '/') ? '/' : 0); return 0; @@ -265,12 +315,12 @@ rl_noninc_reverse_search (int count __attribute__((unused)), int key) /* Search forward through the history list for the last string searched for. If there is no saved search string, abort. */ int -rl_noninc_forward_search_again (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_noninc_forward_search_again (count, key) + int count __attribute__((unused)), key __attribute__((unused)); { if (!noninc_search_string) { - ding (); + rl_ding (); return (-1); } noninc_dosearch (noninc_search_string, 1); @@ -280,12 +330,12 @@ rl_noninc_forward_search_again (int count __attribute__((unused)), /* Reverse search in the history list for the last string searched for. If there is no saved search string, abort. */ int -rl_noninc_reverse_search_again (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_noninc_reverse_search_again (count, key) + int count __attribute__((unused)), key __attribute__((unused)); { if (!noninc_search_string) { - ding (); + rl_ding (); return (-1); } noninc_dosearch (noninc_search_string, -1); @@ -293,69 +343,105 @@ rl_noninc_reverse_search_again (int count __attribute__((unused)), } static int -rl_history_search_internal (count, direction) - int count, direction; +rl_history_search_internal (count, dir) + int count, dir; { - HIST_ENTRY *temp, *old_temp; - int line_len; + HIST_ENTRY *temp; + int ret, oldpos; - maybe_save_line (); + rl_maybe_save_line (); + temp = (HIST_ENTRY *)NULL; - temp = old_temp = (HIST_ENTRY *)NULL; + /* Search COUNT times through the history for a line whose prefix + matches history_search_string. When this loop finishes, TEMP, + if non-null, is the history line to copy into the line buffer. */ while (count) { - temp = (direction < 0) ? previous_history () : next_history (); - if (temp == 0) - break; - /* On an empty prefix, make this the same as previous-history. */ - if (rl_point == 0) - { - count--; - continue; - } - if (STREQN (rl_line_buffer, temp->line, rl_point)) - { - /* Don't find multiple instances of the same line. */ - if (prev_line_found && STREQ (prev_line_found, temp->line)) - continue; - if (direction < 0) - old_temp = temp; - prev_line_found = temp->line; - count--; - } + ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir); + if (ret == -1) + break; + + /* Get the history entry we found. */ + rl_history_search_pos = ret; + oldpos = where_history (); + history_set_pos (rl_history_search_pos); + temp = current_history (); + history_set_pos (oldpos); + + /* Don't find multiple instances of the same line. */ + if (prev_line_found && STREQ (prev_line_found, temp->line)) + continue; + prev_line_found = temp->line; + count--; } + /* If we didn't find anything at all, return. */ if (temp == 0) { - if (direction < 0 && old_temp) - temp = old_temp; - else - { - maybe_unsave_line (); - ding (); - return 1; - } + rl_maybe_unsave_line (); + rl_ding (); + /* If you don't want the saved history line (last match) to show up + in the line buffer after the search fails, change the #if 0 to + #if 1 */ +#if 0 + if (rl_point > rl_history_search_len) + { + rl_point = rl_end = rl_history_search_len; + rl_line_buffer[rl_end] = '\0'; + rl_mark = 0; + } +#else + rl_point = rl_history_search_len; /* rl_maybe_unsave_line changes it */ + rl_mark = rl_end; +#endif + return 1; } - line_len = strlen (temp->line); - if (line_len >= rl_line_buffer_len) - rl_extend_line_buffer (line_len); - strcpy (rl_line_buffer, temp->line); - rl_undo_list = (UNDO_LIST *)temp->data; - rl_end = line_len; + /* Copy the line we found into the current line buffer. */ + make_history_line_current (temp); + + rl_point = rl_history_search_len; + rl_mark = rl_end; + return 0; } +static void +rl_history_search_reinit () +{ + rl_history_search_pos = where_history (); + rl_history_search_len = rl_point; + prev_line_found = (char *)NULL; + if (rl_point) + { + if (rl_history_search_len >= history_string_size - 2) + { + history_string_size = rl_history_search_len + 2; + history_search_string = (char *)xrealloc (history_search_string, history_string_size); + } + history_search_string[0] = '^'; + strncpy (history_search_string + 1, rl_line_buffer, rl_point); + history_search_string[rl_point + 1] = '\0'; + } + _rl_free_saved_history_line (); +} + /* Search forward in the history for the string of characters from the start of the line to rl_point. This is a non-incremental search. */ int -rl_history_search_forward (int count, int ignore __attribute__((unused))) +rl_history_search_forward (count, ignore) + int count, ignore; { if (count == 0) return (0); - if (rl_last_func != rl_history_search_forward) - prev_line_found = (char *)NULL; + + if (rl_last_func != rl_history_search_forward && + rl_last_func != rl_history_search_backward) + rl_history_search_reinit (); + + if (rl_history_search_len == 0) + return (rl_get_next_history (count, ignore)); return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1)); } @@ -363,11 +449,17 @@ rl_history_search_forward (int count, int ignore __attribute__((unused))) from the start of the line to rl_point. This is a non-incremental search. */ int -rl_history_search_backward (int count, int ignore __attribute__((unused))) +rl_history_search_backward (count, ignore) + int count, ignore; { if (count == 0) return (0); - if (rl_last_func != rl_history_search_backward) - prev_line_found = (char *)NULL; + + if (rl_last_func != rl_history_search_forward && + rl_last_func != rl_history_search_backward) + rl_history_search_reinit (); + + if (rl_history_search_len == 0) + return (rl_get_previous_history (count, ignore)); return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1)); } diff --git a/readline/shell.c b/readline/shell.c index becd66e0f9a..ad27cc14884 100644 --- a/readline/shell.c +++ b/readline/shell.c @@ -8,7 +8,7 @@ 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 1, or + 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 @@ -19,14 +19,13 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) # include #endif -#include #include #if defined (HAVE_UNISTD_H) @@ -39,36 +38,61 @@ # include "ansi_stdlib.h" #endif /* HAVE_STDLIB_H */ -#if defined (HAVE_STDIO_H) -# include -#endif /* HAVE_STDIO_H */ - #if defined (HAVE_STRING_H) # include #else # include #endif /* !HAVE_STRING_H */ +#if defined (HAVE_LIMITS_H) +# include +#endif + +#include #include +#include + +#include "rlstdc.h" +#include "rlshell.h" +#include "xmalloc.h" + #if !defined (HAVE_GETPW_DECLS) -extern struct passwd *getpwuid (); +extern struct passwd *getpwuid PARAMS((uid_t)); #endif /* !HAVE_GETPW_DECLS */ -extern char *xmalloc (); +#ifndef NULL +# define NULL 0 +#endif + +#ifndef CHAR_BIT +# define CHAR_BIT 8 +#endif + +/* Nonzero if the integer type T is signed. */ +#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) + +/* Bound on length of the string representing an integer value of type T. + Subtract one for the sign bit if T is signed; + 302 / 1000 is log10 (2) rounded up; + add one for integer division truncation; + add one more for a minus sign if t is signed. */ +#define INT_STRLEN_BOUND(t) \ + ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \ + + 1 + TYPE_SIGNED (t)) /* All of these functions are resolved from bash if we are linking readline as part of bash. */ /* Does shell-like quoting using single quotes. */ char * -single_quote (string) +sh_single_quote (string) char *string; { register int c; char *result, *r, *s; - result = (char *)xmalloc (3 + (3 * strlen (string))); + result = (char *)xmalloc (3 + (4 * strlen (string))); r = result; *r++ = '\''; @@ -93,24 +117,24 @@ single_quote (string) /* Set the environment variables LINES and COLUMNS to lines and cols, respectively. */ void -set_lines_and_columns (lines, cols) +sh_set_lines_and_columns (lines, cols) int lines, cols; { char *b; #if defined (HAVE_PUTENV) - b = xmalloc (24); + b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("LINES=") + 1); sprintf (b, "LINES=%d", lines); putenv (b); - b = xmalloc (24); + b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("COLUMNS=") + 1); sprintf (b, "COLUMNS=%d", cols); putenv (b); #else /* !HAVE_PUTENV */ # if defined (HAVE_SETENV) - b = xmalloc (8); + b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1); sprintf (b, "%d", lines); setenv ("LINES", b, 1); - b = xmalloc (8); + b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1); sprintf (b, "%d", cols); setenv ("COLUMNS", b, 1); # endif /* HAVE_SETENV */ @@ -118,14 +142,14 @@ set_lines_and_columns (lines, cols) } char * -get_env_value (varname) - char *varname; +sh_get_env_value (varname) + const char *varname; { return ((char *)getenv (varname)); } char * -get_home_dir () +sh_get_home_dir () { char *home_dir; struct passwd *entry; @@ -136,3 +160,37 @@ get_home_dir () home_dir = entry->pw_dir; return (home_dir); } + +#if !defined (O_NDELAY) +# if defined (FNDELAY) +# define O_NDELAY FNDELAY +# endif +#endif + +int +sh_unset_nodelay_mode (fd) + int fd; +{ + int flags, bflags; + + if ((flags = fcntl (fd, F_GETFL, 0)) < 0) + return -1; + + bflags = 0; + +#ifdef O_NONBLOCK + bflags |= O_NONBLOCK; +#endif + +#ifdef O_NDELAY + bflags |= O_NDELAY; +#endif + + if (flags & bflags) + { + flags &= ~bflags; + return (fcntl (fd, F_SETFL, flags)); + } + + return 0; +} diff --git a/readline/signals.c b/readline/signals.c index 3a34432f143..0a1468b6b2a 100644 --- a/readline/signals.c +++ b/readline/signals.c @@ -7,7 +7,7 @@ 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 1, or + 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 @@ -18,7 +18,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) @@ -40,15 +40,13 @@ # include #endif /* GWINSZ_IN_SYS_IOCTL */ -#if defined (__GO32__) -# undef HANDLE_SIGNALS -#endif /* __GO32__ */ - #if defined (HANDLE_SIGNALS) /* Some standard library routines. */ #include "readline.h" #include "history.h" +#include "rlprivate.h" + #if !defined (RETSIGTYPE) # if defined (VOID_SIGHANDLER) # define RETSIGTYPE void @@ -63,23 +61,20 @@ # define SIGHANDLER_RETURN return (0) #endif -/* This typedef is equivalant to the one for Function; it allows us +/* This typedef is equivalent to the one for Function; it allows us to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */ typedef RETSIGTYPE SigHandler (); -extern int readline_echoing_p; -extern int rl_pending_input; -extern int _rl_meta_flag; +#if defined (HAVE_POSIX_SIGNALS) +typedef struct sigaction sighandler_cxt; +# define rl_sigaction(s, nh, oh) sigaction(s, nh, oh) +#else +typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt; +# define sigemptyset(m) +#endif /* !HAVE_POSIX_SIGNALS */ -extern void free_undo_list (); -extern void _rl_get_screen_size (); -extern void _rl_redisplay_after_sigwinch (); -extern void _rl_clean_up_for_exit (); -extern void _rl_kill_kbd_macro (); -extern void _rl_init_argument (); -extern void rl_deprep_terminal (), rl_prep_terminal (); - -static SigHandler *rl_set_sighandler (); +static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *)); +static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *)); /* Exported variables for use by applications. */ @@ -101,14 +96,6 @@ static int sigwinch_set_flag; /* */ /* **************************************************************** */ -#if defined (HAVE_POSIX_SIGNALS) -typedef struct sigaction sighandler_cxt; -# define rl_sigaction(s, nh, oh) sigaction(s, nh, oh) -#else -typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt; -# define sigemptyset(m) -#endif /* !HAVE_POSIX_SIGNALS */ - static sighandler_cxt old_int, old_term, old_alrm, old_quit; #if defined (SIGTSTP) static sighandler_cxt old_tstp, old_ttou, old_ttin; @@ -133,6 +120,8 @@ rl_signal_handler (sig) # endif /* !HAVE_BSD_SIGNALS */ #endif /* !HAVE_POSIX_SIGNALS */ + RL_SETSTATE(RL_STATE_SIGHANDLER); + #if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS) /* Since the signal will not be blocked while we are in the signal handler, ignore it until rl_clear_signals resets the catcher. */ @@ -165,6 +154,10 @@ rl_signal_handler (sig) # endif /* HAVE_BSD_SIGNALS */ #endif /* !HAVE_POSIX_SIGNALS */ +#if defined (__EMX__) + signal (sig, SIG_ACK); +#endif + kill (getpid (), sig); /* Let the signal that we just sent through. */ @@ -179,6 +172,7 @@ rl_signal_handler (sig) rl_reset_after_signal (); } + RL_UNSETSTATE(RL_STATE_SIGHANDLER); SIGHANDLER_RETURN; } @@ -199,6 +193,7 @@ rl_sigwinch_handler (sig) rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch); #endif + RL_SETSTATE(RL_STATE_SIGHANDLER); rl_resize_terminal (); /* If another sigwinch handler has been installed, call it. */ @@ -206,6 +201,7 @@ rl_sigwinch_handler (sig) if (oh && oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL) (*oh) (sig); + RL_UNSETSTATE(RL_STATE_SIGHANDLER); SIGHANDLER_RETURN; } #endif /* SIGWINCH */ @@ -232,17 +228,25 @@ rl_set_sighandler (sig, handler, ohandler) SigHandler *handler; sighandler_cxt *ohandler; { + sighandler_cxt old_handler; #if defined (HAVE_POSIX_SIGNALS) struct sigaction act; act.sa_handler = handler; - act.sa_flags = 0; + act.sa_flags = 0; /* XXX - should we set SA_RESTART for SIGWINCH? */ sigemptyset (&act.sa_mask); sigemptyset (&ohandler->sa_mask); - sigaction (sig, &act, ohandler); + sigaction (sig, &act, &old_handler); #else - ohandler->sa_handler = (SigHandler *)signal (sig, handler); + old_handler.sa_handler = (SigHandler *)signal (sig, handler); #endif /* !HAVE_POSIX_SIGNALS */ + + /* XXX -- assume we have memcpy */ + /* If rl_set_signals is called twice in a row, don't set the old handler to + rl_signal_handler, because that would cause infinite recursion. */ + if (handler != rl_signal_handler || old_handler.sa_handler != rl_signal_handler) + memcpy (ohandler, &old_handler, sizeof (sighandler_cxt)); + return (ohandler->sa_handler); } @@ -360,7 +364,7 @@ rl_cleanup_after_signal () _rl_clean_up_for_exit (); (*rl_deprep_term_function) (); rl_clear_signals (); - rl_pending_input = 0; + rl_clear_pending_input (); } /* Reset the terminal and readline state after a signal handler returns. */ @@ -380,7 +384,7 @@ rl_free_line_state () { register HIST_ENTRY *entry; - free_undo_list (); + rl_free_undo_list (); entry = current_history (); if (entry) diff --git a/readline/tcap.h b/readline/tcap.h index acb2d76ab48..58ab894d93e 100644 --- a/readline/tcap.h +++ b/readline/tcap.h @@ -8,7 +8,7 @@ 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 1, or (at your option) + 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 @@ -19,7 +19,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #if !defined (_RLTCAP_H_) #define _RLTCAP_H_ diff --git a/readline/terminal.c b/readline/terminal.c index 1d2fead7768..c6f53e3a500 100644 --- a/readline/terminal.c +++ b/readline/terminal.c @@ -7,7 +7,7 @@ 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 1, or + 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 @@ -18,7 +18,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) @@ -46,9 +46,7 @@ # include #endif -#include #include -#include /* System-specific feature definitions and include files. */ #include "rldefs.h" @@ -64,18 +62,12 @@ #include "readline.h" #include "history.h" -/* Variables and functions imported from readline.c */ -extern FILE *_rl_in_stream, *_rl_out_stream; -extern int readline_echoing_p; -extern int _rl_bell_preference; -extern Keymap _rl_keymap; +#include "rlprivate.h" +#include "rlshell.h" +#include "xmalloc.h" -/* Functions imported from bind.c */ -extern void _rl_bind_if_unbound (); - -/* Functions imported from shell.c */ -extern void set_lines_and_columns (); -extern char *get_env_value (); +#define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay) +#define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc) /* **************************************************************** */ /* */ @@ -88,9 +80,6 @@ static char *term_string_buffer = (char *)NULL; static int tcap_initialized; -/* Non-zero means this terminal can't really do anything. */ -static int dumb_term; - #if !defined (__linux__) # if defined (__EMX__) || defined (NEED_EXTERN_PC) extern @@ -99,27 +88,36 @@ char PC, *BC, *UP; #endif /* __linux__ */ /* Some strings to control terminal actions. These are output by tputs (). */ -char *term_goto, *term_clreol, *term_clrpag, *term_backspace; -char *term_cr, *term_pc; +char *_rl_term_clreol; +char *_rl_term_clrpag; +char *_rl_term_cr; +char *_rl_term_backspace; +char *_rl_term_goto; +char *_rl_term_pc; /* Non-zero if we determine that the terminal can do character insertion. */ -int terminal_can_insert = 0; +int _rl_terminal_can_insert = 0; /* How to insert characters. */ -char *term_im, *term_ei, *term_ic, *term_ip, *term_IC; +char *_rl_term_im; +char *_rl_term_ei; +char *_rl_term_ic; +char *_rl_term_ip; +char *_rl_term_IC; /* How to delete characters. */ -char *term_dc, *term_DC; +char *_rl_term_dc; +char *_rl_term_DC; #if defined (HACK_TERMCAP_MOTION) -char *term_forward_char; +char *_rl_term_forward_char; #endif /* HACK_TERMCAP_MOTION */ /* How to go up a line. */ -char *term_up; +char *_rl_term_up; -/* A visible bell, if the terminal can be made to flash the screen. */ -static char *visible_bell; +/* A visible bell; char if the terminal can be made to flash the screen. */ +static char *_rl_visible_bell; /* Non-zero means the terminal can auto-wrap lines. */ int _rl_term_autowrap; @@ -128,20 +126,36 @@ int _rl_term_autowrap; static int term_has_meta; /* The sequences to write to turn on and off the meta key, if this - terminal has one. */ -static char *term_mm, *term_mo; + terminal has one. */ +static char *_rl_term_mm; +static char *_rl_term_mo; /* The key sequences output by the arrow keys, if this terminal has any. */ -static char *term_ku, *term_kd, *term_kr, *term_kl; +static char *_rl_term_ku; +static char *_rl_term_kd; +static char *_rl_term_kr; +static char *_rl_term_kl; /* How to initialize and reset the arrow keys, if this terminal has any. */ -static char *term_ks, *term_ke; +static char *_rl_term_ks; +static char *_rl_term_ke; /* The key sequences sent by the Home and End keys, if any. */ -static char *term_kh, *term_kH; +static char *_rl_term_kh; +static char *_rl_term_kH; +static char *_rl_term_at7; /* @7 */ + +/* Insert key */ +static char *_rl_term_kI; + +/* Cursor control */ +static char *_rl_term_vs; /* very visible */ +static char *_rl_term_ve; /* normal */ + +static void bind_termcap_arrow_keys PARAMS((Keymap)); /* Variables that hold the screen dimensions, used by the display code. */ -int screenwidth, screenheight, screenchars; +int _rl_screenwidth, _rl_screenheight, _rl_screenchars; /* Non-zero means the user wants to enable the keypad. */ int _rl_enable_keypad; @@ -149,6 +163,22 @@ int _rl_enable_keypad; /* Non-zero means the user wants to enable a meta key. */ int _rl_enable_meta = 1; +#if defined (__EMX__) +static void +_emx_get_screensize (swp, shp) + int *swp, *shp; +{ + int sz[2]; + + _scrsize (sz); + + if (swp) + *swp = sz[0]; + if (shp) + *shp = sz[1]; +} +#endif + /* Get readline's idea of the screen size. TTY is a file descriptor open to the terminal. If IGNORE_ENV is true, we do not pay attention to the values of $LINES and $COLUMNS. The tests for TERM_STRING_BUFFER being @@ -161,124 +191,148 @@ _rl_get_screen_size (tty, ignore_env) #if defined (TIOCGWINSZ) struct winsize window_size; #endif /* TIOCGWINSZ */ -#if defined (__EMX__) - int sz[2]; -#endif #if defined (TIOCGWINSZ) if (ioctl (tty, TIOCGWINSZ, &window_size) == 0) { - screenwidth = (int) window_size.ws_col; - screenheight = (int) window_size.ws_row; + _rl_screenwidth = (int) window_size.ws_col; + _rl_screenheight = (int) window_size.ws_row; } #endif /* TIOCGWINSZ */ #if defined (__EMX__) - _scrsize (sz); - screenwidth = sz[0]; - screenheight = sz[1]; + _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight); #endif /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV is unset. */ - if (screenwidth <= 0) + if (_rl_screenwidth <= 0) { - if (ignore_env == 0 && (ss = get_env_value ("COLUMNS"))) - screenwidth = atoi (ss); + if (ignore_env == 0 && (ss = sh_get_env_value ("COLUMNS"))) + _rl_screenwidth = atoi (ss); - if (screenwidth <= 0 && term_string_buffer) - screenwidth = tgetnum ("co"); +#if !defined (__DJGPP__) + if (_rl_screenwidth <= 0 && term_string_buffer) + _rl_screenwidth = tgetnum ("co"); +#endif } /* Environment variable LINES overrides setting of "li" if IGNORE_ENV is unset. */ - if (screenheight <= 0) + if (_rl_screenheight <= 0) { - if (ignore_env == 0 && (ss = get_env_value ("LINES"))) - screenheight = atoi (ss); + if (ignore_env == 0 && (ss = sh_get_env_value ("LINES"))) + _rl_screenheight = atoi (ss); - if (screenheight <= 0 && term_string_buffer) - screenheight = tgetnum ("li"); +#if !defined (__DJGPP__) + if (_rl_screenheight <= 0 && term_string_buffer) + _rl_screenheight = tgetnum ("li"); +#endif } /* If all else fails, default to 80x24 terminal. */ - if (screenwidth <= 1) - screenwidth = 80; + if (_rl_screenwidth <= 1) + _rl_screenwidth = 80; - if (screenheight <= 0) - screenheight = 24; + if (_rl_screenheight <= 0) + _rl_screenheight = 24; /* If we're being compiled as part of bash, set the environment variables $LINES and $COLUMNS to new values. Otherwise, just do a pair of putenv () or setenv () calls. */ - set_lines_and_columns (screenheight, screenwidth); + sh_set_lines_and_columns (_rl_screenheight, _rl_screenwidth); - if (!_rl_term_autowrap) - screenwidth--; + if (_rl_term_autowrap == 0) + _rl_screenwidth--; - screenchars = screenwidth * screenheight; + _rl_screenchars = _rl_screenwidth * _rl_screenheight; } void _rl_set_screen_size (rows, cols) int rows, cols; { - screenheight = rows; - screenwidth = cols; + if (rows == 0 || cols == 0) + return; + + _rl_screenheight = rows; + _rl_screenwidth = cols; if (_rl_term_autowrap == 0) - screenwidth--; + _rl_screenwidth--; - screenchars = screenwidth * screenheight; + _rl_screenchars = _rl_screenwidth * _rl_screenheight; } -extern void _rl_redisplay_after_sigwinch(); +void +rl_set_screen_size (rows, cols) + int rows, cols; +{ + _rl_set_screen_size (rows, cols); +} +void +rl_get_screen_size (rows, cols) + int *rows, *cols; +{ + if (rows) + *rows = _rl_screenheight; + if (cols) + *cols = _rl_screenwidth; +} + void rl_resize_terminal () { if (readline_echoing_p) { _rl_get_screen_size (fileno (rl_instream), 1); - _rl_redisplay_after_sigwinch (); + if (CUSTOM_REDISPLAY_FUNC ()) + rl_forced_update_display (); + else + _rl_redisplay_after_sigwinch (); } } struct _tc_string { - const char *tc_var; - char **tc_value; + const char *tc_var; + char **tc_value; }; /* This should be kept sorted, just in case we decide to change the search algorithm to something smarter. */ static struct _tc_string tc_strings[] = { - {"DC", &term_DC}, - {"IC", &term_IC}, - {"ce", &term_clreol}, - {"cl", &term_clrpag}, - {"cr", &term_cr}, - {"dc", &term_dc}, - {"ei", &term_ei}, - {"ic", &term_ic}, - {"im", &term_im}, - {"kd", &term_kd}, - {"kh", &term_kh}, /* home */ - {"kH", &term_kH}, /* end */ - {"kl", &term_kl}, - {"kr", &term_kr}, - {"ku", &term_ku}, - {"ks", &term_ks}, - {"ke", &term_ke}, - {"le", &term_backspace}, - {"mm", &term_mm}, - {"mo", &term_mo}, + { "@7", &_rl_term_at7 }, + { "DC", &_rl_term_DC }, + { "IC", &_rl_term_IC }, + { "ce", &_rl_term_clreol }, + { "cl", &_rl_term_clrpag }, + { "cr", &_rl_term_cr }, + { "dc", &_rl_term_dc }, + { "ei", &_rl_term_ei }, + { "ic", &_rl_term_ic }, + { "im", &_rl_term_im }, + { "kH", &_rl_term_kH }, /* home down ?? */ + { "kI", &_rl_term_kI }, /* insert */ + { "kd", &_rl_term_kd }, + { "ke", &_rl_term_ke }, /* end keypad mode */ + { "kh", &_rl_term_kh }, /* home */ + { "kl", &_rl_term_kl }, + { "kr", &_rl_term_kr }, + { "ks", &_rl_term_ks }, /* start keypad mode */ + { "ku", &_rl_term_ku }, + { "le", &_rl_term_backspace }, + { "mm", &_rl_term_mm }, + { "mo", &_rl_term_mo }, #if defined (HACK_TERMCAP_MOTION) - {"nd", &term_forward_char}, + { "nd", &_rl_term_forward_char }, #endif - {"pc", &term_pc}, - {"up", &term_up}, - {"vb", &visible_bell}, + { "pc", &_rl_term_pc }, + { "up", &_rl_term_up }, + { "vb", &_rl_visible_bell }, + { "vs", &_rl_term_vs }, + { "ve", &_rl_term_ve }, }; #define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string)) @@ -289,73 +343,99 @@ static void get_term_capabilities (bp) char **bp; { - register int i; +#if !defined (__DJGPP__) /* XXX - doesn't DJGPP have a termcap library? */ + register unsigned int i; - for (i = 0; i < (int) NUM_TC_STRINGS; i++) + for (i = 0; i < NUM_TC_STRINGS; i++) +# ifdef __LCC__ + *(tc_strings[i].tc_value) = tgetstr ((char *)tc_strings[i].tc_var, bp); +# else *(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp); +# endif +#endif tcap_initialized = 1; } int _rl_init_terminal_io (terminal_name) - char *terminal_name; + const char *terminal_name; { -#if defined (__GO32__) - screenwidth = ScreenCols (); - screenheight = ScreenRows (); - screenchars = screenwidth * screenheight; - term_cr = (char*) "\r"; - term_im = term_ei = term_ic = term_IC = (char *)NULL; - term_up = term_dc = term_DC = visible_bell = (char *)NULL; - - /* Does the __GO32__ have a meta key? I don't know. */ - term_has_meta = 0; - term_mm = term_mo = (char *)NULL; - - /* It probably has arrow keys, but I don't know what they are. */ - term_ku = term_kd = term_kr = term_kl = (char *)NULL; - -#if defined (HACK_TERMCAP_MOTION) - term_forward_char = (char *)NULL; -#endif /* HACK_TERMCAP_MOTION */ - terminal_can_insert = _rl_term_autowrap = 0; - return; -#else /* !__GO32__ */ - const char *term; char *buffer; - int tty; - Keymap xkeymap; + int tty, tgetent_ret; - term = terminal_name ? terminal_name : get_env_value ("TERM"); - - if (term_string_buffer == 0) - term_string_buffer = xmalloc (2032); - - if (term_buffer == 0) - term_buffer = xmalloc (4080); - - buffer = term_string_buffer; - - term_clrpag = term_cr = term_clreol = (char *)NULL; + term = terminal_name ? terminal_name : sh_get_env_value ("TERM"); + _rl_term_clrpag = _rl_term_cr = _rl_term_clreol = (char *)NULL; + tty = rl_instream ? fileno (rl_instream) : 0; + _rl_screenwidth = _rl_screenheight = 0; if (term == 0) term = "dumb"; - if (tgetent (term_buffer, term) <= 0) + /* I've separated this out for later work on not calling tgetent at all + if the calling application has supplied a custom redisplay function, + (and possibly if the application has supplied a custom input function). */ + if (CUSTOM_REDISPLAY_FUNC()) { - dumb_term = 1; - screenwidth = 79; - screenheight = 24; - screenchars = 79 * 24; - term_cr = (char*) "\r"; - term_im = term_ei = term_ic = term_IC = (char *)NULL; - term_up = term_dc = term_DC = visible_bell = (char *)NULL; - term_ku = term_kd = term_kl = term_kr = (char *)NULL; + tgetent_ret = -1; + } + else + { + if (term_string_buffer == 0) + term_string_buffer = (char *)xmalloc(2032); + + if (term_buffer == 0) + term_buffer = (char *)xmalloc(4080); + + buffer = term_string_buffer; + + tgetent_ret = tgetent (term_buffer, term); + } + + if (tgetent_ret <= 0) + { + FREE (term_string_buffer); + FREE (term_buffer); + buffer = term_buffer = term_string_buffer = (char *)NULL; + + _rl_term_autowrap = 0; /* used by _rl_get_screen_size */ + +#if defined (__EMX__) + _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight); + _rl_screenwidth--; +#else /* !__EMX__ */ + _rl_get_screen_size (tty, 0); +#endif /* !__EMX__ */ + + /* Defaults. */ + if (_rl_screenwidth <= 0 || _rl_screenheight <= 0) + { + _rl_screenwidth = 79; + _rl_screenheight = 24; + } + + /* Everything below here is used by the redisplay code (tputs). */ + _rl_screenchars = _rl_screenwidth * _rl_screenheight; + _rl_term_cr = (char*)"\r"; + _rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL; + _rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL; + _rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL; + _rl_term_kh = _rl_term_kH = _rl_term_kI = (char *)NULL; + _rl_term_ks = _rl_term_ke = _rl_term_at7 = (char *)NULL; + _rl_term_mm = _rl_term_mo = (char *)NULL; + _rl_term_ve = _rl_term_vs = (char *)NULL; #if defined (HACK_TERMCAP_MOTION) term_forward_char = (char *)NULL; #endif - terminal_can_insert = 0; + _rl_terminal_can_insert = term_has_meta = 0; + + /* Reasonable defaults for tgoto(). Readline currently only uses + tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we + change that later... */ + PC = '\0'; + BC = _rl_term_backspace = (char*)"\b"; + UP = _rl_term_up; + return 0; } @@ -363,16 +443,12 @@ _rl_init_terminal_io (terminal_name) /* Set up the variables that the termcap library expects the application to provide. */ - PC = term_pc ? *term_pc : 0; - BC = term_backspace; - UP = term_up; + PC = _rl_term_pc ? *_rl_term_pc : 0; + BC = _rl_term_backspace; + UP = _rl_term_up; - if (!term_cr) - term_cr = (char*) "\r"; - - tty = rl_instream ? fileno (rl_instream) : 0; - - screenwidth = screenheight = 0; + if (!_rl_term_cr) + _rl_term_cr = (char*)"\r"; _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn"); @@ -382,53 +458,57 @@ _rl_init_terminal_io (terminal_name) character insertion if *any one of* the capabilities `IC', `im', `ic' or `ip' is provided." But we can't do anything if only `ip' is provided, so... */ - terminal_can_insert = (term_IC || term_im || term_ic); + _rl_terminal_can_insert = (_rl_term_IC || _rl_term_im || _rl_term_ic); /* Check to see if this terminal has a meta key and clear the capability variables if there is none. */ term_has_meta = (tgetflag ("km") || tgetflag ("MT")); if (!term_has_meta) - term_mm = term_mo = (char *)NULL; + _rl_term_mm = _rl_term_mo = (char *)NULL; /* Attempt to find and bind the arrow keys. Do not override already bound keys in an overzealous attempt, however. */ - xkeymap = _rl_keymap; - _rl_keymap = emacs_standard_keymap; - _rl_bind_if_unbound (term_ku, rl_get_previous_history); - _rl_bind_if_unbound (term_kd, rl_get_next_history); - _rl_bind_if_unbound (term_kr, rl_forward); - _rl_bind_if_unbound (term_kl, rl_backward); - - _rl_bind_if_unbound (term_kh, rl_beg_of_line); /* Home */ - _rl_bind_if_unbound (term_kH, rl_end_of_line); /* End */ + bind_termcap_arrow_keys (emacs_standard_keymap); #if defined (VI_MODE) - _rl_keymap = vi_movement_keymap; - _rl_bind_if_unbound (term_ku, rl_get_previous_history); - _rl_bind_if_unbound (term_kd, rl_get_next_history); - _rl_bind_if_unbound (term_kr, rl_forward); - _rl_bind_if_unbound (term_kl, rl_backward); - - _rl_bind_if_unbound (term_kh, rl_beg_of_line); /* Home */ - _rl_bind_if_unbound (term_kH, rl_end_of_line); /* End */ + bind_termcap_arrow_keys (vi_movement_keymap); + bind_termcap_arrow_keys (vi_insertion_keymap); #endif /* VI_MODE */ - _rl_keymap = xkeymap; - -#endif /* !__GO32__ */ return 0; } +/* Bind the arrow key sequences from the termcap description in MAP. */ +static void +bind_termcap_arrow_keys (map) + Keymap map; +{ + Keymap xkeymap; + + xkeymap = _rl_keymap; + _rl_keymap = map; + + _rl_bind_if_unbound (_rl_term_ku, rl_get_previous_history); + _rl_bind_if_unbound (_rl_term_kd, rl_get_next_history); + _rl_bind_if_unbound (_rl_term_kr, rl_forward); + _rl_bind_if_unbound (_rl_term_kl, rl_backward); + + _rl_bind_if_unbound (_rl_term_kh, rl_beg_of_line); /* Home */ + _rl_bind_if_unbound (_rl_term_at7, rl_end_of_line); /* End */ + + _rl_keymap = xkeymap; +} + char * rl_get_termcap (cap) - char *cap; + const char *cap; { - register int i; + register unsigned int i; if (tcap_initialized == 0) return ((char *)NULL); - for (i = 0; i < (int) NUM_TC_STRINGS; i++) + for (i = 0; i < NUM_TC_STRINGS; i++) { if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0) return *(tc_strings[i].tc_value); @@ -440,7 +520,7 @@ rl_get_termcap (cap) has changed. */ int rl_reset_terminal (terminal_name) - char *terminal_name; + const char *terminal_name; { _rl_init_terminal_io (terminal_name); return 0; @@ -462,10 +542,11 @@ _rl_output_character_function (c) return putc (c, _rl_out_stream); } #endif /* !_MINIX */ + /* Write COUNT characters from STRING to the output stream. */ void _rl_output_some_chars (string, count) - char *string; + const char *string; int count; { fwrite (string, 1, count, _rl_out_stream); @@ -478,12 +559,10 @@ _rl_backspace (count) { register int i; -#if !defined (__GO32__) - if (term_backspace) + if (_rl_term_backspace) for (i = 0; i < count; i++) - tputs (term_backspace, 1, _rl_output_character_function); + tputs (_rl_term_backspace, 1, _rl_output_character_function); else -#endif /* !__GO32__ */ for (i = 0; i < count; i++) putc ('\b', _rl_out_stream); return 0; @@ -491,11 +570,11 @@ _rl_backspace (count) /* Move to the start of the next line. */ int -crlf () +rl_crlf () { #if defined (NEW_TTY_DRIVER) - if (term_cr) - tputs (term_cr, 1, _rl_output_character_function); + if (_rl_term_cr) + tputs (_rl_term_cr, 1, _rl_output_character_function); #endif /* NEW_TTY_DRIVER */ putc ('\n', _rl_out_stream); return 0; @@ -503,20 +582,19 @@ crlf () /* Ring the terminal bell. */ int -ding () +rl_ding () { if (readline_echoing_p) { -#if !defined (__GO32__) switch (_rl_bell_preference) { case NO_BELL: default: break; case VISIBLE_BELL: - if (visible_bell) + if (_rl_visible_bell) { - tputs (visible_bell, 1, _rl_output_character_function); + tputs (_rl_visible_bell, 1, _rl_output_character_function); break; } /* FALLTHROUGH */ @@ -525,10 +603,6 @@ ding () fflush (stderr); break; } -#else /* __GO32__ */ - fprintf (stderr, "\007"); - fflush (stderr); -#endif /* __GO32__ */ return (0); } return (-1); @@ -543,16 +617,46 @@ ding () void _rl_enable_meta_key () { - if (term_has_meta && term_mm) - tputs (term_mm, 1, _rl_output_character_function); +#if !defined (__DJGPP__) + if (term_has_meta && _rl_term_mm) + tputs (_rl_term_mm, 1, _rl_output_character_function); +#endif } void _rl_control_keypad (on) int on; { - if (on && term_ks) - tputs (term_ks, 1, _rl_output_character_function); - else if (!on && term_ke) - tputs (term_ke, 1, _rl_output_character_function); +#if !defined (__DJGPP__) + if (on && _rl_term_ks) + tputs (_rl_term_ks, 1, _rl_output_character_function); + else if (!on && _rl_term_ke) + tputs (_rl_term_ke, 1, _rl_output_character_function); +#endif +} + +/* **************************************************************** */ +/* */ +/* Controlling the Cursor */ +/* */ +/* **************************************************************** */ + +/* Set the cursor appropriately depending on IM, which is one of the + insert modes (insert or overwrite). Insert mode gets the normal + cursor. Overwrite mode gets a very visible cursor. Only does + anything if we have both capabilities. */ +void +_rl_set_cursor (im, force) + int im, force; +{ + if (_rl_term_ve && _rl_term_vs) + { + if (force || im != rl_insert_mode) + { + if (im == RL_IM_OVERWRITE) + tputs (_rl_term_vs, 1, _rl_output_character_function); + else + tputs (_rl_term_ve, 1, _rl_output_character_function); + } + } } diff --git a/readline/text.c b/readline/text.c new file mode 100644 index 00000000000..f84fd91344f --- /dev/null +++ b/readline/text.c @@ -0,0 +1,1540 @@ +/* text.c -- text handling commands for readline. */ + +/* Copyright (C) 1987-2002 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 + +#if defined (HAVE_UNISTD_H) +# include +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#if defined (HAVE_LOCALE_H) +# include +#endif + +#include + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" +#include "rlmbutil.h" + +#if defined (__EMX__) +# define INCL_DOSPROCESS +# include +#endif /* __EMX__ */ + +/* Some standard library routines. */ +#include "readline.h" +#include "history.h" + +#include "rlprivate.h" +#include "rlshell.h" +#include "xmalloc.h" + +/* Forward declarations. */ +static int rl_change_case PARAMS((int, int)); +static int _rl_char_search PARAMS((int, int, int)); + +/* **************************************************************** */ +/* */ +/* Insert and Delete */ +/* */ +/* **************************************************************** */ + +/* Insert a string of text into the line at point. This is the only + way that you should do insertion. _rl_insert_char () calls this + function. Returns the number of characters inserted. */ +int +rl_insert_text (string) + const char *string; +{ + register int i, l; + + l = (string && *string) ? strlen (string) : 0; + if (l == 0) + return 0; + + if (rl_end + l >= rl_line_buffer_len) + rl_extend_line_buffer (rl_end + l); + + for (i = rl_end; i >= rl_point; i--) + rl_line_buffer[i + l] = rl_line_buffer[i]; + strncpy (rl_line_buffer + rl_point, string, l); + + /* Remember how to undo this if we aren't undoing something. */ + if (_rl_doing_an_undo == 0) + { + /* If possible and desirable, concatenate the undos. */ + if ((l == 1) && + rl_undo_list && + (rl_undo_list->what == UNDO_INSERT) && + (rl_undo_list->end == rl_point) && + (rl_undo_list->end - rl_undo_list->start < 20)) + rl_undo_list->end++; + else + rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL); + } + rl_point += l; + rl_end += l; + rl_line_buffer[rl_end] = '\0'; + return l; +} + +/* Delete the string between FROM and TO. FROM is inclusive, TO is not. + Returns the number of characters deleted. */ +int +rl_delete_text (from, to) + int from, to; +{ + register char *text; + register int diff, i; + + /* Fix it if the caller is confused. */ + if (from > to) + SWAP (from, to); + + /* fix boundaries */ + if (to > rl_end) + { + to = rl_end; + if (from > to) + from = to; + } + if (from < 0) + from = 0; + + text = rl_copy_text (from, to); + + /* Some versions of strncpy() can't handle overlapping arguments. */ + diff = to - from; + for (i = from; i < rl_end - diff; i++) + rl_line_buffer[i] = rl_line_buffer[i + diff]; + + /* Remember how to undo this delete. */ + if (_rl_doing_an_undo == 0) + rl_add_undo (UNDO_DELETE, from, to, text); + else + free (text); + + rl_end -= diff; + rl_line_buffer[rl_end] = '\0'; + return (diff); +} + +/* Fix up point so that it is within the line boundaries after killing + text. If FIX_MARK_TOO is non-zero, the mark is forced within line + boundaries also. */ + +#define _RL_FIX_POINT(x) \ + do { \ + if (x > rl_end) \ + x = rl_end; \ + else if (x < 0) \ + x = 0; \ + } while (0) + +void +_rl_fix_point (fix_mark_too) + int fix_mark_too; +{ + _RL_FIX_POINT (rl_point); + if (fix_mark_too) + _RL_FIX_POINT (rl_mark); +} +#undef _RL_FIX_POINT + +int +_rl_replace_text (text, start, end) + const char *text; + int start, end; +{ + int n; + + rl_begin_undo_group (); + rl_delete_text (start, end + 1); + rl_point = start; + n = rl_insert_text (text); + rl_end_undo_group (); + + return n; +} + +/* Replace the current line buffer contents with TEXT. If CLEAR_UNDO is + non-zero, we free the current undo list. */ +void +rl_replace_line (text, clear_undo) + const char *text; + int clear_undo; +{ + int len; + + len = strlen (text); + if (len >= rl_line_buffer_len) + rl_extend_line_buffer (len); + strcpy (rl_line_buffer, text); + rl_end = len; + + if (clear_undo) + rl_free_undo_list (); + + _rl_fix_point (1); +} + +/* **************************************************************** */ +/* */ +/* Readline character functions */ +/* */ +/* **************************************************************** */ + +/* This is not a gap editor, just a stupid line input routine. No hair + is involved in writing any of the functions, and none should be. */ + +/* Note that: + + rl_end is the place in the string that we would place '\0'; + i.e., it is always safe to place '\0' there. + + rl_point is the place in the string where the cursor is. Sometimes + this is the same as rl_end. + + Any command that is called interactively receives two arguments. + The first is a count: the numeric arg pased to this command. + The second is the key which invoked this command. +*/ + +/* **************************************************************** */ +/* */ +/* Movement Commands */ +/* */ +/* **************************************************************** */ + +/* Note that if you `optimize' the display for these functions, you cannot + use said functions in other functions which do not do optimizing display. + I.e., you will have to update the data base for rl_redisplay, and you + might as well let rl_redisplay do that job. */ + +/* Move forward COUNT bytes. */ +int +rl_forward_byte (count, key) + int count, key; +{ + if (count < 0) + return (rl_backward_byte (-count, key)); + + if (count > 0) + { + int end = rl_point + count; +#if defined (VI_MODE) + int lend = rl_end > 0 ? rl_end - (rl_editing_mode == vi_mode) : rl_end; +#else + int lend = rl_end; +#endif + + if (end > lend) + { + rl_point = lend; + rl_ding (); + } + else + rl_point = end; + } + + if (rl_end < 0) + rl_end = 0; + + return 0; +} + +#if defined (HANDLE_MULTIBYTE) +/* Move forward COUNT characters. */ +int +rl_forward_char (count, key) + int count, key; +{ + int point; + + if (MB_CUR_MAX == 1 || rl_byte_oriented) + return (rl_forward_byte (count, key)); + + if (count < 0) + return (rl_backward_char (-count, key)); + + if (count > 0) + { + point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO); + +#if defined (VI_MODE) + if (rl_end <= point && rl_editing_mode == vi_mode) + point = _rl_find_prev_mbchar (rl_line_buffer, rl_end, MB_FIND_NONZERO); +#endif + + if (rl_point == point) + rl_ding (); + + rl_point = point; + + if (rl_end < 0) + rl_end = 0; + } + + return 0; +} +#else /* !HANDLE_MULTIBYTE */ +int +rl_forward_char (count, key) + int count, key; +{ + return (rl_forward_byte (count, key)); +} +#endif /* !HANDLE_MULTIBYTE */ + +/* Backwards compatibility. */ +int +rl_forward (count, key) + int count, key; +{ + return (rl_forward_char (count, key)); +} + +/* Move backward COUNT bytes. */ +int +rl_backward_byte (count, key) + int count, key; +{ + if (count < 0) + return (rl_forward_byte (-count, key)); + + if (count > 0) + { + if (rl_point < count) + { + rl_point = 0; + rl_ding (); + } + else + rl_point -= count; + } + + if (rl_point < 0) + rl_point = 0; + + return 0; +} + +#if defined (HANDLE_MULTIBYTE) +/* Move backward COUNT characters. */ +int +rl_backward_char (count, key) + int count, key; +{ + int point; + + if (MB_CUR_MAX == 1 || rl_byte_oriented) + return (rl_backward_byte (count, key)); + + if (count < 0) + return (rl_forward_char (-count, key)); + + if (count > 0) + { + point = rl_point; + + while (count > 0 && point > 0) + { + point = _rl_find_prev_mbchar (rl_line_buffer, point, MB_FIND_NONZERO); + count--; + } + if (count > 0) + { + rl_point = 0; + rl_ding (); + } + else + rl_point = point; + } + + return 0; +} +#else +int +rl_backward_char (count, key) + int count, key; +{ + return (rl_backward_byte (count, key)); +} +#endif + +/* Backwards compatibility. */ +int +rl_backward (count, key) + int count, key; +{ + return (rl_backward_char (count, key)); +} + +/* Move to the beginning of the line. */ +int +rl_beg_of_line (count, key) + int count __attribute__((unused)), key __attribute__((unused)); +{ + rl_point = 0; + return 0; +} + +/* Move to the end of the line. */ +int +rl_end_of_line (count, key) + int count __attribute__((unused)), key __attribute__((unused)); +{ + rl_point = rl_end; + return 0; +} + +/* XXX - these might need changes for multibyte characters */ +/* Move forward a word. We do what Emacs does. */ +int +rl_forward_word (count, key) + int count, key; +{ + int c; + + if (count < 0) + return (rl_backward_word (-count, key)); + + while (count) + { + if (rl_point == rl_end) + return 0; + + /* If we are not in a word, move forward until we are in one. + Then, move forward until we hit a non-alphabetic character. */ + c = rl_line_buffer[rl_point]; + if (rl_alphabetic (c) == 0) + { + while (++rl_point < rl_end) + { + c = rl_line_buffer[rl_point]; + if (rl_alphabetic (c)) + break; + } + } + + if (rl_point == rl_end) + return 0; + + while (++rl_point < rl_end) + { + c = rl_line_buffer[rl_point]; + if (rl_alphabetic (c) == 0) + break; + } + --count; + } + + return 0; +} + +/* Move backward a word. We do what Emacs does. */ +int +rl_backward_word (count, key) + int count, key; +{ + int c; + + if (count < 0) + return (rl_forward_word (-count, key)); + + while (count) + { + if (!rl_point) + return 0; + + /* Like rl_forward_word (), except that we look at the characters + just before point. */ + + c = rl_line_buffer[rl_point - 1]; + if (rl_alphabetic (c) == 0) + { + while (--rl_point) + { + c = rl_line_buffer[rl_point - 1]; + if (rl_alphabetic (c)) + break; + } + } + + while (rl_point) + { + c = rl_line_buffer[rl_point - 1]; + if (rl_alphabetic (c) == 0) + break; + else + --rl_point; + } + + --count; + } + + return 0; +} + +/* Clear the current line. Numeric argument to C-l does this. */ +int +rl_refresh_line (ignore1, ignore2) + int ignore1 __attribute__((unused)), ignore2 __attribute__((unused)); +{ + int curr_line; + + curr_line = _rl_current_display_line (); + + _rl_move_vert (curr_line); + _rl_move_cursor_relative (0, rl_line_buffer); /* XXX is this right */ + + _rl_clear_to_eol (0); /* arg of 0 means to not use spaces */ + + rl_forced_update_display (); + rl_display_fixed = 1; + + return 0; +} + +/* C-l typed to a line without quoting clears the screen, and then reprints + the prompt and the current input line. Given a numeric arg, redraw only + the current line. */ +int +rl_clear_screen (count, key) + int count, key; +{ + if (rl_explicit_arg) + { + rl_refresh_line (count, key); + return 0; + } + + _rl_clear_screen (); /* calls termcap function to clear screen */ + rl_forced_update_display (); + rl_display_fixed = 1; + + return 0; +} + +int +rl_arrow_keys (count, c) + int count, c __attribute__((unused)); +{ + int ch; + + RL_SETSTATE(RL_STATE_MOREINPUT); + ch = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + switch (_rl_to_upper (ch)) + { + case 'A': + rl_get_previous_history (count, ch); + break; + + case 'B': + rl_get_next_history (count, ch); + break; + + case 'C': + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_forward_char (count, ch); + else + rl_forward_byte (count, ch); + break; + + case 'D': + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_backward_char (count, ch); + else + rl_backward_byte (count, ch); + break; + + default: + rl_ding (); + } + + return 0; +} + +/* **************************************************************** */ +/* */ +/* Text commands */ +/* */ +/* **************************************************************** */ + +#ifdef HANDLE_MULTIBYTE +static char pending_bytes[MB_LEN_MAX]; +static int pending_bytes_length = 0; +static mbstate_t ps = {0}; +#endif + +/* Insert the character C at the current location, moving point forward. + If C introduces a multibyte sequence, we read the whole sequence and + then insert the multibyte char into the line buffer. */ +int +_rl_insert_char (count, c) + int count, c; +{ + register int i; + char *string; +#ifdef HANDLE_MULTIBYTE + int string_size; + char incoming[MB_LEN_MAX + 1]; + int incoming_length = 0; + mbstate_t ps_back; + static int stored_count = 0; +#endif + + if (count <= 0) + return 0; + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX == 1 || rl_byte_oriented) + { + incoming[0] = c; + incoming[1] = '\0'; + incoming_length = 1; + } + else + { + wchar_t wc; + size_t ret; + + if (stored_count <= 0) + stored_count = count; + else + count = stored_count; + + ps_back = ps; + pending_bytes[pending_bytes_length++] = c; + ret = mbrtowc (&wc, pending_bytes, pending_bytes_length, &ps); + + if (ret == (size_t)-2) + { + /* Bytes too short to compose character, try to wait for next byte. + Restore the state of the byte sequence, because in this case the + effect of mbstate is undefined. */ + ps = ps_back; + return 1; + } + else if (ret == (size_t)-1) + { + /* Invalid byte sequence for the current locale. Treat first byte + as a single character. */ + incoming[0] = pending_bytes[0]; + incoming[1] = '\0'; + incoming_length = 1; + pending_bytes_length--; + memmove (pending_bytes, pending_bytes + 1, pending_bytes_length); + /* Clear the state of the byte sequence, because in this case the + effect of mbstate is undefined. */ + memset (&ps, 0, sizeof (mbstate_t)); + } + else if (ret == (size_t)0) + { + incoming[0] = '\0'; + incoming_length = 0; + pending_bytes_length--; + /* Clear the state of the byte sequence, because in this case the + effect of mbstate is undefined. */ + memset (&ps, 0, sizeof (mbstate_t)); + } + else + { + /* We successfully read a single multibyte character. */ + memcpy (incoming, pending_bytes, pending_bytes_length); + incoming[pending_bytes_length] = '\0'; + incoming_length = pending_bytes_length; + pending_bytes_length = 0; + } + } +#endif /* HANDLE_MULTIBYTE */ + + /* If we can optimize, then do it. But don't let people crash + readline because of extra large arguments. */ + if (count > 1 && count <= 1024) + { +#if defined (HANDLE_MULTIBYTE) + string_size = count * incoming_length; + string = (char *)xmalloc (1 + string_size); + + i = 0; + while (i < string_size) + { + strncpy (string + i, incoming, incoming_length); + i += incoming_length; + } + incoming_length = 0; + stored_count = 0; +#else /* !HANDLE_MULTIBYTE */ + string = (char *)xmalloc (1 + count); + + for (i = 0; i < count; i++) + string[i] = c; +#endif /* !HANDLE_MULTIBYTE */ + + string[i] = '\0'; + rl_insert_text (string); + free (string); + + return 0; + } + + if (count > 1024) + { + int decreaser; +#if defined (HANDLE_MULTIBYTE) + string_size = incoming_length * 1024; + string = (char *)xmalloc (1 + string_size); + + i = 0; + while (i < string_size) + { + strncpy (string + i, incoming, incoming_length); + i += incoming_length; + } + + while (count) + { + decreaser = (count > 1024) ? 1024 : count; + string[decreaser*incoming_length] = '\0'; + rl_insert_text (string); + count -= decreaser; + } + + free (string); + incoming_length = 0; + stored_count = 0; +#else /* !HANDLE_MULTIBYTE */ + char str[1024+1]; + + for (i = 0; i < 1024; i++) + str[i] = c; + + while (count) + { + decreaser = (count > 1024 ? 1024 : count); + str[decreaser] = '\0'; + rl_insert_text (str); + count -= decreaser; + } +#endif /* !HANDLE_MULTIBYTE */ + + return 0; + } + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX == 1 || rl_byte_oriented) + { +#endif + /* We are inserting a single character. + If there is pending input, then make a string of all of the + pending characters that are bound to rl_insert, and insert + them all. */ + if (_rl_any_typein ()) + _rl_insert_typein (c); + else + { + /* Inserting a single character. */ + char str[2]; + + str[1] = '\0'; + str[0] = c; + rl_insert_text (str); + } +#if defined (HANDLE_MULTIBYTE) + } + else + { + rl_insert_text (incoming); + stored_count = 0; + } +#endif + + return 0; +} + +/* Overwrite the character at point (or next COUNT characters) with C. + If C introduces a multibyte character sequence, read the entire sequence + before starting the overwrite loop. */ +int +_rl_overwrite_char (count, c) + int count, c; +{ + int i; +#if defined (HANDLE_MULTIBYTE) + char mbkey[MB_LEN_MAX]; + int k; + + /* Read an entire multibyte character sequence to insert COUNT times. */ + if (count > 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0) + k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX); +#endif + + for (i = 0; i < count; i++) + { + rl_begin_undo_group (); + + if (rl_point < rl_end) + rl_delete (1, c); + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_insert_text (mbkey); + else +#endif + _rl_insert_char (1, c); + + rl_end_undo_group (); + } + + return 0; +} + +int +rl_insert (count, c) + int count, c; +{ + return (rl_insert_mode == RL_IM_INSERT ? _rl_insert_char (count, c) + : _rl_overwrite_char (count, c)); +} + +/* Insert the next typed character verbatim. */ +int +rl_quoted_insert (count, key) + int count, key __attribute__((unused)); +{ + int c; + +#if defined (HANDLE_SIGNALS) + _rl_disable_tty_signals (); +#endif + + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + +#if defined (HANDLE_SIGNALS) + _rl_restore_tty_signals (); +#endif + + return (_rl_insert_char (count, c)); +} + +/* Insert a tab character. */ +int +rl_tab_insert (count, key) + int count, key __attribute__((unused)); +{ + return (_rl_insert_char (count, '\t')); +} + +/* What to do when a NEWLINE is pressed. We accept the whole line. + KEY is the key that invoked this command. I guess it could have + meaning in the future. */ +int +rl_newline (count, key) + int count __attribute__((unused)), key __attribute__((unused)); +{ + rl_done = 1; + + if (_rl_history_preserve_point) + _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; + + RL_SETSTATE(RL_STATE_DONE); + +#if defined (VI_MODE) + if (rl_editing_mode == vi_mode) + { + _rl_vi_done_inserting (); + _rl_vi_reset_last (); + } +#endif /* VI_MODE */ + + /* If we've been asked to erase empty lines, suppress the final update, + since _rl_update_final calls rl_crlf(). */ + if (rl_erase_empty_line && rl_point == 0 && rl_end == 0) + return 0; + + if (readline_echoing_p) + _rl_update_final (); + return 0; +} + +/* What to do for some uppercase characters, like meta characters, + and some characters appearing in emacs_ctlx_keymap. This function + is just a stub, you bind keys to it and the code in _rl_dispatch () + is special cased. */ +int +rl_do_lowercase_version (ignore1, ignore2) + int ignore1 __attribute__((unused)), ignore2 __attribute__((unused)); +{ + return 0; +} + +/* This is different from what vi does, so the code's not shared. Emacs + rubout in overwrite mode has one oddity: it replaces a control + character that's displayed as two characters (^X) with two spaces. */ +int +_rl_overwrite_rubout (count, key) + int count, key; +{ + int opoint; + int i, l; + + if (rl_point == 0) + { + rl_ding (); + return 1; + } + + opoint = rl_point; + + /* L == number of spaces to insert */ + for (i = l = 0; i < count; i++) + { + rl_backward_char (1, key); + l += rl_character_len (rl_line_buffer[rl_point], rl_point); /* not exactly right */ + } + + rl_begin_undo_group (); + + if (count > 1 || rl_explicit_arg) + rl_kill_text (opoint, rl_point); + else + rl_delete_text (opoint, rl_point); + + /* Emacs puts point at the beginning of the sequence of spaces. */ + opoint = rl_point; + _rl_insert_char (l, ' '); + rl_point = opoint; + + rl_end_undo_group (); + + return 0; +} + +/* Rubout the character behind point. */ +int +rl_rubout (count, key) + int count, key; +{ + if (count < 0) + return (rl_delete (-count, key)); + + if (!rl_point) + { + rl_ding (); + return -1; + } + + if (rl_insert_mode == RL_IM_OVERWRITE) + return (_rl_overwrite_rubout (count, key)); + + return (_rl_rubout_char (count, key)); +} + +int +_rl_rubout_char (count, key) + int count, key; +{ + int orig_point; + unsigned char c; + + /* Duplicated code because this is called from other parts of the library. */ + if (count < 0) + return (rl_delete (-count, key)); + + if (rl_point == 0) + { + rl_ding (); + return -1; + } + + if (count > 1 || rl_explicit_arg) + { + orig_point = rl_point; +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_backward_char (count, key); + else +#endif + rl_backward_byte (count, key); + rl_kill_text (orig_point, rl_point); + } + else + { +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX == 1 || rl_byte_oriented) + { +#endif + c = rl_line_buffer[--rl_point]; + rl_delete_text (rl_point, rl_point + 1); +#if defined (HANDLE_MULTIBYTE) + } + else + { + int orig_point; + + orig_point = rl_point; + rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); + c = rl_line_buffer[rl_point]; + rl_delete_text (rl_point, orig_point); + } +#endif /* HANDLE_MULTIBYTE */ + + /* I don't think that the hack for end of line is needed for + multibyte chars. */ +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX == 1 || rl_byte_oriented) +#endif + if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos) + { + int l; + l = rl_character_len (c, rl_point); + _rl_erase_at_end_of_line (l); + } + } + + return 0; +} + +/* Delete the character under the cursor. Given a numeric argument, + kill that many characters instead. */ +int +rl_delete (count, key) + int count, key; +{ + int r; + + if (count < 0) + return (_rl_rubout_char (-count, key)); + + if (rl_point == rl_end) + { + rl_ding (); + return -1; + } + + if (count > 1 || rl_explicit_arg) + { + int orig_point = rl_point; +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_forward_char (count, key); + else +#endif + rl_forward_byte (count, key); + + r = rl_kill_text (orig_point, rl_point); + rl_point = orig_point; + return r; + } + else + { + int new_point; + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + new_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); + else + new_point = rl_point + 1; + + return (rl_delete_text (rl_point, new_point)); + } +} + +/* Delete the character under the cursor, unless the insertion + point is at the end of the line, in which case the character + behind the cursor is deleted. COUNT is obeyed and may be used + to delete forward or backward that many characters. */ +int +rl_rubout_or_delete (count, key) + int count, key; +{ + if (rl_end != 0 && rl_point == rl_end) + return (_rl_rubout_char (count, key)); + else + return (rl_delete (count, key)); +} + +/* Delete all spaces and tabs around point. */ +int +rl_delete_horizontal_space (count, ignore) + int count __attribute__((unused)), ignore __attribute__((unused)); +{ + int start = rl_point; + + while (rl_point && whitespace (rl_line_buffer[rl_point - 1])) + rl_point--; + + start = rl_point; + + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + + if (start != rl_point) + { + rl_delete_text (start, rl_point); + rl_point = start; + } + return 0; +} + +/* Like the tcsh editing function delete-char-or-list. The eof character + is caught before this is invoked, so this really does the same thing as + delete-char-or-list-or-eof, as long as it's bound to the eof character. */ +int +rl_delete_or_show_completions (count, key) + int count, key; +{ + if (rl_end != 0 && rl_point == rl_end) + return (rl_possible_completions (count, key)); + else + return (rl_delete (count, key)); +} + +#ifndef RL_COMMENT_BEGIN_DEFAULT +#define RL_COMMENT_BEGIN_DEFAULT "#" +#endif + +/* Turn the current line into a comment in shell history. + A K*rn shell style function. */ +int +rl_insert_comment (count, key) + int count __attribute__((unused)), key; +{ + char *rl_comment_text; + int rl_comment_len; + + rl_beg_of_line (1, key); + rl_comment_text = (char*)(_rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT); + + if (rl_explicit_arg == 0) + rl_insert_text (rl_comment_text); + else + { + rl_comment_len = strlen (rl_comment_text); + if (STREQN (rl_comment_text, rl_line_buffer, rl_comment_len)) + rl_delete_text (rl_point, rl_point + rl_comment_len); + else + rl_insert_text (rl_comment_text); + } + + (*rl_redisplay_function) (); + rl_newline (1, '\n'); + + return (0); +} + +/* **************************************************************** */ +/* */ +/* Changing Case */ +/* */ +/* **************************************************************** */ + +/* The three kinds of things that we know how to do. */ +#define UpCase 1 +#define DownCase 2 +#define CapCase 3 + +/* Uppercase the word at point. */ +int +rl_upcase_word (count, key) + int count, key __attribute__((unused)); +{ + return (rl_change_case (count, UpCase)); +} + +/* Lowercase the word at point. */ +int +rl_downcase_word (count, key) + int count, key __attribute__((unused)); +{ + return (rl_change_case (count, DownCase)); +} + +/* Upcase the first letter, downcase the rest. */ +int +rl_capitalize_word (count, key) + int count, key __attribute__((unused)); +{ + return (rl_change_case (count, CapCase)); +} + +/* The meaty function. + Change the case of COUNT words, performing OP on them. + OP is one of UpCase, DownCase, or CapCase. + If a negative argument is given, leave point where it started, + otherwise, leave it where it moves to. */ +static int +rl_change_case (count, op) + int count, op; +{ + register int start, end; + int inword, c; + + start = rl_point; + rl_forward_word (count, 0); + end = rl_point; + + if (count < 0) + SWAP (start, end); + + /* We are going to modify some text, so let's prepare to undo it. */ + rl_modifying (start, end); + + for (inword = 0; start < end; start++) + { + c = rl_line_buffer[start]; + switch (op) + { + case UpCase: + rl_line_buffer[start] = _rl_to_upper (c); + break; + + case DownCase: + rl_line_buffer[start] = _rl_to_lower (c); + break; + + case CapCase: + rl_line_buffer[start] = (inword == 0) ? _rl_to_upper (c) : _rl_to_lower (c); + inword = rl_alphabetic (rl_line_buffer[start]); + break; + + default: + rl_ding (); + return -1; + } + } + rl_point = end; + return 0; +} + +/* **************************************************************** */ +/* */ +/* Transposition */ +/* */ +/* **************************************************************** */ + +/* Transpose the words at point. If point is at the end of the line, + transpose the two words before point. */ +int +rl_transpose_words (count, key) + int count, key; +{ + char *word1, *word2; + int w1_beg, w1_end, w2_beg, w2_end; + int orig_point = rl_point; + + if (!count) + return 0; + + /* Find the two words. */ + rl_forward_word (count, key); + w2_end = rl_point; + rl_backward_word (1, key); + w2_beg = rl_point; + rl_backward_word (count, key); + w1_beg = rl_point; + rl_forward_word (1, key); + w1_end = rl_point; + + /* Do some check to make sure that there really are two words. */ + if ((w1_beg == w2_beg) || (w2_beg < w1_end)) + { + rl_ding (); + rl_point = orig_point; + return -1; + } + + /* Get the text of the words. */ + word1 = rl_copy_text (w1_beg, w1_end); + word2 = rl_copy_text (w2_beg, w2_end); + + /* We are about to do many insertions and deletions. Remember them + as one operation. */ + rl_begin_undo_group (); + + /* Do the stuff at word2 first, so that we don't have to worry + about word1 moving. */ + rl_point = w2_beg; + rl_delete_text (w2_beg, w2_end); + rl_insert_text (word1); + + rl_point = w1_beg; + rl_delete_text (w1_beg, w1_end); + rl_insert_text (word2); + + /* This is exactly correct since the text before this point has not + changed in length. */ + rl_point = w2_end; + + /* I think that does it. */ + rl_end_undo_group (); + free (word1); + free (word2); + + return 0; +} + +/* Transpose the characters at point. If point is at the end of the line, + then transpose the characters before point. */ +int +rl_transpose_chars (count, key) + int count, key __attribute__((unused)); +{ +#if defined (HANDLE_MULTIBYTE) + char *dummy; + int i, prev_point; +#else + char dummy[2]; +#endif + int char_length; + + if (count == 0) + return 0; + + if (!rl_point || rl_end < 2) + { + rl_ding (); + return -1; + } + + rl_begin_undo_group (); + + if (rl_point == rl_end) + { + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); + else + --rl_point; + count = 1; + } + +#if defined (HANDLE_MULTIBYTE) + prev_point = rl_point; + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); + else +#endif + rl_point--; + +#if defined (HANDLE_MULTIBYTE) + char_length = prev_point - rl_point; + dummy = (char *)xmalloc (char_length + 1); + for (i = 0; i < char_length; i++) + dummy[i] = rl_line_buffer[rl_point + i]; + dummy[i] = '\0'; +#else + dummy[0] = rl_line_buffer[rl_point]; + dummy[char_length = 1] = '\0'; +#endif + + rl_delete_text (rl_point, rl_point + char_length); + + rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO); + + _rl_fix_point (0); + rl_insert_text (dummy); + rl_end_undo_group (); + +#if defined (HANDLE_MULTIBYTE) + free (dummy); +#endif + + return 0; +} + +/* **************************************************************** */ +/* */ +/* Character Searching */ +/* */ +/* **************************************************************** */ + +int +#if defined (HANDLE_MULTIBYTE) +_rl_char_search_internal (count, dir, smbchar, len) + int count, dir; + char *smbchar; + int len; +#else +_rl_char_search_internal (count, dir, schar) + int count, dir, schar; +#endif +{ + int pos, inc; +#if defined (HANDLE_MULTIBYTE) + int prepos; +#endif + + pos = rl_point; + inc = (dir < 0) ? -1 : 1; + while (count) + { + if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end)) + { + rl_ding (); + return -1; + } + +#if defined (HANDLE_MULTIBYTE) + pos = (inc > 0) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY) + : _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY); +#else + pos += inc; +#endif + do + { +#if defined (HANDLE_MULTIBYTE) + if (_rl_is_mbchar_matched (rl_line_buffer, pos, rl_end, smbchar, len)) +#else + if (rl_line_buffer[pos] == schar) +#endif + { + count--; + if (dir < 0) + rl_point = (dir == BTO) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY) + : pos; + else + rl_point = (dir == FTO) ? _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY) + : pos; + break; + } +#if defined (HANDLE_MULTIBYTE) + prepos = pos; +#endif + } +#if defined (HANDLE_MULTIBYTE) + while ((dir < 0) ? (pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)) != prepos + : (pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)) != prepos); +#else + while ((dir < 0) ? pos-- : ++pos < rl_end); +#endif + } + return (0); +} + +/* Search COUNT times for a character read from the current input stream. + FDIR is the direction to search if COUNT is non-negative; otherwise + the search goes in BDIR. So much is dependent on HANDLE_MULTIBYTE + that there are two separate versions of this function. */ +#if defined (HANDLE_MULTIBYTE) +static int +_rl_char_search (count, fdir, bdir) + int count, fdir, bdir; +{ + char mbchar[MB_LEN_MAX]; + int mb_len; + + mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX); + + if (count < 0) + return (_rl_char_search_internal (-count, bdir, mbchar, mb_len)); + else + return (_rl_char_search_internal (count, fdir, mbchar, mb_len)); +} +#else /* !HANDLE_MULTIBYTE */ +static int +_rl_char_search (count, fdir, bdir) + int count, fdir, bdir; +{ + int c; + + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (count < 0) + return (_rl_char_search_internal (-count, bdir, c)); + else + return (_rl_char_search_internal (count, fdir, c)); +} +#endif /* !HANDLE_MULTIBYTE */ + +int +rl_char_search (count, key) + int count, key __attribute__((unused)); +{ + return (_rl_char_search (count, FFIND, BFIND)); +} + +int +rl_backward_char_search (count, key) + int count, key __attribute__((unused)); +{ + return (_rl_char_search (count, BFIND, FFIND)); +} + +/* **************************************************************** */ +/* */ +/* The Mark and the Region. */ +/* */ +/* **************************************************************** */ + +/* Set the mark at POSITION. */ +int +_rl_set_mark_at_pos (position) + int position; +{ + if (position > rl_end) + return -1; + + rl_mark = position; + return 0; +} + +/* A bindable command to set the mark. */ +int +rl_set_mark (count, key) + int count, key __attribute__((unused)); +{ + return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point)); +} + +/* Exchange the position of mark and point. */ +int +rl_exchange_point_and_mark (count, key) + int count __attribute__((unused)), key __attribute__((unused)); +{ + if (rl_mark > rl_end) + rl_mark = -1; + + if (rl_mark == -1) + { + rl_ding (); + return -1; + } + else + SWAP (rl_point, rl_mark); + + return 0; +} diff --git a/readline/tilde.c b/readline/tilde.c index 05c9ed741ed..11209903cf8 100644 --- a/readline/tilde.c +++ b/readline/tilde.c @@ -7,7 +7,7 @@ Readline 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 + Free Software Foundation; either version 2, or (at your option) any later version. Readline is distributed in the hope that it will be useful, but @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with Readline; see the file COPYING. If not, write to the Free - Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #if defined (HAVE_CONFIG_H) # include @@ -47,16 +47,19 @@ #include "tilde.h" +#if defined (TEST) || defined (STATIC_MALLOC) +static void *xmalloc (), *xrealloc (); +#else +# include "xmalloc.h" +#endif /* TEST || STATIC_MALLOC */ + #if !defined (HAVE_GETPW_DECLS) -extern struct passwd *getpwuid (), *getpwnam (); +extern struct passwd *getpwuid PARAMS((uid_t)); +extern struct passwd *getpwnam PARAMS((const char *)); #endif /* !HAVE_GETPW_DECLS */ #if !defined (savestring) -extern char *xmalloc (); -# ifndef strcpy -extern char *strcpy (); -# endif -#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x)) +#define savestring(x) strcpy ((char *)xmalloc (1 + strlen (x)), (x)) #endif /* !savestring */ #if !defined (NULL) @@ -67,62 +70,63 @@ extern char *strcpy (); # endif /* !__STDC__ */ #endif /* !NULL */ -#if defined (TEST) || defined (STATIC_MALLOC) -static char *xmalloc (), *xrealloc (); -#else -extern char *xmalloc (), *xrealloc (); -#endif /* TEST || STATIC_MALLOC */ - /* If being compiled as part of bash, these will be satisfied from variables.o. If being compiled as part of readline, they will be satisfied from shell.o. */ -extern char *get_home_dir (); -extern char *get_env_value (); +extern char *sh_get_home_dir PARAMS((void)); +extern char *sh_get_env_value PARAMS((const char *)); /* The default value of tilde_additional_prefixes. This is set to whitespace preceding a tilde so that simple programs which do not perform any word separation get desired behaviour. */ static const char *default_prefixes[] = - { " ~", "\t~", (char *)NULL }; + { " ~", "\t~", (const char *)NULL }; /* The default value of tilde_additional_suffixes. This is set to whitespace or newline so that simple programs which do not perform any word separation get desired behaviour. */ static const char *default_suffixes[] = - { " ", "\n", (char *)NULL }; + { " ", "\n", (const char *)NULL }; /* If non-null, this contains the address of a function that the application wants called before trying the standard tilde expansions. The function is called with the text sans tilde, and returns a malloc()'ed string which is the expansion, or a NULL pointer if the expansion fails. */ -CPFunction *tilde_expansion_preexpansion_hook = (CPFunction *)NULL; +tilde_hook_func_t *tilde_expansion_preexpansion_hook = (tilde_hook_func_t *)NULL; /* If non-null, this contains the address of a function to call if the standard meaning for expanding a tilde fails. The function is called with the text (sans tilde, as in "foo"), and returns a malloc()'ed string which is the expansion, or a NULL pointer if there is no expansion. */ -CPFunction *tilde_expansion_failure_hook = (CPFunction *)NULL; +tilde_hook_func_t *tilde_expansion_failure_hook = (tilde_hook_func_t *)NULL; /* When non-null, this is a NULL terminated array of strings which are duplicates for a tilde prefix. Bash uses this to expand `=~' and `:~'. */ -const char ** tilde_additional_prefixes = default_prefixes; +char **tilde_additional_prefixes = (char **)default_prefixes; /* When non-null, this is a NULL terminated array of strings which match the end of a username, instead of just "/". Bash sets this to `:' and `=~'. */ -const char **tilde_additional_suffixes = default_suffixes; +char **tilde_additional_suffixes = (char **)default_suffixes; + +static int tilde_find_prefix PARAMS((const char *, int *)); +static int tilde_find_suffix PARAMS((const char *)); +static char *isolate_tilde_prefix PARAMS((const char *, int *)); +static char *glue_prefix_and_suffix PARAMS((char *, const char *, int)); /* Find the start of a tilde expansion in STRING, and return the index of the tilde which starts the expansion. Place the length of the text which identified this tilde starter in LEN, excluding the tilde itself. */ static int tilde_find_prefix (string, len) - char *string; + const char *string; int *len; { register int i, j, string_len; - register const char **prefixes = tilde_additional_prefixes; + register char **prefixes; + + prefixes = tilde_additional_prefixes; string_len = strlen (string); *len = 0; @@ -151,17 +155,21 @@ tilde_find_prefix (string, len) the character which ends the tilde definition. */ static int tilde_find_suffix (string) - char *string; + const char *string; { register int i, j, string_len; - register const char **suffixes; + register char **suffixes; suffixes = tilde_additional_suffixes; string_len = strlen (string); for (i = 0; i < string_len; i++) { +#if defined (__MSDOS__) + if (string[i] == '/' || string[i] == '\\' /* || !string[i] */) +#else if (string[i] == '/' /* || !string[i] */) +#endif break; for (j = 0; suffixes && suffixes[j]; j++) @@ -176,16 +184,16 @@ tilde_find_suffix (string) /* Return a new string which is the result of tilde expanding STRING. */ char * tilde_expand (string) - char *string; + const char *string; { char *result; int result_size, result_index; result_index = result_size = 0; - if ((result = strchr (string, '~'))) - result = xmalloc (result_size = (strlen (string) + 16)); + if ((result = (char*)strchr(string, '~'))) + result = (char *)xmalloc (result_size = (strlen (string) + 16)); else - result = xmalloc (result_size = (strlen (string) + 1)); + result = (char *)xmalloc (result_size = (strlen (string) + 1)); /* Scan through STRING expanding tildes as we come to them. */ while (1) @@ -199,7 +207,7 @@ tilde_expand (string) /* Copy the skipped text into the result. */ if ((result_index + start + 1) > result_size) - result = xrealloc (result, 1 + (result_size += (start + 20))); + result = (char *)xrealloc (result, 1 + (result_size += (start + 20))); strncpy (result + result_index, string, start); result_index += start; @@ -216,7 +224,7 @@ tilde_expand (string) break; /* Expand the entire tilde word, and copy it into RESULT. */ - tilde_word = xmalloc (1 + end); + tilde_word = (char *)xmalloc (1 + end); strncpy (tilde_word, string, end); tilde_word[end] = '\0'; string += end; @@ -225,11 +233,18 @@ tilde_expand (string) free (tilde_word); len = strlen (expansion); - if ((result_index + len + 1) > result_size) - result = xrealloc (result, 1 + (result_size += (len + 20))); +#ifdef __CYGWIN__ + /* Fix for Cygwin to prevent ~user/xxx from expanding to //xxx when + $HOME for `user' is /. On cygwin, // denotes a network drive. */ + if (len > 1 || *expansion != '/' || *string != '/') +#endif + { + if ((result_index + len + 1) > result_size) + result = (char *)xrealloc (result, 1 + (result_size += (len + 20))); - strcpy (result + result_index, expansion); - result_index += len; + strcpy (result + result_index, expansion); + result_index += len; + } free (expansion); } @@ -243,14 +258,18 @@ tilde_expand (string) the location it points to. */ static char * isolate_tilde_prefix (fname, lenp) - char *fname; + const char *fname; int *lenp; { char *ret; int i; - ret = xmalloc (strlen (fname)); + ret = (char *)xmalloc (strlen (fname)); +#if defined (__MSDOS__) + for (i = 1; fname[i] && fname[i] != '/' && fname[i] != '\\'; i++) +#else for (i = 1; fname[i] && fname[i] != '/'; i++) +#endif ret[i - 1] = fname[i]; ret[i - 1] = '\0'; if (lenp) @@ -262,7 +281,8 @@ isolate_tilde_prefix (fname, lenp) SUFFIND. */ static char * glue_prefix_and_suffix (prefix, suffix, suffind) - char *prefix, *suffix; + char *prefix; + const char *suffix; int suffind; { char *ret; @@ -270,8 +290,8 @@ glue_prefix_and_suffix (prefix, suffix, suffind) plen = (prefix && *prefix) ? strlen (prefix) : 0; slen = strlen (suffix + suffind); - ret = xmalloc (plen + slen + 1); - if (prefix && *prefix) + ret = (char *)xmalloc (plen + slen + 1); + if (plen) strcpy (ret, prefix); strcpy (ret + plen, suffix + suffind); return ret; @@ -282,7 +302,7 @@ glue_prefix_and_suffix (prefix, suffix, suffind) This always returns a newly-allocated string, never static storage. */ char * tilde_expand_word (filename) - char *filename; + const char *filename; { char *dirname, *expansion, *username; int user_len; @@ -300,12 +320,12 @@ tilde_expand_word (filename) if (filename[1] == '\0' || filename[1] == '/') { /* Prefix $HOME to the rest of the string. */ - expansion = get_env_value ("HOME"); + expansion = sh_get_env_value ("HOME"); /* If there is no HOME variable, look up the directory in the password database. */ if (expansion == 0) - expansion = get_home_dir (); + expansion = sh_get_home_dir (); return (glue_prefix_and_suffix (expansion, filename, 1)); } @@ -394,28 +414,28 @@ main (argc, argv) static void memory_error_and_abort (); -static char * +static void * xmalloc (bytes) - int bytes; + size_t bytes; { - char *temp = (char *)malloc (bytes); + void *temp = (char *)malloc (bytes); if (!temp) memory_error_and_abort (); return (temp); } -static char * +static void * xrealloc (pointer, bytes) - char *pointer; + void *pointer; int bytes; { - char *temp; + void *temp; if (!pointer) - temp = (char *)malloc (bytes); + temp = malloc (bytes); else - temp = (char *)realloc (pointer, bytes); + temp = realloc (pointer, bytes); if (!temp) memory_error_and_abort (); diff --git a/readline/tilde.h b/readline/tilde.h index 45eea1b66e5..f8182c999d9 100644 --- a/readline/tilde.h +++ b/readline/tilde.h @@ -8,7 +8,7 @@ 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 1, or (at your option) + 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 @@ -19,47 +19,60 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #if !defined (_TILDE_H_) # define _TILDE_H_ -/* Function pointers can be declared as (Function *)foo. */ -#if !defined (_FUNCTION_DEF) -# define _FUNCTION_DEF -typedef int Function (); -typedef void VFunction (); -typedef char *CPFunction (); -typedef char **CPPFunction (); -#endif /* _FUNCTION_DEF */ +#ifdef __cplusplus +extern "C" { +#endif + +/* A function can be defined using prototypes and compile on both ANSI C + and traditional C compilers with something like this: + extern char *func PARAMS((char *, char *, int)); */ + +#if !defined (PARAMS) +# if defined (__STDC__) || defined (__GNUC__) || defined (__cplusplus) +# define PARAMS(protos) protos +# else +# define PARAMS(protos) () +# endif +#endif + +typedef char *tilde_hook_func_t PARAMS((char *)); /* If non-null, this contains the address of a function that the application wants called before trying the standard tilde expansions. The function is called with the text sans tilde, and returns a malloc()'ed string which is the expansion, or a NULL pointer if the expansion fails. */ -extern CPFunction *tilde_expansion_preexpansion_hook; +extern tilde_hook_func_t *tilde_expansion_preexpansion_hook; /* If non-null, this contains the address of a function to call if the standard meaning for expanding a tilde fails. The function is called with the text (sans tilde, as in "foo"), and returns a malloc()'ed string which is the expansion, or a NULL pointer if there is no expansion. */ -extern CPFunction *tilde_expansion_failure_hook; +extern tilde_hook_func_t *tilde_expansion_failure_hook; /* When non-null, this is a NULL terminated array of strings which are duplicates for a tilde prefix. Bash uses this to expand `=~' and `:~'. */ -extern const char **tilde_additional_prefixes; +extern char **tilde_additional_prefixes; /* When non-null, this is a NULL terminated array of strings which match the end of a username, instead of just "/". Bash sets this to `:' and `=~'. */ -extern const char **tilde_additional_suffixes; +extern char **tilde_additional_suffixes; /* Return a new string which is the result of tilde expanding STRING. */ -extern char *tilde_expand (); +extern char *tilde_expand PARAMS((const char *)); /* Do the work of tilde expansion on FILENAME. FILENAME starts with a tilde. If there is no expansion, call tilde_expansion_failure_hook. */ -extern char *tilde_expand_word (); +extern char *tilde_expand_word PARAMS((const char *)); + +#ifdef __cplusplus +} +#endif #endif /* _TILDE_H_ */ diff --git a/readline/undo.c b/readline/undo.c index c8f4892b774..df913195fad 100644 --- a/readline/undo.c +++ b/readline/undo.c @@ -8,7 +8,7 @@ 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 1, or + 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 @@ -19,7 +19,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) @@ -47,7 +47,8 @@ #include "readline.h" #include "history.h" -#define SWAP(s, e) do { int t; t = s; s = e; e = t; } while (0) +#include "rlprivate.h" +#include "xmalloc.h" /* Non-zero tells rl_delete_text and rl_insert_text to not add to the undo list. */ @@ -84,7 +85,7 @@ rl_add_undo (what, start, end, text) /* Free the existing undo list. */ void -free_undo_list () +rl_free_undo_list () { while (rl_undo_list) { @@ -105,17 +106,18 @@ int rl_do_undo () { UNDO_LIST *release; - int waiting_for_begin = 0; - int start = 0, end = 0; + 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. */ @@ -150,11 +152,12 @@ rl_do_undo () if (waiting_for_begin) waiting_for_begin--; else - ding (); + rl_ding (); break; } _rl_doing_an_undo = 0; + RL_UNSETSTATE(RL_STATE_UNDOING); release = rl_undo_list; rl_undo_list = rl_undo_list->next; @@ -168,13 +171,14 @@ rl_do_undo () int _rl_fix_last_undo_of_type (type, start, end) - int type, start, end; + unsigned int type; + int start, end; { UNDO_LIST *rl; for (rl = rl_undo_list; rl; rl = rl->next) { - if ((int) rl->what == type) + if (rl->what == type) { rl->start = start; rl->end = end; @@ -225,11 +229,11 @@ rl_modifying (start, end) /* Revert the current line to its previous state. */ int -rl_revert_line (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_revert_line (count, key) + int count __attribute__((unused)), key __attribute__((unused)); { if (!rl_undo_list) - ding (); + rl_ding (); else { while (rl_undo_list) @@ -240,7 +244,8 @@ rl_revert_line (int count __attribute__((unused)), /* Do some undoing of things that were done. */ int -rl_undo_command (int count, int key __attribute__((unused))) +rl_undo_command (count, key) + int count, key __attribute__((unused)); { if (count < 0) return 0; /* Nothing to do. */ @@ -251,7 +256,7 @@ rl_undo_command (int count, int key __attribute__((unused))) count--; else { - ding (); + rl_ding (); break; } } diff --git a/readline/util.c b/readline/util.c index bcd8f3bc5b2..2a6e4e3398a 100644 --- a/readline/util.c +++ b/readline/util.c @@ -7,7 +7,7 @@ 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 1, or + 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 @@ -18,7 +18,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) @@ -52,24 +52,8 @@ /* Some standard library routines. */ #include "readline.h" -#define SWAP(s, e) do { int t; t = s; s = e; e = t; } while (0) - -/* Pseudo-globals imported from readline.c */ -extern int readline_echoing_p; -extern procenv_t readline_top_level; -extern int rl_line_buffer_len; -extern Function *rl_last_func; - -extern int _rl_defining_kbd_macro; -extern char *_rl_executing_macro; - -/* Pseudo-global functions imported from other library files. */ -extern void _rl_replace_text (); -extern void _rl_pop_executing_macro (); -extern void _rl_set_the_line (); -extern void _rl_init_argument (); - -extern char *xmalloc (), *xrealloc (); +#include "rlprivate.h" +#include "xmalloc.h" /* **************************************************************** */ /* */ @@ -84,7 +68,7 @@ int _rl_allow_pathname_alphabetic_chars = 0; static const char *pathname_alphabetic_chars = "/-_=~.#$"; int -alphabetic (c) +rl_alphabetic (c) int c; { if (ALPHABETIC (c)) @@ -98,36 +82,36 @@ alphabetic (c) int _rl_abort_internal () { - ding (); + rl_ding (); rl_clear_message (); _rl_init_argument (); - rl_pending_input = 0; + rl_clear_pending_input (); - _rl_defining_kbd_macro = 0; - while (_rl_executing_macro) + RL_UNSETSTATE (RL_STATE_MACRODEF); + while (rl_executing_macro) _rl_pop_executing_macro (); - rl_last_func = (Function *)NULL; + rl_last_func = (rl_command_func_t *)NULL; longjmp (readline_top_level, 1); return (0); } int -rl_abort (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_abort (count, key) + int count __attribute__((unused)), key __attribute__((unused)); { return (_rl_abort_internal ()); } int -rl_tty_status (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_tty_status (count, key) + int count __attribute__((unused)), key __attribute__((unused)); { #if defined (TIOCSTAT) ioctl (1, TIOCSTAT, (char *)0); rl_refresh_line (count, key); #else - ding (); + rl_ding (); #endif return 0; } @@ -146,7 +130,7 @@ rl_copy_text (from, to) SWAP (from, to); length = to - from; - copy = xmalloc (1 + length); + copy = (char *)xmalloc (1 + length); strncpy (copy, rl_line_buffer + from, length); copy[length] = '\0'; return (copy); @@ -161,7 +145,7 @@ rl_extend_line_buffer (len) while (len >= rl_line_buffer_len) { rl_line_buffer_len += DEFAULT_BUFFER_SIZE; - rl_line_buffer = xrealloc (rl_line_buffer, rl_line_buffer_len); + rl_line_buffer = (char *)xrealloc (rl_line_buffer, rl_line_buffer_len); } _rl_set_the_line (); @@ -170,8 +154,8 @@ rl_extend_line_buffer (len) /* A function for simple tilde expansion. */ int -rl_tilde_expand (int ignore __attribute__((unused)), - int key __attribute__((unused))) +rl_tilde_expand (ignore, key) + int ignore __attribute__((unused)), key __attribute__((unused)); { register int start, end; char *homedir, *temp; @@ -207,7 +191,7 @@ rl_tilde_expand (int ignore __attribute__((unused)), if (rl_line_buffer[start] == '~') { len = end - start + 1; - temp = xmalloc (len + 1); + temp = (char *)xmalloc (len + 1); strncpy (temp, rl_line_buffer + start, len); temp[len] = '\0'; homedir = tilde_expand (temp); @@ -229,16 +213,51 @@ rl_tilde_expand (int ignore __attribute__((unused)), match in s1. The compare is case insensitive. */ char * _rl_strindex (s1, s2) - register char *s1, *s2; + register const char *s1, *s2; { register int i, l, len; for (i = 0, l = strlen (s2), len = strlen (s1); (len - i) >= l; i++) if (_rl_strnicmp (s1 + i, s2, l) == 0) - return (s1 + i); + return ((char *) (s1 + i)); return ((char *)NULL); } +#ifndef HAVE_STRPBRK +/* Find the first occurrence in STRING1 of any character from STRING2. + Return a pointer to the character in STRING1. */ +char * +_rl_strpbrk (string1, string2) + const char *string1, *string2; +{ + register const char *scan; +#if defined (HANDLE_MULTIBYTE) + mbstate_t ps; + register int i, v; + + memset (&ps, 0, sizeof (mbstate_t)); +#endif + + for (; *string1; string1++) + { + for (scan = string2; *scan; scan++) + { + if (*string1 == *scan) + return ((char *)string1); + } +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + v = _rl_get_char_len (string1, &ps); + if (v > 1) + string += v - 1; /* -1 to account for auto-increment in loop */ + } +#endif + } + return ((char *)NULL); +} +#endif + #if !defined (HAVE_STRCASECMP) /* Compare at most COUNT characters from string1 to string2. Case doesn't matter. */ @@ -297,69 +316,23 @@ _rl_qsort_string_compare (s1, s2) #endif } -/* Function equivalents for the macros defined in chartypes.h. */ -#undef _rl_uppercase_p -int -_rl_uppercase_p (c) - int c; -{ - return (isupper (c)); -} +/* Function equivalents for the macros defined in chardefs.h. */ +#define FUNCTION_FOR_MACRO(f) int (f) (c) int c; { return f (c); } -#undef _rl_lowercase_p -int -_rl_lowercase_p (c) - int c; -{ - return (islower (c)); -} - -#undef _rl_pure_alphabetic -int -_rl_pure_alphabetic (c) - int c; -{ - return (isupper (c) || islower (c)); -} - -#undef _rl_digit_p -int -_rl_digit_p (c) - int c; -{ - return (isdigit (c)); -} - -#undef _rl_to_lower -int -_rl_to_lower (c) - int c; -{ - return (isupper (c) ? tolower (c) : c); -} - -#undef _rl_to_upper -int -_rl_to_upper (c) - int c; -{ - return (islower (c) ? toupper (c) : c); -} - -#undef _rl_digit_value -int -_rl_digit_value (c) - int c; -{ - return (isdigit (c) ? c - '0' : c); -} +FUNCTION_FOR_MACRO (_rl_digit_p) +FUNCTION_FOR_MACRO (_rl_digit_value) +FUNCTION_FOR_MACRO (_rl_lowercase_p) +FUNCTION_FOR_MACRO (_rl_pure_alphabetic) +FUNCTION_FOR_MACRO (_rl_to_lower) +FUNCTION_FOR_MACRO (_rl_to_upper) +FUNCTION_FOR_MACRO (_rl_uppercase_p) /* Backwards compatibility, now that savestring has been removed from all `public' readline header files. */ #undef _rl_savestring char * _rl_savestring (s) - char *s; + const char *s; { - return ((char *)strcpy (xmalloc (1 + (int)strlen (s)), (s))); + return (strcpy ((char *)xmalloc (1 + (int)strlen (s)), (s))); } diff --git a/readline/vi_keymap.c b/readline/vi_keymap.c index 14929a31930..53a67c674ce 100644 --- a/readline/vi_keymap.c +++ b/readline/vi_keymap.c @@ -7,7 +7,7 @@ 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 1, or + 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 @@ -18,7 +18,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #if !defined (BUFSIZ) #include @@ -33,429 +33,429 @@ extern KEYMAP_ENTRY_ARRAY vi_escape_keymap; /* The keymap arrays for handling vi mode. */ KEYMAP_ENTRY_ARRAY vi_movement_keymap = { /* The regular control keys come first. */ - { ISFUNC, (Function *)0x0 }, /* Control-@ */ - { ISFUNC, (Function *)0x0 }, /* Control-a */ - { ISFUNC, (Function *)0x0 }, /* Control-b */ - { ISFUNC, (Function *)0x0 }, /* Control-c */ - { ISFUNC, rl_vi_eof_maybe }, /* Control-d */ - { ISFUNC, rl_emacs_editing_mode }, /* Control-e */ - { ISFUNC, (Function *)0x0 }, /* Control-f */ - { ISFUNC, rl_abort }, /* Control-g */ - { ISFUNC, rl_backward }, /* Control-h */ - { ISFUNC, (Function *)0x0 }, /* Control-i */ - { ISFUNC, rl_newline }, /* Control-j */ - { ISFUNC, rl_kill_line }, /* Control-k */ - { ISFUNC, rl_clear_screen }, /* Control-l */ - { ISFUNC, rl_newline }, /* Control-m */ - { ISFUNC, rl_get_next_history }, /* Control-n */ - { ISFUNC, (Function *)0x0 }, /* Control-o */ - { ISFUNC, rl_get_previous_history }, /* Control-p */ - { ISFUNC, rl_quoted_insert }, /* Control-q */ - { ISFUNC, rl_reverse_search_history }, /* Control-r */ - { ISFUNC, rl_forward_search_history }, /* Control-s */ - { ISFUNC, rl_transpose_chars }, /* Control-t */ - { ISFUNC, rl_unix_line_discard }, /* Control-u */ - { ISFUNC, rl_quoted_insert }, /* Control-v */ - { ISFUNC, rl_unix_word_rubout }, /* Control-w */ - { ISFUNC, (Function *)0x0 }, /* Control-x */ - { ISFUNC, rl_yank }, /* Control-y */ - { ISFUNC, (Function *)0x0 }, /* Control-z */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-@ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-a */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-b */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-c */ + { ISFUNC, rl_vi_eof_maybe }, /* Control-d */ + { ISFUNC, rl_emacs_editing_mode }, /* Control-e */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-f */ + { ISFUNC, rl_abort }, /* Control-g */ + { ISFUNC, rl_backward_char }, /* Control-h */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-i */ + { ISFUNC, rl_newline }, /* Control-j */ + { ISFUNC, rl_kill_line }, /* Control-k */ + { ISFUNC, rl_clear_screen }, /* Control-l */ + { ISFUNC, rl_newline }, /* Control-m */ + { ISFUNC, rl_get_next_history }, /* Control-n */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-o */ + { ISFUNC, rl_get_previous_history }, /* Control-p */ + { ISFUNC, rl_quoted_insert }, /* Control-q */ + { ISFUNC, rl_reverse_search_history }, /* Control-r */ + { ISFUNC, rl_forward_search_history }, /* Control-s */ + { ISFUNC, rl_transpose_chars }, /* Control-t */ + { ISFUNC, rl_unix_line_discard }, /* Control-u */ + { ISFUNC, rl_quoted_insert }, /* Control-v */ + { ISFUNC, rl_unix_word_rubout }, /* Control-w */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-x */ + { ISFUNC, rl_yank }, /* Control-y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-z */ - { ISFUNC, (Function *)0x0 }, /* Control-[ */ /* vi_escape_keymap */ - { ISFUNC, (Function *)0x0 }, /* Control-\ */ - { ISFUNC, (Function *)0x0 }, /* Control-] */ - { ISFUNC, (Function *)0x0 }, /* Control-^ */ - { ISFUNC, rl_vi_undo }, /* Control-_ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-[ */ /* vi_escape_keymap */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-\ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-] */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-^ */ + { ISFUNC, rl_vi_undo }, /* Control-_ */ /* The start of printing characters. */ - { ISFUNC, rl_forward }, /* SPACE */ - { ISFUNC, (Function *)0x0 }, /* ! */ - { ISFUNC, (Function *)0x0 }, /* " */ - { ISFUNC, rl_insert_comment }, /* # */ - { ISFUNC, rl_end_of_line }, /* $ */ - { ISFUNC, rl_vi_match }, /* % */ - { ISFUNC, rl_vi_tilde_expand }, /* & */ - { ISFUNC, (Function *)0x0 }, /* ' */ - { ISFUNC, (Function *)0x0 }, /* ( */ - { ISFUNC, (Function *)0x0 }, /* ) */ - { ISFUNC, rl_vi_complete }, /* * */ - { ISFUNC, rl_get_next_history}, /* + */ - { ISFUNC, rl_vi_char_search }, /* , */ - { ISFUNC, rl_get_previous_history }, /* - */ - { ISFUNC, rl_vi_redo }, /* . */ - { ISFUNC, rl_vi_search }, /* / */ + { ISFUNC, rl_forward_char }, /* SPACE */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ! */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* " */ + { ISFUNC, rl_insert_comment }, /* # */ + { ISFUNC, rl_end_of_line }, /* $ */ + { ISFUNC, rl_vi_match }, /* % */ + { ISFUNC, rl_vi_tilde_expand }, /* & */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ' */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ( */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ) */ + { ISFUNC, rl_vi_complete }, /* * */ + { ISFUNC, rl_get_next_history}, /* + */ + { ISFUNC, rl_vi_char_search }, /* , */ + { ISFUNC, rl_get_previous_history }, /* - */ + { ISFUNC, rl_vi_redo }, /* . */ + { ISFUNC, rl_vi_search }, /* / */ /* Regular digits. */ - { ISFUNC, rl_beg_of_line }, /* 0 */ - { ISFUNC, rl_vi_arg_digit }, /* 1 */ - { ISFUNC, rl_vi_arg_digit }, /* 2 */ - { ISFUNC, rl_vi_arg_digit }, /* 3 */ - { ISFUNC, rl_vi_arg_digit }, /* 4 */ - { ISFUNC, rl_vi_arg_digit }, /* 5 */ - { ISFUNC, rl_vi_arg_digit }, /* 6 */ - { ISFUNC, rl_vi_arg_digit }, /* 7 */ - { ISFUNC, rl_vi_arg_digit }, /* 8 */ - { ISFUNC, rl_vi_arg_digit }, /* 9 */ + { ISFUNC, rl_beg_of_line }, /* 0 */ + { ISFUNC, rl_vi_arg_digit }, /* 1 */ + { ISFUNC, rl_vi_arg_digit }, /* 2 */ + { ISFUNC, rl_vi_arg_digit }, /* 3 */ + { ISFUNC, rl_vi_arg_digit }, /* 4 */ + { ISFUNC, rl_vi_arg_digit }, /* 5 */ + { ISFUNC, rl_vi_arg_digit }, /* 6 */ + { ISFUNC, rl_vi_arg_digit }, /* 7 */ + { ISFUNC, rl_vi_arg_digit }, /* 8 */ + { ISFUNC, rl_vi_arg_digit }, /* 9 */ /* A little more punctuation. */ - { ISFUNC, (Function *)0x0 }, /* : */ - { ISFUNC, rl_vi_char_search }, /* ; */ - { ISFUNC, (Function *)0x0 }, /* < */ - { ISFUNC, rl_vi_complete }, /* = */ - { ISFUNC, (Function *)0x0 }, /* > */ - { ISFUNC, rl_vi_search }, /* ? */ - { ISFUNC, (Function *)0x0 }, /* @ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* : */ + { ISFUNC, rl_vi_char_search }, /* ; */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* < */ + { ISFUNC, rl_vi_complete }, /* = */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* > */ + { ISFUNC, rl_vi_search }, /* ? */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* @ */ /* Uppercase alphabet. */ - { ISFUNC, rl_vi_append_eol }, /* A */ - { ISFUNC, rl_vi_prev_word}, /* B */ - { ISFUNC, rl_vi_change_to }, /* C */ - { ISFUNC, rl_vi_delete_to }, /* D */ - { ISFUNC, rl_vi_end_word }, /* E */ - { ISFUNC, rl_vi_char_search }, /* F */ - { ISFUNC, rl_vi_fetch_history }, /* G */ - { ISFUNC, (Function *)0x0 }, /* H */ - { ISFUNC, rl_vi_insert_beg }, /* I */ - { ISFUNC, (Function *)0x0 }, /* J */ - { ISFUNC, (Function *)0x0 }, /* K */ - { ISFUNC, (Function *)0x0 }, /* L */ - { ISFUNC, (Function *)0x0 }, /* M */ - { ISFUNC, rl_vi_search_again }, /* N */ - { ISFUNC, (Function *)0x0 }, /* O */ - { ISFUNC, rl_vi_put }, /* P */ - { ISFUNC, (Function *)0x0 }, /* Q */ - { ISFUNC, rl_vi_replace }, /* R */ - { ISFUNC, rl_vi_subst }, /* S */ - { ISFUNC, rl_vi_char_search }, /* T */ - { ISFUNC, rl_revert_line }, /* U */ - { ISFUNC, (Function *)0x0 }, /* V */ - { ISFUNC, rl_vi_next_word }, /* W */ - { ISFUNC, rl_rubout }, /* X */ - { ISFUNC, rl_vi_yank_to }, /* Y */ - { ISFUNC, (Function *)0x0 }, /* Z */ + { ISFUNC, rl_vi_append_eol }, /* A */ + { ISFUNC, rl_vi_prev_word}, /* B */ + { ISFUNC, rl_vi_change_to }, /* C */ + { ISFUNC, rl_vi_delete_to }, /* D */ + { ISFUNC, rl_vi_end_word }, /* E */ + { ISFUNC, rl_vi_char_search }, /* F */ + { ISFUNC, rl_vi_fetch_history }, /* G */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* H */ + { ISFUNC, rl_vi_insert_beg }, /* I */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* J */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* K */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* L */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* M */ + { ISFUNC, rl_vi_search_again }, /* N */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* O */ + { ISFUNC, rl_vi_put }, /* P */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Q */ + { ISFUNC, rl_vi_replace }, /* R */ + { ISFUNC, rl_vi_subst }, /* S */ + { ISFUNC, rl_vi_char_search }, /* T */ + { ISFUNC, rl_revert_line }, /* U */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* V */ + { ISFUNC, rl_vi_next_word }, /* W */ + { ISFUNC, rl_rubout }, /* X */ + { ISFUNC, rl_vi_yank_to }, /* Y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Z */ /* Some more punctuation. */ - { ISFUNC, (Function *)0x0 }, /* [ */ - { ISFUNC, rl_vi_complete }, /* \ */ - { ISFUNC, (Function *)0x0 }, /* ] */ - { ISFUNC, rl_vi_first_print }, /* ^ */ - { ISFUNC, rl_vi_yank_arg }, /* _ */ - { ISFUNC, rl_vi_goto_mark }, /* ` */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* [ */ + { ISFUNC, rl_vi_complete }, /* \ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ] */ + { ISFUNC, rl_vi_first_print }, /* ^ */ + { ISFUNC, rl_vi_yank_arg }, /* _ */ + { ISFUNC, rl_vi_goto_mark }, /* ` */ /* Lowercase alphabet. */ - { ISFUNC, rl_vi_append_mode }, /* a */ - { ISFUNC, rl_vi_prev_word }, /* b */ - { ISFUNC, rl_vi_change_to }, /* c */ - { ISFUNC, rl_vi_delete_to }, /* d */ - { ISFUNC, rl_vi_end_word }, /* e */ - { ISFUNC, rl_vi_char_search }, /* f */ - { ISFUNC, (Function *)0x0 }, /* g */ - { ISFUNC, rl_backward }, /* h */ - { ISFUNC, rl_vi_insertion_mode }, /* i */ - { ISFUNC, rl_get_next_history }, /* j */ - { ISFUNC, rl_get_previous_history }, /* k */ - { ISFUNC, rl_forward }, /* l */ - { ISFUNC, rl_vi_set_mark }, /* m */ - { ISFUNC, rl_vi_search_again }, /* n */ - { ISFUNC, (Function *)0x0 }, /* o */ - { ISFUNC, rl_vi_put }, /* p */ - { ISFUNC, (Function *)0x0 }, /* q */ - { ISFUNC, rl_vi_change_char }, /* r */ - { ISFUNC, rl_vi_subst }, /* s */ - { ISFUNC, rl_vi_char_search }, /* t */ - { ISFUNC, rl_vi_undo }, /* u */ - { ISFUNC, (Function *)0x0 }, /* v */ - { ISFUNC, rl_vi_next_word }, /* w */ - { ISFUNC, rl_vi_delete }, /* x */ - { ISFUNC, rl_vi_yank_to }, /* y */ - { ISFUNC, (Function *)0x0 }, /* z */ + { ISFUNC, rl_vi_append_mode }, /* a */ + { ISFUNC, rl_vi_prev_word }, /* b */ + { ISFUNC, rl_vi_change_to }, /* c */ + { ISFUNC, rl_vi_delete_to }, /* d */ + { ISFUNC, rl_vi_end_word }, /* e */ + { ISFUNC, rl_vi_char_search }, /* f */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* g */ + { ISFUNC, rl_backward_char }, /* h */ + { ISFUNC, rl_vi_insertion_mode }, /* i */ + { ISFUNC, rl_get_next_history }, /* j */ + { ISFUNC, rl_get_previous_history }, /* k */ + { ISFUNC, rl_forward_char }, /* l */ + { ISFUNC, rl_vi_set_mark }, /* m */ + { ISFUNC, rl_vi_search_again }, /* n */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* o */ + { ISFUNC, rl_vi_put }, /* p */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* q */ + { ISFUNC, rl_vi_change_char }, /* r */ + { ISFUNC, rl_vi_subst }, /* s */ + { ISFUNC, rl_vi_char_search }, /* t */ + { ISFUNC, rl_vi_undo }, /* u */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* v */ + { ISFUNC, rl_vi_next_word }, /* w */ + { ISFUNC, rl_vi_delete }, /* x */ + { ISFUNC, rl_vi_yank_to }, /* y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* z */ /* Final punctuation. */ - { ISFUNC, (Function *)0x0 }, /* { */ - { ISFUNC, rl_vi_column }, /* | */ - { ISFUNC, (Function *)0x0 }, /* } */ - { ISFUNC, rl_vi_change_case }, /* ~ */ - { ISFUNC, (Function *)0x0 }, /* RUBOUT */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* { */ + { ISFUNC, rl_vi_column }, /* | */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* } */ + { ISFUNC, rl_vi_change_case }, /* ~ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* RUBOUT */ #if KEYMAP_SIZE > 128 /* Undefined keys. */ - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 } + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 } #endif /* KEYMAP_SIZE > 128 */ }; KEYMAP_ENTRY_ARRAY vi_insertion_keymap = { /* The regular control keys come first. */ - { ISFUNC, (Function *)0x0 }, /* Control-@ */ - { ISFUNC, rl_insert }, /* Control-a */ - { ISFUNC, rl_insert }, /* Control-b */ - { ISFUNC, rl_insert }, /* Control-c */ - { ISFUNC, rl_vi_eof_maybe }, /* Control-d */ - { ISFUNC, rl_insert }, /* Control-e */ - { ISFUNC, rl_insert }, /* Control-f */ - { ISFUNC, rl_insert }, /* Control-g */ - { ISFUNC, rl_rubout }, /* Control-h */ - { ISFUNC, rl_complete }, /* Control-i */ - { ISFUNC, rl_newline }, /* Control-j */ - { ISFUNC, rl_insert }, /* Control-k */ - { ISFUNC, rl_insert }, /* Control-l */ - { ISFUNC, rl_newline }, /* Control-m */ - { ISFUNC, rl_insert }, /* Control-n */ - { ISFUNC, rl_insert }, /* Control-o */ - { ISFUNC, rl_insert }, /* Control-p */ - { ISFUNC, rl_insert }, /* Control-q */ - { ISFUNC, rl_reverse_search_history }, /* Control-r */ - { ISFUNC, rl_forward_search_history }, /* Control-s */ - { ISFUNC, rl_transpose_chars }, /* Control-t */ - { ISFUNC, rl_unix_line_discard }, /* Control-u */ - { ISFUNC, rl_quoted_insert }, /* Control-v */ - { ISFUNC, rl_unix_word_rubout }, /* Control-w */ - { ISFUNC, rl_insert }, /* Control-x */ - { ISFUNC, rl_yank }, /* Control-y */ - { ISFUNC, rl_insert }, /* Control-z */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-@ */ + { ISFUNC, rl_insert }, /* Control-a */ + { ISFUNC, rl_insert }, /* Control-b */ + { ISFUNC, rl_insert }, /* Control-c */ + { ISFUNC, rl_vi_eof_maybe }, /* Control-d */ + { ISFUNC, rl_insert }, /* Control-e */ + { ISFUNC, rl_insert }, /* Control-f */ + { ISFUNC, rl_insert }, /* Control-g */ + { ISFUNC, rl_rubout }, /* Control-h */ + { ISFUNC, rl_complete }, /* Control-i */ + { ISFUNC, rl_newline }, /* Control-j */ + { ISFUNC, rl_insert }, /* Control-k */ + { ISFUNC, rl_insert }, /* Control-l */ + { ISFUNC, rl_newline }, /* Control-m */ + { ISFUNC, rl_insert }, /* Control-n */ + { ISFUNC, rl_insert }, /* Control-o */ + { ISFUNC, rl_insert }, /* Control-p */ + { ISFUNC, rl_insert }, /* Control-q */ + { ISFUNC, rl_reverse_search_history }, /* Control-r */ + { ISFUNC, rl_forward_search_history }, /* Control-s */ + { ISFUNC, rl_transpose_chars }, /* Control-t */ + { ISFUNC, rl_unix_line_discard }, /* Control-u */ + { ISFUNC, rl_quoted_insert }, /* Control-v */ + { ISFUNC, rl_unix_word_rubout }, /* Control-w */ + { ISFUNC, rl_insert }, /* Control-x */ + { ISFUNC, rl_yank }, /* Control-y */ + { ISFUNC, rl_insert }, /* Control-z */ - { ISFUNC, rl_vi_movement_mode }, /* Control-[ */ - { ISFUNC, rl_insert }, /* Control-\ */ - { ISFUNC, rl_insert }, /* Control-] */ - { ISFUNC, rl_insert }, /* Control-^ */ - { ISFUNC, rl_vi_undo }, /* Control-_ */ + { ISFUNC, rl_vi_movement_mode }, /* Control-[ */ + { ISFUNC, rl_insert }, /* Control-\ */ + { ISFUNC, rl_insert }, /* Control-] */ + { ISFUNC, rl_insert }, /* Control-^ */ + { ISFUNC, rl_vi_undo }, /* Control-_ */ /* The start of printing characters. */ - { ISFUNC, rl_insert }, /* SPACE */ - { ISFUNC, rl_insert }, /* ! */ - { ISFUNC, rl_insert }, /* " */ - { ISFUNC, rl_insert }, /* # */ - { ISFUNC, rl_insert }, /* $ */ - { ISFUNC, rl_insert }, /* % */ - { ISFUNC, rl_insert }, /* & */ - { ISFUNC, rl_insert }, /* ' */ - { ISFUNC, rl_insert }, /* ( */ - { ISFUNC, rl_insert }, /* ) */ - { ISFUNC, rl_insert }, /* * */ - { ISFUNC, rl_insert }, /* + */ - { ISFUNC, rl_insert }, /* , */ - { ISFUNC, rl_insert }, /* - */ - { ISFUNC, rl_insert }, /* . */ - { ISFUNC, rl_insert }, /* / */ + { ISFUNC, rl_insert }, /* SPACE */ + { ISFUNC, rl_insert }, /* ! */ + { ISFUNC, rl_insert }, /* " */ + { ISFUNC, rl_insert }, /* # */ + { ISFUNC, rl_insert }, /* $ */ + { ISFUNC, rl_insert }, /* % */ + { ISFUNC, rl_insert }, /* & */ + { ISFUNC, rl_insert }, /* ' */ + { ISFUNC, rl_insert }, /* ( */ + { ISFUNC, rl_insert }, /* ) */ + { ISFUNC, rl_insert }, /* * */ + { ISFUNC, rl_insert }, /* + */ + { ISFUNC, rl_insert }, /* , */ + { ISFUNC, rl_insert }, /* - */ + { ISFUNC, rl_insert }, /* . */ + { ISFUNC, rl_insert }, /* / */ /* Regular digits. */ - { ISFUNC, rl_insert }, /* 0 */ - { ISFUNC, rl_insert }, /* 1 */ - { ISFUNC, rl_insert }, /* 2 */ - { ISFUNC, rl_insert }, /* 3 */ - { ISFUNC, rl_insert }, /* 4 */ - { ISFUNC, rl_insert }, /* 5 */ - { ISFUNC, rl_insert }, /* 6 */ - { ISFUNC, rl_insert }, /* 7 */ - { ISFUNC, rl_insert }, /* 8 */ - { ISFUNC, rl_insert }, /* 9 */ + { ISFUNC, rl_insert }, /* 0 */ + { ISFUNC, rl_insert }, /* 1 */ + { ISFUNC, rl_insert }, /* 2 */ + { ISFUNC, rl_insert }, /* 3 */ + { ISFUNC, rl_insert }, /* 4 */ + { ISFUNC, rl_insert }, /* 5 */ + { ISFUNC, rl_insert }, /* 6 */ + { ISFUNC, rl_insert }, /* 7 */ + { ISFUNC, rl_insert }, /* 8 */ + { ISFUNC, rl_insert }, /* 9 */ /* A little more punctuation. */ - { ISFUNC, rl_insert }, /* : */ - { ISFUNC, rl_insert }, /* ; */ - { ISFUNC, rl_insert }, /* < */ - { ISFUNC, rl_insert }, /* = */ - { ISFUNC, rl_insert }, /* > */ - { ISFUNC, rl_insert }, /* ? */ - { ISFUNC, rl_insert }, /* @ */ + { ISFUNC, rl_insert }, /* : */ + { ISFUNC, rl_insert }, /* ; */ + { ISFUNC, rl_insert }, /* < */ + { ISFUNC, rl_insert }, /* = */ + { ISFUNC, rl_insert }, /* > */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* @ */ /* Uppercase alphabet. */ - { ISFUNC, rl_insert }, /* A */ - { ISFUNC, rl_insert }, /* B */ - { ISFUNC, rl_insert }, /* C */ - { ISFUNC, rl_insert }, /* D */ - { ISFUNC, rl_insert }, /* E */ - { ISFUNC, rl_insert }, /* F */ - { ISFUNC, rl_insert }, /* G */ - { ISFUNC, rl_insert }, /* H */ - { ISFUNC, rl_insert }, /* I */ - { ISFUNC, rl_insert }, /* J */ - { ISFUNC, rl_insert }, /* K */ - { ISFUNC, rl_insert }, /* L */ - { ISFUNC, rl_insert }, /* M */ - { ISFUNC, rl_insert }, /* N */ - { ISFUNC, rl_insert }, /* O */ - { ISFUNC, rl_insert }, /* P */ - { ISFUNC, rl_insert }, /* Q */ - { ISFUNC, rl_insert }, /* R */ - { ISFUNC, rl_insert }, /* S */ - { ISFUNC, rl_insert }, /* T */ - { ISFUNC, rl_insert }, /* U */ - { ISFUNC, rl_insert }, /* V */ - { ISFUNC, rl_insert }, /* W */ - { ISFUNC, rl_insert }, /* X */ - { ISFUNC, rl_insert }, /* Y */ - { ISFUNC, rl_insert }, /* Z */ + { ISFUNC, rl_insert }, /* A */ + { ISFUNC, rl_insert }, /* B */ + { ISFUNC, rl_insert }, /* C */ + { ISFUNC, rl_insert }, /* D */ + { ISFUNC, rl_insert }, /* E */ + { ISFUNC, rl_insert }, /* F */ + { ISFUNC, rl_insert }, /* G */ + { ISFUNC, rl_insert }, /* H */ + { ISFUNC, rl_insert }, /* I */ + { ISFUNC, rl_insert }, /* J */ + { ISFUNC, rl_insert }, /* K */ + { ISFUNC, rl_insert }, /* L */ + { ISFUNC, rl_insert }, /* M */ + { ISFUNC, rl_insert }, /* N */ + { ISFUNC, rl_insert }, /* O */ + { ISFUNC, rl_insert }, /* P */ + { ISFUNC, rl_insert }, /* Q */ + { ISFUNC, rl_insert }, /* R */ + { ISFUNC, rl_insert }, /* S */ + { ISFUNC, rl_insert }, /* T */ + { ISFUNC, rl_insert }, /* U */ + { ISFUNC, rl_insert }, /* V */ + { ISFUNC, rl_insert }, /* W */ + { ISFUNC, rl_insert }, /* X */ + { ISFUNC, rl_insert }, /* Y */ + { ISFUNC, rl_insert }, /* Z */ /* Some more punctuation. */ - { ISFUNC, rl_insert }, /* [ */ - { ISFUNC, rl_insert }, /* \ */ - { ISFUNC, rl_insert }, /* ] */ - { ISFUNC, rl_insert }, /* ^ */ - { ISFUNC, rl_insert }, /* _ */ - { ISFUNC, rl_insert }, /* ` */ + { ISFUNC, rl_insert }, /* [ */ + { ISFUNC, rl_insert }, /* \ */ + { ISFUNC, rl_insert }, /* ] */ + { ISFUNC, rl_insert }, /* ^ */ + { ISFUNC, rl_insert }, /* _ */ + { ISFUNC, rl_insert }, /* ` */ /* Lowercase alphabet. */ - { ISFUNC, rl_insert }, /* a */ - { ISFUNC, rl_insert }, /* b */ - { ISFUNC, rl_insert }, /* c */ - { ISFUNC, rl_insert }, /* d */ - { ISFUNC, rl_insert }, /* e */ - { ISFUNC, rl_insert }, /* f */ - { ISFUNC, rl_insert }, /* g */ - { ISFUNC, rl_insert }, /* h */ - { ISFUNC, rl_insert }, /* i */ - { ISFUNC, rl_insert }, /* j */ - { ISFUNC, rl_insert }, /* k */ - { ISFUNC, rl_insert }, /* l */ - { ISFUNC, rl_insert }, /* m */ - { ISFUNC, rl_insert }, /* n */ - { ISFUNC, rl_insert }, /* o */ - { ISFUNC, rl_insert }, /* p */ - { ISFUNC, rl_insert }, /* q */ - { ISFUNC, rl_insert }, /* r */ - { ISFUNC, rl_insert }, /* s */ - { ISFUNC, rl_insert }, /* t */ - { ISFUNC, rl_insert }, /* u */ - { ISFUNC, rl_insert }, /* v */ - { ISFUNC, rl_insert }, /* w */ - { ISFUNC, rl_insert }, /* x */ - { ISFUNC, rl_insert }, /* y */ - { ISFUNC, rl_insert }, /* z */ + { ISFUNC, rl_insert }, /* a */ + { ISFUNC, rl_insert }, /* b */ + { ISFUNC, rl_insert }, /* c */ + { ISFUNC, rl_insert }, /* d */ + { ISFUNC, rl_insert }, /* e */ + { ISFUNC, rl_insert }, /* f */ + { ISFUNC, rl_insert }, /* g */ + { ISFUNC, rl_insert }, /* h */ + { ISFUNC, rl_insert }, /* i */ + { ISFUNC, rl_insert }, /* j */ + { ISFUNC, rl_insert }, /* k */ + { ISFUNC, rl_insert }, /* l */ + { ISFUNC, rl_insert }, /* m */ + { ISFUNC, rl_insert }, /* n */ + { ISFUNC, rl_insert }, /* o */ + { ISFUNC, rl_insert }, /* p */ + { ISFUNC, rl_insert }, /* q */ + { ISFUNC, rl_insert }, /* r */ + { ISFUNC, rl_insert }, /* s */ + { ISFUNC, rl_insert }, /* t */ + { ISFUNC, rl_insert }, /* u */ + { ISFUNC, rl_insert }, /* v */ + { ISFUNC, rl_insert }, /* w */ + { ISFUNC, rl_insert }, /* x */ + { ISFUNC, rl_insert }, /* y */ + { ISFUNC, rl_insert }, /* z */ /* Final punctuation. */ - { ISFUNC, rl_insert }, /* { */ - { ISFUNC, rl_insert }, /* | */ - { ISFUNC, rl_insert }, /* } */ - { ISFUNC, rl_insert }, /* ~ */ - { ISFUNC, rl_rubout }, /* RUBOUT */ + { ISFUNC, rl_insert }, /* { */ + { ISFUNC, rl_insert }, /* | */ + { ISFUNC, rl_insert }, /* } */ + { ISFUNC, rl_insert }, /* ~ */ + { ISFUNC, rl_rubout }, /* RUBOUT */ #if KEYMAP_SIZE > 128 /* Pure 8-bit characters (128 - 159). @@ -598,280 +598,280 @@ KEYMAP_ENTRY_ARRAY vi_insertion_keymap = { #if 0 KEYMAP_ENTRY_ARRAY vi_escape_keymap = { /* The regular control keys come first. */ - { ISFUNC, (Function *)0x0 }, /* Control-@ */ - { ISFUNC, (Function *)0x0 }, /* Control-a */ - { ISFUNC, (Function *)0x0 }, /* Control-b */ - { ISFUNC, (Function *)0x0 }, /* Control-c */ - { ISFUNC, (Function *)0x0 }, /* Control-d */ - { ISFUNC, (Function *)0x0 }, /* Control-e */ - { ISFUNC, (Function *)0x0 }, /* Control-f */ - { ISFUNC, (Function *)0x0 }, /* Control-g */ - { ISFUNC, (Function *)0x0 }, /* Control-h */ - { ISFUNC, rl_tab_insert}, /* Control-i */ - { ISFUNC, rl_emacs_editing_mode}, /* Control-j */ - { ISFUNC, rl_kill_line }, /* Control-k */ - { ISFUNC, (Function *)0x0 }, /* Control-l */ - { ISFUNC, rl_emacs_editing_mode}, /* Control-m */ - { ISFUNC, (Function *)0x0 }, /* Control-n */ - { ISFUNC, (Function *)0x0 }, /* Control-o */ - { ISFUNC, (Function *)0x0 }, /* Control-p */ - { ISFUNC, (Function *)0x0 }, /* Control-q */ - { ISFUNC, (Function *)0x0 }, /* Control-r */ - { ISFUNC, (Function *)0x0 }, /* Control-s */ - { ISFUNC, (Function *)0x0 }, /* Control-t */ - { ISFUNC, (Function *)0x0 }, /* Control-u */ - { ISFUNC, (Function *)0x0 }, /* Control-v */ - { ISFUNC, (Function *)0x0 }, /* Control-w */ - { ISFUNC, (Function *)0x0 }, /* Control-x */ - { ISFUNC, (Function *)0x0 }, /* Control-y */ - { ISFUNC, (Function *)0x0 }, /* Control-z */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-@ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-a */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-b */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-c */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-d */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-e */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-f */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-g */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-h */ + { ISFUNC, rl_tab_insert}, /* Control-i */ + { ISFUNC, rl_emacs_editing_mode}, /* Control-j */ + { ISFUNC, rl_kill_line }, /* Control-k */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-l */ + { ISFUNC, rl_emacs_editing_mode}, /* Control-m */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-n */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-o */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-p */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-q */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-r */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-s */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-t */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-u */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-v */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-w */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-x */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-z */ - { ISFUNC, rl_vi_movement_mode }, /* Control-[ */ - { ISFUNC, (Function *)0x0 }, /* Control-\ */ - { ISFUNC, (Function *)0x0 }, /* Control-] */ - { ISFUNC, (Function *)0x0 }, /* Control-^ */ - { ISFUNC, rl_vi_undo }, /* Control-_ */ + { ISFUNC, rl_vi_movement_mode }, /* Control-[ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-\ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-] */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* Control-^ */ + { ISFUNC, rl_vi_undo }, /* Control-_ */ /* The start of printing characters. */ - { ISFUNC, (Function *)0x0 }, /* SPACE */ - { ISFUNC, (Function *)0x0 }, /* ! */ - { ISFUNC, (Function *)0x0 }, /* " */ - { ISFUNC, (Function *)0x0 }, /* # */ - { ISFUNC, (Function *)0x0 }, /* $ */ - { ISFUNC, (Function *)0x0 }, /* % */ - { ISFUNC, (Function *)0x0 }, /* & */ - { ISFUNC, (Function *)0x0 }, /* ' */ - { ISFUNC, (Function *)0x0 }, /* ( */ - { ISFUNC, (Function *)0x0 }, /* ) */ - { ISFUNC, (Function *)0x0 }, /* * */ - { ISFUNC, (Function *)0x0 }, /* + */ - { ISFUNC, (Function *)0x0 }, /* , */ - { ISFUNC, (Function *)0x0 }, /* - */ - { ISFUNC, (Function *)0x0 }, /* . */ - { ISFUNC, (Function *)0x0 }, /* / */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* SPACE */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ! */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* " */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* # */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* $ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* % */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* & */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ' */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ( */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ) */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* * */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* + */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* , */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* - */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* . */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* / */ /* Regular digits. */ - { ISFUNC, rl_vi_arg_digit }, /* 0 */ - { ISFUNC, rl_vi_arg_digit }, /* 1 */ - { ISFUNC, rl_vi_arg_digit }, /* 2 */ - { ISFUNC, rl_vi_arg_digit }, /* 3 */ - { ISFUNC, rl_vi_arg_digit }, /* 4 */ - { ISFUNC, rl_vi_arg_digit }, /* 5 */ - { ISFUNC, rl_vi_arg_digit }, /* 6 */ - { ISFUNC, rl_vi_arg_digit }, /* 7 */ - { ISFUNC, rl_vi_arg_digit }, /* 8 */ - { ISFUNC, rl_vi_arg_digit }, /* 9 */ + { ISFUNC, rl_vi_arg_digit }, /* 0 */ + { ISFUNC, rl_vi_arg_digit }, /* 1 */ + { ISFUNC, rl_vi_arg_digit }, /* 2 */ + { ISFUNC, rl_vi_arg_digit }, /* 3 */ + { ISFUNC, rl_vi_arg_digit }, /* 4 */ + { ISFUNC, rl_vi_arg_digit }, /* 5 */ + { ISFUNC, rl_vi_arg_digit }, /* 6 */ + { ISFUNC, rl_vi_arg_digit }, /* 7 */ + { ISFUNC, rl_vi_arg_digit }, /* 8 */ + { ISFUNC, rl_vi_arg_digit }, /* 9 */ /* A little more punctuation. */ - { ISFUNC, (Function *)0x0 }, /* : */ - { ISFUNC, (Function *)0x0 }, /* ; */ - { ISFUNC, (Function *)0x0 }, /* < */ - { ISFUNC, (Function *)0x0 }, /* = */ - { ISFUNC, (Function *)0x0 }, /* > */ - { ISFUNC, (Function *)0x0 }, /* ? */ - { ISFUNC, (Function *)0x0 }, /* @ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* : */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ; */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* < */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* = */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* > */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ? */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* @ */ /* Uppercase alphabet. */ - { ISFUNC, rl_do_lowercase_version }, /* A */ - { ISFUNC, rl_do_lowercase_version }, /* B */ - { ISFUNC, rl_do_lowercase_version }, /* C */ - { ISFUNC, rl_do_lowercase_version }, /* D */ - { ISFUNC, rl_do_lowercase_version }, /* E */ - { ISFUNC, rl_do_lowercase_version }, /* F */ - { ISFUNC, rl_do_lowercase_version }, /* G */ - { ISFUNC, rl_do_lowercase_version }, /* H */ - { ISFUNC, rl_do_lowercase_version }, /* I */ - { ISFUNC, rl_do_lowercase_version }, /* J */ - { ISFUNC, rl_do_lowercase_version }, /* K */ - { ISFUNC, rl_do_lowercase_version }, /* L */ - { ISFUNC, rl_do_lowercase_version }, /* M */ - { ISFUNC, rl_do_lowercase_version }, /* N */ - { ISFUNC, rl_do_lowercase_version }, /* O */ - { ISFUNC, rl_do_lowercase_version }, /* P */ - { ISFUNC, rl_do_lowercase_version }, /* Q */ - { ISFUNC, rl_do_lowercase_version }, /* R */ - { ISFUNC, rl_do_lowercase_version }, /* S */ - { ISFUNC, rl_do_lowercase_version }, /* T */ - { ISFUNC, rl_do_lowercase_version }, /* U */ - { ISFUNC, rl_do_lowercase_version }, /* V */ - { ISFUNC, rl_do_lowercase_version }, /* W */ - { ISFUNC, rl_do_lowercase_version }, /* X */ - { ISFUNC, rl_do_lowercase_version }, /* Y */ - { ISFUNC, rl_do_lowercase_version }, /* Z */ + { ISFUNC, rl_do_lowercase_version }, /* A */ + { ISFUNC, rl_do_lowercase_version }, /* B */ + { ISFUNC, rl_do_lowercase_version }, /* C */ + { ISFUNC, rl_do_lowercase_version }, /* D */ + { ISFUNC, rl_do_lowercase_version }, /* E */ + { ISFUNC, rl_do_lowercase_version }, /* F */ + { ISFUNC, rl_do_lowercase_version }, /* G */ + { ISFUNC, rl_do_lowercase_version }, /* H */ + { ISFUNC, rl_do_lowercase_version }, /* I */ + { ISFUNC, rl_do_lowercase_version }, /* J */ + { ISFUNC, rl_do_lowercase_version }, /* K */ + { ISFUNC, rl_do_lowercase_version }, /* L */ + { ISFUNC, rl_do_lowercase_version }, /* M */ + { ISFUNC, rl_do_lowercase_version }, /* N */ + { ISFUNC, rl_do_lowercase_version }, /* O */ + { ISFUNC, rl_do_lowercase_version }, /* P */ + { ISFUNC, rl_do_lowercase_version }, /* Q */ + { ISFUNC, rl_do_lowercase_version }, /* R */ + { ISFUNC, rl_do_lowercase_version }, /* S */ + { ISFUNC, rl_do_lowercase_version }, /* T */ + { ISFUNC, rl_do_lowercase_version }, /* U */ + { ISFUNC, rl_do_lowercase_version }, /* V */ + { ISFUNC, rl_do_lowercase_version }, /* W */ + { ISFUNC, rl_do_lowercase_version }, /* X */ + { ISFUNC, rl_do_lowercase_version }, /* Y */ + { ISFUNC, rl_do_lowercase_version }, /* Z */ /* Some more punctuation. */ - { ISFUNC, rl_arrow_keys }, /* [ */ - { ISFUNC, (Function *)0x0 }, /* \ */ - { ISFUNC, (Function *)0x0 }, /* ] */ - { ISFUNC, (Function *)0x0 }, /* ^ */ - { ISFUNC, (Function *)0x0 }, /* _ */ - { ISFUNC, (Function *)0x0 }, /* ` */ + { ISFUNC, rl_arrow_keys }, /* [ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* \ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ] */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ^ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* _ */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ` */ /* Lowercase alphabet. */ - { ISFUNC, (Function *)0x0 }, /* a */ - { ISFUNC, (Function *)0x0 }, /* b */ - { ISFUNC, (Function *)0x0 }, /* c */ - { ISFUNC, (Function *)0x0 }, /* d */ - { ISFUNC, (Function *)0x0 }, /* e */ - { ISFUNC, (Function *)0x0 }, /* f */ - { ISFUNC, (Function *)0x0 }, /* g */ - { ISFUNC, (Function *)0x0 }, /* h */ - { ISFUNC, (Function *)0x0 }, /* i */ - { ISFUNC, (Function *)0x0 }, /* j */ - { ISFUNC, (Function *)0x0 }, /* k */ - { ISFUNC, (Function *)0x0 }, /* l */ - { ISFUNC, (Function *)0x0 }, /* m */ - { ISFUNC, (Function *)0x0 }, /* n */ - { ISFUNC, rl_arrow_keys }, /* o */ - { ISFUNC, (Function *)0x0 }, /* p */ - { ISFUNC, (Function *)0x0 }, /* q */ - { ISFUNC, (Function *)0x0 }, /* r */ - { ISFUNC, (Function *)0x0 }, /* s */ - { ISFUNC, (Function *)0x0 }, /* t */ - { ISFUNC, (Function *)0x0 }, /* u */ - { ISFUNC, (Function *)0x0 }, /* v */ - { ISFUNC, (Function *)0x0 }, /* w */ - { ISFUNC, (Function *)0x0 }, /* x */ - { ISFUNC, (Function *)0x0 }, /* y */ - { ISFUNC, (Function *)0x0 }, /* z */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* a */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* b */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* c */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* d */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* e */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* f */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* g */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* h */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* i */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* j */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* k */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* l */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* m */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* n */ + { ISFUNC, rl_arrow_keys }, /* o */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* p */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* q */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* r */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* s */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* t */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* u */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* v */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* w */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* x */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* y */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* z */ /* Final punctuation. */ - { ISFUNC, (Function *)0x0 }, /* { */ - { ISFUNC, (Function *)0x0 }, /* | */ - { ISFUNC, (Function *)0x0 }, /* } */ - { ISFUNC, (Function *)0x0 }, /* ~ */ - { ISFUNC, rl_backward_kill_word }, /* RUBOUT */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* { */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* | */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* } */ + { ISFUNC, (rl_command_func_t *)0x0 }, /* ~ */ + { ISFUNC, rl_backward_kill_word }, /* RUBOUT */ #if KEYMAP_SIZE > 128 /* Undefined keys. */ - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 }, - { ISFUNC, (Function *)0x0 } + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 }, + { ISFUNC, (rl_command_func_t *)0x0 } #endif /* KEYMAP_SIZE > 128 */ }; #endif diff --git a/readline/vi_mode.c b/readline/vi_mode.c index eb392b643ba..01df589f625 100644 --- a/readline/vi_mode.c +++ b/readline/vi_mode.c @@ -8,7 +8,7 @@ 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 1, or + 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 @@ -19,7 +19,7 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY /* **************************************************************** */ @@ -51,54 +51,23 @@ /* Some standard library routines. */ #include "rldefs.h" +#include "rlmbutil.h" + #include "readline.h" #include "history.h" -#ifndef _rl_digit_p -#define _rl_digit_p(c) ((c) >= '0' && (c) <= '9') -#endif - -#ifndef _rl_digit_value -#define _rl_digit_value(c) ((c) - '0') -#endif +#include "rlprivate.h" +#include "xmalloc.h" #ifndef member #define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0) #endif -#ifndef isident -#define isident(c) ((_rl_pure_alphabetic (c) || _rl_digit_p (c) || c == '_')) -#endif - -#ifndef exchange -#define exchange(x, y) do {int temp = x; x = y; y = temp;} while (0) -#endif - -extern char *xmalloc (), *xrealloc (); - -/* Variables imported from readline.c */ -extern int rl_point, rl_end, rl_mark; -extern FILE *rl_instream; -extern int rl_line_buffer_len, rl_explicit_arg, rl_numeric_arg; -extern Keymap _rl_keymap; -extern char *rl_prompt; -extern char *rl_line_buffer; -extern int rl_arg_sign; - -extern int _rl_doing_an_undo; -extern int _rl_undo_group_level; - -extern void _rl_dispatch (); -extern int _rl_char_search_internal (); - -extern void rl_extend_line_buffer (); -extern int rl_vi_check (); - /* Non-zero means enter insertion mode. */ static int _rl_vi_doing_insert; /* Command keys which do movement for xxx_to commands. */ -static const char *vi_motion = " hl^$0ftFt;,%wbeWBE|"; +static const char *vi_motion = " hl^$0ftFT;,%wbeWBE|"; /* Keymap used for vi replace characters. Created dynamically since rarely used. */ @@ -118,7 +87,11 @@ static int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */ static int _rl_vi_last_repeat = 1; static int _rl_vi_last_arg_sign = 1; static int _rl_vi_last_motion; +#if defined (HANDLE_MULTIBYTE) +static char _rl_vi_last_search_mbchar[MB_LEN_MAX]; +#else static int _rl_vi_last_search_char; +#endif static int _rl_vi_last_replacement; static int _rl_vi_last_key_before_insert; @@ -129,20 +102,18 @@ static int vi_redoing; static const char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~"; /* Arrays for the saved marks. */ -static int vi_mark_chars[27]; +static int vi_mark_chars['z' - 'a' + 1]; -static int rl_digit_loop1 (); +static void _rl_vi_stuff_insert PARAMS((int)); +static void _rl_vi_save_insert PARAMS((UNDO_LIST *)); +static int rl_digit_loop1 PARAMS((void)); void _rl_vi_initialize_line () { -#ifndef __QNXNTO__ - register uint i; -#else register unsigned int i; -#endif - for (i = 0; i < (int) sizeof (vi_mark_chars) / sizeof (int); i++) + for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++) vi_mark_chars[i] = -1; } @@ -189,12 +160,15 @@ int rl_vi_redo (count, c) int count, c __attribute__((unused)); { + int r; + if (!rl_explicit_arg) { rl_numeric_arg = _rl_vi_last_repeat; rl_arg_sign = _rl_vi_last_arg_sign; } + r = 0; vi_redoing = 1; /* If we're redoing an insert with `i', stuff in the inserted text and do not go into insertion mode. */ @@ -206,10 +180,10 @@ rl_vi_redo (count, c) rl_point--; } else - _rl_dispatch (_rl_vi_last_command, _rl_keymap); + r = _rl_dispatch (_rl_vi_last_command, _rl_keymap); vi_redoing = 0; - return (0); + return (r); } /* A placeholder for further expansion. */ @@ -219,10 +193,10 @@ rl_vi_undo (count, key) { return (rl_undo_command (count, key)); } - + /* Yank the nth arg from the previous line into this line at point. */ int -rl_vi_yank_arg (count, key) +rl_vi_yank_arg (count, key) int count, key __attribute__((unused)); { /* Readline thinks that the first word on a line is the 0th, while vi @@ -295,7 +269,7 @@ rl_vi_search (count, key) break; default: - ding (); + rl_ding (); break; } return (0); @@ -351,7 +325,7 @@ rl_vi_prev_word (count, key) if (rl_point == 0) { - ding (); + rl_ding (); return (0); } @@ -373,7 +347,7 @@ rl_vi_next_word (count, key) if (rl_point >= (rl_end - 1)) { - ding (); + rl_ding (); return (0); } @@ -391,7 +365,7 @@ rl_vi_end_word (count, key) { if (count < 0) { - ding (); + rl_ding (); return -1; } @@ -481,14 +455,14 @@ rl_vi_fword (count, ignore) while (count-- && rl_point < (rl_end - 1)) { /* Move to white space (really non-identifer). */ - if (isident (rl_line_buffer[rl_point])) + if (_rl_isident (rl_line_buffer[rl_point])) { - while (isident (rl_line_buffer[rl_point]) && rl_point < rl_end) + while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end) rl_point++; } else /* if (!whitespace (rl_line_buffer[rl_point])) */ { - while (!isident (rl_line_buffer[rl_point]) && + while (!_rl_isident (rl_line_buffer[rl_point]) && !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) rl_point++; } @@ -518,9 +492,9 @@ rl_vi_bword (count, ignore) back so we don't get messed up by the rl_point++ down there in the while loop. Without this code, words like `l;' screw up the function. */ - last_is_ident = isident (rl_line_buffer[rl_point - 1]); - if ((isident (rl_line_buffer[rl_point]) && !last_is_ident) || - (!isident (rl_line_buffer[rl_point]) && last_is_ident)) + last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]); + if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) || + (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident)) rl_point--; while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) @@ -528,10 +502,10 @@ rl_vi_bword (count, ignore) if (rl_point > 0) { - if (isident (rl_line_buffer[rl_point])) - while (--rl_point >= 0 && isident (rl_line_buffer[rl_point])); + if (_rl_isident (rl_line_buffer[rl_point])) + while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point])); else - while (--rl_point >= 0 && !isident (rl_line_buffer[rl_point]) && + while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) && !whitespace (rl_line_buffer[rl_point])); rl_point++; } @@ -553,10 +527,10 @@ rl_vi_eword (count, ignore) if (rl_point < rl_end) { - if (isident (rl_line_buffer[rl_point])) - while (++rl_point < rl_end && isident (rl_line_buffer[rl_point])); + if (_rl_isident (rl_line_buffer[rl_point])) + while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point])); else - while (++rl_point < rl_end && !isident (rl_line_buffer[rl_point]) + while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point]) && !whitespace (rl_line_buffer[rl_point])); } rl_point--; @@ -578,7 +552,17 @@ rl_vi_append_mode (count, key) int count __attribute__((unused)), key; { if (rl_point < rl_end) - rl_point++; + { + if (MB_CUR_MAX == 1 || rl_byte_oriented) + rl_point++; + else + { + int point = rl_point; + rl_forward_char (1, key); + if (point == rl_point) + rl_point = rl_end; + } + } rl_vi_insertion_mode (1, key); return (0); } @@ -632,17 +616,18 @@ _rl_vi_save_insert (up) if (len >= vi_insert_buffer_size) { vi_insert_buffer_size += (len + 32) - (len % 32); - vi_insert_buffer = xrealloc (vi_insert_buffer, vi_insert_buffer_size); + vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size); } strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1); vi_insert_buffer[len-1] = '\0'; } - + void _rl_vi_done_inserting () { if (_rl_vi_doing_insert) { + /* The `C', `s', and `S' commands set this. */ rl_end_undo_group (); /* Now, the text between rl_undo_list->next->start and rl_undo_list->next->end is what was inserted while in insert @@ -671,7 +656,7 @@ rl_vi_movement_mode (count, key) int count __attribute__((unused)), key; { if (rl_point > 0) - rl_backward (1, key); + rl_backward_char (1, key); _rl_keymap = vi_movement_keymap; _rl_vi_done_inserting (); @@ -688,6 +673,51 @@ rl_vi_arg_digit (count, c) return (rl_digit_argument (count, c)); } +/* Change the case of the next COUNT characters. */ +#if defined (HANDLE_MULTIBYTE) +static int +_rl_vi_change_mbchar_case (count) + int count; +{ + wchar_t wc; + char mb[MB_LEN_MAX]; + mbstate_t ps; + + memset (&ps, 0, sizeof (mbstate_t)); + if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0) + count--; + while (count-- && rl_point < rl_end) + { + mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps); + if (iswupper (wc)) + wc = towlower (wc); + else if (iswlower (wc)) + wc = towupper (wc); + else + { + /* Just skip over chars neither upper nor lower case */ + rl_forward_char (1, 0); + continue; + } + + /* Vi is kind of strange here. */ + if (wc) + { + wctomb (mb, wc); + rl_begin_undo_group (); + rl_delete (1, 0); + rl_insert_text (mb); + rl_end_undo_group (); + rl_vi_check (); + } + else + rl_forward_char (1, 0); + } + + return 0; +} +#endif + int rl_vi_change_case (count, ignore) int count, ignore __attribute__((unused)); @@ -698,6 +728,11 @@ rl_vi_change_case (count, ignore) if (rl_point >= rl_end) return (0); +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + return (_rl_vi_change_mbchar_case (count)); +#endif + while (count-- && rl_point < rl_end) { if (_rl_uppercase_p (rl_line_buffer[rl_point])) @@ -707,7 +742,7 @@ rl_vi_change_case (count, ignore) else { /* Just skip over characters neither upper nor lower case. */ - rl_forward (1, c); + rl_forward_char (1, c); continue; } @@ -716,12 +751,12 @@ rl_vi_change_case (count, ignore) { rl_begin_undo_group (); rl_delete (1, c); - rl_insert (1, c); + _rl_insert_char (1, c); rl_end_undo_group (); rl_vi_check (); } else - rl_forward (1, c); + rl_forward_char (1, c); } return (0); } @@ -731,10 +766,10 @@ rl_vi_put (count, key) int count __attribute__((unused)), key; { if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end)) - rl_point++; + rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); rl_yank (1, key); - rl_backward (1, key); + rl_backward_char (1, key); return (0); } @@ -742,7 +777,12 @@ int rl_vi_check () { if (rl_point && rl_point == rl_end) - rl_point--; + { + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); + else + rl_point--; + } return (0); } @@ -765,7 +805,9 @@ rl_vi_domove (key, nextkey) int old_end; rl_mark = rl_point; + RL_SETSTATE(RL_STATE_MOREINPUT); c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); *nextkey = c; if (!member (c, vi_motion)) @@ -776,7 +818,9 @@ rl_vi_domove (key, nextkey) rl_numeric_arg = _rl_digit_value (c); rl_digit_loop1 (); rl_numeric_arg *= save; + RL_SETSTATE(RL_STATE_MOREINPUT); c = rl_read_key (); /* real command */ + RL_UNSETSTATE(RL_STATE_MOREINPUT); *nextkey = c; } else if (key == c && (key == 'd' || key == 'y' || key == 'c')) @@ -840,24 +884,36 @@ rl_vi_domove (key, nextkey) } if (rl_mark < rl_point) - exchange (rl_point, rl_mark); + SWAP (rl_point, rl_mark); return (0); } /* A simplified loop for vi. Don't dispatch key at end. - Don't recognize minus sign? */ + Don't recognize minus sign? + Should this do rl_save_prompt/rl_restore_prompt? */ static int rl_digit_loop1 () { int key, c; + RL_SETSTATE(RL_STATE_NUMERICARG); while (1) { - rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg, 0); + if (rl_numeric_arg > 1000000) + { + rl_explicit_arg = rl_numeric_arg = 0; + rl_ding (); + rl_clear_message (); + RL_UNSETSTATE(RL_STATE_NUMERICARG); + return 1; + } + rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); + RL_SETSTATE(RL_STATE_MOREINPUT); key = c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); - if (_rl_keymap[c].type == ISFUNC && + if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument) { rl_numeric_arg *= 4; @@ -880,6 +936,8 @@ rl_digit_loop1 () break; } } + + RL_UNSETSTATE(RL_STATE_NUMERICARG); return (0); } @@ -896,7 +954,7 @@ rl_vi_delete_to (count, key) if (rl_vi_domove (key, &c)) { - ding (); + rl_ding (); return -1; } @@ -924,7 +982,7 @@ rl_vi_change_to (count, key) if (rl_vi_domove (key, &c)) { - ding (); + rl_ding (); return -1; } @@ -974,7 +1032,7 @@ rl_vi_yank_to (count, key) if (rl_vi_domove (key, &c)) { - ding (); + rl_ding (); return -1; } @@ -1000,19 +1058,22 @@ rl_vi_delete (count, key) if (rl_end == 0) { - ding (); + rl_ding (); return -1; } - end = rl_point + count; + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO); + else + end = rl_point + count; if (end >= rl_end) end = rl_end; rl_kill_text (rl_point, end); - + if (rl_point > 0 && rl_point == rl_end) - rl_backward (1, key); + rl_backward_char (1, key); return (0); } @@ -1037,7 +1098,12 @@ int rl_vi_char_search (count, key) int count, key; { +#if defined (HANDLE_MULTIBYTE) + static char *target; + static int mb_len; +#else static char target; +#endif static int orig_dir, dir; if (key == ';' || key == ',') @@ -1045,9 +1111,22 @@ rl_vi_char_search (count, key) else { if (vi_redoing) +#if defined (HANDLE_MULTIBYTE) + target = _rl_vi_last_search_mbchar; +#else target = _rl_vi_last_search_char; +#endif else - _rl_vi_last_search_char = target = rl_getc (rl_instream); + { +#if defined (HANDLE_MULTIBYTE) + mb_len = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX); + target = _rl_vi_last_search_mbchar; +#else + RL_SETSTATE(RL_STATE_MOREINPUT); + _rl_vi_last_search_char = target = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); +#endif + } switch (key) { @@ -1069,7 +1148,11 @@ rl_vi_char_search (count, key) } } +#if defined (HANDLE_MULTIBYTE) + return (_rl_char_search_internal (count, dir, target, mb_len)); +#else return (_rl_char_search_internal (count, dir, target)); +#endif } /* Match brackets */ @@ -1077,19 +1160,30 @@ int rl_vi_match (ignore, key) int ignore __attribute__((unused)), key; { - int count = 1, brack, pos; + int count = 1, brack, pos, tmp, pre; pos = rl_point; if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) { - while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 && - rl_point < rl_end - 1) - rl_forward (1, key); + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) + { + pre = rl_point; + rl_forward_char (1, key); + if (pre == rl_point) + break; + } + } + else + while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 && + rl_point < rl_end - 1) + rl_forward_char (1, key); if (brack <= 0) { rl_point = pos; - ding (); + rl_ding (); return -1; } } @@ -1100,7 +1194,16 @@ rl_vi_match (ignore, key) { while (count) { - if (--pos >= 0) + tmp = pos; + if (MB_CUR_MAX == 1 || rl_byte_oriented) + pos--; + else + { + pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY); + if (tmp == pos) + pos--; + } + if (pos >= 0) { int b = rl_vi_bracktype (rl_line_buffer[pos]); if (b == -brack) @@ -1110,7 +1213,7 @@ rl_vi_match (ignore, key) } else { - ding (); + rl_ding (); return -1; } } @@ -1119,7 +1222,12 @@ rl_vi_match (ignore, key) { /* brack > 0 */ while (count) { - if (++pos < rl_end) + if (MB_CUR_MAX == 1 || rl_byte_oriented) + pos++; + else + pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY); + + if (pos < rl_end) { int b = rl_vi_bracktype (rl_line_buffer[pos]); if (b == -brack) @@ -1129,7 +1237,7 @@ rl_vi_match (ignore, key) } else { - ding (); + rl_ding (); return -1; } } @@ -1154,6 +1262,11 @@ rl_vi_bracktype (c) } } +/* XXX - think about reading an entire mbchar with _rl_read_mbchar and + inserting it in one bunch instead of the loop below (like in + rl_vi_char_search or _rl_vi_change_mbchar_case. Set c to mbchar[0] + for test against 033 or ^C. Make sure that _rl_read_mbchar does + this right. */ int rl_vi_change_char (count, key) int count, key __attribute__((unused)); @@ -1163,7 +1276,11 @@ rl_vi_change_char (count, key) if (vi_redoing) c = _rl_vi_last_replacement; else - _rl_vi_last_replacement = c = rl_getc (rl_instream); + { + RL_SETSTATE(RL_STATE_MOREINPUT); + _rl_vi_last_replacement = c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + } if (c == '\033' || c == CTRL ('C')) return -1; @@ -1173,9 +1290,19 @@ rl_vi_change_char (count, key) rl_begin_undo_group (); rl_delete (1, c); - rl_insert (1, c); +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + while (_rl_insert_char (1, c)) + { + RL_SETSTATE (RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE (RL_STATE_MOREINPUT); + } + else +#endif + _rl_insert_char (1, c); if (count == 0) - rl_backward (1, c); + rl_backward_char (1, c); rl_end_undo_group (); } @@ -1186,66 +1313,29 @@ int rl_vi_subst (count, key) int count, key; { - rl_begin_undo_group (); + /* If we are redoing, rl_vi_change_to will stuff the last motion char */ + if (vi_redoing == 0) + rl_stuff_char ((key == 'S') ? 'c' : ' '); /* `S' == `cc', `s' == `c ' */ - if (_rl_uppercase_p (key)) - { - rl_beg_of_line (1, key); - rl_kill_line (1, key); - } - else - rl_delete_text (rl_point, rl_point+count); - - rl_end_undo_group (); - - _rl_vi_set_last (key, count, rl_arg_sign); - - if (vi_redoing) - { - int o = _rl_doing_an_undo; - - _rl_doing_an_undo = 1; - if (vi_insert_buffer && *vi_insert_buffer) - rl_insert_text (vi_insert_buffer); - _rl_doing_an_undo = o; - } - else - { - rl_begin_undo_group (); - _rl_vi_doing_insert = 1; - rl_vi_insertion_mode (1, key); - } - - return (0); + return (rl_vi_change_to (count, 'c')); } int rl_vi_overstrike (count, key) int count, key; { - int i; - if (_rl_vi_doing_insert == 0) { _rl_vi_doing_insert = 1; rl_begin_undo_group (); } - for (i = 0; i < count; i++) + if (count > 0) { - vi_replace_count++; - rl_begin_undo_group (); - - if (rl_point < rl_end) - { - rl_delete (1, key); - rl_insert (1, key); - } - else - rl_insert (1, key); - - rl_end_undo_group (); + _rl_overwrite_char (count, key); + vi_replace_count += count; } + return (0); } @@ -1259,7 +1349,7 @@ rl_vi_overstrike_delete (count, key) { if (vi_replace_count == 0) { - ding (); + rl_ding (); break; } s = rl_point; @@ -1268,7 +1358,7 @@ rl_vi_overstrike_delete (count, key) vi_replace_count--; if (rl_point == s) - rl_backward (1, key); + rl_backward_char (1, key); } if (vi_replace_count == 0 && _rl_vi_doing_insert) @@ -1329,7 +1419,7 @@ rl_vi_possible_completions() } else if (rl_line_buffer[rl_point - 1] == ';') { - ding (); + rl_ding (); return (0); } @@ -1347,10 +1437,13 @@ rl_vi_set_mark (count, key) { int ch; + RL_SETSTATE(RL_STATE_MOREINPUT); ch = rl_read_key (); - if (_rl_lowercase_p (ch) == 0) + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (ch < 'a' || ch > 'z') { - ding (); + rl_ding (); return -1; } ch -= 'a'; @@ -1364,22 +1457,25 @@ rl_vi_goto_mark (count, key) { int ch; + RL_SETSTATE(RL_STATE_MOREINPUT); ch = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + if (ch == '`') { rl_point = rl_mark; return 0; } - else if (_rl_lowercase_p (ch) == 0) + else if (ch < 'a' || ch > 'z') { - ding (); + rl_ding (); return -1; } ch -= 'a'; if (vi_mark_chars[ch] == -1) { - ding (); + rl_ding (); return -1; } rl_point = vi_mark_chars[ch]; diff --git a/readline/xmalloc.c b/readline/xmalloc.c index 4160651191b..8985d340d39 100644 --- a/readline/xmalloc.c +++ b/readline/xmalloc.c @@ -7,7 +7,7 @@ Readline 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 + Free Software Foundation; either version 2, or (at your option) any later version. Readline is distributed in the hope that it will be useful, but @@ -17,7 +17,8 @@ You should have received a copy of the GNU General Public License along with Readline; see the file COPYING. If not, write to the Free - Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) #include @@ -31,7 +32,7 @@ # include "ansi_stdlib.h" #endif /* HAVE_STDLIB_H */ -static void memory_error_and_abort (); +#include "xmalloc.h" /* **************************************************************** */ /* */ @@ -39,35 +40,6 @@ static void memory_error_and_abort (); /* */ /* **************************************************************** */ -/* Return a pointer to free()able block of memory large enough - to hold BYTES number of bytes. If the memory cannot be allocated, - print an error message and abort. */ -char * -xmalloc (bytes) - int bytes; -{ - char *temp; - - temp = (char *)malloc (bytes); - if (temp == 0) - memory_error_and_abort ("xmalloc"); - return (temp); -} - -char * -xrealloc (pointer, bytes) - char *pointer; - int bytes; -{ - char *temp; - - temp = pointer ? (char *)realloc (pointer, bytes) : (char *)malloc (bytes); - - if (temp == 0) - memory_error_and_abort ("xrealloc"); - return (temp); -} - static void memory_error_and_abort (fname) char *fname; @@ -76,11 +48,40 @@ memory_error_and_abort (fname) exit (2); } +/* Return a pointer to free()able block of memory large enough + to hold BYTES number of bytes. If the memory cannot be allocated, + print an error message and abort. */ +PTR_T +xmalloc (bytes) + size_t bytes; +{ + PTR_T temp; + + temp = malloc (bytes); + if (temp == 0) + memory_error_and_abort ("xmalloc"); + return (temp); +} + +PTR_T +xrealloc (pointer, bytes) + PTR_T pointer; + size_t bytes; +{ + PTR_T temp; + + temp = pointer ? realloc (pointer, bytes) : malloc (bytes); + + if (temp == 0) + memory_error_and_abort ("xrealloc"); + return (temp); +} + /* Use this as the function to call when adding unwind protects so we don't need to know what free() returns. */ void xfree (string) - char *string; + PTR_T string; { if (string) free (string); diff --git a/readline/xmalloc.h b/readline/xmalloc.h new file mode 100644 index 00000000000..9cb08ba21f1 --- /dev/null +++ b/readline/xmalloc.h @@ -0,0 +1,46 @@ +/* xmalloc.h -- memory allocation that aborts on errors. */ + +/* Copyright (C) 1999 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 (_XMALLOC_H_) +#define _XMALLOC_H_ + +#if defined (READLINE_LIBRARY) +# include "rlstdc.h" +#else +# include +#endif + +#ifndef PTR_T + +#ifdef __STDC__ +# define PTR_T void * +#else +# define PTR_T char * +#endif + +#endif /* !PTR_T */ + +extern PTR_T xmalloc PARAMS((size_t)); +extern PTR_T xrealloc PARAMS((void *, size_t)); +extern void xfree PARAMS((void *)); + +#endif /* _XMALLOC_H_ */ From 666dd7ba7f020aca156b16be7922dcce66039bf4 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Nov 2002 13:30:48 +0400 Subject: [PATCH 13/89] discard warnings in readline 4.3 --- readline/display.c | 4 ++-- readline/mbutil.c | 4 ++-- readline/rlmbutil.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/readline/display.c b/readline/display.c index 180061b29ae..82899d04f0c 100644 --- a/readline/display.c +++ b/readline/display.c @@ -70,7 +70,7 @@ static void insert_some_chars PARAMS((char *, int, int)); static void cr PARAMS((void)); #if defined (HANDLE_MULTIBYTE) -static int _rl_col_width PARAMS((char *, int, int)); +static int _rl_col_width PARAMS((const char *, int, int)); static int *_rl_wrapped_line; #else # define _rl_col_width(l, s, e) (((e) <= (s)) ? 0 : (e) - (s)) @@ -2118,7 +2118,7 @@ _rl_current_display_line () scan from the beginning of the string to take the state into account. */ static int _rl_col_width (str, start, end) - char *str; + const char *str; int start, end; { wchar_t wc; diff --git a/readline/mbutil.c b/readline/mbutil.c index 1b7342bfc0b..debad6320ce 100644 --- a/readline/mbutil.c +++ b/readline/mbutil.c @@ -196,7 +196,7 @@ _rl_find_prev_mbchar_internal (string, seed, find_non_zero) if it couldn't parse a complete multibyte character. */ int _rl_get_char_len (src, ps) - char *src; + const char *src; mbstate_t *ps; { size_t tmp; @@ -251,7 +251,7 @@ _rl_compare_chars (buf1, pos1, ps1, buf2, pos2, ps2) it returns -1 */ int _rl_adjust_point(string, point, ps) - char *string; + const char *string; int point; mbstate_t *ps; { diff --git a/readline/rlmbutil.h b/readline/rlmbutil.h index 27ca32bfc7d..4660a72fce5 100644 --- a/readline/rlmbutil.h +++ b/readline/rlmbutil.h @@ -82,8 +82,8 @@ extern int _rl_find_next_mbchar PARAMS((char *, int, int, int)); #ifdef HANDLE_MULTIBYTE extern int _rl_compare_chars PARAMS((char *, int, mbstate_t *, char *, int, mbstate_t *)); -extern int _rl_get_char_len PARAMS((char *, mbstate_t *)); -extern int _rl_adjust_point PARAMS((char *, int, mbstate_t *)); +extern int _rl_get_char_len PARAMS((const char *, mbstate_t *)); +extern int _rl_adjust_point PARAMS((const char *, int, mbstate_t *)); extern int _rl_read_mbchar PARAMS((char *, int)); extern int _rl_read_mbstring PARAMS((int, char *, int)); From 0b19cb1e2dcf180ced44403f3ce8d78437468348 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Nov 2002 22:16:29 +0100 Subject: [PATCH 14/89] Do-compile: - applied some changes from the 4.0 tree (enable multiple --conf-environment options, add --with-debug, don't add "-max" prefix just because BDB is enabled) Build-tools/Do-compile: - applied some changes from the 4.0 tree (enable multiple --conf-environment options, add --with-debug, don't add "-max" prefix just because BDB is enabled) --- Build-tools/Do-compile | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/Build-tools/Do-compile b/Build-tools/Do-compile index 067b88888ac..dd082181200 100755 --- a/Build-tools/Do-compile +++ b/Build-tools/Do-compile @@ -14,7 +14,7 @@ $opt_innodb=$opt_bdb=$opt_raid=$opt_libwrap=0; GetOptions( "bdb", "build-thread=i", - "config-env=s", + "config-env=s" => \@config_env, "config-options=s" => \@config_options, "dbd-options=s", "debug", @@ -45,6 +45,7 @@ GetOptions( "use-old-distribution", "user=s", "version-suffix=s", + "with-debug", "with-low-memory", "with-other-libc=s", "with-small-disk", @@ -53,11 +54,6 @@ GetOptions( usage() if ($opt_help); usage() if (!$opt_distribution); -if ($opt_bdb && $opt_version_suffix eq "") -{ - $opt_version_suffix="-max"; -} - if (@make_options > 0) { chomp(@make_options); @@ -70,6 +66,12 @@ if (@config_options > 0) $opt_config_options= join(" ", @config_options); } +if (@config_env > 0) +{ + chomp(@config_env); + $opt_config_env= join(" ", @config_env); +} + chomp($host=`hostname`); $full_host_name=$host; $connect_option= ($opt_tcpip ? "--host=$host" : ""); @@ -208,6 +210,7 @@ if ($opt_stage <= 1) $opt_config_options.= " --disable-shared" if (!$opt_enable_shared); # Default for binary versions $opt_config_options.= " --with-berkeley-db" if ($opt_bdb); $opt_config_options.= " --with-client-ldflags=-all-static" if ($opt_static_client); + $opt_config_options.= " --with-debug" if ($opt_with_debug); $opt_config_options.= " --with-libwrap" if ($opt_libwrap); $opt_config_options.= " --with-low-memory" if ($opt_with_low_memory); $opt_config_options.= " --with-mysqld-ldflags=-all-static" if ($opt_static_server); @@ -258,7 +261,7 @@ if ($opt_stage <= 3) log_system("rm -fr mysql-3* mysql-4* $pwd/$host/*.tar.gz"); log_system("nm -n sql/mysqld | gzip -9 -v 2>&1 > sql/mysqld.sym.gz | cat"); - $flags.= "--no-strip" if ($opt_no_strip); + $flags.= "--no-strip" if ($opt_no_strip || $opt_with_debug); check_system("scripts/make_binary_distribution --tmp=$opt_tmp --suffix=$opt_suffix $flags",".tar.gz created"); safe_system("mv mysql*.tar.gz $pwd/$host"); if (-f "client/.libs/mysqladmin") @@ -500,6 +503,9 @@ If user is empty then no mail is sent. --version-suffix suffix Set name suffix (e.g. 'com' or '-max') for a distribution +--with-debug +Build binaries with debug information (implies "--no-strip") + --with-low-memory Use less memory when compiling. @@ -530,7 +536,7 @@ sub abort print TMP "To: $email\n"; print TMP "Subject: $ver$opt_version_suffix compilation failed\n\n"; close TMP; - system("tail -40 $log > $log.mail"); + system("tail -n 40 $log > $log.mail"); system("cat $mail_header_file $log.mail | $sendmail -t -f $email"); unlink($mail_header_file); unlink("$log.mail"); @@ -606,7 +612,7 @@ sub which my(@progs)=@_; foreach $prog (@progs) { - chomp($found=`which $prog | head -1`); + chomp($found=`which $prog | head -n 1`); if ($? == 0 && $found ne "" && index($found," ") == -1) { $found =~ s|/+|/|g; # Make nicer output From d0236e30a4c878ff352e4f6ee1f4c1ff74de9e26 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Nov 2002 17:55:49 +0200 Subject: [PATCH 15/89] A fix for --bind-address=hostname --- sql/mysqld.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 71b832f24f4..8d6a1a8a700 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3543,7 +3543,6 @@ static void set_options(void) #endif my_bind_addr = htonl( INADDR_ANY ); } - /* Initiates DEBUG - but no debugging here ! */ static void get_options(int argc,char **argv) @@ -3893,7 +3892,7 @@ static void get_options(int argc,char **argv) else { struct hostent *ent; - if (!optarg || !optarg[0]) + if (optarg && optarg[0]) ent=gethostbyname(optarg); else { From 6f5b38b9dd0841e1841af1243dd19b5a12b59e34 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Nov 2002 18:14:27 +0200 Subject: [PATCH 16/89] fix error in result mysql-test/r/func_test.result: Fixing the error in result --- mysql-test/r/func_test.result | 1 - 1 file changed, 1 deletion(-) diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result index da82567db4d..2f40740d4aa 100644 --- a/mysql-test/r/func_test.result +++ b/mysql-test/r/func_test.result @@ -27,7 +27,6 @@ -1.49 or -1.49 0.6 or 0.6 1 1 start ctime1 ctime2 -2002-11-04 00:00:00 20021029165106 20021105164731 start ctime1 ctime2 2002-11-04 00:00:00 20021029165106 20021105164731 5 between 0 and 10 between 0 and 1 (5 between 0 and 10) between 0 and 1 From a3a99fc7cadc43a5efc071d33dc90ed7f7799034 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Nov 2002 22:13:23 +0200 Subject: [PATCH 17/89] A fix for the bug with: delete from table where column<=>NULL on indexed columns --- mysql-test/r/delete.result | 6 ++++++ mysql-test/t/delete.test | 5 +++++ sql/opt_range.cc | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result index c2230722aa6..e3e95c79fb7 100644 --- a/mysql-test/r/delete.result +++ b/mysql-test/r/delete.result @@ -24,3 +24,9 @@ create table t1 (a bigint not null, primary key (a,a,a,a,a,a,a,a,a,a)); insert into t1 values (2),(4),(6),(8),(10),(12),(14),(16),(18),(20),(22),(24),(26),(23),(27); delete from t1 where a=27; drop table t1; +create table t1 (id int, index(id)); +insert into t1 values(NULL); +delete from t1 where id <=> NULL; +select * from t1; +id +drop table if exists t1; diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test index 953e22cdd55..fc57fdabcd5 100644 --- a/mysql-test/t/delete.test +++ b/mysql-test/t/delete.test @@ -35,3 +35,8 @@ create table t1 (a bigint not null, primary key (a,a,a,a,a,a,a,a,a,a)); insert into t1 values (2),(4),(6),(8),(10),(12),(14),(16),(18),(20),(22),(24),(26),(23),(27); delete from t1 where a=27; drop table t1; +create table t1 (id int, index(id)); +insert into t1 values(NULL); +delete from t1 where id <=> NULL; +select * from t1; +drop table if exists t1; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index f33a2d312b4..14999097c62 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1024,7 +1024,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, field->cmp_type() != value->result_type()) DBUG_RETURN(0); - if (value->save_in_field(field)) + if (value->save_in_field(field) || value->is_null()) { // TODO; Check if we can we remove the following block. if (type == Item_func::EQUAL_FUNC) From 9a2ac08bac0de5e0e42edb1e45ed28da4a7f1b1c Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Nov 2002 21:42:44 +0100 Subject: [PATCH 18/89] configure.in: - fix MYSQL_NO_DASH_VERSION if version number ends on one digit only ("comment" test failed when MySQL version was changed from 4.0.5 to 4.0.5a) configure.in: - fix MYSQL_NO_DASH_VERSION if version number ends on one digit only ("comment" test failed when MySQL version was changed from 4.0.5 to 4.0.5a) --- configure.in | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.in b/configure.in index cc9e9f772b4..4dfee69f1c0 100644 --- a/configure.in +++ b/configure.in @@ -15,6 +15,7 @@ SHARED_LIB_VERSION=11:0:0 # Set all version vars based on $VERSION. How do we do this more elegant ? # Remember that regexps needs to quote [ and ] since this is run through m4 MYSQL_NO_DASH_VERSION=`echo $VERSION | sed -e "s|-.*$||"` +MYSQL_NO_DASH_VERSION=`echo $VERSION | sed -e "s|[a-z]*-.*$||"` MYSQL_BASE_VERSION=`echo $MYSQL_NO_DASH_VERSION | sed -e "s|\.[[^.]]*$||"` F_PART=`echo $MYSQL_BASE_VERSION | sed -e "s|\.||g"| sed -e "s|[a-zA-Z]\+||"|sed -e "s|^\(..\)$|\\10|"` L_PART=`echo $MYSQL_NO_DASH_VERSION | sed -e "s|^[[0-9]]\.[[0-9]]*\.||" | sed -e "s|^\(.\)$|0\\1|" | sed -e "s|[[a-z]]||"` From b473d7d6405e9ab2d65baff3e7a79faae0229c09 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Nov 2002 22:14:57 +0100 Subject: [PATCH 19/89] configure.in: - actually follow the hints in the comment above and "Remember that regexps needs to quote [ and ] since this is run through m4"... configure.in: - actually follow the hints in the comment above and "Remember that regexps needs to quote [ and ] since this is run through m4"... --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 4dfee69f1c0..9b70e81d088 100644 --- a/configure.in +++ b/configure.in @@ -15,7 +15,7 @@ SHARED_LIB_VERSION=11:0:0 # Set all version vars based on $VERSION. How do we do this more elegant ? # Remember that regexps needs to quote [ and ] since this is run through m4 MYSQL_NO_DASH_VERSION=`echo $VERSION | sed -e "s|-.*$||"` -MYSQL_NO_DASH_VERSION=`echo $VERSION | sed -e "s|[a-z]*-.*$||"` +MYSQL_NO_DASH_VERSION=`echo $VERSION | sed -e "s|[[a-z]]*-.*$||"` MYSQL_BASE_VERSION=`echo $MYSQL_NO_DASH_VERSION | sed -e "s|\.[[^.]]*$||"` F_PART=`echo $MYSQL_BASE_VERSION | sed -e "s|\.||g"| sed -e "s|[a-zA-Z]\+||"|sed -e "s|^\(..\)$|\\10|"` L_PART=`echo $MYSQL_NO_DASH_VERSION | sed -e "s|^[[0-9]]\.[[0-9]]*\.||" | sed -e "s|^\(.\)$|0\\1|" | sed -e "s|[[a-z]]||"` From 03ac294cceb5619557fffacbf95901f4c5b1997f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Nov 2002 00:33:15 +0200 Subject: [PATCH 20/89] fixed invalidation of query cache excluded double call of 'invalidate()' mysql-test/r/innodb_cache.result: test of invalidation mysql-test/t/innodb_cache.test: test of invalidation sql/handler.cc: excluded double call of 'invalidate()' sql/sql_delete.cc: fixed invalidation of query cache sql/sql_insert.cc: fixed invalidation of query cache sql/sql_update.cc: fixed invalidation of query cache --- mysql-test/r/innodb_cache.result | 10 ++++++++++ mysql-test/t/innodb_cache.test | 9 ++++++++- sql/handler.cc | 2 +- sql/sql_delete.cc | 10 ++++------ sql/sql_insert.cc | 9 +++------ sql/sql_update.cc | 10 ++++------ 6 files changed, 30 insertions(+), 20 deletions(-) diff --git a/mysql-test/r/innodb_cache.result b/mysql-test/r/innodb_cache.result index eaa030046da..47abcb45fe5 100644 --- a/mysql-test/r/innodb_cache.result +++ b/mysql-test/r/innodb_cache.result @@ -98,3 +98,13 @@ commit; show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 1 +drop table if exists t1; +CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id)) TYPE=InnoDB; +select count(*) from t1; +count(*) +0 +insert into t1 (id) values (0); +select count(*) from t1; +count(*) +1 +drop table t1; diff --git a/mysql-test/t/innodb_cache.test b/mysql-test/t/innodb_cache.test index 21d30420eaf..9066a5f19ba 100644 --- a/mysql-test/t/innodb_cache.test +++ b/mysql-test/t/innodb_cache.test @@ -47,4 +47,11 @@ select * from t3; show status like "Qcache_queries_in_cache"; show status like "Qcache_hits"; commit; -show status like "Qcache_queries_in_cache"; \ No newline at end of file +show status like "Qcache_queries_in_cache"; + +drop table if exists t1; +CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id)) TYPE=InnoDB; +select count(*) from t1; +insert into t1 (id) values (0); +select count(*) from t1; +drop table t1; diff --git a/sql/handler.cc b/sql/handler.cc index f07e90d2eb9..c4e742ef519 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -314,7 +314,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) } #endif #ifdef HAVE_QUERY_CACHE - if (transaction_commited) + if (transaction_commited && thd->transaction.changed_tables) query_cache.invalidate(thd->transaction.changed_tables); #endif /*HAVE_QUERY_CACHE*/ if (error && trans == &thd->transaction.all && mysql_bin_log.is_open()) diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 5f2d7e36a04..1361ff39388 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -179,14 +179,12 @@ cleanup: if (ha_autocommit_or_rollback(thd,error >= 0)) error=1; } + /* - Only invalidate the query cache if something changed or if we - didn't commit the transacion (query cache is automaticly - invalidated on commit) + Store table for future invalidation or invalidate it in + the query cache if something changed */ - if (deleted && - (!transactional_table || - thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) + if (deleted) { query_cache_invalidate3(thd, table_list, 1); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 2508314c469..6ce2b50fc36 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -319,13 +319,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List &fields, error=ha_autocommit_or_rollback(thd,error); /* - Only invalidate the query cache if something changed or if we - didn't commit the transacion (query cache is automaticly - invalidated on commit) + Store table for future invalidation or invalidate it in + the query cache if something changed */ - if ((info.copied || info.deleted) && - (!transactional_table || - thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) + if (info.copied || info.deleted) { query_cache_invalidate3(thd, table_list, 1); } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index b5263322301..97e6ea43bfd 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -318,14 +318,12 @@ int mysql_update(THD *thd, if (ha_autocommit_or_rollback(thd, error >= 0)) error=1; } + /* - Only invalidate the query cache if something changed or if we - didn't commit the transacion (query cache is automaticly - invalidated on commit) + Store table for future invalidation or invalidate it in + the query cache if something changed */ - if (updated && - (!transactional_table || - thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) + if (updated) { query_cache_invalidate3(thd, table_list, 1); } From cb5a2b2fd5541bf019dd0fe1012e687ce1e68eaa Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Nov 2002 13:35:43 +0200 Subject: [PATCH 21/89] Fixed bug with indexed NULL column <=> NULL Fix for Mac OS X shutdown mysql-test/mysql-test-run.sh: Log client error messages mysql-test/r/null_key.result: Test for bug in <=> NULL mysql-test/t/null_key.test: Test for bug in <=> NULL sql/mysqld.cc: Fix for Mac OS X shutdown sql/opt_range.cc: Fixed bug with indexed NULL column <=> NULL --- mysql-test/mysql-test-run.sh | 3 ++- mysql-test/r/null_key.result | 17 +++++++++++++++++ mysql-test/t/null_key.test | 21 +++++++++++++++++++++ sql/mysqld.cc | 4 ++++ sql/opt_range.cc | 18 ++++++++++++------ 5 files changed, 56 insertions(+), 7 deletions(-) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 514ef9e704a..fcddf52c66b 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -249,6 +249,7 @@ SLAVE_MYPID="$MYRUN_DIR/mysqld-slave.pid" SLAVE_MYLOG="$MYSQL_TEST_DIR/var/log/mysqld-slave.log" SLAVE_MYERR="$MYSQL_TEST_DIR/var/log/mysqld-slave.err" +CLIENT_MYLOG="$MYSQL_TEST_DIR/var/log/client.log" SMALL_SERVER="-O key_buffer_size=1M -O sort_buffer=256K -O max_heap_table_size=1M" export MASTER_MYPORT @@ -344,7 +345,7 @@ SLAVE_MYSQLD=$MYSQLD #this can be changed later if we are doing gcov #-- wait_for_server_start () { - $MYSQLADMIN --no-defaults -u $DBUSER --silent -O connect_timeout=10 -w3 --host=$hostname --port=$1 ping >/dev/null 2>&1 + $MYSQLADMIN --no-defaults -u $DBUSER --silent -O connect_timeout=10 -w3 --host=$hostname --port=$1 ping >> $CLIENT_MYLOG 2>&1 exit_code=$? if [ $exit_code != 0 ]; then echo "Error: Could not start $2, exit code $exit_code"; diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result index a0f88b804aa..46bcbebe170 100644 --- a/mysql-test/r/null_key.result +++ b/mysql-test/r/null_key.result @@ -126,3 +126,20 @@ order_id product_id product_type 3d7ce39b5d4b3e3d22aaafe9b633de51 5880836 3 id id id id +id id2 +NULL 0 +1 1 +id id2 +NULL 0 +id id2 +NULL 0 +1 1 +id id2 +NULL 0 +1 1 +id id2 +1 1 +id id2 +1 1 +id id2 +1 1 diff --git a/mysql-test/t/null_key.test b/mysql-test/t/null_key.test index 3ab8b993f43..b1cbd5cdfb0 100644 --- a/mysql-test/t/null_key.test +++ b/mysql-test/t/null_key.test @@ -135,3 +135,24 @@ select * from t1, t2 where t1.id = t2.id; alter table t1 add key id (id); select * from t1, t2 where t1.id = t2.id; drop table t1,t2; + +# +# Check bug when doing <=> NULL on an indexed null field +# + +create table t1 ( + id integer, + id2 integer not null, + index (id), + index (id2) +); +insert into t1 values(null,null),(1,1); +select * from t1; +select * from t1 where id <=> null; +select * from t1 where id <=> null or id > 0; +select * from t1 where id is null or id > 0; +select * from t1 where id2 <=> null or id2 > 0; +select * from t1 where id2 is null or id2 > 0; +delete from t1 where id <=> NULL; +select * from t1; +drop table t1; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 71b832f24f4..7a33a3cfc49 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -739,7 +739,11 @@ static sig_handler print_signal_warning(int sig) void unireg_end(int signal_number __attribute__((unused))) { clean_up(); +#ifdef SIGNALS_DONT_BREAK_READ + exit(0); +#else pthread_exit(0); // Exit is in main thread +#endif } diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 42f20c0f767..0645fe15df3 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -931,8 +931,11 @@ get_mm_leaf(Field *field,KEY_PART *key_part, if (!(res= value->val_str(&tmp))) DBUG_RETURN(&null_element); - // Check if this was a function. This should have be optimized away - // in the sql_select.cc + /* + TODO: + Check if this was a function. This should have be optimized away + in the sql_select.cc + */ if (res != &tmp) { tmp.copy(*res); // Get own copy @@ -1011,8 +1014,10 @@ get_mm_leaf(Field *field,KEY_PART *key_part, type != Item_func::EQUAL_FUNC) DBUG_RETURN(0); // Can't optimize this - /* We can't always use indexes when comparing a string index to a number */ - /* cmp_type() is checked to allow compare of dates to numbers */ + /* + We can't always use indexes when comparing a string index to a number + cmp_type() is checked to allow compare of dates to numbers + */ if (field->result_type() == STRING_RESULT && value->result_type() != STRING_RESULT && field->cmp_type() != value->result_type()) @@ -1020,6 +1025,7 @@ get_mm_leaf(Field *field,KEY_PART *key_part, if (value->save_in_field(field)) { + /* This happens when we try to insert a NULL field in a not null column */ if (type == Item_func::EQUAL_FUNC) { /* convert column_name <=> NULL -> column_name IS NULL */ @@ -1029,14 +1035,14 @@ get_mm_leaf(Field *field,KEY_PART *key_part, *str = 1; DBUG_RETURN(new SEL_ARG(field,str,str)); } - DBUG_RETURN(&null_element); // NULL is never true + DBUG_RETURN(&null_element); // cmp with NULL is never true } // Get local copy of key char *str= (char*) sql_alloc(key_part->part_length+maybe_null); if (!str) DBUG_RETURN(0); if (maybe_null) - *str=0; // Not NULL + *str= (char) field->is_real_null(); // Set to 1 if null field->get_key_image(str+maybe_null,key_part->part_length); if (!(tree=new SEL_ARG(field,str,str))) DBUG_RETURN(0); From 89083f2d6d078eb25f1fe013d8cd5bc46b9a631c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Nov 2002 13:47:01 +0200 Subject: [PATCH 22/89] reverting a change --- sql/opt_range.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 14999097c62..f33a2d312b4 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1024,7 +1024,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, field->cmp_type() != value->result_type()) DBUG_RETURN(0); - if (value->save_in_field(field) || value->is_null()) + if (value->save_in_field(field)) { // TODO; Check if we can we remove the following block. if (type == Item_func::EQUAL_FUNC) From 001446d97134edad95b3235082256c0202f51cd9 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Nov 2002 13:52:40 +0200 Subject: [PATCH 23/89] Moved test to correct file --- mysql-test/r/func_test.result | 3 --- mysql-test/r/func_time.result | 5 +++++ mysql-test/t/func_test.test | 10 ---------- mysql-test/t/func_time.test | 18 ++++++++++++++++++ 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result index 2f40740d4aa..586e345ea10 100644 --- a/mysql-test/r/func_test.result +++ b/mysql-test/r/func_test.result @@ -26,9 +26,6 @@ 1 1 1 -1.49 or -1.49 0.6 or 0.6 1 1 -start ctime1 ctime2 -start ctime1 ctime2 -2002-11-04 00:00:00 20021029165106 20021105164731 5 between 0 and 10 between 0 and 1 (5 between 0 and 10) between 0 and 1 0 1 1 and 2 between 2 and 10 2 between 2 and 10 and 1 diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 71fc7e4b90b..a77d9b2cdff 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -220,3 +220,8 @@ to_days("0000-00-00") to_days(d) to_days(dt) to_days(t) to_days(c) NULL NULL NULL NULL NULL extract(MONTH FROM "0000-00-00") extract(MONTH FROM d) extract(MONTH FROM dt) extract(MONTH FROM t) extract(MONTH FROM c) 0 0 0 0 0 +start ctime1 ctime2 +start ctime1 ctime2 +2002-11-04 00:00:00 20021029165106 20021105164731 +start ctime1 ctime2 +2002-11-04 00:00:00 2002-10-29 16:51:06 2002-11-05 16:47:31 diff --git a/mysql-test/t/func_test.test b/mysql-test/t/func_test.test index ccbb531e2e6..ec44009b1a6 100644 --- a/mysql-test/t/func_test.test +++ b/mysql-test/t/func_test.test @@ -15,16 +15,6 @@ select 2 between 1 and 3, "monty" between "max" and "my",2=2 and "monty" between select 'b' between 'a' and 'c', 'B' between 'a' and 'c'; select 2 in (3,2,5,9,5,1),"monty" in ("david","monty","allan"), 1.2 in (1.4,1.2,1.0); select -1.49 or -1.49,0.6 or 0.6; -drop table if exists t1,t2; -CREATE TABLE t1 ( start datetime default NULL) TYPE=MyISAM; -INSERT INTO t1 VALUES ('2002-10-21 00:00:00'); -INSERT INTO t1 VALUES ('2002-10-28 00:00:00'); -INSERT INTO t1 VALUES ('2002-11-04 00:00:00'); -CREATE TABLE t2 ( ctime1 timestamp(14) NOT NULL, ctime2 timestamp(14) NOT NULL) TYPE=MyISAM; -INSERT INTO t2 VALUES (20021029165106,20021105164731); -select * from t1, t2 where t1.start between t2.ctime1 and t2.ctime2; -select * from t1, t2 where t1.start >= t2.ctime1 and t1.start <= t2.ctime2; -drop table if exists t1,t2; # # Wrong usage of functions diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index ffb0f8bbf1e..e267339d64c 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -150,3 +150,21 @@ select yearweek("0000-00-00"),yearweek(d),yearweek(dt),yearweek(t),yearweek(c) f select to_days("0000-00-00"),to_days(d),to_days(dt),to_days(t),to_days(c) from t1; select extract(MONTH FROM "0000-00-00"),extract(MONTH FROM d),extract(MONTH FROM dt),extract(MONTH FROM t),extract(MONTH FROM c) from t1; drop table t1; + + +# +# Test problem with TIMESTAMP and BETWEEN +# + +CREATE TABLE t1 ( start datetime default NULL); +INSERT INTO t1 VALUES ('2002-10-21 00:00:00'),('2002-10-28 00:00:00'),('2002-11-04 00:00:00'); +CREATE TABLE t2 ( ctime1 timestamp(14) NOT NULL, ctime2 timestamp(14) NOT NULL); +INSERT INTO t2 VALUES (20021029165106,20021105164731); +CREATE TABLE t3 (ctime1 char(19) NOT NULL, ctime2 char(19) NOT NULL); +INSERT INTO t3 VALUES ("2002-10-29 16:51:06","2002-11-05 16:47:31"); + +# The following statement should be fixed to return a row in 4.1 +select * from t1, t2 where t1.start between t2.ctime1 and t2.ctime2; +select * from t1, t2 where t1.start >= t2.ctime1 and t1.start <= t2.ctime2; +select * from t1, t3 where t1.start between t3.ctime1 and t3.ctime2; +drop table t1,t2,t3; From fa76afe6edbc6572f179d1dcf859f013e85ef7dd Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Nov 2002 13:59:06 +0200 Subject: [PATCH 24/89] ut0mem.c: Flush stderr if we run out of memory, so that the error message more probably finds its way to the error log innobase/ut/ut0mem.c: Flush stderr if we run out of memory, so that the error message more probably finds its way to the error log --- innobase/ut/ut0mem.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/innobase/ut/ut0mem.c b/innobase/ut/ut0mem.c index 2a7643551ad..03f15031fdf 100644 --- a/innobase/ut/ut0mem.c +++ b/innobase/ut/ut0mem.c @@ -90,6 +90,12 @@ ut_malloc_low( "InnoDB: on Linux we get a stack trace.\n", n, ut_total_allocated_memory, errno); + /* Flush stderr to make more probable that the error + message gets in the error file before we generate a seg + fault */ + + fflush(stderr); + os_fast_mutex_unlock(&ut_list_mutex); /* Make an intentional seg fault so that we get a stack From 0e9a75a4f7151ea7930a5eaddfc91fd210873f16 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Nov 2002 14:50:53 +0100 Subject: [PATCH 25/89] Moved safe_to_cache_query from thd to lex. This is required for prepared statements and stored procedures. BitKeeper/etc/ignore: Added bkpull.log bkpull.log.2 bkpull.log.3 build.log sql/safe_to_cache_query.txt to the ignore list sql/item_create.cc: Moved safe_to_cache_query from thd to lex. sql/item_func.cc: Moved safe_to_cache_query from thd to lex. sql/sql_cache.cc: Moved safe_to_cache_query from thd to lex. Note: Query_cache::is_cacheable() has both a thd and lex argument. We assumed that it's the lex->safe_to_cache_query we should test. sql/sql_class.cc: Moved safe_to_cache_query from thd to lex. sql/sql_class.h: Moved safe_to_cache_query from thd to lex. sql/sql_lex.cc: Moved safe_to_cache_query from thd to lex. We set it to 1 initially. It's then set to 0 in cases where it's know not to be safe. (Before this change, it was set to 0 in thd, and then set to 1 before parsing.) sql/sql_lex.h: Moved safe_to_cache_query from thd to lex. sql/sql_parse.cc: Moved safe_to_cache_query from thd to lex. No point in setting it here now, it's set in lex_start() later. sql/sql_prepare.cc: Moved safe_to_cache_query from thd to lex. Must set it after lex_start() has been called. sql/sql_yacc.yy: Moved safe_to_cache_query from thd to lex. --- .bzrignore | 5 +++++ sql/item_create.cc | 14 +++++++------- sql/item_func.cc | 4 ++-- sql/sql_cache.cc | 10 +++++----- sql/sql_class.cc | 2 +- sql/sql_class.h | 1 - sql/sql_lex.cc | 3 ++- sql/sql_lex.h | 1 + sql/sql_parse.cc | 1 - sql/sql_prepare.cc | 2 +- sql/sql_yacc.yy | 40 ++++++++++++++++++++-------------------- 11 files changed, 44 insertions(+), 39 deletions(-) diff --git a/.bzrignore b/.bzrignore index 278c3de2ee5..978926c8c37 100644 --- a/.bzrignore +++ b/.bzrignore @@ -557,3 +557,8 @@ vio/test-ssl vio/test-sslclient vio/test-sslserver vio/viotest-ssl +bkpull.log +bkpull.log.2 +bkpull.log.3 +build.log +sql/safe_to_cache_query.txt diff --git a/sql/item_create.cc b/sql/item_create.cc index e4c9a160686..ad9058c1691 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -76,7 +76,7 @@ Item *create_func_ceiling(Item* a) Item *create_func_connection_id(void) { THD *thd=current_thd; - thd->safe_to_cache_query=0; + thd->lex.safe_to_cache_query=0; return new Item_int("CONNECTION_ID()",(longlong) thd->thread_id,10); } @@ -149,7 +149,7 @@ Item *create_func_floor(Item* a) Item *create_func_found_rows(void) { THD *thd=current_thd; - thd->safe_to_cache_query=0; + thd->lex.safe_to_cache_query=0; return new Item_int("FOUND_ROWS()",(longlong) thd->found_rows(),21); } @@ -160,7 +160,7 @@ Item *create_func_from_days(Item* a) Item *create_func_get_lock(Item* a, Item *b) { - current_thd->safe_to_cache_query=0; + current_thd->lex.safe_to_cache_query=0; return new Item_func_get_lock(a, b); } @@ -308,7 +308,7 @@ Item *create_func_radians(Item *a) Item *create_func_release_lock(Item* a) { - current_thd->safe_to_cache_query=0; + current_thd->lex.safe_to_cache_query=0; return new Item_func_release_lock(a); } @@ -416,13 +416,13 @@ Item *create_func_year(Item* a) Item *create_load_file(Item* a) { - current_thd->safe_to_cache_query=0; + current_thd->lex.safe_to_cache_query=0; return new Item_load_file(a); } Item *create_wait_for_master_pos(Item* a, Item* b) { - current_thd->safe_to_cache_query=0; + current_thd->lex.safe_to_cache_query=0; return new Item_master_pos_wait(a, b); } @@ -443,7 +443,7 @@ Item *create_func_cast(Item *a, Item_cast cast_type) Item *create_func_is_free_lock(Item* a) { - current_thd->safe_to_cache_query=0; + current_thd->lex.safe_to_cache_query=0; return new Item_func_is_free_lock(a); } diff --git a/sql/item_func.cc b/sql/item_func.cc index 75260065be6..e28fda0340e 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2470,7 +2470,7 @@ Item *get_system_var(enum_var_type var_type, LEX_STRING name) } if (!(item=var->item(thd, var_type))) return 0; // Impossible - thd->safe_to_cache_query=0; + thd->lex.safe_to_cache_query=0; buff[0]='@'; buff[1]='@'; pos=buff+2; @@ -2496,7 +2496,7 @@ Item *get_system_var(enum_var_type var_type, const char *var_name, uint length, DBUG_ASSERT(var != 0); if (!(item=var->item(thd, var_type))) return 0; // Impossible - thd->safe_to_cache_query=0; + thd->lex.safe_to_cache_query=0; item->set_name(item_name); // Will use original name return item; } diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index ef584f4364e..aa0f5824b4e 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -289,7 +289,7 @@ TODO list: if (thd->temp_tables || global_merge_table_count) - - Another option would be to set thd->safe_to_cache_query to 0 + - Another option would be to set thd->lex.safe_to_cache_query to 0 in 'get_lock_data' if any of the tables was a tmp table or a MRG_ISAM table. (This could be done with almost no speed penalty) @@ -900,7 +900,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) /* Check that we haven't forgot to reset the query cache variables */ DBUG_ASSERT(thd->net.query_cache_query == 0); - if (!thd->safe_to_cache_query) + if (!thd->lex.safe_to_cache_query) { DBUG_PRINT("qcache", ("SELECT is non-cacheable")); goto err; @@ -994,7 +994,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) table_list.db, table_list.alias)); refused++; // This is actually a hit STRUCT_UNLOCK(&structure_guard_mutex); - thd->safe_to_cache_query=0; // Don't try to cache this + thd->lex.safe_to_cache_query=0; // Don't try to cache this BLOCK_UNLOCK_RD(query_block); DBUG_RETURN(-1); // Privilege error } @@ -1003,7 +1003,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) DBUG_PRINT("qcache", ("Need to check column privileges for %s.%s", table_list.db, table_list.alias)); BLOCK_UNLOCK_RD(query_block); - thd->safe_to_cache_query=0; // Don't try to cache this + thd->lex.safe_to_cache_query=0; // Don't try to cache this goto err_unlock; // Parse query } } @@ -2457,7 +2457,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len, (thd->variables.query_cache_type == 1 || (thd->variables.query_cache_type == 2 && (lex->select_lex.options & OPTION_TO_QUERY_CACHE))) && - thd->safe_to_cache_query) + lex->safe_to_cache_query) { my_bool has_transactions = 0; DBUG_PRINT("qcache", ("options %lx %lx, type %u", diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 4141211ad92..9bca7245cba 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -87,7 +87,7 @@ THD::THD():user_time(0), fatal_error(0), host=user=priv_user=db=query=ip=0; host_or_ip="unknown ip"; locked=killed=count_cuted_fields=some_tables_deleted=no_errors=password= - query_start_used=safe_to_cache_query=prepare_command=0; + query_start_used=prepare_command=0; db_length=query_length=col_access=0; query_error=0; next_insert_id=last_insert_id=0; diff --git a/sql/sql_class.h b/sql/sql_class.h index acdf2471ba8..e64cfbc198a 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -507,7 +507,6 @@ public: bool query_start_used,last_insert_id_used,insert_id_used,rand_used; bool system_thread,in_lock_tables,global_read_lock; bool query_error, bootstrap, cleanup_done; - bool safe_to_cache_query; bool volatile killed; bool prepare_command; Item_param *params; // Pointer to array of params diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 9ed66aede6f..e3ffe2a8120 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -154,6 +154,7 @@ LEX *lex_start(THD *thd, uchar *buf,uint length) lex->ignore_space=test(thd->sql_mode & MODE_IGNORE_SPACE); lex->slave_thd_opt=0; lex->sql_command=SQLCOM_END; + lex->safe_to_cache_query= 1; bzero(&lex->mi,sizeof(lex->mi)); return lex; } @@ -182,7 +183,7 @@ static int find_keyword(LEX *lex, uint len, bool function) udf_func *udf; if (function && using_udf_functions && (udf=find_udf((char*) tok, len))) { - lex->thd->safe_to_cache_query=0; + lex->safe_to_cache_query=0; lex->yylval->udf=udf; switch (udf->returns) { case STRING_RESULT: diff --git a/sql/sql_lex.h b/sql/sql_lex.h index dd41af4b250..fa4eca80ee2 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -440,6 +440,7 @@ typedef struct st_lex bool drop_primary, drop_if_exists, drop_temporary, local_file; bool in_comment, ignore_space, verbose, simple_alter; bool derived_tables, describe, olap; + bool safe_to_cache_query; uint slave_thd_opt; CHARSET_INFO *charset; char *help_arg; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 263ac50120d..4e5f0019ad6 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2875,7 +2875,6 @@ mysql_init_query(THD *thd) thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0; thd->sent_row_count= thd->examined_row_count= 0; thd->fatal_error= thd->rand_used= 0; - thd->safe_to_cache_query= 1; thd->possible_loops= 0; DBUG_VOID_RETURN; } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 08377a10501..527878596f4 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -606,9 +606,9 @@ static bool parse_prepare_query(PREP_STMT *stmt, mysql_log.write(thd,COM_PREPARE,"%s",packet); mysql_init_query(thd); thd->prepare_command=true; - thd->safe_to_cache_query= 0; LEX *lex=lex_start(thd, (uchar*) packet, length); + lex->safe_to_cache_query= 0; if (!yyparse() && !thd->fatal_error) error= send_prepare_results(stmt); lex_end(lex); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index eaae24d0310..5dcb4f09951 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1676,7 +1676,7 @@ select_option: YYABORT; Select->options|= OPTION_FOUND_ROWS; } - | SQL_NO_CACHE_SYM { current_thd->safe_to_cache_query=0; } + | SQL_NO_CACHE_SYM { Lex->safe_to_cache_query=0; } | SQL_CACHE_SYM { Select->options|= OPTION_TO_QUERY_CACHE; } | ALL {} ; @@ -1689,7 +1689,7 @@ select_lock_type: if (check_simple_select()) YYABORT; lex->lock_option= TL_WRITE; - lex->thd->safe_to_cache_query=0; + lex->safe_to_cache_query=0; } | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM { @@ -1697,7 +1697,7 @@ select_lock_type: if (check_simple_select()) YYABORT; lex->lock_option= TL_READ_WITH_SHARED_LOCKS; - lex->thd->safe_to_cache_query=0; + lex->safe_to_cache_query=0; } ; @@ -1885,12 +1885,12 @@ simple_expr: | '@' ident_or_text SET_VAR expr { $$= new Item_func_set_user_var($2,$4); - current_thd->safe_to_cache_query=0; + Lex->safe_to_cache_query=0; } | '@' ident_or_text { $$= new Item_func_get_user_var($2); - current_thd->safe_to_cache_query=0; + Lex->safe_to_cache_query=0; } | '@' '@' opt_var_ident_type ident_or_text { @@ -1944,13 +1944,13 @@ simple_expr: | CONCAT_WS '(' expr ',' expr_list ')' { $$= new Item_func_concat_ws($3, *$5); } | CURDATE optional_braces - { $$= new Item_func_curdate(); current_thd->safe_to_cache_query=0; } + { $$= new Item_func_curdate(); Lex->safe_to_cache_query=0; } | CURTIME optional_braces - { $$= new Item_func_curtime(); current_thd->safe_to_cache_query=0; } + { $$= new Item_func_curtime(); Lex->safe_to_cache_query=0; } | CURTIME '(' expr ')' { $$= new Item_func_curtime($3); - current_thd->safe_to_cache_query=0; + Lex->safe_to_cache_query=0; } | DATE_ADD_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')' { $$= new Item_date_add_interval($3,$6,$7,0); } @@ -1959,7 +1959,7 @@ simple_expr: | DATABASE '(' ')' { $$= new Item_func_database(); - current_thd->safe_to_cache_query=0; + Lex->safe_to_cache_query=0; } | ELT_FUNC '(' expr ',' expr_list ')' { $$= new Item_func_elt($3, *$5); } @@ -1968,7 +1968,7 @@ simple_expr: | ENCRYPT '(' expr ')' { $$= new Item_func_encrypt($3); - current_thd->safe_to_cache_query=0; + Lex->safe_to_cache_query=0; } | ENCRYPT '(' expr ',' expr ')' { $$= new Item_func_encrypt($3,$5); } | DECODE_SYM '(' expr ',' TEXT_STRING ')' @@ -2028,7 +2028,7 @@ simple_expr: | LAST_INSERT_ID '(' expr ')' { $$= new Item_func_set_last_insert_id($3); - current_thd->safe_to_cache_query=0; + Lex->safe_to_cache_query=0; } | LEFT '(' expr ',' expr ')' { $$= new Item_func_left($3,$5); } @@ -2083,9 +2083,9 @@ simple_expr: { $$= new Item_func_spatial_collection(* $3, Geometry::wkbMultiPolygon, Geometry::wkbPolygon ); } | NOW_SYM optional_braces - { $$= new Item_func_now(); current_thd->safe_to_cache_query=0;} + { $$= new Item_func_now(); Lex->safe_to_cache_query=0;} | NOW_SYM '(' expr ')' - { $$= new Item_func_now($3); current_thd->safe_to_cache_query=0;} + { $$= new Item_func_now($3); Lex->safe_to_cache_query=0;} | PASSWORD '(' expr ')' { $$= new Item_func_password($3); @@ -2104,9 +2104,9 @@ simple_expr: | POSITION_SYM '(' no_in_expr IN_SYM expr ')' { $$ = new Item_func_locate($5,$3); } | RAND '(' expr ')' - { $$= new Item_func_rand($3); current_thd->safe_to_cache_query=0;} + { $$= new Item_func_rand($3); Lex->safe_to_cache_query=0;} | RAND '(' ')' - { $$= new Item_func_rand(); current_thd->safe_to_cache_query=0;} + { $$= new Item_func_rand(); Lex->safe_to_cache_query=0;} | REPLACE '(' expr ',' expr ',' expr ')' { $$= new Item_func_replace($3,$5,$7); } | RIGHT '(' expr ',' expr ')' @@ -2189,12 +2189,12 @@ simple_expr: | UNIX_TIMESTAMP '(' ')' { $$= new Item_func_unix_timestamp(); - current_thd->safe_to_cache_query=0; + Lex->safe_to_cache_query=0; } | UNIX_TIMESTAMP '(' expr ')' { $$= new Item_func_unix_timestamp($3); } | USER '(' ')' - { $$= new Item_func_user(); current_thd->safe_to_cache_query=0; } + { $$= new Item_func_user(); Lex->safe_to_cache_query=0; } | WEEK_SYM '(' expr ')' { $$= new Item_func_week($3,new Item_int((char*) "0",0,1)); } | WEEK_SYM '(' expr ',' expr ')' @@ -2208,7 +2208,7 @@ simple_expr: | BENCHMARK_SYM '(' ULONG_NUM ',' expr ')' { $$=new Item_func_benchmark($3,$5); - current_thd->safe_to_cache_query=0; + Lex->safe_to_cache_query=0; } | EXTRACT_SYM '(' interval FROM expr ')' { $$=new Item_extract( $3, $5); }; @@ -2667,7 +2667,7 @@ procedure_clause: lex->proc_list.next= (byte**) &lex->proc_list.first; if (add_proc_to_list(new Item_field(NULL,NULL,$2.str))) YYABORT; - current_thd->safe_to_cache_query=0; + Lex->safe_to_cache_query=0; } '(' procedure_list ')'; @@ -2739,7 +2739,7 @@ opt_into: } | INTO select_var_list_init { - current_thd->safe_to_cache_query=0; + Lex->safe_to_cache_query=0; } ; From ed4a4b89cdebaa31560fcbfd0f677e4b59a54123 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Nov 2002 18:35:58 +0400 Subject: [PATCH 26/89] correct some warnings with const char* --- readline/bind.c | 8 ++--- readline/display.c | 11 ++++--- readline/histexpand.c | 4 +-- readline/history.h | 4 +-- readline/isearch.c | 4 +-- readline/readline.h | 4 +-- readline/rlprivate.h | 22 ++++++------- readline/tcap.h | 2 +- readline/terminal.c | 77 ++++++++++++++++++++++--------------------- readline/text.c | 4 +-- readline/tilde.c | 2 +- 11 files changed, 72 insertions(+), 70 deletions(-) diff --git a/readline/bind.c b/readline/bind.c index 324499acf8f..7e8ca04e0d6 100644 --- a/readline/bind.c +++ b/readline/bind.c @@ -1629,17 +1629,17 @@ rl_set_keymap_from_edit_mode () } -char * +const char * rl_get_keymap_name_from_edit_mode () { if (rl_editing_mode == emacs_mode) - return (char*)"emacs"; + return "emacs"; #if defined (VI_MODE) else if (rl_editing_mode == vi_mode) - return (char*)"vi"; + return "vi"; #endif /* VI_MODE */ else - return (char*)"nope"; + return "nope"; } /* **************************************************************** */ diff --git a/readline/display.c b/readline/display.c index 82899d04f0c..f393e7e8516 100644 --- a/readline/display.c +++ b/readline/display.c @@ -121,7 +121,7 @@ int _rl_suppress_redisplay = 0; /* The stuff that gets printed out before the actual text of the line. This is usually pointing to rl_prompt. */ -char *rl_display_prompt = (char *)NULL; +const char *rl_display_prompt = (char *)NULL; /* Pseudo-global variables declared here. */ /* The visible cursor position. If you print some text, adjust this. */ @@ -382,7 +382,7 @@ rl_redisplay () register char *line; int c_pos, inv_botlin, lb_botlin, lb_linenum; int newlines, lpos, temp; - char *prompt_this_line; + const char *prompt_this_line; #if defined (HANDLE_MULTIBYTE) wchar_t wc; size_t wc_bytes; @@ -395,7 +395,7 @@ rl_redisplay () return; if (!rl_display_prompt) - rl_display_prompt = (char*)""; + rl_display_prompt = ""; if (invisible_line == 0) { @@ -1760,7 +1760,7 @@ rl_reset_line_state () { rl_on_new_line (); - rl_display_prompt = (char*)(rl_prompt ? rl_prompt : ""); + rl_display_prompt = rl_prompt ? rl_prompt : ""; forced_display = 1; return 0; } @@ -1999,7 +1999,8 @@ static void redraw_prompt (t) char *t; { - char *oldp, *oldl, *oldlprefix; + const char *oldp; + char *oldl, *oldlprefix; int oldlen, oldlast, oldplen, oldninvis; /* Geez, I should make this a struct. */ diff --git a/readline/histexpand.c b/readline/histexpand.c index a98067956c2..f01d54c5b1d 100644 --- a/readline/histexpand.c +++ b/readline/histexpand.c @@ -85,14 +85,14 @@ char history_comment_char = '\0'; /* The list of characters which inhibit the expansion of text if found immediately following history_expansion_char. */ -char *history_no_expand_chars = (char*)" \t\n\r="; +const char *history_no_expand_chars = " \t\n\r="; /* If set to a non-zero value, single quotes inhibit history expansion. The default is 0. */ int history_quotes_inhibit_expansion = 0; /* Used to split words by history_tokenize_internal. */ -char *history_word_delimiters = (char*)HISTORY_WORD_DELIMITERS; +const char *history_word_delimiters = HISTORY_WORD_DELIMITERS; /* If set, this points to a function that is called to verify that a particular history expansion should be performed. */ diff --git a/readline/history.h b/readline/history.h index 58b5de4655f..afd85104554 100644 --- a/readline/history.h +++ b/readline/history.h @@ -225,9 +225,9 @@ extern int history_length; extern int history_max_entries; extern char history_expansion_char; extern char history_subst_char; -extern char *history_word_delimiters; +extern const char *history_word_delimiters; extern char history_comment_char; -extern char *history_no_expand_chars; +extern const char *history_no_expand_chars; extern char *history_search_delimiter_chars; extern int history_quotes_inhibit_expansion; diff --git a/readline/isearch.c b/readline/isearch.c index c0604ce703c..137842a841f 100644 --- a/readline/isearch.c +++ b/readline/isearch.c @@ -70,7 +70,7 @@ static char *prev_line_found; static char *last_isearch_string; static int last_isearch_string_len; -static char default_isearch_terminators[] = "\033\012"; +static const char *default_isearch_terminators = "\033\012"; /* Search backwards through the history looking for a string which is typed interactively. Start with the current line. */ @@ -186,7 +186,7 @@ rl_search_history (direction, invoking_key) /* The list of characters which terminate the search, but are not subsequently executed. If the variable isearch-terminators has been set, we use that value, otherwise we use ESC and C-J. */ - char *isearch_terminators; + const char *isearch_terminators; RL_SETSTATE(RL_STATE_ISEARCH); orig_point = rl_point; diff --git a/readline/readline.h b/readline/readline.h index f11b3d0357c..9425de50aef 100644 --- a/readline/readline.h +++ b/readline/readline.h @@ -329,7 +329,7 @@ extern void rl_set_keymap PARAMS((Keymap)); extern Keymap rl_get_keymap PARAMS((void)); /* Undocumented; used internally only. */ extern void rl_set_keymap_from_edit_mode PARAMS((void)); -extern char *rl_get_keymap_name_from_edit_mode PARAMS((void)); +extern const char *rl_get_keymap_name_from_edit_mode PARAMS((void)); /* Functions for manipulating the funmap, which maps command names to functions. */ extern int rl_add_funmap_entry PARAMS((const char *, rl_command_func_t *)); @@ -390,7 +390,7 @@ extern void rl_resize_terminal PARAMS((void)); extern void rl_set_screen_size PARAMS((int, int)); extern void rl_get_screen_size PARAMS((int *, int *)); -extern char *rl_get_termcap PARAMS((const char *)); +extern const char *rl_get_termcap PARAMS((const char *)); /* Functions for character input. */ extern int rl_stuff_char PARAMS((int)); diff --git a/readline/rlprivate.h b/readline/rlprivate.h index 78bee107dcd..36645fb4a65 100644 --- a/readline/rlprivate.h +++ b/readline/rlprivate.h @@ -230,7 +230,7 @@ extern int _rl_page_completions; extern int _rl_vis_botlin; extern int _rl_last_c_pos; extern int _rl_suppress_redisplay; -extern char *rl_display_prompt; +extern const char *rl_display_prompt; /* isearch.c */ extern char *_rl_isearch_terminators; @@ -261,16 +261,16 @@ extern procenv_t readline_top_level; /* 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 const char *_rl_term_clreol; +extern const char *_rl_term_clrpag; +extern const char *_rl_term_im; +extern const char *_rl_term_ic; +extern const char *_rl_term_ei; +extern const char *_rl_term_DC; +extern const char *_rl_term_up; +extern const char *_rl_term_dc; +extern const char *_rl_term_cr; +extern const char *_rl_term_IC; extern int _rl_screenheight; extern int _rl_screenwidth; extern int _rl_screenchars; diff --git a/readline/tcap.h b/readline/tcap.h index 58ab894d93e..4606520bf87 100644 --- a/readline/tcap.h +++ b/readline/tcap.h @@ -42,7 +42,7 @@ #endif extern char PC; -extern char *UP, *BC; +extern const char *UP, *BC; extern short ospeed; diff --git a/readline/terminal.c b/readline/terminal.c index c6f53e3a500..9ca4d6e43c5 100644 --- a/readline/terminal.c +++ b/readline/terminal.c @@ -84,40 +84,41 @@ static int tcap_initialized; # if defined (__EMX__) || defined (NEED_EXTERN_PC) extern # endif /* __EMX__ || NEED_EXTERN_PC */ -char PC, *BC, *UP; +const char PC; +const char *BC, *UP; #endif /* __linux__ */ /* Some strings to control terminal actions. These are output by tputs (). */ -char *_rl_term_clreol; -char *_rl_term_clrpag; -char *_rl_term_cr; -char *_rl_term_backspace; -char *_rl_term_goto; -char *_rl_term_pc; +const char *_rl_term_clreol; +const char *_rl_term_clrpag; +const char *_rl_term_cr; +const char *_rl_term_backspace; +const char *_rl_term_goto; +const char *_rl_term_pc; /* Non-zero if we determine that the terminal can do character insertion. */ int _rl_terminal_can_insert = 0; /* How to insert characters. */ -char *_rl_term_im; -char *_rl_term_ei; -char *_rl_term_ic; -char *_rl_term_ip; -char *_rl_term_IC; +const char *_rl_term_im; +const char *_rl_term_ei; +const char *_rl_term_ic; +const char *_rl_term_ip; +const char *_rl_term_IC; /* How to delete characters. */ -char *_rl_term_dc; -char *_rl_term_DC; +const char *_rl_term_dc; +const char *_rl_term_DC; #if defined (HACK_TERMCAP_MOTION) char *_rl_term_forward_char; #endif /* HACK_TERMCAP_MOTION */ /* How to go up a line. */ -char *_rl_term_up; +const char *_rl_term_up; /* A visible bell; char if the terminal can be made to flash the screen. */ -static char *_rl_visible_bell; +static const char *_rl_visible_bell; /* Non-zero means the terminal can auto-wrap lines. */ int _rl_term_autowrap; @@ -127,30 +128,30 @@ static int term_has_meta; /* The sequences to write to turn on and off the meta key, if this terminal has one. */ -static char *_rl_term_mm; -static char *_rl_term_mo; +static const char *_rl_term_mm; +static const char *_rl_term_mo; /* The key sequences output by the arrow keys, if this terminal has any. */ -static char *_rl_term_ku; -static char *_rl_term_kd; -static char *_rl_term_kr; -static char *_rl_term_kl; +static const char *_rl_term_ku; +static const char *_rl_term_kd; +static const char *_rl_term_kr; +static const char *_rl_term_kl; /* How to initialize and reset the arrow keys, if this terminal has any. */ -static char *_rl_term_ks; -static char *_rl_term_ke; +static const char *_rl_term_ks; +static const char *_rl_term_ke; /* The key sequences sent by the Home and End keys, if any. */ -static char *_rl_term_kh; -static char *_rl_term_kH; -static char *_rl_term_at7; /* @7 */ +static const char *_rl_term_kh; +static const char *_rl_term_kH; +static const char *_rl_term_at7; /* @7 */ /* Insert key */ -static char *_rl_term_kI; +static const char *_rl_term_kI; /* Cursor control */ -static char *_rl_term_vs; /* very visible */ -static char *_rl_term_ve; /* normal */ +static const char *_rl_term_vs; /* very visible */ +static const char *_rl_term_ve; /* normal */ static void bind_termcap_arrow_keys PARAMS((Keymap)); @@ -296,7 +297,7 @@ rl_resize_terminal () struct _tc_string { const char *tc_var; - char **tc_value; + const char **tc_value; }; /* This should be kept sorted, just in case we decide to change the @@ -416,7 +417,7 @@ _rl_init_terminal_io (terminal_name) /* Everything below here is used by the redisplay code (tputs). */ _rl_screenchars = _rl_screenwidth * _rl_screenheight; - _rl_term_cr = (char*)"\r"; + _rl_term_cr = "\r"; _rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL; _rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL; _rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL; @@ -433,8 +434,8 @@ _rl_init_terminal_io (terminal_name) tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we change that later... */ PC = '\0'; - BC = _rl_term_backspace = (char*)"\b"; - UP = _rl_term_up; + BC = (char*)(_rl_term_backspace = "\b"); + UP = (char*)_rl_term_up; return 0; } @@ -444,11 +445,11 @@ _rl_init_terminal_io (terminal_name) /* Set up the variables that the termcap library expects the application to provide. */ PC = _rl_term_pc ? *_rl_term_pc : 0; - BC = _rl_term_backspace; - UP = _rl_term_up; + BC = (char*)_rl_term_backspace; + UP = (char*)_rl_term_up; if (!_rl_term_cr) - _rl_term_cr = (char*)"\r"; + _rl_term_cr = "\r"; _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn"); @@ -500,7 +501,7 @@ bind_termcap_arrow_keys (map) _rl_keymap = xkeymap; } -char * +const char * rl_get_termcap (cap) const char *cap; { diff --git a/readline/text.c b/readline/text.c index f84fd91344f..81a468fdbda 100644 --- a/readline/text.c +++ b/readline/text.c @@ -1132,11 +1132,11 @@ int rl_insert_comment (count, key) int count __attribute__((unused)), key; { - char *rl_comment_text; + const char *rl_comment_text; int rl_comment_len; rl_beg_of_line (1, key); - rl_comment_text = (char*)(_rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT); + rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT; if (rl_explicit_arg == 0) rl_insert_text (rl_comment_text); diff --git a/readline/tilde.c b/readline/tilde.c index 11209903cf8..fab4aab65ad 100644 --- a/readline/tilde.c +++ b/readline/tilde.c @@ -190,7 +190,7 @@ tilde_expand (string) int result_size, result_index; result_index = result_size = 0; - if ((result = (char*)strchr(string, '~'))) + if ((result = strchr(string, '~'))) result = (char *)xmalloc (result_size = (strlen (string) + 16)); else result = (char *)xmalloc (result_size = (strlen (string) + 1)); From 3853ff4de26c9e7d3dee8b3b14292311a7ff85ab Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Nov 2002 18:26:45 +0100 Subject: [PATCH 27/89] scripts/safe_mysqld.sh - fix setting of niceness level support-files/mysql.server.sh - applied some fixes from 4.0 mysql.server script - fix my.cnf parsing scripts/safe_mysqld.sh: - fix setting of niceness level, if one adds "renice -20 $$" to safe_mysqld as hinted in the manual (which could result in NOHUP_NICENESS having a value of "-15" and hence there would be one dash too much) support-files/mysql.server.sh: - applied some fixes from 4.0 mysql.server script - fix to actually parse the documented section ([mysql.server] not [mysql_server]) in my.cnf on startup --- scripts/safe_mysqld.sh | 2 +- support-files/mysql.server.sh | 40 +++++++++++++++++++++++------------ 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/scripts/safe_mysqld.sh b/scripts/safe_mysqld.sh index 2b625dbdfa3..2272443c972 100644 --- a/scripts/safe_mysqld.sh +++ b/scripts/safe_mysqld.sh @@ -159,7 +159,7 @@ then NOHUP_NICENESS=`nohup nice 2>&1` if test $? -eq 0 && test x"$NOHUP_NICENESS" != x0 && nice --1 echo foo > /dev/null 2>&1 then - NOHUP_NICENESS="nice --$NOHUP_NICENESS nohup" + NOHUP_NICENESS="nice -n $NOHUP_NICENESS nohup" else NOHUP_NICENESS="nohup" fi diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index ecc49106c91..91821fd09e5 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -2,7 +2,7 @@ # Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB # This file is public domain and comes with NO WARRANTY of any kind -# Mysql daemon start/stop script. +# MySQL daemon start/stop script. # Usually this is put in /etc/init.d (at least on machines SYSV R4 based # systems) and linked to /etc/rc3.d/S99mysql and /etc/rc0.d/K01mysql. @@ -20,21 +20,31 @@ # Required-Stop: $local_fs $network $remote_fs # Default-Start: 3 5 # Default-Stop: 3 5 -# Short-Description: start and stop MySLQ +# Short-Description: start and stop MySQL # Description: MySQL is a very fast and reliable SQL database engine. ### END INIT INFO +# If you install MySQL on some other places than @prefix@, then you +# have to do one of the following things for this script to work: +# +# - Run this script from within the MySQL installation directory +# - Create a /etc/my.cnf file with the following information: +# [mysqld] +# basedir= +# - Add the above to any other configuration file (for example ~/.my.ini) +# and copy my_print_defaults to /usr/bin +# - Add the path to the mysql-installation-directory to the basedir variable +# below. +# +# If you want to affect other MySQL variables, you should make your changes +# in the /etc/my.cnf, ~/.my.cnf or other MySQL configuration files. + +basedir= # The following variables are only set for letting mysql.server find things. -# If you want to affect other MySQL variables, you should make your changes -# in the /etc/my.cnf or other configuration files. - -PATH=/sbin:/usr/sbin:/bin:/usr/bin -export PATH # Set some defaults datadir=@localstatedir@ -basedir= pid_file= if test -z "$basedir" then @@ -43,6 +53,10 @@ then else bindir="$basedir/bin" fi + +PATH=/sbin:/usr/sbin:/bin:/usr/bin:$basedir/bin +export PATH + if test -z "$pid_file" then pid_file=$datadir/`@HOSTNAME@`.pid @@ -65,7 +79,7 @@ parse_arguments() { done } -# Get arguments from the my.cnf file, groups [mysqld] and [mysql_server] +# Get arguments from the my.cnf file, groups [mysqld] and [mysql.server] if test -x ./bin/my_print_defaults then print_defaults="./bin/my_print_defaults" @@ -103,7 +117,7 @@ else test -z "$print_defaults" && print_defaults="my_print_defaults" fi -parse_arguments `$print_defaults $defaults mysqld mysql_server` +parse_arguments `$print_defaults $defaults mysqld mysql.server` # Safeguard (relative paths, core dumps..) cd $basedir @@ -123,14 +137,14 @@ case "$mode" in touch /var/lock/subsys/mysql fi else - echo "Can't execute $bindir/safe_mysqld" + echo "Can't execute $bindir/safe_mysqld from dir $basedir" fi ;; 'stop') # Stop daemon. We use a signal here to avoid having to know the # root password. - if test -f "$pid_file" + if test -s "$pid_file" then mysqld_pid=`cat $pid_file` echo "Killing mysqld with pid $mysqld_pid" @@ -140,7 +154,7 @@ case "$mode" in sleep 1 while [ -s $pid_file -a "$flags" != aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ] do - [ -z "$flags" ] && echo "Wait for mysqld to exit\c" || echo ".\c" + [ -z "$flags" ] && echo -n "Wait for mysqld to exit" || echo -n "." flags=a$flags sleep 1 done From fe9bbec4c0c48a680dbfeecd4d334679bc7bd5d4 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 23 Nov 2002 15:49:12 +0200 Subject: [PATCH 28/89] reverting a test that belongs to 3.23 --- mysql-test/r/delete.result | 6 ------ mysql-test/t/delete.test | 5 ----- 2 files changed, 11 deletions(-) diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result index e3e95c79fb7..c2230722aa6 100644 --- a/mysql-test/r/delete.result +++ b/mysql-test/r/delete.result @@ -24,9 +24,3 @@ create table t1 (a bigint not null, primary key (a,a,a,a,a,a,a,a,a,a)); insert into t1 values (2),(4),(6),(8),(10),(12),(14),(16),(18),(20),(22),(24),(26),(23),(27); delete from t1 where a=27; drop table t1; -create table t1 (id int, index(id)); -insert into t1 values(NULL); -delete from t1 where id <=> NULL; -select * from t1; -id -drop table if exists t1; diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test index fc57fdabcd5..953e22cdd55 100644 --- a/mysql-test/t/delete.test +++ b/mysql-test/t/delete.test @@ -35,8 +35,3 @@ create table t1 (a bigint not null, primary key (a,a,a,a,a,a,a,a,a,a)); insert into t1 values (2),(4),(6),(8),(10),(12),(14),(16),(18),(20),(22),(24),(26),(23),(27); delete from t1 where a=27; drop table t1; -create table t1 (id int, index(id)); -insert into t1 values(NULL); -delete from t1 where id <=> NULL; -select * from t1; -drop table if exists t1; From b7bcb96508604ca639103279d0de749bc6f4afa9 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 23 Nov 2002 18:54:15 +0200 Subject: [PATCH 29/89] lock option in table list sql/sql_lex.cc: note about methods location --- sql/sql_lex.cc | 5 ++++- sql/sql_parse.cc | 24 +----------------------- sql/sql_yacc.yy | 13 +++++++++---- 3 files changed, 14 insertions(+), 28 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 9ed66aede6f..286cec87424 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1282,4 +1282,7 @@ List* st_select_lex::get_ignore_index() return ignore_index_ptr; } -// There are st_select_lex::add_table_to_list in sql_parse.cc +/* + There are st_select_lex::add_table_to_list & + st_select_lex::set_lock_for_tables in sql_parse.cc +*/ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 263ac50120d..9199b496dac 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1426,20 +1426,7 @@ mysql_execute_command(THD *thd) { if (!result) { - if ((result=new select_send())) - { - /* - Normal select: - Change lock if we are using SELECT HIGH PRIORITY, - FOR UPDATE or IN SHARE MODE - - TODO: Delete the following loop when locks is set by sql_yacc - */ - TABLE_LIST *table; - for (table = tables ; table ; table=table->next) - table->lock_type= lex->lock_option; - } - else + if (!(result=new select_send())) { res= -1; #ifdef DELETE_ITEMS @@ -1663,9 +1650,6 @@ mysql_execute_command(THD *thd) TABLE_LIST *table; if (check_table_access(thd, SELECT_ACL, tables->next)) goto error; // Error message is given - /* TODO: Delete the following loop when locks is set by sql_yacc */ - for (table = tables->next ; table ; table=table->next) - table->lock_type= lex->lock_option; } unit->offset_limit_cnt= select_lex->offset_limit; unit->select_limit_cnt= select_lex->select_limit+ @@ -2023,12 +2007,6 @@ mysql_execute_command(THD *thd) net_printf(thd,ER_INSERT_TABLE_USED,tables->real_name); DBUG_VOID_RETURN; } - { - /* TODO: Delete the following loop when locks is set by sql_yacc */ - TABLE_LIST *table; - for (table = tables->next ; table ; table=table->next) - table->lock_type= lex->lock_option; - } /* Skip first table, which is the table we are inserting in */ lex->select_lex.table_list.first= diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index eaae24d0310..f2c8869b1af 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -798,7 +798,10 @@ create: ($2 & HA_LEX_CREATE_TMP_TABLE ? &tmp_table_alias : - (LEX_STRING*) 0),1)) + (LEX_STRING*) 0),1, + ((using_update_log)? + TL_READ_NO_INSERT: + TL_READ))) YYABORT; lex->create_list.empty(); lex->key_list.empty(); @@ -2374,8 +2377,9 @@ join_table: } table_ident opt_table_alias opt_key_definition { - SELECT_LEX_NODE *sel=Select; - if (!($$= sel->add_table_to_list($2, $3, 0, TL_UNLOCK, + LEX *lex= Lex; + SELECT_LEX_NODE *sel= lex->current_select; + if (!($$= sel->add_table_to_list($2, $3, 0, lex->lock_option, sel->get_use_index(), sel->get_ignore_index()))) YYABORT; @@ -2388,7 +2392,8 @@ join_table: SELECT_LEX_UNIT *unit= lex->current_select->master_unit(); lex->current_select= unit->outer_select(); if (!($$= lex->current_select-> - add_table_to_list(new Table_ident(unit), $5, 0, TL_UNLOCK))) + add_table_to_list(new Table_ident(unit), $5, 0, + lex->lock_option))) YYABORT; }; From b99dec07b08cc6c54d91b7ee6b0607abc62b9a8c Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 23 Nov 2002 20:40:16 +0200 Subject: [PATCH 30/89] after merging fix (update SCRUM?) mysql-test/t/subselect.test: after merging fix sql/sql_lex.cc: after merging fix sql/sql_update.cc: after merging fix sql/sql_yacc.yy: after merging fix --- mysql-test/t/subselect.test | 2 +- sql/sql_lex.cc | 2 +- sql/sql_update.cc | 1 - sql/sql_yacc.yy | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 75ae1a74125..c86a6e58b1a 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -114,6 +114,7 @@ EXPLAIN SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03'; EXPLAIN SELECT (SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03'); SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03'; SELECT (SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03'); +SELECT 1 FROM searchconthardwarefr3 WHERE 1=(SELECT 1 UNION SELECT 1) UNION ALL SELECT 1; -- error 1240 SELECT 1 FROM searchconthardwarefr3 WHERE 1=(SELECT 1 UNION ALL SELECT 1) UNION SELECT 1; EXPLAIN SELECT 1 FROM searchconthardwarefr3 WHERE 1=(SELECT 1 UNION SELECT 1); @@ -181,7 +182,6 @@ EXPLAIN SELECT numreponse FROM threadhardwarefr7 WHERE numeropost='1' AND numrep EXPLAIN SELECT MAX(numreponse) FROM threadhardwarefr7 WHERE numeropost='1'; EXPLAIN SELECT numreponse FROM threadhardwarefr7 WHERE numeropost='1' AND numreponse=(SELECT MAX(numreponse) FROM threadhardwarefr7 WHERE numeropost='1'); drop table if exists threadhardwarefrtest7; -drop table searchconthardwarefr3; #update with subselects create table t1 (a int NOT NULL, b int, primary key (a)); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 5adc1bec539..cf7d866915e 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -149,7 +149,7 @@ LEX *lex_start(THD *thd, uchar *buf,uint length) lex->select_lex.expr_list.empty(); lex->select_lex.ftfunc_list_alloc.empty(); lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc; - lex->select= &lex->select_lex; + lex->current_select= &lex->select_lex; lex->convert_set= (lex->thd= thd)->variables.convert_set; lex->yacc_yyss=lex->yacc_yyvs=0; lex->ignore_space=test(thd->sql_mode & MODE_IGNORE_SPACE); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index ece2ed3df41..d4dc394ec9b 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -68,7 +68,6 @@ int mysql_update(THD *thd, LINT_INIT(used_index); LINT_INIT(timestamp_query_id); - table_list->lock_type= lock_type; if ((open_and_lock_tables(thd, table_list))) DBUG_RETURN(-1); fix_tables_pointers(&thd->lex.select_lex); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e5ec86e6658..df343714e55 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1631,7 +1631,7 @@ select_init: select_part2: { LEX *lex=Lex; - if (lex->select == &lex->select_lex) + if (lex->current_select == &lex->select_lex) lex->lock_option= TL_READ; /* Only for global SELECT */ mysql_init_select(lex); } From 982e3423f34432cd97692b7a36833e64dcb297eb Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 23 Nov 2002 23:21:49 +0200 Subject: [PATCH 31/89] revert open_ltable changing --- sql/mysql_priv.h | 3 +-- sql/sql_base.cc | 17 +++++------------ 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index a92893ca142..3ba88d493bd 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -448,8 +448,7 @@ void kill_delayed_threads(void); int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, ORDER *order, ha_rows rows, ulong options); int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok=0); -TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update, - bool multiopen= 0); +TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update); TABLE *open_table(THD *thd,const char *db,const char *table,const char *alias, bool *refresh); TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 4c6192bc694..5655225cea3 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1615,24 +1615,17 @@ static bool check_lock_and_start_stmt(THD *thd, TABLE *table, table_list->table table */ -TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type, - bool multiopen) +TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) { TABLE *table; bool refresh; DBUG_ENTER("open_ltable"); thd->proc_info="Opening table"; - if (table_list->next && multiopen) - { - while (open_tables(thd,table_list) && refresh) ; - table= table_list->table; - } - else - while (!(table= open_table(thd,table_list->db, - table_list->real_name,table_list->alias, - &refresh)) && refresh) ; - + while (!(table=open_table(thd,table_list->db, + table_list->real_name,table_list->alias, + &refresh)) && refresh) ; + if (table) { #if defined( __WIN__) || defined(OS2) From 72da2e4c9463aeb80083fd53cc0e6f5091b5f4f7 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 24 Nov 2002 15:47:19 +0200 Subject: [PATCH 32/89] Added new ANSI functions LOCALTIME, LOCALTIMESTAMP and CURRENT_USER Added CEIL as an alias for CEILING Cleaned up CHECK constraint handling. (We don't anymore require braces after CHECK) Added casting to CHAR. mysql-test/r/bigint.result: Moved casting test to cast.test mysql-test/r/func_time.result: Test of new functions mysql-test/t/bigint.test: Moved casting test to cast.test mysql-test/t/func_time.test: Test of new functions sql/item_create.cc: Added casting to CHAR sql/item_func.h: Added casting to CHAR sql/item_timefunc.h: Added casting to CHAR sql/lex.h: Added new ANSI functions LOCALTIME, LOCALTIMESTAMP and CURRENT_USER Added CEIL as an alias for CEILING sql/sql_yacc.yy: Cleaned up CHECK constraint handling. --- mysql-test/r/bigint.result | 21 ------------------ mysql-test/r/cast.result | 39 +++++++++++++++++++++++++++++++++ mysql-test/r/constraints.result | 16 ++++++++++++++ mysql-test/r/func_time.result | 6 +++++ mysql-test/t/bigint.test | 8 ------- mysql-test/t/cast.test | 22 +++++++++++++++++++ mysql-test/t/constraints.test | 21 ++++++++++++++++++ mysql-test/t/func_time.test | 2 ++ sql/item_create.cc | 1 + sql/item_func.h | 2 +- sql/item_timefunc.h | 13 +++++++++++ sql/lex.h | 4 ++++ sql/sql_yacc.yy | 19 +++++++++++----- 13 files changed, 138 insertions(+), 36 deletions(-) create mode 100644 mysql-test/r/cast.result create mode 100644 mysql-test/r/constraints.result create mode 100644 mysql-test/t/cast.test create mode 100644 mysql-test/t/constraints.test diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result index f666c5311b8..6afa74d20e2 100644 --- a/mysql-test/r/bigint.result +++ b/mysql-test/r/bigint.result @@ -52,24 +52,3 @@ select min(big),max(big),max(big)-1 from t1 group by a; min(big) max(big) max(big)-1 -1 9223372036854775807 9223372036854775806 drop table t1; -select CAST(1-2 AS UNSIGNED); -CAST(1-2 AS UNSIGNED) -18446744073709551615 -select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER); -CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER) --1 -select CONVERT('-1',UNSIGNED); -CONVERT('-1',UNSIGNED) -18446744073709551615 -select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1; -cast(-5 as unsigned) | 1 cast(-5 as unsigned) & -1 -18446744073709551611 18446744073709551611 -select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1; -cast(-5 as unsigned) -1 cast(-5 as unsigned) + 1 -18446744073709551610 18446744073709551612 -select ~5, cast(~5 as signed); -~5 cast(~5 as signed) -18446744073709551610 -6 -select cast(5 as unsigned) -6.0; -cast(5 as unsigned) -6.0 --1.0 diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result new file mode 100644 index 00000000000..572b32c171c --- /dev/null +++ b/mysql-test/r/cast.result @@ -0,0 +1,39 @@ +select CAST(1-2 AS UNSIGNED); +CAST(1-2 AS UNSIGNED) +18446744073709551615 +select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER); +CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER) +-1 +select CONVERT('-1',UNSIGNED); +CONVERT('-1',UNSIGNED) +18446744073709551615 +select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1; +cast(-5 as unsigned) | 1 cast(-5 as unsigned) & -1 +18446744073709551611 18446744073709551611 +select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1; +cast(-5 as unsigned) -1 cast(-5 as unsigned) + 1 +18446744073709551610 18446744073709551612 +select ~5, cast(~5 as signed); +~5 cast(~5 as signed) +18446744073709551610 -6 +select cast(5 as unsigned) -6.0; +cast(5 as unsigned) -6.0 +-1.0 +select cast("A" as binary) = "a", cast(BINARY "a" as CHAR) = "A"; +cast("A" as binary) = "a" cast(BINARY "a" as CHAR) = "A" +0 1 +select cast("2001-1-1" as DATE), cast("2001-1-1" as DATETIME); +cast("2001-1-1" as DATE) cast("2001-1-1" as DATETIME) +2001-1-1 2001-1-1 +select cast("1:2:3" as TIME); +cast("1:2:3" as TIME) +1:2:3 +select cast("2001-1-1" as date) = "2001-01-01"; +cast("2001-1-1" as date) = "2001-01-01" +0 +select cast("2001-1-1" as datetime) = "2001-01-01 00:00:00"; +cast("2001-1-1" as datetime) = "2001-01-01 00:00:00" +0 +select cast("1:2:3" as TIME) = "1:02:03"; +cast("1:2:3" as TIME) = "1:02:03" +0 diff --git a/mysql-test/r/constraints.result b/mysql-test/r/constraints.result new file mode 100644 index 00000000000..3b41e291e0f --- /dev/null +++ b/mysql-test/r/constraints.result @@ -0,0 +1,16 @@ +drop table if exists t1; +create table t1 (a int check (a>0)); +insert into t1 values (1); +insert into t1 values (0); +drop table t1; +create table t1 (a int ,b int, check a>b); +insert into t1 values (1,0); +insert into t1 values (0,1); +drop table t1; +create table t1 (a int ,b int, constraint abc check (a>b)); +insert into t1 values (1,0); +insert into t1 values (0,1); +drop table t1; +create table t1 (a int null); +insert into t1 values (1),(NULL); +drop table t1; diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 4a1012f73bf..2941352c776 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -24,6 +24,12 @@ now()-curdate()*1000000-curtime() select strcmp(current_timestamp(),concat(current_date()," ",current_time())); strcmp(current_timestamp(),concat(current_date()," ",current_time())) 0 +select strcmp(localtime(),concat(current_date()," ",current_time())); +strcmp(localtime(),concat(current_date()," ",current_time())) +0 +select strcmp(localtimestamp(),concat(current_date()," ",current_time())); +strcmp(localtimestamp(),concat(current_date()," ",current_time())) +0 select date_format("1997-01-02 03:04:05", "%M %W %D %Y %y %m %d %h %i %s %w"); date_format("1997-01-02 03:04:05", "%M %W %D %Y %y %m %d %h %i %s %w") January Thursday 2nd 1997 97 01 02 03 04 05 4 diff --git a/mysql-test/t/bigint.test b/mysql-test/t/bigint.test index 15b35ac7c87..15c61c2c0dc 100644 --- a/mysql-test/t/bigint.test +++ b/mysql-test/t/bigint.test @@ -35,11 +35,3 @@ alter table t1 modify big bigint not null; select min(big),max(big),max(big)-1 from t1; select min(big),max(big),max(big)-1 from t1 group by a; drop table t1; - -select CAST(1-2 AS UNSIGNED); -select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER); -select CONVERT('-1',UNSIGNED); -select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1; -select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1; -select ~5, cast(~5 as signed); -select cast(5 as unsigned) -6.0; diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test new file mode 100644 index 00000000000..7a120ef5005 --- /dev/null +++ b/mysql-test/t/cast.test @@ -0,0 +1,22 @@ +# +# Test of cast function +# + +select CAST(1-2 AS UNSIGNED); +select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER); +select CONVERT('-1',UNSIGNED); +select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1; +select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1; +select ~5, cast(~5 as signed); +select cast(5 as unsigned) -6.0; +select cast("A" as binary) = "a", cast(BINARY "a" as CHAR) = "A"; +select cast("2001-1-1" as DATE), cast("2001-1-1" as DATETIME); +select cast("1:2:3" as TIME); + +# +# The following should be fixed in 4.1 +# + +select cast("2001-1-1" as date) = "2001-01-01"; +select cast("2001-1-1" as datetime) = "2001-01-01 00:00:00"; +select cast("1:2:3" as TIME) = "1:02:03"; diff --git a/mysql-test/t/constraints.test b/mysql-test/t/constraints.test new file mode 100644 index 00000000000..8682cdc42a2 --- /dev/null +++ b/mysql-test/t/constraints.test @@ -0,0 +1,21 @@ +# +# Testing of constraints +# Currently MySQL only ignores the syntax. +# +drop table if exists t1; + +create table t1 (a int check (a>0)); +insert into t1 values (1); +insert into t1 values (0); +drop table t1; +create table t1 (a int ,b int, check a>b); +insert into t1 values (1,0); +insert into t1 values (0,1); +drop table t1; +create table t1 (a int ,b int, constraint abc check (a>b)); +insert into t1 values (1,0); +insert into t1 values (0,1); +drop table t1; +create table t1 (a int null); +insert into t1 values (1),(NULL); +drop table t1; diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 2ff57959965..fdbc0f71dba 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -12,6 +12,8 @@ select sec_to_time(9001),sec_to_time(9001)+0,time_to_sec("15:12:22"), select sec_to_time(time_to_sec('-838:59:59')); select now()-curdate()*1000000-curtime(); select strcmp(current_timestamp(),concat(current_date()," ",current_time())); +select strcmp(localtime(),concat(current_date()," ",current_time())); +select strcmp(localtimestamp(),concat(current_date()," ",current_time())); select date_format("1997-01-02 03:04:05", "%M %W %D %Y %y %m %d %h %i %s %w"); select date_format("1997-01-02", concat("%M %W %D ","%Y %y %m %d %h %i %s %w")); select dayofmonth("1997-01-02"),dayofmonth(19970323); diff --git a/sql/item_create.cc b/sql/item_create.cc index f28e3248c61..c5f53f0d040 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -425,6 +425,7 @@ Item *create_func_cast(Item *a, Item_cast cast_type) LINT_INIT(res); switch (cast_type) { case ITEM_CAST_BINARY: res= new Item_func_binary(a); break; + case ITEM_CAST_CHAR: res= new Item_char_typecast(a); break; case ITEM_CAST_SIGNED_INT: res= new Item_func_signed(a); break; case ITEM_CAST_UNSIGNED_INT: res= new Item_func_unsigned(a); break; case ITEM_CAST_DATE: res= new Item_date_typecast(a); break; diff --git a/sql/item_func.h b/sql/item_func.h index 2e02d7cfd28..b7e0cee540a 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1003,7 +1003,7 @@ public: enum Item_cast { ITEM_CAST_BINARY, ITEM_CAST_SIGNED_INT, ITEM_CAST_UNSIGNED_INT, - ITEM_CAST_DATE, ITEM_CAST_TIME, ITEM_CAST_DATETIME + ITEM_CAST_DATE, ITEM_CAST_TIME, ITEM_CAST_DATETIME, ITEM_CAST_CHAR }; Item *create_func_cast(Item *a, Item_cast cast_type); diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 0fe487b7983..c0255e71d27 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -410,6 +410,7 @@ public: unsigned int size_of() { return sizeof(*this);} }; + class Item_extract :public Item_int_func { const interval_type int_type; @@ -424,10 +425,12 @@ class Item_extract :public Item_int_func unsigned int size_of() { return sizeof(*this);} }; + class Item_typecast :public Item_str_func { public: Item_typecast(Item *a) :Item_str_func(a) {} + const char *func_name() const { return "char"; } String *val_str(String *a) { a=args[0]->val_str(a); null_value=args[0]->null_value; return a; } void fix_length_and_dec() { max_length=args[0]->max_length; } @@ -435,6 +438,14 @@ public: }; +class Item_char_typecast :public Item_typecast +{ +public: + Item_char_typecast(Item *a) :Item_typecast(a) {} + void fix_length_and_dec() { binary=0; max_length=args[0]->max_length; } +}; + + class Item_date_typecast :public Item_typecast { public: @@ -450,6 +461,7 @@ public: } }; + class Item_time_typecast :public Item_typecast { public: @@ -465,6 +477,7 @@ public: } }; + class Item_datetime_typecast :public Item_typecast { public: diff --git a/sql/lex.h b/sql/lex.h index 49b6a3811e5..717e8a355ca 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -210,6 +210,8 @@ static SYMBOL symbols[] = { { "LIMIT", SYM(LIMIT),0,0}, { "LOAD", SYM(LOAD),0,0}, { "LOCAL", SYM(LOCAL_SYM),0,0}, + { "LOCALTIME", SYM(NOW_SYM),0,0}, + { "LOCALTIMESTAMP", SYM(NOW_SYM),0,0}, { "LOCK", SYM(LOCK_SYM),0,0}, { "LOCKS", SYM(LOCKS_SYM),0,0}, { "LOGS", SYM(LOGS_SYM),0,0}, @@ -394,7 +396,9 @@ static SYMBOL sql_functions[] = { { "BIT_OR", SYM(BIT_OR),0,0}, { "BIT_AND", SYM(BIT_AND),0,0}, { "CAST", SYM(CAST_SYM),0,0}, + { "CEIL", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)}, { "CEILING", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)}, + { "CURRENT_USER", SYM(USER),0,0}, { "BIT_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_length)}, { "CHAR_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)}, { "CHARACTER_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)}, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index f6a0c483bb9..c3c6d8ad66b 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -899,7 +899,7 @@ field_list: field_list_item: - field_spec + field_spec check_constraint | field_spec references { Lex->col_list.empty(); /* Alloced by sql_alloc */ @@ -914,10 +914,16 @@ field_list_item: { Lex->col_list.empty(); /* Alloced by sql_alloc */ } - | opt_constraint CHECK_SYM '(' expr ')' + | opt_constraint check_constraint { Lex->col_list.empty(); /* Alloced by sql_alloc */ - }; + } + ; + +check_constraint: + /* empty */ + | CHECK_SYM expr + ; opt_constraint: /* empty */ @@ -1986,13 +1992,15 @@ in_sum_expr: cast_type: BINARY { $$=ITEM_CAST_BINARY; } + | CHAR_SYM { $$=ITEM_CAST_CHAR; } | SIGNED_SYM { $$=ITEM_CAST_SIGNED_INT; } | SIGNED_SYM INT_SYM { $$=ITEM_CAST_SIGNED_INT; } | UNSIGNED { $$=ITEM_CAST_UNSIGNED_INT; } | UNSIGNED INT_SYM { $$=ITEM_CAST_UNSIGNED_INT; } | DATE_SYM { $$=ITEM_CAST_DATE; } | TIME_SYM { $$=ITEM_CAST_TIME; } - | DATETIME { $$=ITEM_CAST_DATETIME; }; + | DATETIME { $$=ITEM_CAST_DATETIME; } + ; expr_list: { Select->expr_list.push_front(new List); } @@ -2437,7 +2445,7 @@ table_name: { if (!add_table_to_list($1,NULL,1)) YYABORT; }; if_exists: - /* empty */ { $$=0; } + /* empty */ { $$= 0; } | IF EXISTS { $$= 1; } ; @@ -3154,7 +3162,6 @@ keyword: | CACHE_SYM {} | CHANGED {} | CHECKSUM_SYM {} - | CHECK_SYM {} | CIPHER_SYM {} | CLIENT_SYM {} | CLOSE_SYM {} From bb948c635507db07365554d0e33bc09522c77557 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 24 Nov 2002 16:20:41 +0200 Subject: [PATCH 33/89] Rewrote nice handling to make more portable --- scripts/safe_mysqld.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/scripts/safe_mysqld.sh b/scripts/safe_mysqld.sh index 2272443c972..96568bd5d19 100644 --- a/scripts/safe_mysqld.sh +++ b/scripts/safe_mysqld.sh @@ -157,9 +157,14 @@ NOHUP_NICENESS="nohup" if test -w / then NOHUP_NICENESS=`nohup nice 2>&1` - if test $? -eq 0 && test x"$NOHUP_NICENESS" != x0 && nice --1 echo foo > /dev/null 2>&1 - then - NOHUP_NICENESS="nice -n $NOHUP_NICENESS nohup" + if test $? -eq 0 && test x"$NOHUP_NICENESS" != x0 && nice --1 echo foo > /dev/null 2>&1 + then + if $NOHUP_NICENESS -gt 0 + then + $NOHUP_NICENESS="nice --$NOHUP_NICENESS nohup" + else + NOHUP_NICENESS="nice -$NOHUP_NICENESS nohup" + fi else NOHUP_NICENESS="nohup" fi From 79cdd8773c365d80e6ed528668dfb03eda7406b3 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 24 Nov 2002 21:39:22 +0200 Subject: [PATCH 34/89] Updated results after merge from 3.23 --- mysql-test/r/innodb-deadlock.result | 20 +++++++++++++++ mysql-test/r/null_key.result | 16 ++++++++++++ mysql-test/t/innodb-deadlock.test | 38 +++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 mysql-test/r/innodb-deadlock.result create mode 100644 mysql-test/t/innodb-deadlock.test diff --git a/mysql-test/r/innodb-deadlock.result b/mysql-test/r/innodb-deadlock.result new file mode 100644 index 00000000000..121bfa8c6cb --- /dev/null +++ b/mysql-test/r/innodb-deadlock.result @@ -0,0 +1,20 @@ +drop table if exists t1; +create table t1 (id integer, x integer) type=INNODB; +insert into t1 values(0, 0); +set autocommit=0; +SELECT * from t1 where id = 0 FOR UPDATE; +id x +0 0 +set autocommit=0; +update t1 set x=2 where id = 0; +update t1 set x=1 where id = 0; +select * from t1; +id x +0 1 +commit; +commit; +select * from t1; +id x +0 2 +commit; +drop table t1; diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result index b737f9254b0..236def64b5e 100644 --- a/mysql-test/r/null_key.result +++ b/mysql-test/r/null_key.result @@ -228,20 +228,36 @@ alter table t1 add key id (id); select * from t1, t2 where t1.id = t2.id; id id drop table t1,t2; +create table t1 ( +id integer, +id2 integer not null, +index (id), +index (id2) +); +insert into t1 values(null,null),(1,1); +select * from t1; id id2 NULL 0 1 1 +select * from t1 where id <=> null; id id2 NULL 0 +select * from t1 where id <=> null or id > 0; id id2 NULL 0 1 1 +select * from t1 where id is null or id > 0; id id2 NULL 0 1 1 +select * from t1 where id2 <=> null or id2 > 0; id id2 1 1 +select * from t1 where id2 is null or id2 > 0; id id2 1 1 +delete from t1 where id <=> NULL; +select * from t1; id id2 1 1 +drop table t1; diff --git a/mysql-test/t/innodb-deadlock.test b/mysql-test/t/innodb-deadlock.test new file mode 100644 index 00000000000..bc2839bfb3a --- /dev/null +++ b/mysql-test/t/innodb-deadlock.test @@ -0,0 +1,38 @@ +-- source include/have_innodb.inc + +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); +drop table if exists t1; + +# +# Testing of FOR UPDATE +# + +connection con1; +create table t1 (id integer, x integer) type=INNODB; +insert into t1 values(0, 0); +set autocommit=0; +SELECT * from t1 where id = 0 FOR UPDATE; + +connection con2; +set autocommit=0; + +# The following query should hang because con1 is locking the page +--send +update t1 set x=2 where id = 0; +--sleep 2; + +connection con1; +update t1 set x=1 where id = 0; +select * from t1; +commit; + +connection con2; +reap; +commit; + +connection con1; +select * from t1; +commit; + +drop table t1; From 8276111fa1539b0a58acce454b06c6dce143655b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Nov 2002 12:54:55 +0400 Subject: [PATCH 35/89] add define of __attribute__ for readline --- readline/rldefs.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/readline/rldefs.h b/readline/rldefs.h index 4a28bd1e49c..5cba9a5ac32 100644 --- a/readline/rldefs.h +++ b/readline/rldefs.h @@ -32,6 +32,10 @@ #include "rlstdc.h" +#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ <8) +#define __attribute__(A) +#endif + #if defined (_POSIX_VERSION) && !defined (TERMIOS_MISSING) # define TERMIOS_TTY_DRIVER #else From 895e3dbbf831cfc6698f1f1f57586224351458b7 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Nov 2002 12:11:16 +0200 Subject: [PATCH 36/89] Faster parsing of identifiers Compatibility syntax: SERIAL, [PRIMARY] KEY and VALUE sql/sql_lex.cc: Faster handling of identifiers sql/sql_lex.h: Faster handling of identifiers sql/sql_yacc.yy: Added SERIAL (alias for bigint auto_increment) Make PRIMARY optional in field specification Make VALUE alias for VALUES --- sql/sql_lex.cc | 54 +++++++++++++++++++++++++++++-------------------- sql/sql_lex.h | 2 +- sql/sql_yacc.yy | 17 ++++++++++++++-- 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 9ed66aede6f..e5d8ddf8067 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -76,7 +76,7 @@ inline int lex_casecmp(const char *s, const char *t, uint len) #include "lex_hash.h" -static uchar state_map[256]; +static uchar state_map[256], ident_map[256]; void lex_init(void) @@ -91,7 +91,7 @@ void lex_init(void) VOID(pthread_key_create(&THR_LEX,NULL)); /* Fill state_map with states to get a faster parser */ - for (i=0; i < 256 ; i++) + for (i=0; i < sizeof(state_map) ; i++) { if (my_isalpha(system_charset_info,i)) state_map[i]=(uchar) STATE_IDENT; @@ -126,6 +126,20 @@ void lex_init(void) { state_map[(uchar) '"'] = STATE_USER_VARIABLE_DELIMITER; } + + /* + Create a second map to make it faster to find identifiers + */ + for (i=0; i < sizeof(ident_map) ; i++) + { + ident_map[i]= (uchar) (state_map[i] == STATE_IDENT || + state_map[i] == STATE_NUMBER_IDENT); + } + + /* Special handling of hex and binary strings */ + state_map[(uchar)'x']= state_map[(uchar)'X']= (uchar) STATE_IDENT_OR_HEX; + state_map[(uchar)'b']= state_map[(uchar)'b']= (uchar) STATE_IDENT_OR_BIN; + DBUG_VOID_RETURN; } @@ -459,7 +473,7 @@ int yylex(void *arg) } case STATE_CHAR: // Unknown or single char token case STATE_SKIP: // This should not happen - yylval->lex_str.str=(char*) (lex->ptr=lex->tok_start);// Set to first char + yylval->lex_str.str=(char*) (lex->ptr=lex->tok_start);// Set to first chr yylval->lex_str.length=1; c=yyGet(); if (c != ')') @@ -468,12 +482,15 @@ int yylex(void *arg) lex->tok_start=lex->ptr; // Let tok_start point at next item return((int) c); - case STATE_IDENT: // Incomplete keyword or ident - if ((c == 'x' || c == 'X') && yyPeek() == '\'') + case STATE_IDENT_OR_HEX: + if (yyPeek() == '\'') { // Found x'hex-number' - state=STATE_HEX_NUMBER; + state= STATE_HEX_NUMBER; break; } + /* Fall through */ + case STATE_IDENT_OR_BIN: // TODO: Add binary string handling + case STATE_IDENT: #if defined(USE_MB) && defined(USE_MB_IDENT) if (use_mb(system_charset_info)) { @@ -488,8 +505,7 @@ int yylex(void *arg) } lex->ptr += l - 1; } - while (state_map[c=yyGet()] == STATE_IDENT || - state_map[c] == STATE_NUMBER_IDENT) + while (ident_map[c=yyGet()]) { if (my_ismbhead(system_charset_info, c)) { @@ -504,15 +520,13 @@ int yylex(void *arg) } else #endif - while (state_map[c=yyGet()] == STATE_IDENT || - state_map[c] == STATE_NUMBER_IDENT) ; + while (ident_map[c=yyGet()]) ; length= (uint) (lex->ptr - lex->tok_start)-1; if (lex->ignore_space) { for (; state_map[c] == STATE_SKIP ; c= yyGet()); } - if (c == '.' && (state_map[yyPeek()] == STATE_IDENT || - state_map[yyPeek()] == STATE_NUMBER_IDENT)) + if (c == '.' && ident_map[yyPeek()]) lex->next_state=STATE_IDENT_SEP; else { // '(' must follow directly if function @@ -550,7 +564,7 @@ int yylex(void *arg) case STATE_NUMBER_IDENT: // number or ident which num-start while (my_isdigit(system_charset_info,(c = yyGet()))) ; - if (state_map[c] != STATE_IDENT) + if (!ident_map[c]) { // Can't be identifier state=STATE_INT_OR_REAL; break; @@ -575,7 +589,7 @@ int yylex(void *arg) lex->tok_start[0] == '0' ) { // Varbinary while (my_isxdigit(system_charset_info,(c = yyGet()))) ; - if ((lex->ptr - lex->tok_start) >= 4 && state_map[c] != STATE_IDENT) + if ((lex->ptr - lex->tok_start) >= 4 && !ident_map[c]) { yylval->lex_str=get_token(lex,yyLength()); yylval->lex_str.str+=2; // Skip 0x @@ -602,8 +616,7 @@ int yylex(void *arg) } lex->ptr += l - 1; } - while (state_map[c=yyGet()] == STATE_IDENT || - state_map[c] == STATE_NUMBER_IDENT) + while (ident_map[c=yyGet()]) { if (my_ismbhead(system_charset_info, c)) { @@ -618,11 +631,9 @@ int yylex(void *arg) } else #endif - while (state_map[c = yyGet()] == STATE_IDENT || - state_map[c] == STATE_NUMBER_IDENT) ; + while (ident_map[c = yyGet()]) ; - if (c == '.' && (state_map[yyPeek()] == STATE_IDENT || - state_map[yyPeek()] == STATE_NUMBER_IDENT)) + if (c == '.' && ident_map[yyPeek()]) lex->next_state=STATE_IDENT_SEP;// Next is '.' // fall through @@ -900,8 +911,7 @@ int yylex(void *arg) [(global | local | session) .]variable_name */ - while (state_map[c=yyGet()] == STATE_IDENT || - state_map[c] == STATE_NUMBER_IDENT) ; + while (ident_map[c=yyGet()]) ; if (c == '.') lex->next_state=STATE_IDENT_SEP; length= (uint) (lex->ptr - lex->tok_start)-1; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index dd41af4b250..c555bc6ff72 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -78,7 +78,7 @@ enum lex_states STATE_REAL_OR_POINT, STATE_BOOL, STATE_EOL, STATE_ESCAPE, STATE_LONG_COMMENT, STATE_END_LONG_COMMENT, STATE_COLON, STATE_SET_VAR, STATE_USER_END, STATE_HOSTNAME, STATE_SKIP, STATE_USER_VARIABLE_DELIMITER, STATE_SYSTEM_VAR, - STATE_IDENT_OR_KEYWORD + STATE_IDENT_OR_KEYWORD, STATE_IDENT_OR_HEX, STATE_IDENT_OR_BIN }; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index eaae24d0310..f79bf37d2f7 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1110,6 +1110,12 @@ type: $$=FIELD_TYPE_SET; } | LONG_SYM opt_binary { $$=FIELD_TYPE_MEDIUM_BLOB; } + | SERIAL_SYM + { + $$=FIELD_TYPE_LONGLONG; + Lex->type|= (AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNSIGNED_FLAG | + UNIQUE_FLAG); + } ; char: @@ -1184,12 +1190,13 @@ attribute: | DEFAULT literal { Lex->default_value=$2; } | AUTO_INC { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; } | SERIAL_SYM DEFAULT VALUE_SYM - { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; } - | PRIMARY_SYM KEY_SYM { Lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG; } + { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG; } + | opt_primary KEY_SYM { Lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG; } | UNIQUE_SYM { Lex->type|= UNIQUE_FLAG; } | UNIQUE_SYM KEY_SYM { Lex->type|= UNIQUE_KEY_FLAG; } | COMMENT_SYM text_literal { Lex->comment= $2; }; + charset_name: BINARY { @@ -1227,6 +1234,11 @@ opt_binary: | BINARY { Lex->charset=my_charset_bin; } | CHAR_SYM SET charset_name { Lex->charset=$3; } ; + +opt_primary: + /* empty */ + | PRIMARY_SYM + references: REFERENCES table_ident { @@ -2882,6 +2894,7 @@ fields: insert_values: VALUES values_list {} + | VALUE_SYM values_list {} | SELECT_SYM { LEX *lex=Lex; From 27f2c605531ee8c9e2e629a6cb1d51fa2f81e0a6 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Nov 2002 13:44:47 +0200 Subject: [PATCH 37/89] removed limit for "FOR UPDATE" and "IN SHARE MODE" (now thay allowed for non-simple selects and applyed to current select) fix for using subselects with update test of locking for non-simple queries (SCRUM?) sql/sql_yacc.yy: removed limit for "FOR UPDATE" and "IN SHARE MODE" (now thay allowed for non-simple selects and applyed to current select) fix for using subselects with update --- mysql-test/r/innodb-non-simple.result | 76 +++++++++++++++++++++++++++ mysql-test/t/innodb-non-simple.test | 76 +++++++++++++++++++++++++++ sql/sql_yacc.yy | 9 ++-- 3 files changed, 155 insertions(+), 6 deletions(-) create mode 100644 mysql-test/r/innodb-non-simple.result create mode 100644 mysql-test/t/innodb-non-simple.test diff --git a/mysql-test/r/innodb-non-simple.result b/mysql-test/r/innodb-non-simple.result new file mode 100644 index 00000000000..8461b9d8d4d --- /dev/null +++ b/mysql-test/r/innodb-non-simple.result @@ -0,0 +1,76 @@ +drop table if exists t1, t2; +create table t1 (id integer, x integer) type=INNODB; +create table t2 (b integer, a integer) type=INNODB; +insert into t1 values(0, 0), (300, 300); +insert into t2 values(0, 10), (1, 20), (2, 30); +set autocommit=0; +select * from t2; +b a +0 10 +1 20 +2 30 +update t2 set a=100 where b=(SELECT x from t1 where id = b FOR UPDATE); +select * from t2; +b a +0 100 +1 20 +2 30 +select * from t1; +id x +0 0 +300 300 +set autocommit=0; +update t1 set x=2 where id = 0; +update t1 set x=1 where id = 0; +select * from t1; +id x +0 1 +300 300 +commit; +commit; +select * from t1; +id x +0 2 +300 300 +commit; +drop table t1, t2; +create table t1 (id integer, x integer) type=INNODB; +create table t2 (b integer, a integer) type=INNODB; +insert into t1 values(0, 0), (300, 300); +insert into t2 values(0, 0), (1, 20), (2, 30); +commit; +select a,b from t2 UNION SELECT id, x from t1 FOR UPDATE; +a b +0 0 +20 1 +30 2 +300 300 +select * from t2; +b a +0 0 +1 20 +2 30 +select * from t1; +id x +0 0 +300 300 +update t2 set a=2 where b = 0; +select * from t2; +b a +0 2 +1 20 +2 30 +update t1 set x=2 where id = 0; +update t1 set x=1 where id = 0; +select * from t1; +id x +0 1 +300 300 +commit; +commit; +select * from t1; +id x +0 2 +300 300 +commit; +drop table t1, t2; diff --git a/mysql-test/t/innodb-non-simple.test b/mysql-test/t/innodb-non-simple.test new file mode 100644 index 00000000000..1d890896d3f --- /dev/null +++ b/mysql-test/t/innodb-non-simple.test @@ -0,0 +1,76 @@ +-- source include/have_innodb.inc + +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); +drop table if exists t1, t2; +# +# Testing of FOR UPDATE +# + +connection con1; +create table t1 (id integer, x integer) type=INNODB; +create table t2 (b integer, a integer) type=INNODB; +insert into t1 values(0, 0), (300, 300); +insert into t2 values(0, 10), (1, 20), (2, 30); +set autocommit=0; +select * from t2; +update t2 set a=100 where b=(SELECT x from t1 where id = b FOR UPDATE); +select * from t2; +select * from t1; + +connection con2; +set autocommit=0; + +# The following query should hang because con1 is locking the page +--send +update t1 set x=2 where id = 0; +--sleep 2; + +connection con1; +update t1 set x=1 where id = 0; +select * from t1; +commit; + +connection con2; +reap; +commit; + +connection con1; +select * from t1; +commit; + +drop table t1, t2; +create table t1 (id integer, x integer) type=INNODB; +create table t2 (b integer, a integer) type=INNODB; +insert into t1 values(0, 0), (300, 300); +insert into t2 values(0, 0), (1, 20), (2, 30); +commit; + +connection con1; +select a,b from t2 UNION SELECT id, x from t1 FOR UPDATE; +select * from t2; +select * from t1; + +connection con2; + +# The following query should hang because con1 is locking the page +update t2 set a=2 where b = 0; +select * from t2; +--send +update t1 set x=2 where id = 0; +--sleep 2; + +connection con1; +update t1 set x=1 where id = 0; +select * from t1; +commit; + +connection con2; +reap; +commit; + +connection con1; +select * from t1; +commit; + +drop table t1, t2; \ No newline at end of file diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index df343714e55..70d50559df9 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1690,17 +1690,14 @@ select_lock_type: | FOR_SYM UPDATE_SYM { LEX *lex=Lex; - if (check_simple_select()) - YYABORT; - lex->lock_option= TL_WRITE; + lex->current_select->set_lock_for_tables(TL_WRITE); lex->thd->safe_to_cache_query=0; } | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM { LEX *lex=Lex; - if (check_simple_select()) - YYABORT; - lex->lock_option= TL_READ_WITH_SHARED_LOCKS; + lex->current_select-> + set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS); lex->thd->safe_to_cache_query=0; } ; From 1b9becc35824401f22b4e7c2b2f9b3dab5348fe9 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Nov 2002 17:33:51 +0200 Subject: [PATCH 38/89] Fixed CAST( xxx as CHAR) sql/item.h: Made some virtual functions non virtual (as they are not used virtually) sql/item_strfunc.cc: Optimizations. sql/item_strfunc.h: Fixed BINARY handling sql/sql_string.h: Indentation cleanups --- sql/item.h | 10 ++++++---- sql/item_strfunc.cc | 11 +++++++---- sql/item_strfunc.h | 3 ++- sql/item_timefunc.h | 19 ++++++++++++++++--- sql/sql_string.h | 5 +++-- 5 files changed, 34 insertions(+), 14 deletions(-) diff --git a/sql/item.h b/sql/item.h index 5eeaa22a2a2..34ca221cadc 100644 --- a/sql/item.h +++ b/sql/item.h @@ -85,12 +85,14 @@ public: virtual bool get_date(TIME *ltime,bool fuzzydate); virtual bool get_time(TIME *ltime); virtual bool is_null() { return 0; }; - virtual CHARSET_INFO *thd_charset() const; - virtual CHARSET_INFO *charset() const { return str_value.charset(); }; - virtual bool binary() const { return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; } - virtual void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); } virtual bool check_loop(uint id); virtual void top_level_item() {} + + virtual bool binary() const + { return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; } + CHARSET_INFO *thd_charset() const; + CHARSET_INFO *charset() const { return str_value.charset(); }; + void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); } }; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 1a561c9eb34..34c89a49e8a 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1363,17 +1363,19 @@ String *Item_func_decode::val_str(String *str) String *Item_func_database::val_str(String *str) { - if (!current_thd->db) + THD *thd= current_thd; + if (!thd->db) str->length(0); else - str->copy((const char*) current_thd->db,(uint) strlen(current_thd->db), system_charset_info, thd_charset()); + str->copy((const char*) thd->db,(uint) strlen(thd->db), + system_charset_info, thd->thd_charset); return str; } String *Item_func_user::val_str(String *str) { THD *thd=current_thd; - CHARSET_INFO *cs=thd_charset(); + CHARSET_INFO *cs=thd->thd_charset; const char *host=thd->host ? thd->host : thd->ip ? thd->ip : ""; uint32 res_length=(strlen(thd->user)+strlen(host)+10) * cs->mbmaxlen; @@ -2128,7 +2130,8 @@ String *Item_func_charset::val_str(String *str) if ((null_value=(args[0]->null_value || !res->charset()))) return 0; - str->copy(res->charset()->name,strlen(res->charset()->name),my_charset_latin1,thd_charset()); + str->copy(res->charset()->name,strlen(res->charset()->name), + my_charset_latin1, thd_charset()); return str; } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 2b308630b48..9fd9143586e 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -494,8 +494,9 @@ public: { String *tmp=args[0]->val_str(a); null_value=args[0]->null_value; + tmp->set_charset(my_charset_bin); return tmp; - } + } void fix_length_and_dec() { set_charset(my_charset_bin); diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 7765769c1d3..f9b987324f0 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -534,8 +534,17 @@ public: Item_typecast(Item *a) :Item_str_func(a) {} const char *func_name() const { return "char"; } String *val_str(String *a) - { a=args[0]->val_str(a); null_value=args[0]->null_value; return a; } - void fix_length_and_dec() { max_length=args[0]->max_length; } + { + String *tmp=args[0]->val_str(a); + null_value=args[0]->null_value; + tmp->set_charset(charset()); + return tmp; + } + void fix_length_and_dec() + { + set_charset(thd_charset()); + max_length=args[0]->max_length; + } void print(String *str); }; @@ -544,7 +553,11 @@ class Item_char_typecast :public Item_typecast { public: Item_char_typecast(Item *a) :Item_typecast(a) {} - void fix_length_and_dec() { binary=0; max_length=args[0]->max_length; } + void fix_length_and_dec() + { + set_charset(thd_charset()); + max_length=args[0]->max_length; + } }; diff --git a/sql/sql_string.h b/sql/sql_string.h index 42f9e446981..dde67b11d50 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -72,7 +72,7 @@ public: { sql_element_free(ptr_arg); } ~String() { free(); } - inline void set_charset(CHARSET_INFO *charset) { str_charset=charset; } + inline void set_charset(CHARSET_INFO *charset) { str_charset= charset; } inline CHARSET_INFO *charset() const { return str_charset; } inline uint32 length() const { return str_length;} inline uint32 alloced_length() const { return Alloced_length;} @@ -177,7 +177,8 @@ public: bool copy(); // Alloc string if not alloced bool copy(const String &s); // Allocate new string bool copy(const char *s,uint32 arg_length, CHARSET_INFO *cs); // Allocate new string - bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom, CHARSET_INFO *csto); + bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom, + CHARSET_INFO *csto); bool append(const String &s); bool append(const char *s,uint32 arg_length=0); bool append(IO_CACHE* file, uint32 arg_length); From 52f18046c496e021a36692cb9ed3544def87584e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Nov 2002 18:34:24 +0200 Subject: [PATCH 39/89] merging tests BitKeeper/deleted/.del-innodb-non-simple.test~380a6ef42b6e15d1: Delete: mysql-test/t/innodb-non-simple.test BitKeeper/deleted/.del-innodb-non-simple.result~2f77d5b0aaf5aa90: Delete: mysql-test/r/innodb-non-simple.result --- mysql-test/r/innodb-deadlock.result | 77 +++++++++++++++++++++++++++ mysql-test/r/innodb-non-simple.result | 76 -------------------------- mysql-test/t/innodb-deadlock.test | 73 +++++++++++++++++++++++++ mysql-test/t/innodb-non-simple.test | 76 -------------------------- 4 files changed, 150 insertions(+), 152 deletions(-) delete mode 100644 mysql-test/r/innodb-non-simple.result delete mode 100644 mysql-test/t/innodb-non-simple.test diff --git a/mysql-test/r/innodb-deadlock.result b/mysql-test/r/innodb-deadlock.result index 121bfa8c6cb..db7155f14fb 100644 --- a/mysql-test/r/innodb-deadlock.result +++ b/mysql-test/r/innodb-deadlock.result @@ -18,3 +18,80 @@ id x 0 2 commit; drop table t1; +drop table if exists t1, t2; +create table t1 (id integer, x integer) type=INNODB; +create table t2 (b integer, a integer) type=INNODB; +insert into t1 values(0, 0), (300, 300); +insert into t2 values(0, 10), (1, 20), (2, 30); +commit; +set autocommit=0; +select * from t2; +b a +0 10 +1 20 +2 30 +update t2 set a=100 where b=(SELECT x from t1 where id = b FOR UPDATE); +select * from t2; +b a +0 100 +1 20 +2 30 +select * from t1; +id x +0 0 +300 300 +set autocommit=0; +update t1 set x=2 where id = 0; +update t1 set x=1 where id = 0; +select * from t1; +id x +0 1 +300 300 +commit; +commit; +select * from t1; +id x +0 2 +300 300 +commit; +drop table t1, t2; +create table t1 (id integer, x integer) type=INNODB; +create table t2 (b integer, a integer) type=INNODB; +insert into t1 values(0, 0), (300, 300); +insert into t2 values(0, 0), (1, 20), (2, 30); +commit; +select a,b from t2 UNION SELECT id, x from t1 FOR UPDATE; +a b +0 0 +20 1 +30 2 +300 300 +select * from t2; +b a +0 0 +1 20 +2 30 +select * from t1; +id x +0 0 +300 300 +update t2 set a=2 where b = 0; +select * from t2; +b a +0 2 +1 20 +2 30 +update t1 set x=2 where id = 0; +update t1 set x=1 where id = 0; +select * from t1; +id x +0 1 +300 300 +commit; +commit; +select * from t1; +id x +0 2 +300 300 +commit; +drop table t1, t2; diff --git a/mysql-test/r/innodb-non-simple.result b/mysql-test/r/innodb-non-simple.result deleted file mode 100644 index 8461b9d8d4d..00000000000 --- a/mysql-test/r/innodb-non-simple.result +++ /dev/null @@ -1,76 +0,0 @@ -drop table if exists t1, t2; -create table t1 (id integer, x integer) type=INNODB; -create table t2 (b integer, a integer) type=INNODB; -insert into t1 values(0, 0), (300, 300); -insert into t2 values(0, 10), (1, 20), (2, 30); -set autocommit=0; -select * from t2; -b a -0 10 -1 20 -2 30 -update t2 set a=100 where b=(SELECT x from t1 where id = b FOR UPDATE); -select * from t2; -b a -0 100 -1 20 -2 30 -select * from t1; -id x -0 0 -300 300 -set autocommit=0; -update t1 set x=2 where id = 0; -update t1 set x=1 where id = 0; -select * from t1; -id x -0 1 -300 300 -commit; -commit; -select * from t1; -id x -0 2 -300 300 -commit; -drop table t1, t2; -create table t1 (id integer, x integer) type=INNODB; -create table t2 (b integer, a integer) type=INNODB; -insert into t1 values(0, 0), (300, 300); -insert into t2 values(0, 0), (1, 20), (2, 30); -commit; -select a,b from t2 UNION SELECT id, x from t1 FOR UPDATE; -a b -0 0 -20 1 -30 2 -300 300 -select * from t2; -b a -0 0 -1 20 -2 30 -select * from t1; -id x -0 0 -300 300 -update t2 set a=2 where b = 0; -select * from t2; -b a -0 2 -1 20 -2 30 -update t1 set x=2 where id = 0; -update t1 set x=1 where id = 0; -select * from t1; -id x -0 1 -300 300 -commit; -commit; -select * from t1; -id x -0 2 -300 300 -commit; -drop table t1, t2; diff --git a/mysql-test/t/innodb-deadlock.test b/mysql-test/t/innodb-deadlock.test index bc2839bfb3a..2648d6cdf9c 100644 --- a/mysql-test/t/innodb-deadlock.test +++ b/mysql-test/t/innodb-deadlock.test @@ -36,3 +36,76 @@ select * from t1; commit; drop table t1; +drop table if exists t1, t2; +# +# Testing of FOR UPDATE +# + +connection con1; +create table t1 (id integer, x integer) type=INNODB; +create table t2 (b integer, a integer) type=INNODB; +insert into t1 values(0, 0), (300, 300); +insert into t2 values(0, 10), (1, 20), (2, 30); +commit; +set autocommit=0; +select * from t2; +update t2 set a=100 where b=(SELECT x from t1 where id = b FOR UPDATE); +select * from t2; +select * from t1; + +connection con2; +set autocommit=0; + +# The following query should hang because con1 is locking the page +--send +update t1 set x=2 where id = 0; +--sleep 2; + +connection con1; +update t1 set x=1 where id = 0; +select * from t1; +commit; + +connection con2; +reap; +commit; + +connection con1; +select * from t1; +commit; + +drop table t1, t2; +create table t1 (id integer, x integer) type=INNODB; +create table t2 (b integer, a integer) type=INNODB; +insert into t1 values(0, 0), (300, 300); +insert into t2 values(0, 0), (1, 20), (2, 30); +commit; + +connection con1; +select a,b from t2 UNION SELECT id, x from t1 FOR UPDATE; +select * from t2; +select * from t1; + +connection con2; + +# The following query should hang because con1 is locking the page +update t2 set a=2 where b = 0; +select * from t2; +--send +update t1 set x=2 where id = 0; +--sleep 2; + +connection con1; +update t1 set x=1 where id = 0; +select * from t1; +commit; + +connection con2; +reap; +commit; + +connection con1; +select * from t1; +commit; + +drop table t1, t2; diff --git a/mysql-test/t/innodb-non-simple.test b/mysql-test/t/innodb-non-simple.test deleted file mode 100644 index 1d890896d3f..00000000000 --- a/mysql-test/t/innodb-non-simple.test +++ /dev/null @@ -1,76 +0,0 @@ --- source include/have_innodb.inc - -connect (con1,localhost,root,,); -connect (con2,localhost,root,,); -drop table if exists t1, t2; -# -# Testing of FOR UPDATE -# - -connection con1; -create table t1 (id integer, x integer) type=INNODB; -create table t2 (b integer, a integer) type=INNODB; -insert into t1 values(0, 0), (300, 300); -insert into t2 values(0, 10), (1, 20), (2, 30); -set autocommit=0; -select * from t2; -update t2 set a=100 where b=(SELECT x from t1 where id = b FOR UPDATE); -select * from t2; -select * from t1; - -connection con2; -set autocommit=0; - -# The following query should hang because con1 is locking the page ---send -update t1 set x=2 where id = 0; ---sleep 2; - -connection con1; -update t1 set x=1 where id = 0; -select * from t1; -commit; - -connection con2; -reap; -commit; - -connection con1; -select * from t1; -commit; - -drop table t1, t2; -create table t1 (id integer, x integer) type=INNODB; -create table t2 (b integer, a integer) type=INNODB; -insert into t1 values(0, 0), (300, 300); -insert into t2 values(0, 0), (1, 20), (2, 30); -commit; - -connection con1; -select a,b from t2 UNION SELECT id, x from t1 FOR UPDATE; -select * from t2; -select * from t1; - -connection con2; - -# The following query should hang because con1 is locking the page -update t2 set a=2 where b = 0; -select * from t2; ---send -update t1 set x=2 where id = 0; ---sleep 2; - -connection con1; -update t1 set x=1 where id = 0; -select * from t1; -commit; - -connection con2; -reap; -commit; - -connection con1; -select * from t1; -commit; - -drop table t1, t2; \ No newline at end of file From 30d1b1436162b00fdbd9af8593cab17b2a40a296 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Nov 2002 21:27:14 +0200 Subject: [PATCH 40/89] subselet in delete (SCRUM) mysql-test/r/subselect.result: subselects in delete test mysql-test/t/subselect.test: subselects in delete test sql/sql_delete.cc: subselet in delete --- mysql-test/r/subselect.result | 19 +++++++++++++++++++ mysql-test/t/subselect.test | 11 +++++++++++ sql/sql_delete.cc | 8 ++++++-- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index a2d29b1c0cf..02f05ce50d6 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -335,3 +335,22 @@ a b 1 21 2 22 drop table t1, t2; +drop table if exists t1, t2; +create table t1 (a int NOT NULL, b int, primary key (a)); +create table t2 (a int NOT NULL, b int, primary key (a)); +insert into t1 values (0, 10),(1, 11),(2, 12); +insert into t2 values (1, 21),(2, 12),(3, 23); +select * from t1; +a b +0 10 +1 11 +2 12 +select * from t1 where b = (select b from t2 where t1.a = t2.a); +a b +2 12 +delete from t1 where b = (select b from t2 where t1.a = t2.a); +select * from t1; +a b +0 10 +1 11 +drop table t1, t2; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 6bba9d4f3cd..3f20abe803a 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -215,3 +215,14 @@ update t1 set b= (select b from t2 where t1.a = t2.a); select * from t1; drop table t1, t2; +#delete with subselects +drop table if exists t1, t2; +create table t1 (a int NOT NULL, b int, primary key (a)); +create table t2 (a int NOT NULL, b int, primary key (a)); +insert into t1 values (0, 10),(1, 11),(2, 12); +insert into t2 values (1, 21),(2, 12),(3, 23); +select * from t1; +select * from t1 where b = (select b from t2 where t1.a = t2.a); +delete from t1 where b = (select b from t2 where t1.a = t2.a); +select * from t1; +drop table t1, t2; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 16d6b6d4631..5b97b2f7750 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -37,14 +37,18 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, bool using_limit=limit != HA_POS_ERROR; bool transactional_table, log_delayed, safe_update, const_cond; ha_rows deleted; + TABLE_LIST *delete_table_list= (TABLE_LIST*) + thd->lex.select_lex.table_list.first; DBUG_ENTER("mysql_delete"); - if (!(table = open_ltable(thd, table_list, table_list->lock_type))) + if ((open_and_lock_tables(thd, table_list))) DBUG_RETURN(-1); + fix_tables_pointers(&thd->lex.select_lex); + table= table_list->table; table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); thd->proc_info="init"; table->map=1; - if (setup_conds(thd,table_list,&conds) || + if (setup_conds(thd, delete_table_list, &conds) || setup_ftfuncs(&thd->lex.select_lex)) DBUG_RETURN(-1); From 4ea2f42e33e1846335c1321fcd4d438d075c8e06 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Nov 2002 22:18:44 +0100 Subject: [PATCH 41/89] myisammrg::index_next_same myisammrg/Makefile.am: myrg_rnext_same.c added --- include/myisammrg.h | 1 + myisam/mi_rkey.c | 17 ++++++++-------- myisam/mi_rrnd.c | 5 ++++- myisam/myisamdef.h | 6 +++++- myisammrg/Makefile.am | 3 ++- myisammrg/myrg_rkey.c | 4 ++-- myisammrg/myrg_rnext_same.c | 40 +++++++++++++++++++++++++++++++++++++ sql/ha_myisammrg.cc | 10 ++++++++++ sql/ha_myisammrg.h | 11 +++++----- 9 files changed, 79 insertions(+), 18 deletions(-) create mode 100644 myisammrg/myrg_rnext_same.c diff --git a/include/myisammrg.h b/include/myisammrg.h index c3b3b39424b..16d3528717b 100644 --- a/include/myisammrg.h +++ b/include/myisammrg.h @@ -84,6 +84,7 @@ extern int myrg_rfirst(MYRG_INFO *file,byte *buf,int inx); extern int myrg_rlast(MYRG_INFO *file,byte *buf,int inx); extern int myrg_rnext(MYRG_INFO *file,byte *buf,int inx); extern int myrg_rprev(MYRG_INFO *file,byte *buf,int inx); +extern int myrg_rnext_same(MYRG_INFO *file,byte *buf); extern int myrg_rkey(MYRG_INFO *file,byte *buf,int inx,const byte *key, uint key_len, enum ha_rkey_function search_flag); extern int myrg_rrnd(MYRG_INFO *file,byte *buf,ulonglong pos); diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index cefb7a74dd1..4a3c76809e8 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -38,7 +38,15 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); info->last_key_func=search_flag; - if (!info->use_packed_key) + if (info->once_flags & USE_PACKED_KEYS) + { + /* key is already packed! */ + key_buff=info->lastkey+info->s->base.max_key_length; + info->last_rkey_length=pack_key_length=key_len; + bmove(key_buff,key,key_len); + info->once_flags&= ~USE_PACKED_KEYS; + } + else { if (key_len == 0) key_len=USE_WHOLE_KEY; @@ -48,13 +56,6 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,share->keyinfo[inx].seg, key_buff,pack_key_length);); } - else - { - /* key is already packed! */ - key_buff=info->lastkey+info->s->base.max_key_length; - info->last_rkey_length=pack_key_length=key_len; - bmove(key_buff,key,key_len); - } if (fast_mi_readinfo(info)) goto err; diff --git a/myisam/mi_rrnd.c b/myisam/mi_rrnd.c index f8009441cff..29f686b0456 100644 --- a/myisam/mi_rrnd.c +++ b/myisam/mi_rrnd.c @@ -46,7 +46,10 @@ int mi_rrnd(MI_INFO *info, byte *buf, register my_off_t filepos) filepos= info->nextpos; } - info->lastinx= -1; /* Can't forward or backward */ + if (info->once_flags & RRND_PRESERVE_LASTINX) + info->once_flags&= ~RRND_PRESERVE_LASTINX; + else + info->lastinx= -1; /* Can't forward or backward */ /* Init all but update-flag */ info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index 6499021861e..c63f4a28562 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -267,7 +267,7 @@ struct st_myisam_info { my_bool quick_mode; my_bool page_changed; /* If info->buff can't be used for rnext */ my_bool buff_used; /* If info->buff has to be reread for rnext */ - my_bool use_packed_key; /* For MYISAMMRG */ + my_bool once_flags; /* For MYISAMMRG */ #ifdef THREAD THR_LOCK_DATA lock; #endif @@ -288,6 +288,10 @@ struct st_myisam_info { #define WRITEINFO_UPDATE_KEYFILE 1 #define WRITEINFO_NO_UNLOCK 2 + /* once_flags */ +#define USE_PACKED_KEYS 1 +#define RRND_PRESERVE_LASTINX 2 + /* bits in state.changed */ #define STATE_CHANGED 1 diff --git a/myisammrg/Makefile.am b/myisammrg/Makefile.am index 6a6824affba..b749b84ba0b 100644 --- a/myisammrg/Makefile.am +++ b/myisammrg/Makefile.am @@ -21,7 +21,8 @@ libmyisammrg_a_SOURCES = myrg_open.c myrg_extra.c myrg_info.c myrg_locking.c \ myrg_rrnd.c myrg_update.c myrg_delete.c myrg_rsame.c \ myrg_panic.c myrg_close.c myrg_create.c myrg_static.c \ myrg_rkey.c myrg_rfirst.c myrg_rlast.c myrg_rnext.c \ - myrg_rprev.c myrg_queue.c myrg_write.c myrg_range.c + myrg_rprev.c myrg_queue.c myrg_write.c myrg_range.c \ + myrg_rnext_same.c # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/myisammrg/myrg_rkey.c b/myisammrg/myrg_rkey.c index ba042352a51..c0cef5a4eca 100644 --- a/myisammrg/myrg_rkey.c +++ b/myisammrg/myrg_rkey.c @@ -62,9 +62,8 @@ int myrg_rkey(MYRG_INFO *info,byte *record,int inx, const byte *key, } else { - mi->use_packed_key=1; + mi->once_flags|= USE_PACKED_KEYS; err=mi_rkey(mi,0,inx,key_buff,pack_key_length,search_flag); - mi->use_packed_key=0; } info->last_used_table=table+1; @@ -83,5 +82,6 @@ int myrg_rkey(MYRG_INFO *info,byte *record,int inx, const byte *key, return HA_ERR_KEY_NOT_FOUND; mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table; + mi->once_flags|= RRND_PRESERVE_LASTINX; return mi_rrnd(mi,record,mi->lastpos); } diff --git a/myisammrg/myrg_rnext_same.c b/myisammrg/myrg_rnext_same.c new file mode 100644 index 00000000000..b569459b77d --- /dev/null +++ b/myisammrg/myrg_rnext_same.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This program 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 of the License, or + (at your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "myrg_def.h" + +int myrg_rnext_same(MYRG_INFO *info, byte *buf) +{ + uint err; + MI_INFO *mi; + + if (!info->current_table) + return (HA_ERR_KEY_NOT_FOUND); + + err=mi_rnext_same(info->current_table->table,buf); + if (err == HA_ERR_END_OF_FILE) + { + queue_remove(&(info->by_key),0); + if (!info->by_key.elements) + return HA_ERR_END_OF_FILE; + + mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table; + mi->once_flags|= RRND_PRESERVE_LASTINX; + return mi_rrnd(mi,buf,mi->lastpos); + } + return err; +} + diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index 07683dca73e..4398aaecf4d 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -160,6 +160,16 @@ int ha_myisammrg::index_last(byte * buf) return error; } +int ha_myisammrg::index_next_same(byte * buf, + const byte *key __attribute__((unused)), + uint length __attribute__((unused))) +{ + statistic_increment(ha_read_next_count,&LOCK_status); + int error=myrg_rnext_same(file,buf); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + int ha_myisammrg::rnd_init(bool scan) { return myrg_extra(file,HA_EXTRA_RESET,0); diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h index 8e33b99e418..008f5339caf 100644 --- a/sql/ha_myisammrg.h +++ b/sql/ha_myisammrg.h @@ -65,15 +65,16 @@ class ha_myisammrg: public handler int index_prev(byte * buf); int index_first(byte * buf); int index_last(byte * buf); + int index_next_same(byte *buf, const byte *key, uint keylen); int rnd_init(bool scan=1); int rnd_next(byte *buf); int rnd_pos(byte * buf, byte *pos); void position(const byte *record); - ha_rows ha_myisammrg::records_in_range(int inx, - const byte *start_key,uint start_key_len, - enum ha_rkey_function start_search_flag, - const byte *end_key,uint end_key_len, - enum ha_rkey_function end_search_flag); + ha_rows records_in_range(int inx, + const byte *start_key,uint start_key_len, + enum ha_rkey_function start_search_flag, + const byte *end_key,uint end_key_len, + enum ha_rkey_function end_search_flag); my_off_t row_position() { return myrg_position(file); } void info(uint); int extra(enum ha_extra_function operation); From da538d2bb56cd7431ad7d87fb7b533004ddac983 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Nov 2002 01:00:05 +0200 Subject: [PATCH 42/89] subselects in insert/replace (SCRUM) mysql-test/r/subselect.result: test of insert/replace with subselects mysql-test/t/subselect.test: test of insert/replace with subselects sql/sql_insert.cc: subselects in insert/replace sql/sql_yacc.yy: subselects in insert/replace --- mysql-test/r/subselect.result | 62 ++++++++++++++++++++++++++++++++++- mysql-test/t/subselect.test | 39 +++++++++++++++++++++- sql/sql_insert.cc | 31 +++++++++++++----- sql/sql_yacc.yy | 8 ++++- 4 files changed, 128 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 02f05ce50d6..ce5e7d2032f 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -335,7 +335,6 @@ a b 1 21 2 22 drop table t1, t2; -drop table if exists t1, t2; create table t1 (a int NOT NULL, b int, primary key (a)); create table t2 (a int NOT NULL, b int, primary key (a)); insert into t1 values (0, 10),(1, 11),(2, 12); @@ -354,3 +353,64 @@ a b 0 10 1 11 drop table t1, t2; +CREATE TABLE t1 (x int); +create table t2 (a int); +insert into t2 values (1); +INSERT INTO t1 (x) VALUES ((SELECT a FROM t2)); +select * from t1; +x +1 +insert into t2 values (1); +INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2)); +select * from t1; +x +1 +2 +INSERT INTO t1 (x) select (SELECT SUM(a)+1 FROM t2) FROM t2; +select * from t1; +x +1 +2 +3 +3 +INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2; +INSERT TABLE 't1' isn't allowed in FROM table list +INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(x) FROM t1)); +select * from t1; +x +1 +2 +3 +3 +9 +drop table t1, t2; +CREATE TABLE t1 (x int not null, y int, primary key (x)); +create table t2 (a int); +insert into t2 values (1); +select * from t1; +x y +replace into t1 (x, y) VALUES ((SELECT a FROM t2), (SELECT a+1 FROM t2)); +select * from t1; +x y +1 2 +replace into t1 (x, y) VALUES ((SELECT a FROM t2), (SELECT a+2 FROM t2)); +select * from t1; +x y +1 3 +replace DELAYED into t1 (x, y) VALUES ((SELECT a+3 FROM t2), (SELECT a FROM t2)); +select * from t1; +x y +1 3 +4 1 +replace DELAYED into t1 (x, y) VALUES ((SELECT a+3 FROM t2), (SELECT a+1 FROM t2)); +select * from t1; +x y +1 3 +4 2 +replace LOW_PRIORITY into t1 (x, y) VALUES ((SELECT a+1 FROM t2), (SELECT a FROM t2)); +select * from t1; +x y +1 3 +4 2 +2 1 +drop table t1, t2; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 3f20abe803a..4dea1ab5bca 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -216,7 +216,6 @@ select * from t1; drop table t1, t2; #delete with subselects -drop table if exists t1, t2; create table t1 (a int NOT NULL, b int, primary key (a)); create table t2 (a int NOT NULL, b int, primary key (a)); insert into t1 values (0, 10),(1, 11),(2, 12); @@ -226,3 +225,41 @@ select * from t1 where b = (select b from t2 where t1.a = t2.a); delete from t1 where b = (select b from t2 where t1.a = t2.a); select * from t1; drop table t1, t2; + +#insert with subselects +CREATE TABLE t1 (x int); +create table t2 (a int); +insert into t2 values (1); +INSERT INTO t1 (x) VALUES ((SELECT a FROM t2)); +select * from t1; +insert into t2 values (1); +INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2)); +-- sleep 1 +select * from t1; +INSERT INTO t1 (x) select (SELECT SUM(a)+1 FROM t2) FROM t2; +select * from t1; +-- error 1093 +INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2; +INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(x) FROM t1)); +-- sleep 1 +select * from t1; +drop table t1, t2; + +#replace with subselects +CREATE TABLE t1 (x int not null, y int, primary key (x)); +create table t2 (a int); +insert into t2 values (1); +select * from t1; +replace into t1 (x, y) VALUES ((SELECT a FROM t2), (SELECT a+1 FROM t2)); +select * from t1; +replace into t1 (x, y) VALUES ((SELECT a FROM t2), (SELECT a+2 FROM t2)); +select * from t1; +replace DELAYED into t1 (x, y) VALUES ((SELECT a+3 FROM t2), (SELECT a FROM t2)); +-- sleep 1 +select * from t1; +replace DELAYED into t1 (x, y) VALUES ((SELECT a+3 FROM t2), (SELECT a+1 FROM t2)); +-- sleep 1 +select * from t1; +replace LOW_PRIORITY into t1 (x, y) VALUES ((SELECT a+1 FROM t2), (SELECT a FROM t2)); +select * from t1; +drop table t1, t2; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index c8a29dcd8da..295c1e339c5 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -114,6 +114,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List &fields, List_item *values; char *query=thd->query; thr_lock_type lock_type = table_list->lock_type; + TABLE_LIST *insert_table_list= (TABLE_LIST*) + thd->lex.select_lex.table_list.first; DBUG_ENTER("mysql_insert"); /* @@ -126,7 +128,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List &fields, thd->slave_thread)) || (lock_type == TL_WRITE_CONCURRENT_INSERT && duplic == DUP_REPLACE)) lock_type=TL_WRITE; + table_list->lock_type= lock_type; + int res; if (lock_type == TL_WRITE_DELAYED) { if (thd->locked_tables) @@ -141,25 +145,34 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List &fields, DBUG_RETURN(-1); } } - if (!(table = delayed_get_table(thd,table_list)) && !thd->fatal_error) - table = open_ltable(thd,table_list,lock_type=thd->update_lock_default); + if ((table= delayed_get_table(thd,table_list)) && !thd->fatal_error) + if (table_list->next && table) + res= open_and_lock_tables(thd, table_list->next); + else + res= (table == 0); + else + res= open_and_lock_tables(thd, table_list); } else - table = open_ltable(thd,table_list,lock_type); - if (!table) + res= open_and_lock_tables(thd, table_list); + if (res) DBUG_RETURN(-1); + fix_tables_pointers(&thd->lex.select_lex); + + table= table_list->table; thd->proc_info="init"; thd->used_tables=0; save_time_stamp=table->time_stamp; values= its++; if (check_insert_fields(thd,table,fields,*values,1) || - setup_tables(table_list) || setup_fields(thd,table_list,*values,0,0,0)) + setup_tables(insert_table_list) || + setup_fields(thd, insert_table_list, *values, 0, 0, 0)) { - table->time_stamp=save_time_stamp; + table->time_stamp= save_time_stamp; goto abort; } value_count= values->elements; - while ((values = its++)) + while ((values= its++)) { counter++; if (values->elements != value_count) @@ -170,9 +183,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List &fields, table->time_stamp=save_time_stamp; goto abort; } - if (setup_fields(thd,table_list,*values,0,0,0)) + if (setup_fields(thd,insert_table_list,*values,0,0,0)) { - table->time_stamp=save_time_stamp; + table->time_stamp= save_time_stamp; goto abort; } } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 4465a6d8695..187ba63e92f 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2837,7 +2837,13 @@ opt_temporary: */ insert: - INSERT { Lex->sql_command = SQLCOM_INSERT; } insert_lock_option + INSERT + { + LEX *lex= Lex; + lex->sql_command = SQLCOM_INSERT; + /* for subselects */ + lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; + } insert_lock_option opt_ignore insert2 { Select->set_lock_for_tables($3); From c6ce7b3fbe8075fa56a26a3b2b30020baf032bbe Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Nov 2002 14:01:08 +0100 Subject: [PATCH 43/89] removed redundant -I include-dirs --- client/Makefile.am | 5 ++--- dbug/Makefile.am | 2 +- extra/Makefile.am | 2 +- fs/Makefile.am | 7 ++----- heap/Makefile.am | 2 +- isam/Makefile.am | 2 +- libmysql/Makefile.am | 3 +-- libmysql_r/Makefile.am | 3 +-- libmysqld/Makefile.am | 5 ++--- merge/Makefile.am | 2 +- myisam/Makefile.am | 2 +- myisammrg/Makefile.am | 2 +- mysys/Makefile.am | 2 +- pstack/Makefile.am | 2 +- readline/Makefile.am | 2 +- regex/Makefile.am | 2 +- sql/Makefile.am | 5 ++--- strings/Makefile.am | 2 +- tests/Makefile.am | 4 +--- tools/Makefile.am | 3 +-- vio/Makefile.am | 2 +- 21 files changed, 25 insertions(+), 36 deletions(-) diff --git a/client/Makefile.am b/client/Makefile.am index 9c994814714..530e82ecae2 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -16,9 +16,8 @@ # This file is public domain and comes with NO WARRANTY of any kind -INCLUDES = -I$(srcdir)/../include \ - -I../include -I$(srcdir)/.. -I$(top_srcdir) \ - -I.. $(openssl_includes) +AUTOMAKE_OPTIONS = nostdinc +INCLUDES = -I$(top_srcdir)/include $(openssl_includes) LIBS = @CLIENT_LIBS@ LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysql/libmysqlclient.la bin_PROGRAMS = mysql mysqladmin mysqlcheck mysqlshow \ diff --git a/dbug/Makefile.am b/dbug/Makefile.am index 08f0164c02c..bd512ee1d1d 100644 --- a/dbug/Makefile.am +++ b/dbug/Makefile.am @@ -15,7 +15,7 @@ # Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, # MA 02111-1307, USA -INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include +INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include LDADD = libdbug.a ../strings/libmystrings.a pkglib_LIBRARIES = libdbug.a noinst_HEADERS = dbug_long.h diff --git a/extra/Makefile.am b/extra/Makefile.am index 2d7dc95f616..6895d7a09f8 100644 --- a/extra/Makefile.am +++ b/extra/Makefile.am @@ -14,7 +14,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include -I.. +INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include LDADD = @CLIENT_EXTRA_LDFLAGS@ ../mysys/libmysys.a \ ../dbug/libdbug.a ../strings/libmystrings.a bin_PROGRAMS = replace comp_err perror resolveip my_print_defaults \ diff --git a/fs/Makefile.am b/fs/Makefile.am index 33d1acd913d..6fea3d455a3 100644 --- a/fs/Makefile.am +++ b/fs/Makefile.am @@ -27,11 +27,8 @@ DISTCLEANFILES = CorbaFS-common.* CorbaFS-stubs.* CorbaFS-skels.* CorbaFS.h MYSQLDATAdir = $(localstatedir) MYSQLSHAREdir = $(pkgdatadir) MYSQLBASEdir= $(prefix) -INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include \ - -I$(srcdir)/../regex \ - -I$(srcdir) -I../include -I.. -I. \ - -I$(srcdir) -I../include -I.. -I. \ - $(orbit_includes) +INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include \ + -I$(top_srcdir)/regex $(orbit_includes) WRAPLIBS= @WRAPLIBS@ libexec_PROGRAMS = mysqlcorbafsd noinst_PROGRAMS =mysqlfs_test diff --git a/heap/Makefile.am b/heap/Makefile.am index 41d98b79ae9..ec631148dce 100644 --- a/heap/Makefile.am +++ b/heap/Makefile.am @@ -14,7 +14,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include +INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include LDADD = libheap.a ../mysys/libmysys.a ../dbug/libdbug.a \ ../strings/libmystrings.a pkglib_LIBRARIES = libheap.a diff --git a/isam/Makefile.am b/isam/Makefile.am index 8f23138f29f..6d9e4176d43 100644 --- a/isam/Makefile.am +++ b/isam/Makefile.am @@ -14,7 +14,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include +INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include LDADD = @CLIENT_EXTRA_LDFLAGS@ libnisam.a ../mysys/libmysys.a \ ../dbug/libdbug.a ../strings/libmystrings.a pkglib_LIBRARIES = libnisam.a diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am index 3d380c14076..1d5a5b19180 100644 --- a/libmysql/Makefile.am +++ b/libmysql/Makefile.am @@ -20,8 +20,7 @@ target = libmysqlclient.la target_defs = -DUNDEF_THREADS_HACK -DDONT_USE_RAID @LIB_EXTRA_CCFLAGS@ -DMYSQL_CLIENT LIBS = @CLIENT_LIBS@ -INCLUDES = -I$(srcdir)/../include -I../include \ - -I$(srcdir)/.. -I$(top_srcdir) -I.. $(openssl_includes) +INCLUDES = -I$(top_srcdir)/include $(openssl_includes) include $(srcdir)/Makefile.shared diff --git a/libmysql_r/Makefile.am b/libmysql_r/Makefile.am index e01fc7634a1..265e31fafdb 100644 --- a/libmysql_r/Makefile.am +++ b/libmysql_r/Makefile.am @@ -21,8 +21,7 @@ target = libmysqlclient_r.la target_defs = -DDONT_USE_RAID @LIB_EXTRA_CCFLAGS@ ## LIBS = @LIBS@ -INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include \ - -I$(srcdir)/.. -I$(top_srcdir) -I.. $(openssl_includes) +INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include $(openssl_includes) ## automake barfs if you don't use $(srcdir) or $(top_srcdir) in include include $(top_srcdir)/libmysql/Makefile.shared diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index 022a589e304..18469422e39 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -25,9 +25,8 @@ DEFS = -DEMBEDDED_LIBRARY -DMYSQL_SERVER \ -DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \ -DDATADIR="\"$(MYSQLDATAdir)\"" \ -DSHAREDIR="\"$(MYSQLSHAREdir)\"" -INCLUDES= @MT_INCLUDES@ @bdb_includes@ -I$(srcdir)/../include \ - -I../include -I$(srcdir)/.. -I$(top_srcdir) -I.. \ - -I../sql -I../regex +INCLUDES= @MT_INCLUDES@ @bdb_includes@ -I$(top_srcdir)/include \ + -I$(top_srcdir)/sql -I$(top_srcdir)/regex noinst_LIBRARIES = libmysqld_int.a pkglib_LIBRARIES = libmysqld.a diff --git a/merge/Makefile.am b/merge/Makefile.am index 78441e84fac..25e15e9c6ec 100644 --- a/merge/Makefile.am +++ b/merge/Makefile.am @@ -14,7 +14,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include +INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include pkglib_LIBRARIES = libmerge.a noinst_HEADERS = mrg_def.h libmerge_a_SOURCES = mrg_open.c mrg_extra.c mrg_info.c mrg_locking.c \ diff --git a/myisam/Makefile.am b/myisam/Makefile.am index 1dbce5727f0..f8225868d96 100644 --- a/myisam/Makefile.am +++ b/myisam/Makefile.am @@ -17,7 +17,7 @@ EXTRA_DIST = mi_test_all.sh mi_test_all.res pkgdata_DATA = mi_test_all mi_test_all.res -INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include +INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include LDADD = @CLIENT_EXTRA_LDFLAGS@ libmyisam.a ../mysys/libmysys.a \ ../dbug/libdbug.a ../strings/libmystrings.a pkglib_LIBRARIES = libmyisam.a diff --git a/myisammrg/Makefile.am b/myisammrg/Makefile.am index b749b84ba0b..b5b1260385b 100644 --- a/myisammrg/Makefile.am +++ b/myisammrg/Makefile.am @@ -14,7 +14,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include +INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include pkglib_LIBRARIES = libmyisammrg.a noinst_HEADERS = myrg_def.h libmyisammrg_a_SOURCES = myrg_open.c myrg_extra.c myrg_info.c myrg_locking.c \ diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 2661363de11..330e1d6e59d 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -17,7 +17,7 @@ MYSQLDATAdir = $(localstatedir) MYSQLSHAREdir = $(pkgdatadir) MYSQLBASEdir= $(prefix) -INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include -I.. -I$(srcdir) +INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include -I$(srcdir) pkglib_LIBRARIES = libmysys.a LDADD = libmysys.a ../dbug/libdbug.a \ ../strings/libmystrings.a diff --git a/pstack/Makefile.am b/pstack/Makefile.am index 863a52f4488..77f84d212cd 100644 --- a/pstack/Makefile.am +++ b/pstack/Makefile.am @@ -20,7 +20,7 @@ # SUBDIRS = aout -INCLUDES = -I$(srcdir)/../include -I../include +INCLUDES = -I$(top_srcdir)/include noinst_HEADERS = bucomm.h debug.h ieee.h budbg.h demangle.h \ linuxthreads.h pstack.h pstacktrace.h SRC= bucomm.c filemode.c linuxthreads.c rddbg.c \ diff --git a/readline/Makefile.am b/readline/Makefile.am index e9c6b3b8d58..2fdb2e04bcd 100644 --- a/readline/Makefile.am +++ b/readline/Makefile.am @@ -2,7 +2,7 @@ # Makefile for the GNU readline library. # Copyright (C) 1994,1996,1997 Free Software Foundation, Inc. -INCLUDES = -I$(srcdir)/../include -I$(srcdir)/.. -I.. +INCLUDES = -I$(top_srcdir)/include noinst_LIBRARIES = libreadline.a diff --git a/regex/Makefile.am b/regex/Makefile.am index ee421b70bcf..2e23efcbf2a 100644 --- a/regex/Makefile.am +++ b/regex/Makefile.am @@ -15,7 +15,7 @@ # Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, # MA 02111-1307, USA -INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include +INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include noinst_LIBRARIES = libregex.a LDADD = libregex.a ../strings/libmystrings.a noinst_HEADERS = cclass.h cname.h regex2.h utils.h engine.c regex.h diff --git a/sql/Makefile.am b/sql/Makefile.am index 09fedd393c2..828e74c67fc 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -22,9 +22,8 @@ MYSQLSHAREdir = $(pkgdatadir) MYSQLBASEdir= $(prefix) INCLUDES = @MT_INCLUDES@ \ @bdb_includes@ @innodb_includes@ \ - -I$(srcdir)/../include \ - -I$(srcdir)/../regex \ - -I$(srcdir) -I../include -I. $(openssl_includes) + -I$(top_srcdir)/include -I$(top_srcdir)/regex \ + -I$(srcdir) $(openssl_includes) WRAPLIBS= @WRAPLIBS@ SUBDIRS = share libexec_PROGRAMS = mysqld diff --git a/strings/Makefile.am b/strings/Makefile.am index e53ff21cdf8..ac0b6d7f1e0 100644 --- a/strings/Makefile.am +++ b/strings/Makefile.am @@ -16,7 +16,7 @@ # This file is public domain and comes with NO WARRANTY of any kind -INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include +INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include pkglib_LIBRARIES = libmystrings.a # Exact one of ASSEMBLER_X diff --git a/tests/Makefile.am b/tests/Makefile.am index 4935b6cd95a..5dc6871bd43 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -29,9 +29,7 @@ EXTRA_DIST = auto_increment.res auto_increment.tst \ # # C Test for 4.1 protocol # -INCLUDES = -I$(srcdir)/../include $(openssl_includes) \ - -I../include -I$(srcdir)/.. -I$(top_srcdir) \ - -I.. +INCLUDES = -I$(top_srcdir)/include $(openssl_includes) LIBS = @CLIENT_LIBS@ LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysql/libmysqlclient.la noinst_PROGRAMS = client_test diff --git a/tools/Makefile.am b/tools/Makefile.am index 3c786dc9281..0dc0b90c60e 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,5 +1,4 @@ -INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include \ - $(openssl_includes) -I../include +INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include $(openssl_includes) LDADD= @CLIENT_EXTRA_LDFLAGS@ ../libmysql_r/libmysqlclient_r.la @openssl_libs@ bin_PROGRAMS= mysqlmanager mysqlmanager_SOURCES= mysqlmanager.c diff --git a/vio/Makefile.am b/vio/Makefile.am index b53f3be9f91..16c70b12454 100644 --- a/vio/Makefile.am +++ b/vio/Makefile.am @@ -14,7 +14,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -INCLUDES = -I$(srcdir)/../include -I../include $(openssl_includes) +INCLUDES = -I$(top_srcdir)/include $(openssl_includes) LDADD = @CLIENT_EXTRA_LDFLAGS@ libvio.a $(openssl_libs) pkglib_LIBRARIES = libvio.a noinst_PROGRAMS = test-ssl test-sslserver test-sslclient From 0c417889d90caa3c663413ff125d9df0a4f95b87 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Nov 2002 14:03:25 +0100 Subject: [PATCH 44/89] mysql.cc has to support older readline to compile on FreeBSD :(( --- client/mysql.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/client/mysql.cc b/client/mysql.cc index 391779ef801..13943691fb4 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1070,9 +1070,13 @@ static void initialize_readline (char *name) rl_readline_name = name; /* Tell the completer that we want a crack first. */ - /* rl_attempted_completion_function = (CPPFunction *)mysql_completion;*/ +#if RL_READLINE_VERSION > 0x0400 rl_attempted_completion_function = &new_mysql_completion; rl_completion_entry_function= &no_completion; +#else + rl_attempted_completion_function =(CPPFunction *)new_mysql_completion; + rl_completion_entry_function= (Function *)no_completion; +#endif } /* @@ -1087,7 +1091,11 @@ static char **new_mysql_completion (const char *text, int end __attribute__((unused))) { if (!status.batch && !quick) +#if RL_READLINE_VERSION > 0x0400 return rl_completion_matches(text, new_command_generator); +#else + return completion_matches((char *)text, (CPFunction *)new_command_generator); +#endif else return (char**) 0; } From 1144c5cfd8dcf3f7125174327f94587ad4820050 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Nov 2002 14:18:16 +0100 Subject: [PATCH 45/89] Pass thd as an argument to yyparse(), getting rid of all current_thd in the parser. BitKeeper/etc/ignore: Added bkpull.log.4 bkpull.log.5 bkpull.log.6 bkpush.log sql/sql_yacc.output to the ignore list --- .bzrignore | 5 ++++ sql/sql_parse.cc | 4 ++-- sql/sql_prepare.cc | 4 ++-- sql/sql_yacc.yy | 59 ++++++++++++++++++++++++++-------------------- 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/.bzrignore b/.bzrignore index 978926c8c37..88995ac7c65 100644 --- a/.bzrignore +++ b/.bzrignore @@ -562,3 +562,8 @@ bkpull.log.2 bkpull.log.3 build.log sql/safe_to_cache_query.txt +bkpull.log.4 +bkpull.log.5 +bkpull.log.6 +bkpush.log +sql/sql_yacc.output diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 86333552837..0ca62fd4f52 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -51,7 +51,7 @@ #define TRANS_MEM_ROOT_BLOCK_SIZE 4096 #define TRANS_MEM_ROOT_PREALLOC 4096 -extern int yyparse(void); +extern int yyparse(void *thd); extern "C" pthread_mutex_t THR_LOCK_keycache; #ifdef SOLARIS extern "C" int gethostname(char *name, int namelen); @@ -2951,7 +2951,7 @@ mysql_parse(THD *thd, char *inBuf, uint length) if (query_cache_send_result_to_client(thd, inBuf, length) <= 0) { LEX *lex=lex_start(thd, (uchar*) inBuf, length); - if (!yyparse() && ! thd->fatal_error) + if (!yyparse((void *)thd) && ! thd->fatal_error) { if (mqh_used && thd->user_connect && check_mqh(thd, lex->sql_command)) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index a3a1f93a829..ee97283760d 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -56,7 +56,7 @@ Long data handling: #define IS_PARAM_NULL(pos, param_no) pos[param_no/8] & (1 << param_no & 7) -extern int yyparse(void); +extern int yyparse(void *thd); /* Find prepared statement in thd @@ -605,7 +605,7 @@ static bool parse_prepare_query(PREP_STMT *stmt, LEX *lex=lex_start(thd, (uchar*) packet, length); lex->safe_to_cache_query= 0; - if (!yyparse() && !thd->fatal_error) + if (!yyparse((void *)thd) && !thd->fatal_error) error= send_prepare_results(stmt); lex_end(lex); DBUG_RETURN(error); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 4465a6d8695..1385f94a6ce 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -17,10 +17,16 @@ /* sql_yacc.yy */ %{ +/* Pass thd as an arg to yyparse(). The type will be void*, so it +** must be cast to (THD*) when used. Use the YYTHD macro for this. +*/ +#define YYPARSE_PARAM yythd +#define YYTHD ((THD *)yythd) + #define MYSQL_YACC #define YYINITDEPTH 100 #define YYMAXDEPTH 3200 /* Because of 64K stack */ -#define Lex current_lex +#define Lex (&(YYTHD->lex)) #define Select Lex->current_select #include "mysql_priv.h" #include "slave.h" @@ -35,9 +41,9 @@ int yylex(void *yylval); #define yyoverflow(A,B,C,D,E,F) if (my_yyoverflow((B),(D),(int*) (F))) { yyerror((char*) (A)); return 2; } -inline Item *or_or_concat(Item* A, Item* B) +inline Item *or_or_concat(THD *thd, Item* A, Item* B) { - return (current_thd->sql_mode & MODE_PIPES_AS_CONCAT ? + return (thd->sql_mode & MODE_PIPES_AS_CONCAT ? (Item*) new Item_func_concat(A,B) : (Item*) new Item_cond_or(A,B)); } @@ -661,11 +667,11 @@ END_OF_INPUT query: END_OF_INPUT { - THD *thd=current_thd; + THD *thd= YYTHD; if (!thd->bootstrap && (!(thd->lex.select_lex.options & OPTION_FOUND_COMMENT))) { - send_error(current_thd,ER_EMPTY_QUERY); + send_error(thd,ER_EMPTY_QUERY); YYABORT; } else @@ -791,7 +797,7 @@ master_def: create: CREATE opt_table_options TABLE_SYM opt_if_not_exists table_ident { - THD *thd=current_thd; + THD *thd= YYTHD; LEX *lex=Lex; lex->sql_command= SQLCOM_CREATE_TABLE; if (!lex->select_lex.add_table_to_list($5, @@ -1075,7 +1081,7 @@ type: | TIME_SYM { $$=FIELD_TYPE_TIME; } | TIMESTAMP { - if (current_thd->sql_mode & MODE_SAPDB) + if (YYTHD->sql_mode & MODE_SAPDB) $$=FIELD_TYPE_DATETIME; else $$=FIELD_TYPE_TIMESTAMP; @@ -1146,7 +1152,7 @@ int_type: | BIGINT { $$=FIELD_TYPE_LONGLONG; }; real_type: - REAL { $$= current_thd->sql_mode & MODE_REAL_AS_FLOAT ? + REAL { $$= YYTHD->sql_mode & MODE_REAL_AS_FLOAT ? FIELD_TYPE_FLOAT : FIELD_TYPE_DOUBLE; } | DOUBLE_SYM { $$=FIELD_TYPE_DOUBLE; } | DOUBLE_SYM PRECISION { $$=FIELD_TYPE_DOUBLE; }; @@ -1211,7 +1217,7 @@ charset_name: { if (!($$=get_charset_by_name("binary",MYF(0)))) { - net_printf(current_thd,ER_UNKNOWN_CHARACTER_SET,"binary"); + net_printf(YYTHD,ER_UNKNOWN_CHARACTER_SET,"binary"); YYABORT; } } @@ -1219,7 +1225,7 @@ charset_name: { if (!($$=get_charset_by_name($1.str,MYF(0)))) { - net_printf(current_thd,ER_UNKNOWN_CHARACTER_SET,$1.str); + net_printf(YYTHD,ER_UNKNOWN_CHARACTER_SET,$1.str); YYABORT; } }; @@ -1247,6 +1253,7 @@ opt_binary: opt_primary: /* empty */ | PRIMARY_SYM + ; references: REFERENCES table_ident @@ -1347,7 +1354,7 @@ string_list: alter: ALTER opt_ignore TABLE_SYM table_ident { - THD *thd=current_thd; + THD *thd= YYTHD; LEX *lex=&thd->lex; lex->sql_command = SQLCOM_ALTER_TABLE; lex->name=0; @@ -1776,7 +1783,7 @@ expr_expr: { $$= new Item_func_between($1,$3,$5); } | expr NOT BETWEEN_SYM no_and_expr AND expr { $$= new Item_func_not(new Item_func_between($1,$4,$6)); } - | expr OR_OR_CONCAT expr { $$= or_or_concat($1,$3); } + | expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); } | expr OR expr { $$= new Item_cond_or($1,$3); } | expr XOR expr { $$= new Item_cond_xor($1,$3); } | expr AND expr { $$= new Item_cond_and($1,$3); } @@ -1818,7 +1825,7 @@ no_in_expr: { $$= new Item_func_between($1,$3,$5); } | no_in_expr NOT BETWEEN_SYM no_and_expr AND expr { $$= new Item_func_not(new Item_func_between($1,$4,$6)); } - | no_in_expr OR_OR_CONCAT expr { $$= or_or_concat($1,$3); } + | no_in_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); } | no_in_expr OR expr { $$= new Item_cond_or($1,$3); } | no_in_expr XOR expr { $$= new Item_cond_xor($1,$3); } | no_in_expr AND expr { $$= new Item_cond_and($1,$3); } @@ -1863,7 +1870,7 @@ no_and_expr: { $$= new Item_func_between($1,$3,$5); } | no_and_expr NOT BETWEEN_SYM no_and_expr AND expr { $$= new Item_func_not(new Item_func_between($1,$4,$6)); } - | no_and_expr OR_OR_CONCAT expr { $$= or_or_concat($1,$3); } + | no_and_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); } | no_and_expr OR expr { $$= new Item_cond_or($1,$3); } | no_and_expr XOR expr { $$= new Item_cond_xor($1,$3); } | no_and_expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); } @@ -3009,7 +3016,7 @@ update_list: }; opt_low_priority: - /* empty */ { $$= current_thd->update_lock_default; } + /* empty */ { $$= YYTHD->update_lock_default; } | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }; /* Delete rows from a table */ @@ -3193,7 +3200,7 @@ show_param: { Lex->sql_command= SQLCOM_SHOW_PROCESSLIST;} | opt_var_type VARIABLES wild { - THD *thd= current_thd; + THD *thd= YYTHD; thd->lex.sql_command= SQLCOM_SHOW_VARIABLES; thd->lex.option_type= (enum_var_type) $1; } @@ -3404,7 +3411,7 @@ opt_local: | LOCAL_SYM { $$=1;}; load_data_lock: - /* empty */ { $$= current_thd->update_lock_default; } + /* empty */ { $$= YYTHD->update_lock_default; } | CONCURRENT { $$= TL_WRITE_CONCURRENT_INSERT ; } | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }; @@ -3453,13 +3460,13 @@ opt_ignore_lines: /* Common definitions */ text_literal: - TEXT_STRING { $$ = new Item_string($1.str,$1.length,current_thd->thd_charset); } + TEXT_STRING { $$ = new Item_string($1.str,$1.length,YYTHD->thd_charset); } | UNDERSCORE_CHARSET TEXT_STRING { $$ = new Item_string($2.str,$2.length,Lex->charset); } | text_literal TEXT_STRING { ((Item_string*) $1)->append($2.str,$2.length); }; text_string: - TEXT_STRING { $$= new String($1.str,$1.length,current_thd->thd_charset); } + TEXT_STRING { $$= new String($1.str,$1.length,YYTHD->thd_charset); } | HEX_NUM { Item *tmp = new Item_varbinary($1.str,$1.length); @@ -3469,7 +3476,7 @@ param_marker: '?' { LEX *lex=Lex; - if (current_thd->prepare_command) + if (YYTHD->prepare_command) { lex->param_list.push_back($$=new Item_param()); lex->param_count++; @@ -3505,7 +3512,7 @@ insert_ident: table_wild: ident '.' '*' { $$ = new Item_field(NullS,$1.str,"*"); } | ident '.' ident '.' '*' - { $$ = new Item_field((current_thd->client_capabilities & + { $$ = new Item_field((YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS : $1.str),$3.str,"*"); }; order_ident: @@ -3530,7 +3537,7 @@ simple_ident: | ident '.' ident '.' ident { SELECT_LEX_NODE *sel=Select; - $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field((current_thd->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str) : (Item*) new Item_ref((current_thd->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str); + $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field((YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str) : (Item*) new Item_ref((YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str); }; @@ -3813,7 +3820,7 @@ option_value: } | PASSWORD equal text_or_password { - THD *thd=current_thd; + THD *thd=YYTHD; LEX_USER *user; if (!(user=(LEX_USER*) sql_alloc(sizeof(LEX_USER)))) YYABORT; @@ -3895,7 +3902,7 @@ table_lock: lock_option: READ_SYM { $$=TL_READ_NO_INSERT; } - | WRITE_SYM { $$=current_thd->update_lock_default; } + | WRITE_SYM { $$=YYTHD->update_lock_default; } | LOW_PRIORITY WRITE_SYM { $$=TL_WRITE_LOW_PRIORITY; } | READ_SYM LOCAL_SYM { $$= TL_READ; } ; @@ -4332,7 +4339,7 @@ singleval_subselect: singleval_subselect_init: select_init { - $$= new Item_singleval_subselect(current_thd, + $$= new Item_singleval_subselect(YYTHD, Lex->current_select->master_unit()-> first_select()); }; @@ -4347,7 +4354,7 @@ exists_subselect: exists_subselect_init: select_init { - $$= new Item_exists_subselect(current_thd, + $$= new Item_exists_subselect(YYTHD, Lex->current_select->master_unit()-> first_select()); }; From cb746b6ce98845d4f88495570def630c85ea1ea0 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Nov 2002 14:19:39 +0100 Subject: [PATCH 46/89] typo fixed --- myisam/ft_parser.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/myisam/ft_parser.c b/myisam/ft_parser.c index 29a48352cd6..358706a8ffa 100644 --- a/myisam/ft_parser.c +++ b/myisam/ft_parser.c @@ -111,7 +111,7 @@ FT_WORD * ft_linearize(TREE *wtree) #else #define misc_word_char(X) ((X)=='\'' || (X)=='-') #endif -#define word_char(s,X) (true_word_char(s,X) || misc_word_char(s,X)) +#define word_char(s,X) (true_word_char(s,X) || misc_word_char(X)) /* returns: @@ -132,8 +132,8 @@ byte ft_get_word(byte **start, byte *end, FT_WORD *word, FTB_PARAM *param) { for (;doc Date: Tue, 26 Nov 2002 15:33:30 +0100 Subject: [PATCH 47/89] temporary fix to make mysql.cc to compile --with-readline (thought it won't compile --without-readline) preper fix is to follow... --- client/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/Makefile.am b/client/Makefile.am index 530e82ecae2..92c46519275 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -16,7 +16,7 @@ # This file is public domain and comes with NO WARRANTY of any kind -AUTOMAKE_OPTIONS = nostdinc +#AUTOMAKE_OPTIONS = nostdinc INCLUDES = -I$(top_srcdir)/include $(openssl_includes) LIBS = @CLIENT_LIBS@ LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysql/libmysqlclient.la From ae729f93158e57ef52b57ead0ec4f0c052fdda92 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Nov 2002 16:49:55 +0200 Subject: [PATCH 48/89] A fix for a bug with derived tables within subselect within derived tables within ...... --- mysql-test/r/derived.result | 3 +++ mysql-test/t/derived.test | 3 ++- sql/sql_derived.cc | 18 +++++++++++------- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index 204ca86f306..b397c2f7635 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -65,3 +65,6 @@ a t 19 19 20 20 drop table if exists t1; +SELECT * FROM (SELECT (SELECT * FROM (SELECT 1 as a))); +(SELECT * FROM (SELECT 1 as a)) +1 diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index de765a0e280..c1d8af4074a 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -33,4 +33,5 @@ while ($1) } enable_query_log; SELECT * FROM (SELECT * FROM t1) ORDER BY a ASC LIMIT 0,20; -drop table if exists t1; \ No newline at end of file +drop table if exists t1; +SELECT * FROM (SELECT (SELECT * FROM (SELECT 1 as a))); diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index b3d2b1602d0..6dc001a1932 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -50,15 +50,19 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) if (res) DBUG_RETURN(-1); - for (TABLE_LIST *cursor= (TABLE_LIST *)tables; - cursor; - cursor=cursor->next) + for (SELECT_LEX *ssl= sl; ssl; ssl= ssl->next_select_in_list()) { - if (cursor->derived) + TABLE_LIST *t_tables= (TABLE_LIST *)ssl->table_list.first; + for (TABLE_LIST *cursor= (TABLE_LIST *)t_tables; + cursor; + cursor=cursor->next) { - res= mysql_derived(thd, lex, (SELECT_LEX_UNIT *)cursor->derived, - cursor); - if (res) DBUG_RETURN(res); + if (cursor->derived) + { + res= mysql_derived(thd, lex, (SELECT_LEX_UNIT *)cursor->derived, + cursor); + if (res) DBUG_RETURN(res); + } } } Item *item; From 9ee2cee69aefa5f76cc73a8864c3283dd080d70a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Nov 2002 22:33:33 +0200 Subject: [PATCH 49/89] multi-delete with subselects (SCRUM) mysql-test/r/subselect.result: Multi-delete with subselect test mysql-test/t/subselect.test: Multi-delete with subselect test sql/sql_parse.cc: multi-delete with subselects --- mysql-test/r/subselect.result | 27 +++++++++++++++++++++++++++ mysql-test/t/subselect.test | 15 +++++++++++++++ sql/sql_parse.cc | 4 +++- 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index ce5e7d2032f..3bcb74af066 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -353,6 +353,33 @@ a b 0 10 1 11 drop table t1, t2; +drop table if exists t11, t12, t2; +create table t11 (a int NOT NULL, b int, primary key (a)); +create table t12 (a int NOT NULL, b int, primary key (a)); +create table t2 (a int NOT NULL, b int, primary key (a)); +insert into t11 values (0, 10),(1, 11),(2, 12); +insert into t12 values (33, 10),(22, 11),(2, 12); +insert into t2 values (1, 21),(2, 12),(3, 23); +select * from t11; +a b +0 10 +1 11 +2 12 +select * from t12; +a b +33 10 +22 11 +2 12 +delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2 where t11.a = t2.a); +select * from t11; +a b +0 10 +1 11 +select * from t12; +a b +33 10 +22 11 +drop table t11, t12, t2; CREATE TABLE t1 (x int); create table t2 (a int); insert into t2 values (1); diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 4dea1ab5bca..9d332665695 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -226,6 +226,21 @@ delete from t1 where b = (select b from t2 where t1.a = t2.a); select * from t1; drop table t1, t2; +#multi-delete with subselects +drop table if exists t11, t12, t2; +create table t11 (a int NOT NULL, b int, primary key (a)); +create table t12 (a int NOT NULL, b int, primary key (a)); +create table t2 (a int NOT NULL, b int, primary key (a)); +insert into t11 values (0, 10),(1, 11),(2, 12); +insert into t12 values (33, 10),(22, 11),(2, 12); +insert into t2 values (1, 21),(2, 12),(3, 23); +select * from t11; +select * from t12; +delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2 where t11.a = t2.a); +select * from t11; +select * from t12; +drop table t11, t12, t2; + #insert with subselects CREATE TABLE t1 (x int); create table t2 (a int); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 86333552837..e1cf553b5a5 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2095,10 +2095,12 @@ mysql_execute_command(THD *thd) /* Fix tables-to-be-deleted-from list to point at opened tables */ for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next) auxi->table= auxi->table_list->table; + fix_tables_pointers(&lex->select_lex); if (!thd->fatal_error && (result= new multi_delete(thd,aux_tables, table_count))) { - res= mysql_select(thd,tables,select_lex->item_list, + res= mysql_select(thd,select_lex->get_table_list(), + select_lex->item_list, select_lex->where, (ORDER *)NULL,(ORDER *)NULL,(Item *)NULL, (ORDER *)NULL, From 4adb15f3fa83c2ca5b0d5586fa90d2b50dbedb61 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Nov 2002 03:49:35 +0500 Subject: [PATCH 50/89] add new tests, new functions sql-bench/crash-me.sh: Add tests: - If double double quotes are allowed in identifiers. - Rollback rolls back meta data - NULL sort and NULL sort perserve. - remove one check of "serial". - (Column,Table,Named constraints) new test to crash me if the check syntax is only supported by the parser, but not done for real. - For all ..USER tests, (like current_user), add an extra test if ...USER() is supported. - Add tests for constants TRUE and FALSE - Add test of LIMIT # OFFSET (PostgreSQL syntax) - tests of a lot of new functions --- sql-bench/crash-me.sh | 249 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 228 insertions(+), 21 deletions(-) diff --git a/sql-bench/crash-me.sh b/sql-bench/crash-me.sh index 02e3072a3f9..5fa67773566 100644 --- a/sql-bench/crash-me.sh +++ b/sql-bench/crash-me.sh @@ -38,7 +38,7 @@ # as such, and clarify ones such as "mediumint" with comments such as # "3-byte int" or "same as xxx". -$version="1.58"; +$version="1.59"; use DBI; use Getopt::Long; @@ -253,6 +253,9 @@ check_and_report("\` as identifier quote",'quote_ident_with_`',[], 'select `A` from crash_me',[],"1",0); check_and_report("[] as identifier quote",'quote_ident_with_[',[], 'select [A] from crash_me',[],"1",0); +report('Double "" in identifiers as "','quote_ident_with_dbl_"', + 'create table crash_me1 ("abc""d" integer)', + 'drop table crash_me1'); report("Column alias","column_alias","select a as ab from crash_me"); report("Table alias","table_alias","select b.a from crash_me as b"); @@ -301,6 +304,7 @@ try_and_report("LIMIT number of rows","select_limit", ["with TOP", "select TOP 1 * from crash_me"]); report("SELECT with LIMIT #,#","select_limit2", "select * from crash_me limit 1,1"); +report("SELECT with LIMIT # OFFSET #","select_limit3", "select * from crash_me limit 1 offset 1"); # The following alter table commands MUST be kept together! if ($dbh->do("create table crash_q (a integer, b integer,c1 CHAR(10))")) @@ -434,6 +438,9 @@ report("hex strings (x'1ace')","hex_strings","select x'1ace' $end_query"); report_result("Value of logical operation (1=1)","logical_value", "select (1=1) $end_query"); +report_result("Value of TRUE","value_of_true","select TRUE $end_query"); +report_result("Value of FALSE","value_of_false","select FALSE $end_query"); + $logical_value= $limits{'logical_value'}; $false=0; @@ -584,7 +591,7 @@ print "$limits{'query_size'}\n"; "int not null identity,unique(q)", # postgres types "box","bool","circle","polygon","point","line","lseg","path", - "interval", "serial", "inet", "cidr", "macaddr", + "interval", "inet", "cidr", "macaddr", # oracle types "varchar2(16)","nvarchar2(16)","number(9,2)","number(9)", @@ -769,7 +776,6 @@ try_and_report("Automatic row id", "automatic_rowid", ["CURRENT_DATE","current_date","current_date",0,2], ["CURRENT_TIME","current_time","current_time",0,2], ["CURRENT_TIMESTAMP","current_timestamp","current_timestamp",0,2], - ["CURRENT_USER","current_user","current_user",0,2], ["EXTRACT","extract_sql","extract(minute from timestamp '2000-02-23 18:43:12.987')",43,0], ["LOCALTIME","localtime","localtime",0,2], ["LOCALTIMESTAMP","localtimestamp","localtimestamp",0,2], @@ -778,11 +784,8 @@ try_and_report("Automatic row id", "automatic_rowid", ["NULLIF with numbers","nullif_num","NULLIF(NULLIF(1,2),1)",undef(),4], ["OCTET_LENGTH","octet_length","octet_length('abc')",3,0], ["POSITION","position","position('ll' in 'hello')",3,0], - ["SESSION_USER","session_user","session_user",0,2], - ["SYSTEM_USER","system_user","system_user",0,2], ["TRIM","trim","trim(trailing from trim(LEADING FROM ' abc '))","abc",3], ["UPPER","upper","UPPER('abc')","ABC",1], - ["USER","user","user"], ["concatenation with ||","concat_as_||","'abc' || 'def'","abcdef",1], ); @@ -960,8 +963,61 @@ try_and_report("Automatic row id", "automatic_rowid", ["automatic num->string convert","auto_num2string","concat('a',2)","a2",1], ["automatic string->num convert","auto_string2num","'1'+2",3,0], ["concatenation with +","concat_as_+","'abc' + 'def'","abcdef",1], + ["SUBSTR (2 arg)",'substr2arg',"substr('abcd',2)",'bcd',1], #sapdb func + ["SUBSTR (3 arg)",'substr3arg',"substr('abcd',2,2)",'bc',1], + ["LFILL (3 arg)",'lfill3arg',"lfill('abcd','.',6)",'..abcd',1], + ["RFILL (3 arg)",'rfill3arg',"rfill('abcd','.',6)",'abcd..',1], + ["RPAD (4 arg)",'rpad4arg',"rpad('abcd',2,'+-',8)",'abcd+-+-',1], + ["LPAD (4 arg)",'rpad4arg',"lpad('abcd',2,'+-',8)",'+-+-abcd',1], + ["SAPDB compatible TRIM (1 arg)",'trim1arg',"trim(' abcd ')",'abcd',1], + ["SAPDB compatible TRIM (2 arg)",'trim2arg',"trim('..abcd..','.')",'abcd',1], + ["LTRIM (2 arg)",'ltrim2arg',"ltrim('..abcd..','.')",'abcd..',1], + ["RTRIM (2 arg)",'rtrim2arg',"rtrim('..abcd..','.')",'..abcd',1], + ["EXPAND",'expand2arg',"expand('abcd',6)",'abcd ',0], + ["REPLACE (2 arg) ",'replace2arg',"replace('AbCd','bC')",'Ad',1], + ["MAPCHAR",'mapchar',"mapchar('AБ')",'Aa',1], + ["ALPHA",'alpha',"alpha('AБ',2)",'AA',1], + ["ASCII in string cast",'ascii_string',"ascii('a')",'a',1], + ["EBCDIC in string cast",'ebcdic_string',"ebcdic('a')",'a',1], + ["TRUNC (1 arg)",'trunc1arg',"trunc(222.6)",222,0], + ["NOROUND",'noround',"noround(222.6)",222.6,0], + ["FIXED",'fixed',"fixed(222.6666,10,2)",'222.67',0], + ["FLOAT",'float',"float(6666.66,4)",6667,0], + ["LENGTH",'length',"length(1)",2,0], + ["INDEX",'index',"index('abcdefg','cd',1,1)",3,0], + ["ADDDATE",'adddate',"ADDDATE('20021201',3)",'20021204',0], + ["SUBDATE",'subdate',"SUBDATE('20021204',3)",'20021201',0], + ["DATEDIFF (2 arg)",'datediff2arg',"DATEDIFF('20021204','20021201')",'3',0], # sapdb + ["DAYOFWEEK with sapdb internal date as arg",'dayofweek_sapdb',"DAYOFWEEK('19630816')",'5',0], + ["WEEKOFYEAR",'weekofyear',"WEEKOFYEAR('19630816')",'33',0], + ["DAYOFMONTH with sapdb internal date as arg",'dayofmonth_sapdb',"dayofmonth('19630816')",'16',0], + ["DAYOFYEAR with sapdb internal date as arg",'dayofyear_sapdb',"DAYOFYEAR('19630816')",'228',0], + ["MAKEDATE",'makedate',"MAKEDATE(1963,228)",'19630816',0], + ["DAYNAME with sapdb internal date as arg",'dayname_sapdb',"DAYNAME('19630816')",'Friday',0], + ["MONTHNAME with sapdb internal date as arg",'monthname_sapdb',"MONTHNAME('19630816')",'August',0], + ["ADDTIME",'addtime',"ADDTIME('00200212','00000300')",'00200215',0], + ["SUBTIME",'subdate',"SUBDATE('00200215','00000300')",'00200212',0], + ["TIMEDIFF",'timediff',"TIMEDIFF('00200215','00200212')",'00000003',0], + ["MAKETIME",'maketime',"MAKETIME(20,02,12)",'00200212',0], + ["YEAR with sapdb internal date as arg",'year_sapdb',"YEAR('20021201')",'2002',0], + ["MONTH with sapdb internal date as arg",'month_sapdb',"MONTH('20021201')",'12',0], + ["DAY",'day',"DAY('20021201')",1,0], + ["HOUR with sapdb internal time as arg",'hour_sapdb',"HOUR('00200212')",20,0], + ["MINUTE with sapdb internal time as arg",'minute_sapdb',"MINUTE('00200212')",2,0], + ["SECOND with sapdb internal time as arg",'second_sapdb',"SECOND('00200212')",12,0], + ["MICROSECOND",'microsecond',"MICROSECOND('19630816200212111111')",'111111',0], + ["TIMESTAMP",'timestamp',"timestamp('19630816','00200212')",'19630816200212000000',0], + ["TIME",'time',"time('00200212')",'00200212',0], + ["DATE",'date',"date('19630816')",'19630816',0], + ["VALUE",'value',"value(NULL,'WALRUS')",'WALRUS',0], + ["DECODE",'decode',"DECODE('S-103','T72',1,'S-103',2,'Leopard',3)",2,0], + ["NUM",'num',"NUM('2123')",2123,0], + ["CHAR (conversation date)",'char_date',"CHAR(DATE('19630816'),EUR)",'16.08.1963',0], + ["CHR (any type to string)",'chr_str',"CHR(67)",'67',0], + ["HEX",'hex',"HEX('A')",41,0], ); + @sql_group_functions= ( ["AVG","avg","avg(a)",1,0], @@ -1131,6 +1187,20 @@ else } +if ($limits{'func_extra_noround'} eq 'yes') +{ + report("Ignoring NOROUND","ignoring_noround", + "create table crash_q (a int)", + "insert into crash_q values(noround(10.22))", + "drop table crash_q $drop_attr"); +} + +check_parenthesis("func_sql_","CURRENT_USER"); +check_parenthesis("func_sql_","SESSION_USER"); +check_parenthesis("func_sql_","SYSTEM_USER"); +check_parenthesis("func_sql_","USER"); + + report("LIKE on numbers","like_with_number", "create table crash_q (a int,b int)", "insert into crash_q values(10,10)", @@ -1561,19 +1631,29 @@ if (!defined($limits{"transactions"})) { my ($limit,$type); $limit="transactions"; + $limit_r="rollback_metadata"; print "$limit: "; foreach $type (('', 'type=bdb', 'type=innodb', 'type=gemini')) { undef($limits{$limit}); - last if (!report_trans($limit, + if (!report_trans($limit, [create_table("crash_q",["a integer not null"],[], $type), "insert into crash_q values (1)"], "select * from crash_q", "drop table crash_q $drop_attr" - )); + )) + { + report_rollback($limit_r, + [create_table("crash_q",["a integer not null"],[], + $type)], + "insert into crash_q values (1)", + "drop table crash_q $drop_attr" ); + last; + }; } print "$limits{$limit}\n"; + print "$limit_r: $limits{$limit_r}\n"; } report("atomic updates","atomic_updates", @@ -1644,14 +1724,29 @@ report("Column constraints","constraint_check", "create table crash_q (a int check (a>0))", "drop table crash_q $drop_attr"); +report("Ignoring column constraints","ignoring_constraint_check", + "create table crash_q (a int check (a>0))", + "insert into crash_q values(0)", + "drop table crash_q $drop_attr") if ($limits{'constraint_check'} eq 'yes'); + report("Table constraints","constraint_check_table", "create table crash_q (a int ,b int, check (a>b))", "drop table crash_q $drop_attr"); -report("Named constraints","constraint_check", +report("Ignoring table constraints","ignoring_constraint_check_table", + "create table crash_q (a int ,b int, check (a>b))", + "insert into crash_q values(0,0)", + "drop table crash_q $drop_attr") if ($limits{'constraint_check_table'} eq 'yes'); + +report("Named constraints","constraint_check_named", "create table crash_q (a int ,b int, constraint abc check (a>b))", "drop table crash_q $drop_attr"); +report("Ignoring named constraints","ignoring_constraint_check_named", + "create table crash_q (a int ,b int, constraint abc check (a>b))", + "insert into crash_q values(0,0)", + "drop table crash_q $drop_attr") if ($limits{'constraint_check_named'} eq 'yes'); + report("NULL constraint (SyBase style)","constraint_null", "create table crash_q (a int null)", "drop table crash_q $drop_attr"); @@ -2018,7 +2113,7 @@ $key="safe_decimal_arithmetic"; if (!defined($limits{$key})) { print "$prompt="; - save_incomplete($limit,$prompt); + save_incomplete($key,$prompt); if (!safe_query($server->create("crash_me_a",["a decimal(10,2)","b decimal(10,2)"]))) { print DBI->errstr(); @@ -2045,6 +2140,53 @@ if (!defined($limits{$key})) print "$prompt=$limits{$key} (cached)\n"; } +# Check where is null values in sorted recordset +if (!safe_query($server->create("crash_me_n",["i integer","r integer"]))) + { + print DBI->errstr(); + die "Can't create table 'crash_me_n' $DBI::errstr\n"; + }; +assert("insert into crash_me_n (i) values(1)"); +assert("insert into crash_me_n values(2,2)"); +assert("insert into crash_me_n values(3,3)"); +assert("insert into crash_me_n values(4,4)"); +assert("insert into crash_me_n (i) values(5)"); + +$key = "position_of_null"; +$prompt ="Where is null values in sorted recordset"; +if (!defined($limits{$key})) +{ + save_incomplete($key,$prompt); + print "$prompt="; + $sth=$dbh->prepare("select r from crash_me_n order by r "); + $sth->execute; + $limit= detect_null_position($sth); + $sth->finish; + print "$limit\n"; + save_config_data($key,$limit,$prompt); +} else { + print "$prompt=$limits{$key} (cache)\n"; +} + +$key = "position_of_null_desc"; +$prompt ="Where is null values in sorted recordset (DESC)"; +if (!defined($limits{$key})) +{ + save_incomplete($key,$prompt); + print "$prompt="; + $sth=$dbh->prepare("select r from crash_me_n order by r desc"); + $sth->execute; + $limit= detect_null_position($sth); + $sth->finish; + print "$limit\n"; + save_config_data($key,$limit,$prompt); +} else { + print "$prompt=$limits{$key} (cache)\n"; +} + + +assert("drop table crash_me_n $drop_attr"); + # # End of test @@ -2059,6 +2201,41 @@ $dbh->disconnect || warn $dbh->errstr; save_all_config_data(); exit 0; +# Check where is nulls in the sorted result (for) +# it expects exactly 5 rows in the result + +sub detect_null_position +{ + my $sth = shift; + my ($z,$r1,$r2,$r3,$r4,$r5); + $r1 = $sth->fetchrow_array; + $r2 = $sth->fetchrow_array; + $r3 = $sth->fetchrow_array; + $r4 = $sth->fetchrow_array; + $r5 = $sth->fetchrow_array; + return "first" if ( !defined($r1) && !defined($r2) && defined($r3)); + return "last" if ( !defined($r5) && !defined($r4) && defined($r3)); + return "random"; +} + +sub check_parenthesis { + my $prefix=shift; + my $fn=shift; + my $resultat='no'; + my $param_name=$prefix.lc($fn); + + save_incomplete($param_name,$fn); + if (safe_query("select $fn $end_query") == 1) + { + $resultat="yes"; + } + elsif ( safe_query("select $fn() $end_query") == 1) + { + $resultat="with_parenthesis"; + } + save_config_data($param_name,$resultat,$fn); +} + sub usage { print <rollback; - if ($rc) { - $dbh->{AutoCommit} = 1; + $dbh->rollback; + $dbh->{AutoCommit} = 1; if (safe_query_result($check,"","")) { save_config_data($limit,"yes",$limit); } safe_query($clear); - } else { - $dbh->{AutoCommit} = 1; - save_config_data($limit,"error",$limit); - } } else { save_config_data($limit,"error",$limit); } @@ -2603,6 +2775,39 @@ sub report_trans return $limits{$limit} ne "yes"; } +sub report_rollback +{ + my ($limit,$queries,$check,$clear)=@_; + if (!defined($limits{$limit})) + { + save_incomplete($limit,$prompt); + eval {undef($dbh->{AutoCommit})}; + if (!$@) + { + if (safe_query(\@$queries)) + { + $dbh->rollback; + $dbh->{AutoCommit} = 1; + if (safe_query($check)) { + save_config_data($limit,"no",$limit); + } else { + save_config_data($limit,"yes",$limit); + }; + safe_query($clear); + } else { + save_config_data($limit,"error",$limit); + } + } + else + { + save_config_data($limit,"error",$limit); + } + safe_query($clear); + } + $dbh->{AutoCommit} = 1; + return $limits{$limit} ne "yes"; +} + sub check_and_report { @@ -2929,7 +3134,7 @@ sub read_config_data { if ($key !~ /restart/i) { - $limits{$key}=$limit; + $limits{$key}=$limit eq "null"? undef : $limit; $prompts{$key}=length($prompt) ? substr($prompt,2) : ""; delete $limits{'restart'}; } @@ -2959,7 +3164,8 @@ sub save_config_data return if (defined($limits{$key}) && $limits{$key} eq $limit); if (!defined($limit) || $limit eq "") { - die "Undefined limit for $key\n"; +# die "Undefined limit for $key\n"; + $limit = 'null'; } print CONFIG_FILE "$key=$limit\t# $prompt\n"; $limits{$key}=$limit; @@ -3613,5 +3819,6 @@ sub check_query } + ### TODO: # OID test instead of / in addition to _rowid From a5541519512f4a843e9ff43e1c9ceab21b9a5d76 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Nov 2002 01:12:16 +0200 Subject: [PATCH 51/89] reverse order in global select list allow to avoid recursion in derived tables sql/sql_delete.cc: new order in global select list sql/sql_derived.cc: removed recursion from derived tables sql/sql_insert.cc: new order in global select list sql/sql_lex.h: pointer to global select list sql/sql_select.cc: new order in global select list sql/sql_update.cc: new order in global select list --- sql/sql_delete.cc | 2 +- sql/sql_derived.cc | 15 --------------- sql/sql_insert.cc | 2 +- sql/sql_lex.h | 2 ++ sql/sql_parse.cc | 44 +++++++++++++++++++++++--------------------- sql/sql_select.cc | 4 ++-- sql/sql_update.cc | 2 +- 7 files changed, 30 insertions(+), 41 deletions(-) diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 5b97b2f7750..07958ebcfab 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -43,7 +43,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, if ((open_and_lock_tables(thd, table_list))) DBUG_RETURN(-1); - fix_tables_pointers(&thd->lex.select_lex); + fix_tables_pointers(thd->lex.all_selects_list); table= table_list->table; table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); thd->proc_info="init"; diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 6dc001a1932..afdd1ccfdb2 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -50,21 +50,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) if (res) DBUG_RETURN(-1); - for (SELECT_LEX *ssl= sl; ssl; ssl= ssl->next_select_in_list()) - { - TABLE_LIST *t_tables= (TABLE_LIST *)ssl->table_list.first; - for (TABLE_LIST *cursor= (TABLE_LIST *)t_tables; - cursor; - cursor=cursor->next) - { - if (cursor->derived) - { - res= mysql_derived(thd, lex, (SELECT_LEX_UNIT *)cursor->derived, - cursor); - if (res) DBUG_RETURN(res); - } - } - } Item *item; List_iterator it(sl->item_list); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 295c1e339c5..1ca44046997 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -157,7 +157,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List &fields, res= open_and_lock_tables(thd, table_list); if (res) DBUG_RETURN(-1); - fix_tables_pointers(&thd->lex.select_lex); + fix_tables_pointers(thd->lex.all_selects_list); table= table_list->table; thd->proc_info="init"; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 93f01dd66dc..65c6f4ceb49 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -388,6 +388,8 @@ typedef struct st_lex SELECT_LEX select_lex; /* first SELECT_LEX */ /* current SELECT_LEX in parsing */ SELECT_LEX_NODE *current_select; + /* list of all SELECT_LEX */ + SELECT_LEX *all_selects_list; uchar *ptr,*tok_start,*tok_end,*end_of_query; char *length,*dec,*change,*name; char *backup_dir; /* For RESTORE/BACKUP */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 86333552837..7a1277e75bd 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1316,7 +1316,7 @@ mysql_execute_command(THD *thd) that is not a SHOW command or a select that only access local variables, but for now this is probably good enough. */ - if (tables || lex->select_lex.next_select_in_list()) + if (tables || &lex->select_lex != lex->all_selects_list) mysql_reset_errors(thd); /* Save old warning count to be able to send to client how many warnings we @@ -1353,22 +1353,23 @@ mysql_execute_command(THD *thd) */ if (lex->derived_tables) { - for (SELECT_LEX *sl= &lex->select_lex; sl; sl= sl->next_select_in_list()) - if (sl->linkage != DERIVED_TABLE_TYPE) - for (TABLE_LIST *cursor= sl->get_table_list(); - cursor; - cursor= cursor->next) - if (cursor->derived && (res=mysql_derived(thd, lex, - (SELECT_LEX_UNIT *) - cursor->derived, - cursor))) - { - if (res < 0 || thd->net.report_error) - send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); - DBUG_VOID_RETURN; - } - } - if ((lex->select_lex.next_select_in_list() && + for (SELECT_LEX *sl= lex->all_selects_list; + sl; + sl= sl->next_select_in_list()) + for (TABLE_LIST *cursor= sl->get_table_list(); + cursor; + cursor= cursor->next) + if (cursor->derived && (res=mysql_derived(thd, lex, + (SELECT_LEX_UNIT *) + cursor->derived, + cursor))) + { + if (res < 0 || thd->net.report_error) + send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); + DBUG_VOID_RETURN; + } + } + if ((&lex->select_lex != lex->all_selects_list && lex->unit.create_total_list(thd, lex, &tables)) || (table_rules_on && tables && thd->slave_thread && !tables_ok(thd,tables))) @@ -1415,7 +1416,7 @@ mysql_execute_command(THD *thd) } else thd->send_explain_fields(result); - fix_tables_pointers(select_lex); + fix_tables_pointers(lex->all_selects_list); res= mysql_explain_union(thd, &thd->lex.unit, result); MYSQL_LOCK *save_lock= thd->lock; thd->lock= (MYSQL_LOCK *)0; @@ -2841,9 +2842,11 @@ mysql_init_query(THD *thd) lex->value_list.empty(); lex->param_list.empty(); lex->unit.global_parameters= lex->unit.slave= lex->current_select= - &lex->select_lex; + lex->all_selects_list= &lex->select_lex; lex->select_lex.master= &lex->unit; lex->select_lex.prev= &lex->unit.slave; + lex->select_lex.link_next= 0; + lex->select_lex.link_prev= (st_select_lex_node**)&(lex->all_selects_list); lex->olap=lex->describe=0; lex->derived_tables= false; thd->check_loops_counter= thd->select_number= @@ -2896,8 +2899,7 @@ mysql_new_select(LEX *lex, bool move_down) select_lex->master_unit()->global_parameters= select_lex; DBUG_ASSERT(lex->current_select->linkage != GLOBAL_OPTIONS_TYPE); - select_lex->include_global(lex->current_select->select_lex()-> - next_select_in_list_addr()); + select_lex->include_global((st_select_lex_node**)&lex->all_selects_list); lex->current_select= select_lex; return 0; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 8f406efc030..bb7f23a6710 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -158,7 +158,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result) { int res; register SELECT_LEX *select_lex = &lex->select_lex; - fix_tables_pointers(select_lex); + fix_tables_pointers(lex->all_selects_list); if (select_lex->next_select()) res=mysql_union(thd,lex,result); else @@ -7514,7 +7514,7 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) { res= mysql_explain_select(thd, sl, (((&thd->lex.select_lex)==sl)? - ((sl->next_select_in_list())?"PRIMARY": + ((thd->lex.all_selects_list != sl)?"PRIMARY": "SIMPLE"): ((sl == first)? ((sl->linkage == DERIVED_TABLE_TYPE) ? diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 409b00b5703..c2ba65248a7 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -70,7 +70,7 @@ int mysql_update(THD *thd, if ((open_and_lock_tables(thd, table_list))) DBUG_RETURN(-1); - fix_tables_pointers(&thd->lex.select_lex); + fix_tables_pointers(thd->lex.all_selects_list); table= table_list->table; save_time_stamp=table->time_stamp; From 4826ed009186289b1b3f7a39a8bd0076cb85b712 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Nov 2002 18:51:38 -0800 Subject: [PATCH 52/89] =?UTF-8?q?select=5Ftest.c,=20insert=5Ftest.c:=20=20?= =?UTF-8?q?=20Added=20my=5Fglobal.h=20to=20compile=20after=20my=5Flist.h?= =?UTF-8?q?=20is=20added=20to=20mysql.h=20sql=5Fprepare.cc:=20=20=20Handle?= =?UTF-8?q?=20close=20stmt=20from=20client=20=20=20Minor=20fixups=20to=20m?= =?UTF-8?q?ake=20SET=20variable=3D=3F=20to=20work=20sql=5Fparse.cc:=20=20?= =?UTF-8?q?=20Added=20missed=20COM=5FCLOSE=5FSTMT=20mysql=5Fpriv.h:=20=20?= =?UTF-8?q?=20Change=20mysql=5Fstmt=5Fclose=20to=20mysql=5Fstmt=5Ffree=20t?= =?UTF-8?q?o=20not=20to=20conflict=20with=20client=20type=20libmysql.c:=20?= =?UTF-8?q?=20=20Clean=20all=20open=20stmts=20during=20mysql=5Fclose()=20i?= =?UTF-8?q?mplicitly?= libmysql/libmysql.c: Clean all open stmts during mysql_close() implicitly sql/mysql_priv.h: Handle close_stmt from client Change mysql_stmt_close to mysql_stmt_free to not to conflict with client type sql/sql_parse.cc: Added missed COM_CLOSE_STMT sql/sql_prepare.cc: Handle close stmt from client Change mysql_stmt_close to mysql_stmt_free to not to conflict with client type Minor fixups to make SET variable=? to work client/insert_test.c: Added my_global.h to compile after my_list.h is added to mysql.h client/select_test.c: Added my_global.h to compile after my_list.h is added to mysql.h --- client/insert_test.c | 1 + client/select_test.c | 1 + include/mysql.h | 9 +++++++-- libmysql/libmysql.c | 43 ++++++++++++++++++++++++++++++++++-------- sql/mysql_priv.h | 2 +- sql/sql_parse.cc | 7 ++++++- sql/sql_prepare.cc | 45 +++++++++++++++++++++++++++----------------- 7 files changed, 79 insertions(+), 29 deletions(-) diff --git a/client/insert_test.c b/client/insert_test.c index 42691df6875..fb4890faf73 100644 --- a/client/insert_test.c +++ b/client/insert_test.c @@ -16,6 +16,7 @@ #include #include +#include #include "mysql.h" #define INSERT_QUERY "insert into test (name,num) values ('item %d', %d)" diff --git a/client/select_test.c b/client/select_test.c index ee2a9192865..d7f18c0f1f0 100644 --- a/client/select_test.c +++ b/client/select_test.c @@ -19,6 +19,7 @@ #endif #include #include +#include "my_global.h" #include "mysql.h" #define SELECT_QUERY "select name from test where num = %d" diff --git a/include/mysql.h b/include/mysql.h index 230c0aad9df..67558e39cdb 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -61,6 +61,8 @@ typedef int my_socket; #define CHECK_EXTRA_ARGUMENTS #endif +#include "my_list.h" /* for LISTs used in 'MYSQL' and 'MYSQL_STMT' */ + extern unsigned int mysql_port; extern char *mysql_unix_port; @@ -213,6 +215,8 @@ typedef struct st_mysql struct st_mysql* last_used_slave; /* needed for round-robin slave pick */ /* needed for send/read/store/use result to work correctly with replication */ struct st_mysql* last_used_con; + + LIST *stmts; /* list of all statements */ } MYSQL; @@ -457,6 +461,7 @@ typedef struct st_mysql_stmt MYSQL_RES *result; /* resultset */ MYSQL_BIND *bind; /* row binding */ MYSQL_FIELD *fields; /* prepare meta info */ + LIST list; /* list to keep track of all stmts */ char *query; /* query buffer */ MEM_ROOT mem_root; /* root allocations */ MYSQL_RES tmp_result; /* Used by mysql_prepare_result */ @@ -469,8 +474,8 @@ typedef struct st_mysql_stmt char last_error[MYSQL_ERRMSG_SIZE]; /* error message */ my_bool long_alloced; /* flag to indicate long alloced */ my_bool send_types_to_server; /* to indicate types supply to server */ - my_bool param_buffers; /* to indicate the param bound buffers */ - my_bool res_buffers; /* to indicate the result bound buffers */ + my_bool param_buffers; /* to indicate the param bound buffers */ + my_bool res_buffers; /* to indicate the output bound buffers */ } MYSQL_STMT; diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 410be65660f..352ac520fed 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -114,6 +114,7 @@ static my_bool send_file_to_server(MYSQL *mysql,const char *filename); static sig_handler pipe_sig_handler(int sig); static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to, const char *from, ulong length); +static my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list); static my_bool org_my_init_done=0; @@ -2436,6 +2437,16 @@ mysql_close(MYSQL *mysql) } mysql->rpl_pivot=0; } + if (mysql->stmts) + { + /* Free any open prepared statements */ + LIST *element, *next_element; + for (element= mysql->stmts; element; element= next_element) + { + next_element= element->next; + stmt_close((MYSQL_STMT *)element->data, 0); + } + } if (mysql != mysql->master) mysql_close(mysql->master); if (mysql->free_me) @@ -3675,18 +3686,20 @@ mysql_prepare(MYSQL *mysql, const char *query, ulong length) } if (simple_command(mysql, COM_PREPARE, query, length, 1)) { - mysql_stmt_close(stmt); + stmt_close(stmt, 1); DBUG_RETURN(0); } init_alloc_root(&stmt->mem_root,8192,0); if (read_prepare_result(mysql, stmt)) { - mysql_stmt_close(stmt); + stmt_close(stmt, 1); DBUG_RETURN(0); } stmt->state= MY_ST_PREPARE; stmt->mysql= mysql; + mysql->stmts= list_add(mysql->stmts, &stmt->list); + stmt->list.data= stmt; DBUG_PRINT("info", ("Parameter count: %ld", stmt->param_count)); DBUG_RETURN(stmt); } @@ -4304,7 +4317,6 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind) DBUG_RETURN(0); } - /* Fetch row data to bind buffers */ @@ -4387,27 +4399,42 @@ int STDCALL mysql_fetch(MYSQL_STMT *stmt) *********************************************************************/ /* - Close the statement handle by freeing all resources -*/ + Close the statement handle by freeing all alloced resources -my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt) + SYNOPSIS + mysql_stmt_close() + stmt Statement handle + skip_list Flag to indicate delete from list or not + RETURN VALUES + 0 ok + 1 error +*/ +static my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list) { my_bool error=0; DBUG_ENTER("mysql_stmt_close"); - if (stmt->state != MY_ST_UNKNOWN) + DBUG_ASSERT(stmt != 0); + if (stmt->state == MY_ST_PREPARE || stmt->state == MY_ST_EXECUTE) { char buff[4]; int4store(buff, stmt->stmt_id); - error= simple_command(stmt->mysql, COM_CLOSE_STMT, buff, 4, 0); + error= simple_command(stmt->mysql, COM_CLOSE_STMT, buff, 4, 1); } mysql_free_result(stmt->result); free_root(&stmt->mem_root, MYF(0)); my_free((gptr) stmt->query, MYF(MY_WME | MY_ALLOW_ZERO_PTR)); + if (!skip_list) + stmt->mysql->stmts= list_delete(stmt->mysql->stmts, &stmt->list); my_free((gptr) stmt, MYF(MY_WME)); DBUG_RETURN(error); } +my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt) +{ + return stmt_close(stmt, 0); +} + /* Return statement error code */ diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 3ba88d493bd..d8c602d69fb 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -516,7 +516,7 @@ int compare_prep_stmt(void *not_used, PREP_STMT *stmt, ulong *key); void free_prep_stmt(PREP_STMT *stmt, TREE_FREE mode, void *not_used); bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length); void mysql_stmt_execute(THD *thd, char *packet); -void mysql_stm_close(THD *thd, char *packet); +void mysql_stmt_free(THD *thd, char *packet); void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length); int check_insert_fields(THD *thd,TABLE *table,List &fields, List &values, ulong counter); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 263ac50120d..b1bdb3f6d0f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -74,7 +74,7 @@ const char *command_name[]={ "Drop DB", "Refresh", "Shutdown", "Statistics", "Processlist", "Connect","Kill","Debug","Ping","Time","Delayed_insert","Change user", "Binlog Dump","Table Dump", "Connect Out", "Register Slave", - "Prepare", "Prepare Execute", "Long Data" + "Prepare", "Prepare Execute", "Long Data", "Close stmt" }; static char empty_c_string[1]= {0}; // Used for not defined 'db' @@ -1004,6 +1004,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, mysql_stmt_prepare(thd, packet, packet_length); break; } + case COM_CLOSE_STMT: + { + mysql_stmt_free(thd, packet); + break; + } case COM_QUERY: { if (alloc_query(thd, packet, packet_length)) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 3ec12177778..fcae61d698e 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -20,32 +20,47 @@ This file contains the implementation of prepare and executes. Prepare: - - Server gets the query from client with command 'COM_PREPARE' + - Server gets the query from client with command 'COM_PREPARE'; + in the following format: + [COM_PREPARE:1] [query] - Parse the query and recognize any parameter markers '?' and - store its information list lex->param_list + store its information list in lex->param_list + - Allocate a new statement for this prepare; and keep this in + 'thd->prepared_statements' pool. - Without executing the query, return back to client the total number of parameters along with result-set metadata information - (if any) + (if any) in the following format: + [STMT_ID:4][Columns:2][Param_count:2][Columns meta info][Params meta info] Prepare-execute: - Server gets the command 'COM_EXECUTE' to execute the previously prepared query. If there is any param markers; then client will send the data in the following format: - [null_bits][types_specified(0/1)][[length][data]][[length][data] .. [length][data]. + [COM_EXECUTE:1] + [STMT_ID:4] + [NULL_BITS:(param_count+7)/8)] + [TYPES_SUPPLIED_BY_CLIENT(0/1):1] + [[length]data] + [[length]data] .. [[length]data]. + (Note: Except for string/binary types; all other types will not be + supplied with length field) - Replace the param items with this new data. If it is a first execute or types altered by client; then setup the conversion routines. - Execute the query without re-parsing and send back the results to client Long data handling: + - Server gets the long data in pieces with command type 'COM_LONG_DATA'. - The packet recieved will have the format as: - [COM_LONG_DATA:1][parameter_number:2][type:2][data] + [COM_LONG_DATA:1][STMT_ID:4][parameter_number:2][type:2][data] - Checks if the type is specified by client, and if yes reads the type, and stores the data in that format. - It's up to the client to check for read data ended. The server doesn't - care. + care; and also server doesn't notify to the client that it got the + data or not; if there is any error; then during execute; the error + will be returned ***********************************************************************/ @@ -238,9 +253,9 @@ static void setup_param_str(Item_param *param, uchar **pos) *pos+=len; } -static void setup_param_functions(Item_param *param, uchar read_pos) +static void setup_param_functions(Item_param *param, uchar param_type) { - switch (read_pos) { + switch (param_type) { case FIELD_TYPE_TINY: param->setup_param_func= setup_param_tiny; param->item_result_type = INT_RESULT; @@ -286,7 +301,6 @@ static bool setup_params_data(PREP_STMT *stmt) uchar *pos=(uchar*) thd->net.read_pos+1+MYSQL_STMT_HEADER; //skip header uchar *read_pos= pos+(stmt->param_count+7) / 8; //skip null bits - ulong param_no; if (*read_pos++) //types supplied / first execute { @@ -304,7 +318,7 @@ static bool setup_params_data(PREP_STMT *stmt) } param_iterator.rewind(); } - param_no= 0; + ulong param_no= 0; while ((param= (Item_param *)param_iterator++)) { if (!param->long_data_supplied) @@ -319,7 +333,6 @@ static bool setup_params_data(PREP_STMT *stmt) DBUG_RETURN(0); } - /* Validates insert fields */ @@ -473,7 +486,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, List all_fields(fields); DBUG_ENTER("mysql_test_select_fields"); - if (!(table = open_ltable(thd,tables,tables->lock_type))) + if (!(table = open_ltable(thd,tables,TL_READ))) DBUG_RETURN(1); thd->used_tables=0; // Updated by setup_fields @@ -627,8 +640,8 @@ static bool init_param_items(THD *thd, PREP_STMT *stmt) { DBUG_PRINT("info",("param: %lx", to)); } - return 0; #endif + return 0; } /* @@ -671,7 +684,6 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length) stmt.mem_root= thd->mem_root; tree_insert(&thd->prepared_statements, (void *)&stmt, 0, (void *)0); thd->mem_root= thd_root; // restore main mem_root - thd->last_prepared_stmt= &stmt; DBUG_RETURN(0); err: @@ -722,7 +734,6 @@ void mysql_stmt_execute(THD *thd, char *packet) have re-check on setup_* and other things .. */ mysql_execute_command(stmt->thd); - thd->last_prepared_stmt= stmt; if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), WAIT_PRIOR); @@ -775,11 +786,11 @@ void mysql_stmt_reset(THD *thd, char *packet) Delete a prepared statement from memory */ -void mysql_stmt_close(THD *thd, char *packet) +void mysql_stmt_free(THD *thd, char *packet) { ulong stmt_id= uint4korr(packet); PREP_STMT *stmt; - DBUG_ENTER("mysql_stmt_close"); + DBUG_ENTER("mysql_stmt_free"); if (!(stmt=find_prepared_statement(thd, stmt_id, "close"))) { From 8ff65ac252d44d883b00c240a5bccd2dedfa609b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Nov 2002 12:31:32 +0200 Subject: [PATCH 53/89] after merging fix --- mysql-test/r/subselect.result | 76 ++++++++++++++++------------------- mysql-test/t/subselect.test | 36 +++++++---------- sql/sql_select.cc | 1 + sql/sql_yacc.yy | 12 ++++-- 4 files changed, 57 insertions(+), 68 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 1b428954030..f91cacd2f6d 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -285,46 +285,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 index NULL topic 3 NULL 2 Using index 2 SUBSELECT No tables used 3 UNION No tables used -SELECT 1 IN (SELECT 1 FROM t1 HAVING a); -Unknown column 'a' in 'having clause' -SELECT * from t1 where topic IN (SELECT topic FROM t1 GROUP BY date); -topic date pseudo -40143 2002-08-03 joce -43506 2002-10-02 joce -SELECT * from t1 where topic IN (SELECT topic FROM t1 GROUP BY date HAVING topic < 4100); -topic date pseudo -43506 2002-10-02 joce -SELECT * from t1 where topic IN (SELECT SUM(topic) FROM t1); -topic date pseudo -SELECT * from t1 where topic = any (SELECT topic FROM st1 GROUP BY date); -topic date pseudo -40143 2002-08-03 joce -43506 2002-10-02 joce -SELECT * from t1 where topic = any (SELECT topic FROM t1 GROUP BY date HAVING topic < 4100); -topic date pseudo -43506 2002-10-02 joce -SELECT * from t1 where topic = any (SELECT SUM(topic) FROM t1); -topic date pseudo -SELECT * from t1 where topic = all (SELECT topic FROM t1 GROUP BY date); -topic date pseudo -SELECT * from t1 where topic = all (SELECT topic FROM t1 GROUP BY date HAVING topic < 4100); -topic date pseudo -40143 2002-08-03 joce -SELECT * from t1 where topic = all (SELECT SUM(topic) FROM t1); -topic date pseudo -SELECT * from t1 where topic <> any (SELECT SUM(topic) FROM t1); -topic date pseudo -40143 2002-08-03 joce -43506 2002-10-02 joce -CREATE TABLE `t2` ( -`numeropost` mediumint(8) unsigned NOT NULL auto_increment, -`maxnumrep` int(10) unsigned NOT NULL default '0', -PRIMARY KEY (`numeropost`), -UNIQUE KEY `maxnumrep` (`maxnumrep`)) TYPE=MyISAM ROW_FORMAT=FIXED; -INSERT INTO t1 (numeropost,maxnumrep) VALUES (40143,1),(43506,2); -SELECT SQL_CALC_FOUND_ROWS numeropost,maxnumrep FROM t2 WHERE numeropost IN (SELECT topic FROM t1 WHERE pseudo='joce' AND date >= '2002-10-06') ORDER BY maxnumrep DESC LIMIT 0,20; -numeropost maxnumrep -drop table t1,t2; +drop table t1; CREATE TABLE `t1` ( `numeropost` mediumint(8) unsigned NOT NULL auto_increment, `maxnumrep` int(10) unsigned NOT NULL default '0', @@ -349,8 +310,39 @@ numeropost maxnumrep 40143 1 SELECT (SELECT 1) as a FROM (SELECT 1 FROM t1 HAVING a=1); Unknown column 'a' in 'having clause' -drop table t1, t2; -drop table if exists t1; +SELECT 1 IN (SELECT 1 FROM t2 HAVING a); +Unknown column 'a' in 'having clause' +SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY date); +mot topic date pseudo +joce 40143 2002-10-22 joce +joce 43506 2002-10-22 joce +SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100); +mot topic date pseudo +joce 43506 2002-10-22 joce +SELECT * from t2 where topic IN (SELECT SUM(topic) FROM t1); +mot topic date pseudo +SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date); +mot topic date pseudo +joce 40143 2002-10-22 joce +joce 43506 2002-10-22 joce +SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100); +mot topic date pseudo +joce 43506 2002-10-22 joce +SELECT * from t2 where topic = any (SELECT SUM(topic) FROM t1); +mot topic date pseudo +SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date); +mot topic date pseudo +joce 40143 2002-10-22 joce +SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100); +mot topic date pseudo +joce 40143 2002-10-22 joce +SELECT * from t2 where topic = all (SELECT SUM(topic) FROM t2); +mot topic date pseudo +SELECT * from t2 where topic <> any (SELECT SUM(topic) FROM t2); +mot topic date pseudo +joce 40143 2002-10-22 joce +joce 43506 2002-10-22 joce +drop table t1,t2; CREATE TABLE `t1` ( `numeropost` mediumint(8) unsigned NOT NULL auto_increment, `maxnumrep` int(10) unsigned NOT NULL default '0', diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index eeac0bbb81e..3888584900d 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -171,10 +171,21 @@ select numeropost as a FROM t1 GROUP BY (SELECT 1 FROM t1 HAVING a=1); SELECT numeropost,maxnumrep FROM t1 WHERE exists (SELECT 1 FROM t2 WHERE (mot='joce') AND date >= '2002-10-21' AND t1.numeropost = t2.topic) ORDER BY maxnumrep DESC LIMIT 0, 20; -- error 1054 SELECT (SELECT 1) as a FROM (SELECT 1 FROM t1 HAVING a=1); -drop table t1, t2; +-- error 1054 +SELECT 1 IN (SELECT 1 FROM t2 HAVING a); +SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY date); +SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100); +SELECT * from t2 where topic IN (SELECT SUM(topic) FROM t1); +SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date); +SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100); +SELECT * from t2 where topic = any (SELECT SUM(topic) FROM t1); +SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date); +SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100); +SELECT * from t2 where topic = all (SELECT SUM(topic) FROM t2); +SELECT * from t2 where topic <> any (SELECT SUM(topic) FROM t2); +drop table t1,t2; #forumconthardwarefr7 -drop table if exists t1; CREATE TABLE `t1` ( `numeropost` mediumint(8) unsigned NOT NULL auto_increment, `maxnumrep` int(10) unsigned NOT NULL default '0', @@ -215,26 +226,7 @@ INSERT INTO t1 (numeropost,numreponse,pseudo) VALUES (1,1,'joce'),(1,2,'joce'),( EXPLAIN SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT 1 FROM t1 WHERE numeropost='1'); EXPLAIN SELECT MAX(numreponse) FROM t1 WHERE numeropost='1'; EXPLAIN SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT MAX(numreponse) FROM t1 WHERE numeropost='1'); -SELECT 1 IN (SELECT 1 FROM t1 HAVING a); -SELECT * from t1 where topic IN (SELECT topic FROM t1 GROUP BY date); -SELECT * from t1 where topic IN (SELECT topic FROM t1 GROUP BY date HAVING topic < 4100); -SELECT * from t1 where topic IN (SELECT SUM(topic) FROM t1); -SELECT * from t1 where topic = any (SELECT topic FROM t1 GROUP BY date); -SELECT * from t1 where topic = any (SELECT topic FROM t1 GROUP BY date HAVING topic < 4100); -SELECT * from t1 where topic = any (SELECT SUM(topic) FROM t1); -SELECT * from t1 where topic = all (SELECT topic FROM t1 GROUP BY date); -SELECT * from t1 where topic = all (SELECT topic FROM t1 GROUP BY date HAVING topic < 4100); -SELECT * from t1 where topic = all (SELECT SUM(topic) FROM t1); -SELECT * from t1 where topic <> any (SELECT SUM(topic) FROM t1); -CREATE TABLE `t2` ( - `numeropost` mediumint(8) unsigned NOT NULL auto_increment, - `maxnumrep` int(10) unsigned NOT NULL default '0', - PRIMARY KEY (`numeropost`), - UNIQUE KEY `maxnumrep` (`maxnumrep`)) TYPE=MyISAM ROW_FORMAT=FIXED; - -INSERT INTO t2 (numeropost,maxnumrep) VALUES (40143,1),(43506,2); -SELECT SQL_CALC_FOUND_ROWS numeropost,maxnumrep FROM t2 WHERE numeropost IN (SELECT topic FROM t1 WHERE pseudo='joce' AND date >= '2002-10-06') ORDER BY maxnumrep DESC LIMIT 0,20; -drop table t1,t2; +drop table t1; CREATE TABLE t1 (a int(1)); INSERT INTO t1 VALUES (1); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 501d54958f1..8f406efc030 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2988,6 +2988,7 @@ join_free(JOIN *join) else { for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++) + { delete tab->select; delete tab->quick; x_free(tab->cache.buff); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index af5d6690133..cbe72313b93 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -654,7 +654,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); table_to_table_list table_to_table opt_table_list opt_as handler_rkey_function handler_read_or_scan single_multi table_wild_list table_wild_one opt_wild - union union_option + union union_list union_option precision opt_on_delete_item subselect_start opt_and subselect_end select_var_list select_var_list_init help opt_len END_OF_INPUT @@ -1254,8 +1254,8 @@ opt_binary: opt_primary: /* empty */ - | PRIMARY_SYM - + | PRIMARY_SYM; + references: REFERENCES table_ident { @@ -4316,7 +4316,11 @@ rollback: union: /* empty */ {} - |UNION_SYM union_option + | union_list + ; + +union_list: + UNION_SYM union_option { LEX *lex=Lex; if (lex->exchange) From 4b021e6ea99ac80745875118ccbde5621588890b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Nov 2002 15:47:39 +0400 Subject: [PATCH 54/89] Preparing to use better string-to-number functions to avoid c_ptr() call, wich is slower and is not ucs2 compatible --- include/m_ctype.h | 30 ++--- mysys/charset.c | 9 +- sql/gstream.cc | 2 +- strings/ctype-big5.c | 10 +- strings/ctype-bin.c | 10 +- strings/ctype-czech.c | 10 +- strings/ctype-euc_kr.c | 10 +- strings/ctype-gb2312.c | 10 +- strings/ctype-gbk.c | 10 +- strings/ctype-latin1_de.c | 10 +- strings/ctype-simple.c | 30 ++--- strings/ctype-sjis.c | 10 +- strings/ctype-tis620.c | 10 +- strings/ctype-ujis.c | 10 +- strings/ctype-utf8.c | 50 ++++----- strings/ctype-win1250ch.c | 10 +- strings/ctype.c | 230 +++++++++++++++++++------------------- 17 files changed, 231 insertions(+), 230 deletions(-) diff --git a/include/m_ctype.h b/include/m_ctype.h index b16db5cde97..deba69700a2 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -125,11 +125,11 @@ typedef struct charset_info_st /* Charset dependant snprintf() */ int (*snprintf)(struct charset_info_st *, char *to, uint n, const char *fmt, ...); - long (*strtol)(struct charset_info_st *, const char *s, char **e, int base); - ulong (*strtoul)(struct charset_info_st *, const char *s, char **e, int base); - longlong (*strtoll)(struct charset_info_st *, const char *s, char **e, int base); - ulonglong (*strtoull)(struct charset_info_st *, const char *s, char **e, int base); - double (*strtod)(struct charset_info_st *, const char *s, char **e); + long (*strntol)(struct charset_info_st *, const char *s, uint l,char **e, int base); + ulong (*strntoul)(struct charset_info_st *, const char *s, uint l, char **e, int base); + longlong (*strntoll)(struct charset_info_st *, const char *s, uint l, char **e, int base); + ulonglong (*strntoull)(struct charset_info_st *, const char *s, uint l, char **e, int base); + double (*strntod)(struct charset_info_st *, const char *s, uint l, char **e); } CHARSET_INFO; @@ -169,11 +169,11 @@ int my_wc_mb_8bit(CHARSET_INFO *cs,my_wc_t wc, uchar *s, uchar *e); int my_snprintf_8bit(struct charset_info_st *, char *to, uint n, const char *fmt, ...); -long my_strtol_8bit(CHARSET_INFO *, const char *s, char **e, int base); -ulong my_strtoul_8bit(CHARSET_INFO *, const char *s, char **e, int base); -longlong my_strtoll_8bit(CHARSET_INFO *, const char *s, char **e, int base); -ulonglong my_strtoull_8bit(CHARSET_INFO *, const char *s, char **e, int base); -double my_strtod_8bit(CHARSET_INFO *, const char *s, char **e); +long my_strntol_8bit(CHARSET_INFO *, const char *s, uint l,char **e, int base); +ulong my_strntoul_8bit(CHARSET_INFO *, const char *s, uint l,char **e, int base); +longlong my_strntoll_8bit(CHARSET_INFO *, const char *s, uint l,char **e, int base); +ulonglong my_strntoull_8bit(CHARSET_INFO *, const char *s, uint l,char **e, int base); +double my_strntod_8bit(CHARSET_INFO *, const char *s, uint l,char **e); my_bool my_like_range_simple(CHARSET_INFO *cs, const char *ptr, uint ptr_length, @@ -257,11 +257,11 @@ int my_wildcmp_mb(CHARSET_INFO *, #define my_strcasecmp(s, a, b) ((s)->strcasecmp((s), (a), (b))) #define my_strncasecmp(s, a, b, l) ((s)->strncasecmp((s), (a), (b), (l))) -#define my_strtol(s, a, b, c) ((s)->strtol((s),(a),(b),(c))) -#define my_strtoul(s, a, b, c) ((s)->strtoul((s),(a),(b),(c))) -#define my_strtoll(s, a, b, c) ((s)->strtoll((s),(a),(b),(c))) -#define my_strtoull(s, a, b, c) ((s)->strtoull((s),(a),(b),(c))) -#define my_strtod(s, a, b) ((s)->strtod((s),(a),(b))) +#define my_strtol(s, a, b, c, d) ((s)->strtol((s),(a),(b),(c),(d))) +#define my_strtoul(s, a, b, c, d) ((s)->strtoul((s),(a),(b),(c),(d))) +#define my_strtoll(s, a, b, c, d) ((s)->strtoll((s),(a),(b),(c),(d))) +#define my_strtoull(s, a, b, c,d) ((s)->strtoull((s),(a),(b),(c),(d))) +#define my_strtod(s, a, b, c ) ((s)->strtod((s),(a),(b),(c))) /* XXX: still need to take care of this one */ diff --git a/mysys/charset.c b/mysys/charset.c index 91bae04046b..cf0628495fc 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -391,10 +391,11 @@ static CHARSET_INFO *add_charset(CHARSET_INFO *cs, myf flags) cs->hash_caseup = my_hash_caseup_simple; cs->hash_sort = my_hash_sort_simple; cs->snprintf = my_snprintf_8bit; - cs->strtol = my_strtol_8bit; - cs->strtoul = my_strtoul_8bit; - cs->strtoll = my_strtoll_8bit; - cs->strtoull = my_strtoull_8bit; + cs->strntol = my_strntol_8bit; + cs->strntoul = my_strntoul_8bit; + cs->strntoll = my_strntoll_8bit; + cs->strntoull = my_strntoull_8bit; + cs->strntod = my_strntod_8bit; cs->mbmaxlen = 1; set_max_sort_char(cs); diff --git a/sql/gstream.cc b/sql/gstream.cc index bd2345212c3..5a58fef6744 100644 --- a/sql/gstream.cc +++ b/sql/gstream.cc @@ -99,7 +99,7 @@ int GTextReadStream::get_next_number(double *d) char *endptr; - *d = my_strtod(my_charset_latin1, cur, &endptr); + *d = strtod(cur, &endptr); if(endptr) { diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index 39ddee854ff..b41ed82aeae 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -6249,11 +6249,11 @@ CHARSET_INFO my_charset_big5 = my_hash_sort_simple, 0, my_snprintf_8bit, - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }; diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index 2573ec89660..29784acab16 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -270,11 +270,11 @@ static CHARSET_INFO my_charset_bin_st = my_hash_sort_bin, /* hash_sort */ 255, /* max_sort_char */ my_snprintf_8bit, /* snprintf */ - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }; diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c index ea3cc702abd..837545ce70f 100644 --- a/strings/ctype-czech.c +++ b/strings/ctype-czech.c @@ -627,11 +627,11 @@ CHARSET_INFO my_charset_czech = my_hash_sort_simple, 0, my_snprintf_8bit, - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }; #endif diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c index 8a614851fe3..57d237364f6 100644 --- a/strings/ctype-euc_kr.c +++ b/strings/ctype-euc_kr.c @@ -8667,11 +8667,11 @@ CHARSET_INFO my_charset_euc_kr = my_hash_sort_simple, 0, my_snprintf_8bit, - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }; #endif diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c index 7a8e9f011a0..205b7c2a1da 100644 --- a/strings/ctype-gb2312.c +++ b/strings/ctype-gb2312.c @@ -5717,11 +5717,11 @@ CHARSET_INFO my_charset_gb2312 = my_hash_sort_simple, 0, my_snprintf_8bit, - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }; #endif diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c index 504039a4e59..aec38e8dfa8 100644 --- a/strings/ctype-gbk.c +++ b/strings/ctype-gbk.c @@ -9904,11 +9904,11 @@ CHARSET_INFO my_charset_gbk = my_hash_sort_simple, 0, my_snprintf_8bit, - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }; diff --git a/strings/ctype-latin1_de.c b/strings/ctype-latin1_de.c index 13a35e3c82e..696fa0f6192 100644 --- a/strings/ctype-latin1_de.c +++ b/strings/ctype-latin1_de.c @@ -445,11 +445,11 @@ CHARSET_INFO my_charset_latin1_de = my_hash_sort_simple, 0, my_snprintf_8bit, - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }; #endif diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index f9a9caad206..6ae305bbf7d 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -244,34 +244,34 @@ void my_hash_sort_simple(CHARSET_INFO *cs, } } -long my_strtol_8bit(CHARSET_INFO *cs __attribute__((unused)), - const char *s, char **e, int base) +long my_strntol_8bit(CHARSET_INFO *cs __attribute__((unused)), + const char *s, uint l, char **e, int base) { - return strtol(s,e,base); + return 0; } -ulong my_strtoul_8bit(CHARSET_INFO *cs __attribute__((unused)), - const char *s, char **e, int base) +ulong my_strntoul_8bit(CHARSET_INFO *cs __attribute__((unused)), + const char *s, uint l, char **e, int base) { - return strtoul(s,e,base); + return 0; } -longlong my_strtoll_8bit(CHARSET_INFO *cs __attribute__((unused)), - const char *s, char **e, int base) +longlong my_strntoll_8bit(CHARSET_INFO *cs __attribute__((unused)), + const char *s, uint l, char **e, int base) { - return strtoll(s,e,base); + return 0; } -ulonglong my_strtoull_8bit(CHARSET_INFO *cs __attribute__((unused)), - const char *s, char **e, int base) +ulonglong my_strntoull_8bit(CHARSET_INFO *cs __attribute__((unused)), + const char *s, uint l, char **e, int base) { - return strtoul(s,e,base); + return 0; } -double my_strtod_8bit(CHARSET_INFO *cs __attribute__((unused)), - const char *s, char **e) +double my_strntod_8bit(CHARSET_INFO *cs __attribute__((unused)), + const char *s, uint l, char **e) { - return strtod(s,e); + return 0; } diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index 91a9fae55fa..1ccf0b1d8f2 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -4491,11 +4491,11 @@ CHARSET_INFO my_charset_sjis = my_hash_sort_simple, 0, my_snprintf_8bit, - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }; #endif diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c index 86056e4f55c..3852589659b 100644 --- a/strings/ctype-tis620.c +++ b/strings/ctype-tis620.c @@ -719,11 +719,11 @@ CHARSET_INFO my_charset_tis620 = my_hash_sort_simple, 0, my_snprintf_8bit, - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }; diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index 7ae229c0135..0f4d8f5dfe2 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -8461,11 +8461,11 @@ CHARSET_INFO my_charset_ujis = my_hash_sort_simple, 0, my_snprintf_8bit, - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }; diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index b471a37a852..e55a6a717e5 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -1986,11 +1986,11 @@ CHARSET_INFO my_charset_utf8 = my_hash_sort_utf8, /* hash_sort */ 0, my_snprintf_8bit, - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }; @@ -2439,34 +2439,34 @@ static int my_snprintf_ucs2(CHARSET_INFO *cs __attribute__((unused)) } -static long my_strtol_ucs2(CHARSET_INFO *cs __attribute__((unused)), - const char *s, char **e, int base) +static long my_strntol_ucs2(CHARSET_INFO *cs __attribute__((unused)), + const char *s, uint l, char **e, int base) { - return strtol(s,e,base); + return 0; } -static ulong my_strtoul_ucs2(CHARSET_INFO *cs __attribute__((unused)), - const char *s, char **e, int base) +static ulong my_strntoul_ucs2(CHARSET_INFO *cs __attribute__((unused)), + const char *s, uint l, char **e, int base) { - return strtoul(s,e,base); + return 0; } -static longlong my_strtoll_ucs2(CHARSET_INFO *cs __attribute__((unused)), - const char *s, char **e, int base) +static longlong my_strntoll_ucs2(CHARSET_INFO *cs __attribute__((unused)), + const char *s, uint l, char **e, int base) { - return strtoll(s,e,base); + return 0; } -static ulonglong my_strtoull_ucs2(CHARSET_INFO *cs __attribute__((unused)), - const char *s, char **e, int base) +static ulonglong my_strntoull_ucs2(CHARSET_INFO *cs __attribute__((unused)), + const char *s, uint l, char **e, int base) { - return strtoul(s,e,base); + return 0; } -double my_strtod_ucs2(CHARSET_INFO *cs __attribute__((unused)), - const char *s, char **e) +double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)), + const char *s, uint l, char **e) { - return strtod(s,e); + return 0; } @@ -2504,11 +2504,11 @@ CHARSET_INFO my_charset_ucs2 = my_hash_sort_ucs2, /* hash_sort */ 0, my_snprintf_ucs2, - my_strtol_ucs2, - my_strtoul_ucs2, - my_strtoll_ucs2, - my_strtoull_ucs2, - my_strtod_ucs2 + my_strntol_ucs2, + my_strntoul_ucs2, + my_strntoll_ucs2, + my_strntoull_ucs2, + my_strntod_ucs2 }; diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c index 73e4a5745af..ae7ab6067f8 100644 --- a/strings/ctype-win1250ch.c +++ b/strings/ctype-win1250ch.c @@ -653,11 +653,11 @@ CHARSET_INFO my_charset_win1250ch = my_hash_sort_simple, 0, my_snprintf_8bit, - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }; diff --git a/strings/ctype.c b/strings/ctype.c index 7ce259bc00f..43a9be3ab4b 100644 --- a/strings/ctype.c +++ b/strings/ctype.c @@ -2841,11 +2841,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit, - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -2884,11 +2884,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -2926,11 +2926,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -2968,11 +2968,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -3011,11 +3011,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -3053,11 +3053,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -3095,11 +3095,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -3137,11 +3137,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -3180,11 +3180,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -3222,11 +3222,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -3264,11 +3264,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -3306,11 +3306,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -3348,11 +3348,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -3390,11 +3390,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -3432,11 +3432,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -3475,11 +3475,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -3517,11 +3517,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -3560,11 +3560,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -3603,11 +3603,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -3645,11 +3645,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -3687,11 +3687,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -3729,11 +3729,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif @@ -3771,11 +3771,11 @@ static CHARSET_INFO compiled_charsets[] = { my_hash_sort_simple, 0, my_snprintf_8bit - my_strtol_8bit, - my_strtoul_8bit, - my_strtoll_8bit, - my_strtoull_8bit, - my_strtod_8bit + my_strntol_8bit, + my_strntoul_8bit, + my_strntoll_8bit, + my_strntoull_8bit, + my_strntod_8bit }, #endif From d3969da2f97e384942e49e6842d4c94a85e01ee7 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Nov 2002 16:14:55 +0400 Subject: [PATCH 55/89] correction for compiling under FreeBSD --- readline/terminal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readline/terminal.c b/readline/terminal.c index 9ca4d6e43c5..397b10a1d46 100644 --- a/readline/terminal.c +++ b/readline/terminal.c @@ -84,8 +84,8 @@ static int tcap_initialized; # if defined (__EMX__) || defined (NEED_EXTERN_PC) extern # endif /* __EMX__ || NEED_EXTERN_PC */ -const char PC; -const char *BC, *UP; +char PC; +char *BC, *UP; #endif /* __linux__ */ /* Some strings to control terminal actions. These are output by tputs (). */ From 1ef8067465a0880419c63f44991371f1c75d08ce Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Nov 2002 15:52:32 +0200 Subject: [PATCH 56/89] after merging fix --- sql/sql_parse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 16ec6f9234c..eed47bbee28 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2101,7 +2101,7 @@ mysql_execute_command(THD *thd) /* Fix tables-to-be-deleted-from list to point at opened tables */ for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next) auxi->table= auxi->table_list->table; - fix_tables_pointers(&lex->select_lex); + fix_tables_pointers(lex->all_selects_list); if (!thd->fatal_error && (result= new multi_delete(thd,aux_tables, table_count))) { From 080b5c6057369fad865e92bed0e20c415f4406c9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Nov 2002 18:08:31 +0400 Subject: [PATCH 57/89] new string-to-number functions include/m_ctype.h: Typo fix sql/field.cc: Use new string-to-number functions strings/ctype-bin.c: Use new string-to-number functions strings/ctype-simple.c: Use new string-to-number functions strings/ctype-utf8.c: Use new string-to-number functions --- include/m_ctype.h | 10 +- sql/field.cc | 12 +- strings/ctype-bin.c | 22 +- strings/ctype-simple.c | 463 +++++++++++++++++++++++++++++++++++++++-- strings/ctype-utf8.c | 457 ++++++++++++++++++++++++++++++++++++++-- 5 files changed, 921 insertions(+), 43 deletions(-) diff --git a/include/m_ctype.h b/include/m_ctype.h index deba69700a2..4af23bb3ab5 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -257,11 +257,11 @@ int my_wildcmp_mb(CHARSET_INFO *, #define my_strcasecmp(s, a, b) ((s)->strcasecmp((s), (a), (b))) #define my_strncasecmp(s, a, b, l) ((s)->strncasecmp((s), (a), (b), (l))) -#define my_strtol(s, a, b, c, d) ((s)->strtol((s),(a),(b),(c),(d))) -#define my_strtoul(s, a, b, c, d) ((s)->strtoul((s),(a),(b),(c),(d))) -#define my_strtoll(s, a, b, c, d) ((s)->strtoll((s),(a),(b),(c),(d))) -#define my_strtoull(s, a, b, c,d) ((s)->strtoull((s),(a),(b),(c),(d))) -#define my_strtod(s, a, b, c ) ((s)->strtod((s),(a),(b),(c))) +#define my_strntol(s, a, b, c, d) ((s)->strntol((s),(a),(b),(c),(d))) +#define my_strntoul(s, a, b, c, d) ((s)->strntoul((s),(a),(b),(c),(d))) +#define my_strntoll(s, a, b, c, d) ((s)->strntoll((s),(a),(b),(c),(d))) +#define my_strntoull(s, a, b, c,d) ((s)->strntoull((s),(a),(b),(c),(d))) +#define my_strntod(s, a, b, c ) ((s)->strntod((s),(a),(b),(c))) /* XXX: still need to take care of this one */ diff --git a/sql/field.cc b/sql/field.cc index f2324a0a331..e0910caeea2 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -921,8 +921,7 @@ void Field_decimal::sql_type(String &res) const int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs) { - String tmp_str(from,len,default_charset_info); - long tmp= strtol(tmp_str.c_ptr(),NULL,10); + long tmp= my_strntol(cs,from,len,(char **)NULL,10); int error= 0; if (unsigned_flag) @@ -1116,8 +1115,7 @@ void Field_tiny::sql_type(String &res) const int Field_short::store(const char *from,uint len,CHARSET_INFO *cs) { - String tmp_str(from,len,default_charset_info); - long tmp= strtol(tmp_str.c_ptr(),NULL,10); + long tmp= my_strntol(cs,from,len,NULL,10); int error= 0; if (unsigned_flag) { @@ -1380,8 +1378,7 @@ void Field_short::sql_type(String &res) const int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs) { - String tmp_str(from,len,default_charset_info); - long tmp= strtol(tmp_str.c_ptr(),NULL,10); + long tmp= my_strntol(cs,from,len,NULL,10); int error= 0; if (unsigned_flag) @@ -3097,8 +3094,7 @@ void Field_time::sql_type(String &res) const int Field_year::store(const char *from, uint len,CHARSET_INFO *cs) { - String tmp_str(from,len,default_charset_info); - long nr= strtol(tmp_str.c_ptr(),NULL,10); + long nr= my_strntol(cs,from,len,NULL,10); if (nr < 0 || nr >= 100 && nr <= 1900 || nr > 2155) { diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index 29784acab16..7431ce82df5 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -22,6 +22,26 @@ #include "m_string.h" #include "m_ctype.h" +static uchar ctype_bin[] = { + 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16, + 16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16, + 16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2 +}; + static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)), const uchar *s, uint slen, @@ -242,7 +262,7 @@ static CHARSET_INFO my_charset_bin_st = MY_CS_COMPILED|MY_CS_BINSORT,/* state */ "binary", /* name */ "", /* comment */ - NULL, /* ctype */ + ctype_bin, /* ctype */ NULL, /* to_lower */ NULL, /* to_upper */ NULL, /* sort_order */ diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 6ae305bbf7d..be4fdc9cb8d 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -15,12 +15,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include -#include "my_sys.h" -#include "m_ctype.h" #include "m_string.h" +#include "m_ctype.h" +#include "my_sys.h" /* defines errno */ #include "stdarg.h" #include "assert.h" + int my_strnxfrm_simple(CHARSET_INFO * cs, uchar *dest, uint len, const uchar *src, uint srclen) @@ -244,34 +245,468 @@ void my_hash_sort_simple(CHARSET_INFO *cs, } } -long my_strntol_8bit(CHARSET_INFO *cs __attribute__((unused)), - const char *s, uint l, char **e, int base) + +#define MY_ERRNO(y) + +long my_strntol_8bit(CHARSET_INFO *cs, + const char *nptr, uint l, char **endptr, int base) { - return 0; + int negative; + register ulong cutoff; + register unsigned int cutlim; + register ulong i; + register const char *s; + register unsigned char c; + const char *save, *e; + int overflow; + + if (base < 0 || base == 1 || base > 36) + base = 10; + + s = nptr; + e = nptr+l; + + for ( ; s='0' && c<='9') + c -= '0'; + else if (c>='A' && c<='F') + c = c - 'A' + 10; + else if (c>='a' && c<='f') + c = c - 'a' + 10; + else + break; + if (c >= base) + break; + if (i > cutoff || (i == cutoff && c > cutlim)) + overflow = 1; + else + { + i *= (ulong) base; + i += c; + } + } + + if (s == save) + goto noconv; + + if (endptr != NULL) + *endptr = (char *) s; + + if (negative) + { + if (i > (ulong) LONG_MIN) + overflow = 1; + } + else if (i > (ulong) LONG_MAX) + overflow = 1; + + if (overflow) + { + MY_ERRNO(ERANGE); + return negative ? LONG_MIN : LONG_MAX; + } + + return (negative ? -((long) i) : (long) i); + +noconv: + MY_ERRNO(EDOM); + if (endptr != NULL) + *endptr = (char *) nptr; + return 0L; } -ulong my_strntoul_8bit(CHARSET_INFO *cs __attribute__((unused)), - const char *s, uint l, char **e, int base) + +ulong my_strntoul_8bit(CHARSET_INFO *cs, + const char *nptr, uint l, char **endptr, int base) { - return 0; + int negative; + register ulong cutoff; + register unsigned int cutlim; + register ulong i; + register const char *s; + register unsigned char c; + const char *save, *e; + int overflow; + + if (base < 0 || base == 1 || base > 36) + base = 10; + + s = nptr; + e = nptr+l; + + for( ; s='0' && c<='9') + c -= '0'; + else if (c>='A' && c<='F') + c = c - 'A' + 10; + else if (c>='a' && c<='a') + c = c - 'a' + 10; + else + break; + if (c >= base) + break; + if (i > cutoff || (i == cutoff && c > cutlim)) + overflow = 1; + else + { + i *= (ulong) base; + i += c; + } + } + + if (s == save) + goto noconv; + + if (endptr != NULL) + *endptr = (char *) s; + + if (overflow) + { + MY_ERRNO(ERANGE); + return ((ulong)~0L); + } + + return (negative ? -((long) i) : (long) i); + +noconv: + MY_ERRNO(EDOM); + if (endptr != NULL) + *endptr = (char *) nptr; + return 0L; } + longlong my_strntoll_8bit(CHARSET_INFO *cs __attribute__((unused)), - const char *s, uint l, char **e, int base) + const char *nptr, uint l, char **endptr, int base) { - return 0; + int negative; + register ulonglong cutoff; + register unsigned int cutlim; + register ulonglong i; + register const char *s, *e; + register unsigned char c; + const char *save; + int overflow; + + if (base < 0 || base == 1 || base > 36) + base = 10; + + s = nptr; + e = nptr+l; + + for(; s='0' && c<='9') + c -= '0'; + else if (c>='A' && c<='F') + c = c - 'A' + 10; + else if (c>='a' && c<='f') + c = c - 'a' + 10; + else + break; + if (c >= base) + break; + if (i > cutoff || (i == cutoff && c > cutlim)) + overflow = 1; + else + { + i *= (ulonglong) base; + i += c; + } + } + + if (s == save) + goto noconv; + + if (endptr != NULL) + *endptr = (char *) s; + + if (negative) + { + if (i > (ulonglong) LONGLONG_MIN) + overflow = 1; + } + else if (i > (ulonglong) LONGLONG_MAX) + overflow = 1; + + if (overflow) + { + MY_ERRNO(ERANGE); + return negative ? LONGLONG_MIN : LONGLONG_MAX; + } + + return (negative ? -((longlong) i) : (longlong) i); + +noconv: + MY_ERRNO(EDOM); + if (endptr != NULL) + *endptr = (char *) nptr; + return 0L; } -ulonglong my_strntoull_8bit(CHARSET_INFO *cs __attribute__((unused)), - const char *s, uint l, char **e, int base) + +ulonglong my_strntoull_8bit(CHARSET_INFO *cs, + const char *nptr, uint l, char **endptr, int base) { - return 0; + int negative; + register ulonglong cutoff; + register unsigned int cutlim; + register ulonglong i; + register const char *s, *e; + register unsigned char c; + const char *save; + int overflow; + + if (base < 0 || base == 1 || base > 36) + base = 10; + + s = nptr; + e = nptr+l; + + for(; s='0' && c<='9') + c -= '0'; + else if (c>='A' && c<='F') + c = c - 'A' + 10; + else if (c>='a' && c<='f') + c = c - 'a' + 10; + else + break; + if (c >= base) + break; + if (i > cutoff || (i == cutoff && c > cutlim)) + overflow = 1; + else + { + i *= (ulonglong) base; + i += c; + } + } + + if (s == save) + goto noconv; + + if (endptr != NULL) + *endptr = (char *) s; + + if (overflow) + { + MY_ERRNO(ERANGE); + return (~(ulonglong) 0); + } + + return (negative ? -((longlong) i) : (longlong) i); + +noconv: + MY_ERRNO(EDOM); + if (endptr != NULL) + *endptr = (char *) nptr; + return 0L; } double my_strntod_8bit(CHARSET_INFO *cs __attribute__((unused)), const char *s, uint l, char **e) { - return 0; + char buf[256]; + double res; + if((l+1)>sizeof(buf)) + { + if (e) + memcpy(*e,s,sizeof(s)); + return 0; + } + strncpy(buf,s,l); + buf[l]='\0'; + res=strtod(buf,e); + if (e) + memcpy(*e,*e-buf+s,sizeof(s)); + return res; } diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index e55a6a717e5..8adeed7144a 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -19,7 +19,10 @@ /* Written by Alexander Barkov */ #include -#include +#include "m_string.h" +#include "m_ctype.h" +#include "my_sys.h" /* defines errno */ + #ifdef HAVE_CHARSET_utf8 #define HAVE_UNIDATA @@ -2438,35 +2441,459 @@ static int my_snprintf_ucs2(CHARSET_INFO *cs __attribute__((unused)) return my_vsnprintf_ucs2(to, n, fmt, args); } +#define MY_ERRNO(x) -static long my_strntol_ucs2(CHARSET_INFO *cs __attribute__((unused)), - const char *s, uint l, char **e, int base) +long my_strntol_ucs2(CHARSET_INFO *cs, + const char *nptr, uint l, char **endptr, int base) { - return 0; + int negative; + register ulong cutoff; + register unsigned int cutlim; + register ulong i; + register const char *s; + register unsigned char c; + const char *save, *e; + int overflow; + + if (base < 0 || base == 1 || base > 36) + base = 10; + + s = nptr; + e = nptr+l; + + for ( ; s= base) + break; + if (i > cutoff || (i == cutoff && c > cutlim)) + overflow = 1; + else + { + i *= (ulong) base; + i += c; + } + } + + if (s == save) + goto noconv; + + if (endptr != NULL) + *endptr = (char *) s; + + if (negative) + { + if (i > (ulong) LONG_MIN) + overflow = 1; + } + else if (i > (ulong) LONG_MAX) + overflow = 1; + + if (overflow) + { + MY_ERRNO(ERANGE); + return negative ? LONG_MIN : LONG_MAX; + } + + return (negative ? -((long) i) : (long) i); + +noconv: + MY_ERRNO(EDOM); + if (endptr != NULL) + *endptr = (char *) nptr; + return 0L; } -static ulong my_strntoul_ucs2(CHARSET_INFO *cs __attribute__((unused)), - const char *s, uint l, char **e, int base) + +ulong my_strntoul_ucs2(CHARSET_INFO *cs, + const char *nptr, uint l, char **endptr, int base) { - return 0; + int negative; + register ulong cutoff; + register unsigned int cutlim; + register ulong i; + register const char *s; + register unsigned char c; + const char *save, *e; + int overflow; + + if (base < 0 || base == 1 || base > 36) + base = 10; + + s = nptr; + e = nptr+l; + + for( ; s= base) + break; + if (i > cutoff || (i == cutoff && c > cutlim)) + overflow = 1; + else + { + i *= (ulong) base; + i += c; + } + } + + if (s == save) + goto noconv; + + if (endptr != NULL) + *endptr = (char *) s; + + if (overflow) + { + MY_ERRNO(ERANGE); + return ((ulong)~0L); + } + + return (negative ? -((long) i) : (long) i); + +noconv: + MY_ERRNO(EDOM); + if (endptr != NULL) + *endptr = (char *) nptr; + return 0L; } -static longlong my_strntoll_ucs2(CHARSET_INFO *cs __attribute__((unused)), - const char *s, uint l, char **e, int base) + +longlong my_strntoll_ucs2(CHARSET_INFO *cs __attribute__((unused)), + const char *nptr, uint l, char **endptr, int base) { - return 0; + int negative; + register ulonglong cutoff; + register unsigned int cutlim; + register ulonglong i; + register const char *s, *e; + register unsigned char c; + const char *save; + int overflow; + + if (base < 0 || base == 1 || base > 36) + base = 10; + + s = nptr; + e = nptr+l; + + for(; s= base) + break; + if (i > cutoff || (i == cutoff && c > cutlim)) + overflow = 1; + else + { + i *= (ulonglong) base; + i += c; + } + } + + if (s == save) + goto noconv; + + if (endptr != NULL) + *endptr = (char *) s; + + if (negative) + { + if (i > (ulonglong) LONGLONG_MIN) + overflow = 1; + } + else if (i > (ulonglong) LONGLONG_MAX) + overflow = 1; + + if (overflow) + { + MY_ERRNO(ERANGE); + return negative ? LONGLONG_MIN : LONGLONG_MAX; + } + + return (negative ? -((longlong) i) : (longlong) i); + +noconv: + MY_ERRNO(EDOM); + if (endptr != NULL) + *endptr = (char *) nptr; + return 0L; } -static ulonglong my_strntoull_ucs2(CHARSET_INFO *cs __attribute__((unused)), - const char *s, uint l, char **e, int base) + +ulonglong my_strntoull_ucs2(CHARSET_INFO *cs, + const char *nptr, uint l, char **endptr, int base) { - return 0; + int negative; + register ulonglong cutoff; + register unsigned int cutlim; + register ulonglong i; + register const char *s, *e; + register unsigned char c; + const char *save; + int overflow; + + if (base < 0 || base == 1 || base > 36) + base = 10; + + s = nptr; + e = nptr+l; + + for(; s= base) + break; + if (i > cutoff || (i == cutoff && c > cutlim)) + overflow = 1; + else + { + i *= (ulonglong) base; + i += c; + } + } + + if (s == save) + goto noconv; + + if (endptr != NULL) + *endptr = (char *) s; + + if (overflow) + { + MY_ERRNO(ERANGE); + return (~(ulonglong) 0); + } + + return (negative ? -((longlong) i) : (longlong) i); + +noconv: + MY_ERRNO(EDOM); + if (endptr != NULL) + *endptr = (char *) nptr; + return 0L; } -double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)), +double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)), const char *s, uint l, char **e) { - return 0; + char buf[256]; + double res; + if((l+1)>sizeof(buf)) + { + if (e) + memcpy(*e,s,sizeof(s)); + return 0; + } + strncpy(buf,s,l); + buf[l]='\0'; + res=strtod(buf,e); + if (e) + memcpy(*e,*e-buf+s,sizeof(s)); + return res; } From 943522556d5230966ab3345d15e44aa057877777 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Nov 2002 17:04:43 +0200 Subject: [PATCH 58/89] after review changes in IN/ALL/ANY/SOME (SCRUM) sql/item.cc: after review changes sql/item.h: after review changes sql/item_subselect.cc: after review changes sql/mysql_priv.h: after review changes sql/sql_base.cc: after review changes --- sql/item.cc | 52 ++++++++++++++++++++++++++++++------------- sql/item.h | 8 +++---- sql/item_subselect.cc | 6 ++--- sql/mysql_priv.h | 2 ++ sql/sql_base.cc | 23 +++++++++++++++++++ 5 files changed, 69 insertions(+), 22 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index f9e92dfedb2..03ca7ea48b9 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -457,30 +457,52 @@ bool Item_asterisk_remover::fix_fields(THD *thd, { DBUG_ENTER("Item_asterisk_remover::fix_fields"); - bool res; + bool res= 1; if (item) if (item->type() == Item::FIELD_ITEM && ((Item_field*) item)->field_name[0] == '*') { - List fields; - fields.push_back(item); - List_iterator it(fields); - it++; - uint elem=fields.elements; - if (insert_fields(thd, list, ((Item_field*) item)->db_name, - ((Item_field*) item)->table_name, &it)) - res= -1; - else - if (fields.elements > 1) + Item_field *fitem= (Item_field*) item; + if (!list->next || fitem->db_name || fitem->table_name) + { + TABLE_LIST *table= find_table_in_list(thd, list, + fitem->db_name, + fitem->table_name); + if (table) { - my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0)); - res= -1; + TABLE * tb= table->table; + if (find_table_in_list(thd, table->next, fitem->db_name, + fitem->table_name) != 0 || + tb->fields == 1) + { + if ((item= new Item_field(tb->field[0]))) + { + res= 0; + tb->field[0]->query_id= thd->query_id; + tb->used_keys&= tb->field[0]->part_of_key; + tb->used_fields= tb->fields; + } + else + thd->fatal_error= 1; // can't create Item => out of memory + } + else + my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), + MYF(0)); } - } + else + if (!fitem->table_name) + my_error(ER_NO_TABLES_USED, MYF(0)); + else + my_error(ER_BAD_TABLE_ERROR, MYF(0), fitem->table_name); + } + else + my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), + MYF(0)); + } else res= item->fix_fields(thd, list, &item); else - res= -1; + thd->fatal_error= 1; // no item given => out of memory *ref= item; DBUG_RETURN(res); } diff --git a/sql/item.h b/sql/item.h index 4dde90d0beb..414dcfbc328 100644 --- a/sql/item.h +++ b/sql/item.h @@ -124,9 +124,9 @@ public: class Item_outer_select_context_saver :public Item_wrapper { public: - Item_outer_select_context_saver(Item *i) + Item_outer_select_context_saver(Item *it) { - item= i; + item= it; } bool fix_fields(THD *, struct st_table_list *, Item ** ref); }; @@ -137,9 +137,9 @@ public: class Item_asterisk_remover :public Item_wrapper { public: - Item_asterisk_remover(Item *i) + Item_asterisk_remover(Item *it) { - item= i; + item= it; } bool fix_fields(THD *, struct st_table_list *, Item ** ref); }; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 750fca5a4f8..555b7ae45c3 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -280,13 +280,13 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, compare_func_creator func) { DBUG_ENTER("Item_in_subselect::single_value_transformer"); - for(SELECT_LEX * sl= select_lex; sl; sl= sl->next_select()) + for (SELECT_LEX * sl= select_lex; sl; sl= sl->next_select()) { Item *item; if (sl->item_list.elements > 1) { my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0)); - item= 0; // Item_asterisk_remover mast fail + item= 0; // Item_asterisk_remover must fail } else item= (Item*) sl->item_list.pop(); @@ -408,7 +408,7 @@ void subselect_union_engine::fix_length_and_dec() { uint32 mlen= 0, len; Item *sel_item= 0; - for(SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select()) + for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select()) { List_iterator_fast li(sl->item_list); Item *s_item= li++; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 0e3ae0a2af9..242f8601b23 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -578,6 +578,8 @@ bool close_thread_table(THD *thd, TABLE **table_ptr); void close_thread_tables(THD *thd,bool locked=0); bool close_thread_table(THD *thd, TABLE **table_ptr); void close_temporary_tables(THD *thd); +TABLE_LIST * find_table_in_list(TABLE_LIST *table, + const char *db_name, const char *table_name); TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name); bool close_temporary_table(THD *thd, const char *db, const char *table_name); void close_temporary(TABLE *table, bool delete_table=1); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 09b29c6b41d..8aa33a65ce3 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -743,6 +743,29 @@ void close_temporary_tables(THD *thd) thd->temporary_tables=0; } +/* + Find first suitable table in given list. + + SYNOPSIS + find_table_in_list() + table - pointer to table list + db_name - data base name or 0 for any + table_name - table name or 0 for any + + RETURN VALUES + NULL Table not found + # Pointer to found table. +*/ + +TABLE_LIST * find_table_in_list(TABLE_LIST *table, + const char *db_name, const char *table_name) +{ + for (; table; table= table->next) + if ((!db_name || !strcmp(table->db, db_name)) && + (!table_name || !strcmp(table->alias, table_name))) + break; + return table; +} TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name) { From 8c603386d25d31b3655e63a65b510079ca7fcce3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Nov 2002 19:32:47 +0400 Subject: [PATCH 59/89] support for HA_READ_BEFORE_KEY and HA_READ_PREFIX_LAST_OR_PREV --- sql/ha_berkeley.cc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index 679642ca949..8edb63b23d6 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -1416,10 +1416,21 @@ int ha_berkeley::index_read(byte * buf, const byte * key, DBT row; int error; KEY *key_info= &table->key_info[active_index]; + int do_prev= 0; DBUG_ENTER("ha_berkeley::index_read"); statistic_increment(ha_read_key_count,&LOCK_status); bzero((char*) &row,sizeof(row)); + if (find_flag == HA_READ_BEFORE_KEY) + { + find_flag= HA_READ_KEY_OR_NEXT; + do_prev= 1; + } + else if (find_flag == HA_READ_PREFIX_LAST_OR_PREV) + { + find_flag= HA_READ_AFTER_KEY; + do_prev= 1; + } if (key_len == key_info->key_length) { error=read_row(cursor->c_get(cursor, pack_key(&last_key, @@ -1453,6 +1464,12 @@ int ha_berkeley::index_read(byte * buf, const byte * key, error=HA_ERR_KEY_NOT_FOUND; } } + if (do_prev) + { + bzero((char*) &row, sizeof(row)); + error= read_row(cursor->c_get(cursor, &last_key, &row, DB_PREV), + (char*) buf, active_index, &row, &last_key, 1); + } DBUG_RETURN(error); } From a598cff2bc12cbaa1efc3a3efe0a6f5e6afbc836 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Nov 2002 17:42:15 +0200 Subject: [PATCH 60/89] typo fixed --- sql/item.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index 03ca7ea48b9..ece627f9fe3 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -465,13 +465,13 @@ bool Item_asterisk_remover::fix_fields(THD *thd, Item_field *fitem= (Item_field*) item; if (!list->next || fitem->db_name || fitem->table_name) { - TABLE_LIST *table= find_table_in_list(thd, list, + TABLE_LIST *table= find_table_in_list(list, fitem->db_name, fitem->table_name); if (table) { TABLE * tb= table->table; - if (find_table_in_list(thd, table->next, fitem->db_name, + if (find_table_in_list(table->next, fitem->db_name, fitem->table_name) != 0 || tb->fields == 1) { From 48a64b57033b004d6e4fa92e5c13b21f0f24af22 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Nov 2002 18:03:10 +0200 Subject: [PATCH 61/89] fixed current_thread --- sql/sql_yacc.yy | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 77d7b48d57f..cb1c7fed838 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1800,10 +1800,10 @@ expr_expr: | expr NOT IN_SYM '(' expr_list ')' { $$= new Item_func_not(new Item_func_in($1,*$5)); } | expr IN_SYM in_subselect - { $$= new Item_in_subselect(current_thd, $1, $3); } + { $$= new Item_in_subselect(YYTHD, $1, $3); } | expr NOT IN_SYM in_subselect { - $$= new Item_func_not(new Item_in_subselect(current_thd, $1, $4)); + $$= new Item_func_not(new Item_in_subselect(YYTHD, $1, $4)); } | expr BETWEEN_SYM no_and_expr AND expr { $$= new Item_func_between($1,$3,$5); } @@ -1824,7 +1824,7 @@ expr_expr: | expr comp_op all_or_any in_subselect %prec EQ { Item_allany_subselect *it= - new Item_allany_subselect(current_thd, $1, (*$2)($3), $4); + new Item_allany_subselect(YYTHD, $1, (*$2)($3), $4); if ($3) $$ = new Item_func_not(it); /* ALL */ else @@ -1870,7 +1870,7 @@ no_in_expr: | no_in_expr comp_op all_or_any in_subselect %prec EQ { Item_allany_subselect *it= - new Item_allany_subselect(current_thd, $1, (*$2)($3), $4); + new Item_allany_subselect(YYTHD, $1, (*$2)($3), $4); if ($3) $$ = new Item_func_not(it); /* ALL */ else @@ -1901,10 +1901,10 @@ no_and_expr: | no_and_expr NOT IN_SYM '(' expr_list ')' { $$= new Item_func_not(new Item_func_in($1,*$5)); } | no_and_expr IN_SYM in_subselect - { $$= new Item_in_subselect(current_thd, $1, $3); } + { $$= new Item_in_subselect(YYTHD, $1, $3); } | no_and_expr NOT IN_SYM in_subselect { - $$= new Item_func_not(new Item_in_subselect(current_thd, $1, $4)); + $$= new Item_func_not(new Item_in_subselect(YYTHD, $1, $4)); } | no_and_expr BETWEEN_SYM no_and_expr AND expr { $$= new Item_func_between($1,$3,$5); } @@ -1924,7 +1924,7 @@ no_and_expr: | no_and_expr comp_op all_or_any in_subselect %prec EQ { Item_allany_subselect *it= - new Item_allany_subselect(current_thd, $1, (*$2)($3), $4); + new Item_allany_subselect(YYTHD, $1, (*$2)($3), $4); if ($3) $$ = new Item_func_not(it); /* ALL */ else From e3114057d4f397e0f8c3c8f98a8caf7ce06d8197 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Nov 2002 19:16:06 +0200 Subject: [PATCH 62/89] layout fix --- sql/filesort.cc | 3 ++- sql/item_cmpfunc.cc | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/sql/filesort.cc b/sql/filesort.cc index 8247b52ad1b..e2a108bfccc 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -84,7 +84,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, #endif // BAR TODO: this is not absolutely correct, but OK for now - for(i=0;ifields;i++) + for (i=0;ifields;i++) if (!table->field[i]->binary()) charset=table->field[i]->charset(); // /BAR TODO @@ -973,6 +973,7 @@ sortlength(SORT_FIELD *sortorder, uint s_length) case ROW_RESULT: // This case should never be choosen DBUG_ASSERT(0); + break; } if (sortorder->item->maybe_null) length++; // Place for NULL marker diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 81e1ca8a031..545db7ce4df 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -131,7 +131,7 @@ Compare_func_row::Compare_func_row(Item_bool_func2 *owner, Item *a, Item* b): return; } cmp_func= (Compare_func **) sql_alloc(sizeof(Compare_func*)*n); - for(uint i=0; i < n; i++) + for (uint i=0; i < n; i++) cmp_func[i]= Compare_func::get_compare_func(owner, a->el(i), b->el(i)); } @@ -191,7 +191,7 @@ int Compare_func_row::compare(Item *a, Item *b) { int res= 0; uint n= a->cols(); - for(uint i= 0; icompare(a->el(i), b->el(i)))) return res; From 8b2be4e459eddae70fad7a033bc53213025449f3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Nov 2002 22:35:23 +0200 Subject: [PATCH 63/89] after-merge fix --- mysql-test/r/subselect.result | 4 ++-- sql/item.cc | 6 ++---- sql/item_subselect.cc | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index f80950e2b21..ea5482405af 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -163,9 +163,9 @@ a 7 delete from t2 where a=100; select * from t3 where a in (select a,b from t2); -Subselect returns more than 1 field +Cardinality error (more/less than 1 columns) select * from t3 where a in (select * from t2); -Subselect returns more than 1 field +Cardinality error (more/less than 1 columns) insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9); select b,max(a) as ma from t4 group by b having b < (select max(t2.a) from t2 where t2.b=t4.b); diff --git a/sql/item.cc b/sql/item.cc index 346bc545ef3..8a33037771b 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -496,8 +496,7 @@ bool Item_asterisk_remover::fix_fields(THD *thd, thd->fatal_error= 1; // can't create Item => out of memory } else - my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), - MYF(0)); + my_error(ER_CARDINALITY_COL, MYF(0), 1); } else if (!fitem->table_name) @@ -506,8 +505,7 @@ bool Item_asterisk_remover::fix_fields(THD *thd, my_error(ER_BAD_TABLE_ERROR, MYF(0), fitem->table_name); } else - my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), - MYF(0)); + my_error(ER_CARDINALITY_COL, MYF(0), 1); } else res= item->fix_fields(thd, list, &item); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 1e016da9ec0..ebe916966d6 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -285,7 +285,7 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, Item *item; if (sl->item_list.elements > 1) { - my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0)); + my_error(ER_CARDINALITY_COL, MYF(0), 1); item= 0; // Item_asterisk_remover must fail } else @@ -297,7 +297,7 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, { sl->item_list.push_back(item); item= (*func)(left_expr, new Item_ref(sl->item_list.head_ref(), - 0, "")); + 0, (char*)"")); if (sl->having) sl->having= new Item_cond_and(sl->having, item); else From bebac6db39d606523442363abebbfb797a9b3237 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Nov 2002 01:00:09 +0200 Subject: [PATCH 64/89] changed compare engine in basic row items (SCRUM) fixed layout sql/item_cmpfunc.cc: changed compare engine in basic row items BitKeeper/etc/ignore: Added libmysqld/item_row.cc to the ignore list sql/item_cmpfunc.h: changed compare engine in basic row items sql/item_func.h: changed compare engine in basic row items fixed layout sql/sql_select.cc: changed compare engine in basic row items --- .bzrignore | 1 + sql/item_cmpfunc.cc | 111 ++++++++++++++++++++++++-------------------- sql/item_cmpfunc.h | 63 ++----------------------- sql/item_func.h | 80 +++++++++++++++++++++---------- sql/sql_select.cc | 4 +- 5 files changed, 124 insertions(+), 135 deletions(-) diff --git a/.bzrignore b/.bzrignore index 88995ac7c65..f0fcf652045 100644 --- a/.bzrignore +++ b/.bzrignore @@ -567,3 +567,4 @@ bkpull.log.5 bkpull.log.6 bkpush.log sql/sql_yacc.output +libmysqld/item_row.cc diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index b1cbe405e73..9f3457d8b8d 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -107,7 +107,7 @@ void Item_bool_func2::fix_length_and_dec() { if (convert_constant_item(field,&args[1])) { - cmp_func= new Compare_func_int(this); // Works for all types. + arg_store.set_compare_func(this, INT_RESULT); // Works for all types. return; } } @@ -119,52 +119,63 @@ void Item_bool_func2::fix_length_and_dec() { if (convert_constant_item(field,&args[0])) { - cmp_func= new Compare_func_int(this); // Works for all types. + arg_store.set_compare_func(this, INT_RESULT); // Works for all types. return; } } } - set_cmp_func(args[0], args[1]); + set_cmp_func(); } -Compare_func* Compare_func::get_compare_func(Item_bool_func2 *owner, - Item *a, Item* b) +int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) { - switch (item_cmp_type(a->result_type(), b->result_type())) + owner= item; + switch (type) { case STRING_RESULT: - return new Compare_func_string(owner); + func= &Arg_comparator::compare_string; + break; case REAL_RESULT: - return new Compare_func_real(owner); + func= &Arg_comparator::compare_real; + break; case INT_RESULT: - return new Compare_func_int(owner); + func= &Arg_comparator::compare_int; + break; case ROW_RESULT: - return new Compare_func_row(owner, a, b); + { + func= &Arg_comparator::compare_row; + uint n= args[0]->cols(); + if (n != args[1]->cols()) + { + my_error(ER_CARDINALITY_COL, MYF(0), n); + comparators= 0; + return 1; + } + if ((comparators= (Arg_comparator *) sql_alloc(sizeof(Arg_comparator)*n))) + for (uint i=0; i < n; i++) + { + comparators[i].set_arg(0, args[0]->el(i)); + comparators[i].set_arg(1, args[1]->el(i)); + comparators[i].set_compare_func(owner); + } + else + { + my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); + current_thd->fatal_error= 1; + return 1; + } + break; + } } return 0; } -Compare_func_row::Compare_func_row(Item_bool_func2 *owner, Item *a, Item* b): - Compare_func(owner) -{ - uint n= a->cols(); - if (n != b->cols()) - { - my_error(ER_CARDINALITY_COL, MYF(0), n); - cmp_func= 0; - return; - } - cmp_func= (Compare_func **) sql_alloc(sizeof(Compare_func*)*n); - for (uint i=0; i < n; i++) - cmp_func[i]= Compare_func::get_compare_func(owner, a->el(i), b->el(i)); -} - -int Compare_func_string::compare(Item *a, Item *b) +int Arg_comparator::compare_string() { String *res1,*res2; - if ((res1= a->val_str(&owner->tmp_value1))) + if ((res1= args[0]->val_str(&owner->tmp_value1))) { - if ((res2= b->val_str(&owner->tmp_value2))) + if ((res2= args[1]->val_str(&owner->tmp_value2))) { owner->null_value= 0; return owner->binary() ? stringcmp(res1,res2) : sortcmp(res1,res2); @@ -174,13 +185,13 @@ int Compare_func_string::compare(Item *a, Item *b) return -1; } -int Compare_func_real::compare(Item *a, Item *b) +int Arg_comparator::compare_real() { - double val1= a->val(); - if (!a->null_value) + double val1= args[0]->val(); + if (!args[0]->null_value) { - double val2= b->val(); - if (!b->null_value) + double val2= args[1]->val(); + if (!args[1]->null_value) { owner->null_value= 0; if (val1 < val2) return -1; @@ -193,13 +204,13 @@ int Compare_func_real::compare(Item *a, Item *b) } -int Compare_func_int::compare(Item *a, Item *b) +int Arg_comparator::compare_int() { - longlong val1= a->val_int(); - if (!a->null_value) + longlong val1= args[0]->val_int(); + if (!args[0]->null_value) { - longlong val2= b->val_int(); - if (!b->null_value) + longlong val2= args[1]->val_int(); + if (!args[1]->null_value) { owner->null_value= 0; if (val1 < val2) return -1; @@ -211,13 +222,13 @@ int Compare_func_int::compare(Item *a, Item *b) return -1; } -int Compare_func_row::compare(Item *a, Item *b) +int Arg_comparator::compare_row() { int res= 0; - uint n= a->cols(); + uint n= args[0]->cols(); for (uint i= 0; icompare(a->el(i), b->el(i)))) + if ((res= comparators[i].compare())) return res; if (owner->null_value) return -1; @@ -227,7 +238,7 @@ int Compare_func_row::compare(Item *a, Item *b) longlong Item_func_eq::val_int() { - int value= cmp_func->compare(args[0], args[1]); + int value= arg_store.compare(); return value == 0 ? 1 : 0; } @@ -281,34 +292,34 @@ longlong Item_func_equal::val_int() longlong Item_func_ne::val_int() { - int value= cmp_func->compare(args[0], args[1]); + int value= arg_store.compare(); return value != 0 && !null_value ? 1 : 0; } longlong Item_func_ge::val_int() { - int value= cmp_func->compare(args[0], args[1]); + int value= arg_store.compare(); return value >= 0 ? 1 : 0; } longlong Item_func_gt::val_int() { - int value= cmp_func->compare(args[0], args[1]); + int value= arg_store.compare(); return value > 0 ? 1 : 0; } longlong Item_func_le::val_int() { - int value= cmp_func->compare(args[0], args[1]); + int value= arg_store.compare(); return value <= 0 && !null_value ? 1 : 0; } longlong Item_func_lt::val_int() { - int value= cmp_func->compare(args[0], args[1]); + int value= arg_store.compare(); return value < 0 && !null_value ? 1 : 0; } @@ -657,7 +668,7 @@ double Item_func_nullif::val() { double value; - if (!cmp_func->compare(args[0], args[1]) || null_value) + if (!arg_store.compare() || null_value) { null_value=1; return 0.0; @@ -671,7 +682,7 @@ longlong Item_func_nullif::val_int() { longlong value; - if (!cmp_func->compare(args[0], args[1]) || null_value) + if (!arg_store.compare() || null_value) { null_value=1; return 0; @@ -685,7 +696,7 @@ String * Item_func_nullif::val_str(String *str) { String *res; - if (!cmp_func->compare(args[0], args[1]) || null_value) + if (!arg_store.compare() || null_value) { null_value=1; return 0; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 8f7bfa0fda4..b9511e82e32 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -30,61 +30,6 @@ public: void fix_length_and_dec() { decimals=0; max_length=1; } }; -class Item_bool_func2; - -class Compare_func -{ -protected: - Item_bool_func2 *owner; -public: - static void *operator new(size_t size) - { - return (void*) sql_alloc((uint) size); - } - static void operator delete(void *ptr,size_t size) {} - - Compare_func(Item_bool_func2 *o) { owner= o; } - virtual ~Compare_func() {}; - virtual int compare(Item *, Item*)= 0; - - static Compare_func* get_compare_func(Item_bool_func2 *owner, - Item* a, Item* b); -}; - -class Compare_func_string: public Compare_func -{ -public: - Compare_func_string(Item_bool_func2 *owner): Compare_func(owner) {}; - int compare(Item *, Item*); -}; - -class Compare_func_real: public Compare_func -{ -public: - Compare_func_real(Item_bool_func2 *owner): Compare_func(owner) {}; - int compare(Item *, Item*); -}; - -class Compare_func_int: public Compare_func -{ -public: - Compare_func_int(Item_bool_func2 *owner): Compare_func(owner) {}; - int compare(Item *, Item*); -}; - -class Compare_func_row: public Compare_func -{ - Compare_func **cmp_func; -public: - Compare_func_row(Item_bool_func2 *owner, Item* a, Item* b); - ~Compare_func_row() - { - if(cmp_func) - sql_element_free(cmp_func); - } - int compare(Item *, Item*); -}; - class Item_bool_func2 :public Item_int_func { /* Bool with 2 string args */ protected: @@ -92,10 +37,9 @@ protected: public: Item_bool_func2(Item *a,Item *b) :Item_int_func(a,b) {} void fix_length_and_dec(); - Compare_func *cmp_func; - void set_cmp_func(Item *a, Item *b) + void set_cmp_func() { - cmp_func= Compare_func::get_compare_func(this, args[0], args[1]); + arg_store.set_compare_func(this); } optimize_type select_optimize() const { return OPTIMIZE_OP; } virtual enum Functype rev_functype() const { return UNKNOWN_FUNC; } @@ -103,13 +47,14 @@ public: void print(String *str) { Item_func::print_op(str); } bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); } - friend class Compare_func_string; static Item_bool_func2* eq_creator(Item *a, Item *b); static Item_bool_func2* ne_creator(Item *a, Item *b); static Item_bool_func2* gt_creator(Item *a, Item *b); static Item_bool_func2* lt_creator(Item *a, Item *b); static Item_bool_func2* ge_creator(Item *a, Item *b); static Item_bool_func2* le_creator(Item *a, Item *b); + + friend class Arg_comparator; }; class Item_bool_rowready_func2 :public Item_bool_func2 diff --git a/sql/item_func.h b/sql/item_func.h index 43fb28e77e8..61bac374152 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -28,10 +28,42 @@ extern "C" /* Bug in BSDI include file */ } #endif +extern Item_result item_cmp_type(Item_result a,Item_result b); +class Item_bool_func2; +class Arg_comparator; + +typedef int (Arg_comparator::*arg_cmp_func)(); + +class Arg_comparator: public Sql_alloc +{ + Item *args[2]; + arg_cmp_func func; + Item_bool_func2 *owner; + Arg_comparator *comparators; // used only for compare_row() + +public: + inline void set_arg(int i, Item *item) { args[i]= item; } + int set_compare_func(Item_bool_func2 *owner, Item_result type); + inline int set_compare_func(Item_bool_func2 *owner) + { + return set_compare_func(owner, item_cmp_type(args[0]->result_type(), + args[1]->result_type())); + } + inline int compare() { return (this->*func)(); } + + int compare_string(); // compare args[0] & args[1] + int compare_real(); // compare args[0] & args[1] + int compare_int(); // compare args[0] & args[1] + int compare_row(); // compare args[0] & args[1] + + friend class Item_func; +}; + class Item_func :public Item_result_field { protected: - Item **args,*tmp_arg[2]; + Item **args; + Arg_comparator arg_store; uint allowed_arg_cols; public: uint arg_count; @@ -53,54 +85,54 @@ public: Item_func(void): allowed_arg_cols(1), arg_count(0) { - with_sum_func=0; + with_sum_func= 0; } Item_func(Item *a): allowed_arg_cols(1), arg_count(1) { - args=tmp_arg; - args[0]=a; - with_sum_func=a->with_sum_func; + args= arg_store.args; + args[0]= a; + with_sum_func= a->with_sum_func; } Item_func(Item *a,Item *b): allowed_arg_cols(1), arg_count(2) { - args=tmp_arg; - args[0]=a; args[1]=b; - with_sum_func=a->with_sum_func || b->with_sum_func; + args= arg_store.args; + args[0]= a; args[1]= b; + with_sum_func= a->with_sum_func || b->with_sum_func; } Item_func(Item *a,Item *b,Item *c): allowed_arg_cols(1) { - arg_count=0; - if ((args=(Item**) sql_alloc(sizeof(Item*)*3))) + arg_count= 0; + if ((args= (Item**) sql_alloc(sizeof(Item*)*3))) { - arg_count=3; - args[0]=a; args[1]=b; args[2]=c; - with_sum_func=a->with_sum_func || b->with_sum_func || c->with_sum_func; + arg_count= 3; + args[0]= a; args[1]= b; args[2]= c; + with_sum_func= a->with_sum_func || b->with_sum_func || c->with_sum_func; } } Item_func(Item *a,Item *b,Item *c,Item *d): allowed_arg_cols(1) { - arg_count=0; - if ((args=(Item**) sql_alloc(sizeof(Item*)*4))) + arg_count= 0; + if ((args= (Item**) sql_alloc(sizeof(Item*)*4))) { - arg_count=4; - args[0]=a; args[1]=b; args[2]=c; args[3]=d; - with_sum_func=a->with_sum_func || b->with_sum_func || c->with_sum_func || - d->with_sum_func; + arg_count= 4; + args[0]= a; args[1]= b; args[2]= c; args[3]= d; + with_sum_func= a->with_sum_func || b->with_sum_func || + c->with_sum_func || d->with_sum_func; } } Item_func(Item *a,Item *b,Item *c,Item *d,Item* e): allowed_arg_cols(1) { - arg_count=5; - if ((args=(Item**) sql_alloc(sizeof(Item*)*5))) + arg_count= 5; + if ((args= (Item**) sql_alloc(sizeof(Item*)*5))) { - args[0]=a; args[1]=b; args[2]=c; args[3]=d; args[4]=e; - with_sum_func=a->with_sum_func || b->with_sum_func || c->with_sum_func || - d->with_sum_func || e->with_sum_func ; + args[0]= a; args[1]= b; args[2]= c; args[3]= d; args[4]= e; + with_sum_func= a->with_sum_func || b->with_sum_func || + c->with_sum_func || d->with_sum_func || e->with_sum_func ; } } Item_func(List &list); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3c063428509..f560cb7907f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3340,7 +3340,7 @@ change_cond_ref_to_const(I_List *save_list,Item *and_father, if ((tmp2=new COND_CMP(and_father,func))) save_list->push_back(tmp2); } - func->set_cmp_func(func->arguments()[0],func->arguments()[1]); + func->set_cmp_func(); } } else if (left_item->eq(field,0) && right_item != value) @@ -3360,7 +3360,7 @@ change_cond_ref_to_const(I_List *save_list,Item *and_father, if ((tmp2=new COND_CMP(and_father,func))) save_list->push_back(tmp2); } - func->set_cmp_func(func->arguments()[0], func->arguments()[1]); + func->set_cmp_func(); } } } From e761be558d6e40db17734f1425372dd228404e5e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Nov 2002 11:04:26 +0400 Subject: [PATCH 65/89] New functions --- sql/item.h | 4 ++-- sql/item_func.h | 4 ++-- sql/item_sum.h | 4 ++-- strings/ctype-simple.c | 20 ++++++++++---------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/sql/item.h b/sql/item.h index 414dcfbc328..9e36e36adfb 100644 --- a/sql/item.h +++ b/sql/item.h @@ -536,9 +536,9 @@ public: enum Type type() const { return COPY_STR_ITEM; } enum Item_result result_type () const { return STRING_RESULT; } double val() - { return null_value ? 0.0 : atof(str_value.c_ptr()); } + { return null_value ? 0.0 : my_strntod(str_value.charset(),str_value.ptr(),str_value.length(),NULL); } longlong val_int() - { return null_value ? LL(0) : strtoll(str_value.c_ptr(),(char**) 0,10); } + { return null_value ? LL(0) : my_strntoll(str_value.charset(),str_value.ptr(),str_value.length(),(char**) 0,10); } String *val_str(String*); void make_field(Send_field *field) { item->make_field(field); } void copy(); diff --git a/sql/item_func.h b/sql/item_func.h index 38f461acc13..352a9e0e272 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -801,12 +801,12 @@ public: double val() { String *res; res=val_str(&str_value); - return res ? atof(res->c_ptr()) : 0.0; + return res ? my_strntod(res->charset(),res->ptr(),res->length(),0) : 0.0; } longlong val_int() { String *res; res=val_str(&str_value); - return res ? strtoll(res->c_ptr(),(char**) 0,10) : (longlong) 0; + return res ? my_strntoll(res->charset(),res->ptr(),res->length(),(char**) 0,10) : (longlong) 0; } enum Item_result result_type () const { return STRING_RESULT; } void fix_length_and_dec(); diff --git a/sql/item_sum.h b/sql/item_sum.h index 70bb3a7c0a1..00803abf25d 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -442,12 +442,12 @@ public: double val() { String *res; res=val_str(&str_value); - return res ? atof(res->c_ptr()) : 0.0; + return res ? my_strntod(res->charset(),res->ptr(),res->length(),(char**) 0) : 0.0; } longlong val_int() { String *res; res=val_str(&str_value); - return res ? strtoll(res->c_ptr(),(char**) 0,10) : (longlong) 0; + return res ? my_strntoll(res->charset(),res->ptr(),res->length(),(char**) 0,10) : (longlong) 0; } enum Item_result result_type () const { return STRING_RESULT; } void fix_length_and_dec(); diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index be4fdc9cb8d..b487159a733 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -18,6 +18,8 @@ #include "m_string.h" #include "m_ctype.h" #include "my_sys.h" /* defines errno */ +#include + #include "stdarg.h" #include "assert.h" @@ -246,8 +248,6 @@ void my_hash_sort_simple(CHARSET_INFO *cs, } -#define MY_ERRNO(y) - long my_strntol_8bit(CHARSET_INFO *cs, const char *nptr, uint l, char **endptr, int base) { @@ -349,14 +349,14 @@ long my_strntol_8bit(CHARSET_INFO *cs, if (overflow) { - MY_ERRNO(ERANGE); + my_errno=(ERANGE); return negative ? LONG_MIN : LONG_MAX; } return (negative ? -((long) i) : (long) i); noconv: - MY_ERRNO(EDOM); + my_errno=(EDOM); if (endptr != NULL) *endptr = (char *) nptr; return 0L; @@ -455,14 +455,14 @@ ulong my_strntoul_8bit(CHARSET_INFO *cs, if (overflow) { - MY_ERRNO(ERANGE); + my_errno=(ERANGE); return ((ulong)~0L); } return (negative ? -((long) i) : (long) i); noconv: - MY_ERRNO(EDOM); + my_errno=(EDOM); if (endptr != NULL) *endptr = (char *) nptr; return 0L; @@ -570,14 +570,14 @@ longlong my_strntoll_8bit(CHARSET_INFO *cs __attribute__((unused)), if (overflow) { - MY_ERRNO(ERANGE); + my_errno=(ERANGE); return negative ? LONGLONG_MIN : LONGLONG_MAX; } return (negative ? -((longlong) i) : (longlong) i); noconv: - MY_ERRNO(EDOM); + my_errno=(EDOM); if (endptr != NULL) *endptr = (char *) nptr; return 0L; @@ -677,14 +677,14 @@ ulonglong my_strntoull_8bit(CHARSET_INFO *cs, if (overflow) { - MY_ERRNO(ERANGE); + my_errno=(ERANGE); return (~(ulonglong) 0); } return (negative ? -((longlong) i) : (longlong) i); noconv: - MY_ERRNO(EDOM); + my_errno=(EDOM); if (endptr != NULL) *endptr = (char *) nptr; return 0L; From fb4dc27cf7134485dcc92aece11ba37b25e8d5fd Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Nov 2002 09:11:35 +0200 Subject: [PATCH 66/89] Item_func_equal made uniform mysql-test/r/row_test.result: Equal test mysql-test/t/row_test.test: Equal test --- mysql-test/r/row_test.result | 6 +++ mysql-test/t/row_test.test | 2 + sql/item_cmpfunc.cc | 99 +++++++++++++++++------------------- sql/item_cmpfunc.h | 8 +-- sql/item_func.h | 6 +++ sql/mysqld.cc | 6 ++- 6 files changed, 70 insertions(+), 57 deletions(-) diff --git a/mysql-test/r/row_test.result b/mysql-test/r/row_test.result index fa7739904d7..bd162e35f86 100644 --- a/mysql-test/r/row_test.result +++ b/mysql-test/r/row_test.result @@ -22,6 +22,12 @@ SELECT (1,2,3)>=(1+1,2,3); SELECT (1,2,3)<>(1+1,2,3); (1,2,3)<>(1+1,2,3) 1 +SELECT (NULL,2,3)=(NULL,2,3); +(NULL,2,3)=(NULL,2,3) +NULL +SELECT (NULL,2,3)<=>(NULL,2,3); +(NULL,2,3)<=>(NULL,2,3) +1 SELECT (1,2,(3,4,5))=(1,2,(3,4,5)); (1,2,(3,4,5))=(1,2,(3,4,5)) 1 diff --git a/mysql-test/t/row_test.test b/mysql-test/t/row_test.test index 8be347cf5fc..24df2dd1b20 100644 --- a/mysql-test/t/row_test.test +++ b/mysql-test/t/row_test.test @@ -6,6 +6,8 @@ SELECT (1,2,3)>(1+1,2,3); SELECT (1,2,3)<=(1+1,2,3); SELECT (1,2,3)>=(1+1,2,3); SELECT (1,2,3)<>(1+1,2,3); +SELECT (NULL,2,3)=(NULL,2,3); +SELECT (NULL,2,3)<=>(NULL,2,3); SELECT (1,2,(3,4,5))=(1,2,(3,4,5)); SELECT ('test',2,3.33)=('test',2,3.33); -- error 1239 diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 9f3457d8b8d..06dc3fca89d 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -88,7 +88,6 @@ static bool convert_constant_item(Field *field, Item **item) return 0; } - void Item_bool_func2::fix_length_and_dec() { max_length=1; // Function returns 0 or 1 @@ -130,20 +129,9 @@ void Item_bool_func2::fix_length_and_dec() int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) { owner= item; - switch (type) + func= comparator_matrix[type][owner->equal]; + if (type == ROW_RESULT) { - case STRING_RESULT: - func= &Arg_comparator::compare_string; - break; - case REAL_RESULT: - func= &Arg_comparator::compare_real; - break; - case INT_RESULT: - func= &Arg_comparator::compare_int; - break; - case ROW_RESULT: - { - func= &Arg_comparator::compare_row; uint n= args[0]->cols(); if (n != args[1]->cols()) { @@ -164,8 +152,6 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) current_thd->fatal_error= 1; return 1; } - break; - } } return 0; } @@ -185,6 +171,18 @@ int Arg_comparator::compare_string() return -1; } +int Arg_comparator::compare_e_string() +{ + String *res1,*res2; + res1= args[0]->val_str(&owner->tmp_value1); + res2= args[1]->val_str(&owner->tmp_value2); + if (!res1 || !res2) + return test(res1 == res2); + return (owner->binary() ? test(stringcmp(res1, res2) == 0) : + test(sortcmp(res1, res2) == 0)); +} + + int Arg_comparator::compare_real() { double val1= args[0]->val(); @@ -203,6 +201,14 @@ int Arg_comparator::compare_real() return -1; } +int Arg_comparator::compare_e_real() +{ + double val1= args[0]->val(); + double val2= args[1]->val(); + if (args[0]->null_value || args[1]->null_value) + return test(args[0]->null_value && args[1]->null_value); + return test(val1 == val2); +} int Arg_comparator::compare_int() { @@ -222,6 +228,16 @@ int Arg_comparator::compare_int() return -1; } +int Arg_comparator::compare_e_int() +{ + longlong val1= args[0]->val_int(); + longlong val2= args[1]->val_int(); + if (args[0]->null_value || args[1]->null_value) + return test(args[0]->null_value && args[1]->null_value); + return test(val1 == val2); +} + + int Arg_comparator::compare_row() { int res= 0; @@ -236,6 +252,19 @@ int Arg_comparator::compare_row() return res; } +int Arg_comparator::compare_e_row() +{ + int res= 0; + uint n= args[0]->cols(); + for (uint i= 0; iresult_type(),args[1]->result_type()); maybe_null=null_value=0; + set_cmp_func(); } longlong Item_func_equal::val_int() { - switch (cmp_result_type) { - case STRING_RESULT: - { - String *res1,*res2; - res1=args[0]->val_str(&tmp_value1); - res2=args[1]->val_str(&tmp_value2); - if (!res1 || !res2) - return test(res1 == res2); - return (binary() ? test(stringcmp(res1,res2) == 0) : - test(sortcmp(res1,res2) == 0)); - } - case REAL_RESULT: - { - double val1=args[0]->val(); - double val2=args[1]->val(); - if (args[0]->null_value || args[1]->null_value) - return test(args[0]->null_value && args[1]->null_value); - return test(val1 == val2); - } - case INT_RESULT: - { - longlong val1=args[0]->val_int(); - longlong val2=args[1]->val_int(); - if (args[0]->null_value || args[1]->null_value) - return test(args[0]->null_value && args[1]->null_value); - return test(val1 == val2); - } - case ROW_RESULT: - { - my_error(ER_WRONG_USAGE, MYF(0), "row", "<=>"); - return 0; - } - } - return 0; // Impossible + return arg_store.compare(); } - longlong Item_func_ne::val_int() { int value= arg_store.compare(); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index b9511e82e32..ca03d02aa77 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -34,8 +34,9 @@ class Item_bool_func2 :public Item_int_func { /* Bool with 2 string args */ protected: String tmp_value1,tmp_value2; + bool equal; public: - Item_bool_func2(Item *a,Item *b) :Item_int_func(a,b) {} + Item_bool_func2(Item *a,Item *b) :Item_int_func(a,b), equal(0) {} void fix_length_and_dec(); void set_cmp_func() { @@ -85,11 +86,10 @@ public: const char *func_name() const { return "="; } }; -class Item_func_equal :public Item_bool_func2 +class Item_func_equal :public Item_bool_rowready_func2 { - Item_result cmp_result_type; public: - Item_func_equal(Item *a,Item *b) :Item_bool_func2(a,b) { }; + Item_func_equal(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { equal=1; }; longlong val_int(); void fix_length_and_dec(); enum Functype functype() const { return EQUAL_FUNC; } diff --git a/sql/item_func.h b/sql/item_func.h index 61bac374152..e3b5fa3445a 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -55,6 +55,12 @@ public: int compare_real(); // compare args[0] & args[1] int compare_int(); // compare args[0] & args[1] int compare_row(); // compare args[0] & args[1] + int compare_e_string(); // compare args[0] & args[1] + int compare_e_real(); // compare args[0] & args[1] + int compare_e_int(); // compare args[0] & args[1] + int compare_e_row(); // compare args[0] & args[1] + + static arg_cmp_func comparator_matrix [4][2]; friend class Item_func; }; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 86da0e846a0..b45caac5ab6 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -337,7 +337,11 @@ ulong query_cache_size=0; ulong query_cache_limit=0; Query_cache query_cache; #endif - +arg_cmp_func Arg_comparator::comparator_matrix[4][2] = +{{&Arg_comparator::compare_string, &Arg_comparator::compare_e_string}, + {&Arg_comparator::compare_real, &Arg_comparator::compare_e_real}, + {&Arg_comparator::compare_int, &Arg_comparator::compare_e_int}, + {&Arg_comparator::compare_row, &Arg_comparator::compare_e_row}}; #ifdef HAVE_SMEM static char *shared_memory_base_name=default_shared_memory_base_name; static bool opt_enable_shared_memory = 0; From 5a1b9e1d05ec4c52e89df1adf40312a55f8b7d3f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Nov 2002 11:33:04 +0400 Subject: [PATCH 67/89] More use of new string->number conversion functions --- sql/field.cc | 26 ++++++-------------------- sql/item_strfunc.cc | 8 ++++---- sql/item_sum.cc | 2 +- 3 files changed, 11 insertions(+), 25 deletions(-) diff --git a/sql/field.cc b/sql/field.cc index e0910caeea2..f0f3b22f1cc 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -15,16 +15,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* - NOTES: - Some of the number class uses the system functions strtol(), strtoll()... - To avoid patching the end \0 or copying the buffer unnecessary, all calls - to system functions are wrapped to a String object that adds the end null - if it only if it isn't there. - This adds some overhead when assigning numbers from strings but makes - everything simpler. - */ - /***************************************************************************** ** This file implements classes defined in field.h *****************************************************************************/ @@ -1592,7 +1582,6 @@ int Field_long::store(const char *from,uint len,CHARSET_INFO *cs) } long tmp; int error= 0; - String tmp_str(from,len,default_charset_info); errno=0; if (unsigned_flag) { @@ -1603,10 +1592,10 @@ int Field_long::store(const char *from,uint len,CHARSET_INFO *cs) error= 1; } else - tmp=(long) strtoul(tmp_str.c_ptr(),NULL,10); + tmp=(long) my_strntoul(cs,from,len,NULL,10); } else - tmp=strtol(tmp_str.c_ptr(),NULL,10); + tmp=my_strntol(cs,from,len,NULL,10); if (errno || current_thd->count_cuted_fields && !test_if_int(from,len)) { current_thd->cuted_fields++; @@ -1837,7 +1826,6 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs) len--; from++; } longlong tmp; - String tmp_str(from,len,default_charset_info); int error= 0; errno=0; if (unsigned_flag) @@ -1849,10 +1837,10 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs) error= 1; } else - tmp=(longlong) strtoull(tmp_str.c_ptr(),NULL,10); + tmp=(longlong) my_strntoull(cs,from,len,NULL,10); } else - tmp=strtoll(tmp_str.c_ptr(),NULL,10); + tmp=my_strntoll(cs,from,len,NULL,10); if (errno || current_thd->count_cuted_fields && !test_if_int(from,len)) { current_thd->cuted_fields++; @@ -2052,9 +2040,8 @@ void Field_longlong::sql_type(String &res) const int Field_float::store(const char *from,uint len,CHARSET_INFO *cs) { - String tmp_str(from,len,default_charset_info); errno=0; - Field_float::store(atof(tmp_str.c_ptr())); + Field_float::store(my_strntod(cs,from,len,(char**)NULL)); if (errno || current_thd->count_cuted_fields && !test_if_real(from,len)) { current_thd->cuted_fields++; @@ -2314,10 +2301,9 @@ void Field_float::sql_type(String &res) const int Field_double::store(const char *from,uint len,CHARSET_INFO *cs) { - String tmp_str(from,len,default_charset_info); errno=0; int error= 0; - double j= atof(tmp_str.c_ptr()); + double j= my_strntod(cs,from,len,(char**)0); if (errno || current_thd->count_cuted_fields && !test_if_real(from,len)) { current_thd->cuted_fields++; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index fc3b4da8561..d7f70de58f8 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -54,14 +54,14 @@ double Item_str_func::val() { String *res; res=val_str(&str_value); - return res ? atof(res->c_ptr()) : 0.0; + return res ? my_strntod(res->charset(),res->ptr(),res->length(),NULL) : 0.0; } longlong Item_str_func::val_int() { String *res; res=val_str(&str_value); - return res ? strtoll(res->c_ptr(),NULL,10) : (longlong) 0; + return res ? my_strntoll(res->charset(),res->ptr(),res->length(),NULL,10) : (longlong) 0; } @@ -1905,9 +1905,9 @@ String *Item_func_conv::val_str(String *str) } null_value=0; if (from_base < 0) - dec= strtoll(res->c_ptr(),&endptr,-from_base); + dec= my_strntoll(res->charset(),res->ptr(),res->length(),&endptr,-from_base); else - dec= (longlong) strtoull(res->c_ptr(),&endptr,from_base); + dec= (longlong) my_strntoull(res->charset(),res->ptr(),res->length(),&endptr,from_base); ptr= longlong2str(dec,ans,to_base); if (str->copy(ans,(uint32) (ptr-ans), thd_charset())) return &empty_string; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 567b5ee6ffa..86c94e03acd 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -334,7 +334,7 @@ double Item_sum_hybrid::val() switch (hybrid_type) { case STRING_RESULT: String *res; res=val_str(&str_value); - return res ? atof(res->c_ptr()) : 0.0; + return res ? my_strntod(res->charset(),res->ptr(),res->length(),(char**)0) : 0.0; case INT_RESULT: if (unsigned_flag) return ulonglong2double(sum_int); From da6e29a6108a8f982b7d5fdf8cfdc77fdd819e68 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Nov 2002 11:28:49 +0200 Subject: [PATCH 68/89] Fix wrong increment in prepared statements handling libmysql/libmysql.c: Fix wrong increment --- libmysql/libmysql.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 410be65660f..fcc0290bea3 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -4186,7 +4186,7 @@ mysql_send_long_data(MYSQL_STMT *stmt, uint param_number, static void fetch_result_tinyint(MYSQL_BIND *param, uchar **row) { *param->buffer= (uchar) **row; - *row++; + (*row)++; } static void fetch_result_short(MYSQL_BIND *param, uchar **row) From 57321e64cd9093bc32e482bd8155c365f2f97ed7 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Nov 2002 13:31:35 +0400 Subject: [PATCH 69/89] support for HA_READ_PREFIX_LAST_OR_PREV, HA_READ_PREFIX_LAST and HA_READ_BEFORE_KEY --- mysys/tree.c | 53 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/mysys/tree.c b/mysys/tree.c index 364b6992108..4b14ffd7112 100644 --- a/mysys/tree.c +++ b/mysys/tree.c @@ -335,54 +335,67 @@ void *tree_search_key(TREE *tree, const void *key, enum ha_rkey_function flag, void *custom_arg) { int cmp; - TREE_ELEMENT *element = tree->root; - TREE_ELEMENT **last_left_step_parent = NULL; - TREE_ELEMENT **last_equal_element = NULL; + TREE_ELEMENT *element= tree->root; + TREE_ELEMENT **last_left_step_parent= NULL, **last_right_step_parent= NULL; + TREE_ELEMENT **last_equal_element= NULL; /* - TODO: handle HA_READ_KEY_OR_PREV, HA_READ_BEFORE_KEY, HA_READ_PREFIX, - HA_READ_PREFIX_LAST flags if needed. + TODO: support for HA_READ_KEY_OR_PREV, HA_READ_PREFIX flags if needed. */ *parents = &tree->null_element; while (element != &tree->null_element) { - *++parents = element; - if ((cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree, element), - key)) == 0) + *++parents= element; + if ((cmp= (*tree->compare)(custom_arg, ELEMENT_KEY(tree, element), + key)) == 0) { switch (flag) { case HA_READ_KEY_EXACT: case HA_READ_KEY_OR_NEXT: - last_equal_element = parents; - cmp = 1; - break; + case HA_READ_BEFORE_KEY: + last_equal_element= parents; + cmp= 1; + break; case HA_READ_AFTER_KEY: - cmp = -1; - break; + cmp= -1; + break; + case HA_READ_PREFIX_LAST: + case HA_READ_PREFIX_LAST_OR_PREV: + last_equal_element= parents; + cmp= -1; + break; default: - return NULL; + return NULL; } } if (cmp < 0) /* element < key */ { - element = element->right; + last_right_step_parent= parents; + element= element->right; } else { - last_left_step_parent = parents; - element = element->left; + last_left_step_parent= parents; + element= element->left; } } switch (flag) { case HA_READ_KEY_EXACT: - *last_pos = last_equal_element; + case HA_READ_PREFIX_LAST: + *last_pos= last_equal_element; break; case HA_READ_KEY_OR_NEXT: - *last_pos = last_equal_element ? last_equal_element : last_left_step_parent; + *last_pos= last_equal_element ? last_equal_element : last_left_step_parent; break; case HA_READ_AFTER_KEY: - *last_pos = last_left_step_parent; + *last_pos= last_left_step_parent; + break; + case HA_READ_PREFIX_LAST_OR_PREV: + *last_pos= last_equal_element ? last_equal_element : last_right_step_parent; + break; + case HA_READ_BEFORE_KEY: + *last_pos= last_right_step_parent; break; default: return NULL; From 0c349665959e300485b7f64119cb20bdce5cd189 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Nov 2002 15:16:56 +0500 Subject: [PATCH 70/89] Correct view of sort.c and mi_too_big_key_for_sort() myisam/mi_check.c: Correct mi_too_big_key_for_sort() myisam/sort.c: Correct view, according rules --- myisam/mi_check.c | 5 +---- myisam/sort.c | 13 +++++++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/myisam/mi_check.c b/myisam/mi_check.c index ba90b2c5bcf..d3222a770a8 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -3682,10 +3682,7 @@ static my_bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows) key_maxlength+=ft_max_word_len_for_sort-HA_FT_MAXLEN; return (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY | HA_FULLTEXT) && ((ulonglong) rows * key_maxlength > - (ulonglong) myisam_max_temp_length || - (ulonglong) rows * (key_maxlength - key->minlength) / 2 > - myisam_max_extra_temp_length || - (rows == 0 && (key_maxlength / key->minlength) > 2))); + (ulonglong) myisam_max_temp_length)); } diff --git a/myisam/sort.c b/myisam/sort.c index 7152855a54b..24a76f11823 100644 --- a/myisam/sort.c +++ b/myisam/sort.c @@ -73,13 +73,14 @@ static int NEAR_F merge_index(MI_SORT_PARAM *,uint,uchar **,BUFFPEK *, int, IO_CACHE *); static int NEAR_F write_keys_varlen(MI_SORT_PARAM *info,uchar **sort_keys, - uint count, BUFFPEK *buffpek,IO_CACHE *tempfile); + uint count, BUFFPEK *buffpek, + IO_CACHE *tempfile); static uint NEAR_F read_to_buffer_varlen(IO_CACHE *fromfile,BUFFPEK *buffpek, uint sort_length); -static int NEAR_F write_merge_key(MI_SORT_PARAM *info, IO_CACHE *to_file,char* key, - uint sort_length, uint count) ; -static int NEAR_F write_merge_key_varlen(MI_SORT_PARAM *info, IO_CACHE *to_file,char* key, - uint sort_length, uint count); +static int NEAR_F write_merge_key(MI_SORT_PARAM *info, IO_CACHE *to_file, + char* key, uint sort_length, uint count); +static int NEAR_F write_merge_key_varlen(MI_SORT_PARAM *info, IO_CACHE *to_file, + char* key, uint sort_length, uint count); inline int my_var_write(MI_SORT_PARAM *info,IO_CACHE *to_file,char *bufs); /* Creates a index of sorted keys @@ -786,7 +787,7 @@ static uint NEAR_F read_to_buffer_varlen(IO_CACHE *fromfile, BUFFPEK *buffpek, return((uint) -1); buffpek->file_pos+=length_of_key; buffp = buffp + sort_length; - } + } buffpek->key=buffpek->base; buffpek->count-= count; buffpek->mem_count= count; From 09fc04ad5fc768e041974b5254d2ca0452111570 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Nov 2002 15:19:42 +0400 Subject: [PATCH 71/89] ::index_read_last() method has been added --- sql/ha_heap.cc | 10 +++++++++- sql/ha_heap.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 4a3b9495f6f..fb4061b31e0 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -81,6 +81,15 @@ int ha_heap::index_read(byte * buf, const byte * key, uint key_len, return error; } +int ha_heap::index_read_last(byte *buf, const byte *key, uint key_len) +{ + statistic_increment(ha_read_key_count, &LOCK_status); + int error= heap_rkey(file, buf, active_index, key, key_len, + HA_READ_PREFIX_LAST); + table->status= error ? STATUS_NOT_FOUND : 0; + return error; +} + int ha_heap::index_read_idx(byte * buf, uint index, const byte * key, uint key_len, enum ha_rkey_function find_flag) { @@ -90,7 +99,6 @@ int ha_heap::index_read_idx(byte * buf, uint index, const byte * key, return error; } - int ha_heap::index_next(byte * buf) { statistic_increment(ha_read_next_count,&LOCK_status); diff --git a/sql/ha_heap.h b/sql/ha_heap.h index f82a1a460d8..fe874dab3f2 100644 --- a/sql/ha_heap.h +++ b/sql/ha_heap.h @@ -67,6 +67,7 @@ class ha_heap: public handler uint key_len, enum ha_rkey_function find_flag); int index_read_idx(byte * buf, uint idx, const byte * key, uint key_len, enum ha_rkey_function find_flag); + int index_read_last(byte * buf, const byte * key, uint key_len); int index_next(byte * buf); int index_prev(byte * buf); int index_first(byte * buf); From 3284c39a1fca442cd4f803df0245e248a349bd16 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Nov 2002 15:28:23 +0400 Subject: [PATCH 72/89] Makefile.am: libmysys.a is needed for my_errno regex/Makefile.am: libmysys.a is needed for my_errno --- regex/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/regex/Makefile.am b/regex/Makefile.am index 2e23efcbf2a..fe72f29b16c 100644 --- a/regex/Makefile.am +++ b/regex/Makefile.am @@ -17,7 +17,7 @@ INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include noinst_LIBRARIES = libregex.a -LDADD = libregex.a ../strings/libmystrings.a +LDADD = libregex.a ../strings/libmystrings.a ../mysys/libmysys.a noinst_HEADERS = cclass.h cname.h regex2.h utils.h engine.c regex.h libregex_a_SOURCES = regerror.c regcomp.c regexec.c regfree.c reginit.c noinst_PROGRAMS = re From b01993fd4ef8e694cb4dbb49912b6ddee73e6095 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Nov 2002 16:10:29 +0100 Subject: [PATCH 73/89] Fixed the reduce/reduce conflicts introduced by subselects. sql/sql_yacc.yy: Fixed the reduce/reduce conflicts introduced by subselects by breaking select_init apart. --- sql/sql_yacc.yy | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index cb1c7fed838..4c8a257bcd3 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1635,17 +1635,9 @@ table_to_table: select: select_init { Lex->sql_command=SQLCOM_SELECT; }; +/* Need select_init2 for subselects. */ select_init: - SELECT_SYM select_part2 - { - LEX *lex= Lex; - if (lex->current_select->set_braces(false)) - { - send_error(lex->thd, ER_SYNTAX_ERROR); - YYABORT; - } - } - union + SELECT_SYM select_init2 | '(' SELECT_SYM select_part2 ')' { @@ -1661,6 +1653,19 @@ select_init: sel->master_unit(); } union_opt; +select_init2: + select_part2 + { + LEX *lex= Lex; + if (lex->current_select->set_braces(false)) + { + send_error(lex->thd, ER_SYNTAX_ERROR); + YYABORT; + } + } + union + ; + select_part2: { LEX *lex=Lex; @@ -4388,7 +4393,7 @@ singleval_subselect: }; singleval_subselect_init: - select_init + select_init2 { $$= new Item_singleval_subselect(YYTHD, Lex->current_select->master_unit()-> @@ -4403,7 +4408,7 @@ exists_subselect: }; exists_subselect_init: - select_init + select_init2 { $$= new Item_exists_subselect(YYTHD, Lex->current_select->master_unit()-> @@ -4418,13 +4423,13 @@ in_subselect: }; in_subselect_init: - select_init + select_init2 { $$= Lex->current_select->master_unit()->first_select(); }; subselect_start: - '(' + '(' SELECT_SYM { if (mysql_new_select(Lex, 1)) YYABORT; From 37a9917243fad186c475f05a19190719ebac4083 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Nov 2002 17:25:41 +0100 Subject: [PATCH 74/89] INSERT ... UPDATE syntax (syntax only) sql_yacc.yy and sql_parse.cc cleanup sql/lex.h: INSERT ... UPDATE syntax sql/sql_parse.cc: merged SQLCOM_REPLACE and SQLCOM_INSERT the same way their _SELECT counterparts were merged long time ago - just to remove duplicate code and be consistent :) now nobody needs SQLCOM_REPLACE* at all :)) sql/sql_yacc.yy: INSERT ... UPDATE syntax cleanup --- sql/lex.h | 3 +- sql/sql_parse.cc | 34 ++++++--------- sql/sql_yacc.yy | 109 ++++++++++++++++++++++++----------------------- 3 files changed, 71 insertions(+), 75 deletions(-) diff --git a/sql/lex.h b/sql/lex.h index 768d995b68b..e55d1cbd4b0 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -135,6 +135,7 @@ static SYMBOL symbols[] = { { "DROP", SYM(DROP),0,0}, { "DUMPFILE", SYM(DUMPFILE),0,0}, { "DYNAMIC", SYM(DYNAMIC_SYM),0,0}, + { "DUPLICATE", SYM(DUPLICATE),0,0}, { "ERRORS", SYM(ERRORS),0,0}, { "END", SYM(END),0,0}, { "ELSE", SYM(ELSE),0,0}, @@ -342,7 +343,7 @@ static SYMBOL symbols[] = { { "SQL_CALC_FOUND_ROWS", SYM(SQL_CALC_FOUND_ROWS),0,0}, { "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM), 0, 0}, { "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT),0,0}, - { "SQL_THREAD", SYM(SQL_THREAD),0,0}, + { "SQL_THREAD", SYM(SQL_THREAD),0,0}, { "SSL", SYM(SSL_SYM),0,0}, { "STRAIGHT_JOIN", SYM(STRAIGHT_JOIN),0,0}, { "START", SYM(START_SYM),0,0}, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a410a9f2d7e..529a8b396f9 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1905,7 +1905,7 @@ mysql_execute_command(THD *thd) select_lex->select_limit, lex->duplicates); } - else + else { multi_update *result; uint table_count; @@ -1932,8 +1932,8 @@ mysql_execute_command(THD *thd) if ((res=open_and_lock_tables(thd,tables))) break; unit->select_limit_cnt= HA_POS_ERROR; - if (!setup_fields(thd,tables,select_lex->item_list,1,0,0) && - !setup_fields(thd,tables,lex->value_list,0,0,0) && + if (!setup_fields(thd,tables,select_lex->item_list,1,0,0) && + !setup_fields(thd,tables,lex->value_list,0,0,0) && !thd->fatal_error && (result=new multi_update(thd,tables,select_lex->item_list, lex->duplicates, table_count))) @@ -1946,7 +1946,7 @@ mysql_execute_command(THD *thd) total_list.push_back(item); while ((item=value_list++)) total_list.push_back(item); - + res= mysql_select(thd, tables, total_list, select_lex->where, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL, @@ -1960,26 +1960,20 @@ mysql_execute_command(THD *thd) res= -1; // Error is not sent close_thread_tables(thd); } - break; + break; + case SQLCOM_REPLACE: case SQLCOM_INSERT: - if (check_access(thd,INSERT_ACL,tables->db,&tables->grant.privilege)) + { + ulong privilege= (lex->duplicates == DUP_REPLACE ? + INSERT_ACL | DELETE_ACL : INSERT_ACL); + if (check_access(thd,privilege,tables->db,&tables->grant.privilege)) goto error; /* purecov: inspected */ - if (grant_option && check_grant(thd,INSERT_ACL,tables)) + if (grant_option && check_grant(thd,privilege,tables)) goto error; res = mysql_insert(thd,tables,lex->field_list,lex->many_values, lex->duplicates); break; - case SQLCOM_REPLACE: - if (check_access(thd,INSERT_ACL | DELETE_ACL, - tables->db,&tables->grant.privilege)) - goto error; /* purecov: inspected */ - if (grant_option && check_grant(thd,INSERT_ACL | DELETE_ACL, - tables)) - - goto error; - res = mysql_insert(thd,tables,lex->field_list,lex->many_values, - DUP_REPLACE); - break; + } case SQLCOM_REPLACE_SELECT: case SQLCOM_INSERT_SELECT: { @@ -1989,8 +1983,8 @@ mysql_execute_command(THD *thd) select privileges for the rest */ { - ulong privilege= (lex->sql_command == SQLCOM_INSERT_SELECT ? - INSERT_ACL : INSERT_ACL | DELETE_ACL); + ulong privilege= (lex->duplicates == DUP_REPLACE ? + INSERT_ACL | DELETE_ACL : INSERT_ACL); TABLE_LIST *save_next=tables->next; tables->next=0; if (check_access(thd, privilege, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 4c8a257bcd3..f2664bd70ea 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -204,6 +204,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token DES_KEY_FILE %token DISABLE_SYM %token DISTINCT +%token DUPLICATE %token DYNAMIC_SYM %token ENABLE_SYM %token ENCLOSED @@ -642,7 +643,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); repair restore backup analyze check field_list field_list_item field_spec kill select_item_list select_item values_list no_braces - limit_clause delete_limit_clause fields opt_values values + opt_limit_clause delete_limit_clause fields opt_values values procedure_list procedure_list2 procedure_item when_list2 expr_list2 handler opt_precision opt_ignore opt_column opt_restrict @@ -660,7 +661,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); table_to_table_list table_to_table opt_table_list opt_as handler_rkey_function handler_read_or_scan single_multi table_wild_list table_wild_one opt_wild - union union_list union_option + union_clause union_list union_option precision opt_on_delete_item subselect_start opt_and subselect_end select_var_list select_var_list_init help opt_len END_OF_INPUT @@ -883,7 +884,7 @@ create3: lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; mysql_init_select(lex); } - select_options select_item_list opt_select_from union {} + select_options select_item_list opt_select_from union_clause {} ; opt_as: @@ -918,27 +919,23 @@ create_table_options: | create_table_option create_table_options; | create_table_option ',' create_table_options; -o_eq: - /* empty */ - | EQ {}; - create_table_option: - TYPE_SYM o_eq table_types { Lex->create_info.db_type= $3; } - | MAX_ROWS o_eq ulonglong_num { Lex->create_info.max_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MAX_ROWS;} - | MIN_ROWS o_eq ulonglong_num { Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;} - | AVG_ROW_LENGTH o_eq ULONG_NUM { Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;} - | PASSWORD o_eq TEXT_STRING { Lex->create_info.password=$3.str; } - | COMMENT_SYM o_eq TEXT_STRING { Lex->create_info.comment=$3.str; } - | AUTO_INC o_eq ulonglong_num { Lex->create_info.auto_increment_value=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AUTO;} - | PACK_KEYS_SYM o_eq ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_PACK_KEYS : HA_OPTION_NO_PACK_KEYS; Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;} - | PACK_KEYS_SYM o_eq DEFAULT { Lex->create_info.table_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS); Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;} - | CHECKSUM_SYM o_eq ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; } - | DELAY_KEY_WRITE_SYM o_eq ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE; } - | ROW_FORMAT_SYM o_eq row_types { Lex->create_info.row_type= $3; } - | RAID_TYPE o_eq raid_types { Lex->create_info.raid_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} - | RAID_CHUNKS o_eq ULONG_NUM { Lex->create_info.raid_chunks= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} - | RAID_CHUNKSIZE o_eq ULONG_NUM { Lex->create_info.raid_chunksize= $3*RAID_BLOCK_SIZE; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} - | UNION_SYM o_eq '(' table_list ')' + TYPE_SYM opt_equal table_types { Lex->create_info.db_type= $3; } + | MAX_ROWS opt_equal ulonglong_num { Lex->create_info.max_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MAX_ROWS;} + | MIN_ROWS opt_equal ulonglong_num { Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;} + | AVG_ROW_LENGTH opt_equal ULONG_NUM { Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;} + | PASSWORD opt_equal TEXT_STRING { Lex->create_info.password=$3.str; } + | COMMENT_SYM opt_equal TEXT_STRING { Lex->create_info.comment=$3.str; } + | AUTO_INC opt_equal ulonglong_num { Lex->create_info.auto_increment_value=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AUTO;} + | PACK_KEYS_SYM opt_equal ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_PACK_KEYS : HA_OPTION_NO_PACK_KEYS; Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;} + | PACK_KEYS_SYM opt_equal DEFAULT { Lex->create_info.table_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS); Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;} + | CHECKSUM_SYM opt_equal ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; } + | DELAY_KEY_WRITE_SYM opt_equal ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE; } + | ROW_FORMAT_SYM opt_equal row_types { Lex->create_info.row_type= $3; } + | RAID_TYPE opt_equal raid_types { Lex->create_info.raid_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} + | RAID_CHUNKS opt_equal ULONG_NUM { Lex->create_info.raid_chunks= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} + | RAID_CHUNKSIZE opt_equal ULONG_NUM { Lex->create_info.raid_chunksize= $3*RAID_BLOCK_SIZE; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} + | UNION_SYM opt_equal '(' table_list ')' { /* Move the union list to the merge_list */ LEX *lex=Lex; @@ -951,19 +948,19 @@ create_table_option: table_list->next=0; lex->create_info.used_fields|= HA_CREATE_USED_UNION; } - | opt_default CHARSET o_eq charset_name_or_default + | opt_default CHARSET opt_equal charset_name_or_default { Lex->create_info.table_charset= $4; Lex->create_info.used_fields|= HA_CREATE_USED_CHARSET; } - | opt_default CHAR_SYM SET o_eq charset_name_or_default + | opt_default CHAR_SYM SET opt_equal charset_name_or_default { Lex->create_info.table_charset= $5; Lex->create_info.used_fields|= HA_CREATE_USED_CHARSET; } - | INSERT_METHOD o_eq merge_insert_types { Lex->create_info.merge_insert_method= $3; Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;} - | DATA_SYM DIRECTORY_SYM o_eq TEXT_STRING { Lex->create_info.data_file_name= $4.str; } - | INDEX DIRECTORY_SYM o_eq TEXT_STRING { Lex->create_info.index_file_name= $4.str; }; + | INSERT_METHOD opt_equal merge_insert_types { Lex->create_info.merge_insert_method= $3; Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;} + | DATA_SYM DIRECTORY_SYM opt_equal TEXT_STRING { Lex->create_info.data_file_name= $4.str; } + | INDEX DIRECTORY_SYM opt_equal TEXT_STRING { Lex->create_info.index_file_name= $4.str; }; table_types: ISAM_SYM { $$= DB_TYPE_ISAM; } @@ -990,7 +987,7 @@ merge_insert_types: | LAST_SYM { $$= MERGE_INSERT_TO_LAST; }; opt_select_from: - /* empty */ + opt_limit_clause {} | select_from select_lock_type; udf_func_type: @@ -1663,7 +1660,7 @@ select_init2: YYABORT; } } - union + union_clause ; select_part2: @@ -1676,16 +1673,18 @@ select_part2: select_options select_item_list select_into select_lock_type; select_into: - limit_clause {} + opt_limit_clause {} + | FROM DUAL_SYM /* oracle compatibility: oracle always requires FROM + clause, and DUAL is system table without fields. + Is "SELECT 1 FROM DUAL" any better than + "SELECT 1" ? Hmmm :) */ + | into | select_from - | FROM DUAL_SYM - | opt_into - | opt_into select_from - | select_from opt_into; + | into select_from + | select_from into; select_from: - FROM join_table_list where_clause group_clause having_clause opt_order_clause limit_clause procedure_clause; - + FROM join_table_list where_clause group_clause having_clause opt_order_clause opt_limit_clause procedure_clause; select_options: /* empty*/ @@ -2460,7 +2459,7 @@ join_table: } | '{' ident join_table LEFT OUTER JOIN_SYM join_table ON expr '}' { add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; } - | '(' SELECT_SYM select_part3 ')' opt_table_alias + | '(' SELECT_SYM select_derived ')' opt_table_alias { LEX *lex=Lex; SELECT_LEX_UNIT *unit= lex->current_select->master_unit(); @@ -2471,7 +2470,7 @@ join_table: YYABORT; }; -select_part3: +select_derived: { LEX *lex= Lex; lex->derived_tables= true; @@ -2481,11 +2480,8 @@ select_part3: mysql_init_select(lex); lex->current_select->linkage= DERIVED_TABLE_TYPE; } - select_options select_item_list select_intoto; - -select_intoto: - limit_clause {} - | select_from; + select_options select_item_list opt_select_from + ; opt_outer: /* empty */ {} @@ -2675,7 +2671,7 @@ order_dir: | DESC { $$ =0; }; -limit_clause: +opt_limit_clause: /* empty */ {} | LIMIT { @@ -2792,7 +2788,7 @@ select_var_ident: '@' ident_or_text } ; -opt_into: +into: INTO OUTFILE TEXT_STRING { LEX *lex=Lex; @@ -2904,7 +2900,7 @@ insert: { Select->set_lock_for_tables($3); } - insert_field_spec + insert_field_spec opt_insert_update ; replace: @@ -2977,7 +2973,7 @@ insert_values: mysql_init_select(lex); } select_options select_item_list select_from select_lock_type - union {} + union_clause {} ; values_list: @@ -3042,6 +3038,11 @@ expr_or_default: | DEFAULT {$$= new Item_default(); } ; +opt_insert_update: + /* empty */ + | ON DUPLICATE KEY_SYM UPDATE_SYM SET update_list + ; + /* Update rows in a table */ update: @@ -3215,7 +3216,7 @@ show_param: lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS; lex->select_lex.select_limit= lex->thd->variables.select_limit; lex->select_lex.offset_limit= 0L; - } limit_clause + } opt_limit_clause | keys_or_index FROM table_ident opt_db { Lex->sql_command= SQLCOM_SHOW_KEYS; @@ -3243,9 +3244,9 @@ show_param: { (void) create_select_for_variable("warning_count"); } | COUNT_SYM '(' '*' ')' ERRORS { (void) create_select_for_variable("error_count"); } - | WARNINGS {Select->offset_limit=0L;} limit_clause + | WARNINGS {Select->offset_limit=0L;} opt_limit_clause { Lex->sql_command = SQLCOM_SHOW_WARNS;} - | ERRORS {Select->offset_limit=0L;} limit_clause + | ERRORS {Select->offset_limit=0L;} opt_limit_clause { Lex->sql_command = SQLCOM_SHOW_ERRORS;} | STATUS_SYM wild { Lex->sql_command= SQLCOM_SHOW_STATUS; } @@ -3997,7 +3998,7 @@ handler: if (!lex->current_select->add_table_to_list($2, 0, 0)) YYABORT; } - handler_read_or_scan where_clause limit_clause { } + handler_read_or_scan where_clause opt_limit_clause { } ; handler_read_or_scan: @@ -4326,7 +4327,7 @@ rollback: */ -union: +union_clause: /* empty */ {} | union_list ; @@ -4378,7 +4379,7 @@ optional_order_or_limit: lex->current_select->select_limit= lex->thd->variables.select_limit; } - opt_order_clause limit_clause + opt_order_clause opt_limit_clause ; union_option: From 6f80b711692d99d5d197cece8fe978eab6f1f3ec Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Nov 2002 19:29:26 +0200 Subject: [PATCH 75/89] fixed * without tables in IN bug fixed sunction-test select in IN bug fixed unions in subselect bug include/mysqld_error.h: new warning mysql-test/r/subselect.result: test of * without tables in IN test of sunction-test select in IN test of unions in subselect mysql-test/t/subselect.test: test of * without tables in IN test of sunction-test select in IN test of unions in subselect sql/item.cc: fixed * substitution without tables sql/item_subselect.cc: fixed subselect rewriting with function-test subselect sql/item_subselect.h: mechanism for subselect removing sql/share/czech/errmsg.txt: new warning sql/share/danish/errmsg.txt: new warning sql/share/dutch/errmsg.txt: new warning sql/share/english/errmsg.txt: new warning sql/share/estonian/errmsg.txt: new warning sql/share/french/errmsg.txt: new warning sql/share/german/errmsg.txt: new warning sql/share/greek/errmsg.txt: new warning sql/share/hungarian/errmsg.txt: new warning sql/share/italian/errmsg.txt: new warning sql/share/japanese/errmsg.txt: new warning sql/share/korean/errmsg.txt: new warning sql/share/norwegian-ny/errmsg.txt: new warning sql/share/norwegian/errmsg.txt: new warning sql/share/polish/errmsg.txt: new warning sql/share/portuguese/errmsg.txt: new warning sql/share/romanian/errmsg.txt: new warning sql/share/russian/errmsg.txt: new warning sql/share/serbian/errmsg.txt: new warning sql/share/slovak/errmsg.txt: new warning sql/share/spanish/errmsg.txt: new warning sql/share/swedish/errmsg.txt: new warning sql/share/ukrainian/errmsg.txt: new warning sql/sql_base.cc: fixed case on no name field in UNION subselect sql/sql_lex.cc: mechanisp of removing single subselect for optimisation purposes sql/sql_lex.h: mechanisp of removing single subselect for optimisation purposes sql/sql_parse.cc: error handling sql/sql_union.cc: fixed unions in subselect sql/sql_yacc.yy: fixed Lex->describe flag appearence --- include/mysqld_error.h | 3 +- mysql-test/r/subselect.result | 27 +++++++++++++ mysql-test/t/subselect.test | 14 +++++++ sql/item.cc | 50 +++++++++++------------ sql/item_subselect.cc | 66 +++++++++++++++++++++++++++---- sql/item_subselect.h | 6 +++ sql/share/czech/errmsg.txt | 1 + sql/share/danish/errmsg.txt | 1 + sql/share/dutch/errmsg.txt | 1 + sql/share/english/errmsg.txt | 1 + sql/share/estonian/errmsg.txt | 1 + sql/share/french/errmsg.txt | 1 + sql/share/german/errmsg.txt | 1 + sql/share/greek/errmsg.txt | 1 + sql/share/hungarian/errmsg.txt | 1 + sql/share/italian/errmsg.txt | 1 + sql/share/japanese/errmsg.txt | 1 + sql/share/korean/errmsg.txt | 1 + sql/share/norwegian-ny/errmsg.txt | 1 + sql/share/norwegian/errmsg.txt | 1 + sql/share/polish/errmsg.txt | 1 + sql/share/portuguese/errmsg.txt | 1 + sql/share/romanian/errmsg.txt | 1 + sql/share/russian/errmsg.txt | 1 + sql/share/serbian/errmsg.txt | 1 + sql/share/slovak/errmsg.txt | 1 + sql/share/spanish/errmsg.txt | 1 + sql/share/swedish/errmsg.txt | 1 + sql/share/ukrainian/errmsg.txt | 1 + sql/sql_base.cc | 2 +- sql/sql_lex.cc | 25 ++++++++++++ sql/sql_lex.h | 3 ++ sql/sql_parse.cc | 12 ++++-- sql/sql_union.cc | 4 ++ sql/sql_yacc.yy | 3 +- 35 files changed, 199 insertions(+), 39 deletions(-) diff --git a/include/mysqld_error.h b/include/mysqld_error.h index ed83c5e57a8..d2ed22b3bfd 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -262,4 +262,5 @@ #define ER_CYCLIC_REFERENCE 1243 #define ER_AUTO_CONVERT 1244 #define ER_ILLEGAL_REFERENCE 1245 -#define ER_ERROR_MESSAGES 246 +#define ER_SELECT_REDUCED 1246 +#define ER_ERROR_MESSAGES 247 diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 990c313686a..21ff3876f7c 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -513,3 +513,30 @@ x y 4 2 2 1 drop table t1, t2; +SELECT * FROM (SELECT 1) WHERE 1 IN (SELECT *); +No tables used +drop table if exists t; +CREATE TABLE t (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin1; +INSERT INTO t VALUES (1),(2); +SELECT * FROM t WHERE id IN (SELECT 1); +id +1 +EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t ref id id 5 const 1 Using where; Using index +Warnings: +Note 1246 Select 2 was reduced during optimisation +SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3); +id +1 +EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t index NULL id 5 NULL 2 Using where; Using index +2 DEPENDENT SUBSELECT No tables used +3 UNION No tables used +SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 3); +id +SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 2); +id +2 +drop table if exists t; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index c9ab505bffb..a0375bb84f0 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -306,3 +306,17 @@ select * from t1; replace LOW_PRIORITY into t1 (x, y) VALUES ((SELECT a+1 FROM t2), (SELECT a FROM t2)); select * from t1; drop table t1, t2; + +-- error 1096 +SELECT * FROM (SELECT 1) WHERE 1 IN (SELECT *); +drop table if exists t; +CREATE TABLE t (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin1; +INSERT INTO t VALUES (1),(2); +SELECT * FROM t WHERE id IN (SELECT 1); +EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1); +SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3); +EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3); +SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 3); +SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 2); +drop table if exists t; + diff --git a/sql/item.cc b/sql/item.cc index ece627f9fe3..a81b4f2394b 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -463,41 +463,41 @@ bool Item_asterisk_remover::fix_fields(THD *thd, ((Item_field*) item)->field_name[0] == '*') { Item_field *fitem= (Item_field*) item; - if (!list->next || fitem->db_name || fitem->table_name) - { - TABLE_LIST *table= find_table_in_list(list, - fitem->db_name, - fitem->table_name); - if (table) + if (list) + if (!list->next || fitem->db_name || fitem->table_name) { - TABLE * tb= table->table; - if (find_table_in_list(table->next, fitem->db_name, - fitem->table_name) != 0 || - tb->fields == 1) + TABLE_LIST *table= find_table_in_list(list, + fitem->db_name, + fitem->table_name); + if (table) { - if ((item= new Item_field(tb->field[0]))) + TABLE * tb= table->table; + if (find_table_in_list(table->next, fitem->db_name, + fitem->table_name) != 0 || + tb->fields == 1) { - res= 0; - tb->field[0]->query_id= thd->query_id; - tb->used_keys&= tb->field[0]->part_of_key; - tb->used_fields= tb->fields; + if ((item= new Item_field(tb->field[0]))) + { + res= 0; + tb->field[0]->query_id= thd->query_id; + tb->used_keys&= tb->field[0]->part_of_key; + tb->used_fields= tb->fields; + } + else + thd->fatal_error= 1; // can't create Item => out of memory } else - thd->fatal_error= 1; // can't create Item => out of memory + my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), + MYF(0)); } else - my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), - MYF(0)); + my_error(ER_BAD_TABLE_ERROR, MYF(0), fitem->table_name); } else - if (!fitem->table_name) - my_error(ER_NO_TABLES_USED, MYF(0)); - else - my_error(ER_BAD_TABLE_ERROR, MYF(0), fitem->table_name); - } + my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), + MYF(0)); else - my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), - MYF(0)); + my_error(ER_NO_TABLES_USED, MYF(0)); } else res= item->fix_fields(thd, list, &item); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 555b7ae45c3..e0bfbe01c9b 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -33,7 +33,7 @@ SUBSELECT TODO: #include "sql_select.h" Item_subselect::Item_subselect(): - Item_result_field(), engine_owner(1), value_assigned(0) + Item_result_field(), engine_owner(1), value_assigned(0), substitution(0) { assign_null(); /* @@ -89,6 +89,13 @@ void Item_subselect::make_field (Send_field *tmp_field) bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { + if (substitution) + { + (*ref)= substitution; + engine->exclude(); + return substitution->fix_fields(thd, tables, ref); + } + char const *save_where= thd->where; int res= engine->prepare(); if (!res) @@ -291,12 +298,12 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, else item= (Item*) sl->item_list.pop(); - left_expr= new Item_outer_select_context_saver(left_expr); + Item *expr= new Item_outer_select_context_saver(left_expr); if (sl->having || sl->with_sum_func || sl->group_list.first) { sl->item_list.push_back(item); - item= (*func)(left_expr, new Item_ref(sl->item_list.head_ref(), + item= (*func)(expr, new Item_ref(sl->item_list.head_ref(), 0, "")); if (sl->having) sl->having= new Item_cond_and(sl->having, item); @@ -307,11 +314,42 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, { sl->item_list.empty(); sl->item_list.push_back(new Item_int(1)); - item= (*func)(left_expr, new Item_asterisk_remover(item)); - if (sl->where) - sl->where= new Item_cond_and(sl->where, item); + if (sl->table_list.elements) + { + item= (*func)(expr, new Item_asterisk_remover(item)); + if (sl->where) + sl->where= new Item_cond_and(sl->where, item); + else + sl->where= item; + } else - sl->where= item; + { + if (item->type() == Item::FIELD_ITEM && + ((Item_field*) item)->field_name[0] == '*') + { + my_error(ER_NO_TABLES_USED, MYF(0)); + DBUG_VOID_RETURN; + } + if (select_lex->next_select()) + { + // it is in union => we should perform it + sl->having= (*func)(expr, item); + } + else + { + // it is single select without tables => possible optimization + item= (*func)(left_expr, item); + substitution= item; + THD *thd= current_thd; + if (thd->lex.describe) + { + char warn_buff[MYSQL_ERRMSG_SIZE]; + sprintf(warn_buff, ER(ER_SELECT_REDUCED), sl->select_number); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_SELECT_REDUCED, warn_buff); + } + } + } } } DBUG_VOID_RETURN; @@ -502,3 +540,17 @@ bool subselect_union_engine::check_loop(uint id) DBUG_RETURN(1); DBUG_RETURN(0); } + +void subselect_single_select_engine::exclude() +{ + select_lex->master_unit()->exclude_level(); + //if (current_thd->lex->describe) +} + +void subselect_union_engine::exclude() +{ + unit->exclude_level(); + // for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select()) + // if (sl->join && sl->join->check_loop(id)) + // DBUG_RETURN(1); +} diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 3a635ace8ba..d323dab51f1 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -36,6 +36,8 @@ class Item_subselect :public Item_result_field my_bool engine_owner; /* Is this item owner of engine */ my_bool value_assigned; /* value already assigned to subselect */ protected: + /* substitution instead of subselect in case of optimization */ + Item *substitution; /* engine that perform execution of subselect (single select or union) */ subselect_engine *engine; /* allowed number of columns (1 for single value subqueries) */ @@ -45,6 +47,7 @@ public: Item_subselect(); Item_subselect(Item_subselect *item) { + substitution= item->substitution; null_value= item->null_value; decimals= item->decimals; max_columns= item->max_columns; @@ -213,6 +216,7 @@ public: virtual bool depended()= 0; /* depended from outer select */ enum Item_result type() { return res_type; } virtual bool check_loop(uint id)= 0; + virtual void exclude()= 0; }; class subselect_single_select_engine: public subselect_engine @@ -232,6 +236,7 @@ public: uint cols(); bool depended(); bool check_loop(uint id); + void exclude(); }; class subselect_union_engine: public subselect_engine @@ -248,4 +253,5 @@ public: uint cols(); bool depended(); bool check_loop(uint id); + void exclude(); }; diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 4838de12ed6..ff73914199f 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -256,3 +256,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 91fa06f184f..f0c78032814 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -250,3 +250,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 50c70ce0d2c..cf8d7ecc6b3 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -258,3 +258,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 1c5564b9ad5..963ba7a29bf 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -247,3 +247,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 8a49cc7fb69..759f569e396 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -252,3 +252,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index a8b602ee295..de2d7ee6854 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -247,3 +247,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index cb449738d61..166d604e013 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -250,3 +250,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index f6c650468b1..9533c25a30d 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -247,3 +247,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index fe47d79a101..07597be6214 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -249,3 +249,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 0d951857392..772f7ba9532 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -247,3 +247,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index df78901a6e9..42b77e56f6b 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -249,3 +249,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index c20110e1aa5..b6a8a403213 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -247,3 +247,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index c75c3ed6140..54cb3bb77e3 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -249,3 +249,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index b5a660773ab..9a6a5f5e427 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -249,3 +249,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index c65a16bf1e4..6488ca27782 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -251,3 +251,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index 355ae90c157..1e50e8bff5e 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -247,3 +247,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index c7a5b41deac..d999661a40b 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -251,3 +251,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s" "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 35134e6d9d5..fb4278c2ae9 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -250,3 +250,4 @@ "Циклическая ссылка на подзапрос", "Преобразование поля '%s' из %s в %s", "Ссылка '%-.64s' не поддерживается (%s)", +"Select %u был упразднен в процессе оптимизации", diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index 354c0bdfac4..526f5834094 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -243,3 +243,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 4f49aeb2f6e..db06c0f4881 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -255,3 +255,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 1bd4aed6897..40d36a571f2 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -248,3 +248,4 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index af3f7ca33dd..817d8acbfef 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -247,3 +247,4 @@ "Syklisk referens i subselect", "Konvertar kolumn '%s' frЕn %s till %s", "Reference '%-.64s' not supported (%s)", +"Select %u was reduced during optimisation", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index c5bfff130fd..a95043f9fcd 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -252,3 +252,4 @@ "Циклiчне посилання на пiдзапит", "Перетворення стовбца '%s' з %s у %s", "Посилання '%-.64s' не пiдтримуется (%s)", +"Select %u was скасовано при оптимiзацii", diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 8aa33a65ce3..b052fb066e0 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2082,7 +2082,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List &fields, while ((item=it++)) { - if (item->type() == Item::FIELD_ITEM && + if (item->type() == Item::FIELD_ITEM && ((Item_field*) item)->field_name && ((Item_field*) item)->field_name[0] == '*') { uint elem= fields.elements; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 5104487c700..041e9c1d892 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1058,6 +1058,31 @@ void st_select_lex_node::exclude() */ } +void st_select_lex_unit::exclude_level() +{ + SELECT_LEX_UNIT *units= 0, **units_last= &units; + for(SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) + { + if (sl->link_prev && (*sl->link_prev= sl->link_next)) + sl->link_next->link_prev= sl->link_prev; + SELECT_LEX_UNIT **last= 0; + for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit()) + last= (SELECT_LEX_UNIT**)&(u->next); + if (last) + { + (*units_last)= sl->first_inner_unit(); + units_last= last; + } + } + if (units) + { + (*prev)= units; + (*units_last)= (SELECT_LEX_UNIT*)next; + } + else + (*prev)= next; +} + st_select_lex* st_select_lex_node::select_lex() { DBUG_ENTER("st_select_lex_node::select_lex (never should be called)"); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index b9691bb1059..4c5ca88b7b0 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -242,6 +242,8 @@ public: List *ignore_index= 0); virtual void set_lock_for_tables(thr_lock_type lock_type) {} void mark_as_dependent(st_select_lex *last); + + friend class st_select_lex_unit; private: void fast_exclude(); }; @@ -288,6 +290,7 @@ public: st_select_lex* outer_select(); st_select_lex* first_select() { return (st_select_lex*) slave; } st_select_lex_unit* next_unit() { return (st_select_lex_unit*) next; } + void st_select_lex_unit::exclude_level(); /* UNION methods */ int prepare(THD *thd, select_result *result); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a410a9f2d7e..26817bc30ac 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1329,7 +1329,6 @@ mysql_execute_command(THD *thd) */ thd->old_total_warn_count= thd->total_warn_count; - thd->net.report_error= 0; if (thd->slave_thread) { /* @@ -2957,6 +2956,8 @@ mysql_parse(THD *thd, char *inBuf, uint length) mysql_init_query(thd); thd->query_length = length; + thd->net.report_error= 0; + if (query_cache_send_result_to_client(thd, inBuf, length) <= 0) { LEX *lex=lex_start(thd, (uchar*) inBuf, length); @@ -2969,8 +2970,13 @@ mysql_parse(THD *thd, char *inBuf, uint length) } else { - mysql_execute_command(thd); - query_cache_end_of_result(&thd->net); + if (thd->net.report_error) + send_error(thd, 0, NullS); + else + { + mysql_execute_command(thd); + query_cache_end_of_result(&thd->net); + } } } else diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 0e6de306c0d..d448a5204e2 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -214,7 +214,11 @@ int st_select_lex_unit::exec() if (dependent || !item || !item->assigned()) { if (optimized && item && item->assigned()) + { item->assigned(0); // We will reinit & rexecute unit + item->assign_null(); + table->file->delete_all_rows(); + } for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) { thd->lex.current_select= sl; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index cb1c7fed838..c4b3c31d91b 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3323,11 +3323,10 @@ describe: YYABORT; } opt_describe_column - | describe_command select + | describe_command { Lex->describe=1; } select { LEX *lex=Lex; lex->select_lex.options|= SELECT_DESCRIBE; - lex->describe=1; }; From 1c2d7aa88090255f21154e262f190c257c8c09ef Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Nov 2002 09:56:26 -0800 Subject: [PATCH 76/89] Get rid of pbool from my_list.h; and avoid using the my_global.h for clients --- client/insert_test.c | 1 - client/select_test.c | 1 - include/my_list.h | 2 +- mysys/list.c | 2 +- 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/client/insert_test.c b/client/insert_test.c index fb4890faf73..42691df6875 100644 --- a/client/insert_test.c +++ b/client/insert_test.c @@ -16,7 +16,6 @@ #include #include -#include #include "mysql.h" #define INSERT_QUERY "insert into test (name,num) values ('item %d', %d)" diff --git a/client/select_test.c b/client/select_test.c index d7f18c0f1f0..ee2a9192865 100644 --- a/client/select_test.c +++ b/client/select_test.c @@ -19,7 +19,6 @@ #endif #include #include -#include "my_global.h" #include "mysql.h" #define SELECT_QUERY "select name from test where num = %d" diff --git a/include/my_list.h b/include/my_list.h index 0f56d4c532b..056e1f13b36 100644 --- a/include/my_list.h +++ b/include/my_list.h @@ -32,7 +32,7 @@ extern LIST *list_add(LIST *root,LIST *element); extern LIST *list_delete(LIST *root,LIST *element); extern LIST *list_cons(void *data,LIST *root); extern LIST *list_reverse(LIST *root); -extern void list_free(LIST *root,pbool free_data); +extern void list_free(LIST *root,uint free_data); extern uint list_length(LIST *list); extern int list_walk(LIST *list,list_walk_action action,gptr argument); diff --git a/mysys/list.c b/mysys/list.c index ac9e1b979a0..17028e8e183 100644 --- a/mysys/list.c +++ b/mysys/list.c @@ -55,7 +55,7 @@ LIST *list_delete(LIST *root, LIST *element) } -void list_free(LIST *root, pbool free_data) +void list_free(LIST *root, uint free_data) { LIST *next; while (root) From c58b8afa49c7bea2fb3d478dd4146332da5b48ad Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Nov 2002 20:58:23 +0200 Subject: [PATCH 77/89] after review fix(CRUM) after merge fix sql/item.cc: after merge fix sql/item_cmpfunc.cc: after review fix sql/item_cmpfunc.h: after review fix --- sql/item.cc | 6 ++---- sql/item_cmpfunc.cc | 3 ++- sql/item_cmpfunc.h | 5 ++--- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index b6acaa9618a..603e3a57ce0 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -497,15 +497,13 @@ bool Item_asterisk_remover::fix_fields(THD *thd, thd->fatal_error= 1; // can't create Item => out of memory } else - my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), - MYF(0)); + my_error(ER_CARDINALITY_COL, MYF(0), 1); } else my_error(ER_BAD_TABLE_ERROR, MYF(0), fitem->table_name); } else - my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), - MYF(0)); + my_error(ER_CARDINALITY_COL, MYF(0), 1); else my_error(ER_NO_TABLES_USED, MYF(0)); } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 06dc3fca89d..146758600c0 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -129,7 +129,8 @@ void Item_bool_func2::fix_length_and_dec() int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) { owner= item; - func= comparator_matrix[type][owner->equal]; + func= comparator_matrix[type][(owner->functype() == Item_func::EQUAL_FUNC)? + 1:0]; if (type == ROW_RESULT) { uint n= args[0]->cols(); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index ca03d02aa77..74c9dec7ef8 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -34,9 +34,8 @@ class Item_bool_func2 :public Item_int_func { /* Bool with 2 string args */ protected: String tmp_value1,tmp_value2; - bool equal; public: - Item_bool_func2(Item *a,Item *b) :Item_int_func(a,b), equal(0) {} + Item_bool_func2(Item *a,Item *b) :Item_int_func(a,b) {} void fix_length_and_dec(); void set_cmp_func() { @@ -89,7 +88,7 @@ public: class Item_func_equal :public Item_bool_rowready_func2 { public: - Item_func_equal(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { equal=1; }; + Item_func_equal(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}; longlong val_int(); void fix_length_and_dec(); enum Functype functype() const { return EQUAL_FUNC; } From 4078d0deffb7720c2732be4bfea5fec107d40779 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Nov 2002 22:59:35 +0200 Subject: [PATCH 78/89] fixed bug IN subselect with ORDER mysql-test/r/subselect.result: test of IN subselect with ORDER mysql-test/t/subselect.test: test of IN subselect with ORDER --- mysql-test/r/subselect.result | 3 +++ mysql-test/t/subselect.test | 2 ++ sql/item_subselect.cc | 15 +++++++++++---- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 6d922201618..ea771938286 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -32,6 +32,9 @@ a 1 SELECT 1 FROM (SELECT (SELECT a)); Unknown column 'a' in 'field list' +SELECT * FROM (SELECT 1 as id) WHERE id IN (SELECT * FROM (SELECT 1 as id) ORDER BY id LIMIT 1); +id +1 drop table if exists t1,t2,t3,t4,t5,t6,t7,t8; create table t1 (a int); create table t2 (a int, b int); diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index a0375bb84f0..3db1402ba90 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -15,6 +15,8 @@ SELECT (SELECT 1), a; SELECT 1 as a FROM (SELECT 1) HAVING (SELECT a)=1; -- error 1054 SELECT 1 FROM (SELECT (SELECT a)); +SELECT * FROM (SELECT 1 as id) WHERE id IN (SELECT * FROM (SELECT 1 as id) ORDER BY id LIMIT 1); + drop table if exists t1,t2,t3,t4,t5,t6,t7,t8; create table t1 (a int); create table t2 (a int, b int); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 0497aaa6be7..6d55f7399c1 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -300,15 +300,22 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, Item *expr= new Item_outer_select_context_saver(left_expr); - if (sl->having || sl->with_sum_func || sl->group_list.first) + if (sl->having || sl->with_sum_func || sl->group_list.first || + sl->order_list.first) { sl->item_list.push_back(item); item= (*func)(expr, new Item_ref(sl->item_list.head_ref(), 0, (char*)"")); - if (sl->having) - sl->having= new Item_cond_and(sl->having, item); + if (sl->having || sl->with_sum_func || sl->group_list.first) + if (sl->having) + sl->having= new Item_cond_and(sl->having, item); + else + sl->having= item; else - sl->having= item; + if (sl->where) + sl->where= new Item_cond_and(sl->having, item); + else + sl->where= item; } else { From 3ec9f7e1c46de3f4bbbf54106d0eaae7d55b1b34 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Nov 2002 23:31:48 +0200 Subject: [PATCH 79/89] test of changing subselects tree --- mysql-test/r/subselect.result | 9 +++++++++ mysql-test/t/subselect.test | 2 ++ 2 files changed, 11 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index ea771938286..523c3af91c4 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -532,6 +532,15 @@ Note 1246 Select 2 was reduced during optimisation SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3); id 1 +SELECT * FROM t WHERE id IN (SELECT 1+(select 1)); +id +2 +EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1+(select 1)); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t ref id id 5 const 1 Using where; Using index +3 SUBSELECT No tables used +Warnings: +Note 1246 Select 2 was reduced during optimisation EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t index NULL id 5 NULL 2 Using where; Using index diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 3db1402ba90..17f3008b62e 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -317,6 +317,8 @@ INSERT INTO t VALUES (1),(2); SELECT * FROM t WHERE id IN (SELECT 1); EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1); SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3); +SELECT * FROM t WHERE id IN (SELECT 1+(select 1)); +EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1+(select 1)); EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3); SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 3); SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 2); From 5996e68fe2a1c92cae95067aaa65e35b6b71a4a4 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Nov 2002 10:17:43 +0400 Subject: [PATCH 80/89] mysql.h: renamed arg name to avoid a warning that it shadows global variable include/mysql.h: renamed arg name to avoid a warning that it shadows global variable --- include/mysql.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mysql.h b/include/mysql.h index 67558e39cdb..c8d3c48f7c3 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -483,8 +483,8 @@ MYSQL_STMT * STDCALL mysql_prepare(MYSQL * mysql, const char *query, unsigned long length); int STDCALL mysql_execute(MYSQL_STMT * stmt); unsigned long STDCALL mysql_param_count(MYSQL_STMT * stmt); -my_bool STDCALL mysql_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bind); -my_bool STDCALL mysql_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bind); +my_bool STDCALL mysql_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd); +my_bool STDCALL mysql_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd); my_bool STDCALL mysql_stmt_close(MYSQL_STMT * stmt); unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT * stmt); const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt); From 781a5bc81ad3fdd6111986a895e6025d6910773e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Nov 2002 11:15:15 +0400 Subject: [PATCH 81/89] Fixesd that wrong charset were used --- sql/item.cc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index 603e3a57ce0..740ec9418c4 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -775,7 +775,7 @@ int Item::save_in_field(Field *field) field->result_type() == STRING_RESULT) { String *result; - CHARSET_INFO *cs=field->charset(); + CHARSET_INFO *cs=charset(); char buff[MAX_FIELD_WIDTH]; // Alloc buffer for small columns str_value.set_quick(buff,sizeof(buff),cs); result=val_str(&str_value); @@ -807,12 +807,11 @@ int Item::save_in_field(Field *field) int Item_string::save_in_field(Field *field) { String *result; - CHARSET_INFO *cs=field->charset(); result=val_str(&str_value); if (null_value) return set_field_to_null(field); field->set_notnull(); - return (field->store(result->ptr(),result->length(),cs)) ? -1 : 0; + return (field->store(result->ptr(),result->length(),charset())) ? -1 : 0; } int Item_int::save_in_field(Field *field) @@ -880,11 +879,10 @@ longlong Item_varbinary::val_int() int Item_varbinary::save_in_field(Field *field) { int error; - CHARSET_INFO *cs=field->charset(); field->set_notnull(); if (field->result_type() == STRING_RESULT) { - error=field->store(str_value.ptr(),str_value.length(),cs); + error=field->store(str_value.ptr(),str_value.length(),charset()); } else { From 5b62dfcdf51a695ebc724cb453919eb909ca274f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Nov 2002 10:44:30 +0200 Subject: [PATCH 82/89] fixed error handling bug fixed naming bug fixed bug of subselect excluding mysql-test/r/subselect.result: test of error handling bug test of naming bug test bug of subselect excluding mysql-test/t/subselect.test: test of error handling bug test of naming bug test bug of subselect excluding sql/item_subselect.cc: fixed naming bug fixed error handling bug sql/sql_lex.cc: fixed subselect excluding bug --- mysql-test/r/subselect.result | 8 ++++++++ mysql-test/t/subselect.test | 4 ++++ sql/item_subselect.cc | 3 ++- sql/sql_lex.cc | 3 +++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 523c3af91c4..bbf70150ee0 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -35,6 +35,14 @@ Unknown column 'a' in 'field list' SELECT * FROM (SELECT 1 as id) WHERE id IN (SELECT * FROM (SELECT 1 as id) ORDER BY id LIMIT 1); id 1 +SELECT * FROM (SELECT 1) WHERE 1 IN (SELECT 1,1); +Cardinality error (more/less than 1 columns) +SELECT 1 IN (SELECT 1); +1 IN (SELECT 1) +1 +SELECT 1 FROM (SELECT 1 as a) WHERE 1 IN (SELECT (SELECT a)); +1 +1 drop table if exists t1,t2,t3,t4,t5,t6,t7,t8; create table t1 (a int); create table t2 (a int, b int); diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 17f3008b62e..c875f8372b3 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -16,6 +16,10 @@ SELECT 1 as a FROM (SELECT 1) HAVING (SELECT a)=1; -- error 1054 SELECT 1 FROM (SELECT (SELECT a)); SELECT * FROM (SELECT 1 as id) WHERE id IN (SELECT * FROM (SELECT 1 as id) ORDER BY id LIMIT 1); +-- error 1239 +SELECT * FROM (SELECT 1) WHERE 1 IN (SELECT 1,1); +SELECT 1 IN (SELECT 1); +SELECT 1 FROM (SELECT 1 as a) WHERE 1 IN (SELECT (SELECT a)); drop table if exists t1,t2,t3,t4,t5,t6,t7,t8; create table t1 (a int); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 6d55f7399c1..e087664e060 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -92,6 +92,7 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) if (substitution) { (*ref)= substitution; + substitution->name= name; engine->exclude(); return substitution->fix_fields(thd, tables, ref); } @@ -293,7 +294,7 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, if (sl->item_list.elements > 1) { my_error(ER_CARDINALITY_COL, MYF(0), 1); - item= 0; // Item_asterisk_remover must fail + DBUG_VOID_RETURN; } else item= (Item*) sl->item_list.pop(); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index c50321ebed7..be0430d4afe 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1071,7 +1071,10 @@ void st_select_lex_unit::exclude_level() sl->link_next->link_prev= sl->link_prev; SELECT_LEX_UNIT **last= 0; for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit()) + { + u->master= master; last= (SELECT_LEX_UNIT**)&(u->next); + } if (last) { (*units_last)= sl->first_inner_unit(); From 4b0a6e6bcdda3d4b97c389cc5063a6afd520b0a0 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Nov 2002 13:29:48 +0400 Subject: [PATCH 83/89] my_strntod_ucs2 and my_strntol_ucs2 fixes --- strings/ctype-utf8.c | 216 +++++++++++++++++++++++-------------------- 1 file changed, 115 insertions(+), 101 deletions(-) diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 8adeed7144a..c77dc871009 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -22,7 +22,7 @@ #include "m_string.h" #include "m_ctype.h" #include "my_sys.h" /* defines errno */ - +#include #ifdef HAVE_CHARSET_utf8 #define HAVE_UNIDATA @@ -2118,7 +2118,7 @@ static int my_ucs2_uni (CHARSET_INFO *cs __attribute__((unused)) , my_wc_t * pwc, const uchar *s, const uchar *e) { if (s+2 > e) /* Need 2 characters */ - return MY_CS_ILSEQ; + return MY_CS_TOOFEW(0); *pwc= ((unsigned char)s[0]) * 256 + ((unsigned char)s[1]); return 2; @@ -2441,118 +2441,114 @@ static int my_snprintf_ucs2(CHARSET_INFO *cs __attribute__((unused)) return my_vsnprintf_ucs2(to, n, fmt, args); } -#define MY_ERRNO(x) long my_strntol_ucs2(CHARSET_INFO *cs, const char *nptr, uint l, char **endptr, int base) { - int negative; - register ulong cutoff; + int negative=0; + int overflow; + int cnv; + my_wc_t wc; register unsigned int cutlim; - register ulong i; - register const char *s; - register unsigned char c; - const char *save, *e; - int overflow; + register ulong cutoff; + register ulong res; + register const char *s=nptr; + register const char *e=nptr+l; + const char *save; - if (base < 0 || base == 1 || base > 36) + do { + if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) + { + switch (wc) + { + case ' ' : break; + case '\t': break; + case '-' : negative= !negative; break; + case '+' : break; + default : goto bs; + } + } + else /* No more characters or bad multibyte sequence */ + { + if (endptr !=NULL ) + *endptr = (char*)s; + my_errno = (cnv==MY_CS_ILSEQ) ? EILSEQ : EDOM; + return 0; + } + s+=cnv; + } while (1); + +bs: + + if (base <= 0 || base == 1 || base > 36) base = 10; - s = nptr; - e = nptr+l; - - for ( ; s= base) - break; - if (i > cutoff || (i == cutoff && c > cutlim)) - overflow = 1; + + do { + if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) + { + s+=cnv; + if ( wc>='0' && wc<='9') + wc -= '0'; + else if ( wc>='A' && wc<='Z') + wc = wc - 'A' + 10; + else if ( wc>='a' && wc<='z') + wc = wc - 'a' + 10; + else + break; + if ((int)wc >= base) + break; + if (res > cutoff || (res == cutoff && wc > cutlim)) + overflow = 1; + else + { + res *= (ulong) base; + res += wc; + } + } + else if (cnv==MY_CS_ILSEQ) + { + if (endptr !=NULL ) + *endptr = (char*)s; + my_errno=EILSEQ; + return 0; + } else { - i *= (ulong) base; - i += c; + /* No more characters */ + break; } - } - - if (s == save) - goto noconv; + } while(1); if (endptr != NULL) *endptr = (char *) s; + if (s == save) + { + my_errno=EDOM; + return 0L; + } + if (negative) { - if (i > (ulong) LONG_MIN) + if (res > (ulong) LONG_MIN) overflow = 1; } - else if (i > (ulong) LONG_MAX) + else if (res > (ulong) LONG_MAX) overflow = 1; if (overflow) { - MY_ERRNO(ERANGE); + my_errno=(ERANGE); return negative ? LONG_MIN : LONG_MAX; } - return (negative ? -((long) i) : (long) i); - -noconv: - MY_ERRNO(EDOM); - if (endptr != NULL) - *endptr = (char *) nptr; - return 0L; + return (negative ? -((long) res) : (long) res); } @@ -2646,14 +2642,14 @@ ulong my_strntoul_ucs2(CHARSET_INFO *cs, if (overflow) { - MY_ERRNO(ERANGE); + my_errno=(ERANGE); return ((ulong)~0L); } return (negative ? -((long) i) : (long) i); noconv: - MY_ERRNO(EDOM); + my_errno=(EDOM); if (endptr != NULL) *endptr = (char *) nptr; return 0L; @@ -2759,14 +2755,14 @@ longlong my_strntoll_ucs2(CHARSET_INFO *cs __attribute__((unused)), if (overflow) { - MY_ERRNO(ERANGE); + my_errno=(ERANGE); return negative ? LONGLONG_MIN : LONGLONG_MAX; } return (negative ? -((longlong) i) : (longlong) i); noconv: - MY_ERRNO(EDOM); + my_errno=(EDOM); if (endptr != NULL) *endptr = (char *) nptr; return 0L; @@ -2864,35 +2860,53 @@ ulonglong my_strntoull_ucs2(CHARSET_INFO *cs, if (overflow) { - MY_ERRNO(ERANGE); + my_errno=(ERANGE); return (~(ulonglong) 0); } return (negative ? -((longlong) i) : (longlong) i); noconv: - MY_ERRNO(EDOM); + my_errno=(EDOM); if (endptr != NULL) *endptr = (char *) nptr; return 0L; } double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)), - const char *s, uint l, char **e) + const char *nptr, uint l, char **endptr) { - char buf[256]; - double res; + char buf[256]; + double res; + register char *b=buf; + register const char *s=nptr; + register const char *e=nptr+l; + my_wc_t wc; + int cnv; + if((l+1)>sizeof(buf)) { - if (e) - memcpy(*e,s,sizeof(s)); + if (endptr) + *endptr=(char*)nptr; + my_errno=ERANGE; return 0; } - strncpy(buf,s,l); - buf[l]='\0'; - res=strtod(buf,e); - if (e) - memcpy(*e,*e-buf+s,sizeof(s)); + + while ((cnv=cs->mb_wc(cs,&wc,s,e))>0) + { + s+=cnv; + if (wc < 128) + { + *b++=wc; + } + else + break; + } + *b='\0'; + + res=strtod(buf,endptr); + if (endptr) + *endptr=(char*) (*endptr-buf+nptr); return res; } From 641c7ff9dd279aa408b1fbe932a5b04f8f0e05ca Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Nov 2002 14:04:36 +0400 Subject: [PATCH 84/89] UCS2 fixes --- strings/ctype-utf8.c | 483 +++++++++++++++++++++---------------------- 1 file changed, 240 insertions(+), 243 deletions(-) diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index c77dc871009..fa66ca7efb4 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -2555,324 +2555,321 @@ bs: ulong my_strntoul_ucs2(CHARSET_INFO *cs, const char *nptr, uint l, char **endptr, int base) { - int negative; - register ulong cutoff; + int negative=0; + int overflow; + int cnv; + my_wc_t wc; register unsigned int cutlim; - register ulong i; - register const char *s; - register unsigned char c; - const char *save, *e; - int overflow; - - if (base < 0 || base == 1 || base > 36) + register ulong cutoff; + register ulong res; + register const char *s=nptr; + register const char *e=nptr+l; + const char *save; + + do { + if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) + { + switch (wc) + { + case ' ' : break; + case '\t': break; + case '-' : negative= !negative; break; + case '+' : break; + default : goto bs; + } + } + else /* No more characters or bad multibyte sequence */ + { + if (endptr !=NULL ) + *endptr = (char*)s; + my_errno = (cnv==MY_CS_ILSEQ) ? EILSEQ : EDOM; + return 0; + } + s+=cnv; + } while (1); + +bs: + + if (base <= 0 || base == 1 || base > 36) base = 10; - s = nptr; - e = nptr+l; - - for( ; s= base) - break; - if (i > cutoff || (i == cutoff && c > cutlim)) - overflow = 1; + do { + if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) + { + s+=cnv; + if ( wc>='0' && wc<='9') + wc -= '0'; + else if ( wc>='A' && wc<='Z') + wc = wc - 'A' + 10; + else if ( wc>='a' && wc<='z') + wc = wc - 'a' + 10; + else + break; + if ((int)wc >= base) + break; + if (res > cutoff || (res == cutoff && wc > cutlim)) + overflow = 1; + else + { + res *= (ulong) base; + res += wc; + } + } + else if (cnv==MY_CS_ILSEQ) + { + if (endptr !=NULL ) + *endptr = (char*)s; + my_errno=EILSEQ; + return 0; + } else { - i *= (ulong) base; - i += c; + /* No more characters */ + break; } - } - - if (s == save) - goto noconv; - + } while(1); + if (endptr != NULL) *endptr = (char *) s; - + + if (s == save) + { + my_errno=EDOM; + return 0L; + } + if (overflow) { my_errno=(ERANGE); return ((ulong)~0L); } - return (negative ? -((long) i) : (long) i); + return (negative ? -((long) res) : (long) res); -noconv: - my_errno=(EDOM); - if (endptr != NULL) - *endptr = (char *) nptr; - return 0L; } -longlong my_strntoll_ucs2(CHARSET_INFO *cs __attribute__((unused)), + +longlong my_strntoll_ucs2(CHARSET_INFO *cs, const char *nptr, uint l, char **endptr, int base) { - int negative; - register ulonglong cutoff; + int negative=0; + int overflow; + int cnv; + my_wc_t wc; + register ulonglong cutoff; register unsigned int cutlim; - register ulonglong i; - register const char *s, *e; - register unsigned char c; + register ulonglong res; + register const char *s=nptr; + register const char *e=nptr+l; const char *save; - int overflow; - - if (base < 0 || base == 1 || base > 36) - base = 10; - - s = nptr; - e = nptr+l; - - for(; smb_wc(cs,&wc,s,e))>0) { - if (my_toupper(cs,s[1]) == 'X') + switch (wc) { - s += 2; - base = 16; + case ' ' : break; + case '\t': break; + case '-' : negative= !negative; break; + case '+' : break; + default : goto bs; } - else - base = 8; - } - else - base = 10; - } - + } + else /* No more characters or bad multibyte sequence */ + { + if (endptr !=NULL ) + *endptr = (char*)s; + my_errno = (cnv==MY_CS_ILSEQ) ? EILSEQ : EDOM; + return 0; + } + s+=cnv; + } while (1); + +bs: + + if (base <= 0 || base == 1 || base > 36) + base = 10; + + overflow = 0; + res = 0; save = s; - cutoff = (~(ulonglong) 0) / (unsigned long int) base; cutlim = (uint) ((~(ulonglong) 0) % (unsigned long int) base); - overflow = 0; - i = 0; - for (c = *s; s != e; c = *++s) - { - if (my_isdigit(cs,c)) - c -= '0'; - else if (my_isalpha(cs,c)) - c = my_toupper(cs,c) - 'A' + 10; - else - break; - if (c >= base) - break; - if (i > cutoff || (i == cutoff && c > cutlim)) - overflow = 1; + do { + if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) + { + s+=cnv; + if ( wc>='0' && wc<='9') + wc -= '0'; + else if ( wc>='A' && wc<='Z') + wc = wc - 'A' + 10; + else if ( wc>='a' && wc<='z') + wc = wc - 'a' + 10; + else + break; + if ((int)wc >= base) + break; + if (res > cutoff || (res == cutoff && wc > cutlim)) + overflow = 1; + else + { + res *= (ulonglong) base; + res += wc; + } + } + else if (cnv==MY_CS_ILSEQ) + { + if (endptr !=NULL ) + *endptr = (char*)s; + my_errno=EILSEQ; + return 0; + } else { - i *= (ulonglong) base; - i += c; + /* No more characters */ + break; } - } - - if (s == save) - goto noconv; - + } while(1); + if (endptr != NULL) *endptr = (char *) s; - + + if (s == save) + { + my_errno=EDOM; + return 0L; + } + if (negative) { - if (i > (ulonglong) LONGLONG_MIN) + if (res > (ulonglong) LONGLONG_MIN) overflow = 1; } - else if (i > (ulonglong) LONGLONG_MAX) + else if (res > (ulonglong) LONGLONG_MAX) overflow = 1; - + if (overflow) { my_errno=(ERANGE); return negative ? LONGLONG_MIN : LONGLONG_MAX; } - - return (negative ? -((longlong) i) : (longlong) i); - -noconv: - my_errno=(EDOM); - if (endptr != NULL) - *endptr = (char *) nptr; - return 0L; + + return (negative ? -((longlong)res) : (longlong)res); } -ulonglong my_strntoull_ucs2(CHARSET_INFO *cs, + + +ulonglong my_strntoull_ucs2(CHARSET_INFO *cs, const char *nptr, uint l, char **endptr, int base) { - int negative; - register ulonglong cutoff; + int negative=0; + int overflow; + int cnv; + my_wc_t wc; + register ulonglong cutoff; register unsigned int cutlim; - register ulonglong i; - register const char *s, *e; - register unsigned char c; + register ulonglong res; + register const char *s=nptr; + register const char *e=nptr+l; const char *save; - int overflow; - - if (base < 0 || base == 1 || base > 36) - base = 10; - - s = nptr; - e = nptr+l; - - for(; smb_wc(cs,&wc,s,e))>0) { - if (my_toupper(cs,s[1]) == 'X') + switch (wc) { - s += 2; - base = 16; + case ' ' : break; + case '\t': break; + case '-' : negative= !negative; break; + case '+' : break; + default : goto bs; } - else - base = 8; - } - else - base = 10; - } - + } + else /* No more characters or bad multibyte sequence */ + { + if (endptr !=NULL ) + *endptr = (char*)s; + my_errno = (cnv==MY_CS_ILSEQ) ? EILSEQ : EDOM; + return 0; + } + s+=cnv; + } while (1); + +bs: + + if (base <= 0 || base == 1 || base > 36) + base = 10; + + overflow = 0; + res = 0; save = s; - cutoff = (~(ulonglong) 0) / (unsigned long int) base; cutlim = (uint) ((~(ulonglong) 0) % (unsigned long int) base); - overflow = 0; - i = 0; - for (c = *s; s != e; c = *++s) - { - if (my_isdigit(cs,c)) - c -= '0'; - else if (my_isalpha(cs,c)) - c = my_toupper(cs,c) - 'A' + 10; - else - break; - if (c >= base) - break; - if (i > cutoff || (i == cutoff && c > cutlim)) - overflow = 1; + do { + if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) + { + s+=cnv; + if ( wc>='0' && wc<='9') + wc -= '0'; + else if ( wc>='A' && wc<='Z') + wc = wc - 'A' + 10; + else if ( wc>='a' && wc<='z') + wc = wc - 'a' + 10; + else + break; + if ((int)wc >= base) + break; + if (res > cutoff || (res == cutoff && wc > cutlim)) + overflow = 1; + else + { + res *= (ulonglong) base; + res += wc; + } + } + else if (cnv==MY_CS_ILSEQ) + { + if (endptr !=NULL ) + *endptr = (char*)s; + my_errno=EILSEQ; + return 0; + } else { - i *= (ulonglong) base; - i += c; + /* No more characters */ + break; } - } - - if (s == save) - goto noconv; - + } while(1); + if (endptr != NULL) *endptr = (char *) s; - + + if (s == save) + { + my_errno=EDOM; + return 0L; + } + if (overflow) { my_errno=(ERANGE); return (~(ulonglong) 0); } - return (negative ? -((longlong) i) : (longlong) i); - -noconv: - my_errno=(EDOM); - if (endptr != NULL) - *endptr = (char *) nptr; - return 0L; + return (negative ? -((longlong) res) : (longlong) res); } + double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)), const char *nptr, uint l, char **endptr) { From 042c34d86dad7f37ff39345f6716c2f25ffeab53 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Nov 2002 12:30:04 +0200 Subject: [PATCH 85/89] checking columns of top items mysql-test/r/row_test.result: changed error message (report requestet columns number) new tests mysql-test/t/row_test.test: new tests sql/item.h: checking columns of wrapper items --- mysql-test/r/row_test.result | 11 ++++++++++- mysql-test/t/row_test.test | 17 ++++++++++++++++- sql/item.cc | 8 ++++---- sql/item.h | 1 + sql/item_row.cc | 2 +- sql/set_var.cc | 2 +- sql/sql_base.cc | 8 +++++--- sql/sql_handler.cc | 2 +- sql/sql_prepare.cc | 3 ++- sql/sql_select.cc | 7 +++++-- sql/sql_yacc.yy | 2 +- 11 files changed, 47 insertions(+), 16 deletions(-) diff --git a/mysql-test/r/row_test.result b/mysql-test/r/row_test.result index bd162e35f86..f5bf9856a60 100644 --- a/mysql-test/r/row_test.result +++ b/mysql-test/r/row_test.result @@ -35,7 +35,7 @@ SELECT ('test',2,3.33)=('test',2,3.33); ('test',2,3.33)=('test',2,3.33) 1 SELECT ('test',2,3.33)=('test',2,3.33,4); -Cardinality error (more/less than 4 columns) +Cardinality error (more/less than 3 columns) drop table if exists t1; create table t1 ( a int, b int, c int); insert into t1 values (1,2,3), (2,3,1), (3,2,1); @@ -49,3 +49,12 @@ a b c 2 3 1 3 2 1 drop table t1; +select (1,1); +Cardinality error (more/less than 1 columns) +drop table if exists t1; +create table t1 (i int); +select 1 from t1 where (1,1); +Cardinality error (more/less than 1 columns) +select count(*) from t1 order by (1,1); +Cardinality error (more/less than 1 columns) +drop table t1; diff --git a/mysql-test/t/row_test.test b/mysql-test/t/row_test.test index 24df2dd1b20..db65e6bd157 100644 --- a/mysql-test/t/row_test.test +++ b/mysql-test/t/row_test.test @@ -18,4 +18,19 @@ insert into t1 values (1,2,3), (2,3,1), (3,2,1); select * from t1 where (1,2,3)=(a,b,c); select * from t1 where (0,2,3)=(a,b,c); select * from t1 where (1,2,3)<(a,b,c); -drop table t1; \ No newline at end of file +drop table t1; + +-- error 1239 +select (1,1); +drop table if exists t1; +create table t1 (i int); +-- error 1239 +select 1 from t1 where (1,1); +-- error 1239 +select count(*) from t1 order by (1,1); +#TODO remove comments after parser fixing +#-- error 1239 +#select count(*) from t1 order by i having (1,1); +#-- error 1239 +#select 1 from t1 limit (1,1), (1,1); +drop table t1; diff --git a/sql/item.cc b/sql/item.cc index 740ec9418c4..2dd5de0e896 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -63,7 +63,7 @@ bool Item::check_cols(uint c) { if (c != 1) { - my_error(ER_CARDINALITY_COL, MYF(0), 1); + my_error(ER_CARDINALITY_COL, MYF(0), c); return 1; } return 0; @@ -570,8 +570,8 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) if (!r) return 1; int res; - if ((res= r->fix_fields(thd, tables, ref))) - return res; + if (r->check_cols(1) || r->fix_fields(thd, tables, ref)) + return 1; r->depended_from= last; thd->lex.current_select->mark_as_dependent(last); thd->add_possible_loop(r); @@ -606,7 +606,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) (char *)field_name); if (!*ref) return 1; - return (*ref)->fix_fields(thd, tables, ref); + return (*ref)->check_cols(1) || (*ref)->fix_fields(thd, tables, ref); } fixed= 1; return 0; diff --git a/sql/item.h b/sql/item.h index 766bd7fba41..11b141613f3 100644 --- a/sql/item.h +++ b/sql/item.h @@ -120,6 +120,7 @@ public: longlong val_int() { return item->val_int(); } String* val_str(String* s) { return item->val_str(s); } void make_field(Send_field* f) { item->make_field(f); } + bool check_cols(uint col) { return item->check_cols(col); } }; diff --git a/sql/item_row.cc b/sql/item_row.cc index 95da4f5901e..464a8fd0ec5 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -59,7 +59,7 @@ bool Item_row::check_cols(uint c) { if (c != arg_count) { - my_error(ER_CARDINALITY_COL, MYF(0), arg_count); + my_error(ER_CARDINALITY_COL, MYF(0), c); return 1; } return 0; diff --git a/sql/set_var.cc b/sql/set_var.cc index 599c4af06cc..566ca6da860 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1344,7 +1344,7 @@ int set_var::check(THD *thd) return 0; } - if (value->fix_fields(thd, 0, &value)) + if (value->check_cols(1) || value->fix_fields(thd, 0, &value)) return -1; if (var->check_update_type(value->result_type())) { diff --git a/sql/sql_base.cc b/sql/sql_base.cc index f8202035d51..8f74903027e 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2101,7 +2101,8 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List &fields, } else { - if (item->fix_fields(thd, tables, it.ref())) + if (item->check_cols(1) || + item->fix_fields(thd, tables, it.ref())) DBUG_RETURN(-1); /* purecov: inspected */ item= *(it.ref()); //Item can be chenged in fix fields if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM && @@ -2255,7 +2256,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) if (*conds) { thd->where="where clause"; - if ((*conds)->fix_fields(thd, tables, conds)) + if ((*conds)->check_cols(1) || (*conds)->fix_fields(thd, tables, conds)) DBUG_RETURN(1); } @@ -2266,7 +2267,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) { /* Make a join an a expression */ thd->where="on clause"; - if (table->on_expr->fix_fields(thd, tables, &table->on_expr)) + if (table->on_expr->check_cols(1) || + table->on_expr->fix_fields(thd, tables, &table->on_expr)) DBUG_RETURN(1); thd->cond_count++; diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index c43869d9d55..909e1643fe5 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -106,7 +106,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, } tables->table=table; - if (cond && cond->fix_fields(thd, tables, &cond)) + if (cond && (cond->check_cols(1) || cond->fix_fields(thd, tables, &cond))) return -1; if (keyname) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index f86add6c389..7943a3e2254 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -501,7 +501,8 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, { thd->where="having clause"; thd->allow_sum_func=1; - if (having->fix_fields(thd, tables, &having) || thd->fatal_error) + if (having->check_cols(1) || having->fix_fields(thd, tables, &having) + || thd->fatal_error) DBUG_RETURN(1); if (having->with_sum_func) having->split_sum_func(all_fields); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f560cb7907f..c1f7e8272bc 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -262,7 +262,8 @@ JOIN::prepare(TABLE_LIST *tables_init, thd->where="having clause"; thd->allow_sum_func=1; select_lex->having_fix_field= 1; - bool having_fix_rc= having->fix_fields(thd, tables_list, &having); + bool having_fix_rc= (having->check_cols(1) || + having->fix_fields(thd, tables_list, &having)); select_lex->having_fix_field= 0; if (having_fix_rc || thd->net.report_error) DBUG_RETURN(-1); /* purecov: inspected */ @@ -6651,7 +6652,9 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List &fields, return 0; } order->in_field_list=0; - if ((*order->item)->fix_fields(thd, tables, order->item) || thd->fatal_error) + Item *it= *order->item; + if (it->check_cols(1) || it->fix_fields(thd, tables, order->item) || + thd->fatal_error) return 1; // Wrong field all_fields.push_front(*order->item); // Add new field to field list order->item=(Item**) all_fields.head_ref(); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index cd15fb19dfb..27996acb0f0 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3416,7 +3416,7 @@ kill: KILL_SYM expr { LEX *lex=Lex; - if ($2->fix_fields(lex->thd, 0, &$2)) + if ($2->check_cols(1) || $2->fix_fields(lex->thd, 0, &$2)) { send_error(lex->thd, ER_SET_CONSTANTS_ONLY); YYABORT; From 76a634b763fc78b70e6109ab065127c33944f4d5 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Nov 2002 12:29:27 +0100 Subject: [PATCH 86/89] s/SQLCOM_MULTI_UPDATE/SQLCOM_UPDATE_MULTI/ to be in line with SQLCOM_DELETE_MULTI --- sql/sql_lex.h | 6 +++--- sql/sql_parse.cc | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 4c5ca88b7b0..f4475b26a0a 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -50,9 +50,9 @@ enum enum_sql_command { SQLCOM_SHOW_CREATE_DB, SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES, - SQLCOM_GRANT, + SQLCOM_GRANT, SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB, - SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, + SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION, SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE, @@ -62,7 +62,7 @@ enum enum_sql_command { SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_SHOW_BINLOGS, SQLCOM_SHOW_OPEN_TABLES, SQLCOM_LOAD_MASTER_DATA, SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ, - SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_MULTI_UPDATE, + SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_UPDATE_MULTI, SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO, SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS, SQLCOM_SHOW_COLUMN_TYPES, SQLCOM_SHOW_TABLE_TYPES, SQLCOM_SHOW_PRIVILEGES, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2e8a431d212..11f1c59fd45 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -362,7 +362,7 @@ void init_update_queries(void) uc_update_queries[SQLCOM_RESTORE_TABLE]=1; uc_update_queries[SQLCOM_DELETE_MULTI]=1; uc_update_queries[SQLCOM_DROP_INDEX]=1; - uc_update_queries[SQLCOM_MULTI_UPDATE]=1; + uc_update_queries[SQLCOM_UPDATE_MULTI]=1; } @@ -1911,7 +1911,7 @@ mysql_execute_command(THD *thd) TABLE_LIST *auxi; const char *msg=0; - lex->sql_command=SQLCOM_MULTI_UPDATE; + lex->sql_command=SQLCOM_UPDATE_MULTI; for (auxi= (TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next) table_count++; @@ -2056,11 +2056,11 @@ mysql_execute_command(THD *thd) /* sql_yacc guarantees that tables and aux_tables are not zero */ if (check_db_used(thd, tables) || check_db_used(thd,aux_tables) || - check_table_access(thd,SELECT_ACL, tables) || + check_table_access(thd,SELECT_ACL, tables) || check_table_access(thd,DELETE_ACL, aux_tables)) goto error; if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where) - { + { send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE); goto error; } From 5234e49baf684e5e81127c549fa9f9fd78efcb05 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Nov 2002 13:17:54 +0100 Subject: [PATCH 87/89] make multi updates statistics visible in SHOW STATUS as Com_update_multi --- sql/mysqld.cc | 3 ++- sql/sql_parse.cc | 26 ++++++++++++++++---------- sql/sql_yacc.yy | 6 ++++-- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index b45caac5ab6..1cbc071fb4d 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4010,7 +4010,7 @@ struct show_var_st status_vars[]= { {"Com_insert_select", (char*) (com_stat+(uint) SQLCOM_INSERT_SELECT),SHOW_LONG}, {"Com_kill", (char*) (com_stat+(uint) SQLCOM_KILL),SHOW_LONG}, {"Com_load", (char*) (com_stat+(uint) SQLCOM_LOAD),SHOW_LONG}, - {"Com_load_master_data", (char*) (com_stat+(uint) SQLCOM_LOAD_MASTER_DATA),SHOW_LONG}, + {"Com_load_master_data", (char*) (com_stat+(uint) SQLCOM_LOAD_MASTER_DATA),SHOW_LONG}, {"Com_load_master_table", (char*) (com_stat+(uint) SQLCOM_LOAD_MASTER_TABLE),SHOW_LONG}, {"Com_lock_tables", (char*) (com_stat+(uint) SQLCOM_LOCK_TABLES),SHOW_LONG}, {"Com_optimize", (char*) (com_stat+(uint) SQLCOM_OPTIMIZE),SHOW_LONG}, @@ -4048,6 +4048,7 @@ struct show_var_st status_vars[]= { {"Com_truncate", (char*) (com_stat+(uint) SQLCOM_TRUNCATE),SHOW_LONG}, {"Com_unlock_tables", (char*) (com_stat+(uint) SQLCOM_UNLOCK_TABLES),SHOW_LONG}, {"Com_update", (char*) (com_stat+(uint) SQLCOM_UPDATE),SHOW_LONG}, + {"Com_update_multi", (char*) (com_stat+(uint) SQLCOM_UPDATE_MULTI),SHOW_LONG}, {"Connections", (char*) &thread_id, SHOW_LONG_CONST}, {"Created_tmp_disk_tables", (char*) &created_tmp_disk_tables,SHOW_LONG}, {"Created_tmp_tables", (char*) &created_tmp_tables, SHOW_LONG}, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 11f1c59fd45..70fb5acdffd 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1894,24 +1894,30 @@ mysql_execute_command(THD *thd) send_error(thd,ER_WRONG_VALUE_COUNT); DBUG_VOID_RETURN; } - if (select_lex->table_list.elements == 1) + res= mysql_update(thd,tables, + select_lex->item_list, + lex->value_list, + select_lex->where, + (ORDER *) select_lex->order_list.first, + select_lex->select_limit, + lex->duplicates); + break; + case SQLCOM_UPDATE_MULTI: + if (check_access(thd,UPDATE_ACL,tables->db,&tables->grant.privilege)) + goto error; + if (grant_option && check_grant(thd,UPDATE_ACL,tables)) + goto error; + if (select_lex->item_list.elements != lex->value_list.elements) { - res= mysql_update(thd,tables, - select_lex->item_list, - lex->value_list, - select_lex->where, - (ORDER *) select_lex->order_list.first, - select_lex->select_limit, - lex->duplicates); + send_error(thd,ER_WRONG_VALUE_COUNT); + DBUG_VOID_RETURN; } - else { multi_update *result; uint table_count; TABLE_LIST *auxi; const char *msg=0; - lex->sql_command=SQLCOM_UPDATE_MULTI; for (auxi= (TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next) table_count++; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index cd15fb19dfb..c54f1f556df 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3051,8 +3051,8 @@ opt_insert_update: /* Update rows in a table */ update: - UPDATE_SYM - { + UPDATE_SYM + { LEX *lex= Lex; lex->sql_command= SQLCOM_UPDATE; lex->select_lex.init_order(); @@ -3061,6 +3061,8 @@ update: SET update_list where_clause opt_order_clause delete_limit_clause { Select->set_lock_for_tables($3); + if (lex->select_lex->table_list.elements > 1) + lex->sql_command=SQLCOM_UPDATE_MULTI; } ; From dcae69799884c1a7cadc6a97dd0bc1606450bd6f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Nov 2002 14:20:25 +0100 Subject: [PATCH 88/89] added missing Com_xxx status variables moved SQLCOM_END to the end of the list bad copy-paste in sql_yacc.yy fixed sql/mysqld.cc: added missing Com_xxx status variables sql/sql_lex.h: moved SQLCOM_END to the end. Comments added. sql/sql_yacc.yy: bad copy-paste fixed :) --- sql/mysqld.cc | 12 +++++++++++- sql/sql_lex.h | 10 +++++++++- sql/sql_yacc.yy | 3 ++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1cbc071fb4d..3df75b3643d 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3984,6 +3984,7 @@ struct show_var_st status_vars[]= { {"Bytes_sent", (char*) &bytes_sent, SHOW_LONG}, {"Com_admin_commands", (char*) &com_other, SHOW_LONG}, {"Com_alter_table", (char*) (com_stat+(uint) SQLCOM_ALTER_TABLE),SHOW_LONG}, + {"Com_alter_db", (char*) (com_stat+(uint) SQLCOM_ALTER_DB),SHOW_LONG}, {"Com_analyze", (char*) (com_stat+(uint) SQLCOM_ANALYZE),SHOW_LONG}, {"Com_backup_table", (char*) (com_stat+(uint) SQLCOM_BACKUP_TABLE),SHOW_LONG}, {"Com_begin", (char*) (com_stat+(uint) SQLCOM_BEGIN),SHOW_LONG}, @@ -3997,6 +3998,7 @@ struct show_var_st status_vars[]= { {"Com_create_table", (char*) (com_stat+(uint) SQLCOM_CREATE_TABLE),SHOW_LONG}, {"Com_delete", (char*) (com_stat+(uint) SQLCOM_DELETE),SHOW_LONG}, {"Com_delete_multi", (char*) (com_stat+(uint) SQLCOM_DELETE_MULTI),SHOW_LONG}, + {"Com_do", (char*) (com_stat+(uint) SQLCOM_DO),SHOW_LONG}, {"Com_drop_db", (char*) (com_stat+(uint) SQLCOM_DROP_DB),SHOW_LONG}, {"Com_drop_function", (char*) (com_stat+(uint) SQLCOM_DROP_FUNCTION),SHOW_LONG}, {"Com_drop_index", (char*) (com_stat+(uint) SQLCOM_DROP_INDEX),SHOW_LONG}, @@ -4006,6 +4008,7 @@ struct show_var_st status_vars[]= { {"Com_ha_close", (char*) (com_stat+(uint) SQLCOM_HA_CLOSE),SHOW_LONG}, {"Com_ha_open", (char*) (com_stat+(uint) SQLCOM_HA_OPEN),SHOW_LONG}, {"Com_ha_read", (char*) (com_stat+(uint) SQLCOM_HA_READ),SHOW_LONG}, + {"Com_help", (char*) (com_stat+(uint) SQLCOM_HELP),SHOW_LONG}, {"Com_insert", (char*) (com_stat+(uint) SQLCOM_INSERT),SHOW_LONG}, {"Com_insert_select", (char*) (com_stat+(uint) SQLCOM_INSERT_SELECT),SHOW_LONG}, {"Com_kill", (char*) (com_stat+(uint) SQLCOM_KILL),SHOW_LONG}, @@ -4027,8 +4030,12 @@ struct show_var_st status_vars[]= { {"Com_set_option", (char*) (com_stat+(uint) SQLCOM_SET_OPTION),SHOW_LONG}, {"Com_show_binlog_events", (char*) (com_stat+(uint) SQLCOM_SHOW_BINLOG_EVENTS),SHOW_LONG}, {"Com_show_binlogs", (char*) (com_stat+(uint) SQLCOM_SHOW_BINLOGS),SHOW_LONG}, - {"Com_show_create", (char*) (com_stat+(uint) SQLCOM_SHOW_CREATE),SHOW_LONG}, + {"Com_show_charsets", (char*) (com_stat+(uint) SQLCOM_SHOW_CHARSETS),SHOW_LONG}, + {"Com_show_column_types", (char*) (com_stat+(uint) SQLCOM_SHOW_COLUMN_TYPES),SHOW_LONG}, + {"Com_show_create_table", (char*) (com_stat+(uint) SQLCOM_SHOW_CREATE),SHOW_LONG}, + {"Com_show_create_db", (char*) (com_stat+(uint) SQLCOM_SHOW_CREATE_DB),SHOW_LONG}, {"Com_show_databases", (char*) (com_stat+(uint) SQLCOM_SHOW_DATABASES),SHOW_LONG}, + {"Com_show_errors", (char*) (com_stat+(uint) SQLCOM_SHOW_ERRORS),SHOW_LONG}, {"Com_show_fields", (char*) (com_stat+(uint) SQLCOM_SHOW_FIELDS),SHOW_LONG}, {"Com_show_grants", (char*) (com_stat+(uint) SQLCOM_SHOW_GRANTS),SHOW_LONG}, {"Com_show_keys", (char*) (com_stat+(uint) SQLCOM_SHOW_KEYS),SHOW_LONG}, @@ -4036,13 +4043,16 @@ struct show_var_st status_vars[]= { {"Com_show_master_status", (char*) (com_stat+(uint) SQLCOM_SHOW_MASTER_STAT),SHOW_LONG}, {"Com_show_new_master", (char*) (com_stat+(uint) SQLCOM_SHOW_NEW_MASTER),SHOW_LONG}, {"Com_show_open_tables", (char*) (com_stat+(uint) SQLCOM_SHOW_OPEN_TABLES),SHOW_LONG}, + {"Com_show_privileges", (char*) (com_stat+(uint) SQLCOM_SHOW_PRIVILEGES),SHOW_LONG}, {"Com_show_processlist", (char*) (com_stat+(uint) SQLCOM_SHOW_PROCESSLIST),SHOW_LONG}, {"Com_show_slave_hosts", (char*) (com_stat+(uint) SQLCOM_SHOW_SLAVE_HOSTS),SHOW_LONG}, {"Com_show_slave_status", (char*) (com_stat+(uint) SQLCOM_SHOW_SLAVE_STAT),SHOW_LONG}, {"Com_show_status", (char*) (com_stat+(uint) SQLCOM_SHOW_STATUS),SHOW_LONG}, {"Com_show_innodb_status", (char*) (com_stat+(uint) SQLCOM_SHOW_INNODB_STATUS),SHOW_LONG}, {"Com_show_tables", (char*) (com_stat+(uint) SQLCOM_SHOW_TABLES),SHOW_LONG}, + {"Com_show_table_types", (char*) (com_stat+(uint) SQLCOM_SHOW_TABLE_TYPES),SHOW_LONG}, {"Com_show_variables", (char*) (com_stat+(uint) SQLCOM_SHOW_VARIABLES),SHOW_LONG}, + {"Com_show_warnings", (char*) (com_stat+(uint) SQLCOM_SHOW_WARNS),SHOW_LONG}, {"Com_slave_start", (char*) (com_stat+(uint) SQLCOM_SLAVE_START),SHOW_LONG}, {"Com_slave_stop", (char*) (com_stat+(uint) SQLCOM_SLAVE_STOP),SHOW_LONG}, {"Com_truncate", (char*) (com_stat+(uint) SQLCOM_TRUNCATE),SHOW_LONG}, diff --git a/sql/sql_lex.h b/sql/sql_lex.h index f4475b26a0a..453728bfc0e 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -37,6 +37,11 @@ class LEX_COLUMN; #define LEX_YYSTYPE YYSTYPE * #endif +/* + When a command is added here, be sure it's also added in mysqld.cc + in "struct show_var_st status_vars[]= {" ... +*/ + enum enum_sql_command { SQLCOM_SELECT, SQLCOM_CREATE_TABLE, SQLCOM_CREATE_INDEX, SQLCOM_ALTER_TABLE, SQLCOM_UPDATE, SQLCOM_INSERT, SQLCOM_INSERT_SELECT, @@ -66,7 +71,10 @@ enum enum_sql_command { SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO, SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS, SQLCOM_SHOW_COLUMN_TYPES, SQLCOM_SHOW_TABLE_TYPES, SQLCOM_SHOW_PRIVILEGES, - SQLCOM_END, SQLCOM_HELP + SQLCOM_HELP, + + /* This should be the last !!! */ + SQLCOM_END }; enum lex_states diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c54f1f556df..ed84502c340 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3060,8 +3060,9 @@ update: opt_low_priority opt_ignore join_table_list SET update_list where_clause opt_order_clause delete_limit_clause { + LEX *lex= Lex; Select->set_lock_for_tables($3); - if (lex->select_lex->table_list.elements > 1) + if (lex->select_lex.table_list.elements > 1) lex->sql_command=SQLCOM_UPDATE_MULTI; } ; From 1d418357ed693231066aeda713617b5e19e68a85 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Nov 2002 16:17:52 +0100 Subject: [PATCH 89/89] let's leave "INSERT ... SELECT ... UPDATE" for the future --- sql/sql_yacc.yy | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2240609a573..13836902736 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -682,7 +682,7 @@ query: { send_error(thd,ER_EMPTY_QUERY); YYABORT; - } + } else { thd->lex.sql_command = SQLCOM_EMPTY_QUERY; @@ -810,7 +810,7 @@ create: LEX *lex=Lex; lex->sql_command= SQLCOM_CREATE_TABLE; if (!lex->select_lex.add_table_to_list($5, - ($2 & + ($2 & HA_LEX_CREATE_TMP_TABLE ? &tmp_table_alias : (LEX_STRING*) 0),1, @@ -1073,7 +1073,7 @@ type: $$=FIELD_TYPE_STRING; } | char opt_binary { Lex->length=(char*) "1"; $$=FIELD_TYPE_STRING; } - | BINARY '(' NUM ')' { Lex->length=$3.str; + | BINARY '(' NUM ')' { Lex->length=$3.str; Lex->charset=my_charset_bin; $$=FIELD_TYPE_STRING; } | varchar '(' NUM ')' opt_binary { Lex->length=$3.str; @@ -1219,15 +1219,15 @@ attribute: charset_name: BINARY - { + { if (!($$=get_charset_by_name("binary",MYF(0)))) { net_printf(YYTHD,ER_UNKNOWN_CHARACTER_SET,"binary"); YYABORT; } } - | ident - { + | ident + { if (!($$=get_charset_by_name($1.str,MYF(0)))) { net_printf(YYTHD,ER_UNKNOWN_CHARACTER_SET,$1.str); @@ -1373,7 +1373,7 @@ alter: lex->alter_list.empty(); lex->select_lex.init_order(); lex->select_lex.db=lex->name=0; - bzero((char*) &lex->create_info,sizeof(lex->create_info)); + bzero((char*) &lex->create_info,sizeof(lex->create_info)); lex->create_info.db_type= DB_TYPE_DEFAULT; lex->create_info.table_charset=thd->db_charset?thd->db_charset:default_charset_info; lex->create_info.row_type= ROW_TYPE_NOT_USED; @@ -1617,12 +1617,12 @@ table_to_table_list: table_to_table: table_ident TO_SYM table_ident - { + { SELECT_LEX_NODE *sl= Lex->current_select; if (!sl->add_table_to_list($1,NULL,1,TL_IGNORE) || !sl->add_table_to_list($3,NULL,1,TL_IGNORE)) YYABORT; - }; + }; /* Select : retrieve data from table @@ -1636,8 +1636,8 @@ select: select_init: SELECT_SYM select_init2 | - '(' SELECT_SYM select_part2 ')' - { + '(' SELECT_SYM select_part2 ')' + { LEX *lex= Lex; SELECT_LEX_NODE * sel= lex->current_select; if (sel->set_braces(true)) @@ -1647,12 +1647,12 @@ select_init: } /* select in braces, can't contain global parameters */ sel->master_unit()->global_parameters= - sel->master_unit(); + sel->master_unit(); } union_opt; select_init2: select_part2 - { + { LEX *lex= Lex; if (lex->current_select->set_braces(false)) { @@ -2901,7 +2901,7 @@ insert: /* for subselects */ lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; } insert_lock_option - opt_ignore insert2 + opt_ignore insert2 { Select->set_lock_for_tables($3); } @@ -2911,7 +2911,7 @@ insert: replace: REPLACE { - LEX *lex=Lex; + LEX *lex=Lex; lex->sql_command = SQLCOM_REPLACE; lex->duplicates= DUP_REPLACE; } @@ -2927,7 +2927,7 @@ insert_lock_option: | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; } | DELAYED_SYM { $$= TL_WRITE_DELAYED; } | HIGH_PRIORITY { $$= TL_WRITE; } - ; + ; replace_lock_option: opt_low_priority { $$= $1; } @@ -3039,13 +3039,22 @@ values: ; expr_or_default: - expr { $$= $1;} + expr { $$= $1;} | DEFAULT {$$= new Item_default(); } ; opt_insert_update: /* empty */ | ON DUPLICATE KEY_SYM UPDATE_SYM SET update_list + { /* for simplisity, let's forget about + INSERT ... SELECT ... UPDATE + for a moment */ + if (Lex->sql_command != SQLCOM_INSERT) + { + send_error(Lex->thd, ER_SYNTAX_ERROR); + YYABORT; + } + } ; /* Update rows in a table */