diff options
author | Ramil Kalimullin <ramil@mysql.com> | 2010-11-18 13:40:57 +0300 |
---|---|---|
committer | Ramil Kalimullin <ramil@mysql.com> | 2010-11-18 13:40:57 +0300 |
commit | e4d2fd35a7333fb6a9c92c6439b4c4123983ccde (patch) | |
tree | f67f4a6e2fd2e3828a0321bbd2b1c6ffc5f0d220 | |
parent | 1c94d43bbb60817252a87453d3a1d1a7d0f2a35c (diff) | |
parent | c324624291a8c7cfbfcc728ce9fa86feb8d4e904 (diff) | |
download | mariadb-git-e4d2fd35a7333fb6a9c92c6439b4c4123983ccde.tar.gz |
Auto-merge from mysql-5.1-bugteam.
172 files changed, 771 insertions, 42247 deletions
diff --git a/.bzrignore b/.bzrignore index e1e2083e2d2..3d27c001e2b 100644 --- a/.bzrignore +++ b/.bzrignore @@ -9,15 +9,19 @@ *.core *.d *.da +*.dll *.exe +*.exp *.gcda *.gcno *.gcov *.idb +*.ilk *.la *.lai *.lib *.lo +*.manifest *.map *.o *.obj @@ -87,6 +91,7 @@ BitKeeper/tmp/* BitKeeper/tmp/bkr3sAHD BitKeeper/tmp/gone CMakeFiles/* +CMakeFiles COPYING COPYING.LIB Docs/#manual.texi# @@ -146,6 +151,7 @@ Makefile Makefile.in Makefile.in' PENDING/* +scripts/scripts TAGS VC++Files/client/mysql_amd64.dsp ac_available_languages_fragment @@ -1968,6 +1974,7 @@ sql-bench/test-transactions sql-bench/test-wisconsin sql/*.cpp sql/*.ds? +sql/*.def sql/*.vcproj sql/.deps/client.Po sql/.deps/derror.Po @@ -2100,6 +2107,7 @@ sql/.libs/udf_example.lai sql/.libs/udf_example.so.0 sql/.libs/udf_example.so.0.0.0 sql/client.c +sql/cmake_dummy.cc sql/Doxyfile sql/f.c sql/gen_lex_hash @@ -3030,6 +3038,7 @@ vio/viotest.cpp win/configure.data win/vs71cache.txt win/vs8cache.txt +win/nmake_cache.txt ylwrap zlib/*.ds? zlib/*.vcproj diff --git a/BUILD/compile-pentium-mysqlfs-debug b/BUILD/compile-pentium-mysqlfs-debug index c871200604e..0f457eec0bb 100755 --- a/BUILD/compile-pentium-mysqlfs-debug +++ b/BUILD/compile-pentium-mysqlfs-debug @@ -6,6 +6,6 @@ path=`dirname $0` extra_flags="$pentium_cflags $debug_cflags" extra_configs="$pentium_configs $debug_configs $static_link" -extra_configs="$extra_configs --with-debug=full --with-mysqlfs --without-server --without-pstack" +extra_configs="$extra_configs --with-debug=full --with-mysqlfs --without-server" . "$path/FINISH.sh" diff --git a/Makefile.am b/Makefile.am index 4ce753ad8aa..9996d187cd4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,7 +23,6 @@ EXTRA_DIST = INSTALL-SOURCE INSTALL-WIN-SOURCE \ SUBDIRS = . include @docs_dirs@ @zlib_dir@ \ @readline_topdir@ sql-common scripts \ - @pstack_dir@ \ @sql_union_dirs@ unittest \ @sql_server@ @man_dirs@ tests \ netware @libmysqld_dirs@ \ @@ -32,7 +31,6 @@ SUBDIRS = . include @docs_dirs@ @zlib_dir@ \ DIST_SUBDIRS = . include Docs zlib \ cmd-line-utils sql-common scripts \ - pstack \ strings mysys dbug extra regex libmysql libmysql_r client unittest storage plugin \ vio sql man tests \ netware libmysqld \ @@ -1192,97 +1192,3 @@ library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. *************************************************************************** - -%%The following software may be included in this product: -pstack (part of GNU Binutils) - -Use of any of this software is governed by the terms of the license below: - -pstack is comprised of various .c and .h files; all begin like this: - -/* bucomm.h -- binutils common include file. - Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. - -This file is part of GNU Binutils. - -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. */ - -*************************************************************************** - -%%The following software may be included in this product: -libiberty.h (part of pstack GNU Binutils) - -Use of any of this software is governed by the terms of the license below: - -See -http://www.koders.com/c/fid99F596804BBE22C076522B848D5575F142079064.aspx - -/* Function declarations for libiberty. - Written by Cygnus Support, 1994. - - The libiberty library provides a number of functions which are - missing on some operating systems. We do not declare those here, - to avoid conflicts with the system header files on operating - systems that do support those functions. In this file we only - declare those functions which are specific to libiberty. */ - -*************************************************************************** - -%%The following software may be included in this product: -ieee.h (part of pstack GNU Binutils) - -Use of any of this software is governed by the terms of the license below: - -See -http://src.opensolaris.org/source/xref//sfw/usr/src/cmd/gdb/gdb-6.3/include/ieee.h - - -/* IEEE Standard 695-1980 "Universal Format for Object Modules" -header file - Contributed by Cygnus Support. */ - -*************************************************************************** - -%%The following software may be included in this product: -pstack.c (part of pstack GNU Binutils) - -Use of any of this software is governed by the terms of the license below: - -/* - pstack.c -- asynchronous stack trace of a running process - Copyright (c) 1999 Ross Thompson - Author: Ross Thompson - Critical bug fix: Tim Waugh -*/ - -/* - This file 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. -*/ - -*************************************************************************** diff --git a/cmd-line-utils/readline/bind.c b/cmd-line-utils/readline/bind.c index c669322f436..0ea8b1ca126 100644 --- a/cmd-line-utils/readline/bind.c +++ b/cmd-line-utils/readline/bind.c @@ -855,7 +855,7 @@ _rl_read_init_file (filename, include_level) { register int i; char *buffer, *openname, *line, *end; - size_t file_size; + size_t file_size = 0; current_readline_init_file = filename; current_readline_init_include_level = include_level; diff --git a/config/ac-macros/maintainer.m4 b/config/ac-macros/maintainer.m4 index 5960853d7f1..b4d2f08e558 100644 --- a/config/ac-macros/maintainer.m4 +++ b/config/ac-macros/maintainer.m4 @@ -19,6 +19,7 @@ AC_DEFUN([MY_MAINTAINER_MODE_WARNINGS], [ AS_IF([test "$GCC" = "yes"], [ C_WARNINGS="-Wall -Wextra -Wunused -Wwrite-strings -Wno-strict-aliasing -Werror" CXX_WARNINGS="${C_WARNINGS} -Wno-unused-parameter" + C_WARNINGS="${C_WARNINGS} -Wdeclaration-after-statement" ]) # Test whether the warning options work. diff --git a/configure.in b/configure.in index 7fd581af009..6c9c64d9c86 100644 --- a/configure.in +++ b/configure.in @@ -910,46 +910,6 @@ struct request_info *req; ]) AC_SUBST(WRAPLIBS) -if test "$TARGET_LINUX" = "true"; then - AC_ARG_WITH(pstack, - [ --with-pstack Use the pstack backtrace library], - [ USE_PSTACK=$withval ], - [ USE_PSTACK=no ]) - pstack_libs= - pstack_dir= - if test "$USE_PSTACK" = yes -a "$TARGET_LINUX" = "true" -a "$BASE_MACHINE_TYPE" = "i386" - then - have_libiberty= have_libbfd= - my_save_LIBS="$LIBS" -dnl I have no idea if this is a good test - can not find docs for libiberty - AC_CHECK_LIB([iberty], [fdmatch], - [have_libiberty=yes - AC_CHECK_LIB([bfd], [bfd_openr], [have_libbfd=yes], , [-liberty])]) - LIBS="$my_save_LIBS" - - if test x"$have_libiberty" = xyes -a x"$have_libbfd" = xyes - then - pstack_dir="pstack" - pstack_libs="../pstack/libpstack.a -lbfd -liberty" - # We must link staticly when using pstack - with_mysqld_ldflags="-all-static" - AC_SUBST([pstack_dir]) - AC_SUBST([pstack_libs]) - AC_DEFINE([USE_PSTACK], [1], [the pstack backtrace library]) -dnl This check isn't needed, but might be nice to give some feedback.... -dnl AC_CHECK_HEADER(libiberty.h, -dnl have_libiberty_h=yes, -dnl have_libiberty_h=no) - else - USE_PSTACK="no" - fi - else - USE_PSTACK="no" - fi -fi -AC_MSG_CHECKING([if we should use pstack]) -AC_MSG_RESULT([$USE_PSTACK]) - # Check for gtty if termio.h doesn't exists if test "$ac_cv_header_termio_h" = "no" -a "$ac_cv_header_termios_h" = "no" then @@ -1178,7 +1138,7 @@ dnl Is this the right match for DEC OSF on alpha? sql/Makefile.in) # Use gen_lex_hash.linux instead of gen_lex_hash # Add library dependencies to mysqld_DEPENDENCIES - lib_DEPENDENCIES="\$(pstack_libs) \$(openssl_libs) \$(yassl_libs)" + lib_DEPENDENCIES="\$(openssl_libs) \$(yassl_libs)" cat > $filesed << EOF s,\(\./gen_lex_hash\)\$(EXEEXT),\1.linux, s%\(mysqld_DEPENDENCIES = \)%\1$lib_DEPENDENCIES % @@ -2880,9 +2840,6 @@ esac AC_SUBST(MAKE_BINARY_DISTRIBUTION_OPTIONS) # Output results -if test -d "$srcdir/pstack" ; then - AC_CONFIG_FILES(pstack/Makefile pstack/aout/Makefile) -fi if test -d "$srcdir/cmd-line-utils/readline" ; then AC_CONFIG_FILES(cmd-line-utils/readline/Makefile) fi diff --git a/include/m_string.h b/include/m_string.h index 3e5cd063b7b..c963e605501 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -73,7 +73,9 @@ extern "C" { extern void *(*my_str_malloc)(size_t); extern void (*my_str_free)(void *); -#if defined(HAVE_STPCPY) +#if defined(HAVE_STPCPY) && MY_GNUC_PREREQ(3, 4) +#define strmov(A,B) __builtin_stpcpy((A),(B)) +#elif defined(HAVE_STPCPY) #define strmov(A,B) stpcpy((A),(B)) #ifndef stpcpy extern char *stpcpy(char *, const char *); /* For AIX with gcc 2.95.3 */ diff --git a/include/my_compiler.h b/include/my_compiler.h index c7d334999d0..5f898621159 100644 --- a/include/my_compiler.h +++ b/include/my_compiler.h @@ -76,6 +76,11 @@ /** Generic (compiler-independent) features. */ + +#ifndef MY_GNUC_PREREQ +# define MY_GNUC_PREREQ(maj, min) (0) +#endif + #ifndef MY_ALIGNOF # ifdef __cplusplus template<typename type> struct my_alignof_helper { char m1; type m2; }; diff --git a/include/mysql_embed.h b/include/mysql_embed.h index 4a7fd3ef63c..a7d6e610918 100644 --- a/include/mysql_embed.h +++ b/include/mysql_embed.h @@ -20,7 +20,6 @@ /* Things we don't need in the embedded version of MySQL */ /* TODO HF add #undef HAVE_VIO if we don't want client in embedded library */ -#undef HAVE_PSTACK /* No stacktrace */ #undef HAVE_OPENSSL #undef HAVE_SMEM /* No shared memory */ #undef HAVE_NDBCLUSTER_DB /* No NDB cluster */ diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 8c612b6894e..deb7cd10d2a 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -131,8 +131,8 @@ int STDCALL mysql_server_init(int argc __attribute__((unused)), mysql_port = MYSQL_PORT; #ifndef MSDOS { - struct servent *serv_ptr; - char *env; + char *env; + struct servent *serv_ptr __attribute__((unused)); /* if builder specifically requested a default port, use that diff --git a/mysql-test/collections/default.weekly b/mysql-test/collections/default.weekly index e69de29bb2d..5865864f4cd 100644 --- a/mysql-test/collections/default.weekly +++ b/mysql-test/collections/default.weekly @@ -0,0 +1,2 @@ +perl mysql-test-run.pl --timer --force --comment=1st --experimental=collections/default.experimental 1st +perl mysql-test-run.pl --timer --force --comment=big-tests --experimental=collections/default.experimental --vardir=var-big-tests --big-test --testcase-timeout=60 --suite-timeout=600 parts.partition_alter1_2_ndb parts.part_supported_sql_func_innodb parts.partition_alter1_2_innodb parts.partition_alter4_innodb parts.partition_alter1_1_2_ndb parts.partition_alter1_1_2_innodb parts.partition_alter1_1_ndb large_tests.alter_table rpl_ndb.rpl_truncate_7ndb_2 main.archive-big main.sum_distinct-big main.mysqlbinlog_row_big main.alter_table-big main.variables-big main.type_newdecimal-big main.read_many_rows_innodb main.log_tables-big main.count_distinct3 main.events_time_zone main.merge-big main.create-big main.events_stress main.ssl-big diff --git a/mysql-test/collections/mysql-5.1-bugteam.daily b/mysql-test/collections/mysql-5.1-bugteam.daily new file mode 100644 index 00000000000..0503bd49f73 --- /dev/null +++ b/mysql-test/collections/mysql-5.1-bugteam.daily @@ -0,0 +1,5 @@ +perl mysql-test-run.pl --timer --force --parallel=auto --comment=n_mix --vardir=var-n_mix --mysqld=--binlog-format=mixed --experimental=collections/default.experimental +perl mysql-test-run.pl --timer --force --parallel=auto --comment=ps_row --vardir=var-ps_row --ps-protocol --mysqld=--binlog-format=row --experimental=collections/default.experimental +perl mysql-test-run.pl --timer --force --parallel=auto --comment=embedded --vardir=var-emebbed --embedded --experimental=collections/default.experimental +perl mysql-test-run.pl --timer --force --parallel=auto --comment=rpl_binlog_row --vardir=var-rpl_binlog_row --suite=rpl,binlog --mysqld=--binlog-format=row --experimental=collections/default.experimental +perl mysql-test-run.pl --timer --force --parallel=auto --comment=funcs_1 --vardir=var-funcs_1 --suite=funcs_1 --experimental=collections/default.experimental diff --git a/mysql-test/collections/mysql-5.1-bugteam.push b/mysql-test/collections/mysql-5.1-bugteam.push new file mode 100644 index 00000000000..d01b98eb87f --- /dev/null +++ b/mysql-test/collections/mysql-5.1-bugteam.push @@ -0,0 +1,4 @@ +perl mysql-test-run.pl --timer --force --parallel=auto --comment=n_mix --vardir=var-n_mix --mysqld=--binlog-format=mixed --experimental=collections/default.experimental --skip-ndb +perl mysql-test-run.pl --timer --force --parallel=auto --comment=ps_row --vardir=var-ps_row --suite=main --ps-protocol --mysqld=--binlog-format=row --experimental=collections/default.experimental --skip-ndb +perl mysql-test-run.pl --timer --force --parallel=auto --comment=embedded --vardir=var-emebbed --suite=main --embedded --experimental=collections/default.experimental --skip-ndb +perl mysql-test-run.pl --timer --force --parallel=auto --comment=funcs_1 --vardir=var-funcs_1 --suite=funcs_1 --experimental=collections/default.experimental --skip-ndb diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index b55e91de14a..d57ddb17622 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -170,8 +170,6 @@ sub collect_test_cases ($$$) { if ( $opt_reorder && !$quick_collect) { # Reorder the test cases in an order that will make them faster to run - my %sort_criteria; - # Make a mapping of test name to a string that represents how that test # should be sorted among the other tests. Put the most important criterion # first, then a sub-criterion, then sub-sub-criterion, etc. @@ -183,24 +181,31 @@ sub collect_test_cases ($$$) { # Append the criteria for sorting, in order of importance. # push(@criteria, "ndb=" . ($tinfo->{'ndb_test'} ? "A" : "B")); + push(@criteria, $tinfo->{template_path}); # Group test with equal options together. # Ending with "~" makes empty sort later than filled my $opts= $tinfo->{'master_opt'} ? $tinfo->{'master_opt'} : []; push(@criteria, join("!", sort @{$opts}) . "~"); + # Add slave opts if any + if ($tinfo->{'slave_opt'}) + { + push(@criteria, join("!", sort @{$tinfo->{'slave_opt'}})); + } + # This sorts tests with force-restart *before* identical tests + push(@criteria, $tinfo->{force_restart} ? "force-restart" : "no-restart"); - $sort_criteria{$tinfo->{name}} = join(" ", @criteria); + $tinfo->{criteria}= join(" ", @criteria); } - @$cases = sort { - $sort_criteria{$a->{'name'}} . $a->{'name'} cmp - $sort_criteria{$b->{'name'}} . $b->{'name'}; } @$cases; + @$cases = sort {$a->{criteria} cmp $b->{criteria}; } @$cases; # For debugging the sort-order # foreach my $tinfo (@$cases) # { - # print("$sort_criteria{$tinfo->{'name'}} -> \t$tinfo->{'name'}\n"); + # my $tname= $tinfo->{name} . ' ' . $tinfo->{combination}; + # my $crit= $tinfo->{criteria}; + # print("$tname\n\t$crit\n"); # } - } if (defined $print_testcases){ diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 22d0071c89d..22c60cf1997 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -663,22 +663,40 @@ sub run_test_server ($$$) { next; } - # Prefer same configuration, or just use next if --noreorder - if (!$opt_reorder or (defined $result and - $result->{template_path} eq $t->{template_path})) - { - #mtr_report("Test uses same config => good match"); - # Test uses same config => good match - $next= splice(@$tests, $i, 1); - last; - } - # Second best choice is the first that does not fulfill # any of the above conditions if (!defined $second_best){ #mtr_report("Setting second_best to $i"); $second_best= $i; } + + # Smart allocation of next test within this thread. + + if ($opt_reorder and $opt_parallel > 1 and defined $result) + { + my $wid= $result->{worker}; + # Reserved for other thread, try next + next if (defined $t->{reserved} and $t->{reserved} != $wid); + if (! defined $t->{reserved}) + { + # Force-restart not relevant when comparing *next* test + $t->{criteria} =~ s/force-restart$/no-restart/; + my $criteria= $t->{criteria}; + # Reserve similar tests for this worker, but not too many + my $maxres= (@$tests - $i) / $opt_parallel + 1; + for (my $j= $i+1; $j <= $i + $maxres; $j++) + { + my $tt= $tests->[$j]; + last unless defined $tt; + last if $tt->{criteria} ne $criteria; + $tt->{reserved}= $wid; + } + } + } + + # At this point we have found next suitable test + $next= splice(@$tests, $i, 1); + last; } # Use second best choice if no other test has been found @@ -687,10 +705,12 @@ sub run_test_server ($$$) { mtr_error("Internal error, second best too large($second_best)") if $second_best > $#$tests; $next= splice(@$tests, $second_best, 1); + delete $next->{reserved}; } if ($next) { - #$next->print_test(); + # We don't need this any more + delete $next->{criteria}; $next->write_test($sock, 'TESTCASE'); $running{$next->key()}= $next; $num_ndb_tests++ if ($next->{ndb_test}); @@ -773,6 +793,11 @@ sub run_worker ($) { delete($test->{'comment'}); delete($test->{'logfile'}); + # A sanity check. Should this happen often we need to look at it. + if (defined $test->{reserved} && $test->{reserved} != $thread_num) { + my $tres= $test->{reserved}; + mtr_warning("Test reserved for w$tres picked up by w$thread_num"); + } $test->{worker} = $thread_num if $opt_parallel > 1; run_testcase($test); @@ -4582,17 +4607,6 @@ sub server_need_restart { } } - # Temporary re-enable the "always restart slave" hack - # this should be removed asap, but will require that each rpl - # testcase cleanup better after itself - ie. stop and reset - # replication - # Use the "#!use-slave-opt" marker to detect that this is a "slave" - # server - if ( $server->option("#!use-slave-opt") ){ - mtr_verbose_restart($server, "Always restart slave(s)"); - return 1; - } - my $is_mysqld= grep ($server eq $_, mysqlds()); if ($is_mysqld) { diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 4ff4cfa586b..48e837f180f 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -1343,4 +1343,18 @@ SELECT 1 FROM t1 ORDER BY @x:=makedate(a,a); 1 1 DROP TABLE t1; +# +# Bug #52160: crash and inconsistent results when grouping +# by a function and column +# +CREATE TABLE t1(a CHAR(10) NOT NULL); +INSERT INTO t1 VALUES (''),(''); +SELECT COUNT(*) FROM t1 GROUP BY TIME_TO_SEC(a); +COUNT(*) +2 +Warnings: +Warning 1292 Truncated incorrect time value: '' +Warning 1292 Truncated incorrect time value: '' +Warning 1292 Truncated incorrect time value: '' +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/r/log_tables.result b/mysql-test/r/log_tables.result index f8321520880..fcde09db7c5 100644 --- a/mysql-test/r/log_tables.result +++ b/mysql-test/r/log_tables.result @@ -899,6 +899,16 @@ TIMESTAMP 1 1 SELECT SQL_NO_CACHE 'Bug#31700 - KEY', f1,f2,f3,SLEEP(1.1) FROM t1 TIMESTAMP 1 1 SELECT SQL_NO_CACHE 'Bug#31700 - PK', f1,f2,f3,SLEEP(1.1) FROM t1 WHERE f1=2 DROP TABLE t1; TRUNCATE TABLE mysql.slow_log; +use mysql; +drop table if exists renamed_general_log; +drop table if exists renamed_slow_log; +RENAME TABLE general_log TO renamed_general_log; +ERROR HY000: Cannot rename 'general_log'. When logging enabled, rename to/from log table must rename two tables: the log table to an archive table and another table back to 'general_log' +RENAME TABLE slow_log TO renamed_slow_log; +ERROR HY000: Cannot rename 'slow_log'. When logging enabled, rename to/from log table must rename two tables: the log table to an archive table and another table back to 'slow_log' +use test; +flush tables with read lock; +unlock tables; SET @@session.long_query_time= @old_long_query_time; SET @@global.log_output= @old_log_output; SET @@global.slow_query_log= @old_slow_query_log; diff --git a/mysql-test/r/sp-bugs.result b/mysql-test/r/sp-bugs.result index 2374b433fba..507c73c2683 100644 --- a/mysql-test/r/sp-bugs.result +++ b/mysql-test/r/sp-bugs.result @@ -73,4 +73,40 @@ CALL p1 (); ERROR HY000: Trigger does not exist DROP TABLE t1; DROP PROCEDURE p1; +# +# Bug#54375: Error in stored procedure leaves connection +# in different default schema +# +SET @@SQL_MODE = 'STRICT_ALL_TABLES'; +DROP DATABASE IF EXISTS db1; +CREATE DATABASE db1; +USE db1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (c1 int NOT NULL PRIMARY KEY); +INSERT INTO t1 VALUES (1); +CREATE FUNCTION f1 ( +some_value int +) +RETURNS smallint +DETERMINISTIC +BEGIN +INSERT INTO t1 SET c1 = some_value; +RETURN(LAST_INSERT_ID()); +END$$ +DROP DATABASE IF EXISTS db2; +CREATE DATABASE db2; +USE db2; +SELECT DATABASE(); +DATABASE() +db2 +SELECT db1.f1(1); +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +SELECT DATABASE(); +DATABASE() +db2 +USE test; +DROP FUNCTION db1.f1; +DROP TABLE db1.t1; +DROP DATABASE db1; +DROP DATABASE db2; End of 5.1 tests diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result index 08c30d884fd..e6fd49b4247 100644 --- a/mysql-test/r/type_blob.result +++ b/mysql-test/r/type_blob.result @@ -974,3 +974,14 @@ ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967 explain select convert(1, binary(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)); ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967295) End of 5.0 tests +# Bug #52160: crash and inconsistent results when grouping +# by a function and column +CREATE FUNCTION f1() RETURNS TINYBLOB RETURN 1; +CREATE TABLE t1(a CHAR(1)); +INSERT INTO t1 VALUES ('0'), ('0'); +SELECT COUNT(*) FROM t1 GROUP BY f1(), a; +COUNT(*) +2 +DROP FUNCTION f1; +DROP TABLE t1; +End of 5.1 tests diff --git a/mysql-test/r/variables-big.result b/mysql-test/r/variables-big.result index 960fc6d22f4..71b32393d82 100644 --- a/mysql-test/r/variables-big.result +++ b/mysql-test/r/variables-big.result @@ -1,20 +1,20 @@ SET SESSION transaction_prealloc_size=1024*1024*1024*1; SHOW PROCESSLIST; Id User Host db Command Time State Info -<Id> root localhost test Query <Time> NULL SHOW PROCESSLIST +<Id> root <Host> test Query <Time> NULL SHOW PROCESSLIST SET SESSION transaction_prealloc_size=1024*1024*1024*2; SHOW PROCESSLIST; Id User Host db Command Time State Info -<Id> root localhost test Query <Time> NULL SHOW PROCESSLIST +<Id> root <Host> test Query <Time> NULL SHOW PROCESSLIST SET SESSION transaction_prealloc_size=1024*1024*1024*3; SHOW PROCESSLIST; Id User Host db Command Time State Info -<Id> root localhost test Query <Time> NULL SHOW PROCESSLIST +<Id> root <Host> test Query <Time> NULL SHOW PROCESSLIST SET SESSION transaction_prealloc_size=1024*1024*1024*4; SHOW PROCESSLIST; Id User Host db Command Time State Info -<Id> root localhost test Query <Time> NULL SHOW PROCESSLIST +<Id> root <Host> test Query <Time> NULL SHOW PROCESSLIST SET SESSION transaction_prealloc_size=1024*1024*1024*5; SHOW PROCESSLIST; Id User Host db Command Time State Info -<Id> root localhost test Query <Time> NULL SHOW PROCESSLIST +<Id> root <Host> test Query <Time> NULL SHOW PROCESSLIST diff --git a/mysql-test/suite/binlog/t/binlog_index-master.opt b/mysql-test/suite/binlog/t/binlog_index-master.opt new file mode 100644 index 00000000000..cef79bc8585 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_index-master.opt @@ -0,0 +1 @@ +--force-restart diff --git a/mysql-test/suite/binlog/t/binlog_stm_binlog-master.opt b/mysql-test/suite/binlog/t/binlog_stm_binlog-master.opt index ad2c6a647b5..377e2114039 100644 --- a/mysql-test/suite/binlog/t/binlog_stm_binlog-master.opt +++ b/mysql-test/suite/binlog/t/binlog_stm_binlog-master.opt @@ -1 +1,2 @@ -O max_binlog_size=4096 +--force-restart diff --git a/mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt b/mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt index e2cfcb299cf..2a1187d3fe4 100644 --- a/mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt +++ b/mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt @@ -1 +1,2 @@ --binlog-do-db=b42829 +--force-restart diff --git a/mysql-test/suite/ibmdb2i/include/have_i54.inc b/mysql-test/suite/ibmdb2i/include/have_i54.inc deleted file mode 100755 index 7054e196153..00000000000 --- a/mysql-test/suite/ibmdb2i/include/have_i54.inc +++ /dev/null @@ -1,20 +0,0 @@ -# Check for IBM i 6.1 or later ---disable_query_log -system uname -rv > $MYSQLTEST_VARDIR/tmp/version; ---disable_warnings -drop table if exists uname_vr; ---enable_warnings -create temporary table uname_vr (r int, v int); ---disable_warnings -eval LOAD DATA INFILE "$MYSQLTEST_VARDIR/tmp/version" into table uname_vr fields terminated by ' '; ---enable_warnings -let $ok = `select count(*) from uname_vr where v = 5 and r = 4`; -drop table uname_vr; -remove_file $MYSQLTEST_VARDIR/tmp/version; ---enable_query_log -if (!$ok) -{ - skip "Need IBM i 5.4 or later"; -} - - diff --git a/mysql-test/suite/ibmdb2i/include/have_i61.inc b/mysql-test/suite/ibmdb2i/include/have_i61.inc deleted file mode 100644 index 84b9a17c1d8..00000000000 --- a/mysql-test/suite/ibmdb2i/include/have_i61.inc +++ /dev/null @@ -1,20 +0,0 @@ -# Check for IBM i 6.1 or later ---disable_query_log -system uname -rv > $MYSQLTEST_VARDIR/tmp/version; ---disable_warnings -drop table if exists uname_vr; ---enable_warnings -create temporary table uname_vr (r int, v int); ---disable_warnings -eval LOAD DATA INFILE "$MYSQLTEST_VARDIR/tmp/version" into table uname_vr fields terminated by ' '; ---enable_warnings -let $ok = `select count(*) from uname_vr where v > 5`; -drop table uname_vr; -remove_file $MYSQLTEST_VARDIR/tmp/version; ---enable_query_log -if (!$ok) -{ - skip "Need IBM i 6.1 or later"; -} - - diff --git a/mysql-test/suite/ibmdb2i/include/have_ibmdb2i.inc b/mysql-test/suite/ibmdb2i/include/have_ibmdb2i.inc deleted file mode 100644 index f3ef0b4f1ac..00000000000 --- a/mysql-test/suite/ibmdb2i/include/have_ibmdb2i.inc +++ /dev/null @@ -1,6 +0,0 @@ -if (!`SELECT count(*) FROM information_schema.engines WHERE - (support = 'YES' OR support = 'DEFAULT') AND - engine = 'ibmdb2i'`) -{ - skip Need ibmdb2i engine; -} diff --git a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44020.result b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44020.result deleted file mode 100644 index ddf92db6bca..00000000000 --- a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44020.result +++ /dev/null @@ -1,11 +0,0 @@ -create schema `A12345_@$#`; -create table `A12345_@$#`.t1 (i int) engine=ibmdb2i; -show create table `A12345_@$#`.t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `i` int(11) DEFAULT NULL -) ENGINE=IBMDB2I DEFAULT CHARSET=latin1 -select * from `A12345_@$#`.t1; -i -drop table `A12345_@$#`.t1; -drop schema `A12345_@$#`; diff --git a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44025.result b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44025.result deleted file mode 100644 index 10a3070fcc4..00000000000 --- a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44025.result +++ /dev/null @@ -1,4 +0,0 @@ -create table t1 (c char(10) collate utf8_swedish_ci, index(c)) engine=ibmdb2i; -drop table t1; -create table t1 (c char(10) collate ucs2_swedish_ci, index(c)) engine=ibmdb2i; -drop table t1; diff --git a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44232.result b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44232.result deleted file mode 100755 index 8276b401073..00000000000 --- a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44232.result +++ /dev/null @@ -1,4 +0,0 @@ -create table t1 (c char(1) character set armscii8) engine=ibmdb2i; -ERROR HY000: Can't create table 'test.t1' (errno: 2504) -create table t1 (c char(1) character set eucjpms ) engine=ibmdb2i; -ERROR HY000: Can't create table 'test.t1' (errno: 2504) diff --git a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44610.result b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44610.result deleted file mode 100755 index 311e800e1b0..00000000000 --- a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_44610.result +++ /dev/null @@ -1,18 +0,0 @@ -create table ABC (i int) engine=ibmdb2i; -drop table ABC; -create table `1234567890ABC` (i int) engine=ibmdb2i; -drop table `1234567890ABC`; -create table `!@#$%` (i int) engine=ibmdb2i; -drop table `!@#$%`; -create table `ABCD#########` (i int) engine=ibmdb2i; -drop table `ABCD#########`; -create table `_` (i int) engine=ibmdb2i; -drop table `_`; -create table `abc##def` (i int) engine=ibmdb2i; -drop table `abc##def`; -set names utf8; -create table İ (s1 int) engine=ibmdb2i; -drop table İ; -create table İİ (s1 int) engine=ibmdb2i; -drop table İİ; -set names latin1; diff --git a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_45196.result b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_45196.result deleted file mode 100644 index 916e1d93ee5..00000000000 --- a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_45196.result +++ /dev/null @@ -1,33 +0,0 @@ -drop table if exists t1; -create table t1 (c char(10), index(c)) collate ucs2_czech_ci engine=ibmdb2i; -insert into t1 values ("ch"),("h"),("i"); -select * from t1 order by c; -c -h -ch -i -drop table t1; -create table t1 (c char(10), index(c)) collate utf8_czech_ci engine=ibmdb2i; -insert into t1 values ("ch"),("h"),("i"); -select * from t1 order by c; -c -h -ch -i -drop table t1; -create table t1 (c char(10), index(c)) collate ucs2_danish_ci engine=ibmdb2i; -insert into t1 values("abc"),("abcd"),("aaaa"); -select c from t1 order by c; -c -abc -abcd -aaaa -drop table t1; -create table t1 (c char(10), index(c)) collate utf8_danish_ci engine=ibmdb2i; -insert into t1 values("abc"),("abcd"),("aaaa"); -select c from t1 order by c; -c -abc -abcd -aaaa -drop table t1; diff --git a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_45793.result b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_45793.result deleted file mode 100644 index 2392b746877..00000000000 --- a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_45793.result +++ /dev/null @@ -1,7 +0,0 @@ -drop table if exists t1; -create table t1 (c char(10), index(c)) charset macce engine=ibmdb2i; -insert into t1 values ("test"); -select * from t1 order by c; -c -test -drop table t1; diff --git a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_45983.result b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_45983.result deleted file mode 100644 index b9f4dcfc656..00000000000 --- a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_45983.result +++ /dev/null @@ -1,20 +0,0 @@ -set ibmdb2i_create_index_option=1; -drop schema if exists test1; -create schema test1; -use test1; -CREATE TABLE t1 (f int primary key, index(f)) engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (f char(10) collate utf8_bin primary key, index(f)) engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (f char(10) collate latin1_swedish_ci primary key, index(f)) engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (f char(10) collate latin1_swedish_ci primary key, i int, index i(i,f)) engine=ibmdb2i; -drop table t1; -create table fd (SQSSEQ CHAR(10)) engine=ibmdb2i; -select * from fd; -SQSSEQ -*HEX -*HEX -*HEX -*HEX -drop table fd; diff --git a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_49329.result b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_49329.result deleted file mode 100644 index d5bfc2579fd..00000000000 --- a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_49329.result +++ /dev/null @@ -1,9 +0,0 @@ -create table ABC (i int) engine=ibmdb2i; -insert into ABC values(1); -create table abc (i int) engine=ibmdb2i; -insert into abc values (2); -select * from ABC; -i -1 -drop table ABC; -drop table abc; diff --git a/mysql-test/suite/ibmdb2i/r/ibmdb2i_collations.result b/mysql-test/suite/ibmdb2i/r/ibmdb2i_collations.result deleted file mode 100644 index 4f7d71cab2d..00000000000 --- a/mysql-test/suite/ibmdb2i/r/ibmdb2i_collations.result +++ /dev/null @@ -1,1204 +0,0 @@ -drop table if exists t1, ffd, fd; -CREATE TABLE t1 (armscii8_bin integer, c char(10), v varchar(20), index(c), index(v)) collate armscii8_bin engine=ibmdb2i; -CREATE TABLE t1 (armscii8_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate armscii8_general_ci engine=ibmdb2i; -CREATE TABLE t1 (ascii_bin integer, c char(10), v varchar(20), index(c), index(v)) collate ascii_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (ascii_bin char(10) primary key) collate ascii_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ascii_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ascii_general_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (ascii_general_ci char(10) primary key) collate ascii_general_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (big5_bin integer, c char(10), v varchar(20), index(c), index(v)) collate big5_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (big5_bin char(10) primary key) collate big5_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (big5_chinese_ci integer, c char(10), v varchar(20), index(c), index(v)) collate big5_chinese_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (big5_chinese_ci char(10) primary key) collate big5_chinese_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (cp1250_bin integer, c char(10), v varchar(20), index(c), index(v)) collate cp1250_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (cp1250_bin char(10) primary key) collate cp1250_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (cp1250_croatian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate cp1250_croatian_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (cp1250_croatian_ci char(10) primary key) collate cp1250_croatian_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (cp1250_czech_cs integer, c char(10), v varchar(20), index(c), index(v)) collate cp1250_czech_cs engine=ibmdb2i; -CREATE TABLE t1 (cp1250_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate cp1250_general_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (cp1250_general_ci char(10) primary key) collate cp1250_general_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (cp1250_polish_ci integer, c char(10), v varchar(20), index(c), index(v)) collate cp1250_polish_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (cp1250_polish_ci char(10) primary key) collate cp1250_polish_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (cp1251_bin integer, c char(10), v varchar(20), index(c), index(v)) collate cp1251_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (cp1251_bin char(10) primary key) collate cp1251_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (cp1251_bulgarian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate cp1251_bulgarian_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (cp1251_bulgarian_ci char(10) primary key) collate cp1251_bulgarian_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (cp1251_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate cp1251_general_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (cp1251_general_ci char(10) primary key) collate cp1251_general_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (cp1251_general_cs integer, c char(10), v varchar(20), index(c), index(v)) collate cp1251_general_cs engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (cp1251_general_cs char(10) primary key) collate cp1251_general_cs engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (cp1251_ukrainian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate cp1251_ukrainian_ci engine=ibmdb2i; -CREATE TABLE t1 (cp1256_bin integer, c char(10), v varchar(20), index(c), index(v)) collate cp1256_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (cp1256_bin char(10) primary key) collate cp1256_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (cp1256_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate cp1256_general_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (cp1256_general_ci char(10) primary key) collate cp1256_general_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (cp1257_bin integer, c char(10), v varchar(20), index(c), index(v)) collate cp1257_bin engine=ibmdb2i; -CREATE TABLE t1 (cp1257_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate cp1257_general_ci engine=ibmdb2i; -CREATE TABLE t1 (cp1257_lithuanian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate cp1257_lithuanian_ci engine=ibmdb2i; -CREATE TABLE t1 (cp850_bin integer, c char(10), v varchar(20), index(c), index(v)) collate cp850_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (cp850_bin char(10) primary key) collate cp850_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (cp850_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate cp850_general_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (cp850_general_ci char(10) primary key) collate cp850_general_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (cp852_bin integer, c char(10), v varchar(20), index(c), index(v)) collate cp852_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (cp852_bin char(10) primary key) collate cp852_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (cp852_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate cp852_general_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (cp852_general_ci char(10) primary key) collate cp852_general_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (cp866_bin integer, c char(10), v varchar(20), index(c), index(v)) collate cp866_bin engine=ibmdb2i; -CREATE TABLE t1 (cp866_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate cp866_general_ci engine=ibmdb2i; -CREATE TABLE t1 (cp932_bin integer, c char(10), v varchar(20), index(c), index(v)) collate cp932_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (cp932_bin char(10) primary key) collate cp932_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (cp932_japanese_ci integer, c char(10), v varchar(20), index(c), index(v)) collate cp932_japanese_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (cp932_japanese_ci char(10) primary key) collate cp932_japanese_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (dec8_bin integer, c char(10), v varchar(20), index(c), index(v)) collate dec8_bin engine=ibmdb2i; -CREATE TABLE t1 (dec8_swedish_ci integer, c char(10), v varchar(20), index(c), index(v)) collate dec8_swedish_ci engine=ibmdb2i; -CREATE TABLE t1 (eucjpms_bin integer, c char(10), v varchar(20), index(c), index(v)) collate eucjpms_bin engine=ibmdb2i; -CREATE TABLE t1 (eucjpms_japanese_ci integer, c char(10), v varchar(20), index(c), index(v)) collate eucjpms_japanese_ci engine=ibmdb2i; -CREATE TABLE t1 (euckr_bin integer, c char(10), v varchar(20), index(c), index(v)) collate euckr_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (euckr_bin char(10) primary key) collate euckr_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (euckr_korean_ci integer, c char(10), v varchar(20), index(c), index(v)) collate euckr_korean_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (euckr_korean_ci char(10) primary key) collate euckr_korean_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (gb2312_bin integer, c char(10), v varchar(20), index(c), index(v)) collate gb2312_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (gb2312_bin char(10) primary key) collate gb2312_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (gb2312_chinese_ci integer, c char(10), v varchar(20), index(c), index(v)) collate gb2312_chinese_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (gb2312_chinese_ci char(10) primary key) collate gb2312_chinese_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (gbk_bin integer, c char(10), v varchar(20), index(c), index(v)) collate gbk_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (gbk_bin char(10) primary key) collate gbk_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (gbk_chinese_ci integer, c char(10), v varchar(20), index(c), index(v)) collate gbk_chinese_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (gbk_chinese_ci char(10) primary key) collate gbk_chinese_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (geostd8_bin integer, c char(10), v varchar(20), index(c), index(v)) collate geostd8_bin engine=ibmdb2i; -CREATE TABLE t1 (geostd8_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate geostd8_general_ci engine=ibmdb2i; -CREATE TABLE t1 (greek_bin integer, c char(10), v varchar(20), index(c), index(v)) collate greek_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (greek_bin char(10) primary key) collate greek_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (greek_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate greek_general_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (greek_general_ci char(10) primary key) collate greek_general_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (hebrew_bin integer, c char(10), v varchar(20), index(c), index(v)) collate hebrew_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (hebrew_bin char(10) primary key) collate hebrew_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (hebrew_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate hebrew_general_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (hebrew_general_ci char(10) primary key) collate hebrew_general_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (hp8_bin integer, c char(10), v varchar(20), index(c), index(v)) collate hp8_bin engine=ibmdb2i; -CREATE TABLE t1 (hp8_english_ci integer, c char(10), v varchar(20), index(c), index(v)) collate hp8_english_ci engine=ibmdb2i; -CREATE TABLE t1 (keybcs2_bin integer, c char(10), v varchar(20), index(c), index(v)) collate keybcs2_bin engine=ibmdb2i; -CREATE TABLE t1 (keybcs2_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate keybcs2_general_ci engine=ibmdb2i; -CREATE TABLE t1 (koi8r_bin integer, c char(10), v varchar(20), index(c), index(v)) collate koi8r_bin engine=ibmdb2i; -CREATE TABLE t1 (koi8r_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate koi8r_general_ci engine=ibmdb2i; -CREATE TABLE t1 (koi8u_bin integer, c char(10), v varchar(20), index(c), index(v)) collate koi8u_bin engine=ibmdb2i; -CREATE TABLE t1 (koi8u_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate koi8u_general_ci engine=ibmdb2i; -CREATE TABLE t1 (latin1_bin integer, c char(10), v varchar(20), index(c), index(v)) collate latin1_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (latin1_bin char(10) primary key) collate latin1_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (latin1_danish_ci integer, c char(10), v varchar(20), index(c), index(v)) collate latin1_danish_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (latin1_danish_ci char(10) primary key) collate latin1_danish_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (latin1_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate latin1_general_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (latin1_general_ci char(10) primary key) collate latin1_general_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (latin1_general_cs integer, c char(10), v varchar(20), index(c), index(v)) collate latin1_general_cs engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (latin1_general_cs char(10) primary key) collate latin1_general_cs engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (latin1_german1_ci integer, c char(10), v varchar(20), index(c), index(v)) collate latin1_german1_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (latin1_german1_ci char(10) primary key) collate latin1_german1_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (latin1_german2_ci integer, c char(10), v varchar(20), index(c), index(v)) collate latin1_german2_ci engine=ibmdb2i; -CREATE TABLE t1 (latin1_spanish_ci integer, c char(10), v varchar(20), index(c), index(v)) collate latin1_spanish_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (latin1_spanish_ci char(10) primary key) collate latin1_spanish_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (latin1_swedish_ci integer, c char(10), v varchar(20), index(c), index(v)) collate latin1_swedish_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (latin1_swedish_ci char(10) primary key) collate latin1_swedish_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (latin2_bin integer, c char(10), v varchar(20), index(c), index(v)) collate latin2_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (latin2_bin char(10) primary key) collate latin2_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (latin2_croatian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate latin2_croatian_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (latin2_croatian_ci char(10) primary key) collate latin2_croatian_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (latin2_czech_cs integer, c char(10), v varchar(20), index(c), index(v)) collate latin2_czech_cs engine=ibmdb2i; -CREATE TABLE t1 (latin2_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate latin2_general_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (latin2_general_ci char(10) primary key) collate latin2_general_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (latin2_hungarian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate latin2_hungarian_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (latin2_hungarian_ci char(10) primary key) collate latin2_hungarian_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (latin5_bin integer, c char(10), v varchar(20), index(c), index(v)) collate latin5_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (latin5_bin char(10) primary key) collate latin5_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (latin5_turkish_ci integer, c char(10), v varchar(20), index(c), index(v)) collate latin5_turkish_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (latin5_turkish_ci char(10) primary key) collate latin5_turkish_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (latin7_bin integer, c char(10), v varchar(20), index(c), index(v)) collate latin7_bin engine=ibmdb2i; -CREATE TABLE t1 (latin7_estonian_cs integer, c char(10), v varchar(20), index(c), index(v)) collate latin7_estonian_cs engine=ibmdb2i; -CREATE TABLE t1 (latin7_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate latin7_general_ci engine=ibmdb2i; -CREATE TABLE t1 (latin7_general_cs integer, c char(10), v varchar(20), index(c), index(v)) collate latin7_general_cs engine=ibmdb2i; -CREATE TABLE t1 (macce_bin integer, c char(10), v varchar(20), index(c), index(v)) collate macce_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (macce_bin char(10) primary key) collate macce_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (macce_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate macce_general_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (macce_general_ci char(10) primary key) collate macce_general_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (macroman_bin integer, c char(10), v varchar(20), index(c), index(v)) collate macroman_bin engine=ibmdb2i; -CREATE TABLE t1 (macroman_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate macroman_general_ci engine=ibmdb2i; -CREATE TABLE t1 (sjis_bin integer, c char(10), v varchar(20), index(c), index(v)) collate sjis_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (sjis_bin char(10) primary key) collate sjis_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (sjis_japanese_ci integer, c char(10), v varchar(20), index(c), index(v)) collate sjis_japanese_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (sjis_japanese_ci char(10) primary key) collate sjis_japanese_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (swe7_bin integer, c char(10), v varchar(20), index(c), index(v)) collate swe7_bin engine=ibmdb2i; -CREATE TABLE t1 (swe7_swedish_ci integer, c char(10), v varchar(20), index(c), index(v)) collate swe7_swedish_ci engine=ibmdb2i; -CREATE TABLE t1 (tis620_bin integer, c char(10), v varchar(20), index(c), index(v)) collate tis620_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (tis620_bin char(10) primary key) collate tis620_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (tis620_thai_ci integer, c char(10), v varchar(20), index(c), index(v)) collate tis620_thai_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 11 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 23 NULL 6 Using where -drop table t1; -create table t1 (tis620_thai_ci char(10) primary key) collate tis620_thai_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ucs2_bin integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (ucs2_bin char(10) primary key) collate ucs2_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ucs2_czech_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_czech_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (ucs2_czech_ci char(10) primary key) collate ucs2_czech_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ucs2_danish_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_danish_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (ucs2_danish_ci char(10) primary key) collate ucs2_danish_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ucs2_esperanto_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_esperanto_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (ucs2_esperanto_ci char(10) primary key) collate ucs2_esperanto_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ucs2_estonian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_estonian_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (ucs2_estonian_ci char(10) primary key) collate ucs2_estonian_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ucs2_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_general_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (ucs2_general_ci char(10) primary key) collate ucs2_general_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ucs2_hungarian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_hungarian_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (ucs2_hungarian_ci char(10) primary key) collate ucs2_hungarian_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ucs2_icelandic_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_icelandic_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (ucs2_icelandic_ci char(10) primary key) collate ucs2_icelandic_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ucs2_latvian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_latvian_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (ucs2_latvian_ci char(10) primary key) collate ucs2_latvian_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ucs2_lithuanian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_lithuanian_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (ucs2_lithuanian_ci char(10) primary key) collate ucs2_lithuanian_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ucs2_persian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_persian_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (ucs2_persian_ci char(10) primary key) collate ucs2_persian_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ucs2_polish_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_polish_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (ucs2_polish_ci char(10) primary key) collate ucs2_polish_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ucs2_romanian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_romanian_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (ucs2_romanian_ci char(10) primary key) collate ucs2_romanian_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ucs2_roman_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_roman_ci engine=ibmdb2i; -CREATE TABLE t1 (ucs2_slovak_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_slovak_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (ucs2_slovak_ci char(10) primary key) collate ucs2_slovak_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ucs2_slovenian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_slovenian_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (ucs2_slovenian_ci char(10) primary key) collate ucs2_slovenian_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ucs2_spanish2_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_spanish2_ci engine=ibmdb2i; -CREATE TABLE t1 (ucs2_spanish_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_spanish_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (ucs2_spanish_ci char(10) primary key) collate ucs2_spanish_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ucs2_swedish_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_swedish_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (ucs2_swedish_ci char(10) primary key) collate ucs2_swedish_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ucs2_turkish_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_turkish_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (ucs2_turkish_ci char(10) primary key) collate ucs2_turkish_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ucs2_unicode_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ucs2_unicode_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 21 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 43 NULL 6 Using where -drop table t1; -create table t1 (ucs2_unicode_ci char(10) primary key) collate ucs2_unicode_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ujis_bin integer, c char(10), v varchar(20), index(c), index(v)) collate ujis_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (ujis_bin char(10) primary key) collate ujis_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (ujis_japanese_ci integer, c char(10), v varchar(20), index(c), index(v)) collate ujis_japanese_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (ujis_japanese_ci char(10) primary key) collate ujis_japanese_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (utf8_bin integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_bin engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (utf8_bin char(10) primary key) collate utf8_bin engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (utf8_czech_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_czech_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (utf8_czech_ci char(10) primary key) collate utf8_czech_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (utf8_danish_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_danish_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (utf8_danish_ci char(10) primary key) collate utf8_danish_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (utf8_esperanto_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_esperanto_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (utf8_esperanto_ci char(10) primary key) collate utf8_esperanto_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (utf8_estonian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_estonian_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (utf8_estonian_ci char(10) primary key) collate utf8_estonian_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (utf8_general_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_general_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (utf8_general_ci char(10) primary key) collate utf8_general_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (utf8_hungarian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_hungarian_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (utf8_hungarian_ci char(10) primary key) collate utf8_hungarian_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (utf8_icelandic_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_icelandic_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (utf8_icelandic_ci char(10) primary key) collate utf8_icelandic_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (utf8_latvian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_latvian_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (utf8_latvian_ci char(10) primary key) collate utf8_latvian_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (utf8_lithuanian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_lithuanian_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (utf8_lithuanian_ci char(10) primary key) collate utf8_lithuanian_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (utf8_persian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_persian_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (utf8_persian_ci char(10) primary key) collate utf8_persian_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (utf8_polish_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_polish_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (utf8_polish_ci char(10) primary key) collate utf8_polish_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (utf8_romanian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_romanian_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (utf8_romanian_ci char(10) primary key) collate utf8_romanian_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (utf8_roman_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_roman_ci engine=ibmdb2i; -CREATE TABLE t1 (utf8_slovak_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_slovak_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (utf8_slovak_ci char(10) primary key) collate utf8_slovak_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (utf8_slovenian_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_slovenian_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (utf8_slovenian_ci char(10) primary key) collate utf8_slovenian_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (utf8_spanish2_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_spanish2_ci engine=ibmdb2i; -CREATE TABLE t1 (utf8_spanish_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_spanish_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (utf8_spanish_ci char(10) primary key) collate utf8_spanish_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (utf8_swedish_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_swedish_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (utf8_swedish_ci char(10) primary key) collate utf8_swedish_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (utf8_turkish_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_turkish_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (utf8_turkish_ci char(10) primary key) collate utf8_turkish_ci engine=ibmdb2i; -drop table t1; -CREATE TABLE t1 (utf8_unicode_ci integer, c char(10), v varchar(20), index(c), index(v)) collate utf8_unicode_ci engine=ibmdb2i; -insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); -insert into t1 select * from t1; -explain select c,v from t1 force index(c) where c like "ab%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range c c 31 NULL 6 Using where -explain select c,v from t1 force index(v) where v like "de%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 63 NULL 6 Using where -drop table t1; -create table t1 (utf8_unicode_ci char(10) primary key) collate utf8_unicode_ci engine=ibmdb2i; -drop table t1; -create table ffd (WHCHD1 CHAR(20), WHCSID decimal(5,0)) engine=ibmdb2i; -create table fd (SQSSEQ CHAR(10)) engine=ibmdb2i; -create temporary table intermed (row integer key auto_increment, cs char(30), ccsid integer); -insert into intermed (cs, ccsid) select * from ffd; -create temporary table intermed2 (row integer key auto_increment, srtseq char(10)); -insert into intermed2 (srtseq) select * from fd; -select ccsid, cs, srtseq from intermed inner join intermed2 on intermed.row = intermed2.row; -ccsid cs srtseq -500 "ascii_bin" QBLA101F4U -500 "ascii_general_ci" QALA101F4S -1200 "big5_bin" QBCHT04B0U -1200 "big5_chinese_ci" QACHT04B0S -1153 "cp1250_bin" QELA20481U -1153 "cp1250_croatian_ci" QALA20481S -1153 "cp1250_general_ci" QCLA20481S -1153 "cp1250_polish_ci" QDLA20481S -1025 "cp1251_bin" QCCYR0401U -1025 "cp1251_bulgarian_ci QACYR0401S -1025 "cp1251_general_ci" QBCYR0401S -1025 "cp1251_general_cs" QBCYR0401U -420 "cp1256_bin" QBARA01A4U -420 "cp1256_general_ci" QAARA01A4S -500 "cp850_bin" QDLA101F4U -500 "cp850_general_ci" QCLA101F4S -870 "cp852_bin" QBLA20366U -870 "cp852_general_ci" QALA20366S -1200 "cp932_bin" QBJPN04B0U -1200 "cp932_japanese_ci" QAJPN04B0S -1200 "euckr_bin" QBKOR04B0U -1200 "euckr_korean_ci" QAKOR04B0S -1200 "gb2312_bin" QBCHS04B0U -1200 "gb2312_chinese_ci" QACHS04B0S -1200 "gbk_bin" QDCHS04B0U -1200 "gbk_chinese_ci" QCCHS04B0S -875 "greek_bin" QBELL036BU -875 "greek_general_ci" QAELL036BS -424 "hebrew_bin" QBHEB01A8U -424 "hebrew_general_ci" QAHEB01A8S -1148 "latin1_bin" QFLA1047CU -1148 "latin1_danish_ci" QALA1047CS -1148 "latin1_general_ci" QBLA1047CS -1148 "latin1_general_cs" QBLA1047CU -1148 "latin1_german1_ci" QCLA1047CS -1148 "latin1_spanish_ci" QDLA1047CS -1148 "latin1_swedish_ci" QELA1047CS -870 "latin2_bin" QGLA20366U -870 "latin2_croatian_ci" QCLA20366S -870 "latin2_general_ci" QELA20366S -870 "latin2_hungarian_ci QFLA20366S -1026 "latin5_bin" QBTRK0402U -1026 "latin5_turkish_ci" QATRK0402S -870 "macce_bin" QILA20366U -870 "macce_general_ci" QHLA20366S -1200 "sjis_bin" QDJPN04B0U -1200 "sjis_japanese_ci" QCJPN04B0S -838 "tis620_bin" QBTHA0346U -838 "tis620_thai_ci" QATHA0346S -13488 "ucs2_bin" *HEX -13488 "ucs2_czech_ci" I34ACS_CZ -13488 "ucs2_danish_ci" I34ADA_DK -13488 "ucs2_esperanto_ci" I34AEO -13488 "ucs2_estonian_ci" I34AET -13488 "ucs2_general_ci" QAUCS04B0S -13488 "ucs2_hungarian_ci" I34AHU -13488 "ucs2_icelandic_ci" I34AIS -13488 "ucs2_latvian_ci" I34ALV -13488 "ucs2_lithuanian_ci" I34ALT -13488 "ucs2_persian_ci" I34AFA -13488 "ucs2_polish_ci" I34APL -13488 "ucs2_romanian_ci" I34ARO -13488 "ucs2_slovak_ci" I34ASK -13488 "ucs2_slovenian_ci" I34ASL -13488 "ucs2_spanish_ci" I34AES -13488 "ucs2_swedish_ci" I34ASW -13488 "ucs2_turkish_ci" I34ATR -13488 "ucs2_unicode_ci" I34AEN -1200 "ujis_bin" QFJPN04B0U -1200 "ujis_japanese_ci" QEJPN04B0S -1208 "utf8_bin" *HEX -1208 "utf8_czech_ci" I34ACS_CZ -1208 "utf8_danish_ci" I34ADA_DK -1208 "utf8_esperanto_ci" I34AEO -1208 "utf8_estonian_ci" I34AET -1200 "utf8_general_ci" QAUCS04B0S -1208 "utf8_hungarian_ci" I34AHU -1208 "utf8_icelandic_ci" I34AIS -1208 "utf8_latvian_ci" I34ALV -1208 "utf8_lithuanian_ci" I34ALT -1208 "utf8_persian_ci" I34AFA -1208 "utf8_polish_ci" I34APL -1208 "utf8_romanian_ci" I34ARO -1208 "utf8_slovak_ci" I34ASK -1208 "utf8_slovenian_ci" I34ASL -1208 "utf8_spanish_ci" I34AES -1208 "utf8_swedish_ci" I34ASW -1208 "utf8_turkish_ci" I34ATR -1208 "utf8_unicode_ci" I34AEN -drop table ffd, fd; diff --git a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44020.test b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44020.test deleted file mode 100644 index 09a7c75cfc0..00000000000 --- a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44020.test +++ /dev/null @@ -1,9 +0,0 @@ -source suite/ibmdb2i/include/have_ibmdb2i.inc; -source include/have_case_sensitive_file_system.inc; - -create schema `A12345_@$#`; -create table `A12345_@$#`.t1 (i int) engine=ibmdb2i; -show create table `A12345_@$#`.t1; -select * from `A12345_@$#`.t1; -drop table `A12345_@$#`.t1; -drop schema `A12345_@$#`; diff --git a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44025.test b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44025.test deleted file mode 100644 index 9b033a2298f..00000000000 --- a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44025.test +++ /dev/null @@ -1,9 +0,0 @@ -source suite/ibmdb2i/include/have_ibmdb2i.inc; -source suite/ibmdb2i/include/have_i61.inc; - - -create table t1 (c char(10) collate utf8_swedish_ci, index(c)) engine=ibmdb2i; -drop table t1; - -create table t1 (c char(10) collate ucs2_swedish_ci, index(c)) engine=ibmdb2i; -drop table t1; diff --git a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44232.test b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44232.test deleted file mode 100755 index ea29b5abcd4..00000000000 --- a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44232.test +++ /dev/null @@ -1,8 +0,0 @@ ---source suite/ibmdb2i/include/have_ibmdb2i.inc ---source suite/ibmdb2i/include/have_i54.inc - ---error 1005 -create table t1 (c char(1) character set armscii8) engine=ibmdb2i; - ---error 1005 -create table t1 (c char(1) character set eucjpms ) engine=ibmdb2i; diff --git a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44610.test b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44610.test deleted file mode 100755 index da69b5d9148..00000000000 --- a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_44610.test +++ /dev/null @@ -1,28 +0,0 @@ -source suite/ibmdb2i/include/have_ibmdb2i.inc; - -# Test RCDFMT generation for a variety of kinds of table names -create table ABC (i int) engine=ibmdb2i; -drop table ABC; - -create table `1234567890ABC` (i int) engine=ibmdb2i; -drop table `1234567890ABC`; - -create table `!@#$%` (i int) engine=ibmdb2i; -drop table `!@#$%`; - -create table `ABCD#########` (i int) engine=ibmdb2i; -drop table `ABCD#########`; - -create table `_` (i int) engine=ibmdb2i; -drop table `_`; - -create table `abc##def` (i int) engine=ibmdb2i; -drop table `abc##def`; - -set names utf8; -create table İ (s1 int) engine=ibmdb2i; -drop table İ; - -create table İİ (s1 int) engine=ibmdb2i; -drop table İİ; -set names latin1; diff --git a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_45196.test b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_45196.test deleted file mode 100644 index 17b1d658975..00000000000 --- a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_45196.test +++ /dev/null @@ -1,26 +0,0 @@ -source suite/ibmdb2i/include/have_ibmdb2i.inc; -source suite/ibmdb2i/include/have_i61.inc; - ---disable_warnings -drop table if exists t1; ---enable_warnings - -create table t1 (c char(10), index(c)) collate ucs2_czech_ci engine=ibmdb2i; -insert into t1 values ("ch"),("h"),("i"); -select * from t1 order by c; -drop table t1; - -create table t1 (c char(10), index(c)) collate utf8_czech_ci engine=ibmdb2i; -insert into t1 values ("ch"),("h"),("i"); -select * from t1 order by c; -drop table t1; - -create table t1 (c char(10), index(c)) collate ucs2_danish_ci engine=ibmdb2i; -insert into t1 values("abc"),("abcd"),("aaaa"); -select c from t1 order by c; -drop table t1; - -create table t1 (c char(10), index(c)) collate utf8_danish_ci engine=ibmdb2i; -insert into t1 values("abc"),("abcd"),("aaaa"); -select c from t1 order by c; -drop table t1; diff --git a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_45793.test b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_45793.test deleted file mode 100644 index 93fb78ff421..00000000000 --- a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_45793.test +++ /dev/null @@ -1,11 +0,0 @@ -source suite/ibmdb2i/include/have_ibmdb2i.inc; -source suite/ibmdb2i/include/have_i61.inc; - ---disable_warnings -drop table if exists t1; ---enable_warnings - -create table t1 (c char(10), index(c)) charset macce engine=ibmdb2i; -insert into t1 values ("test"); -select * from t1 order by c; -drop table t1; diff --git a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_45983.test b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_45983.test deleted file mode 100644 index 695d8e90ada..00000000000 --- a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_45983.test +++ /dev/null @@ -1,47 +0,0 @@ -source suite/ibmdb2i/include/have_ibmdb2i.inc; - -# Confirm that ibmdb2i_create_index_option causes additional *HEX sorted indexes to be created for all non-binary keys. - -set ibmdb2i_create_index_option=1; ---disable_warnings -drop schema if exists test1; -create schema test1; -use test1; ---enable_warnings - ---disable_abort_on_error ---error 0,255 -exec system "DLTF QGPL/FDOUT" > /dev/null; ---enable_abort_on_error - -#No additional index because no string fields in key -CREATE TABLE t1 (f int primary key, index(f)) engine=ibmdb2i; ---error 255 -exec system "DSPFD FILE(\"test1\"/PRIM0001) TYPE(*SEQ) OUTPUT(*OUTFILE) OUTFILE(QGPL/FDOUT) OUTMBR(*FIRST *ADD)" > /dev/null; ---error 255 -exec system "DSPFD FILE(\"test1\"/\"f___H_t1\") TYPE(*SEQ) OUTPUT(*OUTFILE) OUTFILE(QGPL/FDOUT) OUTMBR(*FIRST *ADD)" > /dev/null; -drop table t1; - -#No additional index because binary sorting -CREATE TABLE t1 (f char(10) collate utf8_bin primary key, index(f)) engine=ibmdb2i; ---error 255 -exec system "DSPFD FILE(\"test1\"/PRIM0001) TYPE(*SEQ) OUTPUT(*OUTFILE) OUTFILE(QGPL/FDOUT) OUTMBR(*FIRST *ADD)" > /dev/null; ---error 255 -exec system "DSPFD FILE(\"test1\"/\"f___H_t1\") TYPE(*SEQ) OUTPUT(*OUTFILE) OUTFILE(QGPL/FDOUT) OUTMBR(*FIRST *ADD)" > /dev/null; -drop table t1; - -CREATE TABLE t1 (f char(10) collate latin1_swedish_ci primary key, index(f)) engine=ibmdb2i; -exec system "DSPFD FILE(\"test1\"/PRIM0001) TYPE(*SEQ) OUTPUT(*OUTFILE) OUTFILE(QGPL/FDOUT) OUTMBR(*FIRST *ADD)" > /dev/null; -exec system "DSPFD FILE(\"test1\"/\"f___H_t1\") TYPE(*SEQ) OUTPUT(*OUTFILE) OUTFILE(QGPL/FDOUT) OUTMBR(*FIRST *ADD)" > /dev/null; -drop table t1; - -CREATE TABLE t1 (f char(10) collate latin1_swedish_ci primary key, i int, index i(i,f)) engine=ibmdb2i; -exec system "DSPFD FILE(\"test1\"/PRIM0001) TYPE(*SEQ) OUTPUT(*OUTFILE) OUTFILE(QGPL/FDOUT) OUTMBR(*FIRST *ADD)" > /dev/null; -exec system "DSPFD FILE(\"test1\"/\"i___H_t1\") TYPE(*SEQ) OUTPUT(*OUTFILE) OUTFILE(QGPL/FDOUT) OUTMBR(*FIRST *ADD)" > /dev/null; -drop table t1; - - -create table fd (SQSSEQ CHAR(10)) engine=ibmdb2i; -system system "CPYF FROMFILE(QGPL/FDOUT) TOFILE(\"test1\"/\"fd\") mbropt(*replace) fmtopt(*drop *map)" > /dev/null; -select * from fd; -drop table fd; diff --git a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_49329.test b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_49329.test deleted file mode 100644 index 615df284d8f..00000000000 --- a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_49329.test +++ /dev/null @@ -1,10 +0,0 @@ -source suite/ibmdb2i/include/have_ibmdb2i.inc;
-source include/have_case_sensitive_file_system.inc;
-
-create table ABC (i int) engine=ibmdb2i;
-insert into ABC values(1);
-create table abc (i int) engine=ibmdb2i;
-insert into abc values (2);
-select * from ABC;
-drop table ABC;
-drop table abc;
diff --git a/mysql-test/suite/ibmdb2i/t/ibmdb2i_collations.test b/mysql-test/suite/ibmdb2i/t/ibmdb2i_collations.test deleted file mode 100644 index 899f330d360..00000000000 --- a/mysql-test/suite/ibmdb2i/t/ibmdb2i_collations.test +++ /dev/null @@ -1,44 +0,0 @@ -source suite/ibmdb2i/include/have_ibmdb2i.inc; -source suite/ibmdb2i/include/have_i61.inc; ---disable_warnings -drop table if exists t1, ffd, fd; ---enable_warnings - ---disable_abort_on_error ---error 0,255 -exec system "DLTF QGPL/FFDOUT" > /dev/null; ---error 0,255 -exec system "DLTF QGPL/FDOUT" > /dev/null; ---enable_abort_on_error -let $count= query_get_value(select count(*) from information_schema.COLLATIONS where COLLATION_NAME <> "binary", count(*),1); - -while ($count) -{ - let $collation = query_get_value(select COLLATION_NAME from information_schema.COLLATIONS where COLLATION_NAME <> "binary" order by COLLATION_NAME desc, COLLATION_NAME, $count); - error 0,1005,2504,2028; - eval CREATE TABLE t1 ($collation integer, c char(10), v varchar(20), index(c), index(v)) collate $collation engine=ibmdb2i; - if (!$mysql_errno) - { - insert into t1 (c,v) values ("abc","def"),("abcd", "def"),("abcde","defg"),("aaaa","bbbb"); - insert into t1 select * from t1; - explain select c,v from t1 force index(c) where c like "ab%"; - explain select c,v from t1 force index(v) where v like "de%"; - drop table t1; - eval create table t1 ($collation char(10) primary key) collate $collation engine=ibmdb2i; - system system "DSPFFD FILE(\"test\"/\"t1\") OUTPUT(*OUTFILE) OUTFILE(QGPL/FFDOUT) OUTMBR(*FIRST *ADD)" > /dev/null; - system system "DSPFD FILE(\"test\"/\"t1\") TYPE(*SEQ) OUTPUT(*OUTFILE) OUTFILE(QGPL/FDOUT) OUTMBR(*FIRST *ADD)" > /dev/null; - drop table t1; - } - dec $count; -} - -create table ffd (WHCHD1 CHAR(20), WHCSID decimal(5,0)) engine=ibmdb2i; -system system "CPYF FROMFILE(QGPL/FFDOUT) TOFILE(\"test\"/\"ffd\") mbropt(*replace) fmtopt(*drop *map)" > /dev/null; -create table fd (SQSSEQ CHAR(10)) engine=ibmdb2i; -system system "CPYF FROMFILE(QGPL/FDOUT) TOFILE(\"test\"/\"fd\") mbropt(*replace) fmtopt(*drop *map)" > /dev/null; -create temporary table intermed (row integer key auto_increment, cs char(30), ccsid integer); -insert into intermed (cs, ccsid) select * from ffd; -create temporary table intermed2 (row integer key auto_increment, srtseq char(10)); -insert into intermed2 (srtseq) select * from fd; -select ccsid, cs, srtseq from intermed inner join intermed2 on intermed.row = intermed2.row; -drop table ffd, fd; diff --git a/mysql-test/suite/innodb/r/innodb_mysql.result b/mysql-test/suite/innodb/r/innodb_mysql.result index 65b7da143a4..6ac3e8e6302 100644 --- a/mysql-test/suite/innodb/r/innodb_mysql.result +++ b/mysql-test/suite/innodb/r/innodb_mysql.result @@ -2620,3 +2620,11 @@ t2 CREATE TABLE `t2` ( CONSTRAINT `x` FOREIGN KEY (`fk`) REFERENCES `t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 drop table t2, t1; +# +# Test for bug #56619 - Assertion failed during +# ALTER TABLE RENAME, DISABLE KEYS +# +DROP TABLE IF EXISTS t1, t2; +CREATE TABLE t1 (a INT, INDEX(a)) engine=innodb; +ALTER TABLE t1 RENAME TO t2, DISABLE KEYS; +DROP TABLE IF EXISTS t1, t2; diff --git a/mysql-test/suite/innodb/t/innodb_mysql.test b/mysql-test/suite/innodb/t/innodb_mysql.test index 09dc4c9f187..e99c3c27673 100644 --- a/mysql-test/suite/innodb/t/innodb_mysql.test +++ b/mysql-test/suite/innodb/t/innodb_mysql.test @@ -845,3 +845,16 @@ create table t2 (fk int, key x (fk), constraint x foreign key (FK) references t1 (PK)) engine=InnoDB; show create table t2; drop table t2, t1; + +--echo # +--echo # Test for bug #56619 - Assertion failed during +--echo # ALTER TABLE RENAME, DISABLE KEYS +--echo # +--disable_warnings +DROP TABLE IF EXISTS t1, t2; +--enable_warnings +CREATE TABLE t1 (a INT, INDEX(a)) engine=innodb; +--disable_warnings +ALTER TABLE t1 RENAME TO t2, DISABLE KEYS; +DROP TABLE IF EXISTS t1, t2; +--enable_warnings diff --git a/mysql-test/suite/parts/inc/partition_auto_increment.inc b/mysql-test/suite/parts/inc/partition_auto_increment.inc index 102e57d3d04..034460d49ac 100644 --- a/mysql-test/suite/parts/inc/partition_auto_increment.inc +++ b/mysql-test/suite/parts/inc/partition_auto_increment.inc @@ -105,6 +105,30 @@ OPTIMIZE TABLE t1; SHOW CREATE TABLE t1; DROP TABLE t1; +if (!$skip_update) +{ +eval CREATE TABLE t1 +(a INT NULL AUTO_INCREMENT, + UNIQUE KEY (a)) +ENGINE=$engine; +SET LAST_INSERT_ID = 999; +SET INSERT_ID = 0; +INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL; +SELECT LAST_INSERT_ID(); +SELECT * FROM t1; +INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL; +SELECT LAST_INSERT_ID(); +SELECT * FROM t1; +UPDATE t1 SET a = 1 WHERE a IS NULL; +SELECT LAST_INSERT_ID(); +SELECT * FROM t1; +UPDATE t1 SET a = NULL WHERE a = 1; +SELECT LAST_INSERT_ID(); +SELECT * FROM t1; +DROP TABLE t1; +SET INSERT_ID = 1; +} + -- echo # Simple test with NULL eval CREATE TABLE t1 ( c1 INT NOT NULL AUTO_INCREMENT, @@ -831,5 +855,30 @@ SELECT * FROM t ORDER BY c1 ASC; DROP TABLE t; +if (!$skip_update) +{ +eval CREATE TABLE t1 +(a INT NULL AUTO_INCREMENT, + UNIQUE KEY (a)) +ENGINE=$engine +PARTITION BY KEY(a) PARTITIONS 2; +SET LAST_INSERT_ID = 999; +SET INSERT_ID = 0; +INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL; +SELECT LAST_INSERT_ID(); +SELECT * FROM t1; +INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL; +SELECT LAST_INSERT_ID(); +SELECT * FROM t1; +UPDATE t1 SET a = 1 WHERE a IS NULL; +SELECT LAST_INSERT_ID(); +SELECT * FROM t1; +UPDATE t1 SET a = NULL WHERE a = 1; +SELECT LAST_INSERT_ID(); +SELECT * FROM t1; +DROP TABLE t1; +} + + --echo ############################################################################## } diff --git a/mysql-test/suite/parts/r/partition_auto_increment_blackhole.result b/mysql-test/suite/parts/r/partition_auto_increment_blackhole.result index d6ea8ba0fe4..2344f03ce3f 100644 --- a/mysql-test/suite/parts/r/partition_auto_increment_blackhole.result +++ b/mysql-test/suite/parts/r/partition_auto_increment_blackhole.result @@ -120,6 +120,38 @@ t1 CREATE TABLE `t1` ( PRIMARY KEY (`c1`) ) ENGINE=BLACKHOLE DEFAULT CHARSET=latin1 DROP TABLE t1; +CREATE TABLE t1 +(a INT NULL AUTO_INCREMENT, +UNIQUE KEY (a)) +ENGINE='Blackhole'; +SET LAST_INSERT_ID = 999; +SET INSERT_ID = 0; +INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +UPDATE t1 SET a = 1 WHERE a IS NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +UPDATE t1 SET a = NULL WHERE a = 1; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +DROP TABLE t1; +SET INSERT_ID = 1; # Simple test with NULL CREATE TABLE t1 ( c1 INT NOT NULL AUTO_INCREMENT, diff --git a/mysql-test/suite/parts/r/partition_auto_increment_innodb.result b/mysql-test/suite/parts/r/partition_auto_increment_innodb.result index 4cd7aa57417..5fd576322d5 100644 --- a/mysql-test/suite/parts/r/partition_auto_increment_innodb.result +++ b/mysql-test/suite/parts/r/partition_auto_increment_innodb.result @@ -136,6 +136,42 @@ t1 CREATE TABLE `t1` ( PRIMARY KEY (`c1`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1 DROP TABLE t1; +CREATE TABLE t1 +(a INT NULL AUTO_INCREMENT, +UNIQUE KEY (a)) +ENGINE='InnoDB'; +SET LAST_INSERT_ID = 999; +SET INSERT_ID = 0; +INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +1 +INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +0 +UPDATE t1 SET a = 1 WHERE a IS NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +0 +UPDATE t1 SET a = NULL WHERE a = 1; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +0 +DROP TABLE t1; +SET INSERT_ID = 1; # Simple test with NULL CREATE TABLE t1 ( c1 INT NOT NULL AUTO_INCREMENT, @@ -1023,4 +1059,40 @@ c1 c2 2 20 127 40 DROP TABLE t; +CREATE TABLE t1 +(a INT NULL AUTO_INCREMENT, +UNIQUE KEY (a)) +ENGINE='InnoDB' +PARTITION BY KEY(a) PARTITIONS 2; +SET LAST_INSERT_ID = 999; +SET INSERT_ID = 0; +INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +1 +INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +0 +UPDATE t1 SET a = 1 WHERE a IS NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +0 +UPDATE t1 SET a = NULL WHERE a = 1; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +0 +DROP TABLE t1; ############################################################################## diff --git a/mysql-test/suite/parts/r/partition_auto_increment_memory.result b/mysql-test/suite/parts/r/partition_auto_increment_memory.result index 1a27d1c2e52..c3a5073b029 100644 --- a/mysql-test/suite/parts/r/partition_auto_increment_memory.result +++ b/mysql-test/suite/parts/r/partition_auto_increment_memory.result @@ -136,6 +136,42 @@ t1 CREATE TABLE `t1` ( PRIMARY KEY (`c1`) ) ENGINE=MEMORY AUTO_INCREMENT=102 DEFAULT CHARSET=latin1 DROP TABLE t1; +CREATE TABLE t1 +(a INT NULL AUTO_INCREMENT, +UNIQUE KEY (a)) +ENGINE='Memory'; +SET LAST_INSERT_ID = 999; +SET INSERT_ID = 0; +INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +1 +INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +0 +UPDATE t1 SET a = 1 WHERE a IS NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +0 +UPDATE t1 SET a = NULL WHERE a = 1; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +0 +DROP TABLE t1; +SET INSERT_ID = 1; # Simple test with NULL CREATE TABLE t1 ( c1 INT NOT NULL AUTO_INCREMENT, @@ -1051,4 +1087,40 @@ c1 c2 2 20 127 40 DROP TABLE t; +CREATE TABLE t1 +(a INT NULL AUTO_INCREMENT, +UNIQUE KEY (a)) +ENGINE='Memory' +PARTITION BY KEY(a) PARTITIONS 2; +SET LAST_INSERT_ID = 999; +SET INSERT_ID = 0; +INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +1 +INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +0 +UPDATE t1 SET a = 1 WHERE a IS NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +0 +UPDATE t1 SET a = NULL WHERE a = 1; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +0 +DROP TABLE t1; ############################################################################## diff --git a/mysql-test/suite/parts/r/partition_auto_increment_myisam.result b/mysql-test/suite/parts/r/partition_auto_increment_myisam.result index 9885c78a921..ad440155d33 100644 --- a/mysql-test/suite/parts/r/partition_auto_increment_myisam.result +++ b/mysql-test/suite/parts/r/partition_auto_increment_myisam.result @@ -136,6 +136,42 @@ t1 CREATE TABLE `t1` ( PRIMARY KEY (`c1`) ) ENGINE=MyISAM AUTO_INCREMENT=102 DEFAULT CHARSET=latin1 DROP TABLE t1; +CREATE TABLE t1 +(a INT NULL AUTO_INCREMENT, +UNIQUE KEY (a)) +ENGINE='MyISAM'; +SET LAST_INSERT_ID = 999; +SET INSERT_ID = 0; +INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +1 +INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +0 +UPDATE t1 SET a = 1 WHERE a IS NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +0 +UPDATE t1 SET a = NULL WHERE a = 1; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +0 +DROP TABLE t1; +SET INSERT_ID = 1; # Simple test with NULL CREATE TABLE t1 ( c1 INT NOT NULL AUTO_INCREMENT, @@ -1070,4 +1106,40 @@ c1 c2 2 20 127 40 DROP TABLE t; +CREATE TABLE t1 +(a INT NULL AUTO_INCREMENT, +UNIQUE KEY (a)) +ENGINE='MyISAM' +PARTITION BY KEY(a) PARTITIONS 2; +SET LAST_INSERT_ID = 999; +SET INSERT_ID = 0; +INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +1 +INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +0 +UPDATE t1 SET a = 1 WHERE a IS NULL; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +0 +UPDATE t1 SET a = NULL WHERE a = 1; +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +999 +SELECT * FROM t1; +a +0 +DROP TABLE t1; ############################################################################## diff --git a/mysql-test/suite/parts/t/part_supported_sql_func_innodb.test b/mysql-test/suite/parts/t/part_supported_sql_func_innodb.test index e8d263e369c..002da3c8f37 100644 --- a/mysql-test/suite/parts/t/part_supported_sql_func_innodb.test +++ b/mysql-test/suite/parts/t/part_supported_sql_func_innodb.test @@ -28,6 +28,9 @@ let $do_long_tests= 1; # The server must support partitioning. --source include/have_partition.inc +# This test takes long time, so only run it with the --big mtr-flag. +--source include/big_test.inc + #------------------------------------------------------------------------------# # Engine specific settings and requirements diff --git a/mysql-test/suite/parts/t/partition_alter1_1_2_innodb.test b/mysql-test/suite/parts/t/partition_alter1_1_2_innodb.test index 8e3dde286cf..6ac1803a972 100644 --- a/mysql-test/suite/parts/t/partition_alter1_1_2_innodb.test +++ b/mysql-test/suite/parts/t/partition_alter1_1_2_innodb.test @@ -46,6 +46,9 @@ let $more_pk_ui_tests= 0; # The server must support partitioning. --source include/have_partition.inc +# This test takes long time, so only run it with the --big mtr-flag. +--source include/big_test.inc + #------------------------------------------------------------------------------# # Engine specific settings and requirements diff --git a/mysql-test/suite/parts/t/partition_alter1_2_innodb.test b/mysql-test/suite/parts/t/partition_alter1_2_innodb.test index 76fe7eb0223..2cbe0ab77ab 100644 --- a/mysql-test/suite/parts/t/partition_alter1_2_innodb.test +++ b/mysql-test/suite/parts/t/partition_alter1_2_innodb.test @@ -46,6 +46,9 @@ let $more_pk_ui_tests= 0; # The server must support partitioning. --source include/have_partition.inc +# This test takes long time, so only run it with the --big mtr-flag. +--source include/big_test.inc + #------------------------------------------------------------------------------# # Engine specific settings and requirements diff --git a/mysql-test/suite/parts/t/partition_alter4_innodb.test b/mysql-test/suite/parts/t/partition_alter4_innodb.test index 3061e5c9e7f..1e28a2fc812 100644 --- a/mysql-test/suite/parts/t/partition_alter4_innodb.test +++ b/mysql-test/suite/parts/t/partition_alter4_innodb.test @@ -43,6 +43,9 @@ let $more_pk_ui_tests= 0; # The server must support partitioning. --source include/have_partition.inc +# This test takes long time, so only run it with the --big mtr-flag. +--source include/big_test.inc + #------------------------------------------------------------------------------# # Engine specific settings and requirements diff --git a/mysql-test/suite/rpl/r/rpl_ignore_table.result b/mysql-test/suite/rpl/r/rpl_ignore_table.result index e77be425270..6b845ddcac9 100644 --- a/mysql-test/suite/rpl/r/rpl_ignore_table.result +++ b/mysql-test/suite/rpl/r/rpl_ignore_table.result @@ -141,3 +141,4 @@ HEX(word) SELECT * FROM tmptbl504451f4258$1; ERROR 42S02: Table 'test.tmptbl504451f4258$1' doesn't exist DROP TABLE t5; +call mtr.force_restart(); diff --git a/mysql-test/suite/rpl/t/rpl_cross_version-master.opt b/mysql-test/suite/rpl/t/rpl_cross_version-master.opt index 0ea05290c11..2b2d357b124 100644 --- a/mysql-test/suite/rpl/t/rpl_cross_version-master.opt +++ b/mysql-test/suite/rpl/t/rpl_cross_version-master.opt @@ -1 +1,2 @@ --replicate-same-server-id --relay-log=slave-relay-bin --secure-file-priv=$MYSQL_TMP_DIR +--force-restart diff --git a/mysql-test/suite/rpl/t/rpl_current_user-master.opt b/mysql-test/suite/rpl/t/rpl_current_user-master.opt new file mode 100644 index 00000000000..cef79bc8585 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_current_user-master.opt @@ -0,0 +1 @@ +--force-restart diff --git a/mysql-test/suite/rpl/t/rpl_ignore_table.test b/mysql-test/suite/rpl/t/rpl_ignore_table.test index 66f96e8f4e8..b5666ad6e91 100644 --- a/mysql-test/suite/rpl/t/rpl_ignore_table.test +++ b/mysql-test/suite/rpl/t/rpl_ignore_table.test @@ -174,3 +174,5 @@ SELECT * FROM tmptbl504451f4258$1; connection master; DROP TABLE t5; sync_slave_with_master; + +call mtr.force_restart(); diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.sh b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.sh index 066f72926af..e5bb3e61d11 100644 --- a/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.sh +++ b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.sh @@ -1 +1,2 @@ +rm -f $MYSQLTEST_VARDIR/std_data_master_link ln -s $MYSQLTEST_VARDIR/std_data $MYSQLTEST_VARDIR/std_data_master_link diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.sh b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.sh index 218209a2542..7a0c0bb382a 100644 --- a/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.sh +++ b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.sh @@ -1 +1,2 @@ +rm -f $MYSQLTEST_VARDIR/std_data_slave_link ln -s $MYSQLTEST_VARDIR/std_data $MYSQLTEST_VARDIR/std_data_slave_link diff --git a/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist-master.opt b/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist-master.opt new file mode 100644 index 00000000000..cef79bc8585 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist-master.opt @@ -0,0 +1 @@ +--force-restart diff --git a/mysql-test/suite/sys_vars/README b/mysql-test/suite/sys_vars/README deleted file mode 100644 index a84f00f1f62..00000000000 --- a/mysql-test/suite/sys_vars/README +++ /dev/null @@ -1,3 +0,0 @@ -Some of these tests allocate more than 4GB RAM. -So, assure that the machine on which the suite will be executed has more than 4GB RAM. - diff --git a/mysql-test/suite/sys_vars/inc/timestamp_basic.inc b/mysql-test/suite/sys_vars/inc/timestamp_basic.inc index 9ef57c97043..68ded3e5a97 100644 --- a/mysql-test/suite/sys_vars/inc/timestamp_basic.inc +++ b/mysql-test/suite/sys_vars/inc/timestamp_basic.inc @@ -66,10 +66,6 @@ SET @@timestamp = 0; --echo 'Setting 0 resets timestamp to session default timestamp' -SET @@timestamp = 123456789123456; -SELECT @@timestamp; -SET @@timestamp = 60*60*60*60*365; -SELECT @@timestamp; SET @@timestamp = -1000000000; SELECT @@timestamp; diff --git a/mysql-test/suite/sys_vars/r/general_log_file_basic.result b/mysql-test/suite/sys_vars/r/general_log_file_basic.result index 48a8d90b55e..5c0b93cf4ab 100644 --- a/mysql-test/suite/sys_vars/r/general_log_file_basic.result +++ b/mysql-test/suite/sys_vars/r/general_log_file_basic.result @@ -1,7 +1,6 @@ -SET @start_value = @@global.general_log_file; SELECT @start_value; @start_value -test.log +NULL '#---------------------FN_DYNVARS_004_01-------------------------#' SET @@global.general_log_file = DEFAULT; SELECT RIGHT(@@global.general_log_file,10) AS log_file; @@ -17,4 +16,4 @@ FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='general_log_file'; @@global.general_log_file = VARIABLE_VALUE 1 -SET @@global.general_log_file= @start_value; +SET @@global.general_log_file= 'test.log'; diff --git a/mysql-test/suite/sys_vars/r/general_log_func.result b/mysql-test/suite/sys_vars/r/general_log_func.result index 39ba90265d5..119991396e0 100644 --- a/mysql-test/suite/sys_vars/r/general_log_func.result +++ b/mysql-test/suite/sys_vars/r/general_log_func.result @@ -26,6 +26,7 @@ SELECT @@general_log; INSERT into t1(name) values('Record_3'); INSERT into t1(name) values('Record_4'); ## There should be a difference ## +SET @start_value= @@global.max_allowed_packet; SET @@global.max_allowed_packet= 1024*1024*1024; SET @orig_file= load_file('MYSQLD_LOGFILE.orig'); SET @copy_file= load_file('MYSQLD_LOGFILE.copy'); @@ -34,3 +35,4 @@ STRCMP(@orig_file, @copy_file) 1 ## Dropping tables ## DROP TABLE t1; +SET @@global.max_allowed_packet= @start_value; diff --git a/mysql-test/suite/sys_vars/r/innodb_commit_concurrency_basic.result b/mysql-test/suite/sys_vars/r/innodb_commit_concurrency_basic.result index 301016d4362..201f183ad0e 100644 --- a/mysql-test/suite/sys_vars/r/innodb_commit_concurrency_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_commit_concurrency_basic.result @@ -1,30 +1,23 @@ SET @global_start_value = @@global.innodb_commit_concurrency; SELECT @global_start_value; @global_start_value -0 +10 '#--------------------FN_DYNVARS_046_01------------------------#' -SET @@global.innodb_commit_concurrency = 0; SET @@global.innodb_commit_concurrency = DEFAULT; SELECT @@global.innodb_commit_concurrency; @@global.innodb_commit_concurrency -0 +10 '#---------------------FN_DYNVARS_046_02-------------------------#' SET innodb_commit_concurrency = 1; ERROR HY000: Variable 'innodb_commit_concurrency' is a GLOBAL variable and should be set with SET GLOBAL SELECT @@innodb_commit_concurrency; @@innodb_commit_concurrency -0 +10 SELECT local.innodb_commit_concurrency; ERROR 42S02: Unknown table 'local' in field list SET global innodb_commit_concurrency = 0; -SELECT @@global.innodb_commit_concurrency; -@@global.innodb_commit_concurrency -0 +ERROR HY000: Incorrect arguments to SET '#--------------------FN_DYNVARS_046_03------------------------#' -SET @@global.innodb_commit_concurrency = 0; -SELECT @@global.innodb_commit_concurrency; -@@global.innodb_commit_concurrency -0 SET @@global.innodb_commit_concurrency = 1; SELECT @@global.innodb_commit_concurrency; @@global.innodb_commit_concurrency @@ -35,27 +28,17 @@ SELECT @@global.innodb_commit_concurrency; 1000 '#--------------------FN_DYNVARS_046_04-------------------------#' SET @@global.innodb_commit_concurrency = -1; -Warnings: -Warning 1292 Truncated incorrect commit_concurrency value: '18446744073709551615' -SELECT @@global.innodb_commit_concurrency; -@@global.innodb_commit_concurrency -1000 +SELECT @@global.innodb_commit_concurrency IN (4294967295,18446744073709551615); +@@global.innodb_commit_concurrency IN (4294967295,18446744073709551615) +1 SET @@global.innodb_commit_concurrency = "T"; ERROR 42000: Incorrect argument type to variable 'innodb_commit_concurrency' -SELECT @@global.innodb_commit_concurrency; -@@global.innodb_commit_concurrency -1000 SET @@global.innodb_commit_concurrency = "Y"; ERROR 42000: Incorrect argument type to variable 'innodb_commit_concurrency' -SELECT @@global.innodb_commit_concurrency; -@@global.innodb_commit_concurrency -1000 SET @@global.innodb_commit_concurrency = 1001; -Warnings: -Warning 1292 Truncated incorrect commit_concurrency value: '1001' SELECT @@global.innodb_commit_concurrency; @@global.innodb_commit_concurrency -1000 +1001 '#----------------------FN_DYNVARS_046_05------------------------#' SELECT @@global.innodb_commit_concurrency = VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES @@ -65,32 +48,33 @@ VARIABLE_VALUE 1 SELECT @@global.innodb_commit_concurrency; @@global.innodb_commit_concurrency -1000 +1001 SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_commit_concurrency'; VARIABLE_VALUE -1000 +1001 '#---------------------FN_DYNVARS_046_06-------------------------#' SET @@global.innodb_commit_concurrency = OFF; ERROR 42000: Incorrect argument type to variable 'innodb_commit_concurrency' SELECT @@global.innodb_commit_concurrency; @@global.innodb_commit_concurrency -1000 +1001 SET @@global.innodb_commit_concurrency = ON; ERROR 42000: Incorrect argument type to variable 'innodb_commit_concurrency' SELECT @@global.innodb_commit_concurrency; @@global.innodb_commit_concurrency -1000 +1001 '#---------------------FN_DYNVARS_046_07----------------------#' SET @@global.innodb_commit_concurrency = TRUE; SELECT @@global.innodb_commit_concurrency; @@global.innodb_commit_concurrency 1 SET @@global.innodb_commit_concurrency = FALSE; +ERROR HY000: Incorrect arguments to SET SELECT @@global.innodb_commit_concurrency; @@global.innodb_commit_concurrency -0 +1 SET @@global.innodb_commit_concurrency = @global_start_value; SELECT @@global.innodb_commit_concurrency; @@global.innodb_commit_concurrency -0 +10 diff --git a/mysql-test/suite/sys_vars/r/log_output_basic.result b/mysql-test/suite/sys_vars/r/log_output_basic.result index 481d5862074..6f350556ff9 100644 --- a/mysql-test/suite/sys_vars/r/log_output_basic.result +++ b/mysql-test/suite/sys_vars/r/log_output_basic.result @@ -1,7 +1,7 @@ SET @start_value = @@global.log_output; SELECT @start_value; @start_value -FILE,TABLE +FILE '#--------------------FN_DYNVARS_065_01------------------------#' SET @@global.log_output = FILE; SET @@global.log_output = DEFAULT; @@ -172,4 +172,4 @@ TABLE SET @@global.log_output = @start_value; SELECT @@global.log_output; @@global.log_output -FILE,TABLE +FILE diff --git a/mysql-test/suite/sys_vars/r/log_output_func.result b/mysql-test/suite/sys_vars/r/log_output_func.result index 060f930a161..00a8e824f78 100644 --- a/mysql-test/suite/sys_vars/r/log_output_func.result +++ b/mysql-test/suite/sys_vars/r/log_output_func.result @@ -1,6 +1,5 @@ SET @start_value= @@global.log_output; SET @start_general_log= @@global.general_log; -SET @start_general_log_file= @@global.general_log_file; '#--------------------FN_DYNVARS_065_01-------------------------#' SET @@global.log_output = 'NONE'; 'connect (con1,localhost,root,,,,)' @@ -53,7 +52,7 @@ count(*) DROP TABLE t1; connection default; SET @@global.general_log= 'OFF'; -SET @@global.general_log_file= @start_general_log_file; +SET @@global.general_log_file= '/home/horst/bzr/5.1-52501/mysql-test/var/mysqld.1/mysqld.log'; SET @@global.log_output= @start_value; SET @@global.general_log= @start_general_log; SET @@global.general_log= 'ON'; diff --git a/mysql-test/suite/sys_vars/r/slow_query_log_file_basic.result b/mysql-test/suite/sys_vars/r/slow_query_log_file_basic.result index 925f940a5c4..3cd62187d0b 100644 --- a/mysql-test/suite/sys_vars/r/slow_query_log_file_basic.result +++ b/mysql-test/suite/sys_vars/r/slow_query_log_file_basic.result @@ -1,4 +1,4 @@ -SET @start_value = @@global.slow_query_log_file; +slowtest.log '#---------------------FN_DYNVARS_004_01-------------------------#' SET @@global.slow_query_log_file = DEFAULT; SELECT RIGHT(@@global.slow_query_log_file,15); @@ -14,4 +14,4 @@ FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='slow_query_log_file'; @@global.slow_query_log_file = VARIABLE_VALUE 1 -SET @@global.slow_query_log_file= @start_value; +SET @@global.slow_query_log_file= 'slowtest.log'; diff --git a/mysql-test/suite/sys_vars/r/timestamp_basic_32.result b/mysql-test/suite/sys_vars/r/timestamp_basic_32.result index a8be2201e68..87c9edc668e 100644 --- a/mysql-test/suite/sys_vars/r/timestamp_basic_32.result +++ b/mysql-test/suite/sys_vars/r/timestamp_basic_32.result @@ -8,14 +8,6 @@ ERROR HY000: Variable 'timestamp' is a SESSION variable and can't be used with S '#--------------------FN_DYNVARS_001_03------------------------#' SET @@timestamp = 0; 'Setting 0 resets timestamp to session default timestamp' -SET @@timestamp = 123456789123456; -SELECT @@timestamp; -@@timestamp -2249167232 -SET @@timestamp = 60*60*60*60*365; -SELECT @@timestamp; -@@timestamp -435432704 SET @@timestamp = -1000000000; SELECT @@timestamp; @@timestamp @@ -66,3 +58,7 @@ ERROR 42S02: Unknown table 'session' in field list SELECT timestamp = @@session.timestamp; ERROR 42S22: Unknown column 'timestamp' in 'field list' SET @@timestamp = @session_start_value; +SET @@timestamp = 123456789123456; +ERROR HY000: This version of MySQL doesn't support dates later than 2038 +SET @@timestamp = 60*60*60*60*365; +ERROR HY000: This version of MySQL doesn't support dates later than 2038 diff --git a/mysql-test/suite/sys_vars/r/timestamp_basic_64.result b/mysql-test/suite/sys_vars/r/timestamp_basic_64.result index 824a3ea5529..b5d3979610f 100644 --- a/mysql-test/suite/sys_vars/r/timestamp_basic_64.result +++ b/mysql-test/suite/sys_vars/r/timestamp_basic_64.result @@ -8,14 +8,6 @@ ERROR HY000: Variable 'timestamp' is a SESSION variable and can't be used with S '#--------------------FN_DYNVARS_001_03------------------------#' SET @@timestamp = 0; 'Setting 0 resets timestamp to session default timestamp' -SET @@timestamp = 123456789123456; -SELECT @@timestamp; -@@timestamp -123456789123456 -SET @@timestamp = 60*60*60*60*365; -SELECT @@timestamp; -@@timestamp -4730400000 SET @@timestamp = -1000000000; SELECT @@timestamp; @@timestamp @@ -66,3 +58,11 @@ ERROR 42S02: Unknown table 'session' in field list SELECT timestamp = @@session.timestamp; ERROR 42S22: Unknown column 'timestamp' in 'field list' SET @@timestamp = @session_start_value; +SET @@timestamp = 123456789123456; +SELECT @@timestamp; +@@timestamp +123456789123456 +SET @@timestamp = 60*60*60*60*365; +SELECT @@timestamp; +@@timestamp +4730400000 diff --git a/mysql-test/suite/sys_vars/r/tmp_table_size_basic.result b/mysql-test/suite/sys_vars/r/tmp_table_size_basic.result index 2ebeb8d61d8..06b624ad5c8 100644 --- a/mysql-test/suite/sys_vars/r/tmp_table_size_basic.result +++ b/mysql-test/suite/sys_vars/r/tmp_table_size_basic.result @@ -100,8 +100,6 @@ SELECT @@session.tmp_table_size; SET @@session.tmp_table_size = "Test"; ERROR 42000: Incorrect argument type to variable 'tmp_table_size' SET @@session.tmp_table_size = 12345678901; -Warnings: -Warning 1292 Truncated incorrect tmp_table_size value: '12345678901' SELECT @@session.tmp_table_size IN (12345678901,4294967295); @@session.tmp_table_size IN (12345678901,4294967295) 1 diff --git a/mysql-test/suite/sys_vars/t/completion_type_func.test b/mysql-test/suite/sys_vars/t/completion_type_func.test index 8e363ed2a7d..82e2dc47e54 100644 --- a/mysql-test/suite/sys_vars/t/completion_type_func.test +++ b/mysql-test/suite/sys_vars/t/completion_type_func.test @@ -18,7 +18,7 @@ # server-system-variables.html#option_mysqld_completion_type # # # ################################################################################ - +--source include/not_embedded.inc --source include/have_innodb.inc --disable_warnings diff --git a/mysql-test/suite/sys_vars/t/disabled.def b/mysql-test/suite/sys_vars/t/disabled.def new file mode 100644 index 00000000000..915ea7a6f5c --- /dev/null +++ b/mysql-test/suite/sys_vars/t/disabled.def @@ -0,0 +1,13 @@ +############################################################################## +# +# List the test cases that are to be disabled temporarily. +# +# Separate the test case name and the comment with ':'. +# +# <testcasename> : BUG#<xxxx> <date disabled> <disabler> <comment> +# +# Do not use any TAB characters for whitespace. +# +############################################################################## +sys_vars.max_binlog_cache_size_basic_64 : bug#56408 2010-08-31 Horst +sys_vars.max_binlog_cache_size_basic_32 : bug#56408 2010-08-31 Horst diff --git a/mysql-test/suite/sys_vars/t/general_log_file_basic.test b/mysql-test/suite/sys_vars/t/general_log_file_basic.test index 014108f88d2..35905bad987 100644 --- a/mysql-test/suite/sys_vars/t/general_log_file_basic.test +++ b/mysql-test/suite/sys_vars/t/general_log_file_basic.test @@ -35,7 +35,8 @@ # Saving initial value of general_log_file in a temporary variable # ######################################################################## -SET @start_value = @@global.general_log_file; +#SET @start_value = @@global.general_log_file; +LET $start_value = `SELECT @@global.general_log_file`; SELECT @start_value; @@ -68,7 +69,8 @@ SELECT @@global.general_log_file = VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='general_log_file'; -SET @@global.general_log_file= @start_value; +#SET @@global.general_log_file= @start_value; +eval SET @@global.general_log_file= '$start_value'; ##################################################### # END OF general_log_file TESTS # diff --git a/mysql-test/suite/sys_vars/t/general_log_func.test b/mysql-test/suite/sys_vars/t/general_log_func.test index 24d535e88e5..d355d0d619c 100644 --- a/mysql-test/suite/sys_vars/t/general_log_func.test +++ b/mysql-test/suite/sys_vars/t/general_log_func.test @@ -79,6 +79,7 @@ INSERT into t1(name) values('Record_4'); --chmod 0777 $MYSQLD_LOGFILE.orig --echo ## There should be a difference ## +SET @start_value= @@global.max_allowed_packet; SET @@global.max_allowed_packet= 1024*1024*1024; --replace_result $MYSQLD_LOGFILE MYSQLD_LOGFILE eval SET @orig_file= load_file('$MYSQLD_LOGFILE.orig'); @@ -91,3 +92,4 @@ eval SELECT STRCMP(@orig_file, @copy_file); --echo ## Dropping tables ## DROP TABLE t1; +SET @@global.max_allowed_packet= @start_value; diff --git a/mysql-test/suite/sys_vars/t/innodb_commit_concurrency_basic-master.opt b/mysql-test/suite/sys_vars/t/innodb_commit_concurrency_basic-master.opt new file mode 100644 index 00000000000..727bbc4b11b --- /dev/null +++ b/mysql-test/suite/sys_vars/t/innodb_commit_concurrency_basic-master.opt @@ -0,0 +1 @@ +--innodb-commit-concurrency=10 diff --git a/mysql-test/suite/sys_vars/t/innodb_commit_concurrency_basic.test b/mysql-test/suite/sys_vars/t/innodb_commit_concurrency_basic.test index 1ef69e34999..2c7645f3b25 100644 --- a/mysql-test/suite/sys_vars/t/innodb_commit_concurrency_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_commit_concurrency_basic.test @@ -11,6 +11,10 @@ # Creation Date: 2008-02-07 # # Author: Rizwan # # # +# Modified 2010-09-01 Horst # +# Added amaster.opt with innodb-commit-concurrency > 0 to be able to assign # +# different values <> 0 # +# # #Description:Test Cases of Dynamic System Variable innodb_commit_concurrency # # that checks the behavior of this variable in the following ways # # * Default Value # @@ -43,7 +47,6 @@ SELECT @global_start_value; # Display the DEFAULT value of innodb_commit_concurrency # ######################################################################## -SET @@global.innodb_commit_concurrency = 0; SET @@global.innodb_commit_concurrency = DEFAULT; SELECT @@global.innodb_commit_concurrency; @@ -60,20 +63,14 @@ SELECT @@innodb_commit_concurrency; --Error ER_UNKNOWN_TABLE SELECT local.innodb_commit_concurrency; +--error ER_WRONG_ARGUMENTS SET global innodb_commit_concurrency = 0; -SELECT @@global.innodb_commit_concurrency; - - --echo '#--------------------FN_DYNVARS_046_03------------------------#' ########################################################################## # change the value of innodb_commit_concurrency to a valid value # ########################################################################## - -SET @@global.innodb_commit_concurrency = 0; -SELECT @@global.innodb_commit_concurrency; - SET @@global.innodb_commit_concurrency = 1; SELECT @@global.innodb_commit_concurrency; SET @@global.innodb_commit_concurrency = 1000; @@ -85,15 +82,13 @@ SELECT @@global.innodb_commit_concurrency; ########################################################################### SET @@global.innodb_commit_concurrency = -1; -SELECT @@global.innodb_commit_concurrency; +SELECT @@global.innodb_commit_concurrency IN (4294967295,18446744073709551615); --Error ER_WRONG_TYPE_FOR_VAR SET @@global.innodb_commit_concurrency = "T"; -SELECT @@global.innodb_commit_concurrency; --Error ER_WRONG_TYPE_FOR_VAR SET @@global.innodb_commit_concurrency = "Y"; -SELECT @@global.innodb_commit_concurrency; SET @@global.innodb_commit_concurrency = 1001; SELECT @@global.innodb_commit_concurrency; @@ -131,6 +126,7 @@ SELECT @@global.innodb_commit_concurrency; SET @@global.innodb_commit_concurrency = TRUE; SELECT @@global.innodb_commit_concurrency; +--error ER_WRONG_ARGUMENTS SET @@global.innodb_commit_concurrency = FALSE; SELECT @@global.innodb_commit_concurrency; diff --git a/mysql-test/suite/sys_vars/t/log_output_func.test b/mysql-test/suite/sys_vars/t/log_output_func.test index 007c4f38659..8a2fbe0728b 100644 --- a/mysql-test/suite/sys_vars/t/log_output_func.test +++ b/mysql-test/suite/sys_vars/t/log_output_func.test @@ -26,7 +26,8 @@ SET @start_value= @@global.log_output; SET @start_general_log= @@global.general_log; -SET @start_general_log_file= @@global.general_log_file; +#SET @start_general_log_file= @@global.general_log_file; +LET $start_general_log_file= `SELECT @@global.general_log_file`; --echo '#--------------------FN_DYNVARS_065_01-------------------------#' ################################################################## @@ -113,7 +114,8 @@ file_exists $MYSQLTEST_VARDIR/run/mytest.log ; --echo connection default; connection default; SET @@global.general_log= 'OFF'; -SET @@global.general_log_file= @start_general_log_file; +#SET @@global.general_log_file= @start_general_log_file; +eval SET @@global.general_log_file= '$start_general_log_file'; SET @@global.log_output= @start_value; SET @@global.general_log= @start_general_log; SET @@global.general_log= 'ON'; diff --git a/mysql-test/suite/sys_vars/t/myisam_data_pointer_size_func-master.opt b/mysql-test/suite/sys_vars/t/myisam_data_pointer_size_func-master.opt new file mode 100644 index 00000000000..d392e2e4262 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/myisam_data_pointer_size_func-master.opt @@ -0,0 +1 @@ +--log-error='dummy.log' diff --git a/mysql-test/suite/sys_vars/t/myisam_data_pointer_size_func.test b/mysql-test/suite/sys_vars/t/myisam_data_pointer_size_func.test index 37dd3a5a297..441e9c72982 100644 --- a/mysql-test/suite/sys_vars/t/myisam_data_pointer_size_func.test +++ b/mysql-test/suite/sys_vars/t/myisam_data_pointer_size_func.test @@ -19,6 +19,9 @@ # # ################################################################################ +# due to bug#56486 +--source include/not_windows.inc + --echo '#--------------------FN_DYNVARS_093_01-------------------------#' ############################################################################### # Check if setting myisam_data_pointer_size is changed in every new connection# diff --git a/mysql-test/suite/sys_vars/t/rpl_init_slave_func.test b/mysql-test/suite/sys_vars/t/rpl_init_slave_func.test index f2c66eb3a0a..2cc31c91388 100644 --- a/mysql-test/suite/sys_vars/t/rpl_init_slave_func.test +++ b/mysql-test/suite/sys_vars/t/rpl_init_slave_func.test @@ -55,7 +55,7 @@ DROP TABLE t1; eval SELECT @@global.init_slave = $my_init_slave; --echo Expect 1 # wait for the slave threads have set the global variable. -let $wait_timeout= 90; +let $wait_timeout= 240; let $wait_condition= SELECT @@global.max_connections = @start_max_connections; --source include/wait_condition_sp.inc # check that the action in init_slave does not happen immediately diff --git a/mysql-test/suite/sys_vars/t/slow_query_log_file_basic.test b/mysql-test/suite/sys_vars/t/slow_query_log_file_basic.test index 9125b686cad..810588b8f4e 100644 --- a/mysql-test/suite/sys_vars/t/slow_query_log_file_basic.test +++ b/mysql-test/suite/sys_vars/t/slow_query_log_file_basic.test @@ -35,7 +35,9 @@ # Saving initial value of slow_query_log_file in a temporary variable # ########################################################################### -SET @start_value = @@global.slow_query_log_file; +#SET @start_value = @@global.slow_query_log_file; +LET $start_value = `SELECT @@global.slow_query_log_file`; +--echo $start_value --echo '#---------------------FN_DYNVARS_004_01-------------------------#' ############################################### @@ -65,7 +67,9 @@ SELECT @@global.slow_query_log_file = VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='slow_query_log_file'; -SET @@global.slow_query_log_file= @start_value; +#SET @@global.slow_query_log_file= @start_value; +eval SET @@global.slow_query_log_file= '$start_value'; +#SELECT @start_value; ##################################################### # END OF slow_query_log_file TESTS # ##################################################### diff --git a/mysql-test/suite/sys_vars/t/sql_log_off_func-master.opt b/mysql-test/suite/sys_vars/t/sql_log_off_func-master.opt new file mode 100644 index 00000000000..875ecc54b55 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/sql_log_off_func-master.opt @@ -0,0 +1 @@ +--general-log --log-output=TABLE,FILE diff --git a/mysql-test/suite/sys_vars/t/timestamp_basic_32.test b/mysql-test/suite/sys_vars/t/timestamp_basic_32.test index a2b6139aef9..11b7535d9ef 100644 --- a/mysql-test/suite/sys_vars/t/timestamp_basic_32.test +++ b/mysql-test/suite/sys_vars/t/timestamp_basic_32.test @@ -7,3 +7,7 @@ --source include/have_32bit.inc --source suite/sys_vars/inc/timestamp_basic.inc +--error ER_UNKNOWN_ERROR +SET @@timestamp = 123456789123456; +--error ER_UNKNOWN_ERROR +SET @@timestamp = 60*60*60*60*365; diff --git a/mysql-test/suite/sys_vars/t/timestamp_basic_64.test b/mysql-test/suite/sys_vars/t/timestamp_basic_64.test index fbc86316ed9..5180c86392a 100644 --- a/mysql-test/suite/sys_vars/t/timestamp_basic_64.test +++ b/mysql-test/suite/sys_vars/t/timestamp_basic_64.test @@ -7,3 +7,8 @@ --source include/have_64bit.inc --source suite/sys_vars/inc/timestamp_basic.inc +SET @@timestamp = 123456789123456; +SELECT @@timestamp; +SET @@timestamp = 60*60*60*60*365; +SELECT @@timestamp; + diff --git a/mysql-test/suite/sys_vars/t/tmp_table_size_basic.test b/mysql-test/suite/sys_vars/t/tmp_table_size_basic.test index c2ff51d50ca..116196ddb07 100644 --- a/mysql-test/suite/sys_vars/t/tmp_table_size_basic.test +++ b/mysql-test/suite/sys_vars/t/tmp_table_size_basic.test @@ -133,8 +133,9 @@ SELECT @@session.tmp_table_size; --Error ER_WRONG_TYPE_FOR_VAR SET @@session.tmp_table_size = "Test"; +--disable_warnings SET @@session.tmp_table_size = 12345678901; - +--enable_warnings # With a 64 bit mysqld:12345678901,with a 32 bit mysqld: 4294967295 SELECT @@session.tmp_table_size IN (12345678901,4294967295); diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 9c5e091e03b..4510652b03f 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -13,3 +13,5 @@ kill : Bug#37780 2008-12-03 HHunger need some changes to be query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically main.mysqlhotcopy_myisam : Bug#56817 2010-10-21 anitha mysqlhotcopy* fails main.mysqlhotcopy_archive: Bug#56817 2010-10-21 anitha mysqlhotcopy* fails +log_tables-big : Bug#48646 2010-11-15 mattiasj report already exists +read_many_rows_innodb : Bug#37635 2010-11-15 mattiasj report already exists diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index e764906c374..8fce7072319 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -849,4 +849,14 @@ INSERT INTO t1 VALUES (0),(9.216e-096); SELECT 1 FROM t1 ORDER BY @x:=makedate(a,a); DROP TABLE t1; +--echo # +--echo # Bug #52160: crash and inconsistent results when grouping +--echo # by a function and column +--echo # + +CREATE TABLE t1(a CHAR(10) NOT NULL); +INSERT INTO t1 VALUES (''),(''); +SELECT COUNT(*) FROM t1 GROUP BY TIME_TO_SEC(a); +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/mysql-test/t/key_cache-master.opt b/mysql-test/t/key_cache-master.opt index 66e19c18a8a..6398e3e0a26 100644 --- a/mysql-test/t/key_cache-master.opt +++ b/mysql-test/t/key_cache-master.opt @@ -1 +1,2 @@ --key_buffer_size=2M --small.key_buffer_size=256K --small.key_buffer_size=128K +--force-restart diff --git a/mysql-test/t/log_tables.test b/mysql-test/t/log_tables.test index 076f2e8bc3b..af6c34dec37 100644 --- a/mysql-test/t/log_tables.test +++ b/mysql-test/t/log_tables.test @@ -1027,6 +1027,25 @@ DROP TABLE t1; TRUNCATE TABLE mysql.slow_log; +# +# Bug #47924 main.log_tables times out sporadically +# + +use mysql; +# Should result in error +--disable_warnings +drop table if exists renamed_general_log; +drop table if exists renamed_slow_log; +--enable_warnings +--error ER_CANT_RENAME_LOG_TABLE +RENAME TABLE general_log TO renamed_general_log; +--error ER_CANT_RENAME_LOG_TABLE +RENAME TABLE slow_log TO renamed_slow_log; + +use test; +flush tables with read lock; +unlock tables; + SET @@session.long_query_time= @old_long_query_time; SET @@global.log_output= @old_log_output; diff --git a/mysql-test/t/mysqlbinlog-master.opt b/mysql-test/t/mysqlbinlog-master.opt index ac1a87c73b3..a9f4a6010d8 100644 --- a/mysql-test/t/mysqlbinlog-master.opt +++ b/mysql-test/t/mysqlbinlog-master.opt @@ -1 +1,2 @@ --max-binlog-size=4096 +--force-restart diff --git a/mysql-test/t/sp-bugs.test b/mysql-test/t/sp-bugs.test index 8aa0791e265..fe52632c784 100644 --- a/mysql-test/t/sp-bugs.test +++ b/mysql-test/t/sp-bugs.test @@ -101,4 +101,41 @@ CALL p1 (); DROP TABLE t1; DROP PROCEDURE p1; +--echo # +--echo # Bug#54375: Error in stored procedure leaves connection +--echo # in different default schema +--echo # + +--disable_warnings +SET @@SQL_MODE = 'STRICT_ALL_TABLES'; +DROP DATABASE IF EXISTS db1; +CREATE DATABASE db1; +USE db1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (c1 int NOT NULL PRIMARY KEY); +INSERT INTO t1 VALUES (1); +DELIMITER $$; +CREATE FUNCTION f1 ( + some_value int +) +RETURNS smallint +DETERMINISTIC +BEGIN + INSERT INTO t1 SET c1 = some_value; + RETURN(LAST_INSERT_ID()); +END$$ +DELIMITER ;$$ +DROP DATABASE IF EXISTS db2; +CREATE DATABASE db2; +--enable_warnings +USE db2; +SELECT DATABASE(); +--error ER_DUP_ENTRY +SELECT db1.f1(1); +SELECT DATABASE(); +USE test; +DROP FUNCTION db1.f1; +DROP TABLE db1.t1; +DROP DATABASE db1; +DROP DATABASE db2; --echo End of 5.1 tests diff --git a/mysql-test/t/type_blob.test b/mysql-test/t/type_blob.test index 460da1c1614..4e097edf73d 100644 --- a/mysql-test/t/type_blob.test +++ b/mysql-test/t/type_blob.test @@ -612,3 +612,19 @@ explain select convert(1, binary(4294967296)); explain select convert(1, binary(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)); --echo End of 5.0 tests + +--echo # Bug #52160: crash and inconsistent results when grouping +--echo # by a function and column + +CREATE FUNCTION f1() RETURNS TINYBLOB RETURN 1; + +CREATE TABLE t1(a CHAR(1)); +INSERT INTO t1 VALUES ('0'), ('0'); + +SELECT COUNT(*) FROM t1 GROUP BY f1(), a; + +DROP FUNCTION f1; +DROP TABLE t1; + +--echo End of 5.1 tests + diff --git a/mysql-test/t/variables-big.test b/mysql-test/t/variables-big.test index fdb11ffa907..6c357bb6e54 100644 --- a/mysql-test/t/variables-big.test +++ b/mysql-test/t/variables-big.test @@ -37,19 +37,19 @@ --disable_warnings SET SESSION transaction_prealloc_size=1024*1024*1024*1; ---replace_column 1 <Id> 6 <Time> +--replace_column 1 <Id> 3 <Host> 6 <Time> SHOW PROCESSLIST; SET SESSION transaction_prealloc_size=1024*1024*1024*2; ---replace_column 1 <Id> 6 <Time> +--replace_column 1 <Id> 3 <Host> 6 <Time> SHOW PROCESSLIST; SET SESSION transaction_prealloc_size=1024*1024*1024*3; ---replace_column 1 <Id> 6 <Time> +--replace_column 1 <Id> 3 <Host> 6 <Time> SHOW PROCESSLIST; SET SESSION transaction_prealloc_size=1024*1024*1024*4; ---replace_column 1 <Id> 6 <Time> +--replace_column 1 <Id> 3 <Host> 6 <Time> SHOW PROCESSLIST; SET SESSION transaction_prealloc_size=1024*1024*1024*5; ---replace_column 1 <Id> 6 <Time> +--replace_column 1 <Id> 3 <Host> 6 <Time> SHOW PROCESSLIST; --enable_warnings diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 8042dc2828b..b7faf7c1b95 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -3917,11 +3917,11 @@ restart: if (!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH | BLOCK_REASSIGNED))) { - struct st_hash_link *next_hash_link; - my_off_t next_diskpos; - File next_file; - uint next_status; - uint hash_requests; + struct st_hash_link *UNINIT_VAR(next_hash_link); + my_off_t UNINIT_VAR(next_diskpos); + File UNINIT_VAR(next_file); + uint UNINIT_VAR(next_status); + uint UNINIT_VAR(hash_requests); total_found++; found++; diff --git a/mysys/my_getncpus.c b/mysys/my_getncpus.c index 82e87dee2e4..f9db6603924 100644 --- a/mysys/my_getncpus.c +++ b/mysys/my_getncpus.c @@ -18,9 +18,10 @@ #include "mysys_priv.h" #include <unistd.h> +#ifdef _SC_NPROCESSORS_ONLN + static int ncpus=0; -#ifdef _SC_NPROCESSORS_ONLN int my_getncpus() { if (!ncpus) diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c index 7bac8017324..ebd84548a9b 100644 --- a/mysys/stacktrace.c +++ b/mysys/stacktrace.c @@ -318,6 +318,9 @@ end: /* Produce a core for the thread */ void my_write_core(int sig) { +#ifdef HAVE_gcov + extern void __gcov_flush(void); +#endif signal(sig, SIG_DFL); #ifdef HAVE_gcov /* @@ -325,7 +328,6 @@ void my_write_core(int sig) information from this process, causing gcov output to be incomplete. So we force the writing of coverage information here before terminating. */ - extern void __gcov_flush(void); __gcov_flush(); #endif pthread_kill(pthread_self(), sig); diff --git a/pstack/Makefile.am b/pstack/Makefile.am deleted file mode 100644 index 870fed6ceeb..00000000000 --- a/pstack/Makefile.am +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (C) 2000-2003, 2005 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; version 2 of the License. -# -# 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 - -# -# As pstack doesn't work on all configurations, we have to use -# the USE_PSTACK hack to get all files into distribution -# - -SUBDIRS = aout - -INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include - -pkglib_LIBRARIES = libpstack.a -libpstack_a_SOURCES = bucomm.c filemode.c linuxthreads.c rddbg.c \ - debug.c ieee.c pstack.c stabs.c -noinst_HEADERS = bucomm.h debug.h ieee.h budbg.h demangle.h \ - linuxthreads.h pstack.h pstacktrace.h - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/pstack/aout/Makefile.am b/pstack/aout/Makefile.am deleted file mode 100644 index 2e61555db87..00000000000 --- a/pstack/aout/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -noinst_HEADERS = aout64.h stab.def stab_gnu.h - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/pstack/aout/aout64.h b/pstack/aout/aout64.h deleted file mode 100644 index 76f1140b682..00000000000 --- a/pstack/aout/aout64.h +++ /dev/null @@ -1,475 +0,0 @@ -/* `a.out' object-file definitions, including extensions to 64-bit fields */ - -#ifndef __A_OUT_64_H__ -#define __A_OUT_64_H__ - -/* This is the layout on disk of the 32-bit or 64-bit exec header. */ - -#ifndef external_exec -struct external_exec -{ - bfd_byte e_info[4]; /* magic number and stuff */ - bfd_byte e_text[BYTES_IN_WORD]; /* length of text section in bytes */ - bfd_byte e_data[BYTES_IN_WORD]; /* length of data section in bytes */ - bfd_byte e_bss[BYTES_IN_WORD]; /* length of bss area in bytes */ - bfd_byte e_syms[BYTES_IN_WORD]; /* length of symbol table in bytes */ - bfd_byte e_entry[BYTES_IN_WORD]; /* start address */ - bfd_byte e_trsize[BYTES_IN_WORD]; /* length of text relocation info */ - bfd_byte e_drsize[BYTES_IN_WORD]; /* length of data relocation info */ -}; - -#define EXEC_BYTES_SIZE (4 + BYTES_IN_WORD * 7) - -/* Magic numbers for a.out files */ - -#if ARCH_SIZE==64 -#define OMAGIC 0x1001 /* Code indicating object file */ -#define ZMAGIC 0x1002 /* Code indicating demand-paged executable. */ -#define NMAGIC 0x1003 /* Code indicating pure executable. */ - -/* There is no 64-bit QMAGIC as far as I know. */ - -#define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \ - && N_MAGIC(x) != NMAGIC \ - && N_MAGIC(x) != ZMAGIC) -#else -#define OMAGIC 0407 /* ...object file or impure executable. */ -#define NMAGIC 0410 /* Code indicating pure executable. */ -#define ZMAGIC 0413 /* Code indicating demand-paged executable. */ -#define BMAGIC 0415 /* Used by a b.out object. */ - -/* This indicates a demand-paged executable with the header in the text. - It is used by 386BSD (and variants) and Linux, at least. */ -#ifndef QMAGIC -#define QMAGIC 0314 -#endif -# ifndef N_BADMAG -# define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \ - && N_MAGIC(x) != NMAGIC \ - && N_MAGIC(x) != ZMAGIC \ - && N_MAGIC(x) != QMAGIC) -# endif /* N_BADMAG */ -#endif - -#endif - -#ifdef QMAGIC -#define N_IS_QMAGIC(x) (N_MAGIC (x) == QMAGIC) -#else -#define N_IS_QMAGIC(x) (0) -#endif - -/* The difference between TARGET_PAGE_SIZE and N_SEGSIZE is that TARGET_PAGE_SIZE is - the finest granularity at which you can page something, thus it - controls the padding (if any) before the text segment of a ZMAGIC - file. N_SEGSIZE is the resolution at which things can be marked as - read-only versus read/write, so it controls the padding between the - text segment and the data segment (in memory; on disk the padding - between them is TARGET_PAGE_SIZE). TARGET_PAGE_SIZE and N_SEGSIZE are the same - for most machines, but different for sun3. */ - -/* By default, segment size is constant. But some machines override this - to be a function of the a.out header (e.g. machine type). */ - -#ifndef N_SEGSIZE -#define N_SEGSIZE(x) SEGMENT_SIZE -#endif - -/* Virtual memory address of the text section. - This is getting very complicated. A good reason to discard a.out format - for something that specifies these fields explicitly. But til then... - - * OMAGIC and NMAGIC files: - (object files: text for "relocatable addr 0" right after the header) - start at 0, offset is EXEC_BYTES_SIZE, size as stated. - * The text address, offset, and size of ZMAGIC files depend - on the entry point of the file: - * entry point below TEXT_START_ADDR: - (hack for SunOS shared libraries) - start at 0, offset is 0, size as stated. - * If N_HEADER_IN_TEXT(x) is true (which defaults to being the - case when the entry point is EXEC_BYTES_SIZE or further into a page): - no padding is needed; text can start after exec header. Sun - considers the text segment of such files to include the exec header; - for BFD's purposes, we don't, which makes more work for us. - start at TEXT_START_ADDR + EXEC_BYTES_SIZE, offset is EXEC_BYTES_SIZE, - size as stated minus EXEC_BYTES_SIZE. - * If N_HEADER_IN_TEXT(x) is false (which defaults to being the case when - the entry point is less than EXEC_BYTES_SIZE into a page (e.g. page - aligned)): (padding is needed so that text can start at a page boundary) - start at TEXT_START_ADDR, offset TARGET_PAGE_SIZE, size as stated. - - Specific configurations may want to hardwire N_HEADER_IN_TEXT, - for efficiency or to allow people to play games with the entry point. - In that case, you would #define N_HEADER_IN_TEXT(x) as 1 for sunos, - and as 0 for most other hosts (Sony News, Vax Ultrix, etc). - (Do this in the appropriate bfd target file.) - (The default is a heuristic that will break if people try changing - the entry point, perhaps with the ld -e flag.) - - * QMAGIC is always like a ZMAGIC for which N_HEADER_IN_TEXT is true, - and for which the starting address is TARGET_PAGE_SIZE (or should this be - SEGMENT_SIZE?) (TEXT_START_ADDR only applies to ZMAGIC, not to QMAGIC). - */ - -/* This macro is only relevant for ZMAGIC files; QMAGIC always has the header - in the text. */ -#ifndef N_HEADER_IN_TEXT -#define N_HEADER_IN_TEXT(x) (((x).a_entry & (TARGET_PAGE_SIZE-1)) >= EXEC_BYTES_SIZE) -#endif - -/* Sun shared libraries, not linux. This macro is only relevant for ZMAGIC - files. */ -#ifndef N_SHARED_LIB -#define N_SHARED_LIB(x) ((x).a_entry < TEXT_START_ADDR) -#endif - -/* Returning 0 not TEXT_START_ADDR for OMAGIC and NMAGIC is based on - the assumption that we are dealing with a .o file, not an - executable. This is necessary for OMAGIC (but means we don't work - right on the output from ld -N); more questionable for NMAGIC. */ - -#ifndef N_TXTADDR -#define N_TXTADDR(x) \ - (/* The address of a QMAGIC file is always one page in, */ \ - /* with the header in the text. */ \ - N_IS_QMAGIC (x) ? TARGET_PAGE_SIZE + EXEC_BYTES_SIZE : \ - N_MAGIC(x) != ZMAGIC ? 0 : /* object file or NMAGIC */\ - N_SHARED_LIB(x) ? 0 : \ - N_HEADER_IN_TEXT(x) ? \ - TEXT_START_ADDR + EXEC_BYTES_SIZE : /* no padding */\ - TEXT_START_ADDR /* a page of padding */\ - ) -#endif - -/* If N_HEADER_IN_TEXT is not true for ZMAGIC, there is some padding - to make the text segment start at a certain boundary. For most - systems, this boundary is TARGET_PAGE_SIZE. But for Linux, in the - time-honored tradition of crazy ZMAGIC hacks, it is 1024 which is - not what TARGET_PAGE_SIZE needs to be for QMAGIC. */ - -#ifndef ZMAGIC_DISK_BLOCK_SIZE -#define ZMAGIC_DISK_BLOCK_SIZE TARGET_PAGE_SIZE -#endif - -#define N_DISK_BLOCK_SIZE(x) \ - (N_MAGIC(x) == ZMAGIC ? ZMAGIC_DISK_BLOCK_SIZE : TARGET_PAGE_SIZE) - -/* Offset in an a.out of the start of the text section. */ -#ifndef N_TXTOFF -#define N_TXTOFF(x) \ - (/* For {O,N,Q}MAGIC, no padding. */ \ - N_MAGIC(x) != ZMAGIC ? EXEC_BYTES_SIZE : \ - N_SHARED_LIB(x) ? 0 : \ - N_HEADER_IN_TEXT(x) ? \ - EXEC_BYTES_SIZE : /* no padding */\ - ZMAGIC_DISK_BLOCK_SIZE /* a page of padding */\ - ) -#endif -/* Size of the text section. It's always as stated, except that we - offset it to `undo' the adjustment to N_TXTADDR and N_TXTOFF - for ZMAGIC files that nominally include the exec header - as part of the first page of text. (BFD doesn't consider the - exec header to be part of the text segment.) */ -#ifndef N_TXTSIZE -#define N_TXTSIZE(x) \ - (/* For QMAGIC, we don't consider the header part of the text section. */\ - N_IS_QMAGIC (x) ? (x).a_text - EXEC_BYTES_SIZE : \ - (N_MAGIC(x) != ZMAGIC || N_SHARED_LIB(x)) ? (x).a_text : \ - N_HEADER_IN_TEXT(x) ? \ - (x).a_text - EXEC_BYTES_SIZE: /* no padding */\ - (x).a_text /* a page of padding */\ - ) -#endif -/* The address of the data segment in virtual memory. - It is the text segment address, plus text segment size, rounded - up to a N_SEGSIZE boundary for pure or pageable files. */ -#ifndef N_DATADDR -#define N_DATADDR(x) \ - (N_MAGIC(x)==OMAGIC? (N_TXTADDR(x)+N_TXTSIZE(x)) \ - : (N_SEGSIZE(x) + ((N_TXTADDR(x)+N_TXTSIZE(x)-1) & ~(N_SEGSIZE(x)-1)))) -#endif -/* The address of the BSS segment -- immediately after the data segment. */ - -#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data) - -/* Offsets of the various portions of the file after the text segment. */ - -/* For {Q,Z}MAGIC, there is padding to make the data segment start on - a page boundary. Most of the time the a_text field (and thus - N_TXTSIZE) already contains this padding. It is possible that for - BSDI and/or 386BSD it sometimes doesn't contain the padding, and - perhaps we should be adding it here. But this seems kind of - questionable and probably should be BSDI/386BSD-specific if we do - do it. - - For NMAGIC (at least for hp300 BSD, probably others), there is - padding in memory only, not on disk, so we must *not* ever pad here - for NMAGIC. */ - -#ifndef N_DATOFF -#define N_DATOFF(x) \ - (N_TXTOFF(x) + N_TXTSIZE(x)) -#endif - -#ifndef N_TRELOFF -#define N_TRELOFF(x) ( N_DATOFF(x) + (x).a_data ) -#endif -#ifndef N_DRELOFF -#define N_DRELOFF(x) ( N_TRELOFF(x) + (x).a_trsize ) -#endif -#ifndef N_SYMOFF -#define N_SYMOFF(x) ( N_DRELOFF(x) + (x).a_drsize ) -#endif -#ifndef N_STROFF -#define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms ) -#endif - -/* Symbols */ -#ifndef external_nlist -struct external_nlist { - bfd_byte e_strx[BYTES_IN_WORD]; /* index into string table of name */ - bfd_byte e_type[1]; /* type of symbol */ - bfd_byte e_other[1]; /* misc info (usually empty) */ - bfd_byte e_desc[2]; /* description field */ - bfd_byte e_value[BYTES_IN_WORD]; /* value of symbol */ -}; -#define EXTERNAL_NLIST_SIZE (BYTES_IN_WORD+4+BYTES_IN_WORD) -#endif - -struct internal_nlist { - unsigned long n_strx; /* index into string table of name */ - unsigned char n_type; /* type of symbol */ - unsigned char n_other; /* misc info (usually empty) */ - unsigned short n_desc; /* description field */ - bfd_vma n_value; /* value of symbol */ -}; - -/* The n_type field is the symbol type, containing: */ - -#define N_UNDF 0 /* Undefined symbol */ -#define N_ABS 2 /* Absolute symbol -- defined at particular addr */ -#define N_TEXT 4 /* Text sym -- defined at offset in text seg */ -#define N_DATA 6 /* Data sym -- defined at offset in data seg */ -#define N_BSS 8 /* BSS sym -- defined at offset in zero'd seg */ -#define N_COMM 0x12 /* Common symbol (visible after shared lib dynlink) */ -#define N_FN 0x1f /* File name of .o file */ -#define N_FN_SEQ 0x0C /* N_FN from Sequent compilers (sigh) */ -/* Note: N_EXT can only be usefully OR-ed with N_UNDF, N_ABS, N_TEXT, - N_DATA, or N_BSS. When the low-order bit of other types is set, - (e.g. N_WARNING versus N_FN), they are two different types. */ -#define N_EXT 1 /* External symbol (as opposed to local-to-this-file) */ -#define N_TYPE 0x1e -#define N_STAB 0xe0 /* If any of these bits are on, it's a debug symbol */ - -#define N_INDR 0x0a - -/* The following symbols refer to set elements. - All the N_SET[ATDB] symbols with the same name form one set. - Space is allocated for the set in the text section, and each set - elements value is stored into one word of the space. - The first word of the space is the length of the set (number of elements). - - The address of the set is made into an N_SETV symbol - whose name is the same as the name of the set. - This symbol acts like a N_DATA global symbol - in that it can satisfy undefined external references. */ - -/* These appear as input to LD, in a .o file. */ -#define N_SETA 0x14 /* Absolute set element symbol */ -#define N_SETT 0x16 /* Text set element symbol */ -#define N_SETD 0x18 /* Data set element symbol */ -#define N_SETB 0x1A /* Bss set element symbol */ - -/* This is output from LD. */ -#define N_SETV 0x1C /* Pointer to set vector in data area. */ - -/* Warning symbol. The text gives a warning message, the next symbol - in the table will be undefined. When the symbol is referenced, the - message is printed. */ - -#define N_WARNING 0x1e - -/* Weak symbols. These are a GNU extension to the a.out format. The - semantics are those of ELF weak symbols. Weak symbols are always - externally visible. The N_WEAK? values are squeezed into the - available slots. The value of a N_WEAKU symbol is 0. The values - of the other types are the definitions. */ -#define N_WEAKU 0x0d /* Weak undefined symbol. */ -#define N_WEAKA 0x0e /* Weak absolute symbol. */ -#define N_WEAKT 0x0f /* Weak text symbol. */ -#define N_WEAKD 0x10 /* Weak data symbol. */ -#define N_WEAKB 0x11 /* Weak bss symbol. */ - -/* Relocations - - There are two types of relocation flavours for a.out systems, - standard and extended. The standard form is used on systems where the - instruction has room for all the bits of an offset to the operand, whilst - the extended form is used when an address operand has to be split over n - instructions. Eg, on the 68k, each move instruction can reference - the target with a displacement of 16 or 32 bits. On the sparc, move - instructions use an offset of 14 bits, so the offset is stored in - the reloc field, and the data in the section is ignored. -*/ - -/* This structure describes a single relocation to be performed. - The text-relocation section of the file is a vector of these structures, - all of which apply to the text section. - Likewise, the data-relocation section applies to the data section. */ - -struct reloc_std_external { - bfd_byte r_address[BYTES_IN_WORD]; /* offset of of data to relocate */ - bfd_byte r_index[3]; /* symbol table index of symbol */ - bfd_byte r_type[1]; /* relocation type */ -}; - -#define RELOC_STD_BITS_PCREL_BIG ((unsigned int) 0x80) -#define RELOC_STD_BITS_PCREL_LITTLE ((unsigned int) 0x01) - -#define RELOC_STD_BITS_LENGTH_BIG ((unsigned int) 0x60) -#define RELOC_STD_BITS_LENGTH_SH_BIG 5 -#define RELOC_STD_BITS_LENGTH_LITTLE ((unsigned int) 0x06) -#define RELOC_STD_BITS_LENGTH_SH_LITTLE 1 - -#define RELOC_STD_BITS_EXTERN_BIG ((unsigned int) 0x10) -#define RELOC_STD_BITS_EXTERN_LITTLE ((unsigned int) 0x08) - -#define RELOC_STD_BITS_BASEREL_BIG ((unsigned int) 0x08) -#define RELOC_STD_BITS_BASEREL_LITTLE ((unsigned int) 0x10) - -#define RELOC_STD_BITS_JMPTABLE_BIG ((unsigned int) 0x04) -#define RELOC_STD_BITS_JMPTABLE_LITTLE ((unsigned int) 0x20) - -#define RELOC_STD_BITS_RELATIVE_BIG ((unsigned int) 0x02) -#define RELOC_STD_BITS_RELATIVE_LITTLE ((unsigned int) 0x40) - -#define RELOC_STD_SIZE (BYTES_IN_WORD + 3 + 1) /* Bytes per relocation entry */ - -struct reloc_std_internal -{ - bfd_vma r_address; /* Address (within segment) to be relocated. */ - /* The meaning of r_symbolnum depends on r_extern. */ - unsigned int r_symbolnum:24; - /* Nonzero means value is a pc-relative offset - and it should be relocated for changes in its own address - as well as for changes in the symbol or section specified. */ - unsigned int r_pcrel:1; - /* Length (as exponent of 2) of the field to be relocated. - Thus, a value of 2 indicates 1<<2 bytes. */ - unsigned int r_length:2; - /* 1 => relocate with value of symbol. - r_symbolnum is the index of the symbol - in files the symbol table. - 0 => relocate with the address of a segment. - r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS - (the N_EXT bit may be set also, but signifies nothing). */ - unsigned int r_extern:1; - /* The next three bits are for SunOS shared libraries, and seem to - be undocumented. */ - unsigned int r_baserel:1; /* Linkage table relative */ - unsigned int r_jmptable:1; /* pc-relative to jump table */ - unsigned int r_relative:1; /* "relative relocation" */ - /* unused */ - unsigned int r_pad:1; /* Padding -- set to zero */ -}; - - -/* EXTENDED RELOCS */ - -struct reloc_ext_external { - bfd_byte r_address[BYTES_IN_WORD]; /* offset of of data to relocate */ - bfd_byte r_index[3]; /* symbol table index of symbol */ - bfd_byte r_type[1]; /* relocation type */ - bfd_byte r_addend[BYTES_IN_WORD]; /* datum addend */ -}; - -#define RELOC_EXT_BITS_EXTERN_BIG ((unsigned int) 0x80) -#define RELOC_EXT_BITS_EXTERN_LITTLE ((unsigned int) 0x01) - -#define RELOC_EXT_BITS_TYPE_BIG ((unsigned int) 0x1F) -#define RELOC_EXT_BITS_TYPE_SH_BIG 0 -#define RELOC_EXT_BITS_TYPE_LITTLE ((unsigned int) 0xF8) -#define RELOC_EXT_BITS_TYPE_SH_LITTLE 3 - -/* Bytes per relocation entry */ -#define RELOC_EXT_SIZE (BYTES_IN_WORD + 3 + 1 + BYTES_IN_WORD) - -enum reloc_type -{ - /* simple relocations */ - RELOC_8, /* data[0:7] = addend + sv */ - RELOC_16, /* data[0:15] = addend + sv */ - RELOC_32, /* data[0:31] = addend + sv */ - /* pc-rel displacement */ - RELOC_DISP8, /* data[0:7] = addend - pc + sv */ - RELOC_DISP16, /* data[0:15] = addend - pc + sv */ - RELOC_DISP32, /* data[0:31] = addend - pc + sv */ - /* Special */ - RELOC_WDISP30, /* data[0:29] = (addend + sv - pc)>>2 */ - RELOC_WDISP22, /* data[0:21] = (addend + sv - pc)>>2 */ - RELOC_HI22, /* data[0:21] = (addend + sv)>>10 */ - RELOC_22, /* data[0:21] = (addend + sv) */ - RELOC_13, /* data[0:12] = (addend + sv) */ - RELOC_LO10, /* data[0:9] = (addend + sv) */ - RELOC_SFA_BASE, - RELOC_SFA_OFF13, - /* P.I.C. (base-relative) */ - RELOC_BASE10, /* Not sure - maybe we can do this the */ - RELOC_BASE13, /* right way now */ - RELOC_BASE22, - /* for some sort of pc-rel P.I.C. (?) */ - RELOC_PC10, - RELOC_PC22, - /* P.I.C. jump table */ - RELOC_JMP_TBL, - /* reputedly for shared libraries somehow */ - RELOC_SEGOFF16, - RELOC_GLOB_DAT, - RELOC_JMP_SLOT, - RELOC_RELATIVE, - - RELOC_11, - RELOC_WDISP2_14, - RELOC_WDISP19, - RELOC_HHI22, /* data[0:21] = (addend + sv) >> 42 */ - RELOC_HLO10, /* data[0:9] = (addend + sv) >> 32 */ - - /* 29K relocation types */ - RELOC_JUMPTARG, - RELOC_CONST, - RELOC_CONSTH, - - /* All the new ones I can think of, for sparc v9 */ - - RELOC_64, /* data[0:63] = addend + sv */ - RELOC_DISP64, /* data[0:63] = addend - pc + sv */ - RELOC_WDISP21, /* data[0:20] = (addend + sv - pc)>>2 */ - RELOC_DISP21, /* data[0:20] = addend - pc + sv */ - RELOC_DISP14, /* data[0:13] = addend - pc + sv */ - /* Q . - What are the other ones, - Since this is a clean slate, can we throw away the ones we dont - understand ? Should we sort the values ? What about using a - microcode format like the 68k ? - */ - NO_RELOC - }; - - -struct reloc_internal { - bfd_vma r_address; /* offset of of data to relocate */ - long r_index; /* symbol table index of symbol */ - enum reloc_type r_type; /* relocation type */ - bfd_vma r_addend; /* datum addend */ -}; - -/* Q. - Should the length of the string table be 4 bytes or 8 bytes ? - - Q. - What about archive indexes ? - - */ - -#endif /* __A_OUT_64_H__ */ diff --git a/pstack/aout/stab.def b/pstack/aout/stab.def deleted file mode 100644 index 3c6b456d3a9..00000000000 --- a/pstack/aout/stab.def +++ /dev/null @@ -1,264 +0,0 @@ -/* Table of DBX symbol codes for the GNU system. - Copyright (C) 1988, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. - -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. */ - -/* New stab from Solaris 2. This uses an n_type of 0, which in a.out files - overlaps the N_UNDF used for ordinary symbols. In ELF files, the - debug information is in a different file section, so there is no conflict. - This symbol's n_value gives the size of the string section associated - with this file. The symbol's n_strx (relative to the just-updated - string section start address) gives the name of the source file, - e.g. "foo.c", without any path information. The symbol's n_desc gives - the count of upcoming symbols associated with this file (not including - this one). */ -/* __define_stab (N_UNDF, 0x00, "UNDF") */ - -/* Global variable. Only the name is significant. - To find the address, look in the corresponding external symbol. */ -__define_stab (N_GSYM, 0x20, "GSYM") - -/* Function name for BSD Fortran. Only the name is significant. - To find the address, look in the corresponding external symbol. */ -__define_stab (N_FNAME, 0x22, "FNAME") - -/* Function name or text-segment variable for C. Value is its address. - Desc is supposedly starting line number, but GCC doesn't set it - and DBX seems not to miss it. */ -__define_stab (N_FUN, 0x24, "FUN") - -/* Data-segment variable with internal linkage. Value is its address. - "Static Sym". */ -__define_stab (N_STSYM, 0x26, "STSYM") - -/* BSS-segment variable with internal linkage. Value is its address. */ -__define_stab (N_LCSYM, 0x28, "LCSYM") - -/* Name of main routine. Only the name is significant. */ -__define_stab (N_MAIN, 0x2a, "MAIN") - -/* Solaris2: Read-only data symbols. */ -__define_stab (N_ROSYM, 0x2c, "ROSYM") - -/* Global symbol in Pascal. - Supposedly the value is its line number; I'm skeptical. */ -__define_stab (N_PC, 0x30, "PC") - -/* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */ -__define_stab (N_NSYMS, 0x32, "NSYMS") - -/* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */ -__define_stab (N_NOMAP, 0x34, "NOMAP") - -/* New stab from Solaris 2. Like N_SO, but for the object file. Two in - a row provide the build directory and the relative path of the .o from it. - Solaris2 uses this to avoid putting the stabs info into the linked - executable; this stab goes into the ".stab.index" section, and the debugger - reads the real stabs directly from the .o files instead. */ -__define_stab (N_OBJ, 0x38, "OBJ") - -/* New stab from Solaris 2. Options for the debugger, related to the - source language for this module. E.g. whether to use ANSI - integral promotions or traditional integral promotions. */ -__define_stab (N_OPT, 0x3c, "OPT") - -/* Register variable. Value is number of register. */ -__define_stab (N_RSYM, 0x40, "RSYM") - -/* Modula-2 compilation unit. Can someone say what info it contains? */ -__define_stab (N_M2C, 0x42, "M2C") - -/* Line number in text segment. Desc is the line number; - value is corresponding address. On Solaris2, the line number is - relative to the start of the current function. */ -__define_stab (N_SLINE, 0x44, "SLINE") - -/* Similar, for data segment. */ -__define_stab (N_DSLINE, 0x46, "DSLINE") - -/* Similar, for bss segment. */ -__define_stab (N_BSLINE, 0x48, "BSLINE") - -/* Sun's source-code browser stabs. ?? Don't know what the fields are. - Supposedly the field is "path to associated .cb file". THIS VALUE - OVERLAPS WITH N_BSLINE! */ -__define_stab_duplicate (N_BROWS, 0x48, "BROWS") - -/* GNU Modula-2 definition module dependency. Value is the modification time - of the definition file. Other is non-zero if it is imported with the - GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there - are enough empty fields? */ -__define_stab(N_DEFD, 0x4a, "DEFD") - -/* New in Solaris2. Function start/body/end line numbers. */ -__define_stab(N_FLINE, 0x4C, "FLINE") - -/* THE FOLLOWING TWO STAB VALUES CONFLICT. Happily, one is for Modula-2 - and one is for C++. Still,... */ -/* GNU C++ exception variable. Name is variable name. */ -__define_stab (N_EHDECL, 0x50, "EHDECL") -/* Modula2 info "for imc": name,,0,0,0 according to Ultrix V4.0. */ -__define_stab_duplicate (N_MOD2, 0x50, "MOD2") - -/* GNU C++ `catch' clause. Value is its address. Desc is nonzero if - this entry is immediately followed by a CAUGHT stab saying what exception - was caught. Multiple CAUGHT stabs means that multiple exceptions - can be caught here. If Desc is 0, it means all exceptions are caught - here. */ -__define_stab (N_CATCH, 0x54, "CATCH") - -/* Structure or union element. Value is offset in the structure. */ -__define_stab (N_SSYM, 0x60, "SSYM") - -/* Solaris2: Last stab emitted for module. */ -__define_stab (N_ENDM, 0x62, "ENDM") - -/* Name of main source file. - Value is starting text address of the compilation. - If multiple N_SO's appear, the first to contain a trailing / is the - compilation directory. The first to not contain a trailing / is the - source file name, relative to the compilation directory. Others (perhaps - resulting from cfront) are ignored. - On Solaris2, value is undefined, but desc is a source-language code. */ - -__define_stab (N_SO, 0x64, "SO") - -/* Automatic variable in the stack. Value is offset from frame pointer. - Also used for type descriptions. */ -__define_stab (N_LSYM, 0x80, "LSYM") - -/* Beginning of an include file. Only Sun uses this. - In an object file, only the name is significant. - The Sun linker puts data into some of the other fields. */ -__define_stab (N_BINCL, 0x82, "BINCL") - -/* Name of sub-source file (#include file). - Value is starting text address of the compilation. */ -__define_stab (N_SOL, 0x84, "SOL") - -/* Parameter variable. Value is offset from argument pointer. - (On most machines the argument pointer is the same as the frame pointer. */ -__define_stab (N_PSYM, 0xa0, "PSYM") - -/* End of an include file. No name. - This and N_BINCL act as brackets around the file's output. - In an object file, there is no significant data in this entry. - The Sun linker puts data into some of the fields. */ -__define_stab (N_EINCL, 0xa2, "EINCL") - -/* Alternate entry point. Value is its address. */ -__define_stab (N_ENTRY, 0xa4, "ENTRY") - -/* Beginning of lexical block. - The desc is the nesting level in lexical blocks. - The value is the address of the start of the text for the block. - The variables declared inside the block *precede* the N_LBRAC symbol. - On Solaris2, the value is relative to the start of the current function. */ -__define_stab (N_LBRAC, 0xc0, "LBRAC") - -/* Place holder for deleted include file. Replaces a N_BINCL and everything - up to the corresponding N_EINCL. The Sun linker generates these when - it finds multiple identical copies of the symbols from an include file. - This appears only in output from the Sun linker. */ -__define_stab (N_EXCL, 0xc2, "EXCL") - -/* Modula-2 scope information. Can someone say what info it contains? */ -__define_stab (N_SCOPE, 0xc4, "SCOPE") - -/* End of a lexical block. Desc matches the N_LBRAC's desc. - The value is the address of the end of the text for the block. - On Solaris2, the value is relative to the start of the current function. */ -__define_stab (N_RBRAC, 0xe0, "RBRAC") - -/* Begin named common block. Only the name is significant. */ -__define_stab (N_BCOMM, 0xe2, "BCOMM") - -/* End named common block. Only the name is significant - (and it should match the N_BCOMM). */ -__define_stab (N_ECOMM, 0xe4, "ECOMM") - -/* Member of a common block; value is offset within the common block. - This should occur within a BCOMM/ECOMM pair. */ -__define_stab (N_ECOML, 0xe8, "ECOML") - -/* Solaris2: Pascal "with" statement: type,,0,0,offset */ -__define_stab (N_WITH, 0xea, "WITH") - -/* These STAB's are used on Gould systems for Non-Base register symbols - or something like that. FIXME. I have assigned the values at random - since I don't have a Gould here. Fixups from Gould folk welcome... */ -__define_stab (N_NBTEXT, 0xF0, "NBTEXT") -__define_stab (N_NBDATA, 0xF2, "NBDATA") -__define_stab (N_NBBSS, 0xF4, "NBBSS") -__define_stab (N_NBSTS, 0xF6, "NBSTS") -__define_stab (N_NBLCS, 0xF8, "NBLCS") - -/* Second symbol entry containing a length-value for the preceding entry. - The value is the length. */ -__define_stab (N_LENG, 0xfe, "LENG") - -/* The above information, in matrix format. - - STAB MATRIX - _________________________________________________ - | 00 - 1F are not dbx stab symbols | - | In most cases, the low bit is the EXTernal bit| - - | 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA | - | 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT | - - | 08 BSS | 0A INDR | 0C FN_SEQ | 0E WEAKA | - | 09 |EXT | 0B | 0D WEAKU | 0F WEAKT | - - | 10 WEAKD | 12 COMM | 14 SETA | 16 SETT | - | 11 WEAKB | 13 | 15 | 17 | - - | 18 SETD | 1A SETB | 1C SETV | 1E WARNING| - | 19 | 1B | 1D | 1F FN | - - |_______________________________________________| - | Debug entries with bit 01 set are unused. | - | 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM | - | 28 LCSYM | 2A MAIN | 2C ROSYM | 2E | - | 30 PC | 32 NSYMS | 34 NOMAP | 36 | - | 38 OBJ | 3A | 3C OPT | 3E | - | 40 RSYM | 42 M2C | 44 SLINE | 46 DSLINE | - | 48 BSLINE*| 4A DEFD | 4C FLINE | 4E | - | 50 EHDECL*| 52 | 54 CATCH | 56 | - | 58 | 5A | 5C | 5E | - | 60 SSYM | 62 ENDM | 64 SO | 66 | - | 68 | 6A | 6C | 6E | - | 70 | 72 | 74 | 76 | - | 78 | 7A | 7C | 7E | - | 80 LSYM | 82 BINCL | 84 SOL | 86 | - | 88 | 8A | 8C | 8E | - | 90 | 92 | 94 | 96 | - | 98 | 9A | 9C | 9E | - | A0 PSYM | A2 EINCL | A4 ENTRY | A6 | - | A8 | AA | AC | AE | - | B0 | B2 | B4 | B6 | - | B8 | BA | BC | BE | - | C0 LBRAC | C2 EXCL | C4 SCOPE | C6 | - | C8 | CA | CC | CE | - | D0 | D2 | D4 | D6 | - | D8 | DA | DC | DE | - | E0 RBRAC | E2 BCOMM | E4 ECOMM | E6 | - | E8 ECOML | EA WITH | EC | EE | - | F0 | F2 | F4 | F6 | - | F8 | FA | FC | FE LENG | - +-----------------------------------------------+ - * 50 EHDECL is also MOD2. - * 48 BSLINE is also BROWS. - */ diff --git a/pstack/aout/stab_gnu.h b/pstack/aout/stab_gnu.h deleted file mode 100644 index 7d18e14a263..00000000000 --- a/pstack/aout/stab_gnu.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef __GNU_STAB__ - -/* Indicate the GNU stab.h is in use. */ - -#define __GNU_STAB__ - -#define __define_stab(NAME, CODE, STRING) NAME=CODE, -#define __define_stab_duplicate(NAME, CODE, STRING) NAME=CODE, - -enum __stab_debug_code -{ -#include "aout/stab.def" -LAST_UNUSED_STAB_CODE -}; - -#undef __define_stab - -/* Definitions of "desc" field for N_SO stabs in Solaris2. */ - -#define N_SO_AS 1 -#define N_SO_C 2 -#define N_SO_ANSI_C 3 -#define N_SO_CC 4 /* C++ */ -#define N_SO_FORTRAN 5 -#define N_SO_PASCAL 6 - -/* Solaris2: Floating point type values in basic types. */ - -#define NF_NONE 0 -#define NF_SINGLE 1 /* IEEE 32-bit */ -#define NF_DOUBLE 2 /* IEEE 64-bit */ -#define NF_COMPLEX 3 /* Fortran complex */ -#define NF_COMPLEX16 4 /* Fortran double complex */ -#define NF_COMPLEX32 5 /* Fortran complex*16 */ -#define NF_LDOUBLE 6 /* Long double (whatever that is) */ - -#endif /* __GNU_STAB_ */ diff --git a/pstack/bucomm.c b/pstack/bucomm.c deleted file mode 100644 index d3231e71747..00000000000 --- a/pstack/bucomm.c +++ /dev/null @@ -1,238 +0,0 @@ -/* bucomm.c -- Bin Utils COMmon code. - Copyright (C) 1991, 92, 93, 94, 95, 1997 Free Software Foundation, Inc. - - This file is part of GNU Binutils. - - 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. */ - -/* We might put this in a library someday so it could be dynamically - loaded, but for now it's not necessary. */ - -#include <bfd.h> -#include <libiberty.h> -#include "bucomm.h" - -#include <sys/stat.h> -#include <time.h> /* ctime, maybe time_t */ - -#ifdef ANSI_PROTOTYPES -#include <stdarg.h> -#else -#include <varargs.h> -#endif - -/* Error reporting */ - -char *program_name; - -void -bfd_nonfatal (string) - CONST char *string; -{ - CONST char *errmsg = bfd_errmsg (bfd_get_error ()); - - if (string) - fprintf (stderr, "%s: %s: %s\n", program_name, string, errmsg); - else - fprintf (stderr, "%s: %s\n", program_name, errmsg); -} - -void -bfd_fatal (string) - CONST char *string; -{ - bfd_nonfatal (string); - xexit (1); -} - -#ifdef ANSI_PROTOTYPES -void -fatal (const char *format, ...) -{ - va_list args; - - fprintf (stderr, "%s: ", program_name); - va_start (args, format); - vfprintf (stderr, format, args); - va_end (args); - putc ('\n', stderr); - xexit (1); -} -#else -void -fatal (va_alist) - va_dcl -{ - char *Format; - va_list args; - - fprintf (stderr, "%s: ", program_name); - va_start (args); - Format = va_arg (args, char *); - vfprintf (stderr, Format, args); - va_end (args); - putc ('\n', stderr); - xexit (1); -} -#endif - -/* Set the default BFD target based on the configured target. Doing - this permits the binutils to be configured for a particular target, - and linked against a shared BFD library which was configured for a - different target. */ - -#define TARGET "elf32-i386" /* FIXME: hard-coded! */ -void -set_default_bfd_target () -{ - /* The macro TARGET is defined by Makefile. */ - const char *target = TARGET; - - if (! bfd_set_default_target (target)) - { - char *errmsg; - - errmsg = (char *) xmalloc (100 + strlen (target)); - sprintf (errmsg, "can't set BFD default target to `%s'", target); - bfd_fatal (errmsg); - } -} - -/* After a false return from bfd_check_format_matches with - bfd_get_error () == bfd_error_file_ambiguously_recognized, print - the possible matching targets. */ - -void -list_matching_formats (p) - char **p; -{ - fprintf(stderr, "%s: Matching formats:", program_name); - while (*p) - fprintf(stderr, " %s", *p++); - fprintf(stderr, "\n"); -} - -/* List the supported targets. */ - -void -list_supported_targets (name, f) - const char *name; - FILE *f; -{ - extern bfd_target *bfd_target_vector[]; - int t; - - if (name == NULL) - fprintf (f, "Supported targets:"); - else - fprintf (f, "%s: supported targets:", name); - for (t = 0; bfd_target_vector[t] != NULL; t++) - fprintf (f, " %s", bfd_target_vector[t]->name); - fprintf (f, "\n"); -} - -/* Display the archive header for an element as if it were an ls -l listing: - - Mode User\tGroup\tSize\tDate Name */ - -void -print_arelt_descr (file, abfd, verbose) - FILE *file; - bfd *abfd; - boolean verbose; -{ - struct stat buf; - - if (verbose) - { - if (bfd_stat_arch_elt (abfd, &buf) == 0) - { - char modebuf[11]; - char timebuf[40]; - time_t when = buf.st_mtime; - CONST char *ctime_result = (CONST char *) ctime (&when); - - /* POSIX format: skip weekday and seconds from ctime output. */ - sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20); - - mode_string (buf.st_mode, modebuf); - modebuf[10] = '\0'; - /* POSIX 1003.2/D11 says to skip first character (entry type). */ - fprintf (file, "%s %ld/%ld %6ld %s ", modebuf + 1, - (long) buf.st_uid, (long) buf.st_gid, - (long) buf.st_size, timebuf); - } - } - - fprintf (file, "%s\n", bfd_get_filename (abfd)); -} - -/* Return the name of a temporary file in the same directory as FILENAME. */ - -char * -make_tempname (filename) - char *filename; -{ - static char template[] = "stXXXXXX"; - char *tmpname; - char *slash = strrchr (filename, '/'); - -#if defined (__DJGPP__) || defined (__GO32__) || defined (_WIN32) - if (slash == NULL) - slash = strrchr (filename, '\\'); -#endif - - if (slash != (char *) NULL) - { - char c; - - c = *slash; - *slash = 0; - tmpname = xmalloc (strlen (filename) + sizeof (template) + 1); - strcpy (tmpname, filename); - strcat (tmpname, "/"); - strcat (tmpname, template); - mkstemp (tmpname); - *slash = c; - } - else - { - tmpname = xmalloc (sizeof (template)); - strcpy (tmpname, template); - mkstemp (tmpname); - } - return tmpname; -} - -/* Parse a string into a VMA, with a fatal error if it can't be - parsed. */ - -bfd_vma -parse_vma (s, arg) - const char *s; - const char *arg; -{ - bfd_vma ret; - const char *end; - - ret = bfd_scan_vma (s, &end, 0); - if (*end != '\0') - { - fprintf (stderr, "%s: %s: bad number: %s\n", program_name, arg, s); - exit (1); - } - return ret; -} diff --git a/pstack/bucomm.h b/pstack/bucomm.h deleted file mode 100644 index 6b3633d8d63..00000000000 --- a/pstack/bucomm.h +++ /dev/null @@ -1,91 +0,0 @@ -/* bucomm.h -- binutils common include file. - Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. - -This file is part of GNU Binutils. - -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. */ - -#ifndef _BUCOMM_H -#define _BUCOMM_H - -#include "ansidecl.h" -#include <stdio.h> -#include <sys/types.h> - -#include <errno.h> -#include <unistd.h> - -#include <string.h> - -#include <stdlib.h> - -#include <fcntl.h> - -#ifdef __GNUC__ -# undef alloca -# define alloca __builtin_alloca -#else -# if HAVE_ALLOCA_H -# include <alloca.h> -# else -# ifndef alloca /* predefined by HP cc +Olibcalls */ -# if !defined (__STDC__) && !defined (__hpux) -char *alloca (); -# else -void *alloca (); -# endif /* __STDC__, __hpux */ -# endif /* alloca */ -# endif /* HAVE_ALLOCA_H */ -#endif - -#ifndef BFD_TRUE_FALSE -#define boolean bfd_boolean -#define true TRUE -#define false FALSE -#endif - -/* bucomm.c */ -void bfd_nonfatal PARAMS ((CONST char *)); - -void bfd_fatal PARAMS ((CONST char *)); - -void fatal PARAMS ((CONST char *, ...)); - -void set_default_bfd_target PARAMS ((void)); - -void list_matching_formats PARAMS ((char **p)); - -void list_supported_targets PARAMS ((const char *, FILE *)); - -void print_arelt_descr PARAMS ((FILE *file, bfd *abfd, boolean verbose)); - -char *make_tempname PARAMS ((char *)); - -bfd_vma parse_vma PARAMS ((const char *, const char *)); - -extern char *program_name; - -/* filemode.c */ -void mode_string PARAMS ((unsigned long mode, char *buf)); - -/* version.c */ -extern void print_version PARAMS ((const char *)); - -/* libiberty */ -PTR xmalloc PARAMS ((size_t)); - -PTR xrealloc PARAMS ((PTR, size_t)); - -#endif /* _BUCOMM_H */ diff --git a/pstack/budbg.h b/pstack/budbg.h deleted file mode 100644 index 9f0203ad5e7..00000000000 --- a/pstack/budbg.h +++ /dev/null @@ -1,64 +0,0 @@ -/* budbg.c -- Interfaces to the generic debugging information routines. - Copyright (C) 1995, 1996 Free Software Foundation, Inc. - Written by Ian Lance Taylor <ian@cygnus.com>. - - This file is part of GNU Binutils. - - 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. */ - -#ifndef BUDBG_H -#define BUDBG_H - -#include <stdio.h> - -#ifndef BFD_TRUE_FALSE -#define boolean bfd_boolean -#define true TRUE -#define false FALSE -#endif - -/* Routine used to read generic debugging information. */ - -extern PTR read_debugging_info PARAMS ((bfd *, asymbol **, long)); - -/* Routine used to print generic debugging information. */ - -extern boolean print_debugging_info PARAMS ((FILE *, PTR)); - -/* Routines used to read and write stabs information. */ - -extern PTR start_stab PARAMS ((PTR, bfd *, boolean, asymbol **, long)); - -extern boolean finish_stab PARAMS ((PTR, PTR)); - -extern boolean parse_stab PARAMS ((PTR, PTR, int, int, bfd_vma, const char *)); - -extern boolean write_stabs_in_sections_debugging_info - PARAMS ((bfd *, PTR, bfd_byte **, bfd_size_type *, bfd_byte **, - bfd_size_type *)); - -/* Routines used to read and write IEEE debugging information. */ - -extern boolean parse_ieee - PARAMS ((PTR, bfd *, const bfd_byte *, bfd_size_type)); - -extern boolean write_ieee_debugging_info PARAMS ((bfd *, PTR)); - -/* Routine used to read COFF debugging information. */ - -extern boolean parse_coff PARAMS ((bfd *, asymbol **, long, PTR)); - -#endif diff --git a/pstack/debug.c b/pstack/debug.c deleted file mode 100644 index 73412ae3f03..00000000000 --- a/pstack/debug.c +++ /dev/null @@ -1,3509 +0,0 @@ -/* debug.c -- Handle generic debugging information. - Copyright (C) 1995, 1996 Free Software Foundation, Inc. - Written by Ian Lance Taylor <ian@cygnus.com>. - - This file is part of GNU Binutils. - - 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. */ - -/* This file implements a generic debugging format. We may eventually - have readers which convert different formats into this generic - format, and writers which write it out. The initial impetus for - this was writing a convertor from stabs to HP IEEE-695 debugging - format. */ - -#include <stdio.h> -#include <assert.h> - -#include <bfd.h> -#include "bucomm.h" -#include <libiberty.h> -#include "debug.h" - -/* Global information we keep for debugging. A pointer to this - structure is the debugging handle passed to all the routines. */ - -struct debug_handle -{ - /* A linked list of compilation units. */ - struct debug_unit *units; - /* The current compilation unit. */ - struct debug_unit *current_unit; - /* The current source file. */ - struct debug_file *current_file; - /* The current function. */ - struct debug_function *current_function; - /* The current block. */ - struct debug_block *current_block; - /* The current line number information for the current unit. */ - struct debug_lineno *current_lineno; - /* Mark. This is used by debug_write. */ - unsigned int mark; - /* A struct/class ID used by debug_write. */ - unsigned int class_id; - /* The base for class_id for this call to debug_write. */ - unsigned int base_id; - /* The current line number in debug_write. */ - struct debug_lineno *current_write_lineno; - unsigned int current_write_lineno_index; - /* A list of classes which have assigned ID's during debug_write. - This is linked through the next_id field of debug_class_type. */ - struct debug_class_id *id_list; - /* A list used to avoid recursion during debug_type_samep. */ - struct debug_type_compare_list *compare_list; -}; - -/* Information we keep for a single compilation unit. */ - -struct debug_unit -{ - /* The next compilation unit. */ - struct debug_unit *next; - /* A list of files included in this compilation unit. The first - file is always the main one, and that is where the main file name - is stored. */ - struct debug_file *files; - /* Line number information for this compilation unit. This is not - stored by function, because assembler code may have line number - information without function information. */ - struct debug_lineno *linenos; -}; - -/* Information kept for a single source file. */ - -struct debug_file -{ - /* The next source file in this compilation unit. */ - struct debug_file *next; - /* The name of the source file. */ - const char *filename; - /* Global functions, variables, types, etc. */ - struct debug_namespace *globals; -}; - -/* A type. */ - -struct debug_type -{ - /* Kind of type. */ - enum debug_type_kind kind; - /* Size of type (0 if not known). */ - unsigned int size; - /* Type which is a pointer to this type. */ - debug_type pointer; - /* Tagged union with additional information about the type. */ - union - { - /* DEBUG_KIND_INDIRECT. */ - struct debug_indirect_type *kindirect; - /* DEBUG_KIND_INT. */ - /* Whether the integer is unsigned. */ - boolean kint; - /* DEBUG_KIND_STRUCT, DEBUG_KIND_UNION, DEBUG_KIND_CLASS, - DEBUG_KIND_UNION_CLASS. */ - struct debug_class_type *kclass; - /* DEBUG_KIND_ENUM. */ - struct debug_enum_type *kenum; - /* DEBUG_KIND_POINTER. */ - struct debug_type *kpointer; - /* DEBUG_KIND_FUNCTION. */ - struct debug_function_type *kfunction; - /* DEBUG_KIND_REFERENCE. */ - struct debug_type *kreference; - /* DEBUG_KIND_RANGE. */ - struct debug_range_type *krange; - /* DEBUG_KIND_ARRAY. */ - struct debug_array_type *karray; - /* DEBUG_KIND_SET. */ - struct debug_set_type *kset; - /* DEBUG_KIND_OFFSET. */ - struct debug_offset_type *koffset; - /* DEBUG_KIND_METHOD. */ - struct debug_method_type *kmethod; - /* DEBUG_KIND_CONST. */ - struct debug_type *kconst; - /* DEBUG_KIND_VOLATILE. */ - struct debug_type *kvolatile; - /* DEBUG_KIND_NAMED, DEBUG_KIND_TAGGED. */ - struct debug_named_type *knamed; - } u; -}; - -/* Information kept for an indirect type. */ - -struct debug_indirect_type -{ - /* Slot where the final type will appear. */ - debug_type *slot; - /* Tag. */ - const char *tag; -}; - -/* Information kept for a struct, union, or class. */ - -struct debug_class_type -{ - /* NULL terminated array of fields. */ - debug_field *fields; - /* A mark field which indicates whether the struct has already been - printed. */ - unsigned int mark; - /* This is used to uniquely identify unnamed structs when printing. */ - unsigned int id; - /* The remaining fields are only used for DEBUG_KIND_CLASS and - DEBUG_KIND_UNION_CLASS. */ - /* NULL terminated array of base classes. */ - debug_baseclass *baseclasses; - /* NULL terminated array of methods. */ - debug_method *methods; - /* The type of the class providing the virtual function table for - this class. This may point to the type itself. */ - debug_type vptrbase; -}; - -/* Information kept for an enum. */ - -struct debug_enum_type -{ - /* NULL terminated array of names. */ - const char **names; - /* Array of corresponding values. */ - bfd_signed_vma *values; -}; - -/* Information kept for a function. FIXME: We should be able to - record the parameter types. */ - -struct debug_function_type -{ - /* Return type. */ - debug_type return_type; - /* NULL terminated array of argument types. */ - debug_type *arg_types; - /* Whether the function takes a variable number of arguments. */ - boolean varargs; -}; - -/* Information kept for a range. */ - -struct debug_range_type -{ - /* Range base type. */ - debug_type type; - /* Lower bound. */ - bfd_signed_vma lower; - /* Upper bound. */ - bfd_signed_vma upper; -}; - -/* Information kept for an array. */ - -struct debug_array_type -{ - /* Element type. */ - debug_type element_type; - /* Range type. */ - debug_type range_type; - /* Lower bound. */ - bfd_signed_vma lower; - /* Upper bound. */ - bfd_signed_vma upper; - /* Whether this array is really a string. */ - boolean stringp; -}; - -/* Information kept for a set. */ - -struct debug_set_type -{ - /* Base type. */ - debug_type type; - /* Whether this set is really a bitstring. */ - boolean bitstringp; -}; - -/* Information kept for an offset type (a based pointer). */ - -struct debug_offset_type -{ - /* The type the pointer is an offset from. */ - debug_type base_type; - /* The type the pointer points to. */ - debug_type target_type; -}; - -/* Information kept for a method type. */ - -struct debug_method_type -{ - /* The return type. */ - debug_type return_type; - /* The object type which this method is for. */ - debug_type domain_type; - /* A NULL terminated array of argument types. */ - debug_type *arg_types; - /* Whether the method takes a variable number of arguments. */ - boolean varargs; -}; - -/* Information kept for a named type. */ - -struct debug_named_type -{ - /* Name. */ - struct debug_name *name; - /* Real type. */ - debug_type type; -}; - -/* A field in a struct or union. */ - -struct debug_field -{ - /* Name of the field. */ - const char *name; - /* Type of the field. */ - struct debug_type *type; - /* Visibility of the field. */ - enum debug_visibility visibility; - /* Whether this is a static member. */ - boolean static_member; - union - { - /* If static_member is false. */ - struct - { - /* Bit position of the field in the struct. */ - unsigned int bitpos; - /* Size of the field in bits. */ - unsigned int bitsize; - } f; - /* If static_member is true. */ - struct - { - const char *physname; - } s; - } u; -}; - -/* A base class for an object. */ - -struct debug_baseclass -{ - /* Type of the base class. */ - struct debug_type *type; - /* Bit position of the base class in the object. */ - unsigned int bitpos; - /* Whether the base class is virtual. */ - boolean virtual; - /* Visibility of the base class. */ - enum debug_visibility visibility; -}; - -/* A method of an object. */ - -struct debug_method -{ - /* The name of the method. */ - const char *name; - /* A NULL terminated array of different types of variants. */ - struct debug_method_variant **variants; -}; - -/* The variants of a method function of an object. These indicate - which method to run. */ - -struct debug_method_variant -{ - /* The physical name of the function. */ - const char *physname; - /* The type of the function. */ - struct debug_type *type; - /* The visibility of the function. */ - enum debug_visibility visibility; - /* Whether the function is const. */ - boolean constp; - /* Whether the function is volatile. */ - boolean volatilep; - /* The offset to the function in the virtual function table. */ - bfd_vma voffset; - /* If voffset is VOFFSET_STATIC_METHOD, this is a static method. */ -#define VOFFSET_STATIC_METHOD ((bfd_vma) -1) - /* Context of a virtual method function. */ - struct debug_type *context; -}; - -/* A variable. This is the information we keep for a variable object. - This has no name; a name is associated with a variable in a - debug_name structure. */ - -struct debug_variable -{ - /* Kind of variable. */ - enum debug_var_kind kind; - /* Type. */ - debug_type type; - /* Value. The interpretation of the value depends upon kind. */ - bfd_vma val; -}; - -/* A function. This has no name; a name is associated with a function - in a debug_name structure. */ - -struct debug_function -{ - /* Return type. */ - debug_type return_type; - /* Parameter information. */ - struct debug_parameter *parameters; - /* Block information. The first structure on the list is the main - block of the function, and describes function local variables. */ - struct debug_block *blocks; -}; - -/* A function parameter. */ - -struct debug_parameter -{ - /* Next parameter. */ - struct debug_parameter *next; - /* Name. */ - const char *name; - /* Type. */ - debug_type type; - /* Kind. */ - enum debug_parm_kind kind; - /* Value (meaning depends upon kind). */ - bfd_vma val; -}; - -/* A typed constant. */ - -struct debug_typed_constant -{ - /* Type. */ - debug_type type; - /* Value. FIXME: We may eventually need to support non-integral - values. */ - bfd_vma val; -}; - -/* Information about a block within a function. */ - -struct debug_block -{ - /* Next block with the same parent. */ - struct debug_block *next; - /* Parent block. */ - struct debug_block *parent; - /* List of child blocks. */ - struct debug_block *children; - /* Start address of the block. */ - bfd_vma start; - /* End address of the block. */ - bfd_vma end; - /* Local variables. */ - struct debug_namespace *locals; -}; - -/* Line number information we keep for a compilation unit. FIXME: - This structure is easy to create, but can be very space - inefficient. */ - -struct debug_lineno -{ - /* More line number information for this block. */ - struct debug_lineno *next; - /* Source file. */ - struct debug_file *file; - /* Line numbers, terminated by a -1 or the end of the array. */ -#define DEBUG_LINENO_COUNT 10 - unsigned long linenos[DEBUG_LINENO_COUNT]; - /* Addresses for the line numbers. */ - bfd_vma addrs[DEBUG_LINENO_COUNT]; -}; - -/* A namespace. This is a mapping from names to objects. FIXME: This - should be implemented as a hash table. */ - -struct debug_namespace -{ - /* List of items in this namespace. */ - struct debug_name *list; - /* Pointer to where the next item in this namespace should go. */ - struct debug_name **tail; -}; - -/* Kinds of objects that appear in a namespace. */ - -enum debug_object_kind -{ - /* A type. */ - DEBUG_OBJECT_TYPE, - /* A tagged type (really a different sort of namespace). */ - DEBUG_OBJECT_TAG, - /* A variable. */ - DEBUG_OBJECT_VARIABLE, - /* A function. */ - DEBUG_OBJECT_FUNCTION, - /* An integer constant. */ - DEBUG_OBJECT_INT_CONSTANT, - /* A floating point constant. */ - DEBUG_OBJECT_FLOAT_CONSTANT, - /* A typed constant. */ - DEBUG_OBJECT_TYPED_CONSTANT -}; - -/* Linkage of an object that appears in a namespace. */ - -enum debug_object_linkage -{ - /* Local variable. */ - DEBUG_LINKAGE_AUTOMATIC, - /* Static--either file static or function static, depending upon the - namespace is. */ - DEBUG_LINKAGE_STATIC, - /* Global. */ - DEBUG_LINKAGE_GLOBAL, - /* No linkage. */ - DEBUG_LINKAGE_NONE -}; - -/* A name in a namespace. */ - -struct debug_name -{ - /* Next name in this namespace. */ - struct debug_name *next; - /* Name. */ - const char *name; - /* Mark. This is used by debug_write. */ - unsigned int mark; - /* Kind of object. */ - enum debug_object_kind kind; - /* Linkage of object. */ - enum debug_object_linkage linkage; - /* Tagged union with additional information about the object. */ - union - { - /* DEBUG_OBJECT_TYPE. */ - struct debug_type *type; - /* DEBUG_OBJECT_TAG. */ - struct debug_type *tag; - /* DEBUG_OBJECT_VARIABLE. */ - struct debug_variable *variable; - /* DEBUG_OBJECT_FUNCTION. */ - struct debug_function *function; - /* DEBUG_OBJECT_INT_CONSTANT. */ - bfd_vma int_constant; - /* DEBUG_OBJECT_FLOAT_CONSTANT. */ - double float_constant; - /* DEBUG_OBJECT_TYPED_CONSTANT. */ - struct debug_typed_constant *typed_constant; - } u; -}; - -/* During debug_write, a linked list of these structures is used to - keep track of ID numbers that have been assigned to classes. */ - -struct debug_class_id -{ - /* Next ID number. */ - struct debug_class_id *next; - /* The type with the ID. */ - struct debug_type *type; - /* The tag; NULL if no tag. */ - const char *tag; -}; - -/* During debug_type_samep, a linked list of these structures is kept - on the stack to avoid infinite recursion. */ - -struct debug_type_compare_list -{ - /* Next type on list. */ - struct debug_type_compare_list *next; - /* The types we are comparing. */ - struct debug_type *t1; - struct debug_type *t2; -}; - -/* Local functions. */ - -static void debug_error PARAMS ((const char *)); -static struct debug_name *debug_add_to_namespace - PARAMS ((struct debug_handle *, struct debug_namespace **, const char *, - enum debug_object_kind, enum debug_object_linkage)); -static struct debug_name *debug_add_to_current_namespace - PARAMS ((struct debug_handle *, const char *, enum debug_object_kind, - enum debug_object_linkage)); -static struct debug_type *debug_make_type - PARAMS ((struct debug_handle *, enum debug_type_kind, unsigned int)); -static struct debug_type *debug_get_real_type PARAMS ((PTR, debug_type)); -static boolean debug_write_name - PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR, - struct debug_name *)); -static boolean debug_write_type - PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR, - struct debug_type *, struct debug_name *)); -static boolean debug_write_class_type - PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR, - struct debug_type *, const char *)); -static boolean debug_write_function - PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR, - const char *, enum debug_object_linkage, struct debug_function *)); -static boolean debug_write_block - PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR, - struct debug_block *)); -static boolean debug_write_linenos - PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR, - bfd_vma)); -static boolean debug_set_class_id - PARAMS ((struct debug_handle *, const char *, struct debug_type *)); -static boolean debug_type_samep - PARAMS ((struct debug_handle *, struct debug_type *, struct debug_type *)); -static boolean debug_class_type_samep - PARAMS ((struct debug_handle *, struct debug_type *, struct debug_type *)); - -/* Issue an error message. */ - -static void -debug_error (message) - const char *message; -{ - fprintf (stderr, "%s\n", message); -} - -/* Add an object to a namespace. */ - -static struct debug_name * -debug_add_to_namespace (info, nsp, name, kind, linkage) - struct debug_handle *info; - struct debug_namespace **nsp; - const char *name; - enum debug_object_kind kind; - enum debug_object_linkage linkage; -{ - struct debug_name *n; - struct debug_namespace *ns; - - n = (struct debug_name *) xmalloc (sizeof *n); - memset (n, 0, sizeof *n); - - n->name = name; - n->kind = kind; - n->linkage = linkage; - - ns = *nsp; - if (ns == NULL) - { - ns = (struct debug_namespace *) xmalloc (sizeof *ns); - memset (ns, 0, sizeof *ns); - - ns->tail = &ns->list; - - *nsp = ns; - } - - *ns->tail = n; - ns->tail = &n->next; - - return n; -} - -/* Add an object to the current namespace. */ - -static struct debug_name * -debug_add_to_current_namespace (info, name, kind, linkage) - struct debug_handle *info; - const char *name; - enum debug_object_kind kind; - enum debug_object_linkage linkage; -{ - struct debug_namespace **nsp; - - if (info->current_unit == NULL - || info->current_file == NULL) - { - debug_error ("debug_add_to_current_namespace: no current file"); - return NULL; - } - - if (info->current_block != NULL) - nsp = &info->current_block->locals; - else - nsp = &info->current_file->globals; - - return debug_add_to_namespace (info, nsp, name, kind, linkage); -} - -/* Return a handle for debugging information. */ - -PTR -debug_init () -{ - struct debug_handle *ret; - - ret = (struct debug_handle *) xmalloc (sizeof *ret); - memset (ret, 0, sizeof *ret); - return (PTR) ret; -} - -/* Set the source filename. This implicitly starts a new compilation - unit. */ - -boolean -debug_set_filename (handle, name) - PTR handle; - const char *name; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_file *nfile; - struct debug_unit *nunit; - - if (name == NULL) - name = ""; - - nfile = (struct debug_file *) xmalloc (sizeof *nfile); - memset (nfile, 0, sizeof *nfile); - - nfile->filename = name; - - nunit = (struct debug_unit *) xmalloc (sizeof *nunit); - memset (nunit, 0, sizeof *nunit); - - nunit->files = nfile; - info->current_file = nfile; - - if (info->current_unit != NULL) - info->current_unit->next = nunit; - else - { - assert (info->units == NULL); - info->units = nunit; - } - - info->current_unit = nunit; - - info->current_function = NULL; - info->current_block = NULL; - info->current_lineno = NULL; - - return true; -} - -/* Change source files to the given file name. This is used for - include files in a single compilation unit. */ - -boolean -debug_start_source (handle, name) - PTR handle; - const char *name; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_file *f, **pf; - - if (name == NULL) - name = ""; - - if (info->current_unit == NULL) - { - debug_error ("debug_start_source: no debug_set_filename call"); - return false; - } - - for (f = info->current_unit->files; f != NULL; f = f->next) - { - if (f->filename[0] == name[0] - && f->filename[1] == name[1] - && strcmp (f->filename, name) == 0) - { - info->current_file = f; - return true; - } - } - - f = (struct debug_file *) xmalloc (sizeof *f); - memset (f, 0, sizeof *f); - - f->filename = name; - - for (pf = &info->current_file->next; - *pf != NULL; - pf = &(*pf)->next) - ; - *pf = f; - - info->current_file = f; - - return true; -} - -/* Record a function definition. This implicitly starts a function - block. The debug_type argument is the type of the return value. - The boolean indicates whether the function is globally visible. - The bfd_vma is the address of the start of the function. Currently - the parameter types are specified by calls to - debug_record_parameter. FIXME: There is no way to specify nested - functions. */ - -boolean -debug_record_function (handle, name, return_type, global, addr) - PTR handle; - const char *name; - debug_type return_type; - boolean global; - bfd_vma addr; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_function *f; - struct debug_block *b; - struct debug_name *n; - - if (name == NULL) - name = ""; - if (return_type == NULL) - return false; - - if (info->current_unit == NULL) - { - debug_error ("debug_record_function: no debug_set_filename call"); - return false; - } - - f = (struct debug_function *) xmalloc (sizeof *f); - memset (f, 0, sizeof *f); - - f->return_type = return_type; - - b = (struct debug_block *) xmalloc (sizeof *b); - memset (b, 0, sizeof *b); - - b->start = addr; - b->end = (bfd_vma) -1; - - f->blocks = b; - - info->current_function = f; - info->current_block = b; - - /* FIXME: If we could handle nested functions, this would be the - place: we would want to use a different namespace. */ - n = debug_add_to_namespace (info, - &info->current_file->globals, - name, - DEBUG_OBJECT_FUNCTION, - (global - ? DEBUG_LINKAGE_GLOBAL - : DEBUG_LINKAGE_STATIC)); - if (n == NULL) - return false; - - n->u.function = f; - - return true; -} - -/* Record a parameter for the current function. */ - -boolean -debug_record_parameter (handle, name, type, kind, val) - PTR handle; - const char *name; - debug_type type; - enum debug_parm_kind kind; - bfd_vma val; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_parameter *p, **pp; - - if (name == NULL || type == NULL) - return false; - - if (info->current_unit == NULL - || info->current_function == NULL) - { - debug_error ("debug_record_parameter: no current function"); - return false; - } - - p = (struct debug_parameter *) xmalloc (sizeof *p); - memset (p, 0, sizeof *p); - - p->name = name; - p->type = type; - p->kind = kind; - p->val = val; - - for (pp = &info->current_function->parameters; - *pp != NULL; - pp = &(*pp)->next) - ; - *pp = p; - - return true; -} - -/* End a function. FIXME: This should handle function nesting. */ - -boolean -debug_end_function (handle, addr) - PTR handle; - bfd_vma addr; -{ - struct debug_handle *info = (struct debug_handle *) handle; - - if (info->current_unit == NULL - || info->current_block == NULL - || info->current_function == NULL) - { - debug_error ("debug_end_function: no current function"); - return false; - } - - if (info->current_block->parent != NULL) - { - debug_error ("debug_end_function: some blocks were not closed"); - return false; - } - - info->current_block->end = addr; - - info->current_function = NULL; - info->current_block = NULL; - - return true; -} - -/* Start a block in a function. All local information will be - recorded in this block, until the matching call to debug_end_block. - debug_start_block and debug_end_block may be nested. The bfd_vma - argument is the address at which this block starts. */ - -boolean -debug_start_block (handle, addr) - PTR handle; - bfd_vma addr; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_block *b, **pb; - - /* We must always have a current block: debug_record_function sets - one up. */ - if (info->current_unit == NULL - || info->current_block == NULL) - { - debug_error ("debug_start_block: no current block"); - return false; - } - - b = (struct debug_block *) xmalloc (sizeof *b); - memset (b, 0, sizeof *b); - - b->parent = info->current_block; - b->start = addr; - b->end = (bfd_vma) -1; - - /* This new block is a child of the current block. */ - for (pb = &info->current_block->children; - *pb != NULL; - pb = &(*pb)->next) - ; - *pb = b; - - info->current_block = b; - - return true; -} - -/* Finish a block in a function. This matches the call to - debug_start_block. The argument is the address at which this block - ends. */ - -boolean -debug_end_block (handle, addr) - PTR handle; - bfd_vma addr; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_block *parent; - - if (info->current_unit == NULL - || info->current_block == NULL) - { - debug_error ("debug_end_block: no current block"); - return false; - } - - parent = info->current_block->parent; - if (parent == NULL) - { - debug_error ("debug_end_block: attempt to close top level block"); - return false; - } - - info->current_block->end = addr; - - info->current_block = parent; - - return true; -} - -/* Associate a line number in the current source file and function - with a given address. */ - -boolean -debug_record_line (handle, lineno, addr) - PTR handle; - unsigned long lineno; - bfd_vma addr; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_lineno *l; - unsigned int i; - - if (info->current_unit == NULL) - { - debug_error ("debug_record_line: no current unit"); - return false; - } - - l = info->current_lineno; - if (l != NULL && l->file == info->current_file) - { - for (i = 0; i < DEBUG_LINENO_COUNT; i++) - { - if (l->linenos[i] == (unsigned long) -1) - { - l->linenos[i] = lineno; - l->addrs[i] = addr; - return true; - } - } - } - - /* If we get here, then either 1) there is no current_lineno - structure, which means this is the first line number in this - compilation unit, 2) the current_lineno structure is for a - different file, or 3) the current_lineno structure is full. - Regardless, we want to allocate a new debug_lineno structure, put - it in the right place, and make it the new current_lineno - structure. */ - - l = (struct debug_lineno *) xmalloc (sizeof *l); - memset (l, 0, sizeof *l); - - l->file = info->current_file; - l->linenos[0] = lineno; - l->addrs[0] = addr; - for (i = 1; i < DEBUG_LINENO_COUNT; i++) - l->linenos[i] = (unsigned long) -1; - - if (info->current_lineno != NULL) - info->current_lineno->next = l; - else - info->current_unit->linenos = l; - - info->current_lineno = l; - - return true; -} - -/* Start a named common block. This is a block of variables that may - move in memory. */ - -boolean -debug_start_common_block (handle, name) - PTR handle; - const char *name; -{ - /* FIXME */ - debug_error ("debug_start_common_block: not implemented"); - return false; -} - -/* End a named common block. */ - -boolean -debug_end_common_block (handle, name) - PTR handle; - const char *name; -{ - /* FIXME */ - debug_error ("debug_end_common_block: not implemented"); - return false; -} - -/* Record a named integer constant. */ - -boolean -debug_record_int_const (handle, name, val) - PTR handle; - const char *name; - bfd_vma val; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_name *n; - - if (name == NULL) - return false; - - n = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_INT_CONSTANT, - DEBUG_LINKAGE_NONE); - if (n == NULL) - return false; - - n->u.int_constant = val; - - return true; -} - -/* Record a named floating point constant. */ - -boolean -debug_record_float_const (handle, name, val) - PTR handle; - const char *name; - double val; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_name *n; - - if (name == NULL) - return false; - - n = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_FLOAT_CONSTANT, - DEBUG_LINKAGE_NONE); - if (n == NULL) - return false; - - n->u.float_constant = val; - - return true; -} - -/* Record a typed constant with an integral value. */ - -boolean -debug_record_typed_const (handle, name, type, val) - PTR handle; - const char *name; - debug_type type; - bfd_vma val; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_name *n; - struct debug_typed_constant *tc; - - if (name == NULL || type == NULL) - return false; - - n = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_TYPED_CONSTANT, - DEBUG_LINKAGE_NONE); - if (n == NULL) - return false; - - tc = (struct debug_typed_constant *) xmalloc (sizeof *tc); - memset (tc, 0, sizeof *tc); - - tc->type = type; - tc->val = val; - - n->u.typed_constant = tc; - - return true; -} - -/* Record a label. */ - -boolean -debug_record_label (handle, name, type, addr) - PTR handle; - const char *name; - debug_type type; - bfd_vma addr; -{ - /* FIXME. */ - debug_error ("debug_record_label not implemented"); - return false; -} - -/* Record a variable. */ - -boolean -debug_record_variable (handle, name, type, kind, val) - PTR handle; - const char *name; - debug_type type; - enum debug_var_kind kind; - bfd_vma val; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_namespace **nsp; - enum debug_object_linkage linkage; - struct debug_name *n; - struct debug_variable *v; - - if (name == NULL || type == NULL) - return false; - - if (info->current_unit == NULL - || info->current_file == NULL) - { - debug_error ("debug_record_variable: no current file"); - return false; - } - - if (kind == DEBUG_GLOBAL || kind == DEBUG_STATIC) - { - nsp = &info->current_file->globals; - if (kind == DEBUG_GLOBAL) - linkage = DEBUG_LINKAGE_GLOBAL; - else - linkage = DEBUG_LINKAGE_STATIC; - } - else - { - if (info->current_block == NULL) - { - debug_error ("debug_record_variable: no current block"); - return false; - } - nsp = &info->current_block->locals; - linkage = DEBUG_LINKAGE_AUTOMATIC; - } - - n = debug_add_to_namespace (info, nsp, name, DEBUG_OBJECT_VARIABLE, linkage); - if (n == NULL) - return false; - - v = (struct debug_variable *) xmalloc (sizeof *v); - memset (v, 0, sizeof *v); - - v->kind = kind; - v->type = type; - v->val = val; - - n->u.variable = v; - - return true; -} - -/* Make a type with a given kind and size. */ - -/*ARGSUSED*/ -static struct debug_type * -debug_make_type (info, kind, size) - struct debug_handle *info; - enum debug_type_kind kind; - unsigned int size; -{ - struct debug_type *t; - - t = (struct debug_type *) xmalloc (sizeof *t); - memset (t, 0, sizeof *t); - - t->kind = kind; - t->size = size; - - return t; -} - -/* Make an indirect type which may be used as a placeholder for a type - which is referenced before it is defined. */ - -debug_type -debug_make_indirect_type (handle, slot, tag) - PTR handle; - debug_type *slot; - const char *tag; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_type *t; - struct debug_indirect_type *i; - - t = debug_make_type (info, DEBUG_KIND_INDIRECT, 0); - if (t == NULL) - return DEBUG_TYPE_NULL; - - i = (struct debug_indirect_type *) xmalloc (sizeof *i); - memset (i, 0, sizeof *i); - - i->slot = slot; - i->tag = tag; - - t->u.kindirect = i; - - return t; -} - -/* Make a void type. There is only one of these. */ - -debug_type -debug_make_void_type (handle) - PTR handle; -{ - struct debug_handle *info = (struct debug_handle *) handle; - - return debug_make_type (info, DEBUG_KIND_VOID, 0); -} - -/* Make an integer type of a given size. The boolean argument is true - if the integer is unsigned. */ - -debug_type -debug_make_int_type (handle, size, unsignedp) - PTR handle; - unsigned int size; - boolean unsignedp; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_type *t; - - t = debug_make_type (info, DEBUG_KIND_INT, size); - if (t == NULL) - return DEBUG_TYPE_NULL; - - t->u.kint = unsignedp; - - return t; -} - -/* Make a floating point type of a given size. FIXME: On some - platforms, like an Alpha, you probably need to be able to specify - the format. */ - -debug_type -debug_make_float_type (handle, size) - PTR handle; - unsigned int size; -{ - struct debug_handle *info = (struct debug_handle *) handle; - - return debug_make_type (info, DEBUG_KIND_FLOAT, size); -} - -/* Make a boolean type of a given size. */ - -debug_type -debug_make_bool_type (handle, size) - PTR handle; - unsigned int size; -{ - struct debug_handle *info = (struct debug_handle *) handle; - - return debug_make_type (info, DEBUG_KIND_BOOL, size); -} - -/* Make a complex type of a given size. */ - -debug_type -debug_make_complex_type (handle, size) - PTR handle; - unsigned int size; -{ - struct debug_handle *info = (struct debug_handle *) handle; - - return debug_make_type (info, DEBUG_KIND_COMPLEX, size); -} - -/* Make a structure type. The second argument is true for a struct, - false for a union. The third argument is the size of the struct. - The fourth argument is a NULL terminated array of fields. */ - -debug_type -debug_make_struct_type (handle, structp, size, fields) - PTR handle; - boolean structp; - bfd_vma size; - debug_field *fields; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_type *t; - struct debug_class_type *c; - - t = debug_make_type (info, - structp ? DEBUG_KIND_STRUCT : DEBUG_KIND_UNION, - size); - if (t == NULL) - return DEBUG_TYPE_NULL; - - c = (struct debug_class_type *) xmalloc (sizeof *c); - memset (c, 0, sizeof *c); - - c->fields = fields; - - t->u.kclass = c; - - return t; -} - -/* Make an object type. The first three arguments after the handle - are the same as for debug_make_struct_type. The next arguments are - a NULL terminated array of base classes, a NULL terminated array of - methods, the type of the object holding the virtual function table - if it is not this object, and a boolean which is true if this - object has its own virtual function table. */ - -debug_type -debug_make_object_type (handle, structp, size, fields, baseclasses, - methods, vptrbase, ownvptr) - PTR handle; - boolean structp; - bfd_vma size; - debug_field *fields; - debug_baseclass *baseclasses; - debug_method *methods; - debug_type vptrbase; - boolean ownvptr; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_type *t; - struct debug_class_type *c; - - t = debug_make_type (info, - structp ? DEBUG_KIND_CLASS : DEBUG_KIND_UNION_CLASS, - size); - if (t == NULL) - return DEBUG_TYPE_NULL; - - c = (struct debug_class_type *) xmalloc (sizeof *c); - memset (c, 0, sizeof *c); - - c->fields = fields; - c->baseclasses = baseclasses; - c->methods = methods; - if (ownvptr) - c->vptrbase = t; - else - c->vptrbase = vptrbase; - - t->u.kclass = c; - - return t; -} - -/* Make an enumeration type. The arguments are a null terminated - array of strings, and an array of corresponding values. */ - -debug_type -debug_make_enum_type (handle, names, values) - PTR handle; - const char **names; - bfd_signed_vma *values; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_type *t; - struct debug_enum_type *e; - - t = debug_make_type (info, DEBUG_KIND_ENUM, 0); - if (t == NULL) - return DEBUG_TYPE_NULL; - - e = (struct debug_enum_type *) xmalloc (sizeof *e); - memset (e, 0, sizeof *e); - - e->names = names; - e->values = values; - - t->u.kenum = e; - - return t; -} - -/* Make a pointer to a given type. */ - -debug_type -debug_make_pointer_type (handle, type) - PTR handle; - debug_type type; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_type *t; - - if (type == NULL) - return DEBUG_TYPE_NULL; - - if (type->pointer != DEBUG_TYPE_NULL) - return type->pointer; - - t = debug_make_type (info, DEBUG_KIND_POINTER, 0); - if (t == NULL) - return DEBUG_TYPE_NULL; - - t->u.kpointer = type; - - type->pointer = t; - - return t; -} - -/* Make a function returning a given type. FIXME: We should be able - to record the parameter types. */ - -debug_type -debug_make_function_type (handle, type, arg_types, varargs) - PTR handle; - debug_type type; - debug_type *arg_types; - boolean varargs; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_type *t; - struct debug_function_type *f; - - if (type == NULL) - return DEBUG_TYPE_NULL; - - t = debug_make_type (info, DEBUG_KIND_FUNCTION, 0); - if (t == NULL) - return DEBUG_TYPE_NULL; - - f = (struct debug_function_type *) xmalloc (sizeof *f); - memset (f, 0, sizeof *f); - - f->return_type = type; - f->arg_types = arg_types; - f->varargs = varargs; - - t->u.kfunction = f; - - return t; -} - -/* Make a reference to a given type. */ - -debug_type -debug_make_reference_type (handle, type) - PTR handle; - debug_type type; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_type *t; - - if (type == NULL) - return DEBUG_TYPE_NULL; - - t = debug_make_type (info, DEBUG_KIND_REFERENCE, 0); - if (t == NULL) - return DEBUG_TYPE_NULL; - - t->u.kreference = type; - - return t; -} - -/* Make a range of a given type from a lower to an upper bound. */ - -debug_type -debug_make_range_type (handle, type, lower, upper) - PTR handle; - debug_type type; - bfd_signed_vma lower; - bfd_signed_vma upper; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_type *t; - struct debug_range_type *r; - - if (type == NULL) - return DEBUG_TYPE_NULL; - - t = debug_make_type (info, DEBUG_KIND_RANGE, 0); - if (t == NULL) - return DEBUG_TYPE_NULL; - - r = (struct debug_range_type *) xmalloc (sizeof *r); - memset (r, 0, sizeof *r); - - r->type = type; - r->lower = lower; - r->upper = upper; - - t->u.krange = r; - - return t; -} - -/* Make an array type. The second argument is the type of an element - of the array. The third argument is the type of a range of the - array. The fourth and fifth argument are the lower and upper - bounds, respectively. The sixth argument is true if this array is - actually a string, as in C. */ - -debug_type -debug_make_array_type (handle, element_type, range_type, lower, upper, - stringp) - PTR handle; - debug_type element_type; - debug_type range_type; - bfd_signed_vma lower; - bfd_signed_vma upper; - boolean stringp; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_type *t; - struct debug_array_type *a; - - if (element_type == NULL || range_type == NULL) - return DEBUG_TYPE_NULL; - - t = debug_make_type (info, DEBUG_KIND_ARRAY, 0); - if (t == NULL) - return DEBUG_TYPE_NULL; - - a = (struct debug_array_type *) xmalloc (sizeof *a); - memset (a, 0, sizeof *a); - - a->element_type = element_type; - a->range_type = range_type; - a->lower = lower; - a->upper = upper; - a->stringp = stringp; - - t->u.karray = a; - - return t; -} - -/* Make a set of a given type. For example, a Pascal set type. The - boolean argument is true if this set is actually a bitstring, as in - CHILL. */ - -debug_type -debug_make_set_type (handle, type, bitstringp) - PTR handle; - debug_type type; - boolean bitstringp; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_type *t; - struct debug_set_type *s; - - if (type == NULL) - return DEBUG_TYPE_NULL; - - t = debug_make_type (info, DEBUG_KIND_SET, 0); - if (t == NULL) - return DEBUG_TYPE_NULL; - - s = (struct debug_set_type *) xmalloc (sizeof *s); - memset (s, 0, sizeof *s); - - s->type = type; - s->bitstringp = bitstringp; - - t->u.kset = s; - - return t; -} - -/* Make a type for a pointer which is relative to an object. The - second argument is the type of the object to which the pointer is - relative. The third argument is the type that the pointer points - to. */ - -debug_type -debug_make_offset_type (handle, base_type, target_type) - PTR handle; - debug_type base_type; - debug_type target_type; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_type *t; - struct debug_offset_type *o; - - if (base_type == NULL || target_type == NULL) - return DEBUG_TYPE_NULL; - - t = debug_make_type (info, DEBUG_KIND_OFFSET, 0); - if (t == NULL) - return DEBUG_TYPE_NULL; - - o = (struct debug_offset_type *) xmalloc (sizeof *o); - memset (o, 0, sizeof *o); - - o->base_type = base_type; - o->target_type = target_type; - - t->u.koffset = o; - - return t; -} - -/* Make a type for a method function. The second argument is the - return type, the third argument is the domain, and the fourth - argument is a NULL terminated array of argument types. */ - -debug_type -debug_make_method_type (handle, return_type, domain_type, arg_types, varargs) - PTR handle; - debug_type return_type; - debug_type domain_type; - debug_type *arg_types; - boolean varargs; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_type *t; - struct debug_method_type *m; - - if (return_type == NULL) - return DEBUG_TYPE_NULL; - - t = debug_make_type (info, DEBUG_KIND_METHOD, 0); - if (t == NULL) - return DEBUG_TYPE_NULL; - - m = (struct debug_method_type *) xmalloc (sizeof *m); - memset (m, 0, sizeof *m); - - m->return_type = return_type; - m->domain_type = domain_type; - m->arg_types = arg_types; - m->varargs = varargs; - - t->u.kmethod = m; - - return t; -} - -/* Make a const qualified version of a given type. */ - -debug_type -debug_make_const_type (handle, type) - PTR handle; - debug_type type; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_type *t; - - if (type == NULL) - return DEBUG_TYPE_NULL; - - t = debug_make_type (info, DEBUG_KIND_CONST, 0); - if (t == NULL) - return DEBUG_TYPE_NULL; - - t->u.kconst = type; - - return t; -} - -/* Make a volatile qualified version of a given type. */ - -debug_type -debug_make_volatile_type (handle, type) - PTR handle; - debug_type type; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_type *t; - - if (type == NULL) - return DEBUG_TYPE_NULL; - - t = debug_make_type (info, DEBUG_KIND_VOLATILE, 0); - if (t == NULL) - return DEBUG_TYPE_NULL; - - t->u.kvolatile = type; - - return t; -} - -/* Make an undefined tagged type. For example, a struct which has - been mentioned, but not defined. */ - -debug_type -debug_make_undefined_tagged_type (handle, name, kind) - PTR handle; - const char *name; - enum debug_type_kind kind; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_type *t; - - if (name == NULL) - return DEBUG_TYPE_NULL; - - switch (kind) - { - case DEBUG_KIND_STRUCT: - case DEBUG_KIND_UNION: - case DEBUG_KIND_CLASS: - case DEBUG_KIND_UNION_CLASS: - case DEBUG_KIND_ENUM: - break; - - default: - debug_error ("debug_make_undefined_type: unsupported kind"); - return DEBUG_TYPE_NULL; - } - - t = debug_make_type (info, kind, 0); - if (t == NULL) - return DEBUG_TYPE_NULL; - - return debug_tag_type (handle, name, t); -} - -/* Make a base class for an object. The second argument is the base - class type. The third argument is the bit position of this base - class in the object (always 0 unless doing multiple inheritance). - The fourth argument is whether this is a virtual class. The fifth - argument is the visibility of the base class. */ - -/*ARGSUSED*/ -debug_baseclass -debug_make_baseclass (handle, type, bitpos, virtual, visibility) - PTR handle; - debug_type type; - bfd_vma bitpos; - boolean virtual; - enum debug_visibility visibility; -{ - struct debug_baseclass *b; - - b = (struct debug_baseclass *) xmalloc (sizeof *b); - memset (b, 0, sizeof *b); - - b->type = type; - b->bitpos = bitpos; - b->virtual = virtual; - b->visibility = visibility; - - return b; -} - -/* Make a field for a struct. The second argument is the name. The - third argument is the type of the field. The fourth argument is - the bit position of the field. The fifth argument is the size of - the field (it may be zero). The sixth argument is the visibility - of the field. */ - -/*ARGSUSED*/ -debug_field -debug_make_field (handle, name, type, bitpos, bitsize, visibility) - PTR handle; - const char *name; - debug_type type; - bfd_vma bitpos; - bfd_vma bitsize; - enum debug_visibility visibility; -{ - struct debug_field *f; - - f = (struct debug_field *) xmalloc (sizeof *f); - memset (f, 0, sizeof *f); - - f->name = name; - f->type = type; - f->static_member = false; - f->u.f.bitpos = bitpos; - f->u.f.bitsize = bitsize; - f->visibility = visibility; - - return f; -} - -/* Make a static member of an object. The second argument is the - name. The third argument is the type of the member. The fourth - argument is the physical name of the member (i.e., the name as a - global variable). The fifth argument is the visibility of the - member. */ - -/*ARGSUSED*/ -debug_field -debug_make_static_member (handle, name, type, physname, visibility) - PTR handle; - const char *name; - debug_type type; - const char *physname; - enum debug_visibility visibility; -{ - struct debug_field *f; - - f = (struct debug_field *) xmalloc (sizeof *f); - memset (f, 0, sizeof *f); - - f->name = name; - f->type = type; - f->static_member = true; - f->u.s.physname = physname; - f->visibility = visibility; - - return f; -} - -/* Make a method. The second argument is the name, and the third - argument is a NULL terminated array of method variants. */ - -/*ARGSUSED*/ -debug_method -debug_make_method (handle, name, variants) - PTR handle; - const char *name; - debug_method_variant *variants; -{ - struct debug_method *m; - - m = (struct debug_method *) xmalloc (sizeof *m); - memset (m, 0, sizeof *m); - - m->name = name; - m->variants = variants; - - return m; -} - -/* Make a method argument. The second argument is the real name of - the function. The third argument is the type of the function. The - fourth argument is the visibility. The fifth argument is whether - this is a const function. The sixth argument is whether this is a - volatile function. The seventh argument is the offset in the - virtual function table, if any. The eighth argument is the virtual - function context. FIXME: Are the const and volatile arguments - necessary? Could we just use debug_make_const_type? */ - -/*ARGSUSED*/ -debug_method_variant -debug_make_method_variant (handle, physname, type, visibility, constp, - volatilep, voffset, context) - PTR handle; - const char *physname; - debug_type type; - enum debug_visibility visibility; - boolean constp; - boolean volatilep; - bfd_vma voffset; - debug_type context; -{ - struct debug_method_variant *m; - - m = (struct debug_method_variant *) xmalloc (sizeof *m); - memset (m, 0, sizeof *m); - - m->physname = physname; - m->type = type; - m->visibility = visibility; - m->constp = constp; - m->volatilep = volatilep; - m->voffset = voffset; - m->context = context; - - return m; -} - -/* Make a static method argument. The arguments are the same as for - debug_make_method_variant, except that the last two are omitted - since a static method can not also be virtual. */ - -debug_method_variant -debug_make_static_method_variant (handle, physname, type, visibility, - constp, volatilep) - PTR handle; - const char *physname; - debug_type type; - enum debug_visibility visibility; - boolean constp; - boolean volatilep; -{ - struct debug_method_variant *m; - - m = (struct debug_method_variant *) xmalloc (sizeof *m); - memset (m, 0, sizeof *m); - - m->physname = physname; - m->type = type; - m->visibility = visibility; - m->constp = constp; - m->volatilep = volatilep; - m->voffset = VOFFSET_STATIC_METHOD; - - return m; -} - -/* Name a type. */ - -debug_type -debug_name_type (handle, name, type) - PTR handle; - const char *name; - debug_type type; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_type *t; - struct debug_named_type *n; - struct debug_name *nm; - - if (name == NULL || type == NULL) - return DEBUG_TYPE_NULL; - - if (info->current_unit == NULL - || info->current_file == NULL) - { - debug_error ("debug_name_type: no current file"); - return DEBUG_TYPE_NULL; - /* return false; */ - } - - t = debug_make_type (info, DEBUG_KIND_NAMED, 0); - if (t == NULL) - return DEBUG_TYPE_NULL; - - n = (struct debug_named_type *) xmalloc (sizeof *n); - memset (n, 0, sizeof *n); - - n->type = type; - - t->u.knamed = n; - - /* We always add the name to the global namespace. This is probably - wrong in some cases, but it seems to be right for stabs. FIXME. */ - - nm = debug_add_to_namespace (info, &info->current_file->globals, name, - DEBUG_OBJECT_TYPE, DEBUG_LINKAGE_NONE); - if (nm == NULL) - return DEBUG_TYPE_NULL; - - nm->u.type = t; - - n->name = nm; - - return t; -} - -/* Tag a type. */ - -debug_type -debug_tag_type (handle, name, type) - PTR handle; - const char *name; - debug_type type; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_type *t; - struct debug_named_type *n; - struct debug_name *nm; - - if (name == NULL || type == NULL) - return DEBUG_TYPE_NULL; - - if (info->current_file == NULL) - { - debug_error ("debug_tag_type: no current file"); - return DEBUG_TYPE_NULL; - } - - if (type->kind == DEBUG_KIND_TAGGED) - { - if (strcmp (type->u.knamed->name->name, name) == 0) - return type; - debug_error ("debug_tag_type: extra tag attempted"); - return DEBUG_TYPE_NULL; - } - - t = debug_make_type (info, DEBUG_KIND_TAGGED, 0); - if (t == NULL) - return DEBUG_TYPE_NULL; - - n = (struct debug_named_type *) xmalloc (sizeof *n); - memset (n, 0, sizeof *n); - - n->type = type; - - t->u.knamed = n; - - /* We keep a global namespace of tags for each compilation unit. I - don't know if that is the right thing to do. */ - - nm = debug_add_to_namespace (info, &info->current_file->globals, name, - DEBUG_OBJECT_TAG, DEBUG_LINKAGE_NONE); - if (nm == NULL) - return DEBUG_TYPE_NULL; - - nm->u.tag = t; - - n->name = nm; - - return t; -} - -/* Record the size of a given type. */ - -/*ARGSUSED*/ -boolean -debug_record_type_size (handle, type, size) - PTR handle; - debug_type type; - unsigned int size; -{ -#if 0 - if (type->size != 0 && type->size != size) - fprintf (stderr, "Warning: changing type size from %d to %d\n", - type->size, size); -#endif - - type->size = size; - - return true; -} - -/* Find a named type. */ - -debug_type -debug_find_named_type (handle, name) - PTR handle; - const char *name; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_block *b; - struct debug_file *f; - - /* We only search the current compilation unit. I don't know if - this is right or not. */ - - if (info->current_unit == NULL) - { - debug_error ("debug_find_named_type: no current compilation unit"); - return DEBUG_TYPE_NULL; - } - - for (b = info->current_block; b != NULL; b = b->parent) - { - if (b->locals != NULL) - { - struct debug_name *n; - - for (n = b->locals->list; n != NULL; n = n->next) - { - if (n->kind == DEBUG_OBJECT_TYPE - && n->name[0] == name[0] - && strcmp (n->name, name) == 0) - return n->u.type; - } - } - } - - for (f = info->current_unit->files; f != NULL; f = f->next) - { - if (f->globals != NULL) - { - struct debug_name *n; - - for (n = f->globals->list; n != NULL; n = n->next) - { - if (n->kind == DEBUG_OBJECT_TYPE - && n->name[0] == name[0] - && strcmp (n->name, name) == 0) - return n->u.type; - } - } - } - - return DEBUG_TYPE_NULL; -} - -/* Find a tagged type. */ - -debug_type -debug_find_tagged_type (handle, name, kind) - PTR handle; - const char *name; - enum debug_type_kind kind; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_unit *u; - - /* We search the globals of all the compilation units. I don't know - if this is correct or not. It would be easy to change. */ - - for (u = info->units; u != NULL; u = u->next) - { - struct debug_file *f; - - for (f = u->files; f != NULL; f = f->next) - { - struct debug_name *n; - - if (f->globals != NULL) - { - for (n = f->globals->list; n != NULL; n = n->next) - { - if (n->kind == DEBUG_OBJECT_TAG - && (kind == DEBUG_KIND_ILLEGAL - || n->u.tag->kind == kind) - && n->name[0] == name[0] - && strcmp (n->name, name) == 0) - return n->u.tag; - } - } - } - } - - return DEBUG_TYPE_NULL; -} - -/* Get a base type. */ - -static struct debug_type * -debug_get_real_type (handle, type) - PTR handle; - debug_type type; -{ - switch (type->kind) - { - default: - return type; - case DEBUG_KIND_INDIRECT: - if (*type->u.kindirect->slot != NULL) - return debug_get_real_type (handle, *type->u.kindirect->slot); - return type; - case DEBUG_KIND_NAMED: - case DEBUG_KIND_TAGGED: - return debug_get_real_type (handle, type->u.knamed->type); - } - /*NOTREACHED*/ -} - -/* Get the kind of a type. */ - -enum debug_type_kind -debug_get_type_kind (handle, type) - PTR handle; - debug_type type; -{ - if (type == NULL) - return DEBUG_KIND_ILLEGAL; - type = debug_get_real_type (handle, type); - return type->kind; -} - -/* Get the name of a type. */ - -const char * -debug_get_type_name (handle, type) - PTR handle; - debug_type type; -{ - if (type->kind == DEBUG_KIND_INDIRECT) - { - if (*type->u.kindirect->slot != NULL) - return debug_get_type_name (handle, *type->u.kindirect->slot); - return type->u.kindirect->tag; - } - if (type->kind == DEBUG_KIND_NAMED - || type->kind == DEBUG_KIND_TAGGED) - return type->u.knamed->name->name; - return NULL; -} - -/* Get the size of a type. */ - -bfd_vma -debug_get_type_size (handle, type) - PTR handle; - debug_type type; -{ - if (type == NULL) - return 0; - - /* We don't call debug_get_real_type, because somebody might have - called debug_record_type_size on a named or indirect type. */ - - if (type->size != 0) - return type->size; - - switch (type->kind) - { - default: - return 0; - case DEBUG_KIND_INDIRECT: - if (*type->u.kindirect->slot != NULL) - return debug_get_type_size (handle, *type->u.kindirect->slot); - return 0; - case DEBUG_KIND_NAMED: - case DEBUG_KIND_TAGGED: - return debug_get_type_size (handle, type->u.knamed->type); - } - /*NOTREACHED*/ -} - -/* Get the return type of a function or method type. */ - -debug_type -debug_get_return_type (handle, type) - PTR handle; - debug_type type; -{ - if (type == NULL) - return DEBUG_TYPE_NULL; - type = debug_get_real_type (handle, type); - switch (type->kind) - { - default: - return DEBUG_TYPE_NULL; - case DEBUG_KIND_FUNCTION: - return type->u.kfunction->return_type; - case DEBUG_KIND_METHOD: - return type->u.kmethod->return_type; - } - /*NOTREACHED*/ -} - -/* Get the parameter types of a function or method type (except that - we don't currently store the parameter types of a function). */ - -const debug_type * -debug_get_parameter_types (handle, type, pvarargs) - PTR handle; - debug_type type; - boolean *pvarargs; -{ - if (type == NULL) - return NULL; - type = debug_get_real_type (handle, type); - switch (type->kind) - { - default: - return NULL; - case DEBUG_KIND_FUNCTION: - *pvarargs = type->u.kfunction->varargs; - return type->u.kfunction->arg_types; - case DEBUG_KIND_METHOD: - *pvarargs = type->u.kmethod->varargs; - return type->u.kmethod->arg_types; - } - /*NOTREACHED*/ -} - -/* Get the target type of a type. */ - -debug_type -debug_get_target_type (handle, type) - PTR handle; - debug_type type; -{ - if (type == NULL) - return NULL; - type = debug_get_real_type (handle, type); - switch (type->kind) - { - default: - return NULL; - case DEBUG_KIND_POINTER: - return type->u.kpointer; - case DEBUG_KIND_REFERENCE: - return type->u.kreference; - case DEBUG_KIND_CONST: - return type->u.kconst; - case DEBUG_KIND_VOLATILE: - return type->u.kvolatile; - } - /*NOTREACHED*/ -} - -/* Get the NULL terminated array of fields for a struct, union, or - class. */ - -const debug_field * -debug_get_fields (handle, type) - PTR handle; - debug_type type; -{ - if (type == NULL) - return NULL; - type = debug_get_real_type (handle, type); - switch (type->kind) - { - default: - return NULL; - case DEBUG_KIND_STRUCT: - case DEBUG_KIND_UNION: - case DEBUG_KIND_CLASS: - case DEBUG_KIND_UNION_CLASS: - return type->u.kclass->fields; - } - /*NOTREACHED*/ -} - -/* Get the type of a field. */ - -/*ARGSUSED*/ -debug_type -debug_get_field_type (handle, field) - PTR handle; - debug_field field; -{ - if (field == NULL) - return NULL; - return field->type; -} - -/* Get the name of a field. */ - -/*ARGSUSED*/ -const char * -debug_get_field_name (handle, field) - PTR handle; - debug_field field; -{ - if (field == NULL) - return NULL; - return field->name; -} - -/* Get the bit position of a field. */ - -/*ARGSUSED*/ -bfd_vma -debug_get_field_bitpos (handle, field) - PTR handle; - debug_field field; -{ - if (field == NULL || field->static_member) - return (bfd_vma) -1; - return field->u.f.bitpos; -} - -/* Get the bit size of a field. */ - -/*ARGSUSED*/ -bfd_vma -debug_get_field_bitsize (handle, field) - PTR handle; - debug_field field; -{ - if (field == NULL || field->static_member) - return (bfd_vma) -1; - return field->u.f.bitsize; -} - -/* Get the visibility of a field. */ - -/*ARGSUSED*/ -enum debug_visibility -debug_get_field_visibility (handle, field) - PTR handle; - debug_field field; -{ - if (field == NULL) - return DEBUG_VISIBILITY_IGNORE; - return field->visibility; -} - -/* Get the physical name of a field. */ - -const char * -debug_get_field_physname (handle, field) - PTR handle; - debug_field field; -{ - if (field == NULL || ! field->static_member) - return NULL; - return field->u.s.physname; -} - -/* Write out the debugging information. This is given a handle to - debugging information, and a set of function pointers to call. */ - -boolean -debug_write (handle, fns, fhandle) - PTR handle; - const struct debug_write_fns *fns; - PTR fhandle; -{ - struct debug_handle *info = (struct debug_handle *) handle; - struct debug_unit *u; - - /* We use a mark to tell whether we have already written out a - particular name. We use an integer, so that we don't have to - clear the mark fields if we happen to write out the same - information more than once. */ - ++info->mark; - - /* The base_id field holds an ID value which will never be used, so - that we can tell whether we have assigned an ID during this call - to debug_write. */ - info->base_id = info->class_id; - - /* We keep a linked list of classes for which was have assigned ID's - during this call to debug_write. */ - info->id_list = NULL; - - for (u = info->units; u != NULL; u = u->next) - { - struct debug_file *f; - boolean first_file; - - info->current_write_lineno = u->linenos; - info->current_write_lineno_index = 0; - - if (! (*fns->start_compilation_unit) (fhandle, u->files->filename)) - return false; - - first_file = true; - for (f = u->files; f != NULL; f = f->next) - { - struct debug_name *n; - - if (first_file) - first_file = false; - else - { - if (! (*fns->start_source) (fhandle, f->filename)) - return false; - } - - if (f->globals != NULL) - { - for (n = f->globals->list; n != NULL; n = n->next) - { - if (! debug_write_name (info, fns, fhandle, n)) - return false; - } - } - } - - /* Output any line number information which hasn't already been - handled. */ - if (! debug_write_linenos (info, fns, fhandle, (bfd_vma) -1)) - return false; - } - - return true; -} - -/* Write out an element in a namespace. */ - -static boolean -debug_write_name (info, fns, fhandle, n) - struct debug_handle *info; - const struct debug_write_fns *fns; - PTR fhandle; - struct debug_name *n; -{ - switch (n->kind) - { - case DEBUG_OBJECT_TYPE: - if (! debug_write_type (info, fns, fhandle, n->u.type, n) - || ! (*fns->typdef) (fhandle, n->name)) - return false; - return true; - case DEBUG_OBJECT_TAG: - if (! debug_write_type (info, fns, fhandle, n->u.tag, n)) - return false; - return (*fns->tag) (fhandle, n->name); - case DEBUG_OBJECT_VARIABLE: - if (! debug_write_type (info, fns, fhandle, n->u.variable->type, - (struct debug_name *) NULL)) - return false; - return (*fns->variable) (fhandle, n->name, n->u.variable->kind, - n->u.variable->val); - case DEBUG_OBJECT_FUNCTION: - return debug_write_function (info, fns, fhandle, n->name, - n->linkage, n->u.function); - case DEBUG_OBJECT_INT_CONSTANT: - return (*fns->int_constant) (fhandle, n->name, n->u.int_constant); - case DEBUG_OBJECT_FLOAT_CONSTANT: - return (*fns->float_constant) (fhandle, n->name, n->u.float_constant); - case DEBUG_OBJECT_TYPED_CONSTANT: - if (! debug_write_type (info, fns, fhandle, n->u.typed_constant->type, - (struct debug_name *) NULL)) - return false; - return (*fns->typed_constant) (fhandle, n->name, - n->u.typed_constant->val); - default: - abort (); - return false; - } - /*NOTREACHED*/ -} - -/* Write out a type. If the type is DEBUG_KIND_NAMED or - DEBUG_KIND_TAGGED, then the name argument is the name for which we - are about to call typedef or tag. If the type is anything else, - then the name argument is a tag from a DEBUG_KIND_TAGGED type which - points to this one. */ - -static boolean -debug_write_type (info, fns, fhandle, type, name) - struct debug_handle *info; - const struct debug_write_fns *fns; - PTR fhandle; - struct debug_type *type; - struct debug_name *name; -{ - unsigned int i; - int is; - const char *tag; - - /* If we have a name for this type, just output it. We only output - typedef names after they have been defined. We output type tags - whenever we are not actually defining them. */ - if ((type->kind == DEBUG_KIND_NAMED - || type->kind == DEBUG_KIND_TAGGED) - && (type->u.knamed->name->mark == info->mark - || (type->kind == DEBUG_KIND_TAGGED - && type->u.knamed->name != name))) - { - if (type->kind == DEBUG_KIND_NAMED) - return (*fns->typedef_type) (fhandle, type->u.knamed->name->name); - else - { - struct debug_type *real; - unsigned int id; - - real = debug_get_real_type ((PTR) info, type); - id = 0; - if ((real->kind == DEBUG_KIND_STRUCT - || real->kind == DEBUG_KIND_UNION - || real->kind == DEBUG_KIND_CLASS - || real->kind == DEBUG_KIND_UNION_CLASS) - && real->u.kclass != NULL) - { - if (real->u.kclass->id <= info->base_id) - { - if (! debug_set_class_id (info, - type->u.knamed->name->name, - real)) - return false; - } - id = real->u.kclass->id; - } - - return (*fns->tag_type) (fhandle, type->u.knamed->name->name, id, - real->kind); - } - } - - /* Mark the name after we have already looked for a known name, so - that we don't just define a type in terms of itself. We need to - mark the name here so that a struct containing a pointer to - itself will work. */ - if (name != NULL) - name->mark = info->mark; - - tag = NULL; - if (name != NULL - && type->kind != DEBUG_KIND_NAMED - && type->kind != DEBUG_KIND_TAGGED) - { - assert (name->kind == DEBUG_OBJECT_TAG); - tag = name->name; - } - - switch (type->kind) - { - case DEBUG_KIND_ILLEGAL: - debug_error ("debug_write_type: illegal type encountered"); - return false; - case DEBUG_KIND_INDIRECT: - if (*type->u.kindirect->slot == DEBUG_TYPE_NULL) - return (*fns->empty_type) (fhandle); - return debug_write_type (info, fns, fhandle, *type->u.kindirect->slot, - name); - case DEBUG_KIND_VOID: - return (*fns->void_type) (fhandle); - case DEBUG_KIND_INT: - return (*fns->int_type) (fhandle, type->size, type->u.kint); - case DEBUG_KIND_FLOAT: - return (*fns->float_type) (fhandle, type->size); - case DEBUG_KIND_COMPLEX: - return (*fns->complex_type) (fhandle, type->size); - case DEBUG_KIND_BOOL: - return (*fns->bool_type) (fhandle, type->size); - case DEBUG_KIND_STRUCT: - case DEBUG_KIND_UNION: - if (type->u.kclass != NULL) - { - if (type->u.kclass->id <= info->base_id) - { - if (! debug_set_class_id (info, tag, type)) - return false; - } - - if (info->mark == type->u.kclass->mark) - { - /* We are currently outputting this struct, or we have - already output it. I don't know if this can happen, - but it can happen for a class. */ - assert (type->u.kclass->id > info->base_id); - return (*fns->tag_type) (fhandle, tag, type->u.kclass->id, - type->kind); - } - type->u.kclass->mark = info->mark; - } - - if (! (*fns->start_struct_type) (fhandle, tag, - (type->u.kclass != NULL - ? type->u.kclass->id - : 0), - type->kind == DEBUG_KIND_STRUCT, - type->size)) - return false; - if (type->u.kclass != NULL - && type->u.kclass->fields != NULL) - { - for (i = 0; type->u.kclass->fields[i] != NULL; i++) - { - struct debug_field *f; - - f = type->u.kclass->fields[i]; - if (! debug_write_type (info, fns, fhandle, f->type, - (struct debug_name *) NULL) - || ! (*fns->struct_field) (fhandle, f->name, f->u.f.bitpos, - f->u.f.bitsize, f->visibility)) - return false; - } - } - return (*fns->end_struct_type) (fhandle); - case DEBUG_KIND_CLASS: - case DEBUG_KIND_UNION_CLASS: - return debug_write_class_type (info, fns, fhandle, type, tag); - case DEBUG_KIND_ENUM: - if (type->u.kenum == NULL) - return (*fns->enum_type) (fhandle, tag, (const char **) NULL, - (bfd_signed_vma *) NULL); - return (*fns->enum_type) (fhandle, tag, type->u.kenum->names, - type->u.kenum->values); - case DEBUG_KIND_POINTER: - if (! debug_write_type (info, fns, fhandle, type->u.kpointer, - (struct debug_name *) NULL)) - return false; - return (*fns->pointer_type) (fhandle); - case DEBUG_KIND_FUNCTION: - if (! debug_write_type (info, fns, fhandle, - type->u.kfunction->return_type, - (struct debug_name *) NULL)) - return false; - if (type->u.kfunction->arg_types == NULL) - is = -1; - else - { - for (is = 0; type->u.kfunction->arg_types[is] != NULL; is++) - if (! debug_write_type (info, fns, fhandle, - type->u.kfunction->arg_types[is], - (struct debug_name *) NULL)) - return false; - } - return (*fns->function_type) (fhandle, is, - type->u.kfunction->varargs); - case DEBUG_KIND_REFERENCE: - if (! debug_write_type (info, fns, fhandle, type->u.kreference, - (struct debug_name *) NULL)) - return false; - return (*fns->reference_type) (fhandle); - case DEBUG_KIND_RANGE: - if (! debug_write_type (info, fns, fhandle, type->u.krange->type, - (struct debug_name *) NULL)) - return false; - return (*fns->range_type) (fhandle, type->u.krange->lower, - type->u.krange->upper); - case DEBUG_KIND_ARRAY: - if (! debug_write_type (info, fns, fhandle, type->u.karray->element_type, - (struct debug_name *) NULL) - || ! debug_write_type (info, fns, fhandle, - type->u.karray->range_type, - (struct debug_name *) NULL)) - return false; - return (*fns->array_type) (fhandle, type->u.karray->lower, - type->u.karray->upper, - type->u.karray->stringp); - case DEBUG_KIND_SET: - if (! debug_write_type (info, fns, fhandle, type->u.kset->type, - (struct debug_name *) NULL)) - return false; - return (*fns->set_type) (fhandle, type->u.kset->bitstringp); - case DEBUG_KIND_OFFSET: - if (! debug_write_type (info, fns, fhandle, type->u.koffset->base_type, - (struct debug_name *) NULL) - || ! debug_write_type (info, fns, fhandle, - type->u.koffset->target_type, - (struct debug_name *) NULL)) - return false; - return (*fns->offset_type) (fhandle); - case DEBUG_KIND_METHOD: - if (! debug_write_type (info, fns, fhandle, - type->u.kmethod->return_type, - (struct debug_name *) NULL)) - return false; - if (type->u.kmethod->arg_types == NULL) - is = -1; - else - { - for (is = 0; type->u.kmethod->arg_types[is] != NULL; is++) - if (! debug_write_type (info, fns, fhandle, - type->u.kmethod->arg_types[is], - (struct debug_name *) NULL)) - return false; - } - if (type->u.kmethod->domain_type != NULL) - { - if (! debug_write_type (info, fns, fhandle, - type->u.kmethod->domain_type, - (struct debug_name *) NULL)) - return false; - } - return (*fns->method_type) (fhandle, - type->u.kmethod->domain_type != NULL, - is, - type->u.kmethod->varargs); - case DEBUG_KIND_CONST: - if (! debug_write_type (info, fns, fhandle, type->u.kconst, - (struct debug_name *) NULL)) - return false; - return (*fns->const_type) (fhandle); - case DEBUG_KIND_VOLATILE: - if (! debug_write_type (info, fns, fhandle, type->u.kvolatile, - (struct debug_name *) NULL)) - return false; - return (*fns->volatile_type) (fhandle); - case DEBUG_KIND_NAMED: - return debug_write_type (info, fns, fhandle, type->u.knamed->type, - (struct debug_name *) NULL); - case DEBUG_KIND_TAGGED: - return debug_write_type (info, fns, fhandle, type->u.knamed->type, - type->u.knamed->name); - default: - abort (); - return false; - } -} - -/* Write out a class type. */ - -static boolean -debug_write_class_type (info, fns, fhandle, type, tag) - struct debug_handle *info; - const struct debug_write_fns *fns; - PTR fhandle; - struct debug_type *type; - const char *tag; -{ - unsigned int i; - unsigned int id; - struct debug_type *vptrbase; - - if (type->u.kclass == NULL) - { - id = 0; - vptrbase = NULL; - } - else - { - if (type->u.kclass->id <= info->base_id) - { - if (! debug_set_class_id (info, tag, type)) - return false; - } - - if (info->mark == type->u.kclass->mark) - { - /* We are currently outputting this class, or we have - already output it. This can happen when there are - methods for an anonymous class. */ - assert (type->u.kclass->id > info->base_id); - return (*fns->tag_type) (fhandle, tag, type->u.kclass->id, - type->kind); - } - type->u.kclass->mark = info->mark; - id = type->u.kclass->id; - - vptrbase = type->u.kclass->vptrbase; - if (vptrbase != NULL && vptrbase != type) - { - if (! debug_write_type (info, fns, fhandle, vptrbase, - (struct debug_name *) NULL)) - return false; - } - } - - if (! (*fns->start_class_type) (fhandle, tag, id, - type->kind == DEBUG_KIND_CLASS, - type->size, - vptrbase != NULL, - vptrbase == type)) - return false; - - if (type->u.kclass != NULL) - { - if (type->u.kclass->fields != NULL) - { - for (i = 0; type->u.kclass->fields[i] != NULL; i++) - { - struct debug_field *f; - - f = type->u.kclass->fields[i]; - if (! debug_write_type (info, fns, fhandle, f->type, - (struct debug_name *) NULL)) - return false; - if (f->static_member) - { - if (! (*fns->class_static_member) (fhandle, f->name, - f->u.s.physname, - f->visibility)) - return false; - } - else - { - if (! (*fns->struct_field) (fhandle, f->name, f->u.f.bitpos, - f->u.f.bitsize, f->visibility)) - return false; - } - } - } - - if (type->u.kclass->baseclasses != NULL) - { - for (i = 0; type->u.kclass->baseclasses[i] != NULL; i++) - { - struct debug_baseclass *b; - - b = type->u.kclass->baseclasses[i]; - if (! debug_write_type (info, fns, fhandle, b->type, - (struct debug_name *) NULL)) - return false; - if (! (*fns->class_baseclass) (fhandle, b->bitpos, b->virtual, - b->visibility)) - return false; - } - } - - if (type->u.kclass->methods != NULL) - { - for (i = 0; type->u.kclass->methods[i] != NULL; i++) - { - struct debug_method *m; - unsigned int j; - - m = type->u.kclass->methods[i]; - if (! (*fns->class_start_method) (fhandle, m->name)) - return false; - for (j = 0; m->variants[j] != NULL; j++) - { - struct debug_method_variant *v; - - v = m->variants[j]; - if (v->context != NULL) - { - if (! debug_write_type (info, fns, fhandle, v->context, - (struct debug_name *) NULL)) - return false; - } - if (! debug_write_type (info, fns, fhandle, v->type, - (struct debug_name *) NULL)) - return false; - if (v->voffset != VOFFSET_STATIC_METHOD) - { - if (! (*fns->class_method_variant) (fhandle, v->physname, - v->visibility, - v->constp, - v->volatilep, - v->voffset, - v->context != NULL)) - return false; - } - else - { - if (! (*fns->class_static_method_variant) (fhandle, - v->physname, - v->visibility, - v->constp, - v->volatilep)) - return false; - } - } - if (! (*fns->class_end_method) (fhandle)) - return false; - } - } - } - - return (*fns->end_class_type) (fhandle); -} - -/* Write out information for a function. */ - -static boolean -debug_write_function (info, fns, fhandle, name, linkage, function) - struct debug_handle *info; - const struct debug_write_fns *fns; - PTR fhandle; - const char *name; - enum debug_object_linkage linkage; - struct debug_function *function; -{ - struct debug_parameter *p; - struct debug_block *b; - - if (! debug_write_linenos (info, fns, fhandle, function->blocks->start)) - return false; - - if (! debug_write_type (info, fns, fhandle, function->return_type, - (struct debug_name *) NULL)) - return false; - - if (! (*fns->start_function) (fhandle, name, - linkage == DEBUG_LINKAGE_GLOBAL)) - return false; - - for (p = function->parameters; p != NULL; p = p->next) - { - if (! debug_write_type (info, fns, fhandle, p->type, - (struct debug_name *) NULL) - || ! (*fns->function_parameter) (fhandle, p->name, p->kind, p->val)) - return false; - } - - for (b = function->blocks; b != NULL; b = b->next) - { - if (! debug_write_block (info, fns, fhandle, b)) - return false; - } - - return (*fns->end_function) (fhandle); -} - -/* Write out information for a block. */ - -static boolean -debug_write_block (info, fns, fhandle, block) - struct debug_handle *info; - const struct debug_write_fns *fns; - PTR fhandle; - struct debug_block *block; -{ - struct debug_name *n; - struct debug_block *b; - - if (! debug_write_linenos (info, fns, fhandle, block->start)) - return false; - - /* I can't see any point to writing out a block with no local - variables, so we don't bother, except for the top level block. */ - if (block->locals != NULL || block->parent == NULL) - { - if (! (*fns->start_block) (fhandle, block->start)) - return false; - } - - if (block->locals != NULL) - { - for (n = block->locals->list; n != NULL; n = n->next) - { - if (! debug_write_name (info, fns, fhandle, n)) - return false; - } - } - - for (b = block->children; b != NULL; b = b->next) - { - if (! debug_write_block (info, fns, fhandle, b)) - return false; - } - - if (! debug_write_linenos (info, fns, fhandle, block->end)) - return false; - - if (block->locals != NULL || block->parent == NULL) - { - if (! (*fns->end_block) (fhandle, block->end)) - return false; - } - - return true; -} - -/* Write out line number information up to ADDRESS. */ - -static boolean -debug_write_linenos (info, fns, fhandle, address) - struct debug_handle *info; - const struct debug_write_fns *fns; - PTR fhandle; - bfd_vma address; -{ - while (info->current_write_lineno != NULL) - { - struct debug_lineno *l; - - l = info->current_write_lineno; - - while (info->current_write_lineno_index < DEBUG_LINENO_COUNT) - { - if (l->linenos[info->current_write_lineno_index] - == (unsigned long) -1) - break; - - if (l->addrs[info->current_write_lineno_index] >= address) - return true; - - if (! (*fns->lineno) (fhandle, l->file->filename, - l->linenos[info->current_write_lineno_index], - l->addrs[info->current_write_lineno_index])) - return false; - - ++info->current_write_lineno_index; - } - - info->current_write_lineno = l->next; - info->current_write_lineno_index = 0; - } - - return true; -} - -/* Get the ID number for a class. If during the same call to - debug_write we find a struct with the same definition with the same - name, we use the same ID. This type of things happens because the - same struct will be defined by multiple compilation units. */ - -static boolean -debug_set_class_id (info, tag, type) - struct debug_handle *info; - const char *tag; - struct debug_type *type; -{ - struct debug_class_type *c; - struct debug_class_id *l; - - assert (type->kind == DEBUG_KIND_STRUCT - || type->kind == DEBUG_KIND_UNION - || type->kind == DEBUG_KIND_CLASS - || type->kind == DEBUG_KIND_UNION_CLASS); - - c = type->u.kclass; - - if (c->id > info->base_id) - return true; - - for (l = info->id_list; l != NULL; l = l->next) - { - if (l->type->kind != type->kind) - continue; - - if (tag == NULL) - { - if (l->tag != NULL) - continue; - } - else - { - if (l->tag == NULL - || l->tag[0] != tag[0] - || strcmp (l->tag, tag) != 0) - continue; - } - - if (debug_type_samep (info, l->type, type)) - { - c->id = l->type->u.kclass->id; - return true; - } - } - - /* There are no identical types. Use a new ID, and add it to the - list. */ - ++info->class_id; - c->id = info->class_id; - - l = (struct debug_class_id *) xmalloc (sizeof *l); - memset (l, 0, sizeof *l); - - l->type = type; - l->tag = tag; - - l->next = info->id_list; - info->id_list = l; - - return true; -} - -/* See if two types are the same. At this point, we don't care about - tags and the like. */ - -static boolean -debug_type_samep (info, t1, t2) - struct debug_handle *info; - struct debug_type *t1; - struct debug_type *t2; -{ - struct debug_type_compare_list *l; - struct debug_type_compare_list top; - boolean ret; - - if (t1 == NULL) - return t2 == NULL; - if (t2 == NULL) - return false; - - while (t1->kind == DEBUG_KIND_INDIRECT) - { - t1 = *t1->u.kindirect->slot; - if (t1 == NULL) - return false; - } - while (t2->kind == DEBUG_KIND_INDIRECT) - { - t2 = *t2->u.kindirect->slot; - if (t2 == NULL) - return false; - } - - if (t1 == t2) - return true; - - /* As a special case, permit a typedef to match a tag, since C++ - debugging output will sometimes add a typedef where C debugging - output will not. */ - if (t1->kind == DEBUG_KIND_NAMED - && t2->kind == DEBUG_KIND_TAGGED) - return debug_type_samep (info, t1->u.knamed->type, t2); - else if (t1->kind == DEBUG_KIND_TAGGED - && t2->kind == DEBUG_KIND_NAMED) - return debug_type_samep (info, t1, t2->u.knamed->type); - - if (t1->kind != t2->kind - || t1->size != t2->size) - return false; - - /* Get rid of the trivial cases first. */ - switch (t1->kind) - { - default: - break; - case DEBUG_KIND_VOID: - case DEBUG_KIND_FLOAT: - case DEBUG_KIND_COMPLEX: - case DEBUG_KIND_BOOL: - return true; - case DEBUG_KIND_INT: - return t1->u.kint == t2->u.kint; - } - - /* We have to avoid an infinite recursion. We do this by keeping a - list of types which we are comparing. We just keep the list on - the stack. If we encounter a pair of types we are currently - comparing, we just assume that they are equal. */ - for (l = info->compare_list; l != NULL; l = l->next) - { - if (l->t1 == t1 && l->t2 == t2) - return true; - } - - top.t1 = t1; - top.t2 = t2; - top.next = info->compare_list; - info->compare_list = ⊤ - - switch (t1->kind) - { - default: - abort (); - ret = false; - break; - - case DEBUG_KIND_STRUCT: - case DEBUG_KIND_UNION: - case DEBUG_KIND_CLASS: - case DEBUG_KIND_UNION_CLASS: - if (t1->u.kclass == NULL) - ret = t2->u.kclass == NULL; - else if (t2->u.kclass == NULL) - ret = false; - else if (t1->u.kclass->id > info->base_id - && t1->u.kclass->id == t2->u.kclass->id) - ret = true; - else - ret = debug_class_type_samep (info, t1, t2); - break; - - case DEBUG_KIND_ENUM: - if (t1->u.kenum == NULL) - ret = t2->u.kenum == NULL; - else if (t2->u.kenum == NULL) - ret = false; - else - { - const char **pn1, **pn2; - bfd_signed_vma *pv1, *pv2; - - pn1 = t1->u.kenum->names; - pn2 = t2->u.kenum->names; - pv1 = t1->u.kenum->values; - pv2 = t2->u.kenum->values; - while (*pn1 != NULL && *pn2 != NULL) - { - if (**pn1 != **pn2 - || *pv1 != *pv2 - || strcmp (*pn1, *pn2) != 0) - break; - ++pn1; - ++pn2; - ++pv1; - ++pv2; - } - ret = *pn1 == NULL && *pn2 == NULL; - } - break; - - case DEBUG_KIND_POINTER: - ret = debug_type_samep (info, t1->u.kpointer, t2->u.kpointer); - break; - - case DEBUG_KIND_FUNCTION: - if (t1->u.kfunction->varargs != t2->u.kfunction->varargs - || ! debug_type_samep (info, t1->u.kfunction->return_type, - t2->u.kfunction->return_type) - || ((t1->u.kfunction->arg_types == NULL) - != (t2->u.kfunction->arg_types == NULL))) - ret = false; - else if (t1->u.kfunction->arg_types == NULL) - ret = true; - else - { - struct debug_type **a1, **a2; - - a1 = t1->u.kfunction->arg_types; - a2 = t2->u.kfunction->arg_types; - while (*a1 != NULL && *a2 != NULL) - if (! debug_type_samep (info, *a1, *a2)) - break; - ret = *a1 == NULL && *a2 == NULL; - } - break; - - case DEBUG_KIND_REFERENCE: - ret = debug_type_samep (info, t1->u.kreference, t2->u.kreference); - break; - - case DEBUG_KIND_RANGE: - ret = (t1->u.krange->lower == t2->u.krange->lower - && t1->u.krange->upper == t2->u.krange->upper - && debug_type_samep (info, t1->u.krange->type, - t2->u.krange->type)); - - case DEBUG_KIND_ARRAY: - ret = (t1->u.karray->lower == t2->u.karray->lower - && t1->u.karray->upper == t2->u.karray->upper - && t1->u.karray->stringp == t2->u.karray->stringp - && debug_type_samep (info, t1->u.karray->element_type, - t2->u.karray->element_type)); - break; - - case DEBUG_KIND_SET: - ret = (t1->u.kset->bitstringp == t2->u.kset->bitstringp - && debug_type_samep (info, t1->u.kset->type, t2->u.kset->type)); - break; - - case DEBUG_KIND_OFFSET: - ret = (debug_type_samep (info, t1->u.koffset->base_type, - t2->u.koffset->base_type) - && debug_type_samep (info, t1->u.koffset->target_type, - t2->u.koffset->target_type)); - break; - - case DEBUG_KIND_METHOD: - if (t1->u.kmethod->varargs != t2->u.kmethod->varargs - || ! debug_type_samep (info, t1->u.kmethod->return_type, - t2->u.kmethod->return_type) - || ! debug_type_samep (info, t1->u.kmethod->domain_type, - t2->u.kmethod->domain_type) - || ((t1->u.kmethod->arg_types == NULL) - != (t2->u.kmethod->arg_types == NULL))) - ret = false; - else if (t1->u.kmethod->arg_types == NULL) - ret = true; - else - { - struct debug_type **a1, **a2; - - a1 = t1->u.kmethod->arg_types; - a2 = t2->u.kmethod->arg_types; - while (*a1 != NULL && *a2 != NULL) - if (! debug_type_samep (info, *a1, *a2)) - break; - ret = *a1 == NULL && *a2 == NULL; - } - break; - - case DEBUG_KIND_CONST: - ret = debug_type_samep (info, t1->u.kconst, t2->u.kconst); - break; - - case DEBUG_KIND_VOLATILE: - ret = debug_type_samep (info, t1->u.kvolatile, t2->u.kvolatile); - break; - - case DEBUG_KIND_NAMED: - case DEBUG_KIND_TAGGED: - ret = (strcmp (t1->u.knamed->name->name, t2->u.knamed->name->name) == 0 - && debug_type_samep (info, t1->u.knamed->type, - t2->u.knamed->type)); - break; - } - - info->compare_list = top.next; - - return ret; -} - -/* See if two classes are the same. This is a subroutine of - debug_type_samep. */ - -static boolean -debug_class_type_samep (info, t1, t2) - struct debug_handle *info; - struct debug_type *t1; - struct debug_type *t2; -{ - struct debug_class_type *c1, *c2; - - c1 = t1->u.kclass; - c2 = t2->u.kclass; - - if ((c1->fields == NULL) != (c2->fields == NULL) - || (c1->baseclasses == NULL) != (c2->baseclasses == NULL) - || (c1->methods == NULL) != (c2->methods == NULL) - || (c1->vptrbase == NULL) != (c2->vptrbase == NULL)) - return false; - - if (c1->fields != NULL) - { - struct debug_field **pf1, **pf2; - - for (pf1 = c1->fields, pf2 = c2->fields; - *pf1 != NULL && *pf2 != NULL; - pf1++, pf2++) - { - struct debug_field *f1, *f2; - - f1 = *pf1; - f2 = *pf2; - if (f1->name[0] != f2->name[0] - || f1->visibility != f2->visibility - || f1->static_member != f2->static_member) - return false; - if (f1->static_member) - { - if (strcmp (f1->u.s.physname, f2->u.s.physname) != 0) - return false; - } - else - { - if (f1->u.f.bitpos != f2->u.f.bitpos - || f1->u.f.bitsize != f2->u.f.bitsize) - return false; - } - /* We do the checks which require function calls last. We - don't require that the types of fields have the same - names, since that sometimes fails in the presence of - typedefs and we really don't care. */ - if (strcmp (f1->name, f2->name) != 0 - || ! debug_type_samep (info, - debug_get_real_type ((PTR) info, - f1->type), - debug_get_real_type ((PTR) info, - f2->type))) - return false; - } - if (*pf1 != NULL || *pf2 != NULL) - return false; - } - - if (c1->vptrbase != NULL) - { - if (! debug_type_samep (info, c1->vptrbase, c2->vptrbase)) - return false; - } - - if (c1->baseclasses != NULL) - { - struct debug_baseclass **pb1, **pb2; - - for (pb1 = c1->baseclasses, pb2 = c2->baseclasses; - *pb1 != NULL && *pb2 != NULL; - ++pb1, ++pb2) - { - struct debug_baseclass *b1, *b2; - - b1 = *pb1; - b2 = *pb2; - if (b1->bitpos != b2->bitpos - || b1->virtual != b2->virtual - || b1->visibility != b2->visibility - || ! debug_type_samep (info, b1->type, b2->type)) - return false; - } - if (*pb1 != NULL || *pb2 != NULL) - return false; - } - - if (c1->methods != NULL) - { - struct debug_method **pm1, **pm2; - - for (pm1 = c1->methods, pm2 = c2->methods; - *pm1 != NULL && *pm2 != NULL; - ++pm1, ++pm2) - { - struct debug_method *m1, *m2; - - m1 = *pm1; - m2 = *pm2; - if (m1->name[0] != m2->name[0] - || strcmp (m1->name, m2->name) != 0 - || (m1->variants == NULL) != (m2->variants == NULL)) - return false; - if (m1->variants == NULL) - { - struct debug_method_variant **pv1, **pv2; - - for (pv1 = m1->variants, pv2 = m2->variants; - *pv1 != NULL && *pv2 != NULL; - ++pv1, ++pv2) - { - struct debug_method_variant *v1, *v2; - - v1 = *pv1; - v2 = *pv2; - if (v1->physname[0] != v2->physname[0] - || v1->visibility != v2->visibility - || v1->constp != v2->constp - || v1->volatilep != v2->volatilep - || v1->voffset != v2->voffset - || (v1->context == NULL) != (v2->context == NULL) - || strcmp (v1->physname, v2->physname) != 0 - || ! debug_type_samep (info, v1->type, v2->type)) - return false; - if (v1->context != NULL) - { - if (! debug_type_samep (info, v1->context, - v2->context)) - return false; - } - } - if (*pv1 != NULL || *pv2 != NULL) - return false; - } - } - if (*pm1 != NULL || *pm2 != NULL) - return false; - } - - return true; -} diff --git a/pstack/debug.h b/pstack/debug.h deleted file mode 100644 index a4d3d8306cd..00000000000 --- a/pstack/debug.h +++ /dev/null @@ -1,798 +0,0 @@ -/* debug.h -- Describe generic debugging information. - Copyright (C) 1995, 1996 Free Software Foundation, Inc. - Written by Ian Lance Taylor <ian@cygnus.com>. - - This file is part of GNU Binutils. - - 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. */ - -#ifndef DEBUG_H -#define DEBUG_H - -/* This header file describes a generic debugging information format. - We may eventually have readers which convert different formats into - this generic format, and writers which write it out. The initial - impetus for this was writing a convertor from stabs to HP IEEE-695 - debugging format. */ - -/* Different kinds of types. */ - -enum debug_type_kind -{ - /* Not used. */ - DEBUG_KIND_ILLEGAL, - /* Indirect via a pointer. */ - DEBUG_KIND_INDIRECT, - /* Void. */ - DEBUG_KIND_VOID, - /* Integer. */ - DEBUG_KIND_INT, - /* Floating point. */ - DEBUG_KIND_FLOAT, - /* Complex. */ - DEBUG_KIND_COMPLEX, - /* Boolean. */ - DEBUG_KIND_BOOL, - /* Struct. */ - DEBUG_KIND_STRUCT, - /* Union. */ - DEBUG_KIND_UNION, - /* Class. */ - DEBUG_KIND_CLASS, - /* Union class (can this really happen?). */ - DEBUG_KIND_UNION_CLASS, - /* Enumeration type. */ - DEBUG_KIND_ENUM, - /* Pointer. */ - DEBUG_KIND_POINTER, - /* Function. */ - DEBUG_KIND_FUNCTION, - /* Reference. */ - DEBUG_KIND_REFERENCE, - /* Range. */ - DEBUG_KIND_RANGE, - /* Array. */ - DEBUG_KIND_ARRAY, - /* Set. */ - DEBUG_KIND_SET, - /* Based pointer. */ - DEBUG_KIND_OFFSET, - /* Method. */ - DEBUG_KIND_METHOD, - /* Const qualified type. */ - DEBUG_KIND_CONST, - /* Volatile qualified type. */ - DEBUG_KIND_VOLATILE, - /* Named type. */ - DEBUG_KIND_NAMED, - /* Tagged type. */ - DEBUG_KIND_TAGGED -}; - -/* Different kinds of variables. */ - -enum debug_var_kind -{ - /* Not used. */ - DEBUG_VAR_ILLEGAL, - /* A global variable. */ - DEBUG_GLOBAL, - /* A static variable. */ - DEBUG_STATIC, - /* A local static variable. */ - DEBUG_LOCAL_STATIC, - /* A local variable. */ - DEBUG_LOCAL, - /* A register variable. */ - DEBUG_REGISTER -}; - -/* Different kinds of function parameters. */ - -enum debug_parm_kind -{ - /* Not used. */ - DEBUG_PARM_ILLEGAL, - /* A stack based parameter. */ - DEBUG_PARM_STACK, - /* A register parameter. */ - DEBUG_PARM_REG, - /* A stack based reference parameter. */ - DEBUG_PARM_REFERENCE, - /* A register reference parameter. */ - DEBUG_PARM_REF_REG -}; - -/* Different kinds of visibility. */ - -enum debug_visibility -{ - /* A public field (e.g., a field in a C struct). */ - DEBUG_VISIBILITY_PUBLIC, - /* A protected field. */ - DEBUG_VISIBILITY_PROTECTED, - /* A private field. */ - DEBUG_VISIBILITY_PRIVATE, - /* A field which should be ignored. */ - DEBUG_VISIBILITY_IGNORE -}; - -/* A type. */ - -typedef struct debug_type *debug_type; - -#define DEBUG_TYPE_NULL ((debug_type) NULL) - -/* A field in a struct or union. */ - -typedef struct debug_field *debug_field; - -#define DEBUG_FIELD_NULL ((debug_field) NULL) - -/* A base class for an object. */ - -typedef struct debug_baseclass *debug_baseclass; - -#define DEBUG_BASECLASS_NULL ((debug_baseclass) NULL) - -/* A method of an object. */ - -typedef struct debug_method *debug_method; - -#define DEBUG_METHOD_NULL ((debug_method) NULL) - -/* The arguments to a method function of an object. These indicate - which method to run. */ - -typedef struct debug_method_variant *debug_method_variant; - -#define DEBUG_METHOD_VARIANT_NULL ((debug_method_variant) NULL) - -/* This structure is passed to debug_write. It holds function - pointers that debug_write will call based on the accumulated - debugging information. */ - -struct debug_write_fns -{ - /* This is called at the start of each new compilation unit with the - name of the main file in the new unit. */ - boolean (*start_compilation_unit) PARAMS ((PTR, const char *)); - - /* This is called at the start of each source file within a - compilation unit, before outputting any global information for - that file. The argument is the name of the file. */ - boolean (*start_source) PARAMS ((PTR, const char *)); - - /* Each writer must keep a stack of types. */ - - /* Push an empty type onto the type stack. This type can appear if - there is a reference to a type which is never defined. */ - boolean (*empty_type) PARAMS ((PTR)); - - /* Push a void type onto the type stack. */ - boolean (*void_type) PARAMS ((PTR)); - - /* Push an integer type onto the type stack, given the size and - whether it is unsigned. */ - boolean (*int_type) PARAMS ((PTR, unsigned int, boolean)); - - /* Push a floating type onto the type stack, given the size. */ - boolean (*float_type) PARAMS ((PTR, unsigned int)); - - /* Push a complex type onto the type stack, given the size. */ - boolean (*complex_type) PARAMS ((PTR, unsigned int)); - - /* Push a boolean type onto the type stack, given the size. */ - boolean (*bool_type) PARAMS ((PTR, unsigned int)); - - /* Push an enum type onto the type stack, given the tag, a NULL - terminated array of names and the associated values. If there is - no tag, the tag argument will be NULL. If this is an undefined - enum, the names and values arguments will be NULL. */ - boolean (*enum_type) PARAMS ((PTR, const char *, const char **, - bfd_signed_vma *)); - - /* Pop the top type on the type stack, and push a pointer to that - type onto the type stack. */ - boolean (*pointer_type) PARAMS ((PTR)); - - /* Push a function type onto the type stack. The second argument - indicates the number of argument types that have been pushed onto - the stack. If the number of argument types is passed as -1, then - the argument types of the function are unknown, and no types have - been pushed onto the stack. The third argument is true if the - function takes a variable number of arguments. The return type - of the function is pushed onto the type stack below the argument - types, if any. */ - boolean (*function_type) PARAMS ((PTR, int, boolean)); - - /* Pop the top type on the type stack, and push a reference to that - type onto the type stack. */ - boolean (*reference_type) PARAMS ((PTR)); - - /* Pop the top type on the type stack, and push a range of that type - with the given lower and upper bounds onto the type stack. */ - boolean (*range_type) PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma)); - - /* Push an array type onto the type stack. The top type on the type - stack is the range, and the next type on the type stack is the - element type. These should be popped before the array type is - pushed. The arguments are the lower bound, the upper bound, and - whether the array is a string. */ - boolean (*array_type) PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, - boolean)); - - /* Pop the top type on the type stack, and push a set of that type - onto the type stack. The argument indicates whether this set is - a bitstring. */ - boolean (*set_type) PARAMS ((PTR, boolean)); - - /* Push an offset type onto the type stack. The top type on the - type stack is the target type, and the next type on the type - stack is the base type. These should be popped before the offset - type is pushed. */ - boolean (*offset_type) PARAMS ((PTR)); - - /* Push a method type onto the type stack. If the second argument - is true, the top type on the stack is the class to which the - method belongs; otherwise, the class must be determined by the - class to which the method is attached. The third argument is the - number of argument types; these are pushed onto the type stack in - reverse order (the first type popped is the last argument to the - method). A value of -1 for the third argument means that no - argument information is available. The fourth argument is true - if the function takes a variable number of arguments. The next - type on the type stack below the domain and the argument types is - the return type of the method. All these types must be popped, - and then the method type must be pushed. */ - boolean (*method_type) PARAMS ((PTR, boolean, int, boolean)); - - /* Pop the top type off the type stack, and push a const qualified - version of that type onto the type stack. */ - boolean (*const_type) PARAMS ((PTR)); - - /* Pop the top type off the type stack, and push a volatile - qualified version of that type onto the type stack. */ - boolean (*volatile_type) PARAMS ((PTR)); - - /* Start building a struct. This is followed by calls to the - struct_field function, and finished by a call to the - end_struct_type function. The second argument is the tag; this - will be NULL if there isn't one. If the second argument is NULL, - the third argument is a constant identifying this struct for use - with tag_type. The fourth argument is true for a struct, false - for a union. The fifth argument is the size. If this is an - undefined struct or union, the size will be 0 and struct_field - will not be called before end_struct_type is called. */ - boolean (*start_struct_type) PARAMS ((PTR, const char *, unsigned int, - boolean, unsigned int)); - - /* Add a field to the struct type currently being built. The type - of the field should be popped off the type stack. The arguments - are the name, the bit position, the bit size (may be zero if the - field is not packed), and the visibility. */ - boolean (*struct_field) PARAMS ((PTR, const char *, bfd_vma, bfd_vma, - enum debug_visibility)); - - /* Finish building a struct, and push it onto the type stack. */ - boolean (*end_struct_type) PARAMS ((PTR)); - - /* Start building a class. This is followed by calls to several - functions: struct_field, class_static_member, class_baseclass, - class_start_method, class_method_variant, - class_static_method_variant, and class_end_method. The class is - finished by a call to end_class_type. The first five arguments - are the same as for start_struct_type. The sixth argument is - true if there is a virtual function table; if there is, the - seventh argument is true if the virtual function table can be - found in the type itself, and is false if the type of the object - holding the virtual function table should be popped from the type - stack. */ - boolean (*start_class_type) PARAMS ((PTR, const char *, unsigned int, - boolean, unsigned int, boolean, - boolean)); - - /* Add a static member to the class currently being built. The - arguments are the field name, the physical name, and the - visibility. The type must be popped off the type stack. */ - boolean (*class_static_member) PARAMS ((PTR, const char *, const char *, - enum debug_visibility)); - - /* Add a baseclass to the class currently being built. The type of - the baseclass must be popped off the type stack. The arguments - are the bit position, whether the class is virtual, and the - visibility. */ - boolean (*class_baseclass) PARAMS ((PTR, bfd_vma, boolean, - enum debug_visibility)); - - /* Start adding a method to the class currently being built. This - is followed by calls to class_method_variant and - class_static_method_variant to describe different variants of the - method which take different arguments. The method is finished - with a call to class_end_method. The argument is the method - name. */ - boolean (*class_start_method) PARAMS ((PTR, const char *)); - - /* Describe a variant to the class method currently being built. - The type of the variant must be popped off the type stack. The - second argument is the physical name of the function. The - following arguments are the visibility, whether the variant is - const, whether the variant is volatile, the offset in the virtual - function table, and whether the context is on the type stack - (below the variant type). */ - boolean (*class_method_variant) PARAMS ((PTR, const char *, - enum debug_visibility, - boolean, boolean, - bfd_vma, boolean)); - - /* Describe a static variant to the class method currently being - built. The arguments are the same as for class_method_variant, - except that the last two arguments are omitted. The type of the - variant must be popped off the type stack. */ - boolean (*class_static_method_variant) PARAMS ((PTR, const char *, - enum debug_visibility, - boolean, boolean)); - - /* Finish describing a class method. */ - boolean (*class_end_method) PARAMS ((PTR)); - - /* Finish describing a class, and push it onto the type stack. */ - boolean (*end_class_type) PARAMS ((PTR)); - - /* Push a type on the stack which was given a name by an earlier - call to typdef. */ - boolean (*typedef_type) PARAMS ((PTR, const char *)); - - /* Push a tagged type on the stack which was defined earlier. If - the second argument is not NULL, the type was defined by a call - to tag. If the second argument is NULL, the type was defined by - a call to start_struct_type or start_class_type with a tag of - NULL and the number of the third argument. Either way, the - fourth argument is the tag kind. Note that this may be called - for a struct (class) being defined, in between the call to - start_struct_type (start_class_type) and the call to - end_struct_type (end_class_type). */ - boolean (*tag_type) PARAMS ((PTR, const char *, unsigned int, - enum debug_type_kind)); - - /* Pop the type stack, and typedef it to the given name. */ - boolean (*typdef) PARAMS ((PTR, const char *)); - - /* Pop the type stack, and declare it as a tagged struct or union or - enum or whatever. The tag passed down here is redundant, since - was also passed when enum_type, start_struct_type, or - start_class_type was called. */ - boolean (*tag) PARAMS ((PTR, const char *)); - - /* This is called to record a named integer constant. */ - boolean (*int_constant) PARAMS ((PTR, const char *, bfd_vma)); - - /* This is called to record a named floating point constant. */ - boolean (*float_constant) PARAMS ((PTR, const char *, double)); - - /* This is called to record a typed integer constant. The type is - popped off the type stack. */ - boolean (*typed_constant) PARAMS ((PTR, const char *, bfd_vma)); - - /* This is called to record a variable. The type is popped off the - type stack. */ - boolean (*variable) PARAMS ((PTR, const char *, enum debug_var_kind, - bfd_vma)); - - /* Start writing out a function. The return type must be popped off - the stack. The boolean is true if the function is global. This - is followed by calls to function_parameter, followed by block - information. */ - boolean (*start_function) PARAMS ((PTR, const char *, boolean)); - - /* Record a function parameter for the current function. The type - must be popped off the stack. */ - boolean (*function_parameter) PARAMS ((PTR, const char *, - enum debug_parm_kind, bfd_vma)); - - /* Start writing out a block. There is at least one top level block - per function. Blocks may be nested. The argument is the - starting address of the block. */ - boolean (*start_block) PARAMS ((PTR, bfd_vma)); - - /* Finish writing out a block. The argument is the ending address - of the block. */ - boolean (*end_block) PARAMS ((PTR, bfd_vma)); - - /* Finish writing out a function. */ - boolean (*end_function) PARAMS ((PTR)); - - /* Record line number information for the current compilation unit. */ - boolean (*lineno) PARAMS ((PTR, const char *, unsigned long, bfd_vma)); -}; - -/* Exported functions. */ - -/* The first argument to most of these functions is a handle. This - handle is returned by the debug_init function. The purpose of the - handle is to permit the debugging routines to not use static - variables, and hence to be reentrant. This would be useful for a - program which wanted to handle two executables simultaneously. */ - -/* Return a debugging handle. */ - -extern PTR debug_init PARAMS ((void)); - -/* Set the source filename. This implicitly starts a new compilation - unit. */ - -extern boolean debug_set_filename PARAMS ((PTR, const char *)); - -/* Change source files to the given file name. This is used for - include files in a single compilation unit. */ - -extern boolean debug_start_source PARAMS ((PTR, const char *)); - -/* Record a function definition. This implicitly starts a function - block. The debug_type argument is the type of the return value. - The boolean indicates whether the function is globally visible. - The bfd_vma is the address of the start of the function. Currently - the parameter types are specified by calls to - debug_record_parameter. */ - -extern boolean debug_record_function - PARAMS ((PTR, const char *, debug_type, boolean, bfd_vma)); - -/* Record a parameter for the current function. */ - -extern boolean debug_record_parameter - PARAMS ((PTR, const char *, debug_type, enum debug_parm_kind, bfd_vma)); - -/* End a function definition. The argument is the address where the - function ends. */ - -extern boolean debug_end_function PARAMS ((PTR, bfd_vma)); - -/* Start a block in a function. All local information will be - recorded in this block, until the matching call to debug_end_block. - debug_start_block and debug_end_block may be nested. The argument - is the address at which this block starts. */ - -extern boolean debug_start_block PARAMS ((PTR, bfd_vma)); - -/* Finish a block in a function. This matches the call to - debug_start_block. The argument is the address at which this block - ends. */ - -extern boolean debug_end_block PARAMS ((PTR, bfd_vma)); - -/* Associate a line number in the current source file with a given - address. */ - -extern boolean debug_record_line PARAMS ((PTR, unsigned long, bfd_vma)); - -/* Start a named common block. This is a block of variables that may - move in memory. */ - -extern boolean debug_start_common_block PARAMS ((PTR, const char *)); - -/* End a named common block. */ - -extern boolean debug_end_common_block PARAMS ((PTR, const char *)); - -/* Record a named integer constant. */ - -extern boolean debug_record_int_const PARAMS ((PTR, const char *, bfd_vma)); - -/* Record a named floating point constant. */ - -extern boolean debug_record_float_const PARAMS ((PTR, const char *, double)); - -/* Record a typed constant with an integral value. */ - -extern boolean debug_record_typed_const - PARAMS ((PTR, const char *, debug_type, bfd_vma)); - -/* Record a label. */ - -extern boolean debug_record_label - PARAMS ((PTR, const char *, debug_type, bfd_vma)); - -/* Record a variable. */ - -extern boolean debug_record_variable - PARAMS ((PTR, const char *, debug_type, enum debug_var_kind, bfd_vma)); - -/* Make an indirect type. The first argument is a pointer to the - location where the real type will be placed. The second argument - is the type tag, if there is one; this may be NULL; the only - purpose of this argument is so that debug_get_type_name can return - something useful. This function may be used when a type is - referenced before it is defined. */ - -extern debug_type debug_make_indirect_type - PARAMS ((PTR, debug_type *, const char *)); - -/* Make a void type. */ - -extern debug_type debug_make_void_type PARAMS ((PTR)); - -/* Make an integer type of a given size. The boolean argument is true - if the integer is unsigned. */ - -extern debug_type debug_make_int_type PARAMS ((PTR, unsigned int, boolean)); - -/* Make a floating point type of a given size. FIXME: On some - platforms, like an Alpha, you probably need to be able to specify - the format. */ - -extern debug_type debug_make_float_type PARAMS ((PTR, unsigned int)); - -/* Make a boolean type of a given size. */ - -extern debug_type debug_make_bool_type PARAMS ((PTR, unsigned int)); - -/* Make a complex type of a given size. */ - -extern debug_type debug_make_complex_type PARAMS ((PTR, unsigned int)); - -/* Make a structure type. The second argument is true for a struct, - false for a union. The third argument is the size of the struct. - The fourth argument is a NULL terminated array of fields. */ - -extern debug_type debug_make_struct_type - PARAMS ((PTR, boolean, bfd_vma, debug_field *)); - -/* Make an object type. The first three arguments after the handle - are the same as for debug_make_struct_type. The next arguments are - a NULL terminated array of base classes, a NULL terminated array of - methods, the type of the object holding the virtual function table - if it is not this object, and a boolean which is true if this - object has its own virtual function table. */ - -extern debug_type debug_make_object_type - PARAMS ((PTR, boolean, bfd_vma, debug_field *, debug_baseclass *, - debug_method *, debug_type, boolean)); - -/* Make an enumeration type. The arguments are a null terminated - array of strings, and an array of corresponding values. */ - -extern debug_type debug_make_enum_type - PARAMS ((PTR, const char **, bfd_signed_vma *)); - -/* Make a pointer to a given type. */ - -extern debug_type debug_make_pointer_type - PARAMS ((PTR, debug_type)); - -/* Make a function type. The second argument is the return type. The - third argument is a NULL terminated array of argument types. The - fourth argument is true if the function takes a variable number of - arguments. If the third argument is NULL, then the argument types - are unknown. */ - -extern debug_type debug_make_function_type - PARAMS ((PTR, debug_type, debug_type *, boolean)); - -/* Make a reference to a given type. */ - -extern debug_type debug_make_reference_type PARAMS ((PTR, debug_type)); - -/* Make a range of a given type from a lower to an upper bound. */ - -extern debug_type debug_make_range_type - PARAMS ((PTR, debug_type, bfd_signed_vma, bfd_signed_vma)); - -/* Make an array type. The second argument is the type of an element - of the array. The third argument is the type of a range of the - array. The fourth and fifth argument are the lower and upper - bounds, respectively (if the bounds are not known, lower should be - 0 and upper should be -1). The sixth argument is true if this - array is actually a string, as in C. */ - -extern debug_type debug_make_array_type - PARAMS ((PTR, debug_type, debug_type, bfd_signed_vma, bfd_signed_vma, - boolean)); - -/* Make a set of a given type. For example, a Pascal set type. The - boolean argument is true if this set is actually a bitstring, as in - CHILL. */ - -extern debug_type debug_make_set_type PARAMS ((PTR, debug_type, boolean)); - -/* Make a type for a pointer which is relative to an object. The - second argument is the type of the object to which the pointer is - relative. The third argument is the type that the pointer points - to. */ - -extern debug_type debug_make_offset_type - PARAMS ((PTR, debug_type, debug_type)); - -/* Make a type for a method function. The second argument is the - return type. The third argument is the domain. The fourth - argument is a NULL terminated array of argument types. The fifth - argument is true if the function takes a variable number of - arguments, in which case the array of argument types indicates the - types of the first arguments. The domain and the argument array - may be NULL, in which case this is a stub method and that - information is not available. Stabs debugging uses this, and gets - the argument types from the mangled name. */ - -extern debug_type debug_make_method_type - PARAMS ((PTR, debug_type, debug_type, debug_type *, boolean)); - -/* Make a const qualified version of a given type. */ - -extern debug_type debug_make_const_type PARAMS ((PTR, debug_type)); - -/* Make a volatile qualified version of a given type. */ - -extern debug_type debug_make_volatile_type PARAMS ((PTR, debug_type)); - -/* Make an undefined tagged type. For example, a struct which has - been mentioned, but not defined. */ - -extern debug_type debug_make_undefined_tagged_type - PARAMS ((PTR, const char *, enum debug_type_kind)); - -/* Make a base class for an object. The second argument is the base - class type. The third argument is the bit position of this base - class in the object. The fourth argument is whether this is a - virtual class. The fifth argument is the visibility of the base - class. */ - -extern debug_baseclass debug_make_baseclass - PARAMS ((PTR, debug_type, bfd_vma, boolean, enum debug_visibility)); - -/* Make a field for a struct. The second argument is the name. The - third argument is the type of the field. The fourth argument is - the bit position of the field. The fifth argument is the size of - the field (it may be zero). The sixth argument is the visibility - of the field. */ - -extern debug_field debug_make_field - PARAMS ((PTR, const char *, debug_type, bfd_vma, bfd_vma, - enum debug_visibility)); - -/* Make a static member of an object. The second argument is the - name. The third argument is the type of the member. The fourth - argument is the physical name of the member (i.e., the name as a - global variable). The fifth argument is the visibility of the - member. */ - -extern debug_field debug_make_static_member - PARAMS ((PTR, const char *, debug_type, const char *, - enum debug_visibility)); - -/* Make a method. The second argument is the name, and the third - argument is a NULL terminated array of method variants. Each - method variant is a method with this name but with different - argument types. */ - -extern debug_method debug_make_method - PARAMS ((PTR, const char *, debug_method_variant *)); - -/* Make a method variant. The second argument is the physical name of - the function. The third argument is the type of the function, - probably constructed by debug_make_method_type. The fourth - argument is the visibility. The fifth argument is whether this is - a const function. The sixth argument is whether this is a volatile - function. The seventh argument is the index in the virtual - function table, if any. The eighth argument is the virtual - function context. */ - -extern debug_method_variant debug_make_method_variant - PARAMS ((PTR, const char *, debug_type, enum debug_visibility, boolean, - boolean, bfd_vma, debug_type)); - -/* Make a static method argument. The arguments are the same as for - debug_make_method_variant, except that the last two are omitted - since a static method can not also be virtual. */ - -extern debug_method_variant debug_make_static_method_variant - PARAMS ((PTR, const char *, debug_type, enum debug_visibility, boolean, - boolean)); - -/* Name a type. This returns a new type with an attached name. */ - -extern debug_type debug_name_type PARAMS ((PTR, const char *, debug_type)); - -/* Give a tag to a type, such as a struct or union. This returns a - new type with an attached tag. */ - -extern debug_type debug_tag_type PARAMS ((PTR, const char *, debug_type)); - -/* Record the size of a given type. */ - -extern boolean debug_record_type_size PARAMS ((PTR, debug_type, unsigned int)); - -/* Find a named type. */ - -extern debug_type debug_find_named_type PARAMS ((PTR, const char *)); - -/* Find a tagged type. */ - -extern debug_type debug_find_tagged_type - PARAMS ((PTR, const char *, enum debug_type_kind)); - -/* Get the kind of a type. */ - -extern enum debug_type_kind debug_get_type_kind PARAMS ((PTR, debug_type)); - -/* Get the name of a type. */ - -extern const char *debug_get_type_name PARAMS ((PTR, debug_type)); - -/* Get the size of a type. */ - -extern bfd_vma debug_get_type_size PARAMS ((PTR, debug_type)); - -/* Get the return type of a function or method type. */ - -extern debug_type debug_get_return_type PARAMS ((PTR, debug_type)); - -/* Get the NULL terminated array of parameter types for a function or - method type (actually, parameter types are not currently stored for - function types). This may be used to determine whether a method - type is a stub method or not. The last argument points to a - boolean which is set to true if the function takes a variable - number of arguments. */ - -extern const debug_type *debug_get_parameter_types PARAMS ((PTR, - debug_type, - boolean *)); - -/* Get the target type of a pointer or reference or const or volatile - type. */ - -extern debug_type debug_get_target_type PARAMS ((PTR, debug_type)); - -/* Get the NULL terminated array of fields for a struct, union, or - class. */ - -extern const debug_field *debug_get_fields PARAMS ((PTR, debug_type)); - -/* Get the type of a field. */ - -extern debug_type debug_get_field_type PARAMS ((PTR, debug_field)); - -/* Get the name of a field. */ - -extern const char *debug_get_field_name PARAMS ((PTR, debug_field)); - -/* Get the bit position of a field within the containing structure. - If the field is a static member, this will return (bfd_vma) -1. */ - -extern bfd_vma debug_get_field_bitpos PARAMS ((PTR, debug_field)); - -/* Get the bit size of a field. If the field is a static member, this - will return (bfd_vma) -1. */ - -extern bfd_vma debug_get_field_bitsize PARAMS ((PTR, debug_field)); - -/* Get the visibility of a field. */ - -extern enum debug_visibility debug_get_field_visibility - PARAMS ((PTR, debug_field)); - -/* Get the physical name of a field, if it is a static member. If the - field is not a static member, this will return NULL. */ - -extern const char *debug_get_field_physname PARAMS ((PTR, debug_field)); - -/* Write out the recorded debugging information. This takes a set of - function pointers which are called to do the actual writing. The - first PTR is the debugging handle. The second PTR is a handle - which is passed to the functions. */ - -extern boolean debug_write PARAMS ((PTR, const struct debug_write_fns *, PTR)); - -#endif /* DEBUG_H */ diff --git a/pstack/demangle.h b/pstack/demangle.h deleted file mode 100644 index a961436ca77..00000000000 --- a/pstack/demangle.h +++ /dev/null @@ -1,90 +0,0 @@ -/* Defs for interface to demanglers. - Copyright 1992, 1995, 1996 Free Software Foundation, Inc. - - 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, 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. */ - - -#if !defined (DEMANGLE_H) -#define DEMANGLE_H - -#ifdef IN_GCC -#include "gansidecl.h" -#define PARAMS(ARGS) PROTO(ARGS) -#else /* ! IN_GCC */ -#include <ansidecl.h> -#endif /* IN_GCC */ - -/* Options passed to cplus_demangle (in 2nd parameter). */ - -#define DMGL_NO_OPTS 0 /* For readability... */ -#define DMGL_PARAMS (1 << 0) /* Include function args */ -#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ -#define DMGL_JAVA (1 << 2) /* Demangle as Java rather than C++. */ - -#define DMGL_AUTO (1 << 8) -#define DMGL_GNU (1 << 9) -#define DMGL_LUCID (1 << 10) -#define DMGL_ARM (1 << 11) -/* If none of these are set, use 'current_demangling_style' as the default. */ -#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM) - -/* Enumeration of possible demangling styles. - - Lucid and ARM styles are still kept logically distinct, even though - they now both behave identically. The resulting style is actual the - union of both. I.E. either style recognizes both "__pt__" and "__rf__" - for operator "->", even though the first is lucid style and the second - is ARM style. (FIXME?) */ - -extern enum demangling_styles -{ - unknown_demangling = 0, - auto_demangling = DMGL_AUTO, - gnu_demangling = DMGL_GNU, - lucid_demangling = DMGL_LUCID, - arm_demangling = DMGL_ARM -} current_demangling_style; - -/* Define string names for the various demangling styles. */ - -#define AUTO_DEMANGLING_STYLE_STRING "auto" -#define GNU_DEMANGLING_STYLE_STRING "gnu" -#define LUCID_DEMANGLING_STYLE_STRING "lucid" -#define ARM_DEMANGLING_STYLE_STRING "arm" - -/* Some macros to test what demangling style is active. */ - -#define CURRENT_DEMANGLING_STYLE current_demangling_style -#define AUTO_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_AUTO) -#define GNU_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU) -#define LUCID_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_LUCID) -#define ARM_DEMANGLING (CURRENT_DEMANGLING_STYLE & DMGL_ARM) - -extern char * -cplus_demangle PARAMS ((const char *mangled, int options)); - -extern int -cplus_demangle_opname PARAMS ((const char *opname, char *result, int options)); - -extern const char * -cplus_mangle_opname PARAMS ((const char *opname, int options)); - -/* Note: This sets global state. FIXME if you care about multi-threading. */ - -extern void -set_cplus_marker_for_demangling PARAMS ((int ch)); - -#endif /* DEMANGLE_H */ diff --git a/pstack/filemode.c b/pstack/filemode.c deleted file mode 100644 index 58b52ba7489..00000000000 --- a/pstack/filemode.c +++ /dev/null @@ -1,266 +0,0 @@ -/* filemode.c -- make a string describing file modes - Copyright (C) 1985, 90, 91, 94, 95, 1997 Free Software Foundation, Inc. - - 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, 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 "bfd.h" -#include "bucomm.h" - -static char ftypelet PARAMS ((unsigned long)); -static void setst PARAMS ((unsigned long, char *)); - -/* filemodestring - fill in string STR with an ls-style ASCII - representation of the st_mode field of file stats block STATP. - 10 characters are stored in STR; no terminating null is added. - The characters stored in STR are: - - 0 File type. 'd' for directory, 'c' for character - special, 'b' for block special, 'm' for multiplex, - 'l' for symbolic link, 's' for socket, 'p' for fifo, - '-' for any other file type - - 1 'r' if the owner may read, '-' otherwise. - - 2 'w' if the owner may write, '-' otherwise. - - 3 'x' if the owner may execute, 's' if the file is - set-user-id, '-' otherwise. - 'S' if the file is set-user-id, but the execute - bit isn't set. - - 4 'r' if group members may read, '-' otherwise. - - 5 'w' if group members may write, '-' otherwise. - - 6 'x' if group members may execute, 's' if the file is - set-group-id, '-' otherwise. - 'S' if it is set-group-id but not executable. - - 7 'r' if any user may read, '-' otherwise. - - 8 'w' if any user may write, '-' otherwise. - - 9 'x' if any user may execute, 't' if the file is "sticky" - (will be retained in swap space after execution), '-' - otherwise. - 'T' if the file is sticky but not executable. */ - -#if 0 - -/* This is not used; only mode_string is used. */ - -void -filemodestring (statp, str) - struct stat *statp; - char *str; -{ - mode_string ((unsigned long) statp->st_mode, str); -} - -#endif - -/* Get definitions for the file permission bits. */ - -#ifndef S_IRWXU -#define S_IRWXU 0700 -#endif -#ifndef S_IRUSR -#define S_IRUSR 0400 -#endif -#ifndef S_IWUSR -#define S_IWUSR 0200 -#endif -#ifndef S_IXUSR -#define S_IXUSR 0100 -#endif - -#ifndef S_IRWXG -#define S_IRWXG 0070 -#endif -#ifndef S_IRGRP -#define S_IRGRP 0040 -#endif -#ifndef S_IWGRP -#define S_IWGRP 0020 -#endif -#ifndef S_IXGRP -#define S_IXGRP 0010 -#endif - -#ifndef S_IRWXO -#define S_IRWXO 0007 -#endif -#ifndef S_IROTH -#define S_IROTH 0004 -#endif -#ifndef S_IWOTH -#define S_IWOTH 0002 -#endif -#ifndef S_IXOTH -#define S_IXOTH 0001 -#endif - -/* Like filemodestring, but only the relevant part of the `struct stat' - is given as an argument. */ - -void -mode_string (mode, str) - unsigned long mode; - char *str; -{ - str[0] = ftypelet ((unsigned long) mode); - str[1] = (mode & S_IRUSR) != 0 ? 'r' : '-'; - str[2] = (mode & S_IWUSR) != 0 ? 'w' : '-'; - str[3] = (mode & S_IXUSR) != 0 ? 'x' : '-'; - str[4] = (mode & S_IRGRP) != 0 ? 'r' : '-'; - str[5] = (mode & S_IWGRP) != 0 ? 'w' : '-'; - str[6] = (mode & S_IXGRP) != 0 ? 'x' : '-'; - str[7] = (mode & S_IROTH) != 0 ? 'r' : '-'; - str[8] = (mode & S_IWOTH) != 0 ? 'w' : '-'; - str[9] = (mode & S_IXOTH) != 0 ? 'x' : '-'; - setst ((unsigned long) mode, str); -} - -/* Return a character indicating the type of file described by - file mode BITS: - 'd' for directories - 'b' for block special files - 'c' for character special files - 'm' for multiplexor files - 'l' for symbolic links - 's' for sockets - 'p' for fifos - '-' for any other file type. */ - -#ifndef S_ISDIR -#ifdef S_IFDIR -#define S_ISDIR(i) (((i) & S_IFMT) == S_IFDIR) -#else /* ! defined (S_IFDIR) */ -#define S_ISDIR(i) (((i) & 0170000) == 040000) -#endif /* ! defined (S_IFDIR) */ -#endif /* ! defined (S_ISDIR) */ - -#ifndef S_ISBLK -#ifdef S_IFBLK -#define S_ISBLK(i) (((i) & S_IFMT) == S_IFBLK) -#else /* ! defined (S_IFBLK) */ -#define S_ISBLK(i) 0 -#endif /* ! defined (S_IFBLK) */ -#endif /* ! defined (S_ISBLK) */ - -#ifndef S_ISCHR -#ifdef S_IFCHR -#define S_ISCHR(i) (((i) & S_IFMT) == S_IFCHR) -#else /* ! defined (S_IFCHR) */ -#define S_ISCHR(i) 0 -#endif /* ! defined (S_IFCHR) */ -#endif /* ! defined (S_ISCHR) */ - -#ifndef S_ISFIFO -#ifdef S_IFIFO -#define S_ISFIFO(i) (((i) & S_IFMT) == S_IFIFO) -#else /* ! defined (S_IFIFO) */ -#define S_ISFIFO(i) 0 -#endif /* ! defined (S_IFIFO) */ -#endif /* ! defined (S_ISFIFO) */ - -#ifndef S_ISSOCK -#ifdef S_IFSOCK -#define S_ISSOCK(i) (((i) & S_IFMT) == S_IFSOCK) -#else /* ! defined (S_IFSOCK) */ -#define S_ISSOCK(i) 0 -#endif /* ! defined (S_IFSOCK) */ -#endif /* ! defined (S_ISSOCK) */ - -#ifndef S_ISLNK -#ifdef S_IFLNK -#define S_ISLNK(i) (((i) & S_IFMT) == S_IFLNK) -#else /* ! defined (S_IFLNK) */ -#define S_ISLNK(i) 0 -#endif /* ! defined (S_IFLNK) */ -#endif /* ! defined (S_ISLNK) */ - -static char -ftypelet (bits) - unsigned long bits; -{ - if (S_ISDIR (bits)) - return 'd'; - if (S_ISLNK (bits)) - return 'l'; - if (S_ISBLK (bits)) - return 'b'; - if (S_ISCHR (bits)) - return 'c'; - if (S_ISSOCK (bits)) - return 's'; - if (S_ISFIFO (bits)) - return 'p'; - -#ifdef S_IFMT -#ifdef S_IFMPC - if ((bits & S_IFMT) == S_IFMPC - || (bits & S_IFMT) == S_IFMPB) - return 'm'; -#endif -#ifdef S_IFNWK - if ((bits & S_IFMT) == S_IFNWK) - return 'n'; -#endif -#endif - - return '-'; -} - -/* Set the 's' and 't' flags in file attributes string CHARS, - according to the file mode BITS. */ - -static void -setst (bits, chars) - unsigned long bits; - char *chars; -{ -#ifdef S_ISUID - if (bits & S_ISUID) - { - if (chars[3] != 'x') - /* Set-uid, but not executable by owner. */ - chars[3] = 'S'; - else - chars[3] = 's'; - } -#endif -#ifdef S_ISGID - if (bits & S_ISGID) - { - if (chars[6] != 'x') - /* Set-gid, but not executable by group. */ - chars[6] = 'S'; - else - chars[6] = 's'; - } -#endif -#ifdef S_ISVTX - if (bits & S_ISVTX) - { - if (chars[9] != 'x') - /* Sticky, but not executable by others. */ - chars[9] = 'T'; - else - chars[9] = 't'; - } -#endif -} diff --git a/pstack/ieee.c b/pstack/ieee.c deleted file mode 100644 index 8084656a5ef..00000000000 --- a/pstack/ieee.c +++ /dev/null @@ -1,7602 +0,0 @@ -/* ieee.c -- Read and write IEEE-695 debugging information. - Copyright (C) 1996 Free Software Foundation, Inc. - Written by Ian Lance Taylor <ian@cygnus.com>. - - This file is part of GNU Binutils. - - 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. */ - -/* This file reads and writes IEEE-695 debugging information. */ - -#include <stdio.h> -#include <assert.h> - -#include <bfd.h> -#include "ieee.h" -#include "bucomm.h" -#include <libiberty.h> -#include "debug.h" -#include "budbg.h" - -/* This structure holds an entry on the block stack. */ - -struct ieee_block -{ - /* The kind of block. */ - int kind; - /* The source file name, for a BB5 block. */ - const char *filename; - /* The index of the function type, for a BB4 or BB6 block. */ - unsigned int fnindx; - /* True if this function is being skipped. */ - boolean skip; -}; - -/* This structure is the block stack. */ - -#define BLOCKSTACK_SIZE (16) - -struct ieee_blockstack -{ - /* The stack pointer. */ - struct ieee_block *bsp; - /* The stack. */ - struct ieee_block stack[BLOCKSTACK_SIZE]; -}; - -/* This structure holds information for a variable. */ - -struct ieee_var -{ - /* Start of name. */ - const char *name; - /* Length of name. */ - unsigned long namlen; - /* Type. */ - debug_type type; - /* Slot if we make an indirect type. */ - debug_type *pslot; - /* Kind of variable or function. */ - enum - { - IEEE_UNKNOWN, - IEEE_EXTERNAL, - IEEE_GLOBAL, - IEEE_STATIC, - IEEE_LOCAL, - IEEE_FUNCTION - } kind; -}; - -/* This structure holds all the variables. */ - -struct ieee_vars -{ - /* Number of slots allocated. */ - unsigned int alloc; - /* Variables. */ - struct ieee_var *vars; -}; - -/* This structure holds information for a type. We need this because - we don't want to represent bitfields as real types. */ - -struct ieee_type -{ - /* Type. */ - debug_type type; - /* Slot if this is type is referenced before it is defined. */ - debug_type *pslot; - /* Slots for arguments if we make indirect types for them. */ - debug_type *arg_slots; - /* If this is a bitfield, this is the size in bits. If this is not - a bitfield, this is zero. */ - unsigned long bitsize; -}; - -/* This structure holds all the type information. */ - -struct ieee_types -{ - /* Number of slots allocated. */ - unsigned int alloc; - /* Types. */ - struct ieee_type *types; - /* Builtin types. */ -#define BUILTIN_TYPE_COUNT (60) - debug_type builtins[BUILTIN_TYPE_COUNT]; -}; - -/* This structure holds a linked last of structs with their tag names, - so that we can convert them to C++ classes if necessary. */ - -struct ieee_tag -{ - /* Next tag. */ - struct ieee_tag *next; - /* This tag name. */ - const char *name; - /* The type of the tag. */ - debug_type type; - /* The tagged type is an indirect type pointing at this slot. */ - debug_type slot; - /* This is an array of slots used when a field type is converted - into a indirect type, in case it needs to be later converted into - a reference type. */ - debug_type *fslots; -}; - -/* This structure holds the information we pass around to the parsing - functions. */ - -struct ieee_info -{ - /* The debugging handle. */ - PTR dhandle; - /* The BFD. */ - bfd *abfd; - /* The start of the bytes to be parsed. */ - const bfd_byte *bytes; - /* The end of the bytes to be parsed. */ - const bfd_byte *pend; - /* The block stack. */ - struct ieee_blockstack blockstack; - /* Whether we have seen a BB1 or BB2. */ - boolean saw_filename; - /* The variables. */ - struct ieee_vars vars; - /* The global variables, after a global typedef block. */ - struct ieee_vars *global_vars; - /* The types. */ - struct ieee_types types; - /* The global types, after a global typedef block. */ - struct ieee_types *global_types; - /* The list of tagged structs. */ - struct ieee_tag *tags; -}; - -/* Basic builtin types, not including the pointers. */ - -enum builtin_types -{ - builtin_unknown = 0, - builtin_void = 1, - builtin_signed_char = 2, - builtin_unsigned_char = 3, - builtin_signed_short_int = 4, - builtin_unsigned_short_int = 5, - builtin_signed_long = 6, - builtin_unsigned_long = 7, - builtin_signed_long_long = 8, - builtin_unsigned_long_long = 9, - builtin_float = 10, - builtin_double = 11, - builtin_long_double = 12, - builtin_long_long_double = 13, - builtin_quoted_string = 14, - builtin_instruction_address = 15, - builtin_int = 16, - builtin_unsigned = 17, - builtin_unsigned_int = 18, - builtin_char = 19, - builtin_long = 20, - builtin_short = 21, - builtin_unsigned_short = 22, - builtin_short_int = 23, - builtin_signed_short = 24, - builtin_bcd_float = 25 -}; - -/* These are the values found in the derivation flags of a 'b' - component record of a 'T' type extension record in a C++ pmisc - record. These are bitmasks. */ - -/* Set for a private base class, clear for a public base class. - Protected base classes are not supported. */ -#define BASEFLAGS_PRIVATE (0x1) -/* Set for a virtual base class. */ -#define BASEFLAGS_VIRTUAL (0x2) -/* Set for a friend class, clear for a base class. */ -#define BASEFLAGS_FRIEND (0x10) - -/* These are the values found in the specs flags of a 'd', 'm', or 'v' - component record of a 'T' type extension record in a C++ pmisc - record. The same flags are used for a 'M' record in a C++ pmisc - record. */ - -/* The lower two bits hold visibility information. */ -#define CXXFLAGS_VISIBILITY (0x3) -/* This value in the lower two bits indicates a public member. */ -#define CXXFLAGS_VISIBILITY_PUBLIC (0x0) -/* This value in the lower two bits indicates a private member. */ -#define CXXFLAGS_VISIBILITY_PRIVATE (0x1) -/* This value in the lower two bits indicates a protected member. */ -#define CXXFLAGS_VISIBILITY_PROTECTED (0x2) -/* Set for a static member. */ -#define CXXFLAGS_STATIC (0x4) -/* Set for a virtual override. */ -#define CXXFLAGS_OVERRIDE (0x8) -/* Set for a friend function. */ -#define CXXFLAGS_FRIEND (0x10) -/* Set for a const function. */ -#define CXXFLAGS_CONST (0x20) -/* Set for a volatile function. */ -#define CXXFLAGS_VOLATILE (0x40) -/* Set for an overloaded function. */ -#define CXXFLAGS_OVERLOADED (0x80) -/* Set for an operator function. */ -#define CXXFLAGS_OPERATOR (0x100) -/* Set for a constructor or destructor. */ -#define CXXFLAGS_CTORDTOR (0x400) -/* Set for a constructor. */ -#define CXXFLAGS_CTOR (0x200) -/* Set for an inline function. */ -#define CXXFLAGS_INLINE (0x800) - -/* Local functions. */ - -static void ieee_error - PARAMS ((struct ieee_info *, const bfd_byte *, const char *)); -static void ieee_eof PARAMS ((struct ieee_info *)); -static char *savestring PARAMS ((const char *, unsigned long)); -static boolean ieee_read_number - PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *)); -static boolean ieee_read_optional_number - PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *, boolean *)); -static boolean ieee_read_id - PARAMS ((struct ieee_info *, const bfd_byte **, const char **, - unsigned long *)); -static boolean ieee_read_optional_id - PARAMS ((struct ieee_info *, const bfd_byte **, const char **, - unsigned long *, boolean *)); -static boolean ieee_read_expression - PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *)); -static debug_type ieee_builtin_type - PARAMS ((struct ieee_info *, const bfd_byte *, unsigned int)); -static boolean ieee_alloc_type - PARAMS ((struct ieee_info *, unsigned int, boolean)); -static boolean ieee_read_type_index - PARAMS ((struct ieee_info *, const bfd_byte **, debug_type *)); -static int ieee_regno_to_genreg PARAMS ((bfd *, int)); -static int ieee_genreg_to_regno PARAMS ((bfd *, int)); -static boolean parse_ieee_bb PARAMS ((struct ieee_info *, const bfd_byte **)); -static boolean parse_ieee_be PARAMS ((struct ieee_info *, const bfd_byte **)); -static boolean parse_ieee_nn PARAMS ((struct ieee_info *, const bfd_byte **)); -static boolean parse_ieee_ty PARAMS ((struct ieee_info *, const bfd_byte **)); -static boolean parse_ieee_atn PARAMS ((struct ieee_info *, const bfd_byte **)); -static boolean ieee_read_cxx_misc - PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long)); -static boolean ieee_read_cxx_class - PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long)); -static boolean ieee_read_cxx_defaults - PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long)); -static boolean ieee_read_reference - PARAMS ((struct ieee_info *, const bfd_byte **)); -static boolean ieee_require_asn - PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *)); -static boolean ieee_require_atn65 - PARAMS ((struct ieee_info *, const bfd_byte **, const char **, - unsigned long *)); - -/* Report an error in the IEEE debugging information. */ - -static void -ieee_error (info, p, s) - struct ieee_info *info; - const bfd_byte *p; - const char *s; -{ - if (p != NULL) - fprintf (stderr, "%s: 0x%lx: %s (0x%x)\n", bfd_get_filename (info->abfd), - (unsigned long) (p - info->bytes), s, *p); - else - fprintf (stderr, "%s: %s\n", bfd_get_filename (info->abfd), s); -} - -/* Report an unexpected EOF in the IEEE debugging information. */ - -static void -ieee_eof (info) - struct ieee_info *info; -{ - ieee_error (info, (const bfd_byte *) NULL, - "unexpected end of debugging information"); -} - -/* Save a string in memory. */ - -static char * -savestring (start, len) - const char *start; - unsigned long len; -{ - char *ret; - - ret = (char *) xmalloc (len + 1); - memcpy (ret, start, len); - ret[len] = '\0'; - return ret; -} - -/* Read a number which must be present in an IEEE file. */ - -static boolean -ieee_read_number (info, pp, pv) - struct ieee_info *info; - const bfd_byte **pp; - bfd_vma *pv; -{ - return ieee_read_optional_number (info, pp, pv, (boolean *) NULL); -} - -/* Read a number in an IEEE file. If ppresent is not NULL, the number - need not be there. */ - -static boolean -ieee_read_optional_number (info, pp, pv, ppresent) - struct ieee_info *info; - const bfd_byte **pp; - bfd_vma *pv; - boolean *ppresent; -{ - ieee_record_enum_type b; - - if (*pp >= info->pend) - { - if (ppresent != NULL) - { - *ppresent = false; - return true; - } - ieee_eof (info); - return false; - } - - b = (ieee_record_enum_type) **pp; - ++*pp; - - if (b <= ieee_number_end_enum) - { - *pv = (bfd_vma) b; - if (ppresent != NULL) - *ppresent = true; - return true; - } - - if (b >= ieee_number_repeat_start_enum && b <= ieee_number_repeat_end_enum) - { - unsigned int i; - - i = (int) b - (int) ieee_number_repeat_start_enum; - if (*pp + i - 1 >= info->pend) - { - ieee_eof (info); - return false; - } - - *pv = 0; - for (; i > 0; i--) - { - *pv <<= 8; - *pv += **pp; - ++*pp; - } - - if (ppresent != NULL) - *ppresent = true; - - return true; - } - - if (ppresent != NULL) - { - --*pp; - *ppresent = false; - return true; - } - - ieee_error (info, *pp - 1, "invalid number"); - return false; -} - -/* Read a required string from an IEEE file. */ - -static boolean -ieee_read_id (info, pp, pname, pnamlen) - struct ieee_info *info; - const bfd_byte **pp; - const char **pname; - unsigned long *pnamlen; -{ - return ieee_read_optional_id (info, pp, pname, pnamlen, (boolean *) NULL); -} - -/* Read a string from an IEEE file. If ppresent is not NULL, the - string is optional. */ - -static boolean -ieee_read_optional_id (info, pp, pname, pnamlen, ppresent) - struct ieee_info *info; - const bfd_byte **pp; - const char **pname; - unsigned long *pnamlen; - boolean *ppresent; -{ - bfd_byte b; - unsigned long len; - - if (*pp >= info->pend) - { - ieee_eof (info); - return false; - } - - b = **pp; - ++*pp; - - if (b <= 0x7f) - len = b; - else if ((ieee_record_enum_type) b == ieee_extension_length_1_enum) - { - len = **pp; - ++*pp; - } - else if ((ieee_record_enum_type) b == ieee_extension_length_2_enum) - { - len = (**pp << 8) + (*pp)[1]; - *pp += 2; - } - else - { - if (ppresent != NULL) - { - --*pp; - *ppresent = false; - return true; - } - ieee_error (info, *pp - 1, "invalid string length"); - return false; - } - - if ((unsigned long) (info->pend - *pp) < len) - { - ieee_eof (info); - return false; - } - - *pname = (const char *) *pp; - *pnamlen = len; - *pp += len; - - if (ppresent != NULL) - *ppresent = true; - - return true; -} - -/* Read an expression from an IEEE file. Since this code is only used - to parse debugging information, I haven't bothered to write a full - blown IEEE expression parser. I've only thrown in the things I've - seen in debugging information. This can be easily extended if - necessary. */ - -static boolean -ieee_read_expression (info, pp, pv) - struct ieee_info *info; - const bfd_byte **pp; - bfd_vma *pv; -{ - const bfd_byte *expr_start; -#define EXPR_STACK_SIZE (10) - bfd_vma expr_stack[EXPR_STACK_SIZE]; - bfd_vma *esp; - - expr_start = *pp; - - esp = expr_stack; - - while (1) - { - const bfd_byte *start; - bfd_vma val; - boolean present; - ieee_record_enum_type c; - - start = *pp; - - if (! ieee_read_optional_number (info, pp, &val, &present)) - return false; - - if (present) - { - if (esp - expr_stack >= EXPR_STACK_SIZE) - { - ieee_error (info, start, "expression stack overflow"); - return false; - } - *esp++ = val; - continue; - } - - c = (ieee_record_enum_type) **pp; - - if (c >= ieee_module_beginning_enum) - break; - - ++*pp; - - if (c == ieee_comma) - break; - - switch (c) - { - default: - ieee_error (info, start, "unsupported IEEE expression operator"); - break; - - case ieee_variable_R_enum: - { - bfd_vma indx; - asection *s; - - if (! ieee_read_number (info, pp, &indx)) - return false; - for (s = info->abfd->sections; s != NULL; s = s->next) - if ((bfd_vma) s->target_index == indx) - break; - if (s == NULL) - { - ieee_error (info, start, "unknown section"); - return false; - } - - if (esp - expr_stack >= EXPR_STACK_SIZE) - { - ieee_error (info, start, "expression stack overflow"); - return false; - } - - *esp++ = bfd_get_section_vma (info->abfd, s); - } - break; - - case ieee_function_plus_enum: - case ieee_function_minus_enum: - { - bfd_vma v1, v2; - - if (esp - expr_stack < 2) - { - ieee_error (info, start, "expression stack underflow"); - return false; - } - - v1 = *--esp; - v2 = *--esp; - *esp++ = v1 + v2; - } - break; - } - } - - if (esp - 1 != expr_stack) - { - ieee_error (info, expr_start, "expression stack mismatch"); - return false; - } - - *pv = *--esp; - - return true; -} - -/* Return an IEEE builtin type. */ - -static debug_type -ieee_builtin_type (info, p, indx) - struct ieee_info *info; - const bfd_byte *p; - unsigned int indx; -{ - PTR dhandle; - debug_type type; - const char *name; - - if (indx < BUILTIN_TYPE_COUNT - && info->types.builtins[indx] != DEBUG_TYPE_NULL) - return info->types.builtins[indx]; - - dhandle = info->dhandle; - - if (indx >= 32 && indx < 64) - { - type = debug_make_pointer_type (dhandle, - ieee_builtin_type (info, p, indx - 32)); - assert (indx < BUILTIN_TYPE_COUNT); - info->types.builtins[indx] = type; - return type; - } - - switch ((enum builtin_types) indx) - { - default: - ieee_error (info, p, "unknown builtin type"); - return NULL; - - case builtin_unknown: - type = debug_make_void_type (dhandle); - name = NULL; - break; - - case builtin_void: - type = debug_make_void_type (dhandle); - name = "void"; - break; - - case builtin_signed_char: - type = debug_make_int_type (dhandle, 1, false); - name = "signed char"; - break; - - case builtin_unsigned_char: - type = debug_make_int_type (dhandle, 1, true); - name = "unsigned char"; - break; - - case builtin_signed_short_int: - type = debug_make_int_type (dhandle, 2, false); - name = "signed short int"; - break; - - case builtin_unsigned_short_int: - type = debug_make_int_type (dhandle, 2, true); - name = "unsigned short int"; - break; - - case builtin_signed_long: - type = debug_make_int_type (dhandle, 4, false); - name = "signed long"; - break; - - case builtin_unsigned_long: - type = debug_make_int_type (dhandle, 4, true); - name = "unsigned long"; - break; - - case builtin_signed_long_long: - type = debug_make_int_type (dhandle, 8, false); - name = "signed long long"; - break; - - case builtin_unsigned_long_long: - type = debug_make_int_type (dhandle, 8, true); - name = "unsigned long long"; - break; - - case builtin_float: - type = debug_make_float_type (dhandle, 4); - name = "float"; - break; - - case builtin_double: - type = debug_make_float_type (dhandle, 8); - name = "double"; - break; - - case builtin_long_double: - /* FIXME: The size for this type should depend upon the - processor. */ - type = debug_make_float_type (dhandle, 12); - name = "long double"; - break; - - case builtin_long_long_double: - type = debug_make_float_type (dhandle, 16); - name = "long long double"; - break; - - case builtin_quoted_string: - type = debug_make_array_type (dhandle, - ieee_builtin_type (info, p, - ((unsigned int) - builtin_char)), - ieee_builtin_type (info, p, - ((unsigned int) - builtin_int)), - 0, -1, true); - name = "QUOTED STRING"; - break; - - case builtin_instruction_address: - /* FIXME: This should be a code address. */ - type = debug_make_int_type (dhandle, 4, true); - name = "instruction address"; - break; - - case builtin_int: - /* FIXME: The size for this type should depend upon the - processor. */ - type = debug_make_int_type (dhandle, 4, false); - name = "int"; - break; - - case builtin_unsigned: - /* FIXME: The size for this type should depend upon the - processor. */ - type = debug_make_int_type (dhandle, 4, true); - name = "unsigned"; - break; - - case builtin_unsigned_int: - /* FIXME: The size for this type should depend upon the - processor. */ - type = debug_make_int_type (dhandle, 4, true); - name = "unsigned int"; - break; - - case builtin_char: - type = debug_make_int_type (dhandle, 1, false); - name = "char"; - break; - - case builtin_long: - type = debug_make_int_type (dhandle, 4, false); - name = "long"; - break; - - case builtin_short: - type = debug_make_int_type (dhandle, 2, false); - name = "short"; - break; - - case builtin_unsigned_short: - type = debug_make_int_type (dhandle, 2, true); - name = "unsigned short"; - break; - - case builtin_short_int: - type = debug_make_int_type (dhandle, 2, false); - name = "short int"; - break; - - case builtin_signed_short: - type = debug_make_int_type (dhandle, 2, false); - name = "signed short"; - break; - - case builtin_bcd_float: - ieee_error (info, p, "BCD float type not supported"); - return DEBUG_TYPE_NULL; - } - - if (name != NULL) - type = debug_name_type (dhandle, name, type); - - assert (indx < BUILTIN_TYPE_COUNT); - - info->types.builtins[indx] = type; - - return type; -} - -/* Allocate more space in the type table. If ref is true, this is a - reference to the type; if it is not already defined, we should set - up an indirect type. */ - -static boolean -ieee_alloc_type (info, indx, ref) - struct ieee_info *info; - unsigned int indx; - boolean ref; -{ - unsigned int nalloc; - register struct ieee_type *t; - struct ieee_type *tend; - - if (indx >= info->types.alloc) - { - nalloc = info->types.alloc; - if (nalloc == 0) - nalloc = 4; - while (indx >= nalloc) - nalloc *= 2; - - info->types.types = ((struct ieee_type *) - xrealloc (info->types.types, - nalloc * sizeof *info->types.types)); - - memset (info->types.types + info->types.alloc, 0, - (nalloc - info->types.alloc) * sizeof *info->types.types); - - tend = info->types.types + nalloc; - for (t = info->types.types + info->types.alloc; t < tend; t++) - t->type = DEBUG_TYPE_NULL; - - info->types.alloc = nalloc; - } - - if (ref) - { - t = info->types.types + indx; - if (t->type == NULL) - { - t->pslot = (debug_type *) xmalloc (sizeof *t->pslot); - *t->pslot = DEBUG_TYPE_NULL; - t->type = debug_make_indirect_type (info->dhandle, t->pslot, - (const char *) NULL); - if (t->type == NULL) - return false; - } - } - - return true; -} - -/* Read a type index and return the corresponding type. */ - -static boolean -ieee_read_type_index (info, pp, ptype) - struct ieee_info *info; - const bfd_byte **pp; - debug_type *ptype; -{ - const bfd_byte *start; - bfd_vma indx; - - start = *pp; - - if (! ieee_read_number (info, pp, &indx)) - return false; - - if (indx < 256) - { - *ptype = ieee_builtin_type (info, start, indx); - if (*ptype == NULL) - return false; - return true; - } - - indx -= 256; - if (! ieee_alloc_type (info, indx, true)) - return false; - - *ptype = info->types.types[indx].type; - - return true; -} - -/* Parse IEEE debugging information for a file. This is passed the - bytes which compose the Debug Information Part of an IEEE file. */ - -boolean -parse_ieee (dhandle, abfd, bytes, len) - PTR dhandle; - bfd *abfd; - const bfd_byte *bytes; - bfd_size_type len; -{ - struct ieee_info info; - unsigned int i; - const bfd_byte *p, *pend; - - info.dhandle = dhandle; - info.abfd = abfd; - info.bytes = bytes; - info.pend = bytes + len; - info.blockstack.bsp = info.blockstack.stack; - info.saw_filename = false; - info.vars.alloc = 0; - info.vars.vars = NULL; - info.types.alloc = 0; - info.types.types = NULL; - info.tags = NULL; - for (i = 0; i < BUILTIN_TYPE_COUNT; i++) - info.types.builtins[i] = DEBUG_TYPE_NULL; - - p = bytes; - pend = info.pend; - while (p < pend) - { - const bfd_byte *record_start; - ieee_record_enum_type c; - - record_start = p; - - c = (ieee_record_enum_type) *p++; - - if (c == ieee_at_record_enum) - c = (ieee_record_enum_type) (((unsigned int) c << 8) | *p++); - - if (c <= ieee_number_repeat_end_enum) - { - ieee_error (&info, record_start, "unexpected number"); - return false; - } - - switch (c) - { - default: - ieee_error (&info, record_start, "unexpected record type"); - return false; - - case ieee_bb_record_enum: - if (! parse_ieee_bb (&info, &p)) - return false; - break; - - case ieee_be_record_enum: - if (! parse_ieee_be (&info, &p)) - return false; - break; - - case ieee_nn_record: - if (! parse_ieee_nn (&info, &p)) - return false; - break; - - case ieee_ty_record_enum: - if (! parse_ieee_ty (&info, &p)) - return false; - break; - - case ieee_atn_record_enum: - if (! parse_ieee_atn (&info, &p)) - return false; - break; - } - } - - if (info.blockstack.bsp != info.blockstack.stack) - { - ieee_error (&info, (const bfd_byte *) NULL, - "blocks left on stack at end"); - return false; - } - - return true; -} - -/* Handle an IEEE BB record. */ - -static boolean -parse_ieee_bb (info, pp) - struct ieee_info *info; - const bfd_byte **pp; -{ - const bfd_byte *block_start; - bfd_byte b; - bfd_vma size; - const char *name; - unsigned long namlen; - char *namcopy = NULL; - unsigned int fnindx; - boolean skip; - - block_start = *pp; - - b = **pp; - ++*pp; - - if (! ieee_read_number (info, pp, &size) - || ! ieee_read_id (info, pp, &name, &namlen)) - return false; - - fnindx = (unsigned int) -1; - skip = false; - - switch (b) - { - case 1: - /* BB1: Type definitions local to a module. */ - namcopy = savestring (name, namlen); - if (namcopy == NULL) - return false; - if (! debug_set_filename (info->dhandle, namcopy)) - return false; - info->saw_filename = true; - - /* Discard any variables or types we may have seen before. */ - if (info->vars.vars != NULL) - free (info->vars.vars); - info->vars.vars = NULL; - info->vars.alloc = 0; - if (info->types.types != NULL) - free (info->types.types); - info->types.types = NULL; - info->types.alloc = 0; - - /* Initialize the types to the global types. */ - if (info->global_types != NULL) - { - info->types.alloc = info->global_types->alloc; - info->types.types = ((struct ieee_type *) - xmalloc (info->types.alloc - * sizeof (*info->types.types))); - memcpy (info->types.types, info->global_types->types, - info->types.alloc * sizeof (*info->types.types)); - } - - break; - - case 2: - /* BB2: Global type definitions. The name is supposed to be - empty, but we don't check. */ - if (! debug_set_filename (info->dhandle, "*global*")) - return false; - info->saw_filename = true; - break; - - case 3: - /* BB3: High level module block begin. We don't have to do - anything here. The name is supposed to be the same as for - the BB1, but we don't check. */ - break; - - case 4: - /* BB4: Global function. */ - { - bfd_vma stackspace, typindx, offset; - debug_type return_type; - - if (! ieee_read_number (info, pp, &stackspace) - || ! ieee_read_number (info, pp, &typindx) - || ! ieee_read_expression (info, pp, &offset)) - return false; - - /* We have no way to record the stack space. FIXME. */ - - if (typindx < 256) - { - return_type = ieee_builtin_type (info, block_start, typindx); - if (return_type == DEBUG_TYPE_NULL) - return false; - } - else - { - typindx -= 256; - if (! ieee_alloc_type (info, typindx, true)) - return false; - fnindx = typindx; - return_type = info->types.types[typindx].type; - if (debug_get_type_kind (info->dhandle, return_type) - == DEBUG_KIND_FUNCTION) - return_type = debug_get_return_type (info->dhandle, - return_type); - } - - namcopy = savestring (name, namlen); - if (namcopy == NULL) - return false; - if (! debug_record_function (info->dhandle, namcopy, return_type, - true, offset)) - return false; - } - break; - - case 5: - /* BB5: File name for source line numbers. */ - { - unsigned int i; - - /* We ignore the date and time. FIXME. */ - for (i = 0; i < 6; i++) - { - bfd_vma ignore; - boolean present; - - if (! ieee_read_optional_number (info, pp, &ignore, &present)) - return false; - if (! present) - break; - } - - namcopy = savestring (name, namlen); - if (namcopy == NULL) - return false; - if (! debug_start_source (info->dhandle, namcopy)) - return false; - } - break; - - case 6: - /* BB6: Local function or block. */ - { - bfd_vma stackspace, typindx, offset; - - if (! ieee_read_number (info, pp, &stackspace) - || ! ieee_read_number (info, pp, &typindx) - || ! ieee_read_expression (info, pp, &offset)) - return false; - - /* We have no way to record the stack space. FIXME. */ - - if (namlen == 0) - { - if (! debug_start_block (info->dhandle, offset)) - return false; - /* Change b to indicate that this is a block - rather than a function. */ - b = 0x86; - } - else - { - /* The MRI C++ compiler will output a fake function named - __XRYCPP to hold C++ debugging information. We skip - that function. This is not crucial, but it makes - converting from IEEE to other debug formats work - better. */ - if (strncmp (name, "__XRYCPP", namlen) == 0) - skip = true; - else - { - debug_type return_type; - - if (typindx < 256) - { - return_type = ieee_builtin_type (info, block_start, - typindx); - if (return_type == NULL) - return false; - } - else - { - typindx -= 256; - if (! ieee_alloc_type (info, typindx, true)) - return false; - fnindx = typindx; - return_type = info->types.types[typindx].type; - if (debug_get_type_kind (info->dhandle, return_type) - == DEBUG_KIND_FUNCTION) - return_type = debug_get_return_type (info->dhandle, - return_type); - } - - namcopy = savestring (name, namlen); - if (namcopy == NULL) - return false; - if (! debug_record_function (info->dhandle, namcopy, - return_type, false, offset)) - return false; - } - } - } - break; - - case 10: - /* BB10: Assembler module scope. In the normal case, we - completely ignore all this information. FIXME. */ - { - const char *inam, *vstr; - unsigned long inamlen, vstrlen; - bfd_vma tool_type; - boolean present; - unsigned int i; - - if (! info->saw_filename) - { - namcopy = savestring (name, namlen); - if (namcopy == NULL) - return false; - if (! debug_set_filename (info->dhandle, namcopy)) - return false; - info->saw_filename = true; - } - - if (! ieee_read_id (info, pp, &inam, &inamlen) - || ! ieee_read_number (info, pp, &tool_type) - || ! ieee_read_optional_id (info, pp, &vstr, &vstrlen, &present)) - return false; - for (i = 0; i < 6; i++) - { - bfd_vma ignore; - - if (! ieee_read_optional_number (info, pp, &ignore, &present)) - return false; - if (! present) - break; - } - } - break; - - case 11: - /* BB11: Module section. We completely ignore all this - information. FIXME. */ - { - bfd_vma sectype, secindx, offset, map; - boolean present; - - if (! ieee_read_number (info, pp, §ype) - || ! ieee_read_number (info, pp, &secindx) - || ! ieee_read_expression (info, pp, &offset) - || ! ieee_read_optional_number (info, pp, &map, &present)) - return false; - } - break; - - default: - ieee_error (info, block_start, "unknown BB type"); - return false; - } - - - /* Push this block on the block stack. */ - - if (info->blockstack.bsp >= info->blockstack.stack + BLOCKSTACK_SIZE) - { - ieee_error (info, (const bfd_byte *) NULL, "stack overflow"); - return false; - } - - info->blockstack.bsp->kind = b; - if (b == 5) - info->blockstack.bsp->filename = namcopy; - info->blockstack.bsp->fnindx = fnindx; - info->blockstack.bsp->skip = skip; - ++info->blockstack.bsp; - - return true; -} - -/* Handle an IEEE BE record. */ - -static boolean -parse_ieee_be (info, pp) - struct ieee_info *info; - const bfd_byte **pp; -{ - bfd_vma offset; - - if (info->blockstack.bsp <= info->blockstack.stack) - { - ieee_error (info, *pp, "stack underflow"); - return false; - } - --info->blockstack.bsp; - - switch (info->blockstack.bsp->kind) - { - case 2: - /* When we end the global typedefs block, we copy out the the - contents of info->vars. This is because the variable indices - may be reused in the local blocks. However, we need to - preserve them so that we can locate a function returning a - reference variable whose type is named in the global typedef - block. */ - info->global_vars = ((struct ieee_vars *) - xmalloc (sizeof *info->global_vars)); - info->global_vars->alloc = info->vars.alloc; - info->global_vars->vars = ((struct ieee_var *) - xmalloc (info->vars.alloc - * sizeof (*info->vars.vars))); - memcpy (info->global_vars->vars, info->vars.vars, - info->vars.alloc * sizeof (*info->vars.vars)); - - /* We also copy out the non builtin parts of info->types, since - the types are discarded when we start a new block. */ - info->global_types = ((struct ieee_types *) - xmalloc (sizeof *info->global_types)); - info->global_types->alloc = info->types.alloc; - info->global_types->types = ((struct ieee_type *) - xmalloc (info->types.alloc - * sizeof (*info->types.types))); - memcpy (info->global_types->types, info->types.types, - info->types.alloc * sizeof (*info->types.types)); - memset (info->global_types->builtins, 0, - sizeof (info->global_types->builtins)); - - break; - - case 4: - case 6: - if (! ieee_read_expression (info, pp, &offset)) - return false; - if (! info->blockstack.bsp->skip) - { - if (! debug_end_function (info->dhandle, offset + 1)) - return false; - } - break; - - case 0x86: - /* This is BE6 when BB6 started a block rather than a local - function. */ - if (! ieee_read_expression (info, pp, &offset)) - return false; - if (! debug_end_block (info->dhandle, offset + 1)) - return false; - break; - - case 5: - /* When we end a BB5, we look up the stack for the last BB5, if - there is one, so that we can call debug_start_source. */ - if (info->blockstack.bsp > info->blockstack.stack) - { - struct ieee_block *bl; - - bl = info->blockstack.bsp; - do - { - --bl; - if (bl->kind == 5) - { - if (! debug_start_source (info->dhandle, bl->filename)) - return false; - break; - } - } - while (bl != info->blockstack.stack); - } - break; - - case 11: - if (! ieee_read_expression (info, pp, &offset)) - return false; - /* We just ignore the module size. FIXME. */ - break; - - default: - /* Other block types do not have any trailing information. */ - break; - } - - return true; -} - -/* Parse an NN record. */ - -static boolean -parse_ieee_nn (info, pp) - struct ieee_info *info; - const bfd_byte **pp; -{ - const bfd_byte *nn_start; - bfd_vma varindx; - const char *name; - unsigned long namlen; - - nn_start = *pp; - - if (! ieee_read_number (info, pp, &varindx) - || ! ieee_read_id (info, pp, &name, &namlen)) - return false; - - if (varindx < 32) - { - ieee_error (info, nn_start, "illegal variable index"); - return false; - } - varindx -= 32; - - if (varindx >= info->vars.alloc) - { - unsigned int alloc; - - alloc = info->vars.alloc; - if (alloc == 0) - alloc = 4; - while (varindx >= alloc) - alloc *= 2; - info->vars.vars = ((struct ieee_var *) - xrealloc (info->vars.vars, - alloc * sizeof *info->vars.vars)); - memset (info->vars.vars + info->vars.alloc, 0, - (alloc - info->vars.alloc) * sizeof *info->vars.vars); - info->vars.alloc = alloc; - } - - info->vars.vars[varindx].name = name; - info->vars.vars[varindx].namlen = namlen; - - return true; -} - -/* Parse a TY record. */ - -static boolean -parse_ieee_ty (info, pp) - struct ieee_info *info; - const bfd_byte **pp; -{ - const bfd_byte *ty_start, *ty_var_start, *ty_code_start; - bfd_vma typeindx, varindx, tc; - PTR dhandle; - boolean tag, typdef; - debug_type *arg_slots; - unsigned long type_bitsize; - debug_type type; - - ty_start = *pp; - - if (! ieee_read_number (info, pp, &typeindx)) - return false; - - if (typeindx < 256) - { - ieee_error (info, ty_start, "illegal type index"); - return false; - } - - typeindx -= 256; - if (! ieee_alloc_type (info, typeindx, false)) - return false; - - if (**pp != 0xce) - { - ieee_error (info, *pp, "unknown TY code"); - return false; - } - ++*pp; - - ty_var_start = *pp; - - if (! ieee_read_number (info, pp, &varindx)) - return false; - - if (varindx < 32) - { - ieee_error (info, ty_var_start, "illegal variable index"); - return false; - } - varindx -= 32; - - if (varindx >= info->vars.alloc || info->vars.vars[varindx].name == NULL) - { - ieee_error (info, ty_var_start, "undefined variable in TY"); - return false; - } - - ty_code_start = *pp; - - if (! ieee_read_number (info, pp, &tc)) - return false; - - dhandle = info->dhandle; - - tag = false; - typdef = false; - arg_slots = NULL; - type_bitsize = 0; - switch (tc) - { - default: - ieee_error (info, ty_code_start, "unknown TY code"); - return false; - - case '!': - /* Unknown type, with size. We treat it as int. FIXME. */ - { - bfd_vma size; - - if (! ieee_read_number (info, pp, &size)) - return false; - type = debug_make_int_type (dhandle, size, false); - } - break; - - case 'A': /* Array. */ - case 'a': /* FORTRAN array in column/row order. FIXME: Not - distinguished from normal array. */ - { - debug_type ele_type; - bfd_vma lower, upper; - - if (! ieee_read_type_index (info, pp, &ele_type) - || ! ieee_read_number (info, pp, &lower) - || ! ieee_read_number (info, pp, &upper)) - return false; - type = debug_make_array_type (dhandle, ele_type, - ieee_builtin_type (info, ty_code_start, - ((unsigned int) - builtin_int)), - (bfd_signed_vma) lower, - (bfd_signed_vma) upper, - false); - } - break; - - case 'E': - /* Simple enumeration. */ - { - bfd_vma size; - unsigned int alloc; - const char **names; - unsigned int c; - bfd_signed_vma *vals; - unsigned int i; - - if (! ieee_read_number (info, pp, &size)) - return false; - /* FIXME: we ignore the enumeration size. */ - - alloc = 10; - names = (const char **) xmalloc (alloc * sizeof *names); - memset (names, 0, alloc * sizeof *names); - c = 0; - while (1) - { - const char *name; - unsigned long namlen; - boolean present; - - if (! ieee_read_optional_id (info, pp, &name, &namlen, &present)) - return false; - if (! present) - break; - - if (c + 1 >= alloc) - { - alloc += 10; - names = ((const char **) - xrealloc (names, alloc * sizeof *names)); - } - - names[c] = savestring (name, namlen); - if (names[c] == NULL) - return false; - ++c; - } - - names[c] = NULL; - - vals = (bfd_signed_vma *) xmalloc (c * sizeof *vals); - for (i = 0; i < c; i++) - vals[i] = i; - - type = debug_make_enum_type (dhandle, names, vals); - tag = true; - } - break; - - case 'G': - /* Struct with bit fields. */ - { - bfd_vma size; - unsigned int alloc; - debug_field *fields; - unsigned int c; - - if (! ieee_read_number (info, pp, &size)) - return false; - - alloc = 10; - fields = (debug_field *) xmalloc (alloc * sizeof *fields); - c = 0; - while (1) - { - const char *name; - unsigned long namlen; - boolean present; - debug_type ftype; - bfd_vma bitpos, bitsize; - - if (! ieee_read_optional_id (info, pp, &name, &namlen, &present)) - return false; - if (! present) - break; - if (! ieee_read_type_index (info, pp, &ftype) - || ! ieee_read_number (info, pp, &bitpos) - || ! ieee_read_number (info, pp, &bitsize)) - return false; - - if (c + 1 >= alloc) - { - alloc += 10; - fields = ((debug_field *) - xrealloc (fields, alloc * sizeof *fields)); - } - - fields[c] = debug_make_field (dhandle, savestring (name, namlen), - ftype, bitpos, bitsize, - DEBUG_VISIBILITY_PUBLIC); - if (fields[c] == NULL) - return false; - ++c; - } - - fields[c] = NULL; - - type = debug_make_struct_type (dhandle, true, size, fields); - tag = true; - } - break; - - case 'N': - /* Enumeration. */ - { - unsigned int alloc; - const char **names; - bfd_signed_vma *vals; - unsigned int c; - - alloc = 10; - names = (const char **) xmalloc (alloc * sizeof *names); - vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *names); - c = 0; - while (1) - { - const char *name; - unsigned long namlen; - boolean present; - bfd_vma val; - - if (! ieee_read_optional_id (info, pp, &name, &namlen, &present)) - return false; - if (! present) - break; - if (! ieee_read_number (info, pp, &val)) - return false; - - /* If the length of the name is zero, then the value is - actually the size of the enum. We ignore this - information. FIXME. */ - if (namlen == 0) - continue; - - if (c + 1 >= alloc) - { - alloc += 10; - names = ((const char **) - xrealloc (names, alloc * sizeof *names)); - vals = ((bfd_signed_vma *) - xrealloc (vals, alloc * sizeof *vals)); - } - - names[c] = savestring (name, namlen); - if (names[c] == NULL) - return false; - vals[c] = (bfd_signed_vma) val; - ++c; - } - - names[c] = NULL; - - type = debug_make_enum_type (dhandle, names, vals); - tag = true; - } - break; - - case 'O': /* Small pointer. We don't distinguish small and large - pointers. FIXME. */ - case 'P': /* Large pointer. */ - { - debug_type t; - - if (! ieee_read_type_index (info, pp, &t)) - return false; - type = debug_make_pointer_type (dhandle, t); - } - break; - - case 'R': - /* Range. */ - { - bfd_vma low, high, signedp, size; - - if (! ieee_read_number (info, pp, &low) - || ! ieee_read_number (info, pp, &high) - || ! ieee_read_number (info, pp, &signedp) - || ! ieee_read_number (info, pp, &size)) - return false; - - type = debug_make_range_type (dhandle, - debug_make_int_type (dhandle, size, - ! signedp), - (bfd_signed_vma) low, - (bfd_signed_vma) high); - } - break; - - case 'S': /* Struct. */ - case 'U': /* Union. */ - { - bfd_vma size; - unsigned int alloc; - debug_field *fields; - unsigned int c; - - if (! ieee_read_number (info, pp, &size)) - return false; - - alloc = 10; - fields = (debug_field *) xmalloc (alloc * sizeof *fields); - c = 0; - while (1) - { - const char *name; - unsigned long namlen; - boolean present; - bfd_vma tindx; - bfd_vma offset; - debug_type ftype; - bfd_vma bitsize; - - if (! ieee_read_optional_id (info, pp, &name, &namlen, &present)) - return false; - if (! present) - break; - if (! ieee_read_number (info, pp, &tindx) - || ! ieee_read_number (info, pp, &offset)) - return false; - - if (tindx < 256) - { - ftype = ieee_builtin_type (info, ty_code_start, tindx); - bitsize = 0; - offset *= 8; - } - else - { - struct ieee_type *t; - - tindx -= 256; - if (! ieee_alloc_type (info, tindx, true)) - return false; - t = info->types.types + tindx; - ftype = t->type; - bitsize = t->bitsize; - if (bitsize == 0) - offset *= 8; - } - - if (c + 1 >= alloc) - { - alloc += 10; - fields = ((debug_field *) - xrealloc (fields, alloc * sizeof *fields)); - } - - fields[c] = debug_make_field (dhandle, savestring (name, namlen), - ftype, offset, bitsize, - DEBUG_VISIBILITY_PUBLIC); - if (fields[c] == NULL) - return false; - ++c; - } - - fields[c] = NULL; - - type = debug_make_struct_type (dhandle, tc == 'S', size, fields); - tag = true; - } - break; - - case 'T': - /* Typedef. */ - if (! ieee_read_type_index (info, pp, &type)) - return false; - typdef = true; - break; - - case 'X': - /* Procedure. FIXME: This is an extern declaration, which we - have no way of representing. */ - { - bfd_vma attr; - debug_type rtype; - bfd_vma nargs; - boolean present; - struct ieee_var *pv; - - /* FIXME: We ignore the attribute and the argument names. */ - - if (! ieee_read_number (info, pp, &attr) - || ! ieee_read_type_index (info, pp, &rtype) - || ! ieee_read_number (info, pp, &nargs)) - return false; - do - { - const char *name; - unsigned long namlen; - - if (! ieee_read_optional_id (info, pp, &name, &namlen, &present)) - return false; - } - while (present); - - pv = info->vars.vars + varindx; - pv->kind = IEEE_EXTERNAL; - if (pv->namlen > 0 - && debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER) - { - /* Set up the return type as an indirect type pointing to - the variable slot, so that we can change it to a - reference later if appropriate. */ - pv->pslot = (debug_type *) xmalloc (sizeof *pv->pslot); - *pv->pslot = rtype; - rtype = debug_make_indirect_type (dhandle, pv->pslot, - (const char *) NULL); - } - - type = debug_make_function_type (dhandle, rtype, (debug_type *) NULL, - false); - } - break; - - case 'V': - /* Void. This is not documented, but the MRI compiler emits it. */ - type = debug_make_void_type (dhandle); - break; - - case 'Z': - /* Array with 0 lower bound. */ - { - debug_type etype; - bfd_vma high; - - if (! ieee_read_type_index (info, pp, &etype) - || ! ieee_read_number (info, pp, &high)) - return false; - - type = debug_make_array_type (dhandle, etype, - ieee_builtin_type (info, ty_code_start, - ((unsigned int) - builtin_int)), - 0, (bfd_signed_vma) high, false); - } - break; - - case 'c': /* Complex. */ - case 'd': /* Double complex. */ - { - const char *name; - unsigned long namlen; - - /* FIXME: I don't know what the name means. */ - - if (! ieee_read_id (info, pp, &name, &namlen)) - return false; - - type = debug_make_complex_type (dhandle, tc == 'c' ? 4 : 8); - } - break; - - case 'f': - /* Pascal file name. FIXME. */ - ieee_error (info, ty_code_start, "Pascal file name not supported"); - return false; - - case 'g': - /* Bitfield type. */ - { - bfd_vma signedp, bitsize, dummy; - const bfd_byte *hold; - boolean present; - - if (! ieee_read_number (info, pp, &signedp) - || ! ieee_read_number (info, pp, &bitsize)) - return false; - - /* I think the documentation says that there is a type index, - but some actual files do not have one. */ - hold = *pp; - if (! ieee_read_optional_number (info, pp, &dummy, &present)) - return false; - if (! present) - { - /* FIXME: This is just a guess. */ - type = debug_make_int_type (dhandle, 4, - signedp ? false : true); - } - else - { - *pp = hold; - if (! ieee_read_type_index (info, pp, &type)) - return false; - } - type_bitsize = bitsize; - } - break; - - case 'n': - /* Qualifier. */ - { - bfd_vma kind; - debug_type t; - - if (! ieee_read_number (info, pp, &kind) - || ! ieee_read_type_index (info, pp, &t)) - return false; - - switch (kind) - { - default: - ieee_error (info, ty_start, "unsupported qualifer"); - return false; - - case 1: - type = debug_make_const_type (dhandle, t); - break; - - case 2: - type = debug_make_volatile_type (dhandle, t); - break; - } - } - break; - - case 's': - /* Set. */ - { - bfd_vma size; - debug_type etype; - - if (! ieee_read_number (info, pp, &size) - || ! ieee_read_type_index (info, pp, &etype)) - return false; - - /* FIXME: We ignore the size. */ - - type = debug_make_set_type (dhandle, etype, false); - } - break; - - case 'x': - /* Procedure with compiler dependencies. */ - { - struct ieee_var *pv; - bfd_vma attr, frame_type, push_mask, nargs, level, father; - debug_type rtype; - debug_type *arg_types; - boolean varargs; - boolean present; - - /* FIXME: We ignore some of this information. */ - - pv = info->vars.vars + varindx; - - if (! ieee_read_number (info, pp, &attr) - || ! ieee_read_number (info, pp, &frame_type) - || ! ieee_read_number (info, pp, &push_mask) - || ! ieee_read_type_index (info, pp, &rtype) - || ! ieee_read_number (info, pp, &nargs)) - return false; - if (nargs == (bfd_vma) -1) - { - arg_types = NULL; - varargs = false; - } - else - { - unsigned int i; - - arg_types = ((debug_type *) - xmalloc ((nargs + 1) * sizeof *arg_types)); - for (i = 0; i < nargs; i++) - if (! ieee_read_type_index (info, pp, arg_types + i)) - return false; - - /* If the last type is pointer to void, this is really a - varargs function. */ - varargs = false; - if (nargs > 0) - { - debug_type last; - - last = arg_types[nargs - 1]; - if (debug_get_type_kind (dhandle, last) == DEBUG_KIND_POINTER - && (debug_get_type_kind (dhandle, - debug_get_target_type (dhandle, - last)) - == DEBUG_KIND_VOID)) - { - --nargs; - varargs = true; - } - } - - /* If there are any pointer arguments, turn them into - indirect types in case we later need to convert them to - reference types. */ - for (i = 0; i < nargs; i++) - { - if (debug_get_type_kind (dhandle, arg_types[i]) - == DEBUG_KIND_POINTER) - { - if (arg_slots == NULL) - { - arg_slots = ((debug_type *) - xmalloc (nargs * sizeof *arg_slots)); - memset (arg_slots, 0, nargs * sizeof *arg_slots); - } - arg_slots[i] = arg_types[i]; - arg_types[i] = - debug_make_indirect_type (dhandle, - arg_slots + i, - (const char *) NULL); - } - } - - arg_types[nargs] = DEBUG_TYPE_NULL; - } - if (! ieee_read_number (info, pp, &level) - || ! ieee_read_optional_number (info, pp, &father, &present)) - return false; - - /* We can't distinguish between a global function and a static - function. */ - pv->kind = IEEE_FUNCTION; - - if (pv->namlen > 0 - && debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER) - { - /* Set up the return type as an indirect type pointing to - the variable slot, so that we can change it to a - reference later if appropriate. */ - pv->pslot = (debug_type *) xmalloc (sizeof *pv->pslot); - *pv->pslot = rtype; - rtype = debug_make_indirect_type (dhandle, pv->pslot, - (const char *) NULL); - } - - type = debug_make_function_type (dhandle, rtype, arg_types, varargs); - } - break; - } - - /* Record the type in the table. */ - - if (type == DEBUG_TYPE_NULL) - return false; - - info->vars.vars[varindx].type = type; - - if ((tag || typdef) - && info->vars.vars[varindx].namlen > 0) - { - const char *name; - - name = savestring (info->vars.vars[varindx].name, - info->vars.vars[varindx].namlen); - if (typdef) - type = debug_name_type (dhandle, name, type); - else if (tc == 'E' || tc == 'N') - type = debug_tag_type (dhandle, name, type); - else - { - struct ieee_tag *it; - - /* We must allocate all struct tags as indirect types, so - that if we later see a definition of the tag as a C++ - record we can update the indirect slot and automatically - change all the existing references. */ - it = (struct ieee_tag *) xmalloc (sizeof *it); - memset (it, 0, sizeof *it); - it->next = info->tags; - info->tags = it; - it->name = name; - it->slot = type; - - type = debug_make_indirect_type (dhandle, &it->slot, name); - type = debug_tag_type (dhandle, name, type); - - it->type = type; - } - if (type == NULL) - return false; - } - - info->types.types[typeindx].type = type; - info->types.types[typeindx].arg_slots = arg_slots; - info->types.types[typeindx].bitsize = type_bitsize; - - /* We may have already allocated type as an indirect type pointing - to slot. It does no harm to replace the indirect type with the - real type. Filling in slot as well handles the indirect types - which are already hanging around. */ - if (info->types.types[typeindx].pslot != NULL) - *info->types.types[typeindx].pslot = type; - - return true; -} - -/* Parse an ATN record. */ - -static boolean -parse_ieee_atn (info, pp) - struct ieee_info *info; - const bfd_byte **pp; -{ - const bfd_byte *atn_start, *atn_code_start; - bfd_vma varindx; - struct ieee_var *pvar; - debug_type type; - bfd_vma atn_code; - PTR dhandle; - bfd_vma v, v2, v3, v4, v5; - const char *name; - unsigned long namlen; - char *namcopy; - boolean present; - int blocktype; - - atn_start = *pp; - - if (! ieee_read_number (info, pp, &varindx) - || ! ieee_read_type_index (info, pp, &type)) - return false; - - atn_code_start = *pp; - - if (! ieee_read_number (info, pp, &atn_code)) - return false; - - if (varindx == 0) - { - pvar = NULL; - name = ""; - namlen = 0; - } - else if (varindx < 32) - { - ieee_error (info, atn_start, "illegal variable index"); - return false; - } - else - { - varindx -= 32; - if (varindx >= info->vars.alloc - || info->vars.vars[varindx].name == NULL) - { - /* The MRI compiler or linker sometimes omits the NN record - for a pmisc record. */ - if (atn_code == 62) - { - if (varindx >= info->vars.alloc) - { - unsigned int alloc; - - alloc = info->vars.alloc; - if (alloc == 0) - alloc = 4; - while (varindx >= alloc) - alloc *= 2; - info->vars.vars = ((struct ieee_var *) - xrealloc (info->vars.vars, - (alloc - * sizeof *info->vars.vars))); - memset (info->vars.vars + info->vars.alloc, 0, - ((alloc - info->vars.alloc) - * sizeof *info->vars.vars)); - info->vars.alloc = alloc; - } - - pvar = info->vars.vars + varindx; - pvar->name = ""; - pvar->namlen = 0; - } - else - { - ieee_error (info, atn_start, "undefined variable in ATN"); - return false; - } - } - - pvar = info->vars.vars + varindx; - - pvar->type = type; - - name = pvar->name; - namlen = pvar->namlen; - } - - dhandle = info->dhandle; - - /* If we are going to call debug_record_variable with a pointer - type, change the type to an indirect type so that we can later - change it to a reference type if we encounter a C++ pmisc 'R' - record. */ - if (pvar != NULL - && type != DEBUG_TYPE_NULL - && debug_get_type_kind (dhandle, type) == DEBUG_KIND_POINTER) - { - switch (atn_code) - { - case 1: - case 2: - case 3: - case 5: - case 8: - case 10: - pvar->pslot = (debug_type *) xmalloc (sizeof *pvar->pslot); - *pvar->pslot = type; - type = debug_make_indirect_type (dhandle, pvar->pslot, - (const char *) NULL); - pvar->type = type; - break; - } - } - - switch (atn_code) - { - default: - ieee_error (info, atn_code_start, "unknown ATN type"); - return false; - - case 1: - /* Automatic variable. */ - if (! ieee_read_number (info, pp, &v)) - return false; - namcopy = savestring (name, namlen); - if (type == NULL) - type = debug_make_void_type (dhandle); - if (pvar != NULL) - pvar->kind = IEEE_LOCAL; - return debug_record_variable (dhandle, namcopy, type, DEBUG_LOCAL, v); - - case 2: - /* Register variable. */ - if (! ieee_read_number (info, pp, &v)) - return false; - namcopy = savestring (name, namlen); - if (type == NULL) - type = debug_make_void_type (dhandle); - if (pvar != NULL) - pvar->kind = IEEE_LOCAL; - return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER, - ieee_regno_to_genreg (info->abfd, v)); - - case 3: - /* Static variable. */ - if (! ieee_require_asn (info, pp, &v)) - return false; - namcopy = savestring (name, namlen); - if (type == NULL) - type = debug_make_void_type (dhandle); - if (info->blockstack.bsp <= info->blockstack.stack) - blocktype = 0; - else - blocktype = info->blockstack.bsp[-1].kind; - if (pvar != NULL) - { - if (blocktype == 4 || blocktype == 6) - pvar->kind = IEEE_LOCAL; - else - pvar->kind = IEEE_STATIC; - } - return debug_record_variable (dhandle, namcopy, type, - (blocktype == 4 || blocktype == 6 - ? DEBUG_LOCAL_STATIC - : DEBUG_STATIC), - v); - - case 4: - /* External function. We don't currently record these. FIXME. */ - if (pvar != NULL) - pvar->kind = IEEE_EXTERNAL; - return true; - - case 5: - /* External variable. We don't currently record these. FIXME. */ - if (pvar != NULL) - pvar->kind = IEEE_EXTERNAL; - return true; - - case 7: - if (! ieee_read_number (info, pp, &v) - || ! ieee_read_number (info, pp, &v2) - || ! ieee_read_optional_number (info, pp, &v3, &present)) - return false; - if (present) - { - if (! ieee_read_optional_number (info, pp, &v4, &present)) - return false; - } - - /* We just ignore the two optional fields in v3 and v4, since - they are not defined. */ - - if (! ieee_require_asn (info, pp, &v3)) - return false; - - /* We have no way to record the column number. FIXME. */ - - return debug_record_line (dhandle, v, v3); - - case 8: - /* Global variable. */ - if (! ieee_require_asn (info, pp, &v)) - return false; - namcopy = savestring (name, namlen); - if (type == NULL) - type = debug_make_void_type (dhandle); - if (pvar != NULL) - pvar->kind = IEEE_GLOBAL; - return debug_record_variable (dhandle, namcopy, type, DEBUG_GLOBAL, v); - - case 9: - /* Variable lifetime information. */ - if (! ieee_read_number (info, pp, &v)) - return false; - - /* We have no way to record this information. FIXME. */ - return true; - - case 10: - /* Locked register. The spec says that there are two required - fields, but at least on occasion the MRI compiler only emits - one. */ - if (! ieee_read_number (info, pp, &v) - || ! ieee_read_optional_number (info, pp, &v2, &present)) - return false; - - /* I think this means a variable that is both in a register and - a frame slot. We ignore the frame slot. FIXME. */ - - namcopy = savestring (name, namlen); - if (type == NULL) - type = debug_make_void_type (dhandle); - if (pvar != NULL) - pvar->kind = IEEE_LOCAL; - return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER, v); - - case 11: - /* Reserved for FORTRAN common. */ - ieee_error (info, atn_code_start, "unsupported ATN11"); - - /* Return true to keep going. */ - return true; - - case 12: - /* Based variable. */ - v3 = 0; - v4 = 0x80; - v5 = 0; - if (! ieee_read_number (info, pp, &v) - || ! ieee_read_number (info, pp, &v2) - || ! ieee_read_optional_number (info, pp, &v3, &present)) - return false; - if (present) - { - if (! ieee_read_optional_number (info, pp, &v4, &present)) - return false; - if (present) - { - if (! ieee_read_optional_number (info, pp, &v5, &present)) - return false; - } - } - - /* We have no way to record this information. FIXME. */ - - ieee_error (info, atn_code_start, "unsupported ATN12"); - - /* Return true to keep going. */ - return true; - - case 16: - /* Constant. The description of this that I have is ambiguous, - so I'm not going to try to implement it. */ - if (! ieee_read_number (info, pp, &v) - || ! ieee_read_optional_number (info, pp, &v2, &present)) - return false; - if (present) - { - if (! ieee_read_optional_number (info, pp, &v2, &present)) - return false; - if (present) - { - if (! ieee_read_optional_id (info, pp, &name, &namlen, &present)) - return false; - } - } - - if ((ieee_record_enum_type) **pp == ieee_e2_first_byte_enum) - { - if (! ieee_require_asn (info, pp, &v3)) - return false; - } - - return true; - - case 19: - /* Static variable from assembler. */ - v2 = 0; - if (! ieee_read_number (info, pp, &v) - || ! ieee_read_optional_number (info, pp, &v2, &present) - || ! ieee_require_asn (info, pp, &v3)) - return false; - namcopy = savestring (name, namlen); - /* We don't really handle this correctly. FIXME. */ - return debug_record_variable (dhandle, namcopy, - debug_make_void_type (dhandle), - v2 != 0 ? DEBUG_GLOBAL : DEBUG_STATIC, - v3); - - case 62: - /* Procedure miscellaneous information. */ - case 63: - /* Variable miscellaneous information. */ - case 64: - /* Module miscellaneous information. */ - if (! ieee_read_number (info, pp, &v) - || ! ieee_read_number (info, pp, &v2) - || ! ieee_read_optional_id (info, pp, &name, &namlen, &present)) - return false; - - if (atn_code == 62 && v == 80) - { - if (present) - { - ieee_error (info, atn_code_start, - "unexpected string in C++ misc"); - return false; - } - return ieee_read_cxx_misc (info, pp, v2); - } - - /* We just ignore all of this stuff. FIXME. */ - - for (; v2 > 0; --v2) - { - switch ((ieee_record_enum_type) **pp) - { - default: - ieee_error (info, *pp, "bad misc record"); - return false; - - case ieee_at_record_enum: - if (! ieee_require_atn65 (info, pp, &name, &namlen)) - return false; - break; - - case ieee_e2_first_byte_enum: - if (! ieee_require_asn (info, pp, &v3)) - return false; - break; - } - } - - return true; - } - - /*NOTREACHED*/ -} - -/* Handle C++ debugging miscellaneous records. This is called for - procedure miscellaneous records of type 80. */ - -static boolean -ieee_read_cxx_misc (info, pp, count) - struct ieee_info *info; - const bfd_byte **pp; - unsigned long count; -{ - const bfd_byte *start; - bfd_vma category; - - start = *pp; - - /* Get the category of C++ misc record. */ - if (! ieee_require_asn (info, pp, &category)) - return false; - --count; - - switch (category) - { - default: - ieee_error (info, start, "unrecognized C++ misc record"); - return false; - - case 'T': - if (! ieee_read_cxx_class (info, pp, count)) - return false; - break; - - case 'M': - { - bfd_vma flags; - const char *name; - unsigned long namlen; - - /* The IEEE spec indicates that the 'M' record only has a - flags field. The MRI compiler also emits the name of the - function. */ - - if (! ieee_require_asn (info, pp, &flags)) - return false; - if (*pp < info->pend - && (ieee_record_enum_type) **pp == ieee_at_record_enum) - { - if (! ieee_require_atn65 (info, pp, &name, &namlen)) - return false; - } - - /* This is emitted for method functions, but I don't think we - care very much. It might help if it told us useful - information like the class with which this function is - associated, but it doesn't, so it isn't helpful. */ - } - break; - - case 'B': - if (! ieee_read_cxx_defaults (info, pp, count)) - return false; - break; - - case 'z': - { - const char *name, *mangled, *class; - unsigned long namlen, mangledlen, classlen; - bfd_vma control; - - /* Pointer to member. */ - - if (! ieee_require_atn65 (info, pp, &name, &namlen) - || ! ieee_require_atn65 (info, pp, &mangled, &mangledlen) - || ! ieee_require_atn65 (info, pp, &class, &classlen) - || ! ieee_require_asn (info, pp, &control)) - return false; - - /* FIXME: We should now track down name and change its type. */ - } - break; - - case 'R': - if (! ieee_read_reference (info, pp)) - return false; - break; - } - - return true; -} - -/* Read a C++ class definition. This is a pmisc type 80 record of - category 'T'. */ - -static boolean -ieee_read_cxx_class (info, pp, count) - struct ieee_info *info; - const bfd_byte **pp; - unsigned long count; -{ - const bfd_byte *start; - bfd_vma class; - const char *tag; - unsigned long taglen; - struct ieee_tag *it; - PTR dhandle; - debug_field *fields; - unsigned int field_count, field_alloc; - debug_baseclass *baseclasses; - unsigned int baseclasses_count, baseclasses_alloc; - const debug_field *structfields; - struct ieee_method - { - const char *name; - unsigned long namlen; - debug_method_variant *variants; - unsigned count; - unsigned int alloc; - } *methods; - unsigned int methods_count, methods_alloc; - debug_type vptrbase; - boolean ownvptr; - debug_method *dmethods; - - start = *pp; - - if (! ieee_require_asn (info, pp, &class)) - return false; - --count; - - if (! ieee_require_atn65 (info, pp, &tag, &taglen)) - return false; - --count; - - /* Find the C struct with this name. */ - for (it = info->tags; it != NULL; it = it->next) - if (it->name[0] == tag[0] - && strncmp (it->name, tag, taglen) == 0 - && strlen (it->name) == taglen) - break; - if (it == NULL) - { - ieee_error (info, start, "undefined C++ object"); - return false; - } - - dhandle = info->dhandle; - - fields = NULL; - field_count = 0; - field_alloc = 0; - baseclasses = NULL; - baseclasses_count = 0; - baseclasses_alloc = 0; - methods = NULL; - methods_count = 0; - methods_alloc = 0; - vptrbase = DEBUG_TYPE_NULL; - ownvptr = false; - - structfields = debug_get_fields (dhandle, it->type); - - while (count > 0) - { - bfd_vma id; - const bfd_byte *spec_start; - - spec_start = *pp; - - if (! ieee_require_asn (info, pp, &id)) - return false; - --count; - - switch (id) - { - default: - ieee_error (info, spec_start, "unrecognized C++ object spec"); - return false; - - case 'b': - { - bfd_vma flags, cinline; - const char *basename, *fieldname; - unsigned long baselen, fieldlen; - char *basecopy; - debug_type basetype; - bfd_vma bitpos; - boolean virtualp; - enum debug_visibility visibility; - debug_baseclass baseclass; - - /* This represents a base or friend class. */ - - if (! ieee_require_asn (info, pp, &flags) - || ! ieee_require_atn65 (info, pp, &basename, &baselen) - || ! ieee_require_asn (info, pp, &cinline) - || ! ieee_require_atn65 (info, pp, &fieldname, &fieldlen)) - return false; - count -= 4; - - /* We have no way of recording friend information, so we - just ignore it. */ - if ((flags & BASEFLAGS_FRIEND) != 0) - break; - - /* I assume that either all of the members of the - baseclass are included in the object, starting at the - beginning of the object, or that none of them are - included. */ - - if ((fieldlen == 0) == (cinline == 0)) - { - ieee_error (info, start, "unsupported C++ object type"); - return false; - } - - basecopy = savestring (basename, baselen); - basetype = debug_find_tagged_type (dhandle, basecopy, - DEBUG_KIND_ILLEGAL); - free (basecopy); - if (basetype == DEBUG_TYPE_NULL) - { - ieee_error (info, start, "C++ base class not defined"); - return false; - } - - if (fieldlen == 0) - bitpos = 0; - else - { - const debug_field *pf; - - if (structfields == NULL) - { - ieee_error (info, start, "C++ object has no fields"); - return false; - } - - for (pf = structfields; *pf != DEBUG_FIELD_NULL; pf++) - { - const char *fname; - - fname = debug_get_field_name (dhandle, *pf); - if (fname == NULL) - return false; - if (fname[0] == fieldname[0] - && strncmp (fname, fieldname, fieldlen) == 0 - && strlen (fname) == fieldlen) - break; - } - if (*pf == DEBUG_FIELD_NULL) - { - ieee_error (info, start, - "C++ base class not found in container"); - return false; - } - - bitpos = debug_get_field_bitpos (dhandle, *pf); - } - - if ((flags & BASEFLAGS_VIRTUAL) != 0) - virtualp = true; - else - virtualp = false; - if ((flags & BASEFLAGS_PRIVATE) != 0) - visibility = DEBUG_VISIBILITY_PRIVATE; - else - visibility = DEBUG_VISIBILITY_PUBLIC; - - baseclass = debug_make_baseclass (dhandle, basetype, bitpos, - virtualp, visibility); - if (baseclass == DEBUG_BASECLASS_NULL) - return false; - - if (baseclasses_count + 1 >= baseclasses_alloc) - { - baseclasses_alloc += 10; - baseclasses = ((debug_baseclass *) - xrealloc (baseclasses, - (baseclasses_alloc - * sizeof *baseclasses))); - } - - baseclasses[baseclasses_count] = baseclass; - ++baseclasses_count; - baseclasses[baseclasses_count] = DEBUG_BASECLASS_NULL; - } - break; - - case 'd': - { - bfd_vma flags; - const char *fieldname, *mangledname; - unsigned long fieldlen, mangledlen; - char *fieldcopy; - boolean staticp; - debug_type ftype; - const debug_field *pf = NULL; - enum debug_visibility visibility; - debug_field field; - - /* This represents a data member. */ - - if (! ieee_require_asn (info, pp, &flags) - || ! ieee_require_atn65 (info, pp, &fieldname, &fieldlen) - || ! ieee_require_atn65 (info, pp, &mangledname, &mangledlen)) - return false; - count -= 3; - - fieldcopy = savestring (fieldname, fieldlen); - - staticp = (flags & CXXFLAGS_STATIC) != 0 ? true : false; - - if (staticp) - { - struct ieee_var *pv, *pvend; - - /* See if we can find a definition for this variable. */ - pv = info->vars.vars; - pvend = pv + info->vars.alloc; - for (; pv < pvend; pv++) - if (pv->namlen == mangledlen - && strncmp (pv->name, mangledname, mangledlen) == 0) - break; - if (pv < pvend) - ftype = pv->type; - else - { - /* This can happen if the variable is never used. */ - ftype = ieee_builtin_type (info, start, - (unsigned int) builtin_void); - } - } - else - { - unsigned int findx; - - if (structfields == NULL) - { - ieee_error (info, start, "C++ object has no fields"); - return false; - } - - for (pf = structfields, findx = 0; - *pf != DEBUG_FIELD_NULL; - pf++, findx++) - { - const char *fname; - - fname = debug_get_field_name (dhandle, *pf); - if (fname == NULL) - return false; - if (fname[0] == mangledname[0] - && strncmp (fname, mangledname, mangledlen) == 0 - && strlen (fname) == mangledlen) - break; - } - if (*pf == DEBUG_FIELD_NULL) - { - ieee_error (info, start, - "C++ data member not found in container"); - return false; - } - - ftype = debug_get_field_type (dhandle, *pf); - - if (debug_get_type_kind (dhandle, ftype) == DEBUG_KIND_POINTER) - { - /* We might need to convert this field into a - reference type later on, so make it an indirect - type. */ - if (it->fslots == NULL) - { - unsigned int fcnt; - const debug_field *pfcnt; - - fcnt = 0; - for (pfcnt = structfields; - *pfcnt != DEBUG_FIELD_NULL; - pfcnt++) - ++fcnt; - it->fslots = ((debug_type *) - xmalloc (fcnt * sizeof *it->fslots)); - memset (it->fslots, 0, - fcnt * sizeof *it->fslots); - } - - if (ftype == DEBUG_TYPE_NULL) - return false; - it->fslots[findx] = ftype; - ftype = debug_make_indirect_type (dhandle, - it->fslots + findx, - (const char *) NULL); - } - } - if (ftype == DEBUG_TYPE_NULL) - return false; - - switch (flags & CXXFLAGS_VISIBILITY) - { - default: - ieee_error (info, start, "unknown C++ visibility"); - return false; - - case CXXFLAGS_VISIBILITY_PUBLIC: - visibility = DEBUG_VISIBILITY_PUBLIC; - break; - - case CXXFLAGS_VISIBILITY_PRIVATE: - visibility = DEBUG_VISIBILITY_PRIVATE; - break; - - case CXXFLAGS_VISIBILITY_PROTECTED: - visibility = DEBUG_VISIBILITY_PROTECTED; - break; - } - - if (staticp) - { - char *mangledcopy; - - mangledcopy = savestring (mangledname, mangledlen); - - field = debug_make_static_member (dhandle, fieldcopy, - ftype, mangledcopy, - visibility); - } - else - { - bfd_vma bitpos, bitsize; - - bitpos = debug_get_field_bitpos (dhandle, *pf); - bitsize = debug_get_field_bitsize (dhandle, *pf); - if (bitpos == (bfd_vma) -1 || bitsize == (bfd_vma) -1) - { - ieee_error (info, start, "bad C++ field bit pos or size"); - return false; - } - field = debug_make_field (dhandle, fieldcopy, ftype, bitpos, - bitsize, visibility); - } - - if (field == DEBUG_FIELD_NULL) - return false; - - if (field_count + 1 >= field_alloc) - { - field_alloc += 10; - fields = ((debug_field *) - xrealloc (fields, field_alloc * sizeof *fields)); - } - - fields[field_count] = field; - ++field_count; - fields[field_count] = DEBUG_FIELD_NULL; - } - break; - - case 'm': - case 'v': - { - bfd_vma flags, voffset, control; - const char *name, *mangled; - unsigned long namlen, mangledlen; - struct ieee_var *pv, *pvend; - debug_type type; - enum debug_visibility visibility; - boolean constp, volatilep; - char *mangledcopy; - debug_method_variant mv; - struct ieee_method *meth; - unsigned int im; - - if (! ieee_require_asn (info, pp, &flags) - || ! ieee_require_atn65 (info, pp, &name, &namlen) - || ! ieee_require_atn65 (info, pp, &mangled, &mangledlen)) - return false; - count -= 3; - if (id != 'v') - voffset = 0; - else - { - if (! ieee_require_asn (info, pp, &voffset)) - return false; - --count; - } - if (! ieee_require_asn (info, pp, &control)) - return false; - --count; - - /* We just ignore the control information. */ - - /* We have no way to represent friend information, so we - just ignore it. */ - if ((flags & CXXFLAGS_FRIEND) != 0) - break; - - /* We should already have seen a type for the function. */ - pv = info->vars.vars; - pvend = pv + info->vars.alloc; - for (; pv < pvend; pv++) - if (pv->namlen == mangledlen - && strncmp (pv->name, mangled, mangledlen) == 0) - break; - - if (pv >= pvend) - { - /* We won't have type information for this function if - it is not included in this file. We don't try to - handle this case. FIXME. */ - type = (debug_make_function_type - (dhandle, - ieee_builtin_type (info, start, - (unsigned int) builtin_void), - (debug_type *) NULL, - false)); - } - else - { - debug_type return_type; - const debug_type *arg_types; - boolean varargs; - - if (debug_get_type_kind (dhandle, pv->type) - != DEBUG_KIND_FUNCTION) - { - ieee_error (info, start, - "bad type for C++ method function"); - return false; - } - - return_type = debug_get_return_type (dhandle, pv->type); - arg_types = debug_get_parameter_types (dhandle, pv->type, - &varargs); - if (return_type == DEBUG_TYPE_NULL || arg_types == NULL) - { - ieee_error (info, start, - "no type information for C++ method function"); - return false; - } - - type = debug_make_method_type (dhandle, return_type, it->type, - (debug_type *) arg_types, - varargs); - } - if (type == DEBUG_TYPE_NULL) - return false; - - switch (flags & CXXFLAGS_VISIBILITY) - { - default: - ieee_error (info, start, "unknown C++ visibility"); - return false; - - case CXXFLAGS_VISIBILITY_PUBLIC: - visibility = DEBUG_VISIBILITY_PUBLIC; - break; - - case CXXFLAGS_VISIBILITY_PRIVATE: - visibility = DEBUG_VISIBILITY_PRIVATE; - break; - - case CXXFLAGS_VISIBILITY_PROTECTED: - visibility = DEBUG_VISIBILITY_PROTECTED; - break; - } - - constp = (flags & CXXFLAGS_CONST) != 0 ? true : false; - volatilep = (flags & CXXFLAGS_VOLATILE) != 0 ? true : false; - - mangledcopy = savestring (mangled, mangledlen); - - if ((flags & CXXFLAGS_STATIC) != 0) - { - if (id == 'v') - { - ieee_error (info, start, "C++ static virtual method"); - return false; - } - mv = debug_make_static_method_variant (dhandle, mangledcopy, - type, visibility, - constp, volatilep); - } - else - { - debug_type vcontext; - - if (id != 'v') - vcontext = DEBUG_TYPE_NULL; - else - { - /* FIXME: How can we calculate this correctly? */ - vcontext = it->type; - } - mv = debug_make_method_variant (dhandle, mangledcopy, type, - visibility, constp, - volatilep, voffset, - vcontext); - } - if (mv == DEBUG_METHOD_VARIANT_NULL) - return false; - - for (meth = methods, im = 0; im < methods_count; meth++, im++) - if (meth->namlen == namlen - && strncmp (meth->name, name, namlen) == 0) - break; - if (im >= methods_count) - { - if (methods_count >= methods_alloc) - { - methods_alloc += 10; - methods = ((struct ieee_method *) - xrealloc (methods, - methods_alloc * sizeof *methods)); - } - methods[methods_count].name = name; - methods[methods_count].namlen = namlen; - methods[methods_count].variants = NULL; - methods[methods_count].count = 0; - methods[methods_count].alloc = 0; - meth = methods + methods_count; - ++methods_count; - } - - if (meth->count + 1 >= meth->alloc) - { - meth->alloc += 10; - meth->variants = ((debug_method_variant *) - xrealloc (meth->variants, - (meth->alloc - * sizeof *meth->variants))); - } - - meth->variants[meth->count] = mv; - ++meth->count; - meth->variants[meth->count] = DEBUG_METHOD_VARIANT_NULL; - } - break; - - case 'o': - { - bfd_vma spec; - - /* We have no way to store this information, so we just - ignore it. */ - if (! ieee_require_asn (info, pp, &spec)) - return false; - --count; - if ((spec & 4) != 0) - { - const char *filename; - unsigned long filenamlen; - bfd_vma lineno; - - if (! ieee_require_atn65 (info, pp, &filename, &filenamlen) - || ! ieee_require_asn (info, pp, &lineno)) - return false; - count -= 2; - } - else if ((spec & 8) != 0) - { - const char *mangled; - unsigned long mangledlen; - - if (! ieee_require_atn65 (info, pp, &mangled, &mangledlen)) - return false; - --count; - } - else - { - ieee_error (info, start, - "unrecognized C++ object overhead spec"); - return false; - } - } - break; - - case 'z': - { - const char *vname, *basename; - unsigned long vnamelen, baselen; - bfd_vma vsize, control; - - /* A virtual table pointer. */ - - if (! ieee_require_atn65 (info, pp, &vname, &vnamelen) - || ! ieee_require_asn (info, pp, &vsize) - || ! ieee_require_atn65 (info, pp, &basename, &baselen) - || ! ieee_require_asn (info, pp, &control)) - return false; - count -= 4; - - /* We just ignore the control number. We don't care what - the virtual table name is. We have no way to store the - virtual table size, and I don't think we care anyhow. */ - - /* FIXME: We can't handle multiple virtual table pointers. */ - - if (baselen == 0) - ownvptr = true; - else - { - char *basecopy; - - basecopy = savestring (basename, baselen); - vptrbase = debug_find_tagged_type (dhandle, basecopy, - DEBUG_KIND_ILLEGAL); - free (basecopy); - if (vptrbase == DEBUG_TYPE_NULL) - { - ieee_error (info, start, "undefined C++ vtable"); - return false; - } - } - } - break; - } - } - - /* Now that we have seen all the method variants, we can call - debug_make_method for each one. */ - - if (methods_count == 0) - dmethods = NULL; - else - { - unsigned int i; - - dmethods = ((debug_method *) - xmalloc ((methods_count + 1) * sizeof *dmethods)); - for (i = 0; i < methods_count; i++) - { - char *namcopy; - - namcopy = savestring (methods[i].name, methods[i].namlen); - dmethods[i] = debug_make_method (dhandle, namcopy, - methods[i].variants); - if (dmethods[i] == DEBUG_METHOD_NULL) - return false; - } - dmethods[i] = DEBUG_METHOD_NULL; - free (methods); - } - - /* The struct type was created as an indirect type pointing at - it->slot. We update it->slot to automatically update all - references to this struct. */ - it->slot = debug_make_object_type (dhandle, - class != 'u', - debug_get_type_size (dhandle, - it->slot), - fields, baseclasses, dmethods, - vptrbase, ownvptr); - if (it->slot == DEBUG_TYPE_NULL) - return false; - - return true; -} - -/* Read C++ default argument value and reference type information. */ - -static boolean -ieee_read_cxx_defaults (info, pp, count) - struct ieee_info *info; - const bfd_byte **pp; - unsigned long count; -{ - const bfd_byte *start; - const char *fnname; - unsigned long fnlen; - bfd_vma defcount; - - start = *pp; - - /* Giving the function name before the argument count is an addendum - to the spec. The function name is demangled, though, so this - record must always refer to the current function. */ - - if (info->blockstack.bsp <= info->blockstack.stack - || info->blockstack.bsp[-1].fnindx == (unsigned int) -1) - { - ieee_error (info, start, "C++ default values not in a function"); - return false; - } - - if (! ieee_require_atn65 (info, pp, &fnname, &fnlen) - || ! ieee_require_asn (info, pp, &defcount)) - return false; - count -= 2; - - while (defcount-- > 0) - { - bfd_vma type, val; - const char *strval; - unsigned long strvallen; - - if (! ieee_require_asn (info, pp, &type)) - return false; - --count; - - switch (type) - { - case 0: - case 4: - break; - - case 1: - case 2: - if (! ieee_require_asn (info, pp, &val)) - return false; - --count; - break; - - case 3: - case 7: - if (! ieee_require_atn65 (info, pp, &strval, &strvallen)) - return false; - --count; - break; - - default: - ieee_error (info, start, "unrecognized C++ default type"); - return false; - } - - /* We have no way to record the default argument values, so we - just ignore them. FIXME. */ - } - - /* Any remaining arguments are indices of parameters that are really - reference type. */ - if (count > 0) - { - PTR dhandle; - debug_type *arg_slots; - - dhandle = info->dhandle; - arg_slots = info->types.types[info->blockstack.bsp[-1].fnindx].arg_slots; - while (count-- > 0) - { - bfd_vma indx; - debug_type target; - - if (! ieee_require_asn (info, pp, &indx)) - return false; - /* The index is 1 based. */ - --indx; - if (arg_slots == NULL - || arg_slots[indx] == DEBUG_TYPE_NULL - || (debug_get_type_kind (dhandle, arg_slots[indx]) - != DEBUG_KIND_POINTER)) - { - ieee_error (info, start, "reference parameter is not a pointer"); - return false; - } - - target = debug_get_target_type (dhandle, arg_slots[indx]); - arg_slots[indx] = debug_make_reference_type (dhandle, target); - if (arg_slots[indx] == DEBUG_TYPE_NULL) - return false; - } - } - - return true; -} - -/* Read a C++ reference definition. */ - -static boolean -ieee_read_reference (info, pp) - struct ieee_info *info; - const bfd_byte **pp; -{ - const bfd_byte *start; - bfd_vma flags; - const char *class, *name; - unsigned long classlen, namlen; - debug_type *pslot; - debug_type target; - - start = *pp; - - if (! ieee_require_asn (info, pp, &flags)) - return false; - - /* Giving the class name before the member name is in an addendum to - the spec. */ - if (flags == 3) - { - if (! ieee_require_atn65 (info, pp, &class, &classlen)) - return false; - } - - if (! ieee_require_atn65 (info, pp, &name, &namlen)) - return false; - - pslot = NULL; - if (flags != 3) - { - int pass; - - /* We search from the last variable indices to the first in - hopes of finding local variables correctly. We search the - local variables on the first pass, and the global variables - on the second. FIXME: This probably won't work in all cases. - On the other hand, I don't know what will. */ - for (pass = 0; pass < 2; pass++) - { - struct ieee_vars *vars; - int i; - struct ieee_var *pv = NULL; - - if (pass == 0) - vars = &info->vars; - else - { - vars = info->global_vars; - if (vars == NULL) - break; - } - - for (i = (int) vars->alloc - 1; i >= 0; i--) - { - boolean found; - - pv = vars->vars + i; - - if (pv->pslot == NULL - || pv->namlen != namlen - || strncmp (pv->name, name, namlen) != 0) - continue; - - found = false; - switch (flags) - { - default: - ieee_error (info, start, - "unrecognized C++ reference type"); - return false; - - case 0: - /* Global variable or function. */ - if (pv->kind == IEEE_GLOBAL - || pv->kind == IEEE_EXTERNAL - || pv->kind == IEEE_FUNCTION) - found = true; - break; - - case 1: - /* Global static variable or function. */ - if (pv->kind == IEEE_STATIC - || pv->kind == IEEE_FUNCTION) - found = true; - break; - - case 2: - /* Local variable. */ - if (pv->kind == IEEE_LOCAL) - found = true; - break; - } - - if (found) - break; - } - - if (i >= 0) - { - pslot = pv->pslot; - break; - } - } - } - else - { - struct ieee_tag *it; - - for (it = info->tags; it != NULL; it = it->next) - { - if (it->name[0] == class[0] - && strncmp (it->name, class, classlen) == 0 - && strlen (it->name) == classlen) - { - if (it->fslots != NULL) - { - const debug_field *pf; - unsigned int findx; - - pf = debug_get_fields (info->dhandle, it->type); - if (pf == NULL) - { - ieee_error (info, start, - "C++ reference in class with no fields"); - return false; - } - - for (findx = 0; *pf != DEBUG_FIELD_NULL; pf++, findx++) - { - const char *fname; - - fname = debug_get_field_name (info->dhandle, *pf); - if (fname == NULL) - return false; - if (strncmp (fname, name, namlen) == 0 - && strlen (fname) == namlen) - { - pslot = it->fslots + findx; - break; - } - } - } - - break; - } - } - } - - if (pslot == NULL) - { - ieee_error (info, start, "C++ reference not found"); - return false; - } - - /* We allocated the type of the object as an indirect type pointing - to *pslot, which we can now update to be a reference type. */ - if (debug_get_type_kind (info->dhandle, *pslot) != DEBUG_KIND_POINTER) - { - ieee_error (info, start, "C++ reference is not pointer"); - return false; - } - - target = debug_get_target_type (info->dhandle, *pslot); - *pslot = debug_make_reference_type (info->dhandle, target); - if (*pslot == DEBUG_TYPE_NULL) - return false; - - return true; -} - -/* Require an ASN record. */ - -static boolean -ieee_require_asn (info, pp, pv) - struct ieee_info *info; - const bfd_byte **pp; - bfd_vma *pv; -{ - const bfd_byte *start; - ieee_record_enum_type c; - bfd_vma varindx; - - start = *pp; - - c = (ieee_record_enum_type) **pp; - if (c != ieee_e2_first_byte_enum) - { - ieee_error (info, start, "missing required ASN"); - return false; - } - ++*pp; - - c = (ieee_record_enum_type) (((unsigned int) c << 8) | **pp); - if (c != ieee_asn_record_enum) - { - ieee_error (info, start, "missing required ASN"); - return false; - } - ++*pp; - - /* Just ignore the variable index. */ - if (! ieee_read_number (info, pp, &varindx)) - return false; - - return ieee_read_expression (info, pp, pv); -} - -/* Require an ATN65 record. */ - -static boolean -ieee_require_atn65 (info, pp, pname, pnamlen) - struct ieee_info *info; - const bfd_byte **pp; - const char **pname; - unsigned long *pnamlen; -{ - const bfd_byte *start; - ieee_record_enum_type c; - bfd_vma name_indx, type_indx, atn_code; - - start = *pp; - - c = (ieee_record_enum_type) **pp; - if (c != ieee_at_record_enum) - { - ieee_error (info, start, "missing required ATN65"); - return false; - } - ++*pp; - - c = (ieee_record_enum_type) (((unsigned int) c << 8) | **pp); - if (c != ieee_atn_record_enum) - { - ieee_error (info, start, "missing required ATN65"); - return false; - } - ++*pp; - - if (! ieee_read_number (info, pp, &name_indx) - || ! ieee_read_number (info, pp, &type_indx) - || ! ieee_read_number (info, pp, &atn_code)) - return false; - - /* Just ignore name_indx. */ - - if (type_indx != 0 || atn_code != 65) - { - ieee_error (info, start, "bad ATN65 record"); - return false; - } - - return ieee_read_id (info, pp, pname, pnamlen); -} - -/* Convert a register number in IEEE debugging information into a - generic register number. */ - -static int -ieee_regno_to_genreg (abfd, r) - bfd *abfd; - int r; -{ - switch (bfd_get_arch (abfd)) - { - case bfd_arch_m68k: - /* For some reasons stabs adds 2 to the floating point register - numbers. */ - if (r >= 16) - r += 2; - break; - - case bfd_arch_i960: - /* Stabs uses 0 to 15 for r0 to r15, 16 to 31 for g0 to g15, and - 32 to 35 for fp0 to fp3. */ - --r; - break; - - default: - break; - } - - return r; -} - -/* Convert a generic register number to an IEEE specific one. */ - -static int -ieee_genreg_to_regno (abfd, r) - bfd *abfd; - int r; -{ - switch (bfd_get_arch (abfd)) - { - case bfd_arch_m68k: - /* For some reason stabs add 2 to the floating point register - numbers. */ - if (r >= 18) - r -= 2; - break; - - case bfd_arch_i960: - /* Stabs uses 0 to 15 for r0 to r15, 16 to 31 for g0 to g15, and - 32 to 35 for fp0 to fp3. */ - ++r; - break; - - default: - break; - } - - return r; -} - -/* These routines build IEEE debugging information out of the generic - debugging information. */ - -/* We build the IEEE debugging information byte by byte. Rather than - waste time copying data around, we use a linked list of buffers to - hold the data. */ - -#define IEEE_BUFSIZE (490) - -struct ieee_buf -{ - /* Next buffer. */ - struct ieee_buf *next; - /* Number of data bytes in this buffer. */ - unsigned int c; - /* Bytes. */ - bfd_byte buf[IEEE_BUFSIZE]; -}; - -/* A list of buffers. */ - -struct ieee_buflist -{ - /* Head of list. */ - struct ieee_buf *head; - /* Tail--last buffer on list. */ - struct ieee_buf *tail; -}; - -/* In order to generate the BB11 blocks required by the HP emulator, - we keep track of ranges of addresses which correspond to a given - compilation unit. */ - -struct ieee_range -{ - /* Next range. */ - struct ieee_range *next; - /* Low address. */ - bfd_vma low; - /* High address. */ - bfd_vma high; -}; - -/* This structure holds information for a class on the type stack. */ - -struct ieee_type_class -{ - /* The name index in the debugging information. */ - unsigned int indx; - /* The pmisc records for the class. */ - struct ieee_buflist pmiscbuf; - /* The number of pmisc records. */ - unsigned int pmisccount; - /* The name of the class holding the virtual table, if not this - class. */ - const char *vclass; - /* Whether this class holds its own virtual table. */ - boolean ownvptr; - /* The largest virtual table offset seen so far. */ - bfd_vma voffset; - /* The current method. */ - const char *method; - /* Additional pmisc records used to record fields of reference type. */ - struct ieee_buflist refs; -}; - -/* This is how we store types for the writing routines. Most types - are simply represented by a type index. */ - -struct ieee_write_type -{ - /* Type index. */ - unsigned int indx; - /* The size of the type, if known. */ - unsigned int size; - /* The name of the type, if any. */ - const char *name; - /* If this is a function or method type, we build the type here, and - only add it to the output buffers if we need it. */ - struct ieee_buflist fndef; - /* If this is a struct, this is where the struct definition is - built. */ - struct ieee_buflist strdef; - /* If this is a class, this is where the class information is built. */ - struct ieee_type_class *classdef; - /* Whether the type is unsigned. */ - unsigned int unsignedp : 1; - /* Whether this is a reference type. */ - unsigned int referencep : 1; - /* Whether this is in the local type block. */ - unsigned int localp : 1; - /* Whether this is a duplicate struct definition which we are - ignoring. */ - unsigned int ignorep : 1; -}; - -/* This is the type stack used by the debug writing routines. FIXME: - We could generate more efficient output if we remembered when we - have output a particular type before. */ - -struct ieee_type_stack -{ - /* Next entry on stack. */ - struct ieee_type_stack *next; - /* Type information. */ - struct ieee_write_type type; -}; - -/* This is a list of associations between a name and some types. - These are used for typedefs and tags. */ - -struct ieee_name_type -{ - /* Next type for this name. */ - struct ieee_name_type *next; - /* ID number. For a typedef, this is the index of the type to which - this name is typedefed. */ - unsigned int id; - /* Type. */ - struct ieee_write_type type; - /* If this is a tag which has not yet been defined, this is the - kind. If the tag has been defined, this is DEBUG_KIND_ILLEGAL. */ - enum debug_type_kind kind; -}; - -/* We use a hash table to associate names and types. */ - -struct ieee_name_type_hash_table -{ - struct bfd_hash_table root; -}; - -struct ieee_name_type_hash_entry -{ - struct bfd_hash_entry root; - /* Information for this name. */ - struct ieee_name_type *types; -}; - -/* This is a list of enums. */ - -struct ieee_defined_enum -{ - /* Next enum. */ - struct ieee_defined_enum *next; - /* Type index. */ - unsigned int indx; - /* Whether this enum has been defined. */ - boolean defined; - /* Tag. */ - const char *tag; - /* Names. */ - const char **names; - /* Values. */ - bfd_signed_vma *vals; -}; - -/* We keep a list of modified versions of types, so that we don't - output them more than once. */ - -struct ieee_modified_type -{ - /* Pointer to this type. */ - unsigned int pointer; - /* Function with unknown arguments returning this type. */ - unsigned int function; - /* Const version of this type. */ - unsigned int const_qualified; - /* Volatile version of this type. */ - unsigned int volatile_qualified; - /* List of arrays of this type of various bounds. */ - struct ieee_modified_array_type *arrays; -}; - -/* A list of arrays bounds. */ - -struct ieee_modified_array_type -{ - /* Next array bounds. */ - struct ieee_modified_array_type *next; - /* Type index with these bounds. */ - unsigned int indx; - /* Low bound. */ - bfd_signed_vma low; - /* High bound. */ - bfd_signed_vma high; -}; - -/* This is a list of pending function parameter information. We don't - output them until we see the first block. */ - -struct ieee_pending_parm -{ - /* Next pending parameter. */ - struct ieee_pending_parm *next; - /* Name. */ - const char *name; - /* Type index. */ - unsigned int type; - /* Whether the type is a reference. */ - boolean referencep; - /* Kind. */ - enum debug_parm_kind kind; - /* Value. */ - bfd_vma val; -}; - -/* This is the handle passed down by debug_write. */ - -struct ieee_handle -{ - /* BFD we are writing to. */ - bfd *abfd; - /* Whether we got an error in a subroutine called via traverse or - map_over_sections. */ - boolean error; - /* Current data buffer list. */ - struct ieee_buflist *current; - /* Current data buffer. */ - struct ieee_buf *curbuf; - /* Filename of current compilation unit. */ - const char *filename; - /* Module name of current compilation unit. */ - const char *modname; - /* List of buffer for global types. */ - struct ieee_buflist global_types; - /* List of finished data buffers. */ - struct ieee_buflist data; - /* List of buffers for typedefs in the current compilation unit. */ - struct ieee_buflist types; - /* List of buffers for variables and functions in the current - compilation unit. */ - struct ieee_buflist vars; - /* List of buffers for C++ class definitions in the current - compilation unit. */ - struct ieee_buflist cxx; - /* List of buffers for line numbers in the current compilation unit. */ - struct ieee_buflist linenos; - /* Ranges for the current compilation unit. */ - struct ieee_range *ranges; - /* Ranges for all debugging information. */ - struct ieee_range *global_ranges; - /* Nested pending ranges. */ - struct ieee_range *pending_ranges; - /* Type stack. */ - struct ieee_type_stack *type_stack; - /* Next unallocated type index. */ - unsigned int type_indx; - /* Next unallocated name index. */ - unsigned int name_indx; - /* Typedefs. */ - struct ieee_name_type_hash_table typedefs; - /* Tags. */ - struct ieee_name_type_hash_table tags; - /* Enums. */ - struct ieee_defined_enum *enums; - /* Modified versions of types. */ - struct ieee_modified_type *modified; - /* Number of entries allocated in modified. */ - unsigned int modified_alloc; - /* 4 byte complex type. */ - unsigned int complex_float_index; - /* 8 byte complex type. */ - unsigned int complex_double_index; - /* The depth of block nesting. This is 0 outside a function, and 1 - just after start_function is called. */ - unsigned int block_depth; - /* The name of the current function. */ - const char *fnname; - /* List of buffers for the type of the function we are currently - writing out. */ - struct ieee_buflist fntype; - /* List of buffers for the parameters of the function we are - currently writing out. */ - struct ieee_buflist fnargs; - /* Number of arguments written to fnargs. */ - unsigned int fnargcount; - /* Pending function parameters. */ - struct ieee_pending_parm *pending_parms; - /* Current line number filename. */ - const char *lineno_filename; - /* Line number name index. */ - unsigned int lineno_name_indx; - /* Filename of pending line number. */ - const char *pending_lineno_filename; - /* Pending line number. */ - unsigned long pending_lineno; - /* Address of pending line number. */ - bfd_vma pending_lineno_addr; - /* Highest address seen at end of procedure. */ - bfd_vma highaddr; -}; - -static boolean ieee_init_buffer - PARAMS ((struct ieee_handle *, struct ieee_buflist *)); -static boolean ieee_change_buffer - PARAMS ((struct ieee_handle *, struct ieee_buflist *)); -static boolean ieee_append_buffer - PARAMS ((struct ieee_handle *, struct ieee_buflist *, - struct ieee_buflist *)); -static boolean ieee_real_write_byte PARAMS ((struct ieee_handle *, int)); -static boolean ieee_write_2bytes PARAMS ((struct ieee_handle *, int)); -static boolean ieee_write_number PARAMS ((struct ieee_handle *, bfd_vma)); -static boolean ieee_write_id PARAMS ((struct ieee_handle *, const char *)); -static boolean ieee_write_asn - PARAMS ((struct ieee_handle *, unsigned int, bfd_vma)); -static boolean ieee_write_atn65 - PARAMS ((struct ieee_handle *, unsigned int, const char *)); -static boolean ieee_push_type - PARAMS ((struct ieee_handle *, unsigned int, unsigned int, boolean, - boolean)); -static unsigned int ieee_pop_type PARAMS ((struct ieee_handle *)); -static void ieee_pop_unused_type PARAMS ((struct ieee_handle *)); -static unsigned int ieee_pop_type_used - PARAMS ((struct ieee_handle *, boolean)); -static boolean ieee_add_range - PARAMS ((struct ieee_handle *, boolean, bfd_vma, bfd_vma)); -static boolean ieee_start_range PARAMS ((struct ieee_handle *, bfd_vma)); -static boolean ieee_end_range PARAMS ((struct ieee_handle *, bfd_vma)); -static boolean ieee_define_type - PARAMS ((struct ieee_handle *, unsigned int, boolean, boolean)); -static boolean ieee_define_named_type - PARAMS ((struct ieee_handle *, const char *, unsigned int, unsigned int, - boolean, boolean, struct ieee_buflist *)); -static struct ieee_modified_type *ieee_get_modified_info - PARAMS ((struct ieee_handle *, unsigned int)); -static struct bfd_hash_entry *ieee_name_type_newfunc - PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); -static boolean ieee_write_undefined_tag - PARAMS ((struct ieee_name_type_hash_entry *, PTR)); -static boolean ieee_finish_compilation_unit PARAMS ((struct ieee_handle *)); -static void ieee_add_bb11_blocks PARAMS ((bfd *, asection *, PTR)); -static boolean ieee_add_bb11 - PARAMS ((struct ieee_handle *, asection *, bfd_vma, bfd_vma)); -static boolean ieee_output_pending_parms PARAMS ((struct ieee_handle *)); -static unsigned int ieee_vis_to_flags PARAMS ((enum debug_visibility)); -static boolean ieee_class_method_var - PARAMS ((struct ieee_handle *, const char *, enum debug_visibility, boolean, - boolean, boolean, bfd_vma, boolean)); - -static boolean ieee_start_compilation_unit PARAMS ((PTR, const char *)); -static boolean ieee_start_source PARAMS ((PTR, const char *)); -static boolean ieee_empty_type PARAMS ((PTR)); -static boolean ieee_void_type PARAMS ((PTR)); -static boolean ieee_int_type PARAMS ((PTR, unsigned int, boolean)); -static boolean ieee_float_type PARAMS ((PTR, unsigned int)); -static boolean ieee_complex_type PARAMS ((PTR, unsigned int)); -static boolean ieee_bool_type PARAMS ((PTR, unsigned int)); -static boolean ieee_enum_type - PARAMS ((PTR, const char *, const char **, bfd_signed_vma *)); -static boolean ieee_pointer_type PARAMS ((PTR)); -static boolean ieee_function_type PARAMS ((PTR, int, boolean)); -static boolean ieee_reference_type PARAMS ((PTR)); -static boolean ieee_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma)); -static boolean ieee_array_type - PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, boolean)); -static boolean ieee_set_type PARAMS ((PTR, boolean)); -static boolean ieee_offset_type PARAMS ((PTR)); -static boolean ieee_method_type PARAMS ((PTR, boolean, int, boolean)); -static boolean ieee_const_type PARAMS ((PTR)); -static boolean ieee_volatile_type PARAMS ((PTR)); -static boolean ieee_start_struct_type - PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int)); -static boolean ieee_struct_field - PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility)); -static boolean ieee_end_struct_type PARAMS ((PTR)); -static boolean ieee_start_class_type - PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int, boolean, - boolean)); -static boolean ieee_class_static_member - PARAMS ((PTR, const char *, const char *, enum debug_visibility)); -static boolean ieee_class_baseclass - PARAMS ((PTR, bfd_vma, boolean, enum debug_visibility)); -static boolean ieee_class_start_method PARAMS ((PTR, const char *)); -static boolean ieee_class_method_variant - PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean, - bfd_vma, boolean)); -static boolean ieee_class_static_method_variant - PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean)); -static boolean ieee_class_end_method PARAMS ((PTR)); -static boolean ieee_end_class_type PARAMS ((PTR)); -static boolean ieee_typedef_type PARAMS ((PTR, const char *)); -static boolean ieee_tag_type - PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind)); -static boolean ieee_typdef PARAMS ((PTR, const char *)); -static boolean ieee_tag PARAMS ((PTR, const char *)); -static boolean ieee_int_constant PARAMS ((PTR, const char *, bfd_vma)); -static boolean ieee_float_constant PARAMS ((PTR, const char *, double)); -static boolean ieee_typed_constant PARAMS ((PTR, const char *, bfd_vma)); -static boolean ieee_variable - PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma)); -static boolean ieee_start_function PARAMS ((PTR, const char *, boolean)); -static boolean ieee_function_parameter - PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma)); -static boolean ieee_start_block PARAMS ((PTR, bfd_vma)); -static boolean ieee_end_block PARAMS ((PTR, bfd_vma)); -static boolean ieee_end_function PARAMS ((PTR)); -static boolean ieee_lineno - PARAMS ((PTR, const char *, unsigned long, bfd_vma)); - -static const struct debug_write_fns ieee_fns = -{ - ieee_start_compilation_unit, - ieee_start_source, - ieee_empty_type, - ieee_void_type, - ieee_int_type, - ieee_float_type, - ieee_complex_type, - ieee_bool_type, - ieee_enum_type, - ieee_pointer_type, - ieee_function_type, - ieee_reference_type, - ieee_range_type, - ieee_array_type, - ieee_set_type, - ieee_offset_type, - ieee_method_type, - ieee_const_type, - ieee_volatile_type, - ieee_start_struct_type, - ieee_struct_field, - ieee_end_struct_type, - ieee_start_class_type, - ieee_class_static_member, - ieee_class_baseclass, - ieee_class_start_method, - ieee_class_method_variant, - ieee_class_static_method_variant, - ieee_class_end_method, - ieee_end_class_type, - ieee_typedef_type, - ieee_tag_type, - ieee_typdef, - ieee_tag, - ieee_int_constant, - ieee_float_constant, - ieee_typed_constant, - ieee_variable, - ieee_start_function, - ieee_function_parameter, - ieee_start_block, - ieee_end_block, - ieee_end_function, - ieee_lineno -}; - -/* Initialize a buffer to be empty. */ - -/*ARGSUSED*/ -static boolean -ieee_init_buffer (info, buflist) - struct ieee_handle *info; - struct ieee_buflist *buflist; -{ - buflist->head = NULL; - buflist->tail = NULL; - return true; -} - -/* See whether a buffer list has any data. */ - -#define ieee_buffer_emptyp(buflist) ((buflist)->head == NULL) - -/* Change the current buffer to a specified buffer chain. */ - -static boolean -ieee_change_buffer (info, buflist) - struct ieee_handle *info; - struct ieee_buflist *buflist; -{ - if (buflist->head == NULL) - { - struct ieee_buf *buf; - - buf = (struct ieee_buf *) xmalloc (sizeof *buf); - buf->next = NULL; - buf->c = 0; - buflist->head = buf; - buflist->tail = buf; - } - - info->current = buflist; - info->curbuf = buflist->tail; - - return true; -} - -/* Append a buffer chain. */ - -/*ARGSUSED*/ -static boolean -ieee_append_buffer (info, mainbuf, newbuf) - struct ieee_handle *info; - struct ieee_buflist *mainbuf; - struct ieee_buflist *newbuf; -{ - if (newbuf->head != NULL) - { - if (mainbuf->head == NULL) - mainbuf->head = newbuf->head; - else - mainbuf->tail->next = newbuf->head; - mainbuf->tail = newbuf->tail; - } - return true; -} - -/* Write a byte into the buffer. We use a macro for speed and a - function for the complex cases. */ - -#define ieee_write_byte(info, b) \ - ((info)->curbuf->c < IEEE_BUFSIZE \ - ? ((info)->curbuf->buf[(info)->curbuf->c++] = (b), true) \ - : ieee_real_write_byte ((info), (b))) - -static boolean -ieee_real_write_byte (info, b) - struct ieee_handle *info; - int b; -{ - if (info->curbuf->c >= IEEE_BUFSIZE) - { - struct ieee_buf *n; - - n = (struct ieee_buf *) xmalloc (sizeof *n); - n->next = NULL; - n->c = 0; - if (info->current->head == NULL) - info->current->head = n; - else - info->current->tail->next = n; - info->current->tail = n; - info->curbuf = n; - } - - info->curbuf->buf[info->curbuf->c] = b; - ++info->curbuf->c; - - return true; -} - -/* Write out two bytes. */ - -static boolean -ieee_write_2bytes (info, i) - struct ieee_handle *info; - int i; -{ - return (ieee_write_byte (info, i >> 8) - && ieee_write_byte (info, i & 0xff)); -} - -/* Write out an integer. */ - -static boolean -ieee_write_number (info, v) - struct ieee_handle *info; - bfd_vma v; -{ - bfd_vma t; - bfd_byte ab[20]; - bfd_byte *p; - unsigned int c; - - if (v <= (bfd_vma) ieee_number_end_enum) - return ieee_write_byte (info, (int) v); - - t = v; - p = ab + sizeof ab; - while (t != 0) - { - *--p = t & 0xff; - t >>= 8; - } - c = (ab + 20) - p; - - if (c > (unsigned int) (ieee_number_repeat_end_enum - - ieee_number_repeat_start_enum)) - { - fprintf (stderr, "IEEE numeric overflow: 0x"); - fprintf_vma (stderr, v); - fprintf (stderr, "\n"); - return false; - } - - if (! ieee_write_byte (info, (int) ieee_number_repeat_start_enum + c)) - return false; - for (; c > 0; --c, ++p) - { - if (! ieee_write_byte (info, *p)) - return false; - } - - return true; -} - -/* Write out a string. */ - -static boolean -ieee_write_id (info, s) - struct ieee_handle *info; - const char *s; -{ - unsigned int len; - - len = strlen (s); - if (len <= 0x7f) - { - if (! ieee_write_byte (info, len)) - return false; - } - else if (len <= 0xff) - { - if (! ieee_write_byte (info, (int) ieee_extension_length_1_enum) - || ! ieee_write_byte (info, len)) - return false; - } - else if (len <= 0xffff) - { - if (! ieee_write_byte (info, (int) ieee_extension_length_2_enum) - || ! ieee_write_2bytes (info, len)) - return false; - } - else - { - fprintf (stderr, "IEEE string length overflow: %u\n", len); - return false; - } - - for (; *s != '\0'; s++) - if (! ieee_write_byte (info, *s)) - return false; - - return true; -} - -/* Write out an ASN record. */ - -static boolean -ieee_write_asn (info, indx, val) - struct ieee_handle *info; - unsigned int indx; - bfd_vma val; -{ - return (ieee_write_2bytes (info, (int) ieee_asn_record_enum) - && ieee_write_number (info, indx) - && ieee_write_number (info, val)); -} - -/* Write out an ATN65 record. */ - -static boolean -ieee_write_atn65 (info, indx, s) - struct ieee_handle *info; - unsigned int indx; - const char *s; -{ - return (ieee_write_2bytes (info, (int) ieee_atn_record_enum) - && ieee_write_number (info, indx) - && ieee_write_number (info, 0) - && ieee_write_number (info, 65) - && ieee_write_id (info, s)); -} - -/* Push a type index onto the type stack. */ - -static boolean -ieee_push_type (info, indx, size, unsignedp, localp) - struct ieee_handle *info; - unsigned int indx; - unsigned int size; - boolean unsignedp; - boolean localp; -{ - struct ieee_type_stack *ts; - - ts = (struct ieee_type_stack *) xmalloc (sizeof *ts); - memset (ts, 0, sizeof *ts); - - ts->type.indx = indx; - ts->type.size = size; - ts->type.unsignedp = unsignedp; - ts->type.localp = localp; - - ts->next = info->type_stack; - info->type_stack = ts; - - return true; -} - -/* Pop a type index off the type stack. */ - -static unsigned int -ieee_pop_type (info) - struct ieee_handle *info; -{ - return ieee_pop_type_used (info, true); -} - -/* Pop an unused type index off the type stack. */ - -static void -ieee_pop_unused_type (info) - struct ieee_handle *info; -{ - (void) ieee_pop_type_used (info, false); -} - -/* Pop a used or unused type index off the type stack. */ - -static unsigned int -ieee_pop_type_used (info, used) - struct ieee_handle *info; - boolean used; -{ - struct ieee_type_stack *ts; - unsigned int ret; - - ts = info->type_stack; - assert (ts != NULL); - - /* If this is a function type, and we need it, we need to append the - actual definition to the typedef block now. */ - if (used && ! ieee_buffer_emptyp (&ts->type.fndef)) - { - struct ieee_buflist *buflist; - - if (ts->type.localp) - { - /* Make sure we have started the types block. */ - if (ieee_buffer_emptyp (&info->types)) - { - if (! ieee_change_buffer (info, &info->types) - || ! ieee_write_byte (info, (int) ieee_bb_record_enum) - || ! ieee_write_byte (info, 1) - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, info->modname)) - return false; - } - buflist = &info->types; - } - else - { - /* Make sure we started the global type block. */ - if (ieee_buffer_emptyp (&info->global_types)) - { - if (! ieee_change_buffer (info, &info->global_types) - || ! ieee_write_byte (info, (int) ieee_bb_record_enum) - || ! ieee_write_byte (info, 2) - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, "")) - return false; - } - buflist = &info->global_types; - } - - if (! ieee_append_buffer (info, buflist, &ts->type.fndef)) - return false; - } - - ret = ts->type.indx; - info->type_stack = ts->next; - free (ts); - return ret; -} - -/* Add a range of bytes included in the current compilation unit. */ - -static boolean -ieee_add_range (info, global, low, high) - struct ieee_handle *info; - boolean global; - bfd_vma low; - bfd_vma high; -{ - struct ieee_range **plist, *r, **pr; - - if (low == (bfd_vma) -1 || high == (bfd_vma) -1 || low == high) - return true; - - if (global) - plist = &info->global_ranges; - else - plist = &info->ranges; - - for (r = *plist; r != NULL; r = r->next) - { - if (high >= r->low && low <= r->high) - { - /* The new range overlaps r. */ - if (low < r->low) - r->low = low; - if (high > r->high) - r->high = high; - pr = &r->next; - while (*pr != NULL && (*pr)->low <= r->high) - { - struct ieee_range *n; - - if ((*pr)->high > r->high) - r->high = (*pr)->high; - n = (*pr)->next; - free (*pr); - *pr = n; - } - return true; - } - } - - r = (struct ieee_range *) xmalloc (sizeof *r); - memset (r, 0, sizeof *r); - - r->low = low; - r->high = high; - - /* Store the ranges sorted by address. */ - for (pr = plist; *pr != NULL; pr = &(*pr)->next) - if ((*pr)->low > high) - break; - r->next = *pr; - *pr = r; - - return true; -} - -/* Start a new range for which we only have the low address. */ - -static boolean -ieee_start_range (info, low) - struct ieee_handle *info; - bfd_vma low; -{ - struct ieee_range *r; - - r = (struct ieee_range *) xmalloc (sizeof *r); - memset (r, 0, sizeof *r); - r->low = low; - r->next = info->pending_ranges; - info->pending_ranges = r; - return true; -} - -/* Finish a range started by ieee_start_range. */ - -static boolean -ieee_end_range (info, high) - struct ieee_handle *info; - bfd_vma high; -{ - struct ieee_range *r; - bfd_vma low; - - assert (info->pending_ranges != NULL); - r = info->pending_ranges; - low = r->low; - info->pending_ranges = r->next; - free (r); - return ieee_add_range (info, false, low, high); -} - -/* Start defining a type. */ - -static boolean -ieee_define_type (info, size, unsignedp, localp) - struct ieee_handle *info; - unsigned int size; - boolean unsignedp; - boolean localp; -{ - return ieee_define_named_type (info, (const char *) NULL, - (unsigned int) -1, size, unsignedp, - localp, (struct ieee_buflist *) NULL); -} - -/* Start defining a named type. */ - -static boolean -ieee_define_named_type (info, name, indx, size, unsignedp, localp, buflist) - struct ieee_handle *info; - const char *name; - unsigned int indx; - unsigned int size; - boolean unsignedp; - boolean localp; - struct ieee_buflist *buflist; -{ - unsigned int type_indx; - unsigned int name_indx; - - if (indx != (unsigned int) -1) - type_indx = indx; - else - { - type_indx = info->type_indx; - ++info->type_indx; - } - - name_indx = info->name_indx; - ++info->name_indx; - - if (name == NULL) - name = ""; - - /* If we were given a buffer, use it; otherwise, use either the - local or the global type information, and make sure that the type - block is started. */ - if (buflist != NULL) - { - if (! ieee_change_buffer (info, buflist)) - return false; - } - else if (localp) - { - if (! ieee_buffer_emptyp (&info->types)) - { - if (! ieee_change_buffer (info, &info->types)) - return false; - } - else - { - if (! ieee_change_buffer (info, &info->types) - || ! ieee_write_byte (info, (int) ieee_bb_record_enum) - || ! ieee_write_byte (info, 1) - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, info->modname)) - return false; - } - } - else - { - if (! ieee_buffer_emptyp (&info->global_types)) - { - if (! ieee_change_buffer (info, &info->global_types)) - return false; - } - else - { - if (! ieee_change_buffer (info, &info->global_types) - || ! ieee_write_byte (info, (int) ieee_bb_record_enum) - || ! ieee_write_byte (info, 2) - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, "")) - return false; - } - } - - /* Push the new type on the type stack, write out an NN record, and - write out the start of a TY record. The caller will then finish - the TY record. */ - if (! ieee_push_type (info, type_indx, size, unsignedp, localp)) - return false; - - return (ieee_write_byte (info, (int) ieee_nn_record) - && ieee_write_number (info, name_indx) - && ieee_write_id (info, name) - && ieee_write_byte (info, (int) ieee_ty_record_enum) - && ieee_write_number (info, type_indx) - && ieee_write_byte (info, 0xce) - && ieee_write_number (info, name_indx)); -} - -/* Get an entry to the list of modified versions of a type. */ - -static struct ieee_modified_type * -ieee_get_modified_info (info, indx) - struct ieee_handle *info; - unsigned int indx; -{ - if (indx >= info->modified_alloc) - { - unsigned int nalloc; - - nalloc = info->modified_alloc; - if (nalloc == 0) - nalloc = 16; - while (indx >= nalloc) - nalloc *= 2; - info->modified = ((struct ieee_modified_type *) - xrealloc (info->modified, - nalloc * sizeof *info->modified)); - memset (info->modified + info->modified_alloc, 0, - (nalloc - info->modified_alloc) * sizeof *info->modified); - info->modified_alloc = nalloc; - } - - return info->modified + indx; -} - -/* Routines for the hash table mapping names to types. */ - -/* Initialize an entry in the hash table. */ - -static struct bfd_hash_entry * -ieee_name_type_newfunc (entry, table, string) - struct bfd_hash_entry *entry; - struct bfd_hash_table *table; - const char *string; -{ - struct ieee_name_type_hash_entry *ret = - (struct ieee_name_type_hash_entry *) entry; - - /* Allocate the structure if it has not already been allocated by a - subclass. */ - if (ret == NULL) - ret = ((struct ieee_name_type_hash_entry *) - bfd_hash_allocate (table, sizeof *ret)); - if (ret == NULL) - return NULL; - - /* Call the allocation method of the superclass. */ - ret = ((struct ieee_name_type_hash_entry *) - bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); - if (ret) - { - /* Set local fields. */ - ret->types = NULL; - } - - return (struct bfd_hash_entry *) ret; -} - -/* Look up an entry in the hash table. */ - -#define ieee_name_type_hash_lookup(table, string, create, copy) \ - ((struct ieee_name_type_hash_entry *) \ - bfd_hash_lookup (&(table)->root, (string), (create), (copy))) - -/* Traverse the hash table. */ - -#define ieee_name_type_hash_traverse(table, func, info) \ - (bfd_hash_traverse \ - (&(table)->root, \ - (boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func), \ - (info))) - -/* The general routine to write out IEEE debugging information. */ - -boolean -write_ieee_debugging_info (abfd, dhandle) - bfd *abfd; - PTR dhandle; -{ - struct ieee_handle info; - asection *s; - const char *err; - struct ieee_buf *b; - - memset (&info, 0, sizeof info); - info.abfd = abfd; - info.type_indx = 256; - info.name_indx = 32; - - if (! bfd_hash_table_init (&info.typedefs.root, ieee_name_type_newfunc) - || ! bfd_hash_table_init (&info.tags.root, ieee_name_type_newfunc)) - return false; - - if (! ieee_init_buffer (&info, &info.global_types) - || ! ieee_init_buffer (&info, &info.data) - || ! ieee_init_buffer (&info, &info.types) - || ! ieee_init_buffer (&info, &info.vars) - || ! ieee_init_buffer (&info, &info.cxx) - || ! ieee_init_buffer (&info, &info.linenos) - || ! ieee_init_buffer (&info, &info.fntype) - || ! ieee_init_buffer (&info, &info.fnargs)) - return false; - - if (! debug_write (dhandle, &ieee_fns, (PTR) &info)) - return false; - - if (info.filename != NULL) - { - if (! ieee_finish_compilation_unit (&info)) - return false; - } - - /* Put any undefined tags in the global typedef information. */ - info.error = false; - ieee_name_type_hash_traverse (&info.tags, - ieee_write_undefined_tag, - (PTR) &info); - if (info.error) - return false; - - /* Prepend the global typedef information to the other data. */ - if (! ieee_buffer_emptyp (&info.global_types)) - { - /* The HP debugger seems to have a bug in which it ignores the - last entry in the global types, so we add a dummy entry. */ - if (! ieee_change_buffer (&info, &info.global_types) - || ! ieee_write_byte (&info, (int) ieee_nn_record) - || ! ieee_write_number (&info, info.name_indx) - || ! ieee_write_id (&info, "") - || ! ieee_write_byte (&info, (int) ieee_ty_record_enum) - || ! ieee_write_number (&info, info.type_indx) - || ! ieee_write_byte (&info, 0xce) - || ! ieee_write_number (&info, info.name_indx) - || ! ieee_write_number (&info, 'P') - || ! ieee_write_number (&info, (int) builtin_void + 32) - || ! ieee_write_byte (&info, (int) ieee_be_record_enum)) - return false; - - if (! ieee_append_buffer (&info, &info.global_types, &info.data)) - return false; - info.data = info.global_types; - } - - /* Make sure that we have declare BB11 blocks for each range in the - file. They are added to info->vars. */ - info.error = false; - if (! ieee_init_buffer (&info, &info.vars)) - return false; - bfd_map_over_sections (abfd, ieee_add_bb11_blocks, (PTR) &info); - if (info.error) - return false; - if (! ieee_buffer_emptyp (&info.vars)) - { - if (! ieee_change_buffer (&info, &info.vars) - || ! ieee_write_byte (&info, (int) ieee_be_record_enum)) - return false; - - if (! ieee_append_buffer (&info, &info.data, &info.vars)) - return false; - } - - /* Now all the data is in info.data. Write it out to the BFD. We - normally would need to worry about whether all the other sections - are set up yet, but the IEEE backend will handle this particular - case correctly regardless. */ - if (ieee_buffer_emptyp (&info.data)) - { - /* There is no debugging information. */ - return true; - } - err = NULL; - s = bfd_make_section (abfd, ".debug"); - if (s == NULL) - err = "bfd_make_section"; - if (err == NULL) - { - if (! bfd_set_section_flags (abfd, s, SEC_DEBUGGING | SEC_HAS_CONTENTS)) - err = "bfd_set_section_flags"; - } - if (err == NULL) - { - bfd_size_type size; - - size = 0; - for (b = info.data.head; b != NULL; b = b->next) - size += b->c; - if (! bfd_set_section_size (abfd, s, size)) - err = "bfd_set_section_size"; - } - if (err == NULL) - { - file_ptr offset; - - offset = 0; - for (b = info.data.head; b != NULL; b = b->next) - { - if (! bfd_set_section_contents (abfd, s, b->buf, offset, b->c)) - { - err = "bfd_set_section_contents"; - break; - } - offset += b->c; - } - } - - if (err != NULL) - { - fprintf (stderr, "%s: %s: %s\n", bfd_get_filename (abfd), err, - bfd_errmsg (bfd_get_error ())); - return false; - } - - bfd_hash_table_free (&info.typedefs.root); - bfd_hash_table_free (&info.tags.root); - - return true; -} - -/* Write out information for an undefined tag. This is called via - ieee_name_type_hash_traverse. */ - -static boolean -ieee_write_undefined_tag (h, p) - struct ieee_name_type_hash_entry *h; - PTR p; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - struct ieee_name_type *nt; - - for (nt = h->types; nt != NULL; nt = nt->next) - { - unsigned int name_indx; - char code; - - if (nt->kind == DEBUG_KIND_ILLEGAL) - continue; - - if (ieee_buffer_emptyp (&info->global_types)) - { - if (! ieee_change_buffer (info, &info->global_types) - || ! ieee_write_byte (info, (int) ieee_bb_record_enum) - || ! ieee_write_byte (info, 2) - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, "")) - { - info->error = true; - return false; - } - } - else - { - if (! ieee_change_buffer (info, &info->global_types)) - { - info->error = true; - return false; - } - } - - name_indx = info->name_indx; - ++info->name_indx; - if (! ieee_write_byte (info, (int) ieee_nn_record) - || ! ieee_write_number (info, name_indx) - || ! ieee_write_id (info, nt->type.name) - || ! ieee_write_byte (info, (int) ieee_ty_record_enum) - || ! ieee_write_number (info, nt->type.indx) - || ! ieee_write_byte (info, 0xce) - || ! ieee_write_number (info, name_indx)) - { - info->error = true; - return false; - } - - switch (nt->kind) - { - default: - abort (); - info->error = true; - return false; - case DEBUG_KIND_STRUCT: - case DEBUG_KIND_CLASS: - code = 'S'; - break; - case DEBUG_KIND_UNION: - case DEBUG_KIND_UNION_CLASS: - code = 'U'; - break; - case DEBUG_KIND_ENUM: - code = 'E'; - break; - } - if (! ieee_write_number (info, code) - || ! ieee_write_number (info, 0)) - { - info->error = true; - return false; - } - } - - return true; -} - -/* Start writing out information for a compilation unit. */ - -static boolean -ieee_start_compilation_unit (p, filename) - PTR p; - const char *filename; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - const char *modname; - char *c, *s; - unsigned int nindx; - - if (info->filename != NULL) - { - if (! ieee_finish_compilation_unit (info)) - return false; - } - - info->filename = filename; - modname = strrchr (filename, '/'); - if (modname != NULL) - ++modname; - else - { - modname = strrchr (filename, '\\'); - if (modname != NULL) - ++modname; - else - modname = filename; - } - c = xstrdup (modname); - s = strrchr (c, '.'); - if (s != NULL) - *s = '\0'; - info->modname = c; - - if (! ieee_init_buffer (info, &info->types) - || ! ieee_init_buffer (info, &info->vars) - || ! ieee_init_buffer (info, &info->cxx) - || ! ieee_init_buffer (info, &info->linenos)) - return false; - info->ranges = NULL; - - /* Always include a BB1 and a BB3 block. That is what the output of - the MRI linker seems to look like. */ - if (! ieee_change_buffer (info, &info->types) - || ! ieee_write_byte (info, (int) ieee_bb_record_enum) - || ! ieee_write_byte (info, 1) - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, info->modname)) - return false; - - nindx = info->name_indx; - ++info->name_indx; - if (! ieee_change_buffer (info, &info->vars) - || ! ieee_write_byte (info, (int) ieee_bb_record_enum) - || ! ieee_write_byte (info, 3) - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, info->modname)) - return false; - - return true; -} - -/* Finish up a compilation unit. */ - -static boolean -ieee_finish_compilation_unit (info) - struct ieee_handle *info; -{ - struct ieee_range *r; - - if (! ieee_buffer_emptyp (&info->types)) - { - if (! ieee_change_buffer (info, &info->types) - || ! ieee_write_byte (info, (int) ieee_be_record_enum)) - return false; - } - - if (! ieee_buffer_emptyp (&info->cxx)) - { - /* Append any C++ information to the global function and - variable information. */ - assert (! ieee_buffer_emptyp (&info->vars)); - if (! ieee_change_buffer (info, &info->vars)) - return false; - - /* We put the pmisc records in a dummy procedure, just as the - MRI compiler does. */ - if (! ieee_write_byte (info, (int) ieee_bb_record_enum) - || ! ieee_write_byte (info, 6) - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, "__XRYCPP") - || ! ieee_write_number (info, 0) - || ! ieee_write_number (info, 0) - || ! ieee_write_number (info, info->highaddr - 1) - || ! ieee_append_buffer (info, &info->vars, &info->cxx) - || ! ieee_change_buffer (info, &info->vars) - || ! ieee_write_byte (info, (int) ieee_be_record_enum) - || ! ieee_write_number (info, info->highaddr - 1)) - return false; - } - - if (! ieee_buffer_emptyp (&info->vars)) - { - if (! ieee_change_buffer (info, &info->vars) - || ! ieee_write_byte (info, (int) ieee_be_record_enum)) - return false; - } - - if (info->pending_lineno_filename != NULL) - { - /* Force out the pending line number. */ - if (! ieee_lineno ((PTR) info, (const char *) NULL, 0, (bfd_vma) -1)) - return false; - } - if (! ieee_buffer_emptyp (&info->linenos)) - { - if (! ieee_change_buffer (info, &info->linenos) - || ! ieee_write_byte (info, (int) ieee_be_record_enum)) - return false; - if (strcmp (info->filename, info->lineno_filename) != 0) - { - /* We were not in the main file. We just closed the - included line number block, and now we must close the - main line number block. */ - if (! ieee_write_byte (info, (int) ieee_be_record_enum)) - return false; - } - } - - if (! ieee_append_buffer (info, &info->data, &info->types) - || ! ieee_append_buffer (info, &info->data, &info->vars) - || ! ieee_append_buffer (info, &info->data, &info->linenos)) - return false; - - /* Build BB10/BB11 blocks based on the ranges we recorded. */ - if (! ieee_change_buffer (info, &info->data)) - return false; - - if (! ieee_write_byte (info, (int) ieee_bb_record_enum) - || ! ieee_write_byte (info, 10) - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, info->modname) - || ! ieee_write_id (info, "") - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, "GNU objcopy")) - return false; - - for (r = info->ranges; r != NULL; r = r->next) - { - bfd_vma low, high; - asection *s; - int kind; - - low = r->low; - high = r->high; - - /* Find the section corresponding to this range. */ - for (s = info->abfd->sections; s != NULL; s = s->next) - { - if (bfd_get_section_vma (info->abfd, s) <= low - && high <= (bfd_get_section_vma (info->abfd, s) - + bfd_section_size (info->abfd, s))) - break; - } - - if (s == NULL) - { - /* Just ignore this range. */ - continue; - } - - /* Coalesce ranges if it seems reasonable. */ - while (r->next != NULL - && high + 0x1000 >= r->next->low - && (r->next->high - <= (bfd_get_section_vma (info->abfd, s) - + bfd_section_size (info->abfd, s)))) - { - r = r->next; - high = r->high; - } - - if ((s->flags & SEC_CODE) != 0) - kind = 1; - else if ((s->flags & SEC_READONLY) != 0) - kind = 3; - else - kind = 2; - - if (! ieee_write_byte (info, (int) ieee_bb_record_enum) - || ! ieee_write_byte (info, 11) - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, "") - || ! ieee_write_number (info, kind) - || ! ieee_write_number (info, s->index + IEEE_SECTION_NUMBER_BASE) - || ! ieee_write_number (info, low) - || ! ieee_write_byte (info, (int) ieee_be_record_enum) - || ! ieee_write_number (info, high - low)) - return false; - - /* Add this range to the list of global ranges. */ - if (! ieee_add_range (info, true, low, high)) - return false; - } - - if (! ieee_write_byte (info, (int) ieee_be_record_enum)) - return false; - - return true; -} - -/* Add BB11 blocks describing each range that we have not already - described. */ - -static void -ieee_add_bb11_blocks (abfd, sec, data) - bfd *abfd; - asection *sec; - PTR data; -{ - struct ieee_handle *info = (struct ieee_handle *) data; - bfd_vma low, high; - struct ieee_range *r; - - low = bfd_get_section_vma (abfd, sec); - high = low + bfd_section_size (abfd, sec); - - /* Find the first range at or after this section. The ranges are - sorted by address. */ - for (r = info->global_ranges; r != NULL; r = r->next) - if (r->high > low) - break; - - while (low < high) - { - if (r == NULL || r->low >= high) - { - if (! ieee_add_bb11 (info, sec, low, high)) - info->error = true; - return; - } - - if (low < r->low - && r->low - low > 0x100) - { - if (! ieee_add_bb11 (info, sec, low, r->low)) - { - info->error = true; - return; - } - } - low = r->high; - - r = r->next; - } -} - -/* Add a single BB11 block for a range. We add it to info->vars. */ - -static boolean -ieee_add_bb11 (info, sec, low, high) - struct ieee_handle *info; - asection *sec; - bfd_vma low; - bfd_vma high; -{ - int kind; - - if (! ieee_buffer_emptyp (&info->vars)) - { - if (! ieee_change_buffer (info, &info->vars)) - return false; - } - else - { - const char *filename, *modname; - char *c, *s; - - /* Start the enclosing BB10 block. */ - filename = bfd_get_filename (info->abfd); - modname = strrchr (filename, '/'); - if (modname != NULL) - ++modname; - else - { - modname = strrchr (filename, '\\'); - if (modname != NULL) - ++modname; - else - modname = filename; - } - c = xstrdup (modname); - s = strrchr (c, '.'); - if (s != NULL) - *s = '\0'; - - if (! ieee_change_buffer (info, &info->vars) - || ! ieee_write_byte (info, (int) ieee_bb_record_enum) - || ! ieee_write_byte (info, 10) - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, c) - || ! ieee_write_id (info, "") - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, "GNU objcopy")) - return false; - - free (c); - } - - if ((sec->flags & SEC_CODE) != 0) - kind = 1; - else if ((sec->flags & SEC_READONLY) != 0) - kind = 3; - else - kind = 2; - - if (! ieee_write_byte (info, (int) ieee_bb_record_enum) - || ! ieee_write_byte (info, 11) - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, "") - || ! ieee_write_number (info, kind) - || ! ieee_write_number (info, sec->index + IEEE_SECTION_NUMBER_BASE) - || ! ieee_write_number (info, low) - || ! ieee_write_byte (info, (int) ieee_be_record_enum) - || ! ieee_write_number (info, high - low)) - return false; - - return true; -} - -/* Start recording information from a particular source file. This is - used to record which file defined which types, variables, etc. It - is not used for line numbers, since the lineno entry point passes - down the file name anyhow. IEEE debugging information doesn't seem - to store this information anywhere. */ - -/*ARGSUSED*/ -static boolean -ieee_start_source (p, filename) - PTR p; - const char *filename; -{ - return true; -} - -/* Make an empty type. */ - -static boolean -ieee_empty_type (p) - PTR p; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - - return ieee_push_type (info, (int) builtin_unknown, 0, false, false); -} - -/* Make a void type. */ - -static boolean -ieee_void_type (p) - PTR p; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - - return ieee_push_type (info, (int) builtin_void, 0, false, false); -} - -/* Make an integer type. */ - -static boolean -ieee_int_type (p, size, unsignedp) - PTR p; - unsigned int size; - boolean unsignedp; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - unsigned int indx; - - switch (size) - { - case 1: - indx = (int) builtin_signed_char; - break; - case 2: - indx = (int) builtin_signed_short_int; - break; - case 4: - indx = (int) builtin_signed_long; - break; - case 8: - indx = (int) builtin_signed_long_long; - break; - default: - fprintf (stderr, "IEEE unsupported integer type size %u\n", size); - return false; - } - - if (unsignedp) - ++indx; - - return ieee_push_type (info, indx, size, unsignedp, false); -} - -/* Make a floating point type. */ - -static boolean -ieee_float_type (p, size) - PTR p; - unsigned int size; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - unsigned int indx; - - switch (size) - { - case 4: - indx = (int) builtin_float; - break; - case 8: - indx = (int) builtin_double; - break; - case 12: - /* FIXME: This size really depends upon the processor. */ - indx = (int) builtin_long_double; - break; - case 16: - indx = (int) builtin_long_long_double; - break; - default: - fprintf (stderr, "IEEE unsupported float type size %u\n", size); - return false; - } - - return ieee_push_type (info, indx, size, false, false); -} - -/* Make a complex type. */ - -static boolean -ieee_complex_type (p, size) - PTR p; - unsigned int size; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - char code; - - switch (size) - { - case 4: - if (info->complex_float_index != 0) - return ieee_push_type (info, info->complex_float_index, size * 2, - false, false); - code = 'c'; - break; - case 12: - case 16: - /* These cases can be output by gcc -gstabs. Outputting the - wrong type is better than crashing. */ - case 8: - if (info->complex_double_index != 0) - return ieee_push_type (info, info->complex_double_index, size * 2, - false, false); - code = 'd'; - break; - default: - fprintf (stderr, "IEEE unsupported complex type size %u\n", size); - return false; - } - - /* FIXME: I don't know what the string is for. */ - if (! ieee_define_type (info, size * 2, false, false) - || ! ieee_write_number (info, code) - || ! ieee_write_id (info, "")) - return false; - - if (size == 4) - info->complex_float_index = info->type_stack->type.indx; - else - info->complex_double_index = info->type_stack->type.indx; - - return true; -} - -/* Make a boolean type. IEEE doesn't support these, so we just make - an integer type instead. */ - -static boolean -ieee_bool_type (p, size) - PTR p; - unsigned int size; -{ - return ieee_int_type (p, size, true); -} - -/* Make an enumeration. */ - -static boolean -ieee_enum_type (p, tag, names, vals) - PTR p; - const char *tag; - const char **names; - bfd_signed_vma *vals; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - struct ieee_defined_enum *e; - boolean localp, simple; - unsigned int indx; - int i = 0; - - localp = false; - indx = (unsigned int) -1; - for (e = info->enums; e != NULL; e = e->next) - { - if (tag == NULL) - { - if (e->tag != NULL) - continue; - } - else - { - if (e->tag == NULL - || tag[0] != e->tag[0] - || strcmp (tag, e->tag) != 0) - continue; - } - - if (! e->defined) - { - /* This enum tag has been seen but not defined. */ - indx = e->indx; - break; - } - - if (names != NULL && e->names != NULL) - { - for (i = 0; names[i] != NULL && e->names[i] != NULL; i++) - { - if (names[i][0] != e->names[i][0] - || vals[i] != e->vals[i] - || strcmp (names[i], e->names[i]) != 0) - break; - } - } - - if ((names == NULL && e->names == NULL) - || (names != NULL - && e->names != NULL - && names[i] == NULL - && e->names[i] == NULL)) - { - /* We've seen this enum before. */ - return ieee_push_type (info, e->indx, 0, true, false); - } - - if (tag != NULL) - { - /* We've already seen an enum of the same name, so we must make - sure to output this one locally. */ - localp = true; - break; - } - } - - /* If this is a simple enumeration, in which the values start at 0 - and always increment by 1, we can use type E. Otherwise we must - use type N. */ - - simple = true; - if (names != NULL) - { - for (i = 0; names[i] != NULL; i++) - { - if (vals[i] != i) - { - simple = false; - break; - } - } - } - - if (! ieee_define_named_type (info, tag, indx, 0, true, localp, - (struct ieee_buflist *) NULL) - || ! ieee_write_number (info, simple ? 'E' : 'N')) - return false; - if (simple) - { - /* FIXME: This is supposed to be the enumeration size, but we - don't store that. */ - if (! ieee_write_number (info, 4)) - return false; - } - if (names != NULL) - { - for (i = 0; names[i] != NULL; i++) - { - if (! ieee_write_id (info, names[i])) - return false; - if (! simple) - { - if (! ieee_write_number (info, vals[i])) - return false; - } - } - } - - if (! localp) - { - if (indx == (unsigned int) -1) - { - e = (struct ieee_defined_enum *) xmalloc (sizeof *e); - memset (e, 0, sizeof *e); - e->indx = info->type_stack->type.indx; - e->tag = tag; - - e->next = info->enums; - info->enums = e; - } - - e->names = names; - e->vals = vals; - e->defined = true; - } - - return true; -} - -/* Make a pointer type. */ - -static boolean -ieee_pointer_type (p) - PTR p; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - boolean localp; - unsigned int indx; - struct ieee_modified_type *m = NULL; - - localp = info->type_stack->type.localp; - indx = ieee_pop_type (info); - - /* A pointer to a simple builtin type can be obtained by adding 32. - FIXME: Will this be a short pointer, and will that matter? */ - if (indx < 32) - return ieee_push_type (info, indx + 32, 0, true, false); - - if (! localp) - { - m = ieee_get_modified_info (p, indx); - if (m == NULL) - return false; - - /* FIXME: The size should depend upon the architecture. */ - if (m->pointer > 0) - return ieee_push_type (info, m->pointer, 4, true, false); - } - - if (! ieee_define_type (info, 4, true, localp) - || ! ieee_write_number (info, 'P') - || ! ieee_write_number (info, indx)) - return false; - - if (! localp) - m->pointer = info->type_stack->type.indx; - - return true; -} - -/* Make a function type. This will be called for a method, but we - don't want to actually add it to the type table in that case. We - handle this by defining the type in a private buffer, and only - adding that buffer to the typedef block if we are going to use it. */ - -static boolean -ieee_function_type (p, argcount, varargs) - PTR p; - int argcount; - boolean varargs; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - boolean localp; - unsigned int *args = NULL; - int i; - unsigned int retindx; - struct ieee_buflist fndef; - struct ieee_modified_type *m; - - localp = false; - - if (argcount > 0) - { - args = (unsigned int *) xmalloc (argcount * sizeof *args); - for (i = argcount - 1; i >= 0; i--) - { - if (info->type_stack->type.localp) - localp = true; - args[i] = ieee_pop_type (info); - } - } - else if (argcount < 0) - varargs = false; - - if (info->type_stack->type.localp) - localp = true; - retindx = ieee_pop_type (info); - - m = NULL; - if (argcount < 0 && ! localp) - { - m = ieee_get_modified_info (p, retindx); - if (m == NULL) - return false; - - if (m->function > 0) - return ieee_push_type (info, m->function, 0, true, false); - } - - /* An attribute of 0x41 means that the frame and push mask are - unknown. */ - if (! ieee_init_buffer (info, &fndef) - || ! ieee_define_named_type (info, (const char *) NULL, - (unsigned int) -1, 0, true, localp, - &fndef) - || ! ieee_write_number (info, 'x') - || ! ieee_write_number (info, 0x41) - || ! ieee_write_number (info, 0) - || ! ieee_write_number (info, 0) - || ! ieee_write_number (info, retindx) - || ! ieee_write_number (info, (bfd_vma) argcount + (varargs ? 1 : 0))) - return false; - if (argcount > 0) - { - for (i = 0; i < argcount; i++) - if (! ieee_write_number (info, args[i])) - return false; - free (args); - } - if (varargs) - { - /* A varargs function is represented by writing out the last - argument as type void *, although this makes little sense. */ - if (! ieee_write_number (info, (bfd_vma) builtin_void + 32)) - return false; - } - - if (! ieee_write_number (info, 0)) - return false; - - /* We wrote the information into fndef, in case we don't need it. - It will be appended to info->types by ieee_pop_type. */ - info->type_stack->type.fndef = fndef; - - if (m != NULL) - m->function = info->type_stack->type.indx; - - return true; -} - -/* Make a reference type. */ - -static boolean -ieee_reference_type (p) - PTR p; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - - /* IEEE appears to record a normal pointer type, and then use a - pmisc record to indicate that it is really a reference. */ - - if (! ieee_pointer_type (p)) - return false; - info->type_stack->type.referencep = true; - return true; -} - -/* Make a range type. */ - -static boolean -ieee_range_type (p, low, high) - PTR p; - bfd_signed_vma low; - bfd_signed_vma high; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - unsigned int size; - boolean unsignedp, localp; - - size = info->type_stack->type.size; - unsignedp = info->type_stack->type.unsignedp; - localp = info->type_stack->type.localp; - ieee_pop_unused_type (info); - return (ieee_define_type (info, size, unsignedp, localp) - && ieee_write_number (info, 'R') - && ieee_write_number (info, (bfd_vma) low) - && ieee_write_number (info, (bfd_vma) high) - && ieee_write_number (info, unsignedp ? 0 : 1) - && ieee_write_number (info, size)); -} - -/* Make an array type. */ - -/*ARGSUSED*/ -static boolean -ieee_array_type (p, low, high, stringp) - PTR p; - bfd_signed_vma low; - bfd_signed_vma high; - boolean stringp; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - unsigned int eleindx; - boolean localp; - unsigned int size; - struct ieee_modified_type *m = NULL; - struct ieee_modified_array_type *a; - - /* IEEE does not store the range, so we just ignore it. */ - ieee_pop_unused_type (info); - localp = info->type_stack->type.localp; - size = info->type_stack->type.size; - eleindx = ieee_pop_type (info); - - /* If we don't know the range, treat the size as exactly one - element. */ - if (low < high) - size *= (high - low) + 1; - - if (! localp) - { - m = ieee_get_modified_info (info, eleindx); - if (m == NULL) - return false; - - for (a = m->arrays; a != NULL; a = a->next) - { - if (a->low == low && a->high == high) - return ieee_push_type (info, a->indx, size, false, false); - } - } - - if (! ieee_define_type (info, size, false, localp) - || ! ieee_write_number (info, low == 0 ? 'Z' : 'C') - || ! ieee_write_number (info, eleindx)) - return false; - if (low != 0) - { - if (! ieee_write_number (info, low)) - return false; - } - - if (! ieee_write_number (info, high + 1)) - return false; - - if (! localp) - { - a = (struct ieee_modified_array_type *) xmalloc (sizeof *a); - memset (a, 0, sizeof *a); - - a->indx = info->type_stack->type.indx; - a->low = low; - a->high = high; - - a->next = m->arrays; - m->arrays = a; - } - - return true; -} - -/* Make a set type. */ - -static boolean -ieee_set_type (p, bitstringp) - PTR p; - boolean bitstringp; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - boolean localp; - unsigned int eleindx; - - localp = info->type_stack->type.localp; - eleindx = ieee_pop_type (info); - - /* FIXME: We don't know the size, so we just use 4. */ - - return (ieee_define_type (info, 0, true, localp) - && ieee_write_number (info, 's') - && ieee_write_number (info, 4) - && ieee_write_number (info, eleindx)); -} - -/* Make an offset type. */ - -static boolean -ieee_offset_type (p) - PTR p; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - unsigned int targetindx, baseindx; - - targetindx = ieee_pop_type (info); - baseindx = ieee_pop_type (info); - - /* FIXME: The MRI C++ compiler does not appear to generate any - useful type information about an offset type. It just records a - pointer to member as an integer. The MRI/HP IEEE spec does - describe a pmisc record which can be used for a pointer to - member. Unfortunately, it does not describe the target type, - which seems pretty important. I'm going to punt this for now. */ - - return ieee_int_type (p, 4, true); -} - -/* Make a method type. */ - -static boolean -ieee_method_type (p, domain, argcount, varargs) - PTR p; - boolean domain; - int argcount; - boolean varargs; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - - /* FIXME: The MRI/HP IEEE spec defines a pmisc record to use for a - method, but the definition is incomplete. We just output an 'x' - type. */ - - if (domain) - ieee_pop_unused_type (info); - - return ieee_function_type (p, argcount, varargs); -} - -/* Make a const qualified type. */ - -static boolean -ieee_const_type (p) - PTR p; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - unsigned int size; - boolean unsignedp, localp; - unsigned int indx; - struct ieee_modified_type *m = NULL; - - size = info->type_stack->type.size; - unsignedp = info->type_stack->type.unsignedp; - localp = info->type_stack->type.localp; - indx = ieee_pop_type (info); - - if (! localp) - { - m = ieee_get_modified_info (info, indx); - if (m == NULL) - return false; - - if (m->const_qualified > 0) - return ieee_push_type (info, m->const_qualified, size, unsignedp, - false); - } - - if (! ieee_define_type (info, size, unsignedp, localp) - || ! ieee_write_number (info, 'n') - || ! ieee_write_number (info, 1) - || ! ieee_write_number (info, indx)) - return false; - - if (! localp) - m->const_qualified = info->type_stack->type.indx; - - return true; -} - -/* Make a volatile qualified type. */ - -static boolean -ieee_volatile_type (p) - PTR p; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - unsigned int size; - boolean unsignedp, localp; - unsigned int indx; - struct ieee_modified_type *m = NULL; - - size = info->type_stack->type.size; - unsignedp = info->type_stack->type.unsignedp; - localp = info->type_stack->type.localp; - indx = ieee_pop_type (info); - - if (! localp) - { - m = ieee_get_modified_info (info, indx); - if (m == NULL) - return false; - - if (m->volatile_qualified > 0) - return ieee_push_type (info, m->volatile_qualified, size, unsignedp, - false); - } - - if (! ieee_define_type (info, size, unsignedp, localp) - || ! ieee_write_number (info, 'n') - || ! ieee_write_number (info, 2) - || ! ieee_write_number (info, indx)) - return false; - - if (! localp) - m->volatile_qualified = info->type_stack->type.indx; - - return true; -} - -/* Convert an enum debug_visibility into a CXXFLAGS value. */ - -static unsigned int -ieee_vis_to_flags (visibility) - enum debug_visibility visibility; -{ - switch (visibility) - { - default: - abort (); - case DEBUG_VISIBILITY_PUBLIC: - return CXXFLAGS_VISIBILITY_PUBLIC; - case DEBUG_VISIBILITY_PRIVATE: - return CXXFLAGS_VISIBILITY_PRIVATE; - case DEBUG_VISIBILITY_PROTECTED: - return CXXFLAGS_VISIBILITY_PROTECTED; - } - /*NOTREACHED*/ -} - -/* Start defining a struct type. We build it in the strdef field on - the stack, to avoid confusing type definitions required by the - fields with the struct type itself. */ - -static boolean -ieee_start_struct_type (p, tag, id, structp, size) - PTR p; - const char *tag; - unsigned int id; - boolean structp; - unsigned int size; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - boolean localp, ignorep; - boolean copy; - char ab[20]; - const char *look; - struct ieee_name_type_hash_entry *h; - struct ieee_name_type *nt, *ntlook; - struct ieee_buflist strdef; - - localp = false; - ignorep = false; - - /* We need to create a tag for internal use even if we don't want - one for external use. This will let us refer to an anonymous - struct. */ - if (tag != NULL) - { - look = tag; - copy = false; - } - else - { - sprintf (ab, "__anon%u", id); - look = ab; - copy = true; - } - - /* If we already have references to the tag, we must use the - existing type index. */ - h = ieee_name_type_hash_lookup (&info->tags, look, true, copy); - if (h == NULL) - return false; - - nt = NULL; - for (ntlook = h->types; ntlook != NULL; ntlook = ntlook->next) - { - if (ntlook->id == id) - nt = ntlook; - else if (! ntlook->type.localp) - { - /* We are creating a duplicate definition of a globally - defined tag. Force it to be local to avoid - confusion. */ - localp = true; - } - } - - if (nt != NULL) - { - assert (localp == nt->type.localp); - if (nt->kind == DEBUG_KIND_ILLEGAL && ! localp) - { - /* We've already seen a global definition of the type. - Ignore this new definition. */ - ignorep = true; - } - } - else - { - nt = (struct ieee_name_type *) xmalloc (sizeof *nt); - memset (nt, 0, sizeof *nt); - nt->id = id; - nt->type.name = h->root.string; - nt->next = h->types; - h->types = nt; - nt->type.indx = info->type_indx; - ++info->type_indx; - } - - nt->kind = DEBUG_KIND_ILLEGAL; - - if (! ieee_init_buffer (info, &strdef) - || ! ieee_define_named_type (info, tag, nt->type.indx, size, true, - localp, &strdef) - || ! ieee_write_number (info, structp ? 'S' : 'U') - || ! ieee_write_number (info, size)) - return false; - - if (! ignorep) - { - const char *hold; - - /* We never want nt->type.name to be NULL. We want the rest of - the type to be the object set up on the type stack; it will - have a NULL name if tag is NULL. */ - hold = nt->type.name; - nt->type = info->type_stack->type; - nt->type.name = hold; - } - - info->type_stack->type.name = tag; - info->type_stack->type.strdef = strdef; - info->type_stack->type.ignorep = ignorep; - - return true; -} - -/* Add a field to a struct. */ - -static boolean -ieee_struct_field (p, name, bitpos, bitsize, visibility) - PTR p; - const char *name; - bfd_vma bitpos; - bfd_vma bitsize; - enum debug_visibility visibility; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - unsigned int size; - boolean unsignedp; - boolean referencep; - boolean localp; - unsigned int indx; - bfd_vma offset; - - assert (info->type_stack != NULL - && info->type_stack->next != NULL - && ! ieee_buffer_emptyp (&info->type_stack->next->type.strdef)); - - /* If we are ignoring this struct definition, just pop and ignore - the type. */ - if (info->type_stack->next->type.ignorep) - { - ieee_pop_unused_type (info); - return true; - } - - size = info->type_stack->type.size; - unsignedp = info->type_stack->type.unsignedp; - referencep = info->type_stack->type.referencep; - localp = info->type_stack->type.localp; - indx = ieee_pop_type (info); - - if (localp) - info->type_stack->type.localp = true; - - if (info->type_stack->type.classdef != NULL) - { - unsigned int flags; - unsigned int nindx; - - /* This is a class. We must add a description of this field to - the class records we are building. */ - - flags = ieee_vis_to_flags (visibility); - nindx = info->type_stack->type.classdef->indx; - if (! ieee_change_buffer (info, - &info->type_stack->type.classdef->pmiscbuf) - || ! ieee_write_asn (info, nindx, 'd') - || ! ieee_write_asn (info, nindx, flags) - || ! ieee_write_atn65 (info, nindx, name) - || ! ieee_write_atn65 (info, nindx, name)) - return false; - info->type_stack->type.classdef->pmisccount += 4; - - if (referencep) - { - unsigned int nindx; - - /* We need to output a record recording that this field is - really of reference type. We put this on the refs field - of classdef, so that it can be appended to the C++ - records after the class is defined. */ - - nindx = info->name_indx; - ++info->name_indx; - - if (! ieee_change_buffer (info, - &info->type_stack->type.classdef->refs) - || ! ieee_write_byte (info, (int) ieee_nn_record) - || ! ieee_write_number (info, nindx) - || ! ieee_write_id (info, "") - || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum) - || ! ieee_write_number (info, nindx) - || ! ieee_write_number (info, 0) - || ! ieee_write_number (info, 62) - || ! ieee_write_number (info, 80) - || ! ieee_write_number (info, 4) - || ! ieee_write_asn (info, nindx, 'R') - || ! ieee_write_asn (info, nindx, 3) - || ! ieee_write_atn65 (info, nindx, info->type_stack->type.name) - || ! ieee_write_atn65 (info, nindx, name)) - return false; - } - } - - /* If the bitsize doesn't match the expected size, we need to output - a bitfield type. */ - if (size == 0 || bitsize == 0 || bitsize == size * 8) - offset = bitpos / 8; - else - { - if (! ieee_define_type (info, 0, unsignedp, - info->type_stack->type.localp) - || ! ieee_write_number (info, 'g') - || ! ieee_write_number (info, unsignedp ? 0 : 1) - || ! ieee_write_number (info, bitsize) - || ! ieee_write_number (info, indx)) - return false; - indx = ieee_pop_type (info); - offset = bitpos; - } - - /* Switch to the struct we are building in order to output this - field definition. */ - return (ieee_change_buffer (info, &info->type_stack->type.strdef) - && ieee_write_id (info, name) - && ieee_write_number (info, indx) - && ieee_write_number (info, offset)); -} - -/* Finish up a struct type. */ - -static boolean -ieee_end_struct_type (p) - PTR p; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - struct ieee_buflist *pb; - - assert (info->type_stack != NULL - && ! ieee_buffer_emptyp (&info->type_stack->type.strdef)); - - /* If we were ignoring this struct definition because it was a - duplicate defintion, just through away whatever bytes we have - accumulated. Leave the type on the stack. */ - if (info->type_stack->type.ignorep) - return true; - - /* If this is not a duplicate definition of this tag, then localp - will be false, and we can put it in the global type block. - FIXME: We should avoid outputting duplicate definitions which are - the same. */ - if (! info->type_stack->type.localp) - { - /* Make sure we have started the global type block. */ - if (ieee_buffer_emptyp (&info->global_types)) - { - if (! ieee_change_buffer (info, &info->global_types) - || ! ieee_write_byte (info, (int) ieee_bb_record_enum) - || ! ieee_write_byte (info, 2) - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, "")) - return false; - } - pb = &info->global_types; - } - else - { - /* Make sure we have started the types block. */ - if (ieee_buffer_emptyp (&info->types)) - { - if (! ieee_change_buffer (info, &info->types) - || ! ieee_write_byte (info, (int) ieee_bb_record_enum) - || ! ieee_write_byte (info, 1) - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, info->modname)) - return false; - } - pb = &info->types; - } - - /* Append the struct definition to the types. */ - if (! ieee_append_buffer (info, pb, &info->type_stack->type.strdef) - || ! ieee_init_buffer (info, &info->type_stack->type.strdef)) - return false; - - /* Leave the struct on the type stack. */ - - return true; -} - -/* Start a class type. */ - -static boolean -ieee_start_class_type (p, tag, id, structp, size, vptr, ownvptr) - PTR p; - const char *tag; - unsigned int id; - boolean structp; - unsigned int size; - boolean vptr; - boolean ownvptr; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - const char *vclass; - struct ieee_buflist pmiscbuf; - unsigned int indx; - struct ieee_type_class *classdef; - - /* A C++ class is output as a C++ struct along with a set of pmisc - records describing the class. */ - - /* We need to have a name so that we can associate the struct and - the class. */ - if (tag == NULL) - { - char *t; - - t = (char *) xmalloc (20); - sprintf (t, "__anon%u", id); - tag = t; - } - - /* We can't write out the virtual table information until we have - finished the class, because we don't know the virtual table size. - We get the size from the largest voffset we see. */ - vclass = NULL; - if (vptr && ! ownvptr) - { - vclass = info->type_stack->type.name; - assert (vclass != NULL); - /* We don't call ieee_pop_unused_type, since the class should - get defined. */ - (void) ieee_pop_type (info); - } - - if (! ieee_start_struct_type (p, tag, id, structp, size)) - return false; - - indx = info->name_indx; - ++info->name_indx; - - /* We write out pmisc records into the classdef field. We will - write out the pmisc start after we know the number of records we - need. */ - if (! ieee_init_buffer (info, &pmiscbuf) - || ! ieee_change_buffer (info, &pmiscbuf) - || ! ieee_write_asn (info, indx, 'T') - || ! ieee_write_asn (info, indx, structp ? 'o' : 'u') - || ! ieee_write_atn65 (info, indx, tag)) - return false; - - classdef = (struct ieee_type_class *) xmalloc (sizeof *classdef); - memset (classdef, 0, sizeof *classdef); - - classdef->indx = indx; - classdef->pmiscbuf = pmiscbuf; - classdef->pmisccount = 3; - classdef->vclass = vclass; - classdef->ownvptr = ownvptr; - - info->type_stack->type.classdef = classdef; - - return true; -} - -/* Add a static member to a class. */ - -static boolean -ieee_class_static_member (p, name, physname, visibility) - PTR p; - const char *name; - const char *physname; - enum debug_visibility visibility; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - unsigned int flags; - unsigned int nindx; - - /* We don't care about the type. Hopefully there will be a call to - ieee_variable declaring the physical name and the type, since - that is where an IEEE consumer must get the type. */ - ieee_pop_unused_type (info); - - assert (info->type_stack != NULL - && info->type_stack->type.classdef != NULL); - - flags = ieee_vis_to_flags (visibility); - flags |= CXXFLAGS_STATIC; - - nindx = info->type_stack->type.classdef->indx; - - if (! ieee_change_buffer (info, &info->type_stack->type.classdef->pmiscbuf) - || ! ieee_write_asn (info, nindx, 'd') - || ! ieee_write_asn (info, nindx, flags) - || ! ieee_write_atn65 (info, nindx, name) - || ! ieee_write_atn65 (info, nindx, physname)) - return false; - info->type_stack->type.classdef->pmisccount += 4; - - return true; -} - -/* Add a base class to a class. */ - -static boolean -ieee_class_baseclass (p, bitpos, virtual, visibility) - PTR p; - bfd_vma bitpos; - boolean virtual; - enum debug_visibility visibility; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - const char *bname; - boolean localp; - unsigned int bindx; - char *fname; - unsigned int flags; - unsigned int nindx; - - assert (info->type_stack != NULL - && info->type_stack->type.name != NULL - && info->type_stack->next != NULL - && info->type_stack->next->type.classdef != NULL - && ! ieee_buffer_emptyp (&info->type_stack->next->type.strdef)); - - bname = info->type_stack->type.name; - localp = info->type_stack->type.localp; - bindx = ieee_pop_type (info); - - /* We are currently defining both a struct and a class. We must - write out a field definition in the struct which holds the base - class. The stabs debugging reader will create a field named - _vb$CLASS for a virtual base class, so we just use that. FIXME: - we should not depend upon a detail of stabs debugging. */ - if (virtual) - { - fname = (char *) xmalloc (strlen (bname) + sizeof "_vb$"); - sprintf (fname, "_vb$%s", bname); - flags = BASEFLAGS_VIRTUAL; - } - else - { - if (localp) - info->type_stack->type.localp = true; - - fname = (char *) xmalloc (strlen (bname) + sizeof "_b$"); - sprintf (fname, "_b$%s", bname); - - if (! ieee_change_buffer (info, &info->type_stack->type.strdef) - || ! ieee_write_id (info, fname) - || ! ieee_write_number (info, bindx) - || ! ieee_write_number (info, bitpos / 8)) - return false; - flags = 0; - } - - if (visibility == DEBUG_VISIBILITY_PRIVATE) - flags |= BASEFLAGS_PRIVATE; - - nindx = info->type_stack->type.classdef->indx; - - if (! ieee_change_buffer (info, &info->type_stack->type.classdef->pmiscbuf) - || ! ieee_write_asn (info, nindx, 'b') - || ! ieee_write_asn (info, nindx, flags) - || ! ieee_write_atn65 (info, nindx, bname) - || ! ieee_write_asn (info, nindx, 0) - || ! ieee_write_atn65 (info, nindx, fname)) - return false; - info->type_stack->type.classdef->pmisccount += 5; - - free (fname); - - return true; -} - -/* Start building a method for a class. */ - -static boolean -ieee_class_start_method (p, name) - PTR p; - const char *name; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - - assert (info->type_stack != NULL - && info->type_stack->type.classdef != NULL - && info->type_stack->type.classdef->method == NULL); - - info->type_stack->type.classdef->method = name; - - return true; -} - -/* Define a new method variant, either static or not. */ - -static boolean -ieee_class_method_var (info, physname, visibility, staticp, constp, - volatilep, voffset, context) - struct ieee_handle *info; - const char *physname; - enum debug_visibility visibility; - boolean staticp; - boolean constp; - boolean volatilep; - bfd_vma voffset; - boolean context; -{ - unsigned int flags; - unsigned int nindx; - boolean virtual; - - /* We don't need the type of the method. An IEEE consumer which - wants the type must track down the function by the physical name - and get the type from that. */ - ieee_pop_unused_type (info); - - /* We don't use the context. FIXME: We probably ought to use it to - adjust the voffset somehow, but I don't really know how. */ - if (context) - ieee_pop_unused_type (info); - - assert (info->type_stack != NULL - && info->type_stack->type.classdef != NULL - && info->type_stack->type.classdef->method != NULL); - - flags = ieee_vis_to_flags (visibility); - - /* FIXME: We never set CXXFLAGS_OVERRIDE, CXXFLAGS_OPERATOR, - CXXFLAGS_CTORDTOR, CXXFLAGS_CTOR, or CXXFLAGS_INLINE. */ - - if (staticp) - flags |= CXXFLAGS_STATIC; - if (constp) - flags |= CXXFLAGS_CONST; - if (volatilep) - flags |= CXXFLAGS_VOLATILE; - - nindx = info->type_stack->type.classdef->indx; - - virtual = context || voffset > 0; - - if (! ieee_change_buffer (info, - &info->type_stack->type.classdef->pmiscbuf) - || ! ieee_write_asn (info, nindx, virtual ? 'v' : 'm') - || ! ieee_write_asn (info, nindx, flags) - || ! ieee_write_atn65 (info, nindx, - info->type_stack->type.classdef->method) - || ! ieee_write_atn65 (info, nindx, physname)) - return false; - - if (virtual) - { - if (voffset > info->type_stack->type.classdef->voffset) - info->type_stack->type.classdef->voffset = voffset; - if (! ieee_write_asn (info, nindx, voffset)) - return false; - ++info->type_stack->type.classdef->pmisccount; - } - - if (! ieee_write_asn (info, nindx, 0)) - return false; - - info->type_stack->type.classdef->pmisccount += 5; - - return true; -} - -/* Define a new method variant. */ - -static boolean -ieee_class_method_variant (p, physname, visibility, constp, volatilep, - voffset, context) - PTR p; - const char *physname; - enum debug_visibility visibility; - boolean constp; - boolean volatilep; - bfd_vma voffset; - boolean context; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - - return ieee_class_method_var (info, physname, visibility, false, constp, - volatilep, voffset, context); -} - -/* Define a new static method variant. */ - -static boolean -ieee_class_static_method_variant (p, physname, visibility, constp, volatilep) - PTR p; - const char *physname; - enum debug_visibility visibility; - boolean constp; - boolean volatilep; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - - return ieee_class_method_var (info, physname, visibility, true, constp, - volatilep, 0, false); -} - -/* Finish up a method. */ - -static boolean -ieee_class_end_method (p) - PTR p; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - - assert (info->type_stack != NULL - && info->type_stack->type.classdef != NULL - && info->type_stack->type.classdef->method != NULL); - - info->type_stack->type.classdef->method = NULL; - - return true; -} - -/* Finish up a class. */ - -static boolean -ieee_end_class_type (p) - PTR p; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - unsigned int nindx; - - assert (info->type_stack != NULL - && info->type_stack->type.classdef != NULL); - - /* If we were ignoring this class definition because it was a - duplicate definition, just through away whatever bytes we have - accumulated. Leave the type on the stack. */ - if (info->type_stack->type.ignorep) - return true; - - nindx = info->type_stack->type.classdef->indx; - - /* If we have a virtual table, we can write out the information now. */ - if (info->type_stack->type.classdef->vclass != NULL - || info->type_stack->type.classdef->ownvptr) - { - if (! ieee_change_buffer (info, - &info->type_stack->type.classdef->pmiscbuf) - || ! ieee_write_asn (info, nindx, 'z') - || ! ieee_write_atn65 (info, nindx, "") - || ! ieee_write_asn (info, nindx, - info->type_stack->type.classdef->voffset)) - return false; - if (info->type_stack->type.classdef->ownvptr) - { - if (! ieee_write_atn65 (info, nindx, "")) - return false; - } - else - { - if (! ieee_write_atn65 (info, nindx, - info->type_stack->type.classdef->vclass)) - return false; - } - if (! ieee_write_asn (info, nindx, 0)) - return false; - info->type_stack->type.classdef->pmisccount += 5; - } - - /* Now that we know the number of pmisc records, we can write out - the atn62 which starts the pmisc records, and append them to the - C++ buffers. */ - - if (! ieee_change_buffer (info, &info->cxx) - || ! ieee_write_byte (info, (int) ieee_nn_record) - || ! ieee_write_number (info, nindx) - || ! ieee_write_id (info, "") - || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum) - || ! ieee_write_number (info, nindx) - || ! ieee_write_number (info, 0) - || ! ieee_write_number (info, 62) - || ! ieee_write_number (info, 80) - || ! ieee_write_number (info, - info->type_stack->type.classdef->pmisccount)) - return false; - - if (! ieee_append_buffer (info, &info->cxx, - &info->type_stack->type.classdef->pmiscbuf)) - return false; - if (! ieee_buffer_emptyp (&info->type_stack->type.classdef->refs)) - { - if (! ieee_append_buffer (info, &info->cxx, - &info->type_stack->type.classdef->refs)) - return false; - } - - return ieee_end_struct_type (p); -} - -/* Push a previously seen typedef onto the type stack. */ - -static boolean -ieee_typedef_type (p, name) - PTR p; - const char *name; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - struct ieee_name_type_hash_entry *h; - struct ieee_name_type *nt; - - h = ieee_name_type_hash_lookup (&info->typedefs, name, false, false); - - /* h should never be NULL, since that would imply that the generic - debugging code has asked for a typedef which it has not yet - defined. */ - assert (h != NULL); - - /* We always use the most recently defined type for this name, which - will be the first one on the list. */ - - nt = h->types; - if (! ieee_push_type (info, nt->type.indx, nt->type.size, - nt->type.unsignedp, nt->type.localp)) - return false; - - /* Copy over any other type information we may have. */ - info->type_stack->type = nt->type; - - return true; -} - -/* Push a tagged type onto the type stack. */ - -static boolean -ieee_tag_type (p, name, id, kind) - PTR p; - const char *name; - unsigned int id; - enum debug_type_kind kind; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - boolean localp; - boolean copy; - char ab[20]; - struct ieee_name_type_hash_entry *h; - struct ieee_name_type *nt; - - if (kind == DEBUG_KIND_ENUM) - { - struct ieee_defined_enum *e; - - if (name == NULL) - abort (); - for (e = info->enums; e != NULL; e = e->next) - if (e->tag != NULL && strcmp (e->tag, name) == 0) - return ieee_push_type (info, e->indx, 0, true, false); - - e = (struct ieee_defined_enum *) xmalloc (sizeof *e); - memset (e, 0, sizeof *e); - - e->indx = info->type_indx; - ++info->type_indx; - e->tag = name; - e->defined = false; - - e->next = info->enums; - info->enums = e; - - return ieee_push_type (info, e->indx, 0, true, false); - } - - localp = false; - - copy = false; - if (name == NULL) - { - sprintf (ab, "__anon%u", id); - name = ab; - copy = true; - } - - h = ieee_name_type_hash_lookup (&info->tags, name, true, copy); - if (h == NULL) - return false; - - for (nt = h->types; nt != NULL; nt = nt->next) - { - if (nt->id == id) - { - if (! ieee_push_type (info, nt->type.indx, nt->type.size, - nt->type.unsignedp, nt->type.localp)) - return false; - /* Copy over any other type information we may have. */ - info->type_stack->type = nt->type; - return true; - } - - if (! nt->type.localp) - { - /* This is a duplicate of a global type, so it must be - local. */ - localp = true; - } - } - - nt = (struct ieee_name_type *) xmalloc (sizeof *nt); - memset (nt, 0, sizeof *nt); - - nt->id = id; - nt->type.name = h->root.string; - nt->type.indx = info->type_indx; - nt->type.localp = localp; - ++info->type_indx; - nt->kind = kind; - - nt->next = h->types; - h->types = nt; - - if (! ieee_push_type (info, nt->type.indx, 0, false, localp)) - return false; - - info->type_stack->type.name = h->root.string; - - return true; -} - -/* Output a typedef. */ - -static boolean -ieee_typdef (p, name) - PTR p; - const char *name; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - struct ieee_write_type type; - unsigned int indx; - boolean found; - boolean localp; - struct ieee_name_type_hash_entry *h; - struct ieee_name_type *nt; - - type = info->type_stack->type; - indx = type.indx; - - /* If this is a simple builtin type using a builtin name, we don't - want to output the typedef itself. We also want to change the - type index to correspond to the name being used. We recognize - names used in stabs debugging output even if they don't exactly - correspond to the names used for the IEEE builtin types. */ - found = false; - if (indx <= (unsigned int) builtin_bcd_float) - { - switch ((enum builtin_types) indx) - { - default: - break; - - case builtin_void: - if (strcmp (name, "void") == 0) - found = true; - break; - - case builtin_signed_char: - case builtin_char: - if (strcmp (name, "signed char") == 0) - { - indx = (unsigned int) builtin_signed_char; - found = true; - } - else if (strcmp (name, "char") == 0) - { - indx = (unsigned int) builtin_char; - found = true; - } - break; - - case builtin_unsigned_char: - if (strcmp (name, "unsigned char") == 0) - found = true; - break; - - case builtin_signed_short_int: - case builtin_short: - case builtin_short_int: - case builtin_signed_short: - if (strcmp (name, "signed short int") == 0) - { - indx = (unsigned int) builtin_signed_short_int; - found = true; - } - else if (strcmp (name, "short") == 0) - { - indx = (unsigned int) builtin_short; - found = true; - } - else if (strcmp (name, "short int") == 0) - { - indx = (unsigned int) builtin_short_int; - found = true; - } - else if (strcmp (name, "signed short") == 0) - { - indx = (unsigned int) builtin_signed_short; - found = true; - } - break; - - case builtin_unsigned_short_int: - case builtin_unsigned_short: - if (strcmp (name, "unsigned short int") == 0 - || strcmp (name, "short unsigned int") == 0) - { - indx = builtin_unsigned_short_int; - found = true; - } - else if (strcmp (name, "unsigned short") == 0) - { - indx = builtin_unsigned_short; - found = true; - } - break; - - case builtin_signed_long: - case builtin_int: /* FIXME: Size depends upon architecture. */ - case builtin_long: - if (strcmp (name, "signed long") == 0) - { - indx = builtin_signed_long; - found = true; - } - else if (strcmp (name, "int") == 0) - { - indx = builtin_int; - found = true; - } - else if (strcmp (name, "long") == 0 - || strcmp (name, "long int") == 0) - { - indx = builtin_long; - found = true; - } - break; - - case builtin_unsigned_long: - case builtin_unsigned: /* FIXME: Size depends upon architecture. */ - case builtin_unsigned_int: /* FIXME: Like builtin_unsigned. */ - if (strcmp (name, "unsigned long") == 0 - || strcmp (name, "long unsigned int") == 0) - { - indx = builtin_unsigned_long; - found = true; - } - else if (strcmp (name, "unsigned") == 0) - { - indx = builtin_unsigned; - found = true; - } - else if (strcmp (name, "unsigned int") == 0) - { - indx = builtin_unsigned_int; - found = true; - } - break; - - case builtin_signed_long_long: - if (strcmp (name, "signed long long") == 0 - || strcmp (name, "long long int") == 0) - found = true; - break; - - case builtin_unsigned_long_long: - if (strcmp (name, "unsigned long long") == 0 - || strcmp (name, "long long unsigned int") == 0) - found = true; - break; - - case builtin_float: - if (strcmp (name, "float") == 0) - found = true; - break; - - case builtin_double: - if (strcmp (name, "double") == 0) - found = true; - break; - - case builtin_long_double: - if (strcmp (name, "long double") == 0) - found = true; - break; - - case builtin_long_long_double: - if (strcmp (name, "long long double") == 0) - found = true; - break; - } - - if (found) - type.indx = indx; - } - - h = ieee_name_type_hash_lookup (&info->typedefs, name, true, false); - if (h == NULL) - return false; - - /* See if we have already defined this type with this name. */ - localp = type.localp; - for (nt = h->types; nt != NULL; nt = nt->next) - { - if (nt->id == indx) - { - /* If this is a global definition, then we don't need to - do anything here. */ - if (! nt->type.localp) - { - ieee_pop_unused_type (info); - return true; - } - } - else - { - /* This is a duplicate definition, so make this one local. */ - localp = true; - } - } - - /* We need to add a new typedef for this type. */ - - nt = (struct ieee_name_type *) xmalloc (sizeof *nt); - memset (nt, 0, sizeof *nt); - nt->id = indx; - nt->type = type; - nt->type.name = name; - nt->type.localp = localp; - nt->kind = DEBUG_KIND_ILLEGAL; - - nt->next = h->types; - h->types = nt; - - if (found) - { - /* This is one of the builtin typedefs, so we don't need to - actually define it. */ - ieee_pop_unused_type (info); - return true; - } - - indx = ieee_pop_type (info); - - if (! ieee_define_named_type (info, name, (unsigned int) -1, type.size, - type.unsignedp, localp, - (struct ieee_buflist *) NULL) - || ! ieee_write_number (info, 'T') - || ! ieee_write_number (info, indx)) - return false; - - /* Remove the type we just added to the type stack. This should not - be ieee_pop_unused_type, since the type is used, we just don't - need it now. */ - (void) ieee_pop_type (info); - - return true; -} - -/* Output a tag for a type. We don't have to do anything here. */ - -static boolean -ieee_tag (p, name) - PTR p; - const char *name; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - - /* This should not be ieee_pop_unused_type, since we want the type - to be defined. */ - (void) ieee_pop_type (info); - return true; -} - -/* Output an integer constant. */ - -static boolean -ieee_int_constant (p, name, val) - PTR p; - const char *name; - bfd_vma val; -{ - /* FIXME. */ - return true; -} - -/* Output a floating point constant. */ - -static boolean -ieee_float_constant (p, name, val) - PTR p; - const char *name; - double val; -{ - /* FIXME. */ - return true; -} - -/* Output a typed constant. */ - -static boolean -ieee_typed_constant (p, name, val) - PTR p; - const char *name; - bfd_vma val; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - - /* FIXME. */ - ieee_pop_unused_type (info); - return true; -} - -/* Output a variable. */ - -static boolean -ieee_variable (p, name, kind, val) - PTR p; - const char *name; - enum debug_var_kind kind; - bfd_vma val; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - unsigned int name_indx; - unsigned int size; - boolean referencep; - unsigned int type_indx; - boolean asn; - int refflag; - - size = info->type_stack->type.size; - referencep = info->type_stack->type.referencep; - type_indx = ieee_pop_type (info); - - assert (! ieee_buffer_emptyp (&info->vars)); - if (! ieee_change_buffer (info, &info->vars)) - return false; - - name_indx = info->name_indx; - ++info->name_indx; - - /* Write out an NN and an ATN record for this variable. */ - if (! ieee_write_byte (info, (int) ieee_nn_record) - || ! ieee_write_number (info, name_indx) - || ! ieee_write_id (info, name) - || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum) - || ! ieee_write_number (info, name_indx) - || ! ieee_write_number (info, type_indx)) - return false; - switch (kind) - { - default: - abort (); - return false; - case DEBUG_GLOBAL: - if (! ieee_write_number (info, 8) - || ! ieee_add_range (info, false, val, val + size)) - return false; - refflag = 0; - asn = true; - break; - case DEBUG_STATIC: - if (! ieee_write_number (info, 3) - || ! ieee_add_range (info, false, val, val + size)) - return false; - refflag = 1; - asn = true; - break; - case DEBUG_LOCAL_STATIC: - if (! ieee_write_number (info, 3) - || ! ieee_add_range (info, false, val, val + size)) - return false; - refflag = 2; - asn = true; - break; - case DEBUG_LOCAL: - if (! ieee_write_number (info, 1) - || ! ieee_write_number (info, val)) - return false; - refflag = 2; - asn = false; - break; - case DEBUG_REGISTER: - if (! ieee_write_number (info, 2) - || ! ieee_write_number (info, - ieee_genreg_to_regno (info->abfd, val))) - return false; - refflag = 2; - asn = false; - break; - } - - if (asn) - { - if (! ieee_write_asn (info, name_indx, val)) - return false; - } - - /* If this is really a reference type, then we just output it with - pointer type, and must now output a C++ record indicating that it - is really reference type. */ - if (referencep) - { - unsigned int nindx; - - nindx = info->name_indx; - ++info->name_indx; - - /* If this is a global variable, we want to output the misc - record in the C++ misc record block. Otherwise, we want to - output it just after the variable definition, which is where - the current buffer is. */ - if (refflag != 2) - { - if (! ieee_change_buffer (info, &info->cxx)) - return false; - } - - if (! ieee_write_byte (info, (int) ieee_nn_record) - || ! ieee_write_number (info, nindx) - || ! ieee_write_id (info, "") - || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum) - || ! ieee_write_number (info, nindx) - || ! ieee_write_number (info, 0) - || ! ieee_write_number (info, 62) - || ! ieee_write_number (info, 80) - || ! ieee_write_number (info, 3) - || ! ieee_write_asn (info, nindx, 'R') - || ! ieee_write_asn (info, nindx, refflag) - || ! ieee_write_atn65 (info, nindx, name)) - return false; - } - - return true; -} - -/* Start outputting information for a function. */ - -static boolean -ieee_start_function (p, name, global) - PTR p; - const char *name; - boolean global; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - boolean referencep; - unsigned int retindx, typeindx; - - referencep = info->type_stack->type.referencep; - retindx = ieee_pop_type (info); - - /* Besides recording a BB4 or BB6 block, we record the type of the - function in the BB1 typedef block. We can't write out the full - type until we have seen all the parameters, so we accumulate it - in info->fntype and info->fnargs. */ - if (! ieee_buffer_emptyp (&info->fntype)) - { - /* FIXME: This might happen someday if we support nested - functions. */ - abort (); - } - - info->fnname = name; - - /* An attribute of 0x40 means that the push mask is unknown. */ - if (! ieee_define_named_type (info, name, (unsigned int) -1, 0, false, true, - &info->fntype) - || ! ieee_write_number (info, 'x') - || ! ieee_write_number (info, 0x40) - || ! ieee_write_number (info, 0) - || ! ieee_write_number (info, 0) - || ! ieee_write_number (info, retindx)) - return false; - - typeindx = ieee_pop_type (info); - - if (! ieee_init_buffer (info, &info->fnargs)) - return false; - info->fnargcount = 0; - - /* If the function return value is actually a reference type, we - must add a record indicating that. */ - if (referencep) - { - unsigned int nindx; - - nindx = info->name_indx; - ++info->name_indx; - if (! ieee_change_buffer (info, &info->cxx) - || ! ieee_write_byte (info, (int) ieee_nn_record) - || ! ieee_write_number (info, nindx) - || ! ieee_write_id (info, "") - || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum) - || ! ieee_write_number (info, nindx) - || ! ieee_write_number (info, 0) - || ! ieee_write_number (info, 62) - || ! ieee_write_number (info, 80) - || ! ieee_write_number (info, 3) - || ! ieee_write_asn (info, nindx, 'R') - || ! ieee_write_asn (info, nindx, global ? 0 : 1) - || ! ieee_write_atn65 (info, nindx, name)) - return false; - } - - assert (! ieee_buffer_emptyp (&info->vars)); - if (! ieee_change_buffer (info, &info->vars)) - return false; - - /* The address is written out as the first block. */ - - ++info->block_depth; - - return (ieee_write_byte (info, (int) ieee_bb_record_enum) - && ieee_write_byte (info, global ? 4 : 6) - && ieee_write_number (info, 0) - && ieee_write_id (info, name) - && ieee_write_number (info, 0) - && ieee_write_number (info, typeindx)); -} - -/* Add a function parameter. This will normally be called before the - first block, so we postpone them until we see the block. */ - -static boolean -ieee_function_parameter (p, name, kind, val) - PTR p; - const char *name; - enum debug_parm_kind kind; - bfd_vma val; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - struct ieee_pending_parm *m, **pm; - - assert (info->block_depth == 1); - - m = (struct ieee_pending_parm *) xmalloc (sizeof *m); - memset (m, 0, sizeof *m); - - m->next = NULL; - m->name = name; - m->referencep = info->type_stack->type.referencep; - m->type = ieee_pop_type (info); - m->kind = kind; - m->val = val; - - for (pm = &info->pending_parms; *pm != NULL; pm = &(*pm)->next) - ; - *pm = m; - - /* Add the type to the fnargs list. */ - if (! ieee_change_buffer (info, &info->fnargs) - || ! ieee_write_number (info, m->type)) - return false; - ++info->fnargcount; - - return true; -} - -/* Output pending function parameters. */ - -static boolean -ieee_output_pending_parms (info) - struct ieee_handle *info; -{ - struct ieee_pending_parm *m; - unsigned int refcount; - - refcount = 0; - for (m = info->pending_parms; m != NULL; m = m->next) - { - enum debug_var_kind vkind; - - switch (m->kind) - { - default: - abort (); - return false; - case DEBUG_PARM_STACK: - case DEBUG_PARM_REFERENCE: - vkind = DEBUG_LOCAL; - break; - case DEBUG_PARM_REG: - case DEBUG_PARM_REF_REG: - vkind = DEBUG_REGISTER; - break; - } - - if (! ieee_push_type (info, m->type, 0, false, false)) - return false; - info->type_stack->type.referencep = m->referencep; - if (m->referencep) - ++refcount; - if (! ieee_variable ((PTR) info, m->name, vkind, m->val)) - return false; - } - - /* If there are any reference parameters, we need to output a - miscellaneous record indicating them. */ - if (refcount > 0) - { - unsigned int nindx, varindx; - - /* FIXME: The MRI compiler outputs the demangled function name - here, but we are outputting the mangled name. */ - nindx = info->name_indx; - ++info->name_indx; - if (! ieee_change_buffer (info, &info->vars) - || ! ieee_write_byte (info, (int) ieee_nn_record) - || ! ieee_write_number (info, nindx) - || ! ieee_write_id (info, "") - || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum) - || ! ieee_write_number (info, nindx) - || ! ieee_write_number (info, 0) - || ! ieee_write_number (info, 62) - || ! ieee_write_number (info, 80) - || ! ieee_write_number (info, refcount + 3) - || ! ieee_write_asn (info, nindx, 'B') - || ! ieee_write_atn65 (info, nindx, info->fnname) - || ! ieee_write_asn (info, nindx, 0)) - return false; - for (m = info->pending_parms, varindx = 1; - m != NULL; - m = m->next, varindx++) - { - if (m->referencep) - { - if (! ieee_write_asn (info, nindx, varindx)) - return false; - } - } - } - - m = info->pending_parms; - while (m != NULL) - { - struct ieee_pending_parm *next; - - next = m->next; - free (m); - m = next; - } - - info->pending_parms = NULL; - - return true; -} - -/* Start a block. If this is the first block, we output the address - to finish the BB4 or BB6, and then output the function parameters. */ - -static boolean -ieee_start_block (p, addr) - PTR p; - bfd_vma addr; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - - if (! ieee_change_buffer (info, &info->vars)) - return false; - - if (info->block_depth == 1) - { - if (! ieee_write_number (info, addr) - || ! ieee_output_pending_parms (info)) - return false; - } - else - { - if (! ieee_write_byte (info, (int) ieee_bb_record_enum) - || ! ieee_write_byte (info, 6) - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, "") - || ! ieee_write_number (info, 0) - || ! ieee_write_number (info, 0) - || ! ieee_write_number (info, addr)) - return false; - } - - if (! ieee_start_range (info, addr)) - return false; - - ++info->block_depth; - - return true; -} - -/* End a block. */ - -static boolean -ieee_end_block (p, addr) - PTR p; - bfd_vma addr; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - - /* The address we are given is the end of the block, but IEEE seems - to want to the address of the last byte in the block, so we - subtract one. */ - if (! ieee_change_buffer (info, &info->vars) - || ! ieee_write_byte (info, (int) ieee_be_record_enum) - || ! ieee_write_number (info, addr - 1)) - return false; - - if (! ieee_end_range (info, addr)) - return false; - - --info->block_depth; - - if (addr > info->highaddr) - info->highaddr = addr; - - return true; -} - -/* End a function. */ - -static boolean -ieee_end_function (p) - PTR p; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - - assert (info->block_depth == 1); - - --info->block_depth; - - /* Now we can finish up fntype, and add it to the typdef section. - At this point, fntype is the 'x' type up to the argument count, - and fnargs is the argument types. We must add the argument - count, and we must add the level. FIXME: We don't record varargs - functions correctly. In fact, stabs debugging does not give us - enough information to do so. */ - if (! ieee_change_buffer (info, &info->fntype) - || ! ieee_write_number (info, info->fnargcount) - || ! ieee_change_buffer (info, &info->fnargs) - || ! ieee_write_number (info, 0)) - return false; - - /* Make sure the typdef block has been started. */ - if (ieee_buffer_emptyp (&info->types)) - { - if (! ieee_change_buffer (info, &info->types) - || ! ieee_write_byte (info, (int) ieee_bb_record_enum) - || ! ieee_write_byte (info, 1) - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, info->modname)) - return false; - } - - if (! ieee_append_buffer (info, &info->types, &info->fntype) - || ! ieee_append_buffer (info, &info->types, &info->fnargs)) - return false; - - info->fnname = NULL; - if (! ieee_init_buffer (info, &info->fntype) - || ! ieee_init_buffer (info, &info->fnargs)) - return false; - info->fnargcount = 0; - - return true; -} - -/* Record line number information. */ - -static boolean -ieee_lineno (p, filename, lineno, addr) - PTR p; - const char *filename; - unsigned long lineno; - bfd_vma addr; -{ - struct ieee_handle *info = (struct ieee_handle *) p; - - assert (info->filename != NULL); - - /* The HP simulator seems to get confused when more than one line is - listed for the same address, at least if they are in different - files. We handle this by always listing the last line for a - given address, since that seems to be the one that gdb uses. */ - if (info->pending_lineno_filename != NULL - && addr != info->pending_lineno_addr) - { - /* Make sure we have a line number block. */ - if (! ieee_buffer_emptyp (&info->linenos)) - { - if (! ieee_change_buffer (info, &info->linenos)) - return false; - } - else - { - info->lineno_name_indx = info->name_indx; - ++info->name_indx; - if (! ieee_change_buffer (info, &info->linenos) - || ! ieee_write_byte (info, (int) ieee_bb_record_enum) - || ! ieee_write_byte (info, 5) - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, info->filename) - || ! ieee_write_byte (info, (int) ieee_nn_record) - || ! ieee_write_number (info, info->lineno_name_indx) - || ! ieee_write_id (info, "")) - return false; - info->lineno_filename = info->filename; - } - - if (strcmp (info->pending_lineno_filename, info->lineno_filename) != 0) - { - if (strcmp (info->filename, info->lineno_filename) != 0) - { - /* We were not in the main file. Close the block for the - included file. */ - if (! ieee_write_byte (info, (int) ieee_be_record_enum)) - return false; - if (strcmp (info->filename, info->pending_lineno_filename) == 0) - { - /* We need a new NN record, and we aren't about to - output one. */ - info->lineno_name_indx = info->name_indx; - ++info->name_indx; - if (! ieee_write_byte (info, (int) ieee_nn_record) - || ! ieee_write_number (info, info->lineno_name_indx) - || ! ieee_write_id (info, "")) - return false; - } - } - if (strcmp (info->filename, info->pending_lineno_filename) != 0) - { - /* We are not changing to the main file. Open a block for - the new included file. */ - info->lineno_name_indx = info->name_indx; - ++info->name_indx; - if (! ieee_write_byte (info, (int) ieee_bb_record_enum) - || ! ieee_write_byte (info, 5) - || ! ieee_write_number (info, 0) - || ! ieee_write_id (info, info->pending_lineno_filename) - || ! ieee_write_byte (info, (int) ieee_nn_record) - || ! ieee_write_number (info, info->lineno_name_indx) - || ! ieee_write_id (info, "")) - return false; - } - info->lineno_filename = info->pending_lineno_filename; - } - - if (! ieee_write_2bytes (info, (int) ieee_atn_record_enum) - || ! ieee_write_number (info, info->lineno_name_indx) - || ! ieee_write_number (info, 0) - || ! ieee_write_number (info, 7) - || ! ieee_write_number (info, info->pending_lineno) - || ! ieee_write_number (info, 0) - || ! ieee_write_asn (info, info->lineno_name_indx, - info->pending_lineno_addr)) - return false; - } - - info->pending_lineno_filename = filename; - info->pending_lineno = lineno; - info->pending_lineno_addr = addr; - - return true; -} diff --git a/pstack/ieee.h b/pstack/ieee.h deleted file mode 100644 index 56634b2819a..00000000000 --- a/pstack/ieee.h +++ /dev/null @@ -1,138 +0,0 @@ -/* IEEE Standard 695-1980 "Universal Format for Object Modules" header file - Contributed by Cygnus Support. */ - -#define N_W_VARIABLES 8 -#define Module_Beginning 0xe0 - -typedef struct ieee_module { - char *processor; - char *module_name; -} ieee_module_begin_type; - -#define Address_Descriptor 0xec -typedef struct ieee_address { -bfd_vma number_of_bits_mau; - bfd_vma number_of_maus_in_address; - - unsigned char byte_order; -#define IEEE_LITTLE 0xcc -#define IEEE_BIG 0xcd -} ieee_address_descriptor_type; - -typedef union ieee_w_variable { - file_ptr offset[N_W_VARIABLES]; - struct { - file_ptr extension_record; - file_ptr environmental_record; - file_ptr section_part; - file_ptr external_part; - file_ptr debug_information_part; - file_ptr data_part; - file_ptr trailer_part; - file_ptr me_record; - } r; -} ieee_w_variable_type; - - - - - -typedef enum ieee_record -{ - ieee_number_start_enum = 0x00, - ieee_number_end_enum=0x7f, - ieee_number_repeat_start_enum = 0x80, - ieee_number_repeat_end_enum = 0x88, - ieee_number_repeat_4_enum = 0x84, - ieee_number_repeat_3_enum = 0x83, - ieee_number_repeat_2_enum = 0x82, - ieee_number_repeat_1_enum = 0x81, - ieee_module_beginning_enum = 0xe0, - ieee_module_end_enum = 0xe1, - ieee_extension_length_1_enum = 0xde, - ieee_extension_length_2_enum = 0xdf, - ieee_section_type_enum = 0xe6, - ieee_section_alignment_enum = 0xe7, - ieee_external_symbol_enum = 0xe8, - ieee_comma = 0x90, - ieee_external_reference_enum = 0xe9, - ieee_set_current_section_enum = 0xe5, - ieee_address_descriptor_enum = 0xec, - ieee_load_constant_bytes_enum = 0xed, - ieee_load_with_relocation_enum = 0xe4, - - ieee_variable_A_enum = 0xc1, - ieee_variable_B_enum = 0xc2, - ieee_variable_C_enum = 0xc3, - ieee_variable_D_enum = 0xc4, - ieee_variable_E_enum = 0xc5, - ieee_variable_F_enum = 0xc6, - ieee_variable_G_enum = 0xc7, - ieee_variable_H_enum = 0xc8, - ieee_variable_I_enum = 0xc9, - ieee_variable_J_enum = 0xca, - ieee_variable_K_enum = 0xcb, - ieee_variable_L_enum = 0xcc, - ieee_variable_M_enum = 0xcd, - ieee_variable_N_enum = 0xce, - ieee_variable_O_enum = 0xcf, - ieee_variable_P_enum = 0xd0, - ieee_variable_Q_enum = 0xd1, - ieee_variable_R_enum = 0xd2, - ieee_variable_S_enum = 0xd3, - ieee_variable_T_enum = 0xd4, - ieee_variable_U_enum = 0xd5, - ieee_variable_V_enum = 0xd6, - ieee_variable_W_enum = 0xd7, - ieee_variable_X_enum = 0xd8, - ieee_variable_Y_enum = 0xd9, - ieee_variable_Z_enum = 0xda, - ieee_function_plus_enum = 0xa5, - ieee_function_minus_enum = 0xa6, - ieee_function_signed_open_b_enum = 0xba, - ieee_function_signed_close_b_enum = 0xbb, - - ieee_function_unsigned_open_b_enum = 0xbc, - ieee_function_unsigned_close_b_enum = 0xbd, - - ieee_function_either_open_b_enum = 0xbe, - ieee_function_either_close_b_enum = 0xbf, - ieee_record_seperator_enum = 0xdb, - - ieee_e2_first_byte_enum = 0xe2, - ieee_section_size_enum = 0xe2d3, - ieee_physical_region_size_enum = 0xe2c1, - ieee_region_base_address_enum = 0xe2c2, - ieee_mau_size_enum = 0xe2c6, - ieee_m_value_enum = 0xe2cd, - ieee_section_base_address_enum = 0xe2cc, - ieee_asn_record_enum = 0xe2ce, - ieee_section_offset_enum = 0xe2d2, - ieee_value_starting_address_enum = 0xe2c7, - ieee_assign_value_to_variable_enum = 0xe2d7, - ieee_set_current_pc_enum = 0xe2d0, - ieee_value_record_enum = 0xe2c9, - ieee_nn_record = 0xf0, - ieee_at_record_enum = 0xf1, - ieee_ty_record_enum = 0xf2, - ieee_attribute_record_enum = 0xf1c9, - ieee_atn_record_enum = 0xf1ce, - ieee_external_reference_info_record_enum = 0xf1d8, - ieee_weak_external_reference_enum= 0xf4, - ieee_repeat_data_enum = 0xf7, - ieee_bb_record_enum = 0xf8, - ieee_be_record_enum = 0xf9 -} ieee_record_enum_type; - - -typedef struct ieee_section { - unsigned int section_index; - unsigned int section_type; - char *section_name; - unsigned int parent_section_index; - unsigned int sibling_section_index; - unsigned int context_index; -} ieee_section_type; -#define IEEE_REFERENCE_BASE 11 -#define IEEE_PUBLIC_BASE 32 -#define IEEE_SECTION_NUMBER_BASE 1 diff --git a/pstack/libiberty.h b/pstack/libiberty.h deleted file mode 100644 index ca0043d31c6..00000000000 --- a/pstack/libiberty.h +++ /dev/null @@ -1,180 +0,0 @@ -/* Function declarations for libiberty. - Written by Cygnus Support, 1994. - - The libiberty library provides a number of functions which are - missing on some operating systems. We do not declare those here, - to avoid conflicts with the system header files on operating - systems that do support those functions. In this file we only - declare those functions which are specific to libiberty. */ - -#ifndef LIBIBERTY_H -#define LIBIBERTY_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "ansidecl.h" - -/* Build an argument vector from a string. Allocates memory using - malloc. Use freeargv to free the vector. */ - -extern char **buildargv PARAMS ((char *)); - -/* Free a vector returned by buildargv. */ - -extern void freeargv PARAMS ((char **)); - -/* Duplicate an argument vector. Allocates memory using malloc. Use - freeargv to free the vector. */ - -extern char **dupargv PARAMS ((char **)); - - -/* Return the last component of a path name. Note that we can't use a - prototype here because the parameter is declared inconsistently - across different systems, sometimes as "char *" and sometimes as - "const char *" */ - -#if defined (__GNU_LIBRARY__ ) || defined (__linux__) || defined (__FreeBSD__) -extern char *basename PARAMS ((const char *)); -#else -extern char *basename (); -#endif - -/* Concatenate an arbitrary number of strings, up to (char *) NULL. - Allocates memory using xmalloc. */ - -extern char *concat PARAMS ((const char *, ...)); - -/* Check whether two file descriptors refer to the same file. */ - -extern int fdmatch PARAMS ((int fd1, int fd2)); - -/* Get the amount of time the process has run, in microseconds. */ - -extern long get_run_time PARAMS ((void)); - -/* Choose a temporary directory to use for scratch files. */ - -extern char *choose_temp_base PARAMS ((void)); - -/* Allocate memory filled with spaces. Allocates using malloc. */ - -extern const char *spaces PARAMS ((int count)); - -/* Return the maximum error number for which strerror will return a - string. */ - -extern int errno_max PARAMS ((void)); - -/* Return the name of an errno value (e.g., strerrno (EINVAL) returns - "EINVAL"). */ - -extern const char *strerrno PARAMS ((int)); - -/* Given the name of an errno value, return the value. */ - -extern int strtoerrno PARAMS ((const char *)); - -/* ANSI's strerror(), but more robust. */ - -extern char *xstrerror PARAMS ((int)); - -/* Return the maximum signal number for which strsignal will return a - string. */ - -extern int signo_max PARAMS ((void)); - -/* Return a signal message string for a signal number - (e.g., strsignal (SIGHUP) returns something like "Hangup"). */ -/* This is commented out as it can conflict with one in system headers. - We still document its existence though. */ - -/*extern const char *strsignal PARAMS ((int));*/ - -/* Return the name of a signal number (e.g., strsigno (SIGHUP) returns - "SIGHUP"). */ - -extern const char *strsigno PARAMS ((int)); - -/* Given the name of a signal, return its number. */ - -extern int strtosigno PARAMS ((const char *)); - -/* Register a function to be run by xexit. Returns 0 on success. */ - -extern int xatexit PARAMS ((void (*fn) (void))); - -/* Exit, calling all the functions registered with xatexit. */ - -#ifndef __GNUC__ -extern void xexit PARAMS ((int status)); -#else -void xexit PARAMS ((int status)) __attribute__ ((noreturn)); -#endif - -/* Set the program name used by xmalloc. */ - -extern void xmalloc_set_program_name PARAMS ((const char *)); - -/* Allocate memory without fail. If malloc fails, this will print a - message to stderr (using the name set by xmalloc_set_program_name, - if any) and then call xexit. */ - -#ifdef ANSI_PROTOTYPES -/* Get a definition for size_t. */ -#include <stddef.h> -#endif -extern PTR xmalloc PARAMS ((size_t)); - -/* Reallocate memory without fail. This works like xmalloc. - - FIXME: We do not declare the parameter types for the same reason as - xmalloc. */ - -extern PTR xrealloc PARAMS ((PTR, size_t)); - -/* Allocate memory without fail and set it to zero. This works like - xmalloc. */ - -extern PTR xcalloc PARAMS ((size_t, size_t)); - -/* Copy a string into a memory buffer without fail. */ - -extern char *xstrdup PARAMS ((const char *)); - -/* hex character manipulation routines */ - -#define _hex_array_size 256 -#define _hex_bad 99 -extern char _hex_value[_hex_array_size]; -extern void hex_init PARAMS ((void)); -#define hex_p(c) (hex_value (c) != _hex_bad) -/* If you change this, note well: Some code relies on side effects in - the argument being performed exactly once. */ -#define hex_value(c) (_hex_value[(unsigned char) (c)]) - -/* Definitions used by the pexecute routine. */ - -#define PEXECUTE_FIRST 1 -#define PEXECUTE_LAST 2 -#define PEXECUTE_ONE (PEXECUTE_FIRST + PEXECUTE_LAST) -#define PEXECUTE_SEARCH 4 -#define PEXECUTE_VERBOSE 8 - -/* Execute a program. */ - -extern int pexecute PARAMS ((const char *, char * const *, const char *, - const char *, char **, char **, int)); - -/* Wait for pexecute to finish. */ - -extern int pwait PARAMS ((int, int *, int)); - -#ifdef __cplusplus -} -#endif - - -#endif /* ! defined (LIBIBERTY_H) */ diff --git a/pstack/linuxthreads.c b/pstack/linuxthreads.c deleted file mode 100644 index 8624bd21782..00000000000 --- a/pstack/linuxthreads.c +++ /dev/null @@ -1,90 +0,0 @@ -/* $Header$ */ - -/* - * LinuxThreads specific stuff. - */ - -#include <sys/types.h> - -#include <assert.h> -#include <limits.h> /* PTHREAD_THREADS_MAX */ -#include <pthread.h> -#include <stdio.h> -#include <unistd.h> -#include <signal.h> -#include <sched.h> - -#include "linuxthreads.h" - -#define AT_INT(intval) *((int32_t*)(intval)) - -/* - * Internal LinuxThreads variables. - * Official interface exposed to GDB. - */ -#if 1 -extern volatile int __pthread_threads_debug; -extern volatile char __pthread_handles; -extern char __pthread_initial_thread; -/*extern volatile Elf32_Sym* __pthread_manager_thread;*/ -extern const int __pthread_sizeof_handle; -extern const int __pthread_offsetof_descr; -extern const int __pthread_offsetof_pid; -extern volatile int __pthread_handles_num; -#endif /* 0 */ - -/* - * Notify others. - */ -int -linuxthreads_notify_others( const int signotify) -{ - const pid_t mypid = getpid(); - //const pthread_t mytid = pthread_self(); - int i; - int threadcount = 0; - int threads[PTHREAD_THREADS_MAX]; - int pid; - - TRACE_FPRINTF((stderr, "theadcount:%d\n", __pthread_handles_num)); - if (__pthread_handles_num==2) { - /* no threads beside the initial thread */ - return 0; - } - /*assert(maxthreads>=3); - assert(maxthreads>=__pthread_handles_num+2);*/ - - // take the initial thread with us - pid = AT_INT(&__pthread_initial_thread + __pthread_offsetof_pid); - if (pid!=mypid && pid!=0) - threads[threadcount++] = pid; - // don't know why, but always handles[0]==handles[1] - for (i=1; i<__pthread_handles_num; ++i) { - const int descr = AT_INT(&__pthread_handles+i*__pthread_sizeof_handle+__pthread_offsetof_descr); - assert(descr!=0); - pid = AT_INT(descr+__pthread_offsetof_pid); - if (pid!=mypid && pid!=0) - threads[threadcount++] = pid; - } - /* TRACE_FPRINTF((stderr, "Stopping threads...")); */ - //for (i=0; i<threadcount; ++i) { - // /* TRACE_FPRINTF((stderr, "%d ", threads[i])); */ - // fflush(stdout); - // kill(threads[i], SIGSTOP); /* Tell thread to stop */ - //} - /* TRACE_FPRINTF((stderr, " done!\n")); */ - for (i=0; i<threadcount; ++i) { - TRACE_FPRINTF((stderr, "--- NOTIFYING %d\n", threads[i])); - kill(threads[i], signotify); /* Tell to print stack trace */ - /* TRACE_FPRINTF((stderr, "--- WAITING FOR %d\n", threads[i])); */ - /*pause(); Wait for confirmation. */ - } - for (i=0; i<threadcount; ++i) - sched_yield(); - for (i=0; i<threadcount; ++i) { - TRACE_FPRINTF((stderr, "--- KILLING %d\n", threads[i])); - kill(threads[i], SIGKILL); /* Tell thread die :) */ - } - return __pthread_handles_num; -} - diff --git a/pstack/linuxthreads.h b/pstack/linuxthreads.h deleted file mode 100644 index f5eb0f652d8..00000000000 --- a/pstack/linuxthreads.h +++ /dev/null @@ -1,28 +0,0 @@ -/* $Header$ */ - -/* - * LinuxThreads specific stuff. - */ - -#ifndef pstack_linuxthreads_h_ -#define pstack_linuxthreads_h_ - -#include <pthread.h> -#include "pstacktrace.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Tell other threads to dump stacks... - */ -int -linuxthreads_notify_others( const int signotify); - -#ifdef __cplusplus -} -#endif - -#endif /* pstack_linuxthreads_h_ */ - diff --git a/pstack/pstack.c b/pstack/pstack.c deleted file mode 100644 index 4cdd80d68b5..00000000000 --- a/pstack/pstack.c +++ /dev/null @@ -1,2746 +0,0 @@ -/* - pstack.c -- asynchronous stack trace of a running process - Copyright (c) 1999 Ross Thompson - Author: Ross Thompson <ross@whatsis.com> - Critical bug fix: Tim Waugh -*/ - -/* - This file 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. -*/ - -/* RESTRICTIONS: - - pstack currently works only on Linux, only on an x86 machine running - 32 bit ELF binaries (64 bit not supported). Also, for symbolic - information, you need to use a GNU compiler to generate your - program, and you can't strip symbols from the binaries. For thread - information to be dumped, you have to use the debug-aware version - of libpthread.so. (To check, run 'nm' on your libpthread.so, and - make sure that the symbol "__pthread_threads_debug" is defined.) - - The details of pulling stuff out of ELF files and running through - program images is very platform specific, and I don't want to - try to support modes or machine types I can't test in or on. - If someone wants to generalize this to other architectures, I would - be happy to help and coordinate the activity. Please send me whatever - changes you make to support these machines, so that I can own the - central font of all truth (at least as regards this program). - - Thanks -*/ - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <sys/ptrace.h> -#include <asm/ptrace.h> - -#include <assert.h> -#include <fcntl.h> -#include <link.h> -#include <malloc.h> -#include <string.h> -#include <stdarg.h> -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <signal.h> -#include <pthread.h> -#include <limits.h> /* PTHREAD_THREADS_MAX */ - - -#include <bfd.h> - -#include "libiberty.h" - -#include "pstack.h" /* just one function */ -#include "budbg.h" /* binutils stuff related to debugging symbols. */ -#include "bucomm.h" /* some common stuff */ -#include "debug.h" /* and more binutils stuff... */ -#include "budbg.h" -#include "linuxthreads.h" /* LinuxThreads specific stuff... */ - - -/* - * fprintf for file descriptors :) NOTE: we have to use fixed-size buffer :)( - * due to malloc's unavalaibility. - */ -int -fdprintf( int fd, - const char* fmt,...) -{ - char xbuf[2048];// FIXME: enough? - va_list ap; - int r; - if (fd<0) - return -1; - va_start(ap, fmt); - r = vsnprintf(xbuf, sizeof(xbuf), fmt, ap); - va_end(ap); - return write(fd, xbuf, r); -} - -int -fdputc( char c, - int fd) -{ - if (fd<0) - return -1; - return write(fd, &c, sizeof(c)); -} - -int -fdputs( const char* s, - int fd) -{ - if (fd<0) - return -1; - return write(fd, s, strlen(s)); -} - -/* - * Use this function to open log file. - * Flags: truncate on opening. - */ -static const char* path_format = "stack-trace-on-segv-%d.txt"; -static int -open_log_file( const pthread_t tid, - const pid_t pid) -{ - char fname[PATH_MAX]; - int r; - snprintf(fname, sizeof(fname), path_format, tid, pid); - r = open(fname, O_WRONLY|O_CREAT|O_TRUNC, - S_IRUSR|S_IWUSR); - if (r<0) - perror("open"); - return r; -} -/* - * Add additional debugging information for functions. - */ - -/* - * Lineno - */ -typedef struct { - int lineno; - bfd_vma addr; -} debug_lineno_t; - -/* - * Block - a {} pair. - */ -typedef struct debug_block_st { - bfd_vma begin_addr; /* where did it start */ - bfd_vma end_addr; /* where did it end */ - struct debug_block_st* parent; - struct debug_block_st* childs; - int childs_count; -} debug_block_t; - -/* - * Function parameter. - */ -typedef struct { - bfd_vma offset; /* Offset in the stack */ - const char* name; /* And name. */ -} debug_parameter_t; - -/* - * Extra information about functions. - */ -typedef struct { - asymbol* symbol; /* mangled function name, addr */ - debug_lineno_t* lines; - int lines_count; - int max_lines_count; - const char* name; - const char* filename;/* a file name it occured in... */ - debug_block_t* block; /* each function has a block, or not, you know */ - debug_parameter_t* argv; /* argument types. */ - int argc; - int max_argc; -} debug_function_t; - -/* This is the structure we use as a handle for these routines. */ -struct pr_handle -{ - /* File to print information to. */ - FILE *f; - /* Current indentation level. */ - unsigned int indent; - /* Type stack. */ - struct pr_stack *stack; - /* Parameter number we are about to output. */ - int parameter; - debug_block_t* block; /* current block */ - debug_function_t* function; /* current function */ - debug_function_t* functions; /* all functions */ - int functions_size; /* current size */ - int functions_maxsize; /* maximum size */ -}; - -/* The type stack. */ - -struct pr_stack -{ - /* Next element on the stack. */ - struct pr_stack *next; - /* This element. */ - char *type; - /* Current visibility of fields if this is a class. */ - enum debug_visibility visibility; - /* Name of the current method we are handling. */ - const char *method; -}; - -static void indent PARAMS ((struct pr_handle *)); -static boolean push_type PARAMS ((struct pr_handle *, const char *)); -static boolean prepend_type PARAMS ((struct pr_handle *, const char *)); -static boolean append_type PARAMS ((struct pr_handle *, const char *)); -static boolean substitute_type PARAMS ((struct pr_handle *, const char *)); -static boolean indent_type PARAMS ((struct pr_handle *)); -static char *pop_type PARAMS ((struct pr_handle *)); -static void print_vma PARAMS ((bfd_vma, char *, boolean, boolean)); -static boolean pr_fix_visibility - PARAMS ((struct pr_handle *, enum debug_visibility)); - -static boolean pr_start_compilation_unit PARAMS ((PTR, const char *)); -static boolean pr_start_source PARAMS ((PTR, const char *)); -static boolean pr_empty_type PARAMS ((PTR)); -static boolean pr_void_type PARAMS ((PTR)); -static boolean pr_int_type PARAMS ((PTR, unsigned int, boolean)); -static boolean pr_float_type PARAMS ((PTR, unsigned int)); -static boolean pr_complex_type PARAMS ((PTR, unsigned int)); -static boolean pr_bool_type PARAMS ((PTR, unsigned int)); -static boolean pr_enum_type - PARAMS ((PTR, const char *, const char **, bfd_signed_vma *)); -static boolean pr_pointer_type PARAMS ((PTR)); -static boolean pr_function_type PARAMS ((PTR, int, boolean)); -static boolean pr_reference_type PARAMS ((PTR)); -static boolean pr_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma)); -static boolean pr_array_type - PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, boolean)); -static boolean pr_set_type PARAMS ((PTR, boolean)); -static boolean pr_offset_type PARAMS ((PTR)); -static boolean pr_method_type PARAMS ((PTR, boolean, int, boolean)); -static boolean pr_const_type PARAMS ((PTR)); -static boolean pr_volatile_type PARAMS ((PTR)); -static boolean pr_start_struct_type - PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int)); -static boolean pr_struct_field - PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility)); -static boolean pr_end_struct_type PARAMS ((PTR)); -static boolean pr_start_class_type - PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int, boolean, - boolean)); -static boolean pr_class_static_member - PARAMS ((PTR, const char *, const char *, enum debug_visibility)); -static boolean pr_class_baseclass - PARAMS ((PTR, bfd_vma, boolean, enum debug_visibility)); -static boolean pr_class_start_method PARAMS ((PTR, const char *)); -static boolean pr_class_method_variant - PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean, - bfd_vma, boolean)); -static boolean pr_class_static_method_variant - PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean)); -static boolean pr_class_end_method PARAMS ((PTR)); -static boolean pr_end_class_type PARAMS ((PTR)); -static boolean pr_typedef_type PARAMS ((PTR, const char *)); -static boolean pr_tag_type - PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind)); -static boolean pr_typdef PARAMS ((PTR, const char *)); -static boolean pr_tag PARAMS ((PTR, const char *)); -static boolean pr_int_constant PARAMS ((PTR, const char *, bfd_vma)); -static boolean pr_float_constant PARAMS ((PTR, const char *, double)); -static boolean pr_typed_constant PARAMS ((PTR, const char *, bfd_vma)); -static boolean pr_variable - PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma)); -static boolean pr_start_function PARAMS ((PTR, const char *, boolean)); -static boolean pr_function_parameter - PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma)); -static boolean pr_start_block PARAMS ((PTR, bfd_vma)); -static boolean pr_end_block PARAMS ((PTR, bfd_vma)); -static boolean pr_end_function PARAMS ((PTR)); -static boolean pr_lineno PARAMS ((PTR, const char *, unsigned long, bfd_vma)); - -static const struct debug_write_fns pr_fns = -{ - pr_start_compilation_unit, - pr_start_source, - pr_empty_type, - pr_void_type, - pr_int_type, - pr_float_type, - pr_complex_type, - pr_bool_type, - pr_enum_type, - pr_pointer_type, - pr_function_type, - pr_reference_type, - pr_range_type, - pr_array_type, - pr_set_type, - pr_offset_type, - pr_method_type, - pr_const_type, - pr_volatile_type, - pr_start_struct_type, - pr_struct_field, - pr_end_struct_type, - pr_start_class_type, - pr_class_static_member, - pr_class_baseclass, - pr_class_start_method, - pr_class_method_variant, - pr_class_static_method_variant, - pr_class_end_method, - pr_end_class_type, - pr_typedef_type, - pr_tag_type, - pr_typdef, - pr_tag, - pr_int_constant, - pr_float_constant, - pr_typed_constant, - pr_variable, - pr_start_function, - pr_function_parameter, - pr_start_block, - pr_end_block, - pr_end_function, - pr_lineno -}; - - -/* Indent to the current indentation level. */ - -static void -indent (info) - struct pr_handle *info; -{ - unsigned int i; - - for (i = 0; i < info->indent; i++) - TRACE_PUTC ((' ', info->f)); -} - -/* Push a type on the type stack. */ - -static boolean -push_type (info, type) - struct pr_handle *info; - const char *type; -{ - struct pr_stack *n; - - if (type == NULL) - return false; - - n = (struct pr_stack *) xmalloc (sizeof *n); - memset (n, 0, sizeof *n); - - n->type = xstrdup (type); - n->visibility = DEBUG_VISIBILITY_IGNORE; - n->method = NULL; - n->next = info->stack; - info->stack = n; - - return true; -} - -/* Prepend a string onto the type on the top of the type stack. */ - -static boolean -prepend_type (info, s) - struct pr_handle *info; - const char *s; -{ - char *n; - - assert (info->stack != NULL); - - n = (char *) xmalloc (strlen (s) + strlen (info->stack->type) + 1); - sprintf (n, "%s%s", s, info->stack->type); - free (info->stack->type); - info->stack->type = n; - - return true; -} - -/* Append a string to the type on the top of the type stack. */ - -static boolean -append_type (info, s) - struct pr_handle *info; - const char *s; -{ - unsigned int len; - - if (s == NULL) - return false; - - assert (info->stack != NULL); - - len = strlen (info->stack->type); - info->stack->type = (char *) xrealloc (info->stack->type, - len + strlen (s) + 1); - strcpy (info->stack->type + len, s); - - return true; -} - -/* We use an underscore to indicate where the name should go in a type - string. This function substitutes a string for the underscore. If - there is no underscore, the name follows the type. */ - -static boolean -substitute_type (info, s) - struct pr_handle *info; - const char *s; -{ - char *u; - - assert (info->stack != NULL); - - u = strchr (info->stack->type, '|'); - if (u != NULL) - { - char *n; - - n = (char *) xmalloc (strlen (info->stack->type) + strlen (s)); - - memcpy (n, info->stack->type, u - info->stack->type); - strcpy (n + (u - info->stack->type), s); - strcat (n, u + 1); - - free (info->stack->type); - info->stack->type = n; - - return true; - } - - if (strchr (s, '|') != NULL - && (strchr (info->stack->type, '{') != NULL - || strchr (info->stack->type, '(') != NULL)) - { - if (! prepend_type (info, "(") - || ! append_type (info, ")")) - return false; - } - - if (*s == '\0') - return true; - - return (append_type (info, " ") - && append_type (info, s)); -} - -/* Indent the type at the top of the stack by appending spaces. */ - -static boolean -indent_type (info) - struct pr_handle *info; -{ - unsigned int i; - - for (i = 0; i < info->indent; i++) - { - if (! append_type (info, " ")) - return false; - } - - return true; -} - -/* Pop a type from the type stack. */ - -static char * -pop_type (info) - struct pr_handle *info; -{ - struct pr_stack *o; - char *ret; - - assert (info->stack != NULL); - - o = info->stack; - info->stack = o->next; - ret = o->type; - free (o); - - return ret; -} - -/* Print a VMA value into a string. */ - -static void -print_vma (vma, buf, unsignedp, hexp) - bfd_vma vma; - char *buf; - boolean unsignedp; - boolean hexp; -{ - if (sizeof (vma) <= sizeof (unsigned long)) - { - if (hexp) - sprintf (buf, "0x%lx", (unsigned long) vma); - else if (unsignedp) - sprintf (buf, "%lu", (unsigned long) vma); - else - sprintf (buf, "%ld", (long) vma); - } - else - { - buf[0] = '0'; - buf[1] = 'x'; - sprintf_vma (buf + 2, vma); - } -} - -/* Start a new compilation unit. */ - -static boolean -pr_start_compilation_unit (p, filename) - PTR p; - const char *filename; -{ - struct pr_handle *info = (struct pr_handle *) p; - - assert (info->indent == 0); -/* - TRACE_FPRINTF( (info->f, "%s:\n", filename)); -*/ - return true; -} - -/* Start a source file within a compilation unit. */ - -static boolean -pr_start_source (p, filename) - PTR p; - const char *filename; -{ - struct pr_handle *info = (struct pr_handle *) p; - - assert (info->indent == 0); -/* - TRACE_FPRINTF( (info->f, " %s:\n", filename)); -*/ - return true; -} - -/* Push an empty type onto the type stack. */ - -static boolean -pr_empty_type (p) - PTR p; -{ - struct pr_handle *info = (struct pr_handle *) p; - - return push_type (info, "<undefined>"); -} - -/* Push a void type onto the type stack. */ - -static boolean -pr_void_type (p) - PTR p; -{ - struct pr_handle *info = (struct pr_handle *) p; - - return push_type (info, "void"); -} - -/* Push an integer type onto the type stack. */ - -static boolean -pr_int_type (p, size, unsignedp) - PTR p; - unsigned int size; - boolean unsignedp; -{ - struct pr_handle *info = (struct pr_handle *) p; - char ab[10]; - - sprintf (ab, "%sint%d", unsignedp ? "u" : "", size * 8); - return push_type (info, ab); -} - -/* Push a floating type onto the type stack. */ - -static boolean -pr_float_type (p, size) - PTR p; - unsigned int size; -{ - struct pr_handle *info = (struct pr_handle *) p; - char ab[10]; - - if (size == 4) - return push_type (info, "float"); - else if (size == 8) - return push_type (info, "double"); - - sprintf (ab, "float%d", size * 8); - return push_type (info, ab); -} - -/* Push a complex type onto the type stack. */ - -static boolean -pr_complex_type (p, size) - PTR p; - unsigned int size; -{ - struct pr_handle *info = (struct pr_handle *) p; - - if (! pr_float_type (p, size)) - return false; - - return prepend_type (info, "complex "); -} - -/* Push a boolean type onto the type stack. */ - -static boolean -pr_bool_type (p, size) - PTR p; - unsigned int size; -{ - struct pr_handle *info = (struct pr_handle *) p; - char ab[10]; - - sprintf (ab, "bool%d", size * 8); - - return push_type (info, ab); -} - -/* Push an enum type onto the type stack. */ - -static boolean -pr_enum_type (p, tag, names, values) - PTR p; - const char *tag; - const char **names; - bfd_signed_vma *values; -{ - struct pr_handle *info = (struct pr_handle *) p; - unsigned int i; - bfd_signed_vma val; - - if (! push_type (info, "enum ")) - return false; - if (tag != NULL) - { - if (! append_type (info, tag) - || ! append_type (info, " ")) - return false; - } - if (! append_type (info, "{ ")) - return false; - - if (names == NULL) - { - if (! append_type (info, "/* undefined */")) - return false; - } - else - { - val = 0; - for (i = 0; names[i] != NULL; i++) - { - if (i > 0) - { - if (! append_type (info, ", ")) - return false; - } - - if (! append_type (info, names[i])) - return false; - - if (values[i] != val) - { - char ab[20]; - - print_vma (values[i], ab, false, false); - if (! append_type (info, " = ") - || ! append_type (info, ab)) - return false; - val = values[i]; - } - - ++val; - } - } - - return append_type (info, " }"); -} - -/* Turn the top type on the stack into a pointer. */ - -static boolean -pr_pointer_type (p) - PTR p; -{ - struct pr_handle *info = (struct pr_handle *) p; - char *s; - - assert (info->stack != NULL); - - s = strchr (info->stack->type, '|'); - if (s != NULL && s[1] == '[') - return substitute_type (info, "(*|)"); - return substitute_type (info, "*|"); -} - -/* Turn the top type on the stack into a function returning that type. */ - -static boolean -pr_function_type (p, argcount, varargs) - PTR p; - int argcount; - boolean varargs; -{ - struct pr_handle *info = (struct pr_handle *) p; - char **arg_types; - unsigned int len; - char *s; - - assert (info->stack != NULL); - - len = 10; - - if (argcount <= 0) - { - arg_types = NULL; - len += 15; - } - else - { - int i; - - arg_types = (char **) xmalloc (argcount * sizeof *arg_types); - for (i = argcount - 1; i >= 0; i--) - { - if (! substitute_type (info, "")) - return false; - arg_types[i] = pop_type (info); - if (arg_types[i] == NULL) - return false; - len += strlen (arg_types[i]) + 2; - } - if (varargs) - len += 5; - } - - /* Now the return type is on the top of the stack. */ - - s = (char *) xmalloc (len); - strcpy (s, "(|) ("); - - if (argcount < 0) - { -#if 0 - /* Turn off unknown arguments. */ - strcat (s, "/* unknown */"); -#endif - } - else - { - int i; - - for (i = 0; i < argcount; i++) - { - if (i > 0) - strcat (s, ", "); - strcat (s, arg_types[i]); - } - if (varargs) - { - if (i > 0) - strcat (s, ", "); - strcat (s, "..."); - } - if (argcount > 0) - free (arg_types); - } - - strcat (s, ")"); - - if (! substitute_type (info, s)) - return false; - - free (s); - - return true; -} - -/* Turn the top type on the stack into a reference to that type. */ - -static boolean -pr_reference_type (p) - PTR p; -{ - struct pr_handle *info = (struct pr_handle *) p; - - assert (info->stack != NULL); - - return substitute_type (info, "&|"); -} - -/* Make a range type. */ - -static boolean -pr_range_type (p, lower, upper) - PTR p; - bfd_signed_vma lower; - bfd_signed_vma upper; -{ - struct pr_handle *info = (struct pr_handle *) p; - char abl[20], abu[20]; - - assert (info->stack != NULL); - - if (! substitute_type (info, "")) - return false; - - print_vma (lower, abl, false, false); - print_vma (upper, abu, false, false); - - return (prepend_type (info, "range (") - && append_type (info, "):") - && append_type (info, abl) - && append_type (info, ":") - && append_type (info, abu)); -} - -/* Make an array type. */ - -/*ARGSUSED*/ -static boolean -pr_array_type (p, lower, upper, stringp) - PTR p; - bfd_signed_vma lower; - bfd_signed_vma upper; - boolean stringp; -{ - struct pr_handle *info = (struct pr_handle *) p; - char *range_type; - char abl[20], abu[20], ab[50]; - - range_type = pop_type (info); - if (range_type == NULL) - return false; - - if (lower == 0) - { - if (upper == -1) - sprintf (ab, "|[]"); - else - { - print_vma (upper + 1, abu, false, false); - sprintf (ab, "|[%s]", abu); - } - } - else - { - print_vma (lower, abl, false, false); - print_vma (upper, abu, false, false); - sprintf (ab, "|[%s:%s]", abl, abu); - } - - if (! substitute_type (info, ab)) - return false; - - if (strcmp (range_type, "int") != 0) - { - if (! append_type (info, ":") - || ! append_type (info, range_type)) - return false; - } - - if (stringp) - { - if (! append_type (info, " /* string */")) - return false; - } - - return true; -} - -/* Make a set type. */ - -/*ARGSUSED*/ -static boolean -pr_set_type (p, bitstringp) - PTR p; - boolean bitstringp; -{ - struct pr_handle *info = (struct pr_handle *) p; - - if (! substitute_type (info, "")) - return false; - - if (! prepend_type (info, "set { ") - || ! append_type (info, " }")) - return false; - - if (bitstringp) - { - if (! append_type (info, "/* bitstring */")) - return false; - } - - return true; -} - -/* Make an offset type. */ - -static boolean -pr_offset_type (p) - PTR p; -{ - struct pr_handle *info = (struct pr_handle *) p; - char *t; - - if (! substitute_type (info, "")) - return false; - - t = pop_type (info); - if (t == NULL) - return false; - - return (substitute_type (info, "") - && prepend_type (info, " ") - && prepend_type (info, t) - && append_type (info, "::|")); -} - -/* Make a method type. */ - -static boolean -pr_method_type (p, domain, argcount, varargs) - PTR p; - boolean domain; - int argcount; - boolean varargs; -{ - struct pr_handle *info = (struct pr_handle *) p; - unsigned int len; - char *domain_type; - char **arg_types; - char *s; - - len = 10; - - if (! domain) - domain_type = NULL; - else - { - if (! substitute_type (info, "")) - return false; - domain_type = pop_type (info); - if (domain_type == NULL) - return false; - if (strncmp (domain_type, "class ", sizeof "class " - 1) == 0 - && strchr (domain_type + sizeof "class " - 1, ' ') == NULL) - domain_type += sizeof "class " - 1; - else if (strncmp (domain_type, "union class ", - sizeof "union class ") == 0 - && (strchr (domain_type + sizeof "union class " - 1, ' ') - == NULL)) - domain_type += sizeof "union class " - 1; - len += strlen (domain_type); - } - - if (argcount <= 0) - { - arg_types = NULL; - len += 15; - } - else - { - int i; - - arg_types = (char **) xmalloc (argcount * sizeof *arg_types); - for (i = argcount - 1; i >= 0; i--) - { - if (! substitute_type (info, "")) - return false; - arg_types[i] = pop_type (info); - if (arg_types[i] == NULL) - return false; - len += strlen (arg_types[i]) + 2; - } - if (varargs) - len += 5; - } - - /* Now the return type is on the top of the stack. */ - - s = (char *) xmalloc (len); - if (! domain) - *s = '\0'; - else - strcpy (s, domain_type); - strcat (s, "::| ("); - - if (argcount < 0) - strcat (s, "/* unknown */"); - else - { - int i; - - for (i = 0; i < argcount; i++) - { - if (i > 0) - strcat (s, ", "); - strcat (s, arg_types[i]); - } - if (varargs) - { - if (i > 0) - strcat (s, ", "); - strcat (s, "..."); - } - if (argcount > 0) - free (arg_types); - } - - strcat (s, ")"); - - if (! substitute_type (info, s)) - return false; - - free (s); - - return true; -} - -/* Make a const qualified type. */ - -static boolean -pr_const_type (p) - PTR p; -{ - struct pr_handle *info = (struct pr_handle *) p; - - return substitute_type (info, "const |"); -} - -/* Make a volatile qualified type. */ - -static boolean -pr_volatile_type (p) - PTR p; -{ - struct pr_handle *info = (struct pr_handle *) p; - - return substitute_type (info, "volatile |"); -} - -/* Start accumulating a struct type. */ - -static boolean -pr_start_struct_type (p, tag, id, structp, size) - PTR p; - const char *tag; - unsigned int id; - boolean structp; - unsigned int size; -{ - struct pr_handle *info = (struct pr_handle *) p; - - info->indent += 2; - - if (! push_type (info, structp ? "struct " : "union ")) - return false; - if (tag != NULL) - { - if (! append_type (info, tag)) - return false; - } - else - { - char idbuf[20]; - - sprintf (idbuf, "%%anon%u", id); - if (! append_type (info, idbuf)) - return false; - } - - if (! append_type (info, " {")) - return false; - if (size != 0 || tag != NULL) - { - char ab[30]; - - if (! append_type (info, " /*")) - return false; - - if (size != 0) - { - sprintf (ab, " size %u", size); - if (! append_type (info, ab)) - return false; - } - if (tag != NULL) - { - sprintf (ab, " id %u", id); - if (! append_type (info, ab)) - return false; - } - if (! append_type (info, " */")) - return false; - } - if (! append_type (info, "\n")) - return false; - - info->stack->visibility = DEBUG_VISIBILITY_PUBLIC; - - return indent_type (info); -} - -/* Output the visibility of a field in a struct. */ - -static boolean -pr_fix_visibility (info, visibility) - struct pr_handle *info; - enum debug_visibility visibility; -{ - const char *s; - char *t; - unsigned int len; - - assert (info->stack != NULL); - - if (info->stack->visibility == visibility) - return true; - - assert (info->stack->visibility != DEBUG_VISIBILITY_IGNORE); - - switch (visibility) - { - case DEBUG_VISIBILITY_PUBLIC: - s = "public"; - break; - case DEBUG_VISIBILITY_PRIVATE: - s = "private"; - break; - case DEBUG_VISIBILITY_PROTECTED: - s = "protected"; - break; - case DEBUG_VISIBILITY_IGNORE: - s = "/* ignore */"; - break; - default: - abort (); - return false; - } - - /* Trim off a trailing space in the struct string, to make the - output look a bit better, then stick on the visibility string. */ - - t = info->stack->type; - len = strlen (t); - assert (t[len - 1] == ' '); - t[len - 1] = '\0'; - - if (! append_type (info, s) - || ! append_type (info, ":\n") - || ! indent_type (info)) - return false; - - info->stack->visibility = visibility; - - return true; -} - -/* Add a field to a struct type. */ - -static boolean -pr_struct_field (p, name, bitpos, bitsize, visibility) - PTR p; - const char *name; - bfd_vma bitpos; - bfd_vma bitsize; - enum debug_visibility visibility; -{ - struct pr_handle *info = (struct pr_handle *) p; - char ab[20]; - char *t; - - if (! substitute_type (info, name)) - return false; - - if (! append_type (info, "; /* ")) - return false; - - if (bitsize != 0) - { - print_vma (bitsize, ab, true, false); - if (! append_type (info, "bitsize ") - || ! append_type (info, ab) - || ! append_type (info, ", ")) - return false; - } - - print_vma (bitpos, ab, true, false); - if (! append_type (info, "bitpos ") - || ! append_type (info, ab) - || ! append_type (info, " */\n") - || ! indent_type (info)) - return false; - - t = pop_type (info); - if (t == NULL) - return false; - - if (! pr_fix_visibility (info, visibility)) - return false; - - return append_type (info, t); -} - -/* Finish a struct type. */ - -static boolean -pr_end_struct_type (p) - PTR p; -{ - struct pr_handle *info = (struct pr_handle *) p; - char *s; - - assert (info->stack != NULL); - assert (info->indent >= 2); - - info->indent -= 2; - - /* Change the trailing indentation to have a close brace. */ - s = info->stack->type + strlen (info->stack->type) - 2; - assert (s[0] == ' ' && s[1] == ' ' && s[2] == '\0'); - - *s++ = '}'; - *s = '\0'; - - return true; -} - -/* Start a class type. */ - -static boolean -pr_start_class_type (p, tag, id, structp, size, vptr, ownvptr) - PTR p; - const char *tag; - unsigned int id; - boolean structp; - unsigned int size; - boolean vptr; - boolean ownvptr; -{ - struct pr_handle *info = (struct pr_handle *) p; - char *tv = NULL; - - info->indent += 2; - - if (vptr && ! ownvptr) - { - tv = pop_type (info); - if (tv == NULL) - return false; - } - - if (! push_type (info, structp ? "class " : "union class ")) - return false; - if (tag != NULL) - { - if (! append_type (info, tag)) - return false; - } - else - { - char idbuf[20]; - - sprintf (idbuf, "%%anon%u", id); - if (! append_type (info, idbuf)) - return false; - } - - if (! append_type (info, " {")) - return false; - if (size != 0 || vptr || ownvptr || tag != NULL) - { - if (! append_type (info, " /*")) - return false; - - if (size != 0) - { - char ab[20]; - - sprintf (ab, "%u", size); - if (! append_type (info, " size ") - || ! append_type (info, ab)) - return false; - } - - if (vptr) - { - if (! append_type (info, " vtable ")) - return false; - if (ownvptr) - { - if (! append_type (info, "self ")) - return false; - } - else - { - if (! append_type (info, tv) - || ! append_type (info, " ")) - return false; - } - } - - if (tag != NULL) - { - char ab[30]; - - sprintf (ab, " id %u", id); - if (! append_type (info, ab)) - return false; - } - - if (! append_type (info, " */")) - return false; - } - - info->stack->visibility = DEBUG_VISIBILITY_PRIVATE; - - return (append_type (info, "\n") - && indent_type (info)); -} - -/* Add a static member to a class. */ - -static boolean -pr_class_static_member (p, name, physname, visibility) - PTR p; - const char *name; - const char *physname; - enum debug_visibility visibility; -{ - struct pr_handle *info = (struct pr_handle *) p; - char *t; - - if (! substitute_type (info, name)) - return false; - - if (! prepend_type (info, "static ") - || ! append_type (info, "; /* ") - || ! append_type (info, physname) - || ! append_type (info, " */\n") - || ! indent_type (info)) - return false; - - t = pop_type (info); - if (t == NULL) - return false; - - if (! pr_fix_visibility (info, visibility)) - return false; - - return append_type (info, t); -} - -/* Add a base class to a class. */ - -static boolean -pr_class_baseclass (p, bitpos, virtual, visibility) - PTR p; - bfd_vma bitpos; - boolean virtual; - enum debug_visibility visibility; -{ - struct pr_handle *info = (struct pr_handle *) p; - char *t; - const char *prefix; - char ab[20]; - char *s, *l, *n; - - assert (info->stack != NULL && info->stack->next != NULL); - - if (! substitute_type (info, "")) - return false; - - t = pop_type (info); - if (t == NULL) - return false; - - if (strncmp (t, "class ", sizeof "class " - 1) == 0) - t += sizeof "class " - 1; - - /* Push it back on to take advantage of the prepend_type and - append_type routines. */ - if (! push_type (info, t)) - return false; - - if (virtual) - { - if (! prepend_type (info, "virtual ")) - return false; - } - - switch (visibility) - { - case DEBUG_VISIBILITY_PUBLIC: - prefix = "public "; - break; - case DEBUG_VISIBILITY_PROTECTED: - prefix = "protected "; - break; - case DEBUG_VISIBILITY_PRIVATE: - prefix = "private "; - break; - default: - prefix = "/* unknown visibility */ "; - break; - } - - if (! prepend_type (info, prefix)) - return false; - - if (bitpos != 0) - { - print_vma (bitpos, ab, true, false); - if (! append_type (info, " /* bitpos ") - || ! append_type (info, ab) - || ! append_type (info, " */")) - return false; - } - - /* Now the top of the stack is something like "public A / * bitpos - 10 * /". The next element on the stack is something like "class - xx { / * size 8 * /\n...". We want to substitute the top of the - stack in before the {. */ - s = strchr (info->stack->next->type, '{'); - assert (s != NULL); - --s; - - /* If there is already a ':', then we already have a baseclass, and - we must append this one after a comma. */ - for (l = info->stack->next->type; l != s; l++) - if (*l == ':') - break; - if (! prepend_type (info, l == s ? " : " : ", ")) - return false; - - t = pop_type (info); - if (t == NULL) - return false; - - n = (char *) xmalloc (strlen (info->stack->type) + strlen (t) + 1); - memcpy (n, info->stack->type, s - info->stack->type); - strcpy (n + (s - info->stack->type), t); - strcat (n, s); - - free (info->stack->type); - info->stack->type = n; - - free (t); - - return true; -} - -/* Start adding a method to a class. */ - -static boolean -pr_class_start_method (p, name) - PTR p; - const char *name; -{ - struct pr_handle *info = (struct pr_handle *) p; - - assert (info->stack != NULL); - info->stack->method = name; - return true; -} - -/* Add a variant to a method. */ - -static boolean -pr_class_method_variant (p, physname, visibility, constp, volatilep, voffset, - context) - PTR p; - const char *physname; - enum debug_visibility visibility; - boolean constp; - boolean volatilep; - bfd_vma voffset; - boolean context; -{ - struct pr_handle *info = (struct pr_handle *) p; - char *method_type; - char *context_type; - - assert (info->stack != NULL); - assert (info->stack->next != NULL); - - /* Put the const and volatile qualifiers on the type. */ - if (volatilep) - { - if (! append_type (info, " volatile")) - return false; - } - if (constp) - { - if (! append_type (info, " const")) - return false; - } - - /* Stick the name of the method into its type. */ - if (! substitute_type (info, - (context - ? info->stack->next->next->method - : info->stack->next->method))) - return false; - - /* Get the type. */ - method_type = pop_type (info); - if (method_type == NULL) - return false; - - /* Pull off the context type if there is one. */ - if (! context) - context_type = NULL; - else - { - context_type = pop_type (info); - if (context_type == NULL) - return false; - } - - /* Now the top of the stack is the class. */ - - if (! pr_fix_visibility (info, visibility)) - return false; - - if (! append_type (info, method_type) - || ! append_type (info, " /* ") - || ! append_type (info, physname) - || ! append_type (info, " ")) - return false; - if (context || voffset != 0) - { - char ab[20]; - - if (context) - { - if (! append_type (info, "context ") - || ! append_type (info, context_type) - || ! append_type (info, " ")) - return false; - } - print_vma (voffset, ab, true, false); - if (! append_type (info, "voffset ") - || ! append_type (info, ab)) - return false; - } - - return (append_type (info, " */;\n") - && indent_type (info)); -} - -/* Add a static variant to a method. */ - -static boolean -pr_class_static_method_variant (p, physname, visibility, constp, volatilep) - PTR p; - const char *physname; - enum debug_visibility visibility; - boolean constp; - boolean volatilep; -{ - struct pr_handle *info = (struct pr_handle *) p; - char *method_type; - - assert (info->stack != NULL); - assert (info->stack->next != NULL); - assert (info->stack->next->method != NULL); - - /* Put the const and volatile qualifiers on the type. */ - if (volatilep) - { - if (! append_type (info, " volatile")) - return false; - } - if (constp) - { - if (! append_type (info, " const")) - return false; - } - - /* Mark it as static. */ - if (! prepend_type (info, "static ")) - return false; - - /* Stick the name of the method into its type. */ - if (! substitute_type (info, info->stack->next->method)) - return false; - - /* Get the type. */ - method_type = pop_type (info); - if (method_type == NULL) - return false; - - /* Now the top of the stack is the class. */ - - if (! pr_fix_visibility (info, visibility)) - return false; - - return (append_type (info, method_type) - && append_type (info, " /* ") - && append_type (info, physname) - && append_type (info, " */;\n") - && indent_type (info)); -} - -/* Finish up a method. */ - -static boolean -pr_class_end_method (p) - PTR p; -{ - struct pr_handle *info = (struct pr_handle *) p; - - info->stack->method = NULL; - return true; -} - -/* Finish up a class. */ - -static boolean -pr_end_class_type (p) - PTR p; -{ - return pr_end_struct_type (p); -} - -/* Push a type on the stack using a typedef name. */ - -static boolean -pr_typedef_type (p, name) - PTR p; - const char *name; -{ - struct pr_handle *info = (struct pr_handle *) p; - - return push_type (info, name); -} - -/* Push a type on the stack using a tag name. */ - -static boolean -pr_tag_type (p, name, id, kind) - PTR p; - const char *name; - unsigned int id; - enum debug_type_kind kind; -{ - struct pr_handle *info = (struct pr_handle *) p; - const char *t, *tag; - char idbuf[30]; - - switch (kind) - { - case DEBUG_KIND_STRUCT: - t = "struct "; - break; - case DEBUG_KIND_UNION: - t = "union "; - break; - case DEBUG_KIND_ENUM: - t = "enum "; - break; - case DEBUG_KIND_CLASS: - t = "class "; - break; - case DEBUG_KIND_UNION_CLASS: - t = "union class "; - break; - default: - abort (); - return false; - } - - if (! push_type (info, t)) - return false; - if (name != NULL) - tag = name; - else - { - sprintf (idbuf, "%%anon%u", id); - tag = idbuf; - } - - if (! append_type (info, tag)) - return false; - if (name != NULL && kind != DEBUG_KIND_ENUM) - { - sprintf (idbuf, " /* id %u */", id); - if (! append_type (info, idbuf)) - return false; - } - - return true; -} - -/* Output a typedef. */ - -static boolean -pr_typdef (p, name) - PTR p; - const char *name; -{ - struct pr_handle *info = (struct pr_handle *) p; - char *s; - - if (! substitute_type (info, name)) - return false; - - s = pop_type (info); - if (s == NULL) - return false; -/* - indent (info); - TRACE_FPRINTF( (info->f, "typedef %s;\n", s)); -*/ - free (s); - - return true; -} - -/* Output a tag. The tag should already be in the string on the - stack, so all we have to do here is print it out. */ - -/*ARGSUSED*/ -static boolean -pr_tag (p, name) - PTR p; - const char *name; -{ - struct pr_handle *info = (struct pr_handle *) p; - char *t; - - t = pop_type (info); - if (t == NULL) - return false; -/* - indent (info); - TRACE_FPRINTF( (info->f, "%s;\n", t)); -*/ - free (t); - - return true; -} - -/* Output an integer constant. */ - -static boolean -pr_int_constant (p, name, val) - PTR p; - const char *name; - bfd_vma val; -{ -/* - struct pr_handle *info = (struct pr_handle *) p; - char ab[20]; - indent (info); - print_vma (val, ab, false, false); - TRACE_FPRINTF( (info->f, "const int %s = %s;\n", name, ab)); - */ - return true; -} - -/* Output a floating point constant. */ - -static boolean -pr_float_constant (p, name, val) - PTR p; - const char *name; - double val; -{ -/* - struct pr_handle *info = (struct pr_handle *) p; - indent (info); - TRACE_FPRINTF( (info->f, "const double %s = %g;\n", name, val)); - */ - return true; -} - -/* Output a typed constant. */ - -static boolean -pr_typed_constant (p, name, val) - PTR p; - const char *name; - bfd_vma val; -{ - struct pr_handle *info = (struct pr_handle *) p; - char *t; - - t = pop_type (info); - if (t == NULL) - return false; -/* - char ab[20]; - indent (info); - print_vma (val, ab, false, false); - TRACE_FPRINTF( (info->f, "const %s %s = %s;\n", t, name, ab)); -*/ - free (t); - - return true; -} - -/* Output a variable. */ - -static boolean -pr_variable (p, name, kind, val) - PTR p; - const char *name; - enum debug_var_kind kind; - bfd_vma val; -{ - struct pr_handle *info = (struct pr_handle *) p; - char *t; - char ab[20]; - (void)ab; - - if (! substitute_type (info, name)) - return false; - - t = pop_type (info); - if (t == NULL) - return false; - -#if 0 - indent (info); - switch (kind) - { - case DEBUG_STATIC: - case DEBUG_LOCAL_STATIC: - TRACE_FPRINTF( (info->f, "static ")); - break; - case DEBUG_REGISTER: - TRACE_FPRINTF( (info->f, "register ")); - break; - default: - break; - } - print_vma (val, ab, true, true); - TRACE_FPRINTF( (info->f, "%s /* %s */;\n", t, ab)); -#else /* 0 */ -#if 0 - if (kind==DEBUG_STATIC || kind==DEBUG_LOCAL_STATIC) { - print_vma (val, ab, true, true); - TRACE_FPRINTF( (info->f, "STATIC_VAR: %s /* %s */;\n", t, ab)); - } -#endif /* 0 */ -#endif /* !0 */ - - free (t); - - return true; -} - -/* Start outputting a function. */ - -static boolean -pr_start_function (p, name, global) - PTR p; - const char *name; - boolean global; -{ - struct pr_handle *info = (struct pr_handle *) p; - char *t; - - if (! substitute_type (info, name)) - return false; - - t = pop_type (info); - if (t == NULL) - return false; - -#if 0 - indent (info); - if (! global) - TRACE_FPRINTF( (info->f, "static ")); - TRACE_FPRINTF( (info->f, "%s (", t)); - info->parameter = 1; -#else /* 0 */ - if (info->functions_size==info->functions_maxsize) { - info->functions_maxsize *= 2; - info->functions = xrealloc(info->functions, - info->functions_maxsize*sizeof(debug_function_t)); - assert(info->functions!=0); - } - /* info->functions[info->functions_size] = xmalloc(sizeof(debug_function_t)); */ - info->function = &info->functions[info->functions_size]; - ++info->functions_size; - info->function->symbol = NULL; - info->function->lines = NULL; - info->function->lines_count = 0; - info->function->max_lines_count = 0; - info->function->name = t; - info->function->filename = NULL; - info->function->block = NULL; - info->function->argv = NULL; - info->function->argc = 0; - info->function->max_argc = 0; -#endif /* !0 */ - return true; -} - -/* Output a function parameter. */ - -static boolean -pr_function_parameter (p, name, kind, val) - PTR p; - const char *name; - enum debug_parm_kind kind; - bfd_vma val; -{ - struct pr_handle *info = (struct pr_handle *) p; - debug_function_t* f = info->function; - char *t; - char ab[20]; - (void)ab; - - if (kind == DEBUG_PARM_REFERENCE - || kind == DEBUG_PARM_REF_REG) - { - if (! pr_reference_type (p)) - return false; - } - - if (! substitute_type (info, name)) - return false; - - t = pop_type (info); - if (t == NULL) - return false; - -#if 0 - if (info->parameter != 1) - TRACE_FPRINTF( (info->f, ", ")); - - if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG) - TRACE_FPRINTF( (info->f, "register ")); - - print_vma (val, ab, true, true); - TRACE_FPRINTF( (info->f, "%s /* %s */", t, ab)); - free (t); - ++info->parameter; -#else /* 0 */ - assert(f!=NULL); - if (f->argv==NULL) { - f->max_argc = 7; /* rarely anyone has more than that many args... */ - f->argv = xmalloc(sizeof(debug_parameter_t)*f->max_argc); - } else if (f->argc==f->max_argc) { - f->max_argc *= 2; - f->argv = realloc(f->argv,sizeof(debug_parameter_t)*f->max_argc); - } - f->argv[f->argc].offset = val; - f->argv[f->argc].name = t; - ++f->argc; -#endif /* !0 */ - return true; -} - -/* Start writing out a block. */ - -static boolean -pr_start_block (p, addr) - PTR p; - bfd_vma addr; -{ - struct pr_handle *info = (struct pr_handle *) p; - char ab[20]; - debug_block_t* block = 0; - (void)ab; -#if 0 - if (info->parameter > 0) - { - TRACE_FPRINTF( (info->f, ")\n")); - info->parameter = 0; - } - indent (info); - print_vma (addr, ab, true, true); - TRACE_FPRINTF( (info->f, "{ /* %s */\n", ab)); - info->indent += 2; -#else - if (info->block) { - if (info->block->childs_count==0) - info->block->childs = xmalloc(sizeof(debug_block_t)); - else - info->block->childs = xrealloc(info->block->childs, - info->block->childs_count*sizeof(debug_block_t)); - block = &info->block->childs[info->block->childs_count]; - } else { - block = xmalloc(sizeof(debug_block_t)); - info->function->block = block; - } - block->begin_addr = addr; - block->end_addr = 0; - block->parent = info->block; - block->childs = NULL; - block->childs_count = 0; - info->block = block; -#endif - return true; -} - -/* Write out line number information. */ - -static boolean -pr_lineno (p, filename, lineno, addr) - PTR p; - const char *filename; - unsigned long lineno; - bfd_vma addr; -{ - struct pr_handle *info = (struct pr_handle *) p; - char ab[20]; - debug_function_t* f = info->function; - (void)ab; - -#if 0 - indent (info); - print_vma (addr, ab, true, true); - TRACE_FPRINTF( (info->f, "/* file %s line %lu addr %s */\n", filename, lineno, ab)); -#else /* 0 */ - if (f==NULL) /* FIXME: skips junk silently. */ - return true; - /* assert(f!=NULL); */ - if (f->filename==NULL) { - f->filename = filename; - assert(f->lines==0); - f->max_lines_count = 4; - f->lines = xmalloc(sizeof(debug_lineno_t)*f->max_lines_count); - } - if (f->lines_count==f->max_lines_count) { - f->max_lines_count *= 2; - f->lines = xrealloc(f->lines, sizeof(debug_lineno_t)*f->max_lines_count); - } - f->lines[f->lines_count].lineno = lineno; - f->lines[f->lines_count].addr = addr; - ++f->lines_count; -#endif /* !0 */ - - return true; -} - -/* Finish writing out a block. */ - -static boolean -pr_end_block (p, addr) - PTR p; - bfd_vma addr; -{ - struct pr_handle *info = (struct pr_handle *) p; - -#if 0 - char ab[20]; - - info->indent -= 2; - indent (info); - print_vma (addr, ab, true, true); - TRACE_FPRINTF( (info->f, "} /* %s */\n", ab)); -#else /* 0 */ - assert(info->block!=0); - info->block->end_addr = addr; - info->block = info->block->parent; -#endif /* !0 */ - - return true; -} - -/* Finish writing out a function. */ - -/*ARGSUSED*/ -static boolean -pr_end_function (p) - PTR p; -{ - struct pr_handle *info = (struct pr_handle *) p; - assert(info->block==0); - info->function = NULL; - return true; -} - -/* third parameter to segv_action. */ -/* Got it after a bit of head scratching and stack dumping. */ -typedef struct { - u_int32_t foo1; /* +0x00 */ - u_int32_t foo2; - u_int32_t foo3; - u_int32_t foo4; /* usually 2 */ - u_int32_t foo5; /* +0x10 */ - u_int32_t xgs; /* always zero */ - u_int32_t xfs; /* always zero */ - u_int32_t xes; /* always es=ds=ss */ - u_int32_t xds; /* +0x20 */ - u_int32_t edi; - u_int32_t esi; - u_int32_t ebp; - u_int32_t esp; /* +0x30 */ - u_int32_t ebx; - u_int32_t edx; - u_int32_t ecx; - u_int32_t eax; /* +0x40 */ - u_int32_t foo11; /* usually 0xe */ - u_int32_t foo12; /* usually 0x6 */ - u_int32_t eip; /* instruction pointer */ - u_int32_t xcs; /* +0x50 */ - u_int32_t foo21; /* usually 0x2 */ - u_int32_t foo22; /* second stack pointer?! Probably. */ - u_int32_t xss; - u_int32_t foo31; /* +0x60 */ /* usually 0x0 */ - u_int32_t foo32; /* usually 0x2 */ - u_int32_t fault_addr; /* Address which caused a fault */ - u_int32_t foo41; /* usually 0x2 */ -} signal_regs_t; - -signal_regs_t* ptrace_regs = 0; /* Tells my_ptrace to "ptrace" current process" */ -/* - * my_ptrace: small wrapper around ptrace. - * Act as normal ptrace if ptrace_regs==0. - * Read data from current process if ptrace_regs!=0. - */ -static int -my_ptrace( int request, - int pid, - int addr, - int data) -{ - if (ptrace_regs==0) - return ptrace(request, pid, addr, data); - /* we are tracing ourselves! */ - switch (request) { - case PTRACE_ATTACH: return 0; - case PTRACE_CONT: return 0; - case PTRACE_DETACH: return 0; - case PTRACE_PEEKUSER: - switch (addr / 4) { - case EIP: return ptrace_regs->eip; - case EBP: return ptrace_regs->ebp; - default: assert(0); - } - case PTRACE_PEEKTEXT: /* FALLTHROUGH */ - case PTRACE_PEEKDATA: return *(int*)(addr); - default: assert(0); - } - errno = 1; /* what to do here? */ - return 1; /* failed?! */ -} - -#define MAXARGS 6 - -/* - * To minimize the number of parameters. - */ -typedef struct { - asymbol** syms; /* Sorted! */ - int symcount; - debug_function_t** functions; - int functions_size; -} symbol_data_t; - -/* - * Perform a search. A binary search for a symbol. - */ -static void -decode_symbol( symbol_data_t* symbol_data, - const unsigned long addr, - char* buf, - const int bufsize) -{ - asymbol** syms = symbol_data->syms; - const int symcount = symbol_data->symcount; - int bottom = 0; - int top = symcount - 1; - int i; - if (symcount==0) { - sprintf(buf, "????"); - return; - } - while (top>bottom+1) { - i = (top+bottom) / 2; - if (bfd_asymbol_value(syms[i])==addr) { - sprintf(buf, "%s", syms[i]->name); - return; - } else if (bfd_asymbol_value(syms[i]) > addr) - top = i; - else - bottom = i; - } - i = bottom; - if (addr<bfd_asymbol_value(syms[i]) || addr>(syms[i]->section->vma+syms[i]->section->_cooked_size)) - sprintf(buf, "????"); - else - sprintf(buf, "%s + 0x%lx", syms[i]->name, addr-bfd_asymbol_value(syms[i])); -} - -/* - * 1. Perform a binary search for an debug_function_t. - * 2. Fill buf/bufsize with name, parameters and lineno, if found - * Or with '????' otherwise. - */ -static debug_function_t* -find_debug_function_t( symbol_data_t* symbol_data, - const pid_t pid, - const unsigned long fp, /* frame pointer */ - const unsigned long addr, - char* buf, /* string buffer */ - const int bufsize)/* FIXME: not used! */ -{ - debug_function_t** syms = symbol_data->functions; - debug_function_t* f = NULL; - debug_block_t* block = NULL; - debug_lineno_t* lineno = NULL; - const int symcount = symbol_data->functions_size; - int bottom = 0; - int top = symcount - 1; - int i; - char* bufptr = buf; - - if (symcount==0) { - sprintf(buf, "????"); - return NULL; - } - while (top>bottom+1) { - i = (top+bottom) / 2; - if (syms[i]->block->begin_addr==addr) { - f = syms[i]; - break; - } else if (syms[i]->block->begin_addr > addr) - top = i; - else - if (syms[i]->block->end_addr >= addr) { - f = syms[i]; - break; - } else - bottom = i; - } - i = bottom; - if (f!=0) - block = f->block; - else { - block = syms[i]->block; - if (block->begin_addr>=addr && block->end_addr<=addr) - f = syms[i]; - } - if (f==0) - sprintf(buf, "????"); - else { - /* - * Do the backtrace the GDB way... - */ - unsigned long arg; - /* assert(f->lines_count>0); */ - if (f->lines_count>0) { - lineno = &f->lines[f->lines_count-1]; - for (i=1; i<f->lines_count; ++i) - if (f->lines[i].addr>addr) { - lineno = &f->lines[i-1]; - break; - } - } - bufptr[0] = 0; - bufptr += sprintf(bufptr, "%s+0x%lx (", f->name, addr-block->begin_addr); - for (i=0; i<f->argc; ++i) { - bufptr += sprintf(bufptr, "%s = ", f->argv[i].name); - /* FIXME: better parameter printing */ - errno = 0; - arg = my_ptrace(PTRACE_PEEKDATA, pid, fp+f->argv[i].offset, 0); - assert(errno==0); - bufptr += sprintf(bufptr, "0x%x", arg); - if (i!=f->argc-1) - bufptr += sprintf(bufptr, ", "); - } - if (lineno!=0) - bufptr += sprintf(bufptr, ") at %s:%d", f->filename, lineno->lineno); - } - return f; -} - -/* - * Advance through the stacks and display frames as needed. - */ -static int -my_crawl( int pid, - symbol_data_t* symbol_data, - int fout) -{ - unsigned long pc = 0; - unsigned long fp = 0; - unsigned long nextfp; - unsigned long nargs; - unsigned long i; - unsigned long arg; - char buf[8096]; // FIXME: enough? - debug_function_t* f = 0; - - errno = 0; - - pc = my_ptrace(PTRACE_PEEKUSER, pid, EIP * 4, 0); - if (!errno) - fp = my_ptrace(PTRACE_PEEKUSER, pid, EBP * 4, 0); - - if (!errno) { -#if 1 - f = find_debug_function_t(symbol_data, pid, fp, pc, buf, sizeof(buf)); - fdprintf(fout,"0x%08lx: %s", pc, buf); - for ( ; !errno && fp; ) { - nextfp = my_ptrace(PTRACE_PEEKDATA, pid, fp, 0); - if (errno) - break; - - if (f==0) { - nargs = (nextfp - fp - 8) / 4; - if (nargs > MAXARGS) - nargs = MAXARGS; - if (nargs > 0) { - fdputs(" (", fout); - for (i = 1; i <= nargs; i++) { - arg = my_ptrace(PTRACE_PEEKDATA, pid, fp + 4 * (i + 1), 0); - if (errno) - break; - fdprintf(fout,"%lx", arg); - if (i < nargs) - fdputs(", ", fout); - } - fdputc(')', fout); - nargs = nextfp - fp - 8 - (4 * nargs); - if (!errno && nargs > 0) - fdprintf(fout," + %lx\n", nargs); - else - fdputc('\n', fout); - } else - fdputc('\n', fout); - } else - fdputc('\n', fout); - - if (errno || !nextfp) - break; - pc = my_ptrace(PTRACE_PEEKDATA, pid, fp + 4, 0); - fp = nextfp; - if (errno) - break; - f = find_debug_function_t(symbol_data, pid, fp, pc, buf, sizeof(buf)); - fdprintf(fout,"0x%08lx: %s", pc, buf); - } -#else /* 1 */ - decode_symbol(symbol_data, pc, buf, sizeof(buf)); - fdprintf(fout,"0x%08lx: %s", pc, buf); - for ( ; !errno && fp; ) { - nextfp = my_ptrace(PTRACE_PEEKDATA, pid, fp, 0); - if (errno) - break; - - nargs = (nextfp - fp - 8) / 4; - if (nargs > MAXARGS) - nargs = MAXARGS; - if (nargs > 0) { - fputs(" (", fout); - for (i = 1; i <= nargs; i++) { - arg = my_ptrace(PTRACE_PEEKDATA, pid, fp + 4 * (i + 1), 0); - if (errno) - break; - fdprintf(fout,"%lx", arg); - if (i < nargs) - fputs(", ", fout); - } - fdputc(')', fout); - nargs = nextfp - fp - 8 - (4 * nargs); - if (!errno && nargs > 0) - fdprintf(fout," + %lx\n", nargs); - else - fdputc('\n', fout); - } else - fdputc('\n', fout); - - if (errno || !nextfp) - break; - pc = my_ptrace(PTRACE_PEEKDATA, pid, fp + 4, 0); - fp = nextfp; - if (errno) - break; - decode_symbol(symbol_data, pc, buf, sizeof(buf)); - fdprintf(fout,"0x%08lx: %s", pc, buf); - } -#endif /* !1 */ - } - if (errno) - perror("my_crawl"); - return errno; -} - -/* layout from /usr/src/linux/arch/i386/kernel/process.c */ -static void -show_regs( signal_regs_t* regs, - int fd) -{ - /* long cr0 = 0L, cr2 = 0L, cr3 = 0L; */ - - fdprintf(fd,"\n"); - fdprintf(fd,"FAULT ADDR: %08x\n", regs->fault_addr); - fdprintf(fd,"EIP: %04x:[<%08x>]",0xffff & regs->xcs,regs->eip); - if (regs->xcs & 3) - fdprintf(fd," ESP: %04x:%08x",0xffff & regs->xss,regs->esp); - /*fdprintf(fd," EFLAGS: %08lx\n",regs->eflags); */ - fdprintf(fd, "\n"); - fdprintf(fd,"EAX: %08x EBX: %08x ECX: %08x EDX: %08x\n", - regs->eax,regs->ebx,regs->ecx,regs->edx); - fdprintf(fd,"ESI: %08x EDI: %08x EBP: %08x", - regs->esi, regs->edi, regs->ebp); - fdprintf(fd," DS: %04x ES: %04x\n", - 0xffff & regs->xds,0xffff & regs->xes); - /* - __asm__("movl %%cr0, %0": "=r" (cr0)); - __asm__("movl %%cr2, %0": "=r" (cr2)); - __asm__("movl %%cr3, %0": "=r" (cr3)); - fprintf(stderr,"CR0: %08lx CR2: %08lx CR3: %08lx\n", cr0, cr2, cr3); */ -} - -/* - * Load a BFD for an executable based on PID. Return 0 on failure. - */ -static bfd* -load_bfd( const int pid) -{ - char filename[512]; - bfd* abfd = 0; - - /* Get the contents from procfs. */ -#if 1 - sprintf(filename, "/proc/%d/exe", pid); -#else - sprintf(filename, "crashing"); -#endif - - if ((abfd = bfd_openr (filename, 0))== NULL) - bfd_nonfatal (filename); - else { - char** matching; - assert(bfd_check_format(abfd, bfd_archive)!=true); - - /* - * There is no indication in BFD documentation that it should be done. - * God knows why... - */ - if (!bfd_check_format_matches (abfd, bfd_object, &matching)) { - bfd_nonfatal (bfd_get_filename (abfd)); - if (bfd_get_error () == bfd_error_file_ambiguously_recognized) { - list_matching_formats (matching); - free (matching); - } - } - } - return abfd; -} - -/* - * Those are for qsort. We need only function addresses, so all the others don't count. - */ -/* - * Compare two BFD::asymbol-s. - */ -static int -compare_symbols(const void* ap, - const void* bp) -{ - const asymbol *a = *(const asymbol **)ap; - const asymbol *b = *(const asymbol **)bp; - if (bfd_asymbol_value (a) > bfd_asymbol_value (b)) - return 1; - else if (bfd_asymbol_value (a) < bfd_asymbol_value (b)) - return -1; - return 0; -} - -/* - * Compare two debug_asymbol_t-s. - */ -static int -compare_debug_function_t(const void* ap, - const void* bp) -{ - const debug_function_t *a = *(const debug_function_t **)ap; - const debug_function_t *b = *(const debug_function_t **)bp; - assert(a->block!=0); - assert(b->block!=0); - { - const bfd_vma addr1 = a->block->begin_addr; - const bfd_vma addr2 = b->block->begin_addr; - if (addr1 > addr2) - return 1; - else if (addr2 > addr1) - return -1; - } - return 0; -} - -/* - * Filter out (in place) symbols that are useless for stack tracing. - * COUNT is the number of elements in SYMBOLS. - * Return the number of useful symbols. - */ - -static long -remove_useless_symbols( asymbol** symbols, - long count) -{ - asymbol** in_ptr = symbols; - asymbol** out_ptr = symbols; - - while (--count >= 0) { - asymbol *sym = *in_ptr++; - - if (sym->name == NULL || sym->name[0] == '\0' || sym->value==0) - continue; - if (sym->flags & (BSF_DEBUGGING)) - continue; - if (bfd_is_und_section (sym->section) || bfd_is_com_section (sym->section)) - continue; - *out_ptr++ = sym; - } - return out_ptr - symbols; -} - -/* - * Debugging information. - */ -static bfd* abfd = 0; -static PTR dhandle = 0; -static asymbol** syms = 0; -static long symcount = 0; -static asymbol** sorted_syms = 0; -static long sorted_symcount = 0; -static debug_function_t** functions = 0; -static int functions_size = 0; -static int sigreport = SIGUSR1; -static pthread_t segv_tid; /* What thread did SEGV? */ -static pid_t segv_pid; - -/* - * We'll get here after a SIGSEGV. But you can install it on other signals, too :) - * Because we are in the middle of the SIGSEGV, we are on our own. We can't do - * any malloc(), any fopen(), nothing. The last is actually a sin. We event can't - * fprintf(stderr,...)!!! - */ -static void -segv_action(int signo, siginfo_t* siginfo, void* ptr) -{ - symbol_data_t symbol_data; - int fd = -1; - - segv_pid = getpid(); - segv_tid = pthread_self(); - fd = open_log_file(segv_tid, segv_pid); - /* signal(SIGSEGV, SIG_DFL); */ - ptrace_regs = (signal_regs_t*)ptr; - assert(ptrace_regs!=0); - - /* Show user how guilty we are. */ - fdprintf(fd,"--------- SEGV in PROCESS %d, THREAD %d ---------------\n", segv_pid, pthread_self()); - show_regs(ptrace_regs, fd); - - /* Some form of stack trace, too. */ - fdprintf(fd, "STACK TRACE:\n"); - - symbol_data.syms = sorted_syms; - symbol_data.symcount = sorted_symcount; - symbol_data.functions = functions; - symbol_data.functions_size = functions_size; - my_crawl(segv_pid, &symbol_data, fd); - //fflush(stdout); - close(fd); - linuxthreads_notify_others(sigreport); -} - - -static void -report_action(int signo, siginfo_t* siginfo, void* ptr) -{ - const int pid = getpid(); - pthread_t tid = pthread_self(); - symbol_data_t symbol_data; - int fd; - if (pthread_equal(tid, segv_tid)) { - /* We have already printed our stack trace... */ - return; - } - - fd = open_log_file(tid, pid); - fdprintf(fd, "REPORT: CURRENT PROCESS:%d, THREAD:%d\n", getpid(), pthread_self()); - /* signal(SIGSEGV, SIG_DFL); */ - ptrace_regs = (signal_regs_t*)ptr; - assert(ptrace_regs!=0); - - /* Show user how guilty we are. */ - fdprintf(fd,"--------- STACK TRACE FOR PROCESS %d, THREAD %d ---------------\n", pid, pthread_self()); - show_regs(ptrace_regs, fd); - - /* Some form of stack trace, too. */ - fdprintf(fd, "STACK TRACE:\n"); - - symbol_data.syms = sorted_syms; - symbol_data.symcount = sorted_symcount; - symbol_data.functions = functions; - symbol_data.functions_size = functions_size; - my_crawl(pid, &symbol_data, fd); - //fflush(stdout); - close(fd); - /* Tell segv_thread to proceed after pause(). */ - /*pthread_kill(segv_tid, sigreport); - kill(segv_pid, sigreport); - pthread_cancel(tid); */ -} - -/* - * Main library routine. Just call it on your program. - */ -int -pstack_install_segv_action( const char* path_format_) -{ - const int pid = getpid(); - struct sigaction act; - - /* Store what we have to for later usage. */ - path_format = path_format_; - - /* We need a signal action for SIGSEGV and sigreport ! */ - sigreport = SIGUSR1; - act.sa_handler = 0; - sigemptyset(&act.sa_mask); - act.sa_flags = SA_SIGINFO|SA_ONESHOT; /* Just one SIGSEGV. */ - act.sa_sigaction = segv_action; - act.sa_restorer = NULL; - if (sigaction(SIGSEGV, &act, NULL)!=0) { - perror("sigaction"); - return 1; - } - act.sa_sigaction = report_action; - act.sa_flags = SA_SIGINFO; /* But many sigreports. */ - if (sigaction(sigreport, &act, NULL)!=0) { - perror("sigaction"); - return 1; - } - - /* And a little setup for libiberty. */ - program_name = "crashing"; - xmalloc_set_program_name (program_name); - - /* Umm, and initialize BFD, too */ - bfd_init(); -#if 0 - list_supported_targets(0, stdout); - set_default_bfd_target(); -#endif /* 0 */ - - if ((abfd = load_bfd(pid))==0) - fprintf(stderr, "BFD load failed..\n"); - else { - long storage_needed= (bfd_get_file_flags(abfd) & HAS_SYMS) ? - bfd_get_symtab_upper_bound (abfd) : 0; - long i; - (void)i; - - if (storage_needed < 0) - fprintf(stderr, "Symbol table size estimation failure.\n"); - else if (storage_needed > 0) { - syms = (asymbol **) xmalloc (storage_needed); - symcount = bfd_canonicalize_symtab (abfd, syms); - - TRACE_FPRINTF((stderr, "TOTAL: %ld SYMBOLS.\n", symcount)); - /* We need debugging info, too! */ - if (symcount==0 || (dhandle = read_debugging_info (abfd, syms, symcount))==0) - fprintf(stderr, "NO DEBUGGING INFORMATION FOUND.\n"); - - /* We make a copy of syms to sort. We don't want to sort syms - because that will screw up the relocs. */ - sorted_syms = (asymbol **) xmalloc (symcount * sizeof (asymbol *)); - memcpy (sorted_syms, syms, symcount * sizeof (asymbol *)); - -#if 0 - for (i=0; i<symcount; ++i) - if (syms[i]->name!=0 && strlen(syms[i]->name)>0 && syms[i]->value!=0) - printf("%08lx T %s\n", syms[i]->section->vma + syms[i]->value, syms[i]->name); -#endif - sorted_symcount = remove_useless_symbols (sorted_syms, symcount); - TRACE_FPRINTF((stderr, "SORTED: %ld SYMBOLS.\n", sorted_symcount)); - - /* Sort the symbols into section and symbol order */ - qsort (sorted_syms, sorted_symcount, sizeof (asymbol *), compare_symbols); -#if 0 - for (i=0; i<sorted_symcount; ++i) - if (sorted_syms[i]->name!=0 && strlen(sorted_syms[i]->name)>0 && sorted_syms[i]->value!=0) - printf("%08lx T %s\n", sorted_syms[i]->section->vma + sorted_syms[i]->value, sorted_syms[i]->name); -#endif - /* We have symbols, we need debugging info somehow sorted out. */ - if (dhandle==0) { - fprintf(stderr, "STACK TRACE WILL BE UNCOMFORTABLE.\n"); - } else { - /* Start collecting the debugging information.... */ - struct pr_handle info; - - info.f = stdout; - info.indent = 0; - info.stack = NULL; - info.parameter = 0; - info.block = NULL; - info.function = NULL; - info.functions_size = 0; - info.functions_maxsize = 1000; - info.functions = (debug_function_t*)xmalloc(sizeof(debug_function_t)*info.functions_maxsize); - debug_write (dhandle, &pr_fns, (PTR) &info); - TRACE_FPRINTF((stdout, "\n%d DEBUG SYMBOLS\n", info.functions_size)); - assert(info.functions_size!=0); - functions = xmalloc(sizeof(debug_function_t*)*info.functions_size); - functions_size = info.functions_size; - for (i=0; i<functions_size; ++i) - functions[i] = &info.functions[i]; - /* Sort the symbols into section and symbol order */ - qsort (functions, functions_size, sizeof(debug_function_t*), - compare_debug_function_t); -#if 0 - for (i=0; i<info.functions_size; ++i) - fprintf(stdout, "%08lx T %s\n", info.functions[i].block->begin_addr, info.functions[i].name); -#endif - fflush(stdout); - } - } else /* storage_needed == 0 */ - fprintf(stderr, "NO SYMBOLS FOUND.\n"); - } - return 0; -} - -/*********************************************************************/ -/*********************************************************************/ -/*********************************************************************/ diff --git a/pstack/pstack.h b/pstack/pstack.h deleted file mode 100644 index 4c4fad7e754..00000000000 --- a/pstack/pstack.h +++ /dev/null @@ -1,22 +0,0 @@ -/* $Header$ */ - -#ifndef pstack_pstack_h_ -#define pstack_pstack_h_ - -#include "pstacktrace.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Install the stack-trace-on-SEGV handler.... - */ -extern int -pstack_install_segv_action( const char* path_format); -#ifdef __cplusplus -} -#endif - -#endif /* pstack_pstack_h_ */ - diff --git a/pstack/pstacktrace.h b/pstack/pstacktrace.h deleted file mode 100644 index c884bcb9f87..00000000000 --- a/pstack/pstacktrace.h +++ /dev/null @@ -1,24 +0,0 @@ -/* $Header$ */ - -/* - * Debugging macros. - */ - -#ifndef pstacktrace_h_ -#define pstacktrace_h_ - -#define PSTACK_DEBUG 1 -#undef PSTACK_DEBUG - -#ifdef PSTACK_DEBUG -# define TRACE_PUTC(a) putc a -# define TRACE_FPUTS(a) fputs a -# define TRACE_FPRINTF(a) fprintf a -#else /* PSTACK_DEBUG */ -# define TRACE_PUTC(a) (void)0 -# define TRACE_FPUTS(a) (void)0 -# define TRACE_FPRINTF(a) (void)0 -#endif /* !PSTACK_DEBUG */ - -#endif /* pstacktrace_h_ */ - diff --git a/pstack/rddbg.c b/pstack/rddbg.c deleted file mode 100644 index be3dfc21c57..00000000000 --- a/pstack/rddbg.c +++ /dev/null @@ -1,462 +0,0 @@ -/* rddbg.c -- Read debugging information into a generic form. - Copyright (C) 1995, 96, 1997 Free Software Foundation, Inc. - Written by Ian Lance Taylor <ian@cygnus.com>. - - This file is part of GNU Binutils. - - 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. */ - -/* This file reads debugging information into a generic form. This - file knows how to dig the debugging information out of an object - file. */ - -#include <bfd.h> -#include "bucomm.h" -#include <libiberty.h> -#include "debug.h" -#include "budbg.h" - -static boolean read_section_stabs_debugging_info - PARAMS ((bfd *, asymbol **, long, PTR, boolean *)); -static boolean read_symbol_stabs_debugging_info - PARAMS ((bfd *, asymbol **, long, PTR, boolean *)); -static boolean read_ieee_debugging_info PARAMS ((bfd *, PTR, boolean *)); -static void save_stab PARAMS ((int, int, bfd_vma, const char *)); -static void stab_context PARAMS ((void)); -static void free_saved_stabs PARAMS ((void)); - -/* Read debugging information from a BFD. Returns a generic debugging - pointer. */ - -PTR -read_debugging_info (abfd, syms, symcount) - bfd *abfd; - asymbol **syms; - long symcount; -{ - PTR dhandle; - boolean found; - - dhandle = debug_init (); - if (dhandle == NULL) - return NULL; - - if (! read_section_stabs_debugging_info (abfd, syms, symcount, dhandle, - &found)) - return NULL; - - if (bfd_get_flavour (abfd) == bfd_target_aout_flavour) - { - if (! read_symbol_stabs_debugging_info (abfd, syms, symcount, dhandle, - &found)) - return NULL; - } - - if (bfd_get_flavour (abfd) == bfd_target_ieee_flavour) - { - if (! read_ieee_debugging_info (abfd, dhandle, &found)) - return NULL; - } - - /* Try reading the COFF symbols if we didn't find any stabs in COFF - sections. */ - if (! found - && bfd_get_flavour (abfd) == bfd_target_coff_flavour - && symcount > 0) - { -#if 0 -/* - * JZ: Do we need coff? - */ - if (! parse_coff (abfd, syms, symcount, dhandle)) -#else - fprintf (stderr, "%s: COFF support temporarily disabled\n", - bfd_get_filename (abfd)); - return NULL; -#endif - return NULL; - found = true; - } - - if (! found) - { - fprintf (stderr, "%s: no recognized debugging information\n", - bfd_get_filename (abfd)); - return NULL; - } - - return dhandle; -} - -/* Read stabs in sections debugging information from a BFD. */ - -static boolean -read_section_stabs_debugging_info (abfd, syms, symcount, dhandle, pfound) - bfd *abfd; - asymbol **syms; - long symcount; - PTR dhandle; - boolean *pfound; -{ - static struct - { - const char *secname; - const char *strsecname; - } names[] = { { ".stab", ".stabstr" } }; - unsigned int i; - PTR shandle; - - *pfound = false; - shandle = NULL; - - for (i = 0; i < sizeof names / sizeof names[0]; i++) - { - asection *sec, *strsec; - - sec = bfd_get_section_by_name (abfd, names[i].secname); - strsec = bfd_get_section_by_name (abfd, names[i].strsecname); - if (sec != NULL && strsec != NULL) - { - bfd_size_type stabsize, strsize; - bfd_byte *stabs, *strings; - bfd_byte *stab; - bfd_size_type stroff, next_stroff; - - stabsize = bfd_section_size (abfd, sec); - stabs = (bfd_byte *) xmalloc (stabsize); - if (! bfd_get_section_contents (abfd, sec, stabs, 0, stabsize)) - { - fprintf (stderr, "%s: %s: %s\n", - bfd_get_filename (abfd), names[i].secname, - bfd_errmsg (bfd_get_error ())); - return false; - } - - strsize = bfd_section_size (abfd, strsec); - strings = (bfd_byte *) xmalloc (strsize); - if (! bfd_get_section_contents (abfd, strsec, strings, 0, strsize)) - { - fprintf (stderr, "%s: %s: %s\n", - bfd_get_filename (abfd), names[i].strsecname, - bfd_errmsg (bfd_get_error ())); - return false; - } - - if (shandle == NULL) - { - shandle = start_stab (dhandle, abfd, true, syms, symcount); - if (shandle == NULL) - return false; - } - - *pfound = true; - - stroff = 0; - next_stroff = 0; - for (stab = stabs; stab < stabs + stabsize; stab += 12) - { - bfd_size_type strx; - int type; - int other; - int desc; - bfd_vma value; - - /* This code presumes 32 bit values. */ - - strx = bfd_get_32 (abfd, stab); - type = bfd_get_8 (abfd, stab + 4); - other = bfd_get_8 (abfd, stab + 5); - desc = bfd_get_16 (abfd, stab + 6); - value = bfd_get_32 (abfd, stab + 8); - - if (type == 0) - { - /* Special type 0 stabs indicate the offset to the - next string table. */ - stroff = next_stroff; - next_stroff += value; - } - else - { - char *f, *s; - - f = NULL; - s = (char *) strings + stroff + strx; - while (s[strlen (s) - 1] == '\\' - && stab + 12 < stabs + stabsize) - { - char *p; - - stab += 12; - p = s + strlen (s) - 1; - *p = '\0'; - s = concat (s, - ((char *) strings - + stroff - + bfd_get_32 (abfd, stab)), - (const char *) NULL); - - /* We have to restore the backslash, because, if - the linker is hashing stabs strings, we may - see the same string more than once. */ - *p = '\\'; - - if (f != NULL) - free (f); - f = s; - } - - save_stab (type, desc, value, s); - - if (! parse_stab (dhandle, shandle, type, desc, value, s)) - { -#if 0 -/* - * JZ: skip the junk. - */ - stab_context (); - free_saved_stabs (); - return false; -#endif - } - - /* Don't free f, since I think the stabs code - expects strings to hang around. This should be - straightened out. FIXME. */ - } - } - - free_saved_stabs (); - free (stabs); - - /* Don't free strings, since I think the stabs code expects - the strings to hang around. This should be straightened - out. FIXME. */ - } - } - - if (shandle != NULL) - { - if (! finish_stab (dhandle, shandle)) - return false; - } - - return true; -} - -/* Read stabs in the symbol table. */ - -static boolean -read_symbol_stabs_debugging_info (abfd, syms, symcount, dhandle, pfound) - bfd *abfd; - asymbol **syms; - long symcount; - PTR dhandle; - boolean *pfound; -{ - PTR shandle; - asymbol **ps, **symend; - - shandle = NULL; - symend = syms + symcount; - for (ps = syms; ps < symend; ps++) - { - symbol_info i; - - bfd_get_symbol_info (abfd, *ps, &i); - - if (i.type == '-') - { - const char *s; - char *f; - - if (shandle == NULL) - { - shandle = start_stab (dhandle, abfd, false, syms, symcount); - if (shandle == NULL) - return false; - } - - *pfound = true; - - s = i.name; - f = NULL; - while (s[strlen (s) - 1] == '\\' - && ps + 1 < symend) - { - char *sc, *n; - - ++ps; - sc = xstrdup (s); - sc[strlen (sc) - 1] = '\0'; - n = concat (sc, bfd_asymbol_name (*ps), (const char *) NULL); - free (sc); - if (f != NULL) - free (f); - f = n; - s = n; - } - - save_stab (i.stab_type, i.stab_desc, i.value, s); - - if (! parse_stab (dhandle, shandle, i.stab_type, i.stab_desc, - i.value, s)) - { - stab_context (); - free_saved_stabs (); - return false; - } - - /* Don't free f, since I think the stabs code expects - strings to hang around. This should be straightened out. - FIXME. */ - } - } - - free_saved_stabs (); - - if (shandle != NULL) - { - if (! finish_stab (dhandle, shandle)) - return false; - } - - return true; -} - -/* Read IEEE debugging information. */ - -static boolean -read_ieee_debugging_info (abfd, dhandle, pfound) - bfd *abfd; - PTR dhandle; - boolean *pfound; -{ - asection *dsec; - bfd_size_type size; - bfd_byte *contents; - - /* The BFD backend puts the debugging information into a section - named .debug. */ - - dsec = bfd_get_section_by_name (abfd, ".debug"); - if (dsec == NULL) - return true; - - size = bfd_section_size (abfd, dsec); - contents = (bfd_byte *) xmalloc (size); - if (! bfd_get_section_contents (abfd, dsec, contents, 0, size)) - return false; - - if (! parse_ieee (dhandle, abfd, contents, size)) - return false; - - free (contents); - - *pfound = true; - - return true; -} - -/* Record stabs strings, so that we can give some context for errors. */ - -#define SAVE_STABS_COUNT (16) - -struct saved_stab -{ - int type; - int desc; - bfd_vma value; - char *string; -}; - -static struct saved_stab saved_stabs[SAVE_STABS_COUNT]; -static int saved_stabs_index; - -/* Save a stabs string. */ - -static void -save_stab (type, desc, value, string) - int type; - int desc; - bfd_vma value; - const char *string; -{ - if (saved_stabs[saved_stabs_index].string != NULL) - free (saved_stabs[saved_stabs_index].string); - saved_stabs[saved_stabs_index].type = type; - saved_stabs[saved_stabs_index].desc = desc; - saved_stabs[saved_stabs_index].value = value; - saved_stabs[saved_stabs_index].string = xstrdup (string); - saved_stabs_index = (saved_stabs_index + 1) % SAVE_STABS_COUNT; -} - -/* Provide context for an error. */ - -static void -stab_context () -{ - int i; - - fprintf (stderr, "Last stabs entries before error:\n"); - fprintf (stderr, "n_type n_desc n_value string\n"); - - i = saved_stabs_index; - do - { - struct saved_stab *stabp; - - stabp = saved_stabs + i; - if (stabp->string != NULL) - { - const char *s; - - s = bfd_get_stab_name (stabp->type); - if (s != NULL) - fprintf (stderr, "%-6s", s); - else if (stabp->type == 0) - fprintf (stderr, "HdrSym"); - else - fprintf (stderr, "%-6d", stabp->type); - fprintf (stderr, " %-6d ", stabp->desc); - fprintf_vma (stderr, stabp->value); - if (stabp->type != 0) - fprintf (stderr, " %s", stabp->string); - fprintf (stderr, "\n"); - } - i = (i + 1) % SAVE_STABS_COUNT; - } - while (i != saved_stabs_index); -} - -/* Free the saved stab strings. */ - -static void -free_saved_stabs () -{ - int i; - - for (i = 0; i < SAVE_STABS_COUNT; i++) - { - if (saved_stabs[i].string != NULL) - { - free (saved_stabs[i].string); - saved_stabs[i].string = NULL; - } - } - - saved_stabs_index = 0; -} diff --git a/pstack/stabs.c b/pstack/stabs.c deleted file mode 100644 index 076231d19cb..00000000000 --- a/pstack/stabs.c +++ /dev/null @@ -1,5082 +0,0 @@ -/* stabs.c -- Parse stabs debugging information - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. - Written by Ian Lance Taylor <ian@cygnus.com>. - - This file is part of GNU Binutils. - - 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. */ - -/* This file contains code which parses stabs debugging information. - The organization of this code is based on the gdb stabs reading - code. The job it does is somewhat different, because it is not - trying to identify the correct address for anything. */ - -#include <stdio.h> -#include <ctype.h> - -#include <bfd.h> -#include "bucomm.h" -#include <libiberty.h> -#include "demangle.h" -#include "debug.h" -#include "budbg.h" - -/* Meaningless definition needs by aout64.h. FIXME. */ -#define BYTES_IN_WORD 4 - -#include "aout/aout64.h" -#include "aout/stab_gnu.h" - -/* The number of predefined XCOFF types. */ - -#define XCOFF_TYPE_COUNT 34 - -/* This structure is used as a handle so that the stab parsing doesn't - need to use any static variables. */ - -struct stab_handle -{ - /* The BFD. */ - bfd *abfd; - /* True if this is stabs in sections. */ - boolean sections; - /* The symbol table. */ - asymbol **syms; - /* The number of symbols. */ - long symcount; - /* The accumulated file name string. */ - char *so_string; - /* The value of the last N_SO symbol. */ - bfd_vma so_value; - /* The value of the start of the file, so that we can handle file - relative N_LBRAC and N_RBRAC symbols. */ - bfd_vma file_start_offset; - /* The offset of the start of the function, so that we can handle - function relative N_LBRAC and N_RBRAC symbols. */ - bfd_vma function_start_offset; - /* The version number of gcc which compiled the current compilation - unit, 0 if not compiled by gcc. */ - int gcc_compiled; - /* Whether an N_OPT symbol was seen that was not generated by gcc, - so that we can detect the SunPRO compiler. */ - boolean n_opt_found; - /* The main file name. */ - char *main_filename; - /* A stack of unfinished N_BINCL files. */ - struct bincl_file *bincl_stack; - /* A list of finished N_BINCL files. */ - struct bincl_file *bincl_list; - /* Whether we are inside a function or not. */ - boolean within_function; - /* The address of the end of the function, used if we have seen an - N_FUN symbol while in a function. This is -1 if we have not seen - an N_FUN (the normal case). */ - bfd_vma function_end; - /* The depth of block nesting. */ - int block_depth; - /* List of pending variable definitions. */ - struct stab_pending_var *pending; - /* Number of files for which we have types. */ - unsigned int files; - /* Lists of types per file. */ - struct stab_types **file_types; - /* Predefined XCOFF types. */ - debug_type xcoff_types[XCOFF_TYPE_COUNT]; - /* Undefined tags. */ - struct stab_tag *tags; -}; - -/* A list of these structures is used to hold pending variable - definitions seen before the N_LBRAC of a block. */ - -struct stab_pending_var -{ - /* Next pending variable definition. */ - struct stab_pending_var *next; - /* Name. */ - const char *name; - /* Type. */ - debug_type type; - /* Kind. */ - enum debug_var_kind kind; - /* Value. */ - bfd_vma val; -}; - -/* A list of these structures is used to hold the types for a single - file. */ - -struct stab_types -{ - /* Next set of slots for this file. */ - struct stab_types *next; - /* Types indexed by type number. */ -#define STAB_TYPES_SLOTS (16) - debug_type types[STAB_TYPES_SLOTS]; -}; - -/* We keep a list of undefined tags that we encounter, so that we can - fill them in if the tag is later defined. */ - -struct stab_tag -{ - /* Next undefined tag. */ - struct stab_tag *next; - /* Tag name. */ - const char *name; - /* Type kind. */ - enum debug_type_kind kind; - /* Slot to hold real type when we discover it. If we don't, we fill - in an undefined tag type. */ - debug_type slot; - /* Indirect type we have created to point at slot. */ - debug_type type; -}; - -static char *savestring PARAMS ((const char *, int)); -static bfd_vma parse_number PARAMS ((const char **, boolean *)); -static void bad_stab PARAMS ((const char *)); -static void warn_stab PARAMS ((const char *, const char *)); -static boolean parse_stab_string - PARAMS ((PTR, struct stab_handle *, int, int, bfd_vma, const char *)); -static debug_type parse_stab_type - PARAMS ((PTR, struct stab_handle *, const char *, const char **, - debug_type **)); -static boolean parse_stab_type_number - PARAMS ((const char **, int *)); -static debug_type parse_stab_range_type - PARAMS ((PTR, struct stab_handle *, const char *, const char **, - const int *)); -static debug_type parse_stab_sun_builtin_type PARAMS ((PTR, const char **)); -static debug_type parse_stab_sun_floating_type - PARAMS ((PTR, const char **)); -static debug_type parse_stab_enum_type PARAMS ((PTR, const char **)); -static debug_type parse_stab_struct_type - PARAMS ((PTR, struct stab_handle *, const char *, const char **, boolean, - const int *)); -static boolean parse_stab_baseclasses - PARAMS ((PTR, struct stab_handle *, const char **, debug_baseclass **)); -static boolean parse_stab_struct_fields - PARAMS ((PTR, struct stab_handle *, const char **, debug_field **, - boolean *)); -static boolean parse_stab_cpp_abbrev - PARAMS ((PTR, struct stab_handle *, const char **, debug_field *)); -static boolean parse_stab_one_struct_field - PARAMS ((PTR, struct stab_handle *, const char **, const char *, - debug_field *, boolean *)); -static boolean parse_stab_members - PARAMS ((PTR, struct stab_handle *, const char *, const char **, - const int *, debug_method **)); -static debug_type parse_stab_argtypes - PARAMS ((PTR, struct stab_handle *, debug_type, const char *, const char *, - debug_type, const char *, boolean, boolean, const char **)); -static boolean parse_stab_tilde_field - PARAMS ((PTR, struct stab_handle *, const char **, const int *, - debug_type *, boolean *)); -static debug_type parse_stab_array_type - PARAMS ((PTR, struct stab_handle *, const char **, boolean)); -static void push_bincl PARAMS ((struct stab_handle *, const char *, bfd_vma)); -static const char *pop_bincl PARAMS ((struct stab_handle *)); -static boolean find_excl - PARAMS ((struct stab_handle *, const char *, bfd_vma)); -static boolean stab_record_variable - PARAMS ((PTR, struct stab_handle *, const char *, debug_type, - enum debug_var_kind, bfd_vma)); -static boolean stab_emit_pending_vars PARAMS ((PTR, struct stab_handle *)); -static debug_type *stab_find_slot - PARAMS ((struct stab_handle *, const int *)); -static debug_type stab_find_type - PARAMS ((PTR, struct stab_handle *, const int *)); -static boolean stab_record_type - PARAMS ((PTR, struct stab_handle *, const int *, debug_type)); -static debug_type stab_xcoff_builtin_type - PARAMS ((PTR, struct stab_handle *, int)); -static debug_type stab_find_tagged_type - PARAMS ((PTR, struct stab_handle *, const char *, int, - enum debug_type_kind)); -static debug_type *stab_demangle_argtypes - PARAMS ((PTR, struct stab_handle *, const char *, boolean *)); - -/* Save a string in memory. */ - -static char * -savestring (start, len) - const char *start; - int len; -{ - char *ret; - - ret = (char *) xmalloc (len + 1); - memcpy (ret, start, len); - ret[len] = '\0'; - return ret; -} - -/* Read a number from a string. */ - -static bfd_vma -parse_number (pp, poverflow) - const char **pp; - boolean *poverflow; -{ - unsigned long ul; - const char *orig; - - if (poverflow != NULL) - *poverflow = false; - - orig = *pp; - - errno = 0; - ul = strtoul (*pp, (char **) pp, 0); - if (ul + 1 != 0 || errno == 0) - return (bfd_vma) ul; - - /* Note that even though strtoul overflowed, it should have set *pp - to the end of the number, which is where we want it. */ - - if (sizeof (bfd_vma) > sizeof (unsigned long)) - { - const char *p; - boolean neg; - int base; - bfd_vma over, lastdig; - boolean overflow; - bfd_vma v; - - /* Our own version of strtoul, for a bfd_vma. */ - - p = orig; - - neg = false; - if (*p == '+') - ++p; - else if (*p == '-') - { - neg = true; - ++p; - } - - base = 10; - if (*p == '0') - { - if (p[1] == 'x' || p[1] == 'X') - { - base = 16; - p += 2; - } - else - { - base = 8; - ++p; - } - } - - over = ((bfd_vma) (bfd_signed_vma) -1) / (bfd_vma) base; - lastdig = ((bfd_vma) (bfd_signed_vma) -1) % (bfd_vma) base; - - overflow = false; - v = 0; - while (1) - { - int d; - - d = *p++; - if (isdigit ((unsigned char) d)) - d -= '0'; - else if (isupper ((unsigned char) d)) - d -= 'A'; - else if (islower ((unsigned char) d)) - d -= 'a'; - else - break; - - if (d >= base) - break; - - if (v > over || (v == over && (bfd_vma) d > lastdig)) - { - overflow = true; - break; - } - } - - if (! overflow) - { - if (neg) - v = - v; - return v; - } - } - - /* If we get here, the number is too large to represent in a - bfd_vma. */ - - if (poverflow != NULL) - *poverflow = true; - else - warn_stab (orig, "numeric overflow"); - - return 0; -} - -/* Give an error for a bad stab string. */ - -static void -bad_stab (p) - const char *p; -{ - fprintf (stderr, "Bad stab: %s\n", p); -} - -/* Warn about something in a stab string. */ - -static void -warn_stab (p, err) - const char *p; - const char *err; -{ - fprintf (stderr, "Warning: %s: %s\n", err, p); -} - -/* Create a handle to parse stabs symbols with. */ - -/*ARGSUSED*/ -PTR -start_stab (dhandle, abfd, sections, syms, symcount) - PTR dhandle; - bfd *abfd; - boolean sections; - asymbol **syms; - long symcount; -{ - struct stab_handle *ret; - - ret = (struct stab_handle *) xmalloc (sizeof *ret); - memset (ret, 0, sizeof *ret); - ret->abfd = abfd; - ret->sections = sections; - ret->syms = syms; - ret->symcount = symcount; - ret->files = 1; - ret->file_types = (struct stab_types **) xmalloc (sizeof *ret->file_types); - ret->file_types[0] = NULL; - ret->function_end = (bfd_vma) -1; - return (PTR) ret; -} - -/* When we have processed all the stabs information, we need to go - through and fill in all the undefined tags. */ - -boolean -finish_stab (dhandle, handle) - PTR dhandle; - PTR handle; -{ - struct stab_handle *info = (struct stab_handle *) handle; - struct stab_tag *st; - - if (info->within_function) - { - if (! stab_emit_pending_vars (dhandle, info) - || ! debug_end_function (dhandle, info->function_end)) - return false; - info->within_function = false; - info->function_end = (bfd_vma) -1; - } - - for (st = info->tags; st != NULL; st = st->next) - { - enum debug_type_kind kind; - - kind = st->kind; - if (kind == DEBUG_KIND_ILLEGAL) - kind = DEBUG_KIND_STRUCT; - st->slot = debug_make_undefined_tagged_type (dhandle, st->name, kind); - if (st->slot == DEBUG_TYPE_NULL) - return false; - } - - return true; -} - -/* Handle a single stabs symbol. */ - -boolean -parse_stab (dhandle, handle, type, desc, value, string) - PTR dhandle; - PTR handle; - int type; - int desc; - bfd_vma value; - const char *string; -{ - struct stab_handle *info = (struct stab_handle *) handle; - - /* gcc will emit two N_SO strings per compilation unit, one for the - directory name and one for the file name. We just collect N_SO - strings as we see them, and start the new compilation unit when - we see a non N_SO symbol. */ - if (info->so_string != NULL - && (type != N_SO || *string == '\0' || value != info->so_value)) - { - if (! debug_set_filename (dhandle, info->so_string)) - return false; - info->main_filename = info->so_string; - - info->gcc_compiled = 0; - info->n_opt_found = false; - - /* Generally, for stabs in the symbol table, the N_LBRAC and - N_RBRAC symbols are relative to the N_SO symbol value. */ - if (! info->sections) - info->file_start_offset = info->so_value; - - /* We need to reset the mapping from type numbers to types. We - can't free the old mapping, because of the use of - debug_make_indirect_type. */ - info->files = 1; - info->file_types = ((struct stab_types **) - xmalloc (sizeof *info->file_types)); - info->file_types[0] = NULL; - - info->so_string = NULL; - - /* Now process whatever type we just got. */ - } - - switch (type) - { - case N_FN: - case N_FN_SEQ: - break; - - case N_LBRAC: - /* Ignore extra outermost context from SunPRO cc and acc. */ - if (info->n_opt_found && desc == 1) - break; - - if (! info->within_function) - { - fprintf (stderr, "N_LBRAC not within function\n"); - return false; - } - - /* Start an inner lexical block. */ - if (! debug_start_block (dhandle, - (value - + info->file_start_offset - + info->function_start_offset))) - return false; - - /* Emit any pending variable definitions. */ - if (! stab_emit_pending_vars (dhandle, info)) - return false; - - ++info->block_depth; - break; - - case N_RBRAC: - /* Ignore extra outermost context from SunPRO cc and acc. */ - if (info->n_opt_found && desc == 1) - break; - - /* We shouldn't have any pending variable definitions here, but, - if we do, we probably need to emit them before closing the - block. */ - if (! stab_emit_pending_vars (dhandle, info)) - return false; - - /* End an inner lexical block. */ - if (! debug_end_block (dhandle, - (value - + info->file_start_offset - + info->function_start_offset))) - return false; - - --info->block_depth; - if (info->block_depth < 0) - { - fprintf (stderr, "Too many N_RBRACs\n"); - return false; - } - break; - - case N_SO: - /* This always ends a function. */ - if (info->within_function) - { - bfd_vma endval; - - endval = value; - if (*string != '\0' - && info->function_end != (bfd_vma) -1 - && info->function_end < endval) - endval = info->function_end; - if (! stab_emit_pending_vars (dhandle, info) - || ! debug_end_function (dhandle, endval)) - return false; - info->within_function = false; - info->function_end = (bfd_vma) -1; - } - - /* An empty string is emitted by gcc at the end of a compilation - unit. */ - if (*string == '\0') - return true; - - /* Just accumulate strings until we see a non N_SO symbol. If - the string starts with '/', we discard the previously - accumulated strings. */ - if (info->so_string == NULL) - info->so_string = xstrdup (string); - else - { - char *f; - - f = info->so_string; - if (*string == '/') - info->so_string = xstrdup (string); - else - info->so_string = concat (info->so_string, string, - (const char *) NULL); - free (f); - } - - info->so_value = value; - - break; - - case N_SOL: - /* Start an include file. */ - if (! debug_start_source (dhandle, string)) - return false; - break; - - case N_BINCL: - /* Start an include file which may be replaced. */ - push_bincl (info, string, value); - if (! debug_start_source (dhandle, string)) - return false; - break; - - case N_EINCL: - /* End an N_BINCL include. */ - if (! debug_start_source (dhandle, pop_bincl (info))) - return false; - break; - - case N_EXCL: - /* This is a duplicate of a header file named by N_BINCL which - was eliminated by the linker. */ - if (! find_excl (info, string, value)) - return false; - break; - - case N_SLINE: - if (! debug_record_line (dhandle, desc, - value + info->function_start_offset)) - return false; - break; - - case N_BCOMM: - if (! debug_start_common_block (dhandle, string)) - return false; - break; - - case N_ECOMM: - if (! debug_end_common_block (dhandle, string)) - return false; - break; - - case N_FUN: - if (*string == '\0') - { - if (info->within_function) - { - /* This always marks the end of a function; we don't - need to worry about info->function_end. */ - if (info->sections) - value += info->function_start_offset; - if (! stab_emit_pending_vars (dhandle, info) - || ! debug_end_function (dhandle, value)) - return false; - info->within_function = false; - info->function_end = (bfd_vma) -1; - } - break; - } - - /* A const static symbol in the .text section will have an N_FUN - entry. We need to use these to mark the end of the function, - in case we are looking at gcc output before it was changed to - always emit an empty N_FUN. We can't call debug_end_function - here, because it might be a local static symbol. */ - if (info->within_function - && (info->function_end == (bfd_vma) -1 - || value < info->function_end)) - info->function_end = value; - - /* Fall through. */ - /* FIXME: gdb checks the string for N_STSYM, N_LCSYM or N_ROSYM - symbols, and if it does not start with :S, gdb relocates the - value to the start of the section. gcc always seems to use - :S, so we don't worry about this. */ - /* Fall through. */ - default: - { - const char *colon; - - colon = strchr (string, ':'); - if (colon != NULL - && (colon[1] == 'f' || colon[1] == 'F')) - { - if (info->within_function) - { - bfd_vma endval; - - endval = value; - if (info->function_end != (bfd_vma) -1 - && info->function_end < endval) - endval = info->function_end; - if (! stab_emit_pending_vars (dhandle, info) - || ! debug_end_function (dhandle, endval)) - return false; - info->function_end = (bfd_vma) -1; - } - /* For stabs in sections, line numbers and block addresses - are offsets from the start of the function. */ - if (info->sections) - info->function_start_offset = value; - info->within_function = true; - } - - if (! parse_stab_string (dhandle, info, type, desc, value, string)) - return false; - } - break; - - case N_OPT: - if (string != NULL && strcmp (string, "gcc2_compiled.") == 0) - info->gcc_compiled = 2; - else if (string != NULL && strcmp (string, "gcc_compiled.") == 0) - info->gcc_compiled = 1; - else - info->n_opt_found = true; - break; - - case N_OBJ: - case N_ENDM: - case N_MAIN: - break; - } - - return true; -} - -/* Parse the stabs string. */ - -static boolean -parse_stab_string (dhandle, info, stabtype, desc, value, string) - PTR dhandle; - struct stab_handle *info; - int stabtype; - int desc; - bfd_vma value; - const char *string; -{ - const char *p; - char *name; - int type; - debug_type dtype; - boolean synonym; - unsigned int lineno; - debug_type *slot; - - p = strchr (string, ':'); - if (p == NULL) - return true; - - while (p[1] == ':') - { - p += 2; - p = strchr (p, ':'); - if (p == NULL) - { - bad_stab (string); - return false; - } - } - - /* GCC 2.x puts the line number in desc. SunOS apparently puts in - the number of bytes occupied by a type or object, which we - ignore. */ - if (info->gcc_compiled >= 2) - lineno = desc; - else - lineno = 0; - - /* FIXME: Sometimes the special C++ names start with '.'. */ - name = NULL; - if (string[0] == '$') - { - switch (string[1]) - { - case 't': - name = "this"; - break; - case 'v': - /* Was: name = "vptr"; */ - break; - case 'e': - name = "eh_throw"; - break; - case '_': - /* This was an anonymous type that was never fixed up. */ - break; - case 'X': - /* SunPRO (3.0 at least) static variable encoding. */ - break; - default: - warn_stab (string, "unknown C++ encoded name"); - break; - } - } - - if (name == NULL) - { - if (p == string || (string[0] == ' ' && p == string + 1)) - name = NULL; - else - name = savestring (string, p - string); - } - - ++p; - if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-') - type = 'l'; - else - type = *p++; - - switch (type) - { - case 'c': - /* c is a special case, not followed by a type-number. - SYMBOL:c=iVALUE for an integer constant symbol. - SYMBOL:c=rVALUE for a floating constant symbol. - SYMBOL:c=eTYPE,INTVALUE for an enum constant symbol. - e.g. "b:c=e6,0" for "const b = blob1" - (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */ - if (*p != '=') - { - bad_stab (string); - return false; - } - ++p; - switch (*p++) - { - case 'r': - /* Floating point constant. */ - if (! debug_record_float_const (dhandle, name, atof (p))) - return false; - break; - case 'i': - /* Integer constant. */ - /* Defining integer constants this way is kind of silly, - since 'e' constants allows the compiler to give not only - the value, but the type as well. C has at least int, - long, unsigned int, and long long as constant types; - other languages probably should have at least unsigned as - well as signed constants. */ - if (! debug_record_int_const (dhandle, name, atoi (p))) - return false; - break; - case 'e': - /* SYMBOL:c=eTYPE,INTVALUE for a constant symbol whose value - can be represented as integral. - e.g. "b:c=e6,0" for "const b = blob1" - (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */ - dtype = parse_stab_type (dhandle, info, (const char *) NULL, - &p, (debug_type **) NULL); - if (dtype == DEBUG_TYPE_NULL) - return false; - if (*p != ',') - { - bad_stab (string); - return false; - } - if (! debug_record_typed_const (dhandle, name, dtype, atoi (p))) - return false; - break; - default: - bad_stab (string); - return false; - } - - break; - - case 'C': - /* The name of a caught exception. */ - dtype = parse_stab_type (dhandle, info, (const char *) NULL, - &p, (debug_type **) NULL); - if (dtype == DEBUG_TYPE_NULL) - return false; - if (! debug_record_label (dhandle, name, dtype, value)) - return false; - break; - - case 'f': - case 'F': - /* A function definition. */ - dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, - (debug_type **) NULL); - if (dtype == DEBUG_TYPE_NULL) - return false; - if (! debug_record_function (dhandle, name, dtype, type == 'F', value)) - return false; - - /* Sun acc puts declared types of arguments here. We don't care - about their actual types (FIXME -- we should remember the whole - function prototype), but the list may define some new types - that we have to remember, so we must scan it now. */ - while (*p == ';') - { - ++p; - if (parse_stab_type (dhandle, info, (const char *) NULL, &p, - (debug_type **) NULL) - == DEBUG_TYPE_NULL) - return false; - } - - break; - - case 'G': - { - char leading; - long c; - asymbol **ps; - - /* A global symbol. The value must be extracted from the - symbol table. */ - dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, - (debug_type **) NULL); - if (dtype == DEBUG_TYPE_NULL) - return false; - leading = bfd_get_symbol_leading_char (info->abfd); - for (c = info->symcount, ps = info->syms; c > 0; --c, ++ps) - { - const char *n; - - n = bfd_asymbol_name (*ps); - if (leading != '\0' && *n == leading) - ++n; - if (*n == *name && strcmp (n, name) == 0) - break; - } - if (c > 0) - value = bfd_asymbol_value (*ps); - if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL, - value)) - return false; - } - break; - - /* This case is faked by a conditional above, when there is no - code letter in the dbx data. Dbx data never actually - contains 'l'. */ - case 'l': - case 's': - dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, - (debug_type **) NULL); - if (dtype == DEBUG_TYPE_NULL) - return false; - if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL, - value)) - return false; - break; - - case 'p': - /* A function parameter. */ - if (*p != 'F') - dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, - (debug_type **) NULL); - else - { - /* pF is a two-letter code that means a function parameter in - Fortran. The type-number specifies the type of the return - value. Translate it into a pointer-to-function type. */ - ++p; - dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, - (debug_type **) NULL); - if (dtype != DEBUG_TYPE_NULL) - { - debug_type ftype; - - ftype = debug_make_function_type (dhandle, dtype, - (debug_type *) NULL, false); - dtype = debug_make_pointer_type (dhandle, ftype); - } - } - if (dtype == DEBUG_TYPE_NULL) - return false; - if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_STACK, - value)) - return false; - - /* FIXME: At this point gdb considers rearranging the parameter - address on a big endian machine if it is smaller than an int. - We have no way to do that, since we don't really know much - about the target. */ - - break; - - case 'P': - if (stabtype == N_FUN) - { - /* Prototype of a function referenced by this file. */ - while (*p == ';') - { - ++p; - if (parse_stab_type (dhandle, info, (const char *) NULL, &p, - (debug_type **) NULL) - == DEBUG_TYPE_NULL) - return false; - } - break; - } - /* Fall through. */ - case 'R': - /* Parameter which is in a register. */ - dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, - (debug_type **) NULL); - if (dtype == DEBUG_TYPE_NULL) - return false; - if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REG, - value)) - return false; - break; - - case 'r': - /* Register variable (either global or local). */ - dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, - (debug_type **) NULL); - if (dtype == DEBUG_TYPE_NULL) - return false; - if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_REGISTER, - value)) - return false; - - /* FIXME: At this point gdb checks to combine pairs of 'p' and - 'r' stabs into a single 'P' stab. */ - - break; - - case 'S': - /* Static symbol at top level of file */ - dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, - (debug_type **) NULL); - if (dtype == DEBUG_TYPE_NULL) - return false; - if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_STATIC, - value)) - return false; - break; - - case 't': - /* A typedef. */ - dtype = parse_stab_type (dhandle, info, name, &p, &slot); - if (dtype == DEBUG_TYPE_NULL) - return false; - if (name == NULL) - { - /* A nameless type. Nothing to do. */ - return true; - } - - dtype = debug_name_type (dhandle, name, dtype); - if (dtype == DEBUG_TYPE_NULL) - return false; - - if (slot != NULL) - *slot = dtype; - - break; - - case 'T': - /* Struct, union, or enum tag. For GNU C++, this can be be followed - by 't' which means we are typedef'ing it as well. */ - if (*p != 't') - { - synonym = false; - /* FIXME: gdb sets synonym to true if the current language - is C++. */ - } - else - { - synonym = true; - ++p; - } - - dtype = parse_stab_type (dhandle, info, name, &p, &slot); - if (dtype == DEBUG_TYPE_NULL) - return false; - if (name == NULL) - return true; - - dtype = debug_tag_type (dhandle, name, dtype); - if (dtype == DEBUG_TYPE_NULL) - return false; - if (slot != NULL) - *slot = dtype; - - /* See if we have a cross reference to this tag which we can now - fill in. */ - { - register struct stab_tag **pst; - - for (pst = &info->tags; *pst != NULL; pst = &(*pst)->next) - { - if ((*pst)->name[0] == name[0] - && strcmp ((*pst)->name, name) == 0) - { - (*pst)->slot = dtype; - *pst = (*pst)->next; - break; - } - } - } - - if (synonym) - { - dtype = debug_name_type (dhandle, name, dtype); - if (dtype == DEBUG_TYPE_NULL) - return false; - - if (slot != NULL) - *slot = dtype; - } - - break; - - case 'V': - /* Static symbol of local scope */ - dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, - (debug_type **) NULL); - if (dtype == DEBUG_TYPE_NULL) - return false; - /* FIXME: gdb checks os9k_stabs here. */ - if (! stab_record_variable (dhandle, info, name, dtype, - DEBUG_LOCAL_STATIC, value)) - return false; - break; - - case 'v': - /* Reference parameter. */ - dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, - (debug_type **) NULL); - if (dtype == DEBUG_TYPE_NULL) - return false; - if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REFERENCE, - value)) - return false; - break; - - case 'a': - /* Reference parameter which is in a register. */ - dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, - (debug_type **) NULL); - if (dtype == DEBUG_TYPE_NULL) - return false; - if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REF_REG, - value)) - return false; - break; - - case 'X': - /* This is used by Sun FORTRAN for "function result value". - Sun claims ("dbx and dbxtool interfaces", 2nd ed) - that Pascal uses it too, but when I tried it Pascal used - "x:3" (local symbol) instead. */ - dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, - (debug_type **) NULL); - if (dtype == DEBUG_TYPE_NULL) - return false; - if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL, - value)) - return false; - break; - - default: - bad_stab (string); - return false; - } - - /* FIXME: gdb converts structure values to structure pointers in a - couple of cases, depending upon the target. */ - - return true; -} - -/* Parse a stabs type. The typename argument is non-NULL if this is a - typedef or a tag definition. The pp argument points to the stab - string, and is updated. The slotp argument points to a place to - store the slot used if the type is being defined. */ - -static debug_type -parse_stab_type (dhandle, info, typename, pp, slotp) - PTR dhandle; - struct stab_handle *info; - const char *typename; - const char **pp; - debug_type **slotp; -{ - const char *orig; - int typenums[2]; - int size; - boolean stringp; - int descriptor; - debug_type dtype; - - if (slotp != NULL) - *slotp = NULL; - - orig = *pp; - - size = -1; - stringp = false; - - /* Read type number if present. The type number may be omitted. - for instance in a two-dimensional array declared with type - "ar1;1;10;ar1;1;10;4". */ - if (! isdigit ((unsigned char) **pp) && **pp != '(' && **pp != '-') - { - /* 'typenums=' not present, type is anonymous. Read and return - the definition, but don't put it in the type vector. */ - typenums[0] = typenums[1] = -1; - } - else - { - if (! parse_stab_type_number (pp, typenums)) - return DEBUG_TYPE_NULL; - - if (**pp != '=') - { - /* Type is not being defined here. Either it already - exists, or this is a forward reference to it. */ - return stab_find_type (dhandle, info, typenums); - } - - /* Only set the slot if the type is being defined. This means - that the mapping from type numbers to types will only record - the name of the typedef which defines a type. If we don't do - this, then something like - typedef int foo; - int i; - will record that i is of type foo. Unfortunately, stabs - information is ambiguous about variable types. For this code, - typedef int foo; - int i; - foo j; - the stabs information records both i and j as having the same - type. This could be fixed by patching the compiler. */ - if (slotp != NULL && typenums[0] >= 0 && typenums[1] >= 0) - *slotp = stab_find_slot (info, typenums); - - /* Type is being defined here. */ - /* Skip the '='. */ - ++*pp; - - while (**pp == '@') - { - const char *p = *pp + 1; - const char *attr; - - if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-') - { - /* Member type. */ - break; - } - - /* Type attributes. */ - attr = p; - - for (; *p != ';'; ++p) - { - if (*p == '\0') - { - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - } - *pp = p + 1; - - switch (*attr) - { - case 's': - size = atoi (attr + 1); - if (size <= 0) - size = -1; - break; - - case 'S': - stringp = true; - break; - - default: - /* Ignore unrecognized type attributes, so future - compilers can invent new ones. */ - break; - } - } - } - - descriptor = **pp; - ++*pp; - - switch (descriptor) - { - case 'x': - { - enum debug_type_kind code; - const char *q1, *q2, *p; - - /* A cross reference to another type. */ - - switch (**pp) - { - case 's': - code = DEBUG_KIND_STRUCT; - break; - case 'u': - code = DEBUG_KIND_UNION; - break; - case 'e': - code = DEBUG_KIND_ENUM; - break; - default: - /* Complain and keep going, so compilers can invent new - cross-reference types. */ - warn_stab (orig, "unrecognized cross reference type"); - code = DEBUG_KIND_STRUCT; - break; - } - ++*pp; - - q1 = strchr (*pp, '<'); - p = strchr (*pp, ':'); - if (p == NULL) - { - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - while (q1 != NULL && p > q1 && p[1] == ':') - { - q2 = strchr (q1, '>'); - if (q2 == NULL || q2 < p) - break; - p += 2; - p = strchr (p, ':'); - if (p == NULL) - { - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - } - - dtype = stab_find_tagged_type (dhandle, info, *pp, p - *pp, code); - - *pp = p + 1; - } - break; - - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '(': - { - const char *hold; - int xtypenums[2]; - - /* This type is defined as another type. */ - - (*pp)--; - hold = *pp; - - /* Peek ahead at the number to detect void. */ - if (! parse_stab_type_number (pp, xtypenums)) - return DEBUG_TYPE_NULL; - - if (typenums[0] == xtypenums[0] && typenums[1] == xtypenums[1]) - { - /* This type is being defined as itself, which means that - it is void. */ - dtype = debug_make_void_type (dhandle); - } - else - { - *pp = hold; - - /* Go back to the number and have parse_stab_type get it. - This means that we can deal with something like - t(1,2)=(3,4)=... which the Lucid compiler uses. */ - dtype = parse_stab_type (dhandle, info, (const char *) NULL, - pp, (debug_type **) NULL); - if (dtype == DEBUG_TYPE_NULL) - return DEBUG_TYPE_NULL; - } - - if (typenums[0] != -1) - { - if (! stab_record_type (dhandle, info, typenums, dtype)) - return DEBUG_TYPE_NULL; - } - - break; - } - - case '*': - dtype = debug_make_pointer_type (dhandle, - parse_stab_type (dhandle, info, - (const char *) NULL, - pp, - (debug_type **) NULL)); - break; - - case '&': - /* Reference to another type. */ - dtype = (debug_make_reference_type - (dhandle, - parse_stab_type (dhandle, info, (const char *) NULL, pp, - (debug_type **) NULL))); - break; - - case 'f': - /* Function returning another type. */ - /* FIXME: gdb checks os9k_stabs here. */ - dtype = (debug_make_function_type - (dhandle, - parse_stab_type (dhandle, info, (const char *) NULL, pp, - (debug_type **) NULL), - (debug_type *) NULL, false)); - break; - - case 'k': - /* Const qualifier on some type (Sun). */ - /* FIXME: gdb accepts 'c' here if os9k_stabs. */ - dtype = debug_make_const_type (dhandle, - parse_stab_type (dhandle, info, - (const char *) NULL, - pp, - (debug_type **) NULL)); - break; - - case 'B': - /* Volatile qual on some type (Sun). */ - /* FIXME: gdb accepts 'i' here if os9k_stabs. */ - dtype = (debug_make_volatile_type - (dhandle, - parse_stab_type (dhandle, info, (const char *) NULL, pp, - (debug_type **) NULL))); - break; - - case '@': - /* Offset (class & variable) type. This is used for a pointer - relative to an object. */ - { - debug_type domain; - debug_type memtype; - - /* Member type. */ - - domain = parse_stab_type (dhandle, info, (const char *) NULL, pp, - (debug_type **) NULL); - if (domain == DEBUG_TYPE_NULL) - return DEBUG_TYPE_NULL; - - if (**pp != ',') - { - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - ++*pp; - - memtype = parse_stab_type (dhandle, info, (const char *) NULL, pp, - (debug_type **) NULL); - if (memtype == DEBUG_TYPE_NULL) - return DEBUG_TYPE_NULL; - - dtype = debug_make_offset_type (dhandle, domain, memtype); - } - break; - - case '#': - /* Method (class & fn) type. */ - if (**pp == '#') - { - debug_type return_type; - - ++*pp; - return_type = parse_stab_type (dhandle, info, (const char *) NULL, - pp, (debug_type **) NULL); - if (return_type == DEBUG_TYPE_NULL) - return DEBUG_TYPE_NULL; - if (**pp != ';') - { - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - ++*pp; - dtype = debug_make_method_type (dhandle, return_type, - DEBUG_TYPE_NULL, - (debug_type *) NULL, false); - } - else - { - debug_type domain; - debug_type return_type; - debug_type *args; - unsigned int n; - unsigned int alloc; - boolean varargs; - - domain = parse_stab_type (dhandle, info, (const char *) NULL, - pp, (debug_type **) NULL); - if (domain == DEBUG_TYPE_NULL) - return DEBUG_TYPE_NULL; - - if (**pp != ',') - { - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - ++*pp; - - return_type = parse_stab_type (dhandle, info, (const char *) NULL, - pp, (debug_type **) NULL); - if (return_type == DEBUG_TYPE_NULL) - return DEBUG_TYPE_NULL; - - alloc = 10; - args = (debug_type *) xmalloc (alloc * sizeof *args); - n = 0; - while (**pp != ';') - { - if (**pp != ',') - { - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - ++*pp; - - if (n + 1 >= alloc) - { - alloc += 10; - args = ((debug_type *) - xrealloc ((PTR) args, alloc * sizeof *args)); - } - - args[n] = parse_stab_type (dhandle, info, (const char *) NULL, - pp, (debug_type **) NULL); - if (args[n] == DEBUG_TYPE_NULL) - return DEBUG_TYPE_NULL; - ++n; - } - ++*pp; - - /* If the last type is not void, then this function takes a - variable number of arguments. Otherwise, we must strip - the void type. */ - if (n == 0 - || debug_get_type_kind (dhandle, args[n - 1]) != DEBUG_KIND_VOID) - varargs = true; - else - { - --n; - varargs = false; - } - - args[n] = DEBUG_TYPE_NULL; - - dtype = debug_make_method_type (dhandle, return_type, domain, args, - varargs); - } - break; - - case 'r': - /* Range type. */ - dtype = parse_stab_range_type (dhandle, info, typename, pp, typenums); - break; - - case 'b': - /* FIXME: gdb checks os9k_stabs here. */ - /* Sun ACC builtin int type. */ - dtype = parse_stab_sun_builtin_type (dhandle, pp); - break; - - case 'R': - /* Sun ACC builtin float type. */ - dtype = parse_stab_sun_floating_type (dhandle, pp); - break; - - case 'e': - /* Enumeration type. */ - dtype = parse_stab_enum_type (dhandle, pp); - break; - - case 's': - case 'u': - /* Struct or union type. */ - dtype = parse_stab_struct_type (dhandle, info, typename, pp, - descriptor == 's', typenums); - break; - - case 'a': - /* Array type. */ - if (**pp != 'r') - { - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - ++*pp; - - dtype = parse_stab_array_type (dhandle, info, pp, stringp); - break; - - case 'S': - dtype = debug_make_set_type (dhandle, - parse_stab_type (dhandle, info, - (const char *) NULL, - pp, - (debug_type **) NULL), - stringp); - break; - - default: - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - - if (dtype == DEBUG_TYPE_NULL) - return DEBUG_TYPE_NULL; - - if (typenums[0] != -1) - { - if (! stab_record_type (dhandle, info, typenums, dtype)) - return DEBUG_TYPE_NULL; - } - - if (size != -1) - { - if (! debug_record_type_size (dhandle, dtype, (unsigned int) size)) - return DEBUG_TYPE_NULL; - } - - return dtype; -} - -/* Read a number by which a type is referred to in dbx data, or - perhaps read a pair (FILENUM, TYPENUM) in parentheses. Just a - single number N is equivalent to (0,N). Return the two numbers by - storing them in the vector TYPENUMS. */ - -static boolean -parse_stab_type_number (pp, typenums) - const char **pp; - int *typenums; -{ - const char *orig; - - orig = *pp; - - if (**pp != '(') - { - typenums[0] = 0; - typenums[1] = (int) parse_number (pp, (boolean *) NULL); - } - else - { - ++*pp; - typenums[0] = (int) parse_number (pp, (boolean *) NULL); - if (**pp != ',') - { - bad_stab (orig); - return false; - } - ++*pp; - typenums[1] = (int) parse_number (pp, (boolean *) NULL); - if (**pp != ')') - { - bad_stab (orig); - return false; - } - ++*pp; - } - - return true; -} - -/* Parse a range type. */ - -static debug_type -parse_stab_range_type (dhandle, info, typename, pp, typenums) - PTR dhandle; - struct stab_handle *info; - const char *typename; - const char **pp; - const int *typenums; -{ - const char *orig; - int rangenums[2]; - boolean self_subrange; - debug_type index_type; - const char *s2, *s3; - bfd_signed_vma n2, n3; - boolean ov2, ov3; - - orig = *pp; - - index_type = DEBUG_TYPE_NULL; - - /* First comes a type we are a subrange of. - In C it is usually 0, 1 or the type being defined. */ - if (! parse_stab_type_number (pp, rangenums)) - return DEBUG_TYPE_NULL; - - self_subrange = (rangenums[0] == typenums[0] - && rangenums[1] == typenums[1]); - - if (**pp == '=') - { - *pp = orig; - index_type = parse_stab_type (dhandle, info, (const char *) NULL, - pp, (debug_type **) NULL); - if (index_type == DEBUG_TYPE_NULL) - return DEBUG_TYPE_NULL; - } - - if (**pp == ';') - ++*pp; - - /* The remaining two operands are usually lower and upper bounds of - the range. But in some special cases they mean something else. */ - s2 = *pp; - n2 = parse_number (pp, &ov2); - if (**pp != ';') - { - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - ++*pp; - - s3 = *pp; - n3 = parse_number (pp, &ov3); - if (**pp != ';') - { - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - ++*pp; - - if (ov2 || ov3) - { - /* gcc will emit range stabs for long long types. Handle this - as a special case. FIXME: This needs to be more general. */ -#define LLLOW "01000000000000000000000;" -#define LLHIGH "0777777777777777777777;" -#define ULLHIGH "01777777777777777777777;" - if (index_type == DEBUG_TYPE_NULL) - { - if (strncmp (s2, LLLOW, sizeof LLLOW - 1) == 0 - && strncmp (s3, LLHIGH, sizeof LLHIGH - 1) == 0) - return debug_make_int_type (dhandle, 8, false); - if (! ov2 - && n2 == 0 - && strncmp (s3, ULLHIGH, sizeof ULLHIGH - 1) == 0) - return debug_make_int_type (dhandle, 8, true); - } - - warn_stab (orig, "numeric overflow"); - } - - if (index_type == DEBUG_TYPE_NULL) - { - /* A type defined as a subrange of itself, with both bounds 0, - is void. */ - if (self_subrange && n2 == 0 && n3 == 0) - return debug_make_void_type (dhandle); - - /* A type defined as a subrange of itself, with n2 positive and - n3 zero, is a complex type, and n2 is the number of bytes. */ - if (self_subrange && n3 == 0 && n2 > 0) - return debug_make_complex_type (dhandle, n2); - - /* If n3 is zero and n2 is positive, this is a floating point - type, and n2 is the number of bytes. */ - if (n3 == 0 && n2 > 0) - return debug_make_float_type (dhandle, n2); - - /* If the upper bound is -1, this is an unsigned int. */ - if (n2 == 0 && n3 == -1) - { - /* When gcc is used with -gstabs, but not -gstabs+, it will emit - long long int:t6=r1;0;-1; - long long unsigned int:t7=r1;0;-1; - We hack here to handle this reasonably. */ - if (typename != NULL) - { - if (strcmp (typename, "long long int") == 0) - return debug_make_int_type (dhandle, 8, false); - else if (strcmp (typename, "long long unsigned int") == 0) - return debug_make_int_type (dhandle, 8, true); - } - /* FIXME: The size here really depends upon the target. */ - return debug_make_int_type (dhandle, 4, true); - } - - /* A range of 0 to 127 is char. */ - if (self_subrange && n2 == 0 && n3 == 127) - return debug_make_int_type (dhandle, 1, false); - - /* FIXME: gdb checks for the language CHILL here. */ - - if (n2 == 0) - { - if (n3 < 0) - return debug_make_int_type (dhandle, - n3, true); - else if (n3 == 0xff) - return debug_make_int_type (dhandle, 1, true); - else if (n3 == 0xffff) - return debug_make_int_type (dhandle, 2, true); - /* -1 is used for the upper bound of (4 byte) "unsigned int" - and "unsigned long", and we already checked for that, so - don't need to test for it here. */ - } - else if (n3 == 0 - && n2 < 0 - && (self_subrange || n2 == -8)) - return debug_make_int_type (dhandle, - n2, true); - else if (n2 == - n3 - 1) - { - if (n3 == 0x7f) - return debug_make_int_type (dhandle, 1, false); - else if (n3 == 0x7fff) - return debug_make_int_type (dhandle, 2, false); - else if (n3 == 0x7fffffff) - return debug_make_int_type (dhandle, 4, false); - } - } - - /* At this point I don't have the faintest idea how to deal with a - self_subrange type; I'm going to assume that this is used as an - idiom, and that all of them are special cases. So . . . */ - if (self_subrange) - { - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - - index_type = stab_find_type (dhandle, info, rangenums); - if (index_type == DEBUG_TYPE_NULL) - { - /* Does this actually ever happen? Is that why we are worrying - about dealing with it rather than just calling error_type? */ - warn_stab (orig, "missing index type"); - index_type = debug_make_int_type (dhandle, 4, false); - } - - return debug_make_range_type (dhandle, index_type, n2, n3); -} - -/* Sun's ACC uses a somewhat saner method for specifying the builtin - typedefs in every file (for int, long, etc): - - type = b <signed> <width>; <offset>; <nbits> - signed = u or s. Possible c in addition to u or s (for char?). - offset = offset from high order bit to start bit of type. - width is # bytes in object of this type, nbits is # bits in type. - - The width/offset stuff appears to be for small objects stored in - larger ones (e.g. `shorts' in `int' registers). We ignore it for now, - FIXME. */ - -static debug_type -parse_stab_sun_builtin_type (dhandle, pp) - PTR dhandle; - const char **pp; -{ - const char *orig; - boolean unsignedp; - bfd_vma bits; - - orig = *pp; - - switch (**pp) - { - case 's': - unsignedp = false; - break; - case 'u': - unsignedp = true; - break; - default: - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - ++*pp; - - /* For some odd reason, all forms of char put a c here. This is strange - because no other type has this honor. We can safely ignore this because - we actually determine 'char'acterness by the number of bits specified in - the descriptor. */ - if (**pp == 'c') - ++*pp; - - /* The first number appears to be the number of bytes occupied - by this type, except that unsigned short is 4 instead of 2. - Since this information is redundant with the third number, - we will ignore it. */ - (void) parse_number (pp, (boolean *) NULL); - if (**pp != ';') - { - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - ++*pp; - - /* The second number is always 0, so ignore it too. */ - (void) parse_number (pp, (boolean *) NULL); - if (**pp != ';') - { - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - ++*pp; - - /* The third number is the number of bits for this type. */ - bits = parse_number (pp, (boolean *) NULL); - - /* The type *should* end with a semicolon. If it are embedded - in a larger type the semicolon may be the only way to know where - the type ends. If this type is at the end of the stabstring we - can deal with the omitted semicolon (but we don't have to like - it). Don't bother to complain(), Sun's compiler omits the semicolon - for "void". */ - if (**pp == ';') - ++*pp; - - if (bits == 0) - return debug_make_void_type (dhandle); - - return debug_make_int_type (dhandle, bits / 8, unsignedp); -} - -/* Parse a builtin floating type generated by the Sun compiler. */ - -static debug_type -parse_stab_sun_floating_type (dhandle, pp) - PTR dhandle; - const char **pp; -{ - const char *orig; - bfd_vma details; - bfd_vma bytes; - - orig = *pp; - - /* The first number has more details about the type, for example - FN_COMPLEX. */ - details = parse_number (pp, (boolean *) NULL); - if (**pp != ';') - { - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - - /* The second number is the number of bytes occupied by this type */ - bytes = parse_number (pp, (boolean *) NULL); - if (**pp != ';') - { - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - - if (details == NF_COMPLEX - || details == NF_COMPLEX16 - || details == NF_COMPLEX32) - return debug_make_complex_type (dhandle, bytes); - - return debug_make_float_type (dhandle, bytes); -} - -/* Handle an enum type. */ - -static debug_type -parse_stab_enum_type (dhandle, pp) - PTR dhandle; - const char **pp; -{ - const char *orig; - const char **names; - bfd_signed_vma *values; - unsigned int n; - unsigned int alloc; - - orig = *pp; - - /* FIXME: gdb checks os9k_stabs here. */ - - /* The aix4 compiler emits an extra field before the enum members; - my guess is it's a type of some sort. Just ignore it. */ - if (**pp == '-') - { - while (**pp != ':') - ++*pp; - ++*pp; - } - - /* Read the value-names and their values. - The input syntax is NAME:VALUE,NAME:VALUE, and so on. - A semicolon or comma instead of a NAME means the end. */ - alloc = 10; - names = (const char **) xmalloc (alloc * sizeof *names); - values = (bfd_signed_vma *) xmalloc (alloc * sizeof *values); - n = 0; - while (**pp != '\0' && **pp != ';' && **pp != ',') - { - const char *p; - char *name; - bfd_signed_vma val; - - p = *pp; - while (*p != ':') - ++p; - - name = savestring (*pp, p - *pp); - - *pp = p + 1; - val = (bfd_signed_vma) parse_number (pp, (boolean *) NULL); - if (**pp != ',') - { - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - ++*pp; - - if (n + 1 >= alloc) - { - alloc += 10; - names = ((const char **) - xrealloc ((PTR) names, alloc * sizeof *names)); - values = ((bfd_signed_vma *) - xrealloc ((PTR) values, alloc * sizeof *values)); - } - - names[n] = name; - values[n] = val; - ++n; - } - - names[n] = NULL; - values[n] = 0; - - if (**pp == ';') - ++*pp; - - return debug_make_enum_type (dhandle, names, values); -} - -/* Read the description of a structure (or union type) and return an object - describing the type. - - PP points to a character pointer that points to the next unconsumed token - in the the stabs string. For example, given stabs "A:T4=s4a:1,0,32;;", - *PP will point to "4a:1,0,32;;". */ - -static debug_type -parse_stab_struct_type (dhandle, info, tagname, pp, structp, typenums) - PTR dhandle; - struct stab_handle *info; - const char *tagname; - const char **pp; - boolean structp; - const int *typenums; -{ - const char *orig; - bfd_vma size; - debug_baseclass *baseclasses; - debug_field *fields; - boolean statics; - debug_method *methods; - debug_type vptrbase; - boolean ownvptr; - - orig = *pp; - - /* Get the size. */ - size = parse_number (pp, (boolean *) NULL); - - /* Get the other information. */ - if (! parse_stab_baseclasses (dhandle, info, pp, &baseclasses) - || ! parse_stab_struct_fields (dhandle, info, pp, &fields, &statics) - || ! parse_stab_members (dhandle, info, tagname, pp, typenums, &methods) - || ! parse_stab_tilde_field (dhandle, info, pp, typenums, &vptrbase, - &ownvptr)) - return DEBUG_TYPE_NULL; - - if (! statics - && baseclasses == NULL - && methods == NULL - && vptrbase == DEBUG_TYPE_NULL - && ! ownvptr) - return debug_make_struct_type (dhandle, structp, size, fields); - - return debug_make_object_type (dhandle, structp, size, fields, baseclasses, - methods, vptrbase, ownvptr); -} - -/* The stabs for C++ derived classes contain baseclass information which - is marked by a '!' character after the total size. This function is - called when we encounter the baseclass marker, and slurps up all the - baseclass information. - - Immediately following the '!' marker is the number of base classes that - the class is derived from, followed by information for each base class. - For each base class, there are two visibility specifiers, a bit offset - to the base class information within the derived class, a reference to - the type for the base class, and a terminating semicolon. - - A typical example, with two base classes, would be "!2,020,19;0264,21;". - ^^ ^ ^ ^ ^ ^ ^ - Baseclass information marker __________________|| | | | | | | - Number of baseclasses __________________________| | | | | | | - Visibility specifiers (2) ________________________| | | | | | - Offset in bits from start of class _________________| | | | | - Type number for base class ___________________________| | | | - Visibility specifiers (2) _______________________________| | | - Offset in bits from start of class ________________________| | - Type number of base class ____________________________________| - - Return true for success, false for failure. */ - -static boolean -parse_stab_baseclasses (dhandle, info, pp, retp) - PTR dhandle; - struct stab_handle *info; - const char **pp; - debug_baseclass **retp; -{ - const char *orig; - unsigned int c, i; - debug_baseclass *classes; - - *retp = NULL; - - orig = *pp; - - if (**pp != '!') - { - /* No base classes. */ - return true; - } - ++*pp; - - c = (unsigned int) parse_number (pp, (boolean *) NULL); - - if (**pp != ',') - { - bad_stab (orig); - return false; - } - ++*pp; - - classes = (debug_baseclass *) xmalloc ((c + 1) * sizeof (**retp)); - - for (i = 0; i < c; i++) - { - boolean virtual; - enum debug_visibility visibility; - bfd_vma bitpos; - debug_type type; - - switch (**pp) - { - case '0': - virtual = false; - break; - case '1': - virtual = true; - break; - default: - warn_stab (orig, "unknown virtual character for baseclass"); - virtual = false; - break; - } - ++*pp; - - switch (**pp) - { - case '0': - visibility = DEBUG_VISIBILITY_PRIVATE; - break; - case '1': - visibility = DEBUG_VISIBILITY_PROTECTED; - break; - case '2': - visibility = DEBUG_VISIBILITY_PUBLIC; - break; - default: - warn_stab (orig, "unknown visibility character for baseclass"); - visibility = DEBUG_VISIBILITY_PUBLIC; - break; - } - ++*pp; - - /* The remaining value is the bit offset of the portion of the - object corresponding to this baseclass. Always zero in the - absence of multiple inheritance. */ - bitpos = parse_number (pp, (boolean *) NULL); - if (**pp != ',') - { - bad_stab (orig); - return false; - } - ++*pp; - - type = parse_stab_type (dhandle, info, (const char *) NULL, pp, - (debug_type **) NULL); - if (type == DEBUG_TYPE_NULL) - return false; - - classes[i] = debug_make_baseclass (dhandle, type, bitpos, virtual, - visibility); - if (classes[i] == DEBUG_BASECLASS_NULL) - return false; - - if (**pp != ';') - return false; - ++*pp; - } - - classes[i] = DEBUG_BASECLASS_NULL; - - *retp = classes; - - return true; -} - -/* Read struct or class data fields. They have the form: - - NAME : [VISIBILITY] TYPENUM , BITPOS , BITSIZE ; - - At the end, we see a semicolon instead of a field. - - In C++, this may wind up being NAME:?TYPENUM:PHYSNAME; for - a static field. - - The optional VISIBILITY is one of: - - '/0' (VISIBILITY_PRIVATE) - '/1' (VISIBILITY_PROTECTED) - '/2' (VISIBILITY_PUBLIC) - '/9' (VISIBILITY_IGNORE) - - or nothing, for C style fields with public visibility. - - Returns 1 for success, 0 for failure. */ - -static boolean -parse_stab_struct_fields (dhandle, info, pp, retp, staticsp) - PTR dhandle; - struct stab_handle *info; - const char **pp; - debug_field **retp; - boolean *staticsp; -{ - const char *orig; - const char *p; - debug_field *fields; - unsigned int c; - unsigned int alloc; - - *retp = NULL; - *staticsp = false; - - orig = *pp; - - c = 0; - alloc = 10; - fields = (debug_field *) xmalloc (alloc * sizeof *fields); - while (**pp != ';') - { - /* FIXME: gdb checks os9k_stabs here. */ - - p = *pp; - - /* Add 1 to c to leave room for NULL pointer at end. */ - if (c + 1 >= alloc) - { - alloc += 10; - fields = ((debug_field *) - xrealloc ((PTR) fields, alloc * sizeof *fields)); - } - - /* If it starts with CPLUS_MARKER it is a special abbreviation, - unless the CPLUS_MARKER is followed by an underscore, in - which case it is just the name of an anonymous type, which we - should handle like any other type name. We accept either '$' - or '.', because a field name can never contain one of these - characters except as a CPLUS_MARKER. */ - - if ((*p == '$' || *p == '.') && p[1] != '_') - { - ++*pp; - if (! parse_stab_cpp_abbrev (dhandle, info, pp, fields + c)) - return false; - ++c; - continue; - } - - /* Look for the ':' that separates the field name from the field - values. Data members are delimited by a single ':', while member - functions are delimited by a pair of ':'s. When we hit the member - functions (if any), terminate scan loop and return. */ - - p = strchr (p, ':'); - if (p == NULL) - { - bad_stab (orig); - return false; - } - - if (p[1] == ':') - break; - - if (! parse_stab_one_struct_field (dhandle, info, pp, p, fields + c, - staticsp)) - return false; - - ++c; - } - - fields[c] = DEBUG_FIELD_NULL; - - *retp = fields; - - return true; -} - -/* Special GNU C++ name. */ - -static boolean -parse_stab_cpp_abbrev (dhandle, info, pp, retp) - PTR dhandle; - struct stab_handle *info; - const char **pp; - debug_field *retp; -{ - const char *orig; - int cpp_abbrev; - debug_type context; - const char *name; - const char *typename; - debug_type type; - bfd_vma bitpos; - - *retp = DEBUG_FIELD_NULL; - - orig = *pp; - - if (**pp != 'v') - { - bad_stab (*pp); - return false; - } - ++*pp; - - cpp_abbrev = **pp; - ++*pp; - - /* At this point, *pp points to something like "22:23=*22...", where - the type number before the ':' is the "context" and everything - after is a regular type definition. Lookup the type, find it's - name, and construct the field name. */ - - context = parse_stab_type (dhandle, info, (const char *) NULL, pp, - (debug_type **) NULL); - if (context == DEBUG_TYPE_NULL) - return false; - - switch (cpp_abbrev) - { - case 'f': - /* $vf -- a virtual function table pointer. */ - name = "_vptr$"; - break; - case 'b': - /* $vb -- a virtual bsomethingorother */ - typename = debug_get_type_name (dhandle, context); - if (typename == NULL) - { - warn_stab (orig, "unnamed $vb type"); - typename = "FOO"; - } - name = concat ("_vb$", typename, (const char *) NULL); - break; - default: - warn_stab (orig, "unrecognized C++ abbreviation"); - name = "INVALID_CPLUSPLUS_ABBREV"; - break; - } - - if (**pp != ':') - { - bad_stab (orig); - return false; - } - ++*pp; - - type = parse_stab_type (dhandle, info, (const char *) NULL, pp, - (debug_type **) NULL); - if (**pp != ',') - { - bad_stab (orig); - return false; - } - ++*pp; - - bitpos = parse_number (pp, (boolean *) NULL); - if (**pp != ';') - { - bad_stab (orig); - return false; - } - ++*pp; - - *retp = debug_make_field (dhandle, name, type, bitpos, 0, - DEBUG_VISIBILITY_PRIVATE); - if (*retp == DEBUG_FIELD_NULL) - return false; - - return true; -} - -/* Parse a single field in a struct or union. */ - -static boolean -parse_stab_one_struct_field (dhandle, info, pp, p, retp, staticsp) - PTR dhandle; - struct stab_handle *info; - const char **pp; - const char *p; - debug_field *retp; - boolean *staticsp; -{ - const char *orig; - char *name; - enum debug_visibility visibility; - debug_type type; - bfd_vma bitpos; - bfd_vma bitsize; - - orig = *pp; - - /* FIXME: gdb checks ARM_DEMANGLING here. */ - - name = savestring (*pp, p - *pp); - - *pp = p + 1; - - if (**pp != '/') - visibility = DEBUG_VISIBILITY_PUBLIC; - else - { - ++*pp; - switch (**pp) - { - case '0': - visibility = DEBUG_VISIBILITY_PRIVATE; - break; - case '1': - visibility = DEBUG_VISIBILITY_PROTECTED; - break; - case '2': - visibility = DEBUG_VISIBILITY_PUBLIC; - break; - default: - warn_stab (orig, "unknown visibility character for field"); - visibility = DEBUG_VISIBILITY_PUBLIC; - break; - } - ++*pp; - } - - type = parse_stab_type (dhandle, info, (const char *) NULL, pp, - (debug_type **) NULL); - if (type == DEBUG_TYPE_NULL) - return false; - - if (**pp == ':') - { - char *varname; - - /* This is a static class member. */ - ++*pp; - p = strchr (*pp, ';'); - if (p == NULL) - { - bad_stab (orig); - return false; - } - - varname = savestring (*pp, p - *pp); - - *pp = p + 1; - - *retp = debug_make_static_member (dhandle, name, type, varname, - visibility); - *staticsp = true; - - return true; - } - - if (**pp != ',') - { - bad_stab (orig); - return false; - } - ++*pp; - - bitpos = parse_number (pp, (boolean *) NULL); - if (**pp != ',') - { - bad_stab (orig); - return false; - } - ++*pp; - - bitsize = parse_number (pp, (boolean *) NULL); - if (**pp != ';') - { - bad_stab (orig); - return false; - } - ++*pp; - - if (bitpos == 0 && bitsize == 0) - { - /* This can happen in two cases: (1) at least for gcc 2.4.5 or - so, it is a field which has been optimized out. The correct - stab for this case is to use VISIBILITY_IGNORE, but that is a - recent invention. (2) It is a 0-size array. For example - union { int num; char str[0]; } foo. Printing "<no value>" - for str in "p foo" is OK, since foo.str (and thus foo.str[3]) - will continue to work, and a 0-size array as a whole doesn't - have any contents to print. - - I suspect this probably could also happen with gcc -gstabs - (not -gstabs+) for static fields, and perhaps other C++ - extensions. Hopefully few people use -gstabs with gdb, since - it is intended for dbx compatibility. */ - visibility = DEBUG_VISIBILITY_IGNORE; - } - - /* FIXME: gdb does some stuff here to mark fields as unpacked. */ - - *retp = debug_make_field (dhandle, name, type, bitpos, bitsize, visibility); - - return true; -} - -/* Read member function stabs info for C++ classes. The form of each member - function data is: - - NAME :: TYPENUM[=type definition] ARGS : PHYSNAME ; - - An example with two member functions is: - - afunc1::20=##15;:i;2A.;afunc2::20:i;2A.; - - For the case of overloaded operators, the format is op$::*.funcs, where - $ is the CPLUS_MARKER (usually '$'), `*' holds the place for an operator - name (such as `+=') and `.' marks the end of the operator name. */ - -static boolean -parse_stab_members (dhandle, info, tagname, pp, typenums, retp) - PTR dhandle; - struct stab_handle *info; - const char *tagname; - const char **pp; - const int *typenums; - debug_method **retp; -{ - const char *orig; - debug_method *methods; - unsigned int c; - unsigned int alloc; - - *retp = NULL; - - orig = *pp; - - alloc = 0; - methods = NULL; - c = 0; - - while (**pp != ';') - { - const char *p; - char *name; - debug_method_variant *variants; - unsigned int cvars; - unsigned int allocvars; - debug_type look_ahead_type; - - p = strchr (*pp, ':'); - if (p == NULL || p[1] != ':') - break; - - /* FIXME: Some systems use something other than '$' here. */ - if ((*pp)[0] != 'o' || (*pp)[1] != 'p' || (*pp)[2] != '$') - { - name = savestring (*pp, p - *pp); - *pp = p + 2; - } - else - { - /* This is a completely wierd case. In order to stuff in the - names that might contain colons (the usual name delimiter), - Mike Tiemann defined a different name format which is - signalled if the identifier is "op$". In that case, the - format is "op$::XXXX." where XXXX is the name. This is - used for names like "+" or "=". YUUUUUUUK! FIXME! */ - *pp = p + 2; - for (p = *pp; *p != '.' && *p != '\0'; p++) - ; - if (*p != '.') - { - bad_stab (orig); - return false; - } - name = savestring (*pp, p - *pp); - *pp = p + 1; - } - - allocvars = 10; - variants = ((debug_method_variant *) - xmalloc (allocvars * sizeof *variants)); - cvars = 0; - - look_ahead_type = DEBUG_TYPE_NULL; - - do - { - debug_type type; - boolean stub; - char *argtypes; - enum debug_visibility visibility; - boolean constp, volatilep, staticp; - bfd_vma voffset; - debug_type context; - const char *physname; - boolean varargs; - - if (look_ahead_type != DEBUG_TYPE_NULL) - { - /* g++ version 1 kludge */ - type = look_ahead_type; - look_ahead_type = DEBUG_TYPE_NULL; - } - else - { - type = parse_stab_type (dhandle, info, (const char *) NULL, pp, - (debug_type **) NULL); - if (type == DEBUG_TYPE_NULL) - return false; - if (**pp != ':') - { - bad_stab (orig); - return false; - } - } - - ++*pp; - p = strchr (*pp, ';'); - if (p == NULL) - { - bad_stab (orig); - return false; - } - - stub = false; - if (debug_get_type_kind (dhandle, type) == DEBUG_KIND_METHOD - && debug_get_parameter_types (dhandle, type, &varargs) == NULL) - stub = true; - - argtypes = savestring (*pp, p - *pp); - *pp = p + 1; - - switch (**pp) - { - case '0': - visibility = DEBUG_VISIBILITY_PRIVATE; - break; - case '1': - visibility = DEBUG_VISIBILITY_PROTECTED; - break; - default: - visibility = DEBUG_VISIBILITY_PUBLIC; - break; - } - ++*pp; - - constp = false; - volatilep = false; - switch (**pp) - { - case 'A': - /* Normal function. */ - ++*pp; - break; - case 'B': - /* const member function. */ - constp = true; - ++*pp; - break; - case 'C': - /* volatile member function. */ - volatilep = true; - ++*pp; - break; - case 'D': - /* const volatile member function. */ - constp = true; - volatilep = true; - ++*pp; - break; - case '*': - case '?': - case '.': - /* File compiled with g++ version 1; no information. */ - break; - default: - warn_stab (orig, "const/volatile indicator missing"); - break; - } - - staticp = false; - switch (**pp) - { - case '*': - /* virtual member function, followed by index. The sign - bit is supposedly set to distinguish - pointers-to-methods from virtual function indicies. */ - ++*pp; - voffset = parse_number (pp, (boolean *) NULL); - if (**pp != ';') - { - bad_stab (orig); - return false; - } - ++*pp; - voffset &= 0x7fffffff; - - if (**pp == ';' || *pp == '\0') - { - /* Must be g++ version 1. */ - context = DEBUG_TYPE_NULL; - } - else - { - /* Figure out from whence this virtual function - came. It may belong to virtual function table of - one of its baseclasses. */ - look_ahead_type = parse_stab_type (dhandle, info, - (const char *) NULL, - pp, - (debug_type **) NULL); - if (**pp == ':') - { - /* g++ version 1 overloaded methods. */ - context = DEBUG_TYPE_NULL; - } - else - { - context = look_ahead_type; - look_ahead_type = DEBUG_TYPE_NULL; - if (**pp != ';') - { - bad_stab (orig); - return false; - } - ++*pp; - } - } - break; - - case '?': - /* static member function. */ - ++*pp; - staticp = true; - voffset = 0; - context = DEBUG_TYPE_NULL; - if (strncmp (argtypes, name, strlen (name)) != 0) - stub = true; - break; - - default: - warn_stab (orig, "member function type missing"); - voffset = 0; - context = DEBUG_TYPE_NULL; - break; - - case '.': - ++*pp; - voffset = 0; - context = DEBUG_TYPE_NULL; - break; - } - - /* If the type is not a stub, then the argtypes string is - the physical name of the function. Otherwise the - argtypes string is the mangled form of the argument - types, and the full type and the physical name must be - extracted from them. */ - if (! stub) - physname = argtypes; - else - { - debug_type class_type, return_type; - - class_type = stab_find_type (dhandle, info, typenums); - if (class_type == DEBUG_TYPE_NULL) - return false; - return_type = debug_get_return_type (dhandle, type); - if (return_type == DEBUG_TYPE_NULL) - { - bad_stab (orig); - return false; - } - type = parse_stab_argtypes (dhandle, info, class_type, name, - tagname, return_type, argtypes, - constp, volatilep, &physname); - if (type == DEBUG_TYPE_NULL) - return false; - } - - if (cvars + 1 >= allocvars) - { - allocvars += 10; - variants = ((debug_method_variant *) - xrealloc ((PTR) variants, - allocvars * sizeof *variants)); - } - - if (! staticp) - variants[cvars] = debug_make_method_variant (dhandle, physname, - type, visibility, - constp, volatilep, - voffset, context); - else - variants[cvars] = debug_make_static_method_variant (dhandle, - physname, - type, - visibility, - constp, - volatilep); - if (variants[cvars] == DEBUG_METHOD_VARIANT_NULL) - return false; - - ++cvars; - } - while (**pp != ';' && **pp != '\0'); - - variants[cvars] = DEBUG_METHOD_VARIANT_NULL; - - if (**pp != '\0') - ++*pp; - - if (c + 1 >= alloc) - { - alloc += 10; - methods = ((debug_method *) - xrealloc ((PTR) methods, alloc * sizeof *methods)); - } - - methods[c] = debug_make_method (dhandle, name, variants); - - ++c; - } - - if (methods != NULL) - methods[c] = DEBUG_METHOD_NULL; - - *retp = methods; - - return true; -} - -/* Parse a string representing argument types for a method. Stabs - tries to save space by packing argument types into a mangled - string. This string should give us enough information to extract - both argument types and the physical name of the function, given - the tag name. */ - -static debug_type -parse_stab_argtypes (dhandle, info, class_type, fieldname, tagname, - return_type, argtypes, constp, volatilep, pphysname) - PTR dhandle; - struct stab_handle *info; - debug_type class_type; - const char *fieldname; - const char *tagname; - debug_type return_type; - const char *argtypes; - boolean constp; - boolean volatilep; - const char **pphysname; -{ - boolean is_full_physname_constructor; - boolean is_constructor; - boolean is_destructor; - debug_type *args; - boolean varargs; - - /* Constructors are sometimes handled specially. */ - is_full_physname_constructor = ((argtypes[0] == '_' - && argtypes[1] == '_' - && (isdigit ((unsigned char) argtypes[2]) - || argtypes[2] == 'Q' - || argtypes[2] == 't')) - || strncmp (argtypes, "__ct", 4) == 0); - - is_constructor = (is_full_physname_constructor - || (tagname != NULL - && strcmp (fieldname, tagname) == 0)); - is_destructor = ((argtypes[0] == '_' - && (argtypes[1] == '$' || argtypes[1] == '.') - && argtypes[2] == '_') - || strncmp (argtypes, "__dt", 4) == 0); - - if (is_destructor || is_full_physname_constructor) - *pphysname = argtypes; - else - { - unsigned int len; - const char *const_prefix; - const char *volatile_prefix; - char buf[20]; - unsigned int mangled_name_len; - char *physname; - - len = tagname == NULL ? 0 : strlen (tagname); - const_prefix = constp ? "C" : ""; - volatile_prefix = volatilep ? "V" : ""; - - if (len == 0) - sprintf (buf, "__%s%s", const_prefix, volatile_prefix); - else if (tagname != NULL && strchr (tagname, '<') != NULL) - { - /* Template methods are fully mangled. */ - sprintf (buf, "__%s%s", const_prefix, volatile_prefix); - tagname = NULL; - len = 0; - } - else - sprintf (buf, "__%s%s%d", const_prefix, volatile_prefix, len); - - mangled_name_len = ((is_constructor ? 0 : strlen (fieldname)) - + strlen (buf) - + len - + strlen (argtypes) - + 1); - - if (fieldname[0] == 'o' - && fieldname[1] == 'p' - && (fieldname[2] == '$' || fieldname[2] == '.')) - { - const char *opname; - - opname = cplus_mangle_opname (fieldname + 3, 0); - if (opname == NULL) - { - fprintf (stderr, "No mangling for \"%s\"\n", fieldname); - return DEBUG_TYPE_NULL; - } - mangled_name_len += strlen (opname); - physname = (char *) xmalloc (mangled_name_len); - strncpy (physname, fieldname, 3); - strcpy (physname + 3, opname); - } - else - { - physname = (char *) xmalloc (mangled_name_len); - if (is_constructor) - physname[0] = '\0'; - else - strcpy (physname, fieldname); - } - - strcat (physname, buf); - if (tagname != NULL) - strcat (physname, tagname); - strcat (physname, argtypes); - - *pphysname = physname; - } - - if (*argtypes == '\0' || is_destructor) - { - args = (debug_type *) xmalloc (sizeof *args); - *args = NULL; - return debug_make_method_type (dhandle, return_type, class_type, args, - false); - } - - args = stab_demangle_argtypes (dhandle, info, *pphysname, &varargs); - if (args == NULL) - return DEBUG_TYPE_NULL; - - return debug_make_method_type (dhandle, return_type, class_type, args, - varargs); -} - -/* The tail end of stabs for C++ classes that contain a virtual function - pointer contains a tilde, a %, and a type number. - The type number refers to the base class (possibly this class itself) which - contains the vtable pointer for the current class. - - This function is called when we have parsed all the method declarations, - so we can look for the vptr base class info. */ - -static boolean -parse_stab_tilde_field (dhandle, info, pp, typenums, retvptrbase, retownvptr) - PTR dhandle; - struct stab_handle *info; - const char **pp; - const int *typenums; - debug_type *retvptrbase; - boolean *retownvptr; -{ - const char *orig; - const char *hold; - int vtypenums[2]; - - *retvptrbase = DEBUG_TYPE_NULL; - *retownvptr = false; - - orig = *pp; - - /* If we are positioned at a ';', then skip it. */ - if (**pp == ';') - ++*pp; - - if (**pp != '~') - return true; - - ++*pp; - - if (**pp == '=' || **pp == '+' || **pp == '-') - { - /* Obsolete flags that used to indicate the presence of - constructors and/or destructors. */ - ++*pp; - } - - if (**pp != '%') - return true; - - ++*pp; - - hold = *pp; - - /* The next number is the type number of the base class (possibly - our own class) which supplies the vtable for this class. */ - if (! parse_stab_type_number (pp, vtypenums)) - return false; - - if (vtypenums[0] == typenums[0] - && vtypenums[1] == typenums[1]) - *retownvptr = true; - else - { - debug_type vtype; - const char *p; - - *pp = hold; - - vtype = parse_stab_type (dhandle, info, (const char *) NULL, pp, - (debug_type **) NULL); - for (p = *pp; *p != ';' && *p != '\0'; p++) - ; - if (*p != ';') - { - bad_stab (orig); - return false; - } - - *retvptrbase = vtype; - - *pp = p + 1; - } - - return true; -} - -/* Read a definition of an array type. */ - -static debug_type -parse_stab_array_type (dhandle, info, pp, stringp) - PTR dhandle; - struct stab_handle *info; - const char **pp; - boolean stringp; -{ - const char *orig; - const char *p; - int typenums[2]; - debug_type index_type; - boolean adjustable; - bfd_signed_vma lower, upper; - debug_type element_type; - - /* Format of an array type: - "ar<index type>;lower;upper;<array_contents_type>". - OS9000: "arlower,upper;<array_contents_type>". - - Fortran adjustable arrays use Adigits or Tdigits for lower or upper; - for these, produce a type like float[][]. */ - - orig = *pp; - - /* FIXME: gdb checks os9k_stabs here. */ - - /* If the index type is type 0, we take it as int. */ - p = *pp; - if (! parse_stab_type_number (&p, typenums)) - return DEBUG_TYPE_NULL; - if (typenums[0] == 0 && typenums[1] == 0 && **pp != '=') - { - index_type = debug_find_named_type (dhandle, "int"); - if (index_type == DEBUG_TYPE_NULL) - { - index_type = debug_make_int_type (dhandle, 4, false); - if (index_type == DEBUG_TYPE_NULL) - return DEBUG_TYPE_NULL; - } - *pp = p; - } - else - { - index_type = parse_stab_type (dhandle, info, (const char *) NULL, pp, - (debug_type **) NULL); - } - - if (**pp != ';') - { - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - ++*pp; - - adjustable = false; - - if (! isdigit ((unsigned char) **pp) && **pp != '-') - { - ++*pp; - adjustable = true; - } - - lower = (bfd_signed_vma) parse_number (pp, (boolean *) NULL); - if (**pp != ';') - { - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - ++*pp; - - if (! isdigit ((unsigned char) **pp) && **pp != '-') - { - ++*pp; - adjustable = true; - } - - upper = (bfd_signed_vma) parse_number (pp, (boolean *) NULL); - if (**pp != ';') - { - bad_stab (orig); - return DEBUG_TYPE_NULL; - } - ++*pp; - - element_type = parse_stab_type (dhandle, info, (const char *) NULL, pp, - (debug_type **) NULL); - if (element_type == DEBUG_TYPE_NULL) - return DEBUG_TYPE_NULL; - - if (adjustable) - { - lower = 0; - upper = -1; - } - - return debug_make_array_type (dhandle, element_type, index_type, lower, - upper, stringp); -} - -/* This struct holds information about files we have seen using - N_BINCL. */ - -struct bincl_file -{ - /* The next N_BINCL file. */ - struct bincl_file *next; - /* The next N_BINCL on the stack. */ - struct bincl_file *next_stack; - /* The file name. */ - const char *name; - /* The hash value. */ - bfd_vma hash; - /* The file index. */ - unsigned int file; - /* The list of types defined in this file. */ - struct stab_types *file_types; -}; - -/* Start a new N_BINCL file, pushing it onto the stack. */ - -static void -push_bincl (info, name, hash) - struct stab_handle *info; - const char *name; - bfd_vma hash; -{ - struct bincl_file *n; - - n = (struct bincl_file *) xmalloc (sizeof *n); - n->next = info->bincl_list; - n->next_stack = info->bincl_stack; - n->name = name; - n->hash = hash; - n->file = info->files; - n->file_types = NULL; - info->bincl_list = n; - info->bincl_stack = n; - - ++info->files; - info->file_types = ((struct stab_types **) - xrealloc ((PTR) info->file_types, - (info->files - * sizeof *info->file_types))); - info->file_types[n->file] = NULL; -} - -/* Finish an N_BINCL file, at an N_EINCL, popping the name off the - stack. */ - -static const char * -pop_bincl (info) - struct stab_handle *info; -{ - struct bincl_file *o; - - o = info->bincl_stack; - if (o == NULL) - return info->main_filename; - info->bincl_stack = o->next_stack; - - o->file_types = info->file_types[o->file]; - - if (info->bincl_stack == NULL) - return info->main_filename; - return info->bincl_stack->name; -} - -/* Handle an N_EXCL: get the types from the corresponding N_BINCL. */ - -static boolean -find_excl (info, name, hash) - struct stab_handle *info; - const char *name; - bfd_vma hash; -{ - struct bincl_file *l; - - ++info->files; - info->file_types = ((struct stab_types **) - xrealloc ((PTR) info->file_types, - (info->files - * sizeof *info->file_types))); - - for (l = info->bincl_list; l != NULL; l = l->next) - if (l->hash == hash && strcmp (l->name, name) == 0) - break; - if (l == NULL) - { - warn_stab (name, "Undefined N_EXCL"); - info->file_types[info->files - 1] = NULL; - return true; - } - - info->file_types[info->files - 1] = l->file_types; - - return true; -} - -/* Handle a variable definition. gcc emits variable definitions for a - block before the N_LBRAC, so we must hold onto them until we see - it. The SunPRO compiler emits variable definitions after the - N_LBRAC, so we can call debug_record_variable immediately. */ - -static boolean -stab_record_variable (dhandle, info, name, type, kind, val) - PTR dhandle; - struct stab_handle *info; - const char *name; - debug_type type; - enum debug_var_kind kind; - bfd_vma val; -{ - struct stab_pending_var *v; - - if ((kind == DEBUG_GLOBAL || kind == DEBUG_STATIC) - || ! info->within_function - || (info->gcc_compiled == 0 && info->n_opt_found)) - return debug_record_variable (dhandle, name, type, kind, val); - - v = (struct stab_pending_var *) xmalloc (sizeof *v); - memset (v, 0, sizeof *v); - - v->next = info->pending; - v->name = name; - v->type = type; - v->kind = kind; - v->val = val; - info->pending = v; - - return true; -} - -/* Emit pending variable definitions. This is called after we see the - N_LBRAC that starts the block. */ - -static boolean -stab_emit_pending_vars (dhandle, info) - PTR dhandle; - struct stab_handle *info; -{ - struct stab_pending_var *v; - - v = info->pending; - while (v != NULL) - { - struct stab_pending_var *next; - - if (! debug_record_variable (dhandle, v->name, v->type, v->kind, v->val)) - return false; - - next = v->next; - free (v); - v = next; - } - - info->pending = NULL; - - return true; -} - -/* Find the slot for a type in the database. */ - -static debug_type * -stab_find_slot (info, typenums) - struct stab_handle *info; - const int *typenums; -{ - int filenum; - int index; - struct stab_types **ps; - - filenum = typenums[0]; - index = typenums[1]; - - if (filenum < 0 || (unsigned int) filenum >= info->files) - { - fprintf (stderr, "Type file number %d out of range\n", filenum); - return NULL; - } - if (index < 0) - { - fprintf (stderr, "Type index number %d out of range\n", index); - return NULL; - } - - ps = info->file_types + filenum; - - while (index >= STAB_TYPES_SLOTS) - { - if (*ps == NULL) - { - *ps = (struct stab_types *) xmalloc (sizeof **ps); - memset (*ps, 0, sizeof **ps); - } - ps = &(*ps)->next; - index -= STAB_TYPES_SLOTS; - } - if (*ps == NULL) - { - *ps = (struct stab_types *) xmalloc (sizeof **ps); - memset (*ps, 0, sizeof **ps); - } - - return (*ps)->types + index; -} - -/* Find a type given a type number. If the type has not been - allocated yet, create an indirect type. */ - -static debug_type -stab_find_type (dhandle, info, typenums) - PTR dhandle; - struct stab_handle *info; - const int *typenums; -{ - debug_type *slot; - - if (typenums[0] == 0 && typenums[1] < 0) - { - /* A negative type number indicates an XCOFF builtin type. */ - return stab_xcoff_builtin_type (dhandle, info, typenums[1]); - } - - slot = stab_find_slot (info, typenums); - if (slot == NULL) - return DEBUG_TYPE_NULL; - - if (*slot == DEBUG_TYPE_NULL) - return debug_make_indirect_type (dhandle, slot, (const char *) NULL); - - return *slot; -} - -/* Record that a given type number refers to a given type. */ - -static boolean -stab_record_type (dhandle, info, typenums, type) - PTR dhandle; - struct stab_handle *info; - const int *typenums; - debug_type type; -{ - debug_type *slot; - - slot = stab_find_slot (info, typenums); - if (slot == NULL) - return false; - - /* gdb appears to ignore type redefinitions, so we do as well. */ - - *slot = type; - - return true; -} - -/* Return an XCOFF builtin type. */ - -static debug_type -stab_xcoff_builtin_type (dhandle, info, typenum) - PTR dhandle; - struct stab_handle *info; - int typenum; -{ - debug_type rettype; - const char *name; - - if (typenum >= 0 || typenum < -XCOFF_TYPE_COUNT) - { - fprintf (stderr, "Unrecognized XCOFF type %d\n", typenum); - return DEBUG_TYPE_NULL; - } - if (info->xcoff_types[-typenum] != NULL) - return info->xcoff_types[-typenum]; - - switch (-typenum) - { - case 1: - /* The size of this and all the other types are fixed, defined - by the debugging format. */ - name = "int"; - rettype = debug_make_int_type (dhandle, 4, false); - break; - case 2: - name = "char"; - rettype = debug_make_int_type (dhandle, 1, false); - break; - case 3: - name = "short"; - rettype = debug_make_int_type (dhandle, 2, false); - break; - case 4: - name = "long"; - rettype = debug_make_int_type (dhandle, 4, false); - break; - case 5: - name = "unsigned char"; - rettype = debug_make_int_type (dhandle, 1, true); - break; - case 6: - name = "signed char"; - rettype = debug_make_int_type (dhandle, 1, false); - break; - case 7: - name = "unsigned short"; - rettype = debug_make_int_type (dhandle, 2, true); - break; - case 8: - name = "unsigned int"; - rettype = debug_make_int_type (dhandle, 4, true); - break; - case 9: - name = "unsigned"; - rettype = debug_make_int_type (dhandle, 4, true); - case 10: - name = "unsigned long"; - rettype = debug_make_int_type (dhandle, 4, true); - break; - case 11: - name = "void"; - rettype = debug_make_void_type (dhandle); - break; - case 12: - /* IEEE single precision (32 bit). */ - name = "float"; - rettype = debug_make_float_type (dhandle, 4); - break; - case 13: - /* IEEE double precision (64 bit). */ - name = "double"; - rettype = debug_make_float_type (dhandle, 8); - break; - case 14: - /* This is an IEEE double on the RS/6000, and different machines - with different sizes for "long double" should use different - negative type numbers. See stabs.texinfo. */ - name = "long double"; - rettype = debug_make_float_type (dhandle, 8); - break; - case 15: - name = "integer"; - rettype = debug_make_int_type (dhandle, 4, false); - break; - case 16: - name = "boolean"; - rettype = debug_make_bool_type (dhandle, 4); - break; - case 17: - name = "short real"; - rettype = debug_make_float_type (dhandle, 4); - break; - case 18: - name = "real"; - rettype = debug_make_float_type (dhandle, 8); - break; - case 19: - /* FIXME */ - name = "stringptr"; - rettype = NULL; - break; - case 20: - /* FIXME */ - name = "character"; - rettype = debug_make_int_type (dhandle, 1, true); - break; - case 21: - name = "logical*1"; - rettype = debug_make_bool_type (dhandle, 1); - break; - case 22: - name = "logical*2"; - rettype = debug_make_bool_type (dhandle, 2); - break; - case 23: - name = "logical*4"; - rettype = debug_make_bool_type (dhandle, 4); - break; - case 24: - name = "logical"; - rettype = debug_make_bool_type (dhandle, 4); - break; - case 25: - /* Complex type consisting of two IEEE single precision values. */ - name = "complex"; - rettype = debug_make_complex_type (dhandle, 8); - break; - case 26: - /* Complex type consisting of two IEEE double precision values. */ - name = "double complex"; - rettype = debug_make_complex_type (dhandle, 16); - break; - case 27: - name = "integer*1"; - rettype = debug_make_int_type (dhandle, 1, false); - break; - case 28: - name = "integer*2"; - rettype = debug_make_int_type (dhandle, 2, false); - break; - case 29: - name = "integer*4"; - rettype = debug_make_int_type (dhandle, 4, false); - break; - case 30: - /* FIXME */ - name = "wchar"; - rettype = debug_make_int_type (dhandle, 2, false); - break; - case 31: - name = "long long"; - rettype = debug_make_int_type (dhandle, 8, false); - break; - case 32: - name = "unsigned long long"; - rettype = debug_make_int_type (dhandle, 8, true); - break; - case 33: - name = "logical*8"; - rettype = debug_make_bool_type (dhandle, 8); - break; - case 34: - name = "integer*8"; - rettype = debug_make_int_type (dhandle, 8, false); - break; - default: - abort (); - } - - rettype = debug_name_type (dhandle, name, rettype); - - info->xcoff_types[-typenum] = rettype; - - return rettype; -} - -/* Find or create a tagged type. */ - -static debug_type -stab_find_tagged_type (dhandle, info, p, len, kind) - PTR dhandle; - struct stab_handle *info; - const char *p; - int len; - enum debug_type_kind kind; -{ - char *name; - debug_type dtype; - struct stab_tag *st; - - name = savestring (p, len); - - /* We pass DEBUG_KIND_ILLEGAL because we want all tags in the same - namespace. This is right for C, and I don't know how to handle - other languages. FIXME. */ - dtype = debug_find_tagged_type (dhandle, name, DEBUG_KIND_ILLEGAL); - if (dtype != DEBUG_TYPE_NULL) - { - free (name); - return dtype; - } - - /* We need to allocate an entry on the undefined tag list. */ - for (st = info->tags; st != NULL; st = st->next) - { - if (st->name[0] == name[0] - && strcmp (st->name, name) == 0) - { - if (st->kind == DEBUG_KIND_ILLEGAL) - st->kind = kind; - free (name); - break; - } - } - if (st == NULL) - { - st = (struct stab_tag *) xmalloc (sizeof *st); - memset (st, 0, sizeof *st); - - st->next = info->tags; - st->name = name; - st->kind = kind; - st->slot = DEBUG_TYPE_NULL; - st->type = debug_make_indirect_type (dhandle, &st->slot, name); - info->tags = st; - } - - return st->type; -} - -/* In order to get the correct argument types for a stubbed method, we - need to extract the argument types from a C++ mangled string. - Since the argument types can refer back to the return type, this - means that we must demangle the entire physical name. In gdb this - is done by calling cplus_demangle and running the results back - through the C++ expression parser. Since we have no expression - parser, we must duplicate much of the work of cplus_demangle here. - - We assume that GNU style demangling is used, since this is only - done for method stubs, and only g++ should output that form of - debugging information. */ - -/* This structure is used to hold a pointer to type information which - demangling a string. */ - -struct stab_demangle_typestring -{ - /* The start of the type. This is not null terminated. */ - const char *typestring; - /* The length of the type. */ - unsigned int len; -}; - -/* This structure is used to hold information while demangling a - string. */ - -struct stab_demangle_info -{ - /* The debugging information handle. */ - PTR dhandle; - /* The stab information handle. */ - struct stab_handle *info; - /* The array of arguments we are building. */ - debug_type *args; - /* Whether the method takes a variable number of arguments. */ - boolean varargs; - /* The array of types we have remembered. */ - struct stab_demangle_typestring *typestrings; - /* The number of typestrings. */ - unsigned int typestring_count; - /* The number of typestring slots we have allocated. */ - unsigned int typestring_alloc; -}; - -static void stab_bad_demangle PARAMS ((const char *)); -static unsigned int stab_demangle_count PARAMS ((const char **)); -static boolean stab_demangle_get_count - PARAMS ((const char **, unsigned int *)); -static boolean stab_demangle_prefix - PARAMS ((struct stab_demangle_info *, const char **)); -static boolean stab_demangle_function_name - PARAMS ((struct stab_demangle_info *, const char **, const char *)); -static boolean stab_demangle_signature - PARAMS ((struct stab_demangle_info *, const char **)); -static boolean stab_demangle_qualified - PARAMS ((struct stab_demangle_info *, const char **, debug_type *)); -static boolean stab_demangle_template - PARAMS ((struct stab_demangle_info *, const char **)); -static boolean stab_demangle_class - PARAMS ((struct stab_demangle_info *, const char **, const char **)); -static boolean stab_demangle_args - PARAMS ((struct stab_demangle_info *, const char **, debug_type **, - boolean *)); -static boolean stab_demangle_arg - PARAMS ((struct stab_demangle_info *, const char **, debug_type **, - unsigned int *, unsigned int *)); -static boolean stab_demangle_type - PARAMS ((struct stab_demangle_info *, const char **, debug_type *)); -static boolean stab_demangle_fund_type - PARAMS ((struct stab_demangle_info *, const char **, debug_type *)); -static boolean stab_demangle_remember_type - PARAMS ((struct stab_demangle_info *, const char *, int)); - -/* Warn about a bad demangling. */ - -static void -stab_bad_demangle (s) - const char *s; -{ - fprintf (stderr, "bad mangled name `%s'\n", s); -} - -/* Get a count from a stab string. */ - -static unsigned int -stab_demangle_count (pp) - const char **pp; -{ - unsigned int count; - - count = 0; - while (isdigit ((unsigned char) **pp)) - { - count *= 10; - count += **pp - '0'; - ++*pp; - } - return count; -} - -/* Require a count in a string. The count may be multiple digits, in - which case it must end in an underscore. */ - -static boolean -stab_demangle_get_count (pp, pi) - const char **pp; - unsigned int *pi; -{ - if (! isdigit ((unsigned char) **pp)) - return false; - - *pi = **pp - '0'; - ++*pp; - if (isdigit ((unsigned char) **pp)) - { - unsigned int count; - const char *p; - - count = *pi; - p = *pp; - do - { - count *= 10; - count += *p - '0'; - ++p; - } - while (isdigit ((unsigned char) *p)); - if (*p == '_') - { - *pp = p + 1; - *pi = count; - } - } - - return true; -} - -/* This function demangles a physical name, returning a NULL - terminated array of argument types. */ - -static debug_type * -stab_demangle_argtypes (dhandle, info, physname, pvarargs) - PTR dhandle; - struct stab_handle *info; - const char *physname; - boolean *pvarargs; -{ - struct stab_demangle_info minfo; - - minfo.dhandle = dhandle; - minfo.info = info; - minfo.args = NULL; - minfo.varargs = false; - minfo.typestring_alloc = 10; - minfo.typestrings = ((struct stab_demangle_typestring *) - xmalloc (minfo.typestring_alloc - * sizeof *minfo.typestrings)); - minfo.typestring_count = 0; - - /* cplus_demangle checks for special GNU mangled forms, but we can't - see any of them in mangled method argument types. */ - - if (! stab_demangle_prefix (&minfo, &physname)) - goto error_return; - - if (*physname != '\0') - { - if (! stab_demangle_signature (&minfo, &physname)) - goto error_return; - } - - free (minfo.typestrings); - minfo.typestrings = NULL; - - if (minfo.args == NULL) - fprintf (stderr, "no argument types in mangled string\n"); - - *pvarargs = minfo.varargs; - return minfo.args; - - error_return: - if (minfo.typestrings != NULL) - free (minfo.typestrings); - return NULL; -} - -/* Demangle the prefix of the mangled name. */ - -static boolean -stab_demangle_prefix (minfo, pp) - struct stab_demangle_info *minfo; - const char **pp; -{ - const char *scan; - unsigned int i; - - /* cplus_demangle checks for global constructors and destructors, - but we can't see them in mangled argument types. */ - - /* Look for `__'. */ - scan = *pp; - do - { - scan = strchr (scan, '_'); - } - while (scan != NULL && *++scan != '_'); - - if (scan == NULL) - { - stab_bad_demangle (*pp); - return false; - } - - --scan; - - /* We found `__'; move ahead to the last contiguous `__' pair. */ - i = strspn (scan, "_"); - if (i > 2) - scan += i - 2; - - if (scan == *pp - && (isdigit ((unsigned char) scan[2]) - || scan[2] == 'Q' - || scan[2] == 't')) - { - /* This is a GNU style constructor name. */ - *pp = scan + 2; - return true; - } - else if (scan == *pp - && ! isdigit ((unsigned char) scan[2]) - && scan[2] != 't') - { - /* Look for the `__' that separates the prefix from the - signature. */ - while (*scan == '_') - ++scan; - scan = strstr (scan, "__"); - if (scan == NULL || scan[2] == '\0') - { - stab_bad_demangle (*pp); - return false; - } - - return stab_demangle_function_name (minfo, pp, scan); - } - else if (scan[2] != '\0') - { - /* The name doesn't start with `__', but it does contain `__'. */ - return stab_demangle_function_name (minfo, pp, scan); - } - else - { - stab_bad_demangle (*pp); - return false; - } - /*NOTREACHED*/ -} - -/* Demangle a function name prefix. The scan argument points to the - double underscore which separates the function name from the - signature. */ - -static boolean -stab_demangle_function_name (minfo, pp, scan) - struct stab_demangle_info *minfo; - const char **pp; - const char *scan; -{ - const char *name; - - /* The string from *pp to scan is the name of the function. We - don't care about the name, since we just looking for argument - types. However, for conversion operators, the name may include a - type which we must remember in order to handle backreferences. */ - - name = *pp; - *pp = scan + 2; - - if (*pp - name >= 5 - && strncmp (name, "type", 4) == 0 - && (name[4] == '$' || name[4] == '.')) - { - const char *tem; - - /* This is a type conversion operator. */ - tem = name + 5; - if (! stab_demangle_type (minfo, &tem, (debug_type *) NULL)) - return false; - } - else if (name[0] == '_' - && name[1] == '_' - && name[2] == 'o' - && name[3] == 'p') - { - const char *tem; - - /* This is a type conversion operator. */ - tem = name + 4; - if (! stab_demangle_type (minfo, &tem, (debug_type *) NULL)) - return false; - } - - return true; -} - -/* Demangle the signature. This is where the argument types are - found. */ - -static boolean -stab_demangle_signature (minfo, pp) - struct stab_demangle_info *minfo; - const char **pp; -{ - const char *orig; - boolean expect_func, func_done; - const char *hold; - - orig = *pp; - - expect_func = false; - func_done = false; - hold = NULL; - - while (**pp != '\0') - { - switch (**pp) - { - case 'Q': - hold = *pp; - if (! stab_demangle_qualified (minfo, pp, (debug_type *) NULL) - || ! stab_demangle_remember_type (minfo, hold, *pp - hold)) - return false; - expect_func = true; - hold = NULL; - break; - - case 'S': - /* Static member function. FIXME: Can this happen? */ - if (hold == NULL) - hold = *pp; - ++*pp; - break; - - case 'C': - /* Const member function. */ - if (hold == NULL) - hold = *pp; - ++*pp; - break; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - if (hold == NULL) - hold = *pp; - if (! stab_demangle_class (minfo, pp, (const char **) NULL) - || ! stab_demangle_remember_type (minfo, hold, *pp - hold)) - return false; - expect_func = true; - hold = NULL; - break; - - case 'F': - /* Function. I don't know if this actually happens with g++ - output. */ - hold = NULL; - func_done = true; - ++*pp; - if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs)) - return false; - break; - - case 't': - /* Template. */ - if (hold == NULL) - hold = *pp; - if (! stab_demangle_template (minfo, pp) - || ! stab_demangle_remember_type (minfo, hold, *pp - hold)) - return false; - hold = NULL; - expect_func = true; - break; - - case '_': - /* At the outermost level, we cannot have a return type - specified, so if we run into another '_' at this point we - are dealing with a mangled name that is either bogus, or - has been mangled by some algorithm we don't know how to - deal with. So just reject the entire demangling. */ - stab_bad_demangle (orig); - return false; - - default: - /* Assume we have stumbled onto the first outermost function - argument token, and start processing args. */ - func_done = true; - if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs)) - return false; - break; - } - - if (expect_func) - { - func_done = true; - if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs)) - return false; - } - } - - if (! func_done) - { - /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and - bar__3fooi is 'foo::bar(int)'. We get here when we find the - first case, and need to ensure that the '(void)' gets added - to the current declp. */ - if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs)) - return false; - } - - return true; -} - -/* Demangle a qualified name, such as "Q25Outer5Inner" which is the - mangled form of "Outer::Inner". */ - -static boolean -stab_demangle_qualified (minfo, pp, ptype) - struct stab_demangle_info *minfo; - const char **pp; - debug_type *ptype; -{ - const char *orig; - const char *p; - unsigned int qualifiers; - debug_type context; - - orig = *pp; - - switch ((*pp)[1]) - { - case '_': - /* GNU mangled name with more than 9 classes. The count is - preceded by an underscore (to distinguish it from the <= 9 - case) and followed by an underscore. */ - p = *pp + 2; - if (! isdigit ((unsigned char) *p) || *p == '0') - { - stab_bad_demangle (orig); - return false; - } - qualifiers = atoi (p); - while (isdigit ((unsigned char) *p)) - ++p; - if (*p != '_') - { - stab_bad_demangle (orig); - return false; - } - *pp = p + 1; - break; - - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - qualifiers = (*pp)[1] - '0'; - /* Skip an optional underscore after the count. */ - if ((*pp)[2] == '_') - ++*pp; - *pp += 2; - break; - - case '0': - default: - stab_bad_demangle (orig); - return false; - } - - context = DEBUG_TYPE_NULL; - - /* Pick off the names. */ - while (qualifiers-- > 0) - { - if (**pp == '_') - ++*pp; - if (**pp == 't') - { - /* FIXME: I don't know how to handle the ptype != NULL case - here. */ - if (! stab_demangle_template (minfo, pp)) - return false; - } - else - { - unsigned int len; - - len = stab_demangle_count (pp); - if (strlen (*pp) < len) - { - stab_bad_demangle (orig); - return false; - } - - if (ptype != NULL) - { - const debug_field *fields; - - fields = NULL; - if (context != DEBUG_TYPE_NULL) - fields = debug_get_fields (minfo->dhandle, context); - - context = DEBUG_TYPE_NULL; - - if (fields != NULL) - { - char *name; - - /* Try to find the type by looking through the - fields of context until we find a field with the - same type. This ought to work for a class - defined within a class, but it won't work for, - e.g., an enum defined within a class. stabs does - not give us enough information to figure out the - latter case. */ - - name = savestring (*pp, len); - - for (; *fields != DEBUG_FIELD_NULL; fields++) - { - debug_type ft; - const char *dn; - - ft = debug_get_field_type (minfo->dhandle, *fields); - if (ft == NULL) - return false; - dn = debug_get_type_name (minfo->dhandle, ft); - if (dn != NULL && strcmp (dn, name) == 0) - { - context = ft; - break; - } - } - - free (name); - } - - if (context == DEBUG_TYPE_NULL) - { - /* We have to fall back on finding the type by name. - If there are more types to come, then this must - be a class. Otherwise, it could be anything. */ - - if (qualifiers == 0) - { - char *name; - - name = savestring (*pp, len); - context = debug_find_named_type (minfo->dhandle, - name); - free (name); - } - - if (context == DEBUG_TYPE_NULL) - { - context = stab_find_tagged_type (minfo->dhandle, - minfo->info, - *pp, len, - (qualifiers == 0 - ? DEBUG_KIND_ILLEGAL - : DEBUG_KIND_CLASS)); - if (context == DEBUG_TYPE_NULL) - return false; - } - } - } - - *pp += len; - } - } - - if (ptype != NULL) - *ptype = context; - - return true; -} - -/* Demangle a template. */ - -static boolean -stab_demangle_template (minfo, pp) - struct stab_demangle_info *minfo; - const char **pp; -{ - const char *orig; - unsigned int r, i; - - orig = *pp; - - ++*pp; - - /* Skip the template name. */ - r = stab_demangle_count (pp); - if (r == 0 || strlen (*pp) < r) - { - stab_bad_demangle (orig); - return false; - } - *pp += r; - - /* Get the size of the parameter list. */ - if (stab_demangle_get_count (pp, &r) == 0) - { - stab_bad_demangle (orig); - return false; - } - - for (i = 0; i < r; i++) - { - if (**pp == 'Z') - { - /* This is a type parameter. */ - ++*pp; - if (! stab_demangle_type (minfo, pp, (debug_type *) NULL)) - return false; - } - else - { - const char *old_p; - boolean pointerp, realp, integralp, charp, boolp; - boolean done; - - old_p = *pp; - pointerp = false; - realp = false; - integralp = false; - charp = false; - boolp = false; - done = false; - - /* This is a value parameter. */ - - if (! stab_demangle_type (minfo, pp, (debug_type *) NULL)) - return false; - - while (*old_p != '\0' && ! done) - { - switch (*old_p) - { - case 'P': - case 'p': - case 'R': - pointerp = true; - done = true; - break; - case 'C': /* Const. */ - case 'S': /* Signed. */ - case 'U': /* Unsigned. */ - case 'V': /* Volatile. */ - case 'F': /* Function. */ - case 'M': /* Member function. */ - case 'O': /* ??? */ - ++old_p; - break; - case 'Q': /* Qualified name. */ - integralp = true; - done = true; - break; - case 'T': /* Remembered type. */ - abort (); - case 'v': /* Void. */ - abort (); - case 'x': /* Long long. */ - case 'l': /* Long. */ - case 'i': /* Int. */ - case 's': /* Short. */ - case 'w': /* Wchar_t. */ - integralp = true; - done = true; - break; - case 'b': /* Bool. */ - boolp = true; - done = true; - break; - case 'c': /* Char. */ - charp = true; - done = true; - break; - case 'r': /* Long double. */ - case 'd': /* Double. */ - case 'f': /* Float. */ - realp = true; - done = true; - break; - default: - /* Assume it's a user defined integral type. */ - integralp = true; - done = true; - break; - } - } - - if (integralp) - { - if (**pp == 'm') - ++*pp; - while (isdigit ((unsigned char) **pp)) - ++*pp; - } - else if (charp) - { - unsigned int val; - - if (**pp == 'm') - ++*pp; - val = stab_demangle_count (pp); - if (val == 0) - { - stab_bad_demangle (orig); - return false; - } - } - else if (boolp) - { - unsigned int val; - - val = stab_demangle_count (pp); - if (val != 0 && val != 1) - { - stab_bad_demangle (orig); - return false; - } - } - else if (realp) - { - if (**pp == 'm') - ++*pp; - while (isdigit ((unsigned char) **pp)) - ++*pp; - if (**pp == '.') - { - ++*pp; - while (isdigit ((unsigned char) **pp)) - ++*pp; - } - if (**pp == 'e') - { - ++*pp; - while (isdigit ((unsigned char) **pp)) - ++*pp; - } - } - else if (pointerp) - { - unsigned int len; - - if (! stab_demangle_get_count (pp, &len)) - { - stab_bad_demangle (orig); - return false; - } - *pp += len; - } - } - } - - return true; -} - -/* Demangle a class name. */ - -static boolean -stab_demangle_class (minfo, pp, pstart) - struct stab_demangle_info *minfo; - const char **pp; - const char **pstart; -{ - const char *orig; - unsigned int n; - - orig = *pp; - - n = stab_demangle_count (pp); - if (strlen (*pp) < n) - { - stab_bad_demangle (orig); - return false; - } - - if (pstart != NULL) - *pstart = *pp; - - *pp += n; - - return true; -} - -/* Demangle function arguments. If the pargs argument is not NULL, it - is set to a NULL terminated array holding the arguments. */ - -static boolean -stab_demangle_args (minfo, pp, pargs, pvarargs) - struct stab_demangle_info *minfo; - const char **pp; - debug_type **pargs; - boolean *pvarargs; -{ - const char *orig; - unsigned int alloc, count; - - orig = *pp; - - alloc = 10; - if (pargs != NULL) - { - *pargs = (debug_type *) xmalloc (alloc * sizeof **pargs); - *pvarargs = false; - } - count = 0; - - while (**pp != '_' && **pp != '\0' && **pp != 'e') - { - if (**pp == 'N' || **pp == 'T') - { - char temptype; - unsigned int r, t; - - temptype = **pp; - ++*pp; - - if (temptype == 'T') - r = 1; - else - { - if (! stab_demangle_get_count (pp, &r)) - { - stab_bad_demangle (orig); - return false; - } - } - - if (! stab_demangle_get_count (pp, &t)) - { - stab_bad_demangle (orig); - return false; - } - - if (t >= minfo->typestring_count) - { - stab_bad_demangle (orig); - return false; - } - while (r-- > 0) - { - const char *tem; - - tem = minfo->typestrings[t].typestring; - if (! stab_demangle_arg (minfo, &tem, pargs, &count, &alloc)) - return false; - } - } - else - { - if (! stab_demangle_arg (minfo, pp, pargs, &count, &alloc)) - return false; - } - } - - if (pargs != NULL) - (*pargs)[count] = DEBUG_TYPE_NULL; - - if (**pp == 'e') - { - if (pargs != NULL) - *pvarargs = true; - ++*pp; - } - - return true; -} - -/* Demangle a single argument. */ - -static boolean -stab_demangle_arg (minfo, pp, pargs, pcount, palloc) - struct stab_demangle_info *minfo; - const char **pp; - debug_type **pargs; - unsigned int *pcount; - unsigned int *palloc; -{ - const char *start; - debug_type type; - - start = *pp; - if (! stab_demangle_type (minfo, pp, - pargs == NULL ? (debug_type *) NULL : &type) - || ! stab_demangle_remember_type (minfo, start, *pp - start)) - return false; - - if (pargs != NULL) - { - if (type == DEBUG_TYPE_NULL) - return false; - - if (*pcount + 1 >= *palloc) - { - *palloc += 10; - *pargs = ((debug_type *) - xrealloc (*pargs, *palloc * sizeof **pargs)); - } - (*pargs)[*pcount] = type; - ++*pcount; - } - - return true; -} - -/* Demangle a type. If the ptype argument is not NULL, *ptype is set - to the newly allocated type. */ - -static boolean -stab_demangle_type (minfo, pp, ptype) - struct stab_demangle_info *minfo; - const char **pp; - debug_type *ptype; -{ - const char *orig; - - orig = *pp; - - switch (**pp) - { - case 'P': - case 'p': - /* A pointer type. */ - ++*pp; - if (! stab_demangle_type (minfo, pp, ptype)) - return false; - if (ptype != NULL) - *ptype = debug_make_pointer_type (minfo->dhandle, *ptype); - break; - - case 'R': - /* A reference type. */ - ++*pp; - if (! stab_demangle_type (minfo, pp, ptype)) - return false; - if (ptype != NULL) - *ptype = debug_make_reference_type (minfo->dhandle, *ptype); - break; - - case 'A': - /* An array. */ - { - unsigned long high; - - ++*pp; - high = 0; - while (**pp != '\0' && **pp != '_') - { - if (! isdigit ((unsigned char) **pp)) - { - stab_bad_demangle (orig); - return false; - } - high *= 10; - high += **pp - '0'; - ++*pp; - } - if (**pp != '_') - { - stab_bad_demangle (orig); - return false; - } - ++*pp; - - if (! stab_demangle_type (minfo, pp, ptype)) - return false; - if (ptype != NULL) - { - debug_type int_type; - - int_type = debug_find_named_type (minfo->dhandle, "int"); - if (int_type == NULL) - int_type = debug_make_int_type (minfo->dhandle, 4, false); - *ptype = debug_make_array_type (minfo->dhandle, *ptype, int_type, - 0, high, false); - } - } - break; - - case 'T': - /* A back reference to a remembered type. */ - { - unsigned int i; - const char *p; - - ++*pp; - if (! stab_demangle_get_count (pp, &i)) - { - stab_bad_demangle (orig); - return false; - } - if (i >= minfo->typestring_count) - { - stab_bad_demangle (orig); - return false; - } - p = minfo->typestrings[i].typestring; - if (! stab_demangle_type (minfo, &p, ptype)) - return false; - } - break; - - case 'F': - /* A function. */ - { - debug_type *args; - boolean varargs; - - ++*pp; - if (! stab_demangle_args (minfo, pp, - (ptype == NULL - ? (debug_type **) NULL - : &args), - (ptype == NULL - ? (boolean *) NULL - : &varargs))) - return false; - if (**pp != '_') - { - /* cplus_demangle will accept a function without a return - type, but I don't know when that will happen, or what - to do if it does. */ - stab_bad_demangle (orig); - return false; - } - ++*pp; - if (! stab_demangle_type (minfo, pp, ptype)) - return false; - if (ptype != NULL) - *ptype = debug_make_function_type (minfo->dhandle, *ptype, args, - varargs); - - } - break; - - case 'M': - case 'O': - { - boolean memberp, constp, volatilep; - debug_type *args; - boolean varargs; - unsigned int n; - const char *name; - - memberp = **pp == 'M'; - constp = false; - volatilep = false; - args = NULL; - varargs = false; - - ++*pp; - if (! isdigit ((unsigned char) **pp)) - { - stab_bad_demangle (orig); - return false; - } - n = stab_demangle_count (pp); - if (strlen (*pp) < n) - { - stab_bad_demangle (orig); - return false; - } - name = *pp; - *pp += n; - - if (memberp) - { - if (**pp == 'C') - { - constp = true; - ++*pp; - } - else if (**pp == 'V') - { - volatilep = true; - ++*pp; - } - if (**pp != 'F') - { - stab_bad_demangle (orig); - return false; - } - ++*pp; - if (! stab_demangle_args (minfo, pp, - (ptype == NULL - ? (debug_type **) NULL - : &args), - (ptype == NULL - ? (boolean *) NULL - : &varargs))) - return false; - } - - if (**pp != '_') - { - stab_bad_demangle (orig); - return false; - } - ++*pp; - - if (! stab_demangle_type (minfo, pp, ptype)) - return false; - - if (ptype != NULL) - { - debug_type class_type; - - class_type = stab_find_tagged_type (minfo->dhandle, minfo->info, - name, (int) n, - DEBUG_KIND_CLASS); - if (class_type == DEBUG_TYPE_NULL) - return false; - - if (! memberp) - *ptype = debug_make_offset_type (minfo->dhandle, class_type, - *ptype); - else - { - /* FIXME: We have no way to record constp or - volatilep. */ - *ptype = debug_make_method_type (minfo->dhandle, *ptype, - class_type, args, varargs); - } - } - } - break; - - case 'G': - ++*pp; - if (! stab_demangle_type (minfo, pp, ptype)) - return false; - break; - - case 'C': - ++*pp; - if (! stab_demangle_type (minfo, pp, ptype)) - return false; - if (ptype != NULL) - *ptype = debug_make_const_type (minfo->dhandle, *ptype); - break; - - case 'Q': - { - const char *hold; - - hold = *pp; - if (! stab_demangle_qualified (minfo, pp, ptype)) - return false; - } - break; - - default: - if (! stab_demangle_fund_type (minfo, pp, ptype)) - return false; - break; - } - - return true; -} - -/* Demangle a fundamental type. If the ptype argument is not NULL, - *ptype is set to the newly allocated type. */ - -static boolean -stab_demangle_fund_type (minfo, pp, ptype) - struct stab_demangle_info *minfo; - const char **pp; - debug_type *ptype; -{ - const char *orig; - boolean constp, volatilep, unsignedp, signedp; - boolean done; - - orig = *pp; - - constp = false; - volatilep = false; - unsignedp = false; - signedp = false; - - done = false; - while (! done) - { - switch (**pp) - { - case 'C': - constp = true; - ++*pp; - break; - - case 'U': - unsignedp = true; - ++*pp; - break; - - case 'S': - signedp = true; - ++*pp; - break; - - case 'V': - volatilep = true; - ++*pp; - break; - - default: - done = true; - break; - } - } - - switch (**pp) - { - case '\0': - case '_': - /* cplus_demangle permits this, but I don't know what it means. */ - stab_bad_demangle (orig); - break; - - case 'v': /* void */ - if (ptype != NULL) - { - *ptype = debug_find_named_type (minfo->dhandle, "void"); - if (*ptype == DEBUG_TYPE_NULL) - *ptype = debug_make_void_type (minfo->dhandle); - } - ++*pp; - break; - - case 'x': /* long long */ - if (ptype != NULL) - { - *ptype = debug_find_named_type (minfo->dhandle, - (unsignedp - ? "long long unsigned int" - : "long long int")); - if (*ptype == DEBUG_TYPE_NULL) - *ptype = debug_make_int_type (minfo->dhandle, 8, unsignedp); - } - ++*pp; - break; - - case 'l': /* long */ - if (ptype != NULL) - { - *ptype = debug_find_named_type (minfo->dhandle, - (unsignedp - ? "long unsigned int" - : "long int")); - if (*ptype == DEBUG_TYPE_NULL) - *ptype = debug_make_int_type (minfo->dhandle, 4, unsignedp); - } - ++*pp; - break; - - case 'i': /* int */ - if (ptype != NULL) - { - *ptype = debug_find_named_type (minfo->dhandle, - (unsignedp - ? "unsigned int" - : "int")); - if (*ptype == DEBUG_TYPE_NULL) - *ptype = debug_make_int_type (minfo->dhandle, 4, unsignedp); - } - ++*pp; - break; - - case 's': /* short */ - if (ptype != NULL) - { - *ptype = debug_find_named_type (minfo->dhandle, - (unsignedp - ? "short unsigned int" - : "short int")); - if (*ptype == DEBUG_TYPE_NULL) - *ptype = debug_make_int_type (minfo->dhandle, 2, unsignedp); - } - ++*pp; - break; - - case 'b': /* bool */ - if (ptype != NULL) - { - *ptype = debug_find_named_type (minfo->dhandle, "bool"); - if (*ptype == DEBUG_TYPE_NULL) - *ptype = debug_make_bool_type (minfo->dhandle, 4); - } - ++*pp; - break; - - case 'c': /* char */ - if (ptype != NULL) - { - *ptype = debug_find_named_type (minfo->dhandle, - (unsignedp - ? "unsigned char" - : (signedp - ? "signed char" - : "char"))); - if (*ptype == DEBUG_TYPE_NULL) - *ptype = debug_make_int_type (minfo->dhandle, 1, unsignedp); - } - ++*pp; - break; - - case 'w': /* wchar_t */ - if (ptype != NULL) - { - *ptype = debug_find_named_type (minfo->dhandle, "__wchar_t"); - if (*ptype == DEBUG_TYPE_NULL) - *ptype = debug_make_int_type (minfo->dhandle, 2, true); - } - ++*pp; - break; - - case 'r': /* long double */ - if (ptype != NULL) - { - *ptype = debug_find_named_type (minfo->dhandle, "long double"); - if (*ptype == DEBUG_TYPE_NULL) - *ptype = debug_make_float_type (minfo->dhandle, 8); - } - ++*pp; - break; - - case 'd': /* double */ - if (ptype != NULL) - { - *ptype = debug_find_named_type (minfo->dhandle, "double"); - if (*ptype == DEBUG_TYPE_NULL) - *ptype = debug_make_float_type (minfo->dhandle, 8); - } - ++*pp; - break; - - case 'f': /* float */ - if (ptype != NULL) - { - *ptype = debug_find_named_type (minfo->dhandle, "float"); - if (*ptype == DEBUG_TYPE_NULL) - *ptype = debug_make_float_type (minfo->dhandle, 4); - } - ++*pp; - break; - - case 'G': - ++*pp; - if (! isdigit ((unsigned char) **pp)) - { - stab_bad_demangle (orig); - return false; - } - /* Fall through. */ - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - { - const char *hold; - - if (! stab_demangle_class (minfo, pp, &hold)) - return false; - if (ptype != NULL) - { - char *name; - - name = savestring (hold, *pp - hold); - *ptype = debug_find_named_type (minfo->dhandle, name); - if (*ptype == DEBUG_TYPE_NULL) - { - /* FIXME: It is probably incorrect to assume that - undefined types are tagged types. */ - *ptype = stab_find_tagged_type (minfo->dhandle, minfo->info, - hold, *pp - hold, - DEBUG_KIND_ILLEGAL); - } - free (name); - } - } - break; - - case 't': - if (! stab_demangle_template (minfo, pp)) - return false; - if (ptype != NULL) - { - debug_type t; - - /* FIXME: I really don't know how a template should be - represented in the current type system. Perhaps the - template should be demangled into a string, and the type - should be represented as a named type. However, I don't - know what the base type of the named type should be. */ - t = debug_make_void_type (minfo->dhandle); - t = debug_make_pointer_type (minfo->dhandle, t); - t = debug_name_type (minfo->dhandle, "TEMPLATE", t); - *ptype = t; - } - break; - - default: - stab_bad_demangle (orig); - return false; - } - - if (ptype != NULL) - { - if (constp) - *ptype = debug_make_const_type (minfo->dhandle, *ptype); - if (volatilep) - *ptype = debug_make_volatile_type (minfo->dhandle, *ptype); - } - - return true; -} - -/* Remember a type string in a demangled string. */ - -static boolean -stab_demangle_remember_type (minfo, p, len) - struct stab_demangle_info *minfo; - const char *p; - int len; -{ - if (minfo->typestring_count >= minfo->typestring_alloc) - { - minfo->typestring_alloc += 10; - minfo->typestrings = ((struct stab_demangle_typestring *) - xrealloc (minfo->typestrings, - (minfo->typestring_alloc - * sizeof *minfo->typestrings))); - } - - minfo->typestrings[minfo->typestring_count].typestring = p; - minfo->typestrings[minfo->typestring_count].len = (unsigned int) len; - ++minfo->typestring_count; - - return true; -} diff --git a/regex/regexec.c b/regex/regexec.c index 338c1bfa7fe..c0d03335b41 100644 --- a/regex/regexec.c +++ b/regex/regexec.c @@ -117,6 +117,7 @@ size_t nmatch; my_regmatch_t pmatch[]; int eflags; { + char *pstr = (char *) str; register struct re_guts *g = preg->re_g; #ifdef REDEBUG # define GOODFLAGS(f) (f) @@ -133,7 +134,7 @@ int eflags; if ((size_t) g->nstates <= CHAR_BIT*sizeof(states1) && !(eflags®_LARGE)) - return(smatcher(preg->charset, g, (char *)str, nmatch, pmatch, eflags)); + return(smatcher(preg->charset, g, pstr, nmatch, pmatch, eflags)); else - return(lmatcher(preg->charset, g, (char *)str, nmatch, pmatch, eflags)); + return(lmatcher(preg->charset, g, pstr, nmatch, pmatch, eflags)); } diff --git a/sql/Makefile.am b/sql/Makefile.am index 0b22481f850..40a3565cb91 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -41,7 +41,6 @@ mysqld_DEPENDENCIES= @mysql_plugin_libs@ $(SUPPORTING_LIBS) libndb.la LDADD = $(SUPPORTING_LIBS) @ZLIB_LIBS@ @NDB_SCI_LIBS@ mysqld_LDADD = libndb.la \ @MYSQLD_EXTRA_LDFLAGS@ \ - @pstack_libs@ \ @mysql_plugin_libs@ \ $(LDADD) $(CXXLDFLAGS) $(WRAPLIBS) @LIBDL@ \ $(yassl_libs) $(openssl_libs) @MYSQLD_EXTRA_LIBS@ diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc index 23a649a89fa..91c850c6009 100644 --- a/sql/debug_sync.cc +++ b/sql/debug_sync.cc @@ -1718,7 +1718,7 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) if (action->execute) { - const char *old_proc_info; + const char *UNINIT_VAR(old_proc_info); action->execute--; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 155d457de6b..7bcbd241541 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3050,7 +3050,9 @@ int ha_partition::write_row(uchar * buf) my_bitmap_map *old_map; HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data; THD *thd= ha_thd(); - timestamp_auto_set_type orig_timestamp_type= table->timestamp_field_type; + timestamp_auto_set_type saved_timestamp_type= table->timestamp_field_type; + ulong saved_sql_mode= thd->variables.sql_mode; + bool saved_auto_inc_field_not_null= table->auto_increment_field_not_null; #ifdef NOT_NEEDED uchar *rec0= m_rec0; #endif @@ -3086,6 +3088,22 @@ int ha_partition::write_row(uchar * buf) */ if (error) goto exit; + + /* + Don't allow generation of auto_increment value the partitions handler. + If a partitions handler would change the value, then it might not + match the partition any longer. + This can occur if 'SET INSERT_ID = 0; INSERT (NULL)', + So allow this by adding 'MODE_NO_AUTO_VALUE_ON_ZERO' to sql_mode. + The partitions handler::next_insert_id must always be 0. Otherwise + we need to forward release_auto_increment, or reset it for all + partitions. + */ + if (table->next_number_field->val_int() == 0) + { + table->auto_increment_field_not_null= TRUE; + thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO; + } } old_map= dbug_tmp_use_all_columns(table, table->read_set); @@ -3119,7 +3137,9 @@ int ha_partition::write_row(uchar * buf) set_auto_increment_if_higher(table->next_number_field); reenable_binlog(thd); exit: - table->timestamp_field_type= orig_timestamp_type; + thd->variables.sql_mode= saved_sql_mode; + table->auto_increment_field_not_null= saved_auto_inc_field_not_null; + table->timestamp_field_type= saved_timestamp_type; DBUG_RETURN(error); } @@ -3186,11 +3206,24 @@ int ha_partition::update_row(const uchar *old_data, uchar *new_data) } else { + Field *saved_next_number_field= table->next_number_field; + /* + Don't allow generation of auto_increment value for update. + table->next_number_field is never set on UPDATE. + But is set for INSERT ... ON DUPLICATE KEY UPDATE, + and since update_row() does not generate or update an auto_inc value, + we cannot have next_number_field set when moving a row + to another partition with write_row(), since that could + generate/update the auto_inc value. + This gives the same behavior for partitioned vs non partitioned tables. + */ + table->next_number_field= NULL; DBUG_PRINT("info", ("Update from partition %d to partition %d", old_part_id, new_part_id)); tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */ error= m_file[new_part_id]->ha_write_row(new_data); reenable_binlog(thd); + table->next_number_field= saved_next_number_field; if (error) goto exit; diff --git a/sql/handler.cc b/sql/handler.cc index a47a5fd8a3c..1525ca53bca 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -4141,7 +4141,7 @@ int handler::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, */ int handler::read_multi_range_next(KEY_MULTI_RANGE **found_range_p) { - int result; + int UNINIT_VAR(result); DBUG_ENTER("handler::read_multi_range_next"); /* We should not be called after the last call returned EOF. */ diff --git a/sql/item_func.cc b/sql/item_func.cc index 3dbff43bb67..f8c6f48d8f5 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -157,7 +157,14 @@ Item_func::fix_fields(THD *thd, Item **ref) used_tables_cache= not_null_tables_cache= 0; const_item_cache=1; - if (check_stack_overrun(thd, STACK_MIN_SIZE, buff)) + /* + Use stack limit of STACK_MIN_SIZE * 2 since + on some platforms a recursive call to fix_fields + requires more than STACK_MIN_SIZE bytes (e.g. for + MIPS, it takes about 22kB to make one recursive + call to Item_func::fix_fields()) + */ + if (check_stack_overrun(thd, STACK_MIN_SIZE * 2, buff)) return TRUE; // Fatal error if flag is set! if (arg_count) { // Print purify happy diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index ef86406e1be..47bb9509582 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -331,6 +331,7 @@ public: const char *func_name() const { return "time_to_sec"; } void fix_length_and_dec() { + maybe_null= TRUE; decimals=0; max_length=10*MY_CHARSET_BIN_MB_MAXLEN; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d9c4c7fc3f5..d17ccc47abb 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -70,10 +70,8 @@ #endif /* stack traces are only supported on linux intel */ -#if defined(__linux__) && defined(__i386__) && defined(USE_PSTACK) +#if defined(__linux__) && defined(__i386__) #define HAVE_STACK_TRACE_ON_SEGV -#include "../pstack/pstack.h" -char pstack_file_name[80]; #endif /* __linux__ */ /* We have HAVE_purify below as this speeds up the shutdown of MySQL */ @@ -2779,14 +2777,6 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) if (!opt_bootstrap) create_pid_file(); -#ifdef HAVE_STACK_TRACE_ON_SEGV - if (opt_do_pstack) - { - sprintf(pstack_file_name,"mysqld-%lu-%%d-%%d.backtrace", (ulong)getpid()); - pstack_install_segv_action(pstack_file_name); - } -#endif /* HAVE_STACK_TRACE_ON_SEGV */ - /* signal to start_signal_handler that we are ready This works by waiting for start_signal_handler to free mutex, @@ -5963,9 +5953,10 @@ struct my_option my_long_options[] = NO_ARG, 0, 0, 0, 0, 0, 0}, #endif #ifdef HAVE_STACK_TRACE_ON_SEGV - {"enable-pstack", OPT_DO_PSTACK, "Print a symbolic stack trace on failure.", - &opt_do_pstack, &opt_do_pstack, 0, GET_BOOL, NO_ARG, 0, 0, - 0, 0, 0, 0}, + {"enable-pstack", OPT_DO_PSTACK, "Print a symbolic stack trace on failure. " + "This option is deprecated and has no effect; a symbolic stack trace will " + "be printed after a crash whenever possible.", &opt_do_pstack, &opt_do_pstack, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_STACK_TRACE_ON_SEGV */ {"engine-condition-pushdown", OPT_ENGINE_CONDITION_PUSHDOWN, @@ -8654,6 +8645,13 @@ mysqld_get_one_option(int optid, lower_case_table_names= argument ? atoi(argument) : 1; lower_case_table_names_used= 1; break; +#ifdef HAVE_STACK_TRACE_ON_SEGV + case OPT_DO_PSTACK: + sql_print_warning("'--enable-pstack' is deprecated and will be removed " + "in a future release. A symbolic stack trace will be " + "printed after a crash whenever possible."); + break; +#endif #if defined(ENABLED_DEBUG_SYNC) case OPT_DEBUG_SYNC_TIMEOUT: /* diff --git a/sql/slave.cc b/sql/slave.cc index 57d673ea1f4..644aade517c 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2321,7 +2321,7 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli) if (slave_trans_retries) { - int temp_err; + int UNINIT_VAR(temp_err); if (exec_res && (temp_err= has_temporary_error(thd))) { const char *errmsg; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 66d5eff5112..2473abea3c7 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1372,7 +1372,7 @@ sp_head::execute(THD *thd) If the DB has changed, the pointer has changed too, but the original thd->db will then have been freed */ - if (cur_db_changed && !thd->killed) + if (cur_db_changed && thd->killed != THD::KILL_CONNECTION) { /* Force switching back to the saved current database, because it may be diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index d6f05bf5407..48d50c3a303 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -6766,8 +6766,8 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info, { DBUG_ASSERT(!is_subpart); Field *field= part_info->part_field_array[0]; - uint32 max_endpoint_val; - get_endpoint_func get_endpoint; + uint32 UNINIT_VAR(max_endpoint_val); + get_endpoint_func UNINIT_VAR(get_endpoint); bool can_match_multiple_values; /* is not '=' */ uint field_len= field->pack_length_in_rec(); part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE; diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index e85e730db5b..df7054c94d0 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -99,7 +99,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) */ my_error(ER_CANT_RENAME_LOG_TABLE, MYF(0), ren_table->table_name, ren_table->table_name); - DBUG_RETURN(1); + goto err; } } else @@ -112,7 +112,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) */ my_error(ER_CANT_RENAME_LOG_TABLE, MYF(0), ren_table->table_name, ren_table->table_name); - DBUG_RETURN(1); + goto err; } else { @@ -130,7 +130,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) else my_error(ER_CANT_RENAME_LOG_TABLE, MYF(0), rename_log_table[1], rename_log_table[1]); - DBUG_RETURN(1); + goto err; } } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 9767839b5bf..1e5cd02bd51 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -15210,6 +15210,8 @@ calc_group_buffer(JOIN *join,ORDER *group) { key_length+= 8; } + else if (type == MYSQL_TYPE_BLOB) + key_length+= MAX_BLOB_WIDTH; // Can't be used as a key else { /* diff --git a/sql/sql_show.cc b/sql/sql_show.cc index e074461b452..9b344204d64 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -534,12 +534,6 @@ find_files(THD *thd, List<LEX_STRING> *files, const char *db, else if (wild_compare(uname, wild, 0)) continue; } - if (!(file_name= - thd->make_lex_string(file_name, uname, file_name_len, TRUE))) - { - my_dirend(dirp); - DBUG_RETURN(FIND_FILES_OOM); - } } else { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 971e1022d63..b919ea9eae7 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6832,7 +6832,6 @@ view_err: table->alias); } - VOID(pthread_mutex_lock(&LOCK_open)); /* Unlike to the above case close_cached_table() below will remove ALL instances of TABLE from table cache (it will also remove table lock @@ -6853,6 +6852,7 @@ view_err: */ ha_autocommit_or_rollback(thd, 0); + VOID(pthread_mutex_lock(&LOCK_open)); /* Then do a 'simple' rename of the table. First we need to close all instances of 'source' table. @@ -6885,6 +6885,8 @@ view_err: } } } + else + VOID(pthread_mutex_lock(&LOCK_open)); if (error == HA_ERR_WRONG_COMMAND) { diff --git a/storage/ibmdb2i/CMakeLists.txt b/storage/ibmdb2i/CMakeLists.txt deleted file mode 100644 index 11cc4300569..00000000000 --- a/storage/ibmdb2i/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (C) 2006 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; version 2 of the License. -# -# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") -SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") - -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql - ${CMAKE_SOURCE_DIR}/regex - ${CMAKE_SOURCE_DIR}/extra/yassl/include) -ADD_LIBRARY(ibmdb2i ha_ibmdb2i.cc db2i_ileBridge.cc db2i_conversion.cc - db2i_blobCollection.cc db2i_file.cc db2i_charsetSupport.cc - db2i_collationSupport.cc db2i_errors.cc db2i_constraints.cc - db2i_rir.cc db2i_sqlStatementStream.cc db2i_ioBuffers.cc db2i_myconv.cc) diff --git a/storage/ibmdb2i/Makefile.am b/storage/ibmdb2i/Makefile.am deleted file mode 100644 index b9602e392e0..00000000000 --- a/storage/ibmdb2i/Makefile.am +++ /dev/null @@ -1,54 +0,0 @@ -# -# Copyright (c) 2007, 2008, IBM Corporation. -# All rights reserved. -# -# - -#called from the top level Makefile - -MYSQLDATAdir = $(localstatedir) -MYSQLSHAREdir = $(pkgdatadir) -MYSQLBASEdir= $(prefix) -MYSQLLIBdir= $(pkglibdir) -pkgplugindir = $(pkglibdir)/plugin -INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \ - -I$(top_srcdir)/regex \ - -I$(top_srcdir)/sql \ - -I$(srcdir) \ - -I$ /afs/rchland.ibm.com/lande/shadow/dev2000/osxpf/v5r4m0f.xpf/cur/cmvc/base.pgm/my.xpf/apis \ - -I$ /afs/rchland.ibm.com/lande/shadow/dev2000/osxpf/v5r4m0.xpf/bld/cmvc/base.pgm/lg.xpf \ - -I$ /afs/rchland.ibm.com/lande/shadow/dev2000/osxpf/v5r4m0.xpf/bld/cmvc/base.pgm/tq.xpf -WRAPLIBS= - -LDADD = - -DEFS = @DEFS@ - -noinst_HEADERS = ha_ibmdb2i.h db2i_collationSupport.h db2i_file.h \ - db2i_ioBuffers.h db2i_blobCollection.h \ - db2i_global.h db2i_misc.h db2i_charsetSupport.h db2i_errors.h \ - db2i_iconv.h db2i_myconv.h db2i_safeString.h db2i_sqlStatementStream.h \ - db2i_ileBridge.h db2i_validatedPointer.h - -EXTRA_LTLIBRARIES = ha_ibmdb2i.la -pkgplugin_LTLIBRARIES = @plugin_ibmdb2i_shared_target@ -ha_ibmdb2i_la_LIBADD = -liconv -ha_ibmdb2i_la_LDFLAGS = -module -rpath $(MYSQLLIBdir) -ha_ibmdb2i_la_CXXFLAGS= $(AM_CXXFLAGS) -DMYSQL_DYNAMIC_PLUGIN -ha_ibmdb2i_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN -ha_ibmdb2i_la_SOURCES = ha_ibmdb2i.cc db2i_ileBridge.cc db2i_conversion.cc \ - db2i_blobCollection.cc db2i_file.cc db2i_charsetSupport.cc \ - db2i_collationSupport.cc db2i_errors.cc db2i_constraints.cc \ - db2i_rir.cc db2i_sqlStatementStream.cc db2i_ioBuffers.cc \ - db2i_myconv.cc - -EXTRA_LIBRARIES = libibmdb2i.a -noinst_LIBRARIES = @plugin_ibmdb2i_static_target@ -libibmdb2i_a_CXXFLAGS = $(AM_CXXFLAGS) -libibmdb2i_a_CFLAGS = $(AM_CFLAGS) -libibmdb2i_a_SOURCES= $(ha_ibmdb2i_la_SOURCES) - - -EXTRA_DIST = CMakeLists.txt plug.in -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/ibmdb2i/db2i_blobCollection.cc b/storage/ibmdb2i/db2i_blobCollection.cc deleted file mode 100644 index 17101c9c0a4..00000000000 --- a/storage/ibmdb2i/db2i_blobCollection.cc +++ /dev/null @@ -1,107 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - -#include "db2i_blobCollection.h" - -/** - Return the size to use when allocating space for blob reads. - - @param fieldIndex The field to allocate for - @param[out] shouldProtect Indicates whether storage protection should be - applied to the space, because the size returned is - smaller than the maximum possible size. -*/ - -uint32 -BlobCollection::getSizeToAllocate(int fieldIndex, bool& shouldProtect) -{ - Field* field = table->getMySQLTable()->field[fieldIndex]; - uint fieldLength = field->max_display_length(); - - if (fieldLength <= MAX_FULL_ALLOCATE_BLOB_LENGTH) - { - shouldProtect = false; - return fieldLength; - } - - shouldProtect = true; - - uint curMaxSize = table->getBlobFieldActualSize(fieldIndex); - - uint defaultAllocSize = min(defaultAllocation, fieldLength); - - return max(defaultAllocSize, curMaxSize); - -} - -void -BlobCollection::generateBuffer(int fieldIndex) -{ - DBUG_ASSERT(table->db2Field(fieldIndex).isBlob()); - - bool protect; - buffers[table->getBlobIdFromField(fieldIndex)].Malloc(getSizeToAllocate(fieldIndex, protect), protect); - - return; -} - -/** - Realloc the read buffer associated with a blob field. - - This is used when the previous allocation for a blob field is found to be - too small (this is discovered when QMY_READ trips over the protected boundary - page). - - @param fieldIndex The field to be reallocated - @param size The size of buffer to allocate for this field. -*/ - -ValidatedPointer<char>& -BlobCollection::reallocBuffer(int fieldIndex, size_t size) -{ - ProtectedBuffer& buf = buffers[table->getBlobIdFromField(fieldIndex)]; - if (size <= buf.allocLen()) - return buf.ptr(); - - table->updateBlobFieldActualSize(fieldIndex, size); - - DBUG_PRINT("BlobCollection::reallocBuffer",("PERF: reallocing %d to %d: ", fieldIndex, size)); - - bool protect; - buf.Free(); - buf.Malloc(getSizeToAllocate(fieldIndex, protect), protect); - return buf.ptr(); -} diff --git a/storage/ibmdb2i/db2i_blobCollection.h b/storage/ibmdb2i/db2i_blobCollection.h deleted file mode 100644 index 6a60394555f..00000000000 --- a/storage/ibmdb2i/db2i_blobCollection.h +++ /dev/null @@ -1,151 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - -#ifndef DB2I_BLOBCOLLECTION_H -#define DB2I_BLOBCOLLECTION_H - -#include "db2i_global.h" -#include "db2i_file.h" - -/** - @class ProtectedBuffer - @brief Implements memory management for (optionally) protected buffers. - - Buffers created with the protection option will have a guard page set on the - page following requested allocation size. The side effect is that the actual - allocation is up to 2*4096-1 bytes larger than the size requested by the - using code. -*/ - -class ProtectedBuffer -{ -public: - ProtectedBuffer() : protectBuf(false) - {;} - - void Malloc(size_t size, bool protect = false) - { - protectBuf = protect; - bufptr.alloc(size + (protectBuf ? 0x1fff : 0x0)); - if ((void*)bufptr != NULL) - { - len = size; - if (protectBuf) - mprotect(protectedPage(), 0x1000, PROT_NONE); -#ifndef DBUG_OFF - // Prevents a problem with DBUG_PRINT over-reading in recent versions of - // MySQL - *((char*)protectedPage()-1) = 0; -#endif - } - } - - void Free() - { - if ((void*)bufptr != NULL) - { - if (protectBuf) - mprotect(protectedPage(), 0x1000, PROT_READ | PROT_WRITE); - bufptr.dealloc(); - } - } - - ~ProtectedBuffer() - { - Free(); - } - - ValidatedPointer<char>& ptr() {return bufptr;} - bool isProtected() const {return protectBuf;} - size_t allocLen() const {return len;} -private: - void* protectedPage() - { - return (void*)(((address64_t)(void*)bufptr + len + 0x1000) & ~0xfff); - } - - ValidatedPointer<char> bufptr; - size_t len; - bool protectBuf; - -}; - - -/** - @class BlobCollection - @brief Manages memory allocation for reading blobs associated with a table. - - Allocations are done on-demand and are protected with a guard page if less - than the max possible size is allocated. -*/ -class BlobCollection -{ - public: - BlobCollection(db2i_table* db2Table, uint32 defaultAllocSize) : - defaultAllocation(defaultAllocSize), table(db2Table) - { - buffers = new ProtectedBuffer[table->getBlobCount()]; - } - - ~BlobCollection() - { - delete[] buffers; - } - - ValidatedPointer<char>& getBufferPtr(int fieldIndex) - { - int blobIndex = table->getBlobIdFromField(fieldIndex); - if ((char*)buffers[blobIndex].ptr() == NULL) - generateBuffer(fieldIndex); - - return buffers[blobIndex].ptr(); - } - - ValidatedPointer<char>& reallocBuffer(int fieldIndex, size_t size); - - - private: - - uint32 getSizeToAllocate(int fieldIndex, bool& shouldProtect); - void generateBuffer(int fieldIndex); - - db2i_table* table; // The table being read - ProtectedBuffer* buffers; // The buffers - uint32 defaultAllocation; - /* The default size to use when first allocating a buffer */ -}; - -#endif diff --git a/storage/ibmdb2i/db2i_charsetSupport.cc b/storage/ibmdb2i/db2i_charsetSupport.cc deleted file mode 100644 index 83bf1b9448b..00000000000 --- a/storage/ibmdb2i/db2i_charsetSupport.cc +++ /dev/null @@ -1,826 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - - -#include "db2i_charsetSupport.h" -#include "as400_types.h" -#include "as400_protos.h" -#include "db2i_ileBridge.h" -#include "qlgusr.h" -#include "db2i_errors.h" - - -/* - The following arrays define a mapping between IANA-style text descriptors and - IBM i CCSID text descriptors. The mapping is a 1-to-1 correlation between - corresponding array slots. -*/ -#define MAX_IANASTRING 23 -static const char ianaStringType[MAX_IANASTRING][10] = -{ - {"ascii"}, - {"Big5"}, //big5 - {"cp1250"}, - {"cp1251"}, - {"cp1256"}, - {"cp850"}, - {"cp852"}, - {"cp866"}, - {"IBM943"}, //cp932 - {"EUC-KR"}, //euckr - {"IBM1381"}, //gb2312 - {"IBM1386"}, //gbk - {"greek"}, - {"hebrew"}, - {"latin1"}, - {"latin2"}, - {"latin5"}, - {"macce"}, - {"tis620"}, - {"Shift_JIS"}, //sjis - {"ucs2"}, - {"EUC-JP"}, //ujis - {"utf8"} -}; -static const char ccsidType[MAX_IANASTRING][6] = -{ - {"367"}, //ascii - {"950"}, //big5 - {"1250"}, //cp1250 - {"1251"}, //cp1251 - {"1256"}, //cp1256 - {"850"}, //cp850 - {"852"}, //cp852 - {"866"}, //cp866 - {"943"}, //cp932 - {"970"}, //euckr - {"1381"}, //gb2312 - {"1386"}, //gbk - {"813"}, //greek - {"916"}, //hebrew - {"923"}, //latin1 - {"912"}, //latin2 - {"920"}, //latin5 - {"1282"}, //macce - {"874"}, //tis620 - {"943"}, //sjis - {"13488"},//ucs2 - {"5050"}, //ujis - {"1208"} //utf8 -}; - -static _ILEpointer *QlgCvtTextDescToDesc_sym; - -/* We keep a cache of the mapping for text descriptions obtained via - QlgTextDescToDesc. The following structures implement this cache. */ -static HASH textDescMapHash; -static MEM_ROOT textDescMapMemroot; -static pthread_mutex_t textDescMapHashMutex; -struct TextDescMap -{ - struct HashKey - { - int32 inType; - int32 outType; - char inDesc[Qlg_MaxDescSize]; - } hashKey; - char outDesc[Qlg_MaxDescSize]; -}; - -/* We keep a cache of the mapping for open iconv descriptors. The following - structures implement this cache. */ -static HASH iconvMapHash; -static MEM_ROOT iconvMapMemroot; -static pthread_mutex_t iconvMapHashMutex; -struct IconvMap -{ - struct HashKey - { - uint32 direction; // These are uint32s to avoid garbage data in the key from compiler padding - uint32 db2CCSID; - const CHARSET_INFO* myCharset; - } hashKey; - iconv_t iconvDesc; -}; - - -/** - Initialize the static structures used by this module. - - This must only be called once per plugin instantiation. - - @return 0 if successful. Failure otherwise -*/ -int32 initCharsetSupport() -{ - DBUG_ENTER("initCharsetSupport"); - - int actmark = _ILELOAD("QSYS/QLGUSR", ILELOAD_LIBOBJ); - if ( actmark == -1 ) - { - DBUG_PRINT("initCharsetSupport", ("conversion srvpgm activation failed")); - DBUG_RETURN(1); - } - - QlgCvtTextDescToDesc_sym = (ILEpointer*)malloc_aligned(sizeof(ILEpointer)); - if (_ILESYM(QlgCvtTextDescToDesc_sym, actmark, "QlgCvtTextDescToDesc") == -1) - { - DBUG_PRINT("initCharsetSupport", - ("resolve of QlgCvtTextDescToDesc failed")); - DBUG_RETURN(errno); - } - - VOID(pthread_mutex_init(&textDescMapHashMutex,MY_MUTEX_INIT_FAST)); - hash_init(&textDescMapHash, &my_charset_bin, 10, offsetof(TextDescMap, hashKey), sizeof(TextDescMap::hashKey), 0, 0, HASH_UNIQUE); - - VOID(pthread_mutex_init(&iconvMapHashMutex,MY_MUTEX_INIT_FAST)); - hash_init(&iconvMapHash, &my_charset_bin, 10, offsetof(IconvMap, hashKey), sizeof(IconvMap::hashKey), 0, 0, HASH_UNIQUE); - - init_alloc_root(&textDescMapMemroot, 2048, 0); - init_alloc_root(&iconvMapMemroot, 256, 0); - - initMyconv(); - - DBUG_RETURN(0); -} - -/** - Cleanup the static structures used by this module. - - This must only be called once per plugin instantiation and only if - initCharsetSupport() was successful. -*/ -void doneCharsetSupport() -{ - cleanupMyconv(); - - free_root(&textDescMapMemroot, 0); - free_root(&iconvMapMemroot, 0); - - pthread_mutex_destroy(&textDescMapHashMutex); - hash_free(&textDescMapHash); - pthread_mutex_destroy(&iconvMapHashMutex); - hash_free(&iconvMapHash); - free_aligned(QlgCvtTextDescToDesc_sym); -} - - -/** - Convert a text description from one type to another. - - This function is just a wrapper for the IBM i QlgTextDescToDesc function plus - some overrides for conversions that the API does not handle correctly and - support for caching the computed conversion. - - @param inType The type of descriptor pointed to by "in". - @param outType The type of descriptor requested for "out". - @param in The descriptor to be convereted. - @param[out] out The equivalent descriptor - @param hashKey The hash key to be used for caching the conversion result. - - @return 0 if successful. Failure otherwise -*/ -static int32 getNewTextDesc(const int32 inType, - const int32 outType, - const char* in, - char* out, - const TextDescMap::HashKey* hashKey) -{ - DBUG_ENTER("db2i_charsetSupport::getNewTextDesc"); - const arg_type_t signature[] = { ARG_INT32, ARG_INT32, ARG_MEMPTR, ARG_INT32, ARG_MEMPTR, ARG_INT32, ARG_INT32, ARG_END }; - struct ArgList - { - ILEarglist_base base; - int32 CRDIInType; - int32 CRDIOutType; - ILEpointer CRDIDesc; - int32 CRDIDescSize; - ILEpointer CRDODesc; - int32 CRDODescSize; - int32 CTDCCSID; - } *arguments; - - if ((inType == Qlg_TypeIANA) && (outType == Qlg_TypeAix41)) - { - // Override non-standard charsets - if (unlikely(strcmp("IBM1381", in) == 0)) - { - strcpy(out, "IBM-1381"); - DBUG_RETURN(0); - } - } - else if ((inType == Qlg_TypeAS400CCSID) && (outType == Qlg_TypeAix41)) - { - // Override non-standard charsets - if (strcmp("1148", in) == 0) - { - strcpy(out, "IBM-1148"); - DBUG_RETURN(0); - } - else if (unlikely(strcmp("1153", in) == 0)) - { - strcpy(out, "IBM-1153"); - DBUG_RETURN(0); - } - } - - char argBuf[sizeof(ArgList)+15]; - arguments = (ArgList*)roundToQuadWordBdy(argBuf); - - arguments->CRDIInType = inType; - arguments->CRDIOutType = outType; - arguments->CRDIDesc.s.addr = (address64_t) in; - arguments->CRDIDescSize = Qlg_MaxDescSize; - arguments->CRDODesc.s.addr = (address64_t) out; - arguments->CRDODescSize = Qlg_MaxDescSize; - arguments->CTDCCSID = 819; - _ILECALL(QlgCvtTextDescToDesc_sym, - &arguments->base, - signature, - RESULT_INT32); - if (unlikely(arguments->base.result.s_int32.r_int32 < 0)) - { - if (arguments->base.result.s_int32.r_int32 == Qlg_InDescriptorNotFound) - { - DBUG_RETURN(DB2I_ERR_UNSUPP_CHARSET); - } - else - { - getErrTxt(DB2I_ERR_ILECALL,"QlgCvtTextDescToDesc",arguments->base.result.s_int32.r_int32); - DBUG_RETURN(DB2I_ERR_ILECALL); - } - } - - // Store the conversion information into a cache entry - TextDescMap* mapping = (TextDescMap*)alloc_root(&textDescMapMemroot, sizeof(TextDescMap)); - if (unlikely(!mapping)) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - memcpy(&(mapping->hashKey), hashKey, sizeof(hashKey)); - strcpy(mapping->outDesc, out); - pthread_mutex_lock(&textDescMapHashMutex); - my_hash_insert(&textDescMapHash, (const uchar*)mapping); - pthread_mutex_unlock(&textDescMapHashMutex); - - DBUG_RETURN(0); -} - - -/** - Convert a text description from one type to another. - - This function takes a text description in one representation and converts - it into another representation. Although the OS provides some facilities for - doing this, the support is not complete, nor does MySQL always use standard - identifiers. Therefore, there are a lot of hardcoded overrides required. - There is probably some room for optimization here, but this should not be - called frequently under most circumstances. - - @param inType The type of descriptor pointed to by "in". - @param outType The type of descriptor requested for "out". - @param in The descriptor to be convereted. - @param[out] out The equivalent descriptor - - @return 0 if successful. Failure otherwise -*/ -static int32 convertTextDesc(const int32 inType, const int32 outType, const char* inDesc, char* outDesc) -{ - DBUG_ENTER("db2i_charsetSupport::convertTextDesc"); - const char* inDescOverride; - - if (inType == Qlg_TypeIANA) - { - // Override non-standard charsets - if (strcmp("big5", inDesc) == 0) - inDescOverride = "Big5"; - else if (strcmp("cp932", inDesc) == 0) - inDescOverride = "IBM943"; - else if (strcmp("euckr", inDesc) == 0) - inDescOverride = "EUC-KR"; - else if (strcmp("gb2312", inDesc) == 0) - inDescOverride = "IBM1381"; - else if (strcmp("gbk", inDesc) == 0) - inDescOverride = "IBM1386"; - else if (strcmp("sjis", inDesc) == 0) - inDescOverride = "Shift_JIS"; - else if (strcmp("ujis", inDesc) == 0) - inDescOverride = "EUC-JP"; - else - inDescOverride = inDesc; - - // Hardcode non-standard charsets - if (outType == Qlg_TypeAix41) - { - if (strcmp("Big5", inDescOverride) == 0) - { - strcpy(outDesc,"big5"); - DBUG_RETURN(0); - } - else if (strcmp("IBM1386", inDescOverride) == 0) - { - strcpy(outDesc,"GBK"); - DBUG_RETURN(0); - } - else if (strcmp("Shift_JIS", inDescOverride) == 0 || - strcmp("IBM943", inDescOverride) == 0) - { - strcpy(outDesc,"IBM-943"); - DBUG_RETURN(0); - } - else if (strcmp("tis620", inDescOverride) == 0) - { - strcpy(outDesc,"TIS-620"); - DBUG_RETURN(0); - } - else if (strcmp("ucs2", inDescOverride) == 0) - { - strcpy(outDesc,"UCS-2"); - DBUG_RETURN(0); - } - else if (strcmp("cp1250", inDescOverride) == 0) - { - strcpy(outDesc,"IBM-1250"); - DBUG_RETURN(0); - } - else if (strcmp("cp1251", inDescOverride) == 0) - { - strcpy(outDesc,"IBM-1251"); - DBUG_RETURN(0); - } - else if (strcmp("cp1256", inDescOverride) == 0) - { - strcpy(outDesc,"IBM-1256"); - DBUG_RETURN(0); - } - else if (strcmp("macce", inDescOverride) == 0) - { - strcpy(outDesc,"IBM-1282"); - DBUG_RETURN(0); - } - } - else if (outType == Qlg_TypeAS400CCSID) - { - // See if we can fast path the convert - for (int loopCnt = 0; loopCnt < MAX_IANASTRING; ++loopCnt) - { - if (strcmp((char*)ianaStringType[loopCnt],inDescOverride) == 0) - { - strcpy(outDesc,ccsidType[loopCnt]); - DBUG_RETURN(0); - } - } - } - } - else - inDescOverride = inDesc; - - // We call getNewTextDesc for all other conversions and cache the result. - TextDescMap *mapping; - TextDescMap::HashKey hashKey; - hashKey.inType= inType; - hashKey.outType= outType; - uint32 len = strlen(inDescOverride); - memcpy(hashKey.inDesc, inDescOverride, len); - memset(hashKey.inDesc+len, 0, sizeof(hashKey.inDesc) - len); - - if (!(mapping=(TextDescMap *) hash_search(&textDescMapHash, - (const uchar*)&hashKey, - sizeof(hashKey)))) - { - DBUG_RETURN(getNewTextDesc(inType, outType, inDescOverride, outDesc, &hashKey)); - } - else - { - strcpy(outDesc, mapping->outDesc); - } - DBUG_RETURN(0); -} - - -/** - Convert an IANA character set name into a DB2 for i CCSID value. - - @param parmIANADesc An IANA character set name - @param[out] db2Ccsid The equivalent CCSID value - - @return 0 if successful. Failure otherwise -*/ -int32 convertIANAToDb2Ccsid(const char* parmIANADesc, uint16* db2Ccsid) -{ - int32 rc; - uint16 aixCcsid; - char aixCcsidString[Qlg_MaxDescSize]; - int aixEncodingScheme; - int db2EncodingScheme; - rc = convertTextDesc(Qlg_TypeIANA, Qlg_TypeAS400CCSID, parmIANADesc, aixCcsidString); - if (unlikely(rc)) - { - if (rc == DB2I_ERR_UNSUPP_CHARSET) - getErrTxt(DB2I_ERR_UNSUPP_CHARSET, parmIANADesc); - - return rc; - } - aixCcsid = atoi(aixCcsidString); - rc = getEncodingScheme(aixCcsid, aixEncodingScheme); - if (rc != 0) - return rc; - switch(aixEncodingScheme) { // Select on encoding scheme - case 0x1100: // EDCDIC SBCS - case 0x2100: // ASCII SBCS - case 0x4100: // AIX SBCS - case 0x4105: // MS Windows - case 0x5100: // ISO 7 bit ASCII - db2EncodingScheme = 0x1100; - break; - case 0x1200: // EDCDIC DBCS - case 0x2200: // ASCII DBCS - db2EncodingScheme = 0x1200; - break; - case 0x1301: // EDCDIC Mixed - case 0x2300: // ASCII Mixed - case 0x4403: // EUC (ISO 2022) - db2EncodingScheme = 0x1301; - break; - case 0x7200: // UCS2 - db2EncodingScheme = 0x7200; - break; - case 0x7807: // UTF-8 - db2EncodingScheme = 0x7807; - break; - case 0x7500: // UTF-32 - db2EncodingScheme = 0x7500; - break; - default: // Unknown - { - getErrTxt(DB2I_ERR_UNKNOWN_ENCODING,aixEncodingScheme); - return DB2I_ERR_UNKNOWN_ENCODING; - } - break; - } - if (aixEncodingScheme == db2EncodingScheme) - { - *db2Ccsid = aixCcsid; - } - else - { - rc = getAssociatedCCSID(aixCcsid, db2EncodingScheme, db2Ccsid); // EDCDIC SBCS - if (rc != 0) - return rc; - } - - return 0; -} - - -/** - Obtain the encoding scheme of a CCSID. - - @param inCcsid An IBM i CCSID - @param[out] outEncodingScheme The associated encoding scheme - - @return 0 if successful. Failure otherwise -*/ -int32 getEncodingScheme(const uint16 inCcsid, int32& outEncodingScheme) -{ - DBUG_ENTER("db2i_charsetSupport::getEncodingScheme"); - - static bool ptrInited = FALSE; - static char ptrSpace[sizeof(ILEpointer) + 15]; - static ILEpointer* ptrToPtr = (ILEpointer*)roundToQuadWordBdy(ptrSpace); - int rc; - - if (!ptrInited) - { - rc = _RSLOBJ2(ptrToPtr, RSLOBJ_TS_PGM, "QTQGESP", "QSYS"); - - if (rc) - { - getErrTxt(DB2I_ERR_RESOLVE_OBJ,"QTQGESP","QSYS","*PGM",errno); - DBUG_RETURN(DB2I_ERR_RESOLVE_OBJ); - } - ptrInited = TRUE; - } - - DBUG_ASSERT(inCcsid != 0); - - int GESPCCSID = inCcsid; - int GESPLen = 32; - int GESPNbrVal = 0; - int32 GESPES; - int GESPCSCPL[32]; - int GESPFB[3]; - void* ILEArgv[7]; - ILEArgv[0] = &GESPCCSID; - ILEArgv[1] = &GESPLen; - ILEArgv[2] = &GESPNbrVal; - ILEArgv[3] = &GESPES; - ILEArgv[4] = &GESPCSCPL; - ILEArgv[5] = &GESPFB; - ILEArgv[6] = NULL; - - rc = _PGMCALL(ptrToPtr, (void**)&ILEArgv, 0); - - if (rc) - { - getErrTxt(DB2I_ERR_PGMCALL,"QTQGESP","QSYS",rc); - DBUG_RETURN(DB2I_ERR_PGMCALL); - } - if (GESPFB[0] != 0 || - GESPFB[1] != 0 || - GESPFB[2] != 0) - { - getErrTxt(DB2I_ERR_QTQGESP,GESPFB[0],GESPFB[1],GESPFB[2]); - DBUG_RETURN(DB2I_ERR_QTQGESP); - } - outEncodingScheme = GESPES; - - DBUG_RETURN(0); -} - - -/** - Get the best fit equivalent CCSID. (Wrapper for QTQGRDC API) - - @param inCcsid An IBM i CCSID - @param inEncodingScheme The encoding scheme - @param[out] outCcsid The equivalent CCSID - - @return 0 if successful. Failure otherwise -*/ -int32 getAssociatedCCSID(const uint16 inCcsid, const int inEncodingScheme, uint16* outCcsid) -{ - DBUG_ENTER("db2i_charsetSupport::getAssociatedCCSID"); - static bool ptrInited = FALSE; - static char ptrSpace[sizeof(ILEpointer) + 15]; - static ILEpointer* ptrToPtr = (ILEpointer*)roundToQuadWordBdy(ptrSpace); - int rc; - - // Override non-standard charsets - if ((inCcsid == 923) && (inEncodingScheme == 0x1100)) - { - *outCcsid = 1148; - DBUG_RETURN(0); - } - else if ((inCcsid == 1250) && (inEncodingScheme == 0x1100)) - { - *outCcsid = 1153; - DBUG_RETURN(0); - } - - if (!ptrInited) - { - rc = _RSLOBJ2(ptrToPtr, RSLOBJ_TS_PGM, "QTQGRDC", "QSYS"); - - if (rc) - { - getErrTxt(DB2I_ERR_RESOLVE_OBJ,"QTQGRDC","QSYS","*PGM",errno); - DBUG_RETURN(DB2I_ERR_RESOLVE_OBJ); - } - ptrInited = TRUE; - } - - int GRDCCCSID = inCcsid; - int GRDCES = inEncodingScheme; - int GRDCSel = 0; - int GRDCAssCCSID; - int GRDCFB[3]; - void* ILEArgv[7]; - ILEArgv[0] = &GRDCCCSID; - ILEArgv[1] = &GRDCES; - ILEArgv[2] = &GRDCSel; - ILEArgv[3] = &GRDCAssCCSID; - ILEArgv[4] = &GRDCFB; - ILEArgv[5] = NULL; - - rc = _PGMCALL(ptrToPtr, (void**)&ILEArgv, 0); - - if (rc) - { - getErrTxt(DB2I_ERR_PGMCALL,"QTQGRDC","QSYS",rc); - DBUG_RETURN(DB2I_ERR_PGMCALL); - } - if (GRDCFB[0] != 0 || - GRDCFB[1] != 0 || - GRDCFB[2] != 0) - { - getErrTxt(DB2I_ERR_QTQGRDC,GRDCFB[0],GRDCFB[1],GRDCFB[2]); - DBUG_RETURN(DB2I_ERR_QTQGRDC); - } - - *outCcsid = GRDCAssCCSID; - - DBUG_RETURN(0); -} - -/** - Open an iconv conversion between a MySQL charset and the respective IBM i CCSID - - @param direction The direction of the conversion - @param mysqlCSName Name of the MySQL character set - @param db2CCSID The IBM i CCSID - @param hashKey The key to use for inserting the opened conversion into the cache - @param[out] newConversion The iconv descriptor - - @return 0 if successful. Failure otherwise -*/ -static int32 openNewConversion(enum_conversionDirection direction, - const char* mysqlCSName, - uint16 db2CCSID, - IconvMap::HashKey* hashKey, - iconv_t& newConversion) -{ - DBUG_ENTER("db2i_charsetSupport::openNewConversion"); - - char mysqlAix41Desc[Qlg_MaxDescSize]; - char db2Aix41Desc[Qlg_MaxDescSize]; - char db2CcsidString[6] = ""; - int32 rc; - - /* - First we have to convert the MySQL IANA-like name and the DB2 CCSID into - there equivalent iconv descriptions. - */ - rc = convertTextDesc(Qlg_TypeIANA, Qlg_TypeAix41, mysqlCSName, mysqlAix41Desc); - if (unlikely(rc)) - { - if (rc == DB2I_ERR_UNSUPP_CHARSET) - getErrTxt(DB2I_ERR_UNSUPP_CHARSET, mysqlCSName); - - DBUG_RETURN(rc); - } - CHARSET_INFO *cs= &my_charset_bin; - (uint)(cs->cset->long10_to_str)(cs,db2CcsidString,sizeof(db2CcsidString), 10, db2CCSID); - rc = convertTextDesc(Qlg_TypeAS400CCSID, Qlg_TypeAix41, db2CcsidString, db2Aix41Desc); - if (unlikely(rc)) - { - if (rc == DB2I_ERR_UNSUPP_CHARSET) - getErrTxt(DB2I_ERR_UNSUPP_CHARSET, mysqlCSName); - - DBUG_RETURN(rc); - } - - /* Call iconv to open the conversion. */ - if (direction == toDB2) - { - newConversion = iconv_open(db2Aix41Desc, mysqlAix41Desc); - } - else - { - newConversion = iconv_open(mysqlAix41Desc, db2Aix41Desc); - } - - if (unlikely(newConversion == (iconv_t) -1)) - { - getErrTxt(DB2I_ERR_UNSUPP_CHARSET, mysqlCSName); - DBUG_RETURN(DB2I_ERR_UNSUPP_CHARSET); - } - - /* Insert the new conversion into the cache. */ - IconvMap* mapping = (IconvMap*)alloc_root(&iconvMapMemroot, sizeof(IconvMap)); - if (!mapping) - { - my_error(ER_OUTOFMEMORY, MYF(0), sizeof(IconvMap)); - DBUG_RETURN( HA_ERR_OUT_OF_MEM); - } - memcpy(&(mapping->hashKey), hashKey, sizeof(mapping->hashKey)); - mapping->iconvDesc = newConversion; - pthread_mutex_lock(&iconvMapHashMutex); - my_hash_insert(&iconvMapHash, (const uchar*)mapping); - pthread_mutex_unlock(&iconvMapHashMutex); - - DBUG_RETURN(0); -} - - -/** - Open an iconv conversion between a MySQL charset and the respective IBM i CCSID - - @param direction The direction of the conversion - @param cs The MySQL character set - @param db2CCSID The IBM i CCSID - @param[out] newConversion The iconv descriptor - - @return 0 if successful. Failure otherwise -*/ -int32 getConversion(enum_conversionDirection direction, const CHARSET_INFO* cs, uint16 db2CCSID, iconv_t& conversion) -{ - DBUG_ENTER("db2i_charsetSupport::getConversion"); - - int32 rc; - - /* Build the hash key */ - IconvMap::HashKey hashKey; - hashKey.direction= direction; - hashKey.myCharset= cs; - hashKey.db2CCSID= db2CCSID; - - /* Look for the conversion in the cache and add it if it is not there. */ - IconvMap *mapping; - if (!(mapping= (IconvMap *) hash_search(&iconvMapHash, - (const uchar*)&hashKey, - sizeof(hashKey)))) - { - DBUG_PRINT("getConversion", ("Hash miss for direction=%d, cs=%s, ccsid=%d", direction, cs->name, db2CCSID)); - rc= openNewConversion(direction, cs->csname, db2CCSID, &hashKey, conversion); - if (rc) - DBUG_RETURN(rc); - } - else - { - conversion= mapping->iconvDesc; - } - - DBUG_RETURN(0); -} - -/** - Fast-path conversion from ASCII to EBCDIC for use in converting - identifiers to be sent to the QMY APIs. - - @param input ASCII data - @param[out] ouput EBCDIC data - @param ilen Size of input buffer and output buffer -*/ -int convToEbcdic(const char* input, char* output, size_t ilen) -{ - static bool inited = FALSE; - static iconv_t ic; - - if (ilen == 0) - return 0; - - if (!inited) - { - ic = iconv_open( "IBM-037", "ISO8859-1" ); - inited = TRUE; - } - size_t substitutedChars; - size_t olen = ilen; - if (iconv( ic, (char**)&input, &ilen, &output, &olen, &substitutedChars ) == -1) - return errno; - - return 0; -} - - -/** - Fast-path conversion from EBCDIC to ASCII for use in converting - data received from the QMY APIs. - - @param input EBCDIC data - @param[out] ouput ASCII data - @param ilen Size of input buffer and output buffer -*/ -int convFromEbcdic(const char* input, char* output, size_t ilen) -{ - static bool inited = FALSE; - static iconv_t ic; - - if (ilen == 0) - return 0; - - if (!inited) - { - ic = iconv_open("ISO8859-1", "IBM-037"); - inited = TRUE; - } - - size_t substitutedChars; - size_t olen = ilen; - if (iconv( ic, (char**)&input, &ilen, &output, &olen, &substitutedChars) == -1) - return errno; - - return 0; -} diff --git a/storage/ibmdb2i/db2i_charsetSupport.h b/storage/ibmdb2i/db2i_charsetSupport.h deleted file mode 100644 index 77051e1e0db..00000000000 --- a/storage/ibmdb2i/db2i_charsetSupport.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - -#ifndef DB2I_CHARSETSUPPORT_H -#define DB2I_CHARSETSUPPORT_H - -#include "db2i_global.h" -#include "mysql_priv.h" -#include <mysql/plugin.h> -#include "db2i_iconv.h" - -/** - @enum enum_conversionDirection - - Conversion directions for getConversion() -*/ -enum enum_conversionDirection -{ - toMySQL, - toDB2 -}; - -int initCharsetSupport(); -void doneCharsetSupport(); -int32 convertIANAToDb2Ccsid(const char* parmIANADesc, uint16* db2Ccsid); -int32 getEncodingScheme(const uint16 inCcsid, int32& outEncodingScheme); -int32 getAssociatedCCSID(const uint16 inCcsid, const int inEncodingScheme, uint16* outCcsid); -int convToEbcdic(const char* input, char* output, size_t ilen); -int convFromEbcdic(const char* input, char* output, size_t ilen); -int32 getConversion(enum_conversionDirection direction, const CHARSET_INFO* cs, uint16 db2CCSID, iconv_t& conversion); - -#endif diff --git a/storage/ibmdb2i/db2i_collationSupport.cc b/storage/ibmdb2i/db2i_collationSupport.cc deleted file mode 100644 index 65a17fd2452..00000000000 --- a/storage/ibmdb2i/db2i_collationSupport.cc +++ /dev/null @@ -1,355 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - -#include "db2i_collationSupport.h" -#include "db2i_errors.h" - - -/* - The following arrays define a mapping between MySQL collation names and - corresponding IBM i sort sequences. The mapping is a 1-to-1 correlation - between corresponding array slots but is incomplete without case-sensitivity - markers dynamically added to the mySqlSortSequence names. -*/ -#define MAX_COLLATION 87 -static const char* mySQLCollation[MAX_COLLATION] = -{ - {"ascii_general"}, - {"ascii"}, - {"big5_chinese"}, - {"big5"}, - {"cp1250_croatian"}, - {"cp1250_general"}, - {"cp1250_polish"}, - {"cp1250"}, - {"cp1251_bulgarian"}, - {"cp1251_general"}, - {"cp1251"}, - {"cp1256_general"}, - {"cp1256"}, - {"cp850_general"}, - {"cp850"}, - {"cp852_general"}, - {"cp852"}, - {"cp932_japanese"}, - {"cp932"}, - {"euckr_korean"}, - {"euckr"}, - {"gb2312_chinese"}, - {"gb2312"}, - {"gbk_chinese"}, - {"gbk"}, - {"greek_general"}, - {"greek"}, - {"hebrew_general"}, - {"hebrew"}, - {"latin1_danish"}, - {"latin1_general"}, - {"latin1_german1"}, - {"latin1_spanish"}, - {"latin1_swedish"}, - {"latin1"}, - {"latin2_croatian"}, - {"latin2_general"}, - {"latin2_hungarian"}, - {"latin2"}, - {"latin5_turkish"}, - {"latin5"}, - {"macce_general"}, - {"macce"}, - {"sjis_japanese"}, - {"sjis"}, - {"tis620_thai"}, - {"tis620"}, - {"ucs2_czech"}, - {"ucs2_danish"}, - {"ucs2_esperanto"}, - {"ucs2_estonian"}, - {"ucs2_general"}, - {"ucs2_hungarian"}, - {"ucs2_icelandic"}, - {"ucs2_latvian"}, - {"ucs2_lithuanian"}, - {"ucs2_persian"}, - {"ucs2_polish"}, - {"ucs2_romanian"}, - {"ucs2_slovak"}, - {"ucs2_slovenian"}, - {"ucs2_spanish"}, - {"ucs2_swedish"}, - {"ucs2_turkish"}, - {"ucs2_unicode"}, - {"ucs2"}, - {"ujis_japanese"}, - {"ujis"}, - {"utf8_czech"}, - {"utf8_danish"}, - {"utf8_esperanto"}, - {"utf8_estonian"}, - {"utf8_general"}, - {"utf8_hungarian"}, - {"utf8_icelandic"}, - {"utf8_latvian"}, - {"utf8_lithuanian"}, - {"utf8_persian"}, - {"utf8_polish"}, - {"utf8_romanian"}, - {"utf8_slovak"}, - {"utf8_slovenian"}, - {"utf8_spanish"}, - {"utf8_swedish"}, - {"utf8_turkish"}, - {"utf8_unicode"}, - {"utf8"} -}; - - -static const char* mySqlSortSequence[MAX_COLLATION] = -{ - {"QALA101F4"}, - {"QBLA101F4"}, - {"QACHT04B0"}, - {"QBCHT04B0"}, - {"QALA20481"}, - {"QCLA20481"}, - {"QDLA20481"}, - {"QELA20481"}, - {"QACYR0401"}, - {"QBCYR0401"}, - {"QCCYR0401"}, - {"QAARA01A4"}, - {"QBARA01A4"}, - {"QCLA101F4"}, - {"QDLA101F4"}, - {"QALA20366"}, - {"QBLA20366"}, - {"QAJPN04B0"}, - {"QBJPN04B0"}, - {"QAKOR04B0"}, - {"QBKOR04B0"}, - {"QACHS04B0"}, - {"QBCHS04B0"}, - {"QCCHS04B0"}, - {"QDCHS04B0"}, - {"QAELL036B"}, - {"QBELL036B"}, - {"QAHEB01A8"}, - {"QBHEB01A8"}, - {"QALA1047C"}, - {"QBLA1047C"}, - {"QCLA1047C"}, - {"QDLA1047C"}, - {"QELA1047C"}, - {"QFLA1047C"}, - {"QCLA20366"}, - {"QELA20366"}, - {"QFLA20366"}, - {"QGLA20366"}, - {"QATRK0402"}, - {"QBTRK0402"}, - {"QHLA20366"}, - {"QILA20366"}, - {"QCJPN04B0"}, - {"QDJPN04B0"}, - {"QATHA0346"}, - {"QBTHA0346"}, - {"ACS_CZ"}, - {"ADA_DK"}, - {"AEO"}, - {"AET"}, - {"QAUCS04B0"}, - {"AHU"}, - {"AIS"}, - {"ALV"}, - {"ALT"}, - {"AFA"}, - {"APL"}, - {"ARO"}, - {"ASK"}, - {"ASL"}, - {"AES"}, - {"ASW"}, - {"ATR"}, - {"AEN"}, - {"*HEX"}, - {"QEJPN04B0"}, - {"QFJPN04B0"}, - {"ACS_CZ"}, - {"ADA_DK"}, - {"AEO"}, - {"AET"}, - {"QAUCS04B0"}, - {"AHU"}, - {"AIS"}, - {"ALV"}, - {"ALT"}, - {"AFA"}, - {"APL"}, - {"ARO"}, - {"ASK"}, - {"ASL"}, - {"AES"}, - {"ASW"}, - {"ATR"}, - {"AEN"}, - {"*HEX"} -}; - - -/** - Get the IBM i sort sequence that corresponds to the given MySQL collation. - - @param fieldCharSet The collated character set - @param[out] rtnSortSequence The corresponding sort sequence - - @return 0 if successful. Failure otherwise -*/ -static int32 getAssociatedSortSequence(const CHARSET_INFO *fieldCharSet, const char** rtnSortSequence) -{ - DBUG_ENTER("ha_ibmdb2i::getAssociatedSortSequence"); - - if (strcmp(fieldCharSet->csname,"binary") != 0) - { - int collationSearchLen = strlen(fieldCharSet->name); - if (fieldCharSet->state & MY_CS_BINSORT) - collationSearchLen -= 4; - else - collationSearchLen -= 3; - - uint16 loopCnt = 0; - for (loopCnt; loopCnt < MAX_COLLATION; ++loopCnt) - { - if ((strlen(mySQLCollation[loopCnt]) == collationSearchLen) && - (strncmp((char*)mySQLCollation[loopCnt], fieldCharSet->name, collationSearchLen) == 0)) - break; - } - if (loopCnt == MAX_COLLATION) // Did not find associated sort sequence - { - getErrTxt(DB2I_ERR_SRTSEQ); - DBUG_RETURN(DB2I_ERR_SRTSEQ); - } - *rtnSortSequence = mySqlSortSequence[loopCnt]; - } - - DBUG_RETURN(0); -} - - -/** - Update sort sequence information for a key. - - This function accumulates information about a key as it is called for each - field composing the key. The caller should invoke the function for each field - and (with the exception of the charset parm) preserve the values for the - parms across invocations, until a particular key has been evaluated. Once - the last field in the key has been evaluated, the fileSortSequence and - fileSortSequenceLibrary parms will contain the correct information for - creating the corresponding DB2 key. - - @param charset The character set under consideration - @param[in, out] fileSortSequenceType The type of the current key's sort seq - @param[in, out] fileSortSequence The IBM i identifier for the DB2 sort sequence - that corresponds - - @return 0 if successful. Failure otherwise -*/ -int32 updateAssociatedSortSequence(const CHARSET_INFO* charset, - char* fileSortSequenceType, - char* fileSortSequence, - char* fileSortSequenceLibrary) -{ - DBUG_ENTER("ha_ibmdb2i::updateAssociatedSortSequence"); - DBUG_ASSERT(charset); - if (strcmp(charset->csname,"binary") != 0) - { - char newSortSequence[11] = ""; - char newSortSequenceType = ' '; - const char* foundSortSequence; - int rc = getAssociatedSortSequence(charset, &foundSortSequence); - if (rc) DBUG_RETURN (rc); - switch(foundSortSequence[0]) - { - case '*': // Binary - strcat(newSortSequence,foundSortSequence); - newSortSequenceType = 'B'; - break; - case 'Q': // Non-ICU sort sequence - strcat(newSortSequence,foundSortSequence); - if ((charset->state & MY_CS_BINSORT) != 0) - { - strcat(newSortSequence,"U"); - } - else if ((charset->state & MY_CS_CSSORT) != 0) - { - strcat(newSortSequence,"U"); - } - else - { - strcat(newSortSequence,"S"); - } - newSortSequenceType = 'N'; - break; - default: // ICU sort sequence - { - if ((charset->state & MY_CS_CSSORT) == 0) - { - if (osVersion.v >= 6) - strcat(newSortSequence,"I34"); // ICU 3.4 - else - strcat(newSortSequence,"I26"); // ICU 2.6.1 - } - strcat(newSortSequence,foundSortSequence); - newSortSequenceType = 'I'; - } - break; - } - if (*fileSortSequenceType == ' ') // If no sort sequence has been set yet - { - // Set associated sort sequence - strcpy(fileSortSequence,newSortSequence); - strcpy(fileSortSequenceLibrary,"QSYS"); - *fileSortSequenceType = newSortSequenceType; - } - else if (strcmp(fileSortSequence,newSortSequence) != 0) - { - // Only one sort sequence/collation is supported for each DB2 index. - getErrTxt(DB2I_ERR_MIXED_COLLATIONS); - DBUG_RETURN(DB2I_ERR_MIXED_COLLATIONS); - } - } - - DBUG_RETURN(0); -} diff --git a/storage/ibmdb2i/db2i_collationSupport.h b/storage/ibmdb2i/db2i_collationSupport.h deleted file mode 100644 index b2ce09de1ea..00000000000 --- a/storage/ibmdb2i/db2i_collationSupport.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - -#ifndef DB2I_COLLATIONSUPPORT_H -#define DB2I_COLLATIONSUPPORT_H - -#include "db2i_global.h" -#include "mysql_priv.h" - -int32 updateAssociatedSortSequence(const CHARSET_INFO* charset, - char* fileSortSequenceType, - char* fileSortSequence, - char* fileSortSequenceLibrary); - -#endif diff --git a/storage/ibmdb2i/db2i_constraints.cc b/storage/ibmdb2i/db2i_constraints.cc deleted file mode 100644 index 1fde0dd3d14..00000000000 --- a/storage/ibmdb2i/db2i_constraints.cc +++ /dev/null @@ -1,672 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - - -#include "ha_ibmdb2i.h" -#include "db2i_safeString.h" - -// This function is called when building the CREATE TABLE information for -// foreign key constraints. It converts a constraint, table, schema, or -// field name from EBCDIC to ASCII. If the DB2 name is quoted, it removes -// those quotes. It then adds the appropriate quotes for a MySQL identifier. - -static void convNameForCreateInfo(THD *thd, SafeString& info, char* fromName, int len) -{ - int quote; - char cquote; // Quote character - char convName[MAX_DB2_FILENAME_LENGTH]; // Converted name - - memset(convName, 0, sizeof(convName)); - convFromEbcdic(fromName, convName, len); - quote = get_quote_char_for_identifier(thd, convName, len); - cquote = (char) quote; - if (quote != EOF) - info.strcat(cquote); - if (convName[0] == '"') // If DB2 name was quoted, remove quotes - { - if (strstr(convName, "\"\"")) - stripExtraQuotes(convName+1, len-1); - info.strncat((char*)(convName+1), len-2); - } - else // DB2 name was not quoted - info.strncat(convName, len); - if (quote != EOF) - info.strcat(cquote); -} - -/** - Evaluate the parse tree to build foreign key constraint clauses - - @parm lex The parse tree - @parm appendHere The DB2 string to receive the constraint clauses - @parm path The path to the table under consideration - @parm fields Pointer to the table's list of field pointers - @parm[in, out] fileSortSequenceType The sort sequence type associated with the table - @parm[in, out] fileSortSequence The sort sequence associated with the table - @parm[in, out] fileSortSequenceLibrary The sort sequence library associated with the table - - @return 0 if successful; HA_ERR_CANNOT_ADD_FOREIGN otherwise -*/ -int ha_ibmdb2i::buildDB2ConstraintString(LEX* lex, - String& appendHere, - const char* path, - Field** fields, - char* fileSortSequenceType, - char* fileSortSequence, - char* fileSortSequenceLibrary) -{ - List_iterator<Key> keyIter(lex->alter_info.key_list); - char colName[MAX_DB2_COLNAME_LENGTH+1]; - - Key* curKey; - - while (curKey = keyIter++) - { - if (curKey->type == Key::FOREIGN_KEY) - { - appendHere.append(STRING_WITH_LEN(", ")); - - Foreign_key* fk = (Foreign_key*)curKey; - - char db2LibName[MAX_DB2_SCHEMANAME_LENGTH+1]; - if (fk->name) - { - char db2FKName[MAX_DB2_FILENAME_LENGTH+1]; - appendHere.append(STRING_WITH_LEN("CONSTRAINT ")); - if (fk->ref_table->db.str) - { - convertMySQLNameToDB2Name(fk->ref_table->db.str, db2LibName, sizeof(db2LibName)); - } - else - { - db2i_table::getDB2LibNameFromPath(path, db2LibName); - } - if (lower_case_table_names == 1) - my_casedn_str(files_charset_info, db2LibName); - appendHere.append(db2LibName); - - appendHere.append('.'); - - convertMySQLNameToDB2Name(fk->name, db2FKName, sizeof(db2FKName)); - appendHere.append(db2FKName); - } - - appendHere.append(STRING_WITH_LEN(" FOREIGN KEY (")); - - bool firstTime = true; - - List_iterator<Key_part_spec> column(fk->columns); - Key_part_spec* curColumn; - - while (curColumn = column++) - { - if (!firstTime) - { - appendHere.append(','); - } - firstTime = false; - - convertMySQLNameToDB2Name(curColumn->field_name, colName, sizeof(colName)); - appendHere.append(colName); - - // DB2 requires that the sort sequence on the child table match the parent table's - // sort sequence. We ensure that happens by updating the sort sequence according - // to the constrained fields. - Field** field = fields; - do - { - if (strcmp((*field)->field_name, curColumn->field_name) == 0) - { - int rc = updateAssociatedSortSequence((*field)->charset(), - fileSortSequenceType, - fileSortSequence, - fileSortSequenceLibrary); - - if (unlikely(rc)) return rc; - } - } while (*(++field)); - } - - firstTime = true; - - appendHere.append(STRING_WITH_LEN(") REFERENCES ")); - - if (fk->ref_table->db.str) - { - convertMySQLNameToDB2Name(fk->ref_table->db.str, db2LibName, sizeof(db2LibName)); - } - else - { - db2i_table::getDB2LibNameFromPath(path, db2LibName); - } - if (lower_case_table_names == 1) - my_casedn_str(files_charset_info, db2LibName); - appendHere.append(db2LibName); - appendHere.append('.'); - - char db2FileName[MAX_DB2_FILENAME_LENGTH+1]; - convertMySQLNameToDB2Name(fk->ref_table->table.str, db2FileName, sizeof(db2FileName)); - if (lower_case_table_names) - my_casedn_str(files_charset_info, db2FileName); - appendHere.append(db2FileName); - - - if (!fk->ref_columns.is_empty()) - { - List_iterator<Key_part_spec> ref(fk->ref_columns); - Key_part_spec* curRef; - appendHere.append(STRING_WITH_LEN(" (")); - - - while (curRef = ref++) - { - if (!firstTime) - { - appendHere.append(','); - } - firstTime = false; - - convertMySQLNameToDB2Name(curRef->field_name, colName, sizeof(colName)); - appendHere.append(colName); - } - - appendHere.append(STRING_WITH_LEN(") ")); - } - - if (fk->delete_opt != Foreign_key::FK_OPTION_UNDEF) - { - appendHere.append(STRING_WITH_LEN("ON DELETE ")); - switch (fk->delete_opt) - { - case Foreign_key::FK_OPTION_RESTRICT: - appendHere.append(STRING_WITH_LEN("RESTRICT ")); break; - case Foreign_key::FK_OPTION_CASCADE: - appendHere.append(STRING_WITH_LEN("CASCADE ")); break; - case Foreign_key::FK_OPTION_SET_NULL: - appendHere.append(STRING_WITH_LEN("SET NULL ")); break; - case Foreign_key::FK_OPTION_NO_ACTION: - appendHere.append(STRING_WITH_LEN("NO ACTION ")); break; - case Foreign_key::FK_OPTION_DEFAULT: - appendHere.append(STRING_WITH_LEN("SET DEFAULT ")); break; - default: - return HA_ERR_CANNOT_ADD_FOREIGN; break; - } - } - - if (fk->update_opt != Foreign_key::FK_OPTION_UNDEF) - { - appendHere.append(STRING_WITH_LEN("ON UPDATE ")); - switch (fk->update_opt) - { - case Foreign_key::FK_OPTION_RESTRICT: - appendHere.append(STRING_WITH_LEN("RESTRICT ")); break; - case Foreign_key::FK_OPTION_NO_ACTION: - appendHere.append(STRING_WITH_LEN("NO ACTION ")); break; - default: - return HA_ERR_CANNOT_ADD_FOREIGN; break; - } - } - - } - - } - - return 0; -} - - -/*********************************************************************** -Get the foreign key information in the form of a character string so -that it can be inserted into a CREATE TABLE statement. This is used by -the SHOW CREATE TABLE statement. The string will later be freed by the -free_foreign_key_create_info() method. -************************************************************************/ - -char* ha_ibmdb2i::get_foreign_key_create_info(void) -{ - DBUG_ENTER("ha_ibmdb2i::get_foreign_key_create_info"); - int rc = 0; - char* infoBuffer = NULL; // Pointer to string returned to MySQL - uint32 constraintSpaceLength;// Length of space passed to DB2 - ValidatedPointer<char> constraintSpace; // Space pointer passed to DB2 - uint32 neededLen; // Length returned from DB2 - uint32 cstCnt; // Number of foreign key constraints from DB2 - uint32 fld; // - constraint_hdr* cstHdr; // Pointer to constraint header structure - FK_constraint* FKCstDef; // Pointer to constraint definition structure - cst_name* fieldName; // Pointer to field name structure - char* tempPtr; // Temp pointer for traversing constraint space - char convName[128]; - - /* Allocate space to retrieve the DB2 constraint information. */ - - if (!(share = get_share(table_share->path.str, table))) - DBUG_RETURN(NULL); - - constraintSpaceLength = 5000; // Try allocating 5000 bytes and see if enough. - - initBridge(); - - constraintSpace.alloc(constraintSpaceLength); - rc = bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE) - ->constraints(db2Table->dataFile()->getMasterDefnHandle(), - constraintSpace, - constraintSpaceLength, - &neededLen, - &cstCnt); - - if (unlikely(rc == QMY_ERR_NEED_MORE_SPACE)) - { - constraintSpaceLength = neededLen; // Get length of space that's needed - constraintSpace.realloc(constraintSpaceLength); - rc = bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE) - ->constraints(db2Table->dataFile()->getMasterDefnHandle(), - constraintSpace, - constraintSpaceLength, - &neededLen, - &cstCnt); - } - - /* If constraint information was returned by DB2, build a text string */ - /* to return to MySQL. */ - - if ((rc == 0) && (cstCnt > 0)) - { - THD* thd = ha_thd(); - infoBuffer = (char*) my_malloc(MAX_FOREIGN_LEN + 1, MYF(MY_WME)); - if (infoBuffer == NULL) - { - free_share(share); - DBUG_RETURN(NULL); - } - - SafeString info(infoBuffer, MAX_FOREIGN_LEN + 1); - - /* Loop through the DB2 constraints and build a text string for each foreign */ - /* key constraint that is found. */ - - tempPtr = constraintSpace; - cstHdr = (constraint_hdr_t*)(void*)constraintSpace; // Address first constraint definition - for (int i = 0; i < cstCnt && !info.overflowed(); ++i) - { - if (cstHdr->CstType[0] == QMY_CST_FK) // If this is a foreign key constraint - { - tempPtr = (char*)(tempPtr + cstHdr->CstDefOff); - FKCstDef = (FK_constraint_t*)tempPtr; - - /* Process the constraint name. */ - - info.strncat(STRING_WITH_LEN(",\n CONSTRAINT ")); - convNameForCreateInfo(thd, info, - FKCstDef->CstName.Name, FKCstDef->CstName.Len); - - /* Process the names of the foreign keys. */ - - info.strncat(STRING_WITH_LEN(" FOREIGN KEY (")); - tempPtr = (char*)(tempPtr + FKCstDef->KeyColOff); - fieldName= (cst_name_t*)tempPtr; - for (fld = 0; fld < FKCstDef->KeyCnt; ++fld) - { - convNameForCreateInfo(thd, info, fieldName->Name, fieldName->Len); - if ((fld + 1) < FKCstDef->KeyCnt) - { - info.strncat(STRING_WITH_LEN(", ")); - fieldName = fieldName + 1; - } - } - - /* Process the schema-name and name of the referenced table. */ - - info.strncat(STRING_WITH_LEN(") REFERENCES ")); - convNameForCreateInfo(thd, info, - FKCstDef->RefSchema.Name, FKCstDef->RefSchema.Len); - info.strcat('.'); - convNameForCreateInfo(thd, info, - FKCstDef->RefTable.Name, FKCstDef->RefTable.Len); - info.strncat(STRING_WITH_LEN(" (")); - - /* Process the names of the referenced keys. */ - - tempPtr = (char*)FKCstDef; - tempPtr = (char*)(tempPtr + FKCstDef->RefColOff); - fieldName= (cst_name_t*)tempPtr; - for (fld = 0; fld < FKCstDef->RefCnt; ++fld) - { - convNameForCreateInfo(thd, info, fieldName->Name, fieldName->Len); - if ((fld + 1) < FKCstDef->RefCnt) - { - info.strncat(STRING_WITH_LEN(", ")); - fieldName = fieldName + 1; - } - } - - /* Process the ON UPDATE and ON DELETE rules. */ - - info.strncat(STRING_WITH_LEN(") ON UPDATE ")); - switch(FKCstDef->UpdMethod) - { - case QMY_NOACTION: info.strncat(STRING_WITH_LEN("NO ACTION")); break; - case QMY_RESTRICT: info.strncat(STRING_WITH_LEN("RESTRICT")); break; - default: break; - } - info.strncat(STRING_WITH_LEN(" ON DELETE ")); - switch(FKCstDef->DltMethod) - { - case QMY_CASCADE: info.strncat(STRING_WITH_LEN("CASCADE")); break; - case QMY_SETDFT: info.strncat(STRING_WITH_LEN("SET DEFAULT")); break; - case QMY_SETNULL: info.strncat(STRING_WITH_LEN("SET NULL")); break; - case QMY_NOACTION: info.strncat(STRING_WITH_LEN("NO ACTION")); break; - case QMY_RESTRICT: info.strncat(STRING_WITH_LEN("RESTRICT")); break; - default: break; - } - } - - /* Address the next constraint, if any. */ - - if ((i+1) < cstCnt) - { - tempPtr = (char*)cstHdr + cstHdr->CstLen; - cstHdr = (constraint_hdr_t*)(tempPtr); - } - } - } - - /* Cleanup and return */ - free_share(share); - - DBUG_RETURN(infoBuffer); -} - -/*********************************************************************** -Free the foreign key create info (for a table) that was acquired by the -get_foreign_key_create_info() method. -***********************************************************************/ - -void ha_ibmdb2i::free_foreign_key_create_info(char* info) -{ - DBUG_ENTER("ha_ibmdb2i::free_foreign_key_create_info"); - - if (info) - { - my_free(info, MYF(0)); - } - DBUG_VOID_RETURN; -} - -/*********************************************************************** -This method returns to MySQL a list, with one entry in the list describing -each foreign key constraint. -***********************************************************************/ - -int ha_ibmdb2i::get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list) -{ - DBUG_ENTER("ha_ibmdb2i::get_foreign_key_list"); - int rc = 0; - uint32 constraintSpaceLength; // Length of space passed to DB2 - ValidatedPointer<char> constraintSpace; // Space pointer passed to DB2 - uint16 rtnCode; // Return code from DB2 - uint32 neededLen; // Bytes needed to contain DB2 constraint info - uint32 cstCnt; // Number of constraints returned by DB2 - uint32 fld; - constraint_hdr* cstHdr; // Pointer to a cst header structure - FK_constraint* FKCstDef; // Pointer to definition of foreign key constraint - cst_name* fieldName; // Pointer to field name structure - const char *method; - ulong methodLen; - char* tempPtr; // Temp pointer for traversing constraint space - char convName[128]; - - if (!(share = get_share(table_share->path.str, table))) - DBUG_RETURN(0); - - // Allocate space to retrieve the DB2 constraint information. - constraintSpaceLength = 5000; // Try allocating 5000 bytes and see if enough. - - constraintSpace.alloc(constraintSpaceLength); - rc = bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE) - ->constraints(db2Table->dataFile()->getMasterDefnHandle(), - constraintSpace, - constraintSpaceLength, - &neededLen, - &cstCnt); - - if (unlikely(rc == QMY_ERR_NEED_MORE_SPACE)) - { - constraintSpaceLength = neededLen; // Get length of space that's needed - constraintSpace.realloc(constraintSpaceLength); - rc = bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE) - ->constraints(db2Table->dataFile()->getMasterDefnHandle(), - constraintSpace, - constraintSpaceLength, - &neededLen, - &cstCnt); - } - - /* If constraint information was returned by DB2, build a text string */ - /* to return to MySQL. */ - if ((rc == 0) && (cstCnt > 0)) - { - tempPtr = constraintSpace; - cstHdr = (constraint_hdr_t*)(void*)constraintSpace; // Address first constraint definition - for (int i = 0; i < cstCnt; ++i) - { - if (cstHdr->CstType[0] == QMY_CST_FK) // If this is a foreign key constraint - { - FOREIGN_KEY_INFO f_key_info; - LEX_STRING *name= 0; - tempPtr = (char*)(tempPtr + cstHdr->CstDefOff); - FKCstDef = (FK_constraint_t*)tempPtr; - - /* Process the constraint name. */ - - convFromEbcdic(FKCstDef->CstName.Name, convName,FKCstDef->CstName.Len); - if (convName[0] == '"') // If quoted, exclude quotes. - f_key_info.forein_id = thd_make_lex_string(thd, 0, - convName + 1, (uint) (FKCstDef->CstName.Len - 2), 1); - else // Not quoted - f_key_info.forein_id = thd_make_lex_string(thd, 0, - convName, (uint) FKCstDef->CstName.Len, 1); - - /* Process the names of the foreign keys. */ - - - tempPtr = (char*)(tempPtr + FKCstDef->KeyColOff); - fieldName = (cst_name_t*)tempPtr; - for (fld = 0; fld < FKCstDef->KeyCnt; ++fld) - { - convFromEbcdic(fieldName->Name, convName, fieldName->Len); - if (convName[0] == '"') // If quoted, exclude quotes. - name = thd_make_lex_string(thd, name, - convName + 1, (uint) (fieldName->Len - 2), 1); - else - name = thd_make_lex_string(thd, name, convName, (uint) fieldName->Len, 1); - f_key_info.foreign_fields.push_back(name); - if ((fld + 1) < FKCstDef->KeyCnt) - fieldName = fieldName + 1; - } - - /* Process the schema and name of the referenced table. */ - - convFromEbcdic(FKCstDef->RefSchema.Name, convName, FKCstDef->RefSchema.Len); - if (convName[0] == '"') // If quoted, exclude quotes. - f_key_info.referenced_db = thd_make_lex_string(thd, 0, - convName + 1, (uint) (FKCstDef->RefSchema.Len -2), 1); - else - f_key_info.referenced_db = thd_make_lex_string(thd, 0, - convName, (uint) FKCstDef->RefSchema.Len, 1); - convFromEbcdic(FKCstDef->RefTable.Name, convName, FKCstDef->RefTable.Len); - if (convName[0] == '"') // If quoted, exclude quotes. - f_key_info.referenced_table = thd_make_lex_string(thd, 0, - convName +1, (uint) (FKCstDef->RefTable.Len -2), 1); - else - f_key_info.referenced_table = thd_make_lex_string(thd, 0, - convName, (uint) FKCstDef->RefTable.Len, 1); - - /* Process the names of the referenced keys. */ - - tempPtr = (char*)FKCstDef; - tempPtr = (char*)(tempPtr + FKCstDef->RefColOff); - fieldName= (cst_name_t*)tempPtr; - for (fld = 0; fld < FKCstDef->RefCnt; ++fld) - { - convFromEbcdic(fieldName->Name, convName, fieldName->Len); - if (convName[0] == '"') // If quoted, exclude quotes. - name = thd_make_lex_string(thd, name, - convName + 1, (uint) (fieldName->Len -2), 1); - else - name = thd_make_lex_string(thd, name, convName, (uint) fieldName->Len, 1); - f_key_info.referenced_fields.push_back(name); - if ((fld + 1) < FKCstDef->RefCnt) - fieldName = fieldName + 1; - } - - /* Process the ON UPDATE and ON DELETE rules. */ - - switch(FKCstDef->UpdMethod) - { - case QMY_NOACTION: - { - method = "NO ACTION"; - methodLen=9; - } - break; - case QMY_RESTRICT: - { - method = "RESTRICT"; - methodLen = 8; - } - break; - default: break; - } - f_key_info.update_method = thd_make_lex_string( - thd, f_key_info.update_method, method, methodLen, 1); - switch(FKCstDef->DltMethod) - { - case QMY_CASCADE: - { - method = "CASCADE"; - methodLen = 7; - } - break; - case QMY_SETDFT: - { - method = "SET DEFAULT"; - methodLen = 11; - } - break; - case QMY_SETNULL: - { - method = "SET NULL"; - methodLen = 8; - } - break; - case QMY_NOACTION: - { - method = "NO ACTION"; - methodLen = 9; - } - break; - case QMY_RESTRICT: - { - method = "RESTRICT"; - methodLen = 8; - } - break; - default: break; - } - f_key_info.delete_method = thd_make_lex_string( - thd, f_key_info.delete_method, method, methodLen, 1); - f_key_info.referenced_key_name= thd_make_lex_string(thd, 0, (char *)"", 1, 1); - FOREIGN_KEY_INFO *pf_key_info = (FOREIGN_KEY_INFO *) - thd_memdup(thd, &f_key_info, sizeof(FOREIGN_KEY_INFO)); - f_key_list->push_back(pf_key_info); - } - - /* Address the next constraint, if any. */ - - if ((i+1) < cstCnt) - { - tempPtr = (char*)cstHdr + cstHdr->CstLen; - cstHdr = (constraint_hdr_t*)(tempPtr); - } - } - } - - /* Cleanup and return. */ - - free_share(share); - DBUG_RETURN(0); -} - -/*********************************************************************** -Checks if the table is referenced by a foreign key. -Returns: 0 if not referenced (or error occurs), - > 0 if is referenced -***********************************************************************/ - -uint ha_ibmdb2i::referenced_by_foreign_key(void) -{ - DBUG_ENTER("ha_ibmdb2i::referenced_by_foreign_key"); - - int rc = 0; - FILE_HANDLE queryFile = 0; - uint32 resultRowLen; - uint32 count = 0; - - const char* libName = db2Table->getDB2LibName(db2i_table::ASCII_SQL); - const char* fileName = db2Table->getDB2TableName(db2i_table::ASCII_SQL); - - String query(128); - query.append(STRING_WITH_LEN(" SELECT COUNT(*) FROM SYSIBM.SQLFOREIGNKEYS WHERE PKTABLE_SCHEM = '")); - query.append(libName+1, strlen(libName)-2); // parent library name - query.append(STRING_WITH_LEN("' AND PKTABLE_NAME = '")); - query.append(fileName+1, strlen(fileName)-2); // parent file name - query.append(STRING_WITH_LEN("'")); - - SqlStatementStream sqlStream(query); - - rc = bridge()->prepOpen(sqlStream.getPtrToData(), - &queryFile, - &resultRowLen); - if (rc == 0) - { - IOReadBuffer rowBuffer(1, resultRowLen); - rc = bridge()->read(queryFile, rowBuffer.ptr(), QMY_READ_ONLY, QMY_NONE, QMY_FIRST); - if (!rc) count = *((uint32*)rowBuffer.getRowN(0)); - bridge()->deallocateFile(queryFile); - } - DBUG_RETURN(count); -} diff --git a/storage/ibmdb2i/db2i_conversion.cc b/storage/ibmdb2i/db2i_conversion.cc deleted file mode 100644 index 9a85eb01c9b..00000000000 --- a/storage/ibmdb2i/db2i_conversion.cc +++ /dev/null @@ -1,1459 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - - -#include "db2i_ileBridge.h" -#include "mysql_priv.h" -#include "db2i_charsetSupport.h" -#include "ctype.h" -#include "ha_ibmdb2i.h" -#include "db2i_errors.h" -#include "wchar.h" - -const char ZERO_DATETIME_VALUE[] = "0000-00-00 00:00:00"; -const char ZERO_DATETIME_VALUE_SUBST[] = "0001-01-01 00:00:00"; -const char ZERO_DATE_VALUE[] = "0000-00-00"; -const char ZERO_DATE_VALUE_SUBST[] = "0001-01-01"; - - -/** - Put a BCD digit into a BCD string. - - @param[out] bcdString The BCD string to be modified - @param pos The position within the string to be updated. - @param val The value to be assigned into the string at pos. -*/ -static inline void bcdAssign(char* bcdString, uint pos, uint val) -{ - bcdString[pos/2] |= val << ((pos % 2) ? 0 : 4); -} - -/** - Read a BCD digit from a BCD string. - - @param[out] bcdString The BCD string to be read - @param pos The position within the string to be read. - - @return bcdGet The value of the BCD digit at pos. -*/ -static inline uint bcdGet(const char* bcdString, uint pos) -{ - return (bcdString[pos/2] >> ((pos % 2) ? 0 : 4)) & 0xf; -} - -/** - In-place convert a number in ASCII represenation to EBCDIC representation. - - @param string The string of ASCII characters - @param len The length of string -*/ -static inline void convertNumericToEbcdicFast(char* string, int len) -{ - for (int i = 0; i < len; ++i, ++string) - { - switch(*string) - { - case '-': - *string = 0x60; break; - case ':': - *string = 0x7A; break; - case '.': - *string = 0x4B; break; - default: - DBUG_ASSERT(isdigit(*string)); - *string += 0xF0 - '0'; - break; - } - } -} - - -/** - atoi()-like function for a 4-character EBCDIC string. - - @param string The EBCDIC string - @return a4toi_ebcdic The decimal value of the EBCDIC string -*/ -static inline uint16 a4toi_ebcdic(const uchar* string) -{ - return ((string[0]-0xF0) * 1000 + - (string[1]-0xF0) * 100 + - (string[2]-0xF0) * 10 + - (string[3]-0xF0)); -}; - - -/** - atoi()-like function for a 4-character EBCDIC string. - - @param string The EBCDIC string - @return a4toi_ebcdic The decimal value of the EBCDIC string -*/ -static inline uint8 a2toi_ebcdic(const uchar* string) -{ - return ((string[0]-0xF0) * 10 + - (string[1]-0xF0)); -}; - -/** - Perform character conversion for textual field data. -*/ -int ha_ibmdb2i::convertFieldChars(enum_conversionDirection direction, - uint16 fieldID, - const char* input, - char* output, - size_t ilen, - size_t olen, - size_t* outDataLen, - bool tacitErrors, - size_t* substChars) -{ - DBUG_PRINT("ha_ibmdb2i::convertFieldChars",("Direction: %d; length = %d", direction, ilen)); - - if (unlikely(ilen == 0)) - { - if (outDataLen) *outDataLen = 0; - return (0); - } - - iconv_t& conversion = db2Table->getConversionDefinition(direction, fieldID); - - if (unlikely(conversion == (iconv_t)(-1))) - { - return (DB2I_ERR_UNSUPP_CHARSET); - } - - size_t initOLen= olen; - size_t substitutedChars = 0; - int rc = iconv(conversion, (char**)&input, &ilen, &output, &olen, &substitutedChars ); - if (outDataLen) *outDataLen = initOLen - olen; - if (substChars) *substChars = substitutedChars; - if (unlikely(rc < 0)) - { - int er = errno; - if (er == EILSEQ) - { - if (!tacitErrors) getErrTxt(DB2I_ERR_ILL_CHAR, table->field[fieldID]->field_name); - return (DB2I_ERR_ILL_CHAR); - } - else - { - if (!tacitErrors) getErrTxt(DB2I_ERR_ICONV,er); - return (DB2I_ERR_ICONV); - } - } - if (unlikely(substitutedChars) && (!tacitErrors)) - { - warning(ha_thd(), DB2I_ERR_SUB_CHARS, table->field[fieldID]->field_name); - } - - return (0); -} - -/** - Append the appropriate default value clause onto a CREATE TABLE definition - - This was inspired by get_field_default_value in sql/sql_show.cc. - - @param field The field whose value is to be obtained - @param statement The string to receive the DEFAULT clause - @param quoteIt Does the data type require single quotes around the value? - @param ccsid The ccsid of the field value (if a string type); 0 if no conversion needed -*/ -static void get_field_default_value(Field *field, - String &statement, - bool quoteIt, - uint32 ccsid, - bool substituteZeroDates) -{ - if ((field->type() != FIELD_TYPE_BLOB && - !(field->flags & NO_DEFAULT_VALUE_FLAG) && - field->unireg_check != Field::NEXT_NUMBER)) - { - my_ptrdiff_t old_ptr= (my_ptrdiff_t) (field->table->s->default_values - field->table->record[0]); - field->move_field_offset(old_ptr); - - String defaultClause(64); - defaultClause.length(0); - defaultClause.append(" DEFAULT "); - if (!field->is_null()) - { - my_bitmap_map *old_map = tmp_use_all_columns(field->table, field->table->read_set); - char tmp[MAX_FIELD_WIDTH]; - - if (field->real_type() == MYSQL_TYPE_ENUM || - field->real_type() == MYSQL_TYPE_SET) - { - CHARSET_INFO *cs= &my_charset_bin; - uint len = (uint)(cs->cset->longlong10_to_str)(cs,tmp,sizeof(tmp), 10, field->val_int()); - tmp[len]=0; - defaultClause.append(tmp); - } - else - { - String type(tmp, sizeof(tmp), field->charset()); - field->val_str(&type); - if (type.length()) - { - if (field->type() == MYSQL_TYPE_DATE && - memcmp(type.ptr(), STRING_WITH_LEN(ZERO_DATE_VALUE)) == 0) - { - if (substituteZeroDates) - type.set(STRING_WITH_LEN(ZERO_DATE_VALUE_SUBST), field->charset()); - else - { - warning(current_thd, DB2I_ERR_WARN_COL_ATTRS, field->field_name); - return; - } - } - else if ((field->type() == MYSQL_TYPE_DATETIME || - field->type() == MYSQL_TYPE_TIMESTAMP) && - memcmp(type.ptr(), STRING_WITH_LEN(ZERO_DATETIME_VALUE)) == 0) - { - if (substituteZeroDates) - type.set(STRING_WITH_LEN(ZERO_DATETIME_VALUE_SUBST), field->charset()); - else - { - warning(current_thd, DB2I_ERR_WARN_COL_ATTRS, field->field_name); - return; - } - } - - - if (field->type() != MYSQL_TYPE_STRING && - field->type() != MYSQL_TYPE_VARCHAR && - field->type() != MYSQL_TYPE_BLOB && - field->type() != MYSQL_TYPE_BIT) - { - if (quoteIt) - defaultClause.append('\''); - defaultClause.append(type); - if (quoteIt) - defaultClause.append('\''); - } - else - { - int length; - char* out; - - // If a ccsid is specified, we need to make sure that the DEFAULT - // string is converted to that encoding. - if (ccsid != 0) - { - iconv_t iconvD; - if (getConversion(toDB2, field->charset(), ccsid, iconvD)) - { - warning(current_thd, DB2I_ERR_WARN_COL_ATTRS, field->field_name); - return; - } - - size_t ilen = type.length(); - size_t olen = 6 * ilen; - size_t origOlen = olen; - const char* in = type.ptr(); - const char* tempIn = in; - out = (char*)my_malloc(olen, MYF(MY_WME)); - char* tempOut = out; - size_t substitutedChars; - - if (iconv(iconvD, (char**)&tempIn, &ilen, &tempOut, &olen, &substitutedChars) < 0) - { - warning(current_thd, DB2I_ERR_WARN_COL_ATTRS, field->field_name); - my_free(out, MYF(0)); - return; - } - // Now we process the converted string to represent it as - // hexadecimal values. - - length = origOlen - olen; - } - else - { - length = type.length(); - out = (char*)my_malloc(length*2, MYF(MY_WME)); - memcpy(out, (char*)type.ptr(), length); - } - - if (length > 16370) - { - warning(current_thd, DB2I_ERR_WARN_COL_ATTRS, field->field_name); - my_free(out, MYF(0)); - return; - } - - if (ccsid == 1200) - defaultClause.append("ux'"); - else if (ccsid == 13488) - defaultClause.append("gx'"); - else if (field->charset() == &my_charset_bin) - defaultClause.append("binary(x'"); - else - defaultClause.append("x'"); - - const char hexMap[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; - for (int c = length-1; c >= 0; --c) - { - out[c*2+1] = hexMap[out[c] & 0xF]; - out[c*2] = hexMap[out[c] >> 4]; - } - - defaultClause.append(out, length*2); - defaultClause.append('\''); - if (field->charset() == &my_charset_bin) - defaultClause.append(")"); - - my_free(out, MYF(0)); - } - } - else - defaultClause.length(0); - } - tmp_restore_column_map(field->table->read_set, old_map); - } - else if (field->maybe_null()) - defaultClause.append(STRING_WITH_LEN("NULL")); - - if (old_ptr) - field->move_field_offset(-old_ptr); - - statement.append(defaultClause); - } -} - - - - -/** - Convert a MySQL field definition into its corresponding DB2 type. - - The result will be appended to mapping as a DB2 SQL phrase. - - @param field The MySQL field to be evaluated - @param[out] mapping The receiver for the DB2 SQL syntax - @param timeFormat The format to be used for mapping the TIME type -*/ -int ha_ibmdb2i::getFieldTypeMapping(Field* field, - String& mapping, - enum_TimeFormat timeFormat, - enum_BlobMapping blobMapping, - enum_ZeroDate zeroDateHandling, - bool propagateDefaults, - enum_YearFormat yearFormat) -{ - char stringBuildBuffer[257]; - uint32 fieldLength; - bool defaultNeedsQuotes = false; - uint16 db2Ccsid = 0; - - CHARSET_INFO* fieldCharSet = field->charset(); - switch (field->type()) - { - case MYSQL_TYPE_NEWDECIMAL: - { - uint precision= ((Field_new_decimal*)field)->precision; - uint scale= field->decimals(); - - if (precision <= MAX_DEC_PRECISION) - { - sprintf(stringBuildBuffer,"DECIMAL(%d, %d)",precision,scale); - } - else - { - if (scale > precision - MAX_DEC_PRECISION) - { - scale = scale - (precision - MAX_DEC_PRECISION); - precision = MAX_DEC_PRECISION; - sprintf(stringBuildBuffer,"DECIMAL(%d, %d)",precision,scale); - } - else - { - return HA_ERR_UNSUPPORTED; - } - warning(ha_thd(), DB2I_ERR_PRECISION); - } - - mapping.append(stringBuildBuffer); - } - break; - case MYSQL_TYPE_TINY: - mapping.append(STRING_WITH_LEN("SMALLINT")); - break; - case MYSQL_TYPE_SHORT: - if (((Field_num*)field)->unsigned_flag) - mapping.append(STRING_WITH_LEN("INT")); - else - mapping.append(STRING_WITH_LEN("SMALLINT")); - break; - case MYSQL_TYPE_LONG: - if (((Field_num*)field)->unsigned_flag) - mapping.append(STRING_WITH_LEN("BIGINT")); - else - mapping.append(STRING_WITH_LEN("INT")); - break; - case MYSQL_TYPE_FLOAT: - mapping.append(STRING_WITH_LEN("REAL")); - break; - case MYSQL_TYPE_DOUBLE: - mapping.append(STRING_WITH_LEN("DOUBLE")); - break; - case MYSQL_TYPE_LONGLONG: - if (((Field_num*)field)->unsigned_flag) - mapping.append(STRING_WITH_LEN("DECIMAL(20,0)")); - else - mapping.append(STRING_WITH_LEN("BIGINT")); - break; - case MYSQL_TYPE_INT24: - mapping.append(STRING_WITH_LEN("INTEGER")); - break; - case MYSQL_TYPE_DATE: - case MYSQL_TYPE_NEWDATE: - mapping.append(STRING_WITH_LEN("DATE")); - defaultNeedsQuotes = true; - break; - case MYSQL_TYPE_TIME: - if (timeFormat == TIME_OF_DAY) - { - mapping.append(STRING_WITH_LEN("TIME")); - defaultNeedsQuotes = true; - } - else - mapping.append(STRING_WITH_LEN("INTEGER")); - break; - case MYSQL_TYPE_DATETIME: - mapping.append(STRING_WITH_LEN("TIMESTAMP")); - defaultNeedsQuotes = true; - break; - case MYSQL_TYPE_TIMESTAMP: - mapping.append(STRING_WITH_LEN("TIMESTAMP")); - - if (table_share->timestamp_field == field && propagateDefaults) - { - switch (((Field_timestamp*)field)->get_auto_set_type()) - { - case TIMESTAMP_NO_AUTO_SET: - break; - case TIMESTAMP_AUTO_SET_ON_INSERT: - mapping.append(STRING_WITH_LEN(" DEFAULT CURRENT_TIMESTAMP")); - break; - case TIMESTAMP_AUTO_SET_ON_UPDATE: - if (osVersion.v >= 6 && - !field->is_null()) - { - mapping.append(STRING_WITH_LEN(" GENERATED BY DEFAULT FOR EACH ROW ON UPDATE AS ROW CHANGE TIMESTAMP")); - warning(ha_thd(), DB2I_ERR_WARN_COL_ATTRS, field->field_name); - } - else - warning(ha_thd(), DB2I_ERR_WARN_COL_ATTRS, field->field_name); - break; - case TIMESTAMP_AUTO_SET_ON_BOTH: - if (osVersion.v >= 6 && - !field->is_null()) - mapping.append(STRING_WITH_LEN(" GENERATED BY DEFAULT FOR EACH ROW ON UPDATE AS ROW CHANGE TIMESTAMP")); - else - { - mapping.append(STRING_WITH_LEN(" DEFAULT CURRENT_TIMESTAMP")); - warning(ha_thd(), DB2I_ERR_WARN_COL_ATTRS, field->field_name); - } - break; - } - } - else - defaultNeedsQuotes = true; - break; - case MYSQL_TYPE_YEAR: - if (yearFormat == CHAR4) - { - mapping.append(STRING_WITH_LEN("CHAR(4) CCSID 1208")); - defaultNeedsQuotes = true; - } - else - { - mapping.append(STRING_WITH_LEN("SMALLINT")); - defaultNeedsQuotes = false; - } - break; - case MYSQL_TYPE_BIT: - sprintf(stringBuildBuffer, "BINARY(%d)", (field->max_display_length() / 8) + 1); - mapping.append(stringBuildBuffer); - break; - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_VARCHAR: - case MYSQL_TYPE_STRING: - { - if (field->real_type() == MYSQL_TYPE_ENUM || - field->real_type() == MYSQL_TYPE_SET) - { - mapping.append(STRING_WITH_LEN("BIGINT")); - } - else - { - defaultNeedsQuotes = true; - - fieldLength = field->max_display_length(); // Get field byte length - - if (fieldCharSet == &my_charset_bin) - { - if (field->type() == MYSQL_TYPE_STRING) - { - sprintf(stringBuildBuffer, "BINARY(%d)", max(fieldLength, 1)); - } - else - { - if (fieldLength <= MAX_VARCHAR_LENGTH) - { - sprintf(stringBuildBuffer, "VARBINARY(%d)", max(fieldLength, 1)); - } - else if (blobMapping == AS_VARCHAR && - (field->flags & PART_KEY_FLAG)) - { - sprintf(stringBuildBuffer, "LONG VARBINARY "); - } - else - { - fieldLength = min(MAX_BLOB_LENGTH, fieldLength); - sprintf(stringBuildBuffer, "BLOB(%d)", max(fieldLength, 1)); - } - } - mapping.append(stringBuildBuffer); - } - else - { - if (field->type() == MYSQL_TYPE_STRING) - { - if (fieldLength > MAX_CHAR_LENGTH) - return 1; - if (fieldCharSet->mbmaxlen > 1) - { - if (memcmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")-1) == 0 ) // UCS2 - { - sprintf(stringBuildBuffer, "GRAPHIC(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters - db2Ccsid = 13488; - } - else if (memcmp(fieldCharSet->name, "utf8_", sizeof("utf8_")-1) == 0 && - strcmp(fieldCharSet->name, "utf8_general_ci") != 0) - { - sprintf(stringBuildBuffer, "CHAR(%d)", max(fieldLength, 1)); // Number of bytes - db2Ccsid = 1208; - } - else - { - sprintf(stringBuildBuffer, "GRAPHIC(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters - db2Ccsid = 1200; - } - } - else - { - sprintf(stringBuildBuffer, "CHAR(%d)", max(fieldLength, 1)); - } - mapping.append(stringBuildBuffer); - } - else - { - if (fieldLength <= MAX_VARCHAR_LENGTH) - { - if (fieldCharSet->mbmaxlen > 1) - { - if (memcmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")-1) == 0 ) // UCS2 - { - sprintf(stringBuildBuffer, "VARGRAPHIC(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters - db2Ccsid = 13488; - } - else if (memcmp(fieldCharSet->name, "utf8_", sizeof("utf8_")-1) == 0 && - strcmp(fieldCharSet->name, "utf8_general_ci") != 0) - { - sprintf(stringBuildBuffer, "VARCHAR(%d)", max(fieldLength, 1)); // Number of bytes - db2Ccsid = 1208; - } - else - { - sprintf(stringBuildBuffer, "VARGRAPHIC(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters - db2Ccsid = 1200; - } - } - else - { - sprintf(stringBuildBuffer, "VARCHAR(%d)", max(fieldLength, 1)); - } - } - else if (blobMapping == AS_VARCHAR && - (field->flags & PART_KEY_FLAG)) - { - if (fieldCharSet->mbmaxlen > 1) - { - if (memcmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")-1) == 0 ) // UCS2 - { - sprintf(stringBuildBuffer, "LONG VARGRAPHIC "); - db2Ccsid = 13488; - } - else if (memcmp(fieldCharSet->name, "utf8_", sizeof("utf8_")-1) == 0 && - strcmp(fieldCharSet->name, "utf8_general_ci") != 0) - { - sprintf(stringBuildBuffer, "LONG VARCHAR "); - db2Ccsid = 1208; - } - else - { - sprintf(stringBuildBuffer, "LONG VARGRAPHIC "); - db2Ccsid = 1200; - } - } - else - { - sprintf(stringBuildBuffer, "LONG VARCHAR "); - } - } - else - { - fieldLength = min(MAX_BLOB_LENGTH, fieldLength); - - if (fieldCharSet->mbmaxlen > 1) - { - if (memcmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")-1) == 0 ) // UCS2 - { - sprintf(stringBuildBuffer, "DBCLOB(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters - db2Ccsid = 13488; - } - else if (memcmp(fieldCharSet->name, "utf8_", sizeof("utf8_")-1) == 0 && - strcmp(fieldCharSet->name, "utf8_general_ci") != 0) - { - sprintf(stringBuildBuffer, "CLOB(%d)", max(fieldLength, 1)); // Number of bytes - db2Ccsid = 1208; - } - else - { - sprintf(stringBuildBuffer, "DBCLOB(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters - db2Ccsid = 1200; - } - } - else - { - sprintf(stringBuildBuffer, "CLOB(%d)", max(fieldLength, 1)); // Number of characters - } - } - - mapping.append(stringBuildBuffer); - } - if (db2Ccsid == 0) // If not overriding CCSID - { - int32 rtnCode = convertIANAToDb2Ccsid(fieldCharSet->csname, &db2Ccsid); - if (rtnCode) - return rtnCode; - } - - if (db2Ccsid != 1208 && - db2Ccsid != 13488) - { - // Check whether there is a character conversion available. - iconv_t temp; - int32 rc = getConversion(toDB2, fieldCharSet, db2Ccsid, temp); - if (unlikely(rc)) - return rc; - } - - sprintf(stringBuildBuffer, " CCSID %d ", db2Ccsid); - mapping.append(stringBuildBuffer); - } - } - } - break; - - } - - if (propagateDefaults) - get_field_default_value(field, - mapping, - defaultNeedsQuotes, - db2Ccsid, - (zeroDateHandling==SUBSTITUTE_0001_01_01)); - - return 0; -} - - -/** - Convert MySQL field data into the equivalent DB2 format - - @param field The MySQL field to be converted - @param db2Field The corresponding DB2 field definition - @param db2Buf The buffer to receive the converted data - @param data NULL if field points to the correct data; otherwise, - the data to be converted (for use with keys) -*/ -int32 ha_ibmdb2i::convertMySQLtoDB2(Field* field, const DB2Field& db2Field, char* db2Buf, const uchar* data) -{ - enum_field_types fieldType = field->type(); - switch (fieldType) - { - case MYSQL_TYPE_NEWDECIMAL: - { - uint precision= ((Field_new_decimal*)field)->precision; - uint scale= field->decimals(); - uint db2Precision = min(precision, MAX_DEC_PRECISION); - uint truncationAmount = precision - db2Precision; - - if (scale >= truncationAmount) - { - String tempString(precision+2); - - if (data == NULL) - { - field->val_str((String*)&tempString, (String*)(NULL)); - } - else - { - field->val_str(&tempString, data); - } - const char* temp = tempString.ptr(); - char packed[32]; - memset(&packed, 0, sizeof(packed)); - - int bcdPos = db2Precision - (db2Precision % 2 ? 1 : 0); - bcdAssign(packed, bcdPos+1, (temp[0] == '-' ? 0xD : 0xF)); - - int strPos=tempString.length() - 1 - truncationAmount; - - for (;strPos >= 0 && bcdPos >= 0; strPos--) - { - if (my_isdigit(&my_charset_latin1, temp[strPos])) - { - bcdAssign(packed, bcdPos, temp[strPos]-'0'); - --bcdPos; - } - } - memcpy(db2Buf, &packed, (db2Precision/2)+1); - } - - } - break; - case MYSQL_TYPE_TINY: - { - int16 temp = (data == NULL ? field->val_int() : field->val_int(data)); - memcpy(db2Buf , &temp, sizeof(temp)); - } - break; - case MYSQL_TYPE_SHORT: - { - if (((Field_num*)field)->unsigned_flag) - { - memset(db2Buf, 0, 2); - memcpy(db2Buf+2, (data == NULL ? field->ptr : data), 2); - } - else - { - memcpy(db2Buf, (data == NULL ? field->ptr : data), 2); - } - } - break; - case MYSQL_TYPE_LONG: - { - if (((Field_num*)field)->unsigned_flag) - { - memset(db2Buf, 0, 4); - memcpy(db2Buf+4, (data == NULL ? field->ptr : data), 4); - } - else - { - memcpy(db2Buf, (data == NULL ? field->ptr : data), 4); - } - } - break; - case MYSQL_TYPE_FLOAT: - { - memcpy(db2Buf, (data == NULL ? field->ptr : data), 4); - } - break; - case MYSQL_TYPE_DOUBLE: - { - memcpy(db2Buf, (data == NULL ? field->ptr : data), 8); - } - break; - case MYSQL_TYPE_TIMESTAMP: - case MYSQL_TYPE_DATETIME: - { - String tempString(27); - if (data == NULL) - { - field->val_str(&tempString, &tempString); - } - else - { - field->val_str(&tempString, data); - } - memset(db2Buf, '0', 26); - memcpy(db2Buf, tempString.ptr(), tempString.length()); - if (strncmp(db2Buf,ZERO_DATETIME_VALUE,strlen(ZERO_DATETIME_VALUE)) == 0) - { - if (cachedZeroDateOption == SUBSTITUTE_0001_01_01) - memcpy(db2Buf, ZERO_DATETIME_VALUE_SUBST, sizeof(ZERO_DATETIME_VALUE_SUBST)); - else - { - getErrTxt(DB2I_ERR_INVALID_COL_VALUE, field->field_name); - return(DB2I_ERR_INVALID_COL_VALUE); - } - } - (db2Buf)[10] = '-'; - (db2Buf)[13] = (db2Buf)[16] = (db2Buf)[19] = '.'; - - convertNumericToEbcdicFast(db2Buf, 26); - } - break; - case MYSQL_TYPE_LONGLONG: - { - if (((Field_num*)field)->unsigned_flag) - { - char temp[23]; - String tempString(temp, sizeof(temp), &my_charset_latin1); - - if (data == NULL) - { - field->val_str((String*)&tempString, (String*)(NULL)); - } - else - { - field->val_str(&tempString, data); - } - char packed[11]; - memset(packed, 0, sizeof(packed)); - bcdAssign(packed, 21, (temp[0] == '-' ? 0xD : 0xF)); - int strPos=tempString.length()-1; - int bcdPos=20; - - for (;strPos >= 0; strPos--) - { - if (my_isdigit(&my_charset_latin1, temp[strPos])) - { - bcdAssign(packed, bcdPos, temp[strPos]-'0'); - --bcdPos; - } - } - memcpy(db2Buf, &packed, 11); - } - else - { - *(uint64*)db2Buf = *(uint64*)(data == NULL ? field->ptr : data); - } - } - break; - case MYSQL_TYPE_INT24: - { - int32 temp= (data == NULL ? field->val_int() : field->val_int(data)); - memcpy(db2Buf , &temp, sizeof(temp)); - } - break; - case MYSQL_TYPE_DATE: - case MYSQL_TYPE_NEWDATE: - { - String tempString(11); - if (data == NULL) - { - field->val_str(&tempString, (String*)NULL); - } - else - { - field->val_str(&tempString, data); - } - memcpy(db2Buf, tempString.ptr(), 10); - if (strncmp(db2Buf,ZERO_DATE_VALUE,strlen(ZERO_DATE_VALUE)) == 0) - { - if (cachedZeroDateOption == SUBSTITUTE_0001_01_01) - memcpy(db2Buf, ZERO_DATE_VALUE_SUBST, sizeof(ZERO_DATE_VALUE_SUBST)); - else - { - getErrTxt(DB2I_ERR_INVALID_COL_VALUE,field->field_name); - return(DB2I_ERR_INVALID_COL_VALUE); - } - } - - convertNumericToEbcdicFast(db2Buf,10); - } - break; - case MYSQL_TYPE_TIME: - { - if (db2Field.getType() == QMY_TIME) - { - String tempString(10); - if (data == NULL) - { - field->val_str(&tempString, (String*)NULL); - } - else - { - field->val_str(&tempString, data); - } - memcpy(db2Buf, tempString.ptr(), 8); - (db2Buf)[2]=(db2Buf)[5] = '.'; - - convertNumericToEbcdicFast(db2Buf, 8); - } - else - { - int32 temp = sint3korr(data == NULL ? field->ptr : data); - memcpy(db2Buf, &temp, sizeof(temp)); - } - } - break; - case MYSQL_TYPE_YEAR: - { - String tempString(5); - if (db2Field.getType() == QMY_CHAR) - { - if (data == NULL) - { - field->val_str(&tempString, (String*)NULL); - } - else - { - field->val_str(&tempString, data); - } - memcpy(db2Buf, tempString.ptr(), 4); - } - else - { - uint8 temp = *(uint8*)(data == NULL ? field->ptr : data); - *(uint16*)(db2Buf) = (temp ? temp + 1900 : 0); - } - } - break; - case MYSQL_TYPE_BIT: - { - int bytesToCopy = db2Field.getByteLengthInRecord(); - - if (data == NULL) - { - uint64 temp = field->val_int(); - memcpy(db2Buf, - ((char*)&temp) + (sizeof(temp) - bytesToCopy), - bytesToCopy); - } - else - { - memcpy(db2Buf, - data, - bytesToCopy); - } - } - break; - case MYSQL_TYPE_VARCHAR: - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_BLOB: - { - if (field->real_type() == MYSQL_TYPE_ENUM || - field->real_type() == MYSQL_TYPE_SET) - { - int64 temp= (data == NULL ? field->val_int() : field->val_int(data)); - *(int64*)db2Buf = temp; - } - else - { - const uchar* dataToStore; - uint32 bytesToStore; - uint32 bytesToPad = 0; - CHARSET_INFO* fieldCharSet = field->charset(); - uint32 maxDisplayLength = field->max_display_length(); - switch (fieldType) - { - case MYSQL_TYPE_STRING: - { - bytesToStore = maxDisplayLength; - if (data == NULL) - dataToStore = field->ptr; - else - dataToStore = data; - } - break; - case MYSQL_TYPE_VARCHAR: - { - - if (data == NULL) - { - bytesToStore = field->data_length(); - dataToStore = field->ptr + ((Field_varstring*)field)->length_bytes; - } - else - { - // Key lens are stored little-endian - bytesToStore = *(uint8*)data + ((*(uint8*)(data+1)) << 8); - dataToStore = data + 2; - } - bytesToPad = maxDisplayLength - bytesToStore; - } - break; - case MYSQL_TYPE_BLOB: - { - if (data == NULL) - { - bytesToStore = ((Field_blob*)field)->get_length(); - bytesToPad = maxDisplayLength - bytesToStore; - ((Field_blob*)field)->get_ptr((uchar**)&dataToStore); - } - else - { - // Key lens are stored little-endian - bytesToStore = *(uint8*)data + ((*(uint8*)(data+1)) << 8); - dataToStore = data + 2; - } - } - break; - } - - int32 rc; - uint16 db2FieldType = db2Field.getType(); - switch(db2FieldType) - { - case QMY_CHAR: - if (maxDisplayLength == 0) - bytesToPad = 1; - case QMY_VARCHAR: - if (db2FieldType == QMY_VARCHAR) - { - db2Buf += sizeof(uint16); - bytesToPad = 0; - } - - if (bytesToStore > db2Field.getDataLengthInRecord()) - { - bytesToStore = db2Field.getDataLengthInRecord(); - field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); - } - - if (fieldCharSet == &my_charset_bin) // If binary - { - if (bytesToStore) - memcpy(db2Buf, dataToStore, bytesToStore); - if (bytesToPad) - memset(db2Buf + bytesToStore, 0x00, bytesToPad); - } - else if (db2Field.getCCSID() == 1208) // utf8 - { - if (bytesToStore) - memcpy(db2Buf, dataToStore, bytesToStore); - if (bytesToPad) - memset(db2Buf + bytesToStore, ' ', bytesToPad); - } - else // single-byte ASCII to EBCDIC - { - DBUG_ASSERT(fieldCharSet->mbmaxlen == 1); - if (bytesToStore) - { - rc = convertFieldChars(toDB2, field->field_index, (char*)dataToStore, db2Buf, bytesToStore, bytesToStore, NULL); - if (rc) - return rc; - } - if (bytesToPad) - memset(db2Buf + bytesToStore, 0x40, bytesToPad); - } - - if (db2FieldType == QMY_VARCHAR) - *(uint16*)(db2Buf - sizeof(uint16)) = bytesToStore; - break; - case QMY_VARGRAPHIC: - db2Buf += sizeof(uint16); - bytesToPad = 0; - case QMY_GRAPHIC: - if (maxDisplayLength == 0 && db2FieldType == QMY_GRAPHIC) - bytesToPad = 2; - - if (db2Field.getCCSID() == 13488) - { - if (bytesToStore) - memcpy(db2Buf, dataToStore, bytesToStore); - if (bytesToPad) - memset16((db2Buf + bytesToStore), 0x0020, bytesToPad/2); - } - else - { - size_t db2BytesToStore; - size_t maxDb2BytesToStore; - - if (maxDisplayLength == 0 && db2FieldType == QMY_GRAPHIC) - maxDb2BytesToStore = 2; - else - maxDb2BytesToStore = min(((bytesToStore * 2) / fieldCharSet->mbminlen), - ((maxDisplayLength * 2) / fieldCharSet->mbmaxlen)); - - if (bytesToStore == 0) - db2BytesToStore = 0; - else - { - rc = convertFieldChars(toDB2, field->field_index, (char*)dataToStore, db2Buf, bytesToStore, maxDb2BytesToStore, &db2BytesToStore); - if (rc) - return rc; - bytesToStore = db2BytesToStore; - } - if (db2BytesToStore < maxDb2BytesToStore) // If need to pad - memset16((db2Buf + db2BytesToStore), 0x0020, (maxDb2BytesToStore - db2BytesToStore)/2); - } - - if (db2FieldType == QMY_VARGRAPHIC) - *(uint16*)(db2Buf-sizeof(uint16)) = bytesToStore/2; - break; - case QMY_BLOBCLOB: - case QMY_DBCLOB: - { - DBUG_ASSERT(data == NULL); - DB2LobField* lobField = (DB2LobField*)(db2Buf + db2Field.calcBlobPad()); - - if ((fieldCharSet == &my_charset_bin) || // binary or - (db2Field.getCCSID()==13488) || - (db2Field.getCCSID()==1208)) // binary UTF8 - { - } - else - { - char* temp; - int32 rc; - size_t db2BytesToStore; - if (fieldCharSet->mbmaxlen == 1) // single-byte ASCII to EBCDIC - { - temp = getCharacterConversionBuffer(field->field_index, bytesToStore); - rc = convertFieldChars(toDB2, field->field_index, (char*)dataToStore,temp,bytesToStore, bytesToStore, NULL); - if (rc) - return (rc); - } - else // Else Far East, special UTF8 or non-special UTF8/UCS2 - { - size_t maxDb2BytesToStore; - maxDb2BytesToStore = min(((bytesToStore * 2) / fieldCharSet->mbminlen), - ((maxDisplayLength * 2) / fieldCharSet->mbmaxlen)); - temp = getCharacterConversionBuffer(field->field_index, maxDb2BytesToStore); - rc = convertFieldChars(toDB2, field->field_index, (char*)dataToStore,temp,bytesToStore, maxDb2BytesToStore, &db2BytesToStore); - if (rc) - return (rc); - bytesToStore = db2BytesToStore; - } - dataToStore = (uchar*)temp; - } - - uint16 blobID = db2Table->getBlobIdFromField(field->field_index); - if (blobWriteBuffers[blobID] != (char*)dataToStore) - blobWriteBuffers[blobID].reassign((char*)dataToStore); - if ((void*)blobWriteBuffers[blobID]) - lobField->dataHandle = (ILEMemHandle)blobWriteBuffers[blobID]; - else - lobField->dataHandle = 0; - lobField->length = bytesToStore / (db2FieldType == QMY_DBCLOB ? 2 : 1); - } - break; - } - } - } - break; - default: - DBUG_ASSERT(0); - break; - } - - return (ha_thd()->is_error()); -} - - -/** - Convert DB2 field data into the equivalent MySQL format - - @param db2Field The DB2 field definition - @param field The MySQL field to receive the converted data - @param buf The DB2 data to be converted -*/ -int32 ha_ibmdb2i::convertDB2toMySQL(const DB2Field& db2Field, Field* field, const char* buf) -{ - int32 storeRC = 0; // Result of the field->store() operation - - const char* bufPtr = buf + db2Field.getBufferOffset(); - - switch (field->type()) - { - case MYSQL_TYPE_NEWDECIMAL: - { - uint precision= ((Field_new_decimal*)field)->precision; - uint scale= field->decimals(); - uint db2Precision = min(precision, MAX_DEC_PRECISION); - uint decimalPlace = precision-scale+1; - char temp[80]; - - if (precision <= MAX_DEC_PRECISION || - scale > precision - MAX_DEC_PRECISION) - { - uint numNibbles = db2Precision + (db2Precision % 2 ? 0 : 1); - - temp[0] = (bcdGet(bufPtr, numNibbles) == 0xD ? '-' : ' '); - int strPos=1; - int bcdPos=(db2Precision % 2 ? 0 : 1); - - for (;bcdPos < numNibbles; bcdPos++, strPos++) - { - if (strPos == decimalPlace) - { - temp[strPos] = '.'; - strPos++; - } - - temp[strPos] = bcdGet(bufPtr, bcdPos) + '0'; - } - - temp[strPos] = 0; - - storeRC = field->store(temp, strPos, &my_charset_latin1); - } - } - break; - case MYSQL_TYPE_TINY: - { - storeRC = field->store(*(int16*)bufPtr, ((Field_num*)field)->unsigned_flag); - } - break; - case MYSQL_TYPE_SHORT: - { - if (((Field_num*)field)->unsigned_flag) - { - storeRC = field->store(*(int32*)bufPtr, TRUE); - } - else - { - storeRC = field->store(*(int16*)bufPtr, FALSE); - } - } - break; - case MYSQL_TYPE_LONG: - { - if (((Field_num*)field)->unsigned_flag) - { - storeRC = field->store(*(int64*)bufPtr, TRUE); - } - else - { - storeRC = field->store(*(int32*)bufPtr, FALSE); - } - } - break; - case MYSQL_TYPE_FLOAT: - { - storeRC = field->store(*(float*)bufPtr); - } - break; - case MYSQL_TYPE_DOUBLE: - { - storeRC = field->store(*(double*)bufPtr); - } - break; - case MYSQL_TYPE_LONGLONG: - { - char temp[23]; - if (((Field_num*)field)->unsigned_flag) - { - temp[0] = (bcdGet(bufPtr, 21) == 0xD ? '-' : ' '); - int strPos=1; - int bcdPos=0; - - for (;bcdPos <= 20; bcdPos++, strPos++) - { - temp[strPos] = bcdGet(bufPtr, bcdPos) + '0'; - } - - temp[strPos] = 0; - - storeRC = field->store(temp, strPos, &my_charset_latin1); - } - else - { - storeRC = field->store(*(int64*)bufPtr, FALSE); - } - } - break; - case MYSQL_TYPE_INT24: - { - storeRC = field->store(*(int32*)bufPtr, ((Field_num*)field)->unsigned_flag); - } - break; - case MYSQL_TYPE_DATE: - case MYSQL_TYPE_NEWDATE: - { - longlong value= a4toi_ebcdic((uchar*)bufPtr) * 10000 + - a2toi_ebcdic((uchar*)bufPtr+5) * 100 + - a2toi_ebcdic((uchar*)bufPtr+8); - - if (cachedZeroDateOption == SUBSTITUTE_0001_01_01 && - value == (10000 + 100 + 1)) - value = 0; - - storeRC = field->store(value); - } - break; - case MYSQL_TYPE_TIME: - { - if (db2Field.getType() == QMY_TIME) - { - longlong value= a2toi_ebcdic((uchar*)bufPtr) * 10000 + - a2toi_ebcdic((uchar*)bufPtr+3) * 100 + - a2toi_ebcdic((uchar*)bufPtr+6); - - storeRC = field->store(value); - } - else - storeRC = field->store(*((int32*)bufPtr)); - } - break; - case MYSQL_TYPE_TIMESTAMP: - case MYSQL_TYPE_DATETIME: - { - longlong value= (a4toi_ebcdic((uchar*)bufPtr) * 10000 + - a2toi_ebcdic((uchar*)bufPtr+5) * 100 + - a2toi_ebcdic((uchar*)bufPtr+8)) * 1000000LL + - (a2toi_ebcdic((uchar*)bufPtr+11) * 10000 + - a2toi_ebcdic((uchar*)bufPtr+14) * 100 + - a2toi_ebcdic((uchar*)bufPtr+17)); - - if (cachedZeroDateOption == SUBSTITUTE_0001_01_01 && - value == (10000 + 100 + 1) * 1000000LL) - value = 0; - - storeRC = field->store(value); - } - break; - case MYSQL_TYPE_YEAR: - { - if (db2Field.getType() == QMY_CHAR) - { - storeRC = field->store(bufPtr, 4, &my_charset_bin); - } - else - { - storeRC = field->store(*((uint16*)bufPtr)); - } - } - break; - case MYSQL_TYPE_BIT: - { - uint64 temp= 0; - int bytesToCopy= db2Field.getByteLengthInRecord(); - memcpy(((char*)&temp) + (sizeof(temp) - bytesToCopy), bufPtr, bytesToCopy); - storeRC = field->store(temp, TRUE); - } - break; - case MYSQL_TYPE_VARCHAR: - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_BLOB: - { - if (field->real_type() == MYSQL_TYPE_ENUM || - field->real_type() == MYSQL_TYPE_SET) - { - storeRC = field->store(*(int64*)bufPtr); - } - else - { - - const char* dataToStore = NULL; - uint32 bytesToStore = 0; - CHARSET_INFO* fieldCharSet = field->charset(); - switch(db2Field.getType()) - { - case QMY_CHAR: - case QMY_GRAPHIC: - { - bytesToStore = db2Field.getByteLengthInRecord(); - if (bytesToStore == 0) - bytesToStore = 1; - dataToStore = bufPtr; - } - break; - case QMY_VARCHAR: - { - bytesToStore = *(uint16*)bufPtr; - dataToStore = bufPtr+sizeof(uint16); - } - break; - case QMY_VARGRAPHIC: - { - /* For VARGRAPHIC, convert the number of double-byte characters - to the number of bytes. */ - bytesToStore = (*(uint16*)bufPtr)*2; - dataToStore = bufPtr+sizeof(uint16); - } - break; - case QMY_DBCLOB: - case QMY_BLOBCLOB: - { - DB2LobField* lobField = (DB2LobField* )(bufPtr + db2Field.calcBlobPad()); - bytesToStore = lobField->length * (db2Field.getType() == QMY_DBCLOB ? 2 : 1); - dataToStore = (char*)blobReadBuffers->getBufferPtr(field->field_index); - } - break; - - } - - if ((fieldCharSet != &my_charset_bin) && // not binary & - (db2Field.getCCSID() != 13488) && // not UCS2 & - (db2Field.getCCSID() != 1208)) - { - char* temp; - size_t db2BytesToStore; - int rc; - if (fieldCharSet->mbmaxlen > 1) - { - size_t maxDb2BytesToStore = ((bytesToStore / 2) * fieldCharSet->mbmaxlen); // Worst case for number of bytes - temp = getCharacterConversionBuffer(field->field_index, maxDb2BytesToStore); - rc = convertFieldChars(toMySQL, field->field_index, dataToStore, temp, bytesToStore, maxDb2BytesToStore, &db2BytesToStore); - bytesToStore = db2BytesToStore; - } - else // single-byte ASCII to EBCDIC - { - temp = getCharacterConversionBuffer(field->field_index, bytesToStore); - rc = convertFieldChars(toMySQL, field->field_index, dataToStore, temp, bytesToStore, bytesToStore, NULL); - } - if (rc) - return (rc); - dataToStore = temp; - } - - if ((field)->flags & BLOB_FLAG) - ((Field_blob*)(field))->set_ptr(bytesToStore, (uchar*)dataToStore); - else - storeRC = field->store(dataToStore, bytesToStore, &my_charset_bin); - } - } - break; - default: - DBUG_ASSERT(0); - break; - - } - - if (storeRC) - { - invalidDataFound = true; - } - - return 0; -} diff --git a/storage/ibmdb2i/db2i_errors.cc b/storage/ibmdb2i/db2i_errors.cc deleted file mode 100644 index dd50e40e61b..00000000000 --- a/storage/ibmdb2i/db2i_errors.cc +++ /dev/null @@ -1,297 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - -#include "db2i_errors.h" -#include "db2i_ileBridge.h" -#include "db2i_charsetSupport.h" -#include "mysql_priv.h" -#include "stdarg.h" - -#define MAX_MSGSTRING 109 - -/* - The following strings are associated with errors that can be produced - within the storage engine proper. -*/ -static const char* engineErrors[MAX_MSGSTRING] = -{ - {""}, - {"Error opening codeset conversion from %.64s to %.64s (errno = %d)"}, - {"Invalid %-.10s name '%-.128s'"}, - {"Unsupported move from '%-.128s' to '%-.128s' on RENAME TABLE statement"}, - {"The %-.64s character set is not supported."}, - {"Auto_increment is not allowed for a partitioned table"}, - {"Character set conversion error due to unknown encoding scheme %d"}, - {""}, - {"Table '%-.128s' was not found by the storage engine"}, - {"Could not resolve to %-.128s in library %-.10s type %-.10s (errno = %d)"}, - {"Error on _PGMCALL for program %-.10s in library %-.10s (error = %d)"}, - {"Error on _ILECALL for API '%.128s' (error = %d)"}, - {"Error in iconv() function during character set conversion (errno = %d)"}, - {"Error from Get Encoding Scheme (QTQGESP) API: %d, %d, %d"}, - {"Error from Get Related Default CCSID (QTQGRDC) API: %d, %d, %d"}, - {"Data out of range for column '%.192s'"}, - {"Schema name '%.128s' exceeds maximum length of %d characters"}, - {"Multiple collations not supported in a single index or constraint"}, - {"Sort sequence was not found"}, - {"One or more characters in column %.128s were substituted during conversion"}, - {"A decimal column exceeded the maximum precision. Data may be truncated."}, - {"Some data returned by DB2 for table %s could not be converted for MySQL"}, - {""}, - {"Column %.128s contains characters that cannot be converted"}, - {"An invalid name was specified for ibmdb2i_rdb_name."}, - {"A duplicate key was encountered for index '%.128s'"}, - {"A table with the same name exists but has incompatible column definitions."}, - {"The created table was discovered as an existing DB2 object."}, - {"Some attribute(s) defined for column '%.128s' may not be honored by accesses from DB2."}, -}; - -/* - The following strings are associated with errors that can be returned - by the operating system via the QMY_* APIs. Most are very uncommon and - indicate a bug somewhere. -*/ -static const char* systemErrors[MAX_MSGSTRING] = -{ - {"Thread ID is too long"}, - {"Error creating a SPACE memory object"}, - {"Error creating a FILE memory object"}, - {"Error creating a SPACE synchronization token"}, - {"Error creating a FILE synchronization token"}, - {"See message %-.7s in joblog for job %-.6s/%-.10s/%-.10s."}, - {"Error unlocking a synchronization token when closing a connection"}, - {"Invalid action specified for an 'object lock' request"}, - {"Invalid action specified for a savepoint request"}, - {"Partial keys are not supported with an ICU sort sequence"}, - {"Error retrieving an ICU sort key"}, - {"Error converting single-byte sort sequence to UCS-2"}, - {"An unsupported collation was specified"}, - {"Validation failed for referenced table of foreign key constraint"}, - {"Error extracting table for constraint information"}, - {"Error extracting referenced table for constraint information"}, - {"Invalid action specified for a 'commitment control' request"}, - {"Invalid commitment control isolation level specified on 'open' request"}, - {"Invalid file handle"}, - {" "}, - {"Invalid option specified for returning data on 'read' request"}, - {"Invalid orientation specified for 'read' request"}, - {"Invalid option type specified for 'read' request"}, - {"Invalid isolation level for starting commitment control"}, - {"Error unlocking a synchronization token in module QMYALC"}, - {"Length of space for returned format is not long enough"}, - {"SQL XA transactions are currently unsupported by this interface"}, - {"The associated QSQSRVR job was killed or ended unexpectedly."}, - {"Error unlocking a synchronization token in module QMYSEI"}, - {"Error unlocking a synchronization token in module QMYSPO"}, - {"Error converting input CCSID from short form to long form"}, - {" "}, - {"Error getting associated CCSID for CCSID conversion"}, - {"Error converting a string from one CCSID to another"}, - {"Error unlocking a synchronization token"}, - {"Error destroying a synchronization token"}, - {"Error locking a synchronization token"}, - {"Error recreating a synchronization token"}, - {"A space handle was not specified for a constraint request"}, - {"An SQL cursor was specified for a delete request"}, - {" "}, - {"Error on delete request because current UFCB for connection is not open"}, - {"An SQL cursor was specified for an object initialization request"}, - {"An SQL cursor was specified for an object override request"}, - {"A space handle was not specified for an object override request"}, - {"An SQL cursor was specified for an information request"}, - {"An SQL cursor was specified for an object lock request"}, - {"An SQL cursor was specified for an optimize request"}, - {"A data handle was not specified for a read request"}, - {"A row number handle was not specified for a read request"}, - {"A key handle was not specified for a read request"}, - {"An SQL cursor was specified for an row estimation request"}, - {"A space handle was not specified for a row estimation request"}, - {"An SQL cursor was specified for a release record request"}, - {"A statement handle was not specified for an 'execute immediate' request"}, - {"A statement handle was not specified for a 'prepare open' request"}, - {"An SQL cursor was specified for an update request"}, - {"The UFCB was not open for read"}, - {"Error on update request because current UFCB for connection is not open"}, - {"A data handle was not specified for an update request"}, - {"An SQL cursor was specified for a write request"}, - {"A data handle was not specified for a write request"}, - {"An unknown function was specified on a process request"}, - {"A share definition was not specified for an 'allocate share' request"}, - {"A share handle was not specified for an 'allocate share' request"}, - {"A use count handle was not specified for an 'allocate share' request"}, - {"A 'records per key' handle was not specified for an information request"}, - {"Error resolving LOB addresss"}, - {"Length of a LOB space is too small"}, - {"An unknown function was specified for a server request"}, - {"Object authorization failed. See message %-.7s in joblog for job %-.6s/%-.10s/%-.10s. for more information."}, - {" "}, - {"Error locking mutex on server"}, - {"Error unlocking mutex on server"}, - {"Error checking for RDB name in RDB Directory"}, - {"Error creating mutex on server"}, - {"A table with that name already exists"}, - {" "}, - {"Error unlocking mutex"}, - {"Error connecting to server job"}, - {"Error connecting to server job"}, - {" "}, - {"Function check occurred while registering parameter spaces. See joblog."}, - {" "}, - {" "}, - {"End of block"}, - {"The file has changed and might not be compatible with the MySQL table definition"}, - {"Error giving pipe to server job"}, - {"There are open object locks when attempting to deallocate"}, - {"There is no open lock"}, - {" "}, - {" "}, - {"The maximum value for the auto_increment data type was exceeded"}, - {"Error occurred closing the pipe "}, - {"Error occurred taking a descriptor for the pipe"}, - {"Error writing to pipe "}, - {"Server was interrupted "}, - {"No pipe descriptor exists for reuse "}, - {"Error occurred during an SQL prepare statement "}, - {"Error occurred during an SQL open "}, - {" "}, - {" "}, - {" "}, - {" "}, - {" "}, - {" "}, - {"An unspecified error was returned from the system."}, - {" "} -}; - -/** - This function builds the text string for an error code, and substitutes - a variable number of replacement variables into the string. -*/ -void getErrTxt(int errCode, ...) -{ - va_list args; - va_start(args,errCode); - char* buffer = db2i_ileBridge::getBridgeForThread()->getErrorStorage(); - const char* msg; - - if (errCode >= QMY_ERR_MIN && errCode <= QMY_ERR_SQ_OPEN) - msg = systemErrors[errCode - QMY_ERR_MIN]; - else - { - DBUG_ASSERT(errCode >= DB2I_FIRST_ERR && errCode <= DB2I_LAST_ERR); - msg = engineErrors[errCode - DB2I_FIRST_ERR]; - } - - (void) my_vsnprintf (buffer, MYSQL_ERRMSG_SIZE, msg, args); - va_end(args); - fprintf(stderr,"ibmdb2i error %d: %s\n",errCode,buffer); - DBUG_PRINT("error", ("ibmdb2i error %d: %s",errCode,buffer)); -} - -static inline void trimSpace(char* str) -{ - char* end = strchr(str, ' '); - if (end) *end = 0; -} - - -/** - Generate the error text specific to an API error returned by a QMY_* API. - - @parm errCode The error value - @parm errInfo The structure containing the message and job identifiers. -*/ -void reportSystemAPIError(int errCode, const Qmy_Error_output *errInfo) -{ - if (errCode >= QMY_ERR_MIN && errCode <= QMY_ERR_SQ_OPEN) - { - switch(errCode) - { - case QMY_ERR_MSGID: - case QMY_ERR_NOT_AUTH: - { - DBUG_ASSERT(errInfo); - char jMsg[8]; // Error message ID - char jName[11]; // Job name - char jUser[11]; // Job user - char jNbr[7]; // Job number - memset(jMsg, 0, sizeof(jMsg)); - memset(jName, 0, sizeof(jMsg)); - memset(jUser, 0, sizeof(jMsg)); - memset(jMsg, 0, sizeof(jMsg)); - - convFromEbcdic(errInfo->MsgId,jMsg,sizeof(jMsg)-1); - convFromEbcdic(errInfo->JobName,jName,sizeof(jName)-1); - trimSpace(jName); - convFromEbcdic(errInfo->JobUser,jUser,sizeof(jUser)-1); - trimSpace(jUser); - convFromEbcdic(errInfo->JobNbr,jNbr,sizeof(jNbr)-1); - getErrTxt(errCode,jMsg,jNbr,jUser,jName); - } - break; - case QMY_ERR_RTNFMT: - { - getErrTxt(QMY_ERR_LVLID_MISMATCH); - } - break; - default: - getErrTxt(errCode); - break; - } - } -} - - -/** - Generate a warning for the specified error. -*/ -void warning(THD *thd, int errCode, ...) -{ - va_list args; - va_start(args,errCode); - char buffer[MYSQL_ERRMSG_SIZE]; - const char* msg; - - DBUG_ASSERT(errCode >= DB2I_FIRST_ERR && errCode <= DB2I_LAST_ERR); - msg = engineErrors[errCode - DB2I_FIRST_ERR]; - - (void) my_vsnprintf (buffer, MYSQL_ERRMSG_SIZE, msg, args); - va_end(args); - DBUG_PRINT("warning", ("ibmdb2i warning %d: %s",errCode,buffer)); - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, errCode, buffer); -} - - diff --git a/storage/ibmdb2i/db2i_errors.h b/storage/ibmdb2i/db2i_errors.h deleted file mode 100644 index b6dd314ef50..00000000000 --- a/storage/ibmdb2i/db2i_errors.h +++ /dev/null @@ -1,93 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - -#ifndef DB2I_ERRORS_H -#define DB2I_ERRORS_H - -#include "qmyse.h" -class THD; - -/** - @enum DB2I_errors - - @brief These are the errors that can be returned by the storage engine proper - and that are specific to the engine. Refer to db2i_errors.cc for text - descriptions of the errors. -*/ - -enum DB2I_errors -{ - DB2I_FIRST_ERR = 2500, - DB2I_ERR_ICONV_OPEN, - DB2I_ERR_INVALID_NAME, - DB2I_ERR_RENAME_MOVE, - DB2I_ERR_UNSUPP_CHARSET, - DB2I_ERR_PART_AUTOINC, - DB2I_ERR_UNKNOWN_ENCODING, - DB2I_ERR_RESERVED, - DB2I_ERR_TABLE_NOT_FOUND, - DB2I_ERR_RESOLVE_OBJ, - DB2I_ERR_PGMCALL, - DB2I_ERR_ILECALL, - DB2I_ERR_ICONV, - DB2I_ERR_QTQGESP, - DB2I_ERR_QTQGRDC, - DB2I_ERR_INVALID_COL_VALUE, - DB2I_ERR_TOO_LONG_SCHEMA, - DB2I_ERR_MIXED_COLLATIONS, - DB2I_ERR_SRTSEQ, - DB2I_ERR_SUB_CHARS, - DB2I_ERR_PRECISION, - DB2I_ERR_INVALID_DATA, - DB2I_ERR_RESERVED2, - DB2I_ERR_ILL_CHAR, - DB2I_ERR_BAD_RDB_NAME, - DB2I_ERR_UNKNOWN_IDX, - DB2I_ERR_DISCOVERY_MISMATCH, - DB2I_ERR_WARN_CREATE_DISCOVER, - DB2I_ERR_WARN_COL_ATTRS, - DB2I_LAST_ERR = DB2I_ERR_WARN_COL_ATTRS -}; - -void getErrTxt(int errcode, ...); -void reportSystemAPIError(int errCode, const Qmy_Error_output *errInfo); -void warning(THD *thd, int errCode, ...); - -const char* DB2I_SQL0350 = "\xE2\xD8\xD3\xF0\xF3\xF5\xF0"; // SQL0350 in EBCDIC -const char* DB2I_CPF503A = "\xC3\xD7\xC6\xF5\xF0\xF3\xC1"; // CPF503A in EBCDIC -const char* DB2I_SQL0538 = "\xE2\xD8\xD3\xF0\xF5\xF3\xF8"; // SQL0538 in EBCDIC - -#endif diff --git a/storage/ibmdb2i/db2i_file.cc b/storage/ibmdb2i/db2i_file.cc deleted file mode 100644 index a16aa927527..00000000000 --- a/storage/ibmdb2i/db2i_file.cc +++ /dev/null @@ -1,556 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - - -#include "db2i_file.h" -#include "db2i_charsetSupport.h" -#include "db2i_collationSupport.h" -#include "db2i_misc.h" -#include "db2i_errors.h" -#include "my_dir.h" - -db2i_table::db2i_table(const TABLE_SHARE* myTable, const char* path) : - mysqlTable(myTable), - db2StartId(0), - blobFieldCount(0), - blobFields(NULL), - blobFieldActualSizes(NULL), - logicalFiles(NULL), - physicalFile(NULL), - db2TableNameSQLAscii(NULL), - db2LibNameSQLAscii(NULL) -{ - char asciiLibName[MAX_DB2_SCHEMANAME_LENGTH + 1]; - getDB2LibNameFromPath(path, asciiLibName, ASCII_NATIVE); - - char asciiFileName[MAX_DB2_FILENAME_LENGTH + 1]; - getDB2FileNameFromPath(path, asciiFileName, ASCII_NATIVE); - - size_t libNameLen = strlen(asciiLibName); - size_t fileNameLen = strlen(asciiFileName); - - db2LibNameEbcdic=(char *) - my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), - &db2LibNameEbcdic, libNameLen+1, - &db2LibNameAscii, libNameLen+1, - &db2LibNameSQLAscii, libNameLen*2 + 1, - &db2TableNameEbcdic, fileNameLen+1, - &db2TableNameAscii, fileNameLen+1, - &db2TableNameSQLAscii, fileNameLen*2 + 1, - NullS); - - if (likely(db2LibNameEbcdic)) - { - memcpy(db2LibNameAscii, asciiLibName, libNameLen); - convertNativeToSQLName(db2LibNameAscii, db2LibNameSQLAscii); - convToEbcdic(db2LibNameAscii, db2LibNameEbcdic, libNameLen); - memcpy(db2TableNameAscii, asciiFileName, fileNameLen); - convertNativeToSQLName(db2TableNameAscii, db2TableNameSQLAscii); - convToEbcdic(db2TableNameAscii, db2TableNameEbcdic, fileNameLen); - } - - conversionDefinitions[toMySQL] = NULL; - conversionDefinitions[toDB2] = NULL; - - isTemporaryTable = (strstr(mysqlTable->path.str, mysql_tmpdir) == mysqlTable->path.str); -} - - -int32 db2i_table::initDB2Objects(const char* path) -{ - uint fileObjects = 1 + mysqlTable->keys; - ValidatedPointer<ShrDef> fileDefnSpace(sizeof(ShrDef) * fileObjects); - - physicalFile = new db2i_file(this); - physicalFile->fillILEDefn(&fileDefnSpace[0], true); - - logicalFileCount = mysqlTable->keys; - if (logicalFileCount > 0) - { - logicalFiles = new db2i_file*[logicalFileCount]; - for (int k = 0; k < logicalFileCount; k++) - { - logicalFiles[k] = new db2i_file(this, k); - logicalFiles[k]->fillILEDefn(&fileDefnSpace[k+1], false); - } - } - - ValidatedPointer<FILE_HANDLE> fileDefnHandles(sizeof(FILE_HANDLE) * fileObjects); - size_t formatSpaceLen = sizeof(format_hdr_t) + mysqlTable->fields * sizeof(DB2Field); - formatSpace.alloc(formatSpaceLen); - - int rc = db2i_ileBridge::getBridgeForThread()-> - expectErrors(QMY_ERR_RTNFMT)-> - allocateFileDefn(fileDefnSpace, - fileDefnHandles, - fileObjects, - db2LibNameEbcdic, - strlen(db2LibNameEbcdic), - formatSpace, - formatSpaceLen); - - if (rc) - { - // We have to handle a format space error as a special case of a FID - // mismatch. We should only get the space error if columns have been added - // to the DB2 table without MySQL's knowledge, which is effectively a - // FID problem. - if (rc == QMY_ERR_RTNFMT) - { - rc = QMY_ERR_LVLID_MISMATCH; - getErrTxt(rc); - } - return rc; - } - - convFromEbcdic(((format_hdr_t*)formatSpace)->FilLvlId, fileLevelID, sizeof(fileLevelID)); - - if (!doFileIDsMatch(path)) - { - getErrTxt(QMY_ERR_LVLID_MISMATCH); - return QMY_ERR_LVLID_MISMATCH; - } - - physicalFile->setMasterDefnHandle(fileDefnHandles[0]); - for (int k = 0; k < mysqlTable->keys; k++) - { - logicalFiles[k]->setMasterDefnHandle(fileDefnHandles[k+1]); - } - - db2StartId = (uint64)(((format_hdr_t*)formatSpace)->StartIdVal); - db2Fields = (DB2Field*)((char*)(void*)formatSpace + ((format_hdr_t*)formatSpace)->ColDefOff); - - uint fields = mysqlTable->fields; - for (int i = 0; i < fields; ++i) - { - if (db2Field(i).isBlob()) - { - blobFieldCount++; - } - } - - if (blobFieldCount) - { - blobFieldActualSizes = (uint*)my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), - &blobFieldActualSizes, blobFieldCount * sizeof(uint), - &blobFields, blobFieldCount * sizeof(uint16), - NullS); - - int b = 0; - for (int i = 0; i < fields; ++i) - { - if (db2Field(i).isBlob()) - { - blobFields[b++] = i; - } - } - } - - my_multi_malloc(MYF(MY_WME), - &conversionDefinitions[toMySQL], fields * sizeof(iconv_t), - &conversionDefinitions[toDB2], fields * sizeof(iconv_t), - NullS); - for (int i = 0; i < fields; ++i) - { - conversionDefinitions[toMySQL][i] = (iconv_t)(-1); - conversionDefinitions[toDB2][i] = (iconv_t)(-1); - } - - return 0; -} - -int db2i_table::fastInitForCreate(const char* path) -{ - ValidatedPointer<ShrDef> fileDefnSpace(sizeof(ShrDef)); - - physicalFile = new db2i_file(this); - physicalFile->fillILEDefn(fileDefnSpace, true); - - ValidatedPointer<FILE_HANDLE> fileDefnHandles(sizeof(FILE_HANDLE)); - - size_t formatSpaceLen = sizeof(format_hdr_t) + - mysqlTable->fields * sizeof(DB2Field); - formatSpace.alloc(formatSpaceLen); - - int rc = db2i_ileBridge::getBridgeForThread()->allocateFileDefn(fileDefnSpace, - fileDefnHandles, - 1, - db2LibNameEbcdic, - strlen(db2LibNameEbcdic), - formatSpace, - formatSpaceLen); - - if (rc) - return rc; - - convFromEbcdic(((format_hdr_t*)formatSpace)->FilLvlId, fileLevelID, sizeof(fileLevelID)); - doFileIDsMatch(path); - - return 0; -} - -bool db2i_table::doFileIDsMatch(const char* path) -{ - char name_buff[FN_REFLEN]; - - fn_format(name_buff, path, "", FID_EXT, (MY_REPLACE_EXT | MY_UNPACK_FILENAME)); - - File fd = my_open(name_buff, O_RDONLY, MYF(0)); - - if (fd == -1) - { - if (errno == ENOENT) - { - fd = my_create(name_buff, 0, O_WRONLY, MYF(MY_WME)); - - if (fd == -1) - { - // TODO: Report errno here - return false; - } - my_write(fd, (uchar*)fileLevelID, sizeof(fileLevelID), MYF(MY_WME)); - my_close(fd, MYF(0)); - return true; - } - else - { - // TODO: Report errno here - return false; - } - } - - char diskFID[sizeof(fileLevelID)]; - - bool match = false; - - if (my_read(fd, (uchar*)diskFID, sizeof(diskFID), MYF(MY_WME)) == sizeof(diskFID) && - (memcmp(diskFID, fileLevelID, sizeof(diskFID)) == 0)) - match = true; - - my_close(fd, MYF(0)); - - return match; -} - -void db2i_table::deleteAssocFiles(const char* name) -{ - char name_buff[FN_REFLEN]; - fn_format(name_buff, name, "", FID_EXT, (MY_REPLACE_EXT | MY_UNPACK_FILENAME)); - my_delete(name_buff, MYF(0)); -} - -void db2i_table::renameAssocFiles(const char* from, const char* to) -{ - rename_file_ext(from, to, FID_EXT); -} - - -db2i_table::~db2i_table() -{ - if (blobFieldActualSizes) - my_free(blobFieldActualSizes, MYF(0)); - - if (conversionDefinitions[toMySQL]) - my_free(conversionDefinitions[toMySQL], MYF(0)); - - if (logicalFiles) - { - for (int k = 0; k < logicalFileCount; ++k) - { - delete logicalFiles[k]; - } - - delete[] logicalFiles; - } - delete physicalFile; - - my_free(db2LibNameEbcdic, 0); -} - -void db2i_table::getDB2QualifiedName(char* to) -{ - strcat(to, getDB2LibName(ASCII_SQL)); - strcat(to, "."); - strcat(to, getDB2TableName(ASCII_SQL)); -} - - -void db2i_table::getDB2QualifiedNameFromPath(const char* path, char* to) -{ - getDB2LibNameFromPath(path, to); - strcat(to, "."); - getDB2FileNameFromPath(path, strend(to)); -} - - -size_t db2i_table::smartFilenameToTableName(const char *in, char* out, size_t outlen) -{ - if (strchr(in, '@') == NULL) - { - return filename_to_tablename(in, out, outlen); - } - - char* test = (char*) my_malloc(outlen, MYF(MY_WME)); - - filename_to_tablename(in, test, outlen); - - char* cur = test; - - while (*cur) - { - if ((*cur <= 0x20) || (*cur >= 0x80)) - { - strncpy(out, in, outlen); - my_free(test, MYF(0)); - return min(outlen, strlen(out)); - } - ++cur; - } - - strncpy(out, test, outlen); - my_free(test, MYF(0)); - return min(outlen, strlen(out)); -} - -void db2i_table::filenameToTablename(const char* in, char* out, size_t outlen) -{ - if (strchr(in, '#') == NULL) - { - smartFilenameToTableName(in, out, outlen); - return; - } - - char* temp = (char*)sql_alloc(outlen); - - const char* part1, *part2, *part3, *part4; - part1 = in; - part2 = strstr(part1, "#P#"); - if (part2); - { - part3 = part2 + 3; - part4 = strchr(part3, '#'); - if (!part4) - part4 = strend(in); - } - - memcpy(temp, part1, min(outlen, part2 - part1)); - temp[min(outlen-1, part2-part1)] = 0; - - int32 accumLen = smartFilenameToTableName(temp, out, outlen); - - if (part2 && (accumLen + 4 < outlen)) - { - strcat(out, "#P#"); - accumLen += 4; - - memset(temp, 0, min(outlen, part2-part1)); - memcpy(temp, part3, min(outlen, part4-part3)); - temp[min(outlen-1, part4-part3)] = 0; - - accumLen += smartFilenameToTableName(temp, strend(out), outlen-accumLen); - - if (part4 && (accumLen + (strend(in) - part4 + 1) < outlen)) - { - strcat(out, part4); - } - } -} - -void db2i_table::getDB2LibNameFromPath(const char* path, char* lib, NameFormatFlags format) -{ - if (strstr(path, mysql_tmpdir) == path) - { - strcpy(lib, DB2I_TEMP_TABLE_SCHEMA); - } - else - { - const char* c = strend(path) - 1; - while (c > path && *c != '\\' && *c != '/') - --c; - - if (c != path) - { - const char* dbEnd = c; - do { - --c; - } while (c >= path && *c != '\\' && *c != '/'); - - if (c >= path) - { - const char* dbStart = c+1; - char fileName[FN_REFLEN]; - memcpy(fileName, dbStart, dbEnd - dbStart); - fileName[dbEnd-dbStart] = 0; - - char dbName[MAX_DB2_SCHEMANAME_LENGTH+1]; - filenameToTablename(fileName, dbName , sizeof(dbName)); - - convertMySQLNameToDB2Name(dbName, lib, sizeof(dbName), true, (format==ASCII_SQL) ); - } - else - DBUG_ASSERT(0); // This should never happen! - } - } -} - -void db2i_table::getDB2FileNameFromPath(const char* path, char* file, NameFormatFlags format) -{ - const char* fileEnd = strend(path); - const char* c = fileEnd; - while (c > path && *c != '\\' && *c != '/') - --c; - - if (c != path) - { - const char* fileStart = c+1; - char fileName[FN_REFLEN]; - memcpy(fileName, fileStart, fileEnd - fileStart); - fileName[fileEnd - fileStart] = 0; - char db2Name[MAX_DB2_FILENAME_LENGTH+1]; - filenameToTablename(fileName, db2Name, sizeof(db2Name)); - convertMySQLNameToDB2Name(db2Name, file, sizeof(db2Name), true, (format==ASCII_SQL) ); - } -} - -// Generates the DB2 index name when given the MySQL index and table names. -int32 db2i_table::appendQualifiedIndexFileName(const char* indexName, - const char* tableName, - String& to, - NameFormatFlags format, - enum_DB2I_INDEX_TYPE type) -{ - char generatedName[MAX_DB2_FILENAME_LENGTH+1]; - strncpy(generatedName, indexName, DB2I_INDEX_NAME_LENGTH_TO_PRESERVE); - generatedName[DB2I_INDEX_NAME_LENGTH_TO_PRESERVE] = 0; - char* endOfGeneratedName; - - if (type == typeDefault) - { - strcat(generatedName, DB2I_DEFAULT_INDEX_NAME_DELIMITER); - endOfGeneratedName = strend(generatedName); - } - else if (type != typeNone) - { - strcat(generatedName, DB2I_ADDL_INDEX_NAME_DELIMITER); - endOfGeneratedName = strend(generatedName); - *(endOfGeneratedName-2) = char(type); - } - - uint lenWithoutFile = endOfGeneratedName - generatedName; - - char strippedTableName[MAX_DB2_FILENAME_LENGTH+1]; - if (format == ASCII_SQL) - { - strcpy(strippedTableName, tableName); - stripExtraQuotes(strippedTableName+1, sizeof(strippedTableName)); - tableName = strippedTableName; - } - - if (strlen(tableName) > (MAX_DB2_FILENAME_LENGTH-lenWithoutFile)) - return -1; - - strncat(generatedName, - tableName+1, - min(strlen(tableName), (MAX_DB2_FILENAME_LENGTH-lenWithoutFile))-2 ); - - char finalName[MAX_DB2_FILENAME_LENGTH+1]; - convertMySQLNameToDB2Name(generatedName, finalName, sizeof(finalName), true, (format==ASCII_SQL)); - to.append(finalName); - - return 0; -} - - -void db2i_table::findConversionDefinition(enum_conversionDirection direction, uint16 fieldID) -{ - getConversion(direction, - mysqlTable->field[fieldID]->charset(), - db2Field(fieldID).getCCSID(), - conversionDefinitions[direction][fieldID]); -} - - -db2i_file::db2i_file(db2i_table* table) : db2Table(table) -{ - commonCtorInit(); - - DBUG_ASSERT(table->getMySQLTable()->table_name.length <= MAX_DB2_FILENAME_LENGTH-2); - - db2FileName = (char*)table->getDB2TableName(db2i_table::EBCDIC_NATIVE); -} - -db2i_file::db2i_file(db2i_table* table, int index) : db2Table(table) -{ - commonCtorInit(); - - if ((index == table->getMySQLTable()->primary_key) && !table->isTemporary()) - { - db2FileName = (char*)table->getDB2TableName(db2i_table::EBCDIC_NATIVE); - } - else - { - // Generate the index name (in index___table form); quote and EBCDICize it. - String qualifiedPath; - qualifiedPath.length(0); - - const char* asciiFileName = table->getDB2TableName(db2i_table::ASCII_NATIVE); - - db2i_table::appendQualifiedIndexFileName(table->getMySQLTable()->key_info[index].name, - asciiFileName, - qualifiedPath, - db2i_table::ASCII_NATIVE, - typeDefault); - - db2FileName = (char*)my_malloc(qualifiedPath.length()+1, MYF(MY_WME | MY_ZEROFILL)); - convToEbcdic(qualifiedPath.ptr(), db2FileName, qualifiedPath.length()); - } -} - -void db2i_file::commonCtorInit() -{ - masterDefn = 0; - memset(&formats, 0, maxRowFormats*sizeof(RowFormat)); -} - - -void db2i_file::fillILEDefn(ShrDef* defn, bool readInArrivalSeq) -{ - defn->ObjNamLen = strlen(db2FileName); - DBUG_ASSERT(defn->ObjNamLen <= sizeof(defn->ObjNam)); - memcpy(defn->ObjNam, db2FileName, defn->ObjNamLen); - defn->ArrSeq[0] = (readInArrivalSeq ? QMY_YES : QMY_NO); -} - diff --git a/storage/ibmdb2i/db2i_file.h b/storage/ibmdb2i/db2i_file.h deleted file mode 100644 index 7b63b18c315..00000000000 --- a/storage/ibmdb2i/db2i_file.h +++ /dev/null @@ -1,445 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - -#ifndef DB2I_FILE_H -#define DB2I_FILE_H - -#include "db2i_global.h" -#include "db2i_ileBridge.h" -#include "db2i_validatedPointer.h" -#include "db2i_iconv.h" -#include "db2i_charsetSupport.h" - -const char FID_EXT[] = ".FID"; - -class db2i_file; - -#pragma pack(1) -struct DB2LobField -{ - char reserved1; - uint32 length; - char reserved2[4]; - uint32 ordinal; - ILEMemHandle dataHandle; - char reserved3[8]; -}; -#pragma pack(pop) - -class DB2Field -{ - public: - uint16 getType() const { return *(uint16*)(&definition.ColType); } - uint16 getByteLengthInRecord() const { return definition.ColLen; } - uint16 getDataLengthInRecord() const - { - return (getType() == QMY_VARCHAR || getType() == QMY_VARGRAPHIC ? definition.ColLen - 2 : definition.ColLen); - } - uint16 getCCSID() const { return *(uint16*)(&definition.ColCCSID); } - bool isBlob() const - { - uint16 type = getType(); - return (type == QMY_BLOBCLOB || type == QMY_DBCLOB); - } - uint16 getBufferOffset() const { return definition.ColBufOff; } - uint16 calcBlobPad() const - { - DBUG_ASSERT(isBlob()); - return getByteLengthInRecord() - sizeof (DB2LobField); - } - DB2LobField* asBlobField(char* buf) const - { - DBUG_ASSERT(isBlob()); - return (DB2LobField*)(buf + getBufferOffset() + calcBlobPad()); - } - private: - col_def_t definition; -}; - - -/** - @class db2i_table - - @details - This class describes the logical SQL table provided by DB2. - It stores "table-scoped" information such as the name of the - DB2 schema, BLOB descriptions, and the corresponding MySQL table definition. - Only one instance exists per SQL table. -*/ -class db2i_table -{ - public: - enum NameFormatFlags - { - ASCII_SQL, - ASCII_NATIVE, - EBCDIC_NATIVE - }; - - db2i_table(const TABLE_SHARE* myTable, const char* path = NULL); - - ~db2i_table(); - - int32 initDB2Objects(const char* path); - - const TABLE_SHARE* getMySQLTable() const - { - return mysqlTable; - } - - uint64 getStartId() const - { - return db2StartId; - } - - void updateStartId(uint64 newStartId) - { - db2StartId = newStartId; - } - - bool hasBlobs() const - { - return (blobFieldCount > 0); - } - - uint16 getBlobCount() const - { - return blobFieldCount; - } - - uint getBlobFieldActualSize(uint fieldIndex) const - { - return blobFieldActualSizes[getBlobIdFromField(fieldIndex)]; - } - - void updateBlobFieldActualSize(uint fieldIndex, uint32 newSize) - { - // It's OK that this isn't threadsafe, since this is just an advisory - // value. If a race condition causes the lesser of two values to be stored, - // that's OK. - uint16 blobID = getBlobIdFromField(fieldIndex); - DBUG_ASSERT(blobID < blobFieldCount); - - if (blobFieldActualSizes[blobID] < newSize) - { - blobFieldActualSizes[blobID] = newSize; - } - } - - - - const char* getDB2LibName(NameFormatFlags format = EBCDIC_NATIVE) - { - switch (format) - { - case EBCDIC_NATIVE: - return db2LibNameEbcdic; break; - case ASCII_NATIVE: - return db2LibNameAscii; break; - case ASCII_SQL: - return db2LibNameSQLAscii; break; - default: - DBUG_ASSERT(0); - } - return NULL; - } - - const char* getDB2TableName(NameFormatFlags format = EBCDIC_NATIVE) const - { - switch (format) - { - case EBCDIC_NATIVE: - return db2TableNameEbcdic; break; - case ASCII_NATIVE: - return db2TableNameAscii; break; - case ASCII_SQL: - return db2TableNameAscii; break; - break; - default: - DBUG_ASSERT(0); - } - return NULL; - } - - DB2Field& db2Field(int fieldID) const { return db2Fields[fieldID]; } - DB2Field& db2Field(const Field* field) const { return db2Field(field->field_index); } - - void processFormatSpace(); - - void* getFormatSpace(size_t& spaceNeeded) - { - DBUG_ASSERT(formatSpace == NULL); - spaceNeeded = sizeof(format_hdr_t) + mysqlTable->fields * sizeof(DB2Field); - formatSpace.alloc(spaceNeeded); - return (void*)formatSpace; - } - - bool isTemporary() const - { - return isTemporaryTable; - } - - void getDB2QualifiedName(char* to); - static void getDB2LibNameFromPath(const char* path, char* lib, NameFormatFlags format=ASCII_SQL); - static void getDB2FileNameFromPath(const char* path, char* file, NameFormatFlags format=ASCII_SQL); - static void getDB2QualifiedNameFromPath(const char* path, char* to); - static int32 appendQualifiedIndexFileName(const char* indexName, - const char* tableName, - String& to, - NameFormatFlags format=ASCII_SQL, - enum_DB2I_INDEX_TYPE type=typeDefault); - - uint16 getBlobIdFromField(uint16 fieldID) const - { - for (int i = 0; i < blobFieldCount; ++i) - { - if (blobFields[i] == fieldID) - return i; - } - DBUG_ASSERT(0); - return 0; - } - - iconv_t& getConversionDefinition(enum_conversionDirection direction, - uint16 fieldID) - { - if (conversionDefinitions[direction][fieldID] == (iconv_t)(-1)) - findConversionDefinition(direction, fieldID); - - return conversionDefinitions[direction][fieldID]; - } - - const db2i_file* dataFile() const - { - return physicalFile; - } - - const db2i_file* indexFile(uint idx) const - { - return logicalFiles[idx]; - } - - const char* getFileLevelID() const - { - return fileLevelID; - } - - static void deleteAssocFiles(const char* name); - static void renameAssocFiles(const char* from, const char* to); - - int fastInitForCreate(const char* path); - int initDiscoveredTable(const char* path); - - uint16* blobFields; - -private: - - void findConversionDefinition(enum_conversionDirection direction, uint16 fieldID); - static void filenameToTablename(const char* in, char* out, size_t outlen); - static size_t smartFilenameToTableName(const char *in, char* out, size_t outlen); - void convertNativeToSQLName(const char* input, - char* output) - { - - output[0] = input[0]; - - uint o = 1; - uint i = 1; - do - { - output[o++] = input[i]; - if (input[i] == '"' && input[i+1]) - output[o++] = '"'; - } while (input[++i]); - - output[o] = 0; // This isn't the most user-friendly way to handle overflows, - // but at least its safe. - } - - bool doFileIDsMatch(const char* path); - - ValidatedPointer<format_hdr_t> formatSpace; - DB2Field* db2Fields; - uint64 db2StartId; // Starting value for identity column - uint16 blobFieldCount; // Count of LOB fields in the DB2 table - uint* blobFieldActualSizes; // Array of LOB field lengths (actual vs. allocated). - // This is updated as LOBs are read and will contain - // the length of the longest known LOB in that field. - iconv_t* conversionDefinitions[2]; - - const TABLE_SHARE* mysqlTable; - uint16 logicalFileCount; - char* db2LibNameEbcdic; // Quoted and in EBCDIC - char* db2LibNameAscii; - char* db2TableNameEbcdic; - char* db2TableNameAscii; - char* db2TableNameSQLAscii; - char* db2LibNameSQLAscii; - - db2i_file* physicalFile; - db2i_file** logicalFiles; - - bool isTemporaryTable; - char fileLevelID[13]; -}; - -/** - @class db2i_file - - @details This class describes a file object underlaying a particular SQL - table. Both "physical files" (data) and "logical files" (indices) are - described by this class. Only one instance of the class exists per DB2 file - object. The single instance is responsible for de/allocating the multiple - handles used by the handlers. -*/ -class db2i_file -{ - -public: - struct RowFormat - { - uint16 readRowLen; - uint16 readRowNullOffset; - uint16 writeRowLen; - uint16 writeRowNullOffset; - char inited; - }; - -public: - - // Construct an instance for a physical file. - db2i_file(db2i_table* table); - - // Construct an instance for a logical file. - db2i_file(db2i_table* table, int index); - - ~db2i_file() - { - if (masterDefn) - db2i_ileBridge::getBridgeForThread()->deallocateFile(masterDefn); - - if (db2FileName != (char*)db2Table->getDB2TableName(db2i_table::EBCDIC_NATIVE)) - my_free(db2FileName, MYF(0)); - } - - // This is roughly equivalent to an "open". It tells ILE to allocate a descriptor - // for the file. The associated handle is returned to the caller. - int allocateNewInstance(FILE_HANDLE* newHandle, ILEMemHandle inuseSpace) const - { - int rc; - - rc = db2i_ileBridge::getBridgeForThread()->allocateFileInstance(masterDefn, - inuseSpace, - newHandle); - - if (rc) *newHandle = 0; - - return rc; - } - - // This obtains the row layout associated with a particular access intent for - // an open instance of the file. - int obtainRowFormat(FILE_HANDLE instanceHandle, - char intent, - char commitLevel, - const RowFormat** activeFormat) const - { - DBUG_ENTER("db2i_file::obtainRowFormat"); - RowFormat* rowFormat; - - if (intent == QMY_UPDATABLE) - rowFormat = &(formats[readWrite]); - else if (intent == QMY_READ_ONLY) - rowFormat = &(formats[readOnly]); - - if (unlikely(!rowFormat->inited)) - { - int rc = db2i_ileBridge::getBridgeForThread()-> - initFileForIO(instanceHandle, - intent, - commitLevel, - &(rowFormat->writeRowLen), - &(rowFormat->writeRowNullOffset), - &(rowFormat->readRowLen), - &(rowFormat->readRowNullOffset)); - if (rc) DBUG_RETURN(rc); - rowFormat->inited = 1; - } - - *activeFormat = rowFormat; - DBUG_RETURN(0); - } - - const char* getDB2FileName() const - { - return db2FileName; - } - - void fillILEDefn(ShrDef* defn, bool readInArrivalSeq); - - void setMasterDefnHandle(FILE_HANDLE handle) - { - masterDefn = handle; - } - - FILE_HANDLE getMasterDefnHandle() const - { - return masterDefn; - } - -private: - enum RowFormats - { - readOnly = 0, - readWrite, - maxRowFormats - }; - - mutable RowFormat formats[maxRowFormats]; - - void commonCtorInit(); - - char* db2FileName; // Quoted and in EBCDIC - - db2i_table* db2Table; // The logical SQL table contained by this file. - - bool db2CanSort; - - FILE_HANDLE masterDefn; -}; - - -#endif diff --git a/storage/ibmdb2i/db2i_global.h b/storage/ibmdb2i/db2i_global.h deleted file mode 100644 index d201fbd8124..00000000000 --- a/storage/ibmdb2i/db2i_global.h +++ /dev/null @@ -1,138 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - -#ifndef DB2I_GLOBAL_H -#define DB2I_GLOBAL_H - -#define MYSQL_SERVER 1 - -#include "my_global.h" -#include "my_sys.h" - -const uint MAX_DB2_KEY_PARTS=120; -const int MAX_DB2_V5R4_LIBNAME_LENGTH = 10; -const int MAX_DB2_V6R1_LIBNAME_LENGTH = 30; -const int MAX_DB2_SCHEMANAME_LENGTH=258; -const int MAX_DB2_FILENAME_LENGTH=258; -const int MAX_DB2_COLNAME_LENGTH=128; -const int MAX_DB2_SAVEPOINTNAME_LENGTH=128; -const int MAX_DB2_QUALIFIEDNAME_LENGTH=MAX_DB2_V6R1_LIBNAME_LENGTH + 1 + MAX_DB2_FILENAME_LENGTH; -const uint32 MAX_CHAR_LENGTH = 32765; -const uint32 MAX_VARCHAR_LENGTH = 32739; -const uint32 MAX_DEC_PRECISION = 63; -const uint32 MAX_BLOB_LENGTH = 2147483646; -const uint32 MAX_BINARY_LENGTH = MAX_CHAR_LENGTH; -const uint32 MAX_VARBINARY_LENGTH = MAX_VARCHAR_LENGTH; -const uint32 MAX_FULL_ALLOCATE_BLOB_LENGTH = 65536; -const uint32 MAX_FOREIGN_LEN = 64000; -const char* DB2I_TEMP_TABLE_SCHEMA = "QTEMP"; -const char DB2I_ADDL_INDEX_NAME_DELIMITER[5] = {'_','_','_','_','_'}; -const char DB2I_DEFAULT_INDEX_NAME_DELIMITER[3] = {'_','_','_'}; -const int DB2I_INDEX_NAME_LENGTH_TO_PRESERVE = 110; - -enum enum_DB2I_INDEX_TYPE -{ - typeNone = 0, - typeDefault = 'D', - typeHex = 'H', - typeAscii = 'A' -}; - -void* roundToQuadWordBdy(void* ptr) -{ - return (void*)(((uint64)(ptr)+0xf) & ~0xf); -} - -typedef uint64_t ILEMemHandle; - -struct OSVersion -{ - uint8 v; - uint8 r; -}; -extern OSVersion osVersion; - - -/** - Allocate 16-byte aligned space using the MySQL heap allocator - - @details Many of the spaces used by the QMY_* APIS are required to be - aligned on 16 byte boundaries. The standard system malloc will do this - alignment by default. However, in order to use the heap debug and tracking - features of the mysql allocator, we chose to implement an aligning wrapper - around my_malloc. Essentially, we overallocate the storage space, find the - first aligned address in the space, store a pointer to the true malloc - allocation in the bytes immediately preceding the aligned address, and return - the aligned address to the caller. - - @parm size The size of heap storage needed - - @return A 16-byte aligned pointer to the storage requested. -*/ -void* malloc_aligned(size_t size) -{ - char* p; - char* base; - base = (char*)my_malloc(size + sizeof(void*) + 15, MYF(MY_WME)); - if (likely(base)) - { - p = (char*)roundToQuadWordBdy(base + sizeof(void*)); - char** p2 = (char**)(p - sizeof(void*)); - *p2 = base; - } - else - p = NULL; - - return p; -} - -/** - Free a 16-byte aligned space alloced by malloc_aligned - - @details We know that a pointer to the true malloced storage immediately - precedes the aligned address, so we pull that out and call my_free(). - - @parm p A 16-byte aligned pointer generated by malloc_aligned -*/ -void free_aligned(void* p) -{ - if (likely(p)) - { - my_free(*(char**)((char*)p-sizeof(void*)), MYF(0)); - } -} - -#endif diff --git a/storage/ibmdb2i/db2i_iconv.h b/storage/ibmdb2i/db2i_iconv.h deleted file mode 100644 index 9fc6e4ed636..00000000000 --- a/storage/ibmdb2i/db2i_iconv.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - -/** - @file - - @brief Used to redefine iconv symbols to the optimized "myconv" ones -*/ - -#ifndef DB2I_ICONV_H -#define DB2I_ICONV_H - -#include "db2i_myconv.h" -#define iconv_open(A, B) myconv_open(A, B, CONVERTER_DMAP) -#define iconv_close myconv_close -#define iconv myconv_dmap -#define iconv_t myconv_t - -#endif diff --git a/storage/ibmdb2i/db2i_ileBridge.cc b/storage/ibmdb2i/db2i_ileBridge.cc deleted file mode 100644 index 68ae2c2bb72..00000000000 --- a/storage/ibmdb2i/db2i_ileBridge.cc +++ /dev/null @@ -1,1342 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - - -#include "db2i_ileBridge.h" -#include "my_dbug.h" -#include "db2i_global.h" -#include "db2i_charsetSupport.h" -#include "db2i_errors.h" - - -// static class member data -ILEpointer* db2i_ileBridge::functionSymbols; -db2i_ileBridge* db2i_ileBridge::globalBridge; -#ifndef DBUG_OFF -uint32 db2i_ileBridge::registeredPtrs; -#endif - -pthread_key(IleParms*, THR_ILEPARMS); - -static void ileParmsDtor(void* parmsToFree) -{ - if (parmsToFree) - { - free_aligned(parmsToFree); - DBUG_PRINT("db2i_ileBridge", ("Freeing space for parms")); - } -} - - -/** - Convert a timestamp in ILE time format into a unix time_t -*/ -static inline time_t convertILEtime(const ILE_time_t& input) -{ - tm temp; - - temp.tm_sec = input.Second; - temp.tm_min = input.Minute; - temp.tm_hour = input.Hour; - temp.tm_mday = input.Day; - temp.tm_mon = input.Month-1; - temp.tm_year = input.Year - 1900; - temp.tm_isdst = -1; - - return mktime(&temp); -} - -/** - Allocate and intialize a new bridge structure -*/ -db2i_ileBridge* db2i_ileBridge::createNewBridge(CONNECTION_HANDLE connID) -{ - DBUG_PRINT("db2i_ileBridge::createNewBridge",("Building new bridge...")); - db2i_ileBridge* newBridge = (db2i_ileBridge*)my_malloc(sizeof(db2i_ileBridge), MYF(MY_WME)); - - if (unlikely(newBridge == NULL)) - return NULL; - - newBridge->stmtTxActive = false; - newBridge->connErrText = NULL; - newBridge->pendingLockedHandles.head = NULL; - newBridge->cachedConnectionID = connID; - - return newBridge; -} - - -void db2i_ileBridge::destroyBridge(db2i_ileBridge* bridge) -{ - bridge->freeErrorStorage(); - my_free(bridge, MYF(0)); -} - - -void db2i_ileBridge::destroyBridgeForThread(const THD* thd) -{ - void* thdData = *thd_ha_data(thd, ibmdb2i_hton); - if (thdData != NULL) - { - destroyBridge((db2i_ileBridge*)thdData); - } -} - - -void db2i_ileBridge::registerPtr(const void* ptr, ILEMemHandle* receiver) -{ - static const arg_type_t ileSignature[] = { ARG_MEMPTR, ARG_END }; - - if (unlikely(ptr == NULL)) - { - *receiver = 0; - return; - } - - struct ArgList - { - ILEarglist_base base; - ILEpointer ptr; - } *arguments; - - char argBuf[sizeof(ArgList)+15]; - arguments = (ArgList*)roundToQuadWordBdy(argBuf); - - arguments->ptr.s.addr = (address64_t)(ptr); - - _ILECALL(&functionSymbols[funcRegisterSpace], - &arguments->base, - ileSignature, - RESULT_INT64); - -#ifndef DBUG_OFF - uint32 truncHandle = arguments->base.result.r_uint64; - DBUG_PRINT("db2i_ileBridge::registerPtr",("Register 0x%p with handle %d", ptr, truncHandle)); - getBridgeForThread()->registeredPtrs++; -#endif - - *receiver = arguments->base.result.r_uint64; - return; -} - -void db2i_ileBridge::unregisterPtr(ILEMemHandle handle) -{ - static const arg_type_t ileSignature[] = { ARG_UINT64, ARG_END }; - - if (unlikely(handle == NULL)) - return; - - struct ArgList - { - ILEarglist_base base; - uint64 handle; - } *arguments; - - char argBuf[sizeof(ArgList)+15]; - arguments = (ArgList*)roundToQuadWordBdy(argBuf); - - arguments->handle = (uint64)(handle); - - _ILECALL(&functionSymbols[funcUnregisterSpace], - &arguments->base, - ileSignature, - RESULT_VOID); - -#ifndef DBUG_OFF - DBUG_PRINT("db2i_ileBridge::unregisterPtr",("Unregister handle %d", (uint32)handle)); - getBridgeForThread()->registeredPtrs--; -#endif -} - - - -/** - Initialize the bridge component - - @details Resolves srvpgm and function names of the APIs. If this fails, - the approrpiate operating system support (PTFs) is probably not installed. - - WARNING: - Must be called before any other functions in this class are used!!!! - Can only be called by a single thread! -*/ -int db2i_ileBridge::setup() -{ - static const char funcNames[db2i_ileBridge::funcListEnd][32] = - { - {"QmyRegisterParameterSpaces"}, - {"QmyRegisterSpace"}, - {"QmyUnregisterSpace"}, - {"QmyProcessRequest"} - }; - - DBUG_ENTER("db2i_ileBridge::setup"); - - int actmark = _ILELOAD("QSYS/QMYSE", ILELOAD_LIBOBJ); - if ( actmark == -1 ) - { - DBUG_PRINT("db2i_ileBridge::setup", ("srvpgm activation failed")); - DBUG_RETURN(1); - } - - functionSymbols = (ILEpointer*)malloc_aligned(sizeof(ILEpointer) * db2i_ileBridge::funcListEnd); - - for (int i = 0; i < db2i_ileBridge::funcListEnd; i++) - { - if (_ILESYM(&functionSymbols[i], actmark, funcNames[i]) == -1) - { - DBUG_PRINT("db2i_ileBridge::setup", - ("resolve of %s failed", funcNames[i])); - DBUG_RETURN(errno); - } - } - - pthread_key_create(&THR_ILEPARMS, &ileParmsDtor); - -#ifndef DBUG_OFF - registeredPtrs = 0; -#endif - - globalBridge = createNewBridge(0); - - DBUG_RETURN(0); -} - -/** - Cleanup any resources before shutting down plug-in -*/ -void db2i_ileBridge::takedown() -{ - if (globalBridge) - destroyBridge(globalBridge); - free_aligned(functionSymbols); -} - -/** - Call off to QmyProcessRequest to perform the API that the caller prepared -*/ -inline int32 db2i_ileBridge::doIt() -{ - static const arg_type_t ileSignature[] = {ARG_END}; - - struct ArgList - { - ILEarglist_base base; - } *arguments; - - char argBuf[sizeof(ArgList)+15]; - arguments = (ArgList*)roundToQuadWordBdy(argBuf); - - _ILECALL(&functionSymbols[funcProcessRequest], - &arguments->base, - ileSignature, - RESULT_INT32); - - return translateErrorCode(arguments->base.result.s_int32.r_int32); -} - -/** - Call off to QmyProcessRequest to perform the API that the caller prepared and - log any errors that may occur. -*/ -inline int32 db2i_ileBridge::doItWithLog() -{ - int32 rc = doIt(); - - if (unlikely(rc)) - { - // Only report errors that we weren't expecting - if (rc != tacitErrors[0] && - rc != tacitErrors[1] && - rc != QMY_ERR_END_OF_BLOCK) - reportSystemAPIError(rc, (Qmy_Error_output_t*)parms()->outParms); - } - memset(tacitErrors, 0, sizeof(tacitErrors)); - - return rc; -} - - -/** - Interface to QMY_ALLOCATE_SHARE API - - See QMY_ALLOCATE_SHARE documentation for more information about - parameters and return codes. -*/ -int32 db2i_ileBridge::allocateFileDefn(ILEMemHandle definitionSpace, - ILEMemHandle handleSpace, - uint16 fileCount, - const char* schemaName, - uint16 schemaNameLength, - ILEMemHandle formatSpace, - uint32 formatSpaceLen) -{ - DBUG_ASSERT(cachedStateIsCoherent()); - - IleParms* parmBlock = parms(); - Qmy_MAOS0100 *input = (Qmy_MAOS0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_ALLOCATE_SHARE; - input->ShrDefSpcHnd = definitionSpace; - input->ShrHndSpcHnd = handleSpace; - input->ShrDefCnt = fileCount; - input->FmtSpcHnd = formatSpace; - input->FmtSpcLen = formatSpaceLen; - - if (schemaNameLength > sizeof(input->SchNam)) - { - // This should never happen! - DBUG_ASSERT(0); - return HA_ERR_GENERIC; - } - - memcpy(input->SchNam, schemaName, schemaNameLength); - input->SchNamLen = schemaNameLength; - - input->CnnHnd = cachedConnectionID; - - int32 rc = doItWithLog(); - - return rc; -} - - -/** - Interface to QMY_ALLOCATE_INSTANCE API - - See QMY_ALLOCATE_INSTANCE documentation for more information about - parameters and return codes. -*/ -int32 db2i_ileBridge::allocateFileInstance(FILE_HANDLE defnHandle, - ILEMemHandle inuseSpace, - FILE_HANDLE* instance) -{ - DBUG_ASSERT(cachedStateIsCoherent()); - - IleParms* parmBlock = parms(); - Qmy_MAOI0100 *input = (Qmy_MAOI0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_ALLOCATE_INSTANCE; - input->ShrHnd = defnHandle; - input->CnnHnd = cachedConnectionID; - input->UseSpcHnd = inuseSpace; - - int32 rc = doItWithLog(); - - if (likely(rc == 0)) - { - Qmy_MAOI0100_output* output = (Qmy_MAOI0100_output*)parmBlock->outParms; - DBUG_ASSERT(instance); - *instance = output->ObjHnd; - } - - return rc; -} - - -/** - Interface to QMY_DEALLOCATE_OBJECT API - - See QMY_DEALLOCATE_OBJECT documentation for more information about - parameters and return codes. -*/ -int32 db2i_ileBridge::deallocateFile(FILE_HANDLE rfileHandle, - bool postDropTable) -{ - IleParms* parmBlock = parms(); - Qmy_MDLC0100 *input = (Qmy_MDLC0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_DEALLOCATE_OBJECT; - input->ObjHnd = rfileHandle; - input->ObjDrp[0] = (postDropTable ? QMY_YES : QMY_NO); - - DBUG_PRINT("db2i_ileBridge::deallocateFile", ("Deallocating %d", (uint32)rfileHandle)); - - int32 rc = doItWithLog(); - - return rc; -} - - -/** - Interface to QMY_OBJECT_INITIALIZATION API - - See QMY_OBJECT_INITIALIZATION documentation for more information about - parameters and return codes. -*/ -int32 db2i_ileBridge::initFileForIO(FILE_HANDLE rfileHandle, - char accessIntent, - char commitLevel, - uint16* inRecSize, - uint16* inRecNullOffset, - uint16* outRecSize, - uint16* outRecNullOffset) -{ - DBUG_ASSERT(cachedStateIsCoherent()); - IleParms* parmBlock = parms(); - Qmy_MOIX0100 *input = (Qmy_MOIX0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_OBJECT_INITIALIZATION; - input->CmtLvl[0] = commitLevel; - input->Intent[0] = accessIntent; - input->ObjHnd = rfileHandle; - input->CnnHnd = cachedConnectionID; - - int32 rc = doItWithLog(); - - if (likely(rc == 0)) - { - Qmy_MOIX0100_output* output = (Qmy_MOIX0100_output*)parmBlock->outParms; - *inRecSize = output->InNxtRowOff; - *inRecNullOffset = output->InNullMapOff; - *outRecSize = output->OutNxtRowOff; - *outRecNullOffset = output->OutNullMapOff; - } - - return rc; -} - - -/** - Interface to QMY_READ_ROWS API for reading a row with a specific RRN. - - See QMY_READ_ROWS documentation for more information about - parameters and return codes. -*/ -int32 db2i_ileBridge::readByRRN(FILE_HANDLE rfileHandle, - ILEMemHandle buf, - uint32 inRRN, - char accessIntent, - char commitLevel) -{ - DBUG_ASSERT(cachedStateIsCoherent()); - IleParms* parmBlock = parms(); - Qmy_MRDX0100 *input = (Qmy_MRDX0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_READ_ROWS; - input->CmtLvl[0] = commitLevel; - input->ObjHnd = rfileHandle; - input->Intent[0] = accessIntent; - input->OutSpcHnd = (uint64)buf; - input->RelRowNbr = inRRN; - input->CnnHnd = cachedConnectionID; - - int32 rc = doItWithLog(); - - if (rc == QMY_ERR_END_OF_BLOCK) - { - rc = 0; - DBUG_PRINT("db2i_ileBridge::readByRRN", ("End of block signalled")); - } - - return rc; -} - - -/** - Interface to QMY_WRITE_ROWS API. - - See QMY_WRITE_ROWS documentation for more information about - parameters and return codes. -*/ -int32 db2i_ileBridge::writeRows(FILE_HANDLE rfileHandle, - ILEMemHandle buf, - char commitLevel, - int64* outIdVal, - bool* outIdGen, - uint32* dupKeyRRN, - char** dupKeyName, - uint32* dupKeyNameLen, - uint32* outIdIncrement) -{ - DBUG_ASSERT(cachedStateIsCoherent()); - IleParms* parmBlock = parms(); - Qmy_MWRT0100 *input = (Qmy_MWRT0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_WRITE_ROWS; - input->CmtLvl[0] = commitLevel; - - input->ObjHnd = rfileHandle; - input->InSpcHnd = (uint64_t) buf; - input->CnnHnd = cachedConnectionID; - - int32 rc = doItWithLog(); - - Qmy_MWRT0100_output_t* output = (Qmy_MWRT0100_output_t*)parmBlock->outParms; - if (likely(rc == 0 || rc == HA_ERR_FOUND_DUPP_KEY)) - { - DBUG_ASSERT(dupKeyRRN && dupKeyName && dupKeyNameLen && outIdGen && outIdIncrement && outIdVal); - *dupKeyRRN = output->DupRRN; - *dupKeyName = (char*)parmBlock->outParms + output->DupObjNamOff; - *dupKeyNameLen = output->DupObjNamLen; - *outIdGen = (output->NewIdGen[0] == QMY_YES ? TRUE : FALSE); - if (*outIdGen == TRUE) - { - *outIdIncrement = output->IdIncrement; - *outIdVal = output->NewIdVal; - } - } - - return rc; - -} - -/** - Interface to QMY_EXECUTE_IMMEDIATE API. - - See QMY_EXECUTE_IMMEDIATE documentation for more information about - parameters and return codes. -*/ -uint32 db2i_ileBridge::execSQL(const char* statement, - uint32 statementCount, - uint8 commitLevel, - bool autoCreateSchema, - bool dropSchema, - bool noCommit, - FILE_HANDLE fileHandle) - -{ - IleParms* parmBlock = parms(); - Qmy_MSEI0100 *input = (Qmy_MSEI0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_EXECUTE_IMMEDIATE; - - registerPtr(statement, &input->StmtsSpcHnd); - - input->NbrStmts = statementCount; - *(uint16*)(&input->StmtCCSID) = 850; - input->AutoCrtSchema[0] = (autoCreateSchema == TRUE ? QMY_YES : QMY_NO); - input->DropSchema[0] = (dropSchema == TRUE ? QMY_YES : QMY_NO); - input->CmtLvl[0] = commitLevel; - if ((commitLevel == QMY_NONE && statementCount == 1) || noCommit) - { - input->CmtBefore[0] = QMY_NO; - input->CmtAfter[0] = QMY_NO; - } - else - { - input->CmtBefore[0] = QMY_YES; - input->CmtAfter[0] = QMY_YES; - } - input->CnnHnd = current_thd->thread_id; - input->ObjHnd = fileHandle; - - int32 rc = doItWithLog(); - - unregisterPtr(input->StmtsSpcHnd); - - return rc; -} - -/** - Interface to QMY_PREPARE_OPEN_CURSOR API. - - See QMY_PREPARE_OPEN_CURSOR documentation for more information about - parameters and return codes. -*/ -int32 db2i_ileBridge::prepOpen(const char* statement, - FILE_HANDLE* rfileHandle, - uint32* recLength) -{ - IleParms* parmBlock = parms(); - Qmy_MSPO0100 *input = (Qmy_MSPO0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_PREPARE_OPEN_CURSOR; - - registerPtr(statement, &input->StmtsSpcHnd ); - *(uint16*)(&input->StmtCCSID) = 850; - input->CnnHnd = current_thd->thread_id; - - int32 rc = doItWithLog(); - - if (likely(rc == 0)) - { - Qmy_MSPO0100_output* output = (Qmy_MSPO0100_output*)parmBlock->outParms; - *rfileHandle = output->ObjHnd; - *recLength = max(output->InNxtRowOff, output->OutNxtRowOff); - } - - - unregisterPtr(input->StmtsSpcHnd); - - return rc; -} - - -/** - Interface to QMY_DELETE_ROW API. - - See QMY_DELETE_ROW documentation for more information about - parameters and return codes. -*/ -int32 db2i_ileBridge::deleteRow(FILE_HANDLE rfileHandle, - uint32 rrn) -{ - DBUG_ASSERT(cachedStateIsCoherent()); - IleParms* parmBlock = parms(); - Qmy_MDLT0100 *input = (Qmy_MDLT0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_DELETE_ROW; - input->ObjHnd = rfileHandle; - input->RelRowNbr = rrn; - input->CnnHnd = cachedConnectionID; - - int32 rc = doItWithLog(); - - return rc; -} - - -/** - Interface to QMY_UPDATE_ROW API. - - See QMY_UPDATE_ROW documentation for more information about - parameters and return codes. -*/ -int32 db2i_ileBridge::updateRow(FILE_HANDLE rfileHandle, - uint32 rrn, - ILEMemHandle buf, - uint32* dupKeyRRN, - char** dupKeyName, - uint32* dupKeyNameLen) -{ - DBUG_ASSERT(cachedStateIsCoherent()); - IleParms* parmBlock = parms(); - Qmy_MUPD0100 *input = (Qmy_MUPD0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_UPDATE_ROW; - input->ObjHnd = rfileHandle; - input->InSpcHnd = (uint64)buf; - input->RelRowNbr = rrn; - input->CnnHnd = cachedConnectionID; - - int32 rc = doItWithLog(); - - if (rc == HA_ERR_FOUND_DUPP_KEY) - { - Qmy_MUPD0100_output* output = (Qmy_MUPD0100_output*)parmBlock->outParms; - DBUG_ASSERT(dupKeyRRN && dupKeyName && dupKeyNameLen); - *dupKeyRRN = output->DupRRN; - *dupKeyName = (char*)parmBlock->outParms + output->DupObjNamOff; - *dupKeyNameLen = output->DupObjNamLen; - } - - return rc; -} - -/** - Interface to QMY_DESCRIBE_RANGE API. - - See QMY_DESCRIBE_RANGE documentation for more information about - parameters and return codes. -*/ -int32 db2i_ileBridge::recordsInRange(FILE_HANDLE defnHandle, - ILEMemHandle inSpc, - uint32 inKeyCnt, - uint32 inLiteralCnt, - uint32 inBoundsOff, - uint32 inLitDefOff, - uint32 inLiteralsOff, - uint32 inCutoff, - uint32 inSpcLen, - uint16 inEndByte, - uint64* outRecCnt, - uint16* outRtnCode) -{ - DBUG_ASSERT(cachedStateIsCoherent()); - - IleParms* parmBlock = parms(); - Qmy_MDRG0100 *input = (Qmy_MDRG0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_DESCRIBE_RANGE; - input->ShrHnd = defnHandle; - input->SpcHnd = (uint64)inSpc; - input->KeyCnt = inKeyCnt; - input->LiteralCnt = inLiteralCnt; - input->BoundsOff = inBoundsOff; - input->LitDefOff = inLitDefOff; - input->LiteralsOff = inLiteralsOff; - input->Cutoff = inCutoff; - input->SpcLen = inSpcLen; - input->EndByte = inEndByte; - input->CnnHnd = cachedConnectionID; - - int rc = doItWithLog(); - - if (likely(rc == 0)) - { - Qmy_MDRG0100_output* output = (Qmy_MDRG0100_output*)parmBlock->outParms; - DBUG_ASSERT(outRecCnt && outRtnCode); - *outRecCnt = output->RecCnt; - *outRtnCode = output->RtnCode; - } - - return rc; -} - - -/** - Interface to QMY_RELEASE_ROW API. - - See QMY_RELEASE_ROW documentation for more information about - parameters and return codes. -*/ -int32 db2i_ileBridge::rrlslck(FILE_HANDLE rfileHandle, char accessIntent) -{ - DBUG_ASSERT(cachedStateIsCoherent()); - - IleParms* parmBlock = parms(); - Qmy_MRRX0100 *input = (Qmy_MRRX0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_RELEASE_ROW; - - input->ObjHnd = rfileHandle; - input->CnnHnd = cachedConnectionID; - input->Intent[0] = accessIntent; - - int32 rc = doItWithLog(); - - return rc; -} - -/** - Interface to QMY_LOCK_OBJECT API. - - See QMY_LOCK_OBJECT documentation for more information about - parameters and return codes. -*/ -int32 db2i_ileBridge::lockObj(FILE_HANDLE defnHandle, - uint64 lockVal, - char lockAction, - char lockType, - char lockTimeout) -{ - DBUG_ASSERT(cachedStateIsCoherent()); - IleParms* parmBlock = parms(); - Qmy_MOLX0100 *input = (Qmy_MOLX0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_LOCK_OBJECT; - input->ShrHnd = defnHandle; - input->LckTimeoutVal = lockVal; - input->Action[0] = lockAction; - input->LckTyp[0] = lockType; - input->LckTimeout[0] = lockTimeout; - input->CnnHnd = cachedConnectionID; - - int32 rc = doItWithLog(); - - return rc; -} - -/** - Interface to QMY_DESCRIBE_CONSTRAINTS API. - - See QMY_DESCRIBE_CONSTRAINTS documentation for more information about - parameters and return codes. -*/ -int32 db2i_ileBridge::constraints(FILE_HANDLE defnHandle, - ILEMemHandle inSpc, - uint32 inSpcLen, - uint32* outLen, - uint32* outCnt) -{ - DBUG_ASSERT(cachedStateIsCoherent()); - IleParms* parmBlock = parms(); - Qmy_MDCT0100 *input = (Qmy_MDCT0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_DESCRIBE_CONSTRAINTS; - input->ShrHnd = defnHandle; - input->CstSpcHnd = (uint64)inSpc; - input->CstSpcLen = inSpcLen; - input->CnnHnd = cachedConnectionID; - - int32 rc = doItWithLog(); - - if (likely(rc == 0)) - { - Qmy_MDCT0100_output* output = (Qmy_MDCT0100_output*)parmBlock->outParms; - DBUG_ASSERT(outLen && outCnt); - *outLen = output->NeededLen; - *outCnt = output->CstCnt; - } - - return rc; -} - - -/** - Interface to QMY_REORGANIZE_TABLE API. - - See QMY_REORGANIZE_TABLE documentation for more information about - parameters and return codes. -*/ -int32 db2i_ileBridge::optimizeTable(FILE_HANDLE defnHandle) -{ - DBUG_ASSERT(cachedStateIsCoherent()); - IleParms* parmBlock = parms(); - Qmy_MRGX0100 *input = (Qmy_MRGX0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_REORGANIZE_TABLE; - input->ShrHnd = defnHandle; - input->CnnHnd = cachedConnectionID; - - int32 rc = doItWithLog(); - - return rc; -} - - -/** - Interface to QMY_PROCESS_COMMITMENT_CONTROL API. - - See QMY_PROCESS_COMMITMENT_CONTROL documentation for more information about - parameters and return codes. -*/ -int32 db2i_ileBridge::commitmentControl(uint8 function) -{ - DBUG_ASSERT(cachedStateIsCoherent()); - IleParms* parmBlock = parms(); - Qmy_MCCX0100 *input = (Qmy_MCCX0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_PROCESS_COMMITMENT_CONTROL; - input->Function[0] = function; - input->CnnHnd = cachedConnectionID; - - int32 rc = doItWithLog(); - - return rc; -} - - -/** - Interface to QMY_PROCESS_SAVEPOINT API. - - See QMY_PROCESS_SAVEPOINT documentation for more information about parameters and - return codes. -*/ -int32 db2i_ileBridge::savepoint(uint8 function, - const char* savepointName) -{ - DBUG_ASSERT(cachedStateIsCoherent()); - DBUG_PRINT("db2i_ileBridge::savepoint",("%d %s", (uint32)function, savepointName)); - - IleParms* parmBlock = parms(); - Qmy_MSPX0100 *input = (Qmy_MSPX0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - char* savPtNam = (char*)(input+1); - - input->Format = QMY_PROCESS_SAVEPOINT; - - if (strlen(savepointName) > MAX_DB2_SAVEPOINTNAME_LENGTH) - { - DBUG_ASSERT(0); - return HA_ERR_GENERIC; - } - strcpy(savPtNam, savepointName); - - input->Function[0] = function; - input->SavPtNamOff = savPtNam - (char*)(input); - input->SavPtNamLen = strlen(savepointName); - input->CnnHnd = cachedConnectionID; - - int32 rc = doItWithLog(); - - return rc; -} - -static ILEMemHandle traceSpcHandle; -/** - Do initialization for the QMY_* APIs. - - @parm aspName The name of the relational database to use for all - connections. - - @return 0 if successful; error otherwise -*/ -int32 db2i_ileBridge::initILE(const char* aspName, - uint16* traceCtlPtr) -{ - // We forego the typical thread-based parms space because MySQL doesn't - // allow us to clean it up before checking for memory leaks. As a result - // we get a complaint about leaked memory on server shutdown. - int32 rc; - char inParms[db2i_ileBridge_MAX_INPARM_SIZE]; - char outParms[db2i_ileBridge_MAX_OUTPARM_SIZE]; - if (rc = registerParmSpace(inParms, outParms)) - { - reportSystemAPIError(rc, NULL); - return rc; - } - - registerPtr(traceCtlPtr, &traceSpcHandle); - - struct ParmBlock - { - Qmy_MINI0100 parms; - } *parmBlock = (ParmBlock*)inParms; - - memset(inParms, 0, sizeof(ParmBlock)); - - parmBlock->parms.Format = QMY_INITIALIZATION; - - char paddedName[18]; - if (strlen(aspName) > sizeof(paddedName)) - { - getErrTxt(DB2I_ERR_BAD_RDB_NAME); - return DB2I_ERR_BAD_RDB_NAME; - } - - memset(paddedName, ' ', sizeof(paddedName)); - memcpy(paddedName, aspName, strlen(aspName)); - convToEbcdic(paddedName, parmBlock->parms.RDBName, strlen(paddedName)); - - parmBlock->parms.RDBNamLen = strlen(paddedName); - parmBlock->parms.TrcSpcHnd = traceSpcHandle; - - rc = doIt(); - - if (rc) - { - reportSystemAPIError(rc, (Qmy_Error_output_t*)outParms); - } - - return rc; -} - -/** - Signal to the QMY_ APIs to perform any cleanup they need to do. -*/ -int32 db2i_ileBridge::exitILE() -{ - IleParms* parmBlock = parms(); - Qmy_MCLN0100 *input = (Qmy_MCLN0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_CLEANUP; - - int32 rc = doIt(); - - if (rc) - { - reportSystemAPIError(rc, (Qmy_Error_output_t*)parmBlock->outParms); - } - - unregisterPtr(traceSpcHandle); - - DBUG_PRINT("db2i_ileBridge::exitILE", ("Registered ptrs remaining: %d", registeredPtrs)); -#ifndef DBUG_OFF - if (registeredPtrs != 0) - printf("Oh no! IBMDB2I left some pointers registered. Count was %d.\n", registeredPtrs); -#endif - - // This is needed to prevent SAFE_MALLOC from complaining at process termination. - my_pthread_setspecific_ptr(THR_ILEPARMS, NULL); - free_aligned(parmBlock); - - return rc; - -} - - -/** - Designate the specified addresses as parameter passing buffers. - - @parm in Input to the API will go here; format is defined by the individual API - @parm out Output from the API will be; format is defined by the individual API - - @return 0 if success; error otherwise -*/ -int db2i_ileBridge::registerParmSpace(char* in, char* out) -{ - static const arg_type_t ileSignature[] = { ARG_MEMPTR, ARG_MEMPTR, ARG_END }; - - struct ArgList - { - ILEarglist_base base; - ILEpointer input; - ILEpointer output; - } *arguments; - - char argBuf[sizeof(ArgList)+15]; - arguments = (ArgList*)roundToQuadWordBdy(argBuf); - - arguments->input.s.addr = (address64_t)(in); - arguments->output.s.addr = (address64_t)(out); - - _ILECALL(&functionSymbols[funcRegisterParameterSpaces], - &arguments->base, - ileSignature, - RESULT_INT32); - - return arguments->base.result.s_int32.r_int32; -} - - -/** - Interface to QMY_OBJECT_OVERRIDE API. - - See QMY_OBJECT_OVERRIDE documentation for more information about parameters and - return codes. -*/ -int32 db2i_ileBridge::objectOverride(FILE_HANDLE rfileHandle, - ILEMemHandle buf, - uint32 recordWidth) -{ - DBUG_ASSERT(cachedStateIsCoherent()); - IleParms* parmBlock = parms(); - Qmy_MOOX0100 *input = (Qmy_MOOX0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_OBJECT_OVERRIDE; - input->ObjHnd = rfileHandle; - input->OutSpcHnd = (uint64)buf; - input->NxtRowOff = recordWidth; - input->CnnHnd = cachedConnectionID; - - int32 rc = doItWithLog(); - - return rc; -} - -/** - Interface to QMY_DESCRIBE_OBJECT API for obtaining table stats. - - See QMY_DESCRIBE_OBJECT documentation for more information about parameters and - return codes. -*/ -int32 db2i_ileBridge::retrieveTableInfo(FILE_HANDLE defnHandle, - uint16 dataRequested, - ha_statistics& stats, - ILEMemHandle inSpc) -{ - DBUG_ASSERT(cachedStateIsCoherent()); - IleParms* parmBlock = parms(); - Qmy_MDSO0100 *input = (Qmy_MDSO0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_DESCRIBE_OBJECT; - input->ShrHnd = defnHandle; - input->CnnHnd = cachedConnectionID; - - if (dataRequested & objLength) - input->RtnObjLen[0] = QMY_YES; - if (dataRequested & rowCount) - input->RtnRowCnt[0] = QMY_YES; - if (dataRequested & deletedRowCount) - input->RtnDltRowCnt[0] = QMY_YES; - if (dataRequested & rowsPerKey) - { - input->RowKeyHnd = (uint64)inSpc; - input->RtnRowKey[0] = QMY_YES; - } - if (dataRequested & meanRowLen) - input->RtnMeanRowLen[0] = QMY_YES; - if (dataRequested & lastModTime) - input->RtnModTim[0] = QMY_YES; - if (dataRequested & createTime) - input->RtnCrtTim[0] = QMY_YES; - if (dataRequested & ioCount) - input->RtnEstIoCnt[0] = QMY_YES; - - int32 rc = doItWithLog(); - - if (likely(rc == 0)) - { - Qmy_MDSO0100_output* output = (Qmy_MDSO0100_output*)parmBlock->outParms; - if (dataRequested & objLength) - stats.data_file_length = output->ObjLen; - if (dataRequested & rowCount) - stats.records= output->RowCnt; - if (dataRequested & deletedRowCount) - stats.deleted = output->DltRowCnt; - if (dataRequested & meanRowLen) - stats.mean_rec_length = output->MeanRowLen; - if (dataRequested & lastModTime) - stats.update_time = convertILEtime(output->ModTim); - if (dataRequested & createTime) - stats.create_time = convertILEtime(output->CrtTim); - if (dataRequested & ioCount) - stats.data_file_length = output->EstIoCnt; - } - - return rc; -} - -/** - Interface to QMY_DESCRIBE_OBJECT API for finding index size. - - See QMY_DESCRIBE_OBJECT documentation for more information about parameters and - return codes. -*/ -int32 db2i_ileBridge::retrieveIndexInfo(FILE_HANDLE defnHandle, - uint64* outPageCnt) -{ - DBUG_ASSERT(cachedStateIsCoherent()); - IleParms* parmBlock = parms(); - Qmy_MDSO0100 *input = (Qmy_MDSO0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_DESCRIBE_OBJECT; - input->ShrHnd = defnHandle; - input->CnnHnd = cachedConnectionID; - input->RtnPageCnt[0] = QMY_YES; - - int32 rc = doItWithLog(); - - if (likely(rc == 0)) - { - Qmy_MDSO0100_output* output = (Qmy_MDSO0100_output*)parmBlock->outParms; - *outPageCnt = output->PageCnt; - } - - return rc; -} - - -/** - Interface to QMY_CLOSE_CONNECTION API - - See QMY_CLOSE_CONNECTION documentation for more information about parameters and - return codes. -*/ -int32 db2i_ileBridge::closeConnection(CONNECTION_HANDLE conn) -{ - IleParms* parmBlock = parms(); - Qmy_MCCN0100 *input = (Qmy_MCCN0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_CLOSE_CONNECTION; - input->CnnHnd = conn; - - int32 rc = doItWithLog(); - - return rc; -} - - -/** - Interface to QMY_INTERRUPT API - - See QMY_INTERRUPT documentation for more information about parameters and - return codes. -*/ -int32 db2i_ileBridge::readInterrupt(FILE_HANDLE fileHandle) -{ - DBUG_ASSERT(cachedStateIsCoherent()); - IleParms* parmBlock = parms(); - Qmy_MINT0100 *input = (Qmy_MINT0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_INTERRUPT; - input->CnnHnd = cachedConnectionID; - input->ObjHnd = fileHandle; - - int32 rc = doItWithLog(); - - if (rc == QMY_ERR_END_OF_BLOCK) - { - rc = 0; - DBUG_PRINT("db2i_ileBridge::readInterrupt", ("End of block signalled")); - } - - return rc; -} - -/** - Interface to QMY_READ_ROWS API - - See QMY_READ_ROWS documentation for more information about parameters and - return codes. -*/ -int32 db2i_ileBridge::read(FILE_HANDLE rfileHandle, - ILEMemHandle buf, - char accessIntent, - char commitLevel, - char orientation, - bool asyncRead, - ILEMemHandle rrn, - ILEMemHandle key, - uint32 keylen, - uint16 keyParts, - int pipeFD) -{ - DBUG_ASSERT(cachedStateIsCoherent()); - IleParms* parmBlock = parms(); - Qmy_MRDX0100 *input = (Qmy_MRDX0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_READ_ROWS; - input->CmtLvl[0] = commitLevel; - - input->ObjHnd = rfileHandle; - input->Intent[0] = accessIntent; - input->OutSpcHnd = (uint64)buf; - input->OutRRNSpcHnd = (uint64)rrn; - input->RtnData[0] = QMY_RETURN_DATA; - - if (key) - { - input->KeySpcHnd = (uint64)key; - input->KeyColsLen = keylen; - input->KeyColsNbr = keyParts; - } - - input->Async[0] = (asyncRead ? QMY_YES : QMY_NO); - input->PipeDesc = pipeFD; - input->Orientation[0] = orientation; - input->CnnHnd = cachedConnectionID; - - int32 rc = doItWithLog(); - - // QMY_ERR_END_OF_BLOCK is informational only, so we ignore it. - if (rc == QMY_ERR_END_OF_BLOCK) - { - rc = 0; - DBUG_PRINT("db2i_ileBridge::read", ("End of block signalled")); - } - - return rc; -} - - -/** - Interface to QMY_QUIESCE_OBJECT API - - See QMY_QUIESCE_OBJECT documentation for more information about parameters and - return codes. -*/ -int32 db2i_ileBridge::quiesceFileInstance(FILE_HANDLE rfileHandle) -{ - IleParms* parmBlock = parms(); - Qmy_MQSC0100 *input = (Qmy_MQSC0100*)&(parmBlock->inParms); - memset(input, 0, sizeof(*input)); - - input->Format = QMY_QUIESCE_OBJECT; - input->ObjHnd = rfileHandle; - - int32 rc = doItWithLog(); - -#ifndef DBUG_OFF - if (unlikely(rc)) - { - DBUG_ASSERT(0); - } -#endif - - return rc; -} - -void db2i_ileBridge::PreservedHandleList::add(const char* newname, FILE_HANDLE newhandle, IBMDB2I_SHARE* share) -{ - NameHandlePair *newPair = (NameHandlePair*)my_malloc(sizeof(NameHandlePair), MYF(MY_WME)); - - newPair->next = head; - head = newPair; - - strcpy(newPair->name, newname); - newPair->handle = newhandle; - newPair->share = share; - DBUG_PRINT("db2i_ileBridge", ("Added handle %d for %s", uint32(newhandle), newname)); -} - - -FILE_HANDLE db2i_ileBridge::PreservedHandleList::findAndRemove(const char* fileName, IBMDB2I_SHARE** share) -{ - NameHandlePair* current = head; - NameHandlePair* prev = NULL; - - while (current) - { - NameHandlePair* next = current->next; - if (strcmp(fileName, current->name) == 0) - { - FILE_HANDLE tmp = current->handle; - *share = current->share; - if (prev) - prev->next = next; - if (current == head) - head = next; - my_free(current, MYF(0)); - DBUG_PRINT("db2i_ileBridge", ("Found handle %d for %s", uint32(tmp), fileName)); - return tmp; - } - prev = current; - current = next; - } - - return 0; -} - - -IleParms* db2i_ileBridge::initParmsForThread() -{ - - IleParms* p = (IleParms*)malloc_aligned(sizeof(IleParms)); - DBUG_ASSERT((uint64)(&(p->outParms))% 16 == 0); // Guarantee that outParms are aligned correctly - - if (likely(p)) - { - int32 rc = registerParmSpace((p->inParms), (p->outParms)); - if (likely(rc == 0)) - { - my_pthread_setspecific_ptr(THR_ILEPARMS, p); - DBUG_PRINT("db2i_ileBridge", ("Inited space for parms")); - return p; - } - else - reportSystemAPIError(rc, NULL); - } - - return NULL; -} - diff --git a/storage/ibmdb2i/db2i_ileBridge.h b/storage/ibmdb2i/db2i_ileBridge.h deleted file mode 100644 index 10b9820d983..00000000000 --- a/storage/ibmdb2i/db2i_ileBridge.h +++ /dev/null @@ -1,499 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - -#ifndef DB2I_ILEBRIDGE_H -#define DB2I_ILEBRIDGE_H - -#include "db2i_global.h" -#include "mysql_priv.h" -#include "as400_types.h" -#include "as400_protos.h" -#include "qmyse.h" -#include "db2i_errors.h" - -typedef uint64_t FILE_HANDLE; -typedef my_thread_id CONNECTION_HANDLE; -const char SAVEPOINT_NAME[] = {0xD4,0xE2,0xD7,0xC9,0xD5,0xE3,0xC5,0xD9,0xD5,0x0}; -const uint32 TACIT_ERRORS_SIZE=2; - -enum db2i_InfoRequestSpec -{ - objLength = 1, - rowCount = 2, - deletedRowCount = 4, - rowsPerKey = 8, - meanRowLen = 16, - lastModTime = 32, - createTime = 64, - ioCount = 128 -}; - -extern handlerton *ibmdb2i_hton; -struct IBMDB2I_SHARE; - -const uint32 db2i_ileBridge_MAX_INPARM_SIZE = 512; -const uint32 db2i_ileBridge_MAX_OUTPARM_SIZE = 512; - -extern pthread_key(IleParms*, THR_ILEPARMS); -struct IleParms -{ - char inParms[db2i_ileBridge_MAX_INPARM_SIZE]; - char outParms[db2i_ileBridge_MAX_OUTPARM_SIZE]; -}; - -/** - @class db2i_ileBridge - - Implements a connection-based interface to the QMY_* APIs - - @details Each client connection that touches an IBMDB2I table has a "bridge" - associated with it. This bridge is constructed on first use and provides a - more C-like interface to the APIs. As well, it is reponsible for tracking - connection scoped information such as statement transaction state and error - message text. The bridge is destroyed when the connection ends. -*/ -class db2i_ileBridge -{ - enum ileFuncs - { - funcRegisterParameterSpaces, - funcRegisterSpace, - funcUnregisterSpace, - funcProcessRequest, - funcListEnd - }; - - static db2i_ileBridge* globalBridge; -public: - - - static int setup(); - static void takedown(); - - /** - Obtain a pointer to the bridge for the current connection. - - If a MySQL client connection is on the stack, we get the associated brideg. - Otherwise, we use the globalBridge. - */ - static db2i_ileBridge* getBridgeForThread() - { - THD* thd = current_thd; - if (likely(thd)) - return getBridgeForThread(thd); - - return globalBridge; - } - - /** - Obtain a pointer to the bridge for the specified connection. - - If a bridge exists already, we return it immediately. Otherwise, prepare - a new bridge for the connection. - */ - static db2i_ileBridge* getBridgeForThread(const THD* thd) - { - void* thdData = *thd_ha_data(thd, ibmdb2i_hton); - if (likely(thdData != NULL)) - return (db2i_ileBridge*)(thdData); - - db2i_ileBridge* newBridge = createNewBridge(thd->thread_id); - *thd_ha_data(thd, ibmdb2i_hton) = (void*)newBridge; - return newBridge; - } - - static void destroyBridgeForThread(const THD* thd); - static void registerPtr(const void* ptr, ILEMemHandle* receiver); - static void unregisterPtr(ILEMemHandle handle); - int32 allocateFileDefn(ILEMemHandle definitionSpace, - ILEMemHandle handleSpace, - uint16 fileCount, - const char* schemaName, - uint16 schemaNameLength, - ILEMemHandle formatSpace, - uint32 formatSpaceLen); - int32 allocateFileInstance(FILE_HANDLE defnHandle, - ILEMemHandle inuseSpace, - FILE_HANDLE* instance); - int32 deallocateFile(FILE_HANDLE fileHandle, - bool postDropTable=FALSE); - int32 read(FILE_HANDLE rfileHandle, - ILEMemHandle buf, - char accessIntent, - char commitLevel, - char orientation, - bool asyncRead = FALSE, - ILEMemHandle rrn = 0, - ILEMemHandle key = 0, - uint32 keylen = 0, - uint16 keyParts = 0, - int pipeFD = -1); - int32 readByRRN(FILE_HANDLE rfileHandle, - ILEMemHandle buf, - uint32 inRRN, - char accessIntent, - char commitLevel); - int32 writeRows(FILE_HANDLE rfileHandle, - ILEMemHandle buf, - char commitLevel, - int64* outIdVal, - bool* outIdGen, - uint32* dupKeyRRN, - char** dupKeyName, - uint32* dupKeyNameLen, - uint32* outIdIncrement); - uint32 execSQL(const char* statement, - uint32 statementCount, - uint8 commitLevel, - bool autoCreateSchema = FALSE, - bool dropSchema = FALSE, - bool noCommit = FALSE, - FILE_HANDLE fileHandle = 0); - int32 prepOpen(const char* statement, - FILE_HANDLE* rfileHandle, - uint32* recLength); - int32 deleteRow(FILE_HANDLE rfileHandle, - uint32 rrn); - int32 updateRow(FILE_HANDLE rfileHandle, - uint32 rrn, - ILEMemHandle buf, - uint32* dupKeyRRN, - char** dupKeyName, - uint32* dupKeyNameLen); - int32 commitmentControl(uint8 function); - int32 savepoint(uint8 function, - const char* savepointName); - int32 recordsInRange(FILE_HANDLE rfileHandle, - ILEMemHandle inSpc, - uint32 inKeyCnt, - uint32 inLiteralCnt, - uint32 inBoundsOff, - uint32 inLitDefOff, - uint32 inLiteralsOff, - uint32 inCutoff, - uint32 inSpcLen, - uint16 inEndByte, - uint64* outRecCnt, - uint16* outRtnCode); - int32 rrlslck(FILE_HANDLE rfileHandle, - char accessIntent); - int32 lockObj(FILE_HANDLE rfileHandle, - uint64 inTimeoutVal, - char inAction, - char inLockType, - char inTimeout); - int32 constraints(FILE_HANDLE rfileHandle, - ILEMemHandle inSpc, - uint32 inSpcLen, - uint32* outLen, - uint32* outCnt); - int32 optimizeTable(FILE_HANDLE rfileHandle); - static int32 initILE(const char* aspName, - uint16* traceCtlPtr); - int32 initFileForIO(FILE_HANDLE rfileHandle, - char accessIntent, - char commitLevel, - uint16* inRecSize, - uint16* inRecNullOffset, - uint16* outRecSize, - uint16* outRecNullOffset); - int32 readInterrupt(FILE_HANDLE fileHandle); - static int32 exitILE(); - - int32 objectOverride(FILE_HANDLE rfileHandle, - ILEMemHandle buf, - uint32 recordWidth = 0); - - int32 retrieveTableInfo(FILE_HANDLE rfileHandle, - uint16 dataRequested, - ha_statistics& stats, - ILEMemHandle inSpc = NULL); - - int32 retrieveIndexInfo(FILE_HANDLE rfileHandle, - uint64* outPageCnt); - - int32 closeConnection(CONNECTION_HANDLE conn); - int32 quiesceFileInstance(FILE_HANDLE rfileHandle); - - /** - Mark the beginning of a "statement transaction" - - @detail MySQL "statement transactions" (see sql/handler.cc) are implemented - as DB2 savepoints having a predefined name. - - @return 0 if successful; error otherwise - */ - uint32 beginStmtTx() - { - DBUG_ENTER("db2i_ileBridge::beginStmtTx"); - if (stmtTxActive) - DBUG_RETURN(0); - - stmtTxActive = true; - - DBUG_RETURN(savepoint(QMY_SET_SAVEPOINT, SAVEPOINT_NAME)); - } - - /** - Commit a "statement transaction" - - @return 0 if successful; error otherwise - */ - uint32 commitStmtTx() - { - DBUG_ENTER("db2i_ileBridge::commitStmtTx"); - DBUG_ASSERT(stmtTxActive); - stmtTxActive = false; - DBUG_RETURN(savepoint(QMY_RELEASE_SAVEPOINT, SAVEPOINT_NAME)); - } - - /** - Roll back a "statement transaction" - - @return 0 if successful; error otherwise - */ - uint32 rollbackStmtTx() - { - DBUG_ENTER("db2i_ileBridge::rollbackStmtTx"); - DBUG_ASSERT(stmtTxActive); - stmtTxActive = false; - DBUG_RETURN(savepoint(QMY_ROLLBACK_SAVEPOINT, SAVEPOINT_NAME)); - } - - - /** - Provide storage for generating error messages. - - This storage must persist until the error message is retrieved from the - handler instance. It is for this reason that we associate it with the bridge. - - @return Pointer to heap storage of MYSQL_ERRMSG_SIZE bytes - */ - char* getErrorStorage() - { - if (!connErrText) - { - connErrText = (char*)my_malloc(MYSQL_ERRMSG_SIZE, MYF(MY_WME)); - if (connErrText) connErrText[0] = 0; - } - - return connErrText; - } - - /** - Free storage for generating error messages. - */ - void freeErrorStorage() - { - if (likely(connErrText)) - { - my_free(connErrText, MYF(0)); - connErrText = NULL; - } - } - - - /** - Store a file handle for later retrieval. - - If deallocateFile encounters a lock when trying to perform its operation, - the file remains allocated but must be deallocated later. This function - provides a way for the connection to "remember" that this deallocation is - still needed. - - @param newname The name of the file to be added - @param newhandle The handle associated with newname - - */ - void preserveHandle(const char* newname, FILE_HANDLE newhandle, IBMDB2I_SHARE* share) - { - pendingLockedHandles.add(newname, newhandle, share); - } - - /** - Retrieve a file handle stored by preserveHandle(). - - @param name The name of the file to be retrieved. - - @return The handle associated with name - */ - FILE_HANDLE findAndRemovePreservedHandle(const char* name, IBMDB2I_SHARE** share) - { - FILE_HANDLE hdl = pendingLockedHandles.findAndRemove(name, share); - return hdl; - } - - /** - Indicate which error messages should be suppressed on the next API call - - These functions are useful for ensuring that the provided error numbers - are returned if a failure occurs but do not cause a spurious error message - to be returned. - - @return A pointer to this instance - */ - db2i_ileBridge* expectErrors(int32 er1) - { - tacitErrors[0]=er1; - return this; - } - - db2i_ileBridge* expectErrors(int32 er1, int32 er2) - { - tacitErrors[0]=er1; - tacitErrors[1]=er2; - return this; - } - - /** - Obtain the IBM i system message that accompanied the last API failure. - - @return A pointer to the 7 character message ID. - */ - static const char* getErrorMsgID() - { - return ((Qmy_Error_output_t*)parms()->outParms)->MsgId; - } - - /** - Convert an API error code into the equivalent MySQL error code (if any) - - @param rc The QMYSE API error code - - @return If an equivalent exists, the MySQL error code; else rc - */ - static int32 translateErrorCode(int32 rc) - { - if (likely(rc == 0)) - return 0; - - switch (rc) - { - case QMY_ERR_KEY_NOT_FOUND: - return HA_ERR_KEY_NOT_FOUND; - case QMY_ERR_DUP_KEY: - return HA_ERR_FOUND_DUPP_KEY; - case QMY_ERR_END_OF_FILE: - return HA_ERR_END_OF_FILE; - case QMY_ERR_LOCK_TIMEOUT: - return HA_ERR_LOCK_WAIT_TIMEOUT; - case QMY_ERR_CST_VIOLATION: - return HA_ERR_NO_REFERENCED_ROW; - case QMY_ERR_TABLE_NOT_FOUND: - return HA_ERR_NO_SUCH_TABLE; - case QMY_ERR_NON_UNIQUE_KEY: - return ER_DUP_ENTRY; - case QMY_ERR_MSGID: - { - if (memcmp(getErrorMsgID(), DB2I_CPF503A, 7) == 0) - return HA_ERR_ROW_IS_REFERENCED; - if (memcmp(getErrorMsgID(), DB2I_SQL0538, 7) == 0) - return HA_ERR_CANNOT_ADD_FOREIGN; - } - } - return rc; - } - -private: - - static db2i_ileBridge* createNewBridge(CONNECTION_HANDLE connID); - static void destroyBridge(db2i_ileBridge* bridge); - static int registerParmSpace(char* in, char* out); - static int32 doIt(); - int32 doItWithLog(); - - static _ILEpointer *functionSymbols; ///< Array of ILE function pointers - CONNECTION_HANDLE cachedConnectionID; ///< The associated connection - bool stmtTxActive; ///< Inside statement transaction - char *connErrText; ///< Storage for error message - int32 tacitErrors[TACIT_ERRORS_SIZE]; ///< List of errors to be suppressed - - static IleParms* initParmsForThread(); - - /** - Get space for passing parameters to the QMY_* APIs - - @details A fixed-length parameter passing space is associated with each - pthread. This space is allocated and registered by initParmsForThread() - the first time a pthread works with a bridge. The space is cached away - and remains available until the pthread ends. It became necessary to - disassociate the parameter space from the bridge in order to support - future enhancements to MySQL that sever the one-to-one relationship between - pthreads and user connections. The QMY_* APIs scope a registered parameter - space to the thread that executes the register operation. - */ - static IleParms* parms() - { - IleParms* p = my_pthread_getspecific_ptr(IleParms*, THR_ILEPARMS); - if (likely(p)) - return p; - - return initParmsForThread(); - } - - class PreservedHandleList - { - friend db2i_ileBridge* db2i_ileBridge::createNewBridge(CONNECTION_HANDLE); - public: - void add(const char* newname, FILE_HANDLE newhandle, IBMDB2I_SHARE* share); - FILE_HANDLE findAndRemove(const char* fileName, IBMDB2I_SHARE** share); - - private: - struct NameHandlePair - { - char name[FN_REFLEN]; - FILE_HANDLE handle; - IBMDB2I_SHARE* share; - NameHandlePair* next; - }* head; - } pendingLockedHandles; - - -#ifndef DBUG_OFF - bool cachedStateIsCoherent() - { - return (current_thd->thread_id == cachedConnectionID); - } - - friend void db2i_ileBridge::unregisterPtr(ILEMemHandle); - friend void db2i_ileBridge::registerPtr(const void*, ILEMemHandle*); - static uint32 registeredPtrs; -#endif -}; - - - -#endif diff --git a/storage/ibmdb2i/db2i_ioBuffers.cc b/storage/ibmdb2i/db2i_ioBuffers.cc deleted file mode 100644 index 9525a6e34b5..00000000000 --- a/storage/ibmdb2i/db2i_ioBuffers.cc +++ /dev/null @@ -1,332 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - -#include "db2i_ioBuffers.h" - -/** - Request another block of rows - - Request the next set of rows from DB2. This must only be called after - newReadRequest(). - - @param orientation The direction to use when reading through the table. -*/ -void IOAsyncReadBuffer::loadNewRows(char orientation) -{ - rewind(); - maxRows() = rowsToBlock; - - DBUG_PRINT("db2i_ioBuffers::loadNewRows", ("Requesting %d rows, async = %d", rowsToBlock, readIsAsync)); - - rc = getBridge()->expectErrors(QMY_ERR_END_OF_BLOCK, QMY_ERR_LOB_SPACE_TOO_SMALL) - ->read(file, - ptr(), - accessIntent, - commitLevel, - orientation, - readIsAsync, - rrnList, - 0, - 0, - 0); - - DBUG_PRINT("db2i_ioBuffers::loadNewRows", ("recordsRead: %d, rc: %d", (uint32)rowCount(), rc)); - - - *releaseRowNeeded = true; - - if (rc == QMY_ERR_END_OF_BLOCK) - { - // This is really just an informational error, so we ignore it. - rc = 0; - DBUG_PRINT("db2i_ioBuffers::loadNewRows", ("End of block signalled")); - } - else if (rc == QMY_ERR_END_OF_FILE) - { - // If we reach EOF or end-of-key, DB2 guarantees that no rows will be locked. - rc = HA_ERR_END_OF_FILE; - *releaseRowNeeded = false; - } - else if (rc == QMY_ERR_KEY_NOT_FOUND) - { - rc = HA_ERR_KEY_NOT_FOUND; - *releaseRowNeeded = false; - } - - if (rc) closePipe(); -} - - -/** - Empty the message pipe to prepare for another read. -*/ -void IOAsyncReadBuffer::drainPipe() -{ - DBUG_ASSERT(pipeState == PendingFullBufferMsg); - PipeRpy_t msg[32]; - int bytes; - PipeRpy_t* lastMsg; - while ((bytes = read(msgPipe, msg, sizeof(msg))) > 0) - { - DBUG_PRINT("db2i_ioBuffers::drainPipe",("Pipe returned %d bytes", bytes)); - lastMsg = &msg[bytes / (sizeof(msg[0]))-1]; - if (lastMsg->CumRowCnt == maxRows() || - lastMsg->RtnCod != 0) - { - pipeState = ConsumedFullBufferMsg; - break; - } - - } - DBUG_PRINT("db2i_ioBuffers::drainPipe",("rc = %d, rows = %d, max = %d", lastMsg->RtnCod, lastMsg->CumRowCnt, (uint32)maxRows())); -} - - -/** - Poll the message pipe for async read messages - - Only valid in async - - @param orientation The direction to use when reading through the table. -*/ -void IOAsyncReadBuffer::pollNextRow(char orientation) -{ - DBUG_ASSERT(readIsAsync); - - // Handle the case in which the buffer is full. - if (rowCount() == maxRows()) - { - // If we haven't read to the end, exit here. - if (readCursor < rowCount()) - return; - - if (pipeState == PendingFullBufferMsg) - drainPipe(); - if (pipeState == ConsumedFullBufferMsg) - loadNewRows(orientation); - } - - if (!rc) - { - PipeRpy_t* lastMsg = NULL; - while (true) - { - PipeRpy_t msg[32]; - int bytes = read(msgPipe, msg, sizeof(msg)); - DBUG_PRINT("db2i_ioBuffers::pollNextRow",("Pipe returned %d bytes", bytes)); - - if (unlikely(bytes < 0)) - { - DBUG_PRINT("db2i_ioBuffers::pollNextRow", ("Error")); - rc = errno; - break; - } - else if (bytes == 0) - break; - - DBUG_ASSERT(bytes % sizeof(msg[0]) == 0); - lastMsg = &msg[bytes / (sizeof(msg[0]))-1]; - - if (lastMsg->RtnCod || (lastMsg->CumRowCnt == usedRows())) - { - rc = lastMsg->RtnCod; - break; - } - } - - *releaseRowNeeded = true; - - if (rc == QMY_ERR_END_OF_BLOCK) - rc = 0; - else if (rc == QMY_ERR_END_OF_FILE) - { - // If we reach EOF or end-of-key, DB2 guarantees that no rows will be locked. - rc = HA_ERR_END_OF_FILE; - *releaseRowNeeded = false; - } - else if (rc == QMY_ERR_KEY_NOT_FOUND) - { - rc = HA_ERR_KEY_NOT_FOUND; - *releaseRowNeeded = false; - } - - if (lastMsg) - DBUG_PRINT("db2i_ioBuffers::pollNextRow", ("Good data: rc=%d; rows=%d; usedRows=%d", lastMsg->RtnCod, lastMsg->CumRowCnt, (uint32)usedRows())); - if (lastMsg && likely(!rc)) - { - if (lastMsg->CumRowCnt < maxRows()) - pipeState = PendingFullBufferMsg; - else - pipeState = ConsumedFullBufferMsg; - - DBUG_ASSERT(lastMsg->CumRowCnt <= usedRows()); - - } - DBUG_ASSERT(rowCount() <= getRowCapacity()); - } - DBUG_PRINT("db2i_ioBuffers::pollNextRow", ("filledRows: %d, rc: %d", rowCount(), rc)); - if (rc) closePipe(); -} - - -/** - Prepare for the destruction of the row buffer storage. -*/ -void IOAsyncReadBuffer::prepForFree() -{ - interruptRead(); - rewind(); - IORowBuffer::prepForFree(); -} - - -/** - Initialize the newly allocated storage. - - @param sizeChanged Indicates whether the storage capacity is being changed. -*/ -void IOAsyncReadBuffer::initAfterAllocate(bool sizeChanged) -{ - rewind(); - - if (sizeChanged || ((void*)rrnList == NULL)) - rrnList.realloc(getRowCapacity() * sizeof(uint32)); -} - - -/** - Send an initial read request - - @param infile The file (table/index) being read from - @param orientation The orientation to use for this read request - @param rowsToBuffer The number of rows to request each time - @param useAsync Whether reads should be performed asynchronously. - @param key The key to use (if any) - @param keyLength The length of key (if any) - @param keyParts The number of columns in the key (if any) - -*/ -void IOAsyncReadBuffer::newReadRequest(FILE_HANDLE infile, - char orientation, - uint32 rowsToBuffer, - bool useAsync, - ILEMemHandle key, - int keyLength, - int keyParts) -{ - DBUG_ENTER("db2i_ioBuffers::newReadRequest"); - DBUG_ASSERT(rowsToBuffer <= getRowCapacity()); -#ifndef DBUG_OFF - if (readCursor < rowCount()) - DBUG_PRINT("PERF:",("Wasting %d buffered rows!\n", rowCount() - readCursor)); -#endif - - int fildes[2]; - int ileDescriptor = QMY_REUSE; - - interruptRead(); - - if (likely(useAsync)) - { - if (rowsToBuffer == 1) - { - // Async provides little or no benefit for single row reads, so we turn it off - DBUG_PRINT("db2i_ioBuffers::newReadRequest", ("Disabling async")); - useAsync = false; - } - else - { - rc = pipe(fildes); - if (rc) DBUG_VOID_RETURN; - - // Translate the pipe write descriptor into the equivalent ILE descriptor - rc = fstatx(fildes[1], (struct stat*)&ileDescriptor, sizeof(ileDescriptor), STX_XPFFD_PASE); - if (rc) - { - close(fildes[0]); - close(fildes[1]); - DBUG_VOID_RETURN; - } - pipeState = Untouched; - msgPipe = fildes[0]; - - DBUG_PRINT("db2i_ioBuffers::newReadRequest", ("Opened pipe %d", fildes[0])); - } - } - - file = infile; - readIsAsync = useAsync; - rowsToBlock = rowsToBuffer; - - rewind(); - maxRows() = 1; - rc = getBridge()->expectErrors(QMY_ERR_END_OF_BLOCK, QMY_ERR_LOB_SPACE_TOO_SMALL) - ->read(file, - ptr(), - accessIntent, - commitLevel, - orientation, - useAsync, - rrnList, - key, - keyLength, - keyParts, - ileDescriptor); - - // Having shared the pipe with ILE, we relinquish our claim on the write end - // of the pipe. - if (useAsync) - close(fildes[1]); - - // If we reach EOF or end-of-key, DB2 guarantees that no rows will be locked. - if (rc == QMY_ERR_END_OF_FILE) - { - rc = HA_ERR_END_OF_FILE; - *releaseRowNeeded = false; - } - else if (rc == QMY_ERR_KEY_NOT_FOUND) - { - if (rowCount()) - rc = HA_ERR_END_OF_FILE; - else - rc = HA_ERR_KEY_NOT_FOUND; - *releaseRowNeeded = false; - } - else - *releaseRowNeeded = true; - - DBUG_VOID_RETURN; -} diff --git a/storage/ibmdb2i/db2i_ioBuffers.h b/storage/ibmdb2i/db2i_ioBuffers.h deleted file mode 100644 index 350d854f055..00000000000 --- a/storage/ibmdb2i/db2i_ioBuffers.h +++ /dev/null @@ -1,416 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - -/** - @file db2i_ioBuffers.h - - @brief Buffer classes used for interacting with QMYSE read/write buffers. - -*/ - - -#include "db2i_validatedPointer.h" -#include "mysql_priv.h" -#include <sys/stat.h> -#include <fcntl.h> -#include <as400_types.h> - -// Needed for compilers which do not include fstatx in standard headers. -extern "C" int fstatx(int, struct stat *, int, int); - -/** - Basic row buffer - - Provides the basic structure and methods needed for communicating - with QMYSE I/O APIs. - - @details All QMYSE I/O apis use a buffer that is structured as two integer - row counts (max and used) and storage for some number of rows. The row counts - are both input and output for the API, and their usage depends on the - particular API invoked. This class encapsulates that buffer definition. -*/ -class IORowBuffer -{ - public: - IORowBuffer() : allocSize(0), rowLength(0) {;} - ~IORowBuffer() { freeBuf(); } - ValidatedPointer<char>& ptr() { return data; } - - /** - Sets up the buffer to hold the size indicated. - - @param rowLen length of the rows that will be stored in this buffer - @param nullMapOffset position of null map within each row - @param size buffer size requested - */ - void allocBuf(uint32 rowLen, uint16 nullMapOffset, uint32 size) - { - nullOffset = nullMapOffset; - uint32 newSize = size + sizeof(BufferHdr_t); - // If the internal structure of the row is changing, we need to - // remember this and notify the subclasses via initAfterAllocate(); - bool formatChanged = ((size/rowLen) != rowCapacity); - - if (newSize > allocSize) - { - this->freeBuf(); - data.alloc(newSize); - if (likely((void*)data)) - allocSize = newSize; - } - - if (likely((void*)data)) - { - DBUG_ASSERT((uint64)(void*)data % 16 == 0); - rowLength = rowLen; - rowCapacity = size / rowLength; - initAfterAllocate(formatChanged); - } - else - { - allocSize = 0; - rowCapacity = 0; - } - - DBUG_PRINT("db2i_ioBuffers::allocBuf",("rowCapacity = %d", rowCapacity)); - } - - void zeroBuf() - { - memset(data, 0, allocSize); - } - - void freeBuf() - { - if (likely(allocSize)) - { - prepForFree(); - DBUG_PRINT("IORowBuffer::freeBuf",("Freeing 0x%p", (char*)data)); - data.dealloc(); - } - } - - char* getRowN(uint32 n) - { - if (unlikely(n >= getRowCapacity())) - return NULL; - return (char*)data + sizeof(BufferHdr_t) + (rowLength * n); - }; - - uint32 getRowCapacity() const {return rowCapacity;} - uint32 getRowNullOffset() const {return nullOffset;} - uint32 getRowLength() const {return rowLength;} - - protected: - /** - Called prior to freeing buffer storage so that subclasses can do - any required cleanup - */ - virtual void prepForFree() - { - allocSize = 0; - rowCapacity = 0; - } - - /** - Called after buffer storage so that subclasses can do any required setup. - */ - virtual void initAfterAllocate(bool sizeChanged) { return;} - - ValidatedPointer<char> data; - uint32 allocSize; - uint32 rowCapacity; - uint32 rowLength; - uint16 nullOffset; - uint32& usedRows() const { return ((BufferHdr_t*)(char*)data)->UsedRowCnt; } - uint32& maxRows() const {return ((BufferHdr_t*)(char*)data)->MaxRowCnt; } -}; - - -/** - Write buffer - - Implements methods for inserting data into a row buffer for use with the - QMY_WRITE and QMY_UPDATE APIs. - - @details The max row count defines how many rows are in the buffer. The used - row count is updated by QMYSE to indicate how many rows have been - successfully written. -*/ -class IOWriteBuffer : public IORowBuffer -{ - public: - bool endOfBuffer() const {return (maxRows() == getRowCapacity());} - - char* addRow() - { - return getRowN(maxRows()++); - } - - void resetAfterWrite() - { - maxRows() = 0; - } - - void deleteRow() - { - --maxRows(); - } - - uint32 rowCount() const {return maxRows();} - - uint32 rowsWritten() const {return usedRows()-1;} - - private: - void initAfterAllocate(bool sizeChanged) {maxRows() = 0; usedRows() = 0;} -}; - - -/** - Read buffer - - Implements methods for reading data from and managing a row buffer for use - with the QMY_READ APIs. This is primarily for use with metainformation queries. -*/ -class IOReadBuffer : public IORowBuffer -{ - public: - - IOReadBuffer() {;} - IOReadBuffer(uint32 rows, uint32 rowLength) - { - allocBuf(rows, 0, rows * rowLength); - maxRows() = rows; - } - - uint32 rowCount() {return usedRows();} - void setRowsToProcess(uint32 rows) { maxRows() = rows; } -}; - - -/** - Read buffer - - Implements methods for reading data from and managing a row buffer for use - with the QMY_READ APIs. - - @details This class supports both sync and async read modes. The max row - count defines the number of rows that are requested to be read. The used row - count defines how many rows have been read. Sync mode is reasonably - straightforward, but async mode has a complex system of communicating with - QMYSE that is optimized for low latency. In async mode, the used row count is - updated continuously by QMYSE as rows are read. At the same time, messages are - sent to the associated pipe indicating that a row has been read. As long as - the internal read cursor lags behind the used row count, the pipe is never - consulted. But if the internal read cursor "catches up to" the used row count, - then we block on the pipe until we find a message indicating that a new row - has been read or that an error has occurred. -*/ -class IOAsyncReadBuffer : public IOReadBuffer -{ - public: - IOAsyncReadBuffer() : - file(0), readIsAsync(false), msgPipe(QMY_REUSE), bridge(NULL) - { - } - - ~IOAsyncReadBuffer() - { - interruptRead(); - rrnList.dealloc(); - } - - - /** - Signal read operation complete - - Indicates that the storage engine requires no more data from the table. - Must be called between calls to newReadRequest(). - */ - void endRead() - { -#ifndef DBUG_OFF - if (readCursor < rowCount()) - DBUG_PRINT("PERF:",("Wasting %d buffered rows!\n", rowCount() - readCursor)); -#endif - interruptRead(); - - file = 0; - bridge = NULL; - } - - /** - Update data that may change on each read operation - */ - void update(char newAccessIntent, - bool* newReleaseRowNeeded, - char commitLvl) - { - accessIntent = newAccessIntent; - releaseRowNeeded = newReleaseRowNeeded; - commitLevel = commitLvl; - } - - /** - Read the next row in the table. - - Return a pointer to the next row in the table, where "next" is defined - by the orientation. - - @param orientaton - @param[out] rrn The relative record number of the row returned. Not reliable - if NULL is returned by this function. - - @return Pointer to the row. Null if no more rows are available or an error - occurred. - */ - char* readNextRow(char orientation, uint32& rrn) - { - DBUG_PRINT("db2i_ioBuffers::readNextRow", ("readCursor: %d, filledRows: %d, rc: %d", readCursor, rowCount(), rc)); - - while (readCursor >= rowCount() && !rc) - { - if (!readIsAsync) - loadNewRows(orientation); - else - pollNextRow(orientation); - } - - if (readCursor >= rowCount()) - return NULL; - - rrn = rrnList[readCursor]; - return getRowN(readCursor++); - } - - /** - Retrieve the return code generated by the last operation. - - @return The return code, translated to the appropriate HA_ERR_* - value if possible. - */ - int32 lastrc() - { - return db2i_ileBridge::translateErrorCode(rc); - } - - void rewind() - { - readCursor = 0; - rc = 0; - usedRows() = 0; - } - - bool reachedEOD() { return EOD; } - - void newReadRequest(FILE_HANDLE infile, - char orientation, - uint32 rowsToBuffer, - bool useAsync, - ILEMemHandle key, - int keyLength, - int keyParts); - - private: - - /** - End any running async read operation. - */ - void interruptRead() - { - closePipe(); - if (file && readIsAsync && (rc == 0) && (rowCount() < getRowCapacity())) - { - DBUG_PRINT("IOReadBuffer::interruptRead", ("PERF: Interrupting %d", (uint32)file)); - getBridge()->readInterrupt(file); - } - } - - void closePipe() - { - if (msgPipe != QMY_REUSE) - { - DBUG_PRINT("db2i_ioBuffers::closePipe", ("Closing pipe %d", msgPipe)); - close(msgPipe); - msgPipe = QMY_REUSE; - } - } - - /** - Get a pointer to the active ILE bridge. - - Getting the bridge pointer is (relatively) expensive, so we cache - it off for each operation. - */ - db2i_ileBridge* getBridge() - { - if (unlikely(bridge == NULL)) - { - bridge = db2i_ileBridge::getBridgeForThread(); - } - return bridge; - } - - void drainPipe(); - void pollNextRow(char orientation); - void prepForFree(); - void initAfterAllocate(bool sizeChanged); - void loadNewRows(char orientation); - - - uint32 readCursor; // Read position within buffer - int32 rc; // Last return code received - ValidatedPointer<uint32> rrnList; // Receiver for list of rrns - char accessIntent; // The access intent for this read - char commitLevel; // What isolation level should be used - char EOD; // Whether end-of-data was hit - char readIsAsync; // Are reads to be done asynchronously? - bool* releaseRowNeeded; - /* Does the caller need to release the current row when finished reading */ - FILE_HANDLE file; // The file to be read - int msgPipe; - /* The read descriptor of the pipe used to pass messages during async reads */ - db2i_ileBridge* bridge; // Cached pointer to bridge - uint32 rowsToBlock; // Number of rows to request - enum - { - ConsumedFullBufferMsg, - PendingFullBufferMsg, - Untouched - } pipeState; - /* The state of the async read message pipe */ -}; - diff --git a/storage/ibmdb2i/db2i_misc.h b/storage/ibmdb2i/db2i_misc.h deleted file mode 100644 index f0b527aaad0..00000000000 --- a/storage/ibmdb2i/db2i_misc.h +++ /dev/null @@ -1,129 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - -#ifndef DB2I_MISC_H -#define DB2I_MISC_H - -/** - Undelimit quote-delimited DB2 names in-place -*/ -void stripExtraQuotes(char* name, uint maxLen) -{ - char* oldName = (char*)sql_strdup(name); - uint i = 0; - uint j = 0; - do - { - name[j] = oldName[i]; - if (oldName[i] == '"' && oldName[i+1] == '"') - ++i; - } while (++j < maxLen && oldName[++i]); - - if (j == maxLen) - --j; - name[j] = 0; -} - -/** - Convert a MySQL identifier name into a DB2 compatible format - - @parm input The MySQL name - @parm output The DB2 name - @parm outlen The amount of space allocated for output - @parm delimit Should delimiting quotes be placed around the converted name? - @parm delimitQuotes Should quotes in the MySQL be delimited with additional quotes? - - @return FALSE if output was too small and name was truncated; TRUE otherwise -*/ -bool convertMySQLNameToDB2Name(const char* input, - char* output, - size_t outlen, - bool delimit = true, - bool delimitQuotes = true) -{ - uint o = 0; - if (delimit) - output[o++] = '"'; - - uint i = 0; - do - { - output[o] = input[i]; - if (delimitQuotes && input[i] == '"') - output[++o] = '"'; - } while (++o < outlen-2 && input[++i]); - - if (delimit) - output[o++] = '"'; - output[min(o, outlen-1)] = 0; // This isn't the most user-friendly way to handle overflows, - // but at least its safe. - return (o <= outlen-1); -} - -bool isOrdinaryIdentifier(const char* s) -{ - while (*s) - { - if (my_isupper(system_charset_info, *s) || - my_isdigit(system_charset_info, *s) || - (*s == '_') || - (*s == '@') || - (*s == '$') || - (*s == '#') || - (*s == '"')) - ++s; - else - return false; - } - return true; -} - -/** - Fill memory with a 16-bit word. - - @param p Pointer to space to fill. - @param v Value to fill - @param l Length of space (in 16-bit words) -*/ -void memset16(void* p, uint16 v, size_t l) -{ - uint16* p2=(uint16*)p; - while (l--) - { - *(p2++) = v; - } -} - -#endif diff --git a/storage/ibmdb2i/db2i_myconv.cc b/storage/ibmdb2i/db2i_myconv.cc deleted file mode 100644 index 7be6e1236cd..00000000000 --- a/storage/ibmdb2i/db2i_myconv.cc +++ /dev/null @@ -1,1498 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - -/** - @file - - @brief A direct map optimization of iconv and related functions - This was show to significantly reduce character conversion cost - for short strings when compared to calling iconv system code. -*/ - -#include <stdlib.h> -#include <stdio.h> -#include <wchar.h> -#include <errno.h> -#include <iconv.h> -#include <ctype.h> -#include <stdarg.h> -#include <string.h> -#include <as400_protos.h> - -#include "db2i_myconv.h" -#include "db2i_global.h" - -int32_t myconvDebug=0; - -static char szGetTimeString[20]; -static char * GetTimeString(time_t now) -{ - struct tm * tm; - - now = time(&now); - tm = (struct tm *) localtime(&now); - sprintf(szGetTimeString, "%04d/%02d/%02d %02d:%02d:%02d", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); - - return szGetTimeString; -} - -static MEM_ROOT dmapMemRoot; - -void initMyconv() -{ - init_alloc_root(&dmapMemRoot, 0x200, 0); -} - -void cleanupMyconv() -{ - free_root(&dmapMemRoot,0); -} - - -#ifdef DEBUG -/* type: */ -#define STDOUT_WITH_TIME -1 /* to stdout with time */ -#define STDERR_WITH_TIME -2 /* to stderr with time */ -#define STDOUT_WO_TIME 1 /* : to stdout */ -#define STDERR_WO_TIME 2 /* : to stderr */ - - -static void MyPrintf(long type, - char * fmt, ...) -{ - char StdoutFN[256]; - va_list ap; - char * p; - time_t now; - FILE * fd=stderr; - - if (type < 0) - { - now = time(&now); - fprintf(fd, "%s ", GetTimeString(now)); - } - va_start(ap, fmt); - vfprintf(fd, fmt, ap); - va_end(ap); -} -#endif - - - - -#define MAX_CONVERTER 128 - -mycstoccsid(const char* pname) -{ - if (strcmp(pname, "UTF-16")==0) - return 1200; - else if (strcmp(pname, "big5")==0) - return 950; - else - return cstoccsid(pname); -} -#define cstoccsid mycstoccsid - -static struct __myconv_rec myconv_rec [MAX_CONVERTER]; -static struct __dmap_rec dmap_rec [MAX_CONVERTER]; - -static int dmap_open(const char * to, - const char * from, - const int32_t idx) -{ - if (myconvIsSBCS(from) && myconvIsSBCS(to)) { - dmap_rec[idx].codingSchema = DMAP_S2S; - if ((dmap_rec[idx].dmapS2S = (uchar *) alloc_root(&dmapMemRoot, 0x100)) == NULL) { -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", - to, from, idx, DMAP_S2S, errno, __FILE__,__LINE__); -#endif - return -1; - } - memset(dmap_rec[idx].dmapS2S, 0x00, 0x100); - myconv_rec[idx].allocatedSize=0x100; - - { - char dmapSrc[0x100]; - iconv_t cd; - int32_t i; - size_t inBytesLeft=0x100; - size_t outBytesLeft=0x100; - size_t len; - char * inBuf=dmapSrc; - char * outBuf=(char *) dmap_rec[idx].dmapS2S; - - if ((cd = iconv_open(to, from)) == (iconv_t) -1) { -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n", - to, from, idx, errno, __FILE__,__LINE__); -#endif - return -1; - } - - inBytesLeft = 0x100; - for (i = 0; i < inBytesLeft; ++i) - dmapSrc[i]=i; - - do { - if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { -#ifdef DEBUG - if (myconvDebug) { - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d), CS=%d: iconv() returns %d, errno = %d in %s at %d\n", - to, from, idx, DMAP_S2S, len, errno, __FILE__,__LINE__); - MyPrintf(STDERR_WITH_TIME, - "inBytesLeft = %d, inBuf - dmapSrc = %d\n", inBytesLeft, inBuf-dmapSrc); - MyPrintf(STDERR_WITH_TIME, - "outBytesLeft = %d, outBuf - dmapS2S = %d\n", outBytesLeft, outBuf-(char *) dmap_rec[idx].dmapS2S); - } - if ((inBytesLeft == 86 || inBytesLeft == 64 || inBytesLeft == 1) && - memcmp(from, "IBM-1256", 9) == 0 && - memcmp(to, "IBM-420", 8) == 0) { - /* Known problem for IBM-1256_IBM-420 */ - --inBytesLeft; - ++inBuf; - *outBuf=0x00; - ++outBuf; - --outBytesLeft; - continue; - } else if ((inBytesLeft == 173 || inBytesLeft == 172 || - inBytesLeft == 74 || inBytesLeft == 73 || - inBytesLeft == 52 || inBytesLeft == 50 || - inBytesLeft == 31 || inBytesLeft == 20 || - inBytesLeft == 6) && - memcmp(to, "IBM-1256", 9) == 0 && - memcmp(from, "IBM-420", 8) == 0) { - /* Known problem for IBM-420_IBM-1256 */ - --inBytesLeft; - ++inBuf; - *outBuf=0x00; - ++outBuf; - --outBytesLeft; - continue; - } else if ((128 >= inBytesLeft) && - memcmp(to, "IBM-037", 8) == 0 && - memcmp(from, "IBM-367", 8) == 0) { - /* Known problem for IBM-367_IBM-037 */ - --inBytesLeft; - ++inBuf; - *outBuf=0x00; - ++outBuf; - --outBytesLeft; - continue; - } else if (((1 <= inBytesLeft && inBytesLeft <= 4) || (97 <= inBytesLeft && inBytesLeft <= 128)) && - memcmp(to, "IBM-838", 8) == 0 && - memcmp(from, "TIS-620", 8) == 0) { - /* Known problem for TIS-620_IBM-838 */ - --inBytesLeft; - ++inBuf; - *outBuf=0x00; - ++outBuf; - --outBytesLeft; - continue; - } - iconv_close(cd); - return -1; -#else - /* Tolerant to undefined conversions for any converter */ - --inBytesLeft; - ++inBuf; - *outBuf=0x00; - ++outBuf; - --outBytesLeft; - continue; -#endif - } - } while (inBytesLeft > 0); - - if (myconvIsISO(to)) - myconv_rec[idx].subS=0x1A; - else if (myconvIsASCII(to)) - myconv_rec[idx].subS=0x7F; - else if (myconvIsEBCDIC(to)) - myconv_rec[idx].subS=0x3F; - - if (myconvIsISO(from)) - myconv_rec[idx].srcSubS=0x1A; - else if (myconvIsASCII(from)) - myconv_rec[idx].srcSubS=0x7F; - else if (myconvIsEBCDIC(from)) - myconv_rec[idx].srcSubS=0x3F; - - iconv_close(cd); - } - } else if (((myconvIsSBCS(from) && myconvIsUnicode2(to)) && (dmap_rec[idx].codingSchema = DMAP_S2U)) || - ((myconvIsSBCS(from) && myconvIsUTF8(to)) && (dmap_rec[idx].codingSchema = DMAP_S28))) { - int i; - - /* single byte mapping */ - if ((dmap_rec[idx].dmapD12U = (UniChar *) alloc_root(&dmapMemRoot, 0x100 * 2)) == NULL) { -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", - to, from, idx, DMAP_S2U, errno, __FILE__,__LINE__); -#endif - return -1; - } - memset(dmap_rec[idx].dmapD12U, 0x00, 0x100 * 2); - myconv_rec[idx].allocatedSize=0x100 * 2; - - - { - char dmapSrc[2]; - iconv_t cd; - int32_t i; - size_t inBytesLeft; - size_t outBytesLeft; - size_t len; - char * inBuf; - char * outBuf; - char SS=0x1A; -#ifdef support_surrogate - if ((cd = iconv_open("UTF-16", from)) == (iconv_t) -1) { -#else - if ((cd = iconv_open("UCS-2", from)) == (iconv_t) -1) { -#endif -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n", - to, from, idx, errno, __FILE__,__LINE__); -#endif - return -1; - } - - for (i = 0; i < 0x100; ++i) { - dmapSrc[0]=i; - inBuf=dmapSrc; - inBytesLeft=1; - outBuf=(char *) &(dmap_rec[idx].dmapD12U[i]); - outBytesLeft=2; - if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { - if ((errno == EILSEQ || errno == EINVAL) && - inBytesLeft == 1 && - outBytesLeft == 2) { - continue; - } else { -#ifdef DEBUG - if (myconvDebug) { - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed to initialize with iconv(cd,%02x,%d,%02x%02x,%d), errno = %d in %s at %d\n", - to, from, idx, dmapSrc[0], 1, - (&dmap_rec[idx].dmapD12U[i])[0],(&dmap_rec[idx].dmapD12U[i])[1], 2, - errno, __FILE__,__LINE__); - MyPrintf(STDERR_WITH_TIME, - "inBytesLeft=%d, outBytesLeft=%d, %02x%02x\n", - inBytesLeft, outBytesLeft, - (&dmap_rec[idx].dmapD12U[i])[0],(&dmap_rec[idx].dmapD12U[i])[1]); - } -#endif - iconv_close(cd); - return -1; - } - dmap_rec[idx].dmapD12U[i]=0x0000; - } - if (dmap_rec[idx].dmapE02U[i] == 0x001A && /* pick the first one */ - myconv_rec[idx].srcSubS == 0x00) { - myconv_rec[idx].srcSubS=i; - } - } - iconv_close(cd); - } - myconv_rec[idx].subS=0x1A; - myconv_rec[idx].subD=0xFFFD; - - - } else if (((myconvIsUCS2(from) && myconvIsSBCS(to)) && (dmap_rec[idx].codingSchema = DMAP_U2S)) || - ((myconvIsUTF16(from) && myconvIsSBCS(to)) && (dmap_rec[idx].codingSchema = DMAP_T2S)) || - ((myconvIsUTF8(from) && myconvIsSBCS(to)) && (dmap_rec[idx].codingSchema = DMAP_82S))) { - /* UTF-16 -> SBCS, the direct map a bit of waste of space, - * binary search may be reasonable alternative - */ - if ((dmap_rec[idx].dmapU2S = (uchar *) alloc_root(&dmapMemRoot, 0x10000 * 2)) == NULL) { -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", - to, from, idx, DMAP_U2S, errno, __FILE__,__LINE__); -#endif - return -1; - } - memset(dmap_rec[idx].dmapU2S, 0x00, 0x10000); - myconv_rec[idx].allocatedSize=(0x10000 * 2); - - { - iconv_t cd; - int32_t i; - -#ifdef support_surrogate - if ((cd = iconv_open(to, "UTF-16")) == (iconv_t) -1) { -#else - if ((cd = iconv_open(to, "UCS-2")) == (iconv_t) -1) { -#endif -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n", - to, from, idx, errno, __FILE__,__LINE__); -#endif - return -1; - } - - for (i = 0; i < 0x100; ++i) { - UniChar dmapSrc[0x100]; - int32_t j; - for (j = 0; j < 0x100; ++j) { - dmapSrc[j]=i * 0x100 + j; - } - char * inBuf=(char *) dmapSrc; - char * outBuf=(char *) &(dmap_rec[idx].dmapU2S[i*0x100]); - size_t inBytesLeft=sizeof(dmapSrc); - size_t outBytesLeft=0x100; - size_t len; - - if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { - if (inBytesLeft == 0 && outBytesLeft == 0) { /* a number of substitution returns */ - continue; - } -#ifdef DEBUG - if (myconvDebug) { - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", - from, to, idx, errno, __FILE__,__LINE__); - MyPrintf(STDERR_WITH_TIME, - "iconv() retuns %d, errno=%d, InBytesLeft=%d, OutBytesLeft=%d\n", - len, errno, inBytesLeft, outBytesLeft, __FILE__,__LINE__); - } -#endif - iconv_close(cd); - return -1; - } - } - iconv_close(cd); - - myconv_rec[idx].subS = dmap_rec[idx].dmapU2S[0x1A]; - myconv_rec[idx].subD = dmap_rec[idx].dmapU2S[0xFFFD]; - myconv_rec[idx].srcSubS = 0x1A; - myconv_rec[idx].srcSubD = 0xFFFD; - } - - - - } else if (((myconvIsDBCS(from) && myconvIsUnicode2(to)) && (dmap_rec[idx].codingSchema = DMAP_D2U)) || - ((myconvIsDBCS(from) && myconvIsUTF8(to)) && (dmap_rec[idx].codingSchema = DMAP_D28))) { - int i; - /* single byte mapping */ - if ((dmap_rec[idx].dmapD12U = (UniChar *) alloc_root(&dmapMemRoot, 0x100 * 2)) == NULL) { -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", - to, from, idx, DMAP_D2U, errno, __FILE__,__LINE__); -#endif - return -1; - } - memset(dmap_rec[idx].dmapD12U, 0x00, 0x100 * 2); - - /* double byte mapping, assume 7 bit ASCII is not use as the first byte of DBCS. */ - if ((dmap_rec[idx].dmapD22U = (UniChar *) alloc_root(&dmapMemRoot, 0x8000 * 2)) == NULL) { -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", - to, from, idx, DMAP_D2U, errno, __FILE__,__LINE__); -#endif - return -1; - } - memset(dmap_rec[idx].dmapD22U, 0x00, 0x8000 * 2); - - myconv_rec[idx].allocatedSize=(0x100 + 0x8000) * 2; - - - { - char dmapSrc[2]; - iconv_t cd; - int32_t i; - size_t inBytesLeft; - size_t outBytesLeft; - size_t len; - char * inBuf; - char * outBuf; - char SS=0x1A; - -#ifdef support_surrogate - if ((cd = iconv_open("UTF-16", from)) == (iconv_t) -1) { -#else - if ((cd = iconv_open("UCS-2", from)) == (iconv_t) -1) { -#endif -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n", - to, from, idx, errno, __FILE__,__LINE__); -#endif - return -1; - } - - for (i = 0; i < 0x100; ++i) { - dmapSrc[0]=i; - inBuf=dmapSrc; - inBytesLeft=1; - outBuf=(char *) (&dmap_rec[idx].dmapD12U[i]); - outBytesLeft=2; - if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { - if ((errno == EILSEQ || errno == EINVAL) && - inBytesLeft == 1 && - outBytesLeft == 2) { - continue; - } else { -#ifdef DEBUG - if (myconvDebug) { - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed to initialize with iconv(cd,%02x,%d,%02x%02x,%d), errno = %d in %s at %d\n", - to, from, idx, dmapSrc[0], 1, - (&dmap_rec[idx].dmapD12U[i])[0],(&dmap_rec[idx].dmapD12U[i])[1], 2, - errno, __FILE__,__LINE__); - MyPrintf(STDERR_WITH_TIME, - "inBytesLeft=%d, outBytesLeft=%d, %02x%02x\n", - inBytesLeft, outBytesLeft, - (&dmap_rec[idx].dmapD12U[i])[0],(&dmap_rec[idx].dmapD12U[i])[1]); - } -#endif - iconv_close(cd); - return -1; - } - dmap_rec[idx].dmapD12U[i]=0x0000; - } - if (dmap_rec[idx].dmapD12U[i] == 0x001A && /* pick the first one */ - myconv_rec[idx].srcSubS == 0x00) { - myconv_rec[idx].srcSubS=i; - } - } - - - for (i = 0x80; i < 0x100; ++i) { - int j; - if (dmap_rec[idx].dmapD12U[i] != 0x0000) - continue; - for (j = 0x01; j < 0x100; ++j) { - dmapSrc[0]=i; - dmapSrc[1]=j; - int offset = i-0x80; - offset<<=8; - offset+=j; - - inBuf=dmapSrc; - inBytesLeft=2; - outBuf=(char *) &(dmap_rec[idx].dmapD22U[offset]); - outBytesLeft=2; - if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { - if (inBytesLeft == 2 && outBytesLeft == 2 && (errno == EILSEQ || errno == EINVAL)) { - ; /* invalid DBCS character, dmapDD2U[offset] remains 0x0000 */ - } else { -#ifdef DEBUG - if (myconvDebug) { - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed to initialize with iconv(cd,%p,2,%p,2), errno = %d in %s at %d\n", - to, from, idx, - dmapSrc, &(dmap_rec[idx].dmapD22U[offset]), - errno, __FILE__,__LINE__); - MyPrintf(STDERR_WO_TIME, - "iconv(cd,0x%02x%02x,2,0x%04x,2) returns %d, inBytesLeft=%d, outBytesLeft=%d\n", - dmapSrc[0], dmapSrc[1], - dmap_rec[idx].dmapD22U[offset], - len, inBytesLeft, outBytesLeft); - } -#endif - iconv_close(cd); - return -1; - } - } else { -#ifdef TRACE_DMAP - if (myconvDebug) { - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed to initialize with iconv(), rc=%d, errno=%d in %s at %d\n", - to, from, idx, len, errno, __FILE__,__LINE__); - MyPrintf(STDERR_WITH_TIME, - "%04X: src=%04X%04X, inBuf=0x%02X%02X, inBytesLeft=%d, outBuf=%02X%02X%02X, outBytesLeft=%d\n", - i, dmapSrc[0], dmapSrc[1], inBuf[0], inBuf[1], - inBytesLeft, outBuf[-2], outBuf[-1], outBuf[0], outBytesLeft); - MyPrintf(STDERR_WITH_TIME, - "&dmapSrc=%p, inBuf=%p, %p, outBuf=%p\n", - dmapSrc, inBuf, dmap_rec[idx].dmapU2M3 + (i - 0x80) * 2, outBuf); - } -#endif - } - } - if (dmap_rec[idx].dmapD12U[i] == 0xFFFD) { /* pick the last one */ - myconv_rec[idx].srcSubD=i* 0x100 + j; - } - } - iconv_close(cd); - } - - myconv_rec[idx].subS=0x1A; - myconv_rec[idx].subD=0xFFFD; - myconv_rec[idx].srcSubD=0xFCFC; - - - } else if (((myconvIsUCS2(from) && myconvIsDBCS(to)) && (dmap_rec[idx].codingSchema = DMAP_U2D)) || - ((myconvIsUTF16(from) && myconvIsDBCS(to)) && (dmap_rec[idx].codingSchema = DMAP_T2D)) || - ((myconvIsUTF8(from) && myconvIsDBCS(to)) && (dmap_rec[idx].codingSchema = DMAP_82D))) { - /* UTF-16 -> DBCS single/double byte */ - /* A single table will cover all characters, assuming no second byte is 0x00. */ - if ((dmap_rec[idx].dmapU2D = (uchar *) alloc_root(&dmapMemRoot, 0x10000 * 2)) == NULL) { -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", - to, from, idx, DMAP_U2D, errno, __FILE__,__LINE__); -#endif - return -1; - } - - memset(dmap_rec[idx].dmapU2D, 0x00, 0x10000 * 2); - myconv_rec[idx].allocatedSize=(0x10000 * 2); - - { - UniChar dmapSrc[1]; - iconv_t cd; - int32_t i; - size_t inBytesLeft; - size_t outBytesLeft; - size_t len; - char * inBuf; - char * outBuf; - -#ifdef support_surrogate - if ((cd = iconv_open(to, "UTF-16")) == (iconv_t) -1) { -#else - if ((cd = iconv_open(to, "UCS-2")) == (iconv_t) -1) { -#endif -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n", - to, from, idx, errno, __FILE__,__LINE__); -#endif - return -1; - } - - /* easy implementation, convert 1 Unicode character at one time. */ - /* If the open performance is an issue, convert a chunk such as 128 chracters. */ - /* if the converted length is not the same as the original, convert one by one. */ - (dmap_rec[idx].dmapU2D)[0x0000]=0x00; - for (i = 1; i < 0x10000; ++i) { - dmapSrc[0]=i; - inBuf=(char *) dmapSrc; - inBytesLeft=2; - outBuf=(char *) &((dmap_rec[idx].dmapU2D)[2*i]); - outBytesLeft=2; - do { - if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { - if (len == 1 && inBytesLeft == 0 && outBytesLeft == 1 && (dmap_rec[idx].dmapU2D)[2*i] == 0x1A) { - /* UCS-2_TIS-620:0x0080 => 0x1A, converted to SBCS replacement character */ - (dmap_rec[idx].dmapU2D)[2*i+1]=0x00; - break; - } else if (len == 1 && inBytesLeft == 0 && outBytesLeft == 0) { - break; - } - if (errno == EILSEQ || errno == EINVAL) { -#ifdef DEBUG - if (myconvDebug) { - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", - to, from, idx, errno, __FILE__,__LINE__); - MyPrintf(STDERR_WO_TIME, - "iconv(cd,%04x,2,%02x%02x,2) returns inBytesLeft=%d, outBytesLeft=%d\n", - dmapSrc[0], - (dmap_rec[idx].dmapU2D)[2*i], (dmap_rec[idx].dmapU2D)[2*i+1], - inBytesLeft, outBytesLeft); - if (outBuf - (char *) dmap_rec[idx].dmapU2M2 > 1) - MyPrintf(STDERR_WO_TIME, "outBuf[-2..2]=%02X%02X%02X%02X%02X\n", outBuf[-2],outBuf[-1],outBuf[0],outBuf[1],outBuf[2]); - else - MyPrintf(STDERR_WO_TIME, "outBuf[0..2]=%02X%02X%02X\n", outBuf[0],outBuf[1],outBuf[2]); - } -#endif - inBuf+=2; - inBytesLeft-=2; - memcpy(outBuf, (char *) &(myconv_rec[idx].subD), 2); - outBuf+=2; - outBytesLeft-=2; - } else { -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "[%d] dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", - i, to, from, idx, errno, __FILE__,__LINE__); - MyPrintf(STDERR_WO_TIME, - "iconv(cd,%04x,2,%02x%02x,2) returns %d inBytesLeft=%d, outBytesLeft=%d\n", - dmapSrc[0], - (dmap_rec[idx].dmapU2D)[2*i], - (dmap_rec[idx].dmapU2D)[2*i+1], - len, inBytesLeft,outBytesLeft); - if (i == 1) { - MyPrintf(STDERR_WO_TIME, - " inBuf [-1..2]=%02x%02x%02x%02x\n", - inBuf[-1],inBuf[0],inBuf[1],inBuf[2]); - MyPrintf(STDERR_WO_TIME, - " outBuf [-1..2]=%02x%02x%02x%02x\n", - outBuf[-1],outBuf[0],outBuf[1],outBuf[2]); - } else { - MyPrintf(STDERR_WO_TIME, - " inBuf [-2..2]=%02x%02x%02x%02x%02x\n", - inBuf[-2],inBuf[-1],inBuf[0],inBuf[1],inBuf[2]); - MyPrintf(STDERR_WO_TIME, - " outBuf [-2..2]=%02x%02x%02x%02x%02x\n", - outBuf[-2],outBuf[-1],outBuf[0],outBuf[1],outBuf[2]); - } -#endif - iconv_close(cd); - return -1; - } - if (len == 0 && inBytesLeft == 0 && outBytesLeft == 1) { /* converted to SBCS */ - (dmap_rec[idx].dmapU2D)[2*i+1]=0x00; - break; - } - } - } while (inBytesLeft > 0); - } - iconv_close(cd); - myconv_rec[idx].subS = dmap_rec[idx].dmapU2D[2*0x1A]; - myconv_rec[idx].subD = dmap_rec[idx].dmapU2D[2*0xFFFD] * 0x100 - + dmap_rec[idx].dmapU2D[2*0xFFFD+1]; - myconv_rec[idx].srcSubS = 0x1A; - myconv_rec[idx].srcSubD = 0xFFFD; - } - - - } else if (((myconvIsEUC(from) && myconvIsUnicode2(to)) && (dmap_rec[idx].codingSchema = DMAP_E2U)) || - ((myconvIsEUC(from) && myconvIsUTF8(to)) && (dmap_rec[idx].codingSchema = DMAP_E28))) { - int i; - /* S0: 0x00 - 0x7F */ - if ((dmap_rec[idx].dmapE02U = (UniChar *) alloc_root(&dmapMemRoot, 0x100 * 2)) == NULL) { -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", - to, from, idx, DMAP_E2U, errno, __FILE__,__LINE__); -#endif - return -1; - } - memset(dmap_rec[idx].dmapE02U, 0x00, 0x100 * 2); - - /* S1: 0xA0 - 0xFF, 0xA0 - 0xFF */ - if ((dmap_rec[idx].dmapE12U = (UniChar *) alloc_root(&dmapMemRoot, 0x60 * 0x60 * 2)) == NULL) { -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", - to, from, idx, DMAP_E2U, errno, __FILE__,__LINE__); -#endif - return -1; - } - memset(dmap_rec[idx].dmapE12U, 0x00, 0x60 * 0x60 * 2); - - /* SS2: 0x8E + 0xA0 - 0xFF, 0xA0 - 0xFF */ - if ((dmap_rec[idx].dmapE22U = (UniChar *) alloc_root(&dmapMemRoot, 0x60 * 0x61 * 2)) == NULL) { -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", - to, from, idx, DMAP_E2U, errno, __FILE__,__LINE__); -#endif - return -1; - } - memset(dmap_rec[idx].dmapE22U, 0x00, 0x60 * 0x61 * 2); - - /* SS3: 0x8F + 0xA0 - 0xFF, 0xA0 - 0xFF */ - if ((dmap_rec[idx].dmapE32U = (UniChar *) alloc_root(&dmapMemRoot, 0x60 * 0x61 * 2)) == NULL) { -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", - to, from, idx, DMAP_E2U, errno, __FILE__,__LINE__); -#endif - return -1; - } - memset(dmap_rec[idx].dmapE32U, 0x00, 0x60 * 0x61 * 2); - - myconv_rec[idx].allocatedSize=(0x100 + 0x60 * 0x60 + 0x60 * 0x61* 2) * 2; - - - { - char dmapSrc[0x60 * 0x60 * 3]; - iconv_t cd; - int32_t i; - size_t inBytesLeft; - size_t outBytesLeft; - size_t len; - char * inBuf; - char * outBuf; - char SS=0x8E; - -#ifdef support_surrogate - if ((cd = iconv_open("UTF-16", from)) == (iconv_t) -1) { -#else - if ((cd = iconv_open("UCS-2", from)) == (iconv_t) -1) { -#endif -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n", - to, from, idx, errno, __FILE__,__LINE__); -#endif - return -1; - } - - for (i = 0; i < 0x100; ++i) { - dmapSrc[0]=i; - inBuf=dmapSrc; - inBytesLeft=1; - outBuf=(char *) (&dmap_rec[idx].dmapE02U[i]); - outBytesLeft=2; - if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { -#ifdef DEBUG - if (myconvDebug) { - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", - to, from, idx, errno, __FILE__,__LINE__); - } -#endif - dmap_rec[idx].dmapE02U[i]=0x0000; - } - if (dmap_rec[idx].dmapE02U[i] == 0x001A && /* pick the first one */ - myconv_rec[idx].srcSubS == 0x00) { - myconv_rec[idx].srcSubS=i; - } - } - - - inBuf=dmapSrc; - for (i = 0; i < 0x60; ++i) { - int j; - for (j = 0; j < 0x60; ++j) { - *inBuf=i+0xA0; - ++inBuf; - *inBuf=j+0xA0; - ++inBuf; - } - } - inBuf=dmapSrc; - inBytesLeft=0x60 * 0x60 * 2; - outBuf=(char *) dmap_rec[idx].dmapE12U; - outBytesLeft=0x60 * 0x60 * 2; - do { - if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { - if (errno == EILSEQ) { -#ifdef DEBUG - if (myconvDebug) { - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", - to, from, idx, errno, __FILE__,__LINE__); - MyPrintf(STDERR_WO_TIME, "inBytesLeft=%d, outBytesLeft=%d\n", inBytesLeft, outBytesLeft); - if (inBuf - dmapSrc > 1 && inBuf - dmapSrc <= sizeof(dmapSrc) - 2) - MyPrintf(STDERR_WO_TIME, "inBuf[-2..2]=%02X%02X%02X%02X%02X\n", inBuf[-2],inBuf[-1],inBuf[0],inBuf[1],inBuf[2]); - else - MyPrintf(STDERR_WO_TIME, "inBuf[0..2]=%02X%02X%02X\n", inBuf[0],inBuf[1],inBuf[2]); - if (outBuf - (char *) dmap_rec[idx].dmapE12U > 1) - MyPrintf(STDERR_WO_TIME, "outBuf[-2..2]=%02X%02X%02X%02X%02X\n", outBuf[-2],outBuf[-1],outBuf[0],outBuf[1],outBuf[2]); - else - MyPrintf(STDERR_WO_TIME, "outBuf[0..2]=%02X%02X%02X\n", outBuf[0],outBuf[1],outBuf[2]); - } -#endif - inBuf+=2; - inBytesLeft-=2; - outBuf[0]=0x00; - outBuf[1]=0x00; - outBuf+=2; - outBytesLeft-=2; - } else { -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", - to, from, idx, errno, __FILE__,__LINE__); -#endif - iconv_close(cd); - return -1; - } - } - } while (inBytesLeft > 0); - - /* SS2: 0x8E + 1 or 2 bytes */ - /* SS3: 0x8E + 1 or 2 bytes */ - while (SS != 0x00) { - int32_t numSuccess=0; - for (i = 0; i < 0x60; ++i) { - inBuf=dmapSrc; - inBuf[0]=SS; - inBuf[1]=i+0xA0; - inBytesLeft=2; - if (SS == 0x8E) - outBuf=(char *) &(dmap_rec[idx].dmapE22U[i]); - else - outBuf=(char *) &(dmap_rec[idx].dmapE32U[i]); - outBytesLeft=2; - if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { - if (SS == 0x8E) - dmap_rec[idx].dmapE22U[i]=0x0000; - else - dmap_rec[idx].dmapE32U[i]=0x0000; - } else { - ++numSuccess; - } - } - if (numSuccess == 0) { /* SS2 is 2 bytes */ - inBuf=dmapSrc; - for (i = 0; i < 0x60; ++i) { - int j; - for (j = 0; j < 0x60; ++j) { - *inBuf=SS; - ++inBuf; - *inBuf=i+0xA0; - ++inBuf; - *inBuf=j+0xA0; - ++inBuf; - } - } - inBuf=dmapSrc; - inBytesLeft=0x60 * 0x60 * 3; - if (SS == 0x8E) - outBuf=(char *) &(dmap_rec[idx].dmapE22U[0x60]); - else - outBuf=(char *) &(dmap_rec[idx].dmapE32U[0x60]); - outBytesLeft=0x60 * 0x60 * 2; - do { - if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { -#ifdef DEBUG - if (myconvDebug) { - MyPrintf(STDERR_WITH_TIME, - "%02X:dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", - SS, to, from, idx, errno, __FILE__,__LINE__); - MyPrintf(STDERR_WO_TIME, "inBytesLeft=%d, outBytesLeft=%d\n", inBytesLeft, outBytesLeft); - if (inBuf - dmapSrc > 1 && inBuf - dmapSrc <= sizeof(dmapSrc) - 2) - MyPrintf(STDERR_WO_TIME, "inBuf[-2..2]=%02X%02X%02X%02X%02X\n", inBuf[-2],inBuf[-1],inBuf[0],inBuf[1],inBuf[2]); - else - MyPrintf(STDERR_WO_TIME, "inBuf[0..2]=%02X%02X%02X\n", inBuf[0],inBuf[1],inBuf[2]); - } -#endif - if (errno == EILSEQ || errno == EINVAL) { - inBuf+=3; - inBytesLeft-=3; - outBuf[0]=0x00; - outBuf[1]=0x00; - outBuf+=2; - outBytesLeft-=2; - } else { -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "%02X:dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", - SS, to, from, idx, errno, __FILE__,__LINE__); -#endif - iconv_close(cd); - return -1; - } - } - } while (inBytesLeft > 0); - } - if (SS == 0x8E) - SS=0x8F; - else - SS = 0x00; - } - iconv_close(cd); - - myconv_rec[idx].subS=0x1A; - myconv_rec[idx].subD=0xFFFD; - for (i = 0; i < 0x80; ++i) { - if (dmap_rec[idx].dmapE02U[i] == 0x001A) { - myconv_rec[idx].srcSubS=i; /* pick the first one */ - break; - } - } - - for (i = 0; i < 0x60 * 0x60; ++i) { - if (dmap_rec[idx].dmapE12U[i] == 0xFFFD) { - uchar byte1=i / 0x60; - uchar byte2=i % 0x60; - myconv_rec[idx].srcSubD=(byte1 + 0xA0) * 0x100 + (byte2 + 0xA0); /* pick the last one */ - } - } - - } - - } else if (((myconvIsUCS2(from) && myconvIsEUC(to)) && (dmap_rec[idx].codingSchema = DMAP_U2E)) || - ((myconvIsUTF16(from) && myconvIsEUC(to)) && (dmap_rec[idx].codingSchema = DMAP_T2E)) || - ((myconvIsUTF8(from) && myconvIsEUC(to)) && (dmap_rec[idx].codingSchema = DMAP_82E))) { - /* S0: 0x00 - 0xFF */ - if ((dmap_rec[idx].dmapU2S = (uchar *) alloc_root(&dmapMemRoot, 0x100)) == NULL) { -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", - to, from, idx, DMAP_U2E, errno, __FILE__,__LINE__); -#endif - return -1; - } - memset(dmap_rec[idx].dmapU2S, 0x00, 0x100); - - /* U0080 - UFFFF -> S1: 0xA0 - 0xFF, 0xA0 - 0xFF */ - if ((dmap_rec[idx].dmapU2M2 = (uchar *) alloc_root(&dmapMemRoot, 0xFF80 * 2)) == NULL) { -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", - to, from, idx, DMAP_U2E, errno, __FILE__,__LINE__); -#endif - return -1; - } - memset(dmap_rec[idx].dmapU2M2, 0x00, 0xFF80 * 2); - - /* U0080 - UFFFF -> SS2: 0x8E + 0xA0 - 0xFF, 0xA0 - 0xFF - * SS3: 0x8F + 0xA0 - 0xFF, 0xA0 - 0xFF */ - if ((dmap_rec[idx].dmapU2M3 = (uchar *) alloc_root(&dmapMemRoot, 0xFF80 * 3)) == NULL) { -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", - to, from, idx, DMAP_U2E, errno, __FILE__,__LINE__); -#endif - return -1; - } - memset(dmap_rec[idx].dmapU2M3, 0x00, 0xFF80 * 3); - myconv_rec[idx].allocatedSize=(0x100 + 0xFF80 * 2 + 0xFF80 * 3); - - { - UniChar dmapSrc[0x80]; - iconv_t cd; - int32_t i; - size_t inBytesLeft; - size_t outBytesLeft; - size_t len; - char * inBuf; - char * outBuf; - -#ifdef support_surrogate - if ((cd = iconv_open(to, "UTF-16")) == (iconv_t) -1) { -#else - if ((cd = iconv_open(to, "UCS-2")) == (iconv_t) -1) { -#endif -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n", - to, from, idx, errno, __FILE__,__LINE__); -#endif - return -1; - } - - for (i = 0; i < 0x80; ++i) - dmapSrc[i]=i; - inBuf=(char *) dmapSrc; - inBytesLeft=0x80 * 2; - outBuf=(char *) dmap_rec[idx].dmapU2S; - outBytesLeft=0x80; - do { - if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { -#ifdef DEBUG - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", - to, from, idx, errno, __FILE__,__LINE__); -#endif - iconv_close(cd); - return -1; - } - } while (inBytesLeft > 0); - - myconv_rec[idx].srcSubS = 0x1A; - myconv_rec[idx].srcSubD = 0xFFFD; - myconv_rec[idx].subS = dmap_rec[idx].dmapU2S[0x1A]; - - outBuf=(char *) &(myconv_rec[idx].subD); - dmapSrc[0]=0xFFFD; - inBuf=(char *) dmapSrc; - inBytesLeft=2; - outBytesLeft=2; - if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { -#ifdef DEBUG - if (myconvDebug) { - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed to initialize with iconv(), rc=%d, errno=%d in %s at %d\n", - to, from, idx, len, errno, __FILE__,__LINE__); - MyPrintf(STDERR_WO_TIME, "iconv(0x1A,1,%p,1) returns outBuf=%p, outBytesLeft=%d\n", - dmapSrc, outBuf, outBytesLeft); - } -#endif - if (outBytesLeft == 0) { - /* UCS-2_IBM-eucKR returns error. - myconv(iconv) rc=1, error=0, InBytesLeft=0, OutBytesLeft=18 - myconv(iconvRev) rc=-1, error=116, InBytesLeft=2, OutBytesLeft=20 - iconv: 0xFFFD => 0xAFFE => 0x rc=1,-1 sub=0,0 - */ - ; - } else { - iconv_close(cd); - return -1; - } - } - - for (i = 0x80; i < 0xFFFF; ++i) { - uchar eucBuf[3]; - dmapSrc[0]=i; - inBuf=(char *) dmapSrc; - inBytesLeft=2; - outBuf=(char *) eucBuf; - outBytesLeft=sizeof(eucBuf); - errno=0; - if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { - if (len == 1 && errno == 0 && inBytesLeft == 0 && outBytesLeft == 1) { /* substitution occurred. */ continue; - } - - if (errno == EILSEQ) { -#ifdef DEBUG - if (myconvDebug) { - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", - to, from, idx, errno, __FILE__,__LINE__); - MyPrintf(STDERR_WO_TIME, "inBytesLeft=%d, outBytesLeft=%d\n", inBytesLeft, outBytesLeft); - if (inBuf - (char *) dmapSrc > 1 && inBuf - (char *) dmapSrc <= sizeof(dmapSrc) - 2) - MyPrintf(STDERR_WO_TIME, "inBuf[-2..2]=%02X%02X%02X%02X%02X\n", inBuf[-2],inBuf[-1],inBuf[0],inBuf[1],inBuf[2]); - else - MyPrintf(STDERR_WO_TIME, "inBuf[0..2]=%02X%02X%02X\n", inBuf[0],inBuf[1],inBuf[2]); - if (outBuf - (char *) dmap_rec[idx].dmapU2M2 > 1) - MyPrintf(STDERR_WO_TIME, "outBuf[-2..2]=%02X%02X%02X%02X%02X\n", outBuf[-2],outBuf[-1],outBuf[0],outBuf[1],outBuf[2]); - else - MyPrintf(STDERR_WO_TIME, "outBuf[0..2]=%02X%02X%02X\n", outBuf[0],outBuf[1],outBuf[2]); - } -#endif - inBuf+=2; - inBytesLeft-=2; - memcpy(outBuf, (char *) &(myconv_rec[idx].subD), 2); - outBuf+=2; - outBytesLeft-=2; - } else { -#ifdef DEBUG - if (myconvDebug) { - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed to initialize with iconv(), rc = %d, errno = %d in %s at %d\n", - to, from, idx, len, errno, __FILE__,__LINE__); - MyPrintf(STDERR_WITH_TIME, - "%04X: src=%04X%04X, inBuf=0x%02X%02X, inBytesLeft=%d, outBuf[-2..0]=%02X%02X%02X, outBytesLeft=%d\n", - i, dmapSrc[0], dmapSrc[1], inBuf[0], inBuf[1], - inBytesLeft, outBuf[-2], outBuf[-1], outBuf[0], outBytesLeft); - MyPrintf(STDERR_WITH_TIME, - "&dmapSrc=%p, inBuf=%p, dmapU2M2 + %d = %p, outBuf=%p\n", - dmapSrc, inBuf, (i - 0x80) * 2, dmap_rec[idx].dmapU2M2 + (i - 0x80) * 2, outBuf); - } -#endif - iconv_close(cd); - return -1; - } - } - if (sizeof(eucBuf) - outBytesLeft == 1) { - if (i < 0x100) { - (dmap_rec[idx].dmapU2S)[i]=eucBuf[0]; - } else { - dmap_rec[idx].dmapU2M2[(i - 0x80) * 2] = eucBuf[0]; - dmap_rec[idx].dmapU2M2[(i - 0x80) * 2 + 1] = 0x00; - } - } else if (sizeof(eucBuf) - outBytesLeft == 2) { /* 2 bytes */ - dmap_rec[idx].dmapU2M2[(i - 0x80) * 2] = eucBuf[0]; - dmap_rec[idx].dmapU2M2[(i - 0x80) * 2 + 1] = eucBuf[1]; - } else if (sizeof(eucBuf) - outBytesLeft == 3) { /* 3 byte SS2/SS3 */ - dmap_rec[idx].dmapU2M3[(i - 0x80) * 3] = eucBuf[0]; - dmap_rec[idx].dmapU2M3[(i - 0x80) * 3 + 1] = eucBuf[1]; - dmap_rec[idx].dmapU2M3[(i - 0x80) * 3 + 2] = eucBuf[2]; - } else { -#ifdef DEBUG - if (myconvDebug) { - MyPrintf(STDERR_WITH_TIME, - "dmap_open(%s,%s,%d) failed to initialize with iconv(), rc=%d, errno=%d in %s at %d\n", - to, from, idx, len, errno, __FILE__,__LINE__); - MyPrintf(STDERR_WITH_TIME, - "%04X: src=%04X%04X, inBuf=0x%02X%02X, inBytesLeft=%d, outBuf=%02X%02X%02X, outBytesLeft=%d\n", - i, dmapSrc[0], dmapSrc[1], inBuf[0], inBuf[1], - inBytesLeft, outBuf[-2], outBuf[-1], outBuf[0], outBytesLeft); - MyPrintf(STDERR_WITH_TIME, - "&dmapSrc=%p, inBuf=%p, %p, outBuf=%p\n", - dmapSrc, inBuf, dmap_rec[idx].dmapU2M3 + (i - 0x80) * 2, outBuf); - } -#endif - return -1; - } - - } - iconv_close(cd); - } - - } else if (myconvIsUTF16(from) && myconvIsUTF8(to)) { - dmap_rec[idx].codingSchema = DMAP_T28; - - } else if (myconvIsUCS2(from) && myconvIsUTF8(to)) { - dmap_rec[idx].codingSchema = DMAP_U28; - - } else if (myconvIsUTF8(from) && myconvIsUnicode2(to)) { - dmap_rec[idx].codingSchema = DMAP_82U; - - } else if (myconvIsUnicode2(from) && myconvIsUnicode2(to)) { - dmap_rec[idx].codingSchema = DMAP_U2U; - - } else { - - return -1; - } - myconv_rec[idx].cnv_dmap=&(dmap_rec[idx]); - return 0; -} - - - -static int bins_open(const char * to, - const char * from, - const int32_t idx) -{ - return -1; -} - - - -static int32_t dmap_close(const int32_t idx) -{ - if (dmap_rec[idx].codingSchema == DMAP_S2S) { - if (dmap_rec[idx].dmapS2S != NULL) { - dmap_rec[idx].dmapS2S=NULL; - } - } else if (dmap_rec[idx].codingSchema = DMAP_E2U) { - if (dmap_rec[idx].dmapE02U != NULL) { - dmap_rec[idx].dmapE02U=NULL; - } - if (dmap_rec[idx].dmapE12U != NULL) { - dmap_rec[idx].dmapE12U=NULL; - } - if (dmap_rec[idx].dmapE22U != NULL) { - dmap_rec[idx].dmapE22U=NULL; - } - if (dmap_rec[idx].dmapE32U != NULL) { - dmap_rec[idx].dmapE32U=NULL; - } - } - - return 0; -} - - -static int32_t bins_close(const int32_t idx) -{ - return 0; -} - - -myconv_t myconv_open(const char * toCode, - const char * fromCode, - int32_t converter) -{ - int32 i; - for (i = 0; i < MAX_CONVERTER; ++i) { - if (myconv_rec[i].converterType == 0) - break; - } - if (i >= MAX_CONVERTER) - return ((myconv_t) -1); - - myconv_rec[i].converterType = converter; - myconv_rec[i].index=i; - myconv_rec[i].fromCcsid=cstoccsid(fromCode); - if (myconv_rec[i].fromCcsid == 0 && memcmp(fromCode, "big5",5) == 0) - myconv_rec[i].fromCcsid=950; - myconv_rec[i].toCcsid=cstoccsid(toCode); - if (myconv_rec[i].toCcsid == 0 && memcmp(toCode, "big5",5) == 0) - myconv_rec[i].toCcsid=950; - strncpy(myconv_rec[i].from, fromCode, sizeof(myconv_rec[i].from)-1); - strncpy(myconv_rec[i].to, toCode, sizeof(myconv_rec[i].to)-1); - - if (converter == CONVERTER_ICONV) { - if ((myconv_rec[i].cnv_iconv=iconv_open(toCode, fromCode)) == (iconv_t) -1) { - return ((myconv_t) -1); - } - myconv_rec[i].allocatedSize = -1; - myconv_rec[i].srcSubS=myconvGetSubS(fromCode); - myconv_rec[i].srcSubD=myconvGetSubD(fromCode); - myconv_rec[i].subS=myconvGetSubS(toCode); - myconv_rec[i].subD=myconvGetSubD(toCode); - return &(myconv_rec[i]); - } else if (converter == CONVERTER_DMAP && - dmap_open(toCode, fromCode, i) != -1) { - return &(myconv_rec[i]); - } - return ((myconv_t) -1); -} - - - -int32_t myconv_close(myconv_t cd) -{ - int32_t ret=0; - - if (cd->converterType == CONVERTER_ICONV) { - ret=iconv_close(cd->cnv_iconv); - } else if (cd->converterType == CONVERTER_DMAP) { - ret=dmap_close(cd->index); - } - memset(&(myconv_rec[cd->index]), 0x00, sizeof(myconv_rec[cd->index])); - return ret; -} - - - - -/* reference: http://www-306.ibm.com/software/globalization/other/es.jsp */ -/* systemCL would be expensive, and myconvIsXXXXX is called frequently. - need to cache entries */ -#define MAX_CCSID 256 -static int ccsidList [MAX_CCSID]; -static int esList [MAX_CCSID]; -int32 getEncodingScheme(const uint16 inCcsid, int32& outEncodingScheme); -EXTERN int myconvGetES(CCSID ccsid) -{ - /* call QtqValidateCCSID in ILE to get encoding schema */ - /* return QtqValidateCCSID(ccsid); */ - int i; - for (i = 0; i < MAX_CCSID; ++i) { - if (ccsidList[i] == ccsid) - return esList[i]; - if (ccsidList[i] == 0x00) - break; - } - - if (i >= MAX_CCSID) { - i=MAX_CCSID-1; - } - - { - ccsidList[i]=ccsid; - getEncodingScheme(ccsid, esList[i]); -#ifdef DEBUG_PASE - if (myconvDebug) { - fprintf(stderr, "CCSID=%d, ES=0x%04X\n", ccsid, esList[i]); - } -#endif - return esList[i]; - } - return 0; -} - - -EXTERN int myconvIsEBCDIC(const char * pName) -{ - int es = myconvGetES(cstoccsid(pName)); - if (es == 0x1100 || - es == 0x1200 || - es == 0x6100 || - es == 0x6200 || - es == 0x1301 ) { - return TRUE; - } - return FALSE; -} - - -EXTERN int myconvIsISO(const char * pName) -{ - int es = myconvGetES(cstoccsid(pName)); - if (es == 0x4100 || - es == 0x4105 || - es == 0x4155 || - es == 0x5100 || - es == 0x5150 || - es == 0x5200 || - es == 0x5404 || - es == 0x5409 || - es == 0x540A || - es == 0x5700) { - return TRUE; - } - return FALSE; -} - - -EXTERN int myconvIsASCII(const char * pName) -{ - int es = myconvGetES(cstoccsid(pName)); - if (es == 0x2100 || - es == 0x3100 || - es == 0x8100 || - es == 0x2200 || - es == 0x3200 || - es == 0x9200 || - es == 0x2300 || - es == 0x2305 || - es == 0x3300 || - es == 0x2900 || - es == 0x2A00) { - return TRUE; - } else if (memcmp(pName, "big5", 5) == 0) { - return TRUE; - } - return FALSE; -} - - - -EXTERN int myconvIsUCS2(const char * pName) -{ - if (cstoccsid(pName) == 13488) { - return TRUE; - } - return FALSE; -} - - -EXTERN int myconvIsUTF16(const char * pName) -{ - if (cstoccsid(pName) == 1200) { - return TRUE; - } - return FALSE; -} - - -EXTERN int myconvIsUnicode2(const char * pName) -{ - int es = myconvGetES(cstoccsid(pName)); - if (es == 0x7200 || - es == 0x720B || - es == 0x720F) { - return TRUE; - } - return FALSE; -} - - -EXTERN int myconvIsUTF8(const char * pName) -{ - int es = myconvGetES(cstoccsid(pName)); - if (es == 0x7807) { - return TRUE; - } - return FALSE; -} - - -EXTERN int myconvIsUnicode(const char * pName) -{ - int es = myconvGetES(cstoccsid(pName)); - if (es == 0x7200 || - es == 0x720B || - es == 0x720F || - es == 0x7807) { - return TRUE; - } - return FALSE; -} - - -EXTERN int myconvIsEUC(const char * pName) -{ - int es = myconvGetES(cstoccsid(pName)); - if (es == 0x4403) { - return TRUE; - } - return FALSE; -} - - -EXTERN int myconvIsDBCS(const char * pName) -{ - int es = myconvGetES(cstoccsid(pName)); - if (es == 0x1200 || - es == 0x2200 || - es == 0x2300 || - es == 0x2305 || - es == 0x2A00 || - es == 0x3200 || - es == 0x3300 || - es == 0x5200 || - es == 0x6200 || - es == 0x9200) { - return TRUE; - } else if (memcmp(pName, "big5", 5) == 0) { - return TRUE; - } - return FALSE; -} - - -EXTERN int myconvIsSBCS(const char * pName) -{ - int es = myconvGetES(cstoccsid(pName)); - if (es == 0x1100 || - es == 0x2100 || - es == 0x3100 || - es == 0x4100 || - es == 0x4105 || - es == 0x5100 || - es == 0x5150 || - es == 0x6100 || - es == 0x8100) { - return TRUE; - } - return FALSE; -} - - - -EXTERN char myconvGetSubS(const char * code) -{ - if (myconvIsEBCDIC(code)) { - return 0x3F; - } else if (myconvIsASCII(code)) { - return 0x1A; - } else if (myconvIsISO(code)) { - return 0x1A; - } else if (myconvIsEUC(code)) { - return 0x1A; - } else if (myconvIsUCS2(code)) { - return 0x00; - } else if (myconvIsUTF8(code)) { - return 0x1A; - } - return 0x00; -} - - -EXTERN UniChar myconvGetSubD(const char * code) -{ - if (myconvIsEBCDIC(code)) { - return 0xFDFD; - } else if (myconvIsASCII(code)) { - return 0xFCFC; - } else if (myconvIsISO(code)) { - return 0x00; - } else if (myconvIsEUC(code)) { - return 0x00; - } else if (myconvIsUCS2(code)) { - return 0xFFFD; - } else if (myconvIsUTF8(code)) { - return 0x00; - } - return 0x00; -} - diff --git a/storage/ibmdb2i/db2i_myconv.h b/storage/ibmdb2i/db2i_myconv.h deleted file mode 100644 index 98032748148..00000000000 --- a/storage/ibmdb2i/db2i_myconv.h +++ /dev/null @@ -1,3201 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - -/** - @file - - @brief A direct map optimization of iconv and related functions - This was show to significantly reduce character conversion cost - for short strings when compared to calling iconv system code. -*/ - -#ifndef DB2I_MYCONV_H -#define DB2I_MYCONV_H - - -#include <sys/time.h> -#include <stdlib.h> -#include <stdio.h> -#include <wchar.h> -#include <errno.h> -#include <iconv.h> -#include <ctype.h> -#include <time.h> -#include <stdarg.h> -#include <string.h> - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifdef __cplusplus -#define INTERN inline -#define EXTERN extern "C" -#else -#define INTERN static -#define EXTERN extern -#endif - - -/* ANSI integer data types */ -#if defined(__OS400_TGTVRM__) -/* for DTAMDL(*P128), datamodel(P128): int/long/pointer=4/4/16 */ -/* LLP64:4/4/8 is used for teraspace ?? */ -typedef short int16_t; -typedef unsigned short uint16_t; -typedef int int32_t; -typedef unsigned int uint32_t; -typedef long long int64_t; -typedef unsigned long long uint64_t; -#elif defined(PASE) -/* PASE uses IPL32: int/long/pointer=4/4/4 + long long */ -#elif defined(__64BIT__) -/* AIX 64 bit uses LP64: int/long/pointer=4/8/8 */ -#endif - -#define CONVERTER_ICONV 1 -#define CONVERTER_DMAP 2 - -#define DMAP_S2S 10 -#define DMAP_S2U 20 -#define DMAP_D2U 30 -#define DMAP_E2U 40 -#define DMAP_U2S 120 -#define DMAP_T2S 125 -#define DMAP_U2D 130 -#define DMAP_T2D 135 -#define DMAP_U2E 140 -#define DMAP_T2E 145 -#define DMAP_S28 220 -#define DMAP_D28 230 -#define DMAP_E28 240 -#define DMAP_82S 310 -#define DMAP_82D 320 -#define DMAP_82E 330 -#define DMAP_U28 410 -#define DMAP_82U 420 -#define DMAP_T28 425 -#define DMAP_U2U 510 - - -typedef struct __dmap_rec *dmap_t; - -struct __dmap_rec -{ - uint32_t codingSchema; - unsigned char * dmapS2S; /* SBCS -> SBCS */ - /* The following conversion needs be followed by conversion from UCS-2/UTF-16 to UTF-8 */ - UniChar * dmapD12U; /* DBCS(non-EUC) -> UCS-2/UTF-16 */ - UniChar * dmapD22U; /* DBCS(non-EUC) -> UCS-2/UTF-16 */ - UniChar * dmapE02U; /* EUC/SS0 -> UCS-2/UTF-16 */ - UniChar * dmapE12U; /* EUC/SS1 -> UCS-2/UTF-16 */ - UniChar * dmapE22U; /* EUC/0x8E + SS2 -> UCS-2/UTF-16 */ - UniChar * dmapE32U; /* EUC/0x8F + SS3 -> UCS-2/UTF-16 */ - uchar * dmapU2D; /* UCS-2 -> DBCS */ - uchar * dmapU2S; /* UCS-2 -> EUC SS0 */ - uchar * dmapU2M2; /* UCS-2 -> EUC SS1 */ - uchar * dmapU2M3; /* UCS-2 -> EUC SS2/SS3 */ - /* All of these pointers/tables are not used at the same time. - * You may be able save some space if you consolidate them. - */ - uchar * dmapS28; /* SBCS -> UTF-8 */ - uchar * dmapD28; /* DBCS -> UTF-8 */ -}; - -typedef struct __myconv_rec *myconv_t; -struct __myconv_rec -{ - uint32_t converterType; - uint32_t index; /* for close */ - union { - iconv_t cnv_iconv; - dmap_t cnv_dmap; - }; - int32_t allocatedSize; - int32_t fromCcsid; - int32_t toCcsid; - UniChar subD; /* DBCS substitution char */ - char subS; /* SBCS substitution char */ - UniChar srcSubD; /* DBCS substitution char of src codepage */ - char srcSubS; /* SBCS substitution char of src codepage */ - char from [41+1]; /* codepage name is up to 41 bytes */ - char to [41+1]; /* codepage name is up to 41 bytes */ -#ifdef __64BIT__ - char reserved[10]; /* align 128 */ -#else - char reserved[14]; /* align 128 */ -#endif -}; - - -EXTERN int32_t myconvDebug; - - - -EXTERN int myconvGetES(CCSID); -EXTERN int myconvIsEBCDIC(const char *); -EXTERN int myconvIsASCII(const char *); -EXTERN int myconvIsUnicode(const char *); /* UTF-8, UTF-16, or UCS-2 */ -EXTERN int myconvIsUnicode2(const char *); /* 2 byte Unicode */ -EXTERN int myconvIsUCS2(const char *); -EXTERN int myconvIsUTF16(const char *); -EXTERN int myconvIsUTF8(const char *); -EXTERN int myconvIsEUC(const char *); -EXTERN int myconvIsISO(const char *); -EXTERN int myconvIsSBCS(const char *); -EXTERN int myconvIsDBCS(const char *); -EXTERN char myconvGetSubS(const char *); -EXTERN UniChar myconvGetSubD(const char *); - - -EXTERN myconv_t myconv_open(const char*, const char*, int32_t); -EXTERN int myconv_close(myconv_t); - -INTERN size_t myconv_iconv(myconv_t cd , - char** inBuf, - size_t* inBytesLeft, - char** outBuf, - size_t* outBytesLeft, - size_t* numSub) -{ - return iconv(cd->cnv_iconv, inBuf, inBytesLeft, outBuf, outBytesLeft); -} - -INTERN size_t myconv_dmap(myconv_t cd, - char** inBuf, - size_t* inBytesLeft, - char** outBuf, - size_t* outBytesLeft, - size_t* numSub) -{ - if (cd->cnv_dmap->codingSchema == DMAP_S2S) { - register unsigned char * dmapS2S=cd->cnv_dmap->dmapS2S; - register int inLen=*inBytesLeft; - register char * pOut=*outBuf; - register char * pIn=*inBuf; - register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; - register char subS=cd->subS; - register size_t numS=0; - while (0 < inLen) { - if (pLastOutBuf < pOut) - break; - if (*pIn == 0x00) { - *pOut=0x00; - } else { - *pOut=dmapS2S[*pIn]; - if (*pOut == 0x00) { - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(*inBytesLeft-inLen); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - if (*pOut == subS) { - if ((*pOut=dmapS2S[*pIn]) == subS) { - if (*pIn != cd->srcSubS) - ++numS; - } - } - } - ++pIn; - --inLen; - ++pOut; - } - *outBytesLeft-=(*inBytesLeft-inLen); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return 0; - - } else if (cd->cnv_dmap->codingSchema == DMAP_E2U) { - /* use uchar * instead of UniChar to avoid memcpy */ - register uchar * dmapE02U=(uchar *) (cd->cnv_dmap->dmapE02U); - register uchar * dmapE12U=(uchar *) (cd->cnv_dmap->dmapE12U); - register uchar * dmapE22U=(uchar *) (cd->cnv_dmap->dmapE22U); - register uchar * dmapE32U=(uchar *) (cd->cnv_dmap->dmapE32U); - register int inLen=*inBytesLeft; - register char * pOut=*outBuf; - register char * pIn=*inBuf; - register int offset; - register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; - register size_t numS=0; - while (0 < inLen) { - if (pLastOutBuf < pOut) - break; - if (*pIn == 0x00) { - *pOut=0x00; - ++pOut; - *pOut=0x00; - ++pOut; - ++pIn; - --inLen; - } else { - if (*pIn == 0x8E) { /* SS2 */ - if (inLen < 2) { - if (cd->fromCcsid == 33722 || /* IBM-eucJP */ - cd->fromCcsid == 964) /* IBM-eucTW */ - errno=EINVAL; /* 22 */ - else - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - return -1; - } - ++pIn; - if (*pIn < 0xA0) { - if (cd->fromCcsid == 964) /* IBM-eucTW */ - errno=EINVAL; /* 22 */ - else - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-1; - return -1; - } - offset=(*pIn - 0xA0); - offset<<=1; - if (dmapE22U[offset] == 0x00 && - dmapE22U[offset+1] == 0x00) { /* 2 bytes */ - if (inLen < 3) { - if (cd->fromCcsid == 964) /* IBM-eucTW */ - errno=EINVAL; /* 22 */ - else - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-1; - return -1; - } - offset=(*pIn - 0xA0) * 0x60 + 0x60; - ++pIn; - if (*pIn < 0xA0) { - if (cd->fromCcsid == 964) /* IBM-eucTW */ - errno=EINVAL; /* 22 */ - else - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-2; - return -1; - } - offset+=(*pIn - 0xA0); - offset<<=1; - if (dmapE22U[offset] == 0x00 && - dmapE22U[offset+1] == 0x00) { - if (cd->fromCcsid == 964) /* IBM-eucTW */ - errno=EINVAL; /* 22 */ - else - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-2; - return -1; - } - *pOut=dmapE22U[offset]; - ++pOut; - *pOut=dmapE22U[offset+1]; - ++pOut; - if (dmapE22U[offset] == 0xFF && - dmapE22U[offset+1] == 0xFD) { - if (pIn[-2] * 0x100 + pIn[-1] != cd->srcSubD) - ++numS; - } - ++pIn; - inLen-=3; - } else { /* 1 bytes */ - *pOut=dmapE22U[offset]; - ++pOut; - *pOut=dmapE22U[offset+1]; - ++pOut; - ++pIn; - inLen-=2; - } - } else if (*pIn == 0x8F) { /* SS3 */ - if (inLen < 2) { - if (cd->fromCcsid == 33722) /* IBM-eucJP */ - errno=EINVAL; /* 22 */ - else - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - return -1; - } - ++pIn; - if (*pIn < 0xA0) { - if (cd->fromCcsid == 970 || /* IBM-eucKR */ - cd->fromCcsid == 964 || /* IBM-eucTW */ - cd->fromCcsid == 1383 || /* IBM-eucCN */ - (cd->fromCcsid == 33722 && 3 <= inLen)) /* IBM-eucJP */ - errno=EILSEQ; /* 116 */ - else - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-1; - return -1; - } - offset=(*pIn - 0xA0); - offset<<=1; - if (dmapE32U[offset] == 0x00 && - dmapE32U[offset+1] == 0x00) { /* 0x8F + 2 bytes */ - if (inLen < 3) { - if (cd->fromCcsid == 33722) - errno=EINVAL; /* 22 */ - else - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-1; - return -1; - } - offset=(*pIn - 0xA0) * 0x60 + 0x60; - ++pIn; - if (*pIn < 0xA0) { - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-2; - return -1; - } - offset+=(*pIn - 0xA0); - offset<<=1; - if (dmapE32U[offset] == 0x00 && - dmapE32U[offset+1] == 0x00) { - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-2; - return -1; - } - *pOut=dmapE32U[offset]; - ++pOut; - *pOut=dmapE32U[offset+1]; - ++pOut; - if (dmapE32U[offset] == 0xFF && - dmapE32U[offset+1] == 0xFD) { - if (pIn[-2] * 0x100 + pIn[-1] != cd->srcSubD) - ++numS; - } - ++pIn; - inLen-=3; - } else { /* 0x8F + 1 bytes */ - *pOut=dmapE32U[offset]; - ++pOut; - *pOut=dmapE32U[offset+1]; - ++pOut; - ++pIn; - inLen-=2; - } - - } else { - offset=*pIn; - offset<<=1; - if (dmapE02U[offset] == 0x00 && - dmapE02U[offset+1] == 0x00) { /* SS1 */ - if (inLen < 2) { - if ((cd->fromCcsid == 33722 && (*pIn == 0xA0 || (0xA9 <= *pIn && *pIn <= 0xAF) || *pIn == 0xFF)) || - (cd->fromCcsid == 970 && (*pIn == 0xA0 || *pIn == 0xAD || *pIn == 0xAE || *pIn == 0xAF || *pIn == 0xFF)) || - (cd->fromCcsid == 964 && (*pIn == 0xA0 || (0xAA <= *pIn && *pIn <= 0xC1) || *pIn == 0xC3 || *pIn == 0xFE || *pIn == 0xFF)) || - (cd->fromCcsid == 1383 && (*pIn == 0xA0 || *pIn == 0xFF))) - errno=EILSEQ; /* 116 */ - else - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - return -1; - } - if (*pIn < 0xA0) { - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - return -1; - } - offset=(*pIn - 0xA0) * 0x60; - ++pIn; - if (*pIn < 0xA0) { - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-1; - return -1; - } - offset+=(*pIn - 0xA0); - offset<<=1; - if (dmapE12U[offset] == 0x00 && - dmapE12U[offset+1] == 0x00) { /* undefined mapping */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-1; - return -1; - } - *pOut=dmapE12U[offset]; - ++pOut; - *pOut=dmapE12U[offset+1]; - ++pOut; - if (dmapE12U[offset] == 0xFF && - dmapE12U[offset+1] == 0xFD) { - if (pIn[-1] * 0x100 + pIn[0] != cd->srcSubD) - ++numS; - } - ++pIn; - inLen-=2; - } else { - *pOut=dmapE02U[offset]; - ++pOut; - *pOut=dmapE02U[offset+1]; - ++pOut; - if (dmapE02U[offset] == 0x00 && - dmapE02U[offset+1] == 0x1A) { - if (*pIn != cd->srcSubS) - ++numS; - } - ++pIn; - --inLen; - } - } - } - } - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return 0; - - - } else if (cd->cnv_dmap->codingSchema == DMAP_E28) { - /* use uchar * instead of UniChar to avoid memcpy */ - register uchar * dmapE02U=(uchar *) (cd->cnv_dmap->dmapE02U); - register uchar * dmapE12U=(uchar *) (cd->cnv_dmap->dmapE12U); - register uchar * dmapE22U=(uchar *) (cd->cnv_dmap->dmapE22U); - register uchar * dmapE32U=(uchar *) (cd->cnv_dmap->dmapE32U); - register int inLen=*inBytesLeft; - register char * pOut=*outBuf; - register char * pIn=*inBuf; - register int offset; - register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; - register size_t numS=0; - register UniChar in; /* copy part of U28 */ - register UniChar ucs2; - while (0 < inLen) { - if (pLastOutBuf < pOut) - break; - if (*pIn == 0x00) { - *pOut=0x00; - ++pOut; - ++pIn; - --inLen; - } else { - if (*pIn == 0x8E) { /* SS2 */ - if (inLen < 2) { - if (cd->fromCcsid == 33722 || /* IBM-eucJP */ - cd->fromCcsid == 964) /* IBM-eucTW */ - errno=EINVAL; /* 22 */ - else - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - return -1; - } - ++pIn; - if (*pIn < 0xA0) { - if (cd->fromCcsid == 964) /* IBM-eucTW */ - errno=EINVAL; /* 22 */ - else - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-1; - return -1; - } - offset=(*pIn - 0xA0); - offset<<=1; - if (dmapE22U[offset] == 0x00 && - dmapE22U[offset+1] == 0x00) { /* 2 bytes */ - if (inLen < 3) { - if (cd->fromCcsid == 964) /* IBM-eucTW */ - errno=EINVAL; /* 22 */ - else - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-1; - return -1; - } - offset=(*pIn - 0xA0) * 0x60 + 0x60; - ++pIn; - if (*pIn < 0xA0) { - if (cd->fromCcsid == 964) /* IBM-eucTW */ - errno=EINVAL; /* 22 */ - else - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-2; - return -1; - } - offset+=(*pIn - 0xA0); - offset<<=1; - if (dmapE22U[offset] == 0x00 && - dmapE22U[offset+1] == 0x00) { - if (cd->fromCcsid == 964) /* IBM-eucTW */ - errno=EINVAL; /* 22 */ - else - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-2; - return -1; - } - in=dmapE22U[offset]; - in<<=8; - in+=dmapE22U[offset+1]; - if (dmapE22U[offset] == 0xFF && - dmapE22U[offset+1] == 0xFD) { - if (pIn[-2] * 0x100 + pIn[-1] != cd->srcSubD) - ++numS; - } - ++pIn; - inLen-=3; - } else { /* 1 bytes */ - in=dmapE22U[offset]; - in<<=8; - in+=dmapE22U[offset+1]; - ++pIn; - inLen-=2; - } - } else if (*pIn == 0x8F) { /* SS3 */ - if (inLen < 2) { - if (cd->fromCcsid == 33722) /* IBM-eucJP */ - errno=EINVAL; /* 22 */ - else - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - return -1; - } - ++pIn; - if (*pIn < 0xA0) { - if (cd->fromCcsid == 970 || /* IBM-eucKR */ - cd->fromCcsid == 964 || /* IBM-eucTW */ - cd->fromCcsid == 1383 || /* IBM-eucCN */ - (cd->fromCcsid == 33722 && 3 <= inLen)) /* IBM-eucJP */ - errno=EILSEQ; /* 116 */ - else - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-1; - return -1; - } - offset=(*pIn - 0xA0); - offset<<=1; - if (dmapE32U[offset] == 0x00 && - dmapE32U[offset+1] == 0x00) { /* 0x8F + 2 bytes */ - if (inLen < 3) { - if (cd->fromCcsid == 33722) - errno=EINVAL; /* 22 */ - else - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-1; - return -1; - } - offset=(*pIn - 0xA0) * 0x60 + 0x60; - ++pIn; - if (*pIn < 0xA0) { - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-2; - return -1; - } - offset+=(*pIn - 0xA0); - offset<<=1; - if (dmapE32U[offset] == 0x00 && - dmapE32U[offset+1] == 0x00) { - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-2; - return -1; - } - in=dmapE32U[offset]; - in<<=8; - in+=dmapE32U[offset+1]; - if (dmapE32U[offset] == 0xFF && - dmapE32U[offset+1] == 0xFD) { - if (pIn[-2] * 0x100 + pIn[-1] != cd->srcSubD) - ++numS; - } - ++pIn; - inLen-=3; - } else { /* 0x8F + 1 bytes */ - in=dmapE32U[offset]; - in<<=8; - in+=dmapE32U[offset+1]; - ++pIn; - inLen-=2; - } - - } else { - offset=*pIn; - offset<<=1; - if (dmapE02U[offset] == 0x00 && - dmapE02U[offset+1] == 0x00) { /* SS1 */ - if (inLen < 2) { - if ((cd->fromCcsid == 33722 && (*pIn == 0xA0 || (0xA9 <= *pIn && *pIn <= 0xAF) || *pIn == 0xFF)) || - (cd->fromCcsid == 970 && (*pIn == 0xA0 || *pIn == 0xAD || *pIn == 0xAE || *pIn == 0xAF || *pIn == 0xFF)) || - (cd->fromCcsid == 964 && (*pIn == 0xA0 || (0xAA <= *pIn && *pIn <= 0xC1) || *pIn == 0xC3 || *pIn == 0xFE || *pIn == 0xFF)) || - (cd->fromCcsid == 1383 && (*pIn == 0xA0 || *pIn == 0xFF))) - errno=EILSEQ; /* 116 */ - else - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - return -1; - } - if (*pIn < 0xA0) { - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - return -1; - } - offset=(*pIn - 0xA0) * 0x60; - ++pIn; - if (*pIn < 0xA0) { - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-1; - return -1; - } - offset+=(*pIn - 0xA0); - offset<<=1; - if (dmapE12U[offset] == 0x00 && - dmapE12U[offset+1] == 0x00) { /* undefined mapping */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-1; - return -1; - } - in=dmapE12U[offset]; - in<<=8; - in+=dmapE12U[offset+1]; - if (dmapE12U[offset] == 0xFF && - dmapE12U[offset+1] == 0xFD) { - if (pIn[-1] * 0x100 + pIn[0] != cd->srcSubD) - ++numS; - } - ++pIn; - inLen-=2; - } else { - in=dmapE02U[offset]; - in<<=8; - in+=dmapE02U[offset+1]; - if (dmapE02U[offset] == 0x00 && - dmapE02U[offset+1] == 0x1A) { - if (*pIn != cd->srcSubS) - ++numS; - } - ++pIn; - --inLen; - } - } - ucs2=in; - if ((in & 0xFF80) == 0x0000) { /* U28: in & 0b1111111110000000 == 0x0000 */ - *pOut=in; - ++pOut; - } else if ((in & 0xF800) == 0x0000) { /* in & 0b1111100000000000 == 0x0000 */ - register uchar byte; - in>>=6; - in&=0x001F; /* 0b0000000000011111 */ - in|=0x00C0; /* 0b0000000011000000 */ - *pOut=in; - ++pOut; - byte=ucs2; /* dmapD12U[offset+1]; */ - byte&=0x3F; /* 0b00111111; */ - byte|=0x80; /* 0b10000000; */ - *pOut=byte; - ++pOut; - } else if ((in & 0xFC00) == 0xD800) { - *pOut=0xEF; - ++pOut; - *pOut=0xBF; - ++pOut; - *pOut=0xBD; - ++pOut; - } else { - register uchar byte; - register uchar work; - byte=(ucs2>>8); /* dmapD12U[offset]; */ - byte>>=4; - byte|=0xE0; /* 0b11100000; */ - *pOut=byte; - ++pOut; - - byte=(ucs2>>8); /* dmapD12U[offset]; */ - byte<<=2; - work=ucs2; /* dmapD12U[offset+1]; */ - work>>=6; - byte|=work; - byte&=0x3F; /* 0b00111111; */ - byte|=0x80; /* 0b10000000; */ - *pOut=byte; - ++pOut; - - byte=ucs2; /* dmapD12U[offset+1]; */ - byte&=0x3F; /* 0b00111111; */ - byte|=0x80; /* 0b10000000; */ - *pOut=byte; - ++pOut; - } - /* end of U28 */ - } - } - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return 0; - - } else if (cd->cnv_dmap->codingSchema == DMAP_U2E) { - register uchar * dmapU2S=cd->cnv_dmap->dmapU2S; - register uchar * dmapU2M2=cd->cnv_dmap->dmapU2M2 - 0x80 * 2; - register uchar * dmapU2M3=cd->cnv_dmap->dmapU2M3 - 0x80 * 3; - register int inLen=*inBytesLeft; - register char * pOut=*outBuf; - register char * pIn=*inBuf; - register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; - register char subS=cd->subS; - register char * pSubD=(char *) &(cd->subD); - register size_t numS=0; - register size_t rc=0; - while (0 < inLen) { - register uint32_t in; - if (inLen == 1) { - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - return -1; - } - if (pLastOutBuf < pOut) - break; - in=pIn[0]; - in<<=8; - in+=pIn[1]; - if (in == 0x0000) { - *pOut=0x00; - ++pOut; - } else if (in < 0x100 && dmapU2S[in] != 0x0000) { - if ((*pOut=dmapU2S[in]) == subS) { - if (in != cd->srcSubS) - ++numS; - } - ++pOut; - } else { - in<<=1; - if (dmapU2M2[in] == 0x00) { /* not found in dmapU2M2 */ - in*=1.5; - if (dmapU2M3[in] == 0x00) { /* not found in dmapU2M3*/ - *pOut=pSubD[0]; - ++pOut; - *pOut=pSubD[1]; - ++pOut; - ++numS; - ++rc; - } else { - *pOut=dmapU2M3[in]; - ++pOut; - *pOut=dmapU2M3[1+in]; - ++pOut; - *pOut=dmapU2M3[2+in]; - ++pOut; - } - } else { - *pOut=dmapU2M2[in]; - ++pOut; - if (dmapU2M2[1+in] == 0x00) { - if (*pOut == subS) { - in>>=1; - if (in != cd->srcSubS) - ++numS; - } - } else { - *pOut=dmapU2M2[1+in]; - ++pOut; - if (memcmp(pOut-2, pSubD, 2) == 0) { - in>>=1; - if (in != cd->srcSubD) { - ++numS; - ++rc; - } - } - } - } - } - pIn+=2; - inLen-=2; - } - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return rc; /* compatibility to iconv() */ - - } else if (cd->cnv_dmap->codingSchema == DMAP_T2E) { - register uchar * dmapU2S=cd->cnv_dmap->dmapU2S; - register uchar * dmapU2M2=cd->cnv_dmap->dmapU2M2 - 0x80 * 2; - register uchar * dmapU2M3=cd->cnv_dmap->dmapU2M3 - 0x80 * 3; - register int inLen=*inBytesLeft; - register char * pOut=*outBuf; - register char * pIn=*inBuf; - register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; - register char subS=cd->subS; - register char * pSubD=(char *) &(cd->subD); - register size_t numS=0; - register size_t rc=0; - while (0 < inLen) { - register uint32_t in; - if (inLen == 1) { - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen-1; - *outBuf=pOut; - *inBuf=pIn; - ++numS; - *numSub+=numS; - return 0; - } - if (pLastOutBuf < pOut) - break; - in=pIn[0]; - in<<=8; - in+=pIn[1]; - if (in == 0x0000) { - *pOut=0x00; - ++pOut; - } else if (0xD800 <= in && in <= 0xDBFF) { /* first byte of surrogate */ - errno=EINVAL; /* 22 */ - *inBytesLeft=inLen-2; - *outBytesLeft-=(pOut-*outBuf); - *outBuf=pOut; - *inBuf=pIn+2; - ++numS; - *numSub+=numS; - return -1; - - } else if (0xDC00 <= in && in <= 0xDFFF) { /* second byte of surrogate */ - errno=EINVAL; /* 22 */ - *inBytesLeft=inLen-1; - *outBytesLeft-=(pOut-*outBuf); - *outBuf=pOut; - *inBuf=pIn; - ++numS; - *numSub+=numS; - return -1; - - } else if (in < 0x100 && dmapU2S[in] != 0x0000) { - if ((*pOut=dmapU2S[in]) == subS) { - if (in != cd->srcSubS) - ++numS; - } - ++pOut; - } else { - in<<=1; - if (dmapU2M2[in] == 0x00) { /* not found in dmapU2M2 */ - in*=1.5; - if (dmapU2M3[in] == 0x00) { /* not found in dmapU2M3*/ - *pOut=pSubD[0]; - ++pOut; - *pOut=pSubD[1]; - ++pOut; - ++numS; - ++rc; - } else { - *pOut=dmapU2M3[in]; - ++pOut; - *pOut=dmapU2M3[1+in]; - ++pOut; - *pOut=dmapU2M3[2+in]; - ++pOut; - } - } else { - *pOut=dmapU2M2[in]; - ++pOut; - if (dmapU2M2[1+in] == 0x00) { - if (*pOut == subS) { - in>>=1; - if (in != cd->srcSubS) - ++numS; - } - } else { - *pOut=dmapU2M2[1+in]; - ++pOut; - if (memcmp(pOut-2, pSubD, 2) == 0) { - in>>=1; - if (in != cd->srcSubD) { - ++numS; - ++rc; - } - } - } - } - } - pIn+=2; - inLen-=2; - } - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return 0; - - } else if (cd->cnv_dmap->codingSchema == DMAP_82E) { - register uchar * dmapU2S=cd->cnv_dmap->dmapU2S; - register uchar * dmapU2M2=cd->cnv_dmap->dmapU2M2 - 0x80 * 2; - register uchar * dmapU2M3=cd->cnv_dmap->dmapU2M3 - 0x80 * 3; - register int inLen=*inBytesLeft; - register char * pOut=*outBuf; - register char * pIn=*inBuf; - register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; - register char subS=cd->subS; - register char * pSubD=(char *) &(cd->subD); - register size_t numS=0; - register size_t rc=0; - while (0 < inLen) { - register uint32_t in; - uint32_t in2; - if (pLastOutBuf < pOut) - break; - /* convert from UTF-8 to UCS-2 */ - if (*pIn == 0x00) { - in=0x0000; - ++pIn; - --inLen; - } else { /* 82U: */ - register uchar byte1=*pIn; - if ((byte1 & 0x80) == 0x00) { /* if (byte1 & 0b10000000 == 0b00000000) { */ - /* 1 bytes sequence: 0xxxxxxx => 00000000 0xxxxxxx*/ - in=byte1; - ++pIn; - --inLen; - } else if ((byte1 & 0xE0) == 0xC0) { /* (byte1 & 0b11100000 == 0b11000000) { */ - if (inLen < 2) { - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - if (byte1 == 0xC0 || byte1 == 0xC1) { /* invalid sequence */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - /* 2 bytes sequence: - 110yyyyy 10xxxxxx => 00000yyy yyxxxxxx */ - register uchar byte2; - ++pIn; - byte2=*pIn; - if ((byte2 & 0xC0) == 0x80) { /* byte2 & 0b11000000 == 0b10000000) { */ - register uchar work=byte1; - work<<=6; - byte2&=0x3F; /* 0b00111111; */ - byte2|=work; - - byte1&=0x1F; /* 0b00011111; */ - byte1>>=2; - in=byte1; - in<<=8; - in+=byte2; - inLen-=2; - ++pIn; - } else { /* invalid sequence */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-1; - *numSub+=numS; - return -1; - } - } else if ((byte1 & 0xF0) == 0xE0) { /* byte1 & 0b11110000 == 0b11100000 */ - /* 3 bytes sequence: - 1110zzzz 10yyyyyy 10xxxxxx => zzzzyyyy yyxxxxxx */ - register uchar byte2; - register uchar byte3; - if (inLen < 3) { - if (inLen == 2 && (pIn[1] & 0xC0) != 0x80) - errno=EILSEQ; /* 116 */ - else - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - ++pIn; - byte2=*pIn; - ++pIn; - byte3=*pIn; - if ((byte2 & 0xC0) != 0x80 || - (byte3 & 0xC0) != 0x80 || - (byte1 == 0xE0 && byte2 < 0xA0)) { /* invalid sequence, only 0xA0-0xBF allowed after 0xE0 */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-2; - *numSub+=numS; - return -1; - } - { - register uchar work=byte2; - work<<=6; - byte3&=0x3F; /* 0b00111111; */ - byte3|=work; - - byte2&=0x3F; /* 0b00111111; */ - byte2>>=2; - - byte1<<=4; - in=byte1 | byte2;; - in<<=8; - in+=byte3; - inLen-=3; - ++pIn; - } - } else if ((0xF0 <= byte1 && byte1 <= 0xF4)) { /* (bytes1 & 11111000) == 0x1110000 */ - /* 4 bytes sequence - 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx => 110110ww wwzzzzyy 110111yy yyxxxxxx - where uuuuu = wwww + 1 */ - register uchar byte2; - register uchar byte3; - register uchar byte4; - if (inLen < 4) { - if ((inLen >= 2 && (pIn[1] & 0xC0) != 0x80) || - (inLen >= 3 && (pIn[2] & 0xC0) != 0x80) || - (cd->toCcsid == 13488) ) - errno=EILSEQ; /* 116 */ - else - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - ++pIn; - byte2=*pIn; - ++pIn; - byte3=*pIn; - ++pIn; - byte4=*pIn; - if ((byte2 & 0xC0) == 0x80 && /* byte2 & 0b11000000 == 0b10000000 */ - (byte3 & 0xC0) == 0x80 && /* byte3 & 0b11000000 == 0b10000000 */ - (byte4 & 0xC0) == 0x80) { /* byte4 & 0b11000000 == 0b10000000 */ - register uchar work=byte2; - if (byte1 == 0xF0 && byte2 < 0x90) { - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-3; - *numSub+=numS; - return -1; - /* iconv() returns 0 for 0xF4908080 and convert to 0x00 - } else if (byte1 == 0xF4 && byte2 > 0x8F) { - errno=EINVAL; - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-3; - *numSub+=numS; - return -1; - */ - } - - work&=0x30; /* 0b00110000; */ - work>>=4; - byte1&=0x07; /* 0b00000111; */ - byte1<<=2; - byte1+=work; /* uuuuu */ - --byte1; /* wwww */ - - work=byte1 & 0x0F; - work>>=2; - work+=0xD8; /* 0b11011011; */ - in=work; - in<<=8; - - byte1<<=6; - byte2<<=2; - byte2&=0x3C; /* 0b00111100; */ - work=byte3; - work>>=4; - work&=0x03; /* 0b00000011; */ - work|=byte1; - work|=byte2; - in+=work; - - work=byte3; - work>>=2; - work&=0x03; /* 0b00000011; */ - work|=0xDC; /* 0b110111xx; */ - in2=work; - in2<<=8; - - byte3<<=6; - byte4&=0x3F; /* 0b00111111; */ - byte4|=byte3; - in2+=byte4; - inLen-=4; - ++pIn; -#ifdef match_with_GBK - if ((0xD800 == in && in2 < 0xDC80) || - (0xD840 == in && in2 < 0xDC80) || - (0xD880 == in && in2 < 0xDC80) || - (0xD8C0 == in && in2 < 0xDC80) || - (0xD900 == in && in2 < 0xDC80) || - (0xD940 == in && in2 < 0xDC80) || - (0xD980 == in && in2 < 0xDC80) || - (0xD9C0 == in && in2 < 0xDC80) || - (0xDA00 == in && in2 < 0xDC80) || - (0xDA40 == in && in2 < 0xDC80) || - (0xDA80 == in && in2 < 0xDC80) || - (0xDAC0 == in && in2 < 0xDC80) || - (0xDB00 == in && in2 < 0xDC80) || - (0xDB40 == in && in2 < 0xDC80) || - (0xDB80 == in && in2 < 0xDC80) || - (0xDBC0 == in && in2 < 0xDC80)) { -#else - if ((0xD800 <= in && in <= 0xDBFF) && - (0xDC00 <= in2 && in2 <= 0xDFFF)) { -#endif - *pOut=subS; - ++pOut; - ++numS; - continue; - } - } else { /* invalid sequence */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-3; - *numSub+=numS; - return -1; - } - } else if (0xF5 <= byte1 && byte1 <= 0xFF) { /* minic iconv() behavior */ - if (inLen < 4 || - (inLen >= 4 && byte1 == 0xF8 && pIn[1] < 0x90) || - pIn[1] < 0x80 || 0xBF < pIn[1] || - pIn[2] < 0x80 || 0xBF < pIn[2] || - pIn[3] < 0x80 || 0xBF < pIn[3] ) { - if (inLen == 1) - errno=EINVAL; /* 22 */ - else if (inLen == 2 && (pIn[1] & 0xC0) != 0x80) - errno=EILSEQ; /* 116 */ - else if (inLen == 3 && ((pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80)) - errno=EILSEQ; /* 116 */ - else if (inLen >= 4 && (byte1 == 0xF8 || (pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80 || (pIn[3] & 0xC0) != 0x80)) - errno=EILSEQ; /* 116 */ - else - errno=EINVAL; /* 22 */ - - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } else if ((pIn[1] == 0x80 || pIn[1] == 0x90 || pIn[1] == 0xA0 || pIn[1] == 0xB0) && - pIn[2] < 0x82) { - *pOut=subS; /* Though returns replacement character, which iconv() does not return. */ - ++pOut; - ++numS; - pIn+=4; - inLen-=4; - continue; - } else { - *pOut=pSubD[0]; /* Though returns replacement character, which iconv() does not return. */ - ++pOut; - *pOut=pSubD[1]; - ++pOut; - ++numS; - pIn+=4; - inLen-=4; - continue; - /* iconv() returns 0 with strange 1 byte converted values */ - } - - } else { /* invalid sequence */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - } - /* end of UTF-8 to UCS-2 */ - if (in == 0x0000) { - *pOut=0x00; - ++pOut; - } else if (in < 0x100 && dmapU2S[in] != 0x0000) { - if ((*pOut=dmapU2S[in]) == subS) { - if (in != cd->srcSubS) - ++numS; - } - ++pOut; - } else { - in<<=1; - if (dmapU2M2[in] == 0x00) { /* not found in dmapU2M2 */ - in*=1.5; - if (dmapU2M3[in] == 0x00) { /* not found in dmapU2M3*/ - *pOut=pSubD[0]; - ++pOut; - *pOut=pSubD[1]; - ++pOut; - ++numS; - ++rc; - } else { - *pOut=dmapU2M3[in]; - ++pOut; - *pOut=dmapU2M3[1+in]; - ++pOut; - *pOut=dmapU2M3[2+in]; - ++pOut; - } - } else { - *pOut=dmapU2M2[in]; - ++pOut; - if (dmapU2M2[1+in] == 0x00) { - if (*pOut == subS) { - in>>=1; - if (in != cd->srcSubS) - ++numS; - } - } else { - *pOut=dmapU2M2[1+in]; - ++pOut; - if (memcmp(pOut-2, pSubD, 2) == 0) { - in>>=1; - if (in != cd->srcSubD) { - ++numS; - ++rc; - } - } - } - } - } - } - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return 0; - - } else if (cd->cnv_dmap->codingSchema == DMAP_S2U) { - /* use uchar * instead of UniChar to avoid memcpy */ - register uchar * dmapD12U=(uchar *) (cd->cnv_dmap->dmapD12U); - register int inLen=*inBytesLeft; - register char * pOut=*outBuf; - register char * pIn=*inBuf; - register int offset; - register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; - register size_t numS=0; - while (0 < inLen) { - if (pLastOutBuf < pOut) - break; - if (*pIn == 0x00) { - *pOut=0x00; - ++pOut; - *pOut=0x00; - ++pOut; - ++pIn; - --inLen; - } else { - offset=*pIn; - offset<<=1; - *pOut=dmapD12U[offset]; - ++pOut; - *pOut=dmapD12U[offset+1]; - ++pOut; - if (dmapD12U[offset] == 0x00) { - if (dmapD12U[offset+1] == 0x1A) { - if (*pIn != cd->srcSubS) - ++numS; - } else if (dmapD12U[offset+1] == 0x00) { - pOut-=2; - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - } - ++pIn; - --inLen; - } - } - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return 0; - - } else if (cd->cnv_dmap->codingSchema == DMAP_S28) { - /* use uchar * instead of UniChar to avoid memcpy */ - register uchar * dmapD12U=(uchar *) (cd->cnv_dmap->dmapD12U); - register int inLen=*inBytesLeft; - register char * pOut=*outBuf; - register char * pIn=*inBuf; - register int offset; - register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; - register size_t numS=0; - register UniChar in; /* copy part of U28 */ - while (0 < inLen) { - if (pLastOutBuf < pOut) - break; - if (*pIn == 0x00) { - *pOut=0x00; - ++pOut; - ++pIn; - --inLen; - } else { - offset=*pIn; - offset<<=1; - in=dmapD12U[offset]; - in<<=8; - in+=dmapD12U[offset+1]; - if ((in & 0xFF80) == 0x0000) { /* U28: in & 0b1111111110000000 == 0x0000 */ - if (in == 0x000) { - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - *pOut=in; - ++pOut; - } else if ((in & 0xF800) == 0x0000) { /* in & 0b1111100000000000 == 0x0000 */ - register uchar byte; - in>>=6; - in&=0x001F; /* 0b0000000000011111 */ - in|=0x00C0; /* 0b0000000011000000 */ - *pOut=in; - ++pOut; - byte=dmapD12U[offset+1]; - byte&=0x3F; /* 0b00111111; */ - byte|=0x80; /* 0b10000000; */ - *pOut=byte; - ++pOut; - } else if ((in & 0xFC00) == 0xD800) { /* There should not be no surrogate character in SBCS. */ - *pOut=0xEF; - ++pOut; - *pOut=0xBF; - ++pOut; - *pOut=0xBD; - ++pOut; - } else { - register uchar byte; - register uchar work; - byte=dmapD12U[offset]; - byte>>=4; - byte|=0xE0; /* 0b11100000; */ - *pOut=byte; - ++pOut; - - byte=dmapD12U[offset]; - byte<<=2; - work=dmapD12U[offset+1]; - work>>=6; - byte|=work; - byte&=0x3F; /* 0b00111111; */ - byte|=0x80; /* 0b10000000; */ - *pOut=byte; - ++pOut; - - byte=dmapD12U[offset+1]; - byte&=0x3F; /* 0b00111111; */ - byte|=0x80; /* 0b10000000; */ - *pOut=byte; - ++pOut; - } - /* end of U28 */ - if (dmapD12U[offset] == 0x00) { - if (dmapD12U[offset+1] == 0x1A) { - if (*pIn != cd->srcSubS) - ++numS; - } - } - ++pIn; - --inLen; - } - } - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return 0; - - } else if (cd->cnv_dmap->codingSchema == DMAP_U2S) { - register uchar * dmapU2S=cd->cnv_dmap->dmapU2S; - register int inLen=*inBytesLeft; - register char * pOut=*outBuf; - register char * pIn=*inBuf; - register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; - register char subS=cd->subS; - register size_t numS=0; - while (0 < inLen) { - register uint32_t in; - if (inLen == 1) { - errno=EINVAL; /* 22 */ - - *inBytesLeft=inLen; - *outBytesLeft-=(pOut-*outBuf); - *outBuf=pOut; - *inBuf=pIn; - return -1; - } - if (pLastOutBuf < pOut) - break; - in=pIn[0]; - in<<=8; - in+=pIn[1]; - if (in == 0x0000) { - *pOut=0x00; - } else { - if ((*pOut=dmapU2S[in]) == 0x00) { - *pOut=subS; - ++numS; - errno=EINVAL; /* 22 */ - } else if (*pOut == subS) { - if (in != cd->srcSubS) - ++numS; - } - } - ++pOut; - pIn+=2; - inLen-=2; - } - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return numS; - - } else if (cd->cnv_dmap->codingSchema == DMAP_T2S) { - register uchar * dmapU2S=cd->cnv_dmap->dmapU2S; - register int inLen=*inBytesLeft; - register char * pOut=*outBuf; - register char * pIn=*inBuf; - register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; - register char subS=cd->subS; - register size_t numS=0; - while (0 < inLen) { - register uint32_t in; - if (inLen == 1) { - errno=EINVAL; /* 22 */ - - *inBytesLeft=inLen-1; - *outBytesLeft-=(pOut-*outBuf); - *outBuf=pOut; - *inBuf=pIn; - ++numS; - *numSub+=numS; - return 0; - } - if (pLastOutBuf < pOut) - break; - in=pIn[0]; - in<<=8; - in+=pIn[1]; - if (in == 0x0000) { - *pOut=0x00; - - } else if (0xD800 <= in && in <= 0xDFFF) { /* 0xD800-0xDFFF, surrogate first and second values */ - if (0xDC00 <= in ) { - errno=EINVAL; /* 22 */ - *inBytesLeft=inLen-1; - *outBytesLeft-=(pOut-*outBuf); - *outBuf=pOut; - *inBuf=pIn; - return -1; - - } else if (inLen < 4) { - errno=EINVAL; /* 22 */ - *inBytesLeft=inLen-2; - *outBytesLeft-=(pOut-*outBuf); - *outBuf=pOut; - *inBuf=pIn+2; - return -1; - - } else { - register uint32_t in2; - in2=pIn[2]; - in2<<=8; - in2+=pIn[3]; - if (0xDC00 <= in2 && in2 <= 0xDFFF) { /* second surrogate character =0xDC00 - 0xDFFF*/ - *pOut=subS; - ++numS; - pIn+=4; - } else { - errno=EINVAL; /* 22 */ - *inBytesLeft=inLen-1; - *outBytesLeft-=(pOut-*outBuf); - *outBuf=pOut; - *inBuf=pIn; - return -1; - } - } - } else { - if ((*pOut=dmapU2S[in]) == 0x00) { - *pOut=subS; - ++numS; - errno=EINVAL; /* 22 */ - } else if (*pOut == subS) { - if (in != cd->srcSubS) - ++numS; - } - } - ++pOut; - pIn+=2; - inLen-=2; - } - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return 0; - - } else if (cd->cnv_dmap->codingSchema == DMAP_82S) { - register uchar * dmapU2S=cd->cnv_dmap->dmapU2S; - register int inLen=*inBytesLeft; - register char * pOut=*outBuf; - register char * pIn=*inBuf; - register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; - register char subS=cd->subS; - register size_t numS=0; - while (0 < inLen) { - register uint32_t in; - uint32_t in2; /* The second surrogate value */ - if (pLastOutBuf < pOut) - break; - /* convert from UTF-8 to UCS-2 */ - if (*pIn == 0x00) { - in=0x0000; - ++pIn; - --inLen; - } else { /* 82U: */ - register uchar byte1=*pIn; - if ((byte1 & 0x80) == 0x00) { /* if (byte1 & 0b10000000 == 0b00000000) { */ - /* 1 bytes sequence: 0xxxxxxx => 00000000 0xxxxxxx*/ - in=byte1; - ++pIn; - --inLen; - } else if ((byte1 & 0xE0) == 0xC0) { /* (byte1 & 0b11100000 == 0b11000000) { */ - if (inLen < 2) { - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - if (byte1 == 0xC0 || byte1 == 0xC1) { /* invalid sequence */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - /* 2 bytes sequence: - 110yyyyy 10xxxxxx => 00000yyy yyxxxxxx */ - register uchar byte2; - ++pIn; - byte2=*pIn; - if ((byte2 & 0xC0) == 0x80) { /* byte2 & 0b11000000 == 0b10000000) { */ - register uchar work=byte1; - work<<=6; - byte2&=0x3F; /* 0b00111111; */ - byte2|=work; - - byte1&=0x1F; /* 0b00011111; */ - byte1>>=2; - in=byte1; - in<<=8; - in+=byte2; - inLen-=2; - ++pIn; - } else { /* invalid sequence */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-1; - *numSub+=numS; - return -1; - } - } else if ((byte1 & 0xF0) == 0xE0) { /* byte1 & 0b11110000 == 0b11100000 */ - /* 3 bytes sequence: - 1110zzzz 10yyyyyy 10xxxxxx => zzzzyyyy yyxxxxxx */ - register uchar byte2; - register uchar byte3; - if (inLen < 3) { - if (inLen == 2 && (pIn[1] & 0xC0) != 0x80) - errno=EILSEQ; /* 116 */ - else - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - ++pIn; - byte2=*pIn; - ++pIn; - byte3=*pIn; - if ((byte2 & 0xC0) != 0x80 || - (byte3 & 0xC0) != 0x80 || - (byte1 == 0xE0 && byte2 < 0xA0)) { /* invalid sequence, only 0xA0-0xBF allowed after 0xE0 */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-2; - *numSub+=numS; - return -1; - } - { - register uchar work=byte2; - work<<=6; - byte3&=0x3F; /* 0b00111111; */ - byte3|=work; - - byte2&=0x3F; /* 0b00111111; */ - byte2>>=2; - - byte1<<=4; - in=byte1 | byte2;; - in<<=8; - in+=byte3; - inLen-=3; - ++pIn; - } - } else if ((0xF0 <= byte1 && byte1 <= 0xF4) || /* (bytes1 & 11111000) == 0x1110000 */ - ((byte1&=0xF7) && 0xF0 <= byte1 && byte1 <= 0xF4)) { /* minic iconv() behavior */ - /* 4 bytes sequence - 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx => 110110ww wwzzzzyy 110111yy yyxxxxxx - where uuuuu = wwww + 1 */ - register uchar byte2; - register uchar byte3; - register uchar byte4; - if (inLen < 4) { - if ((inLen >= 2 && (pIn[1] & 0xC0) != 0x80) || - (inLen >= 3 && (pIn[2] & 0xC0) != 0x80) || - (cd->toCcsid == 13488) ) - errno=EILSEQ; /* 116 */ - else - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - ++pIn; - byte2=*pIn; - ++pIn; - byte3=*pIn; - ++pIn; - byte4=*pIn; - if ((byte2 & 0xC0) == 0x80 && /* byte2 & 0b11000000 == 0b10000000 */ - (byte3 & 0xC0) == 0x80 && /* byte3 & 0b11000000 == 0b10000000 */ - (byte4 & 0xC0) == 0x80) { /* byte4 & 0b11000000 == 0b10000000 */ - register uchar work=byte2; - if (byte1 == 0xF0 && byte2 < 0x90) { - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-3; - *numSub+=numS; - return -1; - /* iconv() returns 0 for 0xF4908080 and convert to 0x00 - } else if (byte1 == 0xF4 && byte2 > 0x8F) { - errno=EINVAL; - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-3; - *numSub+=numS; - return -1; - */ - } - - work&=0x30; /* 0b00110000; */ - work>>=4; - byte1&=0x07; /* 0b00000111; */ - byte1<<=2; - byte1+=work; /* uuuuu */ - --byte1; /* wwww */ - - work=byte1 & 0x0F; - work>>=2; - work+=0xD8; /* 0b11011011; */ - in=work; - in<<=8; - - byte1<<=6; - byte2<<=2; - byte2&=0x3C; /* 0b00111100; */ - work=byte3; - work>>=4; - work&=0x03; /* 0b00000011; */ - work|=byte1; - work|=byte2; - in+=work; - - work=byte3; - work>>=2; - work&=0x03; /* 0b00000011; */ - work|=0xDC; /* 0b110111xx; */ - in2=work; - in2<<=8; - - byte3<<=6; - byte4&=0x3F; /* 0b00111111; */ - byte4|=byte3; - in2+=byte4; - inLen-=4; - ++pIn; - } else { /* invalid sequence */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-3; - *numSub+=numS; - return -1; - } - } else if ((byte1 & 0xF0) == 0xF0) { /* minic iconv() behavior */ - if (inLen < 4 || - pIn[1] < 0x80 || 0xBF < pIn[1] || - pIn[2] < 0x80 || 0xBF < pIn[2] || - pIn[3] < 0x80 || 0xBF < pIn[3] ) { - if (inLen == 1) - errno=EINVAL; /* 22 */ - else if (inLen == 2 && (pIn[1] & 0xC0) != 0x80) - errno=EILSEQ; /* 116 */ - else if (inLen == 3 && ((pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80)) - errno=EILSEQ; /* 116 */ - else if (inLen >= 4 && ((pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80 || (pIn[3] & 0xC0) != 0x80)) - errno=EILSEQ; /* 116 */ - else - errno=EINVAL; /* 22 */ - - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } else { - *pOut=subS; /* Though returns replacement character, which iconv() does not return. */ - ++pOut; - ++numS; - pIn+=4; - inLen-=4; - /* UTF-8_IBM-850 0xF0908080 : converted value does not match, iconv=0x00, dmap=0x7F - UTF-8_IBM-850 0xF0908081 : converted value does not match, iconv=0x01, dmap=0x7F - UTF-8_IBM-850 0xF0908082 : converted value does not match, iconv=0x02, dmap=0x7F - UTF-8_IBM-850 0xF0908083 : converted value does not match, iconv=0x03, dmap=0x7F - .... - UTF-8_IBM-850 0xF09081BE : converted value does not match, iconv=0x7E, dmap=0x7F - UTF-8_IBM-850 0xF09081BF : converted value does not match, iconv=0x1C, dmap=0x7F - UTF-8_IBM-850 0xF09082A0 : converted value does not match, iconv=0xFF, dmap=0x7F - UTF-8_IBM-850 0xF09082A1 : converted value does not match, iconv=0xAD, dmap=0x7F - .... - */ - continue; - /* iconv() returns 0 with strange 1 byte converted values */ - } - - } else { /* invalid sequence */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - } - /* end of UTF-8 to UCS-2 */ - if (in == 0x0000) { - *pOut=0x00; - } else { - if ((*pOut=dmapU2S[in]) == 0x00) { - *pOut=subS; - ++numS; - errno=EINVAL; /* 22 */ - } else if (*pOut == subS) { - if (in != cd->srcSubS) { - ++numS; - } - } - } - ++pOut; - } - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return 0; - - } else if (cd->cnv_dmap->codingSchema == DMAP_D2U) { - /* use uchar * instead of UniChar to avoid memcpy */ - register uchar * dmapD12U=(uchar *) (cd->cnv_dmap->dmapD12U); - register uchar * dmapD22U=(uchar *) (cd->cnv_dmap->dmapD22U); - register int inLen=*inBytesLeft; - register char * pOut=*outBuf; - register char * pIn=*inBuf; - register int offset; - register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; - register size_t numS=0; - while (0 < inLen) { - if (pLastOutBuf < pOut) - break; - if (*pIn == 0x00) { - *pOut=0x00; - ++pOut; - *pOut=0x00; - ++pOut; - ++pIn; - --inLen; - } else { - offset=*pIn; - offset<<=1; - if (dmapD12U[offset] == 0x00 && - dmapD12U[offset+1] == 0x00) { /* DBCS */ - if (inLen < 2) { - if (*pIn == 0x80 || *pIn == 0xFF || - (cd->fromCcsid == 943 && (*pIn == 0x85 || *pIn == 0x86 || *pIn == 0xA0 || *pIn == 0xEB || *pIn == 0xEC || *pIn == 0xEF || *pIn == 0xFD || *pIn == 0xFE)) || - (cd->fromCcsid == 932 && (*pIn == 0x85 || *pIn == 0x86 || *pIn == 0x87 || *pIn == 0xEB || *pIn == 0xEC || *pIn == 0xED || *pIn == 0xEE || *pIn == 0xEF)) || - (cd->fromCcsid == 1381 && ((0x85 <= *pIn && *pIn <= 0x8B) || (0xAA <= *pIn && *pIn <= 0xAF) || (0xF8 <= *pIn && *pIn <= 0xFE)))) - errno=EILSEQ; /* 116 */ - else - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - return -1; - } - offset-=0x100; - ++pIn; - offset<<=8; - offset+=(*pIn * 2); - if (dmapD22U[offset] == 0x00 && - dmapD22U[offset+1] == 0x00) { - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-1; - return -1; - } - *pOut=dmapD22U[offset]; - ++pOut; - *pOut=dmapD22U[offset+1]; - ++pOut; - if (dmapD22U[offset] == 0xFF && - dmapD22U[offset+1] == 0xFD) { - if (pIn[-1] * 0x100 + pIn[0] != cd->srcSubD) - ++numS; - } - ++pIn; - inLen-=2; - } else { /* SBCS */ - *pOut=dmapD12U[offset]; - ++pOut; - *pOut=dmapD12U[offset+1]; - ++pOut; - if (dmapD12U[offset] == 0x00 && - dmapD12U[offset+1] == 0x1A) { - if (*pIn != cd->srcSubS) - ++numS; - } - ++pIn; - --inLen; - } - } - } - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return 0; - - } else if (cd->cnv_dmap->codingSchema == DMAP_D28) { - /* use uchar * instead of UniChar to avoid memcpy */ - register uchar * dmapD12U=(uchar *) (cd->cnv_dmap->dmapD12U); - register uchar * dmapD22U=(uchar *) (cd->cnv_dmap->dmapD22U); - register int inLen=*inBytesLeft; - register char * pOut=*outBuf; - register char * pIn=*inBuf; - register int offset; - register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; - register size_t numS=0; - register UniChar in; /* copy part of U28 */ - register UniChar ucs2; - while (0 < inLen) { - if (pLastOutBuf < pOut) - break; - if (*pIn == 0x00) { - *pOut=0x00; - ++pOut; - ++pIn; - --inLen; - } else { - offset=*pIn; - offset<<=1; - if (dmapD12U[offset] == 0x00 && - dmapD12U[offset+1] == 0x00) { /* DBCS */ - if (inLen < 2) { - if (*pIn == 0x80 || *pIn == 0xFF || - (cd->fromCcsid == 943 && (*pIn == 0x85 || *pIn == 0x86 || *pIn == 0xA0 || *pIn == 0xEB || *pIn == 0xEC || *pIn == 0xEF || *pIn == 0xFD || *pIn == 0xFE)) || - (cd->fromCcsid == 932 && (*pIn == 0x85 || *pIn == 0x86 || *pIn == 0x87 || *pIn == 0xEB || *pIn == 0xEC || *pIn == 0xED || *pIn == 0xEE || *pIn == 0xEF)) || - (cd->fromCcsid == 1381 && ((0x85 <= *pIn && *pIn <= 0x8B) || (0xAA <= *pIn && *pIn <= 0xAF) || (0xF8 <= *pIn && *pIn <= 0xFE)))) - errno=EILSEQ; /* 116 */ - else - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - return -1; - } - offset-=0x100; - ++pIn; - offset<<=8; - offset+=(*pIn * 2); - if (dmapD22U[offset] == 0x00 && - dmapD22U[offset+1] == 0x00) { - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-1; - return -1; - } - in=dmapD22U[offset]; - in<<=8; - in+=dmapD22U[offset+1]; - ucs2=in; - if (dmapD22U[offset] == 0xFF && - dmapD22U[offset+1] == 0xFD) { - if (in != cd->srcSubD) - ++numS; - } - ++pIn; - inLen-=2; - } else { /* SBCS */ - in=dmapD12U[offset]; - in<<=8; - in+=dmapD12U[offset+1]; - ucs2=in; - if (dmapD12U[offset] == 0x00 && - dmapD12U[offset+1] == 0x1A) { - if (in != cd->srcSubS) - ++numS; - } - ++pIn; - --inLen; - } - if ((in & 0xFF80) == 0x0000) { /* U28: in & 0b1111111110000000 == 0x0000 */ - *pOut=in; - ++pOut; - } else if ((in & 0xF800) == 0x0000) { /* in & 0b1111100000000000 == 0x0000 */ - register uchar byte; - in>>=6; - in&=0x001F; /* 0b0000000000011111 */ - in|=0x00C0; /* 0b0000000011000000 */ - *pOut=in; - ++pOut; - byte=ucs2; /* dmapD12U[offset+1]; */ - byte&=0x3F; /* 0b00111111; */ - byte|=0x80; /* 0b10000000; */ - *pOut=byte; - ++pOut; - } else if ((in & 0xFC00) == 0xD800) { /* There should not be no surrogate character in SBCS. */ - *pOut=0xEF; - ++pOut; - *pOut=0xBF; - ++pOut; - *pOut=0xBD; - ++pOut; - } else { - register uchar byte; - register uchar work; - byte=(ucs2>>8); /* dmapD12U[offset]; */ - byte>>=4; - byte|=0xE0; /* 0b11100000; */ - *pOut=byte; - ++pOut; - - byte=(ucs2>>8); /* dmapD12U[offset]; */ - byte<<=2; - work=ucs2; /* dmapD12U[offset+1]; */ - work>>=6; - byte|=work; - byte&=0x3F; /* 0b00111111; */ - byte|=0x80; /* 0b10000000; */ - *pOut=byte; - ++pOut; - - byte=ucs2; /* dmapD12U[offset+1]; */ - byte&=0x3F; /* 0b00111111; */ - byte|=0x80; /* 0b10000000; */ - *pOut=byte; - ++pOut; - } - /* end of U28 */ - } - } - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return 0; - - } else if (cd->cnv_dmap->codingSchema == DMAP_U2D) { - register uchar * dmapU2D=cd->cnv_dmap->dmapU2D; - register int inLen=*inBytesLeft; - register char * pOut=*outBuf; - register char * pIn=*inBuf; - register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; - register char subS=cd->subS; - register char * pSubD=(char *) &(cd->subD); - register size_t numS=0; - while (0 < inLen) { - register uint32_t in; - if (inLen == 1) { - errno=EINVAL; /* 22 */ - - *inBytesLeft=inLen; - *outBytesLeft-=(pOut-*outBuf); - *outBuf=pOut; - *inBuf=pIn; - return -1; - } - if (pLastOutBuf < pOut) - break; - in=pIn[0]; - in<<=8; - in+=pIn[1]; - if (in == 0x0000) { - *pOut=0x00; - ++pOut; - } else { - in<<=1; - *pOut=dmapU2D[in]; - ++pOut; - if (dmapU2D[in+1] == 0x00) { /* SBCS */ - if (*pOut == subS) { - if (in != cd->srcSubS) - ++numS; - } - } else { - *pOut=dmapU2D[in+1]; - ++pOut; - if (dmapU2D[in] == pSubD[0] && - dmapU2D[in+1] == pSubD[1]) { - in>>=1; - if (in != cd->srcSubD) - ++numS; - } - } - } - pIn+=2; - inLen-=2; - } - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return numS; /* to minic iconv() behavior */ - - } else if (cd->cnv_dmap->codingSchema == DMAP_T2D) { - register uchar * dmapU2D=cd->cnv_dmap->dmapU2D; - register int inLen=*inBytesLeft; - register char * pOut=*outBuf; - register char * pIn=*inBuf; - register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; - register char subS=cd->subS; - register char * pSubD=(char *) &(cd->subD); - register size_t numS=0; - while (0 < inLen) { - register uint32_t in; - if (inLen == 1) { - errno=EINVAL; /* 22 */ - *inBytesLeft=inLen-1; - *outBytesLeft-=(pOut-*outBuf); - *outBuf=pOut; - *inBuf=pIn; - ++numS; - *numSub+=numS; - return 0; - } - if (pLastOutBuf < pOut) - break; - in=pIn[0]; - in<<=8; - in+=pIn[1]; - if (in == 0x0000) { - *pOut=0x00; - ++pOut; - } else if (0xD800 <= in && in <= 0xDBFF) { /* first byte of surrogate */ - errno=EINVAL; /* 22 */ - *inBytesLeft=inLen-2; - *outBytesLeft-=(pOut-*outBuf); - *outBuf=pOut; - *inBuf=pIn+2; - ++numS; - *numSub+=numS; - return -1; - - } else if (0xDC00 <= in && in <= 0xDFFF) { /* second byte of surrogate */ - errno=EINVAL; /* 22 */ - *inBytesLeft=inLen-1; - *outBytesLeft-=(pOut-*outBuf); - *outBuf=pOut; - *inBuf=pIn; - ++numS; - *numSub+=numS; - return -1; - - } else { - in<<=1; - *pOut=dmapU2D[in]; - ++pOut; - if (dmapU2D[in+1] == 0x00) { /* SBCS */ - if (*pOut == subS) { - if (in != cd->srcSubS) - ++numS; - } - } else { - *pOut=dmapU2D[in+1]; - ++pOut; - if (dmapU2D[in] == pSubD[0] && - dmapU2D[in+1] == pSubD[1]) { - in>>=1; - if (in != cd->srcSubD) - ++numS; - } - } - } - pIn+=2; - inLen-=2; - } - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return 0; /* to minic iconv() behavior */ - - } else if (cd->cnv_dmap->codingSchema == DMAP_82D) { - register uchar * dmapU2D=cd->cnv_dmap->dmapU2D; - register int inLen=*inBytesLeft; - register char * pOut=*outBuf; - register char * pIn=*inBuf; - register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; - register char subS=cd->subS; - register char * pSubD=(char *) &(cd->subD); - register size_t numS=0; - while (0 < inLen) { - register uint32_t in; - uint32_t in2; - if (pLastOutBuf < pOut) - break; - /* convert from UTF-8 to UCS-2 */ - if (*pIn == 0x00) { - in=0x0000; - ++pIn; - --inLen; - } else { /* 82U: */ - register uchar byte1=*pIn; - if ((byte1 & 0x80) == 0x00) { /* if (byte1 & 0b10000000 == 0b00000000) { */ - /* 1 bytes sequence: 0xxxxxxx => 00000000 0xxxxxxx*/ - in=byte1; - ++pIn; - --inLen; - } else if ((byte1 & 0xE0) == 0xC0) { /* (byte1 & 0b11100000 == 0b11000000) { */ - if (inLen < 2) { - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - if (byte1 == 0xC0 || byte1 == 0xC1) { /* invalid sequence */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - /* 2 bytes sequence: - 110yyyyy 10xxxxxx => 00000yyy yyxxxxxx */ - register uchar byte2; - ++pIn; - byte2=*pIn; - if ((byte2 & 0xC0) == 0x80) { /* byte2 & 0b11000000 == 0b10000000) { */ - register uchar work=byte1; - work<<=6; - byte2&=0x3F; /* 0b00111111; */ - byte2|=work; - - byte1&=0x1F; /* 0b00011111; */ - byte1>>=2; - in=byte1; - in<<=8; - in+=byte2; - inLen-=2; - ++pIn; - } else { /* invalid sequence */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-1; - *numSub+=numS; - return -1; - } - } else if ((byte1 & 0xF0) == 0xE0) { /* byte1 & 0b11110000 == 0b11100000 */ - /* 3 bytes sequence: - 1110zzzz 10yyyyyy 10xxxxxx => zzzzyyyy yyxxxxxx */ - register uchar byte2; - register uchar byte3; - if (inLen < 3) { - if (inLen == 2 && (pIn[1] & 0xC0) != 0x80) - errno=EILSEQ; /* 116 */ - else - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - ++pIn; - byte2=*pIn; - ++pIn; - byte3=*pIn; - if ((byte2 & 0xC0) != 0x80 || - (byte3 & 0xC0) != 0x80 || - (byte1 == 0xE0 && byte2 < 0xA0)) { /* invalid sequence, only 0xA0-0xBF allowed after 0xE0 */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-2; - *numSub+=numS; - return -1; - } - { - register uchar work=byte2; - work<<=6; - byte3&=0x3F; /* 0b00111111; */ - byte3|=work; - - byte2&=0x3F; /* 0b00111111; */ - byte2>>=2; - - byte1<<=4; - in=byte1 | byte2;; - in<<=8; - in+=byte3; - inLen-=3; - ++pIn; - } - } else if ((0xF0 <= byte1 && byte1 <= 0xF4)) { /* (bytes1 & 11111000) == 0x1110000 */ - /* 4 bytes sequence - 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx => 110110ww wwzzzzyy 110111yy yyxxxxxx - where uuuuu = wwww + 1 */ - register uchar byte2; - register uchar byte3; - register uchar byte4; - if (inLen < 4) { - if ((inLen >= 2 && (pIn[1] & 0xC0) != 0x80) || - (inLen >= 3 && (pIn[2] & 0xC0) != 0x80) || - (cd->toCcsid == 13488) ) - errno=EILSEQ; /* 116 */ - else - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - ++pIn; - byte2=*pIn; - ++pIn; - byte3=*pIn; - ++pIn; - byte4=*pIn; - if ((byte2 & 0xC0) == 0x80 && /* byte2 & 0b11000000 == 0b10000000 */ - (byte3 & 0xC0) == 0x80 && /* byte3 & 0b11000000 == 0b10000000 */ - (byte4 & 0xC0) == 0x80) { /* byte4 & 0b11000000 == 0b10000000 */ - register uchar work=byte2; - if (byte1 == 0xF0 && byte2 < 0x90) { - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-3; - *numSub+=numS; - return -1; - /* iconv() returns 0 for 0xF4908080 and convert to 0x00 - } else if (byte1 == 0xF4 && byte2 > 0x8F) { - errno=EINVAL; - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-3; - *numSub+=numS; - return -1; - */ - } - - work&=0x30; /* 0b00110000; */ - work>>=4; - byte1&=0x07; /* 0b00000111; */ - byte1<<=2; - byte1+=work; /* uuuuu */ - --byte1; /* wwww */ - - work=byte1 & 0x0F; - work>>=2; - work+=0xD8; /* 0b11011011; */ - in=work; - in<<=8; - - byte1<<=6; - byte2<<=2; - byte2&=0x3C; /* 0b00111100; */ - work=byte3; - work>>=4; - work&=0x03; /* 0b00000011; */ - work|=byte1; - work|=byte2; - in+=work; - - work=byte3; - work>>=2; - work&=0x03; /* 0b00000011; */ - work|=0xDC; /* 0b110111xx; */ - in2=work; - in2<<=8; - - byte3<<=6; - byte4&=0x3F; /* 0b00111111; */ - byte4|=byte3; - in2+=byte4; - inLen-=4; - ++pIn; -#ifdef match_with_GBK - if ((0xD800 == in && in2 < 0xDC80) || - (0xD840 == in && in2 < 0xDC80) || - (0xD880 == in && in2 < 0xDC80) || - (0xD8C0 == in && in2 < 0xDC80) || - (0xD900 == in && in2 < 0xDC80) || - (0xD940 == in && in2 < 0xDC80) || - (0xD980 == in && in2 < 0xDC80) || - (0xD9C0 == in && in2 < 0xDC80) || - (0xDA00 == in && in2 < 0xDC80) || - (0xDA40 == in && in2 < 0xDC80) || - (0xDA80 == in && in2 < 0xDC80) || - (0xDAC0 == in && in2 < 0xDC80) || - (0xDB00 == in && in2 < 0xDC80) || - (0xDB40 == in && in2 < 0xDC80) || - (0xDB80 == in && in2 < 0xDC80) || - (0xDBC0 == in && in2 < 0xDC80)) { -#else - if ((0xD800 <= in && in <= 0xDBFF) && - (0xDC00 <= in2 && in2 <= 0xDFFF)) { -#endif - *pOut=subS; - ++pOut; - ++numS; - continue; - } - } else { /* invalid sequence */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-3; - *numSub+=numS; - return -1; - } - } else if (0xF5 <= byte1 && byte1 <= 0xFF) { /* minic iconv() behavior */ - if (inLen < 4 || - (inLen >= 4 && byte1 == 0xF8 && pIn[1] < 0x90) || - pIn[1] < 0x80 || 0xBF < pIn[1] || - pIn[2] < 0x80 || 0xBF < pIn[2] || - pIn[3] < 0x80 || 0xBF < pIn[3] ) { - if (inLen == 1) - errno=EINVAL; /* 22 */ - else if (inLen == 2 && (pIn[1] & 0xC0) != 0x80) - errno=EILSEQ; /* 116 */ - else if (inLen == 3 && ((pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80)) - errno=EILSEQ; /* 116 */ - else if (inLen >= 4 && (byte1 == 0xF8 || (pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80 || (pIn[3] & 0xC0) != 0x80)) - errno=EILSEQ; /* 116 */ - else - errno=EINVAL; /* 22 */ - - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } else if ((pIn[1] == 0x80 || pIn[1] == 0x90 || pIn[1] == 0xA0 || pIn[1] == 0xB0) && - pIn[2] < 0x82) { - *pOut=subS; /* Though returns replacement character, which iconv() does not return. */ - ++pOut; - ++numS; - pIn+=4; - inLen-=4; - continue; - } else { - *pOut=pSubD[0]; /* Though returns replacement character, which iconv() does not return. */ - ++pOut; - *pOut=pSubD[1]; - ++pOut; - ++numS; - pIn+=4; - inLen-=4; - continue; - /* iconv() returns 0 with strange 1 byte converted values */ - } - - } else { /* invalid sequence */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - } - /* end of UTF-8 to UCS-2 */ - if (in == 0x0000) { - *pOut=0x00; - ++pOut; - } else { - in<<=1; - *pOut=dmapU2D[in]; - ++pOut; - if (dmapU2D[in+1] == 0x00) { /* SBCS */ - if (dmapU2D[in] == subS) { - in>>=1; - if (in != cd->srcSubS) - ++numS; - } - } else { - *pOut=dmapU2D[in+1]; - ++pOut; - if (dmapU2D[in] == pSubD[0] && - dmapU2D[in+1] == pSubD[1]) { - in>>=1; - if (in != cd->srcSubD) - ++numS; - } - } - } - } - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return 0; - - } else if (cd->cnv_dmap->codingSchema == DMAP_82U) { - /* See http://unicode.org/versions/corrigendum1.html */ - /* convert from UTF-8 to UTF-16 can cover all conversion from UTF-8 to UCS-2 */ - register int inLen=*inBytesLeft; - register char * pOut=*outBuf; - register char * pIn=*inBuf; - register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; - register size_t numS=0; - while (0 < inLen) { - if (pLastOutBuf < pOut) - break; - if (*pIn == 0x00) { - *pOut=0x00; - ++pOut; - *pOut=0x00; - ++pOut; - ++pIn; - --inLen; - } else { /* 82U: */ - register uchar byte1=*pIn; - if ((byte1 & 0x80) == 0x00) { /* if (byte1 & 0b10000000 == 0b00000000) { */ - /* 1 bytes sequence: 0xxxxxxx => 00000000 0xxxxxxx*/ - *pOut=0x00; - ++pOut; - *pOut=byte1; - ++pOut; - ++pIn; - --inLen; - } else if ((byte1 & 0xE0) == 0xC0) { /* (byte1 & 0b11100000 == 0b11000000) { */ - if (inLen < 2) { - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - if (byte1 == 0xC0 || byte1 == 0xC1) { /* invalid sequence */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - /* 2 bytes sequence: - 110yyyyy 10xxxxxx => 00000yyy yyxxxxxx */ - register uchar byte2; - ++pIn; - byte2=*pIn; - if ((byte2 & 0xC0) == 0x80) { /* byte2 & 0b11000000 == 0b10000000) { */ - register uchar work=byte1; - work<<=6; - byte2&=0x3F; /* 0b00111111; */ - byte2|=work; - - byte1&=0x1F; /* 0b00011111; */ - byte1>>=2; - *pOut=byte1; - ++pOut; - *pOut=byte2; - ++pOut; - inLen-=2; - ++pIn; - } else { /* invalid sequence */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-1; - *numSub+=numS; - return -1; - } - } else if ((byte1 & 0xF0) == 0xE0) { /* byte1 & 0b11110000 == 0b11100000 */ - /* 3 bytes sequence: - 1110zzzz 10yyyyyy 10xxxxxx => zzzzyyyy yyxxxxxx */ - register uchar byte2; - register uchar byte3; - if (inLen < 3) { - if (inLen == 2 && (pIn[1] & 0xC0) != 0x80) - errno=EILSEQ; /* 116 */ - else - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - ++pIn; - byte2=*pIn; - ++pIn; - byte3=*pIn; - if ((byte2 & 0xC0) != 0x80 || - (byte3 & 0xC0) != 0x80 || - (byte1 == 0xE0 && byte2 < 0xA0)) { /* invalid sequence, only 0xA0-0xBF allowed after 0xE0 */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-2; - *numSub+=numS; - return -1; - } - { - register uchar work=byte2; - work<<=6; - byte3&=0x3F; /* 0b00111111; */ - byte3|=work; - - byte2&=0x3F; /* 0b00111111; */ - byte2>>=2; - - byte1<<=4; - *pOut=byte1 | byte2;; - ++pOut; - *pOut=byte3; - ++pOut; - inLen-=3; - ++pIn; - } - } else if ((0xF0 <= byte1 && byte1 <= 0xF4) || /* (bytes1 & 11111000) == 0x1110000 */ - ((byte1&=0xF7) && 0xF0 <= byte1 && byte1 <= 0xF4)) { /* minic iconv() behavior */ - /* 4 bytes sequence - 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx => 110110ww wwzzzzyy 110111yy yyxxxxxx - where uuuuu = wwww + 1 */ - register uchar byte2; - register uchar byte3; - register uchar byte4; - if (inLen < 4 || cd->toCcsid == 13488) { - if ((inLen >= 2 && (pIn[1] & 0xC0) != 0x80) || - (inLen >= 3 && (pIn[2] & 0xC0) != 0x80) || - (cd->toCcsid == 13488) ) - errno=EILSEQ; /* 116 */ - else - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - ++pIn; - byte2=*pIn; - ++pIn; - byte3=*pIn; - ++pIn; - byte4=*pIn; - if ((byte2 & 0xC0) == 0x80 && /* byte2 & 0b11000000 == 0b10000000 */ - (byte3 & 0xC0) == 0x80 && /* byte3 & 0b11000000 == 0b10000000 */ - (byte4 & 0xC0) == 0x80) { /* byte4 & 0b11000000 == 0b10000000 */ - register uchar work=byte2; - if (byte1 == 0xF0 && byte2 < 0x90) { - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-3; - *numSub+=numS; - return -1; - } else if (byte1 == 0xF4 && byte2 > 0x8F) { - errno=EINVAL; /* 22 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-3; - *numSub+=numS; - return -1; - } - - work&=0x30; /* 0b00110000; */ - work>>=4; - byte1&=0x07; /* 0b00000111; */ - byte1<<=2; - byte1+=work; /* uuuuu */ - --byte1; /* wwww */ - - work=byte1 & 0x0F; - work>>=2; - work+=0xD8; /* 0b11011011; */ - *pOut=work; - ++pOut; - - byte1<<=6; - byte2<<=2; - byte2&=0x3C; /* 0b00111100; */ - work=byte3; - work>>=4; - work&=0x03; /* 0b00000011; */ - work|=byte1; - work|=byte2; - *pOut=work; - ++pOut; - - work=byte3; - work>>=2; - work&=0x03; /* 0b00000011; */ - work|=0xDC; /* 0b110111xx; */ - *pOut=work; - ++pOut; - - byte3<<=6; - byte4&=0x3F; /* 0b00111111; */ - byte4|=byte3; - *pOut=byte4; - ++pOut; - inLen-=4; - ++pIn; - } else { /* invalid sequence */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn-3; - *numSub+=numS; - return -1; - } - } else if ((byte1 & 0xF0) == 0xF0) { - if (cd->toCcsid == 13488) { - errno=EILSEQ; /* 116 */ - } else { - if (inLen == 1) - errno=EINVAL; /* 22 */ - else if (inLen == 2 && (pIn[1] & 0xC0) != 0x80) - errno=EILSEQ; /* 116 */ - else if (inLen == 3 && ((pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80)) - errno=EILSEQ; /* 116 */ - else if (inLen >= 4 && ((pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80 || (pIn[3] & 0xC0) != 0x80)) - errno=EILSEQ; /* 116 */ - else - errno=EINVAL; /* 22 */ - } - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - - } else { /* invalid sequence */ - errno=EILSEQ; /* 116 */ - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return -1; - } - } - } - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - *numSub+=numS; - return 0; - } else if (cd->cnv_dmap->codingSchema == DMAP_U28) { - /* See http://unicode.org/versions/corrigendum1.html */ - register int inLen=*inBytesLeft; - register char * pOut=*outBuf; - register char * pIn=*inBuf; - register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; - // register size_t numS=0; - while (0 < inLen) { - register uint32_t in; - if (inLen == 1) { - errno=EINVAL; /* 22 */ - *inBytesLeft=inLen; - *outBytesLeft-=(pOut-*outBuf); - *outBuf=pOut; - *inBuf=pIn; - return -1; - } - if (pLastOutBuf < pOut) - break; - in=pIn[0]; - in<<=8; - in+=pIn[1]; - if (in == 0x0000) { - *pOut=0x00; - ++pOut; - } else if ((in & 0xFF80) == 0x0000) { /* U28: in & 0b1111111110000000 == 0x0000 */ - *pOut=in; - ++pOut; - } else if ((in & 0xF800) == 0x0000) { /* in & 0b1111100000000000 == 0x0000 */ - register uchar byte; - in>>=6; - in&=0x001F; /* 0b0000000000011111 */ - in|=0x00C0; /* 0b0000000011000000 */ - *pOut=in; - ++pOut; - byte=pIn[1]; - byte&=0x3F; /* 0b00111111; */ - byte|=0x80; /* 0b10000000; */ - *pOut=byte; - ++pOut; - } else { - register uchar byte; - register uchar work; - byte=pIn[0]; - byte>>=4; - byte|=0xE0; /* 0b11100000; */ - *pOut=byte; - ++pOut; - - byte=pIn[0]; - byte<<=2; - work=pIn[1]; - work>>=6; - byte|=work; - byte&=0x3F; /* 0b00111111; */ - byte|=0x80; /* 0b10000000; */ - *pOut=byte; - ++pOut; - - byte=pIn[1]; - byte&=0x3F; /* 0b00111111; */ - byte|=0x80; /* 0b10000000; */ - *pOut=byte; - ++pOut; - } - pIn+=2; - inLen-=2; - } - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - // *numSub+=numS; - return 0; - - } else if (cd->cnv_dmap->codingSchema == DMAP_T28) { /* UTF-16_UTF-8 */ - /* See http://unicode.org/versions/corrigendum1.html */ - register int inLen=*inBytesLeft; - register char * pOut=*outBuf; - register char * pIn=*inBuf; - register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; - // register size_t numS=0; - while (0 < inLen) { - register uint32_t in; - if (inLen == 1) { - errno=EINVAL; /* 22 */ - *inBytesLeft=0; - *outBytesLeft-=(pOut-*outBuf); - *outBuf=pOut; - *inBuf=pIn; - return 0; - } - if (pLastOutBuf < pOut) - break; - in=pIn[0]; - in<<=8; - in+=pIn[1]; - if (in == 0x0000) { - *pOut=0x00; - ++pOut; - } else if ((in & 0xFF80) == 0x0000) { /* U28: in & 0b1111111110000000 == 0x0000 */ - *pOut=in; - ++pOut; - } else if ((in & 0xF800) == 0x0000) { /* in & 0b1111100000000000 == 0x0000 */ - register uchar byte; - in>>=6; - in&=0x001F; /* 0b0000000000011111 */ - in|=0x00C0; /* 0b0000000011000000 */ - *pOut=in; - ++pOut; - byte=pIn[1]; - byte&=0x3F; /* 0b00111111; */ - byte|=0x80; /* 0b10000000; */ - *pOut=byte; - ++pOut; - } else if ((in & 0xFC00) == 0xD800) { /* in & 0b1111110000000000 == 0b1101100000000000, first surrogate character */ - if (0xDC00 <= in ) { - errno=EINVAL; /* 22 */ - *inBytesLeft=inLen-1; - *outBytesLeft-=(pOut-*outBuf); - *outBuf=pOut; - *inBuf=pIn; - return -1; - - } else if (inLen < 4) { - errno=EINVAL; /* 22 */ - *inBytesLeft=inLen-2; - *outBytesLeft-=(pOut-*outBuf); - *outBuf=pOut; - *inBuf=pIn+2; - return -1; - - } else if ((pIn[2] & 0xFC) != 0xDC) { /* pIn[2] & 0b11111100 == 0b11011100, second surrogate character */ - errno=EINVAL; /* 22 */ - *inBytesLeft=inLen-2; - *outBytesLeft-=(pOut-*outBuf); - *outBuf=pOut; - *inBuf=pIn+2; - return -1; - - } else { - register uchar byte; - register uchar work; - in>>=6; - in&=0x000F; /* 0b0000000000001111 */ - byte=in; /* wwww */ - ++byte; /* uuuuu */ - work=byte; /* save uuuuu */ - byte>>=2; - byte|=0xF0; /* 0b11110000; */ - *pOut=byte; - ++pOut; - - byte=work; - byte&=0x03; /* 0b00000011; */ - byte<<=4; - byte|=0x80; /* 0b10000000; */ - work=pIn[1]; - work&=0x3C; /* 0b00111100; */ - work>>=2; - byte|=work; - *pOut=byte; - ++pOut; - - byte=pIn[1]; - byte&=0x03; /* 0b00000011; */ - byte<<=4; - byte|=0x80; /* 0b10000000; */ - work=pIn[2]; - work&=0x03; /* 0b00000011; */ - work<<=2; - byte|=work; - work=pIn[3]; - work>>=6; - byte|=work; - *pOut=byte; - ++pOut; - - byte=pIn[3]; - byte&=0x3F; /* 0b00111111; */ - byte|=0x80; /* 0b10000000; */ - *pOut=byte; - ++pOut; - pIn+=2; - inLen-=2; - } - } else if ((in & 0xFC00) == 0xDC00) { /* in & 0b11111100 == 0b11011100, second surrogate character */ - errno=EINVAL; /* 22 */ - *inBytesLeft=inLen-1; - *outBytesLeft-=(pOut-*outBuf); - *outBuf=pOut; - *inBuf=pIn; - return -1; - - } else { - register uchar byte; - register uchar work; - byte=pIn[0]; - byte>>=4; - byte|=0xE0; /* 0b11100000; */ - *pOut=byte; - ++pOut; - - byte=pIn[0]; - byte<<=2; - work=pIn[1]; - work>>=6; - byte|=work; - byte&=0x3F; /* 0b00111111; */ - byte|=0x80; /* 0b10000000; */ - *pOut=byte; - ++pOut; - - byte=pIn[1]; - byte&=0x3F; /* 0b00111111; */ - byte|=0x80; /* 0b10000000; */ - *pOut=byte; - ++pOut; - } - pIn+=2; - inLen-=2; - } - *outBytesLeft-=(pOut-*outBuf); - *inBytesLeft=inLen; - *outBuf=pOut; - *inBuf=pIn; - // *numSub+=numS; - return 0; - - } else if (cd->cnv_dmap->codingSchema == DMAP_U2U) { /* UTF-16_UCS-2 */ - register int inLen=*inBytesLeft; - register int outLen=*outBytesLeft; - if (inLen <= outLen) { - memcpy(*outBuf, *inBuf, inLen); - (*outBytesLeft)-=inLen; - (*inBuf)+=inLen; - (*outBuf)+=inLen; - *inBytesLeft=0; - return 0; - } - memcpy(*outBuf, *inBuf, outLen); - (*outBytesLeft)=0; - (*inBuf)+=outLen; - (*outBuf)+=outLen; - *inBytesLeft-=outLen; - return (*inBytesLeft); - - } else { - return -1; - } - return 0; -} - - -#ifdef DEBUG -inline size_t myconv(myconv_t cd , - char** inBuf, - size_t* inBytesLeft, - char** outBuf, - size_t* outBytesLeft, - size_t* numSub) -{ - if (cd->converterType == CONVERTER_ICONV) { - return myconv_iconv(cd,inBuf,inBytesLeft,outBuf,outBytesLeft,numSub); - } else if (cd->converterType == CONVERTER_DMAP) { - return myconv_dmap(cd,inBuf,inBytesLeft,outBuf,outBytesLeft,numSub); - } - return -1; -} - -inline char * converterName(int32_t type) -{ - if (type == CONVERTER_ICONV) - return "iconv"; - else if (type == CONVERTER_DMAP) - return "dmap"; - - return "?????"; -} -#else -#define myconv(a,b,c,d,e,f) \ -(((a)->converterType == CONVERTER_ICONV)? myconv_iconv((a),(b),(c),(d),(e),(f)): (((a)->converterType == CONVERTER_DMAP)? myconv_dmap((a),(b),(c),(d),(e),(f)): -1)) - - -#define converterName(a) \ -(((a) == CONVERTER_ICONV)? "iconv": ((a) == CONVERTER_DMAP)? "dmap": "?????") -#endif - -void initMyconv(); -void cleanupMyconv(); - -#endif diff --git a/storage/ibmdb2i/db2i_rir.cc b/storage/ibmdb2i/db2i_rir.cc deleted file mode 100644 index 091c4d98383..00000000000 --- a/storage/ibmdb2i/db2i_rir.cc +++ /dev/null @@ -1,686 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - -#include "ha_ibmdb2i.h" - -/* Helper function for records_in_range. - Input: Bitmap of used key parts. - Output: Number of used key parts. */ - -static inline int getKeyCntFromMap(key_part_map keypart_map) -{ - int cnt = 0; - while (keypart_map) - { - keypart_map = keypart_map >> 1; - cnt++; - } - return (cnt); -} - -/** - @brief - Given a starting key and an ending key, estimate the number of rows that - will exist between the two keys. - - INPUT - inx Index to use - min_key Min key. Is NULL if no min range - max_key Max key. Is NULL if no max range - - NOTES - min_key.flag can have one of the following values: - HA_READ_KEY_EXACT Include the key in the range - HA_READ_AFTER_KEY Don't include key in range - - max_key.flag can have one of the following values: - HA_READ_BEFORE_KEY Don't include key in range - HA_READ_AFTER_KEY Include all 'end_key' values in the range - - RETURN - HA_POS_ERROR Error or the storage engine cannot estimate the number of rows - 1 There are no matching keys in the given range - n > 0 There are approximately n rows in the range -*/ -ha_rows ha_ibmdb2i::records_in_range(uint inx, - key_range *min_key, - key_range *max_key) -{ - DBUG_ENTER("ha_ibmdb2i::records_in_range"); - int rc = 0; // Return code - ha_rows rows = 0; // Row count returned to caller of this method - uint32 spcLen; // Length of space passed to DB2 - uint32 keyCnt; // Number of fields in the key composite - uint32 literalCnt = 0; // Number of literals - uint32 boundsOff; // Offset from beginning of space to range bounds - uint32 litDefOff; // Offset from beginning of space to literal definitions - uint32 literalsOff; // Offset from beginning of space to literal values - uint32 cutoff = 0; // Early exit cutoff (currently not used) - uint64 recCnt; // Row count from DB2 - uint16 rtnCode; // Return code from DB2 - Bounds* boundsPtr; // Pointer to a pair of range bounds - Bound* boundPtr; // Pointer to a single (high or low) range bound - LitDef* litDefPtr; // Pointer to a literal definition - char* literalsPtr; // Pointer to the start of all literal values - char* literalPtr; // Pointer to the start of this literal value - char* tempPtr; // Temporary pointer - char* tempMinPtr; // Temporary pointer into min_key - int minKeyCnt = 0; // Number of fields in the min_key composite - int maxKeyCnt = 0; // Number of fields in the max_key composite - size_t tempLen = 0; // Temporary length - uint16 DB2FieldWidth = 0; // DB2 field width - uint32 workFieldLen = 0; // Length of workarea needed for CCSID conversions - bool overrideInclusion; // Indicator for inclusion/exclusion - char* endOfLiteralPtr; // Pointer to the end of this literal - char* endOfMinPtr; // Pointer to end of min_key - uint16 endByte = 0; // End byte of char or graphic literal (padding not included) - bool reuseLiteral; // Indicator that hi and lo bounds use same literal - char* minPtr = NULL; // Work pointer for traversing min_key - char* maxPtr = NULL; // Work pointer for traversing max_key - /* - Handle the special case of 'x < null' anywhere in the key range. There are - no values less than null, but return 1 so that MySQL does not assume - the empty set for the query. - */ - if (min_key != NULL && max_key != NULL && - min_key->flag == HA_READ_AFTER_KEY && max_key->flag == HA_READ_BEFORE_KEY && - min_key->length == max_key->length && - (memcmp((uchar*)min_key->key,(uchar*)max_key->key,min_key->length)==0)) - { - DBUG_PRINT("ha_ibmdb2i::records_in_range",("Estimate 1 row for key %d; special case: < null", inx)); - DBUG_RETURN((ha_rows) 1 ); - } - /* - Determine the number of fields in the key composite. - */ - - if (min_key) - { - minKeyCnt = getKeyCntFromMap(min_key->keypart_map); - minPtr = (char*)min_key->key; - } - if (max_key) - { - maxKeyCnt = getKeyCntFromMap(max_key->keypart_map); - maxPtr = (char*)max_key->key; - } - keyCnt = maxKeyCnt >= minKeyCnt ? maxKeyCnt : minKeyCnt; - - /* - Handle the special case where MySQL does not pass either a min or max - key range. In this case, set the key count to 1 (knowing that there - is at least one key field) to flow through and create one bounds structure. - When both the min and max key ranges are nil, the bounds structure will - specify positive and negative infinity and DB2 will estimate the total - number of rows. */ - - if (keyCnt == 0) - keyCnt = 1; - - /* - Allocate the space needed to pass range information to DB2. The - space must be large enough to store the following: - - one pair of bounds (high and low) per field in the key composite - - one literal definition per literal value - - the literal values - - work area for literal CCSID conversions - Since we don't know yet how many of these structures are needed, - allocate enough space for the maximum that we will possibly need. - The workarea for the literal conversion must be big enough to hold the - largest of the DB2 key fields. - */ - KEY& curKey = table->key_info[inx]; - - for (int i = 0; i < keyCnt; i++) - { - DB2FieldWidth = - db2Table->db2Field(curKey.key_part[i].field->field_index).getByteLengthInRecord(); - if (DB2FieldWidth > workFieldLen) - workFieldLen = DB2FieldWidth; // Get length of largest DB2 field - tempLen = tempLen + DB2FieldWidth; // Tally the DB2 field lengths - } - spcLen = (sizeof(Bounds)*keyCnt) + (sizeof(LitDef)*keyCnt*2) + (tempLen*2) + workFieldLen; - - ValidatedPointer<char> spcPtr(spcLen); // Pointer to space passed to DB2 - memset(spcPtr, 0, spcLen); // Clear the allocated space - /* - Set addressability to the various sections of the DB2 interface space. - */ - boundsOff = 0; // Range bounds are at the start of the space - litDefOff = sizeof(Bounds) * keyCnt; // Literal defs follow all the range bounds - literalsOff = litDefOff + (sizeof(LitDef) * keyCnt * 2); // Literal values are last - boundsPtr = (Bounds_t*)(void*)spcPtr; // Address first bounds structure - tempPtr = (char*)((char*)spcPtr + litDefOff); - litDefPtr = (LitDef_t*)tempPtr; // Address first literal definition - tempPtr = (char*)((char*)spcPtr + literalsOff); - literalsPtr = (char*)tempPtr; // Address start of literal values - literalPtr = literalsPtr; // Address first literal value - /* - For each key part, build the low (min) and high (max) DB2 range bounds. - If literals are specified in the MySQL range, build DB2 literal - definitions and store the literal values for access by DB2. - - If no value is specified for a key part, assume infinity. Negative - infinity will cause processing to start at the first index entry. - Positive infinity will cause processing to end at the last index entry. - When infinity is specified in a bound, inclusion/exclusion and position - are ignored, and there is no literal definition or literal value for - the bound. - - If the keypart value is null, the null indicator is set in the range - bound and the other fields in the bound are ignored. When the bound is - null, only index entries with the null value will be included in the - estimate. If one bound is null, both bounds must be null. When the bound - is not null, the data offset and length must be set, and the literal - value stored for access by DB2. - */ - for (int partsInUse = 0; partsInUse < keyCnt; ++partsInUse) - { - Field *field= curKey.key_part[partsInUse].field; - overrideInclusion = false; - reuseLiteral = false; - endOfLiteralPtr = NULL; - /* - Build the low bound for the key range. - */ - if ((partsInUse + 1) > minKeyCnt) // if no min_key info for this part - boundsPtr->LoBound.Infinity[0] = QMY_NEG_INFINITY; // select...where 3 between x and y - else - { - if ((curKey.key_part[partsInUse].null_bit) && (char*)minPtr[0]) - { // min_key is null - if (max_key == NULL || - ((partsInUse + 1) > maxKeyCnt)) // select...where x='ab' and y=null and z != 'c' - boundsPtr->LoBound.Infinity[0] = QMY_NEG_INFINITY; // select...where x not null or - // select...where x > null - else // max_key is not null - { - if (min_key->flag == HA_READ_KEY_EXACT) - boundsPtr->LoBound.IsNull[0] = QMY_YES; // select...where x is null - else - { - if ((char*)maxPtr[0]) - boundsPtr->LoBound.IsNull[0] = QMY_YES; // select...where a = null and b < 5 (max-before) - // select...where a='a' and b is null and c !='a' (max-after) - else - boundsPtr->LoBound.Infinity[0] = QMY_NEG_INFINITY; // select...where x < y - } - } // end min_key is null - } - else // min_key is not null - { - if (literalCnt) litDefPtr = litDefPtr + 1; - literalCnt = literalCnt + 1; - boundsPtr->LoBound.Position = literalCnt; - /* - Determine inclusion or exclusion. - */ - if (min_key->flag == HA_READ_KEY_EXACT || //select...where a like 'this%' - - /* An example for the following conditions is 'select...where a = 5 and b > null'. */ - - (max_key && - (memcmp((uchar*)minPtr,(uchar*)maxPtr, - curKey.key_part[partsInUse].store_length)==0))) - - { - if ((min_key->flag != HA_READ_KEY_EXACT) || - (max_key && - (memcmp((uchar*)minPtr,(uchar*)maxPtr, - curKey.key_part[partsInUse].store_length)==0))) - overrideInclusion = true; // Need inclusion for both min and max - } - else - boundsPtr->LoBound.Embodiment[0] = QMY_EXCLUSION; - litDefPtr->FieldNbr = field->field_index + 1; - DB2Field& db2Field = db2Table->db2Field(field->field_index); - litDefPtr->DataType = db2Field.getType(); - /* - Convert the literal to DB2 format - */ - if ((field->type() != MYSQL_TYPE_BIT) && // Don't do conversion on BIT data - (field->charset() != &my_charset_bin) && // Don't do conversion on BINARY data - (litDefPtr->DataType == QMY_CHAR || - litDefPtr->DataType == QMY_VARCHAR || - litDefPtr->DataType == QMY_GRAPHIC || - litDefPtr->DataType == QMY_VARGRAPHIC)) - { - // Most of the code is required by the considerable wrangling needed - // to prepare partial keys for use by DB2 - // 1. UTF8 (CCSID 1208) data can be copied across unmodified if it is - // utf8_bin. Otherwise, we need to convert the min and max - // characters into the min and max characters employed - // by the DB2 sort sequence. This is complicated by the fact that - // the character widths are not always equal. - // 2. Likewise, UCS2 (CCSID 13488) data can be copied across unmodified - // if it is ucs2_bin or ucs2_general_ci. Otherwise, we need to - // convert the min and max characters into the min and max characters - // employed by the DB2 sort sequence. - // 3. All other data will use standard iconv conversions. If an - // unconvertible character is encountered, we assume it is the min - // char and fill the remainder of the DB2 key with 0s. This may not - // always be accurate, but it is probably sufficient for range - // estimations. - const char* keyData = minPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0); - char* db2Data = literalPtr; - uint16 outLen = db2Field.getByteLengthInRecord(); - uint16 inLen; - if (litDefPtr->DataType == QMY_VARCHAR || - litDefPtr->DataType == QMY_VARGRAPHIC) - { - inLen = *(uint8*)keyData + ((*(uint8*)(keyData+1)) << 8); - keyData += 2; - outLen -= sizeof(uint16); - db2Data += sizeof(uint16); - } - else - { - inLen = field->max_display_length(); - } - - size_t convertedBytes = 0; - if (db2Field.getCCSID() == 1208) - { - DBUG_ASSERT(inLen <= outLen); - if (strcmp(field->charset()->name, "utf8_bin")) - { - const char* end = keyData+inLen; - const char* curKey = keyData; - char* curDB2 = db2Data; - uint32 min = field->charset()->min_sort_char; - while ((curKey < end) && (curDB2 < db2Data+outLen-3)) - { - my_wc_t temp; - int len = field->charset()->cset->mb_wc(field->charset(), - &temp, - (const uchar*)curKey, - (const uchar*)end); - if (temp != min) - { - DBUG_ASSERT(len <= 3); - switch (len) - { - case 3: *(curDB2+2) = *(curKey+2); - case 2: *(curDB2+1) = *(curKey+1); - case 1: *(curDB2) = *(curKey); - } - curDB2 += len; - } - else - { - *(curDB2++) = 0xEF; - *(curDB2++) = 0xBF; - *(curDB2++) = 0xBF; - } - curKey += len; - } - convertedBytes = curDB2 - db2Data; - } - else - { - memcpy(db2Data, keyData, inLen); - convertedBytes = inLen; - } - rc = 0; - } - else if (db2Field.getCCSID() == 13488) - { - DBUG_ASSERT(inLen <= outLen); - if (strcmp(field->charset()->name, "ucs2_bin") && - strcmp(field->charset()->name, "ucs2_general_ci")) - { - const char* end = keyData+inLen; - const uint16* curKey = (uint16*)keyData; - uint16* curDB2 = (uint16*)db2Data; - uint16 min = field->charset()->min_sort_char; - while (curKey < (uint16*)end) - { - if (*curKey != min) - *curDB2 = *curKey; - else - *curDB2 = 0xFFFF; - ++curKey; - ++curDB2; - } - } - else - { - memcpy(db2Data, keyData, inLen); - } - convertedBytes = inLen; - rc = 0; - } - else - { - rc = convertFieldChars(toDB2, - field->field_index, - keyData, - db2Data, - inLen, - outLen, - &convertedBytes, - true); - - if (rc == DB2I_ERR_ILL_CHAR) - { - // If an illegal character is encountered, we fill the remainder - // of the key with 0x00. This was implemented as a corollary to - // Bug#45012, though it should probably remain even after that - // bug is fixed. - memset(db2Data+convertedBytes, 0x00, outLen-convertedBytes); - convertedBytes = outLen; - rc = 0; - } - } - - if (!rc && - (litDefPtr->DataType == QMY_VARGRAPHIC || - litDefPtr->DataType == QMY_VARCHAR)) - { - *(uint16*)(db2Data-sizeof(uint16)) = - convertedBytes / (litDefPtr->DataType == QMY_VARGRAPHIC ? 2 : 1); - } - - } - else // Non-character fields - { - rc = convertMySQLtoDB2(field, - db2Field, - literalPtr, - (uchar*)minPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0)); - } - - if (rc != 0) break; - litDefPtr->Offset = (uint32_t)(literalPtr - literalsPtr); - litDefPtr->Length = db2Field.getByteLengthInRecord(); - literalPtr = literalPtr + litDefPtr->Length; // Bump pointer for next literal - } - /* If there is a max_key value for this field, and if the max_key value is - the same as the min_key value, then the low bound literal can be reused - for the high bound literal. This eliminates the overhead of copying and - converting the same value twice. */ - if (max_key && ((partsInUse + 1) <= maxKeyCnt) && - (memcmp((uchar*)minPtr,(uchar*)maxPtr, - curKey.key_part[partsInUse].store_length)==0 || endOfLiteralPtr)) - reuseLiteral = true; - minPtr += curKey.key_part[partsInUse].store_length; - } - /* - Build the high bound for the key range. - */ - if (max_key == NULL || ((partsInUse + 1) > maxKeyCnt)) - boundsPtr->HiBound.Infinity[0] = QMY_POS_INFINITY; - else - { - if ((curKey.key_part[partsInUse].null_bit) && (char*)maxPtr[0]) - { - if (min_key == NULL) - boundsPtr->HiBound.Infinity[0] = QMY_POS_INFINITY; - else - boundsPtr->HiBound.IsNull[0] = QMY_YES; // select...where x is null - } - else // max_key field is not null - { - if (boundsPtr->LoBound.IsNull[0] == QMY_YES) // select where x < 10 or x is null - { - rc = HA_POS_ERROR; - break; - } - if (!reuseLiteral) - { - if (literalCnt) - litDefPtr = litDefPtr + 1; - literalCnt = literalCnt + 1; - litDefPtr->FieldNbr = field->field_index + 1; - DB2Field& db2Field = db2Table->db2Field(field->field_index); - litDefPtr->DataType = db2Field.getType(); - /* - Convert the literal to DB2 format - */ - if ((field->type() != MYSQL_TYPE_BIT) && // Don't do conversion on BIT data - (field->charset() != &my_charset_bin) && // Don't do conversion on BINARY data - (litDefPtr->DataType == QMY_CHAR || - litDefPtr->DataType == QMY_VARCHAR || - litDefPtr->DataType == QMY_GRAPHIC || - litDefPtr->DataType == QMY_VARGRAPHIC)) - { - // We need to handle char fields in a special way in order to account - // for partial keys. Refer to the note above for a description of the - // basic design. - char* keyData = maxPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0); - char* db2Data = literalPtr; - uint16 outLen = db2Field.getByteLengthInRecord(); - uint16 inLen; - if (litDefPtr->DataType == QMY_VARCHAR || - litDefPtr->DataType == QMY_VARGRAPHIC) - { - inLen = *(uint8*)keyData + ((*(uint8*)(keyData+1)) << 8); - keyData += 2; - outLen -= sizeof(uint16); - db2Data += sizeof(uint16); - } - else - { - inLen = field->max_display_length(); - } - - size_t convertedBytes; - if (db2Field.getCCSID() == 1208) - { - if (strcmp(field->charset()->name, "utf8_bin")) - { - const char* end = keyData+inLen; - const char* curKey = keyData; - char* curDB2 = db2Data; - uint32 max = field->charset()->max_sort_char; - while (curKey < end && (curDB2 < db2Data+outLen-3)) - { - my_wc_t temp; - int len = field->charset()->cset->mb_wc(field->charset(), &temp, (const uchar*)curKey, (const uchar*)end); - if (temp != max) - { - DBUG_ASSERT(len <= 3); - switch (len) - { - case 3: *(curDB2+2) = *(curKey+2); - case 2: *(curDB2+1) = *(curKey+1); - case 1: *(curDB2) = *(curKey); - } - curDB2 += len; - } - else - { - *(curDB2++) = 0xE4; - *(curDB2++) = 0xB6; - *(curDB2++) = 0xBF; - } - curKey += len; - } - convertedBytes = curDB2 - db2Data; - } - else - { - DBUG_ASSERT(inLen <= outLen); - memcpy(db2Data, keyData, inLen); - convertedBytes = inLen; - } - rc = 0; - } - else if (db2Field.getCCSID() == 13488) - { - if (strcmp(field->charset()->name, "ucs2_bin") && - strcmp(field->charset()->name, "ucs2_general_ci")) - { - char* end = keyData+inLen; - uint16* curKey = (uint16*)keyData; - uint16* curDB2 = (uint16*)db2Data; - uint16 max = field->charset()->max_sort_char; - while (curKey < (uint16*)end) - { - if (*curKey != max) - *curDB2 = *curKey; - else - *curDB2 = 0x4DBF; - ++curKey; - ++curDB2; - } - } - else - { - memcpy(db2Data, keyData, outLen); - } - rc = 0; - } - else - { - size_t substituteChars = 0; - rc = convertFieldChars(toDB2, - field->field_index, - keyData, - db2Data, - inLen, - outLen, - &convertedBytes, - true, - &substituteChars); - - if (rc == DB2I_ERR_ILL_CHAR) - { - // If an illegal character is encountered, we fill the remainder - // of the key with 0xFF. This was implemented to work around - // Bug#45012, though it should probably remain even after that - // bug is fixed. - memset(db2Data+convertedBytes, 0xFF, outLen-convertedBytes); - rc = 0; - } - else if ((substituteChars && - (litDefPtr->DataType == QMY_VARCHAR || - litDefPtr->DataType == QMY_CHAR)) || - strcmp(field->charset()->name, "cp1251_bulgarian_ci") == 0) - { - // When iconv translates the max_sort_char with a substitute - // character, we have no way to know whether this affects - // the sort order of the key. Therefore, to be safe, when - // we know that substitute characters have been used in a - // single-byte string, we traverse the translated key - // in reverse, replacing substitue characters with 0xFF, which - // always sorts with the greatest weight in DB2 sort sequences. - // cp1251_bulgarian_ci is also handled this way because the - // max_sort_char is a control character which does not sort - // equivalently in DB2. - DBUG_ASSERT(inLen == outLen); - char* tmpKey = keyData + inLen - 1; - char* tmpDB2 = db2Data + outLen - 1; - while (*tmpKey == field->charset()->max_sort_char && - *tmpDB2 != 0xFF) - { - *tmpDB2 = 0xFF; - --tmpKey; - --tmpDB2; - } - } - } - - if (!rc && - (litDefPtr->DataType == QMY_VARGRAPHIC || - litDefPtr->DataType == QMY_VARCHAR)) - { - *(uint16*)(db2Data-sizeof(uint16)) = - outLen / (litDefPtr->DataType == QMY_VARGRAPHIC ? 2 : 1); - } - } - else - { - rc = convertMySQLtoDB2(field, - db2Field, - literalPtr, - (uchar*)maxPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0)); - } - if (rc != 0) break; - litDefPtr->Offset = (uint32_t)(literalPtr - literalsPtr); - litDefPtr->Length = db2Field.getByteLengthInRecord(); - literalPtr = literalPtr + litDefPtr->Length; // Bump pointer for next literal - } - boundsPtr->HiBound.Position = literalCnt; - if (max_key->flag == HA_READ_BEFORE_KEY && !overrideInclusion) - boundsPtr->HiBound.Embodiment[0] = QMY_EXCLUSION; - } - maxPtr += curKey.key_part[partsInUse].store_length; - } - /* - Bump to the next field in the key composite. - */ - - if ((partsInUse+1) < keyCnt) - boundsPtr = boundsPtr + 1; - } - - /* - Call DB2 to estimate the number of rows in the key range. - */ - if (rc == 0) - { - rc = db2i_ileBridge::getBridgeForThread()->recordsInRange((indexHandles[inx] ? indexHandles[inx] : db2Table->indexFile(inx)->getMasterDefnHandle()), - spcPtr, - keyCnt, - literalCnt, - boundsOff, - litDefOff, - literalsOff, - cutoff, - (uint32_t)(literalPtr - (char*)spcPtr), - endByte, - &recCnt, - &rtnCode); - } - /* - Set the row count and return. - Beware that if this method returns a zero row count, MySQL assumes the - result set for the query is zero; never return a zero row count. - */ - if ((rc == 0) && (rtnCode == QMY_SUCCESS || rtnCode == QMY_EARLY_EXIT)) - { - rows = recCnt ? (ha_rows)recCnt : 1; - } - - rows = (rows > 0 ? rows : HA_POS_ERROR); - - setIndexReadEstimate(inx, rows); - - DBUG_PRINT("ha_ibmdb2i::recordsInRange",("Estimate %d rows for key %d", uint32(rows), inx)); - - DBUG_RETURN(rows); -} diff --git a/storage/ibmdb2i/db2i_safeString.h b/storage/ibmdb2i/db2i_safeString.h deleted file mode 100644 index e353316c8fc..00000000000 --- a/storage/ibmdb2i/db2i_safeString.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - - -#ifndef DB2I_SAFESTRING_H -#define DB2I_SAFESTRING_H - - -#include <my_global.h> -#include <string.h> - -/** - @class SafeString - - This class was designed to provide safe, but lightweight, concatenation - operations C strings inside pre-allocated buffers. -*/ -class SafeString -{ -public: - SafeString(char* buffer, size_t size) : - allocSize(size), curPos(0), buf(buffer) - { - DBUG_ASSERT(size > 0); - buf[allocSize - 1] = 0xFF; // Set an overflow indicator - } - - char* ptr() { return buf; } - operator char*() { return buf; } - - SafeString& strcat(const char* str) - { - return this->strncat(str, strlen(str)); - } - - SafeString& strcat(char one) - { - if (curPos < allocSize - 2) - { - buf[curPos++] = one; - } - buf[curPos] = 0; - - return *this; - } - - SafeString& strncat(const char* str, size_t len) - { - uint64 amountToCopy = min((allocSize-1) - curPos, len); - memcpy(buf + curPos, str, amountToCopy); - curPos += amountToCopy; - buf[curPos] = 0; - return *this; - } - - bool overflowed() const { return (buf[allocSize - 1] == 0);} - -private: - char* buf; - uint64 curPos; - size_t allocSize; -}; - - -#endif diff --git a/storage/ibmdb2i/db2i_sqlStatementStream.cc b/storage/ibmdb2i/db2i_sqlStatementStream.cc deleted file mode 100644 index 92a8b03fd00..00000000000 --- a/storage/ibmdb2i/db2i_sqlStatementStream.cc +++ /dev/null @@ -1,86 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - -#include "db2i_sqlStatementStream.h" -#include "as400_types.h" - -/** - Add a statement to the statement stream, allocating additional memory as needed. - - @parm stmt The statement text - @parm length The length of the statement text - @parm fileSortSequence The DB2 sort sequence identifier, in EBCDIC - @parm fileSortSequenceLibrary The DB2 sort sequence library, in EBCDIC - - @return Reference to this object -*/ -SqlStatementStream& SqlStatementStream::addStatementInternal(const char* stmt, - uint32 length, - const char* fileSortSequence, - const char* fileSortSequenceLibrary) -{ - uint32 storageNeeded = length + sizeof(StmtHdr_t); - storageNeeded = (storageNeeded + 3) & ~3; // We have to be 4-byte aligned. - if (storageNeeded > storageRemaining()) - { - // We overallocate new storage to reduce number of times reallocation is - // needed. - int newSize = curSize + 2 * storageNeeded; - DBUG_PRINT("SqlStatementStream::addStatementInternal", - ("PERF: Had to realloc! Old size=%d. New size=%d", curSize, newSize)); - char* old_space = block; - char* new_space = (char*)getNewSpace(newSize); - memcpy(new_space, old_space, curSize); - ptr = new_space + (ptr - old_space); - curSize = newSize; - } - - DBUG_ASSERT((address64_t)ptr % 4 == 0); - - memcpy(((StmtHdr_t*)ptr)->SrtSeqNam, - fileSortSequence, - sizeof(((StmtHdr_t*)ptr)->SrtSeqNam)); - memcpy(((StmtHdr_t*)ptr)->SrtSeqSch, - fileSortSequenceLibrary, - sizeof(((StmtHdr_t*)ptr)->SrtSeqSch)); - ((StmtHdr_t*)ptr)->Length = length; - memcpy(ptr + sizeof(StmtHdr_t), stmt, length); - - ptr += storageNeeded; - ++statements; - - return *this; -} diff --git a/storage/ibmdb2i/db2i_sqlStatementStream.h b/storage/ibmdb2i/db2i_sqlStatementStream.h deleted file mode 100644 index 11db41a6c5d..00000000000 --- a/storage/ibmdb2i/db2i_sqlStatementStream.h +++ /dev/null @@ -1,151 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - -#ifndef DB2I_SQLSTATEMENTSTREAM_H -#define DB2I_SQLSTATEMENTSTREAM_H - -#include "db2i_charsetSupport.h" -#include "qmyse.h" - -/** - @class SqlStatementStream - - This class handles building the stream of SQL statements expected by the - QMY_EXECUTE_IMMEDIATE and QMY_PREPARE_OPEN_CURSOR APIs. - Memory allocation is handled internally. -*/ -class SqlStatementStream -{ - public: - /** - ctor to be used when multiple strings may be appended. - */ - SqlStatementStream(uint32 firstStringSize) : statements(0) - { - curSize = firstStringSize + sizeof(StmtHdr_t); - curSize = (curSize + 3) & ~3; - ptr = (char*) getNewSpace(curSize); - if (ptr == NULL) - curSize = 0; - } - - /** - ctor to be used when only a single statement will be executed. - */ - SqlStatementStream(const String& statement) : statements(0), block(NULL), curSize(0), ptr(0) - { - addStatement(statement); - } - - /** - ctor to be used when only a single statement will be executed. - */ - SqlStatementStream(const char* statement) : statements(0), block(NULL), curSize(0), ptr(0) - { - addStatement(statement); - } - - /** - Append an SQL statement, specifiying the DB2 sort sequence under which - the statement should be executed. This is important for CREATE TABLE - and CREATE INDEX statements. - */ - SqlStatementStream& addStatement(const String& append, const char* fileSortSequence, const char* fileSortSequenceLibrary) - { - char sortSeqEbcdic[10]; - char sortSeqLibEbcdic[10]; - - DBUG_ASSERT(strlen(fileSortSequence) <= 10 && - strlen(fileSortSequenceLibrary) <= 10); - memset(sortSeqEbcdic, 0x40, 10); - memset(sortSeqLibEbcdic, 0x40, 10); - convToEbcdic(fileSortSequence, sortSeqEbcdic, strlen(fileSortSequence)); - convToEbcdic(fileSortSequenceLibrary, sortSeqLibEbcdic, strlen(fileSortSequenceLibrary)); - - return addStatementInternal(append.ptr(), append.length(), sortSeqEbcdic, sortSeqLibEbcdic); - } - - /** - Append an SQL statement using default (*HEX) sort sequence. - */ - SqlStatementStream& addStatement(const String& append) - { - const char splatHEX[] = {0x5C, 0xC8, 0xC5, 0xE7, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}; // *HEX - const char blanks[] = {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}; // - - return addStatementInternal(append.ptr(), append.length(), splatHEX, blanks); - } - - /** - Append an SQL statement using default (*HEX) sort sequence. - */ - SqlStatementStream& addStatement(const char* stmt) - { - const char splatHEX[] = {0x5C, 0xC8, 0xC5, 0xE7, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}; // *HEX - const char blanks[] = {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}; // - - return addStatementInternal(stmt, strlen(stmt), splatHEX, blanks); - } - - char* getPtrToData() const { return block; } - uint32 getStatementCount() const { return statements; } - private: - SqlStatementStream& addStatementInternal(const char* stmt, - uint32 length, - const char* fileSortSequence, - const char* fileSortSequenceLibrary); - - uint32 storageRemaining() const - { - return (block == NULL ? 0 : curSize - (ptr - block)); - } - - char* getNewSpace(size_t size) - { - allocBase = (char*)sql_alloc(size + 15); - block = (char*)roundToQuadWordBdy(allocBase); - return block; - } - - uint32 curSize; // The size of the usable memory. - char* allocBase; // The allocated memory (with padding for aligment) - char* block; // The usable memory chunck (aligned for ILE) - char* ptr; // The current position within block. - uint32 statements; // The number of statements that have been appended. -}; - -#endif - diff --git a/storage/ibmdb2i/db2i_validatedPointer.h b/storage/ibmdb2i/db2i_validatedPointer.h deleted file mode 100644 index c4e31d1f11b..00000000000 --- a/storage/ibmdb2i/db2i_validatedPointer.h +++ /dev/null @@ -1,162 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - -#ifndef DB2I_VALIDATEDPOINTER_H -#define DB2I_VALIDATEDPOINTER_H - -#include "db2i_ileBridge.h" - -/** - @class ValidatedPointer - @brief Encapsulates a pointer registered for usage by the QMYSE APIs - - @details As a performance optimization, to prevent pointer validation each - time a particular pointer is thunked across to ILE, QMYSE allows us to - "register" a pointer such that it is validated once and then subsequently - referenced on QMYSE APIs by means of a handle value. This class should be - used to manage memory allocation/registration/unregistration of these - pointers. Using the alloc function guarantees that the resulting storage is - 16-byte aligned, a requirement for many pointers passed to QMYSE. -*/ -template <class T> -class ValidatedPointer -{ -public: - ValidatedPointer<T>() : address(NULL), handle(NULL) {;} - - ValidatedPointer<T>(size_t size) - { - alloc(size); - } - - ValidatedPointer<T>(T* ptr) - { - assign(ptr); - } - - operator T*() - { - return address; - }; - - operator T*() const - { - return address; - }; - - operator void*() - { - return address; - }; - - operator ILEMemHandle() - { - return handle; - } - - void alloc(size_t size) - { - address = (T*)malloc_aligned(size); - if (address) - db2i_ileBridge::registerPtr(address, &handle); - mallocedHere = 1; - } - - void assign(T* ptr) - { - address = ptr; - db2i_ileBridge::registerPtr((void*)ptr, &handle); - mallocedHere = 0; - } - - void realloc(size_t size) - { - dealloc(); - alloc(size); - } - - void reassign(T* ptr) - { - dealloc(); - assign(ptr); - } - - void dealloc() - { - if (address) - { - db2i_ileBridge::unregisterPtr(handle); - - if (mallocedHere) - free_aligned((void*)address); - } - address = NULL; - handle = 0; - } - - ~ValidatedPointer() - { - dealloc(); - } - -private: - // Disable copy ctor and assignment operator, as these would break - // the registration guarantees provided by the class. - ValidatedPointer& operator= (const ValidatedPointer newVal); - ValidatedPointer(ValidatedPointer& newCopy); - - ILEMemHandle handle; - T* address; - char mallocedHere; -}; - - -/** - @class ValidatedObject - @brief This class allows users to instantiate and register a particular - object in a single step. -*/ -template<class T> -class ValidatedObject : public ValidatedPointer<T> -{ - public: - ValidatedObject<T>() : ValidatedPointer<T>(&value) {;} - - T& operator= (const T newVal) { value = newVal; return value; } - - private: - T value; -}; -#endif diff --git a/storage/ibmdb2i/ha_ibmdb2i.cc b/storage/ibmdb2i/ha_ibmdb2i.cc deleted file mode 100644 index 39096be7848..00000000000 --- a/storage/ibmdb2i/ha_ibmdb2i.cc +++ /dev/null @@ -1,3359 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - - -/** - @file ha_ibmdb2i.cc - - @brief - The ha_ibmdb2i storage engine provides an interface from MySQL to IBM DB2 for i. - -*/ - -#ifdef USE_PRAGMA_IMPLEMENTATION -#pragma implementation // gcc: Class implementation -#endif - -#include "ha_ibmdb2i.h" -#include "mysql_priv.h" -#include <mysql/plugin.h> -#include "db2i_ileBridge.h" -#include "db2i_charsetSupport.h" -#include <sys/utsname.h> -#include "db2i_safeString.h" - -static const char __NOT_NULL_VALUE_EBCDIC = 0xF0; // '0' -static const char __NULL_VALUE_EBCDIC = 0xF1; // '1' -static const char __DEFAULT_VALUE_EBCDIC = 0xC4; // 'D' -static const char BlankASPName[19] = " "; -static const int DEFAULT_MAX_ROWS_TO_BUFFER = 4096; - -static const char SAVEPOINT_PREFIX[] = {0xD4, 0xE8, 0xE2, 0xD7}; // MYSP (in EBCDIC) - -OSVersion osVersion; - - -// ================================================================ -// ================================================================ -// System variables -static char* ibmdb2i_rdb_name; -static MYSQL_SYSVAR_STR(rdb_name, ibmdb2i_rdb_name, - PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY, - "The name of the RDB to use", - NULL, - NULL, - BlankASPName); - -static MYSQL_THDVAR_BOOL(transaction_unsafe, - 0, - "Disable support for commitment control", - NULL, - NULL, - FALSE); - -static MYSQL_THDVAR_UINT(lob_alloc_size, - 0, - "Baseline allocation for lob read buffer", - NULL, - NULL, - 2*1024*1024, - 64*1024, - 128*1024*1024, - 1); - -static MYSQL_THDVAR_UINT(max_read_buffer_size, - 0, - "Maximum size of buffers used for read-ahead.", - NULL, - NULL, - 1*1024*1024, - 32*1024, - 16*1024*1024, - 1); - -static MYSQL_THDVAR_UINT(max_write_buffer_size, - 0, - "Maximum size of buffers used for bulk writes.", - NULL, - NULL, - 8*1024*1024, - 32*1024, - 64*1024*1024, - 1); - -static MYSQL_THDVAR_BOOL(compat_opt_time_as_duration, - 0, - "Control how new TIME columns should be defined in DB2. 0=time-of-day (default), 1=duration.", - NULL, - NULL, - FALSE); - -static MYSQL_THDVAR_UINT(compat_opt_year_as_int, - 0, - "Control how new YEAR columns should be defined in DB2. 0=CHAR(4) (default), 1=SMALLINT.", - NULL, - NULL, - 0, - 0, - 1, - 1); - -static MYSQL_THDVAR_UINT(compat_opt_blob_cols, - 0, - "Control how new TEXT and BLOB columns should be defined in DB2. 0=CLOB/BLOB (default), 1=VARCHAR/VARBINARY", - NULL, - NULL, - 0, - 0, - 1, - 1); - -static MYSQL_THDVAR_UINT(compat_opt_allow_zero_date_vals, - 0, - "Allow substitute values to be used when storing a column with a 0000-00-00 date component. 0=No substitution (default), 1=Substitute '0001-01-01'", - NULL, - NULL, - 0, - 0, - 1, - 1); - -static MYSQL_THDVAR_BOOL(propagate_default_col_vals, - 0, - "Should DEFAULT column values be propagated to the DB2 table definition.", - NULL, - NULL, - TRUE); - -static my_bool ibmdb2i_assume_exclusive_use; -static MYSQL_SYSVAR_BOOL(assume_exclusive_use, ibmdb2i_assume_exclusive_use, - 0, - "Can MySQL assume that this process is the only one modifying the DB2 tables. ", - NULL, - NULL, - FALSE); - -static MYSQL_THDVAR_BOOL(async_enabled, - 0, - "Should reads be done asynchronously when possible", - NULL, - NULL, - TRUE); - -static MYSQL_THDVAR_UINT(create_index_option, - 0, - "Control whether additional indexes are created. 0=No (default), 1=Create additional *HEX-based index", - NULL, - NULL, - 0, - 0, - 1, - 1); - -/* static MYSQL_THDVAR_UINT(discovery_mode, - 0, - "Unsupported", - NULL, - NULL, - 0, - 0, - 1, - 1); */ - -static uint32 ibmdb2i_system_trace; -static MYSQL_SYSVAR_UINT(system_trace_level, ibmdb2i_system_trace, - 0, - "Set system tracing level", - NULL, - NULL, - 0, - 0, - 63, - 1); - - -inline uint8 ha_ibmdb2i::getCommitLevel(THD* thd) -{ - if (!THDVAR(thd, transaction_unsafe)) - { - switch (thd_tx_isolation(thd)) - { - case ISO_READ_UNCOMMITTED: - return (accessIntent == QMY_READ_ONLY ? QMY_READ_UNCOMMITTED : QMY_REPEATABLE_READ); - case ISO_READ_COMMITTED: - return (accessIntent == QMY_READ_ONLY ? QMY_READ_COMMITTED : QMY_REPEATABLE_READ); - case ISO_REPEATABLE_READ: - return QMY_REPEATABLE_READ; - case ISO_SERIALIZABLE: - return QMY_SERIALIZABLE; - } - } - - return QMY_NONE; -} - -inline uint8 ha_ibmdb2i::getCommitLevel() -{ - return getCommitLevel(ha_thd()); -} - -//===================================================================== - -static handler *ibmdb2i_create_handler(handlerton *hton, - TABLE_SHARE *table, - MEM_ROOT *mem_root); -static void ibmdb2i_drop_database(handlerton *hton, char* path); -static int ibmdb2i_savepoint_set(handlerton *hton, THD* thd, void *sv); -static int ibmdb2i_savepoint_rollback(handlerton *hton, THD* thd, void *sv); -static int ibmdb2i_savepoint_release(handlerton *hton, THD* thd, void *sv); -static uint ibmdb2i_alter_table_flags(uint flags); - -handlerton *ibmdb2i_hton; -static bool was_ILE_inited; - -/* Tracks the number of open tables */ -static HASH ibmdb2i_open_tables; - -/* Mutex used to synchronize initialization of the hash */ -static pthread_mutex_t ibmdb2i_mutex; - - -/** - Create hash key for tracking open tables. -*/ - -static uchar* ibmdb2i_get_key(IBMDB2I_SHARE *share,size_t *length, - bool not_used __attribute__((unused))) -{ - *length=share->table_name_length; - return (uchar*) share->table_name; -} - - -int ibmdb2i_close_connection(handlerton* hton, THD *thd) -{ - DBUG_PRINT("ha_ibmdb2i::close_connection", ("Closing %d", thd->thread_id)); - db2i_ileBridge::getBridgeForThread(thd)->closeConnection(thd->thread_id); - db2i_ileBridge::destroyBridgeForThread(thd); - - return 0; -} - - -static int ibmdb2i_init_func(void *p) -{ - DBUG_ENTER("ibmdb2i_init_func"); - - utsname tempName; - uname(&tempName); - osVersion.v = atoi(tempName.version); - osVersion.r = atoi(tempName.release); - - was_ILE_inited = false; - ibmdb2i_hton= (handlerton *)p; - VOID(pthread_mutex_init(&ibmdb2i_mutex,MY_MUTEX_INIT_FAST)); - (void) hash_init(&ibmdb2i_open_tables,table_alias_charset,32,0,0, - (hash_get_key) ibmdb2i_get_key,0,0); - - ibmdb2i_hton->state= SHOW_OPTION_YES; - ibmdb2i_hton->create= ibmdb2i_create_handler; - ibmdb2i_hton->drop_database= ibmdb2i_drop_database; - ibmdb2i_hton->commit= ha_ibmdb2i::doCommit; - ibmdb2i_hton->rollback= ha_ibmdb2i::doRollback; - ibmdb2i_hton->savepoint_offset= 0; - ibmdb2i_hton->savepoint_set= ibmdb2i_savepoint_set; - ibmdb2i_hton->savepoint_rollback= ibmdb2i_savepoint_rollback; - ibmdb2i_hton->savepoint_release= ibmdb2i_savepoint_release; - ibmdb2i_hton->alter_table_flags=ibmdb2i_alter_table_flags; - ibmdb2i_hton->close_connection=ibmdb2i_close_connection; - - int rc; - - rc = initCharsetSupport(); - - if (!rc) - rc = db2i_ileBridge::setup(); - - if (!rc) - { - int nameLen = strlen(ibmdb2i_rdb_name); - for (int i = 0; i < nameLen; ++i) - { - ibmdb2i_rdb_name[i] = my_toupper(system_charset_info, (uchar)ibmdb2i_rdb_name[i]); - } - - rc = db2i_ileBridge::initILE(ibmdb2i_rdb_name, (uint16*)(((char*)&ibmdb2i_system_trace)+2)); - if (rc == 0) - { - was_ILE_inited = true; - } - } - - DBUG_RETURN(rc); -} - - -static int ibmdb2i_done_func(void *p) -{ - int error= 0; - DBUG_ENTER("ibmdb2i_done_func"); - - if (ibmdb2i_open_tables.records) - error= 1; - - if (was_ILE_inited) - db2i_ileBridge::exitILE(); - - db2i_ileBridge::takedown(); - - doneCharsetSupport(); - - hash_free(&ibmdb2i_open_tables); - pthread_mutex_destroy(&ibmdb2i_mutex); - - DBUG_RETURN(0); -} - - -IBMDB2I_SHARE *ha_ibmdb2i::get_share(const char *table_name, TABLE *table) -{ - IBMDB2I_SHARE *share; - uint length; - char *tmp_name; - - pthread_mutex_lock(&ibmdb2i_mutex); - length=(uint) strlen(table_name); - - if (!(share=(IBMDB2I_SHARE*) hash_search(&ibmdb2i_open_tables, - (uchar*)table_name, - length))) - { - if (!(share=(IBMDB2I_SHARE *) - my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), - &share, sizeof(*share), - &tmp_name, length+1, - NullS))) - { - pthread_mutex_unlock(&ibmdb2i_mutex); - return NULL; - } - - share->use_count=0; - share->table_name_length=length; - share->table_name=tmp_name; - strmov(share->table_name,table_name); - if (my_hash_insert(&ibmdb2i_open_tables, (uchar*) share)) - goto error; - thr_lock_init(&share->lock); - pthread_mutexattr_t mutexattr = MY_MUTEX_INIT_FAST; - pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&share->mutex, &mutexattr); - - share->db2Table = new db2i_table(table->s, table_name); - int32 rc = share->db2Table->initDB2Objects(table_name); - - if (rc) - { - delete share->db2Table; - hash_delete(&ibmdb2i_open_tables, (uchar*) share); - thr_lock_delete(&share->lock); - my_errno = rc; - goto error; - } - - memset(&share->cachedStats, 0, sizeof(share->cachedStats)); - } - share->use_count++; - pthread_mutex_unlock(&ibmdb2i_mutex); - - db2Table = share->db2Table; - - return share; - -error: - pthread_mutex_destroy(&share->mutex); - my_free((uchar*) share, MYF(0)); - pthread_mutex_unlock(&ibmdb2i_mutex); - - return NULL; -} - - - -int ha_ibmdb2i::free_share(IBMDB2I_SHARE *share) -{ - pthread_mutex_lock(&ibmdb2i_mutex); - if (!--share->use_count) - { - delete share->db2Table; - db2Table = NULL; - - hash_delete(&ibmdb2i_open_tables, (uchar*) share); - thr_lock_delete(&share->lock); - pthread_mutex_destroy(&share->mutex); - my_free(share, MYF(0)); - pthread_mutex_unlock(&ibmdb2i_mutex); - return 1; - } - pthread_mutex_unlock(&ibmdb2i_mutex); - - return 0; -} - -static handler* ibmdb2i_create_handler(handlerton *hton, - TABLE_SHARE *table, - MEM_ROOT *mem_root) -{ - return new (mem_root) ha_ibmdb2i(hton, table); -} - -static void ibmdb2i_drop_database(handlerton *hton, char* path) -{ - DBUG_ENTER("ha_ibmdb2i::ibmdb2i_drop_database"); - int rc = 0; - char queryBuffer[200]; - String query(queryBuffer, sizeof(queryBuffer), system_charset_info); - query.length(0); - query.append(STRING_WITH_LEN(" DROP SCHEMA \"")); - query.append(path+2, strchr(path+2, '/')-(path+2)); - query.append('"'); - - SqlStatementStream sqlStream(query); - - rc = db2i_ileBridge::getBridgeForThread()->execSQL(sqlStream.getPtrToData(), - sqlStream.getStatementCount(), - QMY_NONE, - FALSE, - TRUE); - DBUG_VOID_RETURN; -} - -inline static void genSavepointName(const void* sv, char* out) -{ - *(uint32*)out = *(uint32*)SAVEPOINT_PREFIX; - DBUG_ASSERT(sizeof(SAVEPOINT_PREFIX) == 4); - out += sizeof(SAVEPOINT_PREFIX); - - longlong2str((longlong)sv, out, 10); - while (*out) - { - out += 0xF0; - ++out; - } -} - - -/********************************************************************* -Sets a transaction savepoint. */ -static int ibmdb2i_savepoint_set(handlerton* hton, THD* thd, void* sv) -{ - DBUG_ENTER("ibmdb2i_savepoint_set"); - int rc = 0; - if (!THDVAR(thd ,transaction_unsafe)) - { - char name[64]; - genSavepointName(sv, name); - DBUG_PRINT("ibmdb2i_savepoint_set",("Setting %s", name)); - rc = ha_ibmdb2i::doSavepointSet(thd, name); - } - DBUG_RETURN(rc); -} - - -/********************************************************************* -Rollback a savepoint. */ -static int ibmdb2i_savepoint_rollback(handlerton* hton, THD* thd, void* sv) -{ - DBUG_ENTER("ibmdb2i_savepoint_rollback"); - int rc = 0; - if (!THDVAR(thd,transaction_unsafe)) - { - char name[64]; - genSavepointName(sv, name); - DBUG_PRINT("ibmdb2i_savepoint_rollback",("Rolling back %s", name)); - rc = ha_ibmdb2i::doSavepointRollback(thd, name); - } - DBUG_RETURN(rc); -} - - -/********************************************************************* -Release a savepoint. */ -static int ibmdb2i_savepoint_release(handlerton* hton, THD* thd, void* sv) -{ - DBUG_ENTER("ibmdb2i_savepoint_release"); - int rc = 0; - if (!THDVAR(thd,transaction_unsafe)) - { - char name[64]; - genSavepointName(sv, name); - DBUG_PRINT("ibmdb2i_savepoint_release",("Releasing %s", name)); - rc = ha_ibmdb2i::doSavepointRelease(thd, name); - } - DBUG_RETURN(rc); -} - -/* Thse flags allow for the online add and drop of an index via the CREATE INDEX, - DROP INDEX, and ALTER TABLE statements. These flags indicate that MySQL is not - required to lock the table before calling the storage engine to add or drop the - index(s). */ -static uint ibmdb2i_alter_table_flags(uint flags) -{ - return (HA_ONLINE_ADD_INDEX | HA_ONLINE_DROP_INDEX | - HA_ONLINE_ADD_UNIQUE_INDEX | HA_ONLINE_DROP_UNIQUE_INDEX | - HA_ONLINE_ADD_PK_INDEX | HA_ONLINE_DROP_PK_INDEX); -} - -ha_ibmdb2i::ha_ibmdb2i(handlerton *hton, TABLE_SHARE *table_arg) - :share(NULL), handler(hton, table_arg), - activeHandle(0), dataHandle(0), - activeReadBuf(NULL), activeWriteBuf(NULL), - blobReadBuffers(NULL), accessIntent(QMY_UPDATABLE), currentRRN(0), - releaseRowNeeded(FALSE), - indexReadSizeEstimates(NULL), - outstanding_start_bulk_insert(false), - last_rnd_init_rc(0), - last_index_init_rc(0), - last_start_bulk_insert_rc(0), - autoIncLockAcquired(false), - got_auto_inc_values(false), - next_identity_value(0), - indexHandles(0), - returnDupKeysImmediately(false), - onDupUpdate(false), - blobWriteBuffers(NULL), - forceSingleRowRead(false) - { - activeReferences = 0; - ref_length = sizeof(currentRRN); - if (table_share && table_share->keys > 0) - { - indexHandles = (FILE_HANDLE*)my_malloc(table_share->keys * sizeof(FILE_HANDLE), MYF(MY_WME | MY_ZEROFILL)); - } - clear_alloc_root(&conversionBufferMemroot); - } - - -ha_ibmdb2i::~ha_ibmdb2i() -{ - DBUG_ASSERT(activeReferences == 0 || outstanding_start_bulk_insert); - - if (indexHandles) - my_free(indexHandles, MYF(0)); - if (indexReadSizeEstimates) - my_free(indexReadSizeEstimates, MYF(0)); - - cleanupBuffers(); -} - - -static const char *ha_ibmdb2i_exts[] = { - FID_EXT, - NullS -}; - -const char **ha_ibmdb2i::bas_ext() const -{ - return ha_ibmdb2i_exts; -} - - -int ha_ibmdb2i::open(const char *name, int mode, uint test_if_locked) -{ - DBUG_ENTER("ha_ibmdb2i::open"); - - initBridge(); - - dataHandle = bridge()->findAndRemovePreservedHandle(name, &share); - - if (share) - db2Table = share->db2Table; - - if (!share && (!(share = get_share(name, table)))) - DBUG_RETURN(my_errno); - thr_lock_data_init(&share->lock,&lock,NULL); - - info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE); - - - DBUG_RETURN(0); -} - - - - -int ha_ibmdb2i::close(void) -{ - DBUG_ENTER("ha_ibmdb2i::close"); - int32 rc = 0; - bool preserveShare = false; - - db2i_ileBridge* bridge = db2i_ileBridge::getBridgeForThread(); - - if (dataHandle) - { - if (bridge->expectErrors(QMY_ERR_PEND_LOCKS)->deallocateFile(dataHandle, FALSE) == QMY_ERR_PEND_LOCKS) - { - bridge->preserveHandle(share->table_name, dataHandle, share); - preserveShare = true; - } - dataHandle = 0; - } - - for (int idx = 0; idx < table_share->keys; ++idx) - { - if (indexHandles[idx] != 0) - { - bridge->deallocateFile(indexHandles[idx], FALSE); - } - } - - cleanupBuffers(); - - if (!preserveShare) - { - if (free_share(share)) - share = NULL; - } - - DBUG_RETURN(rc); -} - - - -int ha_ibmdb2i::write_row(uchar * buf) -{ - - DBUG_ENTER("ha_ibmdb2i::write_row"); - - if (last_start_bulk_insert_rc) - DBUG_RETURN( last_start_bulk_insert_rc ); - - ha_statistic_increment(&SSV::ha_write_count); - int rc = 0; - - bool fileHandleNeedsRelease = false; - - if (!activeHandle) - { - rc = useDataFile(); - if (rc) DBUG_RETURN(rc); - fileHandleNeedsRelease = true; - } - - if (!outstanding_start_bulk_insert) - rc = prepWriteBuffer(1, getFileForActiveHandle()); - - if (!rc) - { - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) - table->timestamp_field->set_time(); - - char* writeBuffer = activeWriteBuf->addRow(); - rc = prepareRowForWrite(writeBuffer, - writeBuffer+activeWriteBuf->getRowNullOffset(), - true); - if (rc == 0) - { - // If we are doing block inserts, if the MI is supposed to generate an auto_increment - // (i.e. identity column) value for this record, and if this is not the first record in - // the block, then store the value (that the MI will generate for the identity column) - // into the MySQL write buffer. We can predetermine the value because the file is locked. - - if ((autoIncLockAcquired) && (default_identity_value) && (got_auto_inc_values)) - { - if (unlikely((next_identity_value - 1) == - maxValueForField(table->next_number_field))) - { - rc = QMY_ERR_MAXVALUE; - } - else - { - rc = table->next_number_field->store((longlong) next_identity_value, TRUE); - next_identity_value = next_identity_value + incrementByValue; - } - } - // If the buffer is full, or if we locked the file and this is the first or last row - // of a blocked insert, then flush the buffer. - if (!rc && (activeWriteBuf->endOfBuffer()) || - ((autoIncLockAcquired) && - ((!got_auto_inc_values))) || - (returnDupKeysImmediately)) - rc = flushWrite(activeHandle, buf); - } - else - activeWriteBuf->deleteRow(); - } - - if (fileHandleNeedsRelease) - releaseActiveHandle(); - - DBUG_RETURN(rc); -} - -/** - @brief - Helper function used by write_row and update_row to prepare the MySQL - row for insertion into DB2. -*/ -int ha_ibmdb2i::prepareRowForWrite(char* data, char* nulls, bool honorIdentCols) -{ - int rc = 0; - - // set null map all to non nulls - memset(nulls,__NOT_NULL_VALUE_EBCDIC, table->s->fields); - default_identity_value = FALSE; - - ulong sql_mode = ha_thd()->variables.sql_mode; - - my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set); - for (Field **field = table->field; *field && !rc; ++field) - { - int fieldIndex = (*field)->field_index; - if ((*field)->Field::is_null()) - { - nulls[fieldIndex] = __NULL_VALUE_EBCDIC; - } - if (honorIdentCols && ((*field)->flags & AUTO_INCREMENT_FLAG) && - *field == table->next_number_field) -// && ((!autoIncLockAcquired) || (!got_auto_inc_values))) - { - if (sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) - { - if (!table->auto_increment_field_not_null) - { - nulls[fieldIndex] = __DEFAULT_VALUE_EBCDIC; - default_identity_value = TRUE; - } - } - else if ((*field)->val_int() == 0) - { - nulls[fieldIndex] = __DEFAULT_VALUE_EBCDIC; - default_identity_value = TRUE; - } - } - - DB2Field& db2Field = db2Table->db2Field(fieldIndex); - if (nulls[fieldIndex] == __NOT_NULL_VALUE_EBCDIC || - db2Field.isBlob()) - { - rc = convertMySQLtoDB2(*field, db2Field, data + db2Field.getBufferOffset()); - } - } - - if (!rc && db2Table->hasBlobs()) - rc = db2i_ileBridge::getBridgeForThread()->objectOverride(activeHandle, - activeWriteBuf->ptr()); - - dbug_tmp_restore_column_map(table->read_set, old_map); - - return rc; -} - - - -int ha_ibmdb2i::update_row(const uchar * old_data, uchar * new_data) -{ - DBUG_ENTER("ha_ibmdb2i::update_row"); - ha_statistic_increment(&SSV::ha_update_count); - int rc; - - bool fileHandleNeedsRelease = false; - - if (!activeHandle) - { - rc = useFileByHandle(QMY_UPDATABLE, rrnAssocHandle); - if (rc) DBUG_RETURN(rc); - fileHandleNeedsRelease = true; - } - - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) - table->timestamp_field->set_time(); - - char* writeBuf = activeWriteBuf->addRow(); - rc = prepareRowForWrite(writeBuf, - writeBuf+activeWriteBuf->getRowNullOffset(), - onDupUpdate); - - char* lastDupKeyNamePtr = NULL; - uint32 lastDupKeyNameLen = 0; - - if (!rc) - { - rc = db2i_ileBridge::getBridgeForThread()->updateRow(activeHandle, - currentRRN, - activeWriteBuf->ptr(), - &lastDupKeyRRN, - &lastDupKeyNamePtr, - &lastDupKeyNameLen); - } - - if (lastDupKeyNameLen) - { - lastDupKeyID = getKeyFromName(lastDupKeyNamePtr, lastDupKeyNameLen); - rrnAssocHandle = activeHandle; - } - - if (fileHandleNeedsRelease) - releaseActiveHandle(); - - activeWriteBuf->resetAfterWrite(); - - DBUG_RETURN(rc); -} - - -int ha_ibmdb2i::delete_row(const uchar * buf) -{ - DBUG_ENTER("ha_ibmdb2i::delete_row"); - ha_statistic_increment(&SSV::ha_delete_count); - - bool needReleaseFile = false; - int rc = 0; - - if (!activeHandle) // In some circumstances, MySQL comes here after - { // closing the active handle. We need to re-open. - rc = useFileByHandle(QMY_UPDATABLE, rrnAssocHandle); - needReleaseFile = true; - } - - if (likely(!rc)) - { - rc = db2i_ileBridge::getBridgeForThread()->deleteRow(activeHandle, - currentRRN); - invalidateCachedStats(); - if (needReleaseFile) - releaseActiveHandle(); - } - - DBUG_RETURN(rc); -} - - - -int ha_ibmdb2i::index_init(uint idx, bool sorted) -{ - DBUG_ENTER("ha_ibmdb2i::index_init"); - - int& rc = last_index_init_rc; - rc = 0; - - invalidDataFound=false; - tweakReadSet(); - - active_index=idx; - - rc = useIndexFile(idx); - - if (!rc) - { -// THD* thd = ha_thd(); -// if (accessIntent == QMY_UPDATABLE && -// thd_tx_isolation(thd) == ISO_REPEATABLE_READ && -// !THDVAR(thd, transaction_unsafe)) -// { -// readAccessIntent = QMY_READ_ONLY; -// } -// else -// { - readAccessIntent = accessIntent; -// } - - if (!rc && accessIntent != QMY_READ_ONLY) - rc = prepWriteBuffer(1, db2Table->indexFile(idx)); - - if (rc) - releaseIndexFile(idx); - } - - rrnAssocHandle= 0; - - DBUG_RETURN(rc); -} - - - -int ha_ibmdb2i::index_read(uchar * buf, const uchar * key, - uint key_len, - enum ha_rkey_function find_flag) -{ - DBUG_ENTER("ha_ibmdb2i::index_read"); - - if (unlikely(last_index_init_rc)) DBUG_RETURN(last_index_init_rc); - - int rc; - - ha_rows estimatedRows = getIndexReadEstimate(active_index); - rc = prepReadBuffer(estimatedRows, db2Table->indexFile(active_index), readAccessIntent); - if (unlikely(rc)) DBUG_RETURN(rc); - - DBUG_ASSERT(activeReadBuf); - - keyBuf.allocBuf(activeReadBuf->getRowLength(), - activeReadBuf->getRowNullOffset(), - activeReadBuf->getRowLength()); - keyBuf.zeroBuf(); - - char* db2KeyBufPtr = keyBuf.ptr(); - char* nullKeyMap = db2KeyBufPtr + activeReadBuf->getRowNullOffset(); - - const uchar* keyBegin = key; - int partsInUse; - - KEY& curKey = table->key_info[active_index]; - - for (partsInUse = 0; partsInUse < curKey.key_parts, key - keyBegin < key_len; ++partsInUse) - { - Field* field = curKey.key_part[partsInUse].field; - if ((curKey.key_part[partsInUse].null_bit) && - (char*)key[0]) - { - if (field->flags & AUTO_INCREMENT_FLAG) - { - table->status = STATUS_NOT_FOUND; - DBUG_RETURN(HA_ERR_END_OF_FILE); - } - else - { - nullKeyMap[partsInUse] = __NULL_VALUE_EBCDIC; - } - } - else - { - nullKeyMap[partsInUse] = __NOT_NULL_VALUE_EBCDIC; - convertMySQLtoDB2(field, - db2Table->db2Field(field->field_index), - db2KeyBufPtr, - (uchar*)key+((curKey.key_part[partsInUse].null_bit)? 1 : 0) ); // + (curKey.key_parts+7) / 8); - } - - db2KeyBufPtr += db2Table->db2Field(field->field_index).getByteLengthInRecord(); - key += curKey.key_part[partsInUse].store_length; - } - - keyLen = db2KeyBufPtr - (char*)keyBuf.ptr(); - - DBUG_PRINT("ha_ibmdb2i::index_read", ("find_flag: %d", find_flag)); - - char readDirection = QMY_NEXT; - - switch (find_flag) - { - case HA_READ_AFTER_KEY: - doInitialRead(QMY_AFTER_EQUAL, estimatedRows, - keyBuf.ptr(), keyLen, partsInUse); - break; - case HA_READ_BEFORE_KEY: - doInitialRead(QMY_BEFORE_EQUAL, estimatedRows, - keyBuf.ptr(), keyLen, partsInUse); - break; - case HA_READ_KEY_OR_NEXT: - doInitialRead(QMY_AFTER_OR_EQUAL, estimatedRows, - keyBuf.ptr(), keyLen, partsInUse); - break; - case HA_READ_KEY_OR_PREV: - DBUG_ASSERT(0); // This function is unused - doInitialRead(QMY_BEFORE_OR_EQUAL, estimatedRows, - keyBuf.ptr(), keyLen, partsInUse); - break; - case HA_READ_PREFIX_LAST_OR_PREV: - doInitialRead(QMY_LAST_PREVIOUS, estimatedRows, - keyBuf.ptr(), keyLen, partsInUse); - readDirection = QMY_PREVIOUS; - break; - case HA_READ_PREFIX_LAST: - doInitialRead(QMY_PREFIX_LAST, estimatedRows, - keyBuf.ptr(), keyLen, partsInUse); - readDirection = QMY_PREVIOUS; - break; - case HA_READ_KEY_EXACT: - doInitialRead(QMY_EQUAL, estimatedRows, keyBuf.ptr(), keyLen, partsInUse); - break; - default: - DBUG_ASSERT(0); - return HA_ERR_GENERIC; - break; - } - - ha_statistic_increment(&SSV::ha_read_key_count); - rc = readFromBuffer(buf, readDirection); - - table->status= (rc ? STATUS_NOT_FOUND: 0); - DBUG_RETURN(rc); -} - - -int ha_ibmdb2i::index_next(uchar * buf) -{ - DBUG_ENTER("ha_ibmdb2i::index_next"); - ha_statistic_increment(&SSV::ha_read_next_count); - - int rc = readFromBuffer(buf, QMY_NEXT); - - table->status= (rc ? STATUS_NOT_FOUND: 0); - DBUG_RETURN(rc); -} - - -int ha_ibmdb2i::index_next_same(uchar *buf, const uchar *key, uint keylen) -{ - DBUG_ENTER("ha_ibmdb2i::index_next_same"); - ha_statistic_increment(&SSV::ha_read_next_count); - - int rc = readFromBuffer(buf, QMY_NEXT_EQUAL); - - if (rc == HA_ERR_KEY_NOT_FOUND) - { - rc = HA_ERR_END_OF_FILE; - } - - table->status= (rc ? STATUS_NOT_FOUND: 0); - DBUG_RETURN(rc); -} - -int ha_ibmdb2i::index_read_last(uchar * buf, const uchar * key, uint key_len) -{ - DBUG_ENTER("ha_ibmdb2i::index_read_last"); - DBUG_RETURN(index_read(buf, key, key_len, HA_READ_PREFIX_LAST)); -} - - - -int ha_ibmdb2i::index_prev(uchar * buf) -{ - DBUG_ENTER("ha_ibmdb2i::index_prev"); - ha_statistic_increment(&SSV::ha_read_prev_count); - - int rc = readFromBuffer(buf, QMY_PREVIOUS); - - table->status= (rc ? STATUS_NOT_FOUND: 0); - DBUG_RETURN(rc); -} - - -int ha_ibmdb2i::index_first(uchar * buf) -{ - DBUG_ENTER("ha_ibmdb2i::index_first"); - - if (unlikely(last_index_init_rc)) DBUG_RETURN(last_index_init_rc); - - int rc = prepReadBuffer(DEFAULT_MAX_ROWS_TO_BUFFER, - db2Table->indexFile(active_index), - readAccessIntent); - - if (rc == 0) - { - doInitialRead(QMY_FIRST, DEFAULT_MAX_ROWS_TO_BUFFER); - ha_statistic_increment(&SSV::ha_read_first_count); - rc = readFromBuffer(buf, QMY_NEXT); - } - - table->status= (rc ? STATUS_NOT_FOUND: 0); - DBUG_RETURN(rc); -} - - -int ha_ibmdb2i::index_last(uchar * buf) -{ - DBUG_ENTER("ha_ibmdb2i::index_last"); - - if (unlikely(last_index_init_rc)) DBUG_RETURN(last_index_init_rc); - - int rc = prepReadBuffer(DEFAULT_MAX_ROWS_TO_BUFFER, - db2Table->indexFile(active_index), - readAccessIntent); - - if (rc == 0) - { - doInitialRead(QMY_LAST, DEFAULT_MAX_ROWS_TO_BUFFER); - ha_statistic_increment(&SSV::ha_read_last_count); - rc = readFromBuffer(buf, QMY_PREVIOUS); - } - - table->status= (rc ? STATUS_NOT_FOUND: 0); - DBUG_RETURN(rc); -} - - -int ha_ibmdb2i::rnd_init(bool scan) -{ - DBUG_ENTER("ha_ibmdb2i::rnd_init"); - - int& rc = last_rnd_init_rc; - rc = 0; - - tweakReadSet(); - invalidDataFound=false; - - uint32 rowsToBlockOnRead; - - if (!scan) - { - rowsToBlockOnRead = 1; - } - else - { - rowsToBlockOnRead = DEFAULT_MAX_ROWS_TO_BUFFER; - } - - rc = useDataFile(); - - if (!rc) - { -// THD* thd = ha_thd(); -// if (accessIntent == QMY_UPDATABLE && -// thd_tx_isolation(thd) == ISO_REPEATABLE_READ && -// !THDVAR(thd, transaction_unsafe)) -// { -// readAccessIntent = QMY_READ_ONLY; -// } -// else -// { - readAccessIntent = accessIntent; -// } - - rc = prepReadBuffer(rowsToBlockOnRead, db2Table->dataFile(), readAccessIntent); - - if (!rc && accessIntent != QMY_READ_ONLY) - rc = prepWriteBuffer(1, db2Table->dataFile()); - - if (!rc && scan) - doInitialRead(QMY_FIRST, rowsToBlockOnRead); - - if (rc) - releaseDataFile(); - } - - rrnAssocHandle= 0; - - DBUG_RETURN(0); // MySQL sometimes does not check the return code, causing - // an assert in ha_rnd_end later on if we return a non-zero - // value here. -} - -int ha_ibmdb2i::rnd_end() -{ - DBUG_ENTER("ha_ibmdb2i::rnd_end"); - - warnIfInvalidData(); - if (likely(activeReadBuf)) - activeReadBuf->endRead(); - if (last_rnd_init_rc == 0) - releaseActiveHandle(); - last_rnd_init_rc = 0; - DBUG_RETURN(0); -} - - -int32 ha_ibmdb2i::mungeDB2row(uchar* record, const char* dataPtr, const char* nullMapPtr, bool skipLOBs) -{ - DBUG_ASSERT(dataPtr); - - my_bitmap_map *old_write_map= dbug_tmp_use_all_columns(table, table->write_set); - my_bitmap_map *old_read_map; - - if (unlikely(readAllColumns)) - old_read_map = tmp_use_all_columns(table, table->read_set); - - resetCharacterConversionBuffers(); - - my_ptrdiff_t old_ptr= (my_ptrdiff_t) (record - table->record[0]); - int fieldIndex = 0; - for (Field **field = table->field; *field; ++field, ++fieldIndex) - { - if (unlikely(old_ptr)) - (*field)->move_field_offset(old_ptr); - if (nullMapPtr[fieldIndex] == __NULL_VALUE_EBCDIC || - (!bitmap_is_set(table->read_set, fieldIndex)) || - (skipLOBs && db2Table->db2Field(fieldIndex).isBlob())) - { - (*field)->set_null(); - } - else - { - (*field)->set_notnull(); - convertDB2toMySQL(db2Table->db2Field(fieldIndex), *field, dataPtr); - } - if (unlikely(old_ptr)) - (*field)->move_field_offset(-old_ptr); - - } - - if (unlikely(readAllColumns)) - tmp_restore_column_map(table->read_set, old_read_map); - dbug_tmp_restore_column_map(table->write_set, old_write_map); - - return 0; -} - - -int ha_ibmdb2i::rnd_next(uchar *buf) -{ - DBUG_ENTER("ha_ibmdb2i::rnd_next"); - - if (unlikely(last_rnd_init_rc)) DBUG_RETURN(last_rnd_init_rc); - ha_statistic_increment(&SSV::ha_read_rnd_next_count); - - int rc; - - rc = readFromBuffer(buf, QMY_NEXT); - - table->status= (rc ? STATUS_NOT_FOUND: 0); - DBUG_RETURN(rc); -} - - -void ha_ibmdb2i::position(const uchar *record) -{ - DBUG_ENTER("ha_ibmdb2i::position"); - my_store_ptr(ref, ref_length, currentRRN); - DBUG_VOID_RETURN; -} - - -int ha_ibmdb2i::rnd_pos(uchar * buf, uchar *pos) -{ - DBUG_ENTER("ha_ibmdb2i::rnd_pos"); - if (unlikely(last_rnd_init_rc)) DBUG_RETURN( last_rnd_init_rc); - ha_statistic_increment(&SSV::ha_read_rnd_count); - - currentRRN = my_get_ptr(pos, ref_length); - - tweakReadSet(); - - int rc = 0; - - if (rrnAssocHandle && - (activeHandle != rrnAssocHandle)) - { - if (activeHandle) releaseActiveHandle(); - rc = useFileByHandle(QMY_UPDATABLE, rrnAssocHandle); - } - - if (likely(rc == 0)) - { - rc = prepReadBuffer(1, getFileForActiveHandle(), accessIntent); - - if (likely(rc == 0) && accessIntent == QMY_UPDATABLE) - rc = prepWriteBuffer(1, getFileForActiveHandle()); - - if (likely(rc == 0)) - { - rc = db2i_ileBridge::getBridgeForThread()->readByRRN(activeHandle, - activeReadBuf->ptr(), - currentRRN, - accessIntent, - getCommitLevel()); - - if (likely(rc == 0)) - { - rrnAssocHandle = activeHandle; - const char* readBuf = activeReadBuf->getRowN(0); - rc = mungeDB2row(buf, readBuf, readBuf + activeReadBuf->getRowNullOffset(), false); - releaseRowNeeded = TRUE; - } - } - } - - DBUG_RETURN(rc); -} - - -int ha_ibmdb2i::info(uint flag) -{ - DBUG_ENTER("ha_ibmdb2i::info"); - - uint16 infoRequested = 0; - ValidatedPointer<char> rowKeySpcPtr; // Space pointer passed to DB2 - uint32 rowKeySpcLen; // Length of space passed to DB2 - THD* thd = ha_thd(); - int command = thd_sql_command(thd); - - if (flag & HA_STATUS_AUTO) - stats.auto_increment_value = (ulonglong) 0; - - if (flag & HA_STATUS_ERRKEY) - { - errkey = lastDupKeyID; - my_store_ptr(dup_ref, ref_length, lastDupKeyRRN); - } - - if (flag & HA_STATUS_TIME) - { - if ((flag & HA_STATUS_NO_LOCK) && - ibmdb2i_assume_exclusive_use && - share && - (share->cachedStats.isInited(lastModTime))) - stats.update_time = share->cachedStats.getUpdateTime(); - else - infoRequested |= lastModTime; - } - - if (flag & HA_STATUS_CONST) - { - stats.block_size=4096; - infoRequested |= createTime; - - if (table->s->keys) - { - infoRequested |= rowsPerKey; - rowKeySpcLen = (table->s->keys) * MAX_DB2_KEY_PARTS * sizeof(uint64); - rowKeySpcPtr.alloc(rowKeySpcLen); - memset(rowKeySpcPtr, 0, rowKeySpcLen); // Clear the allocated space - } - } - - if (flag & HA_STATUS_VARIABLE) - { - if ((flag & HA_STATUS_NO_LOCK) && - (command != SQLCOM_SHOW_TABLE_STATUS) && - ibmdb2i_assume_exclusive_use && - share && - (share->cachedStats.isInited(rowCount | deletedRowCount | meanRowLen | ioCount)) && - (share->cachedStats.getRowCount() >= 2)) - { - stats.records = share->cachedStats.getRowCount(); - stats.deleted = share->cachedStats.getDelRowCount(); - stats.mean_rec_length = share->cachedStats.getMeanLength(); - stats.data_file_length = share->cachedStats.getAugmentedDataLength(); - } - else - { - infoRequested |= rowCount | deletedRowCount | meanRowLen; - if (command == SQLCOM_SHOW_TABLE_STATUS) - infoRequested |= objLength; - else - infoRequested |= ioCount; - } - } - - int rc = 0; - - if (infoRequested) - { - DBUG_PRINT("ha_ibmdb2i::info",("Retrieving fresh stats %d", flag)); - - initBridge(thd); - rc = bridge()->retrieveTableInfo((dataHandle ? dataHandle : db2Table->dataFile()->getMasterDefnHandle()), - infoRequested, - stats, - rowKeySpcPtr); - - if (!rc) - { - if ((flag & HA_STATUS_VARIABLE) && - (command != SQLCOM_SHOW_TABLE_STATUS)) - stats.data_file_length = stats.data_file_length * IO_SIZE; - - if ((ibmdb2i_assume_exclusive_use) && - (share) && - (command != SQLCOM_SHOW_TABLE_STATUS)) - { - if (flag & HA_STATUS_VARIABLE) - { - share->cachedStats.cacheRowCount(stats.records); - share->cachedStats.cacheDelRowCount(stats.deleted); - share->cachedStats.cacheMeanLength(stats.mean_rec_length); - share->cachedStats.cacheAugmentedDataLength(stats.data_file_length); - } - - if (flag & HA_STATUS_TIME) - { - share->cachedStats.cacheUpdateTime(stats.update_time); - } - } - - if (flag & HA_STATUS_CONST) - { - ulong i; // Loop counter for indexes - ulong j; // Loop counter for key parts - RowKey* rowKeyPtr; // Pointer to 'number of unique rows' array for this index - - rowKeyPtr = (RowKey_t*)(void*)rowKeySpcPtr; // Address first array of DB2 row counts - for (i = 0; i < table->s->keys; i++) // Do for each index, including primary - { - for (j = 0; j < table->key_info[i].key_parts; j++) - { - table->key_info[i].rec_per_key[j]= rowKeyPtr->RowKeyArray[j]; - } - rowKeyPtr = rowKeyPtr + 1; // Address next array of DB2 row counts - } - } - } - else if (rc == HA_ERR_LOCK_WAIT_TIMEOUT && share) - { - // If we couldn't retrieve the info because the object was locked, - // we'll do our best by returning the most recently cached data. - if ((infoRequested & rowCount) && - share->cachedStats.isInited(rowCount)) - stats.records = share->cachedStats.getRowCount(); - if ((infoRequested & deletedRowCount) && - share->cachedStats.isInited(deletedRowCount)) - stats.deleted = share->cachedStats.getDelRowCount(); - if ((infoRequested & meanRowLen) && - share->cachedStats.isInited(meanRowLen)) - stats.mean_rec_length = share->cachedStats.getMeanLength(); - if ((infoRequested & lastModTime) && - share->cachedStats.isInited(lastModTime)) - stats.update_time = share->cachedStats.getUpdateTime(); - - rc = 0; - } - } - - DBUG_RETURN(rc); -} - - -ha_rows ha_ibmdb2i::records() -{ - DBUG_ENTER("ha_ibmdb2i::records"); - int rc; - rc = bridge()->retrieveTableInfo((dataHandle ? dataHandle : db2Table->dataFile()->getMasterDefnHandle()), - rowCount, - stats); - - if (unlikely(rc)) - { - if (rc == HA_ERR_LOCK_WAIT_TIMEOUT && - share && - (share->cachedStats.isInited(rowCount))) - DBUG_RETURN(share->cachedStats.getRowCount()); - else - DBUG_RETURN(HA_POS_ERROR); - } - else if (share) - { - share->cachedStats.cacheRowCount(stats.records); - } - - DBUG_RETURN(stats.records); -} - - -int ha_ibmdb2i::extra(enum ha_extra_function operation) -{ - DBUG_ENTER("ha_ibmdb2i::extra"); - - switch(operation) - { - // Can these first five flags be replaced by attending to HA_EXTRA_WRITE_CACHE? - case HA_EXTRA_NO_IGNORE_DUP_KEY: - case HA_EXTRA_WRITE_CANNOT_REPLACE: - { - returnDupKeysImmediately = false; - onDupUpdate = false; - } - break; - case HA_EXTRA_INSERT_WITH_UPDATE: - { - returnDupKeysImmediately = true; - onDupUpdate = true; - } - break; - case HA_EXTRA_IGNORE_DUP_KEY: - case HA_EXTRA_WRITE_CAN_REPLACE: - returnDupKeysImmediately = true; - break; - case HA_EXTRA_FLUSH_CACHE: - if (outstanding_start_bulk_insert) - finishBulkInsert(); - break; - } - - - DBUG_RETURN(0); -} - -/** - @brief - The DB2 storage engine will ignore a MySQL generated value and will generate - a new value in SLIC. We arbitrarily set first_value to 1, and set the - interval to infinity for better performance on multi-row inserts. -*/ -void ha_ibmdb2i::get_auto_increment(ulonglong offset, ulonglong increment, - ulonglong nb_desired_values, - ulonglong *first_value, - ulonglong *nb_reserved_values) -{ - DBUG_ENTER("ha_ibmdb2i::get_auto_increment"); - *first_value= 1; - *nb_reserved_values= ULONGLONG_MAX; -} - - - -void ha_ibmdb2i::update_create_info(HA_CREATE_INFO *create_info) -{ - DBUG_ENTER("ha_ibmdb2i::update_create_info"); - - if ((!(create_info->used_fields & HA_CREATE_USED_AUTO)) && - (table->found_next_number_field != NULL)) - { - initBridge(); - - create_info->auto_increment_value= 1; - - ha_rows rowCount = records(); - - if (rowCount == 0) - { - create_info->auto_increment_value = db2Table->getStartId(); - DBUG_VOID_RETURN; - } - else if (rowCount == HA_POS_ERROR) - { - DBUG_VOID_RETURN; - } - - getNextIdVal(&create_info->auto_increment_value); - } - DBUG_VOID_RETURN; -} - - -int ha_ibmdb2i::getNextIdVal(ulonglong *value) -{ - DBUG_ENTER("ha_ibmdb2i::getNextIdVal"); - - char queryBuffer[MAX_DB2_COLNAME_LENGTH + MAX_DB2_QUALIFIEDNAME_LENGTH + 64]; - strcpy(queryBuffer, " SELECT CAST(MAX( "); - convertMySQLNameToDB2Name(table->found_next_number_field->field_name, - strend(queryBuffer), - MAX_DB2_COLNAME_LENGTH+1); - strcat(queryBuffer, ") AS BIGINT) FROM "); - db2Table->getDB2QualifiedName(strend(queryBuffer)); - DBUG_ASSERT(strlen(queryBuffer) < sizeof(queryBuffer)); - - SqlStatementStream sqlStream(queryBuffer); - DBUG_PRINT("ha_ibmdb2i::getNextIdVal", ("Sent to DB2: %s",queryBuffer)); - - int rc = 0; - FILE_HANDLE fileHandle2; - uint32 db2RowDataLen2; - rc = bridge()->prepOpen(sqlStream.getPtrToData(), - &fileHandle2, - &db2RowDataLen2); - if (likely(rc == 0)) - { - IOReadBuffer rowBuffer(1, db2RowDataLen2); - rc = bridge()->read(fileHandle2, - rowBuffer.ptr(), - QMY_READ_ONLY, - QMY_NONE, - QMY_FIRST); - - if (likely(rc == 0)) - { - /* This check is here for the case where the table is not empty, - but the auto_increment starting value has been changed since - the last record was written. */ - - longlong maxIdVal = *(longlong*)(rowBuffer.getRowN(0)); - if ((maxIdVal + 1) > db2Table->getStartId()) - *value = maxIdVal + 1; - else - *value = db2Table->getStartId(); - } - - bridge()->deallocateFile(fileHandle2); - } - DBUG_RETURN(rc); -} - - -/* - Updates index cardinalities. -*/ -int ha_ibmdb2i::analyze(THD* thd, HA_CHECK_OPT *check_opt) -{ - DBUG_ENTER("ha_ibmdb2i::analyze"); - info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE); - DBUG_RETURN(0); -} - -int ha_ibmdb2i::optimize(THD* thd, HA_CHECK_OPT *check_opt) -{ - DBUG_ENTER("ha_ibmdb2i::optimize"); - - initBridge(thd); - - if (unlikely(records() == 0)) - DBUG_RETURN(0); // DB2 doesn't like to reorganize a table with no data. - - quiesceAllFileHandles(); - - int32 rc = bridge()->optimizeTable(db2Table->dataFile()->getMasterDefnHandle()); - info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE); - - DBUG_RETURN(rc); -} - - -/** - @brief - Determines if an ALTER TABLE is allowed to switch the storage engine - for this table. If the table has a foreign key or is referenced by a - foreign key, then it cannot be switched. -*/ -bool ha_ibmdb2i::can_switch_engines(void) -/*=================================*/ -{ - DBUG_ENTER("ha_ibmdb2i::can_switch_engines"); - - int rc = 0; - FILE_HANDLE queryFile = 0; - uint32 resultRowLen; - uint count = 0; - bool can_switch = FALSE; // 1 if changing storage engine is allowed - - const char* libName = db2Table->getDB2LibName(db2i_table::ASCII_SQL); - const char* fileName = db2Table->getDB2TableName(db2i_table::ASCII_SQL); - - String query(256); - query.append(STRING_WITH_LEN(" SELECT COUNT(*) FROM SYSIBM.SQLFOREIGNKEYS WHERE ((PKTABLE_SCHEM = '")); - query.append(libName+1, strlen(libName)-2); // Remove quotes from parent schema name - query.append(STRING_WITH_LEN("' AND PKTABLE_NAME = '")); - query.append(fileName+1,strlen(fileName)-2); // Remove quotes from file name - query.append(STRING_WITH_LEN("') OR (FKTABLE_SCHEM = '")); - query.append(libName+1,strlen(libName)-2); // Remove quotes from child schema - query.append(STRING_WITH_LEN("' AND FKTABLE_NAME = '")); - query.append(fileName+1,strlen(fileName)-2); // Remove quotes from child name - query.append(STRING_WITH_LEN("'))")); - - SqlStatementStream sqlStream(query); - - rc = bridge()->prepOpen(sqlStream.getPtrToData(), - &queryFile, - &resultRowLen); - if (rc == 0) - { - IOReadBuffer rowBuffer(1, resultRowLen); - - rc = bridge()->read(queryFile, - rowBuffer.ptr(), - QMY_READ_ONLY, - QMY_NONE, - QMY_FIRST); - if (!rc) - { - count = *(uint*)(rowBuffer.getRowN(0)); - if (count == 0) - can_switch = TRUE; - } - - bridge()->deallocateFile(queryFile); - } - DBUG_RETURN(can_switch); -} - - - -bool ha_ibmdb2i::check_if_incompatible_data(HA_CREATE_INFO *info, - uint table_changes) -{ - DBUG_ENTER("ha_ibmdb2i::check_if_incompatible_data"); - uint i; - /* Check that auto_increment value and field definitions were - not changed. */ - if ((info->used_fields & HA_CREATE_USED_AUTO && - info->auto_increment_value != 0) || - table_changes != IS_EQUAL_YES) - DBUG_RETURN(COMPATIBLE_DATA_NO); - /* Check if any fields were renamed. */ - for (i= 0; i < table->s->fields; i++) - { - Field *field= table->field[i]; - if (field->flags & FIELD_IS_RENAMED) - { - DBUG_PRINT("info", ("Field has been renamed, copy table")); - DBUG_RETURN(COMPATIBLE_DATA_NO); - } - } - DBUG_RETURN(COMPATIBLE_DATA_YES); -} - -int ha_ibmdb2i::reset_auto_increment(ulonglong value) - { - DBUG_ENTER("ha_ibmdb2i::reset_auto_increment"); - - int rc = 0; - - quiesceAllFileHandles(); - - const char* libName = db2Table->getDB2LibName(db2i_table::ASCII_SQL); - const char* fileName = db2Table->getDB2TableName(db2i_table::ASCII_SQL); - - String query(512); - query.append(STRING_WITH_LEN(" ALTER TABLE ")); - query.append(libName); - query.append('.'); - query.append(fileName); - query.append(STRING_WITH_LEN(" ALTER COLUMN ")); - char colName[MAX_DB2_COLNAME_LENGTH+1]; - convertMySQLNameToDB2Name(table->found_next_number_field->field_name, - colName, - sizeof(colName)); - query.append(colName); - - char restart_value[22]; - CHARSET_INFO *cs= &my_charset_bin; - uint len = (uint)(cs->cset->longlong10_to_str)(cs,restart_value,sizeof(restart_value), 10, value); - restart_value[len] = 0; - - query.append(STRING_WITH_LEN(" RESTART WITH ")); - query.append(restart_value); - - SqlStatementStream sqlStream(query); - DBUG_PRINT("ha_ibmdb2i::reset_auto_increment", ("Sent to DB2: %s",query.c_ptr())); - - rc = db2i_ileBridge::getBridgeForThread()->execSQL(sqlStream.getPtrToData(), - sqlStream.getStatementCount(), - QMY_NONE, //getCommitLevel(), - FALSE, - FALSE, - TRUE, //FALSE, - dataHandle); - if (rc == 0) - db2Table->updateStartId(value); - - DBUG_RETURN(rc); -} - - -/** - @brief - This function receives an error code that was previously set by the handler. - It returns to MySQL the error string associated with that error. -*/ -bool ha_ibmdb2i::get_error_message(int error, String *buf) -{ - DBUG_ENTER("ha_ibmdb2i::get_error_message"); - if ((error >= DB2I_FIRST_ERR && error <= DB2I_LAST_ERR) || - (error >= QMY_ERR_MIN && error <= QMY_ERR_MAX)) - { - db2i_ileBridge* bridge = db2i_ileBridge::getBridgeForThread(ha_thd()); - char* errMsg = bridge->getErrorStorage(); - buf->copy(errMsg, strlen(errMsg),system_charset_info); - bridge->freeErrorStorage(); - } - DBUG_RETURN(FALSE); -} - - -int ha_ibmdb2i::delete_all_rows() -{ - DBUG_ENTER("ha_ibmdb2i::delete_all_rows"); - int rc = 0; - char queryBuffer[MAX_DB2_QUALIFIEDNAME_LENGTH + 64]; - strcpy(queryBuffer, " DELETE FROM "); - db2Table->getDB2QualifiedName(strend(queryBuffer)); - DBUG_ASSERT(strlen(queryBuffer) < sizeof(queryBuffer)); - - SqlStatementStream sqlStream(queryBuffer); - DBUG_PRINT("ha_ibmdb2i::delete_all_rows", ("Sent to DB2: %s",queryBuffer)); - rc = bridge()->execSQL(sqlStream.getPtrToData(), - sqlStream.getStatementCount(), - getCommitLevel(), - false, - false, - true, - dataHandle); - - /* If this method was called on behalf of a TRUNCATE TABLE statement, and if */ - /* the table has an auto_increment field, then reset the starting value for */ - /* the auto_increment field to 1. - */ - if (rc == 0 && thd_sql_command(ha_thd()) == SQLCOM_TRUNCATE && - table->found_next_number_field ) - rc = reset_auto_increment(1); - - invalidateCachedStats(); - - DBUG_RETURN(rc); -} - - -int ha_ibmdb2i::external_lock(THD *thd, int lock_type) -{ - int rc = 0; - - DBUG_ENTER("ha_ibmdb2i::external_lock"); - DBUG_PRINT("ha_ibmdb2i::external_lock",("Lock type: %d", lock_type)); - - if (lock_type == F_RDLCK) - accessIntent = QMY_READ_ONLY; - else if (lock_type == F_WRLCK) - accessIntent = QMY_UPDATABLE; - - initBridge(thd); - int command = thd_sql_command(thd); - - if (!THDVAR(thd,transaction_unsafe)) - { - if (lock_type != F_UNLCK) - { - if (autoCommitIsOn(thd) == QMY_YES) - { - trans_register_ha(thd, FALSE, ibmdb2i_hton); - } - else - { - trans_register_ha(thd, TRUE, ibmdb2i_hton); - if (likely(command != SQLCOM_CREATE_TABLE)) - { - trans_register_ha(thd, FALSE, ibmdb2i_hton); - bridge()->beginStmtTx(); - } - } - } - } - - if (command == SQLCOM_LOCK_TABLES || - command == SQLCOM_ALTER_TABLE || - command == SQLCOM_UNLOCK_TABLES || - (accessIntent == QMY_UPDATABLE && - (command == SQLCOM_UPDATE || - command == SQLCOM_UPDATE_MULTI || - command == SQLCOM_DELETE || - command == SQLCOM_DELETE_MULTI || - command == SQLCOM_REPLACE || - command == SQLCOM_REPLACE_SELECT) && - getCommitLevel(thd) == QMY_NONE)) - { - char action; - char type; - if (lock_type == F_UNLCK) - { - action = QMY_UNLOCK; - type = accessIntent == QMY_READ_ONLY ? QMY_LSRD : QMY_LENR; - } - else - { - action = QMY_LOCK; - type = lock_type == F_RDLCK ? QMY_LSRD : QMY_LENR; - } - - DBUG_PRINT("ha_ibmdb2i::external_lock",("%socking table", action==QMY_LOCK ? "L" : "Unl")); - - if (!dataHandle) - rc = db2Table->dataFile()->allocateNewInstance(&dataHandle, curConnection); - - rc = bridge()->lockObj(dataHandle, - 0, - action, - type, - (command == SQLCOM_LOCK_TABLES ? QMY_NO : QMY_YES)); - - } - - // Cache this away so we don't have to access it on each row operation - cachedZeroDateOption = (enum_ZeroDate)THDVAR(thd, compat_opt_allow_zero_date_vals); - - DBUG_RETURN(rc); -} - - -THR_LOCK_DATA **ha_ibmdb2i::store_lock(THD *thd, - THR_LOCK_DATA **to, - enum thr_lock_type lock_type) -{ - if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) - { - if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && - lock_type <= TL_WRITE) && !(thd->in_lock_tables && thd_sql_command(thd) == SQLCOM_LOCK_TABLES)) - lock_type= TL_WRITE_ALLOW_WRITE; - lock.type=lock_type; - } - *to++= &lock; - return to; -} - - -int ha_ibmdb2i::delete_table(const char *name) -{ - DBUG_ENTER("ha_ibmdb2i::delete_table"); - THD* thd = ha_thd(); - db2i_ileBridge* bridge = db2i_ileBridge::getBridgeForThread(thd); - - char db2Name[MAX_DB2_QUALIFIEDNAME_LENGTH]; - db2i_table::getDB2QualifiedNameFromPath(name, db2Name); - - String query(128); - query.append(STRING_WITH_LEN(" DROP TABLE ")); - query.append(db2Name); - - if (thd_sql_command(thd) == SQLCOM_DROP_TABLE && - thd->lex->drop_mode == DROP_RESTRICT) - query.append(STRING_WITH_LEN(" RESTRICT ")); - DBUG_PRINT("ha_ibmdb2i::delete_table", ("Sent to DB2: %s",query.c_ptr())); - - SqlStatementStream sqlStream(query); - - db2i_table::getDB2LibNameFromPath(name, db2Name); - bool isTemporary = (strcmp(db2Name, DB2I_TEMP_TABLE_SCHEMA) == 0 ? TRUE : FALSE); - - int rc = bridge->execSQL(sqlStream.getPtrToData(), - sqlStream.getStatementCount(), - (isTemporary ? QMY_NONE : getCommitLevel(thd)), - FALSE, - FALSE, - isTemporary); - - if (rc == HA_ERR_NO_SUCH_TABLE) - { - warning(thd, DB2I_ERR_TABLE_NOT_FOUND, name); - rc = 0; - } - - if (rc == 0) - { - db2i_table::deleteAssocFiles(name); - } - - FILE_HANDLE savedHandle = bridge->findAndRemovePreservedHandle(name, &share); - while (savedHandle) - { - bridge->deallocateFile(savedHandle, TRUE); - DBUG_ASSERT(share); - if (free_share(share)) - share = NULL; - savedHandle = bridge->findAndRemovePreservedHandle(name, &share); - } - - my_errno = rc; - DBUG_RETURN(rc); -} - - -int ha_ibmdb2i::rename_table(const char * from, const char * to) -{ - DBUG_ENTER("ha_ibmdb2i::rename_table "); - - char db2FromFileName[MAX_DB2_FILENAME_LENGTH + 1]; - char db2ToFileName[MAX_DB2_FILENAME_LENGTH+1]; - char db2FromLibName[MAX_DB2_SCHEMANAME_LENGTH+1]; - char db2ToLibName[MAX_DB2_SCHEMANAME_LENGTH+1]; - - db2i_table::getDB2LibNameFromPath(from, db2FromLibName); - db2i_table::getDB2LibNameFromPath(to, db2ToLibName); - - if (strcmp(db2FromLibName, db2ToLibName) != 0 ) - { - getErrTxt(DB2I_ERR_RENAME_MOVE,from,to); - DBUG_RETURN(DB2I_ERR_RENAME_MOVE); - } - - db2i_table::getDB2FileNameFromPath(from, db2FromFileName, db2i_table::ASCII_NATIVE); - db2i_table::getDB2FileNameFromPath(to, db2ToFileName); - - char escapedFromFileName[2 * MAX_DB2_FILENAME_LENGTH + 1]; - - uint o = 0; - uint i = 1; - do - { - escapedFromFileName[o++] = db2FromFileName[i]; - if (db2FromFileName[i] == '+') - escapedFromFileName[o++] = '+'; - } while (db2FromFileName[++i]); - escapedFromFileName[o-1] = 0; - - - int rc = 0; - - char queryBuffer[sizeof(db2FromLibName) + 2 * sizeof(db2FromFileName) + 256]; - SafeString selectQuery(queryBuffer, sizeof(queryBuffer)); - selectQuery.strncat(STRING_WITH_LEN("SELECT CAST(INDEX_NAME AS VARCHAR(128) CCSID 1208) FROM QSYS2.SYSINDEXES WHERE INDEX_NAME LIKE '%+_+_+_%")); - selectQuery.strcat(escapedFromFileName); - selectQuery.strncat(STRING_WITH_LEN("' ESCAPE '+' AND TABLE_NAME='")); - selectQuery.strncat(db2FromFileName+1, strlen(db2FromFileName)-2); - selectQuery.strncat(STRING_WITH_LEN("' AND TABLE_SCHEMA='")); - selectQuery.strncat(db2FromLibName+1, strlen(db2FromLibName)-2); - selectQuery.strcat('\''); - DBUG_ASSERT(!selectQuery.overflowed()); - - SqlStatementStream indexQuery(selectQuery.ptr()); - - FILE_HANDLE queryFile = 0; - uint32 resultRowLen; - - initBridge(); - rc = bridge()->prepOpen(indexQuery.getPtrToData(), - &queryFile, - &resultRowLen); - - if (unlikely(rc)) - DBUG_RETURN(rc); - - IOReadBuffer rowBuffer(1, resultRowLen); - - int tableNameLen = strlen(db2FromFileName) - 2; - - SqlStatementStream renameQuery(64); - String query; - while (rc == 0) - { - query.length(0); - - rc = bridge()->read(queryFile, - rowBuffer.ptr(), - QMY_READ_ONLY, - QMY_NONE, - QMY_NEXT); - - if (!rc) - { - const char* rowData = rowBuffer.getRowN(0); - char indexFileName[MAX_DB2_FILENAME_LENGTH]; - memset(indexFileName, 0, sizeof(indexFileName)); - - uint16 fileNameLen = *(uint16*)(rowData); - strncpy(indexFileName, rowData + sizeof(uint16), fileNameLen); - - int bytesToRetain = fileNameLen - tableNameLen; - if (bytesToRetain <= 0) - /* We can't handle index names in which the MySQL index name and - the table name together are longer than the max index name. */ - { - getErrTxt(DB2I_ERR_INVALID_NAME,"index","*generated*"); - DBUG_RETURN(DB2I_ERR_INVALID_NAME); - } - char indexName[MAX_DB2_FILENAME_LENGTH]; - memset(indexName, 0, sizeof(indexName)); - - strncpy(indexName, - indexFileName, - bytesToRetain); - - char db2IndexName[MAX_DB2_FILENAME_LENGTH+1]; - - convertMySQLNameToDB2Name(indexFileName, db2IndexName, sizeof(db2IndexName)); - - query.append(STRING_WITH_LEN("RENAME INDEX ")); - query.append(db2FromLibName); - query.append('.'); - query.append(db2IndexName); - query.append(STRING_WITH_LEN(" TO ")); - if (db2i_table::appendQualifiedIndexFileName(indexName, db2ToFileName, query, db2i_table::ASCII_SQL, typeNone) == -1) - { - getErrTxt(DB2I_ERR_INVALID_NAME,"index","*generated*"); - DBUG_RETURN(DB2I_ERR_INVALID_NAME ); - } - renameQuery.addStatement(query); - DBUG_PRINT("ha_ibmdb2i::rename_table", ("Sent to DB2: %s",query.c_ptr_safe())); - } - } - - - if (queryFile) - bridge()->deallocateFile(queryFile); - - if (rc != HA_ERR_END_OF_FILE) - DBUG_RETURN(rc); - - char db2Name[MAX_DB2_QUALIFIEDNAME_LENGTH]; - - /* Rename the table */ - query.length(0); - query.append(STRING_WITH_LEN(" RENAME TABLE ")); - db2i_table::getDB2QualifiedNameFromPath(from, db2Name); - query.append(db2Name); - query.append(STRING_WITH_LEN(" TO ")); - query.append(db2ToFileName); - DBUG_PRINT("ha_ibmdb2i::rename_table", ("Sent to DB2: %s",query.c_ptr_safe())); - renameQuery.addStatement(query); - rc = bridge()->execSQL(renameQuery.getPtrToData(), - renameQuery.getStatementCount(), - getCommitLevel()); - - if (!rc) - db2i_table::renameAssocFiles(from, to); - - DBUG_RETURN(rc); -} - - -int ha_ibmdb2i::create(const char *name, TABLE *table_arg, - HA_CREATE_INFO *create_info) -{ - DBUG_ENTER("ha_ibmdb2i::create"); - - int rc; - char fileSortSequence[11] = "*HEX"; - char fileSortSequenceLibrary[11] = ""; - char fileSortSequenceType = ' '; - char libName[MAX_DB2_SCHEMANAME_LENGTH+1]; - char fileName[MAX_DB2_FILENAME_LENGTH+1]; - char colName[MAX_DB2_COLNAME_LENGTH+1]; - bool isTemporary; - ulong auto_inc_value; - - db2i_table::getDB2LibNameFromPath(name, libName); - db2i_table::getDB2FileNameFromPath(name, fileName); - - if (osVersion.v < 6) - { - if (strlen(libName) > - MAX_DB2_V5R4_LIBNAME_LENGTH + (isOrdinaryIdentifier(libName) ? 2 : 0)) - { - getErrTxt(DB2I_ERR_TOO_LONG_SCHEMA,libName, MAX_DB2_V5R4_LIBNAME_LENGTH); - DBUG_RETURN(DB2I_ERR_TOO_LONG_SCHEMA); - } - } - else if (strlen(libName) > MAX_DB2_V6R1_LIBNAME_LENGTH) - { - getErrTxt(DB2I_ERR_TOO_LONG_SCHEMA,libName, MAX_DB2_V6R1_LIBNAME_LENGTH); - DBUG_RETURN(DB2I_ERR_TOO_LONG_SCHEMA); - } - - String query(256); - - if (strcmp(libName, DB2I_TEMP_TABLE_SCHEMA)) - { - query.append(STRING_WITH_LEN("CREATE TABLE ")); - query.append(libName); - query.append('.'); - query.append(fileName); - isTemporary = FALSE; - } - else - { - query.append(STRING_WITH_LEN("DECLARE GLOBAL TEMPORARY TABLE ")); - query.append(fileName); - isTemporary = TRUE; - } - query.append(STRING_WITH_LEN(" (")); - - THD* thd = ha_thd(); - enum_TimeFormat timeFormat = (enum_TimeFormat)(THDVAR(thd, compat_opt_time_as_duration)); - enum_YearFormat yearFormat = (enum_YearFormat)(THDVAR(thd, compat_opt_year_as_int)); - enum_BlobMapping blobMapping = (enum_BlobMapping)(THDVAR(thd, compat_opt_blob_cols)); - enum_ZeroDate zeroDate = (enum_ZeroDate)(THDVAR(thd, compat_opt_allow_zero_date_vals)); - bool propagateDefaults = THDVAR(thd, propagate_default_col_vals); - - Field **field; - for (field= table_arg->field; *field; field++) - { - if ( field != table_arg->field ) // Not the first one - query.append(STRING_WITH_LEN(" , ")); - - if (!convertMySQLNameToDB2Name((*field)->field_name, colName, sizeof(colName))) - { - getErrTxt(DB2I_ERR_INVALID_NAME,"field",(*field)->field_name); - DBUG_RETURN(DB2I_ERR_INVALID_NAME ); - } - - query.append(colName); - query.append(' '); - - if (rc = getFieldTypeMapping(*field, - query, - timeFormat, - blobMapping, - zeroDate, - propagateDefaults, - yearFormat)) - DBUG_RETURN(rc); - - if ( (*field)->flags & NOT_NULL_FLAG ) - { - query.append(STRING_WITH_LEN(" NOT NULL ")); - } - if ( (*field)->flags & AUTO_INCREMENT_FLAG ) - { -#ifdef WITH_PARTITION_STORAGE_ENGINE - if (table_arg->part_info) - { - getErrTxt(DB2I_ERR_PART_AUTOINC); - DBUG_RETURN(DB2I_ERR_PART_AUTOINC); - } -#endif - query.append(STRING_WITH_LEN(" GENERATED BY DEFAULT AS IDENTITY ") ); - if (create_info->auto_increment_value != 0) - { - /* Query was ALTER TABLE...AUTO_INCREMENT = x; or - CREATE TABLE ...AUTO_INCREMENT = x; Set the starting - value for the auto_increment column. */ - char stringValue[22]; - CHARSET_INFO *cs= &my_charset_bin; - uint len = (uint)(cs->cset->longlong10_to_str)(cs,stringValue,sizeof(stringValue), 10, create_info->auto_increment_value); - stringValue[len] = 0; - query.append(STRING_WITH_LEN(" (START WITH ")); - query.append(stringValue); - - uint64 maxValue=maxValueForField(*field); - - if (maxValue) - { - len = (uint)(cs->cset->longlong10_to_str)(cs,stringValue,sizeof(stringValue), 10, maxValue); - stringValue[len] = 0; - query.append(STRING_WITH_LEN(" MAXVALUE ")); - query.append(stringValue); - } - - query.append(STRING_WITH_LEN(") ")); - } - - } - } - - String fieldDefinition(128); - - if (table_arg->s->primary_key != MAX_KEY && !isTemporary) - { - query.append(STRING_WITH_LEN(", PRIMARY KEY ")); - rc = buildIndexFieldList(fieldDefinition, - table_arg->key_info[table_arg->s->primary_key], - true, - &fileSortSequenceType, - fileSortSequence, - fileSortSequenceLibrary); - if (rc) DBUG_RETURN(rc); - query.append(fieldDefinition); - } - - rc = buildDB2ConstraintString(thd->lex, - query, - name, - table_arg->field, - &fileSortSequenceType, - fileSortSequence, - fileSortSequenceLibrary); - if (rc) DBUG_RETURN (rc); - - query.append(STRING_WITH_LEN(" ) ")); - - if (isTemporary) - query.append(STRING_WITH_LEN(" ON COMMIT PRESERVE ROWS ")); - - if (create_info->alias) - generateAndAppendRCDFMT(create_info->alias, query); - else if (((TABLE_LIST*)(thd->lex->select_lex.table_list.first))->table_name) - generateAndAppendRCDFMT((char*)((TABLE_LIST*)(thd->lex->select_lex.table_list.first))->table_name, query); - - DBUG_PRINT("ha_ibmdb2i::create", ("Sent to DB2: %s",query.c_ptr())); - SqlStatementStream sqlStream(query.length()); - sqlStream.addStatement(query,fileSortSequence,fileSortSequenceLibrary); - - if (table_arg->s->primary_key != MAX_KEY && - !isTemporary && - (THDVAR(thd, create_index_option)==1) && - (fileSortSequenceType != 'B') && - (fileSortSequenceType != ' ')) - { - rc = generateShadowIndex(sqlStream, - table_arg->key_info[table_arg->s->primary_key], - libName, - fileName, - fieldDefinition); - if (rc) DBUG_RETURN(rc); - } - for (uint i = 0; i < table_arg->s->keys; ++i) - { - if (i != table_arg->s->primary_key || isTemporary) - { - rc = buildCreateIndexStatement(sqlStream, - table_arg->key_info[i], - false, - libName, - fileName); - if (rc) DBUG_RETURN (rc); - } - } - - bool noCommit = isTemporary || ((!autoCommitIsOn(thd)) && (thd_sql_command(thd) == SQLCOM_ALTER_TABLE)); - - initBridge(); - -// if (THDVAR(thd, discovery_mode) == 1) -// bridge()->expectErrors(QMY_ERR_TABLE_EXISTS); - - rc = bridge()->execSQL(sqlStream.getPtrToData(), - sqlStream.getStatementCount(), - (isTemporary ? QMY_NONE : getCommitLevel(thd)), - TRUE, - FALSE, - noCommit ); - - if (unlikely(rc == QMY_ERR_MSGID) && - memcmp(bridge()->getErrorMsgID(), DB2I_SQL0350, 7) == 0) - { - my_error(ER_BLOB_USED_AS_KEY, MYF(0), "*unknown*"); - rc = ER_BLOB_USED_AS_KEY; - } -/* else if (unlikely(rc == QMY_ERR_TABLE_EXISTS) && - THDVAR(thd, discovery_mode) == 1) - { - db2i_table* temp = new db2i_table(table_arg->s, name); - int32 rc = temp->fastInitForCreate(name); - delete temp; - - if (!rc) - warning(thd, DB2I_ERR_WARN_CREATE_DISCOVER); - - DBUG_RETURN(rc); - } -*/ - - if (!rc && !isTemporary) - { - db2i_table* temp = new db2i_table(table_arg->s, name); - rc = temp->fastInitForCreate(name); - delete temp; - if (rc) - delete_table(name); - } - - DBUG_RETURN(rc); -} - - -/** - @brief - Add an index on-line to a table. This method is called on behalf of - a CREATE INDEX or ALTER TABLE statement. - It is implemented via a composed DDL statement passed to DB2. -*/ -int ha_ibmdb2i::add_index(TABLE *table_arg, - KEY *key_info, - uint num_of_keys) -{ - DBUG_ENTER("ha_ibmdb2i::add_index"); - - int rc; - SqlStatementStream sqlStream(256); - const char* libName = db2Table->getDB2LibName(db2i_table::ASCII_SQL); - const char* fileName = db2Table->getDB2TableName(db2i_table::ASCII_SQL); - - quiesceAllFileHandles(); - - uint primaryKey = MAX_KEY; - if (table_arg->s->primary_key >= MAX_KEY && !db2Table->isTemporary()) - { - for (int i = 0; i < num_of_keys; ++i) - { - if (strcmp(key_info[i].name, "PRIMARY") == 0) - { - primaryKey = i; - break; - } - else if (primaryKey == MAX_KEY && - key_info[i].flags & HA_NOSAME) - { - primaryKey = i; - for (int j=0 ; j < key_info[i].key_parts ;j++) - { - uint fieldnr= key_info[i].key_part[j].fieldnr; - if (table_arg->s->field[fieldnr]->null_ptr || - table_arg->s->field[fieldnr]->key_length() != - key_info[i].key_part[j].length) - { - primaryKey = MAX_KEY; - break; - } - } - } - } - } - - - for (int i = 0; i < num_of_keys; ++i) - { - KEY& curKey= key_info[i]; - rc = buildCreateIndexStatement(sqlStream, - curKey, - (i == primaryKey), - libName, - fileName); - if (rc) DBUG_RETURN (rc); - } - - rc = bridge()->execSQL(sqlStream.getPtrToData(), - sqlStream.getStatementCount(), - getCommitLevel(), - FALSE, - FALSE, - FALSE, - dataHandle); - - /* Handle the case where a unique index is being created but an error occurs - because the file contains duplicate key values. */ - if (rc == ER_DUP_ENTRY) - print_keydup_error(MAX_KEY,ER(ER_DUP_ENTRY_WITH_KEY_NAME)); - - DBUG_RETURN(rc); -} - -/** - @brief - Drop an index on-line from a table. This method is called on behalf of - a DROP INDEX or ALTER TABLE statement. - It is implemented via a composed DDL statement passed to DB2. -*/ -int ha_ibmdb2i::prepare_drop_index(TABLE *table_arg, - uint *key_num, uint num_of_keys) -{ - DBUG_ENTER("ha_ibmdb2i::prepare_drop_index"); - int rc; - int i = 0; - String query(64); - SqlStatementStream sqlStream(64 * num_of_keys); - SqlStatementStream shadowStream(64 * num_of_keys); - - quiesceAllFileHandles(); - - const char* libName = db2Table->getDB2LibName(db2i_table::ASCII_SQL); - const char* fileName = db2Table->getDB2TableName(db2i_table::ASCII_SQL); - - while (i < num_of_keys) - { - query.length(0); - DBUG_PRINT("info", ("ha_ibmdb2i::prepare_drop_index %u", key_num[i])); - KEY& curKey= table_arg->key_info[key_num[i]]; - if (key_num[i] == table->s->primary_key && !db2Table->isTemporary()) - { - query.append(STRING_WITH_LEN("ALTER TABLE ")); - query.append(libName); - query.append(STRING_WITH_LEN(".")); - query.append(fileName); - query.append(STRING_WITH_LEN(" DROP PRIMARY KEY")); - } - else - { - query.append(STRING_WITH_LEN("DROP INDEX ")); - query.append(libName); - query.append(STRING_WITH_LEN(".")); - db2i_table::appendQualifiedIndexFileName(curKey.name, fileName, query); - } - DBUG_PRINT("ha_ibmdb2i::prepare_drop_index", ("Sent to DB2: %s",query.c_ptr_safe())); - sqlStream.addStatement(query); - - query.length(0); - query.append(STRING_WITH_LEN("DROP INDEX ")); - query.append(libName); - query.append(STRING_WITH_LEN(".")); - db2i_table::appendQualifiedIndexFileName(curKey.name, fileName, query, db2i_table::ASCII_SQL, typeHex); - - DBUG_PRINT("ha_ibmdb2i::prepare_drop_index", ("Sent to DB2: %s",query.c_ptr_safe())); - shadowStream.addStatement(query); - - ++i; - } - - rc = bridge()->execSQL(sqlStream.getPtrToData(), - sqlStream.getStatementCount(), - getCommitLevel(), - FALSE, - FALSE, - FALSE, - dataHandle); - - if (rc == 0) - bridge()->execSQL(shadowStream.getPtrToData(), - shadowStream.getStatementCount(), - getCommitLevel()); - - DBUG_RETURN(rc); -} - - -void -ha_ibmdb2i::unlock_row() -{ - DBUG_ENTER("ha_ibmdb2i::unlock_row"); - DBUG_VOID_RETURN; -} - -int -ha_ibmdb2i::index_end() -{ - DBUG_ENTER("ha_ibmdb2i::index_end"); - warnIfInvalidData(); - last_index_init_rc = 0; - if (likely(activeReadBuf)) - activeReadBuf->endRead(); - if (likely(!last_index_init_rc)) - releaseIndexFile(active_index); - active_index= MAX_KEY; - DBUG_RETURN (0); -} - -int ha_ibmdb2i::doCommit(handlerton *hton, THD *thd, bool all) -{ - if (!THDVAR(thd, transaction_unsafe)) - { - if (all || autoCommitIsOn(thd)) - { - DBUG_PRINT("ha_ibmdb2i::doCommit",("Committing all")); - return (db2i_ileBridge::getBridgeForThread(thd)->commitmentControl(QMY_COMMIT)); - } - else - { - DBUG_PRINT("ha_ibmdb2i::doCommit",("Committing stmt")); - return (db2i_ileBridge::getBridgeForThread(thd)->commitStmtTx()); - } - } - - return (0); -} - - -int ha_ibmdb2i::doRollback(handlerton *hton, THD *thd, bool all) -{ - if (!THDVAR(thd,transaction_unsafe)) - { - if (all || autoCommitIsOn(thd)) - { - DBUG_PRINT("ha_ibmdb2i::doRollback",("Rolling back all")); - return ( db2i_ileBridge::getBridgeForThread(thd)->commitmentControl(QMY_ROLLBACK)); - } - else - { - DBUG_PRINT("ha_ibmdb2i::doRollback",("Rolling back stmt")); - return (db2i_ileBridge::getBridgeForThread(thd)->rollbackStmtTx()); - } - } - return (0); -} - - -void ha_ibmdb2i::start_bulk_insert(ha_rows rows) -{ - DBUG_ENTER("ha_ibmdb2i::start_bulk_insert"); - DBUG_PRINT("ha_ibmdb2i::start_bulk_insert",("Rows hinted %d", rows)); - int rc; - THD* thd = ha_thd(); - int command = thd_sql_command(thd); - - if (db2Table->hasBlobs() || - (command == SQLCOM_REPLACE || command == SQLCOM_REPLACE_SELECT)) - rows = 1; - else if (rows == 0) - rows = DEFAULT_MAX_ROWS_TO_BUFFER; // Shoot the moon - - // If we're doing a multi-row insert, binlogging is active, and the table has an - // auto_increment column, then we'll attempt to lock the file while we perform a 'fast path' blocked - // insert. If we can't get the lock, then we'll do a row-by-row 'slow path' insert instead. The reason is - // because the MI generates the auto_increment (identity value), and if we can't lock the file, - // then we can't predetermine what that value will be for insertion into the MySQL write buffer. - - if ((rows > 1) && // Multi-row insert - (thd->options & OPTION_BIN_LOG) && // Binlogging is on - (table->found_next_number_field)) // Table has an auto_increment column - { - if (!dataHandle) - rc = db2Table->dataFile()->allocateNewInstance(&dataHandle, curConnection); - - rc = bridge()->lockObj(dataHandle, 1, QMY_LOCK, QMY_LEAR, QMY_YES); - if (rc==0) // Got the lock - { - autoIncLockAcquired = TRUE; - got_auto_inc_values = FALSE; - } - else // Didn't get the lock - rows = 1; // No problem, but don't block inserts - } - - if (activeHandle == 0) - { - last_start_bulk_insert_rc = useDataFile(); - if (last_start_bulk_insert_rc == 0) - last_start_bulk_insert_rc = prepWriteBuffer(rows, db2Table->dataFile()); - } - - if (last_start_bulk_insert_rc == 0) - outstanding_start_bulk_insert = true; - else - { - if (autoIncLockAcquired == TRUE) - { - bridge()->lockObj(dataHandle, 0, QMY_UNLOCK, QMY_LEAR, QMY_YES); - autoIncLockAcquired = FALSE; - } - } - - DBUG_VOID_RETURN; -} - - -int ha_ibmdb2i::end_bulk_insert() -{ - DBUG_ENTER("ha_ibmdb2i::end_bulk_insert"); - int rc = 0; - - if (outstanding_start_bulk_insert) - { - rc = finishBulkInsert(); - } - - my_errno = rc; - - DBUG_RETURN(rc); -} - - -int ha_ibmdb2i::prepReadBuffer(ha_rows rowsToRead, const db2i_file* file, char intent) -{ - DBUG_ENTER("ha_ibmdb2i::prepReadBuffer"); - DBUG_ASSERT(rowsToRead > 0); - - THD* thd = ha_thd(); - char cmtLvl = getCommitLevel(thd); - - const db2i_file::RowFormat* format; - int rc = file->obtainRowFormat(activeHandle, intent, cmtLvl, &format); - - if (unlikely(rc)) DBUG_RETURN(rc); - - if (lobFieldsRequested()) - { - forceSingleRowRead = true; - rowsToRead = 1; - } - - rowsToRead = min(stats.records+1,min(rowsToRead, DEFAULT_MAX_ROWS_TO_BUFFER)); - - uint bufSize = min((format->readRowLen * rowsToRead), THDVAR(thd, max_read_buffer_size)); - multiRowReadBuf.allocBuf(format->readRowLen, format->readRowNullOffset, bufSize); - activeReadBuf = &multiRowReadBuf; - - if (db2Table->hasBlobs()) - { - if (!blobReadBuffers) - blobReadBuffers = new BlobCollection(db2Table, THDVAR(thd, lob_alloc_size)); - rc = prepareReadBufferForLobs(); - if (rc) DBUG_RETURN(rc); - } - -// if (accessIntent == QMY_UPDATABLE && -// thd_tx_isolation(thd) == ISO_REPEATABLE_READ && -// !THDVAR(thd, transaction_unsafe)) -// activeReadBuf->update(QMY_READ_ONLY, &releaseRowNeeded, QMY_REPEATABLE_READ); -// else - activeReadBuf->update(intent, &releaseRowNeeded, cmtLvl); - - DBUG_RETURN(rc); -} - - -int ha_ibmdb2i::prepWriteBuffer(ha_rows rowsToWrite, const db2i_file* file) -{ - DBUG_ENTER("ha_ibmdb2i::prepWriteBuffer"); - DBUG_ASSERT(accessIntent == QMY_UPDATABLE && rowsToWrite > 0); - - const db2i_file::RowFormat* format; - int rc = file->obtainRowFormat(activeHandle, - QMY_UPDATABLE, - getCommitLevel(ha_thd()), - &format); - - if (unlikely(rc)) DBUG_RETURN(rc); - - rowsToWrite = min(rowsToWrite, DEFAULT_MAX_ROWS_TO_BUFFER); - - uint bufSize = min((format->writeRowLen * rowsToWrite), THDVAR(ha_thd(), max_write_buffer_size)); - multiRowWriteBuf.allocBuf(format->writeRowLen, format->writeRowNullOffset, bufSize); - activeWriteBuf = &multiRowWriteBuf; - - if (!blobWriteBuffers && db2Table->hasBlobs()) - { - blobWriteBuffers = new ValidatedPointer<char>[db2Table->getBlobCount()]; - } - DBUG_RETURN(rc); -} - - -int ha_ibmdb2i::flushWrite(FILE_HANDLE fileHandle, uchar* buf ) -{ - DBUG_ENTER("ha_ibmdb2i::flushWrite"); - int rc; - int64 generatedIdValue = 0; - bool IdValueWasGenerated = FALSE; - char* lastDupKeyNamePtr = NULL; - uint32 lastDupKeyNameLen = 0; - int loopCnt = 0; - bool retry_dup = FALSE; - - while (loopCnt == 0 || retry_dup == TRUE) - { - rc = bridge()->writeRows(fileHandle, - activeWriteBuf->ptr(), - getCommitLevel(), - &generatedIdValue, - &IdValueWasGenerated, - &lastDupKeyRRN, - &lastDupKeyNamePtr, - &lastDupKeyNameLen, - &incrementByValue); - loopCnt++; - retry_dup = FALSE; - invalidateCachedStats(); - if (lastDupKeyNameLen) - { - rrnAssocHandle = fileHandle; - - int command = thd_sql_command(ha_thd()); - - if (command == SQLCOM_REPLACE || - command == SQLCOM_REPLACE_SELECT) - lastDupKeyID = 0; - else - { - lastDupKeyID = getKeyFromName(lastDupKeyNamePtr, lastDupKeyNameLen); - - if (likely(lastDupKeyID != MAX_KEY)) - { - uint16 failedRow = activeWriteBuf->rowsWritten()+1; - - if (buf && (failedRow != activeWriteBuf->rowCount())) - { - const char* badRow = activeWriteBuf->getRowN(failedRow-1); - bool savedReadAllColumns = readAllColumns; - readAllColumns = true; - mungeDB2row(buf, - badRow, - badRow + activeWriteBuf->getRowNullOffset(), - true); - readAllColumns = savedReadAllColumns; - - if (table->found_next_number_field) - { - table->next_number_field->store(next_identity_value - (incrementByValue * (activeWriteBuf->rowCount() - (failedRow - 1)))); - } - } - - if (default_identity_value && // Table has ID colm and generating a value - (!autoIncLockAcquired || !got_auto_inc_values) && - // Writing first or only row in block - loopCnt == 1 && // Didn't already retry - lastDupKeyID == table->s->next_number_index) // Autoinc column is in failed index - { - if (alterStartWith() == 0) // Reset next Identity value to max+1 - retry_dup = TRUE; // Rtry the write operation - } - } - else - { - char unknownIndex[MAX_DB2_FILENAME_LENGTH+1]; - convFromEbcdic(lastDupKeyNamePtr, unknownIndex, min(lastDupKeyNameLen, MAX_DB2_FILENAME_LENGTH)); - unknownIndex[min(lastDupKeyNameLen, MAX_DB2_FILENAME_LENGTH)] = 0; - getErrTxt(DB2I_ERR_UNKNOWN_IDX, unknownIndex); - } - } - } - } - - if ((rc == 0 || rc == HA_ERR_FOUND_DUPP_KEY) - && default_identity_value && IdValueWasGenerated && - (!autoIncLockAcquired || !got_auto_inc_values)) - { - /* Save the generated identity value for the MySQL last_insert_id() function. */ - insert_id_for_cur_row = generatedIdValue; - - /* Store the value into MySQL's buf for row-based replication - or for an 'on duplicate key update' clause. */ - table->next_number_field->store((longlong) generatedIdValue, TRUE); - if (autoIncLockAcquired) - { - got_auto_inc_values = TRUE; - next_identity_value = generatedIdValue + incrementByValue; - } - } - else - { - if (!autoIncLockAcquired) // Don't overlay value for first row of a block - insert_id_for_cur_row = 0; - } - - - activeWriteBuf->resetAfterWrite(); - DBUG_RETURN(rc); -} - -int ha_ibmdb2i::alterStartWith() -{ - DBUG_ENTER("ha_ibmdb2i::alterStartWith"); - int rc = 0; - ulonglong nextIdVal; - if (!dataHandle) - rc = db2Table->dataFile()->allocateNewInstance(&dataHandle, curConnection); - if (!rc) {rc = bridge()->lockObj(dataHandle, 1, QMY_LOCK, QMY_LENR, QMY_YES);} - if (!rc) - { - rc = getNextIdVal(&nextIdVal); - if (!rc) {rc = reset_auto_increment(nextIdVal);} - bridge()->lockObj(dataHandle, 0, QMY_UNLOCK, QMY_LENR, QMY_YES); - } - DBUG_RETURN(rc); -} - -bool ha_ibmdb2i::lobFieldsRequested() -{ - if (!db2Table->hasBlobs()) - { - DBUG_PRINT("ha_ibmdb2i::lobFieldsRequested",("No LOBs")); - return (false); - } - - if (readAllColumns) - { - DBUG_PRINT("ha_ibmdb2i::lobFieldsRequested",("All cols requested")); - return (true); - } - - for (int i = 0; i < db2Table->getBlobCount(); ++i) - { - if (bitmap_is_set(table->read_set, db2Table->blobFields[i])) - { - DBUG_PRINT("ha_ibmdb2i::lobFieldsRequested",("LOB requested")); - return (true); - } - } - - DBUG_PRINT("ha_ibmdb2i::lobFieldsRequested",("No LOBs requested")); - return (false); -} - - -int ha_ibmdb2i::prepareReadBufferForLobs() -{ - DBUG_ENTER("ha_ibmdb2i::prepareReadBufferForLobs"); - DBUG_ASSERT(db2Table->hasBlobs()); - - uint32 activeLobFields = 0; - DB2LobField* lobField; - uint16 blobCount = db2Table->getBlobCount(); - - char* readBuf = activeReadBuf->getRowN(0); - - for (int i = 0; i < blobCount; ++i) - { - int fieldID = db2Table->blobFields[i]; - DB2Field& db2Field = db2Table->db2Field(fieldID); - lobField = db2Field.asBlobField(readBuf); - if (readAllColumns || - bitmap_is_set(table->read_set, fieldID)) - { - lobField->dataHandle = (ILEMemHandle)blobReadBuffers->getBufferPtr(fieldID); - activeLobFields++; - } - else - { - lobField->dataHandle = NULL; - } - } - - if (activeLobFields == 0) - { - for (int i = 0; i < blobCount; ++i) - { - DB2Field& db2Field = db2Table->db2Field(db2Table->blobFields[i]); - uint16 offset = db2Field.getBufferOffset() + db2Field.calcBlobPad(); - - for (int r = 1; r < activeReadBuf->getRowCapacity(); ++r) - { - lobField = (DB2LobField*)(activeReadBuf->getRowN(r) + offset); - lobField->dataHandle = NULL; - } - } - } - - activeReadBuf->setRowsToProcess((activeLobFields ? 1 : activeReadBuf->getRowCapacity())); - int rc = bridge()->objectOverride(activeHandle, - activeReadBuf->ptr(), - activeReadBuf->getRowLength()); - DBUG_RETURN(rc); -} - - -uint32 ha_ibmdb2i::adjustLobBuffersForRead() -{ - DBUG_ENTER("ha_ibmdb2i::adjustLobBuffersForRead"); - - char* readBuf = activeReadBuf->getRowN(0); - - for (int i = 0; i < db2Table->getBlobCount(); ++i) - { - DB2Field& db2Field = db2Table->db2Field(db2Table->blobFields[i]); - DB2LobField* lobField = db2Field.asBlobField(readBuf); - if (readAllColumns || - bitmap_is_set(table->read_set, db2Table->blobFields[i])) - { - lobField->dataHandle = (ILEMemHandle)blobReadBuffers->reallocBuffer(db2Table->blobFields[i], lobField->length); - - if (lobField->dataHandle == NULL) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - else - { - lobField->dataHandle = 0; - } - } - - int32 rc = bridge()->objectOverride(activeHandle, - activeReadBuf->ptr()); - DBUG_RETURN(rc); -} - - - -int ha_ibmdb2i::reset() -{ - DBUG_ENTER("ha_ibmdb2i::reset"); - - if (outstanding_start_bulk_insert) - { - finishBulkInsert(); - } - - if (activeHandle != 0) - { - releaseActiveHandle(); - } - - cleanupBuffers(); - - db2i_ileBridge::getBridgeForThread(ha_thd())->freeErrorStorage(); - - last_rnd_init_rc = last_index_init_rc = last_start_bulk_insert_rc = 0; - - returnDupKeysImmediately = false; - onDupUpdate = false; - forceSingleRowRead = false; - -#ifndef DBUG_OFF - cachedBridge=NULL; -#endif - - DBUG_RETURN(0); -} - - -int32 ha_ibmdb2i::buildCreateIndexStatement(SqlStatementStream& sqlStream, - KEY& key, - bool isPrimary, - const char* db2LibName, - const char* db2FileName) -{ - DBUG_ENTER("ha_ibmdb2i::buildCreateIndexStatement"); - - char fileSortSequence[11] = "*HEX"; - char fileSortSequenceLibrary[11] = ""; - char fileSortSequenceType = ' '; - String query(256); - query.length(0); - int rc = 0; - - if (isPrimary) - { - query.append(STRING_WITH_LEN("ALTER TABLE ")); - query.append(db2LibName); - query.append('.'); - query.append(db2FileName); - query.append(STRING_WITH_LEN(" ADD PRIMARY KEY ")); - } - else - { - query.append(STRING_WITH_LEN("CREATE")); - - if (key.flags & HA_NOSAME) - query.append(STRING_WITH_LEN(" UNIQUE WHERE NOT NULL")); - - query.append(STRING_WITH_LEN(" INDEX ")); - - query.append(db2LibName); - query.append('.'); - if (db2i_table::appendQualifiedIndexFileName(key.name, db2FileName, query)) - { - getErrTxt(DB2I_ERR_INVALID_NAME,"index","*generated*"); - DBUG_RETURN(DB2I_ERR_INVALID_NAME ); - } - - query.append(STRING_WITH_LEN(" ON ")); - - query.append(db2LibName); - query.append('.'); - query.append(db2FileName); - } - - String fieldDefinition(128); - rc = buildIndexFieldList(fieldDefinition, - key, - isPrimary, - &fileSortSequenceType, - fileSortSequence, - fileSortSequenceLibrary); - - if (rc) DBUG_RETURN(rc); - - query.append(fieldDefinition); - - if ((THDVAR(ha_thd(), create_index_option)==1) && - (fileSortSequenceType != 'B') && - (fileSortSequenceType != ' ')) - { - rc = generateShadowIndex(sqlStream, - key, - db2LibName, - db2FileName, - fieldDefinition); - if (rc) DBUG_RETURN(rc); - } - - DBUG_PRINT("ha_ibmdb2i::buildCreateIndexStatement", ("Sent to DB2: %s",query.c_ptr_safe())); - sqlStream.addStatement(query,fileSortSequence,fileSortSequenceLibrary); - - DBUG_RETURN(0); -} - -/** - Generate the SQL syntax for the list of fields to be assigned to the - specified key. The corresponding sort sequence is also calculated. - - @param[out] appendHere The string to receive the generated SQL - @param key The key to evaluate - @param isPrimary True if this is being generated on behalf of the primary key - @param[out] fileSortSequenceType The type of the associated sort sequence - @param[out] fileSortSequence The name of the associated sort sequence - @param[out] fileSortSequenceLibrary The library of the associated sort sequence - - @return 0 if successful; error value otherwise -*/ -int32 ha_ibmdb2i::buildIndexFieldList(String& appendHere, - const KEY& key, - bool isPrimary, - char* fileSortSequenceType, - char* fileSortSequence, - char* fileSortSequenceLibrary) -{ - DBUG_ENTER("ha_ibmdb2i::buildIndexFieldList"); - appendHere.append(STRING_WITH_LEN(" ( ")); - for (int j = 0; j < key.key_parts; ++j) - { - char colName[MAX_DB2_COLNAME_LENGTH+1]; - if (j != 0) - { - appendHere.append(STRING_WITH_LEN(" , ")); - } - - KEY_PART_INFO& kpi = key.key_part[j]; - Field* field = kpi.field; - - convertMySQLNameToDB2Name(field->field_name, - colName, - sizeof(colName)); - appendHere.append(colName); - - int32 rc; - rc = updateAssociatedSortSequence(field->charset(), - fileSortSequenceType, - fileSortSequence, - fileSortSequenceLibrary); - if (rc) DBUG_RETURN (rc); - } - - appendHere.append(STRING_WITH_LEN(" ) ")); - - DBUG_RETURN(0); -} - - -/** - Generate an SQL statement that defines a *HEX sorted index to implement - the ibmdb2i_create_index. - - @param[out] stream The stream to append the generated statement to - @param key The key to evaluate - @param[out] libName The library containg the table - @param[out] fileName The DB2-compatible name of the table - @param[out] fieldDefinition The list of the fields in the index, in SQL syntax - - @return 0 if successful; error value otherwise -*/ -int32 ha_ibmdb2i::generateShadowIndex(SqlStatementStream& stream, - const KEY& key, - const char* libName, - const char* fileName, - const String& fieldDefinition) -{ - String shadowQuery(256); - shadowQuery.length(0); - shadowQuery.append(STRING_WITH_LEN("CREATE INDEX ")); - shadowQuery.append(libName); - shadowQuery.append('.'); - if (db2i_table::appendQualifiedIndexFileName(key.name, fileName, shadowQuery, db2i_table::ASCII_SQL, typeHex)) - { - getErrTxt(DB2I_ERR_INVALID_NAME,"index","*generated*"); - return DB2I_ERR_INVALID_NAME; - } - shadowQuery.append(STRING_WITH_LEN(" ON ")); - shadowQuery.append(libName); - shadowQuery.append('.'); - shadowQuery.append(fileName); - shadowQuery.append(fieldDefinition); - DBUG_PRINT("ha_ibmdb2i::generateShadowIndex", ("Sent to DB2: %s",shadowQuery.c_ptr_safe())); - stream.addStatement(shadowQuery,"*HEX","QSYS"); - return 0; -} - - -void ha_ibmdb2i::doInitialRead(char orientation, - uint32 rowsToBuffer, - ILEMemHandle key, - int keyLength, - int keyParts) -{ - DBUG_ENTER("ha_ibmdb2i::doInitialRead"); - - if (forceSingleRowRead) - rowsToBuffer = 1; - else - rowsToBuffer = min(rowsToBuffer, activeReadBuf->getRowCapacity()); - - activeReadBuf->newReadRequest(activeHandle, - orientation, - rowsToBuffer, - THDVAR(ha_thd(), async_enabled), - key, - keyLength, - keyParts); - DBUG_VOID_RETURN; -} - - -int ha_ibmdb2i::start_stmt(THD *thd, thr_lock_type lock_type) -{ - DBUG_ENTER("ha_ibmdb2i::start_stmt"); - initBridge(thd); - if (!THDVAR(thd, transaction_unsafe)) - { - trans_register_ha(thd, FALSE, ibmdb2i_hton); - - if (!autoCommitIsOn(thd)) - { - bridge()->beginStmtTx(); - } - } - - DBUG_RETURN(0); -} - -int32 ha_ibmdb2i::handleLOBReadOverflow() -{ - DBUG_ENTER("ha_ibmdb2i::handleLOBReadOverflow"); - DBUG_ASSERT(db2Table->hasBlobs() && (activeReadBuf->getRowCapacity() == 1)); - - int32 rc = adjustLobBuffersForRead(); - - if (!rc) - { - activeReadBuf->rewind(); - rc = bridge()->expectErrors(QMY_ERR_END_OF_BLOCK) - ->read(activeHandle, - activeReadBuf->ptr(), - accessIntent, - getCommitLevel(), - QMY_SAME); - releaseRowNeeded = TRUE; - - } - DBUG_RETURN(rc); -} - - -int32 ha_ibmdb2i::finishBulkInsert() -{ - int32 rc = 0; - - if (activeWriteBuf->rowCount() && activeHandle) - rc = flushWrite(activeHandle, table->record[0]); - - if (activeHandle) - releaseActiveHandle(); - - if (autoIncLockAcquired == TRUE) - { - // We could check the return code on the unlock, but beware not - // to overlay the return code from the flushwrite or we will mask - // duplicate key errors.. - bridge()->lockObj(dataHandle, 0, QMY_UNLOCK, QMY_LEAR, QMY_YES); - autoIncLockAcquired = FALSE; - } - outstanding_start_bulk_insert = false; - multiRowWriteBuf.freeBuf(); - last_start_bulk_insert_rc = 0; - - resetCharacterConversionBuffers(); - - return rc; -} - -int ha_ibmdb2i::getKeyFromName(const char* name, size_t len) -{ - for (int i = 0; i < table_share->keys; ++i) - { - const char* indexName = db2Table->indexFile(i)->getDB2FileName(); - if ((strncmp(name, indexName, len) == 0) && - (strlen(indexName) == len)) - { - return i; - } - } - return MAX_KEY; -} - -/* -Determine the number of I/O's it takes to read through the table. - */ -double ha_ibmdb2i::scan_time() - { - DBUG_ENTER("ha_ibmdb2i::scan_time"); - DBUG_RETURN(ulonglong2double((stats.data_file_length)/IO_SIZE)); - } - - -/** - Estimate the number of I/O's it takes to read a set of ranges through - an index. - - @param index - @param ranges - @param rows - - @return The estimate number of I/Os -*/ - -double ha_ibmdb2i::read_time(uint index, uint ranges, ha_rows rows) -{ - DBUG_ENTER("ha_ibmdb2i::read_time"); - int rc; - uint64 idxPageCnt = 0; - double cost; - - if (unlikely(rows == HA_POS_ERROR)) - DBUG_RETURN(double(rows) + ranges); - - rc = bridge()->retrieveIndexInfo(db2Table->indexFile(index)->getMasterDefnHandle(), - &idxPageCnt); - if (!rc) - { - if ((idxPageCnt == 1) || // Retrieving rows in requested order or - (ranges == rows)) // 'Sweep' full records retrieval - cost = idxPageCnt/4; - else - { - uint64 totalRecords = stats.records + 1; - double dataPageCount = stats.data_file_length/IO_SIZE; - - cost = (rows * dataPageCount / totalRecords) + - min(idxPageCnt, (log_2(idxPageCnt) * ranges + - rows * (log_2(idxPageCnt) + log_2(rows) - log_2(totalRecords)))); - } - } - else - { - cost = rows2double(ranges+rows); // Use default costing - } - DBUG_RETURN(cost); -} - -int ha_ibmdb2i::useIndexFile(int idx) -{ - DBUG_ENTER("ha_ibmdb2i::useIndexFile"); - - if (activeHandle) - releaseActiveHandle(); - - int rc = 0; - - if (!indexHandles[idx]) - rc = db2Table->indexFile(idx)->allocateNewInstance(&indexHandles[idx], curConnection); - - if (rc == 0) - { - activeHandle = indexHandles[idx]; - bumpInUseCounter(1); - } - - DBUG_RETURN(rc); -} - - -ulong ha_ibmdb2i::index_flags(uint inx, uint part, bool all_parts) const -{ - return HA_READ_NEXT | HA_READ_PREV | HA_KEYREAD_ONLY | HA_READ_ORDER | HA_READ_RANGE; -} - - -static struct st_mysql_sys_var* ibmdb2i_system_variables[] = { - MYSQL_SYSVAR(rdb_name), - MYSQL_SYSVAR(transaction_unsafe), - MYSQL_SYSVAR(lob_alloc_size), - MYSQL_SYSVAR(max_read_buffer_size), - MYSQL_SYSVAR(max_write_buffer_size), - MYSQL_SYSVAR(async_enabled), - MYSQL_SYSVAR(assume_exclusive_use), - MYSQL_SYSVAR(compat_opt_blob_cols), - MYSQL_SYSVAR(compat_opt_time_as_duration), - MYSQL_SYSVAR(compat_opt_allow_zero_date_vals), - MYSQL_SYSVAR(compat_opt_year_as_int), - MYSQL_SYSVAR(propagate_default_col_vals), - MYSQL_SYSVAR(create_index_option), -// MYSQL_SYSVAR(discovery_mode), - MYSQL_SYSVAR(system_trace_level), - NULL -}; - - -struct st_mysql_storage_engine ibmdb2i_storage_engine= -{ MYSQL_HANDLERTON_INTERFACE_VERSION }; - -mysql_declare_plugin(ibmdb2i) -{ - MYSQL_STORAGE_ENGINE_PLUGIN, - &ibmdb2i_storage_engine, - "IBMDB2I", - "The IBM development team in Rochester, Minnesota", - "IBM DB2 for i Storage Engine", - PLUGIN_LICENSE_GPL, - ibmdb2i_init_func, /* Plugin Init */ - ibmdb2i_done_func, /* Plugin Deinit */ - 0x0100 /* 1.0 */, - NULL, /* status variables */ - ibmdb2i_system_variables, /* system variables */ - NULL /* config options */ -} -mysql_declare_plugin_end; diff --git a/storage/ibmdb2i/ha_ibmdb2i.h b/storage/ibmdb2i/ha_ibmdb2i.h deleted file mode 100644 index b2a43232f2d..00000000000 --- a/storage/ibmdb2i/ha_ibmdb2i.h +++ /dev/null @@ -1,822 +0,0 @@ -/* -Licensed Materials - Property of IBM -DB2 Storage Engine Enablement -Copyright IBM Corporation 2007,2008 -All rights reserved - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - (a) Redistributions of source code must retain this list of conditions, the - copyright notice in section {d} below, and the disclaimer following this - list of conditions. - (b) Redistributions in binary form must reproduce this list of conditions, the - copyright notice in section (d) below, and the disclaimer following this - list of conditions, in the documentation and/or other materials provided - with the distribution. - (c) The name of IBM may not be used to endorse or promote products derived from - this software without specific prior written permission. - (d) The text of the required copyright notice is: - Licensed Materials - Property of IBM - DB2 Storage Engine Enablement - Copyright IBM Corporation 2007,2008 - All rights reserved - -THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - -/** @file ha_ibmdb2i.h - - @brief - - @note - - @see -*/ - -#ifdef USE_PRAGMA_INTERFACE -#pragma interface /* gcc class implementation */ -#endif - -#include "as400_types.h" -#include "as400_protos.h" -#include "db2i_global.h" -#include "db2i_ileBridge.h" -#include "builtins.h" -#include "db2i_misc.h" -#include "db2i_file.h" -#include "db2i_blobCollection.h" -#include "db2i_collationSupport.h" -#include "db2i_validatedPointer.h" -#include "db2i_ioBuffers.h" -#include "db2i_errors.h" -#include "db2i_sqlStatementStream.h" - -/** @brief - IBMDB2I_SHARE is a structure that will be shared among all open handlers. - It is used to describe the underlying table definition, and it caches - table statistics. -*/ -struct IBMDB2I_SHARE { - char *table_name; - uint table_name_length,use_count; - pthread_mutex_t mutex; - THR_LOCK lock; - - db2i_table* db2Table; - - class CStats - { - public: - void cacheUpdateTime(time_t time) - {update_time = time; initFlag |= lastModTime;} - time_t getUpdateTime() const - {return update_time;} - void cacheRowCount(ha_rows rows) - {records = rows; initFlag |= rowCount;} - ha_rows getRowCount() const - {return records;} - void cacheDelRowCount(ha_rows rows) - {deleted = rows; initFlag |= deletedRowCount;} - ha_rows getDelRowCount() const - {return deleted;} - void cacheMeanLength(ulong len) - {mean_rec_length = len; initFlag |= meanRowLen;} - ulong getMeanLength() - {return mean_rec_length;} - void cacheAugmentedDataLength(ulong len) - {data_file_length = len; initFlag |= ioCount;} - ulong getAugmentedDataLength() - {return data_file_length;} - bool isInited(uint flags) - {return initFlag & flags;} - void invalidate(uint flags) - {initFlag &= ~flags;} - - private: - uint initFlag; - time_t update_time; - ha_rows records; - ha_rows deleted; - ulong mean_rec_length; - ulong data_file_length; - } cachedStats; - -}; - -class ha_ibmdb2i: public handler -{ - THR_LOCK_DATA lock; ///< MySQL lock - IBMDB2I_SHARE *share; ///< Shared lock info - - // The record we are positioned on, together with the handle used to get - // i. - uint32 currentRRN; - uint32 rrnAssocHandle; - - // Dup key values needed by info() - uint32 lastDupKeyRRN; - uint32 lastDupKeyID; - - bool returnDupKeysImmediately; - - // Dup key value need by update() - bool onDupUpdate; - - - db2i_table* db2Table; - - // The file handle of the PF or LF being accessed by the current operation. - FILE_HANDLE activeHandle; - - // The file handle of the underlying PF - FILE_HANDLE dataHandle; - - // Array of file handles belonging to the underlying LFs - FILE_HANDLE* indexHandles; - - // Flag to indicate whether a call needs to be made to unlock a row when - // a read operation has ended. DB2 will handle row unlocking as we move - // through rows, but if an operation ends before we reach the end of a file, - // DB2 needs to know to unlock the last row read. - bool releaseRowNeeded; - - // Pointer to a definition of the layout of the row buffer for the file - // described by activeHandle - const db2i_file::RowFormat* activeFormat; - - IORowBuffer keyBuf; - uint32 keyLen; - - IOWriteBuffer multiRowWriteBuf; - IOAsyncReadBuffer multiRowReadBuf; - - IOAsyncReadBuffer* activeReadBuf; - IOWriteBuffer* activeWriteBuf; - - BlobCollection* blobReadBuffers; // Dynamically allocated per query and used - // to manage the buffers used for reading LOBs - ValidatedPointer<char>* blobWriteBuffers; - - // Return codes are not used/honored by rnd_init and start_bulk_insert - // so we need a way to signal the failure "downstream" to subsequent - // functions. - int last_rnd_init_rc; - int last_index_init_rc; - int last_start_bulk_insert_rc; - - // end_bulk_insert may get called twice for a single start_bulk_insert - // This is our way to do cleanup only once. - bool outstanding_start_bulk_insert; - - // Auto_increment 'increment by' value needed by write_row() - uint32 incrementByValue; - bool default_identity_value; - - // Flags and values used during write operations for auto_increment processing - bool autoIncLockAcquired; - bool got_auto_inc_values; - uint64 next_identity_value; - - // The access intent indicated by the last external_locks() call. - // May be either QMY_READ or QMY_UPDATABLE - char accessIntent; - char readAccessIntent; - - ha_rows* indexReadSizeEstimates; - - MEM_ROOT conversionBufferMemroot; - - bool forceSingleRowRead; - - bool readAllColumns; - - bool invalidDataFound; - - db2i_ileBridge* cachedBridge; - - ValidatedObject<volatile uint32> curConnection; - uint16 activeReferences; - -public: - - ha_ibmdb2i(handlerton *hton, TABLE_SHARE *table_arg); - ~ha_ibmdb2i(); - - const char *table_type() const { return "IBMDB2I"; } - const char *index_type(uint inx) { return "RADIX"; } - const key_map *keys_to_use_for_scanning() { return &key_map_full; } - const char **bas_ext() const; - - ulonglong table_flags() const - { - return HA_NULL_IN_KEY | HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY | - HA_PARTIAL_COLUMN_READ | - HA_DUPLICATE_POS | HA_NO_PREFIX_CHAR_KEYS | - HA_HAS_RECORDS | HA_BINLOG_ROW_CAPABLE | HA_REQUIRES_KEY_COLUMNS_FOR_DELETE | - HA_CAN_INDEX_BLOBS; - } - - ulong index_flags(uint inx, uint part, bool all_parts) const; - -// Note that we do not implement max_supported_record_length. -// We'll let create fail accordingly if the row is -// too long. This allows us to hide the fact that varchars > 32K are being -// implemented as DB2 LOBs. - - uint max_supported_keys() const { return 4000; } - uint max_supported_key_parts() const { return MAX_DB2_KEY_PARTS; } - uint max_supported_key_length() const { return 32767; } - uint max_supported_key_part_length() const { return 32767; } - double read_time(uint index, uint ranges, ha_rows rows); - double scan_time(); - int open(const char *name, int mode, uint test_if_locked); - int close(void); - int write_row(uchar * buf); - int update_row(const uchar * old_data, uchar * new_data); - int delete_row(const uchar * buf); - int index_init(uint idx, bool sorted); - int index_read(uchar * buf, const uchar * key, - uint key_len, enum ha_rkey_function find_flag); - int index_next(uchar * buf); - int index_read_last(uchar * buf, const uchar * key, uint key_len); - int index_next_same(uchar *buf, const uchar *key, uint keylen); - int index_prev(uchar * buf); - int index_first(uchar * buf); - int index_last(uchar * buf); - int rnd_init(bool scan); - int rnd_end(); - int rnd_next(uchar *buf); - int rnd_pos(uchar * buf, uchar *pos); - void position(const uchar *record); - int info(uint); - ha_rows records(); - int extra(enum ha_extra_function operation); - int external_lock(THD *thd, int lock_type); - int delete_all_rows(void); - ha_rows records_in_range(uint inx, key_range *min_key, - key_range *max_key); - int delete_table(const char *from); - int rename_table(const char * from, const char * to); - int create(const char *name, TABLE *form, - HA_CREATE_INFO *create_info); - int updateFrm(TABLE *table_def, File file); - int openTableDef(TABLE *table_def); - int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys); - int prepare_drop_index(TABLE *table_arg, uint *key_num, uint num_of_keys); - int final_drop_index(TABLE *table_arg) {return 0;} - void get_auto_increment(ulonglong offset, ulonglong increment, - ulonglong nb_desired_values, - ulonglong *first_value, - ulonglong *nb_reserved_values); - int reset_auto_increment(ulonglong value); - void restore_auto_increment(ulonglong prev_insert_id) {return;} - void update_create_info(HA_CREATE_INFO *create_info); - int getNextIdVal(ulonglong *value); - int analyze(THD* thd,HA_CHECK_OPT* check_opt); - int optimize(THD* thd, HA_CHECK_OPT* check_opt); - bool can_switch_engines(); - void free_foreign_key_create_info(char* str); - char* get_foreign_key_create_info(); - int get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list); - uint referenced_by_foreign_key(); - bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes); - virtual bool get_error_message(int error, String *buf); - - THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, - enum thr_lock_type lock_type); - - bool low_byte_first() const { return 0; } - void unlock_row(); - int index_end(); - int reset(); - static int doCommit(handlerton *hton, THD *thd, bool all); - static int doRollback(handlerton *hton, THD *thd, bool all); - void start_bulk_insert(ha_rows rows); - int end_bulk_insert(); - int start_stmt(THD *thd, thr_lock_type lock_type); - - void initBridge(THD* thd = NULL) - { - if (thd == NULL) thd = ha_thd(); - DBUG_PRINT("ha_ibmdb2i::initBridge",("Initing bridge. Conn ID=%d", thd->thread_id)); - cachedBridge = db2i_ileBridge::getBridgeForThread(thd); - } - - db2i_ileBridge* bridge() {DBUG_ASSERT(cachedBridge); return cachedBridge;} - - static uint8 autoCommitIsOn(THD* thd) - { return (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) ? QMY_NO : QMY_YES); } - - uint8 getCommitLevel(); - uint8 getCommitLevel(THD* thd); - - static int doSavepointSet(THD* thd, char* name) - { - return db2i_ileBridge::getBridgeForThread(thd)->savepoint(QMY_SET_SAVEPOINT, - name); - } - - static int doSavepointRollback(THD* thd, char* name) - { - return db2i_ileBridge::getBridgeForThread(thd)->savepoint(QMY_ROLLBACK_SAVEPOINT, - name); - } - - static int doSavepointRelease(THD* thd, char* name) - { - return db2i_ileBridge::getBridgeForThread(thd)->savepoint(QMY_RELEASE_SAVEPOINT, - name); - } - - // We can't guarantee that the rows we know about when this is called - // will be the same number of rows that read returns (since DB2 activity - // may insert additional rows). Therefore, we do as the Federated SE and - // return the max possible. - ha_rows estimate_rows_upper_bound() - { - return HA_POS_ERROR; - } - - -private: - - enum enum_TimeFormat - { - TIME_OF_DAY, - DURATION - }; - - enum enum_BlobMapping - { - AS_BLOB, - AS_VARCHAR - }; - - enum enum_ZeroDate - { - NO_SUBSTITUTE, - SUBSTITUTE_0001_01_01 - }; - - enum enum_YearFormat - { - CHAR4, - SMALLINT - }; - - enum_ZeroDate cachedZeroDateOption; - - IBMDB2I_SHARE *get_share(const char *table_name, TABLE *table); - int free_share(IBMDB2I_SHARE *share); - int32 mungeDB2row(uchar* record, const char* dataPtr, const char* nullMapPtr, bool skipLOBs); - int prepareRowForWrite(char* data, char* nulls, bool honorIdentCols); - int prepareReadBufferForLobs(); - int32 prepareWriteBufferForLobs(); - uint32 adjustLobBuffersForRead(); - bool lobFieldsRequested(); - int convertFieldChars(enum_conversionDirection direction, - uint16 fieldID, - const char* input, - char* output, - size_t ilen, - size_t olen, - size_t* outDataLen, - bool tacitErrors=FALSE, - size_t* substChars=NULL); - - /** - Fast integer log2 function - */ - uint64 log_2(uint64 val) - { - uint64 exp = 0; - while( (val >> exp) != 0) - { - exp++; - } - DBUG_ASSERT(exp-1 == (uint64)log2(val)); - return exp-1; - } - - void bumpInUseCounter(uint16 amount) - { - activeReferences += amount; - DBUG_PRINT("ha_ibmdb2i::bumpInUseCounter", ("activeReferences = %d", activeReferences)); - if (activeReferences) - curConnection = (uint32)(ha_thd()->thread_id); - else - curConnection = 0; - } - - - int useDataFile() - { - DBUG_ENTER("ha_ibmdb2i::useDataFile"); - - int rc = 0; - if (!dataHandle) - rc = db2Table->dataFile()->allocateNewInstance(&dataHandle, curConnection); - else if (activeHandle == dataHandle) - DBUG_RETURN(0); - - DBUG_ASSERT(activeHandle == 0); - - if (likely(rc == 0)) - { - activeHandle = dataHandle; - bumpInUseCounter(1); - } - - DBUG_RETURN(rc); - } - - void releaseAnyLockedRows() - { - if (releaseRowNeeded) - { - DBUG_PRINT("ha_ibmdb2i::releaseAnyLockedRows", ("Releasing rows")); - db2i_ileBridge::getBridgeForThread()->rrlslck(activeHandle, accessIntent); - releaseRowNeeded = FALSE; - } - } - - - void releaseDataFile() - { - DBUG_ENTER("ha_ibmdb2i::releaseDataFile"); - releaseAnyLockedRows(); - bumpInUseCounter(-1); - DBUG_ASSERT((volatile int)activeReferences >= 0); - activeHandle = 0; - DBUG_VOID_RETURN; - } - - int useIndexFile(int idx); - - void releaseIndexFile(int idx) - { - DBUG_ENTER("ha_ibmdb2i::releaseIndexFile"); - releaseAnyLockedRows(); - bumpInUseCounter(-1); - DBUG_ASSERT((volatile int)activeReferences >= 0); - activeHandle = 0; - DBUG_VOID_RETURN; - } - - FILE_HANDLE allocateFileHandle(char* database, char* table, int* activityReference, bool hasBlobs); - - int updateBuffers(const db2i_file::RowFormat* format, uint rowsToRead, uint rowsToWrite); - - int flushWrite(FILE_HANDLE fileHandle, uchar* buf = NULL); - - int alterStartWith(); - - int buildDB2ConstraintString(LEX* lex, - String& appendHere, - const char* database, - Field** fields, - char* fileSortSequenceType, - char* fileSortSequence, - char* fileSortSequenceLibrary); - - void releaseWriteBuffer(); - - void setIndexReadEstimate(uint index, ha_rows rows) - { - if (!indexReadSizeEstimates) - { - indexReadSizeEstimates = (ha_rows*)my_malloc(sizeof(ha_rows) * table->s->keys, MYF(MY_WME | MY_ZEROFILL)); - } - indexReadSizeEstimates[index] = rows; - } - - ha_rows getIndexReadEstimate(uint index) - { - if (indexReadSizeEstimates) - return max(indexReadSizeEstimates[index], 1); - - return 10000; // Assume index scan if no estimate exists. - } - - - void quiesceAllFileHandles() - { - db2i_ileBridge* bridge = db2i_ileBridge::getBridgeForThread(); - if (dataHandle) - { - bridge->quiesceFileInstance(dataHandle); - } - - for (int idx = 0; idx < table_share->keys; ++idx) - { - if (indexHandles[idx] != 0) - { - bridge->quiesceFileInstance(indexHandles[idx]); - } - } - } - - int32 buildCreateIndexStatement(SqlStatementStream& sqlStream, - KEY& key, - bool isPrimary, - const char* db2LibName, - const char* db2FileName); - - int32 buildIndexFieldList(String& appendHere, - const KEY& key, - bool isPrimary, - char* fileSortSequenceType, - char* fileSortSequence, - char* fileSortSequenceLibrary); - - // Specify NULL for data when using the data pointed to by field - int32 convertMySQLtoDB2(Field* field, const DB2Field& db2Field, char* db2Buf, const uchar* data = NULL); - - int32 convertDB2toMySQL(const DB2Field& db2Field, Field* field, const char* buf); - int getFieldTypeMapping(Field* field, - String& mapping, - enum_TimeFormat timeFormate, - enum_BlobMapping blobMapping, - enum_ZeroDate zeroDateHandling, - bool propagateDefaults, - enum_YearFormat yearFormat); - - int getKeyFromName(const char* name, size_t len); - - void releaseActiveHandle() - { - if (activeHandle == dataHandle) - releaseDataFile(); - else - releaseIndexFile(active_index); - } - - - int32 finishBulkInsert(); - - void doInitialRead(char orientation, - uint32 rowsToBuffer, - ILEMemHandle key = 0, - int keyLength = 0, - int keyParts = 0); - - - int32 readFromBuffer(uchar* destination, char orientation) - { - char* row; - int32 rc = 0; - row = activeReadBuf->readNextRow(orientation, currentRRN); - - if (unlikely(!row)) - { - rc = activeReadBuf->lastrc(); - if (rc == QMY_ERR_LOB_SPACE_TOO_SMALL) - { - rc = handleLOBReadOverflow(); - if (rc == 0) - { - DBUG_ASSERT(activeReadBuf->rowCount() == 1); - row = activeReadBuf->readNextRow(orientation, currentRRN); - - if (unlikely(!row)) - rc = activeReadBuf->lastrc(); - } - } - } - - if (likely(rc == 0)) - { - rrnAssocHandle = activeHandle; - rc = mungeDB2row(destination, row, row+activeReadBuf->getRowNullOffset(), false); - } - return rc; - } - - int32 handleLOBReadOverflow(); - - char* getCharacterConversionBuffer(int fieldId, int length) - { - if (unlikely(!alloc_root_inited(&conversionBufferMemroot))) - init_alloc_root(&conversionBufferMemroot, 8192, 0); - - return (char*)alloc_root(&conversionBufferMemroot, length);; - } - - void resetCharacterConversionBuffers() - { - if (alloc_root_inited(&conversionBufferMemroot)) - { - free_root(&conversionBufferMemroot, MYF(MY_MARK_BLOCKS_FREE)); - } - } - - void tweakReadSet() - { - THD* thd = ha_thd(); - int command = thd_sql_command(thd); - if ((command == SQLCOM_UPDATE || - command == SQLCOM_UPDATE_MULTI) || - ((command == SQLCOM_DELETE || - command == SQLCOM_DELETE_MULTI) && - thd->options & OPTION_BIN_LOG)) - readAllColumns = TRUE; - else - readAllColumns = FALSE; - } - - /** - - */ - int useFileByHandle(char intent, - FILE_HANDLE handle) - { - DBUG_ENTER("ha_ibmdb2i::useFileByHandle"); - - const db2i_file* file; - if (handle == dataHandle) - file = db2Table->dataFile(); - else - { - for (uint i = 0; i < table_share->keys; ++i) - { - if (indexHandles[i] == handle) - { - file = db2Table->indexFile(i); - active_index = i; - } - } - } - - int rc = file->obtainRowFormat(handle, intent, getCommitLevel(), &activeFormat); - if (likely(rc == 0)) - { - activeHandle = handle; - bumpInUseCounter(1); - } - - DBUG_RETURN(rc); - } - - const db2i_file* getFileForActiveHandle() const - { - if (activeHandle == dataHandle) - return db2Table->dataFile(); - else - for (uint i = 0; i < table_share->keys; ++i) - if (indexHandles[i] == activeHandle) - return db2Table->indexFile(i); - DBUG_ASSERT(0); - return NULL; - } - - int prepReadBuffer(ha_rows rowsToRead, const db2i_file* file, char intent); - int prepWriteBuffer(ha_rows rowsToWrite, const db2i_file* file); - - void invalidateCachedStats() - { - share->cachedStats.invalidate(rowCount | deletedRowCount | objLength | - meanRowLen | ioCount); - } - - void warnIfInvalidData() - { - if (unlikely(invalidDataFound)) - { - warning(ha_thd(), DB2I_ERR_INVALID_DATA, table->alias); - } - } - - /** - Calculate the maximum value that a particular field can hold. - - This is used to anticipate overflows in the auto_increment processing. - - @param field The Field to be analyzed - - @return The maximum value - */ - static uint64 maxValueForField(const Field* field) - { - uint64 maxValue=0; - switch (field->type()) - { - case MYSQL_TYPE_TINY: - if (((const Field_num*)field)->unsigned_flag) - maxValue = (1 << 8) - 1; - else - maxValue = (1 << 7) - 1; - break; - case MYSQL_TYPE_SHORT: - if (((const Field_num*)field)->unsigned_flag) - maxValue = (1 << 16) - 1; - else - maxValue = (1 << 15) - 1; - break; - case MYSQL_TYPE_INT24: - if (((const Field_num*)field)->unsigned_flag) - maxValue = (1 << 24) - 1; - else - maxValue = (1 << 23) - 1; - break; - case MYSQL_TYPE_LONG: - if (((const Field_num*)field)->unsigned_flag) - maxValue = (1LL << 32) - 1; - else - maxValue = (1 << 31) - 1; - break; - case MYSQL_TYPE_LONGLONG: - if (((const Field_num*)field)->unsigned_flag) - maxValue = ~(0LL); - else - maxValue = 1 << 63 - 1; - break; - } - - return maxValue; - } - - void cleanupBuffers() - { - if (blobReadBuffers) - { - delete blobReadBuffers; - blobReadBuffers = NULL; - } - if (blobWriteBuffers) - { - delete[] blobWriteBuffers; - blobWriteBuffers = NULL; - } - if (alloc_root_inited(&conversionBufferMemroot)) - { - free_root(&conversionBufferMemroot, MYF(0)); - } - } - - -/** - Generate a valid RCDFMT name based on the name of the table. - - The RCDFMT name is devised by munging the name of the table, - uppercasing all ascii alpha-numeric characters and replacing all other - characters with underscores until up to ten characters have been generated. - - @param tableName The name of the table, as given on the MySQL - CREATE TABLE statement - @param[out] query The string to receive the generated RCDFMT name -*/ - static void generateAndAppendRCDFMT(const char* tableName, String& query) - { - char rcdfmt[11]; - - // The RCDFMT name must begin with an alpha character. - // We enforce this by skipping to the first alpha character in the table - // name. If no alpha character exists, we use 'X' for the RCDFMT name; - - while (*tableName && - (!my_isascii(*tableName) || - !my_isalpha(system_charset_info, *tableName))) - { - tableName += my_mbcharlen(system_charset_info, *tableName); - } - - if (unlikely(!(*tableName))) - { - rcdfmt[0]= 'X'; - rcdfmt[1]= 0; - } - else - { - int r= 0; - while ((r < sizeof(rcdfmt)-1) && *tableName) - { - if (my_isascii(*tableName) && - my_isalnum(system_charset_info, *tableName)) - rcdfmt[r] = my_toupper(system_charset_info, *tableName); - else - rcdfmt[r] = '_'; - - ++r; - tableName += my_mbcharlen(system_charset_info, *tableName); - } - rcdfmt[r]= 0; - } - query.append(STRING_WITH_LEN(" RCDFMT ")); - query.append(rcdfmt); - } - - int32 generateShadowIndex(SqlStatementStream& stream, - const KEY& key, - const char* libName, - const char* fileName, - const String& fieldDefinition); -}; diff --git a/storage/ibmdb2i/plug.in b/storage/ibmdb2i/plug.in deleted file mode 100644 index 0913d72aabf..00000000000 --- a/storage/ibmdb2i/plug.in +++ /dev/null @@ -1,12 +0,0 @@ -MYSQL_STORAGE_ENGINE([ibmdb2i], [], [IBM DB2 for i Storage Engine], - [IBM DB2 for i Storage Engine], [max,max-no-ndb]) -MYSQL_PLUGIN_DYNAMIC([ibmdb2i], [ha_ibmdb2i.la]) - -AC_CHECK_HEADER([qlgusr.h], - # qlgusr.h is just one of the headers from the i5/OS PASE environment; the - # EBCDIC headers are in /QIBM/include, and have to be converted to ASCII - # before cpp gets to them - [:], - # Missing PASE environment, can't build this engine - [mysql_plugin_ibmdb2i=no - with_plugin_ibmdb2i=no]) diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c index 5317da78ee4..e185514b9c1 100644 --- a/storage/myisam/ft_nlq_search.c +++ b/storage/myisam/ft_nlq_search.c @@ -63,7 +63,7 @@ static int FT_SUPERDOC_cmp(void* cmp_arg __attribute__((unused)), static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) { - int subkeys, r; + int UNINIT_VAR(subkeys), r; uint keylen, doc_cnt; FT_SUPERDOC sdoc, *sptr; TREE_ELEMENT *selem; diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c index 0b4d781379c..42bd8e26a94 100644 --- a/storage/myisam/mi_create.c +++ b/storage/myisam/mi_create.c @@ -38,7 +38,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, MI_CREATE_INFO *ci,uint flags) { register uint i,j; - File UNINIT_VAR(dfile),file; + File UNINIT_VAR(dfile), UNINIT_VAR(file); int errpos,save_errno, create_mode= O_RDWR | O_TRUNC; myf create_flag; uint fields,length,max_key_length,packed,pointer,real_length_diff, @@ -73,8 +73,6 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, { DBUG_RETURN(my_errno=HA_WRONG_CREATE_OPTION); } - LINT_INIT(dfile); - LINT_INIT(file); errpos=0; options=0; bzero((uchar*) &share,sizeof(share)); diff --git a/storage/myisammrg/myrg_open.c b/storage/myisammrg/myrg_open.c index 18f8aa8d2c0..4bc3f7a4018 100644 --- a/storage/myisammrg/myrg_open.c +++ b/storage/myisammrg/myrg_open.c @@ -221,7 +221,7 @@ MYRG_INFO *myrg_parent_open(const char *parent_name, int (*callback)(void*, const char*), void *callback_param) { - MYRG_INFO *m_info; + MYRG_INFO *UNINIT_VAR(m_info); int rc; int errpos; int save_errno; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 3bfcf3ee233..ed8031b3fc3 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -1175,7 +1175,7 @@ my_bool fetch_n(const char **query_list, unsigned query_count, /* Separate thread query to test some cases */ -static my_bool thread_query(char *query) +static my_bool thread_query(const char *query) { MYSQL *l_mysql; my_bool error; @@ -1197,7 +1197,7 @@ static my_bool thread_query(char *query) goto end; } l_mysql->reconnect= 1; - if (mysql_query(l_mysql, (char *)query)) + if (mysql_query(l_mysql, query)) { fprintf(stderr, "Query failed (%s)\n", mysql_error(l_mysql)); error= 1; @@ -5821,7 +5821,7 @@ static void test_prepare_alter() rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); - if (thread_query((char *)"ALTER TABLE test_prep_alter change id id_new varchar(20)")) + if (thread_query("ALTER TABLE test_prep_alter change id id_new varchar(20)")) exit(1); is_null= 1; |